mirror of
https://github.com/armink/FlashDB.git
synced 2025-01-16 20:12:52 +08:00
【新增】tsdb支持按时间逆序迭代
【修改】全部逆序迭代时的多余操作
This commit is contained in:
parent
03500fa925
commit
ceb75d203a
127
src/fdb_tsdb.c
127
src/fdb_tsdb.c
@ -471,9 +471,8 @@ void fdb_tsl_iter_reverse(fdb_tsdb_t db, fdb_tsl_cb cb, void *arg)
|
|||||||
if (sector.status == FDB_SECTOR_STORE_USING) {
|
if (sector.status == FDB_SECTOR_STORE_USING) {
|
||||||
/* copy the current using sector status */
|
/* copy the current using sector status */
|
||||||
sector = db->cur_sec;
|
sector = db->cur_sec;
|
||||||
tsl.addr.index = db->cur_sec.empty_idx - LOG_IDX_DATA_SIZE;
|
}
|
||||||
} else
|
tsl.addr.index = sector.end_idx;
|
||||||
tsl.addr.index = sector.end_idx;
|
|
||||||
/* search all TSL */
|
/* search all TSL */
|
||||||
do {
|
do {
|
||||||
read_tsl(db, &tsl);
|
read_tsl(db, &tsl);
|
||||||
@ -534,6 +533,28 @@ void fdb_tsl_iter(fdb_tsdb_t db, fdb_tsl_cb cb, void *arg)
|
|||||||
} while ((sec_addr = get_next_sector_addr(db, §or, traversed_len)) != FAILED_ADDR);
|
} while ((sec_addr = get_next_sector_addr(db, §or, traversed_len)) != FAILED_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The TSDB iterator for each TSL addr.
|
||||||
|
* @param db database object
|
||||||
|
* @param starting tsl addr of the current sector
|
||||||
|
* @param ending tsl addr of the current sector
|
||||||
|
* @param from starting timestap
|
||||||
|
*/
|
||||||
|
static int search_tsl_addr(fdb_tsdb_t db,int start,int end,int from)
|
||||||
|
{
|
||||||
|
struct fdb_tsl tsl;
|
||||||
|
while (start <= end) {
|
||||||
|
tsl.addr.index = start + ((end - start) / 2 + 1) / LOG_IDX_DATA_SIZE * LOG_IDX_DATA_SIZE;
|
||||||
|
read_tsl(db, &tsl);
|
||||||
|
if (tsl.time < from) {
|
||||||
|
start = tsl.addr.index + LOG_IDX_DATA_SIZE;
|
||||||
|
} else {
|
||||||
|
end = tsl.addr.index - LOG_IDX_DATA_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The TSDB iterator for each TSL by timestamp.
|
* The TSDB iterator for each TSL by timestamp.
|
||||||
*
|
*
|
||||||
@ -546,14 +567,27 @@ void fdb_tsl_iter(fdb_tsdb_t db, fdb_tsl_cb cb, void *arg)
|
|||||||
void fdb_tsl_iter_by_time(fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl_cb cb, void *cb_arg)
|
void fdb_tsl_iter_by_time(fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl_cb cb, void *cb_arg)
|
||||||
{
|
{
|
||||||
struct tsdb_sec_info sector;
|
struct tsdb_sec_info sector;
|
||||||
uint32_t sec_addr, oldest_addr = db->oldest_addr, traversed_len = 0;
|
uint32_t sec_addr, oldest_addr, traversed_len = 0;
|
||||||
struct fdb_tsl tsl;
|
struct fdb_tsl tsl;
|
||||||
bool found_start_tsl = false;
|
bool found_start_tsl = false;
|
||||||
|
|
||||||
|
uint32_t (*get_sector_addr)(fdb_tsdb_t , tsdb_sec_info_t , uint32_t);
|
||||||
|
uint32_t (*get_tsl_addr)(tsdb_sec_info_t , fdb_tsl_t);
|
||||||
|
|
||||||
if (!db_init_ok(db)) {
|
if (!db_init_ok(db)) {
|
||||||
FDB_INFO("Error: TSL (%s) isn't initialize OK.\n", db_name(db));
|
FDB_INFO("Error: TSL (%s) isn't initialize OK.\n", db_name(db));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(from <= to) {
|
||||||
|
oldest_addr = db->oldest_addr;
|
||||||
|
get_sector_addr = get_next_sector_addr;
|
||||||
|
get_tsl_addr = get_next_tsl_addr;
|
||||||
|
} else {
|
||||||
|
oldest_addr = db->cur_sec.addr;
|
||||||
|
get_sector_addr = get_prev_sector_addr;
|
||||||
|
get_tsl_addr = get_prev_tsl_addr;
|
||||||
|
}
|
||||||
|
|
||||||
// FDB_INFO("from %s", ctime((const time_t * )&from));
|
// FDB_INFO("from %s", ctime((const time_t * )&from));
|
||||||
// FDB_INFO("to %s", ctime((const time_t * )&to));
|
// FDB_INFO("to %s", ctime((const time_t * )&to));
|
||||||
|
|
||||||
@ -564,51 +598,48 @@ void fdb_tsl_iter_by_time(fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl
|
|||||||
sec_addr = oldest_addr;
|
sec_addr = oldest_addr;
|
||||||
/* search all sectors */
|
/* search all sectors */
|
||||||
do {
|
do {
|
||||||
traversed_len += db_sec_size(db);
|
traversed_len += db_sec_size(db);
|
||||||
if (read_sector_info(db, sec_addr, §or, false) != FDB_NO_ERR) {
|
if (read_sector_info(db, sec_addr, §or, false) != FDB_NO_ERR) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* sector has TSL */
|
/* sector has TSL */
|
||||||
if ((sector.status == FDB_SECTOR_STORE_USING || sector.status == FDB_SECTOR_STORE_FULL)) {
|
if ((sector.status == FDB_SECTOR_STORE_USING || sector.status == FDB_SECTOR_STORE_FULL)) {
|
||||||
if (sector.status == FDB_SECTOR_STORE_USING) {
|
if (sector.status == FDB_SECTOR_STORE_USING) {
|
||||||
/* copy the current using sector status */
|
/* copy the current using sector status */
|
||||||
sector = db->cur_sec;
|
sector = db->cur_sec;
|
||||||
}
|
}
|
||||||
if ((found_start_tsl) || (!found_start_tsl && ((from >= sector.start_time && from <= sector.end_time)
|
if ((found_start_tsl) || (!found_start_tsl && ((from >= sector.start_time && from <= sector.end_time)
|
||||||
|| (sec_addr == oldest_addr && from <= sector.start_time)))) {
|
|| (from <= to && sec_addr == oldest_addr && from <= sector.start_time)
|
||||||
uint32_t start = sector.addr + SECTOR_HDR_DATA_SIZE, end = sector.end_idx;
|
|| (from > to && sec_addr == oldest_addr && from >= sector.end_time)))) {
|
||||||
|
uint32_t start = sector.addr + SECTOR_HDR_DATA_SIZE, end = sector.end_idx;
|
||||||
|
|
||||||
found_start_tsl = true;
|
found_start_tsl = true;
|
||||||
/* search start TSL address, using binary search algorithm */
|
|
||||||
while (start <= end) {
|
tsl.addr.index = search_tsl_addr(db,start,end,from);
|
||||||
tsl.addr.index = start + ((end - start) / 2 + 1) / LOG_IDX_DATA_SIZE * LOG_IDX_DATA_SIZE;
|
|
||||||
read_tsl(db, &tsl);
|
/* search all TSL */
|
||||||
if (tsl.time < from) {
|
do {
|
||||||
start = tsl.addr.index + LOG_IDX_DATA_SIZE;
|
read_tsl(db, &tsl);
|
||||||
} else {
|
if (tsl.status != FDB_TSL_UNUSED) {
|
||||||
end = tsl.addr.index - LOG_IDX_DATA_SIZE;
|
if (from <= to && tsl.time >= from && tsl.time <= to) {
|
||||||
}
|
/* iterator is interrupted when callback return true */
|
||||||
}
|
if (cb(&tsl, cb_arg)) {
|
||||||
tsl.addr.index = start;
|
return;
|
||||||
/* search all TSL */
|
}
|
||||||
do {
|
} else if (from > to && tsl.time <= from && tsl.time >= to){
|
||||||
read_tsl(db, &tsl);
|
if (cb(&tsl, cb_arg)) {
|
||||||
if (tsl.status != FDB_TSL_UNUSED) {
|
return;
|
||||||
if (tsl.time >= from && tsl.time <= to) {
|
}
|
||||||
/* iterator is interrupted when callback return true */
|
} else {
|
||||||
if (cb(&tsl, cb_arg)) {
|
return;
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} while ((tsl.addr.index = get_tsl_addr(§or, &tsl)) != FAILED_ADDR);
|
||||||
return;
|
}
|
||||||
}
|
} else if (sector.status == FDB_SECTOR_STORE_EMPTY) {
|
||||||
}
|
return;
|
||||||
} while ((tsl.addr.index = get_next_tsl_addr(§or, &tsl)) != FAILED_ADDR);
|
}
|
||||||
}
|
} while ((sec_addr = get_sector_addr(db, §or, traversed_len)) != FAILED_ADDR);
|
||||||
} else if (sector.status == FDB_SECTOR_STORE_EMPTY) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} while ((sec_addr = get_next_sector_addr(db, §or, traversed_len)) != FAILED_ADDR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool query_count_cb(fdb_tsl_t tsl, void *arg)
|
static bool query_count_cb(fdb_tsl_t tsl, void *arg)
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#define TEST_TS_USER_STATUS1_COUNT (TEST_TS_COUNT/2)
|
#define TEST_TS_USER_STATUS1_COUNT (TEST_TS_COUNT/2)
|
||||||
#define TEST_TS_DELETED_COUNT (TEST_TS_COUNT - TEST_TS_USER_STATUS1_COUNT)
|
#define TEST_TS_DELETED_COUNT (TEST_TS_COUNT - TEST_TS_USER_STATUS1_COUNT)
|
||||||
|
|
||||||
static char log[10];
|
static char logbuf[10];
|
||||||
|
|
||||||
static struct fdb_tsdb test_tsdb;
|
static struct fdb_tsdb test_tsdb;
|
||||||
static int cur_times = 0;
|
static int cur_times = 0;
|
||||||
@ -36,6 +36,18 @@ static fdb_time_t get_time(void)
|
|||||||
|
|
||||||
static void test_fdb_tsdb_init_ex(void)
|
static void test_fdb_tsdb_init_ex(void)
|
||||||
{
|
{
|
||||||
|
if (access("/fdb_tsdb1", 0) < 0)
|
||||||
|
{
|
||||||
|
mkdir("/fdb_tsdb1", 0);
|
||||||
|
}
|
||||||
|
#ifndef FDB_USING_FAL_MODE
|
||||||
|
uint32_t sec_size = 4096, db_size = sec_size * 16;
|
||||||
|
rt_bool_t file_mode = true;
|
||||||
|
fdb_kvdb_control((fdb_kvdb_t)&(test_tsdb), FDB_TSDB_CTRL_SET_SEC_SIZE, &sec_size);
|
||||||
|
fdb_kvdb_control((fdb_kvdb_t)&(test_tsdb), FDB_TSDB_CTRL_SET_FILE_MODE, &file_mode);
|
||||||
|
fdb_kvdb_control((fdb_kvdb_t)&(test_tsdb), FDB_TSDB_CTRL_SET_MAX_SIZE, &db_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
uassert_true(fdb_tsdb_init(&test_tsdb, "test_ts", TEST_TS_PART_NAME, get_time, 128, NULL) == FDB_NO_ERR);
|
uassert_true(fdb_tsdb_init(&test_tsdb, "test_ts", TEST_TS_PART_NAME, get_time, 128, NULL) == FDB_NO_ERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,15 +57,15 @@ static void test_fdb_tsl_append(void)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < TEST_TS_COUNT; ++i) {
|
for (i = 0; i < TEST_TS_COUNT; ++i) {
|
||||||
rt_snprintf(log, sizeof(log), "%d", i);
|
rt_snprintf(logbuf, sizeof(logbuf), "%d", i);
|
||||||
uassert_true(fdb_tsl_append(&test_tsdb, fdb_blob_make(&blob, log, rt_strnlen(log, sizeof(log)))) == FDB_NO_ERR);
|
uassert_true(fdb_tsl_append(&test_tsdb, fdb_blob_make(&blob, logbuf, rt_strnlen(logbuf, sizeof(logbuf)))) == FDB_NO_ERR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_fdb_tsl_iter_cb(fdb_tsl_t tsl, void *arg)
|
static bool test_fdb_tsl_iter_cb(fdb_tsl_t tsl, void *arg)
|
||||||
{
|
{
|
||||||
struct fdb_blob blob;
|
struct fdb_blob blob;
|
||||||
char data[sizeof(log)];
|
char data[sizeof(logbuf)];
|
||||||
size_t read_len;
|
size_t read_len;
|
||||||
|
|
||||||
fdb_blob_make(&blob, data, tsl->log_len);
|
fdb_blob_make(&blob, data, tsl->log_len);
|
||||||
@ -128,6 +140,7 @@ static void test_fdb_tsl_clean(void)
|
|||||||
{
|
{
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
|
|
||||||
|
cur_times = 0;
|
||||||
fdb_tsl_clean(&test_tsdb);
|
fdb_tsl_clean(&test_tsdb);
|
||||||
|
|
||||||
fdb_tsl_iter(&test_tsdb, test_fdb_tsl_clean_cb, &count);
|
fdb_tsl_iter(&test_tsdb, test_fdb_tsl_clean_cb, &count);
|
||||||
@ -148,6 +161,108 @@ static rt_err_t utest_tc_cleanup(void)
|
|||||||
return RT_EOK;
|
return RT_EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static rt_slist_t recv_data_list;
|
||||||
|
|
||||||
|
struct recv_data {
|
||||||
|
int data;
|
||||||
|
fdb_time_t time;
|
||||||
|
rt_slist_t list;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool query_cb(fdb_tsl_t tsl, void *arg)
|
||||||
|
{
|
||||||
|
struct fdb_blob blob;
|
||||||
|
int data;
|
||||||
|
struct recv_data *list;
|
||||||
|
fdb_blob_read((fdb_db_t) &test_tsdb, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &data, sizeof(data))));
|
||||||
|
list = rt_malloc(sizeof(*list));
|
||||||
|
|
||||||
|
list->data = data;
|
||||||
|
list->time = tsl->time;
|
||||||
|
rt_slist_append(&recv_data_list,&list->list);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tsdb_data_utest(fdb_time_t from,fdb_time_t to)
|
||||||
|
{
|
||||||
|
int len,iter_data_len;
|
||||||
|
fdb_time_t start = from;
|
||||||
|
rt_slist_t *node;
|
||||||
|
struct recv_data *recv_obj;
|
||||||
|
|
||||||
|
if(from <= to)
|
||||||
|
iter_data_len = to - from + 1;
|
||||||
|
else
|
||||||
|
iter_data_len = from - to + 1;
|
||||||
|
|
||||||
|
fdb_tsl_iter_by_time(&test_tsdb,from,to,query_cb,NULL);
|
||||||
|
|
||||||
|
len = rt_slist_len(&recv_data_list);
|
||||||
|
uassert_true(len == iter_data_len);
|
||||||
|
|
||||||
|
rt_slist_for_each(node,&recv_data_list) {
|
||||||
|
recv_obj = rt_slist_entry(node, struct recv_data, list);
|
||||||
|
uassert_true(recv_obj->time == recv_obj->data);
|
||||||
|
|
||||||
|
if(start <= to)
|
||||||
|
uassert_true(recv_obj->data == from++);
|
||||||
|
else
|
||||||
|
uassert_true(recv_obj->data == from--);
|
||||||
|
|
||||||
|
rt_free(recv_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_slist_init(&recv_data_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tsdb_fdb_tsl_iter_reverse(void)
|
||||||
|
{
|
||||||
|
rt_slist_t *node;
|
||||||
|
int len,data = 799;
|
||||||
|
struct recv_data *recv_obj;
|
||||||
|
|
||||||
|
fdb_tsl_iter_reverse(&test_tsdb,query_cb,NULL);
|
||||||
|
len = rt_slist_len(&recv_data_list);
|
||||||
|
uassert_true(len == 800);
|
||||||
|
|
||||||
|
rt_slist_for_each(node,&recv_data_list) {
|
||||||
|
recv_obj = rt_slist_entry(node, struct recv_data, list);
|
||||||
|
uassert_true(recv_obj->time == recv_obj->data);
|
||||||
|
uassert_true(recv_obj->data == data--);
|
||||||
|
rt_free(recv_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_slist_init(&recv_data_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_fdb_tsl_iter_by_time_1(void)
|
||||||
|
{
|
||||||
|
struct fdb_blob blob;
|
||||||
|
int data;
|
||||||
|
rt_slist_init(&recv_data_list);
|
||||||
|
|
||||||
|
for(data = 0; data < 800 ; data++) {
|
||||||
|
fdb_tsl_append(&test_tsdb, fdb_blob_make(&blob, &data, sizeof(data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjacent sector iteration */
|
||||||
|
tsdb_data_utest(45,234);
|
||||||
|
/* Iterating across a sector */
|
||||||
|
tsdb_data_utest(37,423);
|
||||||
|
/* Iterating across two sectors */
|
||||||
|
tsdb_data_utest(201,774);
|
||||||
|
/* Same sector iteration */
|
||||||
|
tsdb_data_utest(334,334);
|
||||||
|
/* Reverse iteration of adjacent sectors */
|
||||||
|
tsdb_data_utest(234,2);
|
||||||
|
/* Reverse iterations across a sectors */
|
||||||
|
tsdb_data_utest(650,400);
|
||||||
|
/* Reverse iterations across two sectors */
|
||||||
|
tsdb_data_utest(773,123);
|
||||||
|
/* Reverse iteration of the same sector */
|
||||||
|
tsdb_data_utest(430,425);
|
||||||
|
}
|
||||||
|
|
||||||
static void testcase(void)
|
static void testcase(void)
|
||||||
{
|
{
|
||||||
UTEST_UNIT_RUN(test_fdb_tsdb_init_ex);
|
UTEST_UNIT_RUN(test_fdb_tsdb_init_ex);
|
||||||
@ -158,7 +273,8 @@ static void testcase(void)
|
|||||||
UTEST_UNIT_RUN(test_fdb_tsl_query_count);
|
UTEST_UNIT_RUN(test_fdb_tsl_query_count);
|
||||||
UTEST_UNIT_RUN(test_fdb_tsl_set_status);
|
UTEST_UNIT_RUN(test_fdb_tsl_set_status);
|
||||||
UTEST_UNIT_RUN(test_fdb_tsl_clean);
|
UTEST_UNIT_RUN(test_fdb_tsl_clean);
|
||||||
|
UTEST_UNIT_RUN(test_fdb_tsl_iter_by_time_1);
|
||||||
|
UTEST_UNIT_RUN(tsdb_fdb_tsl_iter_reverse);
|
||||||
}
|
}
|
||||||
UTEST_TC_EXPORT(testcase, "packages.tools.flashdb.tsdb", utest_tc_init, utest_tc_cleanup, 20);
|
UTEST_TC_EXPORT(testcase, "packages.tools.flashdb.tsdb", utest_tc_init, utest_tc_cleanup, 20);
|
||||||
|
#endif /* defined(RT_USING_UTEST) && defined(FDBTC_USING_TSDB) && defined(TC_USING_FDBTC_TSDB) */
|
||||||
#endif /* defined(RT_USING_UTEST) && defined(FDB_USING_TSDB) */
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user