Skip to content

Commit 0e3a412

Browse files
committed
settings: add an API function to load only one settings entry
Add a a function settings_load_one that allows to load only one settings entry instead of a complete subtree. Add as well its implementation for ZMS backend. This will allow a faster return if the Settings entry doesn't exist in the persistent storage. Signed-off-by: Riadh Ghaddab <[email protected]>
1 parent e7fe624 commit 0e3a412

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

include/zephyr/settings/settings.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,18 @@ int settings_load(void);
278278
*/
279279
int settings_load_subtree(const char *subtree);
280280

281+
/**
282+
* Load one serialized item from registered persistence sources.
283+
* Handlers for the serialized item registered earlier will be called for
284+
* the encountered value that corresponds to the name in the argument.
285+
*
286+
* @param[in] name Name/key of the settings item.
287+
* @param[out] buf Pointer to the buffer where the data is going to be loaded
288+
* @param[in] val_len Length of the allocated buffer.
289+
* @return number of loaded bytes on success, negative value on failure.
290+
*/
291+
int settings_load_one(const char *name, void *buf, size_t buf_len);
292+
281293
/**
282294
* Callback function used for direct loading.
283295
* Used by @ref settings_load_subtree_direct function.
@@ -457,6 +469,17 @@ struct settings_store_itf {
457469
* load callback only on the final entity.
458470
*/
459471

472+
int (*csi_load_one)(struct settings_store *cs, const char *name,
473+
char *buf, size_t buf_len);
474+
/**< Loads one value from storage that corresponds to the key defined by name.
475+
*
476+
* Parameters:
477+
* - cs - Corresponding backend handler node.
478+
* - name - Key in string format.
479+
* - buf - Buffer where data should be copied.
480+
* - buf_len - Length of buf.
481+
*/
482+
460483
int (*csi_save_start)(struct settings_store *cs);
461484
/**< Handler called before an export operation.
462485
*

subsys/settings/src/settings_store.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,31 @@ int settings_load_subtree_direct(
8888
return 0;
8989
}
9090

91+
/* Load a single key/value from persistant storage */
92+
int settings_load_one(const char *name, void *buf, size_t buf_len)
93+
{
94+
struct settings_store *cs;
95+
int rc = 0;
96+
const struct settings_load_arg arg = {
97+
.subtree = name
98+
};
99+
100+
/*
101+
* for every config store that supports this function
102+
* load config
103+
*/
104+
k_mutex_lock(&settings_lock, K_FOREVER);
105+
SYS_SLIST_FOR_EACH_CONTAINER(&settings_load_srcs, cs, cs_next) {
106+
if (cs->cs_itf->csi_load_one) {
107+
rc = cs->cs_itf->csi_load_one(cs, name, (char *)buf, buf_len);
108+
} else {
109+
rc = cs->cs_itf->csi_load(cs, &arg);
110+
}
111+
}
112+
k_mutex_unlock(&settings_lock);
113+
return rc;
114+
}
115+
91116
/*
92117
* Append a single value to persisted config. Don't store duplicate value.
93118
*/

subsys/settings/src/settings_zms.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,15 @@ struct settings_zms_read_fn_arg {
2727
};
2828

2929
static int settings_zms_load(struct settings_store *cs, const struct settings_load_arg *arg);
30+
static int settings_zms_load_one(struct settings_store *cs, const char *name, char *buf,
31+
size_t buf_len);
3032
static int settings_zms_save(struct settings_store *cs, const char *name, const char *value,
3133
size_t val_len);
3234
static void *settings_zms_storage_get(struct settings_store *cs);
3335
static int settings_zms_get_last_hash_ids(struct settings_zms *cf);
3436

3537
static struct settings_store_itf settings_zms_itf = {.csi_load = settings_zms_load,
38+
.csi_load_one = settings_zms_load_one,
3639
.csi_save = settings_zms_save,
3740
.csi_storage_get = settings_zms_storage_get};
3841

@@ -199,6 +202,45 @@ static int settings_zms_delete(struct settings_zms *cf, uint32_t name_hash)
199202
return rc;
200203
}
201204

205+
static int settings_zms_load_one(struct settings_store *cs, const char *name, char *buf,
206+
size_t buf_len)
207+
{
208+
struct settings_zms *cf = CONTAINER_OF(cs, struct settings_zms, cf_store);
209+
char r_name[SETTINGS_MAX_NAME_LEN + SETTINGS_EXTRA_LEN + 1];
210+
ssize_t rc = 0;
211+
uint32_t name_hash;
212+
213+
/* verify that name is not NULL */
214+
if (!name || !buf) {
215+
return -EINVAL;
216+
}
217+
218+
name_hash = sys_hash32(name, strlen(name)) & ZMS_HASH_MASK;
219+
for (int i = 0; i <= cf->hash_collision_num; i++) {
220+
name_hash = ZMS_UPDATE_COLLISION_NUM(name_hash, i);
221+
/* Get the name entry from ZMS */
222+
rc = zms_read(&cf->cf_zms, ZMS_NAME_ID_FROM_HASH(name_hash), r_name,
223+
sizeof(r_name) - 1);
224+
if (rc <= 0) {
225+
/* Name doesn't exist */
226+
continue;
227+
}
228+
/* Found a name, this might not include a trailing \0 */
229+
r_name[rc] = '\0';
230+
if (strcmp(name, r_name)) {
231+
/* Names are not equal let's continue to the next collision hash
232+
* if it exists.
233+
*/
234+
continue;
235+
}
236+
/* At this steps the names are equal, let's read the data */
237+
return zms_read(&cf->cf_zms, ZMS_NAME_ID_FROM_HASH(name_hash) + ZMS_DATA_ID_OFFSET,
238+
buf, buf_len);
239+
}
240+
241+
return rc;
242+
}
243+
202244
static int settings_zms_load(struct settings_store *cs, const struct settings_load_arg *arg)
203245
{
204246
int ret = 0;

0 commit comments

Comments
 (0)