diff --git a/src/app/SafeAttributePersistenceProvider.h b/src/app/SafeAttributePersistenceProvider.h index b1e7148c79b1bb..ddf7d630da0532 100644 --- a/src/app/SafeAttributePersistenceProvider.h +++ b/src/app/SafeAttributePersistenceProvider.h @@ -71,7 +71,7 @@ class SafeAttributePersistenceProvider * Read an attribute of type intX, uintX or bool from non-volatile memory. * * @param [in] aPath the attribute path for the data being persisted. - * @param [in,out] aValue where to place the data. + * @param [out] aValue where to place the data. * * @retval CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND if no stored value exists for the attribute */ @@ -112,7 +112,7 @@ class SafeAttributePersistenceProvider * Read an attribute of type nullable intX, uintX from non-volatile memory. * * @param [in] aPath the attribute path for the data being persisted. - * @param [in,out] aValue where to place the data. + * @param [out] aValue where to place the data. * * @retval CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND if no stored value exists for the attribute */ diff --git a/src/app/clusters/scenes-server/SceneTable.h b/src/app/clusters/scenes-server/SceneTable.h index ea4137c748237d..4430ec54ae436d 100644 --- a/src/app/clusters/scenes-server/SceneTable.h +++ b/src/app/clusters/scenes-server/SceneTable.h @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -233,7 +232,7 @@ class SceneTable SceneTable & operator=(const SceneTable &) = delete; - virtual CHIP_ERROR Init(PersistentStorageDelegate * storage) = 0; + virtual CHIP_ERROR Init(PersistentStorageDelegate & storage) = 0; virtual void Finish() = 0; // Global scene count diff --git a/src/app/clusters/scenes-server/SceneTableImpl.cpp b/src/app/clusters/scenes-server/SceneTableImpl.cpp index 86585397ca240f..91ee39e10a6d69 100644 --- a/src/app/clusters/scenes-server/SceneTableImpl.cpp +++ b/src/app/clusters/scenes-server/SceneTableImpl.cpp @@ -48,7 +48,7 @@ StorageKeyName Serializer::FabricEntryDataKey(FabricIndex fabric, EndpointId end // Worst case tested: Add Scene Command with EFS using the default SerializeAdd Method. This yielded a serialized scene of 175 bytes // when using the OnOff, Level Control and Color Control as well as the maximal name length of 16 bytes. Putting 256 gives some -// slack in case different clusters are used. Value obtained by using writer.GetLengthWritten at the end of the SceneTableData +// slack in case different clusters are used. Value obtained by using writer.GetLengthWritten at the end of the Serializer // Serialize method. template <> constexpr size_t Serializer::kEntryMaxBytes() @@ -83,7 +83,7 @@ namespace { /// kGroupId: Tag for GroupID if the Scene is a Group Scene /// kSceneId: Tag for the scene ID. Together with kGroupId, forms the SceneStorageId /// kName: Tag for the name of the scene -/// kTransitionTime: Tag for the transition time of the scene in miliseconds +/// kTransitionTime: Tag for the transition time of the scene in milliseconds enum class TagScene : uint8_t { kGroupId = static_cast(TagEntry::kFabricTableFirstSpecializationReservedTag), @@ -93,13 +93,12 @@ enum class TagScene : uint8_t }; } // namespace -using SceneTableData = TableEntryData; using FabricSceneData = FabricEntryData; template class chip::app::Storage::FabricTableImpl; -CHIP_ERROR DefaultSceneTableImpl::Init(PersistentStorageDelegate * storage) +CHIP_ERROR DefaultSceneTableImpl::Init(PersistentStorageDelegate & storage) { return FabricTableImpl::Init(storage); } @@ -156,7 +155,6 @@ CHIP_ERROR DefaultSceneTableImpl::GetAllSceneIdsInGroup(FabricIndex fabric_index VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL); FabricSceneData fabric(mEndpointId, fabric_index, mMaxPerFabric, mMaxPerEndpoint); - SceneTableData scene(mEndpointId, fabric_index); uint8_t scene_count = 0; CHIP_ERROR err = fabric.Load(this->mStorage); @@ -190,7 +188,6 @@ CHIP_ERROR DefaultSceneTableImpl::DeleteAllScenesInGroup(FabricIndex fabric_inde VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL); FabricSceneData fabric(mEndpointId, fabric_index, mMaxPerFabric, mMaxPerEndpoint); - SceneTableData scene(mEndpointId, fabric_index); CHIP_ERROR err = fabric.Load(this->mStorage); VerifyOrReturnValue(CHIP_ERROR_NOT_FOUND != err, CHIP_NO_ERROR); diff --git a/src/app/clusters/scenes-server/SceneTableImpl.h b/src/app/clusters/scenes-server/SceneTableImpl.h index 839c04facd1551..0608232b6d3e3f 100644 --- a/src/app/clusters/scenes-server/SceneTableImpl.h +++ b/src/app/clusters/scenes-server/SceneTableImpl.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -61,7 +60,7 @@ class DefaultSceneTableImpl DefaultSceneTableImpl() : Super(kMaxScenesPerFabric, kMaxScenesPerEndpoint) {} ~DefaultSceneTableImpl() { Finish(); }; - CHIP_ERROR Init(PersistentStorageDelegate * storage) override; + CHIP_ERROR Init(PersistentStorageDelegate & storage) override; void Finish() override; // Scene count diff --git a/src/app/clusters/scenes-server/scenes-server.cpp b/src/app/clusters/scenes-server/scenes-server.cpp index 2ddfded4ac0900..b5dfb958e179cd 100644 --- a/src/app/clusters/scenes-server/scenes-server.cpp +++ b/src/app/clusters/scenes-server/scenes-server.cpp @@ -333,7 +333,7 @@ CHIP_ERROR ScenesServer::Init() mGroupProvider = Credentials::GetGroupDataProvider(); SceneTable * sceneTable = scenes::GetSceneTableImpl(); - ReturnErrorOnFailure(sceneTable->Init(&Server::GetInstance().GetPersistentStorage())); + ReturnErrorOnFailure(sceneTable->Init(Server::GetInstance().GetPersistentStorage())); ReturnErrorOnFailure(Server::GetInstance().GetFabricTable().AddFabricDelegate(&gFabricDelegate)); mIsInitialized = true; diff --git a/src/app/icd/server/ICDMonitoringTable.cpp b/src/app/icd/server/ICDMonitoringTable.cpp index a6adddde2e7404..267f6f5f841a48 100644 --- a/src/app/icd/server/ICDMonitoringTable.cpp +++ b/src/app/icd/server/ICDMonitoringTable.cpp @@ -30,7 +30,7 @@ enum class Fields : uint8_t kClientType = 5, }; -CHIP_ERROR ICDMonitoringEntry::UpdateKey(StorageKeyName & skey) +CHIP_ERROR ICDMonitoringEntry::UpdateKey(StorageKeyName & skey) const { VerifyOrReturnError(kUndefinedFabricIndex != this->fabricIndex, CHIP_ERROR_INVALID_FABRIC_INDEX); skey = DefaultStorageKeyAllocator::ICDManagementTableEntry(this->fabricIndex, index); diff --git a/src/app/icd/server/ICDMonitoringTable.h b/src/app/icd/server/ICDMonitoringTable.h index dca9fd21972341..e58745c73572e2 100644 --- a/src/app/icd/server/ICDMonitoringTable.h +++ b/src/app/icd/server/ICDMonitoringTable.h @@ -68,7 +68,7 @@ struct ICDMonitoringEntry : public PersistentData this->symmetricKeystore = keyStore; } - CHIP_ERROR UpdateKey(StorageKeyName & key) override; + CHIP_ERROR UpdateKey(StorageKeyName & key) const override; CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override; CHIP_ERROR Deserialize(TLV::TLVReader & reader) override; void Clear() override; diff --git a/src/app/storage/FabricTableImpl.h b/src/app/storage/FabricTableImpl.h index 03493f860b28fd..adf022eaf4ab42 100644 --- a/src/app/storage/FabricTableImpl.h +++ b/src/app/storage/FabricTableImpl.h @@ -17,6 +17,9 @@ #pragma once +#include +#include +#include #include namespace chip { @@ -41,7 +44,7 @@ class FabricTableImpl public: virtual ~FabricTableImpl() { Finish(); }; - CHIP_ERROR Init(PersistentStorageDelegate * storage); + CHIP_ERROR Init(PersistentStorageDelegate & storage); void Finish(); // Entry count diff --git a/src/app/storage/FabricTableImpl.ipp b/src/app/storage/FabricTableImpl.ipp index 7de5ff06ae30e0..ffd39033ca0b0b 100644 --- a/src/app/storage/FabricTableImpl.ipp +++ b/src/app/storage/FabricTableImpl.ipp @@ -61,7 +61,7 @@ struct EndpointEntryCount : public PersistentData -struct TableEntryData : public Data::TableEntry, PersistentData +template +struct TableEntryData : DataAccessor { using Serializer = DefaultSerializer; using TableEntry = Data::TableEntry; @@ -110,18 +110,13 @@ struct TableEntryData : public Data::TableEntry, Persist FabricIndex fabric_index = kUndefinedFabricIndex; EntryIndex index = 0; bool first = true; + Data::TableEntry & mEntry; - TableEntryData(EndpointId endpoint, FabricIndex fabric, EntryIndex idx = 0) : - endpoint_id(endpoint), fabric_index(fabric), index(idx) - {} - TableEntryData(EndpointId endpoint, FabricIndex fabric, StorageId storageId) : - TableEntry(storageId), endpoint_id(endpoint), fabric_index(fabric) - {} - TableEntryData(EndpointId endpoint, FabricIndex fabric, StorageId storageId, StorageData data) : - TableEntry(storageId, data), endpoint_id(endpoint), fabric_index(fabric) + TableEntryData(EndpointId endpoint, FabricIndex fabric, TableEntry & entry, EntryIndex idx = 0) : + endpoint_id(endpoint), fabric_index(fabric), index(idx), mEntry(entry) {} - CHIP_ERROR UpdateKey(StorageKeyName & key) override + CHIP_ERROR UpdateKey(StorageKeyName & key) const override { VerifyOrReturnError(kUndefinedFabricIndex != fabric_index, CHIP_ERROR_INVALID_FABRIC_INDEX); VerifyOrReturnError(kInvalidEndpointId != endpoint_id, CHIP_ERROR_INVALID_ARGUMENT); @@ -129,16 +124,16 @@ struct TableEntryData : public Data::TableEntry, Persist return CHIP_NO_ERROR; } - void Clear() override { this->mStorageData.Clear(); } + void Clear() override { this->mEntry.mStorageData.Clear(); } CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override { TLV::TLVType container; ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, container)); - ReturnErrorOnFailure(Serializer::SerializeId(writer, this->mStorageId)); + ReturnErrorOnFailure(Serializer::SerializeId(writer, this->mEntry.mStorageId)); - ReturnErrorOnFailure(Serializer::SerializeData(writer, this->mStorageData)); + ReturnErrorOnFailure(Serializer::SerializeData(writer, this->mEntry.mStorageData)); return writer.EndContainer(container); } @@ -150,9 +145,9 @@ struct TableEntryData : public Data::TableEntry, Persist TLV::TLVType container; ReturnErrorOnFailure(reader.EnterContainer(container)); - ReturnErrorOnFailure(Serializer::DeserializeId(reader, this->mStorageId)); + ReturnErrorOnFailure(Serializer::DeserializeId(reader, this->mEntry.mStorageId)); - ReturnErrorOnFailure(Serializer::DeserializeData(reader, this->mStorageData)); + ReturnErrorOnFailure(Serializer::DeserializeData(reader, this->mEntry.mStorageData)); return reader.ExitContainer(container); } @@ -167,7 +162,8 @@ template { using Serializer = DefaultSerializer; - using TypedTableEntryData = TableEntryData; + using TypedTableEntryData = TableEntryData; + using Store = PersistentStore; using TableEntry = typename TypedTableEntryData::TableEntry; using TypedEndpointEntryCount = EndpointEntryCount; @@ -184,7 +180,7 @@ struct FabricEntryData : public PersistentData fabric_index(fabric), max_per_fabric(maxPerFabric), max_per_endpoint(maxPerEndpoint) {} - CHIP_ERROR UpdateKey(StorageKeyName & key) override + CHIP_ERROR UpdateKey(StorageKeyName & key) const override { VerifyOrReturnError(kUndefinedFabricIndex != fabric_index, CHIP_ERROR_INVALID_FABRIC_INDEX); VerifyOrReturnError(kInvalidEndpointId != endpoint_id, CHIP_ERROR_INVALID_ARGUMENT); @@ -254,6 +250,8 @@ struct FabricEntryData : public PersistentData CHIP_ERROR err; deleted_entries_count = 0; + TableEntry unused; + Store persistentStore; while ((err = reader.Next(TLV::AnonymousTag())) == CHIP_NO_ERROR) { TLV::TLVType entryIdContainer; @@ -265,11 +263,11 @@ struct FabricEntryData : public PersistentData } else { - TypedTableEntryData entry(endpoint_id, fabric_index, i); + TypedTableEntryData entry(endpoint_id, fabric_index, unused, i); ReturnErrorOnFailure(reader.EnterContainer(entryIdContainer)); ReturnErrorOnFailure(Serializer::DeserializeId(reader, entry_map[i])); ReturnErrorOnFailure(reader.ExitContainer(entryIdContainer)); - ReturnErrorOnFailure(entry.Delete(storage)); + ReturnErrorOnFailure(persistentStore.Delete(entry, storage)); deleted_entries_count++; } @@ -318,14 +316,18 @@ struct FabricEntryData : public PersistentData CHIP_ERROR SaveEntry(PersistentStorageDelegate * storage, const TableEntry & src_entry) { CHIP_ERROR err = CHIP_NO_ERROR; - TypedTableEntryData entry(endpoint_id, fabric_index, src_entry.mStorageId, src_entry.mStorageData); // Look for empty storage space - err = this->Find(entry.mStorageId, entry.index); + EntryIndex index; + err = this->Find(src_entry.mStorageId, index); + + Store persistentStore; + // C++ doesn't have const constructors; variable is declared const + const TypedTableEntryData entry(endpoint_id, fabric_index, const_cast(src_entry), index); if (CHIP_NO_ERROR == err) { - return entry.Save(storage); + return persistentStore.Save(entry, storage); } if (CHIP_ERROR_NOT_FOUND == err) // If not found, entry.index should be the first free index @@ -338,7 +340,7 @@ struct FabricEntryData : public PersistentData ReturnErrorOnFailure(endpoint_count.Save(storage)); entry_count++; - entry_map[entry.index] = entry.mStorageId; + entry_map[entry.index] = src_entry.mStorageId; err = this->Save(storage); if (CHIP_NO_ERROR != err) @@ -348,7 +350,7 @@ struct FabricEntryData : public PersistentData return err; } - err = entry.Save(storage); + err = persistentStore.Save(entry, storage); // on failure to save the entry, undoes the changes to Fabric Entry Data if (CHIP_NO_ERROR != err) @@ -368,14 +370,15 @@ struct FabricEntryData : public PersistentData /// @brief Removes an entry from the non-volatile memory and clears its index in the entry map. Decreases the number of entries /// in the global entry count and in the entry fabric data if successful. As the entry map size is not compressed upon removal, - /// this only clears the entry correpsonding to the entry from the entry map. + /// this only clears the entry corresponding to the entry from the entry map. /// @param storage Storage delegate to access the entry /// @param entry_id Entry to remove /// @return CHIP_NO_ERROR if successful, specific CHIP_ERROR otherwise CHIP_ERROR RemoveEntry(PersistentStorageDelegate * storage, const StorageId & entry_id) { CHIP_ERROR err = CHIP_NO_ERROR; - TypedTableEntryData entry(endpoint_id, fabric_index, entry_id); + TableEntry id_holder(entry_id); + TypedTableEntryData entry(endpoint_id, fabric_index, id_holder); // Empty Entry Fabric Data returns CHIP_NO_ERROR on remove if (entry_count > 0) @@ -401,7 +404,7 @@ struct FabricEntryData : public PersistentData return err; } - err = entry.Delete(storage); + err = Store().Delete(entry, storage); // On failure to delete entry, undo the change to the Fabric Entry Data and the global entry count if (CHIP_NO_ERROR != err) @@ -410,7 +413,7 @@ struct FabricEntryData : public PersistentData ReturnErrorOnFailure(endpoint_entry_count.Save(storage)); entry_count++; - entry_map[entry.index] = entry.mStorageId; + entry_map[entry.index] = id_holder.mStorageId; ReturnErrorOnFailure(this->Save(storage)); return err; } @@ -461,18 +464,13 @@ struct FabricEntryData : public PersistentData }; template -CHIP_ERROR FabricTableImpl::Init(PersistentStorageDelegate * storage) +CHIP_ERROR FabricTableImpl::Init(PersistentStorageDelegate & storage) { using Serializer = DefaultSerializer; - if (storage == nullptr) - { - return CHIP_ERROR_INCORRECT_STATE; - } - // Verify the initialized parameter respects the maximum allowed values for entry capacity VerifyOrReturnError(mMaxPerFabric <= Serializer::kMaxPerFabric() && mMaxPerEndpoint <= Serializer::kMaxPerEndpoint(), CHIP_ERROR_INVALID_INTEGER_VALUE); - this->mStorage = storage; + this->mStorage = &storage; return CHIP_NO_ERROR; } @@ -589,19 +587,17 @@ CHIP_ERROR FabricTableImpl::GetTableEntry using Serializer = DefaultSerializer; using TypedFabricEntryData = FabricEntryData; - using TypedTableEntryData = TableEntryData; - VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL); TypedFabricEntryData fabric(mEndpointId, fabric_index, mMaxPerFabric, mMaxPerEndpoint); - TypedTableEntryData table_entry(mEndpointId, fabric_index); + TableEntryData table_entry(mEndpointId, fabric_index, entry); ReturnErrorOnFailure(fabric.Load(mStorage)); VerifyOrReturnError(fabric.Find(entry_id, table_entry.index) == CHIP_NO_ERROR, CHIP_ERROR_NOT_FOUND); - CHIP_ERROR err = table_entry.Load(mStorage); + CHIP_ERROR err = PersistentStore().Load(table_entry, mStorage); - // If entry.Load returns "buffer too small", the entry in memory is too big to be retrieve (this could happen if the + // If entry.Load returns "buffer too small", the entry in memory is too big to be retrieved (this could happen if the // kEntryMaxBytes was reduced by OTA) and therefore must be deleted as is is no longer considered accessible. if (err == CHIP_ERROR_BUFFER_TOO_SMALL) { @@ -609,9 +605,6 @@ CHIP_ERROR FabricTableImpl::GetTableEntry } ReturnErrorOnFailure(err); - entry.mStorageId = table_entry.mStorageId; - entry.mStorageData = table_entry.mStorageData; - return CHIP_NO_ERROR; } @@ -643,20 +636,20 @@ CHIP_ERROR FabricTableImpl::RemoveTableEn using Serializer = DefaultSerializer; using TypedFabricEntryData = FabricEntryData; - using TypedTableEntryData = TableEntryData; VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL); CHIP_ERROR err = CHIP_NO_ERROR; TypedFabricEntryData fabric(endpoint, fabric_index, mMaxPerFabric, mMaxPerEndpoint); - TypedTableEntryData entry(endpoint, fabric_index, entry_idx); + TableEntry loadedEntry; + TableEntryData entry(endpoint, fabric_index, loadedEntry, entry_idx); ReturnErrorOnFailure(fabric.Load(mStorage)); - err = entry.Load(mStorage); + err = PersistentStore().Load(entry, mStorage); VerifyOrReturnValue(CHIP_ERROR_NOT_FOUND != err, CHIP_NO_ERROR); ReturnErrorOnFailure(err); - return fabric.RemoveEntry(mStorage, entry.mStorageId); + return fabric.RemoveEntry(mStorage, loadedEntry.mStorageId); } template @@ -778,22 +771,19 @@ bool FabricTableImpl::EntryIteratorImpl:: using Serializer = DefaultSerializer; using TypedFabricEntryData = FabricEntryData; - using TypedTableEntryData = TableEntryData; TypedFabricEntryData fabric(mEndpoint, mFabric); - TypedTableEntryData entry(mEndpoint, mFabric); VerifyOrReturnError(fabric.Load(mProvider.mStorage) == CHIP_NO_ERROR, false); // looks for next available entry + PersistentStore persistentStore; while (mEntryIndex < mMaxPerFabric) { if (fabric.entry_map[mEntryIndex].IsValid()) { - entry.index = mEntryIndex; - VerifyOrReturnError(entry.Load(mProvider.mStorage) == CHIP_NO_ERROR, false); - output.mStorageId = entry.mStorageId; - output.mStorageData = entry.mStorageData; + TableEntryData entry(mEndpoint, mFabric, output, mEntryIndex); + VerifyOrReturnError(persistentStore.Load(entry, mProvider.mStorage) == CHIP_NO_ERROR, false); mEntryIndex++; return true; diff --git a/src/app/tests/TestSceneTable.cpp b/src/app/tests/TestSceneTable.cpp index 38e2e19220f13d..f804736f50b841 100644 --- a/src/app/tests/TestSceneTable.cpp +++ b/src/app/tests/TestSceneTable.cpp @@ -684,7 +684,7 @@ class TestSceneTable : public ::testing::Test // Initialize Scene Table SceneTable * sceneTable = scenes::GetSceneTableImpl(); ASSERT_NE(sceneTable, nullptr); - ASSERT_EQ(sceneTable->Init(mpTestStorage), CHIP_NO_ERROR); + ASSERT_EQ(sceneTable->Init(*mpTestStorage), CHIP_NO_ERROR); SetMockNodeConfig(SceneMockNodeConfig); } @@ -696,6 +696,8 @@ class TestSceneTable : public ::testing::Test sceneTable->Finish(); delete mpTestStorage; delete mpSceneHandler; + mpTestStorage = nullptr; + mpSceneHandler = nullptr; chip::Platform::MemoryShutdown(); } @@ -2118,6 +2120,7 @@ TEST_F(TestSceneTable, TestOTAChanges) { SceneTable * sceneTable = scenes::GetSceneTableImpl(kTestEndpoint1, defaultTestTableSize); ASSERT_NE(nullptr, sceneTable); + ASSERT_NE(nullptr, mpTestStorage); // Reset test ResetSceneTable(sceneTable); @@ -2163,7 +2166,7 @@ TEST_F(TestSceneTable, TestOTAChanges) // Create a scene table with a greater capacity than the original one (Max allowed capacity from gen_config.h) TestSceneTableImpl ExpandedSceneTable(scenes::kMaxScenesPerFabric, scenes::kMaxScenesPerEndpoint); - EXPECT_EQ(CHIP_NO_ERROR, ExpandedSceneTable.Init(mpTestStorage)); + EXPECT_EQ(CHIP_NO_ERROR, ExpandedSceneTable.Init(*mpTestStorage)); ExpandedSceneTable.SetEndpoint(kTestEndpoint1); EXPECT_EQ(CHIP_NO_ERROR, ExpandedSceneTable.GetRemainingCapacity(kFabric1, fabric_capacity)); @@ -2201,11 +2204,11 @@ TEST_F(TestSceneTable, TestOTAChanges) // Test failure to init a SceneTable with sizes above the defined max scenes per fabric or globaly TestSceneTableImpl SceneTableTooManyPerFabric(scenes::kMaxScenesPerFabric + 1, scenes::kMaxScenesPerEndpoint); - EXPECT_EQ(CHIP_ERROR_INVALID_INTEGER_VALUE, SceneTableTooManyPerFabric.Init(mpTestStorage)); + EXPECT_EQ(CHIP_ERROR_INVALID_INTEGER_VALUE, SceneTableTooManyPerFabric.Init(*mpTestStorage)); SceneTableTooManyPerFabric.Finish(); TestSceneTableImpl SceneTableTooManyGlobal(scenes::kMaxScenesPerFabric, scenes::kMaxScenesPerEndpoint + 1); - EXPECT_EQ(CHIP_ERROR_INVALID_INTEGER_VALUE, SceneTableTooManyGlobal.Init(mpTestStorage)); + EXPECT_EQ(CHIP_ERROR_INVALID_INTEGER_VALUE, SceneTableTooManyGlobal.Init(*mpTestStorage)); SceneTableTooManyGlobal.Finish(); // Create a new table with a lower limit of scenes per fabric @@ -2213,7 +2216,7 @@ TEST_F(TestSceneTable, TestOTAChanges) uint8_t newTableSize = defaultTestTableSize - 2; uint8_t capacityDifference = static_cast(scenes::kMaxScenesPerFabric - newCapacity); TestSceneTableImpl ReducedSceneTable(newCapacity, newTableSize); - EXPECT_EQ(CHIP_NO_ERROR, ReducedSceneTable.Init(mpTestStorage)); + EXPECT_EQ(CHIP_NO_ERROR, ReducedSceneTable.Init(*mpTestStorage)); ReducedSceneTable.SetEndpoint(kTestEndpoint1); // Global count should not have been modified diff --git a/src/credentials/GroupDataProviderImpl.cpp b/src/credentials/GroupDataProviderImpl.cpp index 3b9be9482b2587..987f1107afc740 100644 --- a/src/credentials/GroupDataProviderImpl.cpp +++ b/src/credentials/GroupDataProviderImpl.cpp @@ -36,7 +36,7 @@ using GroupSession = GroupDataProvider::GroupSession; struct FabricList : public CommonPersistentData::FabricList { - CHIP_ERROR UpdateKey(StorageKeyName & key) override + CHIP_ERROR UpdateKey(StorageKeyName & key) const override { key = DefaultStorageKeyAllocator::GroupFabricList(); return CHIP_NO_ERROR; @@ -81,7 +81,7 @@ struct FabricData : public PersistentData FabricData() = default; FabricData(chip::FabricIndex fabric) : fabric_index(fabric) {} - CHIP_ERROR UpdateKey(StorageKeyName & key) override + CHIP_ERROR UpdateKey(StorageKeyName & key) const override { VerifyOrReturnError(kUndefinedFabricIndex != fabric_index, CHIP_ERROR_INVALID_FABRIC_INDEX); key = DefaultStorageKeyAllocator::FabricGroups(fabric_index); @@ -279,7 +279,7 @@ struct GroupData : public GroupDataProvider::GroupInfo, PersistentData fabric_index(fabric), keyset_id(id), policy(policy_id), keys_count(num_keys) {} - CHIP_ERROR UpdateKey(StorageKeyName & key) override + CHIP_ERROR UpdateKey(StorageKeyName & key) const override { VerifyOrReturnError(kUndefinedFabricIndex != fabric_index, CHIP_ERROR_INVALID_FABRIC_INDEX); VerifyOrReturnError(kInvalidKeysetId != keyset_id, CHIP_ERROR_INVALID_KEY_ID); diff --git a/src/lib/support/PersistentData.h b/src/lib/support/PersistentData.h index 20286d41e6642e..96c905b590b71e 100644 --- a/src/lib/support/PersistentData.h +++ b/src/lib/support/PersistentData.h @@ -21,53 +21,53 @@ #include namespace chip { - -/// @brief Interface to Persistent Storage Delegate allowing storage of data of variable size such as TLV. -/// @tparam kMaxSerializedSize size of the mBuffer necessary to retrieve an entry from the storage. Varies with the type of data -/// stored. Will be allocated on the stack so the implementation needs to be aware of this when choosing this value. -template -struct PersistentData +/// @brief Data accessor allowing data to be persisted by PersistentStore to be accessed +struct DataAccessor { - PersistentData(PersistentStorageDelegate * storage = nullptr) : mStorage(storage) {} - virtual ~PersistentData() = default; - - virtual CHIP_ERROR UpdateKey(StorageKeyName & key) = 0; + virtual ~DataAccessor() = default; + virtual CHIP_ERROR UpdateKey(StorageKeyName & key) const = 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() { return this->Save(this->mStorage); } +/// @brief Interface to PersistentStorageDelegate allowing storage of data of variable size such as TLV, delegating data access +/// to DataAccessor +/// @tparam kMaxSerializedSize size of the mBuffer necessary to retrieve an entry from the storage. Varies with the type of data +/// stored. Will be allocated on the stack so the implementation needs to be aware of this when choosing this value. +template +struct PersistentStore +{ + virtual ~PersistentStore() = default; - virtual CHIP_ERROR Save(PersistentStorageDelegate * storage) + CHIP_ERROR Save(const DataAccessor & persistent, PersistentStorageDelegate * storage) { VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT); StorageKeyName key = StorageKeyName::Uninitialized(); - ReturnErrorOnFailure(UpdateKey(key)); + ReturnErrorOnFailure(persistent.UpdateKey(key)); // Serialize the data TLV::TLVWriter writer; writer.Init(mBuffer, sizeof(mBuffer)); - ReturnErrorOnFailure(Serialize(writer)); + ReturnErrorOnFailure(persistent.Serialize(writer)); // Save serialized data return storage->SyncSetKeyValue(key.KeyName(), mBuffer, static_cast(writer.GetLengthWritten())); } - virtual CHIP_ERROR Load() { return this->Load(this->mStorage); } - - virtual CHIP_ERROR Load(PersistentStorageDelegate * storage) + CHIP_ERROR Load(DataAccessor & persistent, PersistentStorageDelegate * storage) { VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT); StorageKeyName key = StorageKeyName::Uninitialized(); // Update storage key - ReturnErrorOnFailure(UpdateKey(key)); + ReturnErrorOnFailure(persistent.UpdateKey(key)); // Set data to defaults - Clear(); + persistent.Clear(); // Load the serialized data uint16_t size = static_cast(sizeof(mBuffer)); @@ -78,21 +78,42 @@ struct PersistentData // Decode serialized data TLV::TLVReader reader; reader.Init(mBuffer, size); - return Deserialize(reader); + return persistent.Deserialize(reader); } - virtual CHIP_ERROR Delete(PersistentStorageDelegate * storage) + CHIP_ERROR Delete(DataAccessor & persistent, PersistentStorageDelegate * storage) { VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT); StorageKeyName key = StorageKeyName::Uninitialized(); - ReturnErrorOnFailure(UpdateKey(key)); + ReturnErrorOnFailure(persistent.UpdateKey(key)); return storage->SyncDeleteKeyValue(key.KeyName()); } + uint8_t mBuffer[kMaxSerializedSize] = { 0 }; +}; + +/// @brief Combines PersistentStore and DataAccessor +template +struct PersistentData : PersistentStore, DataAccessor +{ + using SizedStore = PersistentStore; + + PersistentData(PersistentStorageDelegate * storage = nullptr) : mStorage(storage) {} + virtual ~PersistentData() = default; + + virtual CHIP_ERROR Save() { return this->Save(this->mStorage); } + + virtual CHIP_ERROR Save(PersistentStorageDelegate * storage) { return SizedStore::Save(*this, storage); } + + virtual CHIP_ERROR Load() { return this->Load(this->mStorage); } + + virtual CHIP_ERROR Load(PersistentStorageDelegate * storage) { return SizedStore::Load(*this, storage); } + + virtual CHIP_ERROR Delete(PersistentStorageDelegate * storage) { return SizedStore::Delete(*this, storage); } + PersistentStorageDelegate * mStorage = nullptr; - uint8_t mBuffer[kMaxSerializedSize] = { 0 }; }; } // namespace chip