[fdb] Add file access cache in file mode. The GC speed is up 2X.

This commit is contained in:
armink 2023-11-19 12:34:43 +08:00
parent 189b22e0a4
commit 718f73fbe6
4 changed files with 138 additions and 33 deletions

View File

@ -47,6 +47,11 @@ extern "C" {
#define FDB_USING_FILE_MODE
#endif
/* the file cache table size, it will improve GC speed in file mode when using cache */
#ifndef FDB_FILE_CACHE_TABLE_SIZE
#define FDB_FILE_CACHE_TABLE_SIZE 2
#endif
#ifndef FDB_WRITE_GRAN
#define FDB_WRITE_GRAN 1
#endif
@ -274,11 +279,12 @@ struct fdb_db {
bool file_mode; /**< is file mode, default is false */
bool not_formatable; /**< is can NOT be formated mode, default is false */
#ifdef FDB_USING_FILE_MODE
uint32_t cur_file_sec[FDB_FILE_CACHE_TABLE_SIZE];/**< last operate sector address */
#if defined(FDB_USING_FILE_POSIX_MODE)
int cur_file; /**< current file object */
int cur_file[FDB_FILE_CACHE_TABLE_SIZE]; /**< current file object */
#elif defined(FDB_USING_FILE_LIBC_MODE)
FILE *cur_file; /**< current file object */
#endif
FILE *cur_file[FDB_FILE_CACHE_TABLE_SIZE]; /**< current file object */
#endif /* FDB_USING_FILE_MODE */
uint32_t cur_sec; /**< current operate sector address */
#endif
void (*lock)(fdb_db_t db); /**< lock the database operate */

View File

@ -50,6 +50,9 @@
#define FDB_DATA_UNUSED 0x00000000
#endif
/* invalid address */
#define FDB_FAILED_ADDR 0xFFFFFFFF
size_t _fdb_set_status(uint8_t status_table[], size_t status_num, size_t status_index);
size_t _fdb_get_status(uint8_t status_table[], size_t status_num);
uint32_t _fdb_continue_ff_addr(fdb_db_t db, uint32_t start, uint32_t end);

View File

@ -44,13 +44,14 @@ fdb_err_t _fdb_init_ex(fdb_db_t db, const char *name, const char *path, fdb_db_t
if (db->file_mode) {
#ifdef FDB_USING_FILE_MODE
memset(db->cur_file_sec, FDB_FAILED_ADDR, FDB_FILE_CACHE_TABLE_SIZE * sizeof(db->cur_file_sec[0]));
/* must set when using file mode */
FDB_ASSERT(db->sec_size != 0);
FDB_ASSERT(db->max_size != 0);
#ifdef FDB_USING_FILE_POSIX_MODE
db->cur_file = -1;
memset(db->cur_file, -1, FDB_FILE_CACHE_TABLE_SIZE * sizeof(db->cur_file[0]));
#else
db->cur_file = 0;
memset(db->cur_file, 0, FDB_FILE_CACHE_TABLE_SIZE * sizeof(db->cur_file[0]));
#endif
db->storage.dir = path;
FDB_ASSERT(strlen(path) != 0)
@ -120,15 +121,17 @@ void _fdb_deinit(fdb_db_t db)
if (db->init_ok) {
#ifdef FDB_USING_FILE_MODE
for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) {
#ifdef FDB_USING_FILE_POSIX_MODE
if (db->cur_file > 0) {
close(db->cur_file);
}
if (db->cur_file[i] > 0) {
close(db->cur_file[i]);
}
#else
if (db->cur_file != 0) {
fclose(db->cur_file);
}
if (db->cur_file[i] != 0) {
fclose(db->cur_file[i]);
}
#endif /* FDB_USING_FILE_POSIX_MODE */
}
#endif /* FDB_USING_FILE_MODE */
}

View File

@ -42,37 +42,81 @@ static void get_db_file_path(fdb_db_t db, uint32_t addr, char *path, size_t size
#include <unistd.h>
#endif
static int get_file_from_cache(fdb_db_t db, uint32_t sec_addr)
{
for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) {
if (db->cur_file_sec[i] == sec_addr)
return db->cur_file[i];
}
return -1;
}
static void update_file_cache(fdb_db_t db, uint32_t sec_addr, int fd)
{
int free_index = FDB_FILE_CACHE_TABLE_SIZE;
for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) {
if (db->cur_file_sec[i] == sec_addr) {
db->cur_file[i] = fd;
return;
} else if (db->cur_file[i] == -1) {
free_index = i;
}
}
if (fd > 0) {
if (free_index < FDB_FILE_CACHE_TABLE_SIZE) {
db->cur_file[free_index] = fd;
db->cur_file_sec[free_index] = sec_addr;
} else {
/* cache is full, move to end */
for (int i = FDB_FILE_CACHE_TABLE_SIZE - 1; i > 0; i--) {
close(db->cur_file[i]);
memcpy(&db->cur_file[i], &db->cur_file[i - 1], sizeof(db->cur_file[0]));
memcpy(&db->cur_file_sec[i], &db->cur_file_sec[i - 1], sizeof(db->cur_file_sec[0]));
}
/* add to head */
db->cur_file[0] = fd;
db->cur_file_sec[0] = sec_addr;
}
}
}
static int open_db_file(fdb_db_t db, uint32_t addr, bool clean)
{
uint32_t sec_addr = FDB_ALIGN_DOWN(addr, db->sec_size);
int fd = db->cur_file;
int fd = get_file_from_cache(db, sec_addr);
char path[DB_PATH_MAX];
if (sec_addr != db->cur_sec || fd <= 0 || clean) {
if (fd <= 0 || clean) {
get_db_file_path(db, addr, path, DB_PATH_MAX);
if (fd > 0) {
close(fd);
fd = -1;
update_file_cache(db, sec_addr, fd);
}
if (clean) {
/* clean the old file */
fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0777);
if (fd <= 0) {
int clean_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0777);
if (clean_fd <= 0) {
FDB_INFO("Error: open (%s) file failed.\n", path);
}
else {
close(fd);
fd = -1;
close(clean_fd);
clean_fd = -1;
}
}
/* open the database file */
fd = open(path, O_RDWR, 0777);
if (get_file_from_cache(db, sec_addr) < 0) {
/* open the database file */
fd = open(path, O_RDWR, 0777);
update_file_cache(db, sec_addr, fd);
}
db->cur_sec = sec_addr;
}
db->cur_file = fd;
return db->cur_file;
return fd;
}
fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void *buf, size_t size)
@ -133,35 +177,84 @@ fdb_err_t _fdb_file_erase(fdb_db_t db, uint32_t addr, size_t size)
return result;
}
#elif defined(FDB_USING_FILE_LIBC_MODE)
static FILE *get_file_from_cache(fdb_db_t db, uint32_t sec_addr)
{
for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) {
if (db->cur_file_sec[i] == sec_addr)
return db->cur_file[i];
}
return NULL;
}
static void update_file_cache(fdb_db_t db, uint32_t sec_addr, FILE *fd)
{
int free_index = FDB_FILE_CACHE_TABLE_SIZE;
for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) {
if (db->cur_file_sec[i] == sec_addr) {
db->cur_file[i] = fd;
return;
}
else if (db->cur_file[i] == 0) {
free_index = i;
}
}
if (fd) {
if (free_index < FDB_FILE_CACHE_TABLE_SIZE) {
db->cur_file[free_index] = fd;
db->cur_file_sec[free_index] = sec_addr;
}
else {
/* cache is full, move to end */
for (int i = FDB_FILE_CACHE_TABLE_SIZE - 1; i > 0; i--) {
close(db->cur_file[i]);
memcpy(&db->cur_file[i], &db->cur_file[i - 1], sizeof(db->cur_file[0]));
memcpy(&db->cur_file_sec[i], &db->cur_file_sec[i - 1], sizeof(db->cur_file_sec[0]));
}
/* add to head */
db->cur_file[0] = fd;
db->cur_file_sec[0] = sec_addr;
}
}
}
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);
FILE *fd = get_file_from_cache(db, sec_addr);
char path[DB_PATH_MAX];
if (sec_addr != db->cur_sec || db->cur_file == NULL || clean) {
char path[DB_PATH_MAX];
if (fd == NULL || clean) {
get_db_file_path(db, addr, path, DB_PATH_MAX);
if (db->cur_file) {
fclose(db->cur_file);
if (fd) {
fclose(fd);
fd = NULL;
update_file_cache(db, sec_addr, fd);
}
if (clean) {
/* clean the old file */
db->cur_file = fopen(path, "wb+");
if (db->cur_file == NULL) {
FILE *clean_fd = fopen(path, "wb+");
if (clean_fd == NULL) {
FDB_INFO("Error: open (%s) file failed.\n", path);
} else {
fclose(db->cur_file);
fclose(clean_fd);
clean_fd = NULL;
}
}
/* open the database file */
db->cur_file = fopen(path, "rb+");
if (get_file_from_cache(db, sec_addr) == NULL) {
/* open the database file */
fd = fopen(path, "rb+");
update_file_cache(db, sec_addr, fd);
}
db->cur_sec = sec_addr;
}
return db->cur_file;
return fd;
}
fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void *buf, size_t size)