Răsfoiți Sursa

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
Radek Tandler 2 ani în urmă
părinte
comite
352e759d1d

+ 24 - 0
components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp

@@ -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));

+ 47 - 5
components/nvs_flash/include/nvs.h

@@ -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.
- *                          If any error except ESP_ERR_INVALID_ARG occurs, \c iterator is set to NULL.
- *                          If ESP_ERR_INVALID_ARG occurs, \c iterator is not changed.
+ * @param[inout]   iterator Iterator obtained from nvs_entry_find or nvs_entry_find_in_handle
+ *                          function. Must be non-NULL. If any error except ESP_ERR_INVALID_ARG
+ *                          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);

+ 40 - 0
components/nvs_flash/src/nvs_api.cpp

@@ -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) {

+ 13 - 13
components/nvs_flash/src/nvs_handle_simple.cpp

@@ -1,16 +1,8 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// 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.
+/*
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 #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;
+}
+
 }
 }

+ 4 - 0
components/nvs_flash/src/nvs_handle_simple.hpp

@@ -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.

+ 9 - 0
components/nvs_flash/src/nvs_storage.cpp

@@ -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 &&

+ 3 - 1
components/nvs_flash/src/nvs_storage.hpp

@@ -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);
 
 

+ 0 - 1
tools/ci/check_copyright_ignore.txt

@@ -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