]> granicus.if.org Git - esp-idf/commitdiff
components/nvs: add erase function
authorIvan Grokhotkov <ivan@espressif.com>
Thu, 22 Sep 2016 16:36:53 +0000 (00:36 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Fri, 23 Sep 2016 00:08:03 +0000 (08:08 +0800)
This change exposes functions to erase single key and to erase all keys from namespace.
TW6769, TW6839

components/nvs_flash/include/nvs.h
components/nvs_flash/src/nvs_api.cpp
components/nvs_flash/src/nvs_page.cpp
components/nvs_flash/src/nvs_page.hpp
components/nvs_flash/src/nvs_storage.cpp
components/nvs_flash/src/nvs_storage.hpp
components/nvs_flash/test/test_nvs.cpp

index dbcd837e17be82e7097abd4c38d721c3a425121e..bfcebc2e59b4b1812fc707e000dd19b31ded9219 100644 (file)
@@ -180,6 +180,41 @@ esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value);
 esp_err_t nvs_get_str (nvs_handle handle, const char* key, char* out_value, size_t* length);
 esp_err_t nvs_get_blob(nvs_handle handle, const char* key, void* out_value, size_t* length);
 
+/**
+ * @brief      Erase key-value pair with given key name.
+ *
+ * Note that actual storage may not be updated until nvs_commit function is called.
+ *
+ * @param[in]  handle  Storage handle obtained with nvs_open. If handle has to be
+ *                     opened as not read only for this call to succeed.
+ *
+ * @param[in]  key     Key name. Maximal length is determined by the underlying
+ *                     implementation, but is guaranteed to be at least
+ *                     16 characters. Shouldn't be empty.
+ *
+ * @return      - ESP_OK if erase operation was successful
+ *              - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
+ *              - ESP_ERR_NVS_READ_ONLY if handle was opened as read only
+ *              - ESP_ERR_NVS_NOT_FOUND if the requested key doesn't exist
+ *              - other error codes from the underlying storage driver
+ */
+esp_err_t nvs_erase_key(nvs_handle handle, const char* key);
+
+/**
+ * @brief      Erase all key-value pairs in a namespace
+ *
+ * Note that actual storage may not be updated until nvs_commit function is called.
+ *
+ * @param[in]  handle  Storage handle obtained with nvs_open. If handle has to be
+ *                     opened as not read only for this call to succeed.
+ *
+ * @return      - ESP_OK if erase operation was successful
+ *              - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL
+ *              - ESP_ERR_NVS_READ_ONLY if handle was opened as read only
+ *              - other error codes from the underlying storage driver
+ */
+esp_err_t nvs_erase_all(nvs_handle handle);
+
 /**
  * @brief      Write any pending changes to non-volatile storage
  *
index fb9faf984a276333878e2f91e8e15d178bc9b618..daa23325d27106fda6cb94ad31562422c5d43b49 100644 (file)
@@ -103,6 +103,36 @@ extern "C" void nvs_close(nvs_handle handle)
     s_nvs_handles.erase(it);
 }
 
+extern "C" esp_err_t nvs_erase_key(nvs_handle handle, const char* key)
+{
+    Lock lock;
+    NVS_DEBUGV("%s %s\r\n", __func__, key);
+    HandleEntry entry;
+    auto err = nvs_find_ns_handle(handle, entry);
+    if (err != ESP_OK) {
+        return err;
+    }
+    if (entry.mReadOnly) {
+        return ESP_ERR_NVS_READ_ONLY;
+    }
+    return s_nvs_storage.eraseItem(entry.mNsIndex, key);
+}
+
+extern "C" esp_err_t nvs_erase_all(nvs_handle handle)
+{
+    Lock lock;
+    NVS_DEBUGV("%s\r\n", __func__);
+    HandleEntry entry;
+    auto err = nvs_find_ns_handle(handle, entry);
+    if (err != ESP_OK) {
+        return err;
+    }
+    if (entry.mReadOnly) {
+        return ESP_ERR_NVS_READ_ONLY;
+    }
+    return s_nvs_storage.eraseNamespace(entry.mNsIndex);
+}
+
 template<typename T>
 static esp_err_t nvs_set(nvs_handle handle, const char* key, T value)
 {
index fed45d34da9d55bea8902701f88a6bfa3e7a802b..4f6a198c612838884a8131439363ea9627a80403 100644 (file)
@@ -278,19 +278,6 @@ esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key)
     return findItem(nsIndex, datatype, key, index, item);
 }
 
-esp_err_t Page::eraseEntry(size_t index)
-{
-    auto state = mEntryTable.get(index);
-    assert(state == EntryState::WRITTEN || state == EntryState::EMPTY);
-
-    auto rc = alterEntryState(index, EntryState::ERASED);
-    if (rc != ESP_OK) {
-        return rc;
-    }
-
-    return ESP_OK;
-}
-
 esp_err_t Page::eraseEntryAndSpan(size_t index)
 {
     auto state = mEntryTable.get(index);
index 63b1c4033a78bbb4777d2da6b2e17904f0cb3f42..c1f430cae55d02d0b50f6866eb31ba7e8a5e1f45 100644 (file)
@@ -206,8 +206,6 @@ protected:
     
     esp_err_t writeEntryData(const uint8_t* data, size_t size);
 
-    esp_err_t eraseEntry(size_t index);
-
     esp_err_t eraseEntryAndSpan(size_t index);
 
     void updateFirstUsedEntry(size_t index, size_t span);
index 7415ed62c30d4dacdf507c5f551ef1d1776c5e2b..4a217ebe18d7c0e8c549d9238b6ec58cb646f5ba 100644 (file)
@@ -69,6 +69,19 @@ esp_err_t Storage::init(uint32_t baseSector, uint32_t sectorCount)
     return ESP_OK;
 }
 
+esp_err_t Storage::findItem(uint8_t nsIndex, ItemType datatype, const char* key, Page* &page, Item& item)
+{
+    size_t itemIndex = 0;
+    for (auto it = std::begin(mPageManager); it != std::end(mPageManager); ++it) {
+        auto err = it->findItem(nsIndex, datatype, key, itemIndex, item);
+        if (err == ESP_OK) {
+            page = it;
+            return ESP_OK;
+        }
+    }
+    return ESP_ERR_NVS_NOT_FOUND;
+}
+
 esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize)
 {
     if (mState != StorageState::ACTIVE) {
@@ -202,6 +215,27 @@ esp_err_t Storage::eraseItem(uint8_t nsIndex, ItemType datatype, const char* key
     return findPage->eraseItem(nsIndex, datatype, key);
 }
 
+esp_err_t Storage::eraseNamespace(uint8_t nsIndex)
+{
+    if (mState != StorageState::ACTIVE) {
+        return ESP_ERR_NVS_NOT_INITIALIZED;
+    }
+
+    for (auto it = std::begin(mPageManager); it != std::end(mPageManager); ++it) {
+        while (true) {
+            auto err = it->eraseItem(nsIndex, ItemType::ANY, nullptr);
+            if (err == ESP_ERR_NVS_NOT_FOUND) {
+                break;
+            }
+            else if (err != ESP_OK) {
+                return err;
+            }
+        }
+    }
+    return ESP_OK;
+
+}
+
 esp_err_t Storage::getItemDataSize(uint8_t nsIndex, ItemType datatype, const char* key, size_t& dataSize)
 {
     if (mState != StorageState::ACTIVE) {
index f99e6fbbc98ae42ea38d4f68e44e569f23049953..f8cee9f2a96809abf45f8ec543b0dedd8eee8bc7 100644 (file)
@@ -69,13 +69,15 @@ public:
         return readItem(nsIndex, itemTypeOf(value), key, &value, sizeof(value));
     }
 
-    template<typename T>
     esp_err_t eraseItem(uint8_t nsIndex, const char* key)
     {
-        return eraseItem(nsIndex, itemTypeOf<T>(), key);
+        return eraseItem(nsIndex, ItemType::ANY, key);
     }
+    
+    esp_err_t eraseNamespace(uint8_t nsIndex);
 
     void debugDump();
+    
     void debugCheck();
 
 
@@ -88,19 +90,7 @@ protected:
 
     void clearNamespaces();
 
-    esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key, Page* &page, Item& item)
-    {
-        size_t itemIndex = 0;
-        for (auto it = std::begin(mPageManager); it != std::end(mPageManager); ++it) {
-            auto err = it->findItem(nsIndex, datatype, key, itemIndex, item);
-            if (err == ESP_OK) {
-                page = it;
-                return ESP_OK;
-            }
-        }
-        return ESP_ERR_NVS_NOT_FOUND;
-    }
-
+    esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key, Page* &page, Item& item);
 
 protected:
     size_t mPageCount;
index c496a09fd4c868c1a8e8e1a9eca370f37de0c3a1..540d977b4ce9762f5b1279756fc6efb921044a8b 100644 (file)
@@ -386,6 +386,27 @@ TEST_CASE("can modify an item on a page which will be erased", "[nvs]")
 }
 
 
+TEST_CASE("can erase items", "[nvs]")
+{
+    SpiFlashEmulator emu(3);
+    Storage storage;
+    CHECK(storage.init(0, 3) == ESP_OK);
+    for (size_t i = 0; i < Page::ENTRY_COUNT * 2 - 3; ++i) {
+        char name[Item::MAX_KEY_LENGTH + 1];
+        snprintf(name, sizeof(name), "key%05d", static_cast<int>(i));
+        REQUIRE(storage.writeItem(3, name, static_cast<int>(i)) == ESP_OK);
+    }
+    CHECK(storage.writeItem(1, "foo", 32) == ESP_OK);
+    CHECK(storage.writeItem(2, "foo", 64) == ESP_OK);
+    CHECK(storage.eraseItem(2, "foo") == ESP_OK);
+    int val;
+    CHECK(storage.readItem(1, "foo", val) == ESP_OK);
+    CHECK(val == 32);
+    CHECK(storage.eraseNamespace(3) == ESP_OK);
+    CHECK(storage.readItem(2, "foo", val) == ESP_ERR_NVS_NOT_FOUND);
+    CHECK(storage.readItem(3, "key00222", val) == ESP_ERR_NVS_NOT_FOUND);
+}
+
 #define TEST_ESP_ERR(rc, res) CHECK((rc) == (res))
 #define TEST_ESP_OK(rc) CHECK((rc) == ESP_OK)