A C++ binding library for FoundationDB.
- fmt : C++ formatting library (standardized in c++20)
- FoundationDB C binding : official C binding library shipped by foundationdb
- C++17 compliant compiler
Here is the quick start tutorial with some example of how to use the c++ binding above. The doxygen documentation provide more precise information.
Making a database connection.
#include <free_fdb/ffdb.hh>
auto ffdb = ffdb::free_fdb("path/to/fdb.cluster");
// making a transaction
auto transaction = ffdb.make_transaction();
// making an iterator
auto iterator = ffdb.make_iterator();
// transaction & iterator can then be used as shown below
When building an instance of
ffdb::free_fdb
class, at construction time a thread is launched in order to handle the fdb network. On the first initialization of the foundationdbffdb::free_fdb
instance the network is setup (it is ensured by a std::once_flag semaphore).
-
Put/Get/Remove key/value
auto trans = ffdb_instance.make_transaction(); // add kev / value trans->put("key_1", "value_1"); // retrieve kev / value auto kv = trans->get("key_1"); assert(kv); assert(kv->key == "key_1"); assert(kv->value == "value_1"); // delete kev / value trans->del("key_1"); assert(trans->get("key_1"));
-
Get/Delete a range of key/value
// We assume 4 key values are currently present in foundationdb // A_key_1/A_value_1, A_key_2/A_value_2, A_key_3/A_value_3, B_key_1/B_value_1 auto trans = ffdb_instance.make_transaction(); // get range from [A, B[ (B exclusive by default) auto result_A_to_B = trans->get_range("A", "B"); assert(3 == result_A_to_B.values.size()); assert(!result_A_to_B.truncated); assert(result_A_to_B.values[0].key == "A_key_1"); assert(result_A_to_B.values[0].value == "A_value_1"); assert(result_A_to_B.values[1].key == "A_key_2"); assert(result_A_to_B.values[1].value == "A_value_2"); assert(result_A_to_B.values[2].key == "A_key_3"); assert(result_A_to_B.values[2].value == "A_value_3"); trans->del_range("A", "B"); // last key still there out of the 4 initial keys auto last = trans->get("B_key_1"); assert(last); assert(last->key == "B_key_1"); assert(last->value == "B_value_1");
A useful trick, to delete completely the database:
auto trans = ffdb_instance.make_transaction(); trans_clear->del_range("", "\xFF");
-
Iterator implementation for range access
// We assume 4 key values are currently present in foundationdb // A_key_1/A_value_1, A_key_2/A_value_2, A_key_3/A_value_3, B_key_1/B_value_1 auto it = ffdb_instance.make_iterator(); // seek the first key starting with 'A', iteration stop until the next character ('B') it.seek("A"); for (; it.is_valid(); ++it) { auto &[key, value] = *it; std::cout << key << ":" << value << "\n"; } // output : // A_key_1 : A_value_1 // A_key_2 : A_value_2 // A_key_3 : A_value_3
seek
is not the only available way to seek initialize your iterator lookup. There areseek_for_prev(std::string)
orseek_first()
andseek_last()
working with the iterator option (parameter of the make_iterator which has not been used in this example).
- Counter implementation (using foundationdb atomic operations)
auto trans = ffdb_instance.make_transaction(); auto counter = ffdb::fdb_counter("counter_key"); assert(counter.value() == 0); counter.add(trans); assert(counter.value() == 1); counter.add(trans, 4); assert(counter.value() == 5); counter.sub(trans, 1); assert(counter.value() == 4); counter.add(trans, -1); assert(counter.value() == 3);
A complete doxygen documentation is available here.
A nix utility is also present in order to install/build locally free_fdb for local development. It is used by the CI.
nix-build . -A ffdb
TODO: hard to have the ci working... it is required to have an instance of foundationdb running. But starting the service isn't trivial through the nix recipe..
If you want to integrate free_fdb from your local nix project, you can add an attribute by fetching the recipe.nix file to your nix file directly with the url. Or you can just copy the recipe.nix file into your repository.
Example taken from the FyS project, {commit-hash} has to be replaced in order to fix the recipe to use in your project:
let pkgs = import <nixpkgs> { };
in with pkgs; rec {
# External Dependencies (personal)
ffdb = (callPackage (builtins.fetchurl
"https://raw.githubusercontent.com/FreeYourSoul/free_fdb/{commit-hash}/recipe.nix") {
rev = "{commit-hash}";
});
#.... your nix