From 9eea31ac18954982e41facc4ebbc03ecfc173461 Mon Sep 17 00:00:00 2001 From: armink Date: Sun, 3 Jan 2021 19:17:51 +0800 Subject: [PATCH] Add file storage mode. --- .../components/FlashDB/inc/fdb_cfg.h | 3 + demos/stm32f103ve/applications/fdb_cfg.h | 3 + demos/stm32f405rg/applications/fdb_cfg.h | 3 + .../applications/fdb_cfg.h | 3 + inc/fdb_cfg.h | 13 +- inc/fdb_def.h | 29 ++- inc/flashdb.h | 8 +- src/fdb.c | 59 +++-- src/fdb_file.c | 209 ++++++++++++++++++ src/fdb_kvdb.c | 50 +++-- src/fdb_tsdb.c | 37 +++- src/fdb_utils.c | 49 +++- 12 files changed, 412 insertions(+), 54 deletions(-) create mode 100644 src/fdb_file.c diff --git a/demos/esp8266_spi_flash/components/FlashDB/inc/fdb_cfg.h b/demos/esp8266_spi_flash/components/FlashDB/inc/fdb_cfg.h index c1fe7d8..4b44862 100644 --- a/demos/esp8266_spi_flash/components/FlashDB/inc/fdb_cfg.h +++ b/demos/esp8266_spi_flash/components/FlashDB/inc/fdb_cfg.h @@ -23,6 +23,9 @@ /* using TSDB (Time series database) feature */ #define FDB_USING_TSDB +/* Using FAL storage mode */ +#define FDB_USING_FAL_MODE + /* the flash write granularity, unit: bit * only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */ #define FDB_WRITE_GRAN 1 /* @note you must define it for a value */ diff --git a/demos/stm32f103ve/applications/fdb_cfg.h b/demos/stm32f103ve/applications/fdb_cfg.h index 95ffb42..2239453 100644 --- a/demos/stm32f103ve/applications/fdb_cfg.h +++ b/demos/stm32f103ve/applications/fdb_cfg.h @@ -23,6 +23,9 @@ /* using TSDB (Time series database) feature */ #define FDB_USING_TSDB +/* Using FAL storage mode */ +#define FDB_USING_FAL_MODE + /* the flash write granularity, unit: bit * only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */ #define FDB_WRITE_GRAN 32 diff --git a/demos/stm32f405rg/applications/fdb_cfg.h b/demos/stm32f405rg/applications/fdb_cfg.h index 09aa363..f9030bd 100644 --- a/demos/stm32f405rg/applications/fdb_cfg.h +++ b/demos/stm32f405rg/applications/fdb_cfg.h @@ -23,6 +23,9 @@ /* using TSDB (Time series database) feature */ #define FDB_USING_TSDB +/* Using FAL storage mode */ +#define FDB_USING_FAL_MODE + /* the flash write granularity, unit: bit * only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */ #define FDB_WRITE_GRAN 8 diff --git a/demos/stm32f405rg_spi_flash/applications/fdb_cfg.h b/demos/stm32f405rg_spi_flash/applications/fdb_cfg.h index 09aa363..f9030bd 100644 --- a/demos/stm32f405rg_spi_flash/applications/fdb_cfg.h +++ b/demos/stm32f405rg_spi_flash/applications/fdb_cfg.h @@ -23,6 +23,9 @@ /* using TSDB (Time series database) feature */ #define FDB_USING_TSDB +/* Using FAL storage mode */ +#define FDB_USING_FAL_MODE + /* the flash write granularity, unit: bit * only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */ #define FDB_WRITE_GRAN 8 diff --git a/inc/fdb_cfg.h b/inc/fdb_cfg.h index 942ac1b..48d92af 100644 --- a/inc/fdb_cfg.h +++ b/inc/fdb_cfg.h @@ -23,12 +23,23 @@ /* using TSDB (Time series database) feature */ #define FDB_USING_TSDB +/* Using FAL storage mode */ +#define FDB_USING_FAL_MODE + +#ifdef FDB_USING_FAL_MODE /* the flash write granularity, unit: bit * only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */ #define FDB_WRITE_GRAN /* @note you must define it for a value */ +#endif + +/* Using file storage mode by LIBC file API, like fopen/fread/fwrte/fclose */ +/* #define FDB_USING_FILE_LIBC_MODE */ + +/* Using file storage mode by POSIX file API, like open/read/write/close */ +/* #define FDB_USING_FILE_POSIX_MODE */ /* MCU Endian Configuration, default is Little Endian Order. */ -/* #define FDB_BIG_ENDIAN */ +/* #define FDB_BIG_ENDIAN */ /* log print macro. default EF_PRINT macro is printf() */ /* #define FDB_PRINT(...) my_printf(__VA_ARGS__) */ diff --git a/inc/fdb_def.h b/inc/fdb_def.h index 6eadd47..b37f152 100644 --- a/inc/fdb_def.h +++ b/inc/fdb_def.h @@ -39,6 +39,14 @@ extern "C" { #define FDB_KV_USING_CACHE #endif +#if defined(FDB_USING_FILE_LIBC_MODE) || defined(FDB_USING_FILE_POSIX_MODE) +#define FDB_USING_FILE_MODE +#endif + +#ifndef FDB_WRITE_GRAN +#define FDB_WRITE_GRAN 1 +#endif + /* log function. default FDB_PRINT macro is printf() */ #ifndef FDB_PRINT #define FDB_PRINT(...) printf(__VA_ARGS__) @@ -65,6 +73,8 @@ if (!(EXPR)) \ #define FDB_KVDB_CTRL_GET_SEC_SIZE 0x1 /**< get sector size control command */ #define FDB_KVDB_CTRL_SET_LOCK 0x2 /**< set lock function control command */ #define FDB_KVDB_CTRL_SET_UNLOCK 0x3 /**< set unlock function control command */ +#define FDB_KVDB_CTRL_SET_FILE_MODE 0x9 /**< set file mode control command */ +#define FDB_KVDB_CTRL_SET_MAX_SIZE 0xA /**< set database max size in file mode control command */ #define FDB_TSDB_CTRL_SET_SEC_SIZE 0x0 /**< set sector size control command */ #define FDB_TSDB_CTRL_GET_SEC_SIZE 0x1 /**< get sector size control command */ @@ -73,6 +83,8 @@ if (!(EXPR)) \ #define FDB_TSDB_CTRL_SET_ROLLOVER 0x4 /**< set rollover control command */ #define FDB_TSDB_CTRL_GET_ROLLOVER 0x5 /**< get rollover control command */ #define FDB_TSDB_CTRL_GET_LAST_TIME 0x6 /**< get last save time control command */ +#define FDB_TSDB_CTRL_SET_FILE_MODE 0x9 /**< set file mode control command */ +#define FDB_TSDB_CTRL_SET_MAX_SIZE 0xA /**< set database max size in file mode control command */ typedef time_t fdb_time_t; #ifdef FDB_USING_TIMESTAMP_64BIT @@ -238,9 +250,22 @@ typedef struct fdb_db *fdb_db_t; struct fdb_db { const char *name; /**< database name */ fdb_db_type type; /**< database type */ - const struct fal_partition *part; /**< flash partition */ + union { +#ifdef FDB_USING_FAL_MODE + const struct fal_partition *part; /**< flash partition for saving database */ +#endif +#ifdef FDB_USING_FILE_MODE + const char *dir; /**< directory path for saving database */ +#endif + } storage; uint32_t sec_size; /**< flash section size. It's a multiple of block size */ + uint32_t max_size; /**< database max size. It's a multiple of section size */ bool init_ok; /**< initialized successfully */ + bool file_mode; /**< is file mode, default is false */ +#ifdef FDB_USING_FILE_MODE + void *cur_file; /**< current file object */ + uint32_t cur_sec; /**< current operate sector address */ +#endif void (*lock)(fdb_db_t db); /**< lock the database operate */ void (*unlock)(fdb_db_t db); /**< unlock the database operate */ @@ -275,7 +300,7 @@ struct fdb_tsdb { struct tsdb_sec_info cur_sec; /**< current using sector */ fdb_time_t last_time; /**< last TSL timestamp */ fdb_get_time get_time; /**< the current timestamp get function */ - size_t max_len; /**< the max log length */ + size_t max_len; /**< the maximum length of each log */ uint32_t oldest_addr; /**< the oldest sector start address */ bool rollover; /**< the oldest data will rollover by newest data, default is true */ diff --git a/inc/flashdb.h b/inc/flashdb.h index 55a14be..de1731d 100644 --- a/inc/flashdb.h +++ b/inc/flashdb.h @@ -15,11 +15,17 @@ #include #include #include +#include #include -#include #include + +#ifdef FDB_USING_FAL_MODE +#include +#endif + #include + #ifdef __cplusplus extern "C" { #endif diff --git a/src/fdb.c b/src/fdb.c index 0b0c500..3749350 100644 --- a/src/fdb.c +++ b/src/fdb.c @@ -16,10 +16,12 @@ #define FDB_LOG_TAG "" +#if !defined(FDB_USING_FAL_MODE) && !defined(FDB_USING_FILE_MODE) +#error "Please defined the FDB_USING_FAL_MODE or FDB_USING_FILE_MODE macro" +#endif + fdb_err_t _fdb_init_ex(fdb_db_t db, const char *name, const char *part_name, fdb_db_type type, void *user_data) { - size_t block_size; - FDB_ASSERT(db); FDB_ASSERT(name); FDB_ASSERT(part_name); @@ -31,21 +33,48 @@ fdb_err_t _fdb_init_ex(fdb_db_t db, const char *name, const char *part_name, fdb db->name = name; db->type = type; db->user_data = user_data; - /* FAL (Flash Abstraction Layer) initialization */ - fal_init(); - /* check the flash partition */ - if ((db->part = fal_partition_find(part_name)) == NULL) { - FDB_INFO("Error: Partition (%s) not found.\n", part_name); - return FDB_PART_NOT_FOUND; + + if (db->file_mode) { +#ifdef FDB_USING_FILE_MODE + /* must set when using file mode */ + FDB_ASSERT(db->sec_size != 0); + FDB_ASSERT(db->max_size != 0); +#ifdef FDB_USING_POSIX_MODE + db->cur_file = (void *)-1; +#else + db->cur_file = (void *)0; +#endif + db->storage.dir = part_name; + FDB_ASSERT(strlen(part_name) != 0) +#endif + } else { +#ifdef FDB_USING_FAL_MODE + size_t block_size; + + /* FAL (Flash Abstraction Layer) initialization */ + fal_init(); + /* check the flash partition */ + if ((db->storage.part = fal_partition_find(part_name)) == NULL) { + FDB_INFO("Error: Partition (%s) not found.\n", part_name); + return FDB_PART_NOT_FOUND; + } + + block_size = fal_flash_device_find(db->storage.part->flash_name)->blk_size; + if (db->sec_size == 0) { + db->sec_size = block_size; + } else { + /* must be aligned with block size */ + FDB_ASSERT(db->sec_size % block_size == 0); + } + + db->max_size = db->storage.part->len; +#endif /* FDB_USING_FAL_MODE */ } - block_size = fal_flash_device_find(db->part->flash_name)->blk_size; - if (db->sec_size == 0) { - db->sec_size = block_size; - } else { - /* must be aligned with block size */ - FDB_ASSERT(db->sec_size % block_size == 0); - } + /* must align with sector size */ + FDB_ASSERT(db->max_size % db->sec_size == 0); + /* must have more than or equal 2 sector */ + FDB_ASSERT(db->max_size / db->sec_size >= 2); return FDB_NO_ERR; } diff --git a/src/fdb_file.c b/src/fdb_file.c new file mode 100644 index 0000000..add5587 --- /dev/null +++ b/src/fdb_file.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2020, Armink, + * Copyright (c) 2020, enkiller, <462747508@qq.com> + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define FDB_LOG_TAG "[file]" + +#ifdef FDB_USING_FILE_MODE + +#define DB_PATH_MAX 256 + +static void get_db_file_path(fdb_db_t db, uint32_t addr, char *path, size_t size) +{ +#define DB_NAME_MAX 8 + + /* from db_name.fdb.0 to db_name.fdb.n */ + char file_name[DB_NAME_MAX + 4 + 10]; + uint32_t sec_addr = FDB_ALIGN_DOWN(addr, db->sec_size); + int index = sec_addr / db->sec_size; + + snprintf(file_name, sizeof(file_name), "%.*s.fdb.%d", DB_NAME_MAX, db->name, index); + if (strlen(db->storage.dir) + 1 + strlen(file_name) >= size) { + /* path is too long */ + FDB_ASSERT(0) + } + snprintf(path, size, "%s/%s", db->storage.dir, file_name); +} + +#if defined(FDB_USING_FILE_POSIX_MODE) +static int open_db_file(fdb_db_t db, uint32_t addr, bool clean) +{ + uint32_t sec_addr = RT_ALIGN_DOWN(addr, db->sec_size); + int fd = (int)db->cur_file; + char path[DB_PATH_MAX]; + + if (sec_addr != db->cur_sec || fd <= 0 || clean) { + get_db_file_path(db, addr, path, DB_PATH_MAX); + + if (fd > 0) { + close(fd); + fd = -1; + } + if (clean) { + /* clean the old file */ + fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0); + if (fd <= 0) { + FDB_INFO("Error: open (%s) file failed.\n", path); + } + else { + close(fd); + fd = -1; + } + } + /* open the database file */ + fd = open(path, O_RDWR, 0); + db->cur_sec = sec_addr; + } + db->cur_file = (void *)fd; + + return (int)db->cur_file; +} + +fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void *buf, size_t size) +{ + fdb_err_t result = FDB_NO_ERR; + int fd = open_db_file(db, addr, false); + if (fd > 0) { + addr = addr % db->sec_size; + lseek(fd, addr, SEEK_SET); + read(fd, buf, size); + } else { + result = FDB_READ_ERR; + } + return result; +} + +fdb_err_t _fdb_file_write(fdb_db_t db, uint32_t addr, const void *buf, size_t size) +{ + fdb_err_t result = FDB_NO_ERR; + int fd = open_db_file(db, addr, false); + if (fd > 0) { + addr = addr % db->sec_size; + lseek(fd, addr, SEEK_SET); + write(fd, buf, size); + fsync(fd); + } else { + result = FDB_READ_ERR; + } + + return result; +} + +fdb_err_t _fdb_file_erase(fdb_db_t db, uint32_t addr, size_t size) +{ + fdb_err_t result = FDB_NO_ERR; + int fd = open_db_file(db, addr, true); + if (fd > 0) { +#define BUF_SIZE 32 + uint8_t buf[BUF_SIZE]; + size_t i; + lseek(fd, 0, SEEK_SET); + for (i = 0; i * BUF_SIZE < size; i++) + { + memset(buf, 0xFF, BUF_SIZE); + write(fd, buf, BUF_SIZE); + } + memset(buf, 0xFF, BUF_SIZE); + write(fd, buf, size - i * BUF_SIZE); + fsync(fd); + } else { + result = FDB_ERASE_ERR; + } + return result; +} +#elif defined(FDB_USING_FILE_LIBC_MODE) +static FILE *open_db_file(fdb_db_t db, uint32_t addr, bool clean) +{ + uint32_t sec_addr = FDB_ALIGN_DOWN(addr, db->sec_size); + + if (sec_addr != db->cur_sec || db->cur_file == NULL || clean) { + char path[DB_PATH_MAX]; + + get_db_file_path(db, addr, path, DB_PATH_MAX); + + if (db->cur_file) { + fclose(db->cur_file); + } + + if (clean) { + /* clean the old file */ + db->cur_file = fopen(path, "wb+"); + if (db->cur_file == NULL) { + FDB_INFO("Error: open (%s) file failed.\n", path); + } else { + fclose(db->cur_file); + } + } + + /* open the database file */ + db->cur_file = fopen(path, "rb+"); + db->cur_sec = sec_addr; + } + + return db->cur_file; +} + +fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void *buf, size_t size) +{ + fdb_err_t result = FDB_NO_ERR; + FILE *fp = open_db_file(db, addr, false); + if (fp) { + addr = addr % db->sec_size; + fseek(fp, addr, SEEK_SET); + fread(buf, size, 1, fp); + } else { + result = FDB_READ_ERR; + } + return result; +} + +fdb_err_t _fdb_file_write(fdb_db_t db, uint32_t addr, const void *buf, size_t size) +{ + fdb_err_t result = FDB_NO_ERR; + FILE *fp = open_db_file(db, addr, false); + if (fp) { + addr = addr % db->sec_size; + fseek(fp, addr, SEEK_SET); + fwrite(buf, size, 1, fp); + fflush(fp); + } else { + result = FDB_READ_ERR; + } + + return result; +} + +fdb_err_t _fdb_file_erase(fdb_db_t db, uint32_t addr, size_t size) +{ + fdb_err_t result = FDB_NO_ERR; + + FILE *fp = open_db_file(db, addr, true); + if (fp != NULL) { +#define BUF_SIZE 32 + uint8_t buf[BUF_SIZE]; + size_t i; + fseek(fp, 0, SEEK_SET); + for (i = 0; i * BUF_SIZE < size; i++) + { + memset(buf, 0xFF, BUF_SIZE); + fwrite(buf, BUF_SIZE, 1, fp); + } + memset(buf, 0xFF, BUF_SIZE); + fwrite(buf, size - i * BUF_SIZE, 1, fp); + fflush(fp); + } else { + result = FDB_ERASE_ERR; + } + return result; +} +#endif /* defined(FDB_USING_FILE_LIBC_MODE) */ + +#endif /* FDB_USING_FILE_MODE */ diff --git a/src/fdb_kvdb.c b/src/fdb_kvdb.c index 6e81226..9abd0b7 100644 --- a/src/fdb_kvdb.c +++ b/src/fdb_kvdb.c @@ -62,7 +62,8 @@ #define KV_STATUS_TABLE_SIZE FDB_STATUS_TABLE_SIZE(FDB_KV_STATUS_NUM) -#define SECTOR_NUM (db_part_size(db) / db_sec_size(db)) +//TODO 文件模式如何支持 +#define SECTOR_NUM (db_max_size(db) / db_sec_size(db)) #define SECTOR_HDR_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct sector_hdr_data))) #define SECTOR_DIRTY_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->status_table.dirty)) @@ -74,7 +75,8 @@ #define db_name(db) (((fdb_db_t)db)->name) #define db_init_ok(db) (((fdb_db_t)db)->init_ok) #define db_sec_size(db) (((fdb_db_t)db)->sec_size) -#define db_part_size(db) (((fdb_db_t)db)->part->len) +#define db_max_size(db) (((fdb_db_t)db)->max_size) + #define db_lock(db) \ do { \ if (((fdb_db_t)db)->lock) ((fdb_db_t)db)->lock((fdb_db_t)db); \ @@ -318,7 +320,7 @@ static fdb_err_t read_kv(fdb_kvdb_t db, fdb_kv_t kv) kv->status = (fdb_kv_status_t) _fdb_get_status(kv_hdr.status_table, FDB_KV_STATUS_NUM); kv->len = kv_hdr.len; - if (kv->len == ~0UL || kv->len > db_part_size(db) || kv->len < KV_NAME_LEN_OFFSET) { + if (kv->len == ~0UL || kv->len > db_max_size(db) || kv->len < KV_NAME_LEN_OFFSET) { /* the KV length was not write, so reserved the info for current KV */ kv->len = KV_HDR_DATA_SIZE; if (kv->status != FDB_KV_ERR_HDR) { @@ -328,7 +330,7 @@ static fdb_err_t read_kv(fdb_kvdb_t db, fdb_kv_t kv) } kv->crc_is_ok = false; return FDB_READ_ERR; - } else if (kv->len > db_sec_size(db) - SECTOR_HDR_DATA_SIZE && kv->len < db_part_size(db)) { + } else if (kv->len > db_sec_size(db) - SECTOR_HDR_DATA_SIZE && kv->len < db_max_size(db)) { //TODO 扇区连续模式,或者写入长度没有写入完整 FDB_ASSERT(0); } @@ -359,6 +361,10 @@ static fdb_err_t read_kv(fdb_kvdb_t db, fdb_kv_t kv) kv->addr.value = kv_name_addr + FDB_WG_ALIGN(kv_hdr.name_len); kv->value_len = kv_hdr.value_len; kv->name_len = kv_hdr.name_len; + if (kv_hdr.name_len >= sizeof(kv->name) / sizeof(kv->name[0])) { + kv_hdr.name_len = sizeof(kv->name) / sizeof(kv->name[0]) - 1; + } + kv->name[kv_hdr.name_len] = '\0'; } return result; @@ -367,7 +373,7 @@ static fdb_err_t read_kv(fdb_kvdb_t db, fdb_kv_t kv) static fdb_err_t read_sector_info(fdb_kvdb_t db, uint32_t addr, kv_sec_info_t sector, bool traversal) { fdb_err_t result = FDB_NO_ERR; - struct sector_hdr_data sec_hdr; + struct sector_hdr_data sec_hdr = { 0 }; FDB_ASSERT(addr % db_sec_size(db) == 0); FDB_ASSERT(sector); @@ -457,7 +463,7 @@ static uint32_t get_next_sector_addr(fdb_kvdb_t db, kv_sec_info_t pre_sec) next_addr = pre_sec->addr + pre_sec->combined * db_sec_size(db); } /* check range */ - if (next_addr < db_part_size(db)) { + if (next_addr < db_max_size(db)) { return next_addr; } else { /* no sector */ @@ -709,7 +715,7 @@ static fdb_err_t write_kv_hdr(fdb_kvdb_t db, uint32_t addr, kv_hdr_data_t kv_hdr static fdb_err_t format_sector(fdb_kvdb_t db, uint32_t addr, uint32_t combined_value) { fdb_err_t result = FDB_NO_ERR; - struct sector_hdr_data sec_hdr; + struct sector_hdr_data sec_hdr = { 0 }; FDB_ASSERT(addr % db_sec_size(db) == 0); @@ -1279,7 +1285,7 @@ fdb_err_t fdb_kv_set_default(fdb_kvdb_t db) /* lock the KV cache */ db_lock(db); /* format all sectors */ - for (addr = 0; addr < db_part_size(db); addr += db_sec_size(db)) { + for (addr = 0; addr < db_max_size(db); addr += db_sec_size(db)) { result = format_sector(db, addr, SECTOR_NOT_COMBINED); if (result != FDB_NO_ERR) { goto __exit; @@ -1379,7 +1385,7 @@ void fdb_kv_print(fdb_kvdb_t db) FDB_PRINT("\nmode: next generation\n"); FDB_PRINT("size: %u/%u bytes.\n", using_size + (size_t)((SECTOR_NUM - FDB_GC_EMPTY_SEC_THRESHOLD) * SECTOR_HDR_DATA_SIZE), - (size_t)(db_part_size(db) - db_sec_size(db) * FDB_GC_EMPTY_SEC_THRESHOLD)); + (size_t)(db_max_size(db) - db_sec_size(db) * FDB_GC_EMPTY_SEC_THRESHOLD)); /* unlock the KV cache */ db_unlock(db); @@ -1430,7 +1436,7 @@ static bool check_sec_hdr_cb(kv_sec_info_t sector, void *arg1, void *arg2) size_t *failed_count = arg1; fdb_kvdb_t db = arg2; - FDB_INFO("Sector header info is incorrect. Auto format this sector (0x%08" PRIX32 ").\n", sector->addr); + FDB_DEBUG("Sector header info is incorrect. Auto format this sector (0x%08" PRIX32 ").\n", sector->addr); (*failed_count) ++; format_sector(db, sector->addr, SECTOR_NOT_COMBINED); } @@ -1532,7 +1538,7 @@ void fdb_kvdb_control(fdb_kvdb_t db, int cmd, void *arg) switch (cmd) { case FDB_KVDB_CTRL_SET_SEC_SIZE: - /* the sector size change MUST before database initialization */ + /* this change MUST before database initialization */ FDB_ASSERT(db->parent.init_ok == false); db->parent.sec_size = *(uint32_t *)arg; break; @@ -1545,6 +1551,22 @@ void fdb_kvdb_control(fdb_kvdb_t db, int cmd, void *arg) case FDB_KVDB_CTRL_SET_UNLOCK: db->parent.unlock = (void (*)(fdb_db_t db))arg; break; + case FDB_KVDB_CTRL_SET_FILE_MODE: +#ifdef FDB_USING_FILE_MODE + /* this change MUST before database initialization */ + FDB_ASSERT(db->parent.init_ok == false); + db->parent.file_mode = *(bool *)arg; +#else + FDB_INFO("Error: set file mode Failed. Please defined the FDB_USING_FILE_MODE macro."); +#endif + break; + case FDB_KVDB_CTRL_SET_MAX_SIZE: +#ifdef FDB_USING_FILE_MODE + /* this change MUST before database initialization */ + FDB_ASSERT(db->parent.init_ok == false); + db->parent.max_size = *(uint32_t *)arg; +#endif + break; } } @@ -1582,10 +1604,6 @@ fdb_err_t fdb_kvdb_init(fdb_kvdb_t db, const char *name, const char *part_name, db->default_kvs = *default_kv; /* there is at least one empty sector for GC. */ FDB_ASSERT((FDB_GC_EMPTY_SEC_THRESHOLD > 0 && FDB_GC_EMPTY_SEC_THRESHOLD < SECTOR_NUM)) - /* must be aligned with sector size */ - FDB_ASSERT(db_part_size(db) % db_sec_size(db) == 0); - /* must be has more than 2 sector */ - FDB_ASSERT(db_part_size(db) / db_sec_size(db) >= 2); #ifdef FDB_KV_USING_CACHE for (i = 0; i < FDB_SECTOR_CACHE_TABLE_SIZE; i++) { @@ -1596,7 +1614,7 @@ fdb_err_t fdb_kvdb_init(fdb_kvdb_t db, const char *name, const char *part_name, } #endif /* FDB_KV_USING_CACHE */ - FDB_DEBUG("KVDB in partition %s, size is %u bytes.\n", ((fdb_db_t)db)->part->name, db_part_size(db)); + FDB_DEBUG("KVDB size is %u bytes.\n", db_max_size(db)); result = _fdb_kv_load(db); diff --git a/src/fdb_tsdb.c b/src/fdb_tsdb.c index 278ddf9..d127259 100644 --- a/src/fdb_tsdb.c +++ b/src/fdb_tsdb.c @@ -48,7 +48,8 @@ #define db_name(db) (((fdb_db_t)db)->name) #define db_init_ok(db) (((fdb_db_t)db)->init_ok) #define db_sec_size(db) (((fdb_db_t)db)->sec_size) -#define db_part_size(db) (((fdb_db_t)db)->part->len) +#define db_max_size(db) (((fdb_db_t)db)->max_size) + #define db_lock(db) \ do { \ if (((fdb_db_t)db)->lock) ((fdb_db_t)db)->lock((fdb_db_t)db); \ @@ -126,8 +127,8 @@ static fdb_err_t read_tsl(fdb_tsdb_t db, fdb_tsl_t tsl) static uint32_t get_next_sector_addr(fdb_tsdb_t db, tsdb_sec_info_t pre_sec, uint32_t traversed_len) { - if (traversed_len + db_sec_size(db) <= db_part_size(db)) { - if (pre_sec->addr + db_sec_size(db) < db_part_size(db)) { + if (traversed_len + db_sec_size(db) <= db_max_size(db)) { + if (pre_sec->addr + db_sec_size(db) < db_max_size(db)) { return pre_sec->addr + db_sec_size(db); } else { /* the next sector is on the top of the partition */ @@ -306,7 +307,7 @@ static fdb_err_t update_sec_status(fdb_tsdb_t db, tsdb_sec_info_t sector, fdb_bl /* change current sector to full */ _FDB_WRITE_STATUS(db, cur_sec_addr, status, FDB_SECTOR_STORE_STATUS_NUM, FDB_SECTOR_STORE_FULL); /* calculate next sector address */ - if (sector->addr + db_sec_size(db) < db_part_size(db)) { + if (sector->addr + db_sec_size(db) < db_max_size(db)) { new_sec_addr = sector->addr + db_sec_size(db); } else { new_sec_addr = 0; @@ -314,7 +315,7 @@ static fdb_err_t update_sec_status(fdb_tsdb_t db, tsdb_sec_info_t sector, fdb_bl read_sector_info(db, new_sec_addr, &db->cur_sec, false); if (sector->status != FDB_SECTOR_STORE_EMPTY) { /* calculate the oldest sector address */ - if (new_sec_addr + db_sec_size(db) < db_part_size(db)) { + if (new_sec_addr + db_sec_size(db) < db_max_size(db)) { db->oldest_addr = new_sec_addr + db_sec_size(db); } else { db->oldest_addr = 0; @@ -671,7 +672,7 @@ void fdb_tsdb_control(fdb_tsdb_t db, int cmd, void *arg) switch (cmd) { case FDB_TSDB_CTRL_SET_SEC_SIZE: - /* the sector size change MUST before database initialization */ + /* this change MUST before database initialization */ FDB_ASSERT(db->parent.init_ok == false); db->parent.sec_size = *(uint32_t *)arg; break; @@ -693,6 +694,22 @@ void fdb_tsdb_control(fdb_tsdb_t db, int cmd, void *arg) case FDB_TSDB_CTRL_GET_LAST_TIME: *(fdb_time_t *)arg = db->last_time; break; + case FDB_TSDB_CTRL_SET_FILE_MODE: +#ifdef FDB_USING_FILE_MODE + /* this change MUST before database initialization */ + FDB_ASSERT(db->parent.init_ok == false); + db->parent.file_mode = *(bool *)arg; +#else + FDB_INFO("Error: set file mode Failed. Please defined the FDB_USING_FILE_MODE macro."); +#endif + break; + case FDB_TSDB_CTRL_SET_MAX_SIZE: +#ifdef FDB_USING_FILE_MODE + /* this change MUST before database initialization */ + FDB_ASSERT(db->parent.init_ok == false); + db->parent.max_size = *(uint32_t *)arg; +#endif + break; } } @@ -727,10 +744,6 @@ fdb_err_t fdb_tsdb_init(fdb_tsdb_t db, const char *name, const char *part_name, db->rollover = true; db->oldest_addr = FDB_DATA_UNUSED; db->cur_sec.addr = FDB_DATA_UNUSED; - /* must align with sector size */ - FDB_ASSERT(db_part_size(db) % db_sec_size(db) == 0); - /* must have more than or equal 2 sector */ - FDB_ASSERT(db_part_size(db) / db_sec_size(db) >= 2); /* must less than sector size */ FDB_ASSERT(max_len < db_sec_size(db)); @@ -748,7 +761,7 @@ fdb_err_t fdb_tsdb_init(fdb_tsdb_t db, const char *name, const char *part_name, latest_addr = db->cur_sec.addr; } /* db->cur_sec is the latest sector, and the next is the oldest sector */ - if (latest_addr + db_sec_size(db) >= db_part_size(db)) { + if (latest_addr + db_sec_size(db) >= db_max_size(db)) { /* db->cur_sec is the the bottom of the partition */ db->oldest_addr = 0; } else { @@ -767,7 +780,7 @@ fdb_err_t fdb_tsdb_init(fdb_tsdb_t db, const char *name, const char *part_name, uint32_t addr = db->cur_sec.addr; if (addr == 0) { - addr = db_part_size(db) - db_sec_size(db); + addr = db_max_size(db) - db_sec_size(db); } else { addr -= db_sec_size(db); } diff --git a/src/fdb_utils.c b/src/fdb_utils.c index e736c78..44b571b 100644 --- a/src/fdb_utils.c +++ b/src/fdb_utils.c @@ -235,11 +235,27 @@ size_t fdb_blob_read(fdb_db_t db, fdb_blob_t blob) return read_len; } +#ifdef FDB_USING_FILE_MODE +extern fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void *buf, size_t size); +extern fdb_err_t _fdb_file_write(fdb_db_t db, uint32_t addr, const void *buf, size_t size); +extern fdb_err_t _fdb_file_erase(fdb_db_t db, uint32_t addr, size_t size); +#endif /* FDB_USING_FILE_LIBC */ + fdb_err_t _fdb_flash_read(fdb_db_t db, uint32_t addr, void *buf, size_t size) { fdb_err_t result = FDB_NO_ERR; - fal_partition_read(db->part, addr, (uint8_t *)buf, size); + if (db->file_mode) { +#ifdef FDB_USING_FILE_MODE + return _fdb_file_read(db, addr, buf, size); +#else + return FDB_READ_ERR; +#endif + } else { +#ifdef FDB_USING_FAL_MODE + fal_partition_read(db->storage.part, addr, (uint8_t *) buf, size); +#endif + } return result; } @@ -248,9 +264,18 @@ fdb_err_t _fdb_flash_erase(fdb_db_t db, uint32_t addr, size_t size) { fdb_err_t result = FDB_NO_ERR; - if (fal_partition_erase(db->part, addr, size) < 0) - { - result = FDB_ERASE_ERR; + if (db->file_mode) { +#ifdef FDB_USING_FILE_MODE + return _fdb_file_erase(db, addr, size); +#else + return FDB_ERASE_ERR; +#endif /* FDB_USING_FILE_MODE */ + } else { +#ifdef FDB_USING_FAL_MODE + if (fal_partition_erase(db->storage.part, addr, size) < 0) { + result = FDB_ERASE_ERR; + } +#endif } return result; @@ -260,9 +285,19 @@ fdb_err_t _fdb_flash_write(fdb_db_t db, uint32_t addr, const void *buf, size_t s { fdb_err_t result = FDB_NO_ERR; - if (fal_partition_write(db->part, addr, (uint8_t *)buf, size) < 0) - { - result = FDB_WRITE_ERR; + if (db->file_mode) { +#ifdef FDB_USING_FILE_MODE + return _fdb_file_write(db, addr, buf, size); +#else + return FDB_READ_ERR; +#endif /* FDB_USING_FILE_MODE */ + } else { +#ifdef FDB_USING_FAL_MODE + if (fal_partition_write(db->storage.part, addr, (uint8_t *)buf, size) < 0) + { + result = FDB_WRITE_ERR; + } +#endif } return result;