fdb_kvdb.c 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049
  1. /*
  2. * Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief KVDB feature.
  9. *
  10. * Key-Value Database feature implement source file.
  11. */
  12. #include <inttypes.h>
  13. #include <string.h>
  14. #include "fdb_low_lvl.h"
  15. #include "flashdb.h"
  16. #define FDB_LOG_TAG "[kv]"
  17. /* rewrite log prefix */
  18. #undef FDB_LOG_PREFIX2
  19. #define FDB_LOG_PREFIX2() \
  20. FDB_PRINT("[%s][%s] ", db_name(db), _fdb_db_path((fdb_db_t)db))
  21. #if defined(FDB_USING_KVDB)
  22. #ifndef FDB_WRITE_GRAN
  23. #error "Please configure flash write granularity (in fdb_cfg.h)"
  24. #endif
  25. #if FDB_WRITE_GRAN != 1 && FDB_WRITE_GRAN != 8 && FDB_WRITE_GRAN != 32 && \
  26. FDB_WRITE_GRAN != 64
  27. #error "the write gran can be only setting as 1, 8, 32 and 64"
  28. #endif
  29. /* magic word(`F`, `D`, `B`, `1`) */
  30. #define SECTOR_MAGIC_WORD 0x30424446
  31. /* magic word(`K`, `V`, `0`, `0`) */
  32. #define KV_MAGIC_WORD 0x3030564B
  33. /* the sector remain threshold before full status */
  34. #ifndef FDB_SEC_REMAIN_THRESHOLD
  35. #define FDB_SEC_REMAIN_THRESHOLD (KV_HDR_DATA_SIZE + FDB_KV_NAME_MAX)
  36. #endif
  37. /* the total remain empty sector threshold before GC */
  38. #ifndef FDB_GC_EMPTY_SEC_THRESHOLD
  39. #define FDB_GC_EMPTY_SEC_THRESHOLD 1
  40. #endif
  41. /* the string KV value buffer size for legacy fdb_get_kv(db, ) function */
  42. #ifndef FDB_STR_KV_VALUE_MAX_SIZE
  43. #define FDB_STR_KV_VALUE_MAX_SIZE 128
  44. #endif
  45. #if FDB_KV_CACHE_TABLE_SIZE > 0xFFFF
  46. #error "The KV cache table size must less than 0xFFFF"
  47. #endif
  48. /* the sector is not combined value */
  49. #if (FDB_BYTE_ERASED == 0xFF)
  50. #define SECTOR_NOT_COMBINED 0xFFFFFFFF
  51. #else
  52. #define SECTOR_NOT_COMBINED 0x00000000
  53. #endif
  54. /* the next address is get failed */
  55. #define FAILED_ADDR 0xFFFFFFFF
  56. #define KV_STATUS_TABLE_SIZE FDB_STATUS_TABLE_SIZE(FDB_KV_STATUS_NUM)
  57. #define SECTOR_NUM (db_max_size(db) / db_sec_size(db))
  58. #define SECTOR_HDR_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct sector_hdr_data)))
  59. #define SECTOR_STORE_OFFSET \
  60. ((unsigned long)(&((struct sector_hdr_data*)0)->status_table.store))
  61. #define SECTOR_DIRTY_OFFSET \
  62. ((unsigned long)(&((struct sector_hdr_data*)0)->status_table.dirty))
  63. #define SECTOR_MAGIC_OFFSET \
  64. ((unsigned long)(&((struct sector_hdr_data*)0)->magic))
  65. #define KV_HDR_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct kv_hdr_data)))
  66. #define KV_MAGIC_OFFSET ((unsigned long)(&((struct kv_hdr_data*)0)->magic))
  67. #define KV_LEN_OFFSET ((unsigned long)(&((struct kv_hdr_data*)0)->len))
  68. #define KV_NAME_LEN_OFFSET \
  69. ((unsigned long)(&((struct kv_hdr_data*)0)->name_len))
  70. #define db_name(db) (((fdb_db_t)db)->name)
  71. #define db_init_ok(db) (((fdb_db_t)db)->init_ok)
  72. #define db_sec_size(db) (((fdb_db_t)db)->sec_size)
  73. #define db_max_size(db) (((fdb_db_t)db)->max_size)
  74. #define db_oldest_addr(db) (((fdb_db_t)db)->oldest_addr)
  75. #define db_lock(db) \
  76. do { \
  77. if (((fdb_db_t)db)->lock) \
  78. ((fdb_db_t)db)->lock((fdb_db_t)db); \
  79. } while (0);
  80. #define db_unlock(db) \
  81. do { \
  82. if (((fdb_db_t)db)->unlock) \
  83. ((fdb_db_t)db)->unlock((fdb_db_t)db); \
  84. } while (0);
  85. #define VER_NUM_KV_NAME "__ver_num__"
  86. struct sector_hdr_data {
  87. struct {
  88. uint8_t
  89. store[FDB_STORE_STATUS_TABLE_SIZE]; /**< sector store status @see
  90. fdb_sector_store_status_t */
  91. uint8_t
  92. dirty[FDB_DIRTY_STATUS_TABLE_SIZE]; /**< sector dirty status @see
  93. fdb_sector_dirty_status_t */
  94. } status_table;
  95. uint32_t magic; /**< magic word(`E`, `F`, `4`, `0`) */
  96. uint32_t combined; /**< the combined next sector number, 0xFFFFFFFF: not
  97. combined */
  98. uint32_t reserved;
  99. #if (FDB_WRITE_GRAN == 64)
  100. uint8_t padding[4]; /**< align padding for 64bit write granularity */
  101. #endif
  102. };
  103. typedef struct sector_hdr_data* sector_hdr_data_t;
  104. struct kv_hdr_data {
  105. uint8_t status_table[KV_STATUS_TABLE_SIZE]; /**< KV node status, @see
  106. fdb_kv_status_t */
  107. uint32_t magic; /**< magic word(`K`, `V`, `4`, `0`) */
  108. uint32_t len; /**< KV node total length (header + name + value), must align
  109. by FDB_WRITE_GRAN */
  110. uint32_t crc32; /**< KV node crc32(name_len + data_len + name + value) */
  111. uint8_t name_len; /**< name length */
  112. uint32_t value_len; /**< value length */
  113. #if (FDB_WRITE_GRAN == 64)
  114. uint8_t padding[4]; /**< align padding for 64bit write granularity */
  115. #endif
  116. };
  117. typedef struct kv_hdr_data* kv_hdr_data_t;
  118. struct alloc_kv_cb_args {
  119. fdb_kvdb_t db;
  120. size_t kv_size;
  121. uint32_t* empty_kv;
  122. };
  123. struct gc_cb_args {
  124. fdb_kvdb_t db;
  125. size_t cur_free_size;
  126. size_t setting_free_size;
  127. uint32_t traversed_len;
  128. };
  129. static void gc_collect(fdb_kvdb_t db);
  130. static void gc_collect_by_free_size(fdb_kvdb_t db, size_t free_size);
  131. #ifdef FDB_KV_USING_CACHE
  132. /*
  133. * It's only caching the current using status sector's empty_addr
  134. */
  135. static void update_sector_cache(fdb_kvdb_t db,
  136. uint32_t sec_addr,
  137. uint32_t empty_addr) {
  138. size_t i, empty_index = FDB_SECTOR_CACHE_TABLE_SIZE;
  139. for (i = 0; i < FDB_SECTOR_CACHE_TABLE_SIZE; i++) {
  140. if ((empty_addr > sec_addr) &&
  141. (empty_addr < sec_addr + db_sec_size(db))) {
  142. /* update the sector empty_addr in cache */
  143. if (db->sector_cache_table[i].addr == sec_addr) {
  144. db->sector_cache_table[i].addr = sec_addr;
  145. db->sector_cache_table[i].empty_addr = empty_addr;
  146. return;
  147. } else if ((db->sector_cache_table[i].addr == FDB_DATA_UNUSED) &&
  148. (empty_index == FDB_SECTOR_CACHE_TABLE_SIZE)) {
  149. empty_index = i;
  150. }
  151. } else if (db->sector_cache_table[i].addr == sec_addr) {
  152. /* delete the sector which status is not current using */
  153. db->sector_cache_table[i].addr = FDB_DATA_UNUSED;
  154. return;
  155. }
  156. }
  157. /* add the sector empty_addr to cache */
  158. if (empty_index < FDB_SECTOR_CACHE_TABLE_SIZE) {
  159. db->sector_cache_table[empty_index].addr = sec_addr;
  160. db->sector_cache_table[empty_index].empty_addr = empty_addr;
  161. }
  162. }
  163. /*
  164. * Get sector info from cache. It's return pika_true when cache is hit.
  165. */
  166. static pika_bool get_sector_from_cache(fdb_kvdb_t db,
  167. uint32_t sec_addr,
  168. uint32_t* empty_addr) {
  169. size_t i;
  170. for (i = 0; i < FDB_SECTOR_CACHE_TABLE_SIZE; i++) {
  171. if (db->sector_cache_table[i].addr == sec_addr) {
  172. if (empty_addr) {
  173. *empty_addr = db->sector_cache_table[i].empty_addr;
  174. }
  175. return pika_true;
  176. }
  177. }
  178. return pika_false;
  179. }
  180. static void update_kv_cache(fdb_kvdb_t db,
  181. const char* name,
  182. size_t name_len,
  183. uint32_t addr) {
  184. size_t i, empty_index = FDB_KV_CACHE_TABLE_SIZE,
  185. min_activity_index = FDB_KV_CACHE_TABLE_SIZE;
  186. uint16_t name_crc = (uint16_t)(fdb_calc_crc32(0, name, name_len) >> 16),
  187. min_activity = 0xFFFF;
  188. for (i = 0; i < FDB_KV_CACHE_TABLE_SIZE; i++) {
  189. if (addr != FDB_DATA_UNUSED) {
  190. /* update the KV address in cache */
  191. if (db->kv_cache_table[i].name_crc == name_crc) {
  192. db->kv_cache_table[i].addr = addr;
  193. return;
  194. } else if ((db->kv_cache_table[i].addr == FDB_DATA_UNUSED) &&
  195. (empty_index == FDB_KV_CACHE_TABLE_SIZE)) {
  196. empty_index = i;
  197. } else if (db->kv_cache_table[i].addr != FDB_DATA_UNUSED) {
  198. if (db->kv_cache_table[i].active > 0) {
  199. db->kv_cache_table[i].active--;
  200. }
  201. if (db->kv_cache_table[i].active < min_activity) {
  202. min_activity_index = i;
  203. min_activity = db->kv_cache_table[i].active;
  204. }
  205. }
  206. } else if (db->kv_cache_table[i].name_crc == name_crc) {
  207. /* delete the KV */
  208. db->kv_cache_table[i].addr = FDB_DATA_UNUSED;
  209. db->kv_cache_table[i].active = 0;
  210. return;
  211. }
  212. }
  213. /* add the KV to cache, using LRU (Least Recently Used) like algorithm */
  214. if (empty_index < FDB_KV_CACHE_TABLE_SIZE) {
  215. db->kv_cache_table[empty_index].addr = addr;
  216. db->kv_cache_table[empty_index].name_crc = name_crc;
  217. db->kv_cache_table[empty_index].active = FDB_KV_CACHE_TABLE_SIZE;
  218. } else if (min_activity_index < FDB_KV_CACHE_TABLE_SIZE) {
  219. db->kv_cache_table[min_activity_index].addr = addr;
  220. db->kv_cache_table[min_activity_index].name_crc = name_crc;
  221. db->kv_cache_table[min_activity_index].active = FDB_KV_CACHE_TABLE_SIZE;
  222. }
  223. }
  224. /*
  225. * Get KV info from cache. It's return pika_true when cache is hit.
  226. */
  227. static pika_bool get_kv_from_cache(fdb_kvdb_t db,
  228. const char* name,
  229. size_t name_len,
  230. uint32_t* addr) {
  231. size_t i;
  232. uint16_t name_crc = (uint16_t)(fdb_calc_crc32(0, name, name_len) >> 16);
  233. for (i = 0; i < FDB_KV_CACHE_TABLE_SIZE; i++) {
  234. if ((db->kv_cache_table[i].addr != FDB_DATA_UNUSED) &&
  235. (db->kv_cache_table[i].name_crc == name_crc)) {
  236. char saved_name[FDB_KV_NAME_MAX] = {0};
  237. /* read the KV name in flash */
  238. _fdb_flash_read((fdb_db_t)db,
  239. db->kv_cache_table[i].addr + KV_HDR_DATA_SIZE,
  240. (uint32_t*)saved_name, FDB_KV_NAME_MAX);
  241. if (!strncmp(name, saved_name, name_len)) {
  242. *addr = db->kv_cache_table[i].addr;
  243. if (db->kv_cache_table[i].active >=
  244. 0xFFFF - FDB_KV_CACHE_TABLE_SIZE) {
  245. db->kv_cache_table[i].active = 0xFFFF;
  246. } else {
  247. db->kv_cache_table[i].active += FDB_KV_CACHE_TABLE_SIZE;
  248. }
  249. return pika_true;
  250. }
  251. }
  252. }
  253. return pika_false;
  254. }
  255. #endif /* FDB_KV_USING_CACHE */
  256. /*
  257. * find the next KV address by magic word on the flash
  258. */
  259. static uint32_t find_next_kv_addr(fdb_kvdb_t db, uint32_t start, uint32_t end) {
  260. uint8_t buf[32];
  261. uint32_t start_bak = start, i;
  262. uint32_t magic;
  263. #ifdef FDB_KV_USING_CACHE
  264. uint32_t empty_kv;
  265. if (get_sector_from_cache(db, FDB_ALIGN_DOWN(start, db_sec_size(db)),
  266. &empty_kv) &&
  267. start == empty_kv) {
  268. return FAILED_ADDR;
  269. }
  270. #endif /* FDB_KV_USING_CACHE */
  271. for (; start < end && start + sizeof(buf) < end;
  272. start += (sizeof(buf) - sizeof(uint32_t))) {
  273. if (_fdb_flash_read((fdb_db_t)db, start, (uint32_t*)buf, sizeof(buf)) !=
  274. FDB_NO_ERR)
  275. return FAILED_ADDR;
  276. for (i = 0; i < sizeof(buf) - sizeof(uint32_t) && start + i < end;
  277. i++) {
  278. #ifndef FDB_BIG_ENDIAN /* Little Endian Order */
  279. magic = buf[i] + (buf[i + 1] << 8) + (buf[i + 2] << 16) +
  280. (buf[i + 3] << 24);
  281. #else /* Big Endian Order */
  282. magic = buf[i + 3] + (buf[i + 2] << 8) + (buf[i + 1] << 16) +
  283. (buf[i] << 24);
  284. #endif
  285. if (magic == KV_MAGIC_WORD &&
  286. (start + i - KV_MAGIC_OFFSET) >= start_bak) {
  287. return start + i - KV_MAGIC_OFFSET;
  288. }
  289. }
  290. }
  291. return FAILED_ADDR;
  292. }
  293. static uint32_t get_next_kv_addr(fdb_kvdb_t db,
  294. kv_sec_info_t sector,
  295. fdb_kv_t pre_kv) {
  296. uint32_t addr = FAILED_ADDR;
  297. if (sector->status.store == FDB_SECTOR_STORE_EMPTY) {
  298. return FAILED_ADDR;
  299. }
  300. if (pre_kv->addr.start == FAILED_ADDR) {
  301. /* the first KV address */
  302. addr = sector->addr + SECTOR_HDR_DATA_SIZE;
  303. } else {
  304. if (pre_kv->addr.start <= sector->addr + db_sec_size(db)) {
  305. if (pre_kv->crc_is_ok) {
  306. addr = pre_kv->addr.start + pre_kv->len;
  307. } else {
  308. /* when pre_kv CRC check failed, maybe the flash has error data
  309. * find_next_kv_addr after pre_kv address */
  310. addr = pre_kv->addr.start + FDB_WG_ALIGN(1);
  311. }
  312. /* check and find next KV address */
  313. addr = find_next_kv_addr(
  314. db, addr,
  315. sector->addr + db_sec_size(db) - SECTOR_HDR_DATA_SIZE);
  316. if (addr == FAILED_ADDR || addr > sector->addr + db_sec_size(db) ||
  317. pre_kv->len == 0) {
  318. // TODO Sector continuous mode
  319. return FAILED_ADDR;
  320. }
  321. } else {
  322. /* no KV */
  323. return FAILED_ADDR;
  324. }
  325. }
  326. return addr;
  327. }
  328. static fdb_err_t read_kv(fdb_kvdb_t db, fdb_kv_t kv) {
  329. struct kv_hdr_data kv_hdr;
  330. uint8_t buf[32];
  331. uint32_t calc_crc32 = 0, crc_data_len, kv_name_addr;
  332. fdb_err_t result = FDB_NO_ERR;
  333. size_t len, size;
  334. /* read KV header raw data */
  335. _fdb_flash_read((fdb_db_t)db, kv->addr.start, (uint32_t*)&kv_hdr,
  336. sizeof(struct kv_hdr_data));
  337. kv->status = (fdb_kv_status_t)_fdb_get_status(kv_hdr.status_table,
  338. FDB_KV_STATUS_NUM);
  339. kv->len = kv_hdr.len;
  340. if (kv->len == ~0UL || kv->len > db_max_size(db) ||
  341. kv->len < KV_HDR_DATA_SIZE) {
  342. /* the KV length was not write, so reserved the info for current KV */
  343. kv->len = KV_HDR_DATA_SIZE;
  344. if (kv->status != FDB_KV_ERR_HDR) {
  345. kv->status = FDB_KV_ERR_HDR;
  346. FDB_DEBUG("Error: The KV @0x%08" PRIX32 " length has an error.\n",
  347. kv->addr.start);
  348. _fdb_write_status((fdb_db_t)db, kv->addr.start, kv_hdr.status_table,
  349. FDB_KV_STATUS_NUM, FDB_KV_ERR_HDR, pika_true);
  350. }
  351. kv->crc_is_ok = pika_false;
  352. return FDB_READ_ERR;
  353. } else if (kv->len > db_sec_size(db) - SECTOR_HDR_DATA_SIZE &&
  354. kv->len < db_max_size(db)) {
  355. // TODO Sector continuous mode, or the write length is not written
  356. // completely
  357. FDB_ASSERT(0);
  358. }
  359. /* CRC32 data len(header.name_len + header.value_len + name + value), using
  360. * sizeof(uint32_t) for compatible V1.x */
  361. calc_crc32 = fdb_calc_crc32(calc_crc32, &kv_hdr.name_len, sizeof(uint32_t));
  362. calc_crc32 =
  363. fdb_calc_crc32(calc_crc32, &kv_hdr.value_len, sizeof(uint32_t));
  364. crc_data_len = kv->len - KV_HDR_DATA_SIZE;
  365. /* calculate the CRC32 value */
  366. for (len = 0, size = 0; len < crc_data_len; len += size) {
  367. if (len + sizeof(buf) < crc_data_len) {
  368. size = sizeof(buf);
  369. } else {
  370. size = crc_data_len - len;
  371. }
  372. _fdb_flash_read((fdb_db_t)db, kv->addr.start + KV_HDR_DATA_SIZE + len,
  373. (uint32_t*)buf, FDB_WG_ALIGN(size));
  374. calc_crc32 = fdb_calc_crc32(calc_crc32, buf, size);
  375. }
  376. /* check CRC32 */
  377. if (calc_crc32 != kv_hdr.crc32) {
  378. kv->crc_is_ok = pika_false;
  379. result = FDB_READ_ERR;
  380. } else {
  381. kv->crc_is_ok = pika_true;
  382. /* the name is behind aligned KV header */
  383. kv_name_addr = kv->addr.start + KV_HDR_DATA_SIZE;
  384. _fdb_flash_read((fdb_db_t)db, kv_name_addr, (uint32_t*)kv->name,
  385. FDB_WG_ALIGN(kv_hdr.name_len));
  386. /* the value is behind aligned name */
  387. kv->addr.value = kv_name_addr + FDB_WG_ALIGN(kv_hdr.name_len);
  388. kv->value_len = kv_hdr.value_len;
  389. kv->name_len = kv_hdr.name_len;
  390. if (kv_hdr.name_len >= sizeof(kv->name) / sizeof(kv->name[0])) {
  391. kv_hdr.name_len = sizeof(kv->name) / sizeof(kv->name[0]) - 1;
  392. }
  393. kv->name[kv_hdr.name_len] = '\0';
  394. }
  395. return result;
  396. }
  397. static fdb_err_t read_sector_info(fdb_kvdb_t db,
  398. uint32_t addr,
  399. kv_sec_info_t sector,
  400. pika_bool traversal) {
  401. fdb_err_t result = FDB_NO_ERR;
  402. struct sector_hdr_data sec_hdr = {0};
  403. FDB_ASSERT(addr % db_sec_size(db) == 0);
  404. FDB_ASSERT(sector);
  405. /* read sector header raw data */
  406. _fdb_flash_read((fdb_db_t)db, addr, (uint32_t*)&sec_hdr,
  407. sizeof(struct sector_hdr_data));
  408. sector->addr = addr;
  409. sector->magic = sec_hdr.magic;
  410. /* check magic word */
  411. if (sector->magic != SECTOR_MAGIC_WORD) {
  412. sector->check_ok = pika_false;
  413. sector->combined = SECTOR_NOT_COMBINED;
  414. return FDB_INIT_FAILED;
  415. }
  416. sector->check_ok = pika_true;
  417. /* get other sector info */
  418. sector->combined = sec_hdr.combined;
  419. sector->status.store = (fdb_sector_store_status_t)_fdb_get_status(
  420. sec_hdr.status_table.store, FDB_SECTOR_STORE_STATUS_NUM);
  421. sector->status.dirty = (fdb_sector_dirty_status_t)_fdb_get_status(
  422. sec_hdr.status_table.dirty, FDB_SECTOR_DIRTY_STATUS_NUM);
  423. /* traversal all KV and calculate the remain space size */
  424. if (traversal) {
  425. sector->remain = 0;
  426. sector->empty_kv = sector->addr + SECTOR_HDR_DATA_SIZE;
  427. if (sector->status.store == FDB_SECTOR_STORE_EMPTY) {
  428. sector->remain = db_sec_size(db) - SECTOR_HDR_DATA_SIZE;
  429. } else if (sector->status.store == FDB_SECTOR_STORE_USING) {
  430. struct fdb_kv kv_obj;
  431. #ifdef FDB_KV_USING_CACHE
  432. if (get_sector_from_cache(db, addr, &sector->empty_kv)) {
  433. sector->remain =
  434. db_sec_size(db) - (sector->empty_kv - sector->addr);
  435. return result;
  436. }
  437. #endif /* FDB_KV_USING_CACHE */
  438. sector->remain = db_sec_size(db) - SECTOR_HDR_DATA_SIZE;
  439. kv_obj.addr.start = sector->addr + SECTOR_HDR_DATA_SIZE;
  440. do {
  441. read_kv(db, &kv_obj);
  442. if (!kv_obj.crc_is_ok) {
  443. if (kv_obj.status != FDB_KV_PRE_WRITE &&
  444. kv_obj.status != FDB_KV_ERR_HDR) {
  445. FDB_INFO("Error: The KV (@0x%08" PRIX32
  446. ") CRC32 check failed!\n",
  447. kv_obj.addr.start);
  448. sector->remain = 0;
  449. result = FDB_READ_ERR;
  450. break;
  451. }
  452. }
  453. sector->empty_kv += kv_obj.len;
  454. sector->remain -= kv_obj.len;
  455. } while ((kv_obj.addr.start = get_next_kv_addr(
  456. db, sector, &kv_obj)) != FAILED_ADDR);
  457. /* check the empty KV address by read continue 0xFF on flash */
  458. {
  459. uint32_t ff_addr;
  460. ff_addr = _fdb_continue_ff_addr((fdb_db_t)db, sector->empty_kv,
  461. sector->addr + db_sec_size(db));
  462. /* check the flash data is clean */
  463. if (sector->empty_kv != ff_addr) {
  464. /* update the sector information */
  465. sector->empty_kv = ff_addr;
  466. sector->remain = db_sec_size(db) - (ff_addr - sector->addr);
  467. }
  468. }
  469. #ifdef FDB_KV_USING_CACHE
  470. update_sector_cache(db, sector->addr, sector->empty_kv);
  471. #endif
  472. }
  473. }
  474. return result;
  475. }
  476. static uint32_t get_next_sector_addr(fdb_kvdb_t db,
  477. kv_sec_info_t pre_sec,
  478. uint32_t traversed_len) {
  479. uint32_t cur_block_size;
  480. if (pre_sec->combined == SECTOR_NOT_COMBINED) {
  481. cur_block_size = db_sec_size(db);
  482. } else {
  483. cur_block_size = pre_sec->combined * db_sec_size(db);
  484. }
  485. if (traversed_len + cur_block_size <= db_max_size(db)) {
  486. /* if reach to the end, roll back to the first sector */
  487. if (pre_sec->addr + cur_block_size < db_max_size(db)) {
  488. return pre_sec->addr + cur_block_size;
  489. } else {
  490. /* the next sector is on the top of the database */
  491. return 0;
  492. }
  493. } else {
  494. /* finished */
  495. return FAILED_ADDR;
  496. }
  497. }
  498. static void kv_iterator(fdb_kvdb_t db,
  499. fdb_kv_t kv,
  500. void* arg1,
  501. void* arg2,
  502. pika_bool (*callback)(fdb_kv_t kv,
  503. void* arg1,
  504. void* arg2)) {
  505. struct kvdb_sec_info sector;
  506. uint32_t sec_addr, traversed_len = 0;
  507. sec_addr = db_oldest_addr(db);
  508. /* search all sectors */
  509. do {
  510. traversed_len += db_sec_size(db);
  511. if (read_sector_info(db, sec_addr, &sector, pika_false) != FDB_NO_ERR) {
  512. continue;
  513. }
  514. if (callback == NULL) {
  515. continue;
  516. }
  517. /* sector has KV */
  518. if (sector.status.store == FDB_SECTOR_STORE_USING ||
  519. sector.status.store == FDB_SECTOR_STORE_FULL) {
  520. kv->addr.start = sector.addr + SECTOR_HDR_DATA_SIZE;
  521. /* search all KV */
  522. do {
  523. read_kv(db, kv);
  524. /* iterator is interrupted when callback return pika_true */
  525. if (callback(kv, arg1, arg2)) {
  526. return;
  527. }
  528. } while ((kv->addr.start = get_next_kv_addr(db, &sector, kv)) !=
  529. FAILED_ADDR);
  530. }
  531. } while ((sec_addr = get_next_sector_addr(db, &sector, traversed_len)) !=
  532. FAILED_ADDR);
  533. }
  534. static pika_bool find_kv_cb(fdb_kv_t kv, void* arg1, void* arg2) {
  535. const char* key = arg1;
  536. pika_bool* find_ok = arg2;
  537. size_t key_len = strlen(key);
  538. if (key_len != kv->name_len) {
  539. return pika_false;
  540. }
  541. /* check KV */
  542. if (kv->crc_is_ok && kv->status == FDB_KV_WRITE &&
  543. !strncmp(kv->name, key, key_len)) {
  544. *find_ok = pika_true;
  545. return pika_true;
  546. }
  547. return pika_false;
  548. }
  549. static pika_bool find_kv_no_cache(fdb_kvdb_t db, const char* key, fdb_kv_t kv) {
  550. pika_bool find_ok = pika_false;
  551. kv_iterator(db, kv, (void*)key, &find_ok, find_kv_cb);
  552. return find_ok;
  553. }
  554. static pika_bool find_kv(fdb_kvdb_t db, const char* key, fdb_kv_t kv) {
  555. pika_bool find_ok = pika_false;
  556. #ifdef FDB_KV_USING_CACHE
  557. size_t key_len = strlen(key);
  558. if (get_kv_from_cache(db, key, key_len, &kv->addr.start)) {
  559. read_kv(db, kv);
  560. return pika_true;
  561. }
  562. #endif /* FDB_KV_USING_CACHE */
  563. find_ok = find_kv_no_cache(db, key, kv);
  564. #ifdef FDB_KV_USING_CACHE
  565. if (find_ok) {
  566. update_kv_cache(db, key, key_len, kv->addr.start);
  567. }
  568. #endif /* FDB_KV_USING_CACHE */
  569. return find_ok;
  570. }
  571. static pika_bool fdb_is_str(uint8_t* value, size_t len) {
  572. #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
  573. size_t i;
  574. for (i = 0; i < len; i++) {
  575. if (!__is_print(value[i])) {
  576. return pika_false;
  577. }
  578. }
  579. return pika_true;
  580. }
  581. static size_t get_kv(fdb_kvdb_t db,
  582. const char* key,
  583. void* value_buf,
  584. size_t buf_len,
  585. size_t* value_len) {
  586. struct fdb_kv kv;
  587. size_t read_len = 0;
  588. if (find_kv(db, key, &kv)) {
  589. if (value_len) {
  590. *value_len = kv.value_len;
  591. }
  592. if (buf_len > kv.value_len) {
  593. read_len = kv.value_len;
  594. } else {
  595. read_len = buf_len;
  596. }
  597. if (value_buf) {
  598. _fdb_flash_read((fdb_db_t)db, kv.addr.value, (uint32_t*)value_buf,
  599. read_len);
  600. }
  601. } else if (value_len) {
  602. *value_len = 0;
  603. }
  604. return read_len;
  605. }
  606. /**
  607. * Get a KV object by key name
  608. *
  609. * @param db database object
  610. * @param key KV name
  611. * @param kv KV object
  612. *
  613. * @return KV object when is not NULL
  614. */
  615. fdb_kv_t fdb_kv_get_obj(fdb_kvdb_t db, const char* key, fdb_kv_t kv) {
  616. pika_bool find_ok = pika_false;
  617. if (!db_init_ok(db)) {
  618. FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db));
  619. return 0;
  620. }
  621. /* lock the KV cache */
  622. db_lock(db);
  623. find_ok = find_kv(db, key, kv);
  624. /* unlock the KV cache */
  625. db_unlock(db);
  626. return find_ok ? kv : NULL;
  627. }
  628. /**
  629. * Convert the KV object to blob object
  630. *
  631. * @param kv KV object
  632. * @param blob blob object
  633. *
  634. * @return new blob object
  635. */
  636. fdb_blob_t fdb_kv_to_blob(fdb_kv_t kv, fdb_blob_t blob) {
  637. blob->saved.meta_addr = kv->addr.start;
  638. blob->saved.addr = kv->addr.value;
  639. blob->saved.len = kv->value_len;
  640. return blob;
  641. }
  642. /**
  643. * Get a blob KV value by key name.
  644. *
  645. * @param db database object
  646. * @param key KV name
  647. * @param blob blob object
  648. *
  649. * @return the actually get size on successful
  650. */
  651. size_t fdb_kv_get_blob(fdb_kvdb_t db, const char* key, fdb_blob_t blob) {
  652. size_t read_len = 0;
  653. if (!db_init_ok(db)) {
  654. FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db));
  655. return 0;
  656. }
  657. /* lock the KV cache */
  658. db_lock(db);
  659. read_len = get_kv(db, key, blob->buf, blob->size, &blob->saved.len);
  660. /* unlock the KV cache */
  661. db_unlock(db);
  662. return read_len;
  663. }
  664. /**
  665. * Get an KV value by key name.
  666. *
  667. * @note this function is NOT supported reentrant
  668. * @note this function is DEPRECATED
  669. *
  670. * @param db database object
  671. * @param key KV name
  672. *
  673. * @return value
  674. */
  675. char* fdb_kv_get(fdb_kvdb_t db, const char* key) {
  676. static char value[FDB_STR_KV_VALUE_MAX_SIZE + 1];
  677. size_t get_size;
  678. struct fdb_blob blob;
  679. if ((get_size = fdb_kv_get_blob(
  680. db, key, fdb_blob_make(&blob, value, FDB_STR_KV_VALUE_MAX_SIZE))) >
  681. 0) {
  682. /* the return value must be string */
  683. if (fdb_is_str((uint8_t*)value, get_size)) {
  684. value[get_size] = '\0';
  685. return value;
  686. } else if (blob.saved.len > FDB_STR_KV_VALUE_MAX_SIZE) {
  687. FDB_INFO(
  688. "Warning: The default string KV value buffer length "
  689. "(%" PRIdLEAST16 ") is too less (%" PRIu32 ").\n",
  690. FDB_STR_KV_VALUE_MAX_SIZE, (uint32_t)blob.saved.len);
  691. } else {
  692. FDB_INFO(
  693. "Warning: The KV value isn't string. Could not be returned\n");
  694. return NULL;
  695. }
  696. }
  697. return NULL;
  698. }
  699. static fdb_err_t write_kv_hdr(fdb_kvdb_t db,
  700. uint32_t addr,
  701. kv_hdr_data_t kv_hdr) {
  702. fdb_err_t result = FDB_NO_ERR;
  703. /* write the status will by write granularity */
  704. result = _fdb_write_status((fdb_db_t)db, addr, kv_hdr->status_table,
  705. FDB_KV_STATUS_NUM, FDB_KV_PRE_WRITE, pika_false);
  706. if (result != FDB_NO_ERR) {
  707. return result;
  708. }
  709. /* write other header data */
  710. result = _fdb_flash_write(
  711. (fdb_db_t)db, addr + KV_MAGIC_OFFSET, &kv_hdr->magic,
  712. sizeof(struct kv_hdr_data) - KV_MAGIC_OFFSET, pika_false);
  713. return result;
  714. }
  715. static fdb_err_t format_sector(fdb_kvdb_t db,
  716. uint32_t addr,
  717. uint32_t combined_value) {
  718. fdb_err_t result = FDB_NO_ERR;
  719. struct sector_hdr_data sec_hdr = {0};
  720. FDB_ASSERT(addr % db_sec_size(db) == 0);
  721. result = _fdb_flash_erase((fdb_db_t)db, addr, db_sec_size(db));
  722. if (result == FDB_NO_ERR) {
  723. /* initialize the header data */
  724. memset(&sec_hdr, FDB_BYTE_ERASED, sizeof(struct sector_hdr_data));
  725. #if (FDB_WRITE_GRAN == 1)
  726. _fdb_set_status(sec_hdr.status_table.store, FDB_SECTOR_STORE_STATUS_NUM,
  727. FDB_SECTOR_STORE_EMPTY);
  728. _fdb_set_status(sec_hdr.status_table.dirty, FDB_SECTOR_DIRTY_STATUS_NUM,
  729. FDB_SECTOR_DIRTY_FALSE);
  730. sec_hdr.magic = SECTOR_MAGIC_WORD;
  731. sec_hdr.combined = combined_value;
  732. sec_hdr.reserved = FDB_DATA_UNUSED;
  733. /* save the header */
  734. result = _fdb_flash_write((fdb_db_t)db, addr, (uint32_t*)&sec_hdr,
  735. SECTOR_HDR_DATA_SIZE, pika_true);
  736. #else // seperate the whole "sec_hdr" program to serval sinle program operation
  737. // to prevent re-program issue on STM32L4xx or other MCU internal flash
  738. /* write the sector store status */
  739. _fdb_write_status((fdb_db_t)db, addr + SECTOR_STORE_OFFSET,
  740. sec_hdr.status_table.store,
  741. FDB_SECTOR_STORE_STATUS_NUM, FDB_SECTOR_STORE_EMPTY,
  742. pika_true);
  743. /* write the sector dirty status */
  744. _fdb_write_status((fdb_db_t)db, addr + SECTOR_DIRTY_OFFSET,
  745. sec_hdr.status_table.dirty,
  746. FDB_SECTOR_DIRTY_STATUS_NUM, FDB_SECTOR_DIRTY_FALSE,
  747. pika_true);
  748. /* write the magic word and combined next sector number */
  749. sec_hdr.magic = SECTOR_MAGIC_WORD;
  750. sec_hdr.combined = combined_value;
  751. sec_hdr.reserved = FDB_DATA_UNUSED;
  752. result = _fdb_flash_write(
  753. (fdb_db_t)db, addr + SECTOR_MAGIC_OFFSET, (void*)(&(sec_hdr.magic)),
  754. (sizeof(struct sector_hdr_data) - SECTOR_MAGIC_OFFSET), pika_true);
  755. #endif
  756. #ifdef FDB_KV_USING_CACHE
  757. /* delete the sector cache */
  758. update_sector_cache(db, addr, addr + db_sec_size(db));
  759. #endif /* FDB_KV_USING_CACHE */
  760. }
  761. return result;
  762. }
  763. static fdb_err_t update_sec_status(fdb_kvdb_t db,
  764. kv_sec_info_t sector,
  765. size_t new_kv_len,
  766. pika_bool* is_full) {
  767. uint8_t status_table[FDB_STORE_STATUS_TABLE_SIZE];
  768. fdb_err_t result = FDB_NO_ERR;
  769. /* change the current sector status */
  770. if (sector->status.store == FDB_SECTOR_STORE_EMPTY) {
  771. /* change the sector status to using */
  772. result = _fdb_write_status((fdb_db_t)db, sector->addr, status_table,
  773. FDB_SECTOR_STORE_STATUS_NUM,
  774. FDB_SECTOR_STORE_USING, pika_true);
  775. } else if (sector->status.store == FDB_SECTOR_STORE_USING) {
  776. /* check remain size */
  777. if (sector->remain < FDB_SEC_REMAIN_THRESHOLD ||
  778. sector->remain - new_kv_len < FDB_SEC_REMAIN_THRESHOLD) {
  779. /* change the sector status to full */
  780. result = _fdb_write_status((fdb_db_t)db, sector->addr, status_table,
  781. FDB_SECTOR_STORE_STATUS_NUM,
  782. FDB_SECTOR_STORE_FULL, pika_true);
  783. #ifdef FDB_KV_USING_CACHE
  784. /* delete the sector cache */
  785. update_sector_cache(db, sector->addr,
  786. sector->addr + db_sec_size(db));
  787. #endif /* FDB_KV_USING_CACHE */
  788. if (is_full) {
  789. *is_full = pika_true;
  790. }
  791. } else if (is_full) {
  792. *is_full = pika_false;
  793. }
  794. }
  795. return result;
  796. }
  797. static void sector_iterator(fdb_kvdb_t db,
  798. kv_sec_info_t sector,
  799. fdb_sector_store_status_t status,
  800. void* arg1,
  801. void* arg2,
  802. pika_bool (*callback)(kv_sec_info_t sector,
  803. void* arg1,
  804. void* arg2),
  805. pika_bool traversal_kv) {
  806. uint32_t sec_addr, traversed_len = 0;
  807. /* search all sectors */
  808. sec_addr = db_oldest_addr(db);
  809. do {
  810. traversed_len += db_sec_size(db);
  811. if (FDB_NO_ERR != read_sector_info(db, sec_addr, sector, pika_false)) {
  812. #ifndef FDB_USING_FILE_MODE
  813. FDB_PRINT("Error: Read sector info failed.\n");
  814. return;
  815. #endif
  816. }
  817. if (status == FDB_SECTOR_STORE_UNUSED ||
  818. status == sector->status.store) {
  819. if (traversal_kv) {
  820. if (FDB_NO_ERR !=
  821. read_sector_info(db, sec_addr, sector, pika_true)) {
  822. return;
  823. }
  824. }
  825. /* iterator is interrupted when callback return pika_true */
  826. if (callback && callback(sector, arg1, arg2)) {
  827. return;
  828. }
  829. }
  830. } while ((sec_addr = get_next_sector_addr(db, sector, traversed_len)) !=
  831. FAILED_ADDR);
  832. }
  833. static pika_bool sector_statistics_cb(kv_sec_info_t sector,
  834. void* arg1,
  835. void* arg2) {
  836. size_t *empty_sector = arg1, *using_sector = arg2;
  837. if (sector->check_ok && sector->status.store == FDB_SECTOR_STORE_EMPTY) {
  838. (*empty_sector)++;
  839. } else if (sector->check_ok &&
  840. sector->status.store == FDB_SECTOR_STORE_USING) {
  841. (*using_sector)++;
  842. }
  843. return pika_false;
  844. }
  845. static pika_bool alloc_kv_cb(kv_sec_info_t sector, void* arg1, void* arg2) {
  846. struct alloc_kv_cb_args* arg = arg1;
  847. /* 1. sector has space
  848. * 2. the NO dirty sector
  849. * 3. the dirty sector only when the gc_request is pika_false */
  850. if (sector->check_ok && sector->remain > arg->kv_size &&
  851. ((sector->status.dirty == FDB_SECTOR_DIRTY_FALSE) ||
  852. (sector->status.dirty == FDB_SECTOR_DIRTY_TRUE &&
  853. !arg->db->gc_request))) {
  854. *(arg->empty_kv) = sector->empty_kv;
  855. return pika_true;
  856. }
  857. return pika_false;
  858. }
  859. static uint32_t alloc_kv(fdb_kvdb_t db, kv_sec_info_t sector, size_t kv_size) {
  860. uint32_t empty_kv = FAILED_ADDR;
  861. size_t empty_sector = 0, using_sector = 0;
  862. struct alloc_kv_cb_args arg = {db, kv_size, &empty_kv};
  863. /* sector status statistics */
  864. sector_iterator(db, sector, FDB_SECTOR_STORE_UNUSED, &empty_sector,
  865. &using_sector, sector_statistics_cb, pika_false);
  866. if (using_sector > 0) {
  867. /* alloc the KV from the using status sector first */
  868. sector_iterator(db, sector, FDB_SECTOR_STORE_USING, &arg, NULL,
  869. alloc_kv_cb, pika_true);
  870. }
  871. if (empty_sector > 0 && empty_kv == FAILED_ADDR) {
  872. if (empty_sector > FDB_GC_EMPTY_SEC_THRESHOLD || db->gc_request) {
  873. sector_iterator(db, sector, FDB_SECTOR_STORE_EMPTY, &arg, NULL,
  874. alloc_kv_cb, pika_true);
  875. } else {
  876. /* no space for new KV now will GC and retry */
  877. FDB_DEBUG("Trigger a GC check after alloc KV failed.\n");
  878. db->gc_request = pika_true;
  879. }
  880. }
  881. return empty_kv;
  882. }
  883. static fdb_err_t del_kv(fdb_kvdb_t db,
  884. const char* key,
  885. fdb_kv_t old_kv,
  886. pika_bool complete_del) {
  887. fdb_err_t result = FDB_NO_ERR;
  888. uint32_t dirty_status_addr;
  889. struct fdb_kv kv = {0};
  890. #if (KV_STATUS_TABLE_SIZE >= FDB_DIRTY_STATUS_TABLE_SIZE)
  891. uint8_t status_table[KV_STATUS_TABLE_SIZE];
  892. #else
  893. uint8_t status_table[DIRTY_STATUS_TABLE_SIZE];
  894. #endif
  895. /* need find KV */
  896. if (!old_kv) {
  897. /* find KV */
  898. if (find_kv(db, key, &kv)) {
  899. old_kv = &kv;
  900. } else {
  901. FDB_DEBUG("Not found '%s' in KV.\n", key);
  902. return FDB_KV_NAME_ERR;
  903. }
  904. }
  905. /* change and save the new status */
  906. if (!complete_del) {
  907. result =
  908. _fdb_write_status((fdb_db_t)db, old_kv->addr.start, status_table,
  909. FDB_KV_STATUS_NUM, FDB_KV_PRE_DELETE, pika_false);
  910. db->last_is_complete_del = pika_true;
  911. } else {
  912. result =
  913. _fdb_write_status((fdb_db_t)db, old_kv->addr.start, status_table,
  914. FDB_KV_STATUS_NUM, FDB_KV_DELETED, pika_true);
  915. if (!db->last_is_complete_del && result == FDB_NO_ERR) {
  916. #ifdef FDB_KV_USING_CACHE
  917. /* delete the KV in flash and cache */
  918. if (key != NULL) {
  919. /* when using del_kv(db, key, NULL, pika_true) or del_kv(db,
  920. * key, kv, pika_true) in fdb_del_kv(db, ) and set_kv(db, ) */
  921. update_kv_cache(db, key, strlen(key), FDB_DATA_UNUSED);
  922. } else if (old_kv != NULL) {
  923. /* when using del_kv(db, NULL, kv, pika_true) in move_kv(db, )
  924. */
  925. update_kv_cache(db, old_kv->name, old_kv->name_len,
  926. FDB_DATA_UNUSED);
  927. }
  928. #endif /* FDB_KV_USING_CACHE */
  929. }
  930. db->last_is_complete_del = pika_false;
  931. }
  932. dirty_status_addr = FDB_ALIGN_DOWN(old_kv->addr.start, db_sec_size(db)) +
  933. SECTOR_DIRTY_OFFSET;
  934. /* read and change the sector dirty status */
  935. if (result == FDB_NO_ERR &&
  936. _fdb_read_status((fdb_db_t)db, dirty_status_addr, status_table,
  937. FDB_SECTOR_DIRTY_STATUS_NUM) ==
  938. FDB_SECTOR_DIRTY_FALSE) {
  939. result = _fdb_write_status((fdb_db_t)db, dirty_status_addr,
  940. status_table, FDB_SECTOR_DIRTY_STATUS_NUM,
  941. FDB_SECTOR_DIRTY_TRUE, pika_true);
  942. }
  943. return result;
  944. }
  945. /*
  946. * move the KV to new space
  947. */
  948. static fdb_err_t move_kv(fdb_kvdb_t db, fdb_kv_t kv) {
  949. fdb_err_t result = FDB_NO_ERR;
  950. uint8_t status_table[KV_STATUS_TABLE_SIZE];
  951. uint32_t kv_addr;
  952. struct kvdb_sec_info sector;
  953. /* prepare to delete the current KV */
  954. if (kv->status == FDB_KV_WRITE) {
  955. del_kv(db, NULL, kv, pika_false);
  956. }
  957. if ((kv_addr = alloc_kv(db, &sector, kv->len)) != FAILED_ADDR) {
  958. if (db->in_recovery_check) {
  959. struct fdb_kv kv_bak;
  960. char name[FDB_KV_NAME_MAX + 1] = {0};
  961. strncpy(name, kv->name, kv->name_len);
  962. /* check the KV in flash is already create success */
  963. if (find_kv_no_cache(db, name, &kv_bak)) {
  964. /* already create success, don't need to duplicate */
  965. result = FDB_NO_ERR;
  966. goto __exit;
  967. }
  968. }
  969. } else {
  970. return FDB_SAVED_FULL;
  971. }
  972. /* start move the KV */
  973. {
  974. uint8_t buf[32];
  975. size_t len, size, kv_len = kv->len;
  976. /* update the new KV sector status first */
  977. update_sec_status(db, &sector, kv->len, NULL);
  978. _fdb_write_status((fdb_db_t)db, kv_addr, status_table,
  979. FDB_KV_STATUS_NUM, FDB_KV_PRE_WRITE, pika_false);
  980. kv_len -= KV_MAGIC_OFFSET;
  981. for (len = 0, size = 0; len < kv_len; len += size) {
  982. if (len + sizeof(buf) < kv_len) {
  983. size = sizeof(buf);
  984. } else {
  985. size = kv_len - len;
  986. }
  987. _fdb_flash_read((fdb_db_t)db,
  988. kv->addr.start + KV_MAGIC_OFFSET + len,
  989. (uint32_t*)buf, FDB_WG_ALIGN(size));
  990. result =
  991. _fdb_flash_write((fdb_db_t)db, kv_addr + KV_MAGIC_OFFSET + len,
  992. (uint32_t*)buf, size, pika_true);
  993. }
  994. _fdb_write_status((fdb_db_t)db, kv_addr, status_table,
  995. FDB_KV_STATUS_NUM, FDB_KV_WRITE, pika_true);
  996. #ifdef FDB_KV_USING_CACHE
  997. update_sector_cache(db, FDB_ALIGN_DOWN(kv_addr, db_sec_size(db)),
  998. kv_addr + KV_HDR_DATA_SIZE +
  999. FDB_WG_ALIGN(kv->name_len) +
  1000. FDB_WG_ALIGN(kv->value_len));
  1001. update_kv_cache(db, kv->name, kv->name_len, kv_addr);
  1002. #endif /* FDB_KV_USING_CACHE */
  1003. }
  1004. FDB_DEBUG("Moved the KV (%.*s) from 0x%08" PRIX32 " to 0x%08" PRIX32 ".\n",
  1005. kv->name_len, kv->name, kv->addr.start, kv_addr);
  1006. __exit:
  1007. del_kv(db, NULL, kv, pika_true);
  1008. return result;
  1009. }
  1010. static uint32_t new_kv(fdb_kvdb_t db, kv_sec_info_t sector, size_t kv_size) {
  1011. pika_bool already_gc = pika_false;
  1012. uint32_t empty_kv = FAILED_ADDR;
  1013. __retry:
  1014. if ((empty_kv = alloc_kv(db, sector, kv_size)) == FAILED_ADDR) {
  1015. if (db->gc_request && !already_gc) {
  1016. FDB_DEBUG("Warning: Alloc an KV (size %" PRIu32
  1017. ") failed when new KV. Now will GC then retry.\n",
  1018. (uint32_t)kv_size);
  1019. gc_collect_by_free_size(db, kv_size);
  1020. already_gc = pika_true;
  1021. goto __retry;
  1022. } else if (already_gc) {
  1023. FDB_DEBUG("Error: Alloc an KV (size %" PRIuLEAST16
  1024. ") failed after GC. KV full.\n",
  1025. kv_size);
  1026. db->gc_request = pika_false;
  1027. }
  1028. }
  1029. return empty_kv;
  1030. }
  1031. static uint32_t new_kv_ex(fdb_kvdb_t db,
  1032. kv_sec_info_t sector,
  1033. size_t key_len,
  1034. size_t buf_len) {
  1035. size_t kv_len =
  1036. KV_HDR_DATA_SIZE + FDB_WG_ALIGN(key_len) + FDB_WG_ALIGN(buf_len);
  1037. return new_kv(db, sector, kv_len);
  1038. }
  1039. static pika_bool gc_check_cb(kv_sec_info_t sector, void* arg1, void* arg2) {
  1040. size_t* empty_sec = arg1;
  1041. if (sector->check_ok) {
  1042. *empty_sec = *empty_sec + 1;
  1043. }
  1044. return pika_false;
  1045. }
  1046. static pika_bool do_gc(kv_sec_info_t sector, void* arg1, void* arg2) {
  1047. struct fdb_kv kv;
  1048. struct gc_cb_args* gc = (struct gc_cb_args*)arg1;
  1049. fdb_kvdb_t db = gc->db;
  1050. gc->traversed_len += db_sec_size(db);
  1051. if (sector->check_ok && (sector->status.dirty == FDB_SECTOR_DIRTY_TRUE ||
  1052. sector->status.dirty == FDB_SECTOR_DIRTY_GC)) {
  1053. uint8_t status_table[FDB_DIRTY_STATUS_TABLE_SIZE];
  1054. /* change the sector status to GC */
  1055. _fdb_write_status((fdb_db_t)db, sector->addr + SECTOR_DIRTY_OFFSET,
  1056. status_table, FDB_SECTOR_DIRTY_STATUS_NUM,
  1057. FDB_SECTOR_DIRTY_GC, pika_true);
  1058. /* search all KV */
  1059. kv.addr.start = sector->addr + SECTOR_HDR_DATA_SIZE;
  1060. do {
  1061. read_kv(db, &kv);
  1062. if (kv.crc_is_ok &&
  1063. (kv.status == FDB_KV_WRITE || kv.status == FDB_KV_PRE_DELETE)) {
  1064. /* move the KV to new space */
  1065. if (move_kv(db, &kv) != FDB_NO_ERR) {
  1066. FDB_DEBUG("Error: Moved the KV (%.*s) for GC failed.\n",
  1067. kv.name_len, kv.name);
  1068. }
  1069. }
  1070. } while ((kv.addr.start = get_next_kv_addr(db, sector, &kv)) !=
  1071. FAILED_ADDR);
  1072. format_sector(db, sector->addr, SECTOR_NOT_COMBINED);
  1073. gc->cur_free_size += db_sec_size(db) - SECTOR_HDR_DATA_SIZE;
  1074. FDB_DEBUG("Collect a sector @0x%08" PRIX32 "\n", sector->addr);
  1075. /* update oldest_addr for next GC sector format */
  1076. db_oldest_addr(db) =
  1077. get_next_sector_addr(db, sector, gc->traversed_len);
  1078. if (gc->cur_free_size >= gc->setting_free_size)
  1079. return pika_true;
  1080. }
  1081. return pika_false;
  1082. }
  1083. static void gc_collect_by_free_size(fdb_kvdb_t db, size_t free_size) {
  1084. struct kvdb_sec_info sector;
  1085. size_t empty_sec = 0;
  1086. struct gc_cb_args arg = {db, 0, free_size, 0};
  1087. /* GC check the empty sector number */
  1088. sector_iterator(db, &sector, FDB_SECTOR_STORE_EMPTY, &empty_sec, NULL,
  1089. gc_check_cb, pika_false);
  1090. /* do GC collect */
  1091. FDB_DEBUG("The remain empty sector is %" PRIu32
  1092. ", GC threshold is %" PRIdLEAST16 ".\n",
  1093. (uint32_t)empty_sec, FDB_GC_EMPTY_SEC_THRESHOLD);
  1094. if (empty_sec <= FDB_GC_EMPTY_SEC_THRESHOLD) {
  1095. sector_iterator(db, &sector, FDB_SECTOR_STORE_UNUSED, &arg, NULL, do_gc,
  1096. pika_false);
  1097. }
  1098. db->gc_request = pika_false;
  1099. }
  1100. /*
  1101. * The GC will be triggered on the following scene:
  1102. * 1. alloc an KV when the flash not has enough space
  1103. * 2. write an KV then the flash not has enough space
  1104. */
  1105. static void gc_collect(fdb_kvdb_t db) {
  1106. gc_collect_by_free_size(db, db_max_size(db));
  1107. }
  1108. static fdb_err_t align_write(fdb_kvdb_t db,
  1109. uint32_t addr,
  1110. const uint32_t* buf,
  1111. size_t size) {
  1112. fdb_err_t result = FDB_NO_ERR;
  1113. size_t align_remain;
  1114. #if (FDB_WRITE_GRAN / 8 > 0)
  1115. uint8_t align_data[FDB_WRITE_GRAN / 8];
  1116. size_t align_data_size = sizeof(align_data);
  1117. #else
  1118. /* For compatibility with C89 */
  1119. uint8_t align_data_u8, *align_data = &align_data_u8;
  1120. size_t align_data_size = 1;
  1121. #endif
  1122. memset(align_data, FDB_BYTE_ERASED, align_data_size);
  1123. result = _fdb_flash_write((fdb_db_t)db, addr, buf, FDB_WG_ALIGN_DOWN(size),
  1124. pika_false);
  1125. align_remain = size - FDB_WG_ALIGN_DOWN(size);
  1126. if (result == FDB_NO_ERR && align_remain) {
  1127. memcpy(align_data, (uint8_t*)buf + FDB_WG_ALIGN_DOWN(size),
  1128. align_remain);
  1129. result = _fdb_flash_write((fdb_db_t)db, addr + FDB_WG_ALIGN_DOWN(size),
  1130. (uint32_t*)align_data, align_data_size,
  1131. pika_false);
  1132. }
  1133. return result;
  1134. }
  1135. static fdb_err_t create_kv_blob(fdb_kvdb_t db,
  1136. kv_sec_info_t sector,
  1137. const char* key,
  1138. const void* value,
  1139. size_t len) {
  1140. fdb_err_t result = FDB_NO_ERR;
  1141. struct kv_hdr_data kv_hdr;
  1142. pika_bool is_full = pika_false;
  1143. uint32_t kv_addr = sector->empty_kv;
  1144. if (strlen(key) > FDB_KV_NAME_MAX) {
  1145. FDB_INFO("Error: The KV name length is more than %d\n",
  1146. FDB_KV_NAME_MAX);
  1147. return FDB_KV_NAME_ERR;
  1148. }
  1149. memset(&kv_hdr, FDB_BYTE_ERASED, sizeof(struct kv_hdr_data));
  1150. kv_hdr.magic = KV_MAGIC_WORD;
  1151. kv_hdr.name_len = strlen(key);
  1152. kv_hdr.value_len = len;
  1153. kv_hdr.len = KV_HDR_DATA_SIZE + FDB_WG_ALIGN(kv_hdr.name_len) +
  1154. FDB_WG_ALIGN(kv_hdr.value_len);
  1155. if (kv_hdr.len > db_sec_size(db) - SECTOR_HDR_DATA_SIZE) {
  1156. FDB_INFO("Error: The KV size is too big\n");
  1157. return FDB_SAVED_FULL;
  1158. }
  1159. if (kv_addr != FAILED_ADDR ||
  1160. (kv_addr = new_kv(db, sector, kv_hdr.len)) != FAILED_ADDR) {
  1161. size_t align_remain;
  1162. /* update the sector status */
  1163. if (result == FDB_NO_ERR) {
  1164. result = update_sec_status(db, sector, kv_hdr.len, &is_full);
  1165. }
  1166. if (result == FDB_NO_ERR) {
  1167. uint8_t ff = FDB_BYTE_ERASED;
  1168. /* start calculate CRC32 */
  1169. kv_hdr.crc32 = 0;
  1170. /* CRC32(header.name_len + header.value_len + name + value), using
  1171. * sizeof(uint32_t) for compatible V1.x */
  1172. kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, &kv_hdr.name_len,
  1173. sizeof(uint32_t));
  1174. kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, &kv_hdr.value_len,
  1175. sizeof(uint32_t));
  1176. kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, key, kv_hdr.name_len);
  1177. align_remain = FDB_WG_ALIGN(kv_hdr.name_len) - kv_hdr.name_len;
  1178. while (align_remain--) {
  1179. kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, &ff, 1);
  1180. }
  1181. kv_hdr.crc32 =
  1182. fdb_calc_crc32(kv_hdr.crc32, value, kv_hdr.value_len);
  1183. align_remain = FDB_WG_ALIGN(kv_hdr.value_len) - kv_hdr.value_len;
  1184. while (align_remain--) {
  1185. kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, &ff, 1);
  1186. }
  1187. /* write KV header data */
  1188. result = write_kv_hdr(db, kv_addr, &kv_hdr);
  1189. }
  1190. /* write key name */
  1191. if (result == FDB_NO_ERR) {
  1192. result = align_write(db, kv_addr + KV_HDR_DATA_SIZE, (uint32_t*)key,
  1193. kv_hdr.name_len);
  1194. #ifdef FDB_KV_USING_CACHE
  1195. if (!is_full) {
  1196. update_sector_cache(db, sector->addr,
  1197. kv_addr + KV_HDR_DATA_SIZE +
  1198. FDB_WG_ALIGN(kv_hdr.name_len) +
  1199. FDB_WG_ALIGN(kv_hdr.value_len));
  1200. }
  1201. update_kv_cache(db, key, kv_hdr.name_len, kv_addr);
  1202. #endif /* FDB_KV_USING_CACHE */
  1203. }
  1204. /* write value */
  1205. if (result == FDB_NO_ERR) {
  1206. result = align_write(
  1207. db, kv_addr + KV_HDR_DATA_SIZE + FDB_WG_ALIGN(kv_hdr.name_len),
  1208. value, kv_hdr.value_len);
  1209. }
  1210. /* change the KV status to KV_WRITE */
  1211. if (result == FDB_NO_ERR) {
  1212. result =
  1213. _fdb_write_status((fdb_db_t)db, kv_addr, kv_hdr.status_table,
  1214. FDB_KV_STATUS_NUM, FDB_KV_WRITE, pika_true);
  1215. }
  1216. /* trigger GC collect when current sector is full */
  1217. if (result == FDB_NO_ERR && is_full) {
  1218. FDB_DEBUG("Trigger a GC check after created KV.\n");
  1219. db->gc_request = pika_true;
  1220. }
  1221. } else {
  1222. result = FDB_SAVED_FULL;
  1223. }
  1224. return result;
  1225. }
  1226. /**
  1227. * Delete an KV.
  1228. *
  1229. * @param db database object
  1230. * @param key KV name
  1231. *
  1232. * @return result
  1233. */
  1234. fdb_err_t fdb_kv_del(fdb_kvdb_t db, const char* key) {
  1235. fdb_err_t result = FDB_NO_ERR;
  1236. if (!db_init_ok(db)) {
  1237. FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db));
  1238. return FDB_INIT_FAILED;
  1239. }
  1240. /* lock the KV cache */
  1241. db_lock(db);
  1242. result = del_kv(db, key, NULL, pika_true);
  1243. /* unlock the KV cache */
  1244. db_unlock(db);
  1245. return result;
  1246. }
  1247. static fdb_err_t set_kv(fdb_kvdb_t db,
  1248. const char* key,
  1249. const void* value_buf,
  1250. size_t buf_len) {
  1251. fdb_err_t result = FDB_NO_ERR;
  1252. pika_bool kv_is_found = pika_false;
  1253. if (value_buf == NULL) {
  1254. result = del_kv(db, key, NULL, pika_true);
  1255. } else {
  1256. /* make sure the flash has enough space */
  1257. if (new_kv_ex(db, &db->cur_sector, strlen(key), buf_len) ==
  1258. FAILED_ADDR) {
  1259. return FDB_SAVED_FULL;
  1260. }
  1261. kv_is_found = find_kv(db, key, &db->cur_kv);
  1262. /* prepare to delete the old KV */
  1263. if (kv_is_found) {
  1264. result = del_kv(db, key, &db->cur_kv, pika_false);
  1265. }
  1266. /* create the new KV */
  1267. if (result == FDB_NO_ERR) {
  1268. result =
  1269. create_kv_blob(db, &db->cur_sector, key, value_buf, buf_len);
  1270. }
  1271. /* delete the old KV */
  1272. if (kv_is_found && result == FDB_NO_ERR) {
  1273. result = del_kv(db, key, &db->cur_kv, pika_true);
  1274. }
  1275. /* process the GC after set KV */
  1276. if (db->gc_request) {
  1277. gc_collect_by_free_size(db, KV_HDR_DATA_SIZE +
  1278. FDB_WG_ALIGN(strlen(key)) +
  1279. FDB_WG_ALIGN(buf_len));
  1280. }
  1281. }
  1282. return result;
  1283. }
  1284. /**
  1285. * Set a blob KV. If it blob value is NULL, delete it.
  1286. * If not find it in flash, then create it.
  1287. *
  1288. * @param db database object
  1289. * @param key KV name
  1290. * @param blob blob object
  1291. *
  1292. * @return result
  1293. */
  1294. fdb_err_t fdb_kv_set_blob(fdb_kvdb_t db, const char* key, fdb_blob_t blob) {
  1295. fdb_err_t result = FDB_NO_ERR;
  1296. if (!db_init_ok(db)) {
  1297. FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db));
  1298. return FDB_INIT_FAILED;
  1299. }
  1300. /* lock the KV cache */
  1301. db_lock(db);
  1302. result = set_kv(db, key, blob->buf, blob->size);
  1303. /* unlock the KV cache */
  1304. db_unlock(db);
  1305. return result;
  1306. }
  1307. /**
  1308. * Set a string KV. If it value is NULL, delete it.
  1309. * If not find it in flash, then create it.
  1310. *
  1311. * @param db database object
  1312. * @param key KV name
  1313. * @param value KV value
  1314. *
  1315. * @return result
  1316. */
  1317. fdb_err_t fdb_kv_set(fdb_kvdb_t db, const char* key, const char* value) {
  1318. struct fdb_blob blob;
  1319. return fdb_kv_set_blob(db, key, fdb_blob_make(&blob, value, strlen(value)));
  1320. }
  1321. /**
  1322. * recovery all KV to default.
  1323. *
  1324. * @param db database object
  1325. * @return result
  1326. */
  1327. fdb_err_t fdb_kv_set_default(fdb_kvdb_t db) {
  1328. fdb_err_t result = FDB_NO_ERR;
  1329. uint32_t addr, i, value_len;
  1330. struct kvdb_sec_info sector;
  1331. /* lock the KV cache */
  1332. db_lock(db);
  1333. /* format all sectors */
  1334. for (addr = 0; addr < db_max_size(db); addr += db_sec_size(db)) {
  1335. result = format_sector(db, addr, SECTOR_NOT_COMBINED);
  1336. if (result != FDB_NO_ERR) {
  1337. goto __exit;
  1338. }
  1339. }
  1340. /* create default KV */
  1341. for (i = 0; i < db->default_kvs.num; i++) {
  1342. /* It seems to be a string when value length is 0.
  1343. * This mechanism is for compatibility with older versions (less then
  1344. * V4.0). */
  1345. if (db->default_kvs.kvs[i].value_len == 0) {
  1346. value_len = strlen(db->default_kvs.kvs[i].value);
  1347. } else {
  1348. value_len = db->default_kvs.kvs[i].value_len;
  1349. }
  1350. sector.empty_kv = FAILED_ADDR;
  1351. fdb_err_t err_create =
  1352. create_kv_blob(db, &sector, db->default_kvs.kvs[i].key,
  1353. db->default_kvs.kvs[i].value, value_len);
  1354. if (err_create != FDB_NO_ERR) {
  1355. FDB_PRINT("Error: Create default KV (%s) failed, error: %d.\n",
  1356. db->default_kvs.kvs[i].key, result);
  1357. }
  1358. if (result != FDB_NO_ERR) {
  1359. goto __exit;
  1360. }
  1361. }
  1362. __exit:
  1363. db_oldest_addr(db) = 0;
  1364. /* unlock the KV cache */
  1365. db_unlock(db);
  1366. return result;
  1367. }
  1368. static pika_bool print_kv_cb(fdb_kv_t kv, void* arg1, void* arg2) {
  1369. pika_bool value_is_str = pika_true, print_value = pika_false;
  1370. size_t* using_size = arg1;
  1371. fdb_kvdb_t db = arg2;
  1372. if (kv->crc_is_ok) {
  1373. /* calculate the total using flash size */
  1374. *using_size += kv->len;
  1375. /* check KV */
  1376. if (kv->status == FDB_KV_WRITE) {
  1377. FDB_PRINT("%.*s=", kv->name_len, kv->name);
  1378. if (kv->value_len < FDB_STR_KV_VALUE_MAX_SIZE) {
  1379. uint8_t buf[32];
  1380. size_t len, size;
  1381. __reload:
  1382. /* check the value is string */
  1383. for (len = 0, size = 0; len < kv->value_len; len += size) {
  1384. if (len + sizeof(buf) < kv->value_len) {
  1385. size = sizeof(buf);
  1386. } else {
  1387. size = kv->value_len - len;
  1388. }
  1389. _fdb_flash_read((fdb_db_t)db, kv->addr.value + len,
  1390. (uint32_t*)buf, FDB_WG_ALIGN(size));
  1391. if (print_value) {
  1392. FDB_PRINT("%.*s", (int)size, buf);
  1393. } else if (!fdb_is_str(buf, size)) {
  1394. value_is_str = pika_false;
  1395. break;
  1396. }
  1397. }
  1398. } else {
  1399. value_is_str = pika_false;
  1400. }
  1401. if (value_is_str && !print_value) {
  1402. print_value = pika_true;
  1403. goto __reload;
  1404. } else if (!value_is_str) {
  1405. FDB_PRINT("blob @0x%08" PRIX32 " %" PRIu32 "bytes",
  1406. kv->addr.value, kv->value_len);
  1407. }
  1408. FDB_PRINT("\n");
  1409. }
  1410. }
  1411. return pika_false;
  1412. }
  1413. /**
  1414. * Print all KV.
  1415. *
  1416. * @param db database object
  1417. */
  1418. void fdb_kv_print(fdb_kvdb_t db) {
  1419. struct fdb_kv kv;
  1420. size_t using_size = 0;
  1421. if (!db_init_ok(db)) {
  1422. FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db));
  1423. return;
  1424. }
  1425. /* lock the KV cache */
  1426. db_lock(db);
  1427. kv_iterator(db, &kv, &using_size, db, print_kv_cb);
  1428. FDB_PRINT("\nmode: next generation\n");
  1429. FDB_PRINT(
  1430. "size: %" PRIu32 "/%" PRIu32 " bytes.\n",
  1431. (uint32_t)using_size +
  1432. ((SECTOR_NUM - FDB_GC_EMPTY_SEC_THRESHOLD) * SECTOR_HDR_DATA_SIZE),
  1433. db_max_size(db) - db_sec_size(db) * FDB_GC_EMPTY_SEC_THRESHOLD);
  1434. /* unlock the KV cache */
  1435. db_unlock(db);
  1436. }
  1437. #ifdef FDB_KV_AUTO_UPDATE
  1438. /*
  1439. * Auto update KV to latest default when current setting version number is
  1440. * changed.
  1441. */
  1442. static void kv_auto_update(fdb_kvdb_t db) {
  1443. size_t saved_ver_num = 0, setting_ver_num = db->ver_num;
  1444. pika_bool is_first_init = pika_false;
  1445. if (!(get_kv(db, VER_NUM_KV_NAME, &saved_ver_num, sizeof(size_t), NULL) >
  1446. 0)) {
  1447. is_first_init = pika_true;
  1448. set_kv(db, VER_NUM_KV_NAME, &setting_ver_num, sizeof(size_t));
  1449. }
  1450. /* check version number */
  1451. if (saved_ver_num != setting_ver_num || is_first_init) {
  1452. size_t i, value_len;
  1453. FDB_DEBUG("Update the KV from version %zu to %zu.\n", saved_ver_num,
  1454. setting_ver_num);
  1455. for (i = 0; i < db->default_kvs.num; i++) {
  1456. /* add a new KV when it's not found */
  1457. if (!find_kv(db, db->default_kvs.kvs[i].key, &db->cur_kv)) {
  1458. /* It seems to be a string when value length is 0.
  1459. * This mechanism is for compatibility with older versions
  1460. * (less then V4.0). */
  1461. if (db->default_kvs.kvs[i].value_len == 0) {
  1462. value_len = strlen(db->default_kvs.kvs[i].value);
  1463. } else {
  1464. value_len = db->default_kvs.kvs[i].value_len;
  1465. }
  1466. db->cur_sector.empty_kv = FAILED_ADDR;
  1467. create_kv_blob(db, &db->cur_sector, db->default_kvs.kvs[i].key,
  1468. db->default_kvs.kvs[i].value, value_len);
  1469. }
  1470. }
  1471. }
  1472. }
  1473. #endif /* FDB_KV_AUTO_UPDATE */
  1474. static pika_bool check_oldest_addr_cb(kv_sec_info_t sector,
  1475. void* arg1,
  1476. void* arg2) {
  1477. uint32_t* sector_oldest_addr = (uint32_t*)arg1;
  1478. fdb_sector_store_status_t* last_sector_status =
  1479. (fdb_sector_store_status_t*)arg2;
  1480. /* The oldest address is 0 by default.
  1481. * The new oldest sector is found when sector status change from empty to
  1482. * full or using.
  1483. */
  1484. if (*last_sector_status == FDB_SECTOR_STORE_EMPTY &&
  1485. (sector->status.store == FDB_SECTOR_STORE_FULL ||
  1486. sector->status.store == FDB_SECTOR_STORE_USING)) {
  1487. *sector_oldest_addr = sector->addr;
  1488. }
  1489. *last_sector_status = sector->status.store;
  1490. return pika_false;
  1491. }
  1492. static pika_bool check_sec_hdr_cb(kv_sec_info_t sector,
  1493. void* arg1,
  1494. void* arg2) {
  1495. if (!sector->check_ok) {
  1496. size_t* failed_count = arg1;
  1497. fdb_kvdb_t db = arg2;
  1498. (*failed_count)++;
  1499. if (db->parent.not_formatable) {
  1500. return pika_true;
  1501. } else {
  1502. FDB_DEBUG(
  1503. "Sector header info is incorrect. Auto format this sector "
  1504. "(0x%08" PRIX32 ").\n",
  1505. sector->addr);
  1506. format_sector(db, sector->addr, SECTOR_NOT_COMBINED);
  1507. }
  1508. }
  1509. return pika_false;
  1510. }
  1511. static pika_bool check_and_recovery_gc_cb(kv_sec_info_t sector,
  1512. void* arg1,
  1513. void* arg2) {
  1514. fdb_kvdb_t db = arg1;
  1515. if (sector->check_ok && sector->status.dirty == FDB_SECTOR_DIRTY_GC) {
  1516. /* make sure the GC request flag to pika_true */
  1517. db->gc_request = pika_true;
  1518. /* resume the GC operate */
  1519. gc_collect(db);
  1520. }
  1521. return pika_false;
  1522. }
  1523. static pika_bool check_and_recovery_kv_cb(fdb_kv_t kv, void* arg1, void* arg2) {
  1524. fdb_kvdb_t db = arg1;
  1525. /* recovery the prepare deleted KV */
  1526. if (kv->crc_is_ok && kv->status == FDB_KV_PRE_DELETE) {
  1527. FDB_INFO(
  1528. "Found an KV (%.*s) which has changed value failed. Now will "
  1529. "recovery it.\n",
  1530. kv->name_len, kv->name);
  1531. /* recovery the old KV */
  1532. if (move_kv(db, kv) == FDB_NO_ERR) {
  1533. FDB_DEBUG("Recovery the KV successful.\n");
  1534. } else {
  1535. FDB_DEBUG("Warning: Moved an KV (size %" PRIu32
  1536. ") failed when recovery. Now will GC then retry.\n",
  1537. kv->len);
  1538. return pika_true;
  1539. }
  1540. } else if (kv->status == FDB_KV_PRE_WRITE) {
  1541. uint8_t status_table[KV_STATUS_TABLE_SIZE];
  1542. /* the KV has not write finish, change the status to error */
  1543. // TODO Draw the state replacement diagram of exception handling
  1544. _fdb_write_status((fdb_db_t)db, kv->addr.start, status_table,
  1545. FDB_KV_STATUS_NUM, FDB_KV_ERR_HDR, pika_true);
  1546. return pika_true;
  1547. } else if (kv->crc_is_ok && kv->status == FDB_KV_WRITE) {
  1548. #ifdef FDB_KV_USING_CACHE
  1549. /* update the cache when first load. If caching is disabled, this step
  1550. * is not performed */
  1551. update_kv_cache(db, kv->name, kv->name_len, kv->addr.start);
  1552. #endif
  1553. }
  1554. return pika_false;
  1555. }
  1556. /**
  1557. * Check and load the flash KV.
  1558. *
  1559. * @return result
  1560. */
  1561. fdb_err_t _fdb_kv_load(fdb_kvdb_t db) {
  1562. fdb_err_t result = FDB_NO_ERR;
  1563. struct fdb_kv kv;
  1564. struct kvdb_sec_info sector;
  1565. size_t check_failed_count = 0;
  1566. db->in_recovery_check = pika_true;
  1567. /* check all sector header */
  1568. sector_iterator(db, &sector, FDB_SECTOR_STORE_UNUSED, &check_failed_count,
  1569. db, check_sec_hdr_cb, pika_false);
  1570. if (db->parent.not_formatable && check_failed_count > 0) {
  1571. result = FDB_READ_ERR;
  1572. goto __exit;
  1573. }
  1574. /* all sector header check failed */
  1575. if (check_failed_count == SECTOR_NUM) {
  1576. FDB_INFO("All sector header is incorrect. Set it to default.\n");
  1577. fdb_kv_set_default(db);
  1578. }
  1579. /* lock the KV cache */
  1580. db_lock(db);
  1581. /* check all sector header for recovery GC */
  1582. sector_iterator(db, &sector, FDB_SECTOR_STORE_UNUSED, db, NULL,
  1583. check_and_recovery_gc_cb, pika_false);
  1584. __retry:
  1585. /* check all KV for recovery */
  1586. kv_iterator(db, &kv, db, NULL, check_and_recovery_kv_cb);
  1587. if (db->gc_request) {
  1588. gc_collect(db);
  1589. goto __retry;
  1590. }
  1591. db->in_recovery_check = pika_false;
  1592. __exit:
  1593. /* unlock the KV cache */
  1594. db_unlock(db);
  1595. return result;
  1596. }
  1597. /**
  1598. * This function will get or set some options of the database
  1599. *
  1600. * @param db database object
  1601. * @param cmd the control command
  1602. * @param arg the argument
  1603. */
  1604. void fdb_kvdb_control(fdb_kvdb_t db, int cmd, void* arg) {
  1605. FDB_ASSERT(db);
  1606. switch (cmd) {
  1607. case FDB_KVDB_CTRL_SET_SEC_SIZE:
  1608. /* this change MUST before database initialization */
  1609. FDB_ASSERT(db->parent.init_ok == pika_false);
  1610. db->parent.sec_size = *(uint32_t*)arg;
  1611. break;
  1612. case FDB_KVDB_CTRL_GET_SEC_SIZE:
  1613. *(uint32_t*)arg = db->parent.sec_size;
  1614. break;
  1615. case FDB_KVDB_CTRL_SET_LOCK:
  1616. #if !defined(__ARMCC_VERSION) && defined(__GNUC__)
  1617. #pragma GCC diagnostic push
  1618. #pragma GCC diagnostic ignored "-Wpedantic"
  1619. #endif
  1620. db->parent.lock = (void (*)(fdb_db_t db))arg;
  1621. #if !defined(__ARMCC_VERSION) && defined(__GNUC__)
  1622. #pragma GCC diagnostic pop
  1623. #endif
  1624. break;
  1625. case FDB_KVDB_CTRL_SET_UNLOCK:
  1626. #if !defined(__ARMCC_VERSION) && defined(__GNUC__)
  1627. #pragma GCC diagnostic push
  1628. #pragma GCC diagnostic ignored "-Wpedantic"
  1629. #endif
  1630. db->parent.unlock = (void (*)(fdb_db_t db))arg;
  1631. #if !defined(__ARMCC_VERSION) && defined(__GNUC__)
  1632. #pragma GCC diagnostic pop
  1633. #endif
  1634. break;
  1635. case FDB_KVDB_CTRL_SET_FILE_MODE:
  1636. #ifdef FDB_USING_FILE_MODE
  1637. /* this change MUST before database initialization */
  1638. FDB_ASSERT(db->parent.init_ok == pika_false);
  1639. db->parent.file_mode = *(pika_bool*)arg;
  1640. #else
  1641. FDB_INFO(
  1642. "Error: set file mode Failed. Please defined the "
  1643. "FDB_USING_FILE_MODE macro.");
  1644. #endif
  1645. break;
  1646. case FDB_KVDB_CTRL_SET_MAX_SIZE:
  1647. #ifdef FDB_USING_FILE_MODE
  1648. /* this change MUST before database initialization */
  1649. FDB_ASSERT(db->parent.init_ok == pika_false);
  1650. db->parent.max_size = *(uint32_t*)arg;
  1651. #endif
  1652. break;
  1653. case FDB_KVDB_CTRL_SET_NOT_FORMAT:
  1654. /* this change MUST before database initialization */
  1655. FDB_ASSERT(db->parent.init_ok == pika_false);
  1656. db->parent.not_formatable = *(pika_bool*)arg;
  1657. break;
  1658. }
  1659. }
  1660. /**
  1661. * The KV database initialization.
  1662. *
  1663. * @param db database object
  1664. * @param name database name
  1665. * @param path FAL mode: partition name, file mode: database saved directory
  1666. * path
  1667. * @param default_kv the default KV set @see fdb_default_kv
  1668. * @param user_data user data
  1669. *
  1670. * @return result
  1671. */
  1672. fdb_err_t fdb_kvdb_init(fdb_kvdb_t db,
  1673. const char* name,
  1674. const char* path,
  1675. struct fdb_default_kv* default_kv,
  1676. void* user_data) {
  1677. fdb_err_t result = FDB_NO_ERR;
  1678. struct kvdb_sec_info sector;
  1679. #ifdef FDB_KV_USING_CACHE
  1680. size_t i;
  1681. #endif
  1682. /* must be aligned with write granularity */
  1683. FDB_ASSERT((FDB_STR_KV_VALUE_MAX_SIZE * 8) % FDB_WRITE_GRAN == 0);
  1684. result = _fdb_init_ex((fdb_db_t)db, name, path, FDB_DB_TYPE_KV, user_data);
  1685. if (result != FDB_NO_ERR) {
  1686. goto __exit;
  1687. }
  1688. db->gc_request = pika_false;
  1689. db->in_recovery_check = pika_false;
  1690. if (default_kv) {
  1691. db->default_kvs = *default_kv;
  1692. } else {
  1693. db->default_kvs.num = 0;
  1694. db->default_kvs.kvs = NULL;
  1695. }
  1696. { /* find the oldest sector address */
  1697. uint32_t sector_oldest_addr = 0;
  1698. fdb_sector_store_status_t last_sector_status = FDB_SECTOR_STORE_UNUSED;
  1699. db_oldest_addr(db) = 0;
  1700. sector_iterator(db, &sector, FDB_SECTOR_STORE_UNUSED,
  1701. &sector_oldest_addr, &last_sector_status,
  1702. check_oldest_addr_cb, pika_false);
  1703. db_oldest_addr(db) = sector_oldest_addr;
  1704. FDB_DEBUG("The oldest addr is @0x%08" PRIX32 "\n", db_oldest_addr(db));
  1705. }
  1706. /* there is at least one empty sector for GC. */
  1707. FDB_ASSERT((FDB_GC_EMPTY_SEC_THRESHOLD > 0 &&
  1708. FDB_GC_EMPTY_SEC_THRESHOLD < SECTOR_NUM))
  1709. #ifdef FDB_KV_USING_CACHE
  1710. for (i = 0; i < FDB_SECTOR_CACHE_TABLE_SIZE; i++) {
  1711. db->sector_cache_table[i].addr = FDB_DATA_UNUSED;
  1712. }
  1713. for (i = 0; i < FDB_KV_CACHE_TABLE_SIZE; i++) {
  1714. db->kv_cache_table[i].addr = FDB_DATA_UNUSED;
  1715. }
  1716. #endif /* FDB_KV_USING_CACHE */
  1717. FDB_DEBUG("KVDB size is %" PRIu32 " bytes.\n", db_max_size(db));
  1718. result = _fdb_kv_load(db);
  1719. #ifdef FDB_KV_AUTO_UPDATE
  1720. if (result == FDB_NO_ERR) {
  1721. kv_auto_update(db);
  1722. }
  1723. #endif
  1724. __exit:
  1725. _fdb_init_finish((fdb_db_t)db, result);
  1726. return result;
  1727. }
  1728. /**
  1729. * The KV database initialization.
  1730. *
  1731. * @param db database object
  1732. *
  1733. * @return result
  1734. */
  1735. fdb_err_t fdb_kvdb_deinit(fdb_kvdb_t db) {
  1736. _fdb_deinit((fdb_db_t)db);
  1737. return FDB_NO_ERR;
  1738. }
  1739. /**
  1740. * The KV database initialization.
  1741. *
  1742. * @param db database object
  1743. * @param itr iterator structure to be initialized
  1744. *
  1745. * @return pointer to the iterator initialized.
  1746. */
  1747. fdb_kv_iterator_t fdb_kv_iterator_init(fdb_kvdb_t db, fdb_kv_iterator_t itr) {
  1748. itr->curr_kv.addr.start = 0;
  1749. /* If iterator statistics is needed */
  1750. itr->iterated_cnt = 0;
  1751. itr->iterated_obj_bytes = 0;
  1752. itr->iterated_value_bytes = 0;
  1753. itr->traversed_len = 0;
  1754. /* Start from sector head */
  1755. itr->sector_addr = db_oldest_addr(db);
  1756. return itr;
  1757. }
  1758. /**
  1759. * The KV database iterator.
  1760. *
  1761. * @param db database object
  1762. * @param itr the iterator structure
  1763. *
  1764. * @return pika_false if iteration is ended, pika_true if iteration is not
  1765. * ended.
  1766. */
  1767. pika_bool fdb_kv_iterate(fdb_kvdb_t db, fdb_kv_iterator_t itr) {
  1768. struct kvdb_sec_info sector;
  1769. fdb_kv_t kv = &(itr->curr_kv);
  1770. do {
  1771. if (read_sector_info(db, itr->sector_addr, &sector, pika_false) ==
  1772. FDB_NO_ERR) {
  1773. if (sector.status.store == FDB_SECTOR_STORE_USING ||
  1774. sector.status.store == FDB_SECTOR_STORE_FULL) {
  1775. if (kv->addr.start == 0) {
  1776. kv->addr.start = sector.addr + SECTOR_HDR_DATA_SIZE;
  1777. } else if ((kv->addr.start = get_next_kv_addr(
  1778. db, &sector, kv)) == FAILED_ADDR) {
  1779. kv->addr.start = 0;
  1780. itr->traversed_len += db_sec_size(db);
  1781. continue;
  1782. }
  1783. do {
  1784. read_kv(db, kv);
  1785. if (kv->status == FDB_KV_WRITE) {
  1786. /* We got a valid kv here. */
  1787. /* If iterator statistics is needed */
  1788. itr->iterated_cnt++;
  1789. itr->iterated_obj_bytes += kv->len;
  1790. itr->iterated_value_bytes += kv->value_len;
  1791. return pika_true;
  1792. }
  1793. } while ((kv->addr.start = get_next_kv_addr(db, &sector, kv)) !=
  1794. FAILED_ADDR);
  1795. }
  1796. }
  1797. /** Set kv->addr.start to 0 when we get into a new sector so that if we
  1798. * successfully get the next sector info, the kv->addr.start is set to
  1799. * the new sector.addr + SECTOR_HDR_DATA_SIZE.
  1800. */
  1801. kv->addr.start = 0;
  1802. itr->traversed_len += db_sec_size(db);
  1803. } while ((itr->sector_addr = get_next_sector_addr(
  1804. db, &sector, itr->traversed_len)) != FAILED_ADDR);
  1805. /* Finally we have iterated all the KVs. */
  1806. return pika_false;
  1807. }
  1808. #endif /* defined(FDB_USING_KVDB) */