Skip to content

Commit 37877be

Browse files
committed
settings: add new API function settings_exist()
Add a function to check if a settings key exist or not. If it exists return the length of its corresponding value. Add ZMS implementation for csi_exist() 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 0b3fe62 commit 37877be

File tree

4 files changed

+137
-3
lines changed

4 files changed

+137
-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
int settings_load_one(const char *name, void *buf, size_t buf_len);
292292

293+
/**
294+
* Check if a settings item exist in the persistent storage or not.
295+
*
296+
* @param[in] name Name/key of the settings item.
297+
* @return length of value if item exists, 0 if not and negative value on failure.
298+
*/
299+
int settings_exist(const char *name);
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+
int (*csi_exist)(struct settings_store *cs, const char *name);
492+
/**< Checks if a key defined by name exist in the storage or not and returns
493+
* its value's size.
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: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ struct default_param {
9393
size_t buf_len;
9494
};
9595

96+
/* Default callback to set a Key/Value pair */
9697
static int settings_set_default_cb(const char *name, size_t len, settings_read_cb read_cb,
9798
void *cb_arg, void *param)
9899
{
@@ -109,6 +110,55 @@ static int settings_set_default_cb(const char *name, size_t len, settings_read_c
109110
return rc;
110111
}
111112

113+
/* Default callback to check if an entry exist or not, returns its size if it exist */
114+
static int settings_exist_default_cb(const char *name, size_t len, settings_read_cb read_cb,
115+
void *cb_arg, void *param)
116+
{
117+
const char *next;
118+
size_t name_len;
119+
size_t *val_len = (size_t *)param;
120+
121+
name_len = settings_name_next(name, &next);
122+
if (name_len == 0) {
123+
*val_len = len;
124+
}
125+
126+
return 0;
127+
}
128+
129+
/* Check if a key exists in the persistant storage, if the key is found returns its size */
130+
int settings_exist(const char *name)
131+
{
132+
struct settings_store *cs;
133+
int rc = 0;
134+
size_t val_len = 0;
135+
136+
/*
137+
* for every config store that supports this function
138+
* check if the key exists
139+
*/
140+
k_mutex_lock(&settings_lock, K_FOREVER);
141+
SYS_SLIST_FOR_EACH_CONTAINER(&settings_load_srcs, cs, cs_next) {
142+
if (cs->cs_itf->csi_exist) {
143+
val_len = cs->cs_itf->csi_exist(cs, name);
144+
} else {
145+
const struct settings_load_arg arg = {
146+
.subtree = name,
147+
.cb = &settings_exist_default_cb,
148+
.param = &val_len
149+
};
150+
rc = cs->cs_itf->csi_load(cs, &arg);
151+
}
152+
}
153+
k_mutex_unlock(&settings_lock);
154+
155+
if (rc >= 0) {
156+
return val_len;
157+
}
158+
159+
return rc;
160+
}
161+
112162
/* Load a single key/value from persistant storage */
113163
int settings_load_one(const char *name, void *buf, size_t buf_len)
114164
{

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 int settings_zms_exist(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_exist = settings_zms_exist};
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 int settings_zms_exist(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+
int val_exist = 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_exist = settings_exist("ps/ss/ss/val2");
251+
zassert_true((val_exist == 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_exist = settings_exist("ps/ss/ss/val2");
257+
zassert_true((val_exist == 1), "Failure: key should exist %d", val_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_exist = settings_exist("ps/ss/val3");
293+
zassert_true((val_exist == 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_exist = settings_exist("ps/ss/val3");
299+
zassert_true((val_exist == 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_exist = settings_exist("ps/val1");
333+
zassert_true((val_exist == 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_exist = settings_exist("ps/val1");
339+
zassert_true((val_exist == 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)