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