移植案例与原理 - utils子系统之KV存储部件 (3)

5、KV存储部件对应UtilsFile接口部分的代码

分析下KV存储部件对应UtilsFile接口部分的代码。我们知道对外接口有设置键值UtilsSetValue、获取键值UtilsGetValue、删除键值UtilsDeleteValue和清除缓存ClearKVCache。我们先看看内部接口,这些接口调用的全部是UtilsFile接口,没有使用POSIX的文件接口。

5.1 内部接口

5.1.1 GetValueByFile和SetValueToFile从文件中读写键值

函数GetValueByFile用于从文件中读取键值,⑴处获取键名对应的键值文件的大小,如果文件大于等于参数中指定的长度len,返回EC_FAILURE。等于也不行,末尾需要放置一个空字符。⑵处打开文件,然后读取文件,读取的内容放入变量value里。⑶处末尾添加null空字符,然后返回获取的字符的长度。函数SetValueToFile用于把键值保存到文件里,⑷处调用UtilsFile接口打开,然后写入到文件里。

static int GetValueByFile(const char* key, char* value, unsigned int len)
{
    unsigned int valueLen = 0;
⑴  if (UtilsFileStat(key, &valueLen) != EC_SUCCESS) {
        return EC_FAILURE;
    }
    if (valueLen >= len) {
        return EC_FAILURE;
    }
⑵  int fd = UtilsFileOpen(key, O_RDONLY_FS, 0);
    if (fd < 0) {
        return EC_FAILURE;
    }
    int ret = UtilsFileRead(fd, value, valueLen);
    UtilsFileClose(fd);
    fd = -1;
    if (ret < 0) {
        return EC_FAILURE;
    }
⑶  value[valueLen] = '\0';
    return valueLen;
}

static int SetValueToFile(const char* key, const char* value)
{
⑷  int fd = UtilsFileOpen(key, O_RDWR_FS | O_CREAT_FS | O_TRUNC_FS, 0);
    if (fd < 0) {
        return EC_FAILURE;
    }
    int ret = UtilsFileWrite(fd, value, strlen(value));
    UtilsFileClose(fd);
    fd = -1;
    return (ret < 0) ? EC_FAILURE : EC_SUCCESS;
}

5.1.2 GetCurrentItem和SetCurrentItem获取设置键值对数量

函数GetCurrentItem用于获取键值对数量,⑴处可以看出,键值对数目保存在文件KV_FILE_SUM里。从文件里读取的键值对数量会放入⑵处的字符串里,字符串的长度为4,所以键值对的数量能是K级。然后执行UtilsFileRead读取文件内容,然后通过atoi函数转换为数值。函数SetCurrentItem用于更新键值对数量,保存到文件里。⑷处把整形的参数转换为字符串,然后打开文件KV_FILE_SUM,并写入。

#define KV_SUM_FILE        "KV_FILE_SUM"
#define KV_SUM_INDEX       4
......
static int GetCurrentItem(void)
{
⑴  int fd = UtilsFileOpen(KV_SUM_FILE, O_RDWR_FS, 0);
    if (fd < 0) {
        return 0;
    }
⑵  char value[KV_SUM_INDEX] = {0};
    int ret = UtilsFileRead(fd, value, KV_SUM_INDEX);
    UtilsFileClose(fd);
    fd = -1;
⑶  return (ret < 0) ? 0 : atoi(value);
}

static int SetCurrentItem(const int num)
{
    char value[KV_SUM_INDEX] = {0};
⑷  if (sprintf_s(value, KV_SUM_INDEX, "%d", num) < 0) {
        return EC_FAILURE;
    }
    int fd = UtilsFileOpen(KV_SUM_FILE, O_RDWR_FS | O_CREAT_FS, 0);
    if (fd < 0) {
        return EC_FAILURE;
    }
    int ret = UtilsFileWrite(fd, value, KV_SUM_INDEX);
    UtilsFileClose(fd);
    fd = -1;
    return (ret < 0) ? EC_FAILURE : EC_SUCCESS;
}

5.1.3 NewItem判断是否新键值对

函数NewItem用于判断给定的键名是否新的键值对,是否已经存在同样的键名。调用函数UtilsFileOpen,如果能打开,说明文件已经存在,否则不存在。

static boolean NewItem(const char* key)
{
    int fd = UtilsFileOpen(key, O_RDONLY_FS, 0);
    if (fd < 0) {
        return TRUE;
    }
    UtilsFileClose(fd);
    return FALSE;
}

