Add file storage mode.

This commit is contained in:
armink 2021-01-03 19:17:51 +08:00
parent d699382c1a
commit 9eea31ac18
12 changed files with 412 additions and 54 deletions

View File

@ -23,6 +23,9 @@
/* using TSDB (Time series database) feature */ /* using TSDB (Time series database) feature */
#define FDB_USING_TSDB #define FDB_USING_TSDB
/* Using FAL storage mode */
#define FDB_USING_FAL_MODE
/* the flash write granularity, unit: bit /* the flash write granularity, unit: bit
* only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */ * only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */
#define FDB_WRITE_GRAN 1 /* @note you must define it for a value */ #define FDB_WRITE_GRAN 1 /* @note you must define it for a value */

View File

@ -23,6 +23,9 @@
/* using TSDB (Time series database) feature */ /* using TSDB (Time series database) feature */
#define FDB_USING_TSDB #define FDB_USING_TSDB
/* Using FAL storage mode */
#define FDB_USING_FAL_MODE
/* the flash write granularity, unit: bit /* the flash write granularity, unit: bit
* only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */ * only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */
#define FDB_WRITE_GRAN 32 #define FDB_WRITE_GRAN 32

View File

@ -23,6 +23,9 @@
/* using TSDB (Time series database) feature */ /* using TSDB (Time series database) feature */
#define FDB_USING_TSDB #define FDB_USING_TSDB
/* Using FAL storage mode */
#define FDB_USING_FAL_MODE
/* the flash write granularity, unit: bit /* the flash write granularity, unit: bit
* only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */ * only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */
#define FDB_WRITE_GRAN 8 #define FDB_WRITE_GRAN 8

View File

@ -23,6 +23,9 @@
/* using TSDB (Time series database) feature */ /* using TSDB (Time series database) feature */
#define FDB_USING_TSDB #define FDB_USING_TSDB
/* Using FAL storage mode */
#define FDB_USING_FAL_MODE
/* the flash write granularity, unit: bit /* the flash write granularity, unit: bit
* only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */ * only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */
#define FDB_WRITE_GRAN 8 #define FDB_WRITE_GRAN 8

View File

@ -23,12 +23,23 @@
/* using TSDB (Time series database) feature */ /* using TSDB (Time series database) feature */
#define FDB_USING_TSDB #define FDB_USING_TSDB
/* Using FAL storage mode */
#define FDB_USING_FAL_MODE
#ifdef FDB_USING_FAL_MODE
/* the flash write granularity, unit: bit /* the flash write granularity, unit: bit
* only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */ * only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */
#define FDB_WRITE_GRAN /* @note you must define it for a value */ #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. */ /* 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() */ /* log print macro. default EF_PRINT macro is printf() */
/* #define FDB_PRINT(...) my_printf(__VA_ARGS__) */ /* #define FDB_PRINT(...) my_printf(__VA_ARGS__) */

View File

