Skip to content

Commit 831da04

Browse files
rghaddabkartben
authored andcommitted
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 <rghaddab@baylibre.com>
1 parent bf20b78 commit 831da04

File tree

3 files changed

+130
-0
lines changed

3 files changed

+130
-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 defines csi_load_one() function use it.
123+
* Otherwise, use the csi_load() function to load the key/value pair
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: 47 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

@@ -203,6 +206,50 @@ static int settings_zms_load_subtree(struct settings_store *cs, const struct set
203206
}
204207
#endif /* CONFIG_SETTINGS_ZMS_LOAD_SUBTREE_PATH */
205208

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

0 commit comments

Comments
 (0)