vkdb
A time series database engine in C++.
Loading...
Searching...
No Matches
mem_table.h
1#ifndef STORAGE_MEM_TABLE_H
2#define STORAGE_MEM_TABLE_H
3
4#include <vkdb/concepts.h>
5#include <vkdb/string.h>
6#include <vkdb/time_series_key.h>
7#include <vkdb/data_range.h>
8
9namespace vkdb {
10
16template <ArithmeticNoCVRefQuals TValue>
17class MemTable {
18public:
19 using key_type = TimeSeriesKey;
20 using mapped_type = std::optional<TValue>;
21 using value_type = std::pair<const key_type, mapped_type>;
22 using size_type = uint64_t;
23 using table_type = std::map<const key_type, mapped_type>;
24
25 static constexpr size_type C0_LAYER_SSTABLE_MAX_ENTRIES{100'000};
26
30 MemTable() noexcept = default;
31
37 MemTable(table_type&& entries) noexcept
38 : table_{std::move(entries)} {}
39
43 MemTable(MemTable&&) noexcept = default;
44
50 MemTable& operator=(MemTable&&) noexcept = default;
51
55 MemTable(const MemTable&) = delete;
56
60 MemTable& operator=(const MemTable&) = delete;
61
65 ~MemTable() noexcept = default;
66
75 void put(const key_type& key, const mapped_type& value) {
76 table_.insert_or_assign(key, value);
77 update_ranges(key);
78 }
79
87 [[nodiscard]] bool contains(const key_type& key) const noexcept {
88 return in_range(key) && table_.contains(key);
89 }
90
99 [[nodiscard]] mapped_type get(const key_type& key) const {
100 if (!in_range(key)) {
101 throw std::invalid_argument{
102 "MemTable::get(): Key '" + key.str() + "' not in the memtable."
103 };
104 }
105 auto it{table_.find(key)};
106 if (it != table_.end()) {
107 return it->second;
108 }
109 throw std::invalid_argument{
110 "MemTable::get(): Key '" + key.str() + "' not in the memtable."
111 };
112 }
113
123 [[nodiscard]] std::vector<value_type> getRange(
124 const key_type& start,
125 const key_type& end
126 ) const {
127 if (!overlaps_with(start, end)) {
128 return {};
129 }
130 std::vector<value_type> entries;
131 for (auto it{table_.lower_bound(start)};
132 it != table_.end() && it->first < end; ++it) {
133 entries.push_back(*it);
134 }
135 return entries;
136 }
137
142 void clear() noexcept {
143 table_.clear();
144 time_range_.clear();
145 key_range_.clear();
146 }
147
153 [[nodiscard]] table_type table() const noexcept {
154 return table_;
155 }
156
162 [[nodiscard]] size_type size() const noexcept {
163 return table_.size();
164 }
165
172 [[nodiscard]] bool empty() const noexcept {
173 return table_.empty();
174 }
175
181 [[nodiscard]] std::string str() const noexcept {
182 std::stringstream ss;
183 ss << size();
184 for (const auto& entry : table()) {
185 ss << entryToString<TValue>(entry);
186 }
187 return ss.str();
188 }
189
198 static void fromString(const std::string& str, MemTable& table) {
199 std::stringstream ss(str);
200 size_type size;
201 ss >> size;
202
203 std::string entry_str;
204 std::getline(ss, entry_str, '[');
205
206 while (std::getline(ss, entry_str, '[')) {
207 auto [entry_key, entry_value]
208 = entryFromString<TValue>(std::move(entry_str));
209 table.put(entry_key, entry_value);
210 }
211 }
212
213private:
221 [[nodiscard]] bool in_range(const key_type& key) const noexcept {
222 return time_range_.inRange(key.timestamp()) && key_range_.inRange(key);
223 }
224
230 void update_ranges(const key_type& key) noexcept {
231 time_range_.updateRange(key.timestamp());
232 key_range_.updateRange(key);
233 }
234
243 [[nodiscard]] bool overlaps_with(const key_type& start,
244 const key_type& end) const noexcept {
245 return time_range_.overlapsWith(start.timestamp(), end.timestamp())
246 || key_range_.overlapsWith(start, end);
247 }
248
253 TimeRange time_range_;
254
259 KeyRange key_range_;
260
265 table_type table_;
266};
267
278template <ArithmeticNoCVRefQuals TValue>
279std::ostream& operator<<(std::ostream& os, const MemTable<TValue>& table) {
280 os << table.str();
281 return os;
282}
283
294template <ArithmeticNoCVRefQuals TValue>
295std::istream& operator>>(std::istream& is, MemTable<TValue>& table) {
296 std::string str;
297 is >> str;
299 return is;
300}
301} // namespace vkdb
302
303#endif // STORAGE_MEM_TABLE_H
bool overlapsWith(const data_type &start, const data_type &end) const noexcept
Check if the range overlaps with the given range.
Definition data_range.h:144
void clear() noexcept
Clear the range.
Definition data_range.h:183
bool inRange(const data_type &data) const noexcept
Check if the data is in the range.
Definition data_range.h:132
void updateRange(const data_type &data) noexcept
Update the range with the given data.
Definition data_range.h:113
In-memory table for storing key-value pairs.
Definition mem_table.h:17
static void fromString(const std::string &str, MemTable &table)
Converts a string representation to a table.
Definition mem_table.h:198
bool empty() const noexcept
Checks if the table is empty.
Definition mem_table.h:172
MemTable() noexcept=default
Construct a new MemTable object.
void put(const key_type &key, const mapped_type &value)
Inserts or updates a key-value pair in the table.
Definition mem_table.h:75
void clear() noexcept
Clears the table.
Definition mem_table.h:142
size_type size() const noexcept
Returns the size of the table.
Definition mem_table.h:162
mapped_type get(const key_type &key) const
Retrieves the value associated with a key.
Definition mem_table.h:99
bool contains(const key_type &key) const noexcept
Checks if the table contains a key.
Definition mem_table.h:87
MemTable(MemTable &&) noexcept=default
Move-construct a MemTable object.
table_type table() const noexcept
Returns the table.
Definition mem_table.h:153
std::string str() const noexcept
Converts the table to a string representation.
Definition mem_table.h:181
std::vector< value_type > getRange(const key_type &start, const key_type &end) const
Retrieves a range of key-value pairs.
Definition mem_table.h:123
Represents a key in vkdb.
std::string str() const noexcept
Get the string representation of the key.