From 718f73fbe65dbdcee2108cff8cc7bea4462fbbc0 Mon Sep 17 00:00:00 2001 From: armink Date: Sun, 19 Nov 2023 12:34:43 +0800 Subject: [PATCH] [fdb] Add file access cache in file mode. The GC speed is up 2X. --- inc/fdb_def.h | 12 +++- inc/fdb_low_lvl.h | 3 + src/fdb.c | 19 ++++--- src/fdb_file.c | 137 ++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 138 insertions(+), 33 deletions(-) diff --git a/inc/fdb_def.h b/inc/fdb_def.h index ea44de6..f124896 100644 --- a/inc/fdb_def.h +++ b/inc/fdb_def.h @@ -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 */ diff --git a/inc/fdb_low_lvl.h b/inc/fdb_low_lvl.h index e6f6ff4..c252dca 100644 --- a/inc/fdb_low_lvl.h +++ b/inc/fdb_low_lvl.h @@ -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); diff --git a/src/fdb.c b/src/fdb.c index 5b066c8..021aa90 100644 --- a/src/fdb.c +++ b/src/fdb.c @@ -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 */ } diff --git a/src/fdb_file.c b/src/fdb_file.c index 0b5ad91..1c99a38 100644 --- a/src/fdb_file.c +++ b/src/fdb_file.c @@ -42,37 +42,81 @@ static void get_db_file_path(fdb_db_t db, uint32_t addr, char *path, size_t size #include #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)