diff --git a/inc/fdb_def.h b/inc/fdb_def.h index 34d07d4..435432e 100644 --- a/inc/fdb_def.h +++ b/inc/fdb_def.h @@ -17,22 +17,22 @@ extern "C" { #endif /* software version number */ -#define FDB_SW_VERSION "1.0.0 beta" -#define FDB_SW_VERSION_NUM 0x10000 +#define FDB_SW_VERSION "1.0.0 beta" +#define FDB_SW_VERSION_NUM 0x10000 /* the KV max name length must less then it */ #ifndef FDB_KV_NAME_MAX -#define FDB_KV_NAME_MAX 32 +#define FDB_KV_NAME_MAX 32 #endif /* the KV cache table size, it will improve KV search speed when using cache */ #ifndef FDB_KV_CACHE_TABLE_SIZE -#define FDB_KV_CACHE_TABLE_SIZE 16 +#define FDB_KV_CACHE_TABLE_SIZE 16 #endif /* the sector cache table size, it will improve KV save speed when using cache */ #ifndef FDB_SECTOR_CACHE_TABLE_SIZE -#define FDB_SECTOR_CACHE_TABLE_SIZE 4 +#define FDB_SECTOR_CACHE_TABLE_SIZE 4 #endif #if (FDB_KV_CACHE_TABLE_SIZE > 0) && (FDB_SECTOR_CACHE_TABLE_SIZE > 0) @@ -41,18 +41,18 @@ extern "C" { /* log function. default FDB_PRINT macro is printf() */ #ifndef FDB_PRINT -#define FDB_PRINT(...) printf(__VA_ARGS__) +#define FDB_PRINT(...) printf(__VA_ARGS__) #endif -#define FDB_LOG_PREFIX1() FDB_PRINT("[FlashDB]"FDB_LOG_TAG) -#define FDB_LOG_PREFIX2() FDB_PRINT(" ") -#define FDB_LOG_PREFIX() FDB_LOG_PREFIX1();FDB_LOG_PREFIX2() +#define FDB_LOG_PREFIX1() FDB_PRINT("[FlashDB]"FDB_LOG_TAG) +#define FDB_LOG_PREFIX2() FDB_PRINT(" ") +#define FDB_LOG_PREFIX() FDB_LOG_PREFIX1();FDB_LOG_PREFIX2() #ifdef FDB_DEBUG_ENABLE -#define FDB_DEBUG(...) FDB_LOG_PREFIX();FDB_PRINT("(%s:%d) ", __FILE__, __LINE__);FDB_PRINT(__VA_ARGS__) +#define FDB_DEBUG(...) FDB_LOG_PREFIX();FDB_PRINT("(%s:%d) ", __FILE__, __LINE__);FDB_PRINT(__VA_ARGS__) #else #define FDB_DEBUG(...) #endif /* routine print function. Must be implement by user. */ -#define FDB_INFO(...) FDB_LOG_PREFIX();FDB_PRINT(__VA_ARGS__) +#define FDB_INFO(...) FDB_LOG_PREFIX();FDB_PRINT(__VA_ARGS__) /* assert for developer. */ #define FDB_ASSERT(EXPR) \ if (!(EXPR)) \ @@ -61,6 +61,9 @@ if (!(EXPR)) \ while (1); \ } +#define FDB_TSDB_CTRL_SET_ROLLOVER 0x0 /**< set rollover control command */ +#define FDB_TSDB_CTRL_GET_ROLLOVER 0x1 /**< get rollover control command */ + typedef time_t fdb_time_t; #ifdef FDB_USING_TIMESTAMP_64BIT typedef int64_t fdb_time_t; @@ -87,7 +90,7 @@ typedef enum { FDB_PART_NOT_FOUND, FDB_KV_NAME_ERR, FDB_KV_NAME_EXIST, - FDB_KV_FULL, + FDB_SAVED_FULL, FDB_INIT_FAILED, } fdb_err_t; @@ -255,6 +258,7 @@ struct fdb_tsdb { fdb_get_time get_time; /**< the current timestamp get function */ size_t max_len; /**< the max log length */ uint32_t oldest_addr; /**< the oldest sector start address */ + bool rollover; /**< the oldest data will rollover by newest data, default is true */ void *user_data; }; diff --git a/inc/flashdb.h b/inc/flashdb.h index 0579163..f10cb26 100644 --- a/inc/flashdb.h +++ b/inc/flashdb.h @@ -24,13 +24,14 @@ extern "C" { #endif -/* fdb.c */ -void fdb_lock_set(fdb_db_t db, void (*lock)(fdb_db_t db), void (*unlock)(fdb_db_t db)); +/* FlashDB database API */ +void fdb_lock_set (fdb_db_t db, void (*lock)(fdb_db_t db), void (*unlock)(fdb_db_t db)); void fdb_sec_size_set(fdb_db_t db, uint32_t sec_size); -fdb_err_t fdb_kvdb_init(fdb_kvdb_t db, const char *name, const char *part_name, struct fdb_default_kv *default_kv, +fdb_err_t fdb_kvdb_init (fdb_kvdb_t db, const char *name, const char *part_name, struct fdb_default_kv *default_kv, void *user_data); -fdb_err_t fdb_tsdb_init(fdb_tsdb_t db, const char *name, const char *part_name, fdb_get_time get_time, size_t max_len, +fdb_err_t fdb_tsdb_init (fdb_tsdb_t db, const char *name, const char *part_name, fdb_get_time get_time, size_t max_len, void *user_data); +void fdb_tsdb_control(fdb_tsdb_t db, int cmd, void *arg); /* blob API */ fdb_blob_t fdb_blob_make (fdb_blob_t blob, const void *value_buf, size_t buf_len); @@ -43,7 +44,7 @@ fdb_err_t fdb_kv_set_blob (fdb_kvdb_t db, const char *key, fdb_blob_t blob); size_t fdb_kv_get_blob (fdb_kvdb_t db, const char *key, fdb_blob_t blob); fdb_err_t fdb_kv_del (fdb_kvdb_t db, const char *key); fdb_kv_t fdb_kv_get_obj (fdb_kvdb_t db, const char *key, fdb_kv_t kv); -fdb_blob_t fdb_kv_to_blob (fdb_kv_t kv, fdb_blob_t blob); +fdb_blob_t fdb_kv_to_blob (fdb_kv_t kv, fdb_blob_t blob); fdb_err_t fdb_kv_set_default(fdb_kvdb_t db); void fdb_kv_print (fdb_kvdb_t db); diff --git a/src/fdb_kvdb.c b/src/fdb_kvdb.c index 850a1ad..e8e8ca7 100644 --- a/src/fdb_kvdb.c +++ b/src/fdb_kvdb.c @@ -923,7 +923,7 @@ static fdb_err_t move_kv(fdb_kvdb_t db, fdb_kv_t kv) } } } else { - return FDB_KV_FULL; + return FDB_SAVED_FULL; } /* start move the KV */ { @@ -1092,7 +1092,7 @@ static fdb_err_t create_kv_blob(fdb_kvdb_t db, kv_sec_info_t sector, const char if (kv_hdr.len > db_sec_size(db) - SECTOR_HDR_DATA_SIZE) { FDB_INFO("Error: The KV size is too big\n"); - return FDB_KV_FULL; + return FDB_SAVED_FULL; } if (kv_addr != FAILED_ADDR || (kv_addr = new_kv(db, sector, kv_hdr.len)) != FAILED_ADDR) { @@ -1146,7 +1146,7 @@ static fdb_err_t create_kv_blob(fdb_kvdb_t db, kv_sec_info_t sector, const char db->gc_request = true; } } else { - result = FDB_KV_FULL; + result = FDB_SAVED_FULL; } return result; @@ -1192,7 +1192,7 @@ static fdb_err_t set_kv(fdb_kvdb_t db, const char *key, const void *value_buf, s } else { /* make sure the flash has enough space */ if (new_kv_ex(db, §or, strlen(key), buf_len) == FAILED_ADDR) { - return FDB_KV_FULL; + return FDB_SAVED_FULL; } kv_is_found = find_kv(db, key, &kv); /* prepare to delete the old KV */ diff --git a/src/fdb_tsdb.c b/src/fdb_tsdb.c index 415c67f..a698849 100644 --- a/src/fdb_tsdb.c +++ b/src/fdb_tsdb.c @@ -287,38 +287,43 @@ static fdb_err_t update_sec_status(fdb_tsdb_t db, tsdb_sec_info_t sector, fdb_bl uint8_t status[FDB_STORE_STATUS_TABLE_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; - /* 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); - FLASH_WRITE(db, cur_sec_addr + SECTOR_END0_TIME_OFFSET, (uint32_t * )&db->last_time, sizeof(fdb_time_t)); - FLASH_WRITE(db, cur_sec_addr + SECTOR_END0_IDX_OFFSET, &end_index, sizeof(end_index)); - _FDB_WRITE_STATUS(db, cur_sec_addr + SECTOR_END0_STATUS_OFFSET, end_status, FDB_TSL_STATUS_NUM, FDB_TSL_WRITE); - } 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); - FLASH_WRITE(db, cur_sec_addr + SECTOR_END1_TIME_OFFSET, (uint32_t * )&db->last_time, sizeof(fdb_time_t)); - FLASH_WRITE(db, cur_sec_addr + SECTOR_END1_IDX_OFFSET, &end_index, sizeof(end_index)); - _FDB_WRITE_STATUS(db, cur_sec_addr + SECTOR_END1_STATUS_OFFSET, end_status, FDB_TSL_STATUS_NUM, FDB_TSL_WRITE); - } - /* 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)) { - new_sec_addr = sector->addr + db_sec_size(db); - } else { - new_sec_addr = 0; - } - 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)) { - db->oldest_addr = new_sec_addr + db_sec_size(db); - } else { - db->oldest_addr = 0; + if (db->rollover) { + 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; + /* 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); + FLASH_WRITE(db, cur_sec_addr + SECTOR_END0_TIME_OFFSET, (uint32_t * )&db->last_time, sizeof(fdb_time_t)); + FLASH_WRITE(db, cur_sec_addr + SECTOR_END0_IDX_OFFSET, &end_index, sizeof(end_index)); + _FDB_WRITE_STATUS(db, cur_sec_addr + SECTOR_END0_STATUS_OFFSET, end_status, FDB_TSL_STATUS_NUM, FDB_TSL_WRITE); + } 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); + FLASH_WRITE(db, cur_sec_addr + SECTOR_END1_TIME_OFFSET, (uint32_t * )&db->last_time, sizeof(fdb_time_t)); + FLASH_WRITE(db, cur_sec_addr + SECTOR_END1_IDX_OFFSET, &end_index, sizeof(end_index)); + _FDB_WRITE_STATUS(db, cur_sec_addr + SECTOR_END1_STATUS_OFFSET, end_status, FDB_TSL_STATUS_NUM, FDB_TSL_WRITE); + } + /* 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)) { + new_sec_addr = sector->addr + db_sec_size(db); + } else { + new_sec_addr = 0; } - format_sector(db, new_sec_addr); 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)) { + db->oldest_addr = new_sec_addr + db_sec_size(db); + } else { + db->oldest_addr = 0; + } + format_sector(db, new_sec_addr); + read_sector_info(db, new_sec_addr, &db->cur_sec, false); + } + } else { + /* not rollover */ + return FDB_SAVED_FULL; } } @@ -341,10 +346,16 @@ static fdb_err_t tsl_append(fdb_tsdb_t db, fdb_blob_t blob) FDB_ASSERT(blob->size <= db->max_len); - update_sec_status(db, &db->cur_sec, blob, cur_time); + result = update_sec_status(db, &db->cur_sec, blob, cur_time); + if (result != FDB_NO_ERR) { + return result; + } /* write the TSL node */ result = write_tsl(db, blob, cur_time); + if (result != FDB_NO_ERR) { + return result; + } /* recalculate the current using sector info */ db->cur_sec.end_idx = db->cur_sec.empty_idx; @@ -645,6 +656,28 @@ void fdb_tsl_clean(fdb_tsdb_t db) db_unlock(db); } +/** + * This function will get or set some options of the database + * + * @param db database object + * @param cmd the control command + * @param arg the argument + */ +void fdb_tsdb_control(fdb_tsdb_t db, int cmd, void *arg) +{ + FDB_ASSERT(db); + + switch (cmd) { + case FDB_TSDB_CTRL_GET_ROLLOVER: + *(bool *)arg = db->rollover; + break; + + case FDB_TSDB_CTRL_SET_ROLLOVER: + db->rollover = *(bool *)arg; + break; + } +} + /** * The time series database initialization. * @@ -672,6 +705,8 @@ fdb_err_t fdb_tsdb_init(fdb_tsdb_t db, const char *name, const char *part_name, db->get_time = get_time; db->max_len = max_len; + /* default rollover flag is true */ + db->rollover = true; db->oldest_addr = FDB_DATA_UNUSED; db->cur_sec.addr = FDB_DATA_UNUSED; /* must align with sector size */