diff --git a/src/fdb_tsdb.c b/src/fdb_tsdb.c index 9c048a5..4ddc3b9 100644 --- a/src/fdb_tsdb.c +++ b/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) { /* copy the current using sector status */ 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 */ do { 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); } +/** + * 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. * @@ -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) { 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; 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)) { 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("to %s", ctime((const time_t * )&to)); @@ -564,51 +598,44 @@ void fdb_tsl_iter_by_time(fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl sec_addr = oldest_addr; /* search all sectors */ do { - traversed_len += db_sec_size(db); - if (read_sector_info(db, sec_addr, §or, false) != FDB_NO_ERR) { - continue; - } - /* sector has TSL */ - if ((sector.status == FDB_SECTOR_STORE_USING || sector.status == FDB_SECTOR_STORE_FULL)) { - if (sector.status == FDB_SECTOR_STORE_USING) { - /* copy the current using sector status */ - sector = db->cur_sec; - } - if ((found_start_tsl) || (!found_start_tsl && ((from >= sector.start_time && from <= sector.end_time) - || (sec_addr == oldest_addr && from <= sector.start_time)))) { - uint32_t start = sector.addr + SECTOR_HDR_DATA_SIZE, end = sector.end_idx; + traversed_len += db_sec_size(db); + if (read_sector_info(db, sec_addr, §or, false) != FDB_NO_ERR) { + continue; + } + /* sector has TSL */ + if ((sector.status == FDB_SECTOR_STORE_USING || sector.status == FDB_SECTOR_STORE_FULL)) { + if (sector.status == FDB_SECTOR_STORE_USING) { + /* copy the current using sector status */ + sector = db->cur_sec; + } + if ((found_start_tsl) || (!found_start_tsl && ((from >= sector.start_time && from <= sector.end_time) + || (from <= to && sec_addr == oldest_addr && from <= sector.start_time) + || (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; - /* search start TSL address, using binary search algorithm */ - 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; - } - } - tsl.addr.index = start; - /* search all TSL */ - do { - read_tsl(db, &tsl); - if (tsl.status != FDB_TSL_UNUSED) { - if (tsl.time >= from && tsl.time <= to) { - /* iterator is interrupted when callback return true */ - if (cb(&tsl, cb_arg)) { - return; - } - } else { - return; - } - } - } while ((tsl.addr.index = get_next_tsl_addr(§or, &tsl)) != FAILED_ADDR); - } - } else if (sector.status == FDB_SECTOR_STORE_EMPTY) { - return; - } - } while ((sec_addr = get_next_sector_addr(db, §or, traversed_len)) != FAILED_ADDR); + found_start_tsl = true; + + tsl.addr.index = search_tsl_addr(db,start,end,from); + + /* search all TSL */ + do { + read_tsl(db, &tsl); + if (tsl.status != FDB_TSL_UNUSED) { + if ((from <= to && tsl.time >= from && tsl.time <= to) || (from > to && tsl.time <= from && tsl.time >= to)) { + /* iterator is interrupted when callback return true */ + if (cb(&tsl, cb_arg)) { + return; + } + } else { + return; + } + } + } while ((tsl.addr.index = get_tsl_addr(§or, &tsl)) != FAILED_ADDR); + } + } else if (sector.status == FDB_SECTOR_STORE_EMPTY) { + return; + } + } while ((sec_addr = get_sector_addr(db, §or, traversed_len)) != FAILED_ADDR); } static bool query_count_cb(fdb_tsl_t tsl, void *arg) diff --git a/tests/fdb_tsdb_tc.c b/tests/fdb_tsdb_tc.c index 3d85e46..b3b1edc 100644 --- a/tests/fdb_tsdb_tc.c +++ b/tests/fdb_tsdb_tc.c @@ -24,7 +24,7 @@ #define TEST_TS_USER_STATUS1_COUNT (TEST_TS_COUNT/2) #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 int cur_times = 0; @@ -36,6 +36,18 @@ static fdb_time_t get_time(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); } @@ -45,15 +57,15 @@ static void test_fdb_tsl_append(void) int i; for (i = 0; i < TEST_TS_COUNT; ++i) { - rt_snprintf(log, sizeof(log), "%d", i); - uassert_true(fdb_tsl_append(&test_tsdb, fdb_blob_make(&blob, log, rt_strnlen(log, sizeof(log)))) == FDB_NO_ERR); + rt_snprintf(logbuf, sizeof(logbuf), "%d", i); + 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) { struct fdb_blob blob; - char data[sizeof(log)]; + char data[sizeof(logbuf)]; size_t read_len; fdb_blob_make(&blob, data, tsl->log_len); @@ -128,6 +140,7 @@ static void test_fdb_tsl_clean(void) { size_t count = 0; + cur_times = 0; fdb_tsl_clean(&test_tsdb); 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; } +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) { 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_set_status); 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); - -#endif /* defined(RT_USING_UTEST) && defined(FDB_USING_TSDB) */ +#endif /* defined(RT_USING_UTEST) && defined(FDBTC_USING_TSDB) && defined(TC_USING_FDBTC_TSDB) */