Skip to content

Commit 57a9d7b

Browse files
committed
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 <[email protected]>
1 parent 801e1a9 commit 57a9d7b

File tree

4 files changed

+141
-3
lines changed

4 files changed

+141
-3
lines changed

include/zephyr/settings/settings.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,14 @@ int settings_load_subtree(const char *subtree);
290290
*/
291291
ssize_t settings_load_one(const char *name, void *buf, size_t buf_len);
292292

293+
/**
294+
* Get the data length of the value relative to the key
295+
*
296+
* @param[in] key Name/key of the settings item.
297+
* @return length of value if item exists, 0 if not and negative value on failure.
298+
*/
299+
ssize_t settings_get_val_len(const char *key);
300+
293301
/**
294302
* Callback function used for direct loading.
295303
* Used by @ref settings_load_subtree_direct function.
@@ -480,6 +488,15 @@ struct settings_store_itf {
480488
* - buf_len - Length of buf.
481489
*/
482490

491+
ssize_t (*csi_get_val_len)(struct settings_store *cs, const char *name);
492+
/**< Gets the value's length associated to the Key defined by name.
493+
* It returns 0 if the Key/Value doesn't exist.
494+
*
495+
* Parameters:
496+
* - cs - Corresponding backend handler node.
497+
* - name - Key in string format.
498+
*/
499+
483500
int (*csi_save_start)(struct settings_store *cs);
484501
/**< Handler called before an export operation.
485502
*

subsys/settings/src/settings_store.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ struct default_param {
9494
size_t *val_len;
9595
};
9696

97+
/* Default callback to set a Key/Value pair */
9798
static int settings_set_default_cb(const char *name, size_t len, settings_read_cb read_cb,
9899
void *cb_arg, void *param)
99100
{
@@ -111,6 +112,59 @@ static int settings_set_default_cb(const char *name, size_t len, settings_read_c
111112
return rc;
112113
}
113114

115+
/* Default callback to get the value's length of the Key defined by name. Returns 0 if Key
116+
* doesn't exist.
117+
*/
118+
static int settings_get_val_len_default_cb(const char *name, size_t len, settings_read_cb read_cb,
119+
void *cb_arg, void *param)
120+
{
121+
const char *next;
122+
size_t name_len;
123+
size_t *val_len = (size_t *)param;
124+
125+
name_len = settings_name_next(name, &next);
126+
if (name_len == 0) {
127+
*val_len = len;
128+
}
129+
130+
return 0;
131+
}
132+
133+
/* Gets the value's size if the Key defined by name is in the persistant storage,
134+
* if not found returns 0.
135+
*/
136+
ssize_t settings_get_val_len(const char *name)
137+
{
138+
struct settings_store *cs;
139+
int rc = 0;
140+
size_t val_len = 0;
141+
142+
/*
143+
* for every config store that supports this function
144+
* get the value's length.
145+
*/
146+
k_mutex_lock(&settings_lock, K_FOREVER);
147+
SYS_SLIST_FOR_EACH_CONTAINER(&settings_load_srcs, cs, cs_next) {
148+
if (cs->cs_itf->csi_get_val_len) {
149+
val_len = cs->cs_itf->csi_get_val_len(cs, name);
150+
} else {
151+
const struct settings_load_arg arg = {
152+
.subtree = name,
153+
.cb = &settings_get_val_len_default_cb,
154+
.param = &val_len
155+
};
156+
rc = cs->cs_itf->csi_load(cs, &arg);
157+
}
158+
}
159+
k_mutex_unlock(&settings_lock);
160+
161+
if (rc >= 0) {
162+
return val_len;
163+
}
164+
165+
return rc;
166+
}
167+
114168
/* Load a single key/value from persistent storage */
115169
int settings_load_one(const char *name, void *buf, size_t buf_len)
116170
{

subsys/settings/src/settings_zms.c

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
3333
size_t val_len);
3434
static void *settings_zms_storage_get(struct settings_store *cs);
3535
static int settings_zms_get_last_hash_ids(struct settings_zms *cf);
36+
static ssize_t settings_zms_get_val_len(struct settings_store *cs, const char *name);
3637

3738
static struct settings_store_itf settings_zms_itf = {.csi_load = settings_zms_load,
3839
.csi_load_one = settings_zms_load_one,
3940
.csi_save = settings_zms_save,
40-
.csi_storage_get = settings_zms_storage_get};
41+
.csi_storage_get = settings_zms_storage_get,
42+
.csi_get_val_len = settings_zms_get_val_len};
4143

4244
static ssize_t settings_zms_read_fn(void *back_end, void *data, size_t len)
4345
{
@@ -293,7 +295,7 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
293295
}
294296
}
295297
}
296-
#endif /* CONFIG_SETTINGS_ZMS_LOAD_SUBTREE_PATH */
298+
#endif /* CONFIG_SETTINGS_ZMS_LOAD_SUBTREE_PATH */
297299
/* If subtree is NULL then we must load all found Settings */
298300
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
299301
uint32_t ll_cache_index = 0;
@@ -340,7 +342,7 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
340342
if (ret < 0) {
341343
return ret;
342344
}
343-
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
345+
#endif /* CONFIG_SETTINGS_ZMS_NO_LL_DELETE */
344346
/* update next ll_hash_id */
345347
#ifdef CONFIG_SETTINGS_ZMS_LL_CACHE
346348
if (ll_cache_index < cf->ll_cache_next) {
@@ -596,6 +598,44 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
596598
return 0;
597599
}
598600

