xref: /aosp_15_r20/external/pigweed/pw_kvs/public/pw_kvs/flash_partition_with_stats.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <algorithm>
17 #include <numeric>
18 
19 #include "pw_containers/vector.h"
20 #include "pw_kvs/flash_memory.h"
21 #include "pw_kvs/key_value_store.h"
22 #include "pw_status/status.h"
23 
24 #ifndef PW_KVS_RECORD_PARTITION_STATS
25 // PW_KVS_RECORD_PARTITION_STATS enables saving stats.
26 #define PW_KVS_RECORD_PARTITION_STATS 0
27 #endif  // PW_KVS_RECORD_PARTITION_STATS
28 
29 namespace pw::kvs {
30 
31 class FlashPartitionWithStats : public FlashPartition {
32  public:
33   // Save flash partition and KVS storage stats. Does not save if
34   // sector_counters_ is zero.
35   Status SaveStorageStats(const KeyValueStore& kvs, const char* label);
36 
37   using FlashPartition::Erase;
38 
39   Status Erase(Address address, size_t num_sectors) override;
40 
sector_erase_counters()41   span<size_t> sector_erase_counters() {
42     return span(sector_counters_.data(), sector_counters_.size());
43   }
44 
min_erase_count()45   size_t min_erase_count() const {
46     if (sector_counters_.empty()) {
47       return 0;
48     }
49     return *std::min_element(sector_counters_.begin(), sector_counters_.end());
50   }
51 
max_erase_count()52   size_t max_erase_count() const {
53     if (sector_counters_.empty()) {
54       return 0;
55     }
56     return *std::max_element(sector_counters_.begin(), sector_counters_.end());
57   }
58 
average_erase_count()59   size_t average_erase_count() const {
60     return sector_counters_.empty()
61                ? 0
62                : total_erase_count() / sector_counters_.size();
63   }
64 
total_erase_count()65   size_t total_erase_count() const {
66     return std::accumulate(
67         sector_counters_.begin(), sector_counters_.end(), 0ul);
68   }
69 
ResetCounters()70   void ResetCounters() { sector_counters_.assign(sector_count(), 0); }
71 
72  protected:
73   FlashPartitionWithStats(
74       Vector<size_t>& sector_counters,
75       FlashMemory* flash,
76       uint32_t flash_start_sector_index,
77       uint32_t flash_sector_count,
78       uint32_t alignment_bytes = 0,  // Defaults to flash alignment
79       PartitionPermission permission = PartitionPermission::kReadAndWrite)
FlashPartition(flash,flash_start_sector_index,flash_sector_count,alignment_bytes,permission)80       : FlashPartition(flash,
81                        flash_start_sector_index,
82                        flash_sector_count,
83                        alignment_bytes,
84                        permission),
85         sector_counters_(sector_counters) {
86     sector_counters_.assign(FlashPartition::sector_count(), 0);
87   }
88 
89  private:
90   Vector<size_t>& sector_counters_;
91 };
92 
93 template <size_t kMaxSectors>
94 class FlashPartitionWithStatsBuffer : public FlashPartitionWithStats {
95  public:
96   FlashPartitionWithStatsBuffer(
97       FlashMemory* flash,
98       uint32_t flash_start_sector_index,
99       uint32_t flash_sector_count,
100       uint32_t alignment_bytes = 0,  // Defaults to flash alignment
101       PartitionPermission permission = PartitionPermission::kReadAndWrite)
FlashPartitionWithStats(sector_counters_,flash,flash_start_sector_index,flash_sector_count,alignment_bytes,permission)102       : FlashPartitionWithStats(sector_counters_,
103                                 flash,
104                                 flash_start_sector_index,
105                                 flash_sector_count,
106                                 alignment_bytes,
107                                 permission) {}
108 
FlashPartitionWithStatsBuffer(FlashMemory * flash)109   FlashPartitionWithStatsBuffer(FlashMemory* flash)
110       : FlashPartitionWithStatsBuffer(
111             flash, 0, flash->sector_count(), flash->alignment_bytes()) {}
112 
113  private:
114   // If PW_KVS_RECORD_PARTITION_STATS is not set, use zero size vector which
115   // will not save any stats.
116   Vector<size_t, PW_KVS_RECORD_PARTITION_STATS ? kMaxSectors : 0>
117       sector_counters_;
118 };
119 
120 }  // namespace pw::kvs
121