update protocol description & added more settings to toml

This commit is contained in:
g2px1 2025-04-21 12:08:27 +03:00
parent c99392fc16
commit 86dbb1f942
8 changed files with 152 additions and 12 deletions

View File

@ -66,6 +66,8 @@ add_executable(sharedMemoryKeyDB
core/UDB.h
core/DatabaseManager.cpp
core/DatabaseManager.h
utils/config/GlobalConfig.h
utils/config/GlobalConfig.cpp
)
add_executable(sharedMemoryKeyDB_client

View File

@ -210,4 +210,53 @@ response = read_bytes(ptr, offset + 1050, response_size)
- После обработки команды — инкрементировать `tail` мод capacity.
- Ответ через `response` + `response_size` + `response_ready` только для `FIND`.
---
---
# Конфиг
Пример:
```toml
# Список баз данных
[[database]]
name = "rates1"
[[database]]
name = "test"
# Настройки базы rates1
[databases.rates1]
shm_queue_capacity = 2048 # Размер очереди команд в shared memory (количество команд)
max_memtable_size = 2097152 # Максимальный размер активной Memtable в байтах (до сброса на диск)
l0_queue_capacity = 2048 # Размер очереди для фоновой компакции L0 SSTables
estimated_element_size = 256 # Оценка среднего размера одного элемента в Memtable в байтах
# Настройки базы test
[databases.test]
shm_queue_capacity = 1024
max_memtable_size = 1048576
l0_queue_capacity = 1024
estimated_element_size = 128
```
## Замечания:
Если параметры не заданы для конкретной базы, используются значения по умолчанию:
```cpp
shm_queue_capacity = 1024
max_memtable_size = 1048576
l0_queue_capacity = 1024
estimated_element_size = 128
```
> Все размеры (max_memtable_size, estimated_element_size) указываются в байтах.
> Shared Memory для каждой базы будет создана с именем /shm_<имя_базы>.
> Очереди (l0_queue, shm_queue) построены на lock-free кольцевых буферах.
## Полное описание параметров конфига
| Параметр | Тип | Описание |
| :----------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `shm_queue_capacity` | `size_t` | **Размер очереди команд в shared memory**. <br>Это количество слотов команд (PUT/DELETE/FIND), которые могут одновременно находиться в памяти. Если очередь заполнится — новые команды временно не смогут быть отправлены. <br>**Важно**: shared memory выделяется исходя из этого размера, поэтому очередь большого размера требует больше памяти. |
| `max_memtable_size` | `size_t` | **Максимальный размер активной Memtable в байтах**. <br>Когда объем данных в Memtable превышает это значение, Memtable сбрасывается на диск в SSTable-файл. <br>**Если значение маленькое** — будет много мелких SSTable-файлов. <br>**Если значение большое** — реже будет происходить сброс, но потребление оперативной памяти будет выше. |
| `l0_queue_capacity` | `size_t` | **Размер очереди файлов для компакции L0 уровня**. <br>Когда Memtable сбрасывается в SSTable, файл ставится в очередь на компакцию. Этот параметр задает максимальное количество файлов, которые можно держать в очереди одновременно. <br>**Если значение маленькое** — компакция будет происходить чаще. <br>**Если большое** — будет задержка в обработке компакции при большом потоке вставок. |
| `estimated_element_size` | `size_t` | **Оценка среднего размера одного элемента в Memtable**. <br>Используется для **приближенного** расчета реального размера Memtable. Нужно, чтобы **не замерять точно каждый вставленный элемент**, а быстро определять когда пора сбрасывать Memtable. <br>**Типичный случай**: текстовые значения без больших вложений имеют размер 64-256 байт. |

View File

@ -4,7 +4,6 @@
#include "DatabaseManager.h"
namespace usub::core
{
DatabaseManager::DatabaseManager(const std::string& config_path)
@ -34,8 +33,10 @@ namespace usub::core
{
throw std::runtime_error("Database entry must be a table");
}
utils::load_global_config(config);
auto& database_settings = utils::database_settings_map.at(db_name);
bool create_new = !SharedMemoryManager::exists("shm_" + db_name);
auto udb = std::make_unique<UDB>(db_name, "shm_" + db_name, 1024, 1024 * 1024, create_new);
auto udb = std::make_unique<UDB>(db_name, "shm_" + db_name, database_settings, create_new);
this->databases_.push_back(DatabaseInstance{std::move(udb), {}});
}
}

View File

