libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
database.hpp
1#pragma once
2
3#include <cstdint>
4#include <cstring>
5
6#include "flash.hpp"
7#include "libxr.hpp"
8#include "libxr_def.hpp"
9#include "libxr_type.hpp"
10
11namespace LibXR
12{
13
14static constexpr uint16_t LIBXR_DATABASE_VERSION = 3;
15
21{
22 public:
27 class KeyBase
28 {
29 public:
30 const char* name_;
32
39 KeyBase(const char* name, RawData raw_data) : name_(name), raw_data_(raw_data) {}
40 };
41
47 template <typename Data>
48 class Key : public KeyBase
49 {
50 public:
51 Data data_;
53
65 Key(Database& database, const char* name, Data init_value)
66 : KeyBase(name, RawData(data_)), database_(database)
67 {
68 if (database.Get(*this) == ErrorCode::NOT_FOUND)
69 {
70 data_ = init_value;
71 database.Add(*this);
72 }
73 }
74
85 Key(Database& database, const char* name)
86 : KeyBase(name, RawData(data_)), database_(database)
87 {
88 if (database.Get(*this) == ErrorCode::NOT_FOUND)
89 {
90 memset(&data_, 0, sizeof(Data));
91 database.Add(*this);
92 }
93 }
94
100 operator Data() { return data_; }
101
107 ErrorCode Set(Data data) { return database_.Set(*this, RawData(data)); }
108
113 ErrorCode Load() { return database_.Get(*this); }
114
120 ErrorCode operator=(Data data) { return Set(data); } // NOLINT
121 };
122
123 private:
129 virtual ErrorCode Get(KeyBase& key) = 0;
130
137 virtual ErrorCode Set(KeyBase& key, RawData data) = 0;
138
144 virtual ErrorCode Add(KeyBase& key) = 0;
145};
146
159{
160 public:
172 explicit DatabaseRawSequential(Flash& flash, size_t max_buffer_size = 256);
173
178 void Init();
179
184 void Save();
185
190 void Load();
191
196 void Restore();
197
206 ErrorCode Get(Database::KeyBase& key) override;
207
215 ErrorCode Set(KeyBase& key, RawData data) override
216 {
217 return SetKey(key.name_, data.addr_, data.size_);
218 }
219
226 ErrorCode Add(KeyBase& key) override
227 {
228 return AddKey(key.name_, key.raw_data_.addr_, key.raw_data_.size_);
229 }
230
231 private:
232 enum class BlockType : uint8_t
233 {
234 MAIN = 0,
235 BACKUP = 1
236 };
237
238#pragma pack(push, 1)
243 struct KeyInfo
244 {
245 uint32_t raw_data;
246
247 KeyInfo() : raw_data(0xFFFFFFFF) {}
248
249 KeyInfo(bool nextKey, uint8_t nameLength, uint32_t dataSize) : raw_data(0)
250 {
251 SetNextKeyExist(nextKey);
252 SetNameLength(nameLength);
253 SetDataSize(dataSize);
254 }
255
256 void SetNextKeyExist(bool value)
257 {
258 raw_data = (raw_data & 0x7FFFFFFF) | (static_cast<uint32_t>(value & 0x1) << 31);
259 }
260 bool GetNextKeyExist() const { return (raw_data >> 31) & 0x1; }
261
262 void SetNameLength(uint8_t len)
263 {
264 raw_data = (raw_data & 0x80FFFFFF) | (static_cast<uint32_t>(len & 0x7F) << 24);
265 }
266 uint8_t GetNameLength() const { return (raw_data >> 24) & 0x7F; }
267
268 void SetDataSize(uint32_t size)
269 {
270 raw_data = (raw_data & 0xFF000000) | (size & 0x00FFFFFF);
271 }
272 uint32_t GetDataSize() const { return raw_data & 0x00FFFFFF; }
273 };
274
275 static_assert(sizeof(KeyInfo) == 4, "KeyInfo size must be 4 bytes");
276#pragma pack(pop)
277
283 {
284 uint32_t header;
286 };
287
288 ErrorCode AddKey(const char* name, const void* data, size_t size);
289 ErrorCode SetKey(const char* name, const void* data, size_t size);
290 ErrorCode SetKey(size_t offset, const void* data, size_t size);
291 ErrorCode GetKeyData(size_t offset, RawData data);
292 void InitBlock(BlockType block);
293 bool IsBlockInited(BlockType block);
294 bool IsBlockEmpty(BlockType block);
295 bool IsBlockError(BlockType block);
296 bool HasLastKey(size_t offset);
297 size_t GetKeySize(size_t offset);
298 size_t GetNextKey(size_t offset);
299 size_t GetLastKey(BlockType block);
300 void SetNestKeyExist(size_t offset, bool exist);
301 bool KeyDataCompare(size_t offset, const void* data, size_t size);
302 bool KeyNameCompare(size_t offset, const char* name);
303 size_t SearchKey(const char* name);
304
305 static constexpr uint32_t FLASH_HEADER =
306 0x12345678 + LIBXR_DATABASE_VERSION;
307 static constexpr uint8_t CHECKSUM_BYTE = 0x56;
308
310 uint8_t* buffer_;
311 uint32_t block_size_;
313};
314
327template <size_t MinWriteSize>
328class DatabaseRaw : public Database
329{
330 static constexpr uint32_t FLASH_HEADER =
331 0x12345678 + LIBXR_DATABASE_VERSION;
332
333 static constexpr uint32_t CHECKSUM_BYTE = 0x9abcedf0;
334
335 enum class BlockType : uint8_t
336 {
337 MAIN = 0,
338 BACKUP = 1
339 };
340
341#pragma pack(push, 1)
342 template <size_t BlockSize>
344 {
345 uint8_t data[BlockSize];
346 };
347#pragma pack(pop)
348
349 template <size_t BlockSize>
351 {
352 public:
353 static void SetFlag(BlockBoolData<BlockSize>& obj, bool value)
354 {
355 memset(obj.data, 0xFF, BlockSize);
356 if (!value)
357 {
358 obj.data[BlockSize - 1] &= 0xF0;
359 }
360 }
361
362 static bool ReadFlag(const BlockBoolData<BlockSize>& obj)
363 {
364 uint8_t last_4bits = obj.data[BlockSize - 1] & 0x0F;
365 return last_4bits == 0x0F;
366 }
367
368 static bool Valid(const BlockBoolData<BlockSize>& obj)
369 {
370 if (BlockSize == 0)
371 {
372 return false;
373 }
374
375 for (size_t i = 0; i < BlockSize - 1; ++i)
376 {
377 if (obj.data[i] != 0xFF)
378 {
379 return false;
380 }
381 }
382
383 uint8_t last_byte = obj.data[BlockSize - 1];
384 if ((last_byte & 0xF0) != 0xF0)
385 {
386 return false;
387 }
388
389 uint8_t last_4bits = last_byte & 0x0F;
390 if (!(last_4bits == 0x0F || last_4bits == 0x00))
391 {
392 return false;
393 }
394
395 return true;
396 }
397 };
398
399#pragma pack(push, 1)
404 struct KeyInfo
405 {
409
410 uint32_t raw_info = 0;
411
412 // 默认构造
413 KeyInfo()
414 {
418 }
419
420 void SetNameLength(uint8_t len)
421 {
422 raw_info = (raw_info & 0x01FFFFFF) | ((len & 0x7F) << 25);
423 }
424
425 uint8_t GetNameLength() const { return (raw_info >> 25) & 0x7F; }
426
427 void SetDataSize(uint32_t size)
428 {
429 raw_info = (raw_info & 0xFE000000) | (size & 0x01FFFFFF);
430 }
431
432 uint32_t GetDataSize() const { return raw_info & 0x01FFFFFF; }
433 };
434#pragma pack(pop)
435
436#pragma pack(push, 1)
442 {
443 FlashInfo()
444 {
445 header = 0xFFFFFFFF;
446 memset(padding, 0xFF, MinWriteSize);
447 }
448
449 union
450 {
451 uint32_t header;
452 uint8_t padding[MinWriteSize];
453 };
455 };
456#pragma pack(pop)
457
460 uint32_t block_size_;
461 uint8_t write_buffer_[MinWriteSize];
462
469 {
470 auto offset = GetNextKey(GetLastKey(BlockType::MAIN));
471 return block_size_ - sizeof(CHECKSUM_BYTE) - offset;
472 }
473
474 ErrorCode AddKeyBody(size_t name_len, size_t size, size_t& key_buf_offset)
475 {
476 bool recycle = false;
477 add_again:
478 size_t last_key_offset = GetLastKey(BlockType::MAIN);
479 key_buf_offset = 0;
480
481 if (AvailableSize() <
482 AlignSize(sizeof(KeyInfo)) + AlignSize(name_len) + AlignSize(size))
483 {
484 if (!recycle)
485 {
486 Recycle();
487 recycle = true;
488 // NOLINTNEXTLINE
489 goto add_again;
490 }
491 else
492 {
493 ASSERT(false);
494 return ErrorCode::FULL;
495 }
496 }
497
498 if (last_key_offset == 0)
499 {
500 FlashInfo flash_info;
501 flash_info.header = FLASH_HEADER;
502 KeyInfo& tmp_key = flash_info.key;
503 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.no_next_key, false);
504 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.available_flag, false);
505 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.uninit, false);
506 tmp_key.SetNameLength(0);
507 tmp_key.SetDataSize(0);
508 Write(0, flash_info);
509 key_buf_offset = GetNextKey(OFFSET_OF(FlashInfo, key));
510 }
511 else
512 {
513 key_buf_offset = GetNextKey(last_key_offset);
514 }
515
516 KeyInfo new_key = {};
517 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.no_next_key, true);
518 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.available_flag, true);
519 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.uninit, true);
520 new_key.SetNameLength(name_len);
521 new_key.SetDataSize(size);
522
523 Write(key_buf_offset, new_key);
524 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.uninit, false);
525
526 if (last_key_offset != 0)
527 {
528 KeyInfo last_key;
529 flash_.Read(last_key_offset, last_key);
530 KeyInfo new_last_key = {};
531 BlockBoolUtil<MinWriteSize>::SetFlag(new_last_key.no_next_key, false);
532 BlockBoolUtil<MinWriteSize>::SetFlag(
533 new_last_key.available_flag,
534 BlockBoolUtil<MinWriteSize>::ReadFlag(last_key.available_flag));
535 BlockBoolUtil<MinWriteSize>::SetFlag(
536 new_last_key.uninit, BlockBoolUtil<MinWriteSize>::ReadFlag(last_key.uninit));
537 new_last_key.SetNameLength(last_key.GetNameLength());
538 new_last_key.SetDataSize(last_key.GetDataSize());
539
540 Write(last_key_offset, new_last_key);
541 }
542
543 Write(key_buf_offset, new_key);
544
545 return ErrorCode::OK;
546 }
547
548 ErrorCode AddKey(size_t name_offset, size_t name_len, const void* data, size_t size)
549 {
550 size_t key_buf_offset = 0;
551 ErrorCode ec = AddKeyBody(name_len, size, key_buf_offset);
552 if (ec != ErrorCode::OK)
553 {
554 return ec;
555 }
556 CopyFlashData(GetKeyName(key_buf_offset), name_offset, name_len);
557 Write(GetKeyData(key_buf_offset), {reinterpret_cast<const uint8_t*>(data), size});
558 return ErrorCode::OK;
559 }
560
561 ErrorCode AddKey(const char* name, const void* data, size_t size)
562 {
563 size_t name_len = strlen(name) + 1;
564 if (auto ans = SearchKey(name))
565 {
566 return SetKey(name, data, size);
567 }
568 size_t key_buf_offset = 0;
569 ErrorCode ec = AddKeyBody(name_len, size, key_buf_offset);
570 if (ec != ErrorCode::OK)
571 {
572 return ec;
573 }
574 Write(GetKeyName(key_buf_offset), {reinterpret_cast<const uint8_t*>(name), name_len});
575 Write(GetKeyData(key_buf_offset), {reinterpret_cast<const uint8_t*>(data), size});
576 return ErrorCode::OK;
577 }
578
579 ErrorCode SetKeyCommon(size_t key_offset, size_t name_len, const void* data,
580 size_t size)
581 {
582 if (key_offset)
583 {
584 KeyInfo key;
585 flash_.Read(key_offset, key);
586 if (key.GetDataSize() == size)
587 {
588 if (KeyDataCompare(key_offset, data, size))
589 {
590 KeyInfo new_key = {};
591 BlockBoolUtil<MinWriteSize>::SetFlag(
592 new_key.no_next_key,
593 BlockBoolUtil<MinWriteSize>::ReadFlag(key.no_next_key));
594 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.available_flag, false);
595 BlockBoolUtil<MinWriteSize>::SetFlag(
596 new_key.uninit, BlockBoolUtil<MinWriteSize>::ReadFlag(key.uninit));
597 new_key.SetNameLength(name_len);
598 new_key.SetDataSize(size);
599 Write(key_offset, new_key);
600 return AddKey(GetKeyName(key_offset), name_len, data, size);
601 }
602 return ErrorCode::OK;
603 }
604 }
605 return ErrorCode::FAILED;
606 }
607
608 ErrorCode SetKey(size_t name_offset, size_t name_length, const void* data, size_t size)
609 {
610 size_t key_offset = SearchKey(name_offset, name_length);
611 return SetKeyCommon(key_offset, name_length, data, size);
612 }
613
614 ErrorCode SetKey(const char* name, const void* data, size_t size, bool recycle = true)
615 {
616 size_t key_offset = SearchKey(name);
617 if (key_offset)
618 {
619 KeyInfo key;
620 flash_.Read(key_offset, key);
621 if (key.GetDataSize() == size)
622 {
623 if (KeyDataCompare(key_offset, data, size))
624 {
625 if (AvailableSize() < AlignSize(size) + AlignSize(sizeof(KeyInfo)) +
626 AlignSize(key.GetNameLength()))
627 {
628 if (recycle)
629 {
630 Recycle();
631 return SetKey(name, data, size, false);
632 }
633 else
634 {
635 ASSERT(false);
636 return ErrorCode::FULL;
637 }
638 }
639 KeyInfo new_key = {};
640 BlockBoolUtil<MinWriteSize>::SetFlag(
641 new_key.no_next_key,
642 BlockBoolUtil<MinWriteSize>::ReadFlag(key.no_next_key));
643 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.available_flag, false);
644 BlockBoolUtil<MinWriteSize>::SetFlag(
645 new_key.uninit, BlockBoolUtil<MinWriteSize>::ReadFlag(key.uninit));
646 new_key.SetNameLength(key.GetNameLength());
647 new_key.SetDataSize(size);
648 Write(key_offset, new_key);
649 return AddKey(GetKeyName(key_offset), key.GetNameLength(), data, size);
650 }
651 return ErrorCode::OK;
652 }
653 }
654 return ErrorCode::FAILED;
655 }
656
657 size_t GetKeyData(size_t offset)
658 {
659 KeyInfo key;
660 flash_.Read(offset, key);
661 return offset + AlignSize(sizeof(KeyInfo)) + AlignSize(key.GetNameLength());
662 }
663
664 size_t GetKeyName(size_t offset) { return offset + AlignSize(sizeof(KeyInfo)); }
665
666 void InitBlock(BlockType block)
667 {
668 size_t offset = 0;
669 if (block == BlockType::BACKUP)
670 {
671 offset = block_size_;
672 }
673 flash_.Erase(offset, block_size_);
674
675 FlashInfo info; // padding filled with 0xFF by constructor
676 info.header = FLASH_HEADER;
677 KeyInfo& tmp_key = info.key;
678 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.no_next_key, true);
679 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.available_flag, true);
680 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.uninit, false);
681 tmp_key.SetNameLength(0);
682 tmp_key.SetDataSize(0);
683 Write(offset, {reinterpret_cast<uint8_t*>(&info), sizeof(FlashInfo)});
684 Write(offset + block_size_ - AlignSize(sizeof(CHECKSUM_BYTE)),
685 {&CHECKSUM_BYTE, sizeof(CHECKSUM_BYTE)});
686 }
687
688 bool IsBlockInited(BlockType block)
689 {
690 size_t offset = 0;
691 if (block == BlockType::BACKUP)
692 {
693 offset = block_size_;
694 }
695 FlashInfo flash_data;
696 flash_.Read(offset, flash_data);
697 return flash_data.header == FLASH_HEADER;
698 }
699
700 bool IsBlockEmpty(BlockType block)
701 {
702 size_t offset = 0;
703 if (block == BlockType::BACKUP)
704 {
705 offset = block_size_;
706 }
707 FlashInfo flash_data;
708 flash_.Read(offset, flash_data);
709 return BlockBoolUtil<MinWriteSize>::ReadFlag(flash_data.key.available_flag) == true;
710 }
711
712 bool IsBlockError(BlockType block)
713 {
714 size_t offset = 0;
715 if (block == BlockType::BACKUP)
716 {
717 offset = block_size_;
718 }
719 uint32_t checksum = 0;
720 flash_.Read(offset + block_size_ - AlignSize(sizeof(CHECKSUM_BYTE)), checksum);
721 return checksum != CHECKSUM_BYTE;
722 }
723
724 size_t GetKeySize(size_t offset)
725 {
726 KeyInfo key;
727 flash_.Read(offset, key);
728 return AlignSize(sizeof(KeyInfo)) + AlignSize(key.GetNameLength()) +
729 AlignSize(key.GetDataSize());
730 }
731
732 size_t GetNextKey(size_t offset)
733 {
734 KeyInfo key;
735 flash_.Read(offset, key);
736 return offset + GetKeySize(offset);
737 }
738
739 size_t GetLastKey(BlockType block)
740 {
741 if (IsBlockEmpty(block))
742 {
743 return 0;
744 }
745
746 KeyInfo key;
747 size_t key_offset = OFFSET_OF(FlashInfo, key);
748 if (block != BlockType::MAIN)
749 {
750 key_offset += block_size_;
751 }
752 flash_.Read(key_offset, key);
753 while (!BlockBoolUtil<MinWriteSize>::ReadFlag(key.no_next_key))
754 {
755 key_offset = GetNextKey(key_offset);
756 flash_.Read(key_offset, key);
757 }
758 return key_offset;
759 }
760
761 bool KeyDataCompare(size_t offset, const void* data, size_t size)
762 {
763 KeyInfo key;
764 flash_.Read(offset, key);
765 size_t key_data_offset = GetKeyData(offset);
766 uint8_t data_buffer = 0;
767 for (size_t i = 0; i < size; i++)
768 {
769 flash_.Read(key_data_offset + i, data_buffer);
770 if (data_buffer != (reinterpret_cast<const uint8_t*>(data))[i])
771 {
772 return true;
773 }
774 }
775 return false;
776 }
777
778 bool KeyNameCompare(size_t offset, const char* name)
779 {
780 KeyInfo key;
781 flash_.Read(offset, key);
782 for (size_t i = 0; i < key.GetNameLength(); i++)
783 {
784 uint8_t data_buffer = 0;
785 flash_.Read(offset + AlignSize(sizeof(KeyInfo)) + i, data_buffer);
786 if (data_buffer != name[i])
787 {
788 return true;
789 }
790 }
791 return false;
792 }
793
794 bool KeyNameCompare(size_t offset_a, size_t offset_b)
795 {
796 KeyInfo key_a, key_b;
797 flash_.Read(offset_a, key_a);
798 flash_.Read(offset_b, key_b);
799 if (key_a.GetNameLength() != key_b.GetNameLength())
800 {
801 return true;
802 }
803 for (size_t i = 0; i < key_a.GetNameLength(); i++)
804 {
805 uint8_t data_buffer_a = 0, data_buffer_b = 0;
806 flash_.Read(offset_a + sizeof(KeyInfo) + i, data_buffer_a);
807 flash_.Read(offset_b + sizeof(KeyInfo) + i, data_buffer_b);
808 if (data_buffer_a != data_buffer_b)
809 {
810 return true;
811 }
812 }
813 return false;
814 }
815
816 void CopyFlashData(size_t dst_offset, size_t src_offset, size_t size)
817 {
818 for (size_t i = 0; i < size; i += MinWriteSize)
819 {
820 flash_.Read(src_offset + i, {write_buffer_, MinWriteSize});
821 flash_.Write(dst_offset + i, {write_buffer_, MinWriteSize});
822 }
823 }
824
825 size_t SearchKey(const char* name)
826 {
827 if (IsBlockEmpty(BlockType::MAIN))
828 {
829 return 0;
830 }
831
832 KeyInfo key;
833 size_t key_offset = OFFSET_OF(FlashInfo, key);
834 flash_.Read(key_offset, key);
835
836 size_t ans = 0, need_cycle = 0;
837
838 while (true)
839 {
840 if (!BlockBoolUtil<MinWriteSize>::ReadFlag(key.available_flag))
841 {
842 key_offset = GetNextKey(key_offset);
843 flash_.Read(key_offset, key);
844 need_cycle++;
845 continue;
846 }
847
848 if (!KeyNameCompare(key_offset, name))
849 {
850 ans = key_offset;
851 break;
852 }
853
854 if (BlockBoolUtil<MinWriteSize>::ReadFlag(key.no_next_key))
855 {
856 break;
857 }
858
859 key_offset = GetNextKey(key_offset);
860 flash_.Read(key_offset, key);
861 }
862
863 if (need_cycle > recycle_threshold_)
864 {
865 Recycle();
866 return SearchKey(name);
867 }
868
869 return ans;
870 }
871
878 size_t AlignSize(size_t size)
879 {
880 return static_cast<size_t>((size + MinWriteSize - 1) / MinWriteSize) * MinWriteSize;
881 }
882
890 ErrorCode Write(size_t offset, ConstRawData data)
891 {
892 if (data.size_ == 0)
893 {
894 return ErrorCode::OK;
895 }
896
897 if (data.size_ % MinWriteSize == 0)
898 {
899 return flash_.Write(offset, data);
900 }
901 else
902 {
903 auto final_block_index = data.size_ - data.size_ % MinWriteSize;
904 if (final_block_index != 0)
905 {
906 flash_.Write(offset, {data.addr_, final_block_index});
907 }
908 memset(write_buffer_, 0xff, MinWriteSize);
910 write_buffer_, reinterpret_cast<const uint8_t*>(data.addr_) + final_block_index,
911 data.size_ % MinWriteSize);
912 return flash_.Write(offset + final_block_index, {write_buffer_, MinWriteSize});
913 }
914 }
915
916 public:
925 ErrorCode Get(Database::KeyBase& key) override
926 {
927 auto ans = SearchKey(key.name_);
928 if (!ans)
929 {
930 return ErrorCode::NOT_FOUND;
931 }
932
933 KeyInfo key_buffer;
934 flash_.Read(ans, key_buffer);
935
936 if (key.raw_data_.size_ < key_buffer.GetDataSize())
937 {
938 return ErrorCode::FAILED;
939 }
940
941 flash_.Read(GetKeyData(ans), key.raw_data_);
942
943 return ErrorCode::OK;
944 }
945
953 ErrorCode Set(KeyBase& key, RawData data) override
954 {
956 return SetKey(key.name_, data.addr_, data.size_);
957 }
958
959 ErrorCode Add(KeyBase& key) override
960 {
961 return AddKey(key.name_, key.raw_data_.addr_, key.raw_data_.size_);
962 }
963
971 explicit DatabaseRaw(Flash& flash, size_t recycle_threshold = 128)
972 : recycle_threshold_(recycle_threshold), flash_(flash)
973 {
974 ASSERT(flash.MinEraseSize() * 2 <= flash_.Size());
975 ASSERT(flash_.MinWriteSize() <= MinWriteSize);
976 auto block_num = static_cast<size_t>(flash_.Size() / flash.MinEraseSize());
977 block_size_ = block_num / 2 * flash.MinEraseSize();
978 Init();
979 }
980
985 void Init()
986 {
987 if (!IsBlockInited(BlockType::BACKUP) || IsBlockError(BlockType::BACKUP))
988 {
989 InitBlock(BlockType::BACKUP);
990 }
991
992 if (!IsBlockInited(BlockType::MAIN) || IsBlockError(BlockType::MAIN))
993 {
994 if (IsBlockEmpty(BlockType::BACKUP))
995 {
996 InitBlock(BlockType::MAIN);
997 }
998 else
999 {
1001 for (uint32_t i = 0; i < block_size_; i += MinWriteSize)
1002 {
1003 flash_.Read(i + block_size_, {write_buffer_, MinWriteSize});
1004 flash_.Write(i, {write_buffer_, MinWriteSize});
1005 }
1006 }
1007 }
1008
1009 if (!IsBlockEmpty(BlockType::BACKUP))
1010 {
1011 InitBlock(BlockType::BACKUP);
1012 }
1013
1014 KeyInfo key;
1015 size_t key_offset = OFFSET_OF(FlashInfo, key);
1016 flash_.Read(key_offset, key);
1017 size_t need_cycle = 0;
1019 {
1020 key_offset = GetNextKey(key_offset);
1021
1022 if (key_offset + sizeof(key) >= flash_.Size())
1023 {
1024 InitBlock(BlockType::MAIN);
1025 break;
1026 }
1027
1028 flash_.Read(key_offset, key);
1029
1030 // TODO: 恢复损坏数据
1032 {
1033 InitBlock(BlockType::MAIN);
1034 break;
1035 }
1037 {
1038 need_cycle += 1;
1039 }
1040 }
1041
1042 if (need_cycle > recycle_threshold_)
1043 {
1044 Recycle();
1045 }
1046 }
1047
1052 void Restore()
1053 {
1054 InitBlock(BlockType::MAIN);
1055 InitBlock(BlockType::BACKUP);
1056 }
1057
1068 ErrorCode Recycle()
1069 {
1070 if (IsBlockEmpty(BlockType::MAIN))
1071 {
1072 return ErrorCode::OK;
1073 }
1074
1075 KeyInfo key;
1076 size_t key_offset = OFFSET_OF(FlashInfo, key);
1077 flash_.Read(key_offset, key);
1078
1079 if (!IsBlockEmpty(BlockType::BACKUP))
1080 {
1081 InitBlock(BlockType::BACKUP);
1082 }
1083
1084 size_t write_buff_offset = OFFSET_OF(FlashInfo, key) + block_size_;
1085
1086 auto new_key = KeyInfo{};
1087 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.uninit, false);
1088 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.available_flag, false);
1089 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.no_next_key, false);
1090 Write(write_buff_offset, new_key);
1091
1092 write_buff_offset += GetKeySize(write_buff_offset);
1093
1094 do
1095 {
1096 key_offset = GetNextKey(key_offset);
1097 flash_.Read(key_offset, key);
1098
1100 {
1101 continue;
1102 }
1103
1104 Write(write_buff_offset, key);
1105 write_buff_offset += AlignSize(sizeof(KeyInfo));
1106 CopyFlashData(write_buff_offset, GetKeyName(key_offset), key.GetNameLength());
1107 write_buff_offset += AlignSize(key.GetNameLength());
1108 CopyFlashData(write_buff_offset, GetKeyData(key_offset), key.GetDataSize());
1109 write_buff_offset += AlignSize(key.GetDataSize());
1111
1113 for (uint32_t i = 0; i < block_size_; i += MinWriteSize)
1114 {
1115 flash_.Read(i + block_size_, {write_buffer_, MinWriteSize});
1116 flash_.Write(i, {write_buffer_, MinWriteSize});
1117 }
1118
1119 InitBlock(BlockType::BACKUP);
1120
1121 return ErrorCode::OK;
1122 }
1123};
1124
1125} // namespace LibXR
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
键的基类,存储键名及其数据 (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
KeyBase(const char *name, RawData raw_data)
构造函数,初始化键名和原始数据 (Constructor to initialize key name and raw data).
Definition database.hpp:39
const char * name_
键名 (Key name).
Definition database.hpp:30
模板类,表示数据库中的具体键 (Template class representing a specific key in the database).
Definition database.hpp:49
Database & database_
关联的数据库对象 (Reference to the associated database).
Definition database.hpp:52
ErrorCode Set(Data data)
设置键的值并更新数据库 (Set the key's value and update the database).
Definition database.hpp:107
Key(Database &database, const char *name, Data init_value)
构造函数,初始化键并从数据库加载数据 (Constructor to initialize key and load data from the database).
Definition database.hpp:65
Data data_
键存储的数据 (The data stored in the key).
Definition database.hpp:51
ErrorCode operator=(Data data)
赋值运算符,设置键的值 (Assignment operator to set the key's value).
Definition database.hpp:120
ErrorCode Load()
从数据库加载键的值 (Load the key's value from the database).
Definition database.hpp:113
Key(Database &database, const char *name)
构造函数,初始化键,并在数据库不存在时赋默认值 (Constructor to initialize key, assigning default value if not found in the d...
Definition database.hpp:85
数据库接口,提供键值存储和管理功能 (Database interface providing key-value storage and management).
Definition database.hpp:21
virtual ErrorCode Add(KeyBase &key)=0
添加新键到数据库 (Add a new key to the database).
virtual ErrorCode Get(KeyBase &key)=0
从数据库获取键的值 (Retrieve the key's value from the database).
virtual ErrorCode Set(KeyBase &key, RawData data)=0
设置数据库中的键值 (Set the key's value in the database).
适用于最小写入单元受限的 Flash 存储的数据库实现 (Database implementation for Flash storage with minimum write unit restri...
Definition database.hpp:329
size_t AvailableSize()
计算可用的存储空间大小 (Calculate the available storage size).
Definition database.hpp:468
static constexpr uint32_t FLASH_HEADER
Flash 头部标识 (Flash header identifier).
Definition database.hpp:330
@ MAIN
主块 (Main block).
@ BACKUP
备份块 (Backup block).
void Restore()
还原存储数据,清空 Flash 区域 (Restore storage data, clearing Flash memory area).
DatabaseRaw(Flash &flash, size_t recycle_threshold=128)
构造函数,初始化 Flash 存储和缓冲区 (Constructor to initialize Flash storage and buffer).
Definition database.hpp:971
ErrorCode Add(KeyBase &key) override
添加新键到数据库 (Add a new key to the database).
Definition database.hpp:959
ErrorCode Set(KeyBase &key, RawData data) override
设置数据库中的键值 (Set the key's value in the database).
Definition database.hpp:953
ErrorCode Recycle()
回收 Flash 空间,整理数据 (Recycle Flash storage space and organize data).
uint32_t block_size_
Flash 块大小 (Flash block size).
Definition database.hpp:460
static constexpr uint32_t CHECKSUM_BYTE
校验字节 (Checksum byte).
Definition database.hpp:333
void Init()
初始化数据库存储区,确保主备块正确 (Initialize database storage, ensuring main and backup blocks are valid).
Definition database.hpp:985
ErrorCode Write(size_t offset, ConstRawData data)
以最小写入单元对齐的方式写入数据 (Write data aligned to the minimum write unit).
Definition database.hpp:890
ErrorCode Get(Database::KeyBase &key) override
获取数据库中的键值 (Retrieve the key's value from the database).
Definition database.hpp:925
Flash & flash_
目标 Flash 存储设备 (Target Flash storage device).
Definition database.hpp:459
uint8_t write_buffer_[MinWriteSize]
写入缓冲区 (Write buffer).
Definition database.hpp:461
size_t AlignSize(size_t size)
计算对齐后的大小 (Calculate the aligned size).
Definition database.hpp:878
size_t recycle_threshold_
回收阈值 (Recycle threshold).
Definition database.hpp:458
适用于不支持逆序写入的 Flash 存储的数据库实现 (Database implementation for Flash storage that does not support reverse w...
Definition database.hpp:159
void Save()
保存当前缓冲区内容到 Flash (Save the current buffer content to Flash).
Definition database.cpp:55
static constexpr uint8_t CHECKSUM_BYTE
校验字节 (Checksum byte).
Definition database.hpp:307
ErrorCode Set(KeyBase &key, RawData data) override
设置数据库中的键值 (Set the key's value in the database).
Definition database.hpp:215
uint32_t max_buffer_size_
最大缓冲区大小 (Maximum buffer size).
Definition database.hpp:312
ErrorCode Get(Database::KeyBase &key) override
获取数据库中的键值 (Retrieve the key's value from the database).
Definition database.cpp:77
void Init()
初始化数据库存储区,确保主备块正确 (Initialize database storage, ensuring main and backup blocks are valid).
Definition database.cpp:25
uint8_t * buffer_
数据缓冲区 (Data buffer).
Definition database.hpp:310
static constexpr uint32_t FLASH_HEADER
Flash 头部标识 (Flash header identifier).
Definition database.hpp:305
ErrorCode Add(KeyBase &key) override
添加新键到数据库 (Add a new key to the database).
Definition database.hpp:226
void Restore()
还原存储数据,清空 Flash 区域 (Restore storage data, clearing Flash memory area).
Definition database.cpp:66
bool IsBlockEmpty(BlockType block)
判断块是否为空 (Check if block is empty).
Definition database.cpp:133
uint32_t block_size_
Flash 块大小 (Flash block size).
Definition database.hpp:311
Flash & flash_
目标 Flash 存储设备 (Target Flash storage device).
Definition database.hpp:309
void Load()
从 Flash 加载数据到缓冲区 (Load data from Flash into the buffer).
Definition database.cpp:64
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:116
@ BACKUP
备份块 (Backup block).
bool IsBlockError(BlockType block)
判断块是否损坏 (Check if block has an error).
Definition database.cpp:150
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
size_t MinWriteSize() const
Returns the minimum writable block size in bytes. 获取最小可写块大小(字节)。
Definition flash.hpp:73
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
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
Definition libxr_mem.cpp:3
原始数据封装类。 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 命名空间
Flash 存储的块信息结构 (Structure representing a Flash storage block).
Definition database.hpp:442
KeyInfo key
Align KeyInfo to MinWriteSize.
Definition database.hpp:454
uint32_t header
Flash block header.
Definition database.hpp:451
键信息结构,存储键的元数据 (Structure containing key metadata).
Definition database.hpp:405
BlockBoolData< MinWriteSize > no_next_key
是否是最后一个键
Definition database.hpp:406
BlockBoolData< MinWriteSize > available_flag
该键是否有效
Definition database.hpp:407
BlockBoolData< MinWriteSize > uninit
该键是否未初始化
Definition database.hpp:408
uint32_t raw_info
高7位为 nameLength,低25位为 dataSize
Definition database.hpp:410
Flash 存储的块信息结构 (Structure representing a Flash storage block).
Definition database.hpp:283
KeyInfo key
该块的键信息 (Key metadata in this block).
Definition database.hpp:285
uint32_t header
Flash 块头标识 (Flash block header identifier).
Definition database.hpp:284
键信息结构,存储键的元数据 (Structure containing key metadata).
Definition database.hpp:244