[fdb] Add file access cache in file mode. The GC speed is up 2X.
This commit is contained in:
parent
189b22e0a4
commit
718f73fbe6
|
@ -47,6 +47,11 @@ extern "C" {
|
||||||
#define FDB_USING_FILE_MODE
|
#define FDB_USING_FILE_MODE
|
||||||
#endif
|
#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
|
#ifndef FDB_WRITE_GRAN
|
||||||
#define FDB_WRITE_GRAN 1
|
#define FDB_WRITE_GRAN 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -274,11 +279,12 @@ struct fdb_db {
|
||||||
bool file_mode; /**< is file mode, default is false */
|
bool file_mode; /**< is file mode, default is false */
|
||||||
bool not_formatable; /**< is can NOT be formated mode, default is false */
|
bool not_formatable; /**< is can NOT be formated mode, default is false */
|
||||||
#ifdef FDB_USING_FILE_MODE
|
#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)
|
#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)
|
#elif defined(FDB_USING_FILE_LIBC_MODE)
|
||||||
FILE *cur_file; /**< current file object */
|
FILE *cur_file[FDB_FILE_CACHE_TABLE_SIZE]; /**< current file object */
|
||||||
#endif
|
#endif /* FDB_USING_FILE_MODE */
|
||||||
uint32_t cur_sec; /**< current operate sector address */
|
uint32_t cur_sec; /**< current operate sector address */
|
||||||
#endif
|
#endif
|
||||||
void (*lock)(fdb_db_t db); /**< lock the database operate */
|
void (*lock)(fdb_db_t db); /**< lock the database operate */
|
||||||
|
|
|
@ -50,6 +50,9 @@
|
||||||
#define FDB_DATA_UNUSED 0x00000000
|
#define FDB_DATA_UNUSED 0x00000000
|
||||||
#endif
|
#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_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);
|
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);
|
uint32_t _fdb_continue_ff_addr(fdb_db_t db, uint32_t start, uint32_t end);
|
||||||
|
|
19
src/fdb.c
19
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) {
|
if (db->file_mode) {
|
||||||
#ifdef FDB_USING_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 */
|
/* must set when using file mode */
|
||||||
FDB_ASSERT(db->sec_size != 0);
|
FDB_ASSERT(db->sec_size != 0);
|
||||||
FDB_ASSERT(db->max_size != 0);
|
FDB_ASSERT(db->max_size != 0);
|
||||||
#ifdef FDB_USING_FILE_POSIX_MODE
|
#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
|
#else
|
||||||
db->cur_file = 0;
|
memset(db->cur_file, 0, FDB_FILE_CACHE_TABLE_SIZE * sizeof(db->cur_file[0]));
|
||||||
#endif
|
#endif
|
||||||
db->storage.dir = path;
|
db->storage.dir = path;
|
||||||
FDB_ASSERT(strlen(path) != 0)
|
FDB_ASSERT(strlen(path) != 0)
|
||||||
|
@ -120,15 +121,17 @@ void _fdb_deinit(fdb_db_t db)
|
||||||
|
|
||||||
if (db->init_ok) {
|
if (db->init_ok) {
|
||||||
#ifdef FDB_USING_FILE_MODE
|
#ifdef FDB_USING_FILE_MODE
|
||||||
|
for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) {
|
||||||
#ifdef FDB_USING_FILE_POSIX_MODE
|
#ifdef FDB_USING_FILE_POSIX_MODE
|
||||||
if (db->cur_file > 0) {
|
if (db->cur_file[i] > 0) {
|
||||||
close(db->cur_file);
|
close(db->cur_file[i]);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (db->cur_file != 0) {
|
if (db->cur_file[i] != 0) {
|
||||||
fclose(db->cur_file);
|
fclose(db->cur_file[i]);
|
||||||
}
|
}
|
||||||
#endif /* FDB_USING_FILE_POSIX_MODE */
|
#endif /* FDB_USING_FILE_POSIX_MODE */
|
||||||
|
}
|
||||||
#endif /* FDB_USING_FILE_MODE */
|
#endif /* FDB_USING_FILE_MODE */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
137
src/fdb_file.c
137
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 <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#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)
|
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);
|
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];
|
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);
|
get_db_file_path(db, addr, path, DB_PATH_MAX);
|
||||||
|
|
||||||
if (fd > 0) {
|
if (fd > 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
|
update_file_cache(db, sec_addr, fd);
|
||||||
}
|
}
|
||||||
if (clean) {
|
if (clean) {
|
||||||
/* clean the old file */
|
/* clean the old file */
|
||||||
fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0777);
|
int clean_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0777);
|
||||||
if (fd <= 0) {
|
if (clean_fd <= 0) {
|
||||||
FDB_INFO("Error: open (%s) file failed.\n", path);
|
FDB_INFO("Error: open (%s) file failed.\n", path);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
close(fd);
|
close(clean_fd);
|
||||||
fd = -1;
|
clean_fd = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* open the database file */
|
if (get_file_from_cache(db, sec_addr) < 0) {
|
||||||
fd = open(path, O_RDWR, 0777);
|
/* open the database file */
|
||||||
|
fd = open(path, O_RDWR, 0777);
|
||||||
|
update_file_cache(db, sec_addr, fd);
|
||||||
|
}
|
||||||
db->cur_sec = sec_addr;
|
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)
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
#elif defined(FDB_USING_FILE_LIBC_MODE)
|
#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)
|
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);
|
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) {
|
if (fd == NULL || clean) {
|
||||||
char path[DB_PATH_MAX];
|
|
||||||
|
|
||||||
get_db_file_path(db, addr, path, DB_PATH_MAX);
|
get_db_file_path(db, addr, path, DB_PATH_MAX);
|
||||||
|
|
||||||
if (db->cur_file) {
|
if (fd) {
|
||||||
fclose(db->cur_file);
|
fclose(fd);
|
||||||
|
fd = NULL;
|
||||||
|
update_file_cache(db, sec_addr, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clean) {
|
if (clean) {
|
||||||
/* clean the old file */
|
/* clean the old file */
|
||||||
db->cur_file = fopen(path, "wb+");
|
FILE *clean_fd = fopen(path, "wb+");
|
||||||
if (db->cur_file == NULL) {
|
if (clean_fd == NULL) {
|
||||||
FDB_INFO("Error: open (%s) file failed.\n", path);
|
FDB_INFO("Error: open (%s) file failed.\n", path);
|
||||||
} else {
|
} else {
|
||||||
fclose(db->cur_file);
|
fclose(clean_fd);
|
||||||
|
clean_fd = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (get_file_from_cache(db, sec_addr) == NULL) {
|
||||||
/* open the database file */
|
/* open the database file */
|
||||||
db->cur_file = fopen(path, "rb+");
|
fd = fopen(path, "rb+");
|
||||||
|
update_file_cache(db, sec_addr, fd);
|
||||||
|
}
|
||||||
db->cur_sec = sec_addr;
|
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)
|
fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void *buf, size_t size)
|
||||||
|
|
Loading…
Reference in New Issue