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:
169 explicit DatabaseRawSequential(Flash& flash, size_t max_buffer_size = 256);
170
175 void Init();
176
181 void Save();
182
187 void Load();
188
193 void Restore();
194
203 ErrorCode Get(Database::KeyBase& key) override;
204
212 ErrorCode Set(KeyBase& key, RawData data) override
213 {
214 return SetKey(key.name_, data.addr_, data.size_);
215 }
216
223 ErrorCode Add(KeyBase& key) override
224 {
225 return AddKey(key.name_, key.raw_data_.addr_, key.raw_data_.size_);
226 }
227
228 private:
229 enum class BlockType : uint8_t
230 {
231 MAIN = 0,
232 BACKUP = 1
233 };
234
235#pragma pack(push, 1)
240 struct KeyInfo
241 {
242 uint32_t raw_data;
243
244 KeyInfo() : raw_data(0xFFFFFFFF) {}
245
246 KeyInfo(bool nextKey, uint8_t nameLength, uint32_t dataSize) : raw_data(0)
247 {
248 SetNextKeyExist(nextKey);
249 SetNameLength(nameLength);
250 SetDataSize(dataSize);
251 }
252
253 void SetNextKeyExist(bool value)
254 {
255 raw_data = (raw_data & 0x7FFFFFFF) | (static_cast<uint32_t>(value & 0x1) << 31);
256 }
257 bool GetNextKeyExist() const { return (raw_data >> 31) & 0x1; }
258
259 void SetNameLength(uint8_t len)
260 {
261 raw_data = (raw_data & 0x80FFFFFF) | (static_cast<uint32_t>(len & 0x7F) << 24);
262 }
263 uint8_t GetNameLength() const { return (raw_data >> 24) & 0x7F; }
264
265 void SetDataSize(uint32_t size)
266 {
267 raw_data = (raw_data & 0xFF000000) | (size & 0x00FFFFFF);
268 }
269 uint32_t GetDataSize() const { return raw_data & 0x00FFFFFF; }
270 };
271
272 static_assert(sizeof(KeyInfo) == 4, "KeyInfo size must be 4 bytes");
273#pragma pack(pop)
274
280 {
281 uint32_t header;
283 };
284
285 ErrorCode AddKey(const char* name, const void* data, size_t size);
286 ErrorCode SetKey(const char* name, const void* data, size_t size);
287 ErrorCode SetKey(size_t offset, const void* data, size_t size);
288 ErrorCode GetKeyData(size_t offset, RawData data);
289 void InitBlock(BlockType block);
290 bool IsBlockInited(BlockType block);
291 bool IsBlockEmpty(BlockType block);
292 bool IsBlockError(BlockType block);
293 bool HasLastKey(size_t offset);
294 size_t GetKeySize(size_t offset);
295 size_t GetNextKey(size_t offset);
296 size_t GetLastKey(BlockType block);
297 void SetNestKeyExist(size_t offset, bool exist);
298 bool KeyDataCompare(size_t offset, const void* data, size_t size);
299 bool KeyNameCompare(size_t offset, const char* name);
300 size_t SearchKey(const char* name);
301
302 static constexpr uint32_t FLASH_HEADER =
303 0x12345678 + LIBXR_DATABASE_VERSION;
304 static constexpr uint8_t CHECKSUM_BYTE = 0x56;
305
307 uint8_t* buffer_;
308 uint32_t block_size_;
310};
311
324template <size_t MinWriteSize>
325class DatabaseRaw : public Database
326{
327 static constexpr uint32_t FLASH_HEADER =
328 0x12345678 + LIBXR_DATABASE_VERSION;
329
330 static constexpr uint32_t CHECKSUM_BYTE = 0x9abcedf0;
331
332 enum class BlockType : uint8_t
333 {
334 MAIN = 0,
335 BACKUP = 1
336 };
337
338#pragma pack(push, 1)
339 template <size_t BlockSize>
341 {
342 uint8_t data[BlockSize];
343 };
344#pragma pack(pop)
345
346 template <size_t BlockSize>
348 {
349 public:
350 static void SetFlag(BlockBoolData<BlockSize>& obj, bool value)
351 {
352 memset(obj.data, 0xFF, BlockSize);
353 if (!value)
354 {
355 obj.data[BlockSize - 1] &= 0xF0;
356 }
357 }
358
359 static bool ReadFlag(const BlockBoolData<BlockSize>& obj)
360 {
361 uint8_t last_4bits = obj.data[BlockSize - 1] & 0x0F;
362 return last_4bits == 0x0F;
363 }
364
365 static bool Valid(const BlockBoolData<BlockSize>& obj)
366 {
367 if (BlockSize == 0)
368 {
369 return false;
370 }
371
372 for (size_t i = 0; i < BlockSize - 1; ++i)
373 {
374 if (obj.data[i] != 0xFF)
375 {
376 return false;
377 }
378 }
379
380 uint8_t last_byte = obj.data[BlockSize - 1];
381 if ((last_byte & 0xF0) != 0xF0)
382 {
383 return false;
384 }
385
386 uint8_t last_4bits = last_byte & 0x0F;
387 if (!(last_4bits == 0x0F || last_4bits == 0x00))
388 {
389 return false;
390 }
391
392 return true;
393 }
394 };
395
396#pragma pack(push, 1)
401 struct KeyInfo
402 {
406
407 uint32_t raw_info = 0;
408
409 // 默认构造
410 KeyInfo()
411 {
415 }
416
417 void SetNameLength(uint8_t len)
418 {
419 raw_info = (raw_info & 0x01FFFFFF) | ((len & 0x7F) << 25);
420 }
421
422 uint8_t GetNameLength() const { return (raw_info >> 25) & 0x7F; }
423
424 void SetDataSize(uint32_t size)
425 {
426 raw_info = (raw_info & 0xFE000000) | (size & 0x01FFFFFF);
427 }
428
429 uint32_t GetDataSize() const { return raw_info & 0x01FFFFFF; }
430 };
431#pragma pack(pop)
432
433#pragma pack(push, 1)
439 {
440 FlashInfo()
441 {
442 header = 0xFFFFFFFF;
443 memset(padding, 0xFF, MinWriteSize);
444 }
445
446 union
447 {
448 uint32_t header;
449 uint8_t padding[MinWriteSize];
450 };
452 };
453#pragma pack(pop)
454
457 uint32_t block_size_;
458 uint8_t write_buffer_[MinWriteSize];
459
466 {
467 auto offset = GetNextKey(GetLastKey(BlockType::MAIN));
468 return block_size_ - sizeof(CHECKSUM_BYTE) - offset;
469 }
470
471 ErrorCode AddKeyBody(size_t name_len, size_t size, size_t& key_buf_offset)
472 {
473 bool recycle = false;
474 add_again:
475 size_t last_key_offset = GetLastKey(BlockType::MAIN);
476 key_buf_offset = 0;
477
478 if (last_key_offset == 0)
479 {
480 FlashInfo flash_info;
481 flash_info.header = FLASH_HEADER;
482 KeyInfo& tmp_key = flash_info.key;
483 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.no_next_key, false);
484 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.available_flag, false);
485 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.uninit, false);
486 tmp_key.SetNameLength(0);
487 tmp_key.SetDataSize(0);
488 Write(0, flash_info);
489 key_buf_offset = GetNextKey(OFFSET_OF(FlashInfo, key));
490 }
491 else
492 {
493 key_buf_offset = GetNextKey(last_key_offset);
494 }
495
496 if (AvailableSize() <
497 AlignSize(sizeof(KeyInfo)) + AlignSize(name_len) + AlignSize(size))
498 {
499 if (!recycle)
500 {
501 Recycle();
502 recycle = true;
503 // NOLINTNEXTLINE
504 goto add_again;
505 }
506 else
507 {
508 ASSERT(false);
509 return ErrorCode::FULL;
510 }
511 }
512
513 KeyInfo new_key = {};
514 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.no_next_key, true);
515 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.available_flag, true);
516 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.uninit, true);
517 new_key.SetNameLength(name_len);
518 new_key.SetDataSize(size);
519
520 Write(key_buf_offset, new_key);
521 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.uninit, false);
522
523 if (last_key_offset != 0)
524 {
525 KeyInfo last_key;
526 flash_.Read(last_key_offset, last_key);
527 KeyInfo new_last_key = {};
528 BlockBoolUtil<MinWriteSize>::SetFlag(new_last_key.no_next_key, false);
529 BlockBoolUtil<MinWriteSize>::SetFlag(
530 new_last_key.available_flag,
531 BlockBoolUtil<MinWriteSize>::ReadFlag(last_key.available_flag));
532 BlockBoolUtil<MinWriteSize>::SetFlag(
533 new_last_key.uninit, BlockBoolUtil<MinWriteSize>::ReadFlag(last_key.uninit));
534 new_last_key.SetNameLength(last_key.GetNameLength());
535 new_last_key.SetDataSize(last_key.GetDataSize());
536
537 Write(last_key_offset, new_last_key);
538 }
539
540 Write(key_buf_offset, new_key);
541
542 return ErrorCode::OK;
543 }
544
545 ErrorCode AddKey(size_t name_offset, size_t name_len, const void* data, size_t size)
546 {
547 size_t key_buf_offset = 0;
548 ErrorCode ec = AddKeyBody(name_len, size, key_buf_offset);
549 if (ec != ErrorCode::OK)
550 {
551 return ec;
552 }
553 CopyFlashData(GetKeyName(key_buf_offset), name_offset, name_len);
554 Write(GetKeyData(key_buf_offset), {reinterpret_cast<const uint8_t*>(data), size});
555 return ErrorCode::OK;
556 }
557
558 ErrorCode AddKey(const char* name, const void* data, size_t size)
559 {
560 size_t name_len = strlen(name) + 1;
561 if (auto ans = SearchKey(name))
562 {
563 return SetKey(name, data, size);
564 }
565 size_t key_buf_offset = 0;
566 ErrorCode ec = AddKeyBody(name_len, size, key_buf_offset);
567 if (ec != ErrorCode::OK)
568 {
569 return ec;
570 }
571 Write(GetKeyName(key_buf_offset), {reinterpret_cast<const uint8_t*>(name), name_len});
572 Write(GetKeyData(key_buf_offset), {reinterpret_cast<const uint8_t*>(data), size});
573 return ErrorCode::OK;
574 }
575
576 ErrorCode SetKeyCommon(size_t key_offset, size_t name_len, const void* data,
577 size_t size)
578 {
579 if (key_offset)
580 {
581 KeyInfo key;
582 flash_.Read(key_offset, key);
583 if (key.GetDataSize() == size)
584 {
585 if (KeyDataCompare(key_offset, data, size))
586 {
587 KeyInfo new_key = {};
588 BlockBoolUtil<MinWriteSize>::SetFlag(
589 new_key.no_next_key,
590 BlockBoolUtil<MinWriteSize>::ReadFlag(key.no_next_key));
591 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.available_flag, false);
592 BlockBoolUtil<MinWriteSize>::SetFlag(
593 new_key.uninit, BlockBoolUtil<MinWriteSize>::ReadFlag(key.uninit));
594 new_key.SetNameLength(name_len);
595 new_key.SetDataSize(size);
596 Write(key_offset, new_key);
597 return AddKey(GetKeyName(key_offset), name_len, data, size);
598 }
599 return ErrorCode::OK;
600 }
601 }
602 return ErrorCode::FAILED;
603 }
604
605 ErrorCode SetKey(size_t name_offset, size_t name_length, const void* data, size_t size)
606 {
607 size_t key_offset = SearchKey(name_offset, name_length);
608 return SetKeyCommon(key_offset, name_length, data, size);
609 }
610
611 ErrorCode SetKey(const char* name, const void* data, size_t size, bool recycle = true)
612 {
613 size_t key_offset = SearchKey(name);
614 if (key_offset)
615 {
616 KeyInfo key;
617 flash_.Read(key_offset, key);
618 if (key.GetDataSize() == size)
619 {
620 if (KeyDataCompare(key_offset, data, size))
621 {
622 if (AvailableSize() < AlignSize(size) + AlignSize(sizeof(KeyInfo)) +
623 AlignSize(key.GetNameLength()))
624 {
625 if (recycle)
626 {
627 Recycle();
628 return SetKey(name, data, size, false);
629 }
630 else
631 {
632 ASSERT(false);
633 return ErrorCode::FULL;
634 }
635 }
636 KeyInfo new_key = {};
637 BlockBoolUtil<MinWriteSize>::SetFlag(
638 new_key.no_next_key,
639 BlockBoolUtil<MinWriteSize>::ReadFlag(key.no_next_key));
640 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.available_flag, false);
641 BlockBoolUtil<MinWriteSize>::SetFlag(
642 new_key.uninit, BlockBoolUtil<MinWriteSize>::ReadFlag(key.uninit));
643 new_key.SetNameLength(key.GetNameLength());
644 new_key.SetDataSize(size);
645 Write(key_offset, new_key);
646 return AddKey(GetKeyName(key_offset), key.GetNameLength(), data, size);
647 }
648 return ErrorCode::OK;
649 }
650 }
651 return ErrorCode::FAILED;
652 }
653
654 size_t GetKeyData(size_t offset)
655 {
656 KeyInfo key;
657 flash_.Read(offset, key);
658 return offset + AlignSize(sizeof(KeyInfo)) + AlignSize(key.GetNameLength());
659 }
660
661 size_t GetKeyName(size_t offset) { return offset + AlignSize(sizeof(KeyInfo)); }
662
663 void InitBlock(BlockType block)
664 {
665 size_t offset = 0;
666 if (block == BlockType::BACKUP)
667 {
668 offset = block_size_;
669 }
670 flash_.Erase(offset, block_size_);
671
672 FlashInfo info; // padding filled with 0xFF by constructor
673 info.header = FLASH_HEADER;
674 KeyInfo& tmp_key = info.key;
675 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.no_next_key, true);
676 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.available_flag, true);
677 BlockBoolUtil<MinWriteSize>::SetFlag(tmp_key.uninit, false);
678 tmp_key.SetNameLength(0);
679 tmp_key.SetDataSize(0);
680 Write(offset, {reinterpret_cast<uint8_t*>(&info), sizeof(FlashInfo)});
681 Write(offset + block_size_ - AlignSize(sizeof(CHECKSUM_BYTE)),
682 {&CHECKSUM_BYTE, sizeof(CHECKSUM_BYTE)});
683 }
684
685 bool IsBlockInited(BlockType block)
686 {
687 size_t offset = 0;
688 if (block == BlockType::BACKUP)
689 {
690 offset = block_size_;
691 }
692 FlashInfo flash_data;
693 flash_.Read(offset, flash_data);
694 return flash_data.header == FLASH_HEADER;
695 }
696
697 bool IsBlockEmpty(BlockType block)
698 {
699 size_t offset = 0;
700 if (block == BlockType::BACKUP)
701 {
702 offset = block_size_;
703 }
704 FlashInfo flash_data;
705 flash_.Read(offset, flash_data);
706 return BlockBoolUtil<MinWriteSize>::ReadFlag(flash_data.key.available_flag) == true;
707 }
708
709 bool IsBlockError(BlockType block)
710 {
711 size_t offset = 0;
712 if (block == BlockType::BACKUP)
713 {
714 offset = block_size_;
715 }
716 uint32_t checksum = 0;
717 flash_.Read(offset + block_size_ - AlignSize(sizeof(CHECKSUM_BYTE)), checksum);
718 return checksum != CHECKSUM_BYTE;
719 }
720
721 size_t GetKeySize(size_t offset)
722 {
723 KeyInfo key;
724 flash_.Read(offset, key);
725 return AlignSize(sizeof(KeyInfo)) + AlignSize(key.GetNameLength()) +
726 AlignSize(key.GetDataSize());
727 }
728
729 size_t GetNextKey(size_t offset)
730 {
731 KeyInfo key;
732 flash_.Read(offset, key);
733 return offset + GetKeySize(offset);
734 }
735
736 size_t GetLastKey(BlockType block)
737 {
738 if (IsBlockEmpty(block))
739 {
740 return 0;
741 }
742
743 KeyInfo key;
744 size_t key_offset = OFFSET_OF(FlashInfo, key);
745 if (block != BlockType::MAIN)
746 {
747 key_offset += block_size_;
748 }
749 flash_.Read(key_offset, key);
750 while (!BlockBoolUtil<MinWriteSize>::ReadFlag(key.no_next_key))
751 {
752 key_offset = GetNextKey(key_offset);
753 flash_.Read(key_offset, key);
754 }
755 return key_offset;
756 }
757
758 bool KeyDataCompare(size_t offset, const void* data, size_t size)
759 {
760 KeyInfo key;
761 flash_.Read(offset, key);
762 size_t key_data_offset = GetKeyData(offset);
763 uint8_t data_buffer = 0;
764 for (size_t i = 0; i < size; i++)
765 {
766 flash_.Read(key_data_offset + i, data_buffer);
767 if (data_buffer != (reinterpret_cast<const uint8_t*>(data))[i])
768 {
769 return true;
770 }
771 }
772 return false;
773 }
774
775 bool KeyNameCompare(size_t offset, const char* name)
776 {
777 KeyInfo key;
778 flash_.Read(offset, key);
779 for (size_t i = 0; i < key.GetNameLength(); i++)
780 {
781 uint8_t data_buffer = 0;
782 flash_.Read(offset + AlignSize(sizeof(KeyInfo)) + i, data_buffer);
783 if (data_buffer != name[i])
784 {
785 return true;
786 }
787 }
788 return false;
789 }
790
791 bool KeyNameCompare(size_t offset_a, size_t offset_b)
792 {
793 KeyInfo key_a, key_b;
794 flash_.Read(offset_a, key_a);
795 flash_.Read(offset_b, key_b);
796 if (key_a.GetNameLength() != key_b.GetNameLength())
797 {
798 return true;
799 }
800 for (size_t i = 0; i < key_a.GetNameLength(); i++)
801 {
802 uint8_t data_buffer_a = 0, data_buffer_b = 0;
803 flash_.Read(offset_a + sizeof(KeyInfo) + i, data_buffer_a);
804 flash_.Read(offset_b + sizeof(KeyInfo) + i, data_buffer_b);
805 if (data_buffer_a != data_buffer_b)
806 {
807 return true;
808 }
809 }
810 return false;
811 }
812
813 void CopyFlashData(size_t dst_offset, size_t src_offset, size_t size)
814 {
815 for (size_t i = 0; i < size; i += MinWriteSize)
816 {
817 flash_.Read(src_offset + i, {write_buffer_, MinWriteSize});
818 flash_.Write(dst_offset + i, {write_buffer_, MinWriteSize});
819 }
820 }
821
822 size_t SearchKey(const char* name)
823 {
824 if (IsBlockEmpty(BlockType::MAIN))
825 {
826 return 0;
827 }
828
829 KeyInfo key;
830 size_t key_offset = OFFSET_OF(FlashInfo, key);
831 flash_.Read(key_offset, key);
832
833 size_t ans = 0, need_cycle = 0;
834
835 while (true)
836 {
837 if (!BlockBoolUtil<MinWriteSize>::ReadFlag(key.available_flag))
838 {
839 key_offset = GetNextKey(key_offset);
840 flash_.Read(key_offset, key);
841 need_cycle++;
842 continue;
843 }
844
845 if (!KeyNameCompare(key_offset, name))
846 {
847 ans = key_offset;
848 break;
849 }
850
851 if (BlockBoolUtil<MinWriteSize>::ReadFlag(key.no_next_key))
852 {
853 break;
854 }
855
856 key_offset = GetNextKey(key_offset);
857 flash_.Read(key_offset, key);
858 }
859
860 if (need_cycle > recycle_threshold_)
861 {
862 Recycle();
863 return SearchKey(name);
864 }
865
866 return ans;
867 }
868
875 size_t AlignSize(size_t size)
876 {
877 return static_cast<size_t>((size + MinWriteSize - 1) / MinWriteSize) * MinWriteSize;
878 }
879
887 ErrorCode Write(size_t offset, ConstRawData data)
888 {
889 if (data.size_ == 0)
890 {
891 return ErrorCode::OK;
892 }
893
894 if (data.size_ % MinWriteSize == 0)
895 {
896 return flash_.Write(offset, data);
897 }
898 else
899 {
900 auto final_block_index = data.size_ - data.size_ % MinWriteSize;
901 if (final_block_index != 0)
902 {
903 flash_.Write(offset, {data.addr_, final_block_index});
904 }
905 memset(write_buffer_, 0xff, MinWriteSize);
906 memcpy(write_buffer_,
907 reinterpret_cast<const uint8_t*>(data.addr_) + final_block_index,
908 data.size_ % MinWriteSize);
909 return flash_.Write(offset + final_block_index, {write_buffer_, MinWriteSize});
910 }
911 }
912
913 public:
922 ErrorCode Get(Database::KeyBase& key) override
923 {
924 auto ans = SearchKey(key.name_);
925 if (!ans)
926 {
927 return ErrorCode::NOT_FOUND;
928 }
929
930 KeyInfo key_buffer;
931 flash_.Read(ans, key_buffer);
932
933 if (key.raw_data_.size_ < key_buffer.GetDataSize())
934 {
935 return ErrorCode::FAILED;
936 }
937
938 flash_.Read(GetKeyData(ans), key.raw_data_);
939
940 return ErrorCode::OK;
941 }
942
950 ErrorCode Set(KeyBase& key, RawData data) override
951 {
952 memcpy(key.raw_data_.addr_, data.addr_, data.size_);
953 return SetKey(key.name_, data.addr_, data.size_);
954 }
955
956 ErrorCode Add(KeyBase& key) override
957 {
958 return AddKey(key.name_, key.raw_data_.addr_, key.raw_data_.size_);
959 }
960
968 explicit DatabaseRaw(Flash& flash, size_t recycle_threshold = 128)
969 : recycle_threshold_(recycle_threshold), flash_(flash)
970 {
971 ASSERT(flash.MinEraseSize() * 2 <= flash_.Size());
972 ASSERT(flash_.MinWriteSize() <= MinWriteSize);
973 auto block_num = static_cast<size_t>(flash_.Size() / flash.MinEraseSize());
974 block_size_ = block_num / 2 * flash.MinEraseSize();
975 Init();
976 }
977
982 void Init()
983 {
984 if (!IsBlockInited(BlockType::BACKUP) || IsBlockError(BlockType::BACKUP))
985 {
986 InitBlock(BlockType::BACKUP);
987 }
988
989 if (!IsBlockInited(BlockType::MAIN) || IsBlockError(BlockType::MAIN))
990 {
991 if (IsBlockEmpty(BlockType::BACKUP))
992 {
993 InitBlock(BlockType::MAIN);
994 }
995 else
996 {
998 for (uint32_t i = 0; i < block_size_; i += MinWriteSize)
999 {
1000 flash_.Read(i + block_size_, {write_buffer_, MinWriteSize});
1001 flash_.Write(i, {write_buffer_, MinWriteSize});
1002 }
1003 }
1004 }
1005
1006 if (!IsBlockEmpty(BlockType::BACKUP))
1007 {
1008 InitBlock(BlockType::BACKUP);
1009 }
1010
1011 KeyInfo key;
1012 size_t key_offset = OFFSET_OF(FlashInfo, key);
1013 flash_.Read(key_offset, key);
1014 size_t need_cycle = 0;
1016 {
1017 key_offset = GetNextKey(key_offset);
1018 flash_.Read(key_offset, key);
1019 // TODO: 恢复损坏数据
1021 {
1022 InitBlock(BlockType::MAIN);
1023 break;
1024 }
1026 {
1027 need_cycle += 1;
1028 }
1029 }
1030
1031 if (need_cycle > recycle_threshold_)
1032 {
1033 Recycle();
1034 }
1035 }
1036
1041 void Restore()
1042 {
1043 InitBlock(BlockType::MAIN);
1044 InitBlock(BlockType::BACKUP);
1045 }
1046
1057 ErrorCode Recycle()
1058 {
1059 if (IsBlockEmpty(BlockType::MAIN))
1060 {
1061 return ErrorCode::OK;
1062 }
1063
1064 KeyInfo key;
1065 size_t key_offset = OFFSET_OF(FlashInfo, key);
1066 flash_.Read(key_offset, key);
1067
1068 if (!IsBlockEmpty(BlockType::BACKUP))
1069 {
1070 ASSERT(false);
1071 return ErrorCode::FAILED;
1072 }
1073
1074 size_t write_buff_offset = OFFSET_OF(FlashInfo, key) + block_size_;
1075
1076 auto new_key = KeyInfo{};
1077 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.uninit, false);
1078 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.available_flag, false);
1079 BlockBoolUtil<MinWriteSize>::SetFlag(new_key.no_next_key, false);
1080 Write(write_buff_offset, new_key);
1081
1082 write_buff_offset += GetKeySize(write_buff_offset);
1083
1084 do
1085 {
1086 key_offset = GetNextKey(key_offset);
1087 flash_.Read(key_offset, key);
1088
1090 {
1091 continue;
1092 }
1093
1094 Write(write_buff_offset, key);
1095 write_buff_offset += AlignSize(sizeof(KeyInfo));
1096 CopyFlashData(write_buff_offset, GetKeyName(key_offset), key.GetNameLength());
1097 write_buff_offset += AlignSize(key.GetNameLength());
1098 CopyFlashData(write_buff_offset, GetKeyData(key_offset), key.GetDataSize());
1099 write_buff_offset += AlignSize(key.GetDataSize());
1101
1103 for (uint32_t i = 0; i < block_size_; i += MinWriteSize)
1104 {
1105 flash_.Read(i + block_size_, {write_buffer_, MinWriteSize});
1106 flash_.Write(i, {write_buffer_, MinWriteSize});
1107 }
1108
1109 InitBlock(BlockType::BACKUP);
1110
1111 return ErrorCode::OK;
1112 }
1113};
1114
1115} // 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:326
size_t AvailableSize()
计算可用的存储空间大小 (Calculate the available storage size).
Definition database.hpp:465
static constexpr uint32_t FLASH_HEADER
Flash 头部标识 (Flash header identifier).
Definition database.hpp:327
@ 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:968
ErrorCode Add(KeyBase &key) override
添加新键到数据库 (Add a new key to the database).
Definition database.hpp:956
ErrorCode Set(KeyBase &key, RawData data) override
设置数据库中的键值 (Set the key's value in the database).
Definition database.hpp:950
ErrorCode Recycle()
回收 Flash 空间,整理数据 (Recycle Flash storage space and organize data).
uint32_t block_size_
Flash 块大小 (Flash block size).
Definition database.hpp:457
static constexpr uint32_t CHECKSUM_BYTE
校验字节 (Checksum byte).
Definition database.hpp:330
void Init()
初始化数据库存储区,确保主备块正确 (Initialize database storage, ensuring main and backup blocks are valid).
Definition database.hpp:982
ErrorCode Write(size_t offset, ConstRawData data)
以最小写入单元对齐的方式写入数据 (Write data aligned to the minimum write unit).
Definition database.hpp:887
ErrorCode Get(Database::KeyBase &key) override
获取数据库中的键值 (Retrieve the key's value from the database).
Definition database.hpp:922
Flash & flash_
目标 Flash 存储设备 (Target Flash storage device).
Definition database.hpp:456
uint8_t write_buffer_[MinWriteSize]
写入缓冲区 (Write buffer).
Definition database.hpp:458
size_t AlignSize(size_t size)
计算对齐后的大小 (Calculate the aligned size).
Definition database.hpp:875
size_t recycle_threshold_
回收阈值 (Recycle threshold).
Definition database.hpp:455
适用于不支持逆序写入的 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:60
static constexpr uint8_t CHECKSUM_BYTE
校验字节 (Checksum byte).
Definition database.hpp:304
ErrorCode Set(KeyBase &key, RawData data) override
设置数据库中的键值 (Set the key's value in the database).
Definition database.hpp:212
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
ErrorCode Add(KeyBase &key) override
添加新键到数据库 (Add a new key to the database).
Definition database.hpp:223
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
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
原始数据封装类。 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:439
KeyInfo key
Align KeyInfo to MinWriteSize.
Definition database.hpp:451
uint32_t header
Flash block header.
Definition database.hpp:448
键信息结构,存储键的元数据 (Structure containing key metadata).
Definition database.hpp:402
BlockBoolData< MinWriteSize > no_next_key
是否是最后一个键
Definition database.hpp:403
BlockBoolData< MinWriteSize > available_flag
该键是否有效
Definition database.hpp:404
BlockBoolData< MinWriteSize > uninit
该键是否未初始化
Definition database.hpp:405
uint32_t raw_info
高7位为 nameLength,低25位为 dataSize
Definition database.hpp:407
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