9 #include <libpmemobj++/string_view.hpp> 
   15 #include "libpmemkv.h" 
   16 #include <libpmemobj/pool_base.h> 
   77     OK = PMEMKV_STATUS_OK,               
 
   78     UNKNOWN_ERROR = PMEMKV_STATUS_UNKNOWN_ERROR, 
 
   79     NOT_FOUND = PMEMKV_STATUS_NOT_FOUND, 
 
   80     NOT_SUPPORTED = PMEMKV_STATUS_NOT_SUPPORTED, 
 
   82     INVALID_ARGUMENT = PMEMKV_STATUS_INVALID_ARGUMENT, 
 
   84     CONFIG_PARSING_ERROR =
 
   85         PMEMKV_STATUS_CONFIG_PARSING_ERROR, 
 
   87         PMEMKV_STATUS_CONFIG_TYPE_ERROR, 
 
   89     STOPPED_BY_CB = PMEMKV_STATUS_STOPPED_BY_CB, 
 
   92         PMEMKV_STATUS_OUT_OF_MEMORY, 
 
   95         PMEMKV_STATUS_WRONG_ENGINE_NAME, 
 
   97     TRANSACTION_SCOPE_ERROR =
 
   98         PMEMKV_STATUS_TRANSACTION_SCOPE_ERROR, 
 
  100     DEFRAG_ERROR = PMEMKV_STATUS_DEFRAG_ERROR, 
 
  103         PMEMKV_STATUS_COMPARATOR_MISMATCH, 
 
  109     static const std::string statuses[] = {
"OK",
 
  114                            "CONFIG_PARSING_ERROR",
 
  119                            "TRANSACTION_SCOPE_ERROR",
 
  121                            "COMPARATOR_MISMATCH"};
 
  123     int status_no = 
static_cast<int>(s);
 
  124     os << statuses[status_no] << 
" (" << status_no << 
")";
 
  151     explicit config(pmemkv_config *cfg) noexcept;
 
  161     template <
typename T>
 
  163             const std::size_t number = 1) noexcept;
 
  165     template <typename T>
 
  167               void (*deleter)(
void *)) noexcept;
 
  168     template <typename T, typename D>
 
  169     status put_object(const std::
string &key, std::unique_ptr<T, D> 
object) noexcept;
 
  172     status put_string(const std::
string &key, const std::
string &value) noexcept;
 
  178     template <typename Comparator>
 
  181     template <typename T>
 
  182     status get_data(const std::
string &key, T *&value, std::
size_t &number) const
 
  184     template <typename T>
 
  187     status get_uint64(const std::
string &key, std::uint64_t &value) const noexcept;
 
  188     status get_int64(const std::
string &key, std::int64_t &value) const noexcept;
 
  189     status get_string(const std::
string &key, std::
string &value) const noexcept;
 
  191     pmemkv_config *
release() noexcept;
 
  217     db(
db &&other) noexcept;
 
  222     status open(
const std::string &engine_name) noexcept;
 
  223     status open(
const std::string &engine_name, 
config &&cfg) noexcept;
 
  225     void close() noexcept;
 
  227     status count_all(std::
size_t &cnt) noexcept;
 
  233                  std::
size_t &cnt) noexcept;
 
  267     status defrag(
double start_percent = 0, 
double amount_percent = 100);
 
  269     std::
string errormsg();
 
  298 template <
typename T, 
typename D>
 
  309     std::unique_ptr<T, D> 
ptr;
 
  320 template <
typename Comparator>
 
  332         return cmp.compare(key1, key2);
 
  340         std::unique_ptr<comparator_base> ptr,
 
  341         std::unique_ptr<pmemkv_comparator, decltype(pmemkv_comparator_delete) *>
 
  343         : ptr(std::move(ptr)), c_cmp(std::move(c_cmp))
 
  352     std::unique_ptr<comparator_base> 
ptr;
 
  353     std::unique_ptr<pmemkv_comparator, decltype(pmemkv_comparator_delete) *> 
c_cmp;
 
  362 static inline void call_up_destructor(
void *
object)
 
  368 static inline void *call_up_get(
void *
object)
 
  370     auto *ptr = 
static_cast<unique_ptr_wrapper_base *
>(object);
 
  374 static inline int call_comparator_function(
const char *k1, 
size_t kb1, 
const char *k2,
 
  375                        size_t kb2, 
void *arg)
 
  377     auto *cmp = 
static_cast<comparator_base *
>(arg);
 
  388     this->_config = 
nullptr;
 
  397     this->_config = other._config;
 
  398     other._config = 
nullptr;
 
  411         pmemkv_config_delete(this->_config);
 
  413     this->_config = other._config;
 
  414     other._config = 
