diff --git a/inc/fdb_def.h b/inc/fdb_def.h index 54cb221..1bfcba9 100644 --- a/inc/fdb_def.h +++ b/inc/fdb_def.h @@ -141,6 +141,15 @@ struct fdb_kv { }; typedef struct fdb_kv *fdb_kv_t; +struct fdb_kv_iterator { + struct fdb_kv curr_kv; /**< Current KV we get from the iterator */ + uint32_t iterated_cnt; /**< How many KVs have we iterated already */ + size_t iterated_obj_bytes; /**< Total storage size of KVs we have iterated. */ + size_t iterated_value_bytes; /**< Total value size of KVs we have iterated. */ + uint32_t sector_addr; /**< Current sector address we're iterating. DO NOT touch it. */ +}; +typedef struct fdb_kv_iterator *fdb_kv_iterator_t; + /* time series log node object */ struct fdb_tsl { fdb_tsl_status_t status; /**< node status, @see fdb_log_status_t */ diff --git a/inc/flashdb.h b/inc/flashdb.h index 366de42..55a14be 100644 --- a/inc/flashdb.h +++ b/inc/flashdb.h @@ -37,15 +37,17 @@ fdb_blob_t fdb_blob_make (fdb_blob_t blob, const void *value_buf, size_t buf size_t fdb_blob_read (fdb_db_t db, fdb_blob_t blob); /* Key-Value API like a KV DB */ -fdb_err_t fdb_kv_set (fdb_kvdb_t db, const char *key, const char *value); -char *fdb_kv_get (fdb_kvdb_t db, const char *key); -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_err_t fdb_kv_set_default(fdb_kvdb_t db); -void fdb_kv_print (fdb_kvdb_t db); +fdb_err_t fdb_kv_set (fdb_kvdb_t db, const char *key, const char *value); +char *fdb_kv_get (fdb_kvdb_t db, const char *key); +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_err_t fdb_kv_set_default (fdb_kvdb_t db); +void fdb_kv_print (fdb_kvdb_t db); +fdb_kv_iterator_t fdb_kv_iterator_init(fdb_kv_iterator_t itr); +bool fdb_kv_iterate (fdb_kvdb_t db, fdb_kv_iterator_t itr); /* Time series log API like a TSDB */ fdb_err_t fdb_tsl_append (fdb_tsdb_t db, fdb_blob_t blob); diff --git a/src/fdb_kvdb.c b/src/fdb_kvdb.c index 4089c79..a381af3 100644 --- a/src/fdb_kvdb.c +++ b/src/fdb_kvdb.c @@ -621,11 +621,11 @@ 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) { - blob->saved.addr = kv->addr.start; - blob->saved.addr = kv->addr.value; - blob->saved.len = kv->value_len; + blob->saved.meta_addr = kv->addr.start; + blob->saved.addr = kv->addr.value; + blob->saved.len = kv->value_len; - return blob; + return blob; } /** @@ -1612,4 +1612,66 @@ __exit: return result; } +/** + * The KV database initialization. + * + * @param itr iterator structure to be initialized + * + * @return pointer to the iterator initialized. + */ +fdb_kv_iterator_t fdb_kv_iterator_init(fdb_kv_iterator_t itr) +{ + itr->curr_kv.addr.start = 0; + + /* If iterator statistics is needed */ + itr->iterated_cnt = 0; + itr->iterated_obj_bytes = 0; + itr->iterated_value_bytes = 0; + /* Start from sector head */ + itr->sector_addr = 0; + return itr; +} + +/** + * The KV database iterator. + * + * @param db database object + * @param itr the iterator structure + * + * @return false if iterate not ended, true if iterate ended. + */ +bool fdb_kv_iterate(fdb_kvdb_t db, fdb_kv_iterator_t itr) +{ + struct kvdb_sec_info sector; + fdb_kv_t kv = &(itr->curr_kv); + do { + if (read_sector_info(db, itr->sector_addr, §or, false) != FDB_NO_ERR) { + continue; + } + else if (sector.status.store == FDB_SECTOR_STORE_USING || sector.status.store == FDB_SECTOR_STORE_FULL) { + if (kv->addr.start == 0) { + kv->addr.start = sector.addr + SECTOR_HDR_DATA_SIZE; + } + else if ((kv->addr.start = get_next_kv_addr(db, §or, kv)) == FAILED_ADDR) { + kv->addr.start = 0; + continue; + } + /* If iterator statistics is needed */ + itr->iterated_cnt++; + itr->iterated_obj_bytes += kv->len; + itr->iterated_value_bytes += kv->value_len; + + /* We got a valid kv here. */ + read_kv(db, kv); + return true; + } + /** Set kv->addr.start to 0 when we get into a new sector so that if we successfully get the next sector info, + * the kv->addr.start is set to the new sector.addr + SECTOR_HDR_DATA_SIZE. + */ + kv->addr.start == 0; + } while ((itr->sector_addr = get_next_sector_addr(db, §or)) != FAILED_ADDR); + /* Finally we have iterated all the KVs. */ + return false; +} + #endif /* defined(FDB_USING_KVDB) */