nvs: Check if an item is modified before writing out an identical copy
This prevents wear and tear on the flash, and it also is faster in some cases since the read-out of flash is a cheaper operation than the erasure of flash. Some library modules (such as the esp_wifi) write out to NVS upon every initialization without checking first that the existing value is the same, and this speeds up initialization of modules that make these design choices and moves it into a centralized place. The comparison functions are based on the read-out functions of the same name, and changes out the memcpy(...) operations for memcmp(...) operations. Signed-off-by: Tim Nordell <tim.nordell@nimbelink.com>
This commit is contained in:
@@ -308,6 +308,58 @@ esp_err_t Page::readItem(uint8_t nsIndex, ItemType datatype, const char* key, vo
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t Page::cmpItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize, uint8_t chunkIdx, VerOffset chunkStart)
|
||||
{
|
||||
size_t index = 0;
|
||||
Item item;
|
||||
|
||||
if (mState == PageState::INVALID) {
|
||||
return ESP_ERR_NVS_INVALID_STATE;
|
||||
}
|
||||
|
||||
esp_err_t rc = findItem(nsIndex, datatype, key, index, item, chunkIdx, chunkStart);
|
||||
if (rc != ESP_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (!isVariableLengthType(datatype)) {
|
||||
if (dataSize != getAlignmentForType(datatype)) {
|
||||
return ESP_ERR_NVS_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
if (memcmp(data, item.data, dataSize)) {
|
||||
return ESP_ERR_NVS_CONTENT_DIFFERS;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (dataSize < static_cast<size_t>(item.varLength.dataSize)) {
|
||||
return ESP_ERR_NVS_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
const uint8_t* dst = reinterpret_cast<const uint8_t*>(data);
|
||||
size_t left = item.varLength.dataSize;
|
||||
for (size_t i = index + 1; i < index + item.span; ++i) {
|
||||
Item ditem;
|
||||
rc = readEntry(i, ditem);
|
||||
if (rc != ESP_OK) {
|
||||
return rc;
|
||||
}
|
||||
size_t willCopy = ENTRY_SIZE;
|
||||
willCopy = (left < willCopy)?left:willCopy;
|
||||
if (memcmp(dst, ditem.rawData, willCopy)) {
|
||||
return ESP_ERR_NVS_CONTENT_DIFFERS;
|
||||
}
|
||||
left -= willCopy;
|
||||
dst += willCopy;
|
||||
}
|
||||
if (Item::calculateCrc32(reinterpret_cast<const uint8_t*>(data), item.varLength.dataSize) != item.varLength.dataCrc32) {
|
||||
return ESP_ERR_NVS_NOT_FOUND;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t Page::eraseItem(uint8_t nsIndex, ItemType datatype, const char* key, uint8_t chunkIdx, VerOffset chunkStart)
|
||||
{
|
||||
size_t index = 0;
|
||||
|
||||
Reference in New Issue
Block a user