nullptr;
 
  434         pmemkv_config_delete(this->_config);
 
  445     if (this->_config == 
nullptr) {
 
  446         this->_config = pmemkv_config_new();
 
  448         if (this->_config == 
nullptr)
 
  465 template <
typename T>
 
  467                    const std::size_t count) noexcept
 
  470         return status::UNKNOWN_ERROR;
 
  472     return static_cast<status>(pmemkv_config_put_data(
 
  473         this->_config, key.data(), (
void *)value, count * 
sizeof(T)));
 
  486 template <
typename T>
 
  488                  void (*deleter)(
void *)) noexcept
 
  491         return status::UNKNOWN_ERROR;
 
  493     return static_cast<status>(pmemkv_config_put_object(this->_config, key.data(),
 
  494                                 (
void *)value, deleter));
 
  505 template <
typename T, 
typename D>
 
  507                  std::unique_ptr<T, D> 
object) noexcept
 
  510         return status::UNKNOWN_ERROR;
 
  516     } 
catch (std::bad_alloc &e) {
 
  517         return status::OUT_OF_MEMORY;
 
  519         return status::UNKNOWN_ERROR;
 
  522     return static_cast<status>(pmemkv_config_put_object_cb(
 
  523         this->_config, key.data(), (
void *)wrapper, internal::call_up_get,
 
  524         internal::call_up_destructor));
 
  543 template <
typename Comparator>
 
  547         std::is_same<decltype(std::declval<Comparator>().compare(
 
  548                      std::declval<string_view>(),
 
  549                      std::declval<string_view>())),
 
  551         "Comparator should implement `int compare(pmem::kv::string_view, pmem::kv::string_view)` method");
 
  552     static_assert(std::is_convertible<decltype(std::declval<Comparator>().name()),
 
  554               "Comparator should implement `std::string name()` method");
 
  556     std::unique_ptr<internal::comparator_base> wrapper;
 
  559         wrapper = std::unique_ptr<internal::comparator_base>(
 
  561                 std::forward<Comparator>(comparator)));
 
  562     } 
catch (std::bad_alloc &e) {
 
  563         return status::OUT_OF_MEMORY;
 
  565         return status::UNKNOWN_ERROR;
 
  569         std::unique_ptr<pmemkv_comparator, decltype(pmemkv_comparator_delete) *>(
 
  570             pmemkv_comparator_new(&internal::call_comparator_function,
 
  571                           std::string(comparator.name()).c_str(),
 
  573             &pmemkv_comparator_delete);
 
  575         return status::UNKNOWN_ERROR;
 
  582     } 
catch (std::bad_alloc &e) {
 
  583         return status::OUT_OF_MEMORY;
 
  585         return status::UNKNOWN_ERROR;
 
  588     return static_cast<status>(pmemkv_config_put_object_cb(
 
  589         this->_config, 
"comparator", (
void *)entry, internal::call_up_get,
 
  590         internal::call_up_destructor));
 
  604         return status::UNKNOWN_ERROR;
 
  606     return static_cast<status>(
 
  607         pmemkv_config_put_uint64(this->_config, key.data(), value));
 
  621         return status::UNKNOWN_ERROR;
 
  623     return static_cast<status>(
 
  624         pmemkv_config_put_int64(this->_config, key.data(), value));
 
  636                  const std::string &value) noexcept
 
  639         return status::UNKNOWN_ERROR;
 
  641     return static_cast<status>(
 
  642         pmemkv_config_put_string(this->_config, key.data(), value.data()));
 
  679     return put_uint64(
"force_create", value ? 1 : 0);
 
  694         return status::UNKNOWN_ERROR;
 
  696     return static_cast<status>(pmemkv_config_put_oid(this->_config, oid));
 
  709 template <
typename T>
 
  711                    std::size_t &count) 
const noexcept
 
  713     if (this->_config == 
nullptr)
 
  714         return status::NOT_FOUND;
 
  717     auto s = 
static_cast<status>(pmemkv_config_get_data(
 
  718         this->_config, key.data(), (
const void **)&value, &size));
 
  723     count = size / 
sizeof(T);
 
  737 template <
typename T>
 
  740     if (this->_config == 
nullptr)
 
  741         return status::NOT_FOUND;
 
  743     auto s = 
static_cast<status>(
 
  744         pmemkv_config_get_object(this->_config, key.data(), (
void **)&value));
 
  760     if (this->_config == 
nullptr)
 
  761         return status::NOT_FOUND;
 
  763     return static_cast<status>(
 
  764         pmemkv_config_get_uint64(this->_config, key.data(), &value));
 
  778     if (this->_config == 
nullptr)
 
  779         return status::NOT_FOUND;
 
  781     return static_cast<status>(
 
  782         pmemkv_config_get_int64(this->_config, key.data(), &value));
 
  796     if (this->_config == 
nullptr)
 
  797         return status::NOT_FOUND;
 
  801     auto s = 
static_cast<status>(
 
  802         pmemkv_config_get_string(this->_config, key.data(), &data));
 
  821     this->_config = 
