libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
database.cpp
1#include "database.hpp"
2
3#include <cstddef>
4#include <cstdint>
5
6#include "libxr_def.hpp"
7
8using namespace LibXR;
9
11 : flash_(flash), max_buffer_size_(max_buffer_size)
12{
13 ASSERT(flash.MinEraseSize() * 2 <= flash.Size());
14 if (max_buffer_size * 2 > flash.Size())
15 {
16 max_buffer_size = flash.Size() / 2;
17 }
18 auto block_num = static_cast<size_t>(flash.Size() / flash.MinEraseSize());
19 block_size_ = block_num / 2 * flash.MinEraseSize();
20 buffer_ = new uint8_t[max_buffer_size];
21
22 Init();
23}
24
26{
27 memset(buffer_, 0xFF, max_buffer_size_);
28 FlashInfo* flash_data_ = reinterpret_cast<FlashInfo*>(buffer_);
29 flash_data_->header = FLASH_HEADER;
30 flash_data_->key = {0, 0, 0};
32
34 {
35 InitBlock(BlockType::BACKUP);
36 }
37
39 {
41 {
42 InitBlock(BlockType::MAIN);
43 }
44 else
45 {
49 }
50 }
51
53 {
54 InitBlock(BlockType::MAIN);
55 }
56
57 Load();
58}
59
68
70
72{
73 memset(buffer_, 0xFF, max_buffer_size_);
74 FlashInfo* flash_data_ = reinterpret_cast<FlashInfo*>(buffer_);
75 flash_data_->header = FLASH_HEADER;
76 flash_data_->key = {0, 0, 0};
80}
81
83{
84 auto ans = SearchKey(key.name_);
85 if (!ans)
86 {
87 return ErrorCode::NOT_FOUND;
88 }
89
90 KeyInfo key_buffer;
91 flash_.Read(ans, key_buffer);
92
93 if (key.raw_data_.size_ != key_buffer.GetDataSize())
94 {
95 return ErrorCode::FAILED;
96 }
97
98 GetKeyData(ans, key.raw_data_);
99
100 return ErrorCode::OK;
101}
102
103void DatabaseRawSequential::InitBlock(BlockType block)
104{
105 size_t offset = 0;
106 if (block == BlockType::BACKUP)
107 {
108 offset = block_size_;
109 }
110
111 flash_.Erase(offset, block_size_);
113}
114
122{
123 size_t offset = 0;
124 if (block == BlockType::BACKUP)
125 {
126 offset = block_size_;
127 }
128 FlashInfo flash_data_;
129 flash_.Read(offset, flash_data_);
130 return flash_data_.header == FLASH_HEADER;
131}
132
139{
140 size_t offset = 0;
141 if (block == BlockType::BACKUP)
142 {
143 offset = block_size_;
144 }
145 FlashInfo flash_data_;
146 flash_.Read(offset, flash_data_);
147 return flash_data_.key.GetNameLength() == 0;
148}
149
156{
157 size_t offset = 0;
158 if (block == BlockType::BACKUP)
159 {
160 offset = block_size_;
161 }
162 uint8_t checksum_byte = 0;
163 flash_.Read(offset + max_buffer_size_ / sizeof(CHECKSUM_BYTE) - 1, checksum_byte);
164 return checksum_byte != CHECKSUM_BYTE;
165}
166
167bool DatabaseRawSequential::HasLastKey(size_t offset)
168{
169 KeyInfo key;
170 flash_.Read(offset, key);
171 return key.GetNextKeyExist();
172}
173
174size_t DatabaseRawSequential::GetKeySize(size_t offset)
175{
176 KeyInfo key;
177 flash_.Read(offset, key);
178 return sizeof(KeyInfo) + key.GetNameLength() + key.GetDataSize();
179}
180
181size_t DatabaseRawSequential::GetNextKey(size_t offset)
182{
183 return offset + GetKeySize(offset);
184}
185
186size_t DatabaseRawSequential::GetLastKey(BlockType block)
187{
188 if (IsBlockEmpty(block))
189 {
190 return 0;
191 }
192
193 size_t offset = OFFSET_OF(FlashInfo, key);
194 while (HasLastKey(offset))
195 {
196 offset = GetNextKey(offset);
197 }
198 return offset;
199}
200
201void DatabaseRawSequential::SetNestKeyExist(size_t offset, bool exist)
202{
203 KeyInfo key;
204 flash_.Read(offset, key);
205 key.SetNextKeyExist(exist);
206 memcpy(buffer_ + offset, &key, sizeof(KeyInfo));
207}
208
209bool DatabaseRawSequential::KeyDataCompare(size_t offset, const void* data, size_t size)
210{
211 KeyInfo key;
212 flash_.Read(offset, key);
213 size_t key_data_offset = offset + sizeof(KeyInfo) + key.GetNameLength();
214 uint8_t data_buffer;
215 for (size_t i = 0; i < size; i++)
216 {
217 flash_.Read(key_data_offset + i, data_buffer);
218 if (data_buffer != ((uint8_t*)data)[i])
219 {
220 return true;
221 }
222 }
223 return false;
224}
225
226bool DatabaseRawSequential::KeyNameCompare(size_t offset, const char* name)
227{
228 KeyInfo key;
229 flash_.Read(offset, key);
230 for (size_t i = 0; i < key.GetNameLength(); i++)
231 {
232 uint8_t data_buffer;
233 flash_.Read(offset + sizeof(KeyInfo) + i, data_buffer);
234 if (data_buffer != name[i])
235 {
236 return true;
237 }
238 }
239 return false;
240}
241
242ErrorCode DatabaseRawSequential::AddKey(const char* name, const void* data, size_t size)
243{
244 if (auto ans = SearchKey(name))
245 {
246 return SetKey(ans, data, size);
247 }
248
249 const uint32_t NAME_LEN = strlen(name) + 1;
250 size_t last_key_offset = GetLastKey(BlockType::MAIN);
251 size_t key_buf_offset =
252 last_key_offset ? GetNextKey(last_key_offset) : OFFSET_OF(FlashInfo, key);
253
254 size_t end_pos_offset = key_buf_offset + sizeof(KeyInfo) + NAME_LEN + size;
255 if (end_pos_offset > max_buffer_size_ - 1)
256 {
257 return ErrorCode::FULL;
258 }
259
260 size_t data_ptr_offset = key_buf_offset + sizeof(KeyInfo);
261 memcpy(buffer_ + data_ptr_offset, name, NAME_LEN);
262 memcpy(buffer_ + data_ptr_offset + NAME_LEN, data, size);
263
264 KeyInfo key_buf = {0, static_cast<uint8_t>(NAME_LEN), static_cast<uint32_t>(size)};
265 memcpy(buffer_ + key_buf_offset, &key_buf, sizeof(KeyInfo));
266 if (last_key_offset)
267 {
268 SetNestKeyExist(last_key_offset, 1);
269 }
270
271 Save();
272 return ErrorCode::OK;
273}
274
275ErrorCode DatabaseRawSequential::SetKey(const char* name, const void* data, size_t size)
276{
277 if (size_t key_offset = SearchKey(name))
278 {
279 return SetKey(key_offset, data, size);
280 }
281 return ErrorCode::FAILED;
282}
283
284ErrorCode DatabaseRawSequential::SetKey(size_t offset, const void* data, size_t size)
285{
286 ASSERT(offset != 0);
287
288 KeyInfo key;
289 flash_.Read(offset, key);
290
291 if (key.GetDataSize() == size)
292 {
293 if (KeyDataCompare(offset, data, size))
294 {
295 memcpy(buffer_ + offset + sizeof(KeyInfo) + key.GetNameLength(), data, size);
296 Save();
297 }
298 return ErrorCode::OK;
299 }
300
301 return ErrorCode::FAILED;
302}
303
304ErrorCode DatabaseRawSequential::GetKeyData(size_t offset, RawData data)
305{
306 KeyInfo key;
307 flash_.Read(offset, key);
308 if (key.GetDataSize() > data.size_)
309 {
310 return ErrorCode::FAILED;
311 }
312 auto data_offset = offset + sizeof(KeyInfo) + key.GetNameLength();
313 flash_.Read(data_offset, {data.addr_, key.GetDataSize()});
314 return ErrorCode::OK;
315}
316
317size_t DatabaseRawSequential::SearchKey(const char* name)
318{
320 {
321 return 0;
322 }
323
324 size_t key_offset = OFFSET_OF(FlashInfo, key);
325 while (true)
326 {
327 if (KeyNameCompare(key_offset, name) == 0)
328 {
329 return key_offset;
330 }
331 if (!HasLastKey(key_offset))
332 {
333 break;
334 }
335 key_offset = GetNextKey(key_offset);
336 }
337 return 0;
338}
键的基类,存储键名及其数据 (Base class for keys, storing key name and associated data).
Definition database.hpp:28
RawData raw_data_
原始数据 (Raw data associated with the key).
Definition database.hpp:31
const char * name_
键名 (Key name).
Definition database.hpp:30
void Save()
保存当前缓冲区内容到 Flash (Save the current buffer content to Flash).
Definition database.cpp:60
static constexpr uint8_t CHECKSUM_BYTE
校验字节 (Checksum byte).
Definition database.hpp:304
uint32_t max_buffer_size_
最大缓冲区大小 (Maximum buffer size).
Definition database.hpp:309
ErrorCode Get(Database::KeyBase &key) override
获取数据库中的键值 (Retrieve the key's value from the database).
Definition database.cpp:82
void Init()
初始化数据库存储区,确保主备块正确 (Initialize database storage, ensuring main and backup blocks are valid).
Definition database.cpp:25
uint8_t * buffer_
数据缓冲区 (Data buffer).
Definition database.hpp:307
static constexpr uint32_t FLASH_HEADER
Flash 头部标识 (Flash header identifier).
Definition database.hpp:302
void Restore()
还原存储数据,清空 Flash 区域 (Restore storage data, clearing Flash memory area).
Definition database.cpp:71
bool IsBlockEmpty(BlockType block)
判断块是否为空 (Check if block is empty).
Definition database.cpp:138
uint32_t block_size_
Flash 块大小 (Flash block size).
Definition database.hpp:308
Flash & flash_
目标 Flash 存储设备 (Target Flash storage device).
Definition database.hpp:306
void Load()
从 Flash 加载数据到缓冲区 (Load data from Flash into the buffer).
Definition database.cpp:69
DatabaseRawSequential(Flash &flash, size_t max_buffer_size=256)
构造函数,初始化 Flash 存储和缓冲区 (Constructor initializing Flash storage and buffer).
Definition database.cpp:10
bool IsBlockInited(BlockType block)
判断块是否已初始化 (Check if block is initialized).
Definition database.cpp:121
@ BACKUP
备份块 (Backup block).
bool IsBlockError(BlockType block)
判断块是否损坏 (Check if block has an error).
Definition database.cpp:155
Abstract base class representing a flash memory interface. 抽象基类,表示闪存接口。
Definition flash.hpp:19
size_t Size() const
Returns the size of the flash memory area. 获取闪存存储区域的大小。
Definition flash.hpp:82
virtual ErrorCode Erase(size_t offset, size_t size)=0
Erases a section of the flash memory. 擦除闪存的指定区域。
virtual ErrorCode Write(size_t offset, ConstRawData data)=0
Writes data to the flash memory. 向闪存写入数据。
virtual ErrorCode Read(size_t offset, RawData data)
Reads data from the flash memory. 从闪存中读取数据。
Definition flash.cpp:12
size_t MinEraseSize() const
Returns the minimum erasable block size in bytes. 获取最小可擦除块大小(字节)。
Definition flash.hpp:64
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
LibXR 命名空间
Definition ch32_gpio.hpp:9
Flash 存储的块信息结构 (Structure representing a Flash storage block).
Definition database.hpp:280
KeyInfo key
该块的键信息 (Key metadata in this block).
Definition database.hpp:282
uint32_t header
Flash 块头标识 (Flash block header identifier).
Definition database.hpp:281
键信息结构,存储键的元数据 (Structure containing key metadata).
Definition database.hpp:241