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;
126 bool initialized()
const {
127 return initialized_ == InitializationState::kReady;
153 size_t offset_bytes = 0)
const;
161 template <
typename Pointer,
162 typename = std::enable_if_t<std::is_pointer<Pointer>::value>>
163 Status Get(
const std::string_view& key,
const Pointer& pointer)
const {
164 using T = std::remove_reference_t<std::remove_pointer_t<Pointer>>;
165 CheckThatObjectCanBePutOrGet<T>();
166 return FixedSizeGet(key, pointer,
sizeof(T));
188 template <
typename T,
189 typename std::enable_if_t<ConvertsToSpan<T>::value>* =
nullptr>
190 Status Put(
const std::string_view& key,
const T& value) {
191 return PutBytes(key, as_bytes(internal::make_span(value)));
194 template <
typename T,
195 typename std::enable_if_t<!ConvertsToSpan<T>::value>* =
nullptr>
196 Status Put(
const std::string_view& key,
const T& value) {
197 CheckThatObjectCanBePutOrGet<T>();
237 return FullMaintenanceHelper(MaintenanceType::kHeavy);
248 return FullMaintenanceHelper(MaintenanceType::kRegular);
257 void LogDebugInfo()
const;
266 const char*
key()
const {
return key_buffer_.data(); }
271 size_t offset_bytes = 0)
const {
272 return kvs_.
Get(
key(), *iterator_, value_buffer, offset_bytes);
275 template <
typename Pointer,
276 typename = std::enable_if_t<std::is_pointer<Pointer>::value>>
277 Status Get(
const Pointer& pointer)
const {
278 using T = std::remove_reference_t<std::remove_pointer_t<Pointer>>;
279 CheckThatObjectCanBePutOrGet<T>();
280 return kvs_.FixedSizeGet(
key(), *iterator_, pointer,
sizeof(T));
288 friend class iterator;
290 constexpr Item(
const KeyValueStore& kvs,
291 const internal::EntryCache::const_iterator& item_iterator)
292 : kvs_(kvs), iterator_(item_iterator), key_buffer_{} {}
296 const KeyValueStore& kvs_;
297 internal::EntryCache::const_iterator iterator_;
300 std::array<char, internal::Entry::kMaxKeyLength + 1> key_buffer_;
311 const iterator original(item_.kvs_, item_.iterator_);
327 return item_.iterator_ == rhs.item_.iterator_;
332 return item_.iterator_ != rhs.item_.iterator_;
340 const internal::EntryCache::const_iterator& item_iterator)
341 : item_(kvs, item_iterator) {}
346 using const_iterator = iterator;
354 size_t size()
const {
return entry_cache_.present_entries(); }
359 return entry_cache_.total_entries();
363 size_t max_size()
const {
return entry_cache_.max_entries(); }
401 size_t redundancy()
const {
return entry_cache_.redundancy(); }
414 size_t partition_sector_size_bytes) {
415 return partition_sector_size_bytes - Entry::entry_overhead();
423 using Address = FlashPartition::Address;
424 using Entry = internal::Entry;
425 using KeyDescriptor = internal::KeyDescriptor;
426 using SectorDescriptor = internal::SectorDescriptor;
435 const SectorDescriptor** temp_sectors_to_skip,
440 using EntryMetadata = internal::EntryMetadata;
441 using EntryState = internal::EntryState;
443 template <
typename T>
444 static constexpr void CheckThatObjectCanBePutOrGet() {
446 std::is_trivially_copyable<T>::value && !std::is_pointer<T>::value,
447 "Only trivially copyable, non-pointer objects may be Put and Get by "
448 "value. Any value may be stored by converting it to a byte span "
449 "with as_bytes(span(&value, 1)) or "
450 "as_writable_bytes(span(&value, 1)).");
453 Status InitializeMetadata();
454 Status LoadEntry(Address entry_address, Address* next_entry_address);
455 Status ScanForEntry(
const SectorDescriptor& sector,
456 Address start_address,
457 Address* next_entry_address);
465 Status RemoveDeletedKeyEntries();
471 Status ReadEntry(
const EntryMetadata& metadata, Entry& entry)
const;
485 Status FindEntry(std::string_view key, EntryMetadata* metadata_out)
const;
493 Status FindExisting(std::string_view key, EntryMetadata* metadata_out)
const;
496 const EntryMetadata& metadata,
498 size_t offset_bytes)
const;
500 Status FixedSizeGet(std::string_view key,
502 size_t size_bytes)
const;
504 Status FixedSizeGet(std::string_view key,
505 const EntryMetadata& metadata,
507 size_t size_bytes)
const;
509 Status CheckWriteOperation(std::string_view key)
const;
510 Status CheckReadOperation(std::string_view key)
const;
512 Status WriteEntryForExistingKey(EntryMetadata& metadata,
513 EntryState new_state,
514 std::string_view key,
519 Status WriteEntry(std::string_view key,
521 EntryState new_state,
522 EntryMetadata* prior_metadata =
nullptr,
523 const internal::Entry* prior_entry =
nullptr);
525 EntryMetadata CreateOrUpdateKeyDescriptor(
const Entry& new_entry,
526 std::string_view key,
527 EntryMetadata* prior_metadata,
530 EntryMetadata UpdateKeyDescriptor(
const Entry& entry,
532 EntryMetadata* prior_metadata,
535 Status GetAddressesForWrite(Address* write_addresses,
size_t write_size);
537 Status GetSectorForWrite(SectorDescriptor** sector,
541 Status MarkSectorCorruptIfNotOk(
Status status, SectorDescriptor* sector);
543 Status AppendEntry(
const Entry& entry,
544 std::string_view key,
548 SectorDescriptor* new_sector,
549 Address new_address);
551 Status RelocateEntry(
const EntryMetadata& metadata,
552 KeyValueStore::Address& address,
564 enum class MaintenanceType {
568 Status FullMaintenanceHelper(MaintenanceType maintenance_type);
574 Status RelocateKeyAddressesInSector(SectorDescriptor& sector_to_gc,
575 const EntryMetadata& metadata,
578 Status GarbageCollectSector(SectorDescriptor& sector_to_gc,
587 Status AddRedundantEntries(EntryMetadata& metadata);
589 Status RepairCorruptSectors();
591 Status EnsureFreeSectorExists();
593 Status EnsureEntryRedundancy();
599 internal::Entry CreateEntry(Address address,
600 std::string_view key,
604 void LogSectors()
const;
605 void LogKeyDescriptor()
const;
607 FlashPartition& partition_;
608 const internal::EntryFormats formats_;
611 internal::Sectors sectors_;
615 internal::EntryCache entry_cache_;
624 static constexpr size_t kGcUsageThresholdPercentage = 70;
626 enum class InitializationState {
637 InitializationState initialized_;
641 mutable bool error_detected_;
643 struct InternalStats {
644 size_t sector_erase_count;
645 size_t corrupt_sectors_recovered;
646 size_t missing_redundant_entries_recovered;
648 InternalStats internal_stats_;
650 uint32_t last_transaction_id_;
653template <
size_t kMaxEntries,
654 size_t kMaxUsableSectors,
655 size_t kRedundancy = 1,
656 size_t kEntryFormats = 1>
662 const EntryFormat& format,
667 reinterpret_cast<const EntryFormat (&)[1]
>(format)),
669 static_assert(kEntryFormats == 1,
670 "kEntryFormats EntryFormats must be specified");
683 temp_sectors_to_skip_,
689 std::copy(formats.begin(), formats.end(), formats_.begin());
693 static_assert(kMaxEntries > 0u);
694 static_assert(kMaxUsableSectors > 0u);
695 static_assert(kRedundancy > 0u);
696 static_assert(kEntryFormats > 0u);
706 const SectorDescriptor* temp_sectors_to_skip_[2 * kRedundancy - 1];
715 internal::EntryCache::AddressList<kRedundancy, kMaxEntries> addresses_;
718 std::array<EntryFormat, kEntryFormats> formats_;
Definition: status_with_size.h:51
Representation of a key-value entry during iteration.
Definition: key_value_store.h:263
Supported iteration methods.
Definition: key_value_store.h:304
Definition: key_value_store.h:657
Definition: key_value_store.h:115
Definition: span_impl.h:235
iterator end() const
Definition: key_value_store.h:351
size_t max_key_value_size_bytes() const
Definition: key_value_store.h:407
StatusWithSize ValueSize(std::string_view key) const
size_t max_size() const
Definition: key_value_store.h:363
StatusWithSize Get(span< std::byte > value_buffer, size_t offset_bytes=0) const
Definition: key_value_store.h:270
uint32_t transaction_count() const
Definition: key_value_store.h:371
const Item * operator->()
Reads the entry into the Item object.
Definition: key_value_store.h:323
iterator operator++(int)
Increments to the next key-value entry in the container.
Definition: key_value_store.h:310
const char * key() const
Definition: key_value_store.h:266
size_t sector_erase_count
The total count of individual sector erases that have been performed.
Definition: key_value_store.h:387
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:331
const Item & operator*()
Reads the entry's key from flash.
Definition: key_value_store.h:317
size_t size() const
Definition: key_value_store.h:354
size_t corrupt_sectors_recovered
The number of corrupt sectors that have been recovered.
Definition: key_value_store.h:389
size_t redundancy() const
Definition: key_value_store.h:401
size_t writable_bytes
Definition: key_value_store.h:379
Status FullMaintenance()
Definition: key_value_store.h:247
bool error_detected() const
Definition: key_value_store.h:404
size_t empty() const
Definition: key_value_store.h:366
Status Delete(std::string_view key)
Status Put(const std::string_view &key, const T &value)
Definition: key_value_store.h:190
Status HeavyMaintenance()
Definition: key_value_store.h:236
size_t reclaimable_bytes
Definition: key_value_store.h:385
constexpr bool operator==(const iterator &rhs) const
Equality comparison of two entries.
Definition: key_value_store.h:326
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:381
Status Get(const std::string_view &key, const Pointer &pointer) const
Definition: key_value_store.h:163
StorageStats GetStorageStats() const
Status PartialMaintenance()
size_t missing_redundant_entries_recovered
Definition: key_value_store.h:392
size_t total_entries_with_deleted() const
Definition: key_value_store.h:358
static constexpr size_t max_key_value_size_bytes(size_t partition_sector_size_bytes)
Definition: key_value_store.h:413
The Pigweed namespace.
Definition: alignment.h:27
Definition: key_value_store.h:376
Definition: key_value_store.h:68