components/nvs: fix formatting
This commit is contained in:
parent
076141aab9
commit
e87d80d478
10 changed files with 89 additions and 102 deletions
|
@ -20,15 +20,15 @@
|
||||||
class HandleEntry : public intrusive_list_node<HandleEntry>
|
class HandleEntry : public intrusive_list_node<HandleEntry>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HandleEntry(){}
|
HandleEntry() {}
|
||||||
|
|
||||||
HandleEntry(nvs_handle handle, bool readOnly, uint8_t nsIndex) :
|
HandleEntry(nvs_handle handle, bool readOnly, uint8_t nsIndex) :
|
||||||
mHandle(handle),
|
mHandle(handle),
|
||||||
mReadOnly(readOnly),
|
mReadOnly(readOnly),
|
||||||
mNsIndex(nsIndex)
|
mNsIndex(nsIndex)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
nvs_handle mHandle;
|
nvs_handle mHandle;
|
||||||
uint8_t mReadOnly;
|
uint8_t mReadOnly;
|
||||||
uint8_t mNsIndex;
|
uint8_t mNsIndex;
|
||||||
|
@ -263,12 +263,10 @@ static esp_err_t nvs_get_str_or_blob(nvs_handle handle, nvs::ItemType type, cons
|
||||||
|
|
||||||
if (length == nullptr) {
|
if (length == nullptr) {
|
||||||
return ESP_ERR_NVS_INVALID_LENGTH;
|
return ESP_ERR_NVS_INVALID_LENGTH;
|
||||||
}
|
} else if (out_value == nullptr) {
|
||||||
else if (out_value == nullptr) {
|
|
||||||
*length = dataSize;
|
*length = dataSize;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
} else if (*length < dataSize) {
|
||||||
else if (*length < dataSize) {
|
|
||||||
*length = dataSize;
|
*length = dataSize;
|
||||||
return ESP_ERR_NVS_INVALID_LENGTH;
|
return ESP_ERR_NVS_INVALID_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
namespace nvs
|
namespace nvs
|
||||||
{
|
{
|
||||||
|
|
||||||
HashList::~HashList()
|
HashList::~HashList()
|
||||||
{
|
{
|
||||||
for (auto it = mBlockList.begin(); it != mBlockList.end();) {
|
for (auto it = mBlockList.begin(); it != mBlockList.end();) {
|
||||||
|
@ -26,13 +26,13 @@ HashList::~HashList()
|
||||||
delete static_cast<HashListBlock*>(tmp);
|
delete static_cast<HashListBlock*>(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HashList::HashListBlock::HashListBlock()
|
HashList::HashListBlock::HashListBlock()
|
||||||
{
|
{
|
||||||
static_assert(sizeof(HashListBlock) == HashListBlock::BYTE_SIZE,
|
static_assert(sizeof(HashListBlock) == HashListBlock::BYTE_SIZE,
|
||||||
"cache block size calculation incorrect");
|
"cache block size calculation incorrect");
|
||||||
}
|
}
|
||||||
|
|
||||||
void HashList::insert(const Item& item, size_t index)
|
void HashList::insert(const Item& item, size_t index)
|
||||||
{
|
{
|
||||||
const uint32_t hash_24 = item.calculateCrc32WithoutValue() & 0xffffff;
|
const uint32_t hash_24 = item.calculateCrc32WithoutValue() & 0xffffff;
|
||||||
|
@ -53,8 +53,7 @@ void HashList::insert(const Item& item, size_t index)
|
||||||
|
|
||||||
void HashList::erase(size_t index)
|
void HashList::erase(size_t index)
|
||||||
{
|
{
|
||||||
for (auto it = std::begin(mBlockList); it != std::end(mBlockList);)
|
for (auto it = std::begin(mBlockList); it != std::end(mBlockList);) {
|
||||||
{
|
|
||||||
bool haveEntries = false;
|
bool haveEntries = false;
|
||||||
for (size_t i = 0; i < it->mCount; ++i) {
|
for (size_t i = 0; i < it->mCount; ++i) {
|
||||||
if (it->mNodes[i].mIndex == index) {
|
if (it->mNodes[i].mIndex == index) {
|
||||||
|
@ -70,8 +69,7 @@ void HashList::erase(size_t index)
|
||||||
++it;
|
++it;
|
||||||
mBlockList.erase(tmp);
|
mBlockList.erase(tmp);
|
||||||
delete static_cast<HashListBlock*>(tmp);
|
delete static_cast<HashListBlock*>(tmp);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,13 +79,12 @@ void HashList::erase(size_t index)
|
||||||
size_t HashList::find(size_t start, const Item& item)
|
size_t HashList::find(size_t start, const Item& item)
|
||||||
{
|
{
|
||||||
const uint32_t hash_24 = item.calculateCrc32WithoutValue() & 0xffffff;
|
const uint32_t hash_24 = item.calculateCrc32WithoutValue() & 0xffffff;
|
||||||
for (auto it = std::begin(mBlockList); it != std::end(mBlockList); ++it)
|
for (auto it = std::begin(mBlockList); it != std::end(mBlockList); ++it) {
|
||||||
{
|
|
||||||
for (size_t index = 0; index < it->mCount; ++index) {
|
for (size_t index = 0; index < it->mCount; ++index) {
|
||||||
HashListNode& e = it->mNodes[index];
|
HashListNode& e = it->mNodes[index];
|
||||||
if (e.mIndex >= start &&
|
if (e.mIndex >= start &&
|
||||||
e.mHash == hash_24 &&
|
e.mHash == hash_24 &&
|
||||||
e.mIndex != 0xff) {
|
e.mIndex != 0xff) {
|
||||||
return e.mIndex;
|
return e.mIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,5 +92,5 @@ size_t HashList::find(size_t start, const Item& item)
|
||||||
return SIZE_MAX;
|
return SIZE_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace nvs
|
} // namespace nvs
|
||||||
|
|
|
@ -29,36 +29,35 @@ public:
|
||||||
void insert(const Item& item, size_t index);
|
void insert(const Item& item, size_t index);
|
||||||
void erase(const size_t index);
|
void erase(const size_t index);
|
||||||
size_t find(size_t start, const Item& item);
|
size_t find(size_t start, const Item& item);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
struct HashListNode {
|
struct HashListNode {
|
||||||
HashListNode() :
|
HashListNode() :
|
||||||
mIndex(0xff), mHash(0)
|
mIndex(0xff), mHash(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
HashListNode(uint32_t hash, size_t index) :
|
HashListNode(uint32_t hash, size_t index) :
|
||||||
mIndex((uint32_t) index), mHash(hash)
|
mIndex((uint32_t) index), mHash(hash)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t mIndex : 8;
|
uint32_t mIndex : 8;
|
||||||
uint32_t mHash : 24;
|
uint32_t mHash : 24;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HashListBlock : public intrusive_list_node<HashList::HashListBlock>
|
struct HashListBlock : public intrusive_list_node<HashList::HashListBlock> {
|
||||||
{
|
|
||||||
HashListBlock();
|
HashListBlock();
|
||||||
|
|
||||||
static const size_t BYTE_SIZE = 128;
|
static const size_t BYTE_SIZE = 128;
|
||||||
static const size_t ENTRY_COUNT = (BYTE_SIZE - sizeof(intrusive_list_node<HashListBlock>) - sizeof(size_t)) / 4;
|
static const size_t ENTRY_COUNT = (BYTE_SIZE - sizeof(intrusive_list_node<HashListBlock>) - sizeof(size_t)) / 4;
|
||||||
|
|
||||||
size_t mCount = 0;
|
size_t mCount = 0;
|
||||||
HashListNode mNodes[ENTRY_COUNT];
|
HashListNode mNodes[ENTRY_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef intrusive_list<HashListBlock> TBlockList;
|
typedef intrusive_list<HashListBlock> TBlockList;
|
||||||
TBlockList mBlockList;
|
TBlockList mBlockList;
|
||||||
}; // class HashList
|
}; // class HashList
|
||||||
|
|
|
@ -29,7 +29,7 @@ uint32_t Page::Header::calculateCrc32()
|
||||||
reinterpret_cast<uint8_t*>(this) + offsetof(Header, mSeqNumber),
|
reinterpret_cast<uint8_t*>(this) + offsetof(Header, mSeqNumber),
|
||||||
offsetof(Header, mCrc32) - offsetof(Header, mSeqNumber));
|
offsetof(Header, mCrc32) - offsetof(Header, mSeqNumber));
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t Page::load(uint32_t sectorNumber)
|
esp_err_t Page::load(uint32_t sectorNumber)
|
||||||
{
|
{
|
||||||
mBaseAddress = sectorNumber * SEC_SIZE;
|
mBaseAddress = sectorNumber * SEC_SIZE;
|
||||||
|
@ -59,15 +59,13 @@ esp_err_t Page::load(uint32_t sectorNumber)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (header.mCrc32 != header.calculateCrc32()) {
|
||||||
else if (header.mCrc32 != header.calculateCrc32()) {
|
|
||||||
header.mState = PageState::CORRUPT;
|
header.mState = PageState::CORRUPT;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
mState = header.mState;
|
mState = header.mState;
|
||||||
mSeqNumber = header.mSeqNumber;
|
mSeqNumber = header.mSeqNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mState) {
|
switch (mState) {
|
||||||
case PageState::UNINITIALIZED:
|
case PageState::UNINITIALIZED:
|
||||||
break;
|
break;
|
||||||
|
@ -172,7 +170,7 @@ esp_err_t Page::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, c
|
||||||
size_t span = (totalSize + ENTRY_SIZE - 1) / ENTRY_SIZE;
|
size_t span = (totalSize + ENTRY_SIZE - 1) / ENTRY_SIZE;
|
||||||
item = Item(nsIndex, datatype, span, key);
|
item = Item(nsIndex, datatype, span, key);
|
||||||
mHashList.insert(item, mNextFreeEntry);
|
mHashList.insert(item, mNextFreeEntry);
|
||||||
|
|
||||||
if (datatype != ItemType::SZ && datatype != ItemType::BLOB) {
|
if (datatype != ItemType::SZ && datatype != ItemType::BLOB) {
|
||||||
memcpy(item.data, data, dataSize);
|
memcpy(item.data, data, dataSize);
|
||||||
item.crc32 = item.calculateCrc32();
|
item.crc32 = item.calculateCrc32();
|
||||||
|
@ -208,6 +206,7 @@ esp_err_t Page::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, c
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
@ -283,21 +282,21 @@ esp_err_t Page::eraseEntry(size_t index)
|
||||||
{
|
{
|
||||||
auto state = mEntryTable.get(index);
|
auto state = mEntryTable.get(index);
|
||||||
assert(state == EntryState::WRITTEN || state == EntryState::EMPTY);
|
assert(state == EntryState::WRITTEN || state == EntryState::EMPTY);
|
||||||
|
|
||||||
auto rc = alterEntryState(index, EntryState::ERASED);
|
auto rc = alterEntryState(index, EntryState::ERASED);
|
||||||
if (rc != ESP_OK) {
|
if (rc != ESP_OK) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t Page::eraseEntryAndSpan(size_t index)
|
esp_err_t Page::eraseEntryAndSpan(size_t index)
|
||||||
{
|
{
|
||||||
auto state = mEntryTable.get(index);
|
auto state = mEntryTable.get(index);
|
||||||
assert(state == EntryState::WRITTEN || state == EntryState::EMPTY);
|
assert(state == EntryState::WRITTEN || state == EntryState::EMPTY);
|
||||||
mHashList.erase(index);
|
mHashList.erase(index);
|
||||||
|
|
||||||
size_t span = 1;
|
size_t span = 1;
|
||||||
if (state == EntryState::WRITTEN) {
|
if (state == EntryState::WRITTEN) {
|
||||||
Item item;
|
Item item;
|
||||||
|
@ -327,8 +326,7 @@ esp_err_t Page::eraseEntryAndSpan(size_t index)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
auto rc = alterEntryState(index, EntryState::ERASED);
|
auto rc = alterEntryState(index, EntryState::ERASED);
|
||||||
if (rc != ESP_OK) {
|
if (rc != ESP_OK) {
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -338,7 +336,7 @@ esp_err_t Page::eraseEntryAndSpan(size_t index)
|
||||||
if (index == mFirstUsedEntry) {
|
if (index == mFirstUsedEntry) {
|
||||||
updateFirstUsedEntry(index, span);
|
updateFirstUsedEntry(index, span);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index + span > mNextFreeEntry) {
|
if (index + span > mNextFreeEntry) {
|
||||||
mNextFreeEntry = index + span;
|
mNextFreeEntry = index + span;
|
||||||
}
|
}
|
||||||
|
@ -361,7 +359,7 @@ void Page::updateFirstUsedEntry(size_t index, size_t span)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t Page::moveItem(Page& other)
|
esp_err_t Page::moveItem(Page& other)
|
||||||
{
|
{
|
||||||
if (mFirstUsedEntry == INVALID_ENTRY) {
|
if (mFirstUsedEntry == INVALID_ENTRY) {
|
||||||
|
@ -371,7 +369,7 @@ esp_err_t Page::moveItem(Page& other)
|
||||||
if (mFindInfo.itemIndex() == mFirstUsedEntry) {
|
if (mFindInfo.itemIndex() == mFirstUsedEntry) {
|
||||||
invalidateCache();
|
invalidateCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other.mState == PageState::UNINITIALIZED) {
|
if (other.mState == PageState::UNINITIALIZED) {
|
||||||
auto err = other.initialize();
|
auto err = other.initialize();
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
|
@ -392,9 +390,9 @@ esp_err_t Page::moveItem(Page& other)
|
||||||
|
|
||||||
size_t span = entry.span;
|
size_t span = entry.span;
|
||||||
size_t end = mFirstUsedEntry + span;
|
size_t end = mFirstUsedEntry + span;
|
||||||
|
|
||||||
assert(mFirstUsedEntry != INVALID_ENTRY || span == 1);
|
assert(mFirstUsedEntry != INVALID_ENTRY || span == 1);
|
||||||
|
|
||||||
for (size_t i = mFirstUsedEntry + 1; i < end; ++i) {
|
for (size_t i = mFirstUsedEntry + 1; i < end; ++i) {
|
||||||
readEntry(i, entry);
|
readEntry(i, entry);
|
||||||
err = other.writeEntry(entry);
|
err = other.writeEntry(entry);
|
||||||
|
@ -485,7 +483,7 @@ esp_err_t Page::mLoadEntryTable()
|
||||||
lastItemIndex = INVALID_ENTRY;
|
lastItemIndex = INVALID_ENTRY;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastItemIndex = i;
|
lastItemIndex = i;
|
||||||
|
|
||||||
auto err = readEntry(i, item);
|
auto err = readEntry(i, item);
|
||||||
|
@ -502,7 +500,7 @@ esp_err_t Page::mLoadEntryTable()
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
mHashList.insert(item, i);
|
mHashList.insert(item, i);
|
||||||
|
|
||||||
if (item.datatype != ItemType::BLOB && item.datatype != ItemType::SZ) {
|
if (item.datatype != ItemType::BLOB && item.datatype != ItemType::SZ) {
|
||||||
|
@ -523,7 +521,7 @@ esp_err_t Page::mLoadEntryTable()
|
||||||
}
|
}
|
||||||
i += span - 1;
|
i += span - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that last item is not duplicate
|
// check that last item is not duplicate
|
||||||
if (lastItemIndex != INVALID_ENTRY) {
|
if (lastItemIndex != INVALID_ENTRY) {
|
||||||
size_t findItemIndex = 0;
|
size_t findItemIndex = 0;
|
||||||
|
@ -538,8 +536,7 @@ esp_err_t Page::mLoadEntryTable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (mState == PageState::FULL || mState == PageState::FREEING) {
|
||||||
else if (mState == PageState::FULL || mState == PageState::FREEING) {
|
|
||||||
// We have already filled mHashList for page in active state.
|
// We have already filled mHashList for page in active state.
|
||||||
// Do the same for the case when page is in full or freeing state.
|
// Do the same for the case when page is in full or freeing state.
|
||||||
Item item;
|
Item item;
|
||||||
|
@ -547,15 +544,15 @@ esp_err_t Page::mLoadEntryTable()
|
||||||
if (mEntryTable.get(i) != EntryState::WRITTEN) {
|
if (mEntryTable.get(i) != EntryState::WRITTEN) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto err = readEntry(i, item);
|
auto err = readEntry(i, item);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
mState = PageState::INVALID;
|
mState = PageState::INVALID;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
mHashList.insert(item, i);
|
mHashList.insert(item, i);
|
||||||
|
|
||||||
size_t span = item.span;
|
size_t span = item.span;
|
||||||
i += span - 1;
|
i += span - 1;
|
||||||
}
|
}
|
||||||
|
@ -574,7 +571,7 @@ esp_err_t Page::initialize()
|
||||||
header.mState = mState;
|
header.mState = mState;
|
||||||
header.mSeqNumber = mSeqNumber;
|
header.mSeqNumber = mSeqNumber;
|
||||||
header.mCrc32 = header.calculateCrc32();
|
header.mCrc32 = header.calculateCrc32();
|
||||||
|
|
||||||
auto rc = spi_flash_write(mBaseAddress, reinterpret_cast<uint32_t*>(&header), sizeof(header));
|
auto rc = spi_flash_write(mBaseAddress, reinterpret_cast<uint32_t*>(&header), sizeof(header));
|
||||||
if (rc != ESP_OK) {
|
if (rc != ESP_OK) {
|
||||||
mState = PageState::INVALID;
|
mState = PageState::INVALID;
|
||||||
|
@ -651,7 +648,7 @@ esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, si
|
||||||
if (mState == PageState::CORRUPT || mState == PageState::INVALID || mState == PageState::UNINITIALIZED) {
|
if (mState == PageState::CORRUPT || mState == PageState::INVALID || mState == PageState::UNINITIALIZED) {
|
||||||
return ESP_ERR_NVS_NOT_FOUND;
|
return ESP_ERR_NVS_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemIndex >= ENTRY_COUNT) {
|
if (itemIndex >= ENTRY_COUNT) {
|
||||||
return ESP_ERR_NVS_NOT_FOUND;
|
return ESP_ERR_NVS_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
@ -665,22 +662,21 @@ esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, si
|
||||||
if (itemIndex > mFirstUsedEntry && itemIndex < ENTRY_COUNT) {
|
if (itemIndex > mFirstUsedEntry && itemIndex < ENTRY_COUNT) {
|
||||||
start = itemIndex;
|
start = itemIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t end = mNextFreeEntry;
|
size_t end = mNextFreeEntry;
|
||||||
if (end > ENTRY_COUNT) {
|
if (end > ENTRY_COUNT) {
|
||||||
end = ENTRY_COUNT;
|
end = ENTRY_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nsIndex != NS_ANY && datatype != ItemType::ANY && key != NULL) {
|
if (nsIndex != NS_ANY && datatype != ItemType::ANY && key != NULL) {
|
||||||
size_t cachedIndex = mHashList.find(start, Item(nsIndex, datatype, 0, key));
|
size_t cachedIndex = mHashList.find(start, Item(nsIndex, datatype, 0, key));
|
||||||
if (cachedIndex < ENTRY_COUNT) {
|
if (cachedIndex < ENTRY_COUNT) {
|
||||||
start = cachedIndex;
|
start = cachedIndex;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return ESP_ERR_NVS_NOT_FOUND;
|
return ESP_ERR_NVS_NOT_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t next;
|
size_t next;
|
||||||
for (size_t i = start; i < end; i = next) {
|
for (size_t i = start; i < end; i = next) {
|
||||||
next = i + 1;
|
next = i + 1;
|
||||||
|
@ -783,7 +779,7 @@ void Page::invalidateCache()
|
||||||
{
|
{
|
||||||
mFindInfo = CachedFindInfo();
|
mFindInfo = CachedFindInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Page::debugDump() const
|
void Page::debugDump() const
|
||||||
{
|
{
|
||||||
printf("state=%x addr=%x seq=%d\nfirstUsed=%d nextFree=%d used=%d erased=%d\n", mState, mBaseAddress, mSeqNumber, static_cast<int>(mFirstUsedEntry), static_cast<int>(mNextFreeEntry), mUsedEntryCount, mErasedEntryCount);
|
printf("state=%x addr=%x seq=%d\nfirstUsed=%d nextFree=%d used=%d erased=%d\n", mState, mBaseAddress, mSeqNumber, static_cast<int>(mFirstUsedEntry), static_cast<int>(mNextFreeEntry), mUsedEntryCount, mErasedEntryCount);
|
||||||
|
@ -793,18 +789,15 @@ void Page::debugDump() const
|
||||||
EntryState state = mEntryTable.get(i);
|
EntryState state = mEntryTable.get(i);
|
||||||
if (state == EntryState::EMPTY) {
|
if (state == EntryState::EMPTY) {
|
||||||
printf("E\n");
|
printf("E\n");
|
||||||
}
|
} else if (state == EntryState::ERASED) {
|
||||||
else if (state == EntryState::ERASED) {
|
|
||||||
printf("X\n");
|
printf("X\n");
|
||||||
}
|
} else if (state == EntryState::WRITTEN) {
|
||||||
else if (state == EntryState::WRITTEN) {
|
|
||||||
Item item;
|
Item item;
|
||||||
readEntry(i, item);
|
readEntry(i, item);
|
||||||
if (skip == 0) {
|
if (skip == 0) {
|
||||||
printf("W ns=%2u type=%2u span=%3u key=\"%s\"\n", item.nsIndex, static_cast<unsigned>(item.datatype), item.span, item.key);
|
printf("W ns=%2u type=%2u span=%3u key=\"%s\"\n", item.nsIndex, static_cast<unsigned>(item.datatype), item.span, item.key);
|
||||||
skip = item.span - 1;
|
skip = item.span - 1;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
printf("D\n");
|
printf("D\n");
|
||||||
skip--;
|
skip--;
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,25 +162,27 @@ public:
|
||||||
esp_err_t erase();
|
esp_err_t erase();
|
||||||
|
|
||||||
void invalidateCache();
|
void invalidateCache();
|
||||||
|
|
||||||
void debugDump() const;
|
void debugDump() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
class Header {
|
class Header
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
Header() {
|
Header()
|
||||||
|
{
|
||||||
std::fill_n(mReserved, sizeof(mReserved)/sizeof(mReserved[0]), UINT32_MAX);
|
std::fill_n(mReserved, sizeof(mReserved)/sizeof(mReserved[0]), UINT32_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
PageState mState; // page state
|
PageState mState; // page state
|
||||||
uint32_t mSeqNumber; // sequence number of this page
|
uint32_t mSeqNumber; // sequence number of this page
|
||||||
uint32_t mReserved[5]; // unused, must be 0xffffffff
|
uint32_t mReserved[5]; // unused, must be 0xffffffff
|
||||||
uint32_t mCrc32; // crc of everything except mState
|
uint32_t mCrc32; // crc of everything except mState
|
||||||
|
|
||||||
uint32_t calculateCrc32();
|
uint32_t calculateCrc32();
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class EntryState {
|
enum class EntryState {
|
||||||
EMPTY = 0x3, // 0b11, default state after flash erase
|
EMPTY = 0x3, // 0b11, default state after flash erase
|
||||||
WRITTEN = EMPTY & ~ESB_WRITTEN, // entry was written
|
WRITTEN = EMPTY & ~ESB_WRITTEN, // entry was written
|
||||||
|
@ -205,9 +207,9 @@ protected:
|
||||||
esp_err_t writeEntryData(const uint8_t* data, size_t size);
|
esp_err_t writeEntryData(const uint8_t* data, size_t size);
|
||||||
|
|
||||||
esp_err_t eraseEntry(size_t index);
|
esp_err_t eraseEntry(size_t index);
|
||||||
|
|
||||||
esp_err_t eraseEntryAndSpan(size_t index);
|
esp_err_t eraseEntryAndSpan(size_t index);
|
||||||
|
|
||||||
void updateFirstUsedEntry(size_t index, size_t span);
|
void updateFirstUsedEntry(size_t index, size_t span);
|
||||||
|
|
||||||
static constexpr size_t getAlignmentForType(ItemType type)
|
static constexpr size_t getAlignmentForType(ItemType type)
|
||||||
|
|
|
@ -47,13 +47,12 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount)
|
||||||
if (mPageList.empty()) {
|
if (mPageList.empty()) {
|
||||||
mSeqNumber = 0;
|
mSeqNumber = 0;
|
||||||
return activatePage();
|
return activatePage();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
uint32_t lastSeqNo;
|
uint32_t lastSeqNo;
|
||||||
assert(mPageList.back().getSeqNumber(lastSeqNo) == ESP_OK);
|
assert(mPageList.back().getSeqNumber(lastSeqNo) == ESP_OK);
|
||||||
mSeqNumber = lastSeqNo + 1;
|
mSeqNumber = lastSeqNo + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if power went out after a new item for the given key was written,
|
// if power went out after a new item for the given key was written,
|
||||||
// but before the old one was erased, we end up with a duplicate item
|
// but before the old one was erased, we end up with a duplicate item
|
||||||
Page& lastPage = back();
|
Page& lastPage = back();
|
||||||
|
@ -64,7 +63,7 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount)
|
||||||
itemIndex += item.span;
|
itemIndex += item.span;
|
||||||
lastItemIndex = itemIndex;
|
lastItemIndex = itemIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastItemIndex != SIZE_MAX) {
|
if (lastItemIndex != SIZE_MAX) {
|
||||||
auto last = PageManager::TPageListIterator(&lastPage);
|
auto last = PageManager::TPageListIterator(&lastPage);
|
||||||
for (auto it = begin(); it != last; ++it) {
|
for (auto it = begin(); it != last; ++it) {
|
||||||
|
@ -78,7 +77,7 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount)
|
||||||
for (auto it = begin(); it!= end(); ++it) {
|
for (auto it = begin(); it!= end(); ++it) {
|
||||||
if (it->state() == Page::PageState::FREEING) {
|
if (it->state() == Page::PageState::FREEING) {
|
||||||
Page* newPage = &mPageList.back();
|
Page* newPage = &mPageList.back();
|
||||||
if(newPage->state() != Page::PageState::ACTIVE) {
|
if (newPage->state() != Page::PageState::ACTIVE) {
|
||||||
auto err = activatePage();
|
auto err = activatePage();
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
|
@ -93,12 +92,12 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto err = it->erase();
|
auto err = it->erase();
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
Page* p = static_cast<Page*>(it);
|
Page* p = static_cast<Page*>(it);
|
||||||
mPageList.erase(it);
|
mPageList.erase(it);
|
||||||
mFreePageList.push_back(p);
|
mFreePageList.push_back(p);
|
||||||
|
@ -139,7 +138,7 @@ esp_err_t PageManager::requestNewPage()
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
Page* newPage = &mPageList.back();
|
Page* newPage = &mPageList.back();
|
||||||
|
|
||||||
Page* erasedPage = maxErasedItemsPageIt;
|
Page* erasedPage = maxErasedItemsPageIt;
|
||||||
|
@ -161,7 +160,7 @@ esp_err_t PageManager::requestNewPage()
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(usedEntries == newPage->getUsedEntryCount());
|
assert(usedEntries == newPage->getUsedEntryCount());
|
||||||
|
|
||||||
mPageList.erase(maxErasedItemsPageIt);
|
mPageList.erase(maxErasedItemsPageIt);
|
||||||
|
@ -188,5 +187,5 @@ esp_err_t PageManager::activatePage()
|
||||||
++mSeqNumber;
|
++mSeqNumber;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace nvs
|
} // namespace nvs
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Iterator;
|
friend class Iterator;
|
||||||
|
|
||||||
esp_err_t activatePage();
|
esp_err_t activatePage();
|
||||||
|
|
||||||
TPageList mPageList;
|
TPageList mPageList;
|
||||||
|
|
|
@ -51,7 +51,7 @@ esp_err_t Storage::init(uint32_t baseSector, uint32_t sectorCount)
|
||||||
Page& p = *it;
|
Page& p = *it;
|
||||||
size_t itemIndex = 0;
|
size_t itemIndex = 0;
|
||||||
Item item;
|
Item item;
|
||||||
while(p.findItem(Page::NS_INDEX, ItemType::U8, nullptr, itemIndex, item) == ESP_OK) {
|
while (p.findItem(Page::NS_INDEX, ItemType::U8, nullptr, itemIndex, item) == ESP_OK) {
|
||||||
NamespaceEntry* entry = new NamespaceEntry;
|
NamespaceEntry* entry = new NamespaceEntry;
|
||||||
item.getKey(entry->mName, sizeof(entry->mName) - 1);
|
item.getKey(entry->mName, sizeof(entry->mName) - 1);
|
||||||
item.getValue(entry->mIndex);
|
item.getValue(entry->mIndex);
|
||||||
|
@ -103,14 +103,13 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
} else if (err != ESP_OK) {
|
||||||
else if (err != ESP_OK) {
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (findPage) {
|
if (findPage) {
|
||||||
if (findPage->state() == Page::PageState::UNINITIALIZED ||
|
if (findPage->state() == Page::PageState::UNINITIALIZED ||
|
||||||
findPage->state() == Page::PageState::INVALID) {
|
findPage->state() == Page::PageState::INVALID) {
|
||||||
auto err = findItem(nsIndex, datatype, key, findPage, item);
|
auto err = findItem(nsIndex, datatype, key, findPage, item);
|
||||||
assert(err == ESP_OK);
|
assert(err == ESP_OK);
|
||||||
}
|
}
|
||||||
|
@ -158,7 +157,7 @@ esp_err_t Storage::createOrOpenNamespace(const char* nsName, bool canCreate, uin
|
||||||
}
|
}
|
||||||
mNamespaceUsage.set(ns, true);
|
mNamespaceUsage.set(ns, true);
|
||||||
nsIndex = ns;
|
nsIndex = ns;
|
||||||
|
|
||||||
NamespaceEntry* entry = new NamespaceEntry;
|
NamespaceEntry* entry = new NamespaceEntry;
|
||||||
entry->mIndex = ns;
|
entry->mIndex = ns;
|
||||||
strncpy(entry->mName, nsName, sizeof(entry->mName) - 1);
|
strncpy(entry->mName, nsName, sizeof(entry->mName) - 1);
|
||||||
|
|
|
@ -74,7 +74,7 @@ public:
|
||||||
{
|
{
|
||||||
return eraseItem(nsIndex, itemTypeOf<T>(), key);
|
return eraseItem(nsIndex, itemTypeOf<T>(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void debugDump();
|
void debugDump();
|
||||||
void debugCheck();
|
void debugCheck();
|
||||||
|
|
||||||
|
|
|
@ -76,9 +76,9 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
static const size_t MAX_KEY_LENGTH = sizeof(key) - 1;
|
static const size_t MAX_KEY_LENGTH = sizeof(key) - 1;
|
||||||
|
|
||||||
Item(uint8_t nsIndex, ItemType datatype, uint8_t span, const char* key_)
|
Item(uint8_t nsIndex, ItemType datatype, uint8_t span, const char* key_)
|
||||||
: nsIndex(nsIndex), datatype(datatype), span(span), reserved(0xff)
|
: nsIndex(nsIndex), datatype(datatype), span(span), reserved(0xff)
|
||||||
{
|
{
|
||||||
std::fill_n(reinterpret_cast<uint32_t*>(key), sizeof(key) / 4, 0xffffffff);
|
std::fill_n(reinterpret_cast<uint32_t*>(key), sizeof(key) / 4, 0xffffffff);
|
||||||
std::fill_n(reinterpret_cast<uint32_t*>(data), sizeof(data) / 4, 0xffffffff);
|
std::fill_n(reinterpret_cast<uint32_t*>(data), sizeof(data) / 4, 0xffffffff);
|
||||||
|
@ -89,7 +89,7 @@ public:
|
||||||
key[0] = 0;
|
key[0] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item()
|
Item()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue