Skip to content

Commit 2fea30c

Browse files
committed
[nrf fromlist] 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. Upstream PR #: 87792 Signed-off-by: Riadh Ghaddab <[email protected]>
1 parent 8edad98 commit 2fea30c

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed

include/zephyr/settings/settings.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,17 @@ 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+
*
284+
* @param[in] name Name/key of the settings item.
285+
* @param[out] buf Pointer to the buffer where the data is going to be loaded
286+
* @param[in] buf_len Length of the allocated buffer.
287+
* @return actual size of value that corresponds to name on success, negative
288+
* value on failure.
289+
*/
290+
ssize_t settings_load_one(const char *name, void *buf, size_t buf_len);
291+
281292
/**
282293
* Callback function used for direct loading.
283294
* Used by @ref settings_load_subtree_direct function.
@@ -457,6 +468,17 @@ struct settings_store_itf {
457468
* load callback only on the final entity.
458469
*/
459470

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

subsys/settings/src/settings_store.c

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

91+
struct default_param {
92+
void *buf;
93+
size_t buf_len;
94+
size_t *val_len;
95+
};
96+
97+
static int settings_set_default_cb(const char *name, size_t len, settings_read_cb read_cb,
98+
void *cb_arg, void *param)
99+
{
100+
int rc = 0;
101+
const char *next;
102+
size_t name_len;
103+
struct default_param *dest = (struct default_param *)param;
104+
105+
name_len = settings_name_next(name, &next);
106+
if (name_len == 0) {
107+
rc = read_cb(cb_arg, dest->buf, MIN(dest->buf_len, len));
108+
*dest->val_len = len;
109+
}
110+
111+
return rc;
112+
}
113+
114+
/* Load a single key/value from persistent storage */
115+
ssize_t settings_load_one(const char *name, void *buf, size_t buf_len)
116+
{
117+
struct settings_store *cs;
118+
size_t val_len = 0;
119+
int rc = 0;
120+
121+
/*
122+
* for every config store that supports this function
123+
* load config
124+
*/
125+
k_mutex_lock(&settings_lock, K_FOREVER);
126+
SYS_SLIST_FOR_EACH_CONTAINER(&settings_load_srcs, cs, cs_next) {
127+
if (cs->cs_itf->csi_load_one) {
128+
rc = cs->cs_itf->csi_load_one(cs, name, (char *)buf, buf_len);
129+
val_len = (rc >= 0) ? rc : 0;
130+
} else {
131+
struct default_param param = {
132+
.buf = buf,
133+
.buf_len = buf_len,
134+
.val_len = &val_len
135+
};
136+
const struct settings_load_arg arg = {
137+
.subtree = name,
138+
.cb = &settings_set_default_cb,
139+
.param = &param
140+
};
141+
rc = cs->cs_itf->csi_load(cs, &arg);
142+
}
143+
}
144+
k_mutex_unlock(&settings_lock);
145+
146+
if (rc >= 0) {
147+
return val_len;
148+
}
149+
return rc;
150+
}
151+
91152
/*
92153
* Append a single value to persisted config. Don't store duplicate value.
93154
*/

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 ssize_t 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 ssize_t 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)