这里首先感谢作者的开源:
FlashDB: 一款支持 KV 数据和时序数据的超轻量级数据库 (gitee.com)
1.FlashDB简介
一款超轻量级的嵌入式数据库,专注于提供嵌入式产品的数据存储方案。FlashDB 不仅支持传统的基于文件系统的数据库模式,而且结合了 Flash 的特性,具有较强的性能及可靠性。并在保证极低的资源占用前提下,尽可能延长 Flash 使用寿命
FlashDB 提供两种数据库模式:
- 键值数据库 :是一种非关系数据库,它将数据存储为键值(Key-Value)对集合,其中键作为唯一标识符。KVDB 操作简洁,可扩展性强。
- 时序数据库 :时间序列数据库 (Time Series Database , 简称 TSDB),它将数据按照 时间顺序存储 。TSDB 数据具有时间戳,数据存储量大,插入及查询性能高,数据写满后默认状态是滚动写入(也可以设置不覆盖方式)
使用场景
如今,物联网产品种类越来越多,运行时产生的数据种类及总量及也在不断变大。FlashDB 提供了多样化的数据存储方案,不仅资源占用小,并且存储容量大,非常适合用于物联网产品。下面是主要应用场景:
- 键值数据库 :
- 产品参数存储
- 用户配置信息存储
- 小文件管理
- 时序数据库 :
- 存储动态产生的结构化数据:如 温湿度传感器采集的环境监测信息,智能手环实时记录的人体健康信息等
- 记录运行日志:存储产品历史的运行日志,异常告警的记录等
主要特性
- 资源占用极低,内存占用几乎为 0 ;
- 支持 多分区,多实例 。数据量大时,可细化分区,降低检索时间;
- 支持 磨损平衡 ,延长 Flash 寿命;
- 支持 掉电保护 功能,可靠性高;
- 支持 字符串及 blob 两种 KV 类型,方便用户操作;
- 支持 KV 增量升级 ,产品固件升级后, KVDB 内容也支持自动升级;
- 支持 修改每条 TSDB 记录的状态,方便用户进行管理;
详细的关于FlashDB的文档
在下载目录下查看
2.基于sfud的FlashDB移植教程
移植准备
下载falshdb库:
http://armink.gitee.io/flashdb/#/zh-cn/
移植平台基于mdk+N32L403MB
外部norflash 使用W25q16,驱动库时sfud
文件目录如下
复制文件到工程目录
文件目录结构
添加头文件
...\middle\flashdb\port\fal\inc
...\middle\flashdb\inc
修改***port.c文件
我们这里基于sfud的驱动移植,所以打开fal_flash_sfud_port.c
即可
接口实现
- 初始化接口
- 读取函数接口
- flash编程(写数据接口)
- flash擦除接口
定义各一个FlashDB 对象
对内部个各个参数赋值
c
static int init(void);
static int read(long offset, uint8_t *buf, size_t size);
static int write(long offset, const uint8_t *buf, size_t size);
static int erase(long offset, size_t size);
/*
构建一个FlashDB的设备
*/
struct fal_flash_dev nor_flash0 =
{
.name = NOR_FLASH_DEV_NAME, // 设备名-这个名字在分区表会使用
.addr = 0, // 设备开始地址
.len = 2 * 1024 * 1024, // 设备大小
.blk_size = 4096, // 扇区大小
.ops = {init, read, write, erase}, // 几个操作函数
.write_gran = 1 // 最小读写颗粒
};
修改fal_cfg.h
文件
定义一个设备列表
c
extern struct fal_flash_dev nor_flash0;
/* 定义一个falsh 设备 flash device table */
#define FAL_FLASH_DEV_TABLE \
{ \
&nor_flash0, \
}
定义一个分区表
c
/* ====================== Partition Configuration ========================== */
#define FAL_PART_HAS_TABLE_CFG
#ifdef FAL_PART_HAS_TABLE_CFG
/* 定义一个分区表partition table */
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "fdb_kvdb1", NOR_FLASH_DEV_NAME, 0, 1024*1024, 0}, \
{FAL_PART_MAGIC_WORD, "fdb_tsdb1", NOR_FLASH_DEV_NAME, 1024*1024, 1024*1024, 0}, \
}
// {FAL_PART_MAGIC_WORD, "bl", "stm32_onchip", 0, 64*1024, 0}, \
// {FAL_PART_MAGIC_WORD, "app", "stm32_onchip", 64*1024, 704*1024, 0}, \
#endif /* FAL_PART_HAS_TABLE_CFG */
移植完成
测试
FlashDB提供了很多的测试用例
c
#include <flashdb.h>
#include <string.h>
#define FDB_LOG_TAG "[main]"
static uint32_t boot_count = 0;
static time_t boot_time[10] = {0, 1, 2, 3};
/* 默认的键值对 default KV nodes */
static struct fdb_default_kv_node default_kv_table[] = {
{"username", "armink", 0}, /* string KV */
{"password", "123456", 0}, /* string KV */
{"boot_count", &boot_count, sizeof(boot_count)}, /* int type KV */
{"boot_time", &boot_time, sizeof(boot_time)}, /* int array type KV */
};
/* 定义一个kv键值对对象 KVDB object */
static struct fdb_kvdb kvdb = {0};
/* TSDB object */
struct fdb_tsdb tsdb = {0};
/* counts for simulated timestamp */
static int counts = 0;
extern void kvdb_basic_sample(fdb_kvdb_t kvdb);
extern void kvdb_type_string_sample(fdb_kvdb_t kvdb);
extern void kvdb_type_blob_sample(fdb_kvdb_t kvdb);
extern void tsdb_sample(fdb_tsdb_t tsdb);
static void lock(fdb_db_t db)
{
__disable_irq();
}
static void unlock(fdb_db_t db)
{
__enable_irq();
}
static fdb_time_t get_time(void)
{
/* Using the counts instead of timestamp.
* Please change this function to return RTC time.
*/
return ++counts;
}
int flashdb_demo(void)
{
fdb_err_t result;
#ifdef FDB_USING_KVDB
{
/* 键值对存储 KVDB Sample*/
struct fdb_default_kv default_kv;
default_kv.kvs = default_kv_table;
default_kv.num = sizeof(default_kv_table) / sizeof(default_kv_table[0]);
/* 设置一个加锁或解锁函数 set the lock and unlock function if you want */
fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_LOCK, (void *)lock);
fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_UNLOCK, (void *)unlock);
/* Key-Value 键值对数据库初始化 database initialization
*
* &kvdb: database object
* "env": database name
* "fdb_kvdb1": 分区名字,确保分区表内部有这个分区名字 The flash partition name base on FAL. Please make sure it's in FAL partition table.
* Please change to YOUR partition name.
* &default_kv: The default KV nodes. It will auto add to KVDB when first initialize successfully.
* NULL: The user data if you need, now is empty.
*/
result = fdb_kvdb_init(&kvdb, "env", "fdb_kvdb1", &default_kv, NULL);
if (result != FDB_NO_ERR)
{
return -1;
}
/* 运行整数值 KV samples */
kvdb_basic_sample(&kvdb);
/* 运行键值为字符串的 KV samples */
kvdb_type_string_sample(&kvdb);
/* run blob KV samples */
kvdb_type_blob_sample(&kvdb);
}
#endif /* FDB_USING_KVDB */
#ifdef FDB_USING_TSDB
{ /* TSDB Sample */
/* set the lock and unlock function if you want */
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_LOCK, (void *)lock);
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_UNLOCK, (void *)unlock);
/* Time series database initialization
*
* &tsdb: database object
* "log": database name
* "fdb_tsdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
* Please change to YOUR partition name.
* get_time: The get current timestamp function.
* 128: maximum length of each log
* NULL: The user data if you need, now is empty.
*/
result = fdb_tsdb_init(&tsdb, "log", "fdb_tsdb1", get_time, 128, NULL);
/* read last saved time for simulated timestamp */
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_GET_LAST_TIME, &counts);
if (result != FDB_NO_ERR)
{
return -1;
}
/* run TSDB sample */
tsdb_sample(&tsdb);
}
#endif /* FDB_USING_TSDB */
return 0;
}
3.官方的移植指南
FlashDB 底层的 Flash 管理及操作依赖于 RT-Thread 的 FAL (Flash Abstraction Layer) Flash 抽象层开源软件包 ,该开源库也支持运行在 裸机平台 (点击查看介绍)。所以只需要将所用到的 Flash 对接到 FAL ,即可完成整个移植工作。
FAL 底层将不同的 Flash 存储介质进行了统一封装,并提供了分区表机制,暴露给上层用户
FlashDB 的每个数据库就是基于 FAL 提供的分区机制,每个数据库都坐落在某个 FAL 的分区上,相当于一个分区对应一个数据库
FAL 移植
定义 flash 设备
在定义 Flash 设备表前,需要先定义 Flash 设备。可以是片内 flash, 也可以是片外基于 SFUD 的 spi flash:
- 定义片内 flash 设备可以参考
fal_flash_stm32f2_port.c
。 - 定义片外 spi flash 设备可以参考
fal_flash_sfud_port.c
。
定义具体的 Flash 设备对象,用户需要根据自己的 Flash 情况分别实现 init
、 read
、 write
、 erase
这些操作函数:
static int init(void)
:可选 的初始化操作。static int read(long offset, uint8_t *buf, size_t size)
:读取操作。
参数 | 描述 |
---|---|
offset | 读取数据的 Flash 偏移地址 |
buf | 存放待读取数据的缓冲区 |
size | 待读取数据的大小 |
return | 返回实际读取的数据大小 |
static int write(long offset, const uint8_t *buf, size_t size)
:写入操作。
参数 | 描述 |
---|---|
offset | 写入数据的 Flash 偏移地址 |
buf | 存放待写入数据的缓冲区 |
size | 待写入数据的大小 |
return | 返回实际写入的数据大小 |
static int erase(long offset, size_t size)
:擦除操作。
参数 | 描述 |
---|---|
offset | 擦除区域的 Flash 偏移地址 |
size | 擦除区域的大小 |
return | 返回实际擦除的区域大小 |
用户需要根据自己的 Flash 情况分别实现这些操作函数。在文件最底部定义了具体的 Flash 设备对象 ,如下示例定义了 stm32f2 片上 flash:stm32f2_onchip_flash
C
const struct fal_flash_dev stm32f2_onchip_flash =
{
.name = "stm32_onchip",//这个名字在分区表内部要使用,否则提示找不到分区
.addr = 0x08000000,
.len = 1024*1024,
.blk_size = 128*1024,
.ops = {init, read, write, erase},
.write_gran = 8
};
-
"stm32_onchip"
: Flash 设备的名字。 -
0x08000000
: 对 Flash 操作的起始地址。 -
1024*1024
:Flash 的总大小(1MB)。 -
128*1024
:Flash 块/扇区大小(因为 STM32F2 各块大小不均匀,所以擦除粒度为最大块的大小:128K)。 -
{init, read, write, erase}
:Flash 的操作函数。 如果没有 init 初始化过程,第一个操作函数位置可以置空。 -
8
: 设置写粒度,单位 bit, 0 表示未生效(默认值为 0 ),该成员是 fal 版本大于 0.4.0 的新增成员。各个 flash 写入粒度不尽相同,可通过该成员进行设置,以下列举几种常见 Flash 写粒度:- nor flash: 1 bit
- stm32f2/f4: 8 bit
- stm32f1: 32 bit
- stm32l4: 64 bit
定义 flash 设备列表
Flash 设备表定义在 fal_cfg.h
头文件中,定义分区表前需 新建 fal_cfg.h
文件 ,请将该文件统一放在对应 BSP 或工程目录的 port 文件夹下,并将该头文件路径加入到工程。fal_cfg.h 可以参考 示例文件 fal/samples/porting/fal_cfg.h 完成。
设备表示例:
C
/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev stm32f2_onchip_flash;
extern struct fal_flash_dev nor_flash0;
/* flash device table */
#define FAL_FLASH_DEV_TABLE \
{ \
&stm32f2_onchip_flash, \
&nor_flash0, \
}
Flash 设备表中,有两个 Flash 对象,一个为 STM32F2 的片内 Flash ,一个为片外的 Nor Flash。
定义 flash 分区表
分区表也定义在 fal_cfg.h
头文件中。Flash 分区基于 Flash 设备,每个 Flash 设备又可以有 N 个分区,这些分区的集合就是分区表。在配置分区表前,务必保证已定义好 Flash 设备 及 设备表 。fal_cfg.h 可以参考 示例文件 fal/samples/porting/fal_cfg.h 完成。
分区表示例:
C
#define NOR_FLASH_DEV_NAME "norflash0"
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "bl", "stm32_onchip", 0, 64*1024, 0}, \
{FAL_PART_MAGIC_WORD, "app", "stm32_onchip", 64*1024, 704*1024, 0}, \
{FAL_PART_MAGIC_WORD, "easyflash", NOR_FLASH_DEV_NAME, 0, 1024*1024, 0}, \
{FAL_PART_MAGIC_WORD, "download", NOR_FLASH_DEV_NAME, 1024*1024, 1024*1024, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */
上面这个分区表详细描述信息如下:
分区名 | Flash 设备名 | 偏移地址 | 大小 | 说明 |
---|---|---|---|---|
"bl" | "stm32_onchip" | 0 | 64KB | 引导程序 |
"app" | "stm32_onchip" | 64*1024 | 704KB | 应用程序 |
"easyflash" | "norflash0" | 0 | 1MB | EasyFlash 参数存储 |
"download" | "norflash0" | 1024*1024 | 1MB | OTA 下载区 |
用户需要修改的分区参数包括:分区名称、关联的 Flash 设备名、偏移地址(相对 Flash 设备内部)、大小,需要注意以下几点:
- 分区名保证 不能重复;
- 关联的 Flash 设备 务必已经在 Flash 设备表中定义好 ,并且 名称一致 ,否则会出现无法找到 Flash 设备的错误;
- 分区的起始地址和大小 不能超过 Flash 设备的地址范围 ,否则会导致包初始化错误;
注意:每个分区定义时,除了填写上面介绍的参数属性外,需在前面增加
FAL_PART_MAGIC_WORD
属性,末尾增加0
(目前用于保留功能)
mobaxterm换行符设置
4.FlashDB基本概念
- 键值数据库(KVDB):是一种非关系数据库,它将数据存储为键值(Key-Value)对集合,其中键作为唯一标识符。KVDB 操作简洁,可扩展性强。
- 时序数据(TSDB) :时间序列数据库 (Time Series Database , 简称 TSDB),它将数据按照 时间顺序存储 。TSDB 数据具有时间戳,数据存储量大,插入及查询性能高。
- 时序记录(TSL) :TSL (Time series log),是 TSDB 中每条记录的简称。
- Blob :在计算机中,blob 常常是数据库中用来存储二进制文件的字段类型。在 FlashDB 中, KV 和 TSL 都使用 blob 类型来存储,该类型可以兼容任意变量类型。
- 迭代器(iterator):它可以让用户透过特定的接口巡访容器中的每一个元素,而不用了解底层的实现。 TSDB 和 KVDB 都支持通过迭代器对数据库进行遍历访问。
功能框图
通过下面的功能框图,可以大致了解 FlashDB 功能模块划分
5.FlashDB API 说明
Blob
构造 blob 对象
构造 blob 对象的过程,其内部是对 blob 结构体初始化赋值的过程,将传入的参数写入 blob 结构体中,并进行返回
fdb_blob_t fdb_blob_make(fdb_blob_t blob, const void *value_buf, size_t buf_len)
参数 | 描述 |
---|---|
blob | blob 初始对象 |
value_buf | 存放数据的缓冲区 |
buf_len | 缓冲区的大小 |
返回 | 创建完成后的 blob 对象 |
读取 blob 数据
通过 KVDB 和 TSDB 的 API 可以返回 blob 对象,此时返回的 blob 对象里存放了 blob 数据的存储地址。该 API 可以将数据库里存放的 blob 数据读取出来,并存放至 blob->buf
。
size_t fdb_blob_read(fdb_db_t db, fdb_blob_t blob)
参数 | 描述 |
---|---|
db | 数据库对象 |
blob | blob 对象 |
返回 | 实际读取到的 blob 数据长度 |
KVDB
初始化 KVDB
fdb_err_t fdb_kvdb_init(fdb_kvdb_t db, const char *name, const char *path, struct fdb_default_kv *default_kv, void *user_data)
参数 | 描述 |
---|---|
db | 数据库对象 |
name | 数据库名称 |
path | FAL 模式:分区表中的分区名,文件模式:数据库保存的路径 |
default_kv | 默认 KV 集合,第一次初始化时,将会把默认 KV 写入数据库中 |
user_data | 用户自定义数据,没有时传入 NULL |
返回 | 错误码 |
控制 KVDB
通过命令控制字,用户可以对数据库进行一些控制操作
void fdb_kvdb_control(fdb_kvdb_t db, int cmd, void *arg)
参数 | 描述 |
---|---|
db | 数据库对象 |
cmd | 命令控制字 |
arg | 控制的参数 |
返回 | 错误码 |
支持的命令控制字如下:
C
#define FDB_KVDB_CTRL_SET_SEC_SIZE 0x00 /**< 设置扇区大小,需要在数据库初始化前配置 */
#define FDB_KVDB_CTRL_GET_SEC_SIZE 0x01 /**< 获取扇区大小 */
#define FDB_KVDB_CTRL_SET_LOCK 0x02 /**< 设置加锁函数 */
#define FDB_KVDB_CTRL_SET_UNLOCK 0x03 /**< 设置解锁函数 */
#define FDB_KVDB_CTRL_SET_FILE_MODE 0x09 /**< 设置文件模式,需要在数据库初始化前配置 */
#define FDB_KVDB_CTRL_SET_MAX_SIZE 0x0A /**< 在文件模式下,设置数据库最大大小,需要在数据库初始化前配置 */
#define FDB_KVDB_CTRL_SET_NOT_FORMAT 0x0B /**< 设置初始化时不进行格式化,需要在数据库初始化前配置 */
扇区大小与块大小
FlashDB 内部存储结构由 N 个扇区组成,每次格式化时是以扇区作为最小单位。而一个扇区通常是 Flash 块大小的 N 倍,比如: Nor Flash 的块大小一般为 4096。
默认 KVDB 会使用 1倍 的块大小作为扇区大小,即:4096。此时,该 KVDB 无法存入超过 4096 长度的 KV 。如果想要存入比如:10K 长度的 KV ,可以通过 control 函数,设置扇区大小为 12K,或者更大大小即可。
反初始化 KVDB
fdb_err_t fdb_kvdb_deinit(fdb_kvdb_t db)
参数 | 描述 |
---|---|
db | 数据库对象 |
设置 KV
使用此方法可以实现对 KV 的增加和修改功能。
-
增加 :当 KVDB 中不存在该名称的 KV 时,则会执行新增操作;
-
修改 :入参中的 KV 名称在当前 KVDB 中存在,则把该 KV 值修改为入参中的值;
在 KVDB 内部实现中,修改 KV 会先删除旧的 KV ,再增加新的 KV,所以修改后数据库剩余容量会变小
通过 KV 的名字来获取其对应的值。支持两种接口
设置 blob 类型KV
fdb_err_t fdb_kv_set_blob(fdb_kvdb_t db, const char *key, fdb_blob_t blob)
参数 | 描述 |
---|---|
db | 数据库对象 |
key | KV 的名称 |
blob | blob 对象,做为 KV 的 value |
返回 | 错误码 |
示例:
C
struct fdb_blob blob;
int temp_data = 36;
/* 通过 fdb_blob_make 构造 blob 对象,作为 "temp" KV 的 value */
fdb_kv_set_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data)));
设置 string 类型KV
fdb_err_t fdb_kv_set(fdb_kvdb_t db, const char *key, const char *value)
参数 | 描述 |
---|---|
db | 数据库对象 |
key | KV 的名称 |
value | KV 的 value |
返回 | 错误码 |
获取 KV
获取 blob 类型 KV
size_t fdb_kv_get_blob(fdb_kvdb_t db, const char *key, fdb_blob_t blob)
参数 | 描述 |
---|---|
db | 数据库对象 |
key | KV 的名称 |
blob | 通过 blob 对象,返回 KV 的 blob value |
返回 | 错误码 |
示例:
C
struct fdb_blob blob;
int temp_data = 0;
/* 构造 blob 对象,用于存储 get 回来的 "temp" KV 的 value 数据 */
fdb_kv_get_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data)));
/* 如果有需要,可以检查 blob.saved.len 是否大于 0 ,确保 get 成功 */
if (blob.saved.len > 0) {
FDB_INFO("get the 'temp' value is: %d\n", temp_data);
}
获取 KV 对象
与 fdb_kv_get_blob
API 不同,该 API 在 get 过程中并不会执行 value 数据的读取动作。返回的 KV 对象中存放了读取回来的 KV 属性,该 API 适用于 value 长度不确定,或 value 长度过长,需要分段读取的场景。
fdb_kv_t fdb_kv_get_obj(fdb_kvdb_t db, const char *key, fdb_kv_t kv)
参数 | 描述 |
---|---|
db | 数据库对象 |
key | KV 的名称 |
kv | 通过 KV 对象,返回 KV 的属性,可以再用 fdb_kv_to_blob 转换为 blob 对象,再进行数据读取 |
返回 | 错误码 |
获取字符串类型 KV
注意 :
- 该函数不允许连续使用,使用时需使用 strdup 包裹,确保每次返回回来的字符串内存空间独立;
- 该函数不支持可重入,返回的值位于函数内部缓冲区,出于安全考虑,请加锁保护。
char *fdb_kv_get(fdb_kvdb_t db, const char *key)
参数 | 描述 |
---|---|
db | 数据库对象 |
key | KV 的名称 |
返回 | !=NULL: KV 的 value;NULL: 获取失败 |
删除 KV
在 KVDB 内部实现中,删除 KV 并不会完全从 KVDB 中移除,而是标记为了删除状态,所以删除后数据库剩余容量不会有变化
fdb_err_t fdb_kv_del(fdb_kvdb_t db, const char *key)
参数 | 描述 |
---|---|
db | 数据库对象 |
key | KV 的名称 |
返回 | 错误码 |
重置 KVDB
将 KVDB 中的 KV 重置为 首次初始时 的默认值
fdb_err_t fdb_kv_set_default(fdb_kvdb_t db)
参数 | 描述 |
---|---|
db | 数据库对象 |
返回 | 错误码 |
打印 KVDB 中的 KV 信息
void fdb_kv_print(fdb_kvdb_t db)
参数 | 描述 |
---|---|
db | 数据库对象 |
返回 | 错误码 |
KV 对象转换为 blob 对象
fdb_blob_t fdb_kv_to_blob(fdb_kv_t kv, fdb_blob_t blob)
参数 | 描述 |
---|---|
kv | 待转换的 KV 对象 |
blob | 转换前的 blob 对象 |
返回 | 转换后的 blob 对象 |
初始化 KV 迭代器
fdb_kv_iterator_t fdb_kv_iterator_init(fdb_kvdb_t db, fdb_kv_iterator_t itr)
参数 | 描述 |
---|---|
db | 数据库对象 |
itr | 待初始化的迭代器对象 |
返回 | 初始化后的迭代器对象 |
迭代 KV
使用该迭代器 API,可以遍历整个 KVDB 中的所有 KV。
注意:使用前请先初始化迭代器
bool fdb_kv_iterate(fdb_kvdb_t db, fdb_kv_iterator_t itr)
TSDB
初始化 TSDB
fdb_err_t fdb_tsdb_init(fdb_tsdb_t db, const char *name, const char *path, fdb_get_time get_time, size_t max_len, void *user_data)
参数 | 描述 |
---|---|
db | 数据库对象 |
name | 数据库名称 |
path | FAL 模式:分区表中的分区名,文件模式:数据库保存的路径 |
get_time | 获取当前时间戳的函数 |
max_len | 每条 TSL 的最大长度 |
user_data | 用户自定义数据,没有时传入 NULL |
返回 | 错误码 |
控制 TSDB
通过命令控制字,用户可以对数据库进行一些控制操作
void fdb_tsdb_control(fdb_tsdb_t db, int cmd, void *arg)
参数 | 描述 |
---|---|
db | 数据库对象 |
cmd | 命令控制字 |
arg | 控制的参数 |
返回 | 错误码 |
支持的命令控制字如下:
C
#define FDB_TSDB_CTRL_SET_SEC_SIZE 0x00 /**< 设置扇区大小,需要在数据库初始化前配置 */
#define FDB_TSDB_CTRL_GET_SEC_SIZE 0x01 /**< 获取扇区大小 */
#define FDB_TSDB_CTRL_SET_LOCK 0x02 /**< 设置加锁函数 */
#define FDB_TSDB_CTRL_SET_UNLOCK 0x03 /**< 设置解锁函数 */
#define FDB_TSDB_CTRL_SET_ROLLOVER 0x04 /**< 设置是否滚动写入,默认滚动。设置非滚动时,如果数据库写满,无法再追加写入。需要在数据库初始化后配置 */
#define FDB_TSDB_CTRL_GET_ROLLOVER 0x05 /**< 获取是否滚动写入 */
#define FDB_TSDB_CTRL_GET_LAST_TIME 0x06 /**< 获取上次追加 TSL 时的时间戳 */
#define FDB_TSDB_CTRL_SET_FILE_MODE 0x09 /**< 设置文件模式,需要在数据库初始化前配置,需要在数据库初始化前配置 */
#define FDB_TSDB_CTRL_SET_MAX_SIZE 0x0A /**< 在文件模式下,设置数据库最大大小,需要在数据库初始化前配置 */
#define FDB_TSDB_CTRL_SET_NOT_FORMAT 0x0B /**< 设置初始化时不进行格式化,需要在数据库初始化前配置 */
反初始化 TSDB
fdb_err_t fdb_tsdb_deinit(fdb_tsdb_t db)
参数 | 描述 |
---|---|
db | 数据库对象 |
追加 TSL
对于 TSDB ,新增 TSL 的过程,就是往 TSDB 末尾追加新 TSL 的过程
fdb_err_t fdb_tsl_append(fdb_tsdb_t db, fdb_blob_t blob)
参数 | 描述 |
---|---|
db | 数据库对象 |
blob | blob 对象,做为 TSL 的数据 |
返回 | 错误码 |
迭代 TSL
遍历整个 TSDB 并执行迭代回调
void fdb_tsl_iter(fdb_tsdb_t db, fdb_tsl_cb cb, void *cb_arg)
参数 | 描述 |
---|---|
db | 数据库对象 |
cb | 回调函数,每次遍历到 TSL 时会执行该回调 |
cb_arg | 回调函数的参数 |
返回 | 错误码 |
逆序迭代 TSL
逆序遍历整个 TSDB 并执行迭代回调
void fdb_tsl_iter_reverse(fdb_tsdb_t db, fdb_tsl_cb cb, void *cb_arg)
参数 | 描述 |
---|---|
db | 数据库对象 |
cb | 回调函数,每次遍历到 TSL 时会执行该回调 |
cb_arg | 回调函数的参数 |
返回 | 错误码 |
按时间段迭代 TSL
按时间段范围,遍历整个 TSDB 并执行迭代回调
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)
参数 | 描述 |
---|---|
db | 数据库对象 |
from | 开始时间戳。如果结束时间戳比开始时间戳要小,此时将会执行逆序迭代。 |
to | 结束时间戳 |
cb | 回调函数,每次遍历到 TSL 时会执行该回调 |
cb_arg | 回调函数的参数 |
返回 | 错误码 |
查询 TSL 的数量
按照传入的时间段,查询符合状态的 TSL 数量
size_t fdb_tsl_query_count(fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl_status_t status)
参数 | 描述 |
---|---|
db | 数据库对象 |
from | 开始时间戳 |
to | 结束时间戳 |
status | TSL 的状态条件 |
返回 | 数量 |
设置 TSL 状态
TSL 状态详见 enum fdb_tsl_status
,必须按照顺序设置 TSL 状态, 点击查看示例
fdb_err_t fdb_tsl_set_status(fdb_tsdb_t db, fdb_tsl_t tsl, fdb_tsl_status_t status)
参数 | 描述 |
---|---|
db | 数据库对象 |
tsl | TSL 对象 |
status | TSL 的新状态 |
返回 | 错误码 |
清空 TSDB
void fdb_tsl_clean(fdb_tsdb_t db)
参数 | 描述 |
---|---|
db | 数据库对象 |
返回 | 错误码 |
TSL 对象转换为 blob 对象
fdb_blob_t fdb_tsl_to_blob(fdb_tsl_t tsl, fdb_blob_t blob)
参数 | 描述 |
---|---|
tsl | 待转换的 TSL 对象 |
blob | 转换前的 blob 对象 |
返回 | 转换后的 blob 对象 |