libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
lifecycle.hpp
1
20 ErrorCode Get(Database::KeyBase& key) override
21 {
22 auto ans = SearchKey(key.name_);
23 if (!ans)
24 {
25 return ErrorCode::NOT_FOUND;
26 }
27
28 KeyInfo key_buffer;
29 ReadFlashOrExit(ans, key_buffer);
30
31 if (key.raw_data_.size_ != key_buffer.GetDataSize())
32 {
33 return ErrorCode::FAILED;
34 }
35
36 ReadFlashOrExit(GetKeyData(ans), key.raw_data_);
37
38 return ErrorCode::OK;
39 }
40
48 ErrorCode Set(KeyBase& key, RawData data) override
49 {
50 return SetKey(key.name_, data.addr_, data.size_);
51 }
52
58 ErrorCode Add(KeyBase& key) override
59 {
60 return AddKey(key.name_, key.raw_data_.addr_, key.raw_data_.size_);
61 }
62
70 explicit DatabaseRaw(Flash& flash, size_t recycle_threshold = 128)
71 : recycle_threshold_(recycle_threshold), flash_(flash)
72 {
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();
77 Init();
78 }
79
90 void Init()
91 {
92 if (!IsBlockValid(BlockType::MAIN))
93 {
94 if (!IsBlockValid(BlockType::BACKUP) || IsBlockEmpty(BlockType::BACKUP))
95 {
96 InitBlock(BlockType::MAIN);
97 }
98 else
99 {
100 size_t used_size = 0;
101 if (!TryGetUsedBlockSize(BlockType::BACKUP, used_size))
102 {
103 InvalidateBlock(BlockType::BACKUP);
104 InitBlock(BlockType::MAIN);
105 }
106 else
107 {
108 EraseFlashOrExit(0, block_size_);
109 CopyBlockPrefixAndChecksum(BlockType::MAIN, BlockType::BACKUP, used_size);
110 InvalidateBlock(BlockType::BACKUP);
111 }
112 }
113 }
114 else if (IsBlockValid(BlockType::BACKUP) && !IsBlockEmpty(BlockType::BACKUP))
115 {
116 // A stale backup must not stay recoverable once the main block is already good.
117 InvalidateBlock(BlockType::BACKUP);
118 }
119
120 KeyInfo key;
121 size_t key_offset = LibXR::OffsetOf(&FlashInfo::key);
122 ReadFlashOrExit(key_offset, key);
123 size_t need_cycle = 0;
125 {
126 key_offset = GetNextKey(key_offset);
127
128 if (key_offset + AlignSize(sizeof(KeyInfo)) > GetChecksumOffset())
129 {
130 InitBlock(BlockType::MAIN);
131 break;
132 }
133
134 ReadFlashOrExit(key_offset, key);
135
136 // 当前策略仍然是“看到未完成键就整块重建”,还没有实现更细粒度的坏数据恢复。
137 // The current policy still rebuilds the whole block when it sees an
138 // incomplete key; finer-grained damaged-data recovery is not implemented
139 // yet.
141 {
142 InitBlock(BlockType::MAIN);
143 break;
144 }
146 {
147 need_cycle += 1;
148 }
149 }
150
151 if (need_cycle > recycle_threshold_)
152 {
153 Recycle();
154 }
155 }
156
164 void Restore()
165 {
166 InitBlock(BlockType::MAIN);
167 InitBlock(BlockType::BACKUP);
168 }
169
186 ErrorCode Recycle()
187 {
188 if (IsBlockEmpty(BlockType::MAIN))
189 {
190 return ErrorCode::OK;
191 }
192
193 KeyInfo key;
194 size_t key_offset = LibXR::OffsetOf(&FlashInfo::key);
195 ReadFlashOrExit(key_offset, key);
196
197 if (!IsBlockValid(BlockType::BACKUP) || !IsBlockEmpty(BlockType::BACKUP))
198 {
199 InitBlock(BlockType::BACKUP);
200 }
201
202 size_t write_buff_offset = LibXR::OffsetOf(&FlashInfo::key) + block_size_;
203
204 auto new_key = KeyInfo{};
205 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.uninit, false);
206 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.available_flag, false);
207 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.no_next_key, false);
208 WriteFlashOrExit(write_buff_offset, new_key);
209
210 write_buff_offset += GetKeySize(write_buff_offset);
211
212 do
213 {
214 key_offset = GetNextKey(key_offset);
215 ReadFlashOrExit(key_offset, key);
216
218 {
219 continue;
220 }
221
222 WriteFlashOrExit(write_buff_offset, key);
223 write_buff_offset += AlignSize(sizeof(KeyInfo));
224 CopyFlashData(write_buff_offset, GetKeyName(key_offset), key.GetNameLength());
225 write_buff_offset += AlignSize(key.GetNameLength());
226 CopyFlashData(write_buff_offset, GetKeyData(key_offset), key.GetDataSize());
227 write_buff_offset += AlignSize(key.GetDataSize());
229
230 const size_t used_size = write_buff_offset - block_size_;
231 EraseFlashOrExit(0, block_size_);
232 CopyBlockPrefixAndChecksum(BlockType::MAIN, BlockType::BACKUP, used_size);
233
234 InitBlock(BlockType::BACKUP);
235
236 return ErrorCode::OK;
237 }
读写对齐布尔位图块的工具 (Helpers for reading and writing aligned boolean flag blocks).
Definition layout.hpp:36
static void SetFlag(BlockBoolData< BlockSize > &obj, bool value)
把一个布尔值编码进位图块 (Encode one boolean value into a flag block).
Definition layout.hpp:43
ErrorCode
定义错误码枚举
size_t OffsetOf(MemberType OwnerType::*member) noexcept
计算成员在宿主对象中的偏移量
Definition libxr_def.hpp:88
KeyInfo key
紧跟在块头后的首个键头 / First key header stored right after the block header.
Definition layout.hpp:184
键信息结构,存储键的元数据 (Structure containing key metadata).
Definition layout.hpp:106
BlockBoolData< MinWriteSize > uninit
该键是否未初始化
Definition layout.hpp:109
BlockBoolData< MinWriteSize > available_flag
该键是否有效
Definition layout.hpp:108
uint32_t GetDataSize() const
获取数据字节数 (Get the payload size in bytes).
Definition layout.hpp:153
BlockBoolData< MinWriteSize > no_next_key
是否是最后一个键
Definition layout.hpp:107
uint8_t GetNameLength() const
获取键名长度 (Get the key name length).
Definition layout.hpp:138