Blink DB Documentation v1.0.0
Blink DB Documentation
Loading...
Searching...
No Matches
sstable.hpp
Go to the documentation of this file.
1
8#ifndef SS_TABLE
9#define SS_TABLE
10
11#include "constants.hpp"
12#include "memtable.hpp"
13#include <cstddef>
14#include <fstream>
15#include <string>
16
24class SS_Table {
25private:
26 std::string index_filename;
27 std::string data_filename;
28 std::vector<std::pair<std::string, uint64_t>> index;
29 bool indexLoaded = false;
30
31 static constexpr size_t KEYS_PER_INDEX_ENTRY = 10;
32
38 std::optional<uint64_t> findStartOffset(const std::string &key) {
39 if (index.empty()) {
40 return std::nullopt;
41 }
42
43 if (key < index[0].first) {
44 return index[0].second;
45 }
46
47 size_t left = 0, right = index.size() - 1;
48 while (left < right) {
49 size_t mid = left + (right - left + 1) / 2;
50 if (index[mid].first <= key) {
51 left = mid;
52 } else {
53 right = mid - 1;
54 }
55 }
56
57 return index[left].second;
58 }
59
60public:
65 SS_Table(const std::string &filename) : index_filename(filename + INDEX_EXTENSION), data_filename(filename + DATA_EXTENSION) {
66 indexLoaded = loadIndex();
67 }
68
74 SS_Table(const std::string &index_filename, const std::string &data_filename) : index_filename(index_filename), data_filename(data_filename) {
75 indexLoaded = loadIndex();
76 }
77
84 static bool createFromMemTable(const std::string &filename, MemTable *memTable) {
85 /*
86 data file format: [Key Size] [Key] [Value Size] [Value]
87 [Key Size] [Key] [Value Size] [Value]
88 [4 bytes] [N bytes] [4 bytes] [M bytes]
89 index file format: [Key Size] [Key] [Offset]
90 */
91 std::ofstream indexFile(filename + INDEX_EXTENSION, std::ios::binary);
92 std::ofstream dataFile(filename + DATA_EXTENSION, std::ios::binary);
93 if (!indexFile.is_open() || !dataFile.is_open()) {
94 return false;
95 }
96
97 std::vector<KeyValuePair> entries;
98 for (auto it = memTable->begin(); it != memTable->end(); ++it) {
99 entries.push_back(*it);
100 }
101
102 uint64_t entries_count = entries.size();
103 uint64_t sparse_index_count = (entries_count + KEYS_PER_INDEX_ENTRY - 1) / KEYS_PER_INDEX_ENTRY;
104 indexFile.write(reinterpret_cast<const char *>(&sparse_index_count), sizeof(sparse_index_count));
105 uint64_t offset = 0;
106
107 for (size_t i = 0; i < entries.size(); i++) {
108 const KeyValuePair &entry = entries[i];
109 uint32_t key_size = entry.getKey().size();
110 uint32_t value_size = entry.getValue().size();
111
112 if (i % KEYS_PER_INDEX_ENTRY == 0) {
113 indexFile.write(reinterpret_cast<const char *>(&key_size), sizeof(key_size));
114 indexFile.write(entry.getKey().c_str(), key_size);
115 indexFile.write(reinterpret_cast<const char *>(&offset), sizeof(offset));
116 }
117
118 dataFile.write(reinterpret_cast<const char *>(&key_size), sizeof(key_size));
119 dataFile.write(entry.getKey().c_str(), key_size);
120 dataFile.write(reinterpret_cast<const char *>(&value_size), sizeof(value_size));
121 dataFile.write(entry.getValue().c_str(), value_size);
122
123 offset += sizeof(key_size) + key_size + sizeof(value_size) + value_size;
124 }
125
126 indexFile.close();
127 dataFile.close();
128 return true;
129 }
130
135 bool loadIndex() {
136 std::ifstream indexFile(index_filename, std::ios::binary);
137 if (!indexFile.is_open()) {
138 return false;
139 }
140
141 index.clear();
142
143 uint64_t entries_count;
144 indexFile.read(reinterpret_cast<char *>(&entries_count), sizeof(entries_count));
145
146 index.reserve(entries_count);
147 for (uint64_t i = 0; i < entries_count; i++) {
148 uint32_t key_size;
149 indexFile.read(reinterpret_cast<char *>(&key_size), sizeof(key_size));
150 std::string key(key_size, '\0');
151 indexFile.read(&key[0], key_size);
152 uint64_t offset;
153 indexFile.read(reinterpret_cast<char *>(&offset), sizeof(offset));
154 index.push_back({std::move(key), offset});
155 }
156 indexFile.close();
157 return true;
158 }
159
165 std::pair<bool, std::string> getValue(std::string key) {
166 if (!indexLoaded) {
167 return {false, ""};
168 }
169 std::optional<uint64_t> start_offset = findStartOffset(key);
170 if (!start_offset.has_value()) {
171 return {false, ""};
172 }
173
174 std::ifstream dataFile(data_filename, std::ios::binary);
175 if (!dataFile.is_open()) {
176 return {false, ""};
177 }
178 dataFile.seekg(start_offset.value());
179
180 while (!dataFile.eof()) {
181 uint32_t key_size;
182 dataFile.read(reinterpret_cast<char *>(&key_size), sizeof(key_size));
183 if (dataFile.eof()) {
184 break;
185 }
186
187 std::string stored_key(key_size, 0);
188 dataFile.read(&stored_key[0], key_size);
189 if (stored_key > key) {
190 return {false, ""};
191 }
192
193 uint32_t value_size;
194 dataFile.read(reinterpret_cast<char *>(&value_size), sizeof(value_size));
195 std::string value(value_size, 0);
196 dataFile.read(&value[0], value_size);
197
198 if (stored_key == key) {
199 dataFile.close();
200 if (value == TOMBSTONE) {
201 return {false, value};
202 }
203 return {true, value};
204 }
205 }
206 dataFile.close();
207 return {false, ""};
208 }
209
214 std::string getIndexFile() const {
215 return index_filename;
216 }
217
222 std::string getDataFilename() const {
223 return data_filename;
224 }
225};
226
227#endif
Key-Value Pair Class.
Definition key_value.hpp:19
const std::string & getValue() const
Get the Value object.
Definition key_value.hpp:58
const std::string & getKey() const
Get the Key object.
Definition key_value.hpp:51
MemTable Class.
Definition memtable.hpp:23
static bool createFromMemTable(const std::string &filename, MemTable *memTable)
Creates an SSTable from a given MemTable.
Definition sstable.hpp:84
SS_Table(const std::string &filename)
Constructs an SS_Table from a given filename (excluding extensions).
Definition sstable.hpp:65
bool loadIndex()
Loads the SSTable index from the index file.
Definition sstable.hpp:135
std::string getDataFilename() const
Gets the filename of the SSTable's data file.
Definition sstable.hpp:222
std::pair< bool, std::string > getValue(std::string key)
Retrieves the value associated with a key from the SSTable.
Definition sstable.hpp:165
std::string getIndexFile() const
Gets the filename of the SSTable's index file.
Definition sstable.hpp:214
SS_Table(const std::string &index_filename, const std::string &data_filename)
Constructs an SS_Table from existing index and data filenames.
Definition sstable.hpp:74
Constants for the database engine.
const std::string INDEX_EXTENSION
Index Extenstion Constant.
Definition constants.hpp:29
const std::string DATA_EXTENSION
Data Extension Constant.
Definition constants.hpp:37
#define TOMBSTONE
TOMOBSTONE constant.
Definition constants.hpp:22
MemTable Class.