601+
static ssize_t settings_zms_get_val_len(struct settings_store *cs, const char *name)
602+
{
603+
struct settings_zms *cf = CONTAINER_OF(cs, struct settings_zms, cf_store);
604+
char r_name[SETTINGS_FULL_NAME_LEN];
605+
ssize_t rc = 0;
606+
uint32_t name_hash;
607+
608+
/* verify that name is not NULL */
609+
if (!name) {
610+
return -EINVAL;
611+
}
612+
613+
name_hash = sys_hash32(name, strnlen(name, SETTINGS_FULL_NAME_LEN)) & ZMS_HASH_MASK;
614+
for (int i = 0; i <= cf->hash_collision_num; i++) {
615+
name_hash = ZMS_UPDATE_COLLISION_NUM(name_hash, i);
616+
/* Get the name entry from ZMS */
617+
rc = zms_read(&cf->cf_zms, ZMS_NAME_ID_FROM_HASH(name_hash), r_name,
618+
sizeof(r_name) - 1);
619+
if (rc <= 0) {
620+
/* Name doesn't exist */
621+
continue;
622+
}
623+
/* Found a name, this might not include a trailing \0 */
624+
r_name[rc] = '\0';
625+
if (strcmp(name, r_name)) {
626+
/* Names are not equal let's continue to the next collision hash
627+
* if it exists.
628+
*/
629+
continue;
630+
}
631+
/* At this steps the names are equal, let's read the data size*/
632+
return zms_get_data_length(&cf->cf_zms,
633+
ZMS_NAME_ID_FROM_HASH(name_hash) + ZMS_DATA_ID_OFFSET);
634+
}
635+
636+
return 0;
637+
}
638+
599639
static int settings_zms_get_last_hash_ids(struct settings_zms *cf)
600640
{
601641
struct settings_hash_linked_list settings_element;

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,13 +240,22 @@ ZTEST(settings_functional, test_register_and_loading)
240240
{
241241
int rc, err;
242242
uint8_t val = 0;
243+
ssize_t val_len = 0;
243244

244245
rc = settings_subsys_init();
245246
zassert_true(rc == 0, "subsys init failed");
246247

247248

249+
/* Check that key that corresponds to val2 do not exist in storage */
250+
val_len = settings_get_val_len("ps/ss/ss/val2");
251+
zassert_true((val_len == 0), "Failure: key should not exist");
252+
248253
settings_save_one("ps/ss/ss/val2", &val, sizeof(uint8_t));
249254

255+
/* Check that the key that corresponds to val2 exists in storage */
256+
val_len = settings_get_val_len("ps/ss/ss/val2");
257+
zassert_true((val_len == 1), "Failure: key should exist");
258+
250259
memset(&data, 0, sizeof(struct stored_data));
251260

252261
rc = settings_register(&val1_settings);
@@ -279,7 +288,16 @@ ZTEST(settings_functional, test_register_and_loading)
279288
err = (data.en1) && (data.en2) && (!data.en3);
280289
zassert_true(err, "wrong data enable found");
281290

291+
/* Check that key that corresponds to val3 do not exist in storage */
292+
val_len = settings_get_val_len("ps/ss/val3");
293+
zassert_true((val_len == 0), "Failure: key should not exist");
294+
282295
settings_save_one("ps/ss/val3", &val, sizeof(uint8_t));
296+
297+
/* Check that the key that corresponds to val3 exists in storage */
298+
val_len = settings_get_val_len("ps/ss/val3");
299+
zassert_true((val_len == 1), "Failure: key should exist");
300+
283301
memset(&data, 0, sizeof(struct stored_data));
284302
/* when we load settings now data.val2 and data.val1 should receive a
285303
* value
@@ -310,7 +328,16 @@ ZTEST(settings_functional, test_register_and_loading)
310328
err = (data.en1) && (data.en2) && (data.en3);
311329
zassert_true(err, "wrong data enable found");
312330

331+
/* Check that key that corresponds to val1 do not exist in storage */
332+
val_len = settings_get_val_len("ps/val1");
333+
zassert_true((val_len == 0), "Failure: key should not exist");
334+
313335
settings_save_one("ps/val1", &val, sizeof(uint8_t));
336+
337+
/* Check that the key that corresponds to val1 exists in storage */
338+
val_len = settings_get_val_len("ps/val1");
339+
zassert_true((val_len == 1), "Failure: key should exist");
340+
314341
memset(&data, 0, sizeof(struct stored_data));
315342
/* when we load settings all data should receive a value loaded */
316343
rc = settings_load();

0 commit comments

Comments
 (0)