5.2 获取键值UtilsGetValue

函数UtilsGetValue用于从文件中读取键值,传入键名key,读出的值保存在参数value,len设置读取的值的长度。如果支持键值对缓存,则执行⑴尝试从缓存中读取,否则执行⑵从文件中读取。读取成功后,会执行⑶把读取的键值加入缓存。

int UtilsGetValue(const char* key, char* value, unsigned int len)
{
    if (!IsValidKey(key) || (value == NULL) || (len > MAX_GET_VALUE_LEN)) {
        return EC_INVALID;
    }
#ifdef FEATURE_KV_CACHE
⑴  if (GetValueByCache(key, value, len) == EC_SUCCESS) {
        return EC_SUCCESS;
    }
#endif
⑵  int ret = GetValueByFile(key, value, len);
    if (ret < 0) {
        return EC_FAILURE;
    }
#ifdef FEATURE_KV_CACHE
⑶  AddKVCache(key, value, FALSE);
#endif
    return ret;
}

5.3 设置键值UtilsGetValue

函数UtilsGetValue用于设置键值对到文件。⑴处获取已有的键值对的数目,⑵处判断要设置的键值是否已经存在。⑶处如果键值对数量已经大于等于允许的最大值,并且要是新增的键值对,则然后EC_FAILURE。⑷处保存键值对到文件,如果支持缓存,则加入缓存。⑸处更新键值对数量。

int UtilsSetValue(const char* key, const char* value)
{
    if (!IsValidKey(key) || !IsValidValue(value, MAX_VALUE_LEN)) {
        return EC_INVALID;
    }
⑴  int currentNum = GetCurrentItem();
⑵  boolean newItem = NewItem(key);
⑶  if ((currentNum >= MAX_KV_SUM) && newItem) {
        return EC_FAILURE;
    }
⑷  int ret = SetValueToFile(key, value);
    if (ret == EC_SUCCESS) {
#ifdef FEATURE_KV_CACHE
        AddKVCache(key, value, TRUE);
#endif
        if (newItem) {
            currentNum++;
        }
    }

⑸  return SetCurrentItem(currentNum);
}

5.4 删除键值UtilsDeleteValue等

函数UtilsDeleteValue用于删除键值文件,如果支持缓存则先从缓存中删除。执行⑴删除文件,⑵处更新键值对数目。函数ClearKVCache用于清除缓存。对于使用UtilsFile接口时,不需要UtilsSetEnv函数。

int UtilsDeleteValue(const char* key)
{
    if (!IsValidKey(key)) {
        return EC_INVALID;
    }
#ifdef FEATURE_KV_CACHE
    DeleteKVCache(key);
#endif
⑴  int ret = UtilsFileDelete(key);
    if (ret == EC_SUCCESS) {
⑵      ret = SetCurrentItem(GetCurrentItem() - 1);
    }
    return ret;
}

#ifdef FEATURE_KV_CACHE
int ClearKVCache(void)
{
    return ClearKVCacheInner();
}
#endif

int UtilsSetEnv(const char* path)
{
    return EC_SUCCESS;
}

小结

本文介绍了utils子系统之KV存储部件的移植适配案例,分析了部件源代码。

如果大家想更加深入的学习 OpenHarmony 开发的内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……

系统架构分析:https://qr18.cn/CgxrRy

  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

在这里插入图片描述

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:https://qr21.cn/FV7h05

相关推荐

  1. 浏览器原理本地存储

    2024-06-19 00:06:01       11 阅读
  2. 3D,kd-tree算法原理

    2024-06-19 00:06:01       8 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-19 00:06:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-19 00:06:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-19 00:06:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-19 00:06:01       18 阅读

热门阅读

  1. 如何构建构建一个AI驱动的通用爬虫

    2024-06-19 00:06:01       7 阅读
  2. Shell中执行.sh文件的常见方式

    2024-06-19 00:06:01       7 阅读
  3. 平移矩阵中的数学思考

    2024-06-19 00:06:01       7 阅读
  4. Spring Cloud Gateway 概述与基本配置(上)

    2024-06-19 00:06:01       6 阅读
  5. 从零学习es8

    2024-06-19 00:06:01       5 阅读
  6. Stage模型

    2024-06-19 00:06:01       6 阅读
  7. 正规式理解

    2024-06-19 00:06:01       5 阅读