forked from espressif/esp-idf
Merge branch 'contrib/github_pr_11118' into 'master'
nvs: support iteration over namespace by handle (GitHub PR) Closes IDFGH-9782 See merge request espressif/esp-idf!23175
This commit is contained in:
@@ -761,6 +761,21 @@ TEST_CASE("nvs iterators tests", "[nvs]")
|
|||||||
return count;
|
return count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto entry_count_handle = [](nvs_handle_t handle, nvs_type_t type)-> int {
|
||||||
|
int count = 0;
|
||||||
|
nvs_iterator_t it = nullptr;
|
||||||
|
esp_err_t res = nvs_entry_find_in_handle(handle, type, &it);
|
||||||
|
for (count = 0; res == ESP_OK; count++)
|
||||||
|
{
|
||||||
|
res = nvs_entry_next(&it);
|
||||||
|
}
|
||||||
|
CHECK(res == ESP_ERR_NVS_NOT_FOUND); // after finishing the loop or if no entry was found to begin with,
|
||||||
|
// res has to be ESP_ERR_NVS_NOT_FOUND or some internal error
|
||||||
|
// or programming error occurred
|
||||||
|
nvs_release_iterator(it); // unneccessary call but emphasizes the programming pattern
|
||||||
|
return count;
|
||||||
|
};
|
||||||
|
|
||||||
SECTION("No partition found return ESP_ERR_NVS_NOT_FOUND") {
|
SECTION("No partition found return ESP_ERR_NVS_NOT_FOUND") {
|
||||||
CHECK(nvs_entry_find("", NULL, NVS_TYPE_ANY, &it) == ESP_ERR_NVS_NOT_FOUND);
|
CHECK(nvs_entry_find("", NULL, NVS_TYPE_ANY, &it) == ESP_ERR_NVS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
@@ -805,6 +820,15 @@ TEST_CASE("nvs iterators tests", "[nvs]")
|
|||||||
CHECK(entry_count(NVS_DEFAULT_PART_NAME, NULL, NVS_TYPE_U64) == 1);
|
CHECK(entry_count(NVS_DEFAULT_PART_NAME, NULL, NVS_TYPE_U64) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SECTION("Number of entries found for specified handle and type is correct") {
|
||||||
|
CHECK(entry_count_handle(handle_1, NVS_TYPE_ANY) == 11);
|
||||||
|
CHECK(entry_count_handle(handle_1, NVS_TYPE_I32) == 3);
|
||||||
|
CHECK(entry_count_handle(handle_2, NVS_TYPE_ANY) == 4);
|
||||||
|
CHECK(entry_count_handle(handle_2, NVS_TYPE_I32) == 2);
|
||||||
|
CHECK(entry_count_handle(handle_2, NVS_TYPE_U64) == 1);
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("New entry is not created when existing key-value pair is set") {
|
SECTION("New entry is not created when existing key-value pair is set") {
|
||||||
CHECK(entry_count(NVS_DEFAULT_PART_NAME, name_2, NVS_TYPE_ANY) == 4);
|
CHECK(entry_count(NVS_DEFAULT_PART_NAME, name_2, NVS_TYPE_ANY) == 4);
|
||||||
TEST_ESP_OK(nvs_set_i32(handle_2, "value1", -222));
|
TEST_ESP_OK(nvs_set_i32(handle_2, "value1", -222));
|
||||||
|
@@ -675,14 +675,53 @@ esp_err_t nvs_entry_find(const char *part_name,
|
|||||||
nvs_type_t type,
|
nvs_type_t type,
|
||||||
nvs_iterator_t *output_iterator);
|
nvs_iterator_t *output_iterator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create an iterator to enumerate NVS entries based on a handle and type
|
||||||
|
*
|
||||||
|
* \code{c}
|
||||||
|
* // Example of listing all the key-value pairs of any type under specified handle (which defines a partition and namespace)
|
||||||
|
* nvs_iterator_t it = NULL;
|
||||||
|
* esp_err_t res = nvs_entry_find_in_handle(<nvs_handle>, NVS_TYPE_ANY, &it);
|
||||||
|
* while(res == ESP_OK) {
|
||||||
|
* nvs_entry_info_t info;
|
||||||
|
* nvs_entry_info(it, &info); // Can omit error check if parameters are guaranteed to be non-NULL
|
||||||
|
* printf("key '%s', type '%d' \n", info.key, info.type);
|
||||||
|
* res = nvs_entry_next(&it);
|
||||||
|
* }
|
||||||
|
* nvs_release_iterator(it);
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* @param[in] handle Handle obtained from nvs_open function.
|
||||||
|
*
|
||||||
|
* @param[in] type One of nvs_type_t values.
|
||||||
|
*
|
||||||
|
* @param[out] output_iterator
|
||||||
|
* Set to a valid iterator to enumerate all the entries found.
|
||||||
|
* Set to NULL if no entry for specified criteria was found.
|
||||||
|
* If any other error except ESP_ERR_INVALID_ARG occurs, \c output_iterator is NULL, too.
|
||||||
|
* If ESP_ERR_INVALID_ARG occurs, \c output_iterator is not changed.
|
||||||
|
* If a valid iterator is obtained through this function, it has to be released
|
||||||
|
* using \c nvs_release_iterator when not used any more, unless ESP_ERR_INVALID_ARG is returned.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK if no internal error or programming error occurred.
|
||||||
|
* - ESP_ERR_NVS_NOT_FOUND if no element of specified criteria has been found.
|
||||||
|
* - ESP_ERR_NO_MEM if memory has been exhausted during allocation of internal structures.
|
||||||
|
* - ESP_ERR_NVS_INVALID_HANDLE if unknown handle was specified.
|
||||||
|
* - ESP_ERR_INVALID_ARG if output_iterator parameter is NULL.
|
||||||
|
* Note: don't release \c output_iterator in case ESP_ERR_INVALID_ARG has been returned
|
||||||
|
*/
|
||||||
|
esp_err_t nvs_entry_find_in_handle(nvs_handle_t handle, nvs_type_t type, nvs_iterator_t *output_iterator);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Advances the iterator to next item matching the iterator criteria.
|
* @brief Advances the iterator to next item matching the iterator criteria.
|
||||||
*
|
*
|
||||||
* Note that any copies of the iterator will be invalid after this call.
|
* Note that any copies of the iterator will be invalid after this call.
|
||||||
*
|
*
|
||||||
* @param[inout] iterator Iterator obtained from nvs_entry_find function. Must be non-NULL.
|
* @param[inout] iterator Iterator obtained from nvs_entry_find or nvs_entry_find_in_handle
|
||||||
* If any error except ESP_ERR_INVALID_ARG occurs, \c iterator is set to NULL.
|
* function. Must be non-NULL. If any error except ESP_ERR_INVALID_ARG
|
||||||
* If ESP_ERR_INVALID_ARG occurs, \c iterator is not changed.
|
* occurs, \c iterator is set to NULL. If ESP_ERR_INVALID_ARG occurs, \c
|
||||||
|
* iterator is not changed.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK if no internal error or programming error occurred.
|
* - ESP_OK if no internal error or programming error occurred.
|
||||||
@@ -695,7 +734,8 @@ esp_err_t nvs_entry_next(nvs_iterator_t *iterator);
|
|||||||
/**
|
/**
|
||||||
* @brief Fills nvs_entry_info_t structure with information about entry pointed to by the iterator.
|
* @brief Fills nvs_entry_info_t structure with information about entry pointed to by the iterator.
|
||||||
*
|
*
|
||||||
* @param[in] iterator Iterator obtained from nvs_entry_find function. Must be non-NULL.
|
* @param[in] iterator Iterator obtained from nvs_entry_find or nvs_entry_find_in_handle
|
||||||
|
* function. Must be non-NULL.
|
||||||
*
|
*
|
||||||
* @param[out] out_info Structure to which entry information is copied.
|
* @param[out] out_info Structure to which entry information is copied.
|
||||||
*
|
*
|
||||||
@@ -708,7 +748,9 @@ esp_err_t nvs_entry_info(const nvs_iterator_t iterator, nvs_entry_info_t *out_in
|
|||||||
/**
|
/**
|
||||||
* @brief Release iterator
|
* @brief Release iterator
|
||||||
*
|
*
|
||||||
* @param[in] iterator Release iterator obtained from nvs_entry_find function. NULL argument is allowed.
|
* @param[in] iterator Release iterator obtained from nvs_entry_find or
|
||||||
|
* nvs_entry_find_in_handle or nvs_entry_next function. NULL argument is
|
||||||
|
* allowed.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void nvs_release_iterator(nvs_iterator_t iterator);
|
void nvs_release_iterator(nvs_iterator_t iterator);
|
||||||
|
@@ -786,6 +786,46 @@ extern "C" esp_err_t nvs_entry_find(const char *part_name, const char *namespace
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" esp_err_t nvs_entry_find_in_handle(nvs_handle_t handle, nvs_type_t type, nvs_iterator_t *output_iterator)
|
||||||
|
{
|
||||||
|
if (output_iterator == nullptr) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t lock_result = Lock::init();
|
||||||
|
if (lock_result != ESP_OK) {
|
||||||
|
*output_iterator = nullptr;
|
||||||
|
return lock_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lock lock;
|
||||||
|
nvs::Storage *pStorage;
|
||||||
|
NVSHandleSimple *handle_obj;
|
||||||
|
|
||||||
|
auto err = nvs_find_ns_handle(handle, &handle_obj);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
*output_iterator = nullptr;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
pStorage = handle_obj->get_storage();
|
||||||
|
nvs_iterator_t it = create_iterator(pStorage, type);
|
||||||
|
if (it == nullptr) {
|
||||||
|
*output_iterator = nullptr;
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool entryFound = handle_obj->findEntryNs(it);
|
||||||
|
if (!entryFound) {
|
||||||
|
free(it);
|
||||||
|
*output_iterator = nullptr;
|
||||||
|
return ESP_ERR_NVS_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
*output_iterator = it;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" esp_err_t nvs_entry_next(nvs_iterator_t *iterator)
|
extern "C" esp_err_t nvs_entry_next(nvs_iterator_t *iterator)
|
||||||
{
|
{
|
||||||
if (iterator == nullptr) {
|
if (iterator == nullptr) {
|
||||||
|
@@ -1,16 +1,8 @@
|
|||||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include "nvs_handle.hpp"
|
#include "nvs_handle.hpp"
|
||||||
#include "nvs_partition_manager.hpp"
|
#include "nvs_partition_manager.hpp"
|
||||||
@@ -126,6 +118,10 @@ bool NVSHandleSimple::findEntry(nvs_opaque_iterator_t* it, const char* name) {
|
|||||||
return mStoragePtr->findEntry(it, name);
|
return mStoragePtr->findEntry(it, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NVSHandleSimple::findEntryNs(nvs_opaque_iterator_t* it) {
|
||||||
|
return mStoragePtr->findEntryNs(it, mNsIndex);
|
||||||
|
}
|
||||||
|
|
||||||
bool NVSHandleSimple::nextEntry(nvs_opaque_iterator_t* it) {
|
bool NVSHandleSimple::nextEntry(nvs_opaque_iterator_t* it) {
|
||||||
return mStoragePtr->nextEntry(it);
|
return mStoragePtr->nextEntry(it);
|
||||||
}
|
}
|
||||||
@@ -134,4 +130,8 @@ const char *NVSHandleSimple::get_partition_name() const {
|
|||||||
return mStoragePtr->getPartName();
|
return mStoragePtr->getPartName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Storage *NVSHandleSimple::get_storage() const {
|
||||||
|
return mStoragePtr;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -69,10 +69,14 @@ public:
|
|||||||
|
|
||||||
bool findEntry(nvs_opaque_iterator_t *it, const char *name);
|
bool findEntry(nvs_opaque_iterator_t *it, const char *name);
|
||||||
|
|
||||||
|
bool findEntryNs(nvs_opaque_iterator_t *it);
|
||||||
|
|
||||||
bool nextEntry(nvs_opaque_iterator_t *it);
|
bool nextEntry(nvs_opaque_iterator_t *it);
|
||||||
|
|
||||||
const char *get_partition_name() const;
|
const char *get_partition_name() const;
|
||||||
|
|
||||||
|
Storage *get_storage() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* The underlying storage's object.
|
* The underlying storage's object.
|
||||||
|
@@ -782,6 +782,15 @@ bool Storage::findEntry(nvs_opaque_iterator_t* it, const char* namespace_name)
|
|||||||
return nextEntry(it);
|
return nextEntry(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Storage::findEntryNs(nvs_opaque_iterator_t* it, uint8_t nsIndex)
|
||||||
|
{
|
||||||
|
it->entryIndex = 0;
|
||||||
|
it->nsIndex = nsIndex;
|
||||||
|
it->page = mPageManager.begin();
|
||||||
|
|
||||||
|
return nextEntry(it);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool isIterableItem(Item& item)
|
inline bool isIterableItem(Item& item)
|
||||||
{
|
{
|
||||||
return (item.nsIndex != 0 &&
|
return (item.nsIndex != 0 &&
|
||||||
|
@@ -125,7 +125,9 @@ public:
|
|||||||
|
|
||||||
esp_err_t calcEntriesInNamespace(uint8_t nsIndex, size_t& usedEntries);
|
esp_err_t calcEntriesInNamespace(uint8_t nsIndex, size_t& usedEntries);
|
||||||
|
|
||||||
bool findEntry(nvs_opaque_iterator_t*, const char* name);
|
bool findEntry(nvs_opaque_iterator_t* it, const char* name);
|
||||||
|
|
||||||
|
bool findEntryNs(nvs_opaque_iterator_t* it, uint8_t nsIndex);
|
||||||
|
|
||||||
bool nextEntry(nvs_opaque_iterator_t* it);
|
bool nextEntry(nvs_opaque_iterator_t* it);
|
||||||
|
|
||||||
|
@@ -596,7 +596,6 @@ components/nvs_flash/src/nvs_cxx_api.cpp
|
|||||||
components/nvs_flash/src/nvs_encrypted_partition.hpp
|
components/nvs_flash/src/nvs_encrypted_partition.hpp
|
||||||
components/nvs_flash/src/nvs_handle_locked.cpp
|
components/nvs_flash/src/nvs_handle_locked.cpp
|
||||||
components/nvs_flash/src/nvs_handle_locked.hpp
|
components/nvs_flash/src/nvs_handle_locked.hpp
|
||||||
components/nvs_flash/src/nvs_handle_simple.cpp
|
|
||||||
components/nvs_flash/src/nvs_item_hash_list.cpp
|
components/nvs_flash/src/nvs_item_hash_list.cpp
|
||||||
components/nvs_flash/src/nvs_pagemanager.hpp
|
components/nvs_flash/src/nvs_pagemanager.hpp
|
||||||
components/nvs_flash/src/nvs_partition.cpp
|
components/nvs_flash/src/nvs_partition.cpp
|
||||||
|
Reference in New Issue
Block a user