This change exposes functions to erase single key and to erase all keys from namespace.
TW6769, TW6839
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
*
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)
{
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);
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);
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) {
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) {
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();
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;
}
+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)