Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
Expand Down
1 change: 0 additions & 1 deletion include/cpp_lmdb/cpp_lmdb.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

// std
#include <concepts>
#include <expected>
#include <iterator>
#include <optional>
#include <utility>
26 changes: 13 additions & 13 deletions include/cpp_lmdb/dbs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@
// lmdb
#include "lmdb.h"

// std
#include <concepts>
#include <expected>

namespace lmdb
{
namespace details
Expand All @@ -31,14 +27,17 @@ class db_base {
using transaction = transaction<KeyValueTrait, ReadOnly, LmdbApi>;

template <read_only_t ReadOnly>
auto make_transaction() const
-> std::expected<transaction<ReadOnly>, error_t>
auto make_transaction() const LMDB_NOEXCEPT
-> LMDB_RESULT(transaction<ReadOnly>)
{
auto txn = details::make_tx<LmdbApi>(_api, _env, ReadOnly);
if (!txn)
return std::unexpected{error_t{txn.error()}};

return transaction<ReadOnly>{_db_index, std::move(txn.value())};
auto const make_transaction
= [this](auto &&txn) -> LMDB_RESULT(transaction<ReadOnly>) {
return transaction<ReadOnly>{_db_index, std::move(txn)};
};

return LMDB_AND_THEN(std::move(txn), make_transaction);
}

private:
Expand All @@ -62,7 +61,8 @@ class ro_db : public details::db_base<KeyValueTrait, LmdbApi> {
public:
using base::base;

auto begin_ro_transaction() const -> std::expected<ro_transaction, error_t>
auto begin_ro_transaction() const LMDB_NOEXCEPT
-> LMDB_RESULT(ro_transaction)
{
return base::template make_transaction<read_only_t::yes>();
}
Expand All @@ -79,13 +79,13 @@ class rw_db : public ro_db<KeyValueTrait, LmdbApi> {
public:
using base::base;

auto begin_rw_transaction() -> std::expected<rw_transaction, error_t>
auto begin_rw_transaction() LMDB_NOEXCEPT -> LMDB_RESULT(rw_transaction)
{
return base::template make_transaction<read_only_t::no>();
}

auto commit_transaction(rw_transaction &&transaction)
-> std::expected<void, error_t>
auto commit_transaction(rw_transaction &&transaction) LMDB_NOEXCEPT
-> LMDB_RESULT(void)
{
return std::move(transaction).commit();
}
Expand Down
47 changes: 21 additions & 26 deletions include/cpp_lmdb/details/details.hpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#pragma once

#include "cpp_lmdb/error.hpp"
#include "cpp_lmdb/types.hpp"

// lmdb
#include "lmdb.h"

// std
#include <expected>
#include <memory>
#include <span>
#include <type_traits>

namespace lmdb::details
{
Expand All @@ -34,7 +33,9 @@ inline auto to_byte_span(MDB_val const &value) noexcept

inline auto to_mdb_val(byte_span const &value) noexcept
{
return MDB_val{value.size(), const_cast<std::byte *>(value.data())};
return MDB_val{
.mv_size = value.size(),
.mv_data = const_cast<std::byte *>(value.data())};
}

template <typename Trait>
Expand All @@ -53,37 +54,34 @@ struct txn_deleter {
LmdbApi const &api;
};

template <class... Ts>
struct overloaded : Ts... {
using Ts::operator()...;
};

template <typename LmdbApi>
using txn_unique_ptr_t = std::unique_ptr<MDB_txn, txn_deleter<LmdbApi>>;

template <typename LmdbApi>
constexpr auto make_tx(
LmdbApi const &api, MDB_env &env, read_only_t const read_only)
-> std::expected<txn_unique_ptr_t<LmdbApi>, int>
LmdbApi const &api,
MDB_env &env,
read_only_t const read_only) LMDB_NOEXCEPT
-> LMDB_RESULT(txn_unique_ptr_t<LmdbApi>)
{
MDB_txn *txn{nullptr};
if (auto const result = api.mdb_txn_begin(
&env,
nullptr,
read_only == read_only_t::yes ? MDB_RDONLY : 0,
&txn);
result != MDB_SUCCESS) {
return std::unexpected{result};
}
LMDB_CALL_API(api.mdb_txn_begin(
&env, nullptr, read_only == read_only_t::yes ? MDB_RDONLY : 0, &txn));

return txn_unique_ptr_t<LmdbApi>{txn, details::txn_deleter<LmdbApi>{api}};
}

template <typename LmdbApi>
constexpr auto commit_tx(LmdbApi const &api, txn_unique_ptr_t<LmdbApi> &&tx)
-> std::expected<void, int>
LMDB_NOEXCEPT -> LMDB_RESULT(void)
{
if (auto const result = api.mdb_txn_commit(tx.release());
result != MDB_SUCCESS) {
return std::unexpected{result};
}

return {};
LMDB_CALL_API(api.mdb_txn_commit(tx.release()));
LMDB_REPORT_SUCCESS();
}

template <typename LmdbApi>
Expand All @@ -102,14 +100,11 @@ using cursor_unique_ptr_t

template <typename LmdbApi>
constexpr auto make_cursor(
LmdbApi const &api, MDB_txn *const txn, MDB_dbi const dbi)
-> std::expected<cursor_unique_ptr_t<LmdbApi>, int>
LmdbApi const &api, MDB_txn *const txn, MDB_dbi const dbi) LMDB_NOEXCEPT
-> LMDB_RESULT(cursor_unique_ptr_t<LmdbApi>)
{
MDB_cursor *cursor{nullptr};
if (auto const result = api.mdb_cursor_open(txn, dbi, &cursor);
result != MDB_SUCCESS) {
return std::unexpected{result};
}
LMDB_CALL_API(api.mdb_cursor_open(txn, dbi, &cursor));

return cursor_unique_ptr_t<LmdbApi>{cursor, cursor_deleter<LmdbApi>{api}};
}
Expand Down
102 changes: 55 additions & 47 deletions include/cpp_lmdb/environment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "cpp_lmdb/concepts.hpp"
#include "cpp_lmdb/db_item.hpp"
#include "cpp_lmdb/dbs.hpp"
#include "cpp_lmdb/error.hpp"
#include "cpp_lmdb/iterators.hpp"
#include "cpp_lmdb/transactions.hpp"
#include "cpp_lmdb/types.hpp"
Expand All @@ -18,9 +19,7 @@

// std
#include <concepts>
#include <expected>
#include <iterator>
#include <optional>
#include <utility>

namespace lmdb
Expand Down Expand Up @@ -66,54 +65,63 @@ class environment_base {
using LmdbApiType = std::remove_reference_t<LmdbApi>;

template <key_value_trait KeyValueTrait, read_only_t ReadOnly>
using open_db_result = std::expected<
std::conditional_t<
ReadOnly == read_only_t::yes,
ro_db<KeyValueTrait, LmdbApiType>,
rw_db<KeyValueTrait, LmdbApiType>>,
error_t>;
using open_db_result = std::conditional_t<
ReadOnly == read_only_t::yes,
ro_db<KeyValueTrait, LmdbApiType>,
rw_db<KeyValueTrait, LmdbApiType>>;

template <key_value_trait KeyValueTrait, read_only_t ReadOnly>
auto open_db(
char const *const name,
create_if_not_exists const create_flag
= create_if_not_exists::no) const
-> open_db_result<KeyValueTrait, ReadOnly>
= create_if_not_exists::no) const LMDB_NOEXCEPT
-> LMDB_RESULT((open_db_result<KeyValueTrait, ReadOnly>))
{
auto &api = _env.get_deleter().api;
auto transaction = make_tx(api, *_env, ReadOnly);
if (!transaction)
return std::unexpected{error_t{transaction.error()}};

const auto creation_flags
= key_value_trait_helper<KeyValueTrait>::db_key_value_flags()
| (create_flag == create_if_not_exists::yes ? MDB_CREATE : 0);

MDB_dbi db_index{};
LMDB_CALL_API(api.mdb_dbi_open(
transaction->get(), name, creation_flags, &db_index));

if constexpr (key_value_trait_helper<KeyValueTrait>::has_key_cmp_fun) {
LMDB_CALL_API(api.mdb_set_compare(
transaction->get(),
db_index,
cmp<typename KeyValueTrait::key_trait>));
}

if constexpr (key_value_trait_helper<
KeyValueTrait>::has_value_cmp_fun) {
LMDB_CALL_API(api.mdb_set_dupsort(
transaction->get(),
db_index,
cmp<typename KeyValueTrait::value_trait>));
}

if (auto const result = commit_tx(api, std::move(transaction.value()));
!result)
return std::unexpected{error_t{result.error()}};

return typename open_db_result<KeyValueTrait, ReadOnly>::value_type{
api, db_index, *_env};

auto txn = make_tx(api, *_env, ReadOnly);

using result_type
= LMDB_RESULT((open_db_result<KeyValueTrait, ReadOnly>));

auto const open_db =
[&env = _env, &api, name, create_flag](auto &&txn) -> result_type {
const auto creation_flags
= key_value_trait_helper<KeyValueTrait>::db_key_value_flags()
| (create_flag == create_if_not_exists::yes ? MDB_CREATE
: 0);

MDB_dbi db_index{};
LMDB_CALL_API(
api.mdb_dbi_open(txn.get(), name, creation_flags, &db_index));

if constexpr (
key_value_trait_helper<KeyValueTrait>::has_key_cmp_fun) {
LMDB_CALL_API(api.mdb_set_compare(
txn.get(),
db_index,
cmp<typename KeyValueTrait::key_trait>));
}

if constexpr (
key_value_trait_helper<KeyValueTrait>::has_value_cmp_fun) {
LMDB_CALL_API(api.mdb_set_dupsort(
txn.get(),
db_index,
cmp<typename KeyValueTrait::value_trait>));
}

auto result = commit_tx(api, std::move(txn));

auto const make_db = [&env, &api, db_index]() -> result_type {
return open_db_result<KeyValueTrait, ReadOnly>{
api, db_index, *env};
};

return LMDB_AND_THEN(std::move(result), make_db);
};

return LMDB_AND_THEN(std::move(txn), open_db);
}

private:
Expand All @@ -134,7 +142,7 @@ class ro_environment : public details::environment_base<LmdbApi> {

template <key_value_trait KeyValueTrait>
auto open_ro_db(char const *const name) const noexcept
-> std::expected<ro_db<KeyValueTrait>, error_t>
-> LMDB_RESULT(ro_db<KeyValueTrait>)
{
return details::environment_base<
LmdbApi>::template open_db<KeyValueTrait, read_only_t::yes>(name);
Expand All @@ -156,7 +164,7 @@ class rw_environment : public ro_environment<LmdbApi> {
char const *const name,
create_if_not_exists const create_flag
= create_if_not_exists::no) noexcept
-> std::expected<rw_db<KeyValueTrait>, error_t>
-> LMDB_RESULT(rw_db<KeyValueTrait>)
{
return base::template open_db<KeyValueTrait, read_only_t::no>(
name, create_flag);
Expand All @@ -179,8 +187,8 @@ template <
auto make_environment(
char const *const environment_path,
db_file_mode_t const db_file_mode,
LmdbApi &&api = LmdbApi{})
LMDB_NOEXCEPT->LMDB_RESULT((environment_t<is_readonly(flags), LmdbApi>))
LmdbApi &&api = LmdbApi{}) LMDB_NOEXCEPT
-> LMDB_RESULT((environment_t<is_readonly(flags), LmdbApi>))
{
MDB_env *env{nullptr};
LMDB_CALL_API(api.mdb_env_create(&env));
Expand Down
Loading
Loading