1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-29 08:21:15 +03:00
This patch moves FDB to utils dir and adds test on `remove keys range`.
This commit is contained in:
Denis Khalikov
2024-08-28 05:11:09 +00:00
committed by Leonid Fedorov
parent a02d15ad11
commit bb861f8fab
7 changed files with 151 additions and 101 deletions

View File

@ -0,0 +1,24 @@
include_directories(${ENGINE_COMMON_INCLUDES})
find_library(FDB_LIB fdb_c)
if (NOT FDB_LIB)
MESSAGE_ONCE(FATAL_ERROR "FoundationDB not installed properly, please install packages foundationdb-cliends and foundationdb-server")
return()
endif()
add_library(fdbcs SHARED src/fdbcs.cpp)
target_link_libraries(fdbcs fdb_c)
add_executable(test_fdb_api test/test_fdb_api.cpp)
add_dependencies(test_fdb_api fdbcs)
target_link_libraries(test_fdb_api fdbcs fdb_c)
install(TARGETS fdbcs
LIBRARY DESTINATION ${ENGINE_LIBDIR}
COMPONENT columnstore-engine
)
install(TARGETS test_fdb_api
RUNTIME DESTINATION ${ENGINE_BINDIR}
COMPONENT columnstore-engine
)

View File

@ -0,0 +1,108 @@
/* Copyright (C) 2024 MariaDB Corporation
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
#pragma once
#include <string>
#include <iostream>
#include <thread>
#include <memory>
// https://apple.github.io/foundationdb/api-c.html
// We have to define `FDB_API_VERSION` before include `fdb_c.h` header.
#define FDB_API_VERSION 630
#include <foundationdb/fdb_c.h>
namespace FDBCS
{
// TODO: How about uint8_t.
using ByteArray = std::string;
// Represensts a `transaction`.
class Transaction
{
public:
Transaction() = delete;
Transaction(const Transaction&) = delete;
Transaction(Transaction&&) = delete;
Transaction& operator=(const Transaction&) = delete;
Transaction& operator=(Transaction&&) = delete;
explicit Transaction(FDBTransaction* tnx);
~Transaction();
// Sets a given `key` and given `value`.
void set(const ByteArray& key, const ByteArray& value) const;
// Gets a `value` by the given `key`.
std::pair<bool, ByteArray> get(const ByteArray& key) const;
// Removes a given `key` from database.
void remove(const ByteArray& key) const;
// Removes all keys in the given range, starting from `beginKey` until `endKey`, but not including `endKey`.
void removeRange(const ByteArray& beginKey, const ByteArray& endKey) const;
// Commits transaction.
bool commit() const;
private:
FDBTransaction* tnx_{nullptr};
};
// Represents network class.
class FDBNetwork
{
public:
FDBNetwork() = default;
FDBNetwork(const FDBNetwork&) = delete;
FDBNetwork(FDBNetwork&&) = delete;
FDBNetwork& operator=(const FDBNetwork&) = delete;
FDBNetwork& operator=(FDBNetwork&&) = delete;
~FDBNetwork();
bool setUpAndRunNetwork();
private:
std::thread netThread;
};
// Represents database class.
class FDBDataBase
{
public:
FDBDataBase() = delete;
FDBDataBase(const FDBDataBase&) = delete;
FDBDataBase& operator=(FDBDataBase&) = delete;
FDBDataBase(FDBDataBase&&) = delete;
FDBDataBase& operator=(FDBDataBase&&) = delete;
explicit FDBDataBase(FDBDatabase* database);
~FDBDataBase();
std::unique_ptr<Transaction> createTransaction() const;
bool isDataBaseReady() const;
private:
FDBDatabase* database_;
const uint32_t secondsToWait_ = 3;
};
// Represents a creator class for the `FDBDatabase`.
class DataBaseCreator
{
public:
// Creates a `FDBDataBase` from the given `clusterFilePath` (path to the cluster file).
static std::shared_ptr<FDBDataBase> createDataBase(const std::string clusterFilePath);
};
bool setAPIVersion();
} // namespace FDBCS

View File

@ -0,0 +1,214 @@
/* Copyright (C) 2024 MariaDB Corporation
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
#include <string>
#include <iostream>
#include <thread>
#include <chrono>
#include "../include/fdbcs.hpp"
namespace FDBCS
{
Transaction::Transaction(FDBTransaction* tnx) : tnx_(tnx)
{
}
Transaction::~Transaction()
{
if (tnx_)
{
fdb_transaction_destroy(tnx_);
tnx_ = nullptr;
}
}
void Transaction::set(const ByteArray& key, const ByteArray& value) const
{
if (tnx_)
{
fdb_transaction_set(tnx_, (uint8_t*)key.c_str(), key.length(), (uint8_t*)value.c_str(), value.length());
}
}
std::pair<bool, ByteArray> Transaction::get(const ByteArray& key) const
{
if (tnx_)
{
FDBFuture* future = fdb_transaction_get(tnx_, (uint8_t*)key.c_str(), key.length(), 0);
auto err = fdb_future_block_until_ready(future);
if (err)
{
fdb_future_destroy(future);
std::cerr << "fdb_future_block_until_read error, code: " << (int)err << std::endl;
return {false, {}};
}
const uint8_t* outValue;
int outValueLength;
fdb_bool_t present;
err = fdb_future_get_value(future, &present, &outValue, &outValueLength);
if (err)
{
fdb_future_destroy(future);
std::cerr << "fdb_future_get_value error, code: " << (int)err << std::endl;
return {false, {}};
}
fdb_future_destroy(future);
if (present)
{
return {true, ByteArray(outValue, outValue + outValueLength)};
}
else
{
return {false, {}};
}
}
return {false, {}};
}
void Transaction::remove(const ByteArray& key) const
{
if (tnx_)
{
fdb_transaction_clear(tnx_, (uint8_t*)key.c_str(), key.length());
}
}
void Transaction::removeRange(const ByteArray& beginKey, const ByteArray& endKey) const
{
if (tnx_)
{
fdb_transaction_clear_range(tnx_, (uint8_t*)beginKey.c_str(), beginKey.length(), (uint8_t*)endKey.c_str(),
endKey.length());
}
}
bool Transaction::commit() const
{
if (tnx_)
{
FDBFuture* future = fdb_transaction_commit(tnx_);
auto err = fdb_future_block_until_ready(future);
if (err)
{
fdb_future_destroy(future);
std::cerr << "fdb_future_block_until_ready error, code: " << (int)err << std::endl;
return false;
}
fdb_future_destroy(future);
}
return true;
}
FDBNetwork::~FDBNetwork()
{
auto err = fdb_stop_network();
if (err)
std::cerr << "fdb_stop_network error, code: " << err << std::endl;
if (netThread.joinable())
netThread.join();
}
bool FDBNetwork::setUpAndRunNetwork()
{
auto err = fdb_setup_network();
if (err)
{
std::cerr << "fdb_setup_network error, code: " << (int)err << std::endl;
return false;
}
netThread = std::thread(
[]
{
// TODO: Try more than on time.
auto err = fdb_run_network();
if (err)
{
std::cerr << "fdb_run_network error, code: " << (int)err << std::endl;
abort();
}
});
return true;
}
FDBDataBase::FDBDataBase(FDBDatabase* database) : database_(database)
{
}
FDBDataBase::~FDBDataBase()
{
if (database_)
fdb_database_destroy(database_);
}
std::unique_ptr<Transaction> FDBDataBase::createTransaction() const
{
FDBTransaction* tnx;
auto err = fdb_database_create_transaction(database_, &tnx);
if (err)
{
std::cerr << "fdb_database_create_transaction error, code: " << (int)err << std::endl;
return nullptr;
}
return std::make_unique<Transaction>(tnx);
}
bool FDBDataBase::isDataBaseReady() const
{
FDBTransaction* tnx;
auto err = fdb_database_create_transaction(database_, &tnx);
if (err)
{
std::cerr << "fdb_database_create_transaction error, code: " << (int)err << std::endl;
return false;
}
ByteArray emptyKey{""};
FDBFuture* future = fdb_transaction_get(tnx, (uint8_t*)emptyKey.c_str(), emptyKey.length(), 0);
uint32_t count = 0;
while (!fdb_future_is_ready(future) && count < secondsToWait_)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
++count;
}
bool ready = fdb_future_is_ready(future);
fdb_future_destroy(future);
fdb_transaction_destroy(tnx);
return ready;
}
std::shared_ptr<FDBDataBase> DataBaseCreator::createDataBase(const std::string clusterFilePath)
{
FDBDatabase* database;
auto err = fdb_create_database(clusterFilePath.c_str(), &database);
if (err)
{
std::cerr << "fdb_create_database error, code: " << (int)err << std::endl;
return nullptr;
}
return std::make_shared<FDBDataBase>(database);
}
bool setAPIVersion()
{
auto err = fdb_select_api_version(FDB_API_VERSION);
return err ? false : true;
}
} // namespace FDBCS

View File

@ -0,0 +1,102 @@
/* Copyright (C) 2024 MariaDB Corporation
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
#include <vector>
#include "../include/fdbcs.hpp"
using namespace std;
using namespace FDBCS;
template <typename T>
static void assert_internal(const T& value, const std::string& errMessage)
{
if (!value)
{
std::cerr << errMessage << std::endl;
abort();
}
}
int main()
{
std::string path = "/etc/foundationdb/fdb.cluster";
assert_internal(setAPIVersion(), "Set api version failed.");
FDBNetwork netWork;
// Create and run network.
assert_internal(netWork.setUpAndRunNetwork(), "Set up network failed.");
// Create database.
auto db = DataBaseCreator::createDataBase(path);
assert_internal(db, "Cannot create FDB.");
assert_internal(db->isDataBaseReady(), "FDB is down.");
const std::vector<std::pair<std::string, std::string>> kvArray{
{"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}};
const std::string endKey = "key4";
// Set a key/value.
{
auto tnx = db->createTransaction();
tnx->set(kvArray[0].first, kvArray[0].second);
assert_internal(tnx->commit(), "Cannot commit set().");
}
// Get a value by a key.
{
auto tnx = db->createTransaction();
auto p = tnx->get(kvArray[0].first);
assert_internal(p.first, "get() failed.");
assert_internal(p.second == kvArray[0].second, "get(): keys are not matched.");
}
// Remove a key.
{
auto tnx = db->createTransaction();
tnx->remove(kvArray[0].first);
assert_internal(tnx->commit(), "Cannot commit remove().");
}
// Check that key is not presetnt anymore.
{
auto tnx = db->createTransaction();
auto p = tnx->get(kvArray[0].first);
assert_internal(!p.first, "Key exists after remove().");
}
// Remove range.
for (const auto& [key, value] : kvArray)
{
{
auto tnx = db->createTransaction();
tnx->set(key, value);
assert_internal(tnx->commit(), "Cannot commit set() for range.");
}
}
{
auto tnx = db->createTransaction();
tnx->removeRange(kvArray.front().first, endKey);
assert_internal(tnx->commit(), "Cannot commit removeRange().");
}
for (const auto& [key, value] : kvArray)
{
{
auto tnx = db->createTransaction();
auto rPair = tnx->get(key);
assert_internal(!rPair.first, "Key exists after remove range.");
}
}
return 0;
}