From b20cb7f79a117e10a38fc9378b9ee841207e734e Mon Sep 17 00:00:00 2001 From: armink Date: Mon, 16 Mar 2026 19:56:03 +0800 Subject: [PATCH 1/3] ci: add matrix test for FDB_WRITE_GRAN=[1,8,32,64,128] --- .github/workflows/main.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ba2dd10..43e60d6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -2,8 +2,12 @@ name: AutoTestCI on: [push, pull_request] jobs: test: - name: AutoTest + name: "AutoTest (GRAN=${{ matrix.write_gran }})" runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + write_gran: [1, 8, 32, 64, 128] env: TEST_BSP_ROOT: ../AutoTestBsp UTEST_RUNNER_PATH: ../UtestRunner @@ -26,7 +30,7 @@ jobs: cp -rf inc/fdb_low_lvl.h $TEST_BSP_ROOT/packages/FlashDB/inc/fdb_low_lvl.h cp -rf inc/flashdb.h $TEST_BSP_ROOT/packages/FlashDB/inc/flashdb.h /opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc --version - scons -j$(nproc) -C $TEST_BSP_ROOT + scons --global-macros="FDB_WRITE_GRAN=${{ matrix.write_gran }}" -j$(nproc) -C $TEST_BSP_ROOT - name: Start test run: | python3 $UTEST_RUNNER_PATH/qemu_runner.py --elf $TEST_BSP_ROOT/rtthread.elf --sd $TEST_BSP_ROOT/sd.bin From f966548e457f45c33a6f4374e6a6017218227d50 Mon Sep 17 00:00:00 2001 From: armink Date: Tue, 17 Mar 2026 19:50:52 +0800 Subject: [PATCH 2/3] fix(kvdb): Auto test failed when FDB_WRITE_GRAN is 128. --- tests/fdb_kvdb_tc.c | 74 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/tests/fdb_kvdb_tc.c b/tests/fdb_kvdb_tc.c index 3db65d4..dddb1b1 100644 --- a/tests/fdb_kvdb_tc.c +++ b/tests/fdb_kvdb_tc.c @@ -14,6 +14,7 @@ #include "utest.h" #include +#include #include #include #include @@ -30,7 +31,78 @@ #define TEST_TS_PART_NAME "fdb_kvdb1" #define TEST_KV_BLOB_NAME "kv_blob_test" #define TEST_KV_NAME "kv_test" -#define TEST_KV_VALUE_LEN 1200 /* only save 3 KVs in a 4096 sector */ + +/* ------------------------------------------------------------------ + * Dynamically compute TEST_KV_VALUE_LEN so that exactly 3 KVs fit + * per TEST_KVDB_SECTOR_SIZE-byte sector for ANY FDB_WRITE_GRAN value, + * AND so that the test_fdb_gc2 GC path works correctly. + * + * Let: + * B = _TKV_BASE = KV_HDR_SZ + aligned_name + * V = TEST_KV_VALUE_LEN (aligned to W) + * kv_size = B + V + * kv5_size= B + 2V (kv5 value = 2×V) + * kv4_size= B + 3V (kv4 value = 3×V) + * th = _TKV_THRESHOLD = KV_HDR_SZ + FDB_KV_NAME_MAX + * usable = TEST_KVDB_SECTOR_SIZE - _TKV_SEC_HDR_SZ + * + * Three constraints, from LEAST to MOST strict: + * + * [A] 4th KV does NOT fit (exactly 3 per sector): + * V >= ceil((usable - 5B - 64) / 4) + * + * [B] kv4 (3×V) occupies a full sector (no normal KV fits after it): + * usable - (B+3V) <= (B+V) + th + * V >= ceil((usable - 3B - 64) / 4) + * + * [C] GC does NOT stop early when kv1+kv2 are moved into the initially + * empty sector (sector3). do_gc() stops when remain > free_size, + * where free_size = kv5_size = B+2V. We need: + * usable - 2*(B+V) <= B + 2V + * 3984 - 3B <= 4V + * V >= ceil((usable - 3B) / 4) ← STRICTEST BOUND (no -64 term) + * + * All three constraints reduce to the same form; [C] dominates. + * The minimum V satisfying [C] (ceiling integer division: (N+3)/4): + * + * V_min = FDB_WG_ALIGN( (usable - 3B + 3) / 4 ) + * ------------------------------------------------------------------*/ + +/* write-gran alignment unit in bytes */ +#define _TKV_W ((FDB_WRITE_GRAN + 7) / 8) + +/* KV status table size */ +#define _TKV_KV_STATUS_SZ FDB_STATUS_TABLE_SIZE(FDB_KV_STATUS_NUM) + +/* Sector header raw size (store_status + dirty_status + magic + combined + reserved) */ +#define _TKV_SEC_HDR_RAW_SZ (FDB_STORE_STATUS_TABLE_SIZE + FDB_DIRTY_STATUS_TABLE_SIZE \ + + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t)) +#define _TKV_SEC_HDR_SZ FDB_WG_ALIGN(_TKV_SEC_HDR_RAW_SZ) + +/* KV header raw size (status + magic + len + crc32 + name_len + value_len) */ +#define _TKV_KV_HDR_RAW_SZ (_TKV_KV_STATUS_SZ + sizeof(uint32_t) + sizeof(uint32_t) \ + + sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t)) +#define _TKV_KV_HDR_SZ FDB_WG_ALIGN(_TKV_KV_HDR_RAW_SZ) + +/* FDB_SEC_REMAIN_THRESHOLD equivalent: KV_HDR_DATA_SIZE + FDB_KV_NAME_MAX */ +#define _TKV_THRESHOLD (_TKV_KV_HDR_SZ + FDB_KV_NAME_MAX) + +/* name length of "kv0".."kv5", aligned */ +#define _TKV_NAME_ALIGNED FDB_WG_ALIGN(3) + +/* usable data space per sector */ +#define _TKV_USABLE (TEST_KVDB_SECTOR_SIZE - _TKV_SEC_HDR_SZ) + +/* per-KV base overhead: header + aligned name */ +#define _TKV_BASE (_TKV_KV_HDR_SZ + _TKV_NAME_ALIGNED) + +/* Minimum V satisfying constraint [C] (the strictest). + * Uses ceiling integer division: (N + 3) / 4. */ +#define _TKV_MAX_VAL_ALIGNED FDB_WG_ALIGN((_TKV_USABLE - 3 * _TKV_BASE + 3) / 4) + +/* TEST_KV_VALUE_LEN: use aligned size directly (already a multiple of W) */ +#define TEST_KV_VALUE_LEN _TKV_MAX_VAL_ALIGNED + #define TEST_KV_MAX_NUM 8 #define TEST_KVDB_SECTOR_SIZE 4096 #define TEST_KVDB_SECTOR_NUM 4 From 105bb0ac81be94fa017a53c702eac705c60d5e09 Mon Sep 17 00:00:00 2001 From: Oliver0927i <18647686198@163.com> Date: Mon, 23 Mar 2026 09:21:51 +0800 Subject: [PATCH 3/3] fix: enum to macro --- src/fdb_tsdb.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/fdb_tsdb.c b/src/fdb_tsdb.c index 42c3f7a..9cf107f 100644 --- a/src/fdb_tsdb.c +++ b/src/fdb_tsdb.c @@ -32,25 +32,28 @@ #define TSL_UINT32_ALIGN_SIZE (FDB_WG_ALIGN(sizeof(uint32_t))) #ifdef FDB_USING_TIMESTAMP_64BIT - #define TSL_TIME_ALIGN_SIZE FDB_WG_ALIGN(sizeof(int64_t)) +#define TSL_TIME_ALIGN_SIZE FDB_WG_ALIGN(sizeof(int64_t)) #else - #define TSL_TIME_ALIGN_SIZE FDB_WG_ALIGN(sizeof(int32_t)) +#define TSL_TIME_ALIGN_SIZE FDB_WG_ALIGN(sizeof(int32_t)) #endif // Autofill to struct sector_hdr_data -enum { - TSL_HDR_PADDING_SIZE = FDB_WG_ALIGN(sizeof(uint32_t)) - sizeof(uint32_t) -}; +#define SECTOR_HDR_PADDING_SIZE (FDB_WG_ALIGN(4) - 4) // Autofill to struct log_idx_data -enum { +#ifdef FDB_USING_TIMESTAMP_64BIT +#define _TSL_FDBTIME_SIZE (8) +#else +#define _TSL_FDBTIME_SIZE (4) +#endif + #ifdef FDB_TSDB_FIXED_BLOB_SIZE - LOG_IDX_BASE_SIZE = TSL_STATUS_TABLE_SIZE + sizeof(fdb_time_t), +#define LOG_IDX_BASE_SIZE (TSL_STATUS_TABLE_SIZE + _TSL_FDBTIME_SIZE) #else - LOG_IDX_BASE_SIZE = TSL_STATUS_TABLE_SIZE + sizeof(fdb_time_t) + sizeof(uint32_t) * 2, +#define LOG_IDX_BASE_SIZE (TSL_STATUS_TABLE_SIZE + _TSL_FDBTIME_SIZE + 4 * 2) #endif - LOG_IDX_PADDING_SIZE = FDB_WG_ALIGN(LOG_IDX_BASE_SIZE) - LOG_IDX_BASE_SIZE -}; + +#define LOG_IDX_PADDING_SIZE (FDB_WG_ALIGN(LOG_IDX_BASE_SIZE) - LOG_IDX_BASE_SIZE) #define SECTOR_HDR_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct sector_hdr_data))) #define LOG_IDX_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct log_idx_data))) @@ -107,8 +110,8 @@ struct sector_hdr_data { uint32_t reserved; // Autofill to the FDB WRITE GRAN alignment -#if TSL_HDR_PADDING_SIZE > 0 - uint8_t padding[TSL_HDR_PADDING_SIZE]; +#if SECTOR_HDR_PADDING_SIZE > 0 + uint8_t padding[SECTOR_HDR_PADDING_SIZE]; #endif }; typedef struct sector_hdr_data *sector_hdr_data_t;