20 ErrorCode Get(Database::KeyBase& key)
override
22 auto ans = SearchKey(key.name_);
25 return ErrorCode::NOT_FOUND;
29 ReadFlashOrExit(ans, key_buffer);
31 if (key.raw_data_.size_ != key_buffer.
GetDataSize())
33 return ErrorCode::FAILED;
36 ReadFlashOrExit(GetKeyData(ans), key.raw_data_);
48 ErrorCode Set(KeyBase& key, RawData data)
override
50 return SetKey(key.name_, data.addr_, data.size_);
60 return AddKey(key.name_, key.raw_data_.addr_, key.raw_data_.size_);
70 explicit DatabaseRaw(Flash& flash,
size_t recycle_threshold = 128)
71 : recycle_threshold_(recycle_threshold), flash_(flash)
73 ASSERT(flash.MinEraseSize() * 2 <= flash_.Size());
74 ASSERT(flash_.MinWriteSize() <= MinWriteSize);
75 auto block_num =
static_cast<size_t>(flash_.Size() / flash.MinEraseSize());
76 block_size_ = block_num / 2 * flash.MinEraseSize();
92 if (!IsBlockValid(BlockType::MAIN))
94 if (!IsBlockValid(BlockType::BACKUP) || IsBlockEmpty(BlockType::BACKUP))
96 InitBlock(BlockType::MAIN);
100 size_t used_size = 0;
101 if (!TryGetUsedBlockSize(BlockType::BACKUP, used_size))
103 InvalidateBlock(BlockType::BACKUP);
104 InitBlock(BlockType::MAIN);
108 EraseFlashOrExit(0, block_size_);
109 CopyBlockPrefixAndChecksum(BlockType::MAIN, BlockType::BACKUP, used_size);
110 InvalidateBlock(BlockType::BACKUP);
114 else if (IsBlockValid(BlockType::BACKUP) && !IsBlockEmpty(BlockType::BACKUP))
117 InvalidateBlock(BlockType::BACKUP);
122 ReadFlashOrExit(key_offset, key);
123 size_t need_cycle = 0;
126 key_offset = GetNextKey(key_offset);
128 if (key_offset + AlignSize(
sizeof(
KeyInfo)) > GetChecksumOffset())
130 InitBlock(BlockType::MAIN);
134 ReadFlashOrExit(key_offset, key);
142 InitBlock(BlockType::MAIN);
151 if (need_cycle > recycle_threshold_)
166 InitBlock(BlockType::MAIN);
167 InitBlock(BlockType::BACKUP);
188 if (IsBlockEmpty(BlockType::MAIN))
190 return ErrorCode::OK;
195 ReadFlashOrExit(key_offset, key);
197 if (!IsBlockValid(BlockType::BACKUP) || !IsBlockEmpty(BlockType::BACKUP))
199 InitBlock(BlockType::BACKUP);
208 WriteFlashOrExit(write_buff_offset, new_key);
210 write_buff_offset += GetKeySize(write_buff_offset);
214 key_offset = GetNextKey(key_offset);
215 ReadFlashOrExit(key_offset, key);
222 WriteFlashOrExit(write_buff_offset, key);
223 write_buff_offset += AlignSize(
sizeof(
KeyInfo));
224 CopyFlashData(write_buff_offset, GetKeyName(key_offset), key.
GetNameLength());
226 CopyFlashData(write_buff_offset, GetKeyData(key_offset), key.
GetDataSize());
230 const size_t used_size = write_buff_offset - block_size_;
231 EraseFlashOrExit(0, block_size_);
232 CopyBlockPrefixAndChecksum(BlockType::MAIN, BlockType::BACKUP, used_size);
234 InitBlock(BlockType::BACKUP);
236 return ErrorCode::OK;
读写对齐布尔位图块的工具 (Helpers for reading and writing aligned boolean flag blocks).
static void SetFlag(BlockBoolData< BlockSize > &obj, bool value)
把一个布尔值编码进位图块 (Encode one boolean value into a flag block).
size_t OffsetOf(MemberType OwnerType::*member) noexcept
计算成员在宿主对象中的偏移量
KeyInfo key
紧跟在块头后的首个键头 / First key header stored right after the block header.
键信息结构,存储键的元数据 (Structure containing key metadata).
BlockBoolData< MinWriteSize > uninit
该键是否未初始化
BlockBoolData< MinWriteSize > available_flag
该键是否有效
uint32_t GetDataSize() const
获取数据字节数 (Get the payload size in bytes).
BlockBoolData< MinWriteSize > no_next_key
是否是最后一个键
uint8_t GetNameLength() const
获取键名长度 (Get the key name length).