Matter SDK Coverage Report
Current view: top level - app/storage - FabricTableImpl.h (source / functions) Coverage Total Hit
Test: SHA:4d2388ac7eed75b2fe5e05e20de377999c632502 Lines: 100.0 % 6 6
Test Date: 2025-07-27 07:17:09 Functions: 80.0 % 5 4

            Line data    Source code
       1              : /**
       2              :  *
       3              :  *    Copyright (c) 2025 Project CHIP Authors
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : 
      18              : #pragma once
      19              : 
      20              : #include <app/storage/TableEntry.h>
      21              : #include <lib/support/CommonIterator.h>
      22              : #include <lib/support/PersistentData.h>
      23              : #include <lib/support/TypeTraits.h>
      24              : 
      25              : namespace chip {
      26              : namespace app {
      27              : namespace Storage {
      28              : 
      29              : /**
      30              :  * @brief Container which exposes various compile-time constants for specializations
      31              :  * of FabricTableImpl.
      32              :  */
      33              : template <class StorageId, class StorageData>
      34              : class DefaultSerializer
      35              : {
      36              : public:
      37              :     // gcc bug prevents us from using a static variable; see:
      38              :     // https://stackoverflow.com/questions/50638053/constexpr-static-data-member-without-initializer
      39              :     // The number of bytes used by an entry (StorageData) + its metadata when persisting to storage
      40              :     static constexpr size_t kEntryMaxBytes();
      41              :     // The number of bytes used by FabricEntryData, which is dependent on the size of StorageId
      42              :     static constexpr size_t kFabricMaxBytes();
      43              :     // The max number of entries per fabric; this value directly affects memory usage
      44              :     static constexpr uint16_t kMaxPerFabric();
      45              :     // The max number of entries for the endpoint (programmatic limit)
      46              :     static constexpr uint16_t kMaxPerEndpoint();
      47              : 
      48              :     DefaultSerializer() {}
      49              :     ~DefaultSerializer(){};
      50              : 
      51              :     static CHIP_ERROR SerializeId(TLV::TLVWriter & writer, const StorageId & id);
      52              :     static CHIP_ERROR DeserializeId(TLV::TLVReader & reader, StorageId & id);
      53              : 
      54              :     static CHIP_ERROR SerializeData(TLV::TLVWriter & writer, const StorageData & data);
      55              :     static CHIP_ERROR DeserializeData(TLV::TLVReader & reader, StorageData & data);
      56              : 
      57              :     static StorageKeyName EndpointEntryCountKey(EndpointId endpoint);
      58              :     // The key for persisting the data for a fabric
      59              :     static StorageKeyName FabricEntryDataKey(FabricIndex fabric, EndpointId endpoint);
      60              :     // The key for persisting the data for an entry in a fabric; FabricEntryDataKey should be a root prefix
      61              :     // of this key, such that removing a fabric removes all its entries
      62              :     static StorageKeyName FabricEntryKey(FabricIndex fabric, EndpointId endpoint, uint16_t idx);
      63              : 
      64              :     // Clears the data to default values
      65           71 :     static void Clear(StorageData & data) { data.Clear(); }
      66              : }; // class DefaultSerializer
      67              : 
      68              : /**
      69              :  * @brief Implementation of a storage accessor in nonvolatile storage of a templatized table that stores by fabric index.
      70              :  *        This class does not actually hold the entries, but rather acts as a wrapper/accessor around the storage layer,
      71              :  *        reading entries from the storage pointed to by calling SetEndpoint.
      72              :  *
      73              :  * FabricTableImpl is an implementation that allows to store arbitrary entities using PersistentStorageDelegate.
      74              :  * It handles the storage of entities by their StorageId and EnpointId over multiple fabrics.
      75              :  */
      76              : template <class StorageId, class StorageData>
      77              : class FabricTableImpl
      78              : {
      79              :     using TableEntry = Data::TableEntryRef<StorageId, StorageData>;
      80              : 
      81              : public:
      82              :     using EntryIterator = CommonIterator<TableEntry>;
      83              :     using EntryIndex    = Data::EntryIndex;
      84              :     using Serializer    = DefaultSerializer<StorageId, StorageData>;
      85              : 
      86           62 :     virtual ~FabricTableImpl() { Finish(); };
      87              : 
      88              :     CHIP_ERROR Init(PersistentStorageDelegate & storage);
      89              :     void Finish();
      90              : 
      91              :     // Entry count
      92              :     /**
      93              :      * @brief Get the total number of stored entries for the entire endpoint
      94              :      * @param entry_count[out] the count of entries
      95              :      * @return CHIP_ERROR, CHIP_NO_ERROR if successful or if the Fabric was not found, specific CHIP_ERROR otherwise
      96              :      */
      97              :     CHIP_ERROR GetEndpointEntryCount(uint8_t & entry_count);
      98              : 
      99              :     /**
     100              :      * @brief Get the total number of stored entries for the specified fabric on the currently selected endpoint.
     101              :      * @param fabric_index the fabric to get the count for
     102              :      * @param entry_count[out] the count of entries
     103              :      * @return CHIP_ERROR, CHIP_NO_ERROR if successful or if the Fabric was not found, specific CHIP_ERROR otherwise
     104              :      */
     105              :     CHIP_ERROR GetFabricEntryCount(FabricIndex fabric_index, uint8_t & entry_count);
     106              : 
     107              :     // Data
     108              :     CHIP_ERROR GetRemainingCapacity(FabricIndex fabric_index, uint8_t & capacity);
     109              : 
     110              :     /**
     111              :      * @brief Writes the entry to persistent storage.
     112              :      * @param fabric_index the fabric to write the entry to
     113              :      * @param entry_id the unique entry identifier
     114              :      * @param data the source data
     115              :      * @param writeBuffer the buffer that will be used to write the data before being persisted; PersistentStorageDelegate does not
     116              :      * offer a way to stream bytes to be written
     117              :      */
     118              :     template <size_t kEntryMaxBytes>
     119              :     CHIP_ERROR SetTableEntry(FabricIndex fabric_index, const StorageId & entry_id, const StorageData & data,
     120              :                              PersistentStore<kEntryMaxBytes> & writeBuffer);
     121              : 
     122              :     /**
     123              :      * @brief Loads the entry from persistent storage.
     124              :      * @param fabric_index the fabric to load the entry from
     125              :      * @param entry_id the unique entry identifier
     126              :      * @param data the target for the loaded data
     127              :      * @param buffer the buffer that will be used to load from persistence; some data types in the data argument, such as
     128              :      * DecodableList, point directly into the buffer, and as such for those types of structures the lifetime of the buffer needs to
     129              :      * be equal to or greater than data
     130              :      */
     131              :     template <size_t kEntryMaxBytes>
     132              :     CHIP_ERROR GetTableEntry(FabricIndex fabric_index, StorageId & entry_id, StorageData & data,
     133              :                              PersistentStore<kEntryMaxBytes> & buffer);
     134              :     CHIP_ERROR FindTableEntry(FabricIndex fabric_index, const StorageId & entry_id, EntryIndex & idx);
     135              :     CHIP_ERROR RemoveTableEntry(FabricIndex fabric_index, const StorageId & entry_id);
     136              :     CHIP_ERROR RemoveTableEntryAtPosition(EndpointId endpoint, FabricIndex fabric_index, EntryIndex entry_idx);
     137              : 
     138              :     // Fabrics
     139              :     CHIP_ERROR RemoveFabric(FabricIndex fabric_index);
     140              :     CHIP_ERROR RemoveEndpoint();
     141              : 
     142              :     /**
     143              :      * @brief Selects the endpoint that the table will point to & entries will be read from.
     144              :      * @param endpoint the endpoint which entries will be stored to or read from.
     145              :      */
     146              :     void SetEndpoint(EndpointId endpoint);
     147              :     void SetTableSize(uint16_t endpointEntryTableSize, uint16_t maxPerFabric);
     148          531 :     bool IsInitialized() { return (mStorage != nullptr); }
     149              : 
     150              :     /**
     151              :      * @brief Iterates through all entries in fabric, calling iterateFn with the allocated iterator.
     152              :      * @tparam kEntryMaxBytes size of the buffer for loading entries, should match DefaultSerializer::kEntryMaxBytes
     153              :      * @tparam UnaryFunc a function of type std::function<CHIP_ERROR(EntryIterator & iterator)>; template arg for GCC inlining
     154              :      * efficiency
     155              :      * @param fabric the fabric to iterate entries for
     156              :      * @param store the in-memory buffer that an entry will be read into
     157              :      * @param iterateFn a function that will be called with the iterator; if this function returns an error result, iteration stops
     158              :      * and IterateEntries returns that same error result.
     159              :      */
     160              :     template <size_t kEntryMaxBytes, class UnaryFunc>
     161              :     CHIP_ERROR IterateEntries(FabricIndex fabric, PersistentStore<kEntryMaxBytes> & store, UnaryFunc iterateFn);
     162              : 
     163              : protected:
     164              :     // This constructor is meant for test purposes, it allows to change the defined max for entries per fabric and global, which
     165              :     // allows to simulate OTA where this value was changed
     166           62 :     FabricTableImpl(uint16_t maxEntriesPerFabric, uint16_t maxEntriesPerEndpoint) :
     167           62 :         mMaxPerFabric(maxEntriesPerFabric), mMaxPerEndpoint(maxEntriesPerEndpoint)
     168           62 :     {}
     169              : 
     170              :     // Endpoint entry count
     171              :     CHIP_ERROR SetEndpointEntryCount(const uint8_t & entry_count);
     172              : 
     173              :     /**
     174              :      * @brief Implementation of an iterator over the elements in the FabricTableImpl.
     175              :      *
     176              :      * If you would like to expose iterators in your subclass of FabricTableImpl, you can:
     177              :      * A) Use this class in an ObjectPool<EntryIteratorImpl> field to allow callers to obtain an iterator, with AutoRelease to free
     178              :      * resources B) Use IterateEntries to allocate on stack
     179              :      */
     180              :     template <size_t kEntryMaxBytes>
     181              :     class EntryIteratorImpl : public EntryIterator
     182              :     {
     183              :     public:
     184              :         EntryIteratorImpl(FabricTableImpl & provider, FabricIndex fabricIdx, EndpointId endpoint, uint16_t maxEntriesPerFabric,
     185              :                           uint16_t maxEntriesPerEndpoint, PersistentStore<kEntryMaxBytes> & store);
     186              :         size_t Count() override;
     187              :         bool Next(TableEntry & output) override;
     188              :         void Release() override;
     189              : 
     190              :     protected:
     191              :         FabricTableImpl & mProvider;
     192              :         PersistentStore<kEntryMaxBytes> & mStore;
     193              :         FabricIndex mFabric  = kUndefinedFabricIndex;
     194              :         EndpointId mEndpoint = kInvalidEndpointId;
     195              :         EntryIndex mNextEntryIdx;
     196              :         EntryIndex mEntryIndex = 0;
     197              :         uint8_t mTotalEntries  = 0;
     198              :         uint16_t mMaxPerFabric;
     199              :         uint16_t mMaxPerEndpoint;
     200              :     };
     201              : 
     202              :     uint16_t mMaxPerFabric;
     203              :     uint16_t mMaxPerEndpoint;
     204              :     EndpointId mEndpointId               = kInvalidEndpointId;
     205              :     PersistentStorageDelegate * mStorage = nullptr;
     206              : }; // class FabricTableImpl
     207              : 
     208              : } // namespace Storage
     209              : } // namespace app
     210              : } // namespace chip
        

Generated by: LCOV version 2.0-1