@ -10,6 +10,7 @@
#include <mutex>
#include "utils/io/Wal.h"
#include "utils/io/VersionManager.h"
#include "utils/config/GlobalConfig.h"
namespace usub::shared_storage
{
@ -19,7 +20,7 @@ namespace usub::shared_storage
class MemTableManager
{
public:
MemTableManager(const std::string& wal_file, size_t max_size, utils::VersionManager& vm);
MemTableManager(const std::string& wal_file, size_t max_size, size_t estimated_element_size, utils::VersionManager& vm);
~MemTableManager();
@ -41,6 +42,7 @@ namespace usub::shared_storage
std::vector<std::pair<typename SkipList::key_type, typename SkipList::value_type>> write_batch;
std::atomic<bool> flushing{false};
VersionManager& version_manager;
size_t estimated_element_size;
private:
size_t estimate_memtable_size() const;
@ -49,7 +51,7 @@ namespace usub::shared_storage
};
template <typename SkipList>
MemTableManager<SkipList>::MemTableManager(const std::string& wal_file, size_t max_size, VersionManager& vm)
MemTableManager<SkipList>::MemTableManager(const std::string& wal_file, size_t max_size, size_t estimated_element_size, VersionManager& vm)
: wal(wal_file), max_memtable_size(max_size), version_manager(vm)
{
this->active_memtable.store(new SkipList(this->version_manager));

View File

@ -7,14 +7,14 @@
namespace usub::core
{
UDB::UDB(const std::string& db_name, const std::string& shm_name,
size_t shm_queue_capacity, size_t max_memtable_size, bool create_new)
utils::DatabaseSettings settings, bool create_new)
: db_name_(db_name),
shm_name_(shm_name),
shm_queue_capacity_(shm_queue_capacity),
max_memtable_size_(max_memtable_size),
shm_queue_capacity_(settings.shm_queue_capacity),
max_memtable_size_(settings.max_memtable_size),
shm_manager_(shm_name, sizeof(SharedCommandQueue), create_new),
version_manager_(db_name),
memtable_manager_(db_name + "_wal", max_memtable_size, this->version_manager_),
memtable_manager_(db_name + "_wal", settings.max_memtable_size, settings.estimated_element_size, this->version_manager_),
compactor_(this->version_manager_),
running_(true)
{

View File

@ -25,14 +25,14 @@
#include "Memtable.h"
#include "utils/io/RecoveryLog.h"
#include "utils/io/Compactor.h"
#include "utils/config/GlobalConfig.h"
namespace usub::core
{
class UDB
{
public:
UDB(const std::string& db_name, const std::string& shm_name, size_t shm_queue_capacity = 1024,
size_t max_memtable_size = 1024 * 1024, bool create_new = true);
UDB(const std::string& db_name, const std::string& shm_name, utils::DatabaseSettings settings, bool create_new = true);
~UDB();
@ -65,4 +65,3 @@ namespace usub::core
}
#endif // UDB_H

View File

@ -0,0 +1,58 @@
//
// Created by Kirill Zhukov on 21.04.2025.
//
#include "GlobalConfig.h"
#include <iostream>
#include "utils/toml/toml.hpp"
namespace usub::utils
{
std::unordered_map<std::string, DatabaseSettings> database_settings_map;
void load_global_config(toml::parse_result& path)
{
try
{
if (auto databases = path["databases"].as_table())
{
for (const auto& db : *databases)
{
const auto& db_name = db.first;
const auto& db_config = db.second;
if (!db_config.is_table())
continue;
DatabaseSettings settings;
const auto& table = *db_config.as_table();
if (auto val = table[toml::path("shm_queue_capacity")].value<size_t>())
settings.shm_queue_capacity = *val;
if (auto val = table[toml::path("max_memtable_size")].value<size_t>())
settings.max_memtable_size = *val;
if (auto val = table[toml::path("l0_queue_capacity")].value<size_t>())
settings.l0_queue_capacity = *val;
if (auto val = table[toml::path("estimated_element_size")].value<size_t>())
settings.estimated_element_size = *val;
database_settings_map.emplace(db_name.str(), settings);
std::cout << "[Config] Loaded for DB '" << db_name << "': "
<< "shm_queue_capacity=" << settings.shm_queue_capacity
<< ", max_memtable_size=" << settings.max_memtable_size
<< ", l0_queue_capacity=" << settings.l0_queue_capacity
<< ", estimated_element_size=" << settings.estimated_element_size
<< "\n";
}
}
}
catch (const std::exception& ex)
{
std::cerr << "[Config] Failed to load config: " << ex.what() << "\n";
}
}
}

View File

@ -0,0 +1,29 @@
//
// Created by Kirill Zhukov on 21.04.2025.
//
#ifndef GLOBAL_CONFIG_H
#define GLOBAL_CONFIG_H
#include <cstddef>
#include <string>
#include <unordered_map>
#include "utils/toml/toml.hpp"
namespace usub::utils
{
struct DatabaseSettings
{
size_t shm_queue_capacity = 1024;
size_t max_memtable_size = 1024 * 1024;
size_t l0_queue_capacity = 1024;
size_t estimated_element_size = 128;
};
extern std::unordered_map<std::string, DatabaseSettings> database_settings_map;
void load_global_config(toml::parse_result& path);
}
#endif //GLOBAL_CONFIG_H