Skip to content
2 changes: 2 additions & 0 deletions inc/fdb_low_lvl.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,6 @@ fdb_err_t _fdb_flash_read(fdb_db_t db, uint32_t addr, void *buf, size_t size);
fdb_err_t _fdb_flash_erase(fdb_db_t db, uint32_t addr, size_t size);
fdb_err_t _fdb_flash_write(fdb_db_t db, uint32_t addr, const void *buf, size_t size, bool sync);

fdb_err_t align_write(fdb_db_t db, uint32_t addr, const uint32_t *buf, size_t size);

#endif /* _FDB_LOW_LVL_H_ */
34 changes: 3 additions & 31 deletions src/fdb_kvdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ static fdb_err_t read_sector_info(fdb_kvdb_t db, uint32_t addr, kv_sec_info_t se
sector->addr = addr;
sector->magic = sec_hdr.magic;
/* check magic word and combined value */
if (sector->magic != SECTOR_MAGIC_WORD ||
if (sector->magic != SECTOR_MAGIC_WORD ||
(sec_hdr.combined != SECTOR_NOT_COMBINED && sec_hdr.combined != SECTOR_COMBINED)) {
sector->check_ok = false;
sector->combined = SECTOR_NOT_COMBINED;
Expand Down Expand Up @@ -1177,34 +1177,6 @@ static void gc_collect(fdb_kvdb_t db)
gc_collect_by_free_size(db, db_max_size(db));
}

static fdb_err_t align_write(fdb_kvdb_t db, uint32_t addr, const uint32_t *buf, size_t size)
{
fdb_err_t result = FDB_NO_ERR;
size_t align_remain;

#if (FDB_WRITE_GRAN / 8 > 0)
uint8_t align_data[FDB_WRITE_GRAN / 8];
size_t align_data_size = sizeof(align_data);
#else
/* For compatibility with C89 */
uint8_t align_data_u8, *align_data = &align_data_u8;
size_t align_data_size = 1;
#endif

memset(align_data, FDB_BYTE_ERASED, align_data_size);
if(FDB_WG_ALIGN_DOWN(size) > 0) {
result = _fdb_flash_write((fdb_db_t) db, addr, buf, FDB_WG_ALIGN_DOWN(size), false);
}

align_remain = size - FDB_WG_ALIGN_DOWN(size);
if (result == FDB_NO_ERR && align_remain) {
memcpy(align_data, (uint8_t *) buf + FDB_WG_ALIGN_DOWN(size), align_remain);
result = _fdb_flash_write((fdb_db_t) db, addr + FDB_WG_ALIGN_DOWN(size), (uint32_t *) align_data,
align_data_size, false);
}

return result;
}

static fdb_err_t create_kv_blob(fdb_kvdb_t db, kv_sec_info_t sector, const char *key, const void *value, size_t len)
{
Expand Down Expand Up @@ -1818,9 +1790,9 @@ fdb_err_t fdb_kvdb_init(fdb_kvdb_t db, const char *name, const char *path, struc

FDB_DEBUG("KVDB size is %" PRIu32 " bytes.\n", db_max_size(db));
db_unlock(db);

result = _fdb_kv_load(db);

db_lock(db);
#ifdef FDB_KV_AUTO_UPDATE
if (result == FDB_NO_ERR) {
Expand Down
89 changes: 64 additions & 25 deletions src/fdb_tsdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,17 @@

#if defined(FDB_USING_TSDB)

#if (FDB_WRITE_GRAN == 64) || (FDB_WRITE_GRAN == 128)
#error "Flash 64 or 128 bits write granularity is not supported in TSDB yet!"
#endif

/* magic word(`T`, `S`, `L`, `0`) */
#define SECTOR_MAGIC_WORD 0x304C5354

#define TSL_STATUS_TABLE_SIZE FDB_STATUS_TABLE_SIZE(FDB_TSL_STATUS_NUM)
#define TSL_UINT32_ALIGN_SIZE (FDB_WG_ALIGN(sizeof(uint32_t)))

#ifdef FDB_USING_TIMESTAMP_64BIT
#define TSL_TIME_ALIGN_SIZE FDB_WG_ALIGN(sizeof(int64_t))
#else
#define TSL_TIME_ALIGN_SIZE FDB_WG_ALIGN(sizeof(int32_t))
#endif

#define SECTOR_HDR_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct sector_hdr_data)))
#define LOG_IDX_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct log_idx_data)))
Expand Down Expand Up @@ -79,14 +82,17 @@

struct sector_hdr_data {
uint8_t status[FDB_STORE_STATUS_TABLE_SIZE]; /**< sector store status @see fdb_sector_store_status_t */
uint32_t magic; /**< magic word(`T`, `S`, `L`, `0`) */
fdb_time_t start_time; /**< the first start node's timestamp */
uint8_t magic[TSL_UINT32_ALIGN_SIZE]; /**< magic word(`T`, `S`, `L`, `0`) */
uint8_t start_time[TSL_TIME_ALIGN_SIZE]; /**< the first start node's timestamp */
struct {
fdb_time_t time; /**< the last end node's timestamp */
uint32_t index; /**< the last end node's index */
uint8_t time[TSL_TIME_ALIGN_SIZE]; /**< the last end node's timestamp */
uint8_t index[TSL_UINT32_ALIGN_SIZE]; /**< the last end node's index */
uint8_t status[TSL_STATUS_TABLE_SIZE]; /**< end node status, @see fdb_tsl_status_t */
} end_info[2];
uint32_t reserved;

// Autofill to the FDB WRITE GRAN alignment
uint8_t padding[FDB_WG_ALIGN(sizeof(uint32_t))- sizeof(uint32_t)];
};
typedef struct sector_hdr_data *sector_hdr_data_t;

Expand All @@ -98,6 +104,23 @@ struct log_idx_data {
uint32_t log_len; /**< node total length (header + name + value), must align by FDB_WRITE_GRAN */
uint32_t log_addr; /**< node address */
#endif
// Autofill to the FDB WRITE GRAN alignment
uint8_t padding[
FDB_WG_ALIGN(
sizeof(uint8_t) * TSL_STATUS_TABLE_SIZE
+ sizeof(fdb_time_t)
#ifndef FDB_TSDB_FIXED_BLOB_SIZE
+ sizeof(uint32_t) * 2
#endif
) -
(
sizeof(uint8_t) * TSL_STATUS_TABLE_SIZE
+ sizeof(fdb_time_t)
#ifndef FDB_TSDB_FIXED_BLOB_SIZE
+ sizeof(uint32_t) * 2
#endif
)
Comment on lines +110 to +122
];
};
typedef struct log_idx_data *log_idx_data_t;

Expand Down Expand Up @@ -219,7 +242,7 @@ static fdb_err_t read_sector_info(fdb_tsdb_t db, uint32_t addr, tsdb_sec_info_t
_fdb_flash_read((fdb_db_t)db, addr, (uint32_t *)&sec_hdr, sizeof(struct sector_hdr_data));

sector->addr = addr;
sector->magic = sec_hdr.magic;
memcpy(&sector->magic, sec_hdr.magic, sizeof(uint32_t));

/* check magic word */
if (sector->magic != SECTOR_MAGIC_WORD) {
Expand All @@ -228,15 +251,15 @@ static fdb_err_t read_sector_info(fdb_tsdb_t db, uint32_t addr, tsdb_sec_info_t
}
sector->check_ok = true;
sector->status = (fdb_sector_store_status_t) _fdb_get_status(sec_hdr.status, FDB_SECTOR_STORE_STATUS_NUM);
sector->start_time = sec_hdr.start_time;
memcpy(&sector->start_time, sec_hdr.start_time, sizeof(fdb_time_t));
sector->end_info_stat[0] = (fdb_tsl_status_t) _fdb_get_status(sec_hdr.end_info[0].status, FDB_TSL_STATUS_NUM);
sector->end_info_stat[1] = (fdb_tsl_status_t) _fdb_get_status(sec_hdr.end_info[1].status, FDB_TSL_STATUS_NUM);
if (sector->end_info_stat[0] == FDB_TSL_WRITE) {
sector->end_time = sec_hdr.end_info[0].time;
sector->end_idx = sec_hdr.end_info[0].index;
memcpy(&sector->end_time, sec_hdr.end_info[0].time, sizeof(fdb_time_t));
memcpy(&sector->end_idx, sec_hdr.end_info[0].index, sizeof(uint32_t));
} else if (sector->end_info_stat[1] == FDB_TSL_WRITE) {
sector->end_time = sec_hdr.end_info[1].time;
sector->end_idx = sec_hdr.end_info[1].index;
memcpy(&sector->end_time, sec_hdr.end_info[1].time, sizeof(fdb_time_t));
memcpy(&sector->end_idx, sec_hdr.end_info[1].index, sizeof(uint32_t));
} else if (sector->end_info_stat[0] == FDB_TSL_PRE_WRITE && sector->end_info_stat[1] == FDB_TSL_PRE_WRITE) {
//TODO There is no valid end node info on this sector, need impl fast query this sector by fdb_tsl_iter_by_time
FDB_ASSERT(0);
Expand Down Expand Up @@ -279,15 +302,17 @@ static fdb_err_t format_sector(fdb_tsdb_t db, uint32_t addr)
{
fdb_err_t result = FDB_NO_ERR;
struct sector_hdr_data sec_hdr;
uint32_t magic = SECTOR_MAGIC_WORD;

FDB_ASSERT(addr % db_sec_size(db) == 0);

result = _fdb_flash_erase((fdb_db_t)db, addr, db_sec_size(db));
if (result == FDB_NO_ERR) {
_FDB_WRITE_STATUS(db, addr, sec_hdr.status, FDB_SECTOR_STORE_STATUS_NUM, FDB_SECTOR_STORE_EMPTY, true);
/* set the magic */
sec_hdr.magic = SECTOR_MAGIC_WORD;
FLASH_WRITE(db, addr + SECTOR_MAGIC_OFFSET, &sec_hdr.magic, sizeof(sec_hdr.magic), true);
memset(sec_hdr.magic, FDB_BYTE_ERASED, TSL_UINT32_ALIGN_SIZE);
memcpy(sec_hdr.magic, &magic, sizeof(uint32_t));
FLASH_WRITE(db, addr + SECTOR_MAGIC_OFFSET, &sec_hdr.magic, TSL_UINT32_ALIGN_SIZE, true);
}

return result;
Expand Down Expand Up @@ -333,7 +358,10 @@ static fdb_err_t write_tsl(fdb_tsdb_t db, fdb_blob_t blob, fdb_time_t time)
/* write other index info */
FLASH_WRITE(db, idx_addr + LOG_IDX_TS_OFFSET, &idx.time, sizeof(struct log_idx_data) - LOG_IDX_TS_OFFSET, false);
/* write blob data */
FLASH_WRITE(db, log_addr, blob->buf, blob->size, false);
result = align_write(db, log_addr, blob->buf, blob->size);
if (result != FDB_NO_ERR){
return result;
}
/* write the status will by write granularity */
_FDB_WRITE_STATUS(db, idx_addr, idx.status_table, FDB_TSL_STATUS_NUM, FDB_TSL_WRITE, true);

Expand All @@ -344,20 +372,29 @@ static fdb_err_t update_sec_status(fdb_tsdb_t db, tsdb_sec_info_t sector, fdb_bl
{
fdb_err_t result = FDB_NO_ERR;
uint8_t status[FDB_STORE_STATUS_TABLE_SIZE];
uint8_t time[TSL_TIME_ALIGN_SIZE];
uint8_t index[TSL_UINT32_ALIGN_SIZE];

if (sector->status == FDB_SECTOR_STORE_USING && sector->remain < LOG_IDX_DATA_SIZE + FDB_WG_ALIGN(blob->size)) {
uint8_t end_status[TSL_STATUS_TABLE_SIZE];
uint32_t end_index = sector->empty_idx - LOG_IDX_DATA_SIZE, new_sec_addr, cur_sec_addr = sector->addr;
uint32_t end_index_temp = sector->empty_idx - LOG_IDX_DATA_SIZE, new_sec_addr, cur_sec_addr = sector->addr;

memset(index, FDB_BYTE_ERASED, TSL_UINT32_ALIGN_SIZE);
memcpy(index, &end_index_temp, sizeof(uint32_t));

memset(time, FDB_BYTE_ERASED, TSL_TIME_ALIGN_SIZE);
memcpy(time, &db->last_time, sizeof(fdb_time_t));

/* save the end node index and timestamp */
if (sector->end_info_stat[0] == FDB_TSL_UNUSED) {
_FDB_WRITE_STATUS(db, cur_sec_addr + SECTOR_END0_STATUS_OFFSET, end_status, FDB_TSL_STATUS_NUM, FDB_TSL_PRE_WRITE, false);
FLASH_WRITE(db, cur_sec_addr + SECTOR_END0_TIME_OFFSET, (uint32_t * )&db->last_time, sizeof(fdb_time_t), false);
FLASH_WRITE(db, cur_sec_addr + SECTOR_END0_IDX_OFFSET, &end_index, sizeof(end_index), false);
FLASH_WRITE(db, cur_sec_addr + SECTOR_END0_TIME_OFFSET, time, TSL_TIME_ALIGN_SIZE, false);
FLASH_WRITE(db, cur_sec_addr + SECTOR_END0_IDX_OFFSET, index, TSL_UINT32_ALIGN_SIZE, false);
_FDB_WRITE_STATUS(db, cur_sec_addr + SECTOR_END0_STATUS_OFFSET, end_status, FDB_TSL_STATUS_NUM, FDB_TSL_WRITE, true);
} else if (sector->end_info_stat[1] == FDB_TSL_UNUSED) {
_FDB_WRITE_STATUS(db, cur_sec_addr + SECTOR_END1_STATUS_OFFSET, end_status, FDB_TSL_STATUS_NUM, FDB_TSL_PRE_WRITE, false);
FLASH_WRITE(db, cur_sec_addr + SECTOR_END1_TIME_OFFSET, (uint32_t * )&db->last_time, sizeof(fdb_time_t), false);
FLASH_WRITE(db, cur_sec_addr + SECTOR_END1_IDX_OFFSET, &end_index, sizeof(end_index), false);
FLASH_WRITE(db, cur_sec_addr + SECTOR_END1_TIME_OFFSET, time, TSL_TIME_ALIGN_SIZE, false);
FLASH_WRITE(db, cur_sec_addr + SECTOR_END1_IDX_OFFSET, index, TSL_UINT32_ALIGN_SIZE, false);
_FDB_WRITE_STATUS(db, cur_sec_addr + SECTOR_END1_STATUS_OFFSET, end_status, FDB_TSL_STATUS_NUM, FDB_TSL_WRITE, true);
}
/* change current sector to full */
Expand Down Expand Up @@ -395,7 +432,9 @@ static fdb_err_t update_sec_status(fdb_tsdb_t db, tsdb_sec_info_t sector, fdb_bl
sector->start_time = cur_time;
_FDB_WRITE_STATUS(db, sector->addr, status, FDB_SECTOR_STORE_STATUS_NUM, FDB_SECTOR_STORE_USING, true);
/* save the start timestamp */
FLASH_WRITE(db, sector->addr + SECTOR_START_TIME_OFFSET, (uint32_t *)&cur_time, sizeof(fdb_time_t), true);
memset(time, FDB_BYTE_ERASED, TSL_TIME_ALIGN_SIZE);
memcpy(time, &cur_time, sizeof(fdb_time_t));
FLASH_WRITE(db, sector->addr + SECTOR_START_TIME_OFFSET, time, TSL_TIME_ALIGN_SIZE, true);
}

return result;
Expand All @@ -415,7 +454,7 @@ static fdb_err_t tsl_append(fdb_tsdb_t db, fdb_blob_t blob, fdb_time_t *timestam
/* check the append length, MUST less than the db->max_len */
if(blob->size > db->max_len)
{
FDB_INFO("Warning: append length (%" PRIdMAX ") is more than the db->max_len (%" PRIdMAX "). This tsl will be dropped.\n",
FDB_INFO("Warning: append length (%" PRIdMAX ") is more than the db->max_len (%" PRIdMAX "). This tsl will be dropped.\n",
(intmax_t)blob->size, (intmax_t)(db->max_len));
return FDB_WRITE_ERR;
}
Expand Down Expand Up @@ -1046,4 +1085,4 @@ fdb_err_t fdb_tsdb_deinit(fdb_tsdb_t db)
return FDB_NO_ERR;
}

#endif /* defined(FDB_USING_TSDB) */
#endif /* defined(FDB_USING_TSDB) */
29 changes: 29 additions & 0 deletions src/fdb_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,3 +318,32 @@ fdb_err_t _fdb_flash_write(fdb_db_t db, uint32_t addr, const void *buf, size_t s
return result;

}

fdb_err_t align_write(fdb_db_t db, uint32_t addr, const uint32_t *buf, size_t size)
{
fdb_err_t result = FDB_NO_ERR;
size_t align_remain;

#if (FDB_WRITE_GRAN / 8 > 0)
uint8_t align_data[FDB_WRITE_GRAN / 8];
size_t align_data_size = sizeof(align_data);
#else
/* For compatibility with C89 */
uint8_t align_data_u8, *align_data = &align_data_u8;
size_t align_data_size = 1;
#endif

memset(align_data, FDB_BYTE_ERASED, align_data_size);
if(FDB_WG_ALIGN_DOWN(size) > 0) {
result = _fdb_flash_write(db, addr, buf, FDB_WG_ALIGN_DOWN(size), false);
}

align_remain = size - FDB_WG_ALIGN_DOWN(size);
if (result == FDB_NO_ERR && align_remain) {
memcpy(align_data, (uint8_t *) buf + FDB_WG_ALIGN_DOWN(size), align_remain);
result = _fdb_flash_write(db, addr + FDB_WG_ALIGN_DOWN(size), (uint32_t *) align_data,
align_data_size, false);
}

return result;
}