Heap.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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/ByteString.h>
  10. #include <AK/Debug.h>
  11. #include <AK/HashMap.h>
  12. #include <AK/RefCounted.h>
  13. #include <AK/Vector.h>
  14. #include <LibCore/File.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 RefCounted<Heap> {
  59. public:
  60. static constexpr u32 VERSION = 5;
  61. static ErrorOr<NonnullRefPtr<Heap>> create(ByteString);
  62. virtual ~Heap();
  63. ByteString const& name() const { return m_name; }
  64. ErrorOr<void> open();
  65. ErrorOr<size_t> file_size_in_bytes() const;
  66. [[nodiscard]] bool has_block(Block::Index) const;
  67. [[nodiscard]] Block::Index request_new_block_index();
  68. Block::Index schemas_root() const { return m_schemas_root; }
  69. void set_schemas_root(Block::Index root)
  70. {
  71. m_schemas_root = root;
  72. update_zero_block().release_value_but_fixme_should_propagate_errors();
  73. }
  74. Block::Index tables_root() const { return m_tables_root; }
  75. void set_tables_root(Block::Index root)
  76. {
  77. m_tables_root = root;
  78. update_zero_block().release_value_but_fixme_should_propagate_errors();
  79. }
  80. Block::Index table_columns_root() const { return m_table_columns_root; }
  81. void set_table_columns_root(Block::Index root)
  82. {
  83. m_table_columns_root = root;
  84. update_zero_block().release_value_but_fixme_should_propagate_errors();
  85. }
  86. u32 version() const { return m_version; }
  87. u32 user_value(size_t index) const
  88. {
  89. return m_user_values[index];
  90. }
  91. void set_user_value(size_t index, u32 value)
  92. {
  93. m_user_values[index] = value;
  94. update_zero_block().release_value_but_fixme_should_propagate_errors();
  95. }
  96. ErrorOr<ByteBuffer> read_storage(Block::Index);
  97. ErrorOr<void> write_storage(Block::Index, ReadonlyBytes);
  98. ErrorOr<void> free_storage(Block::Index);
  99. ErrorOr<void> flush();
  100. private:
  101. explicit Heap(ByteString);
  102. ErrorOr<ByteBuffer> read_raw_block(Block::Index);
  103. ErrorOr<void> write_raw_block(Block::Index, ReadonlyBytes);
  104. ErrorOr<void> write_raw_block_to_wal(Block::Index, ByteBuffer&&);
  105. ErrorOr<Block> read_block(Block::Index);
  106. ErrorOr<void> write_block(Block const&);
  107. ErrorOr<void> free_block(Block const&);
  108. ErrorOr<void> read_zero_block();
  109. ErrorOr<void> initialize_zero_block();
  110. ErrorOr<void> update_zero_block();
  111. ByteString m_name;
  112. OwnPtr<Core::InputBufferedFile> m_file;
  113. Block::Index m_highest_block_written { 0 };
  114. Block::Index m_next_block { 1 };
  115. Block::Index m_schemas_root { 0 };
  116. Block::Index m_tables_root { 0 };
  117. Block::Index m_table_columns_root { 0 };
  118. u32 m_version { VERSION };
  119. Array<u32, 16> m_user_values { 0 };
  120. HashMap<Block::Index, ByteBuffer> m_write_ahead_log;
  121. Vector<Block::Index> m_free_block_indices;
  122. };
  123. }