Skip to content

Commit

Permalink
Feature/common storage class (project-chip#23409)
Browse files Browse the repository at this point in the history
* Moved structures from group data that could be re-used in scenes in a comon location: PersistentData.h

* Refactored the name of Iterator class to CommonIterator

Co-authored-by: Andrei Litvin <[email protected]>
  • Loading branch information
2 people authored and adbridge committed Nov 17, 2022
1 parent 392958d commit c044711
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 167 deletions.
39 changes: 6 additions & 33 deletions src/credentials/GroupDataProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CHIPError.h>
#include <lib/support/CHIPMemString.h>
#include <lib/support/CommonIterator.h>

namespace chip {
namespace Credentials {
Expand Down Expand Up @@ -186,39 +187,11 @@ class GroupDataProvider
virtual void OnGroupRemoved(FabricIndex fabric_index, const GroupInfo & old_group) = 0;
};

/**
* Template used to iterate the stored group data
*/
template <typename T>
class Iterator
{
public:
virtual ~Iterator() = default;
/**
* @retval The number of entries in total that will be iterated.
*/
virtual size_t Count() = 0;
/**
* @param[out] item Value associated with the next element in the iteration.
* @retval true if the next entry is successfully retrieved.
* @retval false if no more entries can be found.
*/
virtual bool Next(T & item) = 0;
/**
* Release the memory allocated by this iterator.
* Must be called before the pointer goes out of scope.
*/
virtual void Release() = 0;

protected:
Iterator() = default;
};

using GroupInfoIterator = Iterator<GroupInfo>;
using GroupKeyIterator = Iterator<GroupKey>;
using EndpointIterator = Iterator<GroupEndpoint>;
using KeySetIterator = Iterator<KeySet>;
using GroupSessionIterator = Iterator<GroupSession>;
using GroupInfoIterator = CommonIterator<GroupInfo>;
using GroupKeyIterator = CommonIterator<GroupKey>;
using EndpointIterator = CommonIterator<GroupEndpoint>;
using KeySetIterator = CommonIterator<KeySet>;
using GroupSessionIterator = CommonIterator<GroupSession>;

GroupDataProvider(uint16_t maxGroupsPerFabric = CHIP_CONFIG_MAX_GROUPS_PER_FABRIC,
uint16_t maxGroupKeysPerFabric = CHIP_CONFIG_MAX_GROUP_KEYS_PER_FABRIC) :
Expand Down
154 changes: 21 additions & 133 deletions src/credentials/GroupDataProviderImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CHIPTLV.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/CommonPersistentData.h>
#include <lib/support/DefaultStorageKeyAllocator.h>
#include <lib/support/PersistentData.h>
#include <lib/support/Pool.h>
#include <stdlib.h>
#include <string.h>

namespace chip {
namespace Credentials {
Expand All @@ -32,69 +33,9 @@ using GroupEndpoint = GroupDataProvider::GroupEndpoint;
using EpochKey = GroupDataProvider::EpochKey;
using KeySet = GroupDataProvider::KeySet;
using GroupSession = GroupDataProvider::GroupSession;
using FabricList = CommonPersistentData::FabricList;

static constexpr size_t kPersistentBufferMax = 128;

template <size_t kMaxSerializedSize>
struct PersistentData
{
virtual ~PersistentData() = default;

virtual CHIP_ERROR UpdateKey(StorageKeyName & key) = 0;
virtual CHIP_ERROR Serialize(TLV::TLVWriter & writer) const = 0;
virtual CHIP_ERROR Deserialize(TLV::TLVReader & reader) = 0;
virtual void Clear() = 0;

virtual CHIP_ERROR Save(PersistentStorageDelegate * storage)
{
VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT);

uint8_t buffer[kMaxSerializedSize] = { 0 };
StorageKeyName key = StorageKeyName::Uninitialized();
ReturnErrorOnFailure(UpdateKey(key));

// Serialize the data
TLV::TLVWriter writer;
writer.Init(buffer, sizeof(buffer));
ReturnErrorOnFailure(Serialize(writer));

// Save serialized data
return storage->SyncSetKeyValue(key.KeyName(), buffer, static_cast<uint16_t>(writer.GetLengthWritten()));
}

CHIP_ERROR Load(PersistentStorageDelegate * storage)
{
VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT);

uint8_t buffer[kMaxSerializedSize] = { 0 };
StorageKeyName key = StorageKeyName::Uninitialized();

// Set data to defaults
Clear();
ReturnErrorOnFailure(UpdateKey(key));

// Load the serialized data
uint16_t size = static_cast<uint16_t>(sizeof(buffer));
CHIP_ERROR err = storage->SyncGetKeyValue(key.KeyName(), buffer, size);
VerifyOrReturnError(CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND != err, CHIP_ERROR_NOT_FOUND);
ReturnErrorOnFailure(err);

// Decode serialized data
TLV::TLVReader reader;
reader.Init(buffer, size);
return Deserialize(reader);
}

virtual CHIP_ERROR Delete(PersistentStorageDelegate * storage)
{
VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT);

StorageKeyName key = StorageKeyName::Uninitialized();
ReturnErrorOnFailure(UpdateKey(key));

return storage->SyncDeleteKeyValue(key.KeyName());
}
};
constexpr size_t kPersistentBufferMax = 128;

struct LinkedData : public PersistentData<kPersistentBufferMax>
{
Expand All @@ -110,59 +51,6 @@ struct LinkedData : public PersistentData<kPersistentBufferMax>
bool first = true;
};

struct FabricList : public PersistentData<kPersistentBufferMax>
{
static constexpr TLV::Tag TagFirstFabric() { return TLV::ContextTag(1); }
static constexpr TLV::Tag TagFabricCount() { return TLV::ContextTag(2); }

chip::FabricIndex first_fabric = kUndefinedFabricIndex;
uint8_t fabric_count = 0;

FabricList() = default;
FabricList(chip::FabricIndex first) : first_fabric(first), fabric_count(1) {}

CHIP_ERROR UpdateKey(StorageKeyName & key) override
{
key = DefaultStorageKeyAllocator::GroupFabricList();
return CHIP_NO_ERROR;
}

void Clear() override
{
first_fabric = kUndefinedFabricIndex;
fabric_count = 0;
}

CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override
{
TLV::TLVType container;
ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, container));

ReturnErrorOnFailure(writer.Put(TagFirstFabric(), static_cast<uint16_t>(first_fabric)));
ReturnErrorOnFailure(writer.Put(TagFabricCount(), static_cast<uint16_t>(fabric_count)));

return writer.EndContainer(container);
}

