22#include "pw_containers/vector.h"
23#include "pw_kvs/checksum.h"
24#include "pw_kvs/flash_memory.h"
25#include "pw_kvs/format.h"
26#include "pw_kvs/internal/entry.h"
27#include "pw_kvs/internal/entry_cache.h"
28#include "pw_kvs/internal/key_descriptor.h"
29#include "pw_kvs/internal/sectors.h"
30#include "pw_kvs/internal/span_traits.h"
31#include "pw_span/span.h"
32#include "pw_status/status.h"
33#include "pw_status/status_with_size.h"
42enum class GargbageCollectOnWrite {
53enum class ErrorRecovery {
73 GargbageCollectOnWrite gc_on_write =
74 GargbageCollectOnWrite::kAsManySectorsNeeded;
78 ErrorRecovery recovery = ErrorRecovery::kLazy;
81 bool verify_on_read =
true;
84 bool verify_on_write =
true;
122 bool initialized()
const {
123 return initialized_ == InitializationState::kReady;
149 size_t offset_bytes = 0)
const;
157 template <
typename Pointer,
158 typename = std::enable_if_t<std::is_pointer<Pointer>::value>>
159 Status Get(
const std::string_view& key,
const Pointer& pointer)
const {
160 using T = std::remove_reference_t<std::remove_pointer_t<Pointer>>;
161 CheckThatObjectCanBePutOrGet<T>();
162 return FixedSizeGet(key, pointer,
sizeof(T));
184 template <
typename T,
185 typename std::enable_if_t<ConvertsToSpan<T>::value>* =
nullptr>
186 Status Put(
const std::string_view& key,
const T& value) {
187 return PutBytes(key, as_bytes(internal::make_span(value)));
190 template <
typename T,
191 typename std::enable_if_t<!ConvertsToSpan<T>::value>* =
nullptr>
192 Status Put(
const std::string_view& key,
const T& value) {
193 CheckThatObjectCanBePutOrGet<T>();
233 return FullMaintenanceHelper(MaintenanceType::kHeavy);
244 return FullMaintenanceHelper(MaintenanceType::kRegular);
253 void LogDebugInfo()
const;
262 const char*
key()
const {
return key_buffer_.data(); }
267 size_t offset_bytes = 0)
const {
268 return kvs_.
Get(
key(), *iterator_, value_buffer, offset_bytes);
271 template <
typename Pointer,
272 typename = std::enable_if_t<std::is_pointer<Pointer>::value>>
273 Status Get(
const Pointer& pointer)
const {
274 using T = std::remove_reference_t<std::remove_pointer_t<Pointer>>;
275 CheckThatObjectCanBePutOrGet<T>();
276 return kvs_.FixedSizeGet(
key(), *iterator_, pointer,
sizeof(T));
284 friend class iterator;
286 constexpr Item(
const KeyValueStore& kvs,
287 const internal::EntryCache::const_iterator& item_iterator)
288 : kvs_(kvs), iterator_(item_iterator), key_buffer_{} {}
292 const KeyValueStore& kvs_;
293 internal::EntryCache::const_iterator iterator_;
296 std::array<char, internal::Entry::kMaxKeyLength + 1> key_buffer_;
307 const iterator original(item_.kvs_, item_.iterator_);
323 return item_.iterator_ == rhs.item_.iterator_;
328 return item_.iterator_ != rhs.item_.iterator_;
336 const internal::EntryCache::const_iterator& item_iterator)
337 : item_(kvs, item_iterator) {}
342 using const_iterator = iterator;
350 size_t size()
const {
return entry_cache_.present_entries(); }
355 return entry_cache_.total_entries();
359 size_t max_size()
const {
return entry_cache_.max_entries(); }
397 size_t redundancy()
const {
return entry_cache_.redundancy(); }
410 size_t partition_sector_size_bytes) {
411 return partition_sector_size_bytes - Entry::entry_overhead();
419 using Address = FlashPartition::Address;
420 using Entry = internal::Entry;
421 using KeyDescriptor = internal::KeyDescriptor;
422 using SectorDescriptor = internal::SectorDescriptor;
431 const SectorDescriptor** temp_sectors_to_skip,
436 using EntryMetadata = internal::EntryMetadata;
437 using EntryState = internal::EntryState;
439 template <
typename T>
440 static constexpr void CheckThatObjectCanBePutOrGet() {
442 std::is_trivially_copyable<T>::value && !std::is_pointer<T>::value,
443 "Only trivially copyable, non-pointer objects may be Put and Get by "
444 "value. Any value may be stored by converting it to a byte span "
445 "with as_bytes(span(&value, 1)) or "
446 "as_writable_bytes(span(&value, 1)).");
449 Status InitializeMetadata();
450 Status LoadEntry(Address entry_address, Address* next_entry_address);
451 Status ScanForEntry(
const SectorDescriptor& sector,
452 Address start_address,
453 Address* next_entry_address);
461 Status RemoveDeletedKeyEntries();
467 Status ReadEntry(
const EntryMetadata& metadata, Entry& entry)
const;
481 Status FindEntry(std::string_view key, EntryMetadata* metadata_out)
const;
489 Status FindExisting(std::string_view key, EntryMetadata* metadata_out)
const;
492 const EntryMetadata& metadata,
494 size_t offset_bytes)
const;
496 Status FixedSizeGet(std::string_view key,
498 size_t size_bytes)
const;
500 Status FixedSizeGet(std::string_view key,
501 const EntryMetadata& metadata,
503 size_t size_bytes)
const;
505 Status CheckWriteOperation(std::string_view key)
const;
506 Status CheckReadOperation(std::string_view key)
const;
508 Status WriteEntryForExistingKey(EntryMetadata& metadata,
509 EntryState new_state,
510 std::string_view key,
515 Status WriteEntry(std::string_view key,
517 EntryState new_state,
518 EntryMetadata* prior_metadata =
nullptr,
519 const internal::Entry* prior_entry =
nullptr);
521 EntryMetadata CreateOrUpdateKeyDescriptor(
const Entry& new_entry,
522 std::string_view key,
523 EntryMetadata* prior_metadata,
526 EntryMetadata UpdateKeyDescriptor(
const Entry& entry,
528 EntryMetadata* prior_metadata,
531 Status GetAddressesForWrite(Address* write_addresses,
size_t write_size);
533 Status GetSectorForWrite(SectorDescriptor** sector,
537 Status MarkSectorCorruptIfNotOk(
Status status, SectorDescriptor* sector);
539 Status AppendEntry(
const Entry& entry,
540 std::string_view key,
544 SectorDescriptor* new_sector,
545 Address new_address);
547 Status RelocateEntry(
const EntryMetadata& metadata,
548 KeyValueStore::Address& address,
560 enum class MaintenanceType {
564 Status FullMaintenanceHelper(MaintenanceType maintenance_type);
570 Status RelocateKeyAddressesInSector(SectorDescriptor& sector_to_gc,
571 const EntryMetadata& metadata,
574 Status GarbageCollectSector(SectorDescriptor& sector_to_gc,
583 Status AddRedundantEntries(EntryMetadata& metadata);
585 Status RepairCorruptSectors();
587 Status EnsureFreeSectorExists();
589 Status EnsureEntryRedundancy();
595 internal::Entry CreateEntry(Address address,
596 std::string_view key,
600 void LogSectors()
const;
601 void LogKeyDescriptor()
const;
603 FlashPartition& partition_;
604 const internal::EntryFormats formats_;
607 internal::Sectors sectors_;
611 internal::EntryCache entry_cache_;
620 static constexpr size_t kGcUsageThresholdPercentage = 70;
622 enum class InitializationState {
633 InitializationState initialized_;
637 mutable bool error_detected_;
639 struct InternalStats {
640 size_t sector_erase_count;
641 size_t corrupt_sectors_recovered;
642 size_t missing_redundant_entries_recovered;
644 InternalStats internal_stats_;
646 uint32_t last_transaction_id_;
649template <
size_t kMaxEntries,
650 size_t kMaxUsableSectors,
651 size_t kRedundancy = 1,
652 size_t kEntryFormats = 1>
658 const EntryFormat& format,
663 reinterpret_cast<const EntryFormat (&)[1]
>(format)),
665 static_assert(kEntryFormats == 1,
666 "kEntryFormats EntryFormats must be specified");
679 temp_sectors_to_skip_,
685 std::copy(formats.begin(), formats.end(), formats_.begin());
689 static_assert(kMaxEntries > 0u);
690 static_assert(kMaxUsableSectors > 0u);
691 static_assert(kRedundancy > 0u);
692 static_assert(kEntryFormats > 0u);
702 const SectorDescriptor* temp_sectors_to_skip_[2 * kRedundancy - 1];
711 internal::EntryCache::AddressList<kRedundancy, kMaxEntries> addresses_;
714 std::array<EntryFormat, kEntryFormats> formats_;
Definition: status_with_size.h:51
Representation of a key-value entry during iteration.
Definition: key_value_store.h:259
Supported iteration methods.
Definition: key_value_store.h:300
Definition: key_value_store.h:653
Definition: key_value_store.h:111
Definition: span_impl.h:235
iterator end() const
Definition: key_value_store.h:347
size_t max_key_value_size_bytes() const
Definition: key_value_store.h:403
StatusWithSize ValueSize(std::string_view key) const
size_t max_size() const
Definition: key_value_store.h:359
StatusWithSize Get(span< std::byte > value_buffer, size_t offset_bytes=0) const
Definition: key_value_store.h:266
uint32_t transaction_count() const
Definition: key_value_store.h:367
const Item * operator->()
Reads the entry into the Item object.
Definition: key_value_store.h:319
iterator operator++(int)
Increments to the next key-value entry in the container.
Definition: key_value_store.h:306
const char * key() const
Definition: key_value_store.h:262
size_t sector_erase_count
The total count of individual sector erases that have been performed.
Definition: key_value_store.h:383
StatusWithSize Get(std::string_view key, span< std::byte > value, size_t offset_bytes=0) const
constexpr bool operator!=(const iterator &rhs) const
Inequality comparison of two entries.
Definition: key_value_store.h:327
const Item & operator*()
Reads the entry's key from flash.
Definition: key_value_store.h:313
size_t size() const
Definition: key_value_store.h:350
size_t corrupt_sectors_recovered
The number of corrupt sectors that have been recovered.
Definition: key_value_store.h:385
size_t redundancy() const
Definition: key_value_store.h:397
size_t writable_bytes
Definition: key_value_store.h:375
Status FullMaintenance()
Definition: key_value_store.h:243
bool error_detected() const
Definition: key_value_store.h:400
size_t empty() const
Definition: key_value_store.h:362
Status Delete(std::string_view key)
Status Put(const std::string_view &key, const T &value)
Definition: key_value_store.h:186
Status HeavyMaintenance()
Definition: key_value_store.h:232
size_t reclaimable_bytes
Definition: key_value_store.h:381
constexpr bool operator==(const iterator &rhs) const
Equality comparison of two entries.
Definition: key_value_store.h:322
iterator & operator++()
Increments to the next key-value entry in the container.
size_t in_use_bytes
The number of bytes in the KVS that are already in use.
Definition: key_value_store.h:377
Status Get(const std::string_view &key, const Pointer &pointer) const
Definition: key_value_store.h:159
StorageStats GetStorageStats() const
Status PartialMaintenance()
size_t missing_redundant_entries_recovered
Definition: key_value_store.h:388
size_t total_entries_with_deleted() const
Definition: key_value_store.h:354
static constexpr size_t max_key_value_size_bytes(size_t partition_sector_size_bytes)
Definition: key_value_store.h:409
The Pigweed namespace.
Definition: alignment.h:27
Definition: key_value_store.h:372
Definition: key_value_store.h:68