luat_lib_fskv.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /*
  2. @module fskv
  3. @summary kv数据库,掉电不丢数据
  4. @version 1.0
  5. @date 2022.12.29
  6. @demo fskv
  7. @tag LUAT_USE_FSKV
  8. @usage
  9. -- 本库的目标是替代fdb库
  10. -- 1. 兼容fdb的函数
  11. -- 2. 使用fdb的flash空间,启用时也会替代fdb库
  12. fskv.init()
  13. fskv.set("wendal", 1234)
  14. log.info("fskv", "wendal", fskv.get("wendal"))
  15. --[[
  16. fskv与fdb的实现机制导致的差异
  17. fskv fdb
  18. 1. value长度 4096 255
  19. 2. key长度 63 64
  20. ]]
  21. */
  22. #include "luat_base.h"
  23. #include "luat_msgbus.h"
  24. #include "luat_malloc.h"
  25. #include "luat_fskv.h"
  26. #include "luat_sfd.h"
  27. #ifndef LUAT_LOG_TAG
  28. #define LUAT_LOG_TAG "fskv"
  29. #include "luat_log.h"
  30. #endif
  31. #define LUAT_FSKV_MAX_SIZE (4096)
  32. extern sfd_drv_t* sfd_onchip;
  33. extern luat_sfd_lfs_t* sfd_lfs;
  34. static char fskv_read_buff[LUAT_FSKV_MAX_SIZE];
  35. /**
  36. 初始化kv数据库
  37. @api fskv.init()
  38. @string 数据库名,当前仅支持env
  39. @string FAL分区名,当前仅支持onchip_fdb
  40. @return boolean 成功返回true,否则返回false
  41. @usage
  42. if fskv.init() then
  43. log.info("fdb", "kv数据库初始化成功")
  44. end
  45. -- 关于清空fdb库
  46. -- 下载工具是没有提供直接清除fdb数据的途径的, 但有有办法解决
  47. -- 写一个main.lua, 执行 fskv.kvdb_init 后 执行 fskv.clear() 即可全清fdb数据.
  48. */
  49. static int l_fskvdb_init(lua_State *L) {
  50. if (sfd_lfs == NULL) {
  51. if (sfd_onchip == NULL) {
  52. luat_sfd_onchip_init();
  53. }
  54. if (sfd_onchip == NULL) {
  55. LLOGE("sfd-onchip init failed");
  56. return 0;
  57. }
  58. if (sfd_lfs == NULL) {
  59. luat_sfd_lfs_init(sfd_onchip);
  60. }
  61. if (sfd_lfs == NULL) {
  62. LLOGE("sfd-onchip lfs int failed");
  63. return 0;
  64. }
  65. }
  66. lua_pushboolean(L, 1);
  67. return 1;
  68. }
  69. /**
  70. 设置一对kv数据
  71. @api fskv.kv_set(key, value)
  72. @string key的名称,必填,不能空字符串
  73. @string 用户数据,必填,不能nil, 支持字符串/数值/table/布尔值, 数据长度最大255字节
  74. @return boolean 成功返回true,否则返回false
  75. @return number 第二个为返回为flashdb的fdb_kv_set_blob返回详细状态,0:无错误 1:擦除错误 2:读错误 3:些错误 4:未找到 5:kv名字错误 6:kv名字存在 7:已保存 8:初始化错误
  76. @usage
  77. if fskv.kvdb_init("env", "onchip_fdb") then
  78. log.info("fdb", fskv.kv_set("wendal", "goodgoodstudy"))
  79. end
  80. */
  81. static int l_fskv_set(lua_State *L) {
  82. if (sfd_lfs == 0) {
  83. LLOGE("call fskv.init() first!!!");
  84. return 0;
  85. }
  86. size_t len;
  87. luaL_Buffer buff;
  88. luaL_buffinit(L, &buff);
  89. const char* key = luaL_checkstring(L, 1);
  90. //luaL_addchar(&buff, 0xA5);
  91. int type = lua_type(L, 2);
  92. switch (type)
  93. {
  94. case LUA_TBOOLEAN:
  95. luaL_addchar(&buff, LUA_TBOOLEAN);
  96. bool val = lua_toboolean(L, 2);
  97. luaL_addlstring(&buff, (const char*)&val, sizeof(val));
  98. break;
  99. case LUA_TNUMBER:
  100. if (lua_isinteger(L, 2)) {
  101. luaL_addchar(&buff, LUA_TINTEGER); // 自定义类型
  102. lua_Integer val = luaL_checkinteger(L, 2);
  103. luaL_addlstring(&buff, (const char*)&val, sizeof(val));
  104. }
  105. else {
  106. luaL_addchar(&buff, LUA_TNUMBER);
  107. lua_getglobal(L, "pack");
  108. if (lua_isnil(L, -1)) {
  109. LLOGW("float number need pack lib");
  110. lua_pushboolean(L, 0);
  111. return 1;
  112. }
  113. lua_getfield(L, -1, "pack");
  114. lua_pushstring(L, ">f");
  115. lua_pushvalue(L, 2);
  116. lua_call(L, 2, 1);
  117. if (lua_isstring(L, -1)) {
  118. const char* val = luaL_checklstring(L, -1, &len);
  119. luaL_addlstring(&buff, val, len);
  120. }
  121. else {
  122. LLOGW("kdb store number fail!!");
  123. lua_pushboolean(L, 0);
  124. return 1;
  125. }
  126. }
  127. break;
  128. case LUA_TSTRING:
  129. {
  130. luaL_addchar(&buff, LUA_TSTRING);
  131. const char* val = luaL_checklstring(L, 2, &len);
  132. luaL_addlstring(&buff, val, len);
  133. break;
  134. }
  135. case LUA_TTABLE:
  136. {
  137. lua_settop(L, 2);
  138. lua_getglobal(L, "json");
  139. if (lua_isnil(L, -1)) {
  140. LLOGW("miss json lib, not support table value");
  141. lua_pushboolean(L, 0);
  142. return 1;
  143. }
  144. lua_getfield(L, -1, "encode");
  145. if (lua_isfunction(L, -1)) {
  146. lua_pushvalue(L, 2);
  147. lua_call(L, 1, 1);
  148. if (lua_isstring(L, -1)) {
  149. luaL_addchar(&buff, LUA_TTABLE);
  150. const char* val = luaL_checklstring(L, -1, &len);
  151. luaL_addlstring(&buff, val, len);
  152. }
  153. else {
  154. LLOGW("json.encode(val) report error");
  155. lua_pushboolean(L, 0);
  156. return 1;
  157. }
  158. }
  159. else {
  160. LLOGW("miss json.encode, not support table value");
  161. lua_pushboolean(L, 0);
  162. return 1;
  163. }
  164. break;
  165. }
  166. default:
  167. {
  168. LLOGW("function/userdata/nil/thread isn't allow");
  169. lua_pushboolean(L, 0);
  170. return 1;
  171. }
  172. }
  173. if (buff.n > LUAT_FSKV_MAX_SIZE) {
  174. LLOGE("value too big %d max %d", buff.n, LUAT_FSKV_MAX_SIZE);
  175. lua_pushboolean(L, 0);
  176. return 1;
  177. }
  178. int ret = luat_fskv_set(key, buff.b, buff.n);
  179. lua_pushboolean(L, ret == buff.n ? 1 : 0);
  180. lua_pushinteger(L, ret);
  181. return 2;
  182. }
  183. /**
  184. 根据key获取对应的数据
  185. @api fskv.kv_get(key, skey)
  186. @string key的名称,必填,不能空字符串
  187. @string 可选的次级key,仅当原始值为table时有效,相当于 fskv.kv_get(key)[skey]
  188. @return any 存在则返回数据,否则返回nil
  189. @usage
  190. if fskv.init() then
  191. log.info("fdb", fskv.get("wendal"))
  192. end
  193. */
  194. static int l_fskv_get(lua_State *L) {
  195. if (sfd_lfs == NULL) {
  196. LLOGE("call fskv.init() first!!!");
  197. return 0;
  198. }
  199. // luaL_Buffer buff;
  200. const char* key = luaL_checkstring(L, 1);
  201. const char* skey = luaL_optstring(L, 2, "");
  202. // luaL_buffinitsize(L, &buff, 8192);
  203. char* buff = fskv_read_buff;
  204. size_t read_len = luat_fskv_get(key, buff, LUAT_FSKV_MAX_SIZE);
  205. if (read_len < 2) {
  206. return 0;
  207. }
  208. lua_Integer *intVal;
  209. // lua_Number *numVal;
  210. if (read_len) {
  211. // LLOGD("KV value T=%02X", buff.b[0]);
  212. switch(buff[0]) {
  213. case LUA_TBOOLEAN:
  214. lua_pushboolean(L, buff[1]);
  215. break;
  216. case LUA_TNUMBER:
  217. lua_getglobal(L, "pack");
  218. lua_getfield(L, -1, "unpack");
  219. lua_pushlstring(L, (char*)(buff + 1), read_len - 1);
  220. lua_pushstring(L, ">f");
  221. lua_call(L, 2, 2);
  222. // _, val = pack.unpack(data, ">f")
  223. break;
  224. case LUA_TINTEGER:
  225. intVal = (lua_Integer*)(&buff[1]);
  226. lua_pushinteger(L, *intVal);
  227. break;
  228. case LUA_TSTRING:
  229. lua_pushlstring(L, (const char*)(buff + 1), read_len - 1);
  230. break;
  231. case LUA_TTABLE:
  232. lua_getglobal(L, "json");
  233. lua_getfield(L, -1, "decode");
  234. lua_pushlstring(L, (const char*)(buff + 1), read_len - 1);
  235. lua_call(L, 1, 1);
  236. if (strlen(skey) > 0 && lua_istable(L, -1)) {
  237. lua_getfield(L, -1, skey);
  238. }
  239. break;
  240. default :
  241. LLOGW("bad value prefix %02X", buff[0]);
  242. lua_pushnil(L);
  243. break;
  244. }
  245. return 1;
  246. }
  247. lua_pushnil(L);
  248. return 1;
  249. }
  250. /**
  251. 根据key删除数据
  252. @api fskv.kv_del(key)
  253. @string key的名称,必填,不能空字符串
  254. @return bool 成功返回true,否则返回false
  255. @usage
  256. if fskv.kvdb_init("env", "onchip_fdb") then
  257. log.info("fdb", fskv.kv_del("wendal"))
  258. end
  259. */
  260. static int l_fskv_del(lua_State *L) {
  261. if (sfd_lfs == NULL) {
  262. LLOGE("call fskv.init() first!!!");
  263. return 0;
  264. }
  265. const char* key = luaL_checkstring(L, 1);
  266. if (key == NULL) {
  267. lua_pushboolean(L, 0);
  268. return 1;
  269. }
  270. int ret = luat_fskv_del(key);
  271. lua_pushboolean(L, ret == 0 ? 1 : 0);
  272. return 1;
  273. }
  274. /**
  275. 清空整个kv数据库
  276. @api fskv.kv_clr()
  277. @return bool 成功返回true,否则返回false
  278. @usage
  279. -- 清空
  280. fskv.kv_clr()
  281. */
  282. static int l_fskv_clr(lua_State *L) {
  283. if (sfd_lfs == NULL) {
  284. LLOGE("call fskv.init() first!!!");
  285. return 0;
  286. }
  287. int ret = luat_fskv_clear();
  288. lua_pushboolean(L, ret == 0 ? 1 : 0);
  289. return 1;
  290. }
  291. // /**
  292. // kv数据库迭代器
  293. // @api fskv.kv_iter()
  294. // @return userdata 成功返回迭代器指针,否则返回nil
  295. // @usage
  296. // -- 清空
  297. // local iter = fskv.kv_iter()
  298. // if iter then
  299. // while 1 do
  300. // local k = fskv.kv_next(iter)
  301. // if not k then
  302. // break
  303. // end
  304. // log.info("fdb", k, "value", fskv.kv_get(k))
  305. // end
  306. // end
  307. // */
  308. // static int l_fskv_iter(lua_State *L) {
  309. // if (kvdb_inited == 0) {
  310. // LLOGE("call fskv.kvdb_init first!!!");
  311. // return 0;
  312. // }
  313. // fdb_kv_iterator_t iter = lua_newuserdata(L, sizeof(struct fdb_kv_iterator));
  314. // if (iter == NULL) {
  315. // return 0;
  316. // }
  317. // iter = fdb_kv_iterator_init(iter);
  318. // if (iter != NULL) {
  319. // return 1;
  320. // }
  321. // return 0;
  322. // }
  323. // /**
  324. // kv迭代器获取下一个key
  325. // @api fskv.kv_iter(iter)
  326. // @userdata fskv.kv_iter()返回的指针
  327. // @return string 成功返回字符串key值, 否则返回nil
  328. // @usage
  329. // -- 清空
  330. // local iter = fskv.kv_iter()
  331. // if iter then
  332. // while 1 do
  333. // local k = fskv.kv_next(iter)
  334. // if not k then
  335. // break
  336. // end
  337. // log.info("fdb", k, "value", fskv.kv_get(k))
  338. // end
  339. // end
  340. // */
  341. // static int l_fskv_next(lua_State *L) {
  342. // fdb_kv_t cur_kv = NULL;
  343. // fdb_kv_iterator_t iter = lua_touserdata(L, 1);
  344. // if (iter == NULL) {
  345. // return 0;
  346. // }
  347. // bool ret = fdb_kv_iterate(kvdb, iter);
  348. // if (ret) {
  349. // cur_kv = &(iter->curr_kv);
  350. // lua_pushlstring(L, cur_kv->name, cur_kv->name_len);
  351. // // TODO 把值也返回一下?
  352. // return 1;
  353. // }
  354. // return 0;
  355. // }
  356. /*
  357. 获取kv数据库状态
  358. @api fskv.stat()
  359. @return int 已使用的空间,单位字节
  360. @return int 总可用空间, 单位字节
  361. @return int 总kv键值对数量, 单位个
  362. @usage
  363. local used, total,kv_count = fskv.stat()
  364. log.info("fdb", "kv", used,total,kv_count)
  365. */
  366. static int l_fskv_stat(lua_State *L) {
  367. size_t using_sz = 0;
  368. size_t max_sz = 0;
  369. size_t kv_count = 0;
  370. if (sfd_lfs == 0) {
  371. LLOGE("call fskv.init() first!!!");
  372. return 0;
  373. }
  374. luat_fskv_stat(&using_sz, &max_sz, &kv_count);
  375. lua_pushinteger(L, using_sz);
  376. lua_pushinteger(L, max_sz);
  377. lua_pushinteger(L, kv_count);
  378. return 3;
  379. }
  380. #include "rotable2.h"
  381. static const rotable_Reg_t reg_fskv[] =
  382. {
  383. { "init" , ROREG_FUNC(l_fskvdb_init)},
  384. { "set", ROREG_FUNC(l_fskv_set)},
  385. { "get", ROREG_FUNC(l_fskv_get)},
  386. { "del", ROREG_FUNC(l_fskv_del)},
  387. { "clr", ROREG_FUNC(l_fskv_clr)},
  388. { "stat", ROREG_FUNC(l_fskv_stat)},
  389. // { "kv_iter", ROREG_FUNC(l_fskv_iter)},
  390. // { "kv_next", ROREG_FUNC(l_fskv_next)},
  391. // { "kv_stat", ROREG_FUNC(l_fskv_stat)},
  392. // -- 提供与fdb兼容的API
  393. { "kvdb_init" , ROREG_FUNC(l_fskvdb_init)},
  394. { "kv_set", ROREG_FUNC(l_fskv_set)},
  395. { "kv_get", ROREG_FUNC(l_fskv_get)},
  396. { "kv_del", ROREG_FUNC(l_fskv_del)},
  397. { "kv_clr", ROREG_FUNC(l_fskv_clr)},
  398. { "kv_stat", ROREG_FUNC(l_fskv_stat)},
  399. { NULL, ROREG_INT(0)}
  400. };
  401. LUAMOD_API int luaopen_fskv( lua_State *L ) {
  402. luat_newlib2(L, reg_fskv);
  403. lua_pushvalue(L, -1);
  404. lua_setglobal(L, "fdb");
  405. return 1;
  406. }