CHIP_ERROR Deserialize(TLV::TLVReader & reader) override
{
ReturnErrorOnFailure(reader.Next(TLV::AnonymousTag()));
VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_INTERNAL);

TLV::TLVType container;
ReturnErrorOnFailure(reader.EnterContainer(container));

// first_fabric
ReturnErrorOnFailure(reader.Next(TagFirstFabric()));
ReturnErrorOnFailure(reader.Get(first_fabric));
// fabric_count
ReturnErrorOnFailure(reader.Next(TagFabricCount()));
ReturnErrorOnFailure(reader.Get(fabric_count));

return reader.ExitContainer(container);
}
};

struct FabricData : public PersistentData<kPersistentBufferMax>
{
static constexpr TLV::Tag TagFirstGroup() { return TLV::ContextTag(1); }
Expand Down Expand Up @@ -257,15 +145,15 @@ struct FabricData : public PersistentData<kPersistentBufferMax>
if (CHIP_ERROR_NOT_FOUND == err)
{
// New fabric list
fabric_list.first_fabric = fabric_index;
fabric_list.fabric_count = 1;
fabric_list.first_entry = fabric_index;
fabric_list.entry_count = 1;
return fabric_list.Save(storage);
}
ReturnErrorOnFailure(err);

// Existing fabric list, search for existing entry
FabricData fabric(fabric_list.first_fabric);
for (size_t i = 0; i < fabric_list.fabric_count; i++)
FabricData fabric(fabric_list.first_entry);
for (size_t i = 0; i < fabric_list.entry_count; i++)
{
err = fabric.Load(storage);
if (CHIP_NO_ERROR != err)
Expand All @@ -280,9 +168,9 @@ struct FabricData : public PersistentData<kPersistentBufferMax>
fabric.fabric_index = fabric.next;
}
// Add this fabric to the fabric list
this->next = fabric_list.first_fabric;
fabric_list.first_fabric = this->fabric_index;
fabric_list.fabric_count++;
this->next = fabric_list.first_entry;
fabric_list.first_entry = this->fabric_index;
fabric_list.entry_count++;
return fabric_list.Save(storage);
}

