Heap.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
  3. * Copyright (c) 2023, Jelle Raaijmakers <jelle@gmta.nl>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/Array.h>
  9. #include <AK/Debug.h>
  10. #include <AK/DeprecatedString.h>
  11. #include <AK/HashMap.h>
  12. #include <AK/Vector.h>
  13. #include <LibCore/File.h>
  14. #include <LibCore/Object.h>
  15. namespace SQL {
  16. /**
  17. * A Block represents a single discrete chunk of 1024 bytes inside the Heap, and
  18. * acts as the container format for the actual data we are storing. This structure
  19. * is used for everything except block 0, the zero / super block.
  20. *
  21. * If data needs to be stored that is larger than 1016 bytes, Blocks are chained
  22. * together by setting the next block index and the data is reconstructed by
  23. * repeatedly reading blocks until the next block index is 0.
  24. */
  25. class Block {
  26. public:
  27. typedef u32 Index;
  28. static constexpr u32 SIZE = 1024;
  29. static constexpr u32 HEADER_SIZE = sizeof(u32) + sizeof(Index);
  30. static constexpr u32 DATA_SIZE = SIZE - HEADER_SIZE;
  31. Block(Index index, u32 size_in_bytes, Index next_block, ByteBuffer data)
  32. : m_index(index)
  33. , m_size_in_bytes(size_in_bytes)
  34. , m_next_block(next_block)
  35. , m_data(move(data))
  36. {
  37. VERIFY(index > 0);
  38. }
  39. Index index() const { return m_index; }
  40. u32 size_in_bytes() const { return m_size_in_bytes; }
  41. Index next_block() const { return m_next_block; }
  42. ByteBuffer const& data() const { return m_data; }
  43. private:
  44. Index m_index;
  45. u32 m_size_in_bytes;
  46. Index m_next_block;
  47. ByteBuffer m_data;
  48. };
  49. /**
  50. * A Heap is a logical container for database (SQL) data. Conceptually a
  51. * Heap can be a database file, or a memory block, or another storage medium.
  52. * It contains datastructures, like B-Trees, hash_index tables, or tuple stores
  53. * (basically a list of data tuples).
  54. *
  55. * A Heap can be thought of the backing storage of a single database. It's
  56. * assumed that a single SQL database is backed by a single Heap.
  57. */
  58. class Heap : public Core::Object {
  59. C_OBJECT(Heap);
  60. public:
  61. static constexpr u32 VERSION = 4;
  62. virtual ~Heap() override;
  63. ErrorOr<void> open();
  64. ErrorOr<size_t> file_size_in_bytes() const;
  65. [[nodiscard]] bool has_block(Block::Index) const;
  66. [[nodiscard]] Block::Index request_new_block_index();
  67. Block::Index schemas_root() const { return m_schemas_root; }
  68. void set_schemas_root(Block::Index root)
  69. {
  70. m_schemas_root = root;
  71. update_zero_block().release_value_but_fixme_should_propagate_errors();
  72. }
  73. Block::Index tables_root() const { return m_tables_root; }
  74. void set_tables_root(Block::Index root)
  75. {
  76. m_tables_root = root;
  77. update_zero_block().release_value_but_fixme_should_propagate_errors();
  78. }
  79. Block::Index table_columns_root() const { return m_table_columns_root; }
  80. void set_table_columns_root(Block::Index root)
  81. {
  82. m_table_columns_root = root;
  83. update_zero_block().release_value_but_fixme_should_propagate_errors();
  84. }
  85. u32 version() const { return m_version; }
  86. u32 user_value(size_t index) const
  87. {
  88. return m_user_values[index];
  89. }
  90. void set_user_value(size_t index, u32 value)
  91. {
  92. m_user_values[index] = value;
  93. update_zero_block().release_value_but_fixme_should_propagate_errors();
  94. }
  95. ErrorOr<ByteBuffer> read_storage(Block::Index);
  96. ErrorOr<void> write_storage(Block::Index, ReadonlyBytes);
  97. ErrorOr<void> free_storage(Block::Index);
  98. ErrorOr<void> flush();
  99. private:
  100. explicit Heap(DeprecatedString);
  101. ErrorOr<ByteBuffer> read_raw_block(Block::Index);
  102. ErrorOr<void> write_raw_block(Block::Index, ReadonlyBytes);
  103. ErrorOr<void> write_raw_block_to_wal(Block::Index, ByteBuffer&&);
  104. ErrorOr<Block> read_block(Block::Index);
  105. ErrorOr<void> write_block(Block const&);
  106. ErrorOr<void> free_block(Block const&);
  107. ErrorOr<void> read_zero_block();
  108. ErrorOr<void> initialize_zero_block();
  109. ErrorOr<void> update_zero_block();
  110. OwnPtr<Core::InputBufferedFile> m_file;
  111. Block::Index m_highest_block_written { 0 };
  112. Block::Index m_next_block { 1 };
  113. Block::Index m_schemas_root { 0 };
  114. Block::Index m_tables_root { 0 };
  115. Block::Index m_table_columns_root { 0 };
  116. u32 m_version { VERSION };
  117. Array<u32, 16> m_user_values { 0 };
  118. HashMap<Block::Index, ByteBuffer> m_write_ahead_log;
  119. Vector<Block::Index> m_free_block_indices;
  120. };
  121. }