blob: f966756d3f6960a17071b9bec4fe11e5dfae19c7 [file] [log] [blame]
David Rogers5cc5ce82020-03-13 19:19:03 -07001// 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
15#include "pw_kvs/flash_partition_with_stats.h"
16
17#include <cstdio>
18
19#include "pw_kvs/flash_memory.h"
20#include "pw_log/log.h"
21
22namespace pw::kvs {
23
24Status FlashPartitionWithStats::SaveStorageStats(const KeyValueStore& kvs,
25 const char* label) {
26 // If size is zero saving stats is disabled so do not save any stats.
27 if (sector_counters_.size() == 0) {
28 return Status::OK;
29 }
30
31 KeyValueStore::StorageStats stats = kvs.GetStorageStats();
32 size_t utilization_percentage = (stats.in_use_bytes * 100) / size_bytes();
33
34 const char* file_name = "flash_stats.csv";
35 std::FILE* out_file = std::fopen(file_name, "a+");
36 if (out_file == nullptr) {
37 PW_LOG_ERROR("Failed to dump to %s", file_name);
38 return Status::NOT_FOUND;
39 }
40
41 // If file is empty add the header row.
42 std::fseek(out_file, 0, SEEK_END);
43 if (std::ftell(out_file) == 0) {
44 std::fprintf(out_file,
45 "Test Name,Total Erases,Utilization Percentage,Transaction "
46 "Count,Entry Count");
47 for (size_t i = 0; i < sector_counters_.size(); i++) {
48 std::fprintf(out_file, ",Sector %zu", i);
49 }
50 std::fprintf(out_file, "\n");
51 }
52
53 std::fprintf(out_file, "\"%s\",%zu", label, total_erase_count());
54 std::fprintf(out_file,
55 ",%zu,%u,%zu",
56 utilization_percentage,
57 kvs.transaction_count(),
58 kvs.size());
59
60 for (size_t counter : sector_erase_counters()) {
61 std::fprintf(out_file, ",%zu", counter);
62 }
63
64 std::fprintf(out_file, "\n");
65 std::fclose(out_file);
66 return Status::OK;
67}
68
69Status FlashPartitionWithStats::Erase(Address address, size_t num_sectors) {
70 size_t base_index = address / FlashPartition::sector_size_bytes();
71 if (base_index < sector_counters_.size()) {
72 num_sectors = std::min(num_sectors, (sector_counters_.size() - base_index));
73 for (size_t i = 0; i < num_sectors; i++) {
74 sector_counters_[base_index + i]++;
75 }
76 }
77
78 return FlashPartition::Erase(address, num_sectors);
79}
80
81} // namespace pw::kvs