Expand All @@ -294,10 +182,10 @@ struct FabricData : public PersistentData<kPersistentBufferMax>
VerifyOrReturnError(CHIP_NO_ERROR == err || CHIP_ERROR_NOT_FOUND == err, err);

// Existing fabric list, search for existing entry
FabricData fabric(fabric_list.first_fabric);
FabricData fabric(fabric_list.first_entry);
FabricData prev;

for (size_t i = 0; i < fabric_list.fabric_count; i++)
for (size_t i = 0; i < fabric_list.entry_count; i++)
{
err = fabric.Load(storage);
if (CHIP_NO_ERROR != err)
Expand All @@ -310,16 +198,16 @@ struct FabricData : public PersistentData<kPersistentBufferMax>
if (i == 0)
{
// Remove first fabric
fabric_list.first_fabric = this->next;
fabric_list.first_entry = this->next;
}
else
{
// Remove intermediate fabric
prev.next = this->next;
ReturnErrorOnFailure(prev.Save(storage));
}
VerifyOrReturnError(fabric_list.fabric_count > 0, CHIP_ERROR_INTERNAL);
fabric_list.fabric_count--;
VerifyOrReturnError(fabric_list.entry_count > 0, CHIP_ERROR_INTERNAL);
fabric_list.entry_count--;
return fabric_list.Save(storage);
}
prev = fabric;
Expand All @@ -336,9 +224,9 @@ struct FabricData : public PersistentData<kPersistentBufferMax>
ReturnErrorOnFailure(fabric_list.Load(storage));

// Existing fabric list, search for existing entry
FabricData fabric(fabric_list.first_fabric);
FabricData fabric(fabric_list.first_entry);

for (size_t i = 0; i < fabric_list.fabric_count; i++)
for (size_t i = 0; i < fabric_list.entry_count; i++)
{
ReturnErrorOnFailure(fabric.Load(storage));
if (fabric.fabric_index == this->fabric_index)
Expand Down Expand Up @@ -1892,10 +1780,10 @@ GroupDataProviderImpl::GroupSessionIteratorImpl::GroupSessionIteratorImpl(GroupD
{
FabricList fabric_list;
ReturnOnFailure(fabric_list.Load(provider.mStorage));
mFirstFabric = fabric_list.first_fabric;
mFabric = fabric_list.first_fabric;
mFirstFabric = fabric_list.first_entry;
mFabric = fabric_list.first_entry;
mFabricCount = 0;
mFabricTotal = fabric_list.fabric_count;
mFabricTotal = fabric_list.entry_count;
mMapCount = 0;
mFirstMap = true;
}
Expand Down
55 changes: 55 additions & 0 deletions src/lib/support/CommonIterator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
*
* Copyright (c) 2022 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* @file
* Contains a standard iterator class.
*/

#pragma once

namespace chip {

/**
* Template used to generate a custom iterator
*/
template <typename T>
class CommonIterator
{
public:
virtual ~CommonIterator() = default;
/**
* @retval The number of entries in total that will be iterated.
*/
virtual size_t Count() = 0;
/**
* @param[out] item Value associated with the next element in the iteration.
* @retval true if the next entry is successfully retrieved.
* @retval false if no more entries can be found.
*/
virtual bool Next(T & item) = 0;
/**
* Release the memory allocated by this iterator.
* Must be called before the iterator goes out of scope in the iterator was dynamically allocated.
*/
virtual void Release() = 0;

protected:
CommonIterator() = default;
};

} // namespace chip
Loading

0 comments on commit c044711

Please sign in to comment.