3535#define SECTOR_MAGIC_WORD 0x30424446
3636/* magic word(`K`, `V`, `0`, `0`) */
3737#define KV_MAGIC_WORD 0x3030564B
38+ /* GC minimum number of empty sectors. GC will using at least 1 empty sector. */
39+ #define GC_MIN_EMPTY_SEC_NUM 1
3840
3941/* the sector remain threshold before full status */
4042#ifndef FDB_SEC_REMAIN_THRESHOLD
@@ -135,9 +137,8 @@ struct alloc_kv_cb_args {
135137
136138struct gc_cb_args {
137139 fdb_kvdb_t db ;
138- size_t cur_free_size ;
139140 size_t setting_free_size ;
140- uint32_t traversed_len ;
141+ size_t last_gc_sec_addr ;
141142};
142143
143144static void gc_collect (fdb_kvdb_t db );
@@ -1071,7 +1072,7 @@ static uint32_t new_kv(fdb_kvdb_t db, kv_sec_info_t sector, size_t kv_size)
10711072
10721073 if ((empty_kv = alloc_kv (db , sector , kv_size )) == FAILED_ADDR ) {
10731074 if (db -> gc_request && !already_gc ) {
1074- FDB_INFO ( "Warning: Alloc an KV (size %" PRIu32 ") failed when new KV. Now will GC then retry.\n" , (uint32_t )kv_size );
1075+ FDB_DEBUG ( " Alloc an KV (size %" PRIu32 ") failed when new KV. Now will GC then retry.\n" , (uint32_t )kv_size );
10751076 gc_collect_by_free_size (db , kv_size );
10761077 already_gc = true;
10771078 goto __retry ;
@@ -1093,10 +1094,12 @@ static uint32_t new_kv_ex(fdb_kvdb_t db, kv_sec_info_t sector, size_t key_len, s
10931094
10941095static bool gc_check_cb (kv_sec_info_t sector , void * arg1 , void * arg2 )
10951096{
1096- size_t * empty_sec = arg1 ;
1097+ size_t * empty_sec_num = arg1 ;
1098+ uint32_t * empty_sec_addr = arg2 ;
10971099
10981100 if (sector -> check_ok ) {
1099- * empty_sec = * empty_sec + 1 ;
1101+ * empty_sec_num = * empty_sec_num + 1 ;
1102+ * empty_sec_addr = sector -> addr ;
11001103 }
11011104
11021105 return false;
@@ -1108,6 +1111,7 @@ static bool do_gc(kv_sec_info_t sector, void *arg1, void *arg2)
11081111 struct fdb_kv kv ;
11091112 struct gc_cb_args * gc = (struct gc_cb_args * )arg1 ;
11101113 fdb_kvdb_t db = gc -> db ;
1114+ uint32_t last_gc_sec_addr = 0 ;
11111115
11121116 if (sector -> check_ok && (sector -> status .dirty == FDB_SECTOR_DIRTY_TRUE || sector -> status .dirty == FDB_SECTOR_DIRTY_GC )) {
11131117 uint8_t status_table [FDB_DIRTY_STATUS_TABLE_SIZE ];
@@ -1122,15 +1126,22 @@ static bool do_gc(kv_sec_info_t sector, void *arg1, void *arg2)
11221126 if (move_kv (db , & kv ) != FDB_NO_ERR ) {
11231127 FDB_INFO ("Error: Moved the KV (%.*s) for GC failed.\n" , kv .name_len , kv .name );
11241128 }
1129+ } else {
1130+ FDB_DEBUG ("KV (%.*s) is garbage NOT need move, collect it.\n" , kv .name_len , kv .name );
11251131 }
11261132 } while ((kv .addr .start = get_next_kv_addr (db , sector , & kv )) != FAILED_ADDR );
11271133 format_sector (db , sector -> addr , SECTOR_NOT_COMBINED );
1128- gc -> cur_free_size += db_sec_size ( db ) - SECTOR_HDR_DATA_SIZE ;
1129- FDB_DEBUG ( "Collect a sector @0x%08" PRIX32 "\n" , sector -> addr ) ;
1134+ last_gc_sec_addr = gc -> last_gc_sec_addr ;
1135+ gc -> last_gc_sec_addr = sector -> addr ;
11301136 /* update oldest_addr for next GC sector format */
11311137 db_oldest_addr (db ) = get_next_sector_addr (db , sector , 0 );
1132- if (gc -> cur_free_size >= gc -> setting_free_size )
1133- return true;
1138+ FDB_DEBUG ("Collect a sector @0x%08" PRIX32 "\n" , sector -> addr );
1139+ /* the collect new space is in last GC sector */
1140+ struct kvdb_sec_info last_gc_sector ;
1141+ if (read_sector_info (db , last_gc_sec_addr , & last_gc_sector , true) == FDB_NO_ERR ) {
1142+ if (last_gc_sector .remain > gc -> setting_free_size )
1143+ return true;
1144+ }
11341145 }
11351146
11361147 return false;
@@ -1139,15 +1150,17 @@ static bool do_gc(kv_sec_info_t sector, void *arg1, void *arg2)
11391150static void gc_collect_by_free_size (fdb_kvdb_t db , size_t free_size )
11401151{
11411152 struct kvdb_sec_info sector ;
1142- size_t empty_sec = 0 ;
1143- struct gc_cb_args arg = { db , 0 , free_size , 0 };
1153+ size_t empty_sec_num = 0 ;
1154+ /* an empty sector address */
1155+ uint32_t empty_sec_addr = 0 ;
11441156
11451157 /* GC check the empty sector number */
1146- sector_iterator (db , & sector , FDB_SECTOR_STORE_EMPTY , & empty_sec , NULL , gc_check_cb , false);
1158+ sector_iterator (db , & sector , FDB_SECTOR_STORE_EMPTY , & empty_sec_num , & empty_sec_addr , gc_check_cb , false);
11471159
11481160 /* do GC collect */
1149- FDB_DEBUG ("The remain empty sector is %" PRIu32 ", GC threshold is %" PRIdLEAST16 ".\n" , (uint32_t )empty_sec , FDB_GC_EMPTY_SEC_THRESHOLD );
1150- if (empty_sec <= FDB_GC_EMPTY_SEC_THRESHOLD ) {
1161+ FDB_DEBUG ("The remain empty sector is %" PRIu32 ", GC threshold is %" PRIdLEAST16 ".\n" , (uint32_t )empty_sec_num , FDB_GC_EMPTY_SEC_THRESHOLD );
1162+ if (empty_sec_num <= FDB_GC_EMPTY_SEC_THRESHOLD ) {
1163+ struct gc_cb_args arg = { db , free_size , empty_sec_addr };
11511164 sector_iterator (db , & sector , FDB_SECTOR_STORE_UNUSED , & arg , NULL , do_gc , false);
11521165 }
11531166
@@ -1580,7 +1593,7 @@ static bool check_sec_hdr_cb(kv_sec_info_t sector, void *arg1, void *arg2)
15801593 if (db -> parent .not_formatable ) {
15811594 return true;
15821595 } else {
1583- FDB_INFO ("Sector header info is incorrect. Auto format this sector (0x%08" PRIX32 ").\n" , sector -> addr );
1596+ FDB_DEBUG ("Sector header info is incorrect. Auto format this sector (0x%08" PRIX32 ").\n" , sector -> addr );
15841597 format_sector (db , sector -> addr , SECTOR_NOT_COMBINED );
15851598 }
15861599 }
0 commit comments