shard kv_store

This commit is contained in:
Sky Johnson 2025-06-13 18:55:13 -05:00
parent ccf617b9bc
commit 652053128d

View File

@ -6,7 +6,7 @@
#include <optional> #include <optional>
#include <string> #include <string>
#include <variant> #include <variant>
#include <sstream> #include <array>
#include <mutex> #include <mutex>
using std::string; using std::string;
@ -15,39 +15,64 @@ class KeyValueStore {
public: public:
using Value = std::variant<int, double, string, bool>; using Value = std::variant<int, double, string, bool>;
private:
static constexpr size_t SHARD_COUNT = 16;
std::array<std::shared_mutex, SHARD_COUNT> mutexes_;
std::array<std::unordered_map<string, Value>, SHARD_COUNT> shards_;
string filename_ = "store.txt";
size_t get_shard(const string& key) const {
return std::hash<string>{}(key) % SHARD_COUNT;
}
public:
void set(const string& key, const Value& value) { void set(const string& key, const Value& value) {
std::unique_lock<std::shared_mutex> lock(mutex_); size_t shard = get_shard(key);
data_[key] = value; std::unique_lock<std::shared_mutex> lock(mutexes_[shard]);
shards_[shard][key] = value;
} }
template<typename T> template<typename T>
std::optional<T> get(const string& key) { std::optional<T> get(const string& key) {
std::shared_lock<std::shared_mutex> lock(mutex_); size_t shard = get_shard(key);
auto it = data_.find(key); std::shared_lock<std::shared_mutex> lock(mutexes_[shard]);
if (it == data_.end()) return std::nullopt; auto it = shards_[shard].find(key);
if (it == shards_[shard].end()) return std::nullopt;
if (auto* ptr = std::get_if<T>(&it->second)) { if (auto* ptr = std::get_if<T>(&it->second)) {
return *ptr; return *ptr;
} }
return std::nullopt; return std::nullopt;
} }
const std::unordered_map<string, Value>& get_all() { std::unordered_map<string, Value> get_all() {
std::shared_lock<std::shared_mutex> lock(mutex_); std::unordered_map<string, Value> result;
return data_;
for (size_t i = 0; i < SHARD_COUNT; ++i) {
std::shared_lock<std::shared_mutex> lock(mutexes_[i]);
for (const auto& [key, value] : shards_[i]) {
result[key] = value;
}
}
return result;
} }
bool del(const string& key) { bool del(const string& key) {
std::unique_lock<std::shared_mutex> lock(mutex_); size_t shard = get_shard(key);
return data_.erase(key) > 0; std::unique_lock<std::shared_mutex> lock(mutexes_[shard]);
return shards_[shard].erase(key) > 0;
} }
size_t size() { size_t size() {
std::shared_lock<std::shared_mutex> lock(mutex_); size_t total = 0;
return data_.size(); for (size_t i = 0; i < SHARD_COUNT; ++i) {
std::shared_lock<std::shared_mutex> lock(mutexes_[i]);
total += shards_[i].size();
}
return total;
} }
void set_file(const string& filename) { void set_file(const string& filename) {
std::unique_lock<std::shared_mutex> lock(mutex_);
filename_ = filename; filename_ = filename;
} }
@ -55,7 +80,6 @@ public:
std::ifstream file(filename_); std::ifstream file(filename_);
if (!file.is_open()) return; if (!file.is_open()) return;
std::unique_lock<std::shared_mutex> lock(mutex_);
string line; string line;
while (std::getline(file, line)) { while (std::getline(file, line)) {
size_t eq = line.find('='); size_t eq = line.find('=');
@ -65,22 +89,30 @@ public:
string val_str = line.substr(eq + 1); string val_str = line.substr(eq + 1);
char type = line[0]; char type = line[0];
Value value;
switch (type) { switch (type) {
case 'i': data_[key] = std::stoi(val_str); break; case 'i': value = std::stoi(val_str); break;
case 'd': data_[key] = std::stod(val_str); break; case 'd': value = std::stod(val_str); break;
case 's': data_[key] = val_str; break; case 's': value = val_str; break;
case 'b': data_[key] = (val_str == "1"); break; case 'b': value = (val_str == "1"); break;
default: continue;
} }
size_t shard = get_shard(key);
std::unique_lock<std::shared_mutex> lock(mutexes_[shard]);
shards_[shard][key] = std::move(value);
} }
} }
void save() { void save() {
std::shared_lock<std::shared_mutex> lock(mutex_);
std::ofstream file(filename_); std::ofstream file(filename_);
if (!file.is_open()) return; if (!file.is_open()) return;
for (const auto& [key, value] : data_) { for (size_t i = 0; i < SHARD_COUNT; ++i) {
file << serialize_entry(key, value) << "\n"; std::shared_lock<std::shared_mutex> lock(mutexes_[i]);
for (const auto& [key, value] : shards_[i]) {
file << serialize_entry(key, value) << "\n";
}
} }
} }
@ -99,8 +131,4 @@ private:
} }
}, value); }, value);
} }
std::unordered_map<string, Value> data_;
mutable std::shared_mutex mutex_;
string filename_ = "store.txt";
}; };