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"
38enum class GargbageCollectOnWrite {
49enum class ErrorRecovery {
69 GargbageCollectOnWrite gc_on_write =
70 GargbageCollectOnWrite::kAsManySectorsNeeded;
74 ErrorRecovery recovery = ErrorRecovery::kLazy;
77 bool verify_on_read =
true;
80 bool verify_on_write =
true;
125 bool initialized()
const {
126 return initialized_ == InitializationState::kReady;
162 span<std::byte> value,
163 size_t offset_bytes = 0)
const;
171 template <
typename Pointer,
172 typename = std::enable_if_t<std::is_pointer<Pointer>::value>>
173 Status Get(
const std::string_view& key,
const Pointer& pointer)
const {
174 using T = std::remove_reference_t<std::remove_pointer_t<Pointer>>;
175 CheckThatObjectCanBePutOrGet<T>();
176 return FixedSizeGet(key, pointer,
sizeof(T));
209 template <
typename T,
210 typename std::enable_if_t<ConvertsToSpan<T>::value>* =
nullptr>
211 Status Put(
const std::string_view& key,
const T& value) {
212 return PutBytes(key, as_bytes(internal::make_span(value)));
215 template <
typename T,
216 typename std::enable_if_t<!ConvertsToSpan<T>::value>* =
nullptr>
217 Status Put(
const std::string_view& key,
const T& value) {
218 CheckThatObjectCanBePutOrGet<T>();
219 return PutBytes(key, as_bytes(span<const T>(&value, 1)));
278 return FullMaintenanceHelper(MaintenanceType::kHeavy);
289 return FullMaintenanceHelper(MaintenanceType::kRegular);
298 void LogDebugInfo()
const;
307 const char*
key()
const {
return key_buffer_.data(); }
312 size_t offset_bytes = 0)
const {
313 return kvs_.
Get(
key(), *iterator_, value_buffer, offset_bytes);
316 template <
typename Pointer,
317 typename = std::enable_if_t<std::is_pointer<Pointer>::value>>
318 Status Get(
const Pointer& pointer)
const {
319 using T = std::remove_reference_t<std::remove_pointer_t<Pointer>>;
320 CheckThatObjectCanBePutOrGet<T>();
321 return kvs_.FixedSizeGet(
key(), *iterator_, pointer,
sizeof(T));
329 friend class iterator;
331 constexpr Item(
const KeyValueStore& kvs,
332 const internal::EntryCache::const_iterator& item_iterator)
333 : kvs_(kvs), iterator_(item_iterator), key_buffer_{} {}
337 const KeyValueStore& kvs_;
338 internal::EntryCache::const_iterator iterator_;
341 std::array<char, internal::Entry::kMaxKeyLength + 1> key_buffer_;
352 const iterator original(item_.kvs_, item_.iterator_);
368 return item_.iterator_ == rhs.item_.iterator_;
373 return item_.iterator_ != rhs.item_.iterator_;
381 const internal::EntryCache::const_iterator& item_iterator)
382 : item_(kvs, item_iterator) {}
387 using const_iterator = iterator;
395 size_t size()
const {
return entry_cache_.present_entries(); }
400 return entry_cache_.total_entries();
404 size_t max_size()
const {
return entry_cache_.max_entries(); }
442 size_t redundancy()
const {
return entry_cache_.redundancy(); }
455 size_t partition_sector_size_bytes) {
456 return partition_sector_size_bytes - Entry::entry_overhead();
464 using Address = FlashPartition::Address;
465 using Entry = internal::Entry;
466 using KeyDescriptor = internal::KeyDescriptor;
467 using SectorDescriptor = internal::SectorDescriptor;
472 span<const EntryFormat> formats,
476 const SectorDescriptor** temp_sectors_to_skip,
481 using EntryMetadata = internal::EntryMetadata;
482 using EntryState = internal::EntryState;
484 template <
typename T>
485 static constexpr void CheckThatObjectCanBePutOrGet() {
487 std::is_trivially_copyable<T>::value && !std::is_pointer<T>::value,
488 "Only trivially copyable, non-pointer objects may be Put and Get by "
489 "value. Any value may be stored by converting it to a byte span "
490 "with as_bytes(span(&value, 1)) or "
491 "as_writable_bytes(span(&value, 1)).");
494 Status InitializeMetadata();
495 Status LoadEntry(Address entry_address, Address* next_entry_address);
496 Status ScanForEntry(
const SectorDescriptor& sector,
497 Address start_address,
498 Address* next_entry_address);
506 Status RemoveDeletedKeyEntries();
508 Status PutBytes(std::string_view key, span<const std::byte> value);
512 Status ReadEntry(
const EntryMetadata& metadata, Entry& entry)
const;
526 Status FindEntry(std::string_view key, EntryMetadata* metadata_out)
const;
534 Status FindExisting(std::string_view key, EntryMetadata* metadata_out)
const;
537 const EntryMetadata& metadata,
538 span<std::byte> value_buffer,
539 size_t offset_bytes)
const;
541 Status FixedSizeGet(std::string_view key,
543 size_t size_bytes)
const;
545 Status FixedSizeGet(std::string_view key,
546 const EntryMetadata& metadata,
548 size_t size_bytes)
const;
550 Status CheckWriteOperation(std::string_view key)
const;
551 Status CheckReadOperation(std::string_view key)
const;
553 Status WriteEntryForExistingKey(EntryMetadata& metadata,
554 EntryState new_state,
555 std::string_view key,
556 span<const std::byte> value);
558 Status WriteEntryForNewKey(std::string_view key, span<const std::byte> value);
560 Status WriteEntry(std::string_view key,
561 span<const std::byte> value,
562 EntryState new_state,
563 EntryMetadata* prior_metadata =
nullptr,
564 const internal::Entry* prior_entry =
nullptr);
566 EntryMetadata CreateOrUpdateKeyDescriptor(
const Entry& new_entry,
567 std::string_view key,
568 EntryMetadata* prior_metadata,
571 EntryMetadata UpdateKeyDescriptor(
const Entry& entry,
573 EntryMetadata* prior_metadata,
576 Status GetAddressesForWrite(Address* write_addresses,
size_t write_size);
578 Status GetSectorForWrite(SectorDescriptor** sector,
580 span<const Address> reserved_addresses);
582 Status MarkSectorCorruptIfNotOk(
Status status, SectorDescriptor* sector);
584 Status AppendEntry(
const Entry& entry,
585 std::string_view key,
586 span<const std::byte> value);
589 SectorDescriptor* new_sector,
590 Address new_address);
592 Status RelocateEntry(
const EntryMetadata& metadata,
593 KeyValueStore::Address& address,
594 span<const Address> reserved_addresses);
605 enum class MaintenanceType {
609 Status FullMaintenanceHelper(MaintenanceType maintenance_type);
613 Status GarbageCollect(span<const Address> reserved_addresses);
615 Status RelocateKeyAddressesInSector(SectorDescriptor& sector_to_gc,
616 const EntryMetadata& metadata,
617 span<const Address> reserved_addresses);
619 Status GarbageCollectSector(SectorDescriptor& sector_to_gc,
620 span<const Address> reserved_addresses);
628 Status AddRedundantEntries(EntryMetadata& metadata);
630 Status RepairCorruptSectors();
632 Status EnsureFreeSectorExists();
634 Status EnsureEntryRedundancy();
640 internal::Entry CreateEntry(Address address,
641 std::string_view key,
642 span<const std::byte> value,
645 void LogSectors()
const;
646 void LogKeyDescriptor()
const;
648 FlashPartition& partition_;
649 const internal::EntryFormats formats_;
652 internal::Sectors sectors_;
656 internal::EntryCache entry_cache_;
665 static constexpr size_t kGcUsageThresholdPercentage = 70;
667 enum class InitializationState {
678 InitializationState initialized_;
682 mutable bool error_detected_;
684 struct InternalStats {
685 size_t sector_erase_count;
686 size_t corrupt_sectors_recovered;
687 size_t missing_redundant_entries_recovered;
689 InternalStats internal_stats_;
691 uint32_t last_transaction_id_;
694template <
size_t kMaxEntries,
695 size_t kMaxUsableSectors,
696 size_t kRedundancy = 1,
697 size_t kEntryFormats = 1>
703 const EntryFormat& format,
707 span<const EntryFormat, kEntryFormats>(
708 reinterpret_cast<const EntryFormat (&)[1]
>(format)),
710 static_assert(kEntryFormats == 1,
711 "kEntryFormats EntryFormats must be specified");
717 span<const EntryFormat, kEntryFormats> formats,
724 temp_sectors_to_skip_,
730 std::copy(formats.begin(), formats.end(), formats_.begin());
734 static_assert(kMaxEntries > 0u);
735 static_assert(kMaxUsableSectors > 0u);
736 static_assert(kRedundancy > 0u);
737 static_assert(kEntryFormats > 0u);
747 const SectorDescriptor* temp_sectors_to_skip_[2 * kRedundancy - 1];
756 internal::EntryCache::AddressList<kRedundancy, kMaxEntries> addresses_;
759 std::array<EntryFormat, kEntryFormats> formats_;
Definition: status_with_size.h:49
Representation of a key-value entry during iteration.
Definition: key_value_store.h:304
StatusWithSize Get(span< std::byte > value_buffer, size_t offset_bytes=0) const
Definition: key_value_store.h:311
const char * key() const
Definition: key_value_store.h:307
Supported iteration methods.
Definition: key_value_store.h:345
const Item * operator->()
Reads the entry into the Item object.
Definition: key_value_store.h:364
iterator operator++(int)
Increments to the next key-value entry in the container.
Definition: key_value_store.h:351
constexpr bool operator!=(const iterator &rhs) const
Inequality comparison of two entries.
Definition: key_value_store.h:372
const Item & operator*()
Reads the entry's key from flash.
Definition: key_value_store.h:358
constexpr bool operator==(const iterator &rhs) const
Equality comparison of two entries.
Definition: key_value_store.h:367
iterator & operator++()
Increments to the next key-value entry in the container.
Definition: key_value_store.h:698
Definition: key_value_store.h:107
iterator end() const
Definition: key_value_store.h:392
size_t max_key_value_size_bytes() const
Definition: key_value_store.h:448
StatusWithSize ValueSize(std::string_view key) const
size_t max_size() const
Definition: key_value_store.h:404
uint32_t transaction_count() const
Definition: key_value_store.h:412
StatusWithSize Get(std::string_view key, span< std::byte > value, size_t offset_bytes=0) const
size_t size() const
Definition: key_value_store.h:395
size_t redundancy() const
Definition: key_value_store.h:442
Status FullMaintenance()
Definition: key_value_store.h:288
bool error_detected() const
Definition: key_value_store.h:445
size_t empty() const
Definition: key_value_store.h:407
Status Delete(std::string_view key)
Status Put(const std::string_view &key, const T &value)
Definition: key_value_store.h:211
Status HeavyMaintenance()
Definition: key_value_store.h:277
Status Get(const std::string_view &key, const Pointer &pointer) const
Definition: key_value_store.h:173
StorageStats GetStorageStats() const
Status PartialMaintenance()
size_t total_entries_with_deleted() const
Definition: key_value_store.h:399
static constexpr size_t max_key_value_size_bytes(size_t partition_sector_size_bytes)
Definition: key_value_store.h:454
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27
Definition: key_value_store.h:417
size_t sector_erase_count
The total count of individual sector erases that have been performed.
Definition: key_value_store.h:428
size_t corrupt_sectors_recovered
The number of corrupt sectors that have been recovered.
Definition: key_value_store.h:430
size_t writable_bytes
Definition: key_value_store.h:420
size_t reclaimable_bytes
Definition: key_value_store.h:426
size_t in_use_bytes
The number of bytes in the KVS that are already in use.
Definition: key_value_store.h:422
size_t missing_redundant_entries_recovered
Definition: key_value_store.h:433
Definition: key_value_store.h:64