nullptr;
 
  831 static inline int call_get_kv_function(
const char *key, 
size_t keybytes,
 
  832                        const char *value, 
size_t valuebytes, 
void *arg)
 
  834     return (*
reinterpret_cast<std::function<get_kv_function> *
>(arg))(
 
  838 static inline void call_get_v_function(
const char *value, 
size_t valuebytes, 
void *arg)
 
  840     (*
reinterpret_cast<std::function<get_v_function> *
>(arg))(
 
  844 static inline void call_get_copy(
const char *v, 
size_t vb, 
void *arg)
 
  846     auto c = 
reinterpret_cast<std::string *
>(arg);
 
  867     this->_db = other._db;
 
  885     std::swap(this->_db, other._db);
 
  899     return static_cast<status>(
 
  900         pmemkv_open(engine_name.c_str(), 
nullptr, &(this->_db)));
 
  913     return static_cast<status>(
 
  914         pmemkv_open(engine_name.c_str(), cfg.release(), &(this->_db)));
 
  922     if (this->_db != 
nullptr)
 
  923         pmemkv_close(this->_db);
 
  945     return static_cast<status>(pmemkv_count_all(this->_db, &cnt));
 
  960     return static_cast<status>(
 
  961         pmemkv_count_above(this->_db, key.data(), key.size(), &cnt));
 
  976     return static_cast<status>(
 
  977         pmemkv_count_equal_above(this->_db, key.data(), key.size(), &cnt));
 
  992     return static_cast<status>(
 
  993         pmemkv_count_equal_below(this->_db, key.data(), key.size(), &cnt));
 
 1008     return static_cast<status>(
 
 1009         pmemkv_count_below(this->_db, key.data(), key.size(), &cnt));
 
 1024                 std::size_t &cnt) noexcept
 
 1026     return static_cast<status>(pmemkv_count_between(
 
 1027         this->_db, key1.data(), key1.size(), key2.data(), key2.size(), &cnt));
 
 1044     return static_cast<status>(pmemkv_get_all(this->_db, callback, arg));
 
 1059     return static_cast<status>(pmemkv_get_all(this->_db, call_get_kv_function, &f));
 
 1081     return static_cast<status>(
 
 1082         pmemkv_get_above(this->_db, key.data(), key.size(), callback, arg));
 
 1101     return static_cast<status>(pmemkv_get_above(this->_db, key.data(), key.size(),
 
 1102                             call_get_kv_function, &f));
 
 1125     return static_cast<status>(
 
 1126         pmemkv_get_equal_above(this->_db, key.data(), key.size(), callback, arg));
 
 1145                   std::function<get_kv_function> f) noexcept
 
 1147     return static_cast<status>(pmemkv_get_equal_above(
 
 1148         this->_db, key.data(), key.size(), call_get_kv_function, &f));
 
 1171     return static_cast<status>(
 
 1172         pmemkv_get_equal_below(this->_db, key.data(), key.size(), callback, arg));
 
 1191                   std::function<get_kv_function> f) noexcept
 
 1193     return static_cast<status>(pmemkv_get_equal_below(
 
 1194         this->_db, key.data(), key.size(), call_get_kv_function, &f));
 
 1216     return static_cast<status>(
 
 1217         pmemkv_get_below(this->_db, key.data(), key.size(), callback, arg));
 
 1236     return static_cast<status>(pmemkv_get_below(this->_db, key.data(), key.size(),
 
 1237                             call_get_kv_function, &f));
 
 1260     return static_cast<status>(pmemkv_get_between(this->_db, key1.data(), key1.size(),
 
 1261                               key2.data(), key2.size(), callback,
 
 1280                   std::function<get_kv_function> f) noexcept
 
 1282     return static_cast<status>(pmemkv_get_between(this->_db, key1.data(), key1.size(),
 
 1283                               key2.data(), key2.size(),
 
 1284                               call_get_kv_function, &f));
 
 1298     return static_cast<status>(pmemkv_exists(this->_db, key.data(), key.size()));
 
 1318     return static_cast<status>(
 
 1319         pmemkv_get(this->_db, key.data(), key.size(), callback, arg));
 
 1335     return static_cast<status>(
 
 1336         pmemkv_get(this->_db, key.data(), key.size(), call_get_v_function, &f));
 
 1351     return static_cast<status>(
 
 1352         pmemkv_get(this->_db, key.data(), key.size(), call_get_copy, value));
 
 1366     return static_cast<status>(pmemkv_put(this->_db, key.data(), key.size(),
 
 1367                           value.data(), value.size()));
 
 1380     return static_cast<status>(pmemkv_remove(this->_db, key.data(), key.size()));
 
 1395     return static_cast<status>(
 
 1396         pmemkv_defrag(this->_db, start_percent, amount_percent));
 
 1408     return std::string(pmemkv_errormsg());
 
 1416 static inline std::string errormsg()
 
 1418     return std::string(pmemkv_errormsg());