Key-Value Database

Last Updated on : 2024-01-09 03:57:30download

The key-value database module enables you to store and retrieve small chunks of data.

Features

  • Add, delete, and query data.
  • Query and read data with fuzzy matching.
  • Encrypted storage.
  • Internal cache acceleration.
  • Wear leveling.
  • Power loss protection.
  • Critical key-value data protection.

How it works

A contiguous storage space (32 KB or 64 KB) is partitioned in the memory. The space is divided into blocks of 4 KB each. Each block is then divided into pages of 128B each.
There are three types of pages by purpose.

  • Management page: The first page of each block serves as the management page, allowing you to maintain the usage of each page in that block.

  • Index page: Includes the key as well as the starting and ending page addresses of the associated value. Each key occupies a page exclusively.

  • Data page: Stores values, which can be across multiple pages.

    Key-Value Database

Scenarios

Store data in key-value pairs that can be read, deleted, and edited.

API description

Initialize key-value database

Key-value database is initialized during product testing, and you do not need to handle it. However, if you do not use Tuya’s testing tool, you must manually initialize or format the key-value database.

/**
* @brief tuya key-value database initialization in mf
*
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*
* @note user don't need to care about this function, it will be called during tuya IoTOS initialization.
*
*/
OPERATE_RET ws_db_init_mf(VOID);

Write to key-value database

Write a key-value pair to the database, with the key, value, and length of the value.

/**
* @brief tuya key-value database write entry
*
* @param[in] key key of the entry you want to write
* @param[in] value value buffer you want to write
* @param[in] len the numbers of bytes you want to write
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*/
OPERATE_RET wd_common_write(IN CONST CHAR_T *key, IN CONST BYTE_T *value, IN CONST UINT_T len);

Read from key-value database

Read a key-value pair from the database, with the key, the buffer to store the value, and length of the buffer. After the data is read, get the value and its length.

/**
* @brief tuya key-value database read entry
*
* @param[in] key key of the entry you want to read
* @param[out] value buffer of the value
* @param[out] p_len length of the buffer
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*
* @note must free the value buffer with wd_common_free_data when you no longer need the buffer
*/
OPERATE_RET wd_common_read(IN CONST CHAR_T *key, OUT BYTE_T **value, OUT UINT_T *p_len);

Delete data from key-value database

Delete a key-value pair from the database, with the key.

/**
* @brief delete the entry from key-value database
*
* @param[in] key key of the entry you want to delete
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*/
OPERATE_RET wd_common_delete(IN CONST CHAR_T *key);

Read from key-value database with fuzzy matching

With fuzzy matching, read a key-value pair that matches the provided fuzzy key, with a buffer for storing the value and its length. After the data is read, get the value and its length. wd_common_fuzzy_read will return the matched key-value data based on the index.

/**
* @brief tuya key-value database fuzzy read entry
*
* @param[in] fuzzy_name key of the entry you want to read
* @param[in] index index of the value sequence
* @param[out] data buffer of the value
* @param[out] p_len length of the buffer
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*
* @note if we have three entries "x1","x2","x3" in database, and read use "x" as the key will got all these 3 entries
* and will choose the return entry by index
*
* @note must free the value buffer with wd_common_free_data when you no longer need the buffer
*/
OPERATE_RET wd_common_fuzzy_read(IN CONST CHAR_T *fuzzy_name, INOUT UINT_T *index, OUT BYTE_T **data, OUT UINT_T *len);

Delete data from key-value database with fuzzy matching

With fuzzy matching, delete a key-value pair that matches the provided fuzzy key.

/**
* @brief fuzzy delete the entry from key-value database
*
* @param[in] key key of the entry you want to delete
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*
* @note delete all entries if the key matches the prefix of entry key
*/
OPERATE_RET wd_common_fuzzy_delete(IN CONST CHAR_T *key);

Write custom data to key-value database

Write data with the key user_param_key that is specifically used to store custom data. Entering a key is not required.

/**
* @brief write the user parameter to the Tuya key-value database
*
* @param[in] data buffer of the data
* @param[in] len length of the data
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*
* @note the key of user parameter entry is "user_param_key"
*/
OPERATE_RET wd_user_param_write(IN CONST BYTE_T *data, IN CONST UINT_T len);

Read custom data from key-value database

Read data with the key user_param_key that is specifically used to store custom data. Entering a key is not required.

/**
* @brief read the user parameter from tuya key-value database
*
* @param[out] buf buffer of the data
* @param[out] len length of the data
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*
* @note the key of user parameter entry is "user_param_key", must free the value buffer with
* wd_common_free_data when you nolonger need the buffer
*/
OPERATE_RET wd_user_param_read(OUT BYTE_T **buf, OUT UINT_T *len);

Release key-value data

Release the resources allocated when calling wd_common_read, wd_common_fuzzy_read, and wd_user_param_read. Note that after successfully calling wd_common_read and wd_common_fuzzy_read, you must call wd_common_free_data to avoid a memory leak.

/**
* @brief free the buffer which is allocated by wd_common_read or wd_common_fuzzy_read
*
* @param[in] data the buffer got from wd_common_read or wd_common_fuzzy_read
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*/
OPERATE_RET wd_common_free_data(IN BYTE_T *data);

Example

sample_kv_demo()
{
    int rt = OPRT_OK;
    // Write data "ddi-xxx": "hello-world-x"
    rt = wd_common_write("ddi-xxx", "hello-world-x", 13);
    EXPECT_EQ(rt, OPRT_OK);

    // Read data "ddi-xxx", requiring wd_common_free_data
    BYTE_T *value = NULL;
    UINT_T len = 0;
    rt = wd_common_read("ddi-xxx", &value, &len);
    EXPECT_EQ(rt, OPRT_OK);
    EXPECT_EQ(memcmp(value, "hello-world-x", 13), 0);
    wd_common_free_data(value);
    value = NULL;
    len = 0;

    // Write data "ddi-xxx": "hello-world-y"
    rt = wd_common_write("ddi-yyy", "hello-world-y", 13);
    EXPECT_EQ(rt, OPRT_OK);

    // Modify data "ddi-xxx": "hello-world-z"
    rt = wd_common_write("ddi-xxx", "hello-world-z", 13);
    EXPECT_EQ(rt, OPRT_OK);
    // Read all data that includes "ddi-". Automatically iterate and retrieve all data.
    UINT index = 0;
    while(rt == OPRT_OK) {
        rt = wd_common_fuzzy_read("ddi-", &index, &value, &len);
        if(value) {
            wd_common_free_data(value);
            value = NULL;
        }
    }

    // Delete data "ddi-xxx"
    rt = wd_common_delete("ddi-xxx");
    EXPECT_EQ(rt, OPRT_OK);

    // Delete all data that includes "ddi-".
    rt = wd_common_fuzzy_delete("ddi-");
    EXPECT_EQ(rt, OPRT_OK);
    return OPRT_OK;
}

FAQs

Can I store custom data in the key-value database?

Yes, you can. Do not exceed the storage limit of the key-value database, typically 32 KB. It is not recommended to frequently read and write the key-value database, particularly during device startup. This can slow down the device’s startup time. Additionally, unstable voltage might lead to failed operations on the flash memory.