Skip to content

Commit ae46151

Browse files
rghaddabkartben
authored andcommitted
settings: zms: load only subtree in the argument
If the subtree argument is not NULL in the settings_load function, load only the setting entry that corresponds to that subtree. If the subtree argument is NULL or it is not found in the storage, load all the existing entries in the storage. Signed-off-by: Riadh Ghaddab <[email protected]>
1 parent 5c38c58 commit ae46151

File tree

3 files changed

+71
-1
lines changed

3 files changed

+71
-1
lines changed

subsys/settings/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ config SETTINGS_ZMS_NO_LL_DELETE
182182
These nodes will be used again when the same Settings element that has
183183
been deleted is created again.
184184

185+
config SETTINGS_ZMS_LOAD_SUBTREE_PATH
186+
bool "Load only subtree path if provided"
187+
help
188+
Loads first the key defined by the subtree path.
189+
If the callback handler returns a zero value it will
190+
continue to look for all the keys under that subtree path.
191+
If the callback handler returns a non negative value, it
192+
returns immeditaley.
193+
185194
config SETTINGS_SHELL
186195
bool "Settings shell"
187196
depends on SHELL

subsys/settings/include/settings/settings_zms.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ extern "C" {
6565
#define ZMS_NAME_ID_FROM_LL_NODE(x) (x & ~BIT(0))
6666
#define ZMS_UPDATE_COLLISION_NUM(x, y) \
6767
((x & ~ZMS_COLLISIONS_MASK) | ((y << 1) & ZMS_COLLISIONS_MASK))
68-
#define ZMS_COLLISION_NUM(x) ((x & ZMS_COLLISIONS_MASK) >> 1)
68+
#define ZMS_COLLISION_NUM(x) ((x & ZMS_COLLISIONS_MASK) >> 1)
69+
#define ZMS_NAME_ID_FROM_HASH(x) ((x & ZMS_HASH_TOTAL_MASK) | BIT(31))
6970

7071
struct settings_zms {
7172
struct settings_store cf_store;

subsys/settings/src/settings_zms.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,56 @@ static int settings_zms_delete(struct settings_zms *cf, uint32_t name_hash)
150150
return rc;
151151
}
152152

153+
#ifdef CONFIG_SETTINGS_ZMS_LOAD_SUBTREE_PATH
154+
/* Loads first the key which is defined by the name found in "subtree" root.
155+
* If the key is not found or further keys under the same subtree are needed
156+
* by the caller, returns 0.
157+
*/
158+
static int settings_zms_load_subtree(struct settings_store *cs, const struct settings_load_arg *arg)
159+
{
160+
struct settings_zms *cf = CONTAINER_OF(cs, struct settings_zms, cf_store);
161+
struct settings_zms_read_fn_arg read_fn_arg;
162+
char name[SETTINGS_MAX_NAME_LEN + SETTINGS_EXTRA_LEN + 1];
163+
ssize_t rc1;
164+
ssize_t rc2;
165+
uint32_t name_hash;
166+
167+
name_hash = sys_hash32(arg->subtree, strlen(arg->subtree)) & ZMS_HASH_MASK;
168+
for (int i = 0; i <= cf->hash_collision_num; i++) {
169+
name_hash = ZMS_UPDATE_COLLISION_NUM(name_hash, i);
170+
/* Get the name entry from ZMS */
171+
rc1 = zms_read(&cf->cf_zms, ZMS_NAME_ID_FROM_HASH(name_hash), &name,
172+
sizeof(name) - 1);
173+
/* get the length of data and verify that it exists */
174+
rc2 = zms_get_data_length(&cf->cf_zms,
175+
ZMS_NAME_ID_FROM_HASH(name_hash) + ZMS_DATA_ID_OFFSET);
176+
if ((rc1 <= 0) || (rc2 <= 0)) {
177+
/* Name or data doesn't exist */
178+
continue;
179+
}
180+
/* Found a name, this might not include a trailing \0 */
181+
name[rc1] = '\0';
182+
if (strcmp(arg->subtree, name)) {
183+
/* Names are not equal let's continue to the next collision hash
184+
* if it exists.
185+
*/
186+
continue;
187+
}
188+
/* At this steps the names are equal, let's set the handler */
189+
read_fn_arg.fs = &cf->cf_zms;
190+
read_fn_arg.id = ZMS_NAME_ID_FROM_HASH(name_hash) + ZMS_DATA_ID_OFFSET;
191+
192+
/* We should return here as there is no need to look for the next
193+
* hash collision
194+
*/
195+
return settings_call_set_handler(arg->subtree, rc2, settings_zms_read_fn, &read_fn_arg,
196+
(void *)arg);
197+
}
198+
199+
return 0;
200+
}
201+
#endif /* CONFIG_SETTINGS_ZMS_LOAD_SUBTREE_PATH */
202+
153203
static int settings_zms_load(struct settings_store *cs, const struct settings_load_arg *arg)
154204
{
155205
int ret = 0;
@@ -160,6 +210,15 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
160210
ssize_t rc1;
161211
ssize_t rc2;
162212
uint32_t ll_hash_id;
213+
#ifdef CONFIG_SETTINGS_ZMS_LOAD_SUBTREE_PATH
214+
/* If arg->subtree is not null we must first load settings in that subtree */
215+
if (arg->subtree != NULL) {
216+
ret = settings_zms_load_subtree(cs, arg);
217+
if (ret) {
218+
return ret;
219+
}
220+
}
221+
#endif /* CONFIG_SETTINGS_ZMS_LOAD_SUBTREE_PATH */
163222

164223
ret = zms_read(&cf->cf_zms, ZMS_LL_HEAD_HASH_ID, &settings_element,
165224
sizeof(struct settings_hash_linked_list));
@@ -168,6 +227,7 @@ static int settings_zms_load(struct settings_store *cs, const struct settings_lo
168227
}
169228
ll_hash_id = settings_element.next_hash;
170229

230+
/* If subtree is NULL then we must load all found Settings */
171231
while (ll_hash_id) {
172232

173233
/* In the ZMS backend, each setting item is stored in two ZMS

0 commit comments

Comments
 (0)