Skip to content

Commit 2b3ab07

Browse files
rghaddabcarlescufi
authored andcommitted
[nrf fromlist] 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. Upstream PR #: 87792 Signed-off-by: Riadh Ghaddab <[email protected]> (cherry picked from commit 5a730f71f49e87fb4da35120826e8d45bc62fef6) (cherry picked from commit 2b82fc1)
1 parent 300fb88 commit 2b3ab07

File tree

4 files changed

+140
-1
lines changed

4 files changed

+140
-1
lines changed

include/zephyr/settings/settings.h

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

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

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

subsys/settings/src/settings_store.c

Lines changed: 55 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,60 @@ 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,
119+
[[maybe_unused]] settings_read_cb read_cb,
120+
[[maybe_unused]] void *cb_arg, void *param)
121+
{
122+
const char *next;
123+
size_t name_len;
124+
size_t *val_len = (size_t *)param;
125+
126+
name_len = settings_name_next(name, &next);
127+
if (name_len == 0) {
128+
*val_len = len;
129+
}
130+
131+
return 0;
132+
}
133+
134+
/* Gets the value's size if the Key defined by name is in the persistent storage,
135+
* if not found returns 0.
136+
*/
137+
ssize_t settings_get_val_len(const char *name)
138+
{
139+
struct settings_store *cs;
140+
int rc = 0;
141+
size_t val_len = 0;
142+
143+
/*
144+
* for every config store that supports this function
145+
* get the value's length.
146+
*/
147+
k_mutex_lock(&settings_lock, K_FOREVER);
148+
SYS_SLIST_FOR_EACH_CONTAINER(&settings_load_srcs, cs, cs_next) {
149+
if (cs->cs_itf->csi_get_val_len) {
150+
val_len = cs->cs_itf->csi_get_val_len(cs, name);
151+
} else {
152+
const struct settings_load_arg arg = {
153+
.subtree = name,
154+
.cb = &settings_get_val_len_default_cb,
155+
.param = &val_len
156+
};
157+
rc = cs->cs_itf->csi_load(cs, &arg);
158+
}
159+
}
160+
k_mutex_unlock(&settings_lock);
161+
162+
if (rc >= 0) {
163+
return val_len;
164+
}
165+
166+
return rc;
167+
}
168+
114169
/* Load a single key/value from persistent storage */
115170
ssize_t settings_load_one(const char *name, void *buf, size_t buf_len)
116171
{

subsys/settings/src/settings_zms.c

Lines changed: 41 additions & 1 deletion
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
{
@@ -529,6 +531,44 @@ static int settings_zms_save(struct settings_store *cs, const char *name, const
529531
return 0;
530532
}
531533

534+
static ssize_t settings_zms_get_val_len(struct settings_store *cs, const char *name)
535+
{
536+
struct settings_zms *cf = CONTAINER_OF(cs, struct settings_zms, cf_store);
537+
char r_name[SETTINGS_MAX_NAME_LEN + SETTINGS_EXTRA_LEN + 1];
538+
ssize_t rc = 0;
539+
uint32_t name_hash;
540+
541+
/* verify that name is not NULL */
542+
if (!name) {
543+
return -EINVAL;
544+
}
545+
546+
name_hash = sys_hash32(name, strlen(name)) & ZMS_HASH_MASK;
547+
for (int i = 0; i <= cf->hash_collision_num; i++) {
548+
name_hash = ZMS_UPDATE_COLLISION_NUM(name_hash, i);
549+
/* Get the name entry from ZMS */
550+
rc = zms_read(&cf->cf_zms, ZMS_NAME_ID_FROM_HASH(name_hash), r_name,
551+
sizeof(r_name) - 1);
552+
if (rc <= 0) {
553+
/* Name doesn't exist */
554+
continue;
555+
}
556+
/* Found a name, this might not include a trailing \0 */
557+
r_name[rc] = '\0';
558+
if (strcmp(name, r_name)) {
559+
/* Names are not equal let's continue to the next collision hash
560+
* if it exists.
561+
*/
562+
continue;
563+
}
564+
/* At this steps the names are equal, let's read the data size*/
565+
return zms_get_data_length(&cf->cf_zms,
566+
ZMS_NAME_ID_FROM_HASH(name_hash) + ZMS_DATA_ID_OFFSET);
567+
}
568+
569+
return 0;
570+
}
571+
532572
static int settings_zms_get_last_hash_ids(struct settings_zms *cf)
533573
{
534574
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)