Add file storage mode.
This commit is contained in:
parent
d699382c1a
commit
9eea31ac18
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -15,11 +15,17 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <fal.h>
|
||||
#include <fdb_cfg.h>
|
||||
|
||||
#ifdef FDB_USING_FAL_MODE
|
||||
#include <fal.h>
|
||||
#endif
|
||||
|
||||
#include <fdb_def.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
59
src/fdb.c
59
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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue