Further FabricTable improvements: (#39164)
* Remove the need to allocate stack memory when removing an entry from persistence
* Remove internal dependency on TableEntry, instead referencing data & id directly
diff --git a/src/app/clusters/scenes-server/SceneTableImpl.cpp b/src/app/clusters/scenes-server/SceneTableImpl.cpp
index 91ee39e..a6286e0 100644
--- a/src/app/clusters/scenes-server/SceneTableImpl.cpp
+++ b/src/app/clusters/scenes-server/SceneTableImpl.cpp
@@ -131,12 +131,16 @@
CHIP_ERROR DefaultSceneTableImpl::SetSceneTableEntry(FabricIndex fabric_index, const SceneTableEntry & entry)
{
- return this->SetTableEntry(fabric_index, entry);
+ return this->SetTableEntry(fabric_index, entry.mStorageId, entry.mStorageData);
}
CHIP_ERROR DefaultSceneTableImpl::GetSceneTableEntry(FabricIndex fabric_index, SceneStorageId scene_id, SceneTableEntry & entry)
{
- return this->GetTableEntry(fabric_index, scene_id, entry);
+ // All data is copied to SceneTableEntry, buffer can be allocated on stack
+ PersistentStore<Serializer::kEntryMaxBytes()> store;
+ ReturnErrorOnFailure(this->GetTableEntry(fabric_index, scene_id, entry.mStorageData, store));
+ entry.mStorageId = scene_id;
+ return CHIP_NO_ERROR;
}
CHIP_ERROR DefaultSceneTableImpl::RemoveSceneTableEntry(FabricIndex fabric_index, SceneStorageId scene_id)
@@ -198,7 +202,7 @@
if (fabric.entry_map[i].mGroupId == group_id)
{
// Removing each scene from the nvm and clearing their entry in the scene map
- ReturnErrorOnFailure(fabric.RemoveEntry(mStorage, fabric.entry_map[i]));
+ ReturnErrorOnFailure(fabric.RemoveEntry(*mStorage, fabric.entry_map[i]));
}
}
diff --git a/src/app/storage/FabricTableImpl.h b/src/app/storage/FabricTableImpl.h
index adf022e..43e384e 100644
--- a/src/app/storage/FabricTableImpl.h
+++ b/src/app/storage/FabricTableImpl.h
@@ -27,6 +27,45 @@
namespace Storage {
/**
+ * @brief Container which exposes various compile-time constants for specializations
+ * of FabricTableImpl.
+ */
+template <class StorageId, class StorageData>
+class DefaultSerializer
+{
+public:
+ // gcc bug prevents us from using a static variable; see:
+ // https://stackoverflow.com/questions/50638053/constexpr-static-data-member-without-initializer
+ // The number of bytes used by an entry (StorageData) + its metadata when persisting to storage
+ static constexpr size_t kEntryMaxBytes();
+ // The number of bytes used by FabricEntryData, which is dependent on the size of StorageId
+ static constexpr size_t kFabricMaxBytes();
+ // The max number of entries per fabric; this value directly affects memory usage
+ static constexpr uint16_t kMaxPerFabric();
+ // The max number of entries for the endpoint (programmatic limit)
+ static constexpr uint16_t kMaxPerEndpoint();
+
+ DefaultSerializer() {}
+ ~DefaultSerializer(){};
+
+ static CHIP_ERROR SerializeId(TLV::TLVWriter & writer, const StorageId & id);
+ static CHIP_ERROR DeserializeId(TLV::TLVReader & reader, StorageId & id);
+
+ static CHIP_ERROR SerializeData(TLV::TLVWriter & writer, const StorageData & data);
+ static CHIP_ERROR DeserializeData(TLV::TLVReader & reader, StorageData & data);
+
+ static StorageKeyName EndpointEntryCountKey(EndpointId endpoint);
+ // The key for persisting the data for a fabric
+ static StorageKeyName FabricEntryDataKey(FabricIndex fabric, EndpointId endpoint);
+ // The key for persisting the data for an entry in a fabric; FabricEntryDataKey should be a root prefix
+ // of this key, such that removing a fabric removes all its entries
+ static StorageKeyName FabricEntryKey(FabricIndex fabric, EndpointId endpoint, uint16_t idx);
+
+ // Clears the data to default values
+ static void Clear(StorageData & data) { data.Clear(); }
+}; // class DefaultSerializer
+
+/**
* @brief Implementation of a storage accessor in nonvolatile storage of a templatized table that stores by fabric index.
* This class does not actually hold the entries, but rather acts as a wrapper/accessor around the storage layer,
* reading entries from the storage pointed to by calling SetEndpoint.
@@ -37,11 +76,13 @@
template <class StorageId, class StorageData, size_t kIteratorsMax>
class FabricTableImpl
{
- using TableEntry = Data::TableEntry<StorageId, StorageData>;
- using EntryIterator = CommonIterator<TableEntry>;
- using EntryIndex = Data::EntryIndex;
+ using TableEntry = Data::TableEntry<StorageId, StorageData>;
public:
+ using EntryIterator = CommonIterator<TableEntry>;
+ using EntryIndex = Data::EntryIndex;
+ using Serializer = DefaultSerializer<StorageId, StorageData>;
+
virtual ~FabricTableImpl() { Finish(); };
CHIP_ERROR Init(PersistentStorageDelegate & storage);
@@ -65,9 +106,22 @@
// Data
CHIP_ERROR GetRemainingCapacity(FabricIndex fabric_index, uint8_t & capacity);
- CHIP_ERROR SetTableEntry(FabricIndex fabric_index, const TableEntry & entry);
- CHIP_ERROR GetTableEntry(FabricIndex fabric_index, StorageId entry_id, TableEntry & entry);
- CHIP_ERROR RemoveTableEntry(FabricIndex fabric_index, StorageId entry_id);
+ CHIP_ERROR SetTableEntry(FabricIndex fabric_index, const StorageId & entry_id, const StorageData & data);
+
+ /**
+ * @brief Loads the entry from persistent storage.
+ * @param fabric_index the fabric to load the entry from
+ * @param entry_id the unique entry identifier
+ * @param data the target for the loaded data
+ * @param buffer the buffer that will be used to load from persistence; some data types in the data argument, such as
+ * DecodableList, point directly into the buffer, and as such for those types of structures the lifetime of the buffer needs to
+ * be equal to or greater than data
+ */
+ template <size_t kEntryMaxBytes>
+ CHIP_ERROR GetTableEntry(FabricIndex fabric_index, StorageId & entry_id, StorageData & data,
+ PersistentStore<kEntryMaxBytes> & buffer);
+ CHIP_ERROR FindTableEntry(FabricIndex fabric_index, const StorageId & entry_id, EntryIndex & idx);
+ CHIP_ERROR RemoveTableEntry(FabricIndex fabric_index, const StorageId & entry_id);
CHIP_ERROR RemoveTableEntryAtPosition(EndpointId endpoint, FabricIndex fabric_index, EntryIndex entry_idx);
// Fabrics
@@ -124,38 +178,6 @@
PersistentStorageDelegate * mStorage = nullptr;
}; // class FabricTableImpl
-template <class StorageId, class StorageData>
-class DefaultSerializer
-{
-public:
- // gcc bug prevents us from using a static variable; see:
- // https://stackoverflow.com/questions/50638053/constexpr-static-data-member-without-initializer
- // The number of bytes used by an entry (StorageData) + its metadata when persisting to storage
- static constexpr size_t kEntryMaxBytes();
- // The number of bytes used by FabricEntryData, which is dependent on the size of StorageId
- static constexpr size_t kFabricMaxBytes();
- // The max number of entries per fabric; this value directly affects memory usage
- static constexpr uint16_t kMaxPerFabric();
- // The max number of entries for the endpoint (programmatic limit)
- static constexpr uint16_t kMaxPerEndpoint();
-
- DefaultSerializer() {}
- ~DefaultSerializer(){};
-
- static CHIP_ERROR SerializeId(TLV::TLVWriter & writer, const StorageId & id);
- static CHIP_ERROR DeserializeId(TLV::TLVReader & reader, StorageId & id);
-
- static CHIP_ERROR SerializeData(TLV::TLVWriter & writer, const StorageData & data);
- static CHIP_ERROR DeserializeData(TLV::TLVReader & reader, StorageData & data);
-
- static StorageKeyName EndpointEntryCountKey(EndpointId endpoint);
- // The key for persisting the data for a fabric
- static StorageKeyName FabricEntryDataKey(FabricIndex fabric, EndpointId endpoint);
- // The key for persisting the data for an entry in a fabric; FabricEntryDataKey should be a root prefix
- // of this key, such that removing a fabric removes all its entries
- static StorageKeyName FabricEntryKey(FabricIndex fabric, EndpointId endpoint, uint16_t idx);
-}; // class DefaultSerializer
-
} // namespace Storage
} // namespace app
} // namespace chip
diff --git a/src/app/storage/FabricTableImpl.ipp b/src/app/storage/FabricTableImpl.ipp
index 8542c36..a5531b0 100644
--- a/src/app/storage/FabricTableImpl.ipp
+++ b/src/app/storage/FabricTableImpl.ipp
@@ -121,22 +121,25 @@
inline const T * operator->() const { return &mRef; }
inline T * operator->() { return &mRef; }
+
+ inline const T & operator*() const { return mRef; }
+ inline T & operator*() { return mRef; }
};
template <class StorageId, class StorageData>
struct TableEntryData : DataAccessor
{
using Serializer = DefaultSerializer<StorageId, StorageData>;
- using TableEntry = Data::TableEntry<StorageId, StorageData>;
EndpointId endpoint_id = kInvalidEndpointId;
FabricIndex fabric_index = kUndefinedFabricIndex;
EntryIndex index = 0;
bool first = true;
- ConstCorrectRef<Data::TableEntry<StorageId, StorageData>> mEntry;
+ ConstCorrectRef<StorageId> storage_id;
+ ConstCorrectRef<StorageData> storage_data;
- TableEntryData(EndpointId endpoint, FabricIndex fabric, TableEntry & entry, EntryIndex idx = 0) :
- endpoint_id(endpoint), fabric_index(fabric), index(idx), mEntry(entry)
+ TableEntryData(EndpointId endpoint, FabricIndex fabric, StorageId & id, StorageData & data, EntryIndex idx = 0) :
+ endpoint_id(endpoint), fabric_index(fabric), index(idx), storage_id(id), storage_data(data)
{}
CHIP_ERROR UpdateKey(StorageKeyName & key) const override
@@ -147,16 +150,16 @@
return CHIP_NO_ERROR;
}
- void Clear() override { this->mEntry->mStorageData.Clear(); }
+ void Clear() override { Serializer::Clear(*storage_data); }
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->mEntry->mStorageId));
+ ReturnErrorOnFailure(Serializer::SerializeId(writer, *storage_id));
- ReturnErrorOnFailure(Serializer::SerializeData(writer, this->mEntry->mStorageData));
+ ReturnErrorOnFailure(Serializer::SerializeData(writer, *storage_data));
return writer.EndContainer(container);
}
@@ -168,9 +171,9 @@
TLV::TLVType container;
ReturnErrorOnFailure(reader.EnterContainer(container));
- ReturnErrorOnFailure(Serializer::DeserializeId(reader, this->mEntry->mStorageId));
+ ReturnErrorOnFailure(Serializer::DeserializeId(reader, *storage_id));
- ReturnErrorOnFailure(Serializer::DeserializeData(reader, this->mEntry->mStorageData));
+ ReturnErrorOnFailure(Serializer::DeserializeData(reader, *storage_data));
return reader.ExitContainer(container);
}
@@ -187,7 +190,6 @@
using Serializer = DefaultSerializer<StorageId, StorageData>;
using TypedTableEntryData = TableEntryData<StorageId, StorageData>;
using Store = PersistentStore<kEntryMaxBytes>;
- using TableEntry = typename TypedTableEntryData::TableEntry;
using TypedEndpointEntryCount = EndpointEntryCount<StorageId, StorageData>;
EndpointId endpoint_id;
@@ -257,7 +259,7 @@
/// deleted so it can adjust the fabric and global entry count accordingly. Even if Deserialize fails, this value will return
/// the number of entries deleted before the failure happened.
/// @return CHIP_NO_ERROR on success, specific CHIP_ERROR otherwise
- CHIP_ERROR Deserialize(TLV::TLVReader & reader, PersistentStorageDelegate * storage, uint8_t & deleted_entries_count)
+ CHIP_ERROR Deserialize(TLV::TLVReader & reader, PersistentStorageDelegate & storage, uint8_t & deleted_entries_count)
{
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
TLV::TLVType fabricEntryContainer;
@@ -273,7 +275,6 @@
CHIP_ERROR err;
deleted_entries_count = 0;
- TableEntry unused;
Store persistentStore;
while ((err = reader.Next(TLV::AnonymousTag())) == CHIP_NO_ERROR)
{
@@ -286,11 +287,11 @@
}
else
{
- TypedTableEntryData entry(endpoint_id, fabric_index, unused, i);
+ StorageId unused;
ReturnErrorOnFailure(reader.EnterContainer(entryIdContainer));
- ReturnErrorOnFailure(Serializer::DeserializeId(reader, entry_map[i]));
+ ReturnErrorOnFailure(Serializer::DeserializeId(reader, unused));
ReturnErrorOnFailure(reader.ExitContainer(entryIdContainer));
- ReturnErrorOnFailure(persistentStore.Delete(entry, storage));
+ ReturnErrorOnFailure(DeleteValue(storage, i));
deleted_entries_count++;
}
@@ -302,13 +303,28 @@
return reader.ExitContainer(fabricEntryContainer);
}
+ /// @brief Finds the id of the entry with the specified index
+ /// @return CHIP_NO_ERROR if managed to find the target entry, CHIP_ERROR_NOT_FOUND if not found
+ CHIP_ERROR FindByIndex(PersistentStorageDelegate & storage, EntryIndex index, StorageId & entry_id)
+ {
+ VerifyOrReturnError(entry_map[index].IsValid(), CHIP_ERROR_NOT_FOUND);
+ VerifyOrReturnError(kUndefinedFabricIndex != fabric_index, CHIP_ERROR_INVALID_FABRIC_INDEX);
+ VerifyOrReturnError(kInvalidEndpointId != endpoint_id, CHIP_ERROR_INVALID_ARGUMENT);
+ if (!storage.SyncDoesKeyExist(Serializer::FabricEntryKey(fabric_index, endpoint_id, index).KeyName()))
+ {
+ return CHIP_ERROR_NOT_FOUND;
+ }
+ entry_id = entry_map[index];
+ return CHIP_NO_ERROR;
+ }
+
/// @brief Finds the index where the current entry should be inserted by going through the endpoint's table and checking
/// whether the entry is already there. If the target is not in the table, sets idx to the first empty space
/// @param target_entry StorageId of entry to find
/// @param idx Index where target or space is found
/// @return CHIP_NO_ERROR if managed to find the target entry, CHIP_ERROR_NOT_FOUND if not found and space left
/// CHIP_ERROR_NO_MEMORY if target was not found and table is full
- CHIP_ERROR Find(StorageId target_entry, EntryIndex & idx)
+ CHIP_ERROR Find(const StorageId & target_entry, EntryIndex & idx)
{
EntryIndex firstFreeIdx = Data::kUndefinedEntryIndex; // storage index if entry not found
uint16_t index = 0;
@@ -336,54 +352,55 @@
return CHIP_ERROR_NO_MEMORY;
}
- CHIP_ERROR SaveEntry(PersistentStorageDelegate * storage, const TableEntry & src_entry)
+ CHIP_ERROR SaveEntry(PersistentStorageDelegate & storage, const StorageId & id, const StorageData & data)
{
CHIP_ERROR err = CHIP_NO_ERROR;
// Look for empty storage space
EntryIndex index;
- err = this->Find(src_entry.mStorageId, index);
+ err = this->Find(id, index);
Store persistentStore;
// C++ doesn't have const constructors; variable is declared const
- const TypedTableEntryData entry(endpoint_id, fabric_index, const_cast<TableEntry &>(src_entry), index);
+ const TypedTableEntryData entry(endpoint_id, fabric_index, const_cast<StorageId &>(id), const_cast<StorageData &>(data),
+ index);
if (CHIP_NO_ERROR == err)
{
- return persistentStore.Save(entry, storage);
+ return persistentStore.Save(entry, &storage);
}
if (CHIP_ERROR_NOT_FOUND == err) // If not found, entry.index should be the first free index
{
// Update the global entry count
TypedEndpointEntryCount endpoint_count(endpoint_id);
- ReturnErrorOnFailure(endpoint_count.Load(storage));
+ ReturnErrorOnFailure(endpoint_count.Load(&storage));
VerifyOrReturnError(endpoint_count.count_value < max_per_endpoint, CHIP_ERROR_NO_MEMORY);
endpoint_count.count_value++;
- ReturnErrorOnFailure(endpoint_count.Save(storage));
+ ReturnErrorOnFailure(endpoint_count.Save(&storage));
entry_count++;
- entry_map[entry.index] = src_entry.mStorageId;
+ entry_map[entry.index] = id;
- err = this->Save(storage);
+ err = this->Save(&storage);
if (CHIP_NO_ERROR != err)
{
endpoint_count.count_value--;
- ReturnErrorOnFailure(endpoint_count.Save(storage));
+ ReturnErrorOnFailure(endpoint_count.Save(&storage));
return err;
}
- err = persistentStore.Save(entry, storage);
+ err = persistentStore.Save(entry, &storage);
// on failure to save the entry, undoes the changes to Fabric Entry Data
if (CHIP_NO_ERROR != err)
{
endpoint_count.count_value--;
- ReturnErrorOnFailure(endpoint_count.Save(storage));
+ ReturnErrorOnFailure(endpoint_count.Save(&storage));
entry_count--;
entry_map[entry.index].Clear();
- ReturnErrorOnFailure(this->Save(storage));
+ ReturnErrorOnFailure(this->Save(&storage));
return err;
}
}
@@ -397,47 +414,46 @@
/// @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 RemoveEntry(PersistentStorageDelegate & storage, const StorageId & entry_id)
{
CHIP_ERROR err = CHIP_NO_ERROR;
- TableEntry id_holder(entry_id);
- TypedTableEntryData entry(endpoint_id, fabric_index, id_holder);
+ EntryIndex entryIndex;
// Empty Entry Fabric Data returns CHIP_NO_ERROR on remove
if (entry_count > 0)
{
// If Find doesn't return CHIP_NO_ERROR, the entry wasn't found, which doesn't return an error
- VerifyOrReturnValue(this->Find(entry_id, entry.index) == CHIP_NO_ERROR, CHIP_NO_ERROR);
+ VerifyOrReturnValue(this->Find(entry_id, entryIndex) == CHIP_NO_ERROR, CHIP_NO_ERROR);
// Update the global entry count
TypedEndpointEntryCount endpoint_entry_count(endpoint_id);
- ReturnErrorOnFailure(endpoint_entry_count.Load(storage));
+ ReturnErrorOnFailure(endpoint_entry_count.Load(&storage));
endpoint_entry_count.count_value--;
- ReturnErrorOnFailure(endpoint_entry_count.Save(storage));
+ ReturnErrorOnFailure(endpoint_entry_count.Save(&storage));
entry_count--;
- entry_map[entry.index].Clear();
- err = this->Save(storage);
+ entry_map[entryIndex].Clear();
+ err = this->Save(&storage);
// On failure to update the entry map, undo the global count modification
if (CHIP_NO_ERROR != err)
{
endpoint_entry_count.count_value++;
- ReturnErrorOnFailure(endpoint_entry_count.Save(storage));
+ ReturnErrorOnFailure(endpoint_entry_count.Save(&storage));
return err;
}
- err = Store().Delete(entry, storage);
+ err = DeleteValue(storage, entryIndex);
// On failure to delete entry, undo the change to the Fabric Entry Data and the global entry count
if (CHIP_NO_ERROR != err)
{
endpoint_entry_count.count_value++;
- ReturnErrorOnFailure(endpoint_entry_count.Save(storage));
+ ReturnErrorOnFailure(endpoint_entry_count.Save(&storage));
entry_count++;
- entry_map[entry.index] = id_holder.mStorageId;
- ReturnErrorOnFailure(this->Save(storage));
+ entry_map[entryIndex] = entry_id;
+ ReturnErrorOnFailure(this->Save(&storage));
return err;
}
}
@@ -468,7 +484,7 @@
TLV::TLVReader reader;
reader.Init(buffer, size);
- err = Deserialize(reader, storage, deleted_entries_count);
+ err = Deserialize(reader, *storage, deleted_entries_count);
// If Deserialize sets the "deleted_entries" variable, the table in flash memory held too many entries (can happen
// if max_per_fabric was reduced during an OTA) and was adjusted during deserializing . The fabric data must then
@@ -484,12 +500,18 @@
return err;
}
+
+private:
+ CHIP_ERROR DeleteValue(PersistentStorageDelegate & storage, EntryIndex index)
+ {
+ StorageKeyName key = Serializer::FabricEntryKey(fabric_index, endpoint_id, index);
+ return storage.SyncDeleteKeyValue(key.KeyName());
+ }
};
template <class StorageId, class StorageData, size_t kIteratorsMax>
CHIP_ERROR FabricTableImpl<StorageId, StorageData, kIteratorsMax>::Init(PersistentStorageDelegate & storage)
{
- using Serializer = DefaultSerializer<StorageId, StorageData>;
// Verify the initialized parameter respects the maximum allowed values for entry capacity
VerifyOrReturnError(mMaxPerFabric <= Serializer::kMaxPerFabric() && mMaxPerEndpoint <= Serializer::kMaxPerEndpoint(),
CHIP_ERROR_INVALID_INTEGER_VALUE);
@@ -505,7 +527,6 @@
CHIP_ERROR FabricTableImpl<StorageId, StorageData, kIteratorsMax>::GetFabricEntryCount(FabricIndex fabric_index,
uint8_t & entry_count)
{
- using Serializer = DefaultSerializer<StorageId, StorageData>;
using TypedFabricEntryData = FabricEntryData<StorageId, StorageData, Serializer::kEntryMaxBytes(),
Serializer::kFabricMaxBytes(), Serializer::kMaxPerFabric()>;
@@ -549,7 +570,6 @@
CHIP_ERROR FabricTableImpl<StorageId, StorageData, kIteratorsMax>::GetRemainingCapacity(FabricIndex fabric_index,
uint8_t & capacity)
{
- using Serializer = DefaultSerializer<StorageId, StorageData>;
using TypedFabricEntryData = FabricEntryData<StorageId, StorageData, Serializer::kEntryMaxBytes(),
Serializer::kFabricMaxBytes(), Serializer::kMaxPerFabric()>;
@@ -585,9 +605,9 @@
}
template <class StorageId, class StorageData, size_t kIteratorsMax>
-CHIP_ERROR FabricTableImpl<StorageId, StorageData, kIteratorsMax>::SetTableEntry(FabricIndex fabric_index, const TableEntry & entry)
+CHIP_ERROR FabricTableImpl<StorageId, StorageData, kIteratorsMax>::SetTableEntry(FabricIndex fabric_index, const StorageId & id,
+ const StorageData & data)
{
- using Serializer = DefaultSerializer<StorageId, StorageData>;
using TypedFabricEntryData = FabricEntryData<StorageId, StorageData, Serializer::kEntryMaxBytes(),
Serializer::kFabricMaxBytes(), Serializer::kMaxPerFabric()>;
@@ -599,26 +619,27 @@
CHIP_ERROR err = fabric.Load(mStorage);
VerifyOrReturnError(CHIP_NO_ERROR == err || CHIP_ERROR_NOT_FOUND == err, err);
- err = fabric.SaveEntry(mStorage, entry);
+ err = fabric.SaveEntry(*mStorage, id, data);
return err;
}
template <class StorageId, class StorageData, size_t kIteratorsMax>
-CHIP_ERROR FabricTableImpl<StorageId, StorageData, kIteratorsMax>::GetTableEntry(FabricIndex fabric_index, StorageId entry_id,
- TableEntry & entry)
+template <size_t kEntryMaxBytes>
+CHIP_ERROR FabricTableImpl<StorageId, StorageData, kIteratorsMax>::GetTableEntry(FabricIndex fabric_index, StorageId & entry_id,
+ StorageData & data,
+ PersistentStore<kEntryMaxBytes> & buffer)
{
- using Serializer = DefaultSerializer<StorageId, StorageData>;
using TypedFabricEntryData = FabricEntryData<StorageId, StorageData, Serializer::kEntryMaxBytes(),
Serializer::kFabricMaxBytes(), Serializer::kMaxPerFabric()>;
VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
TypedFabricEntryData fabric(mEndpointId, fabric_index, mMaxPerFabric, mMaxPerEndpoint);
- TableEntryData<StorageId, StorageData> table_entry(mEndpointId, fabric_index, entry);
+ TableEntryData<StorageId, StorageData> table_entry(mEndpointId, fabric_index, entry_id, data);
ReturnErrorOnFailure(fabric.Load(mStorage));
VerifyOrReturnError(fabric.Find(entry_id, table_entry.index) == CHIP_NO_ERROR, CHIP_ERROR_NOT_FOUND);
- CHIP_ERROR err = PersistentStore<Serializer::kEntryMaxBytes()>().Load(table_entry, mStorage);
+ CHIP_ERROR err = buffer.Load(table_entry, mStorage);
// 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.
@@ -632,9 +653,25 @@
}
template <class StorageId, class StorageData, size_t kIteratorsMax>
-CHIP_ERROR FabricTableImpl<StorageId, StorageData, kIteratorsMax>::RemoveTableEntry(FabricIndex fabric_index, StorageId entry_id)
+CHIP_ERROR FabricTableImpl<StorageId, StorageData, kIteratorsMax>::FindTableEntry(FabricIndex fabric_index,
+ const StorageId & entry_id, EntryIndex & idx)
{
- using Serializer = DefaultSerializer<StorageId, StorageData>;
+ using TypedFabricEntryData = FabricEntryData<StorageId, StorageData, Serializer::kEntryMaxBytes(),
+ Serializer::kFabricMaxBytes(), Serializer::kMaxPerFabric()>;
+ VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
+
+ TypedFabricEntryData fabric(mEndpointId, fabric_index, mMaxPerFabric, mMaxPerEndpoint);
+
+ ReturnErrorOnFailure(fabric.Load(mStorage));
+ VerifyOrReturnError(fabric.Find(entry_id, idx) == CHIP_NO_ERROR, CHIP_ERROR_NOT_FOUND);
+
+ return CHIP_NO_ERROR;
+}
+
+template <class StorageId, class StorageData, size_t kIteratorsMax>
+CHIP_ERROR FabricTableImpl<StorageId, StorageData, kIteratorsMax>::RemoveTableEntry(FabricIndex fabric_index,
+ const StorageId & entry_id)
+{
using TypedFabricEntryData = FabricEntryData<StorageId, StorageData, Serializer::kEntryMaxBytes(),
Serializer::kFabricMaxBytes(), Serializer::kMaxPerFabric()>;
@@ -643,7 +680,7 @@
ReturnErrorOnFailure(fabric.Load(mStorage));
- return fabric.RemoveEntry(mStorage, entry_id);
+ return fabric.RemoveEntry(*mStorage, entry_id);
}
/// @brief This function is meant to provide a way to empty the entry table without knowing any specific entry Id. Outside of this
@@ -656,29 +693,25 @@
FabricIndex fabric_index,
EntryIndex entry_idx)
{
- using Serializer = DefaultSerializer<StorageId, StorageData>;
using TypedFabricEntryData = FabricEntryData<StorageId, StorageData, Serializer::kEntryMaxBytes(),
Serializer::kFabricMaxBytes(), Serializer::kMaxPerFabric()>;
VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INTERNAL);
- CHIP_ERROR err = CHIP_NO_ERROR;
TypedFabricEntryData fabric(endpoint, fabric_index, mMaxPerFabric, mMaxPerEndpoint);
- TableEntry loadedEntry;
- TableEntryData<StorageId, StorageData> entry(endpoint, fabric_index, loadedEntry, entry_idx);
ReturnErrorOnFailure(fabric.Load(mStorage));
- err = PersistentStore<Serializer::kEntryMaxBytes()>().Load(entry, mStorage);
+ StorageId entryId;
+ CHIP_ERROR err = fabric.FindByIndex(*mStorage, entry_idx, entryId);
VerifyOrReturnValue(CHIP_ERROR_NOT_FOUND != err, CHIP_NO_ERROR);
ReturnErrorOnFailure(err);
- return fabric.RemoveEntry(mStorage, loadedEntry.mStorageId);
+ return fabric.RemoveEntry(*mStorage, entryId);
}
template <class StorageId, class StorageData, size_t kIteratorsMax>
CHIP_ERROR FabricTableImpl<StorageId, StorageData, kIteratorsMax>::RemoveFabric(FabricIndex fabric_index)
{
- using Serializer = DefaultSerializer<StorageId, StorageData>;
using TypedFabricEntryData = FabricEntryData<StorageId, StorageData, Serializer::kEntryMaxBytes(),
Serializer::kFabricMaxBytes(), Serializer::kMaxPerFabric()>;
@@ -717,7 +750,6 @@
template <class StorageId, class StorageData, size_t kIteratorsMax>
CHIP_ERROR FabricTableImpl<StorageId, StorageData, kIteratorsMax>::RemoveEndpoint()
{
- using Serializer = DefaultSerializer<StorageId, StorageData>;
using TypedFabricEntryData = FabricEntryData<StorageId, StorageData, Serializer::kEntryMaxBytes(),
Serializer::kFabricMaxBytes(), Serializer::kMaxPerFabric()>;
@@ -757,8 +789,6 @@
template <class StorageId, class StorageData, size_t kIteratorsMax>
void FabricTableImpl<StorageId, StorageData, kIteratorsMax>::SetTableSize(uint16_t endpointTableSize, uint16_t maxPerFabric)
{
- using Serializer = DefaultSerializer<StorageId, StorageData>;
-
// Verify the endpoint passed size respects the limits of the device configuration
VerifyOrDie(Serializer::kMaxPerFabric() > 0);
VerifyOrDie(Serializer::kMaxPerEndpoint() > 0);
@@ -772,7 +802,6 @@
mProvider(provider),
mFabric(fabricIdx), mEndpoint(endpoint), mMaxPerFabric(maxPerFabric), mMaxPerEndpoint(maxPerEndpoint)
{
- using Serializer = DefaultSerializer<StorageId, StorageData>;
using TypedFabricEntryData = FabricEntryData<StorageId, StorageData, Serializer::kEntryMaxBytes(),
Serializer::kFabricMaxBytes(), Serializer::kMaxPerFabric()>;
@@ -791,7 +820,6 @@
template <class StorageId, class StorageData, size_t kIteratorsMax>
bool FabricTableImpl<StorageId, StorageData, kIteratorsMax>::EntryIteratorImpl::Next(TableEntry & output)
{
- using Serializer = DefaultSerializer<StorageId, StorageData>;
using TypedFabricEntryData = FabricEntryData<StorageId, StorageData, Serializer::kEntryMaxBytes(),
Serializer::kFabricMaxBytes(), Serializer::kMaxPerFabric()>;
@@ -805,7 +833,7 @@
{
if (fabric.entry_map[mEntryIndex].IsValid())
{
- TableEntryData<StorageId, StorageData> entry(mEndpoint, mFabric, output, mEntryIndex);
+ TableEntryData<StorageId, StorageData> entry(mEndpoint, mFabric, output.mStorageId, output.mStorageData, mEntryIndex);
VerifyOrReturnError(persistentStore.Load(entry, mProvider.mStorage) == CHIP_NO_ERROR, false);
mEntryIndex++;