Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Account for KVS collisions in NVM identifiers #9489

Merged
merged 4 commits into from
Nov 15, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 190 additions & 28 deletions src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,74 +26,236 @@
#include <lib/support/CHIPMem.h>
#include <platform/KeyValueStoreManager.h>
#include <platform/nxp/k32w/k32w0/K32W0Config.h>
#include <set>
#include <string>

#include "PDM.h"

#include <unordered_map>

namespace chip {
namespace DeviceLayer {
namespace PersistedStorage {

/* TODO: adjust this value */
#define MAX_NO_OF_KEYS 255
/* TODO: adjust these values */
constexpr size_t kMaxNumberOfKeys = 20;
constexpr size_t kMaxKeyValueBytes = 255;

KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance;

/* hashmap having:
* - the matter key string as key;
* - internal PDM identifier as value;
*/
std::unordered_map<std::string, uint8_t> g_kvs_map;

/* set containing used PDM identifiers */
std::set<uint8_t> g_key_ids_set;

/* used to check if we need to restore values from flash (e.g.: reset) */
static bool g_restored_from_flash = false;

CHIP_ERROR RestoreFromFlash()
{
CHIP_ERROR err = CHIP_NO_ERROR;
uint8_t key_id = 0;
char key_string_id[kMaxKeyValueBytes] = { 0 };
size_t key_string_id_size = 0;
uint8_t pdm_id_kvs = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVS;
uint16_t pdm_internal_id = 0;

if (g_restored_from_flash)
{
/* already restored from flash, nothing to do */
return err;
}

for (key_id = 0; key_id < kMaxNumberOfKeys; key_id++)
{
/* key was saved as string in flash (key_string_id) using (key_id + kMaxNumberOfKeys) as PDM key
* value corresponding to key_string_id was saved in flash using key_id as PDM key
*/

pdm_internal_id = chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id + kMaxNumberOfKeys);
err = chip::DeviceLayer::Internal::K32WConfig::ReadConfigValueStr(pdm_internal_id, key_string_id, kMaxKeyValueBytes,
key_string_id_size);

if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
{
err = CHIP_NO_ERROR;
continue;
}
else if (err != CHIP_NO_ERROR)
{
ChipLogProgress(DeviceLayer, "KVS, Error while restoring Matter key [%s] from flash with PDM id: %i", key_string_id,
pdm_internal_id);
return err;
}

if (key_string_id_size)
msandstedt marked this conversation as resolved.
Show resolved Hide resolved
{
g_key_ids_set.insert(key_id);
key_string_id_size = 0;
if (!g_kvs_map.insert(std::make_pair(std::string(key_string_id), key_id)).second)
{
/* key collision is not expected when restoring from flash */
ChipLogProgress(DeviceLayer, "KVS, Unexpected collision while restoring Matter key [%s] from flash with PDM id: %i",
key_string_id, pdm_internal_id);
}
else
{
ChipLogProgress(DeviceLayer, "KVS, restored Matter key [%s] from flash with PDM id: %i", key_string_id,
pdm_internal_id);
}
}
}

g_restored_from_flash = true;

return err;
}

CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size,
size_t offset_bytes)
{
CHIP_ERROR err = CHIP_NO_ERROR;
std::hash<std::string> hash_fn;
uint16_t key_id;
CHIP_ERROR err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
uint8_t pdm_id_kvs = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVS;
size_t read_bytes;
std::unordered_map<std::string, uint8_t>::const_iterator it;
size_t read_bytes = 0;
uint8_t key_id = 0;
uint16_t pdm_internal_id = 0;

VerifyOrExit((key != NULL) && (value != NULL), err = CHIP_ERROR_INVALID_ARGUMENT);
key_id = hash_fn(key) % MAX_NO_OF_KEYS;
VerifyOrExit((key != NULL) && (value != NULL) && (RestoreFromFlash() == CHIP_NO_ERROR), err = CHIP_ERROR_INVALID_ARGUMENT);

ChipLogProgress(DeviceLayer, "KVS, get key id:: %i", key_id);
if ((it = g_kvs_map.find(key)) != g_kvs_map.end())
{
key_id = it->second;
pdm_internal_id = chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id);

err = chip::DeviceLayer::Internal::K32WConfig::ReadConfigValueBin(
chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id), (uint8_t *) value, value_size, read_bytes);
err =
chip::DeviceLayer::Internal::K32WConfig::ReadConfigValueBin(pdm_internal_id, (uint8_t *) value, value_size, read_bytes);
*read_bytes_size = read_bytes;

*read_bytes_size = read_bytes;
ChipLogProgress(DeviceLayer, "KVS, get Matter key [%s] with PDM id: %i", key, pdm_internal_id);
}

exit:
return err;
}

CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size)
{
CHIP_ERROR err = CHIP_NO_ERROR;
std::hash<std::string> hash_fn;
uint16_t key_id;
CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT;
uint8_t key_id;
bool_t put_key = false;
uint8_t pdm_id_kvs = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVS;
std::unordered_map<std::string, uint8_t>::const_iterator it;
uint16_t pdm_internal_id = 0;

VerifyOrExit((key != NULL) && (value != NULL) && (RestoreFromFlash() == CHIP_NO_ERROR), err = CHIP_ERROR_INVALID_ARGUMENT);

if ((it = g_kvs_map.find(key)) == g_kvs_map.end()) /* new key */
{
for (key_id = 0; key_id < kMaxNumberOfKeys; key_id++)
{
std::set<uint8_t>::iterator iter = std::find(g_key_ids_set.begin(), g_key_ids_set.end(), key_id);

if (iter == g_key_ids_set.end())
{
if (g_key_ids_set.size() >= kMaxNumberOfKeys)
{
return CHIP_ERROR_NO_MEMORY;
}

g_key_ids_set.insert(key_id);

put_key = true;
break;
}
}
}
else /* overwrite key */
{
put_key = true;
key_id = it->second;
}

VerifyOrExit((key != NULL) && (value != NULL), err = CHIP_ERROR_INVALID_ARGUMENT);
key_id = hash_fn(key) % MAX_NO_OF_KEYS;
if (put_key)
{
pdm_internal_id = chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id);
ChipLogProgress(DeviceLayer, "KVS, save in flash the value of the Matter key [%s] with PDM id: %i", key, pdm_internal_id);

ChipLogProgress(DeviceLayer, "KVS, put key id:: %i", key_id);
g_kvs_map.insert(std::make_pair(std::string(key), key_id));
err = chip::DeviceLayer::Internal::K32WConfig::WriteConfigValueBin(pdm_internal_id, (uint8_t *) value, value_size);

err = chip::DeviceLayer::Internal::K32WConfig::WriteConfigValueBin(
chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id), (uint8_t *) value, value_size);
/* save the 'key' in flash such that it can be retrieved later on */
if (err == CHIP_NO_ERROR)
{
pdm_internal_id = chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id + kMaxNumberOfKeys);
ChipLogProgress(DeviceLayer, "KVS, save in flash the Matter key [%s] with PDM id: %i", key, pdm_internal_id);

err = chip::DeviceLayer::Internal::K32WConfig::WriteConfigValueStr(pdm_internal_id, key, strlen(key));

if (err != CHIP_NO_ERROR)
{
ChipLogProgress(DeviceLayer, "KVS, Error while saving in flash the Matter key [%s] with PDM id: %i", key,
pdm_internal_id);
}
}
else
{
ChipLogProgress(DeviceLayer, "KVS, Error while saving in flash the value of the Matter key [%s] with PDM id: %i", key,
pdm_internal_id);
}
}

exit:
return err;
}

CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key)
{
CHIP_ERROR err = CHIP_NO_ERROR;
std::hash<std::string> hash_fn;
uint16_t key_id;
uint8_t pdm_id_kvs = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVS;
CHIP_ERROR err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
std::unordered_map<std::string, uint8_t>::const_iterator it;
uint8_t pdm_id_kvs = chip::DeviceLayer::Internal::K32WConfig::kPDMId_KVS;
uint8_t key_id = 0;
uint16_t pdm_internal_id = 0;

VerifyOrExit((key != NULL) && (RestoreFromFlash() == CHIP_NO_ERROR), err = CHIP_ERROR_INVALID_ARGUMENT);

if ((it = g_kvs_map.find(key)) != g_kvs_map.end())
{
key_id = it->second;
pdm_internal_id = chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id);

g_key_ids_set.erase(key_id);
g_kvs_map.erase(it);

ChipLogProgress(DeviceLayer, "KVS, delete from flash the Matter key [%s] with PDM id: %i", key, pdm_internal_id);
err = chip::DeviceLayer::Internal::K32WConfig::ClearConfigValue(pdm_internal_id);

VerifyOrExit(key != NULL, err = CHIP_ERROR_INVALID_ARGUMENT);
key_id = hash_fn(key) % MAX_NO_OF_KEYS;
/* also delete the 'key string' from flash */
if (err == CHIP_NO_ERROR)
{
pdm_internal_id = chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id + kMaxNumberOfKeys);
ChipLogProgress(DeviceLayer, "KVS, delete from flash the value of the Matter key [%s] with PDM id: %i", key,
pdm_internal_id);

ChipLogProgress(DeviceLayer, "KVS, deleting key id:: %i", key_id);
err = chip::DeviceLayer::Internal::K32WConfig::ClearConfigValue(pdm_internal_id);

err = chip::DeviceLayer::Internal::K32WConfig::ClearConfigValue(chip::DeviceLayer::Internal::K32WConfigKey(pdm_id_kvs, key_id));
if (err != CHIP_NO_ERROR)
{
ChipLogProgress(DeviceLayer,
"KVS, Error while deleting from flash the value of the Matter key [%s] with PDM id: %i", key,
pdm_internal_id);
}
}
else
{
ChipLogProgress(DeviceLayer, "KVS, Error while deleting from flash the Matter key [%s] with PDM id: %i", key,
pdm_internal_id);
}
}

exit:
return err;
Expand Down