diff --git a/storage-manager/CMakeLists.txt b/storage-manager/CMakeLists.txt index a874a93d4..d0f823a4c 100755 --- a/storage-manager/CMakeLists.txt +++ b/storage-manager/CMakeLists.txt @@ -75,6 +75,18 @@ set_property(TARGET StorageManager PROPERTY CXX_STANDARD 20) set(TMPDIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) +find_library(FDB_LIB fdb_c) +if (FDB_LIB) + add_library(fdbcs SHARED fdb_wrapper_cpp/src/fdbcs.cpp) + target_link_libraries(fdbcs fdb_c) + + add_executable(test_fdb_api fdb_wrapper_cpp/test/test_fdb_api.cpp) + add_dependencies(test_fdb_api fdbcs) + target_link_libraries(test_fdb_api fdbcs fdb_c) + + add_test(NAME columnstore:test_fdb_api COMMAND test_fdb_api) +endif() + add_executable(unit_tests src/unit_tests.cpp) target_compile_definitions(unit_tests PUBLIC BOOST_NO_CXX11_SCOPED_ENUMS) target_link_libraries(unit_tests storagemanager) @@ -145,3 +157,10 @@ install(FILES storagemanager.cnf DESTINATION ${ENGINE_SYSCONFDIR}/columnstore COMPONENT columnstore-engine ) + +if (FDB_LIB) +install(TARGETS fdbcs + LIBRARY DESTINATION ${ENGINE_LIBDIR} + COMPONENT columnstore-engine +) +endif() diff --git a/storage-manager/fdb_wrapper_cpp/include/fdbcs.hpp b/storage-manager/fdb_wrapper_cpp/include/fdbcs.hpp new file mode 100644 index 000000000..40171a585 --- /dev/null +++ b/storage-manager/fdb_wrapper_cpp/include/fdbcs.hpp @@ -0,0 +1,94 @@ +/* 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 +#include +#include + +// 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 + +namespace FDBCS +{ +// TODO: How about uint8_t. +using ByteArray = std::string; + +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(); + + void set(const ByteArray& key, const ByteArray& value) const; + std::pair get(const ByteArray& key) const; + void remove(const ByteArray& key) const; + bool commit() const; + + private: + FDBTransaction* tnx_{nullptr}; +}; + +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; +}; + +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 createTransaction() const; + + private: + FDBDatabase* database_; +}; + +class DataBaseCreator +{ + public: + static std::unique_ptr createDataBase(const std::string clusterFilePath); +}; + +bool setAPIVersion(); +} // namespace FDBCS diff --git a/storage-manager/fdb_wrapper_cpp/src/fdbcs.cpp b/storage-manager/fdb_wrapper_cpp/src/fdbcs.cpp new file mode 100644 index 000000000..54ac491a9 --- /dev/null +++ b/storage-manager/fdb_wrapper_cpp/src/fdbcs.cpp @@ -0,0 +1,181 @@ +/* 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 +#include +#include +#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 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()); + } +} + +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 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(tnx); +} + +std::unique_ptr 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_unique(database); +} + +bool setAPIVersion() +{ + auto err = fdb_select_api_version(FDB_API_VERSION); + return err ? false : true; +} +} // namespace FDBCS diff --git a/storage-manager/fdb_wrapper_cpp/test/test_fdb_api.cpp b/storage-manager/fdb_wrapper_cpp/test/test_fdb_api.cpp new file mode 100644 index 000000000..2840fefac --- /dev/null +++ b/storage-manager/fdb_wrapper_cpp/test/test_fdb_api.cpp @@ -0,0 +1,63 @@ +/* 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 "../fdb_wrapper_cpp/include/fdbcs.hpp" + +// FIXME: Use GOOGLE test. +#include +using namespace std; +using namespace FDBCS; + +int main() { + std::string path = "/etc/foundationdb/fdb.cluster"; + setAPIVersion(); + FDBNetwork netWork; + // Create and run network. + assert(netWork.setUpAndRunNetwork() == true); + + // Create database. + std::unique_ptr db = DataBaseCreator::createDataBase(path); + std::string key1 = "fajsdlkfjaskljfewiower39423fds"; + std::string value1 = "gfdgjksdflfdsjkslkdrewuior39243"; + // Set a key/value. + { + auto tnx = db->createTransaction(); + tnx->set(key1, value1); + assert(tnx->commit() == true); + } + // Get a value by a key. + { + auto tnx = db->createTransaction(); + auto p = tnx->get(key1); + assert(p.first == true); + assert(p.second == value1); + } + // Remove a key. + { + auto tnx = db->createTransaction(); + tnx->remove(key1); + assert(tnx->commit() == true); + } + // Check that key is not presetnt anymore. + { + auto tnx = db->createTransaction(); + auto p = tnx->get(key1); + assert(p.first == false); + } + + return 0; +}