Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

现有迭代器函数很难覆盖更多应用,一些新迭代器函数的实现探讨 #260

Open
guoweilkd opened this issue Nov 16, 2023 · 1 comment

Comments

@guoweilkd
Copy link
Contributor

目前的TSDB提供了一些迭代器函数如fdb_tsl_iter/reverse(),通过它们虽然可以实现遍历,读取等很多功能。但是在回调中处理tsl,很难满足很多应用的使用,比如这个例子:
tsdb中有100个数据,需要通过网络进行上送到服务器

  1. 用户在回调函数读取最老的tsl,进行联网上送,上送成功后,标记此tsl
  2. 用户在回调函数读取下一个tsl,进行联网上送,上送成功后,标记此tsl
  3. 循环上面的步骤

上述例子中,用户必须在回调函数中一气呵成,否则:

  1. 每次读取时都要遍历数据库,这样效率会变的很差
  2. 回调函数是在互斥锁中的,太多的应用代码逻辑会影响异步append
  3. 回调函数会打断用户的正常使用流程,没有kv那样直接读取方便

总之,如果在数据库中的某个中间点上进行顺序的向下读取,使用上述函数就会变的很困难且低效。

因此,我们是否可以增加一些更便利的迭代器函数,使其实现如下功能:

  1. tsl = fdb_tsl_next_find(db, cur_tsl):根据当前的tsl来读取下一个tsl
  2. tsl = fdb_tsl_prev_find(db, cur_tsl):根据当前的tsl来读取下一个tsl
    这样就可以完美的解决如下功能。

但因为追加可能是异步的,上面的函数可能会有面临如下一些问题:

  1. 在使用当前cur_tsl后, 异步append()造成cur_tsl所在扇区被重写,此时调用fdb_tsl_next_find()会出现错误情况
  2. 如何检测cur_tsl所在扇区被重写? 检测到后如何处理?

如何检测cur_tsl所在扇区被重写,我的思路如下:

  1. fdb_tsl_next_find()内部,先读取cur_tsl所在地址的信息,如果发现id不一致,则表明此扇区被重写了

检测到后如何处理,我的思路如下:

  1. 检测到被重写后,直接返回下一个最老的tsl,或者直接告诉用户被覆盖了?

当然,我认为,用户应该在使用时尽量避免这种情况

对于上面的问题,你有更好的解决思路吗?下面是我的一些简单实现思路,代码进行了简单测试,目前看起来可以实现上述问题

/* 代码实现 */
struct fdb_tsl fdb_tsl_next_find(fdb_tsdb_t db, fdb_tsl_t prestl)
{
    bool index_flag = false;
    struct tsdb_sec_info sector;
    uint32_t sec_addr, traversed_len = 0;
    struct fdb_tsl tsl;

    tsl.status = FDB_TSL_UNUSED;
    if (!prestl) return tsl;

    if (!db_init_ok(db)) {
        FDB_INFO("Error: TSL (%s) isn't initialize OK.\n", db_name(db));
    }

    db_lock(db);

    tsl.addr.index = prestl->addr.index;
    read_tsl(db, &tsl);
    if (tsl.status != FDB_TSL_UNUSED && tsl.time == prestl->time) {
        sec_addr = FDB_ALIGN_DOWN(tsl.addr.index, db_sec_size(db));
        index_flag = true;
    } else {
        sec_addr = db_oldest_addr(db);
    }

    do {
        traversed_len += db_sec_size(db);
        if (read_sector_info(db, sec_addr, &sector, false) != FDB_NO_ERR) {
            index_flag = false;
            continue;
        }
        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 (index_flag) {
                index_flag = false;
                tsl.addr.index = get_next_tsl_addr(&sector, &tsl);
            } else {
                tsl.addr.index = sector.addr + SECTOR_HDR_DATA_SIZE;
            }
            if (tsl.addr.index != FAILED_ADDR) {
                read_tsl(db, &tsl);
                db_unlock(db);
                return tsl;
            }
        }
        if (sec_addr == db->cur_sec.addr) {
            break;
        }
    } while ((sec_addr = get_next_sector_addr(db, &sector, traversed_len)) != FAILED_ADDR);

    db_unlock(db);

    tsl.status = FDB_TSL_UNUSED;
    return tsl;
}
@armink
Copy link
Owner

armink commented Nov 16, 2023

想法非常赞的,考虑的也很完善

检测到被重写后,直接返回下一个最老的tsl,或者直接告诉用户被覆盖了

我觉得可能要看当前 TSDB 模式,我觉得可以增加一个入参,比如回滚模式。为真时,可以直接返回最老的 TSL ,否则是不是直接
返回空

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants