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;
129 bool initialized()
const {
130 return initialized_ == InitializationState::kReady;
167 size_t offset_bytes = 0)
const;
175 template <
typename Pointer,
176 typename = std::enable_if_t<std::is_pointer<Pointer>::value>>
177 Status Get(
const std::string_view& key,
const Pointer& pointer)
const {
178 using T = std::remove_reference_t<std::remove_pointer_t<Pointer>>;
179 CheckThatObjectCanBePutOrGet<T>();
180 return FixedSizeGet(key, pointer,
sizeof(T));
213 template <
typename T,
214 typename std::enable_if_t<ConvertsToSpan<T>::value>* =
nullptr>
215 Status Put(
const std::string_view& key,
const T& value) {
216 return PutBytes(key, as_bytes(internal::make_span(value)));
219 template <
typename T,
220 typename std::enable_if_t<!ConvertsToSpan<T>::value>* =
nullptr>
221 Status Put(
const std::string_view& key,
const T& value) {
222 CheckThatObjectCanBePutOrGet<T>();
282 return FullMaintenanceHelper(MaintenanceType::kHeavy);
293 return FullMaintenanceHelper(MaintenanceType::kRegular);
302 void LogDebugInfo()
const;
311 const char*
key()
const {
return key_buffer_.data(); }
316 size_t offset_bytes = 0)
const {
317 return kvs_.
Get(
key(), *iterator_, value_buffer, offset_bytes);
320 template <
typename Pointer,
321 typename = std::enable_if_t<std::is_pointer<Pointer>::value>>
322 Status Get(
const Pointer& pointer)
const {
323 using T = std::remove_reference_t<std::remove_pointer_t<Pointer>>;
324 CheckThatObjectCanBePutOrGet<T>();
325 return kvs_.FixedSizeGet(
key(), *iterator_, pointer,
sizeof(T));
333 friend class iterator;
335 constexpr Item(
const KeyValueStore& kvs,
336 const internal::EntryCache::const_iterator& item_iterator)
337 : kvs_(kvs), iterator_(item_iterator), key_buffer_{} {}
341 const KeyValueStore& kvs_;
342 internal::EntryCache::const_iterator iterator_;
345 std::array<char, internal::Entry::kMaxKeyLength + 1> key_buffer_;
356 const iterator original(item_.kvs_, item_.iterator_);
372 return item_.iterator_ == rhs.item_.iterator_;
377 return item_.iterator_ != rhs.item_.iterator_;
385 const internal::EntryCache::const_iterator& item_iterator)
386 : item_(kvs, item_iterator) {}
391 using const_iterator = iterator;
399 size_t size()
const {
return entry_cache_.present_entries(); }
404 return entry_cache_.total_entries();
408 size_t max_size()
const {
return entry_cache_.max_entries(); }
446 size_t redundancy()
const {
return entry_cache_.redundancy(); }
459 size_t partition_sector_size_bytes) {
460 return partition_sector_size_bytes - Entry::entry_overhead();
468 using Address = FlashPartition::Address;
469 using Entry = internal::Entry;
470 using KeyDescriptor = internal::KeyDescriptor;
471 using SectorDescriptor = internal::SectorDescriptor;
480 const SectorDescriptor** temp_sectors_to_skip,
485 using EntryMetadata = internal::EntryMetadata;
486 using EntryState = internal::EntryState;
488 template <
typename T>
489 static constexpr void CheckThatObjectCanBePutOrGet() {
491 std::is_trivially_copyable<T>::value && !std::is_pointer<T>::value,
492 "Only trivially copyable, non-pointer objects may be Put and Get by "
493 "value. Any value may be stored by converting it to a byte span "
494 "with as_bytes(span(&value, 1)) or "
495 "as_writable_bytes(span(&value, 1)).");
498 Status InitializeMetadata();
499 Status LoadEntry(Address entry_address, Address* next_entry_address);
500 Status ScanForEntry(
const SectorDescriptor& sector,
501 Address start_address,
502 Address* next_entry_address);
510 Status RemoveDeletedKeyEntries();
516 Status ReadEntry(
const EntryMetadata& metadata, Entry& entry)
const;
530 Status FindEntry(std::string_view key, EntryMetadata* metadata_out)
const;
538 Status FindExisting(std::string_view key, EntryMetadata* metadata_out)
const;
541 const EntryMetadata& metadata,
543 size_t offset_bytes)
const;
545 Status FixedSizeGet(std::string_view key,
547 size_t size_bytes)
const;
549 Status FixedSizeGet(std::string_view key,
550 const EntryMetadata& metadata,
552 size_t size_bytes)
const;
554 Status CheckWriteOperation(std::string_view key)
const;
555 Status CheckReadOperation(std::string_view key)
const;
557 Status WriteEntryForExistingKey(EntryMetadata& metadata,
558 EntryState new_state,
559 std::string_view key,
564 Status WriteEntry(std::string_view key,
566 EntryState new_state,
567 EntryMetadata* prior_metadata =
nullptr,
568 const internal::Entry* prior_entry =
nullptr);
570 EntryMetadata CreateOrUpdateKeyDescriptor(
const Entry& new_entry,
571 std::string_view key,
572 EntryMetadata* prior_metadata,
575 EntryMetadata UpdateKeyDescriptor(
const Entry& entry,
577 EntryMetadata* prior_metadata,
580 Status GetAddressesForWrite(Address* write_addresses,
size_t write_size);
582 Status GetSectorForWrite(SectorDescriptor** sector,
586 Status MarkSectorCorruptIfNotOk(
Status status, SectorDescriptor* sector);
588 Status AppendEntry(
const Entry& entry,
589 std::string_view key,
593 SectorDescriptor* new_sector,
594 Address new_address);
596 Status RelocateEntry(
const EntryMetadata& metadata,
597 KeyValueStore::Address& address,
609 enum class MaintenanceType {
613 Status FullMaintenanceHelper(MaintenanceType maintenance_type);
619 Status RelocateKeyAddressesInSector(SectorDescriptor& sector_to_gc,
620 const EntryMetadata& metadata,
623 Status GarbageCollectSector(SectorDescriptor& sector_to_gc,
632 Status AddRedundantEntries(EntryMetadata& metadata);
634 Status RepairCorruptSectors();
636 Status EnsureFreeSectorExists();
638 Status EnsureEntryRedundancy();
644 internal::Entry CreateEntry(Address address,
645 std::string_view key,
649 void LogSectors()
const;
650 void LogKeyDescriptor()
const;
652 FlashPartition& partition_;
653 const internal::EntryFormats formats_;
656 internal::Sectors sectors_;
660 internal::EntryCache entry_cache_;
669 static constexpr size_t kGcUsageThresholdPercentage = 70;
671 enum class InitializationState {
682 InitializationState initialized_;
686 mutable bool error_detected_;
688 struct InternalStats {
689 size_t sector_erase_count;
690 size_t corrupt_sectors_recovered;
691 size_t missing_redundant_entries_recovered;
693 InternalStats internal_stats_;
695 uint32_t last_transaction_id_;
698template <
size_t kMaxEntries,
699 size_t kMaxUsableSectors,
700 size_t kRedundancy = 1,
701 size_t kEntryFormats = 1>
707 const EntryFormat& format,
712 reinterpret_cast<const EntryFormat (&)[1]
>(format)),
714 static_assert(kEntryFormats == 1,
715 "kEntryFormats EntryFormats must be specified");
728 temp_sectors_to_skip_,
734 std::copy(formats.begin(), formats.end(), formats_.begin());
738 static_assert(kMaxEntries > 0u);
739 static_assert(kMaxUsableSectors > 0u);
740 static_assert(kRedundancy > 0u);
741 static_assert(kEntryFormats > 0u);
751 const SectorDescriptor* temp_sectors_to_skip_[2 * kRedundancy - 1];
760 internal::EntryCache::AddressList<kRedundancy, kMaxEntries> addresses_;
763 std::array<EntryFormat, kEntryFormats> formats_;
Definition: status_with_size.h:51
Representation of a key-value entry during iteration.
Definition: key_value_store.h:308
Supported iteration methods.
Definition: key_value_store.h:349
Definition: key_value_store.h:702
Definition: key_value_store.h:111
Definition: span_impl.h:235
iterator end() const
Definition: key_value_store.h:396
size_t max_key_value_size_bytes() const
Definition: key_value_store.h:452
StatusWithSize ValueSize(std::string_view key) const
size_t max_size() const
Definition: key_value_store.h:408
StatusWithSize Get(span< std::byte > value_buffer, size_t offset_bytes=0) const
Definition: key_value_store.h:315
uint32_t transaction_count() const
Definition: key_value_store.h:416
const Item * operator->()
Reads the entry into the Item object.
Definition: key_value_store.h:368
iterator operator++(int)
Increments to the next key-value entry in the container.
Definition: key_value_store.h:355
const char * key() const
Definition: key_value_store.h:311
size_t sector_erase_count
The total count of individual sector erases that have been performed.
Definition: key_value_store.h:432
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:376
const Item & operator*()
Reads the entry's key from flash.
Definition: key_value_store.h:362
size_t size() const
Definition: key_value_store.h:399
size_t corrupt_sectors_recovered
The number of corrupt sectors that have been recovered.
Definition: key_value_store.h:434
size_t redundancy() const
Definition: key_value_store.h:446
size_t writable_bytes
Definition: key_value_store.h:424
Status FullMaintenance()
Definition: key_value_store.h:292
bool error_detected() const
Definition: key_value_store.h:449
size_t empty() const
Definition: key_value_store.h:411
Status Delete(std::string_view key)
Status Put(const std::string_view &key, const T &value)
Definition: key_value_store.h:215
Status HeavyMaintenance()
Definition: key_value_store.h:281
size_t reclaimable_bytes
Definition: key_value_store.h:430
constexpr bool operator==(const iterator &rhs) const
Equality comparison of two entries.
Definition: key_value_store.h:371
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:426
Status Get(const std::string_view &key, const Pointer &pointer) const
Definition: key_value_store.h:177
StorageStats GetStorageStats() const
Status PartialMaintenance()
size_t missing_redundant_entries_recovered
Definition: key_value_store.h:437
size_t total_entries_with_deleted() const
Definition: key_value_store.h:403
static constexpr size_t max_key_value_size_bytes(size_t partition_sector_size_bytes)
Definition: key_value_store.h:458
The Pigweed namespace.
Definition: alignment.h:27
Definition: key_value_store.h:421
Definition: key_value_store.h:68