1 // Copyright 2020 The Pigweed Authors
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
7 // https://www.apache.org/licenses/LICENSE-2.0
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
15 #define PW_LOG_MODULE_NAME "KVS"
16 #define PW_LOG_LEVEL PW_KVS_LOG_LEVEL
18 #include "pw_kvs/flash_partition_with_stats.h"
22 #include "pw_kvs/flash_memory.h"
23 #include "pw_kvs_private/config.h"
24 #include "pw_log/log.h"
28 Status FlashPartitionWithStats::SaveStorageStats(const KeyValueStore& kvs,
30 // If size is zero saving stats is disabled so do not save any stats.
31 if (sector_counters_.size() == 0) {
35 KeyValueStore::StorageStats stats = kvs.GetStorageStats();
36 size_t utilization_percentage = (stats.in_use_bytes * 100) / size_bytes();
38 const char* file_name = "flash_stats.csv";
39 std::FILE* out_file = std::fopen(file_name, "a+");
40 if (out_file == nullptr) {
41 PW_LOG_ERROR("Failed to dump to %s", file_name);
42 return Status::NotFound();
45 // If file is empty add the header row.
46 std::fseek(out_file, 0, SEEK_END);
47 if (std::ftell(out_file) == 0) {
48 std::fprintf(out_file,
49 "Test Name,Total Erases,Utilization Percentage,Transaction "
51 for (size_t i = 0; i < sector_counters_.size(); i++) {
52 std::fprintf(out_file, ",Sector %zu", i);
54 std::fprintf(out_file, "\n");
57 std::fprintf(out_file, "\"%s\",%zu", label, total_erase_count());
58 std::fprintf(out_file,
60 utilization_percentage,
61 unsigned(kvs.transaction_count()),
64 for (size_t counter : sector_erase_counters()) {
65 std::fprintf(out_file, ",%zu", counter);
68 std::fprintf(out_file, "\n");
69 std::fclose(out_file);
73 Status FlashPartitionWithStats::Erase(Address address, size_t num_sectors) {
74 size_t base_index = address / FlashPartition::sector_size_bytes();
75 if (base_index < sector_counters_.size()) {
76 num_sectors = std::min(num_sectors, (sector_counters_.size() - base_index));
77 for (size_t i = 0; i < num_sectors; i++) {
78 sector_counters_[base_index + i]++;
82 return FlashPartition::Erase(address, num_sectors);
85 } // namespace pw::kvs