Browse Source

settings: add new API function settings_get_val_len()

Add a function to get the value's length of a Key. If it doesn't exist
returns 0.
Add ZMS implementation for csi_get_val_len() and a default implementation
for the other storage systems.
Add some functional tests to verify it.

Signed-off-by: Riadh Ghaddab <rghaddab@baylibre.com>
pull/90028/head
Riadh Ghaddab 4 months ago committed by Benjamin Cabé
parent
commit
cad2f1c103
  1. 17
      include/zephyr/settings/settings.h
  2. 55
      subsys/settings/src/settings_store.c
  3. 42
      subsys/settings/src/settings_zms.c
  4. 27
      tests/subsys/settings/functional/src/settings_basic_test.c

17
include/zephyr/settings/settings.h

@ -289,6 +289,14 @@ int settings_load_subtree(const char *subtree); @@ -289,6 +289,14 @@ int settings_load_subtree(const char *subtree);
*/
ssize_t settings_load_one(const char *name, void *buf, size_t buf_len);
/**
* Get the data length of the value relative to the key
*
* @param[in] key Name/key of the settings item.
* @return length of value if item exists, 0 if not and negative value on failure.
*/
ssize_t settings_get_val_len(const char *key);
/**
* Callback function used for direct loading.
* Used by @ref settings_load_subtree_direct function.
@ -479,6 +487,15 @@ struct settings_store_itf { @@ -479,6 +487,15 @@ struct settings_store_itf {
* - buf_len - Length of buf.
*/
ssize_t (*csi_get_val_len)(struct settings_store *cs, const char *name);
/**< Gets the value's length associated to the Key defined by name.
* It returns 0 if the Key/Value doesn't exist.
*
* Parameters:
* - cs - Corresponding backend handler node.
* - name - Key in string format.
*/
int (*csi_save_start)(struct settings_store *cs);
/**< Handler called before an export operation.
*

55
subsys/settings/src/settings_store.c

@ -94,6 +94,7 @@ struct default_param { @@ -94,6 +94,7 @@ struct default_param {
size_t *val_len;
};
/* Default callback to set a Key/Value pair */
static int settings_set_default_cb(const char *name, size_t len, settings_read_cb read_cb,
void *cb_arg, void *param)
{
@ -111,6 +112,60 @@ static int settings_set_default_cb(const char *name, size_t len, settings_read_c @@ -111,6 +112,60 @@ static int settings_set_default_cb(const char *name, size_t len, settings_read_c
return rc;
}
/* Default callback to get the value's length of the Key defined by name.
* Returns the value's length in the provided `param` pointer
*/
static int settings_get_val_len_default_cb(const char *name, size_t len,
[[maybe_unused]] settings_read_cb read_cb,
[[maybe_unused]] void *cb_arg, void *param)
{
const char *next;
size_t name_len;
size_t *val_len = (size_t *)param;
name_len = settings_name_next(name, &next);
if (name_len == 0) {
*val_len = len;
}
return 0;
}
/* Gets the value's size if the Key defined by name is in the persistent storage,
* Returns 0 if the Key doesn't exist.
*/
ssize_t settings_get_val_len(const char *name)
{
struct settings_store *cs;
int rc = 0;
size_t val_len = 0;
/*
* for every config store that supports this function
* get the value's length.
*/
k_mutex_lock(&settings_lock, K_FOREVER);
SYS_SLIST_FOR_EACH_CONTAINER(&settings_load_srcs, cs, cs_next) {
if (cs->cs_itf->csi_get_val_len) {
val_len = cs->cs_itf->csi_get_val_len(cs, name);
} else {
const struct settings_load_arg arg = {
.subtree = name,
.cb = &settings_get_val_len_default_cb,
.param = &val_len
};
rc = cs->cs_itf->csi_load(cs, &arg);
}
}
k_mutex_unlock(&settings_lock);
if (rc >= 0) {
return val_len;
}
return rc;
}
/* Load a single key/value from persistent storage */
ssize_t settings_load_one(const char *name, void *buf, size_t buf_len)
{

42
subsys/settings/src/settings_zms.c

@ -33,11 +33,13 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const @@ -33,11 +33,13 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
size_t val_len);
static void *settings_zms_storage_get(struct settings_store *cs);
static int settings_zms_get_last_hash_ids(struct settings_zms *cf);
static ssize_t settings_zms_get_val_len(struct settings_store *cs, const char *name);
static struct settings_store_itf settings_zms_itf = {.csi_load = settings_zms_load,
.csi_load_one = settings_zms_load_one,
.csi_save = settings_zms_save,
.csi_storage_get = settings_zms_storage_get};
.csi_storage_get = settings_zms_storage_get,
.csi_get_val_len = settings_zms_get_val_len};
static ssize_t settings_zms_read_fn(void *back_end, void *data, size_t len)
{
@ -530,6 +532,44 @@ no_ll_update: @@ -530,6 +532,44 @@ no_ll_update:
return 0;
}
static ssize_t settings_zms_get_val_len(struct settings_store *cs, const char *name)
{
struct settings_zms *cf = CONTAINER_OF(cs, struct settings_zms, cf_store);
char r_name[SETTINGS_MAX_NAME_LEN + SETTINGS_EXTRA_LEN + 1];
ssize_t rc = 0;
uint32_t name_hash;
/* verify that name is not NULL */
if (!name) {
return -EINVAL;
}
name_hash = sys_hash32(name, strlen(name)) & ZMS_HASH_MASK;
for (int i = 0; i <= cf->hash_collision_num; i++) {
name_hash = ZMS_UPDATE_COLLISION_NUM(name_hash, i);
/* Get the name entry from ZMS */
rc = zms_read(&cf->cf_zms, ZMS_NAME_ID_FROM_HASH(name_hash), r_name,
sizeof(r_name) - 1);
if (rc <= 0) {
/* Name doesn't exist */
continue;
}
/* Found a name, this might not include a trailing \0 */
r_name[rc] = '\0';
if (strcmp(name, r_name)) {
/* Names are not equal let's continue to the next collision hash
* if it exists.
*/
continue;
}
/* At this steps the names are equal, let's read the data size*/
return zms_get_data_length(&cf->cf_zms,
ZMS_NAME_ID_FROM_HASH(name_hash) + ZMS_DATA_ID_OFFSET);
}
return 0;
}
static int settings_zms_get_last_hash_ids(struct settings_zms *cf)
{
struct settings_hash_linked_list settings_element;

27
tests/subsys/settings/functional/src/settings_basic_test.c

@ -240,13 +240,22 @@ ZTEST(settings_functional, test_register_and_loading) @@ -240,13 +240,22 @@ ZTEST(settings_functional, test_register_and_loading)
{
int rc, err;
uint8_t val = 0;
ssize_t val_len = 0;
rc = settings_subsys_init();
zassert_true(rc == 0, "subsys init failed");
/* Check that key that corresponds to val2 do not exist in storage */
val_len = settings_get_val_len("ps/ss/ss/val2");
zassert_true((val_len == 0), "Failure: key should not exist");
settings_save_one("ps/ss/ss/val2", &val, sizeof(uint8_t));
/* Check that the key that corresponds to val2 exists in storage */
val_len = settings_get_val_len("ps/ss/ss/val2");
zassert_true((val_len == 1), "Failure: key should exist");
memset(&data, 0, sizeof(struct stored_data));
rc = settings_register(&val1_settings);
@ -279,7 +288,16 @@ ZTEST(settings_functional, test_register_and_loading) @@ -279,7 +288,16 @@ ZTEST(settings_functional, test_register_and_loading)
err = (data.en1) && (data.en2) && (!data.en3);
zassert_true(err, "wrong data enable found");
/* Check that key that corresponds to val3 do not exist in storage */
val_len = settings_get_val_len("ps/ss/val3");
zassert_true((val_len == 0), "Failure: key should not exist");
settings_save_one("ps/ss/val3", &val, sizeof(uint8_t));
/* Check that the key that corresponds to val3 exists in storage */
val_len = settings_get_val_len("ps/ss/val3");
zassert_true((val_len == 1), "Failure: key should exist");
memset(&data, 0, sizeof(struct stored_data));
/* when we load settings now data.val2 and data.val1 should receive a
* value
@ -310,7 +328,16 @@ ZTEST(settings_functional, test_register_and_loading) @@ -310,7 +328,16 @@ ZTEST(settings_functional, test_register_and_loading)
err = (data.en1) && (data.en2) && (data.en3);
zassert_true(err, "wrong data enable found");
/* Check that key that corresponds to val1 do not exist in storage */
val_len = settings_get_val_len("ps/val1");
zassert_true((val_len == 0), "Failure: key should not exist");
settings_save_one("ps/val1", &val, sizeof(uint8_t));
/* Check that the key that corresponds to val1 exists in storage */
val_len = settings_get_val_len("ps/val1");
zassert_true((val_len == 1), "Failure: key should exist");
memset(&data, 0, sizeof(struct stored_data));
/* when we load settings all data should receive a value loaded */
rc = settings_load();

Loading…
Cancel
Save