@ -39,6 +39,14 @@ extern "C" {
#define FDB_KV_USING_CACHE #define FDB_KV_USING_CACHE
#endif #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() */ /* log function. default FDB_PRINT macro is printf() */
#ifndef FDB_PRINT #ifndef FDB_PRINT
#define FDB_PRINT(...) printf(__VA_ARGS__) #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_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_LOCK 0x2 /**< set lock function control command */
#define FDB_KVDB_CTRL_SET_UNLOCK 0x3 /**< set unlock 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_SET_SEC_SIZE 0x0 /**< set sector size control command */
#define FDB_TSDB_CTRL_GET_SEC_SIZE 0x1 /**< get 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_SET_ROLLOVER 0x4 /**< set rollover control command */
#define FDB_TSDB_CTRL_GET_ROLLOVER 0x5 /**< get 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_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; typedef time_t fdb_time_t;
#ifdef FDB_USING_TIMESTAMP_64BIT #ifdef FDB_USING_TIMESTAMP_64BIT
@ -238,9 +250,22 @@ typedef struct fdb_db *fdb_db_t;
struct fdb_db { struct fdb_db {
const char *name; /**< database name */ const char *name; /**< database name */
fdb_db_type type; /**< database type */ 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 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 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 (*lock)(fdb_db_t db); /**< lock the database operate */
void (*unlock)(fdb_db_t db); /**< unlock 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 */ struct tsdb_sec_info cur_sec; /**< current using sector */
fdb_time_t last_time; /**< last TSL timestamp */ fdb_time_t last_time; /**< last TSL timestamp */
fdb_get_time get_time; /**< the current timestamp get function */ 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 */ uint32_t oldest_addr; /**< the oldest sector start address */
bool rollover; /**< the oldest data will rollover by newest data, default is true */ bool rollover; /**< the oldest data will rollover by newest data, default is true */

View File

@ -15,11 +15,17 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h>
#include <time.h> #include <time.h>
#include <fal.h>
#include <fdb_cfg.h> #include <fdb_cfg.h>
#ifdef FDB_USING_FAL_MODE
#include <fal.h>
#endif
#include <fdb_def.h> #include <fdb_def.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View File

@ -16,10 +16,12 @@
#define FDB_LOG_TAG "" #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) 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(db);
FDB_ASSERT(name); FDB_ASSERT(name);
FDB_ASSERT(part_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->name = name;
db->type = type; db->type = type;
db->user_data = user_data; db->user_data = user_data;
/* FAL (Flash Abstraction Layer) initialization */
fal_init(); if (db->file_mode) {
/* check the flash partition */ #ifdef FDB_USING_FILE_MODE
if ((db->part = fal_partition_find(part_name)) == NULL) { /* must set when using file mode */
FDB_INFO("Error: Partition (%s) not found.\n", part_name); FDB_ASSERT(db->sec_size != 0);
return FDB_PART_NOT_FOUND; 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; /* must align with sector size */
if (db->sec_size == 0) { FDB_ASSERT(db->max_size % db->sec_size == 0);
db->sec_size = block_size; /* must have more than or equal 2 sector */
} else { FDB_ASSERT(db->max_size / db->sec_size >= 2);
/* must be aligned with block size */
FDB_ASSERT(db->sec_size % block_size == 0);
}
return FDB_NO_ERR; return FDB_NO_ERR;
} }

209
src/fdb_file.c Normal file
View File

@ -0,0 +1,209 @@
/*
* Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
* Copyright (c) 2020, enkiller, <462747508@qq.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include <flashdb.h>
#include <fdb_low_lvl.h>
#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 */

View File

@ -62,7 +62,8 @@
#define KV_STATUS_TABLE_SIZE FDB_STATUS_TABLE_SIZE(FDB_KV_STATUS_NUM) #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_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)) #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_name(db) (((fdb_db_t)db)->name)
#define db_init_ok(db) (((fdb_db_t)db)->init_ok) #define db_init_ok(db) (((fdb_db_t)db)->init_ok)
#define db_sec_size(db) (((fdb_db_t)db)->sec_size) #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) \ #define db_lock(db) \
do { \ do { \
if (((fdb_db_t)db)->lock) ((fdb_db_t)db)->lock((fdb_db_t)db); \ 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->status = (fdb_kv_status_t) _fdb_get_status(kv_hdr.status_table, FDB_KV_STATUS_NUM);
kv->len = kv_hdr.len; 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 */ /* the KV length was not write, so reserved the info for current KV */
kv->len = KV_HDR_DATA_SIZE; kv->len = KV_HDR_DATA_SIZE;
if (kv->status != FDB_KV_ERR_HDR) { 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; kv->crc_is_ok = false;
return FDB_READ_ERR; 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 扇区连续模式,或者写入长度没有写入完整 //TODO 扇区连续模式,或者写入长度没有写入完整
FDB_ASSERT(0); 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->addr.value = kv_name_addr + FDB_WG_ALIGN(kv_hdr.name_len);
kv->value_len = kv_hdr.value_len; kv->value_len = kv_hdr.value_len;
kv->name_len = kv_hdr.name_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; 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) 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; 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(addr % db_sec_size(db) == 0);
FDB_ASSERT(sector); 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); next_addr = pre_sec->addr + pre_sec->combined * db_sec_size(db);
} }
/* check range */ /* check range */
if (next_addr < db_part_size(db)) { if (next_addr < db_max_size(db)) {
return next_addr; return next_addr;
} else { } else {
/* no sector */ /* 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) static fdb_err_t format_sector(fdb_kvdb_t db, uint32_t addr, uint32_t combined_value)
{ {
fdb_err_t result = FDB_NO_ERR; 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(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 */ /* lock the KV cache */
db_lock(db); db_lock(db);
/* format all sectors */ /* 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); result = format_sector(db, addr, SECTOR_NOT_COMBINED);
if (result != FDB_NO_ERR) { if (result != FDB_NO_ERR) {
goto __exit; goto __exit;
@ -1379,7 +1385,7 @@ void fdb_kv_print(fdb_kvdb_t db)
FDB_PRINT("\nmode: next generation\n"); 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), 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 */ /* unlock the KV cache */
db_unlock(db); 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; size_t *failed_count = arg1;
fdb_kvdb_t db = arg2; 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) ++; (*failed_count) ++;
format_sector(db, sector->addr, SECTOR_NOT_COMBINED); 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) { switch (cmd) {
case FDB_KVDB_CTRL_SET_SEC_SIZE: 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); FDB_ASSERT(db->parent.init_ok == false);
db->parent.sec_size = *(uint32_t *)arg; db->parent.sec_size = *(uint32_t *)arg;
break; break;
@ -1545,6 +1551,22 @@ void fdb_kvdb_control(fdb_kvdb_t db, int cmd, void *arg)
case FDB_KVDB_CTRL_SET_UNLOCK: case FDB_KVDB_CTRL_SET_UNLOCK:
db->parent.unlock = (void (*)(fdb_db_t db))arg; db->parent.unlock = (void (*)(fdb_db_t db))arg;
break; 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; db->default_kvs = *default_kv;
/* there is at least one empty sector for GC. */ /* there is at least one empty sector for GC. */
FDB_ASSERT((FDB_GC_EMPTY_SEC_THRESHOLD > 0 && FDB_GC_EMPTY_SEC_THRESHOLD < SECTOR_NUM)) 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 #ifdef FDB_KV_USING_CACHE
for (i = 0; i < FDB_SECTOR_CACHE_TABLE_SIZE; i++) { 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 */ #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); result = _fdb_kv_load(db);

View File

@ -48,7 +48,8 @@
#define db_name(db) (((fdb_db_t)db)->name) #define db_name(db) (((fdb_db_t)db)->name)
#define db_init_ok(db) (((fdb_db_t)db)->init_ok) #define db_init_ok(db) (((fdb_db_t)db)->init_ok)
#define db_sec_size(db) (((fdb_db_t)db)->sec_size) #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) \ #define db_lock(db) \
do { \ do { \
if (((fdb_db_t)db)->lock) ((fdb_db_t)db)->lock((fdb_db_t)db); \ 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) 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 (traversed_len + db_sec_size(db) <= db_max_size(db)) {
if (pre_sec->addr + db_sec_size(db) < db_part_size(db)) { if (pre_sec->addr + db_sec_size(db) < db_max_size(db)) {
return pre_sec->addr + db_sec_size(db); return pre_sec->addr + db_sec_size(db);
} else { } else {
/* the next sector is on the top of the partition */ /* 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 */ /* change current sector to full */
_FDB_WRITE_STATUS(db, cur_sec_addr, status, FDB_SECTOR_STORE_STATUS_NUM, FDB_SECTOR_STORE_FULL); _FDB_WRITE_STATUS(db, cur_sec_addr, status, FDB_SECTOR_STORE_STATUS_NUM, FDB_SECTOR_STORE_FULL);
/* calculate next sector address */ /* 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); new_sec_addr = sector->addr + db_sec_size(db);
} else { } else {
new_sec_addr = 0; 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); read_sector_info(db, new_sec_addr, &db->cur_sec, false);
if (sector->status != FDB_SECTOR_STORE_EMPTY) { if (sector->status != FDB_SECTOR_STORE_EMPTY) {
/* calculate the oldest sector address */ /* 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); db->oldest_addr = new_sec_addr + db_sec_size(db);
} else { } else {
db->oldest_addr = 0; db->oldest_addr = 0;
@ -671,7 +672,7 @@ void fdb_tsdb_control(fdb_tsdb_t db, int cmd, void *arg)
switch (cmd) { switch (cmd) {
case FDB_TSDB_CTRL_SET_SEC_SIZE: 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); FDB_ASSERT(db->parent.init_ok == false);
db->parent.sec_size = *(uint32_t *)arg; db->parent.sec_size = *(uint32_t *)arg;
break; break;
@ -693,6 +694,22 @@ void fdb_tsdb_control(fdb_tsdb_t db, int cmd, void *arg)
case FDB_TSDB_CTRL_GET_LAST_TIME: case FDB_TSDB_CTRL_GET_LAST_TIME:
*(fdb_time_t *)arg = db->last_time; *(fdb_time_t *)arg = db->last_time;
break; 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->rollover = true;
db->oldest_addr = FDB_DATA_UNUSED; db->oldest_addr = FDB_DATA_UNUSED;
db->cur_sec.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 */ /* must less than sector size */
FDB_ASSERT(max_len < db_sec_size(db)); 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; latest_addr = db->cur_sec.addr;
} }
/* db->cur_sec is the latest sector, and the next is the oldest sector */ /* 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->cur_sec is the the bottom of the partition */
db->oldest_addr = 0; db->oldest_addr = 0;
} else { } 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; uint32_t addr = db->cur_sec.addr;
if (addr == 0) { if (addr == 0) {
addr = db_part_size(db) - db_sec_size(db); addr = db_max_size(db) - db_sec_size(db);
} else { } else {
addr -= db_sec_size(db); addr -= db_sec_size(db);
} }

View File

@ -235,11 +235,27 @@ size_t fdb_blob_read(fdb_db_t db, fdb_blob_t blob)
return read_len; 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 _fdb_flash_read(fdb_db_t db, uint32_t addr, void *buf, size_t size)
{ {
fdb_err_t result = FDB_NO_ERR; 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; 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; fdb_err_t result = FDB_NO_ERR;
if (fal_partition_erase(db->part, addr, size) < 0) if (db->file_mode) {
{ #ifdef FDB_USING_FILE_MODE
result = FDB_ERASE_ERR; 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; 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; fdb_err_t result = FDB_NO_ERR;
if (fal_partition_write(db->part, addr, (uint8_t *)buf, size) < 0) if (db->file_mode) {
{ #ifdef FDB_USING_FILE_MODE
result = FDB_WRITE_ERR; 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; return result;