sdskv-client.hpp 51.3 KB
Newer Older
1 2 3
#ifndef __SDSKV_CLIENT_HPP
#define __SDSKV_CLIENT_HPP

Matthieu Dorier's avatar
Matthieu Dorier committed
4
#include <type_traits>
5 6 7 8
#include <stdexcept>
#include <vector>
#include <string>
#include <sdskv-client.h>
Matthieu Dorier's avatar
Matthieu Dorier committed
9
#include <sdskv-common.hpp>
10 11 12 13 14 15

#define _CHECK_RET(__ret) \
        if(__ret != SDSKV_SUCCESS) throw exception(__ret)

namespace sdskv {

Matthieu Dorier's avatar
Matthieu Dorier committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57

// The functions bellow (object_size, object_data, object_resize) are defined
// for std::string and std::vector<X> when X is a standard layout type. They
// are used in place of x.size(), x.data(), and x.resize() to allow better
// genericity. Also if a user wants to add support for another type, overloading
// these functions is the way to go: the object_data() function must return a
// void* pointer to where data from an object can be accessed directory.
// object_size() functions must return the size (in bytes) of the underlying
// buffer. object_resize must be able to resize the object.

template<typename T, std::enable_if_t<std::is_standard_layout<T>::value, int> = 0>
inline size_t object_size(const std::vector<T>& v) {
    return sizeof(v[0])*v.size();
}

inline size_t object_size(const std::string& s) {
    return s.size();
}

template<typename T, std::enable_if_t<std::is_standard_layout<T>::value, int> = 0>
inline void* object_data(std::vector<T>& v) {
    return (void*)v.data();
}

inline void* object_data(std::string& s) {
    return (void*)s.data();
}

template<typename T, std::enable_if_t<std::is_standard_layout<T>::value, int> = 0>
inline const void* object_data(const std::vector<T>& v) {
    return (const void*)v.data();
}

inline const void* object_data(const std::string& s) {
    return (const void*)s.data();
}

template<typename T, std::enable_if_t<std::is_standard_layout<T>::value, int> = 0>
inline void object_resize(std::vector<T>& v, size_t new_size) {
    v.resize(new_size);
}

Matthieu Dorier's avatar
Matthieu Dorier committed
58
inline void object_resize(std::string& s, size_t new_size) {
Matthieu Dorier's avatar
Matthieu Dorier committed
59 60 61
    s.resize(new_size);
}

62 63 64
class provider_handle;
class database;

Matthieu Dorier's avatar
Matthieu Dorier committed
65 66 67
/**
 * @brief The sdskv::client class is the C++ equivalent of a C sdskv_client_t.
 */
68 69 70 71 72 73 74 75
class client {

    friend class provider_handle;

    margo_instance_id m_mid = MARGO_INSTANCE_NULL;
    sdskv_client_t m_client = SDSKV_CLIENT_NULL;
    bool           m_owns_client = true;

Matthieu Dorier's avatar
Matthieu Dorier committed
76

77 78
    public:

Matthieu Dorier's avatar
Matthieu Dorier committed
79 80 81
    /**
     * @brief Default constructor. Will create an invalid client.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
82 83
    client() = default;

Matthieu Dorier's avatar
Matthieu Dorier committed
84 85 86 87 88
    /**
     * @brief Main constructor. Creates a valid client from a Margo instance.
     *
     * @param mid Margo instance.
     */
89 90
    client(margo_instance_id mid)
    : m_mid(mid) {
Matthieu Dorier's avatar
Matthieu Dorier committed
91
        sdskv_client_init(mid, &m_client);
92 93
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
94 95 96 97 98 99 100 101
    /**
     * @brief Creates a valid client from an existing sdskv_client_t.
     *
     * @param mid Margo instance.
     * @param c Existing C client.
     * @param transfer_ownership Whether this client instance should take ownership
     * and free the underlying handle in its destructor.
     */
102 103 104 105 106
    client(margo_instance_id mid, sdskv_client_t c, bool transfer_ownership=false)
    : m_mid(mid)
    , m_client(c)
    , m_owns_client(transfer_ownership) {}

Matthieu Dorier's avatar
Matthieu Dorier committed
107 108 109
    /**
     * @brief Deleted copy constructor.
     */
110 111
    client(const client& c) = delete;

Matthieu Dorier's avatar
Matthieu Dorier committed
112 113 114
    /**
     * @brief Move constructor, will invalidate the client that is moved from.
     */
115 116 117
    client(client&& c)
    : m_mid(c.m_mid)
    , m_client(c.m_client)
Matthieu Dorier's avatar
Matthieu Dorier committed
118
    , m_owns_client(c.m_owns_client) {
119 120 121
        c.m_client = SDSKV_CLIENT_NULL;
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
122 123 124
    /**
     * @brief Deleted copy-assignment operator.
     */
125 126
    client& operator=(const client& c) = delete;

Matthieu Dorier's avatar
Matthieu Dorier committed
127 128 129
    /**
     * @brief Move assignment operator, will invalidate the client that is moved from.
     */
130 131 132 133 134 135 136 137 138 139 140 141 142
    client& operator=(client&& c) {
        if(this == &c) return *this;
        if(m_client && m_owns_client) {
            sdskv_client_finalize(m_client);
        }
        m_mid           = c.m_mid;
        m_client        = c.m_client;
        m_owns_client   = c.m_owns_client;
        c.m_client      = SDSKV_CLIENT_NULL;
        c.m_owns_client = true;
        return *this;
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
143 144 145 146
    /**
     * @brief Destructor. If this instance owns the underlying C handle, this handle
     * will be destroyed.
     */
147
    ~client() {
Matthieu Dorier's avatar
Matthieu Dorier committed
148
        if(m_owns_client && m_client)
149 150 151
            sdskv_client_finalize(m_client);
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
152 153 154
    /**
     * @brief Cast operator to sdskv_client_t.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
155 156 157 158
    operator sdskv_client_t() const {
        return m_client;
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
159 160 161 162 163
    /**
     * @brief Cast to bool.
     *
     * @return true if the client is valid, false otherwise.
     */
164 165 166 167
    operator bool() const {
        return m_client != SDSKV_CLIENT_NULL;
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
168 169 170 171 172 173 174 175
    /**
     * @brief Open a database held by a given provider.
     *
     * @param ph Provider handle.
     * @param db_name Database name.
     *
     * @return database instance.
     */
176 177
    database open(const provider_handle& ph, const std::string& db_name) const;

Matthieu Dorier's avatar
Matthieu Dorier committed
178 179 180 181 182 183 184
    /**
     * @brief Open all the databases held by a given provider.
     *
     * @param ph Provider handle.
     *
     * @return Vector of database instances.
     */
185 186 187 188 189 190
    std::vector<database> open(const provider_handle& ph) const;

    //////////////////////////
    // PUT methods
    //////////////////////////

Matthieu Dorier's avatar
Matthieu Dorier committed
191 192 193 194 195 196 197 198 199
    /**
     * @brief Equivalent of sdskv_put.
     *
     * @param db Database instance.
     * @param key Key.
     * @param ksize Size of the key in bytes.
     * @param value Value.
     * @param vsize Size of the value in bytes.
     */
200
    void put(const database& db,
Matthieu Dorier's avatar
Matthieu Dorier committed
201 202
             const void *key, hg_size_t ksize,
             const void *value, hg_size_t vsize) const;
203

Matthieu Dorier's avatar
Matthieu Dorier committed
204 205 206 207 208 209 210 211 212 213 214
    /**
     * @brief Put method taking templated keys and values. This method
     * is meant to work with std::vector<X> and std::string. X must be
     * a standard layout type.
     *
     * @tparam K std::vector<char> or std::string.
     * @tparam V std::vector<char> or std::string.
     * @param db Database instance.
     * @param key Key.
     * @param value Value.
     */
215
    template<typename K, typename V>
Matthieu Dorier's avatar
Matthieu Dorier committed
216
    inline void put(const database& db,
217
             const K& key, const V& value) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
218
        put(db, object_data(key), object_size(key), object_data(value), object_size(value));
219 220
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
221 222 223 224 225 226 227 228 229 230
    /**
     * @brief Equivalent to sdskv_put_multi.
     *
     * @param db Database instance.
     * @param count Number of key/val pairs.
     * @param keys Array of keys.
     * @param ksizes Array of key sizes.
     * @param values Array of values.
     * @param vsizes Array of value sizes.
     */
231
    void put(const database& db,
Matthieu Dorier's avatar
Matthieu Dorier committed
232 233
             hg_size_t count, const void* const* keys, const hg_size_t* ksizes,
             const void* const* values, const hg_size_t *vsizes) const;
234 235 236 237 238

    //////////////////////////
    // PUT_MULTI methods
    //////////////////////////

Matthieu Dorier's avatar
Matthieu Dorier committed
239 240 241 242 243 244 245 246 247
    /**
     * @brief Version of put taking std::vectors instead of arrays of pointers.
     *
     * @param db Database instance.
     * @param keys Vector of pointers to keys.
     * @param ksizes Vector of key sizes.
     * @param values Vector of pointers to values.
     * @param vsizes Vector of value sizes.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
248 249 250
    inline void put(const database& db,
             const std::vector<const void*>& keys, const std::vector<hg_size_t>& ksizes,
             const std::vector<const void*>& values, const  std::vector<hg_size_t>& vsizes) const {
251 252 253 254 255 256 257 258
        if(keys.size() != ksizes.size()
        || keys.size() != values.size()
        || keys.size() != vsizes.size()) {
            throw std::length_error("Provided vectors should have the same size");
        }
        put(db, keys.size(), keys.data(),  ksizes.data(), values.data(), vsizes.data());
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
259 260 261 262 263 264 265 266 267 268
    /**
     * @brief Templated put method. Meant to work with std::vector<X> and std::string types.
     * X must be a standard layout  type.
     *
     * @tparam K std::vector<char> or std::string.
     * @tparam V std::vector<char> or std::string.
     * @param db Database instance.
     * @param keys Vector of keys.
     * @param values Vector of values.
     */
269
    template<typename K, typename V>
Matthieu Dorier's avatar
Matthieu Dorier committed
270
    inline void put(const database& db,
271 272 273 274 275
             const std::vector<K>& keys, const std::vector<V>& values) {
        if(keys.size() != values.size()) {
            throw std::length_error("Provided vectors should have the same size");
        }
        std::vector<const void*> kdata; kdata.reserve(keys.size());
Matthieu Dorier's avatar
Matthieu Dorier committed
276 277 278
        std::vector<const void*> vdata; vdata.reserve(values.size());
        std::vector<hg_size_t> ksizes; ksizes.reserve(keys.size());
        std::vector<hg_size_t> vsizes; vsizes.reserve(values.size());
279
        for(const auto& k : keys) {
Matthieu Dorier's avatar
Matthieu Dorier committed
280 281
            ksizes.push_back(object_size(k));
            kdata.push_back(object_data(k));
282 283
        }
        for(const auto& v : values) {
Matthieu Dorier's avatar
Matthieu Dorier committed
284 285
            vsizes.push_back(object_size(v));
            vdata.push_back(object_data(v));
286 287 288 289
        }
        put(db, kdata, ksizes, vdata, vsizes);
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
290 291 292 293 294 295 296 297 298 299 300 301 302
    /**
     * @brief Put method taking iterators to templated key and value types,
     * meant to work with keys and values of type std::vector<X> and std::string.
     * X must be a standard layout type.
     *
     * @tparam IK Type of iterator to keys.
     * @tparam IV Type of iterator to values.
     * @param db Database instance.
     * @param kbegin beginning of the iterator to keys.
     * @param kend end of the iterator to keys.
     * @param vbegin beginning of the iterator to values.
     * @param vend end of the iterator to values.
     */
303
    template<typename IK, typename IV>
Matthieu Dorier's avatar
Matthieu Dorier committed
304
    inline void put(const database& db,
305 306
             const IK& kbegin, const IK& kend,
             const IV& vbegin, const IV& vend) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
307
        hg_size_t count = std::distance(kbegin, kend);
308 309 310 311 312
        if(count != std::distance(vbegin, vend)) {
            throw std::length_error("Provided iterators should point to the same number of objects");
        }
        std::vector<const void*> kdata; kdata.reserve(count);
        std::vector<const void*> vdata; vdata.reserve(count);
Matthieu Dorier's avatar
Matthieu Dorier committed
313 314
        std::vector<hg_size_t> ksizes; ksizes.reserve(count);
        std::vector<hg_size_t> vsizes; vsizes.reserve(count);
315
        for(auto it = kbegin; it != kend; it++) {
Matthieu Dorier's avatar
Matthieu Dorier committed
316
            ksizes.push_back(object_size(*it));
Matthieu Dorier's avatar
Matthieu Dorier committed
317
            kdata.push_back((const void*)(it->data()));
318 319
        }
        for(auto it = vbegin; it != vend; it++) {
Matthieu Dorier's avatar
Matthieu Dorier committed
320
            vsizes.push_back(object_size(*it));
Matthieu Dorier's avatar
Matthieu Dorier committed
321
            vdata.push_back((const void*)(it->data()));
322 323 324 325 326 327 328 329
        }
        put(db, kdata, ksizes, vdata, vsizes);
    }

    //////////////////////////
    // EXISTS methods
    //////////////////////////

Matthieu Dorier's avatar
Matthieu Dorier committed
330 331 332 333 334 335 336 337 338
    /**
     * @brief Equivalent of sdskv_exists.
     *
     * @param db Database instance.
     * @param key Key.
     * @param ksize Size of the key.
     *
     * @return true if key exists, false otherwise.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
339
    bool exists(const database& db, const void* key, hg_size_t ksize) const;
340

Matthieu Dorier's avatar
Matthieu Dorier committed
341 342 343 344 345 346 347 348 349 350
    /**
     * @brief Templated version of exists method, meant to work with
     * std::string and std::vector<X>. X must be a standard layout type.
     *
     * @tparam K Key type.
     * @param db Database instance.
     * @param key Key.
     *
     * @return true if key exists, false otherwise.
     */
351
    template<typename K>
Matthieu Dorier's avatar
Matthieu Dorier committed
352
    inline bool exists(const database& db, const K& key) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
353
        return exists(db, object_data(key), object_size(key));
354 355 356 357 358 359
    }

    //////////////////////////
    // LENGTH methods
    //////////////////////////

Matthieu Dorier's avatar
Matthieu Dorier committed
360 361 362 363 364 365 366 367 368
    /**
     * @brief Length of the value associated with the provided key.
     *
     * @param db Database instance.
     * @param key Key.
     * @param ksize Size of the key.
     *
     * @return size of the corresponding value.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
369 370
    hg_size_t length(const database& db,
            const void* key, hg_size_t ksize) const;
371

Matthieu Dorier's avatar
Matthieu Dorier committed
372 373 374 375 376 377 378 379 380 381 382
    /**
     * @brief Templated version of the length method, meant to
     * work with std::vector<X> and std::string. X must be a standard
     * layout type.
     *
     * @tparam K Key type.
     * @param db Database instance.
     * @param key Key.
     *
     * @return size of the corresponding value.
     */
383
    template<typename K>
Matthieu Dorier's avatar
Matthieu Dorier committed
384
    inline hg_size_t length(const database& db,
385
            const K& key) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
386
        return length(db, object_data(key), object_size(key));
387 388 389 390 391 392
    }

    //////////////////////////
    // LENGTH_MULTI methods
    //////////////////////////

Matthieu Dorier's avatar
Matthieu Dorier committed
393 394 395 396 397 398 399 400 401
    /**
     * @brief Equivalent to sdskv_length_multi.
     *
     * @param db Database instance.
     * @param num Number of keys.
     * @param keys Array of keys.
     * @param ksizes Array of key sizes.
     * @param vsizes Resulting value sizes.
     */
402
    bool length(const database& db,
Matthieu Dorier's avatar
Matthieu Dorier committed
403 404
            hg_size_t num, const void* const* keys,
            const hg_size_t* ksizes, hg_size_t* vsizes) const;
405

Matthieu Dorier's avatar
Matthieu Dorier committed
406 407 408 409 410 411 412 413 414
    /**
     * @brief Templated version of length, meant to work with
     * std::vector<X> and std::string. X must be a standard layout type.
     *
     * @tparam K Type of keys.
     * @param db Database instance.
     * @param keys Vector of keys.
     * @param vsizes Resulting vector of value sizes.
     */
415
    template<typename K>
Matthieu Dorier's avatar
Matthieu Dorier committed
416
    inline bool length(const database& db,
417
            const std::vector<K>& keys,
Matthieu Dorier's avatar
Matthieu Dorier committed
418
            std::vector<hg_size_t>& vsizes) const {
419 420
        vsizes.resize(keys.size());
        std::vector<const void*> kdata; kdata.reserve(keys.size());
Matthieu Dorier's avatar
Matthieu Dorier committed
421
        std::vector<hg_size_t> ksizes; ksizes.reserve(keys.size());
422
        for(const auto& k : keys) {
Matthieu Dorier's avatar
Matthieu Dorier committed
423 424
            kdata.push_back(object_data(k));
            ksizes.push_back(object_size(k));
425 426 427 428
        }
        return length(db, keys.size(), kdata.data(), ksizes.data(), vsizes.data());
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
429 430 431 432 433 434 435 436 437 438 439
    /**
     * @brief Templated version of length returning a vector of sizes.
     * Meant to work with std::vector<X> and std::string.
     * X must be a standard layout type.
     *
     * @tparam K Key type.
     * @param db Database instance.
     * @param keys Vector of keys.
     *
     * @return Vector of corresponding value sizes.
     */
440
    template<typename K>
Matthieu Dorier's avatar
Matthieu Dorier committed
441 442 443
    inline std::vector<hg_size_t> length(const database& db, const std::vector<K>& keys) const {
        std::vector<hg_size_t> vsizes(keys.size());
        length(db, keys, vsizes);
444 445 446 447 448 449 450
        return vsizes;
    }

    //////////////////////////
    // GET methods
    //////////////////////////

Matthieu Dorier's avatar
Matthieu Dorier committed
451 452 453 454 455 456 457 458 459 460
    /**
     * @brief Equivalent of sdskv_get. Will throw an exception if the key doesn't exist,
     * or if the buffer allocated for the value is too small.
     *
     * @param db Database instance.
     * @param key Key.
     * @param ksize Size of the key.
     * @param value Pointer to a buffer allocated for the value.
     * @param vsize Size of the value buffer.
     */
461
    bool get(const database& db,
Matthieu Dorier's avatar
Matthieu Dorier committed
462 463
             const void* key, hg_size_t ksize,
             void* value, hg_size_t* vsize) const;
464

Matthieu Dorier's avatar
Matthieu Dorier committed
465 466 467 468 469 470 471 472 473 474
    /**
     * @brief Templated version of get, meant to be used with std::vector<X> and std::string.
     * X must be a standard layout type.
     *
     * @tparam K Key type.
     * @tparam V Value type.
     * @param db Database instance.
     * @param key Key.
     * @param value Value.
     */
475
    template<typename K, typename V>
Matthieu Dorier's avatar
Matthieu Dorier committed
476
    inline bool get(const database& db,
477
             const K& key, V& value) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
478 479 480
        hg_size_t s = value.size();
        if(s == 0) {
            s = length(db, key);
Matthieu Dorier's avatar
Matthieu Dorier committed
481
            object_resize(value, s);
Matthieu Dorier's avatar
Matthieu Dorier committed
482
        }
Matthieu Dorier's avatar
Matthieu Dorier committed
483 484
        get(db, object_data(key), object_size(key), object_data(value), &s);
        object_resize(value, s);
485 486 487
        return true;
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
488 489 490 491 492 493 494 495 496 497 498 499
    /**
     * @brief Get method returning its value instead of using an argument.
     * Meant to work with K and V being std::string or std::vector<X, with
     * X a standard layout type.
     *
     * @tparam K Key type.
     * @tparam V Value type.
     * @param db Database instance.
     * @param key Key.
     *
     * @return The value associated with the provided key.
     */
500
    template<typename K, typename V>
Matthieu Dorier's avatar
Matthieu Dorier committed
501
    inline V get(const database& db,
502
          const K& key) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
503
        V value;
504 505 506 507 508 509 510 511
        get(db, key, value);
        return value;
    }

    //////////////////////////
    // GET_MULTI methods
    //////////////////////////

Matthieu Dorier's avatar
Matthieu Dorier committed
512 513 514 515 516 517 518 519 520 521
    /**
     * @brief Equivalent to sdskv_get_multi.
     *
     * @param db Database instance.
     * @param count Number of key/val pairs.
     * @param keys Array of keys.
     * @param ksizes Array of key sizes.
     * @param values Array of value buffers.
     * @param vsizes Array of sizes of value buffers.
     */
522
    bool get(const database& db,
Matthieu Dorier's avatar
Matthieu Dorier committed
523 524
             hg_size_t count, const void* const* keys, const hg_size_t* ksizes,
             void** values, hg_size_t *vsizes) const;
525

Matthieu Dorier's avatar
Matthieu Dorier committed
526 527 528 529 530 531 532 533 534
    /**
     * @brief Get multiple key/val pairs using std::vector of addresses.
     *
     * @param db Database instance.
     * @param keys Vector of key addresses.
     * @param ksizes Vector of key sizes.
     * @param values Vector of value addresses.
     * @param vsizes Vector of value sizes.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
535 536 537
    inline bool get(const database& db,
             const std::vector<const void*>& keys, const std::vector<hg_size_t>& ksizes,
             std::vector<void*>& values, std::vector<hg_size_t>& vsizes) const {
538 539 540 541 542 543 544 545
        if(keys.size() != ksizes.size()
        || keys.size() != values.size()
        || keys.size() != vsizes.size()) {
            throw std::length_error("Provided vectors should have the same size");
        }
        return get(db, keys.size(), keys.data(),  ksizes.data(), values.data(), vsizes.data());
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
546 547 548 549 550 551 552 553 554 555 556
    /**
     * @brief Get multiple key/val pairs using templated keys and values.
     * Meant to work with std::string and std::vector<X> where X is a standard
     * layout type.
     *
     * @tparam K Key type.
     * @tparam V Value type.
     * @param db Database instance.
     * @param keys Vector of keys.
     * @param values Vector of values.
     */
557
    template<typename K, typename V>
Matthieu Dorier's avatar
Matthieu Dorier committed
558
    inline bool get(const database& db,
559 560 561 562 563
             const std::vector<K>& keys, std::vector<V>& values) const {
        if(keys.size() != values.size()) {
            throw std::length_error("Provided vectors should have the same size");
        }
        std::vector<const void*> kdata; kdata.reserve(keys.size());
Matthieu Dorier's avatar
Matthieu Dorier committed
564 565 566
        std::vector<void*> vdata; vdata.reserve(values.size());
        std::vector<hg_size_t> ksizes; ksizes.reserve(keys.size());
        std::vector<hg_size_t> vsizes; vsizes.reserve(values.size());
567
        for(const auto& k : keys) {
Matthieu Dorier's avatar
Matthieu Dorier committed
568 569
            ksizes.push_back(object_size(k));
            kdata.push_back(object_data(k));
570 571
        }
        for(auto& v : values) {
Matthieu Dorier's avatar
Matthieu Dorier committed
572 573
            vsizes.push_back(object_size(v));
            vdata.push_back(object_data(v));
574
        }
Matthieu Dorier's avatar
Matthieu Dorier committed
575 576
        get(db, kdata, ksizes, vdata, vsizes);
        for(unsigned i=0; i < values.size(); i++) {
Matthieu Dorier's avatar
Matthieu Dorier committed
577
            object_resize(values[i], vsizes[i]);
Matthieu Dorier's avatar
Matthieu Dorier committed
578 579
        }
        return true;
580 581
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
582 583 584 585 586 587 588 589 590 591 592 593 594
    /**
     * @brief Get method using iterator to templated keys and values.
     * Meant to work with std::string and std::vector<X> with X a standard
     * layout type.
     *
     * @tparam IK Key iterator type.
     * @tparam IV Value iterator type.
     * @param db Database instance.
     * @param kbegin Beginning iterator for keys.
     * @param kend End iterator for keys.
     * @param vbegin Beginning iterator for values.
     * @param vend End iterator for values.
     */
595
    template<typename IK, typename IV>
Matthieu Dorier's avatar
Matthieu Dorier committed
596
    inline bool get(const database& db,
597 598
             const IK& kbegin, const IK& kend,
             const IV& vbegin, const IV& vend) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
599
        hg_size_t count = std::distance(kbegin, kend);
600 601 602 603
        if(count != std::distance(vbegin, vend)) {
            throw std::length_error("Provided iterators should point to the same number of objects");
        }
        std::vector<const void*> kdata; kdata.reserve(count);
Matthieu Dorier's avatar
Matthieu Dorier committed
604
        std::vector<void*> vdata; vdata.reserve(count);
Matthieu Dorier's avatar
Matthieu Dorier committed
605 606
        std::vector<hg_size_t> ksizes; ksizes.reserve(count);
        std::vector<hg_size_t> vsizes; vsizes.reserve(count);
607
        for(auto it = kbegin; it != kend; it++) {
Matthieu Dorier's avatar
Matthieu Dorier committed
608
            ksizes.push_back(object_size(*it));
Matthieu Dorier's avatar
Matthieu Dorier committed
609
            kdata.push_back((const void*)(it->data()));
610 611
        }
        for(auto it = vbegin; it != vend; it++) {
Matthieu Dorier's avatar
Matthieu Dorier committed
612
            vsizes.push_back(object_size(*it));
Matthieu Dorier's avatar
Matthieu Dorier committed
613
            vdata.push_back((void*)(it->data()));
614 615 616 617
        }
        return get(db, kdata, ksizes, vdata, vsizes);
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
618 619 620 621 622 623 624 625 626 627 628 629 630 631
    /**
     * @brief Get method that returns an a vector of values.
     * Meant to work with std::string and std::vector<X> where X
     * is a standard layout type.
     *
     * @tparam K Key type.
     * @tparam V Value type.
     * @param db Database instance.
     * @param keys Keys.
     *
     * @return the resulting std::vector of values.
     */
    template<typename K, typename V>
    inline std::vector<V> get(
632 633
            const database& db,
            const std::vector<K>& keys) {
Matthieu Dorier's avatar
Matthieu Dorier committed
634 635
        hg_size_t num = keys.size();
        std::vector<hg_size_t> vsizes(num);
636
        length(db, keys, vsizes);
Matthieu Dorier's avatar
Matthieu Dorier committed
637
        std::vector<V> values(num);
638
        for(unsigned i=0 ; i < num; i++) {
Matthieu Dorier's avatar
Matthieu Dorier committed
639
            object_resize(values[i], vsizes[i]);
640
        }
Matthieu Dorier's avatar
Matthieu Dorier committed
641
        get(db, keys, values);
642 643 644 645 646 647 648
        return values;
    }

    //////////////////////////
    // ERASE methods
    //////////////////////////
    
Matthieu Dorier's avatar
Matthieu Dorier committed
649 650 651 652 653 654 655
    /**
     * @brief Equivalent to sdskv_erase.
     *
     * @param db Database instance.
     * @param key Key.
     * @param ksize Size of the key.
     */
656 657
    void erase(const database& db,
               const void* key,
Matthieu Dorier's avatar
Matthieu Dorier committed
658
               hg_size_t ksize) const;
659

Matthieu Dorier's avatar
Matthieu Dorier committed
660 661 662 663 664 665 666 667 668
    /**
     * @brief Templated erase method, meant to be used
     * with keys of type std::string or std::vector<X> where X is a
     * standard layout type.
     *
     * @tparam K Key type.
     * @param db Database instance.
     * @param key Key.
     */
669
    template<typename K>
Matthieu Dorier's avatar
Matthieu Dorier committed
670
    inline void erase( const database& db,
671
               const K& key) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
672
        erase(db, object_data(key), object_size(key));
673 674 675 676 677 678
    }

    //////////////////////////
    // ERASE_MULTI methods
    //////////////////////////

Matthieu Dorier's avatar
Matthieu Dorier committed
679 680 681 682 683 684 685 686
    /**
     * @brief Equivalent to sdskv_erase_multi.
     *
     * @param db Database instance.
     * @param num Number of key/value pairs to erase.
     * @param keys Array of keys.
     * @param ksizes Array of key sizes.
     */
687
    void erase(const database& db,
Matthieu Dorier's avatar
Matthieu Dorier committed
688 689
            hg_size_t num, const void* const* keys,
            const hg_size_t* ksizes) const;
690

Matthieu Dorier's avatar
Matthieu Dorier committed
691 692 693 694 695 696 697 698 699
    /**
     * @brief Erase a vector of keys. The key type K should be
     * std::string or std::vector<X> with X being a standard layout
     * type.
     *
     * @tparam K Type of 
     * @param db Database instance.
     * @param keys Vector of keys to erase.
     */
700
    template<typename K>
Matthieu Dorier's avatar
Matthieu Dorier committed
701
    inline void erase(const database& db,
702 703
            const std::vector<K>& keys) const {
        std::vector<const void*> kdata; kdata.reserve(keys.size());
Matthieu Dorier's avatar
Matthieu Dorier committed
704
        std::vector<hg_size_t> ksizes; ksizes.reserve(keys.size());
705
        for(const auto& k : keys) {
Matthieu Dorier's avatar
Matthieu Dorier committed
706 707
            kdata.push_back(object_data(k));
            ksizes.push_back(object_size(k));
708 709 710 711 712 713 714 715
        }
        return erase(db, keys.size(), kdata.data(), ksizes.data());
    }

    //////////////////////////
    // LIST_KEYS methods
    //////////////////////////
    
Matthieu Dorier's avatar
Matthieu Dorier committed
716 717 718 719 720 721 722 723 724 725 726 727
    /**
     * @brief Equivalent to sdskv_list_keys.
     *
     * @param db Database instance.
     * @param start_key Starting key (excluded from results).
     * @param start_ksize Starting key size.
     * @param prefix Prefix.
     * @param prefix_size Prefix size.
     * @param keys Resulting key buffers.
     * @param ksizes Resulting key buffer sizes.
     * @param max_keys Max number of keys.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
728
    void list_keys(const database& db,
Matthieu Dorier's avatar
Matthieu Dorier committed
729 730 731
            const void *start_key, hg_size_t start_ksize,
            const void *prefix, hg_size_t prefix_size,
            void** keys, hg_size_t* ksizes, hg_size_t* max_keys) const;
732

Matthieu Dorier's avatar
Matthieu Dorier committed
733 734 735
    inline void list_keys(const database& db,
            const void *start_key, hg_size_t start_ksize,
            void** keys, hg_size_t* ksizes, hg_size_t* max_keys) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
736
        list_keys(db, start_key, start_ksize, NULL, 0, keys, ksizes, max_keys);
737 738
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
739 740 741 742 743 744 745 746 747
    /**
     * @brief List keys starting from a given key (excluded).
     * K must be std::string or std::vector<X> with X a standard layout type.
     *
     * @tparam K Key type.
     * @param db Database instance.
     * @param start_key Start key.
     * @param keys Resulting keys.
     */
748
    template<typename K>
Matthieu Dorier's avatar
Matthieu Dorier committed
749
    inline void list_keys(const database& db,
750 751
                const K& start_key,
                std::vector<K>& keys) {
Matthieu Dorier's avatar
Matthieu Dorier committed
752 753
        hg_size_t max_keys = keys.size();
        if(max_keys == 0) return;
754
        std::vector<void*> kdata; kdata.reserve(keys.size());
Matthieu Dorier's avatar
Matthieu Dorier committed
755
        std::vector<hg_size_t> ksizes; ksizes.reserve(keys.size());
756
        for(auto& k : keys) {
Matthieu Dorier's avatar
Matthieu Dorier committed
757 758
            kdata.push_back(object_data(k));
            ksizes.push_back(object_size(k));
759 760
        }
        try {
Matthieu Dorier's avatar
Matthieu Dorier committed
761
            list_keys(db, object_data(start_key), object_size(start_key),
762 763
                kdata.data(), ksizes.data(), &max_keys);
        } catch(exception& e) {
Matthieu Dorier's avatar
Matthieu Dorier committed
764
            if(e.error() == SDSKV_ERR_SIZE && keys[0].size() == 0) {
765
                for(unsigned i=0; i < max_keys; i++) {
Matthieu Dorier's avatar
Matthieu Dorier committed
766 767
                    object_resize(keys[i], ksizes[i]);
                    kdata[i] = object_data(keys[i]);
768
                }
Matthieu Dorier's avatar
Matthieu Dorier committed
769
                list_keys(db, object_data(start_key), object_size(start_key),
770 771 772 773 774 775
                        kdata.data(), ksizes.data(), &max_keys);
            } else {
                throw;
            }
        }
        for(unsigned i=0; i < max_keys; i++) {
Matthieu Dorier's avatar
Matthieu Dorier committed
776
            object_resize(keys[i], ksizes[i]);
777 778 779 780
        }
        keys.resize(max_keys);
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
781 782 783 784 785 786 787 788 789
    /**
     * @brief List keys with a prefix.
     *
     * @tparam K Key type.
     * @param db Database instance.
     * @param start_key Start key (excluded from results).
     * @param prefix Prefix.
     * @param keys Resulting keys.
     */
790
    template<typename K>
Matthieu Dorier's avatar
Matthieu Dorier committed
791
    inline void list_keys(const database& db,
792 793 794
                const K& start_key,
                const K& prefix,
                std::vector<K>& keys) {
Matthieu Dorier's avatar
Matthieu Dorier committed
795
        hg_size_t max_keys = keys.size();
796
        std::vector<void*> kdata; kdata.reserve(keys.size());
Matthieu Dorier's avatar
Matthieu Dorier committed
797
        std::vector<hg_size_t> ksizes; ksizes.reserve(keys.size());
798
        for(auto& k : keys) {
Matthieu Dorier's avatar
Matthieu Dorier committed
799 800
            kdata.push_back(object_data(k));
            ksizes.push_back(object_size(k));
801 802
        }
        try {
Matthieu Dorier's avatar
Matthieu Dorier committed
803 804
            list_keys(db, object_data(start_key), object_size(start_key),
                object_data(prefix), object_size(prefix),
805 806
                kdata.data(), ksizes.data(), &max_keys);
        } catch(exception& e) {
Matthieu Dorier's avatar
Matthieu Dorier committed
807
            if(e.error() == SDSKV_ERR_SIZE && object_size(keys[0]) == 0) {
808
                for(unsigned i=0; i < max_keys; i++) {
Matthieu Dorier's avatar
Matthieu Dorier committed
809 810
                    object_resize(keys[i], ksizes[i]);
                    kdata[i] = object_data(keys[i]);
811
                }
Matthieu Dorier's avatar
Matthieu Dorier committed
812 813
                list_keys(db, object_data(start_key), object_size(start_key),
                        object_data(prefix), object_size(prefix),
814 815 816 817 818 819
                        kdata.data(), ksizes.data(), &max_keys);
            } else {
                throw;
            }
        }
        for(unsigned i=0; i < max_keys; i++) {
Matthieu Dorier's avatar
Matthieu Dorier committed
820
            object_resize(keys[i], ksizes[i]);
821 822 823 824 825 826 827 828
        }
        keys.resize(max_keys);
    }

    //////////////////////////
    // LIST_KEYVALS methods
    //////////////////////////

Matthieu Dorier's avatar
Matthieu Dorier committed
829 830 831
    /**
     * @brief Same as list_keys but also returns the values.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
832
    void list_keyvals(const database& db,
Matthieu Dorier's avatar
Matthieu Dorier committed
833 834 835 836 837 838
            const void *start_key, hg_size_t start_ksize,
            const void *prefix, hg_size_t prefix_size,
            void** keys, hg_size_t* ksizes, 
            void** values, hg_size_t* vsizes,
            hg_size_t* max_items) const;

Matthieu Dorier's avatar
Matthieu Dorier committed
839 840 841
    /**
     * @brief Same as list_keys but also returns the values.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
842 843 844 845 846
    inline void list_keyvals(const database& db,
            const void *start_key, hg_size_t start_ksize,
            void** keys, hg_size_t* ksizes,
            void** values, hg_size_t* vsizes,
            hg_size_t* max_items) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
847
        list_keyvals(db, start_key, start_ksize,
848 849 850
                NULL, 0, keys, ksizes, values, vsizes, max_items);
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
851 852 853
    /**
     * @brief Same as list_keys but also returns the values.
     */
854
    template<typename K, typename V>
Matthieu Dorier's avatar
Matthieu Dorier committed
855
    inline void list_keyvals(const database& db,
856 857 858 859
                const K& start_key,
                std::vector<K>& keys,
                std::vector<V>& values) const {

Matthieu Dorier's avatar
Matthieu Dorier committed
860
        hg_size_t max_keys = std::min(keys.size(), values.size());
861
        std::vector<void*> kdata; kdata.reserve(keys.size());
Matthieu Dorier's avatar
Matthieu Dorier committed
862
        std::vector<hg_size_t> ksizes; ksizes.reserve(keys.size());
863
        std::vector<void*> vdata; vdata.reserve(values.size());
Matthieu Dorier's avatar
Matthieu Dorier committed
864
        std::vector<hg_size_t> vsizes; vsizes.reserve(values.size());
865
        for(auto& k : keys) {
Matthieu Dorier's avatar
Matthieu Dorier committed
866 867
            kdata.push_back(object_data(k));
            ksizes.push_back(object_size(k));
868 869
        }
        for(auto& v : values) {
Matthieu Dorier's avatar
Matthieu Dorier committed
870 871
            vdata.push_back(object_data(v));
            vsizes.push_back(object_size(v));
872 873
        }
        try {
Matthieu Dorier's avatar
Matthieu Dorier committed
874
            list_keyvals(db, object_data(start_key), object_size(start_key),
875 876 877 878 879
                kdata.data(), ksizes.data(), 
                vdata.data(), vsizes.data(), &max_keys);
        } catch(exception& e) {
            if(e.error() == SDSKV_ERR_SIZE) {
                for(unsigned i=0; i < max_keys; i++) {
Matthieu Dorier's avatar
Matthieu Dorier committed
880 881 882 883
                    object_resize(keys[i], ksizes[i]);
                    kdata[i] = object_data(keys[i]);
                    object_resize(values[i], vsizes[i]);
                    vdata[i] = object_data(values[i]);
884
                }
Matthieu Dorier's avatar
Matthieu Dorier committed
885
                list_keyvals(db, object_data(start_key), object_size(start_key),
886 887 888 889 890 891 892
                    kdata.data(), ksizes.data(), 
                    vdata.data(), vsizes.data(), &max_keys);
            } else {
                throw;
            }
        }
        for(unsigned i=0; i < max_keys; i++) {
Matthieu Dorier's avatar
Matthieu Dorier committed
893 894
            object_resize(keys[i], ksizes[i]);
            object_resize(values[i], vsizes[i]);
895 896 897 898 899
        }
        keys.resize(max_keys);
        values.resize(max_keys);
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
900 901 902
    /**
     * @brief Same as list_keys but also returns the values.
     */
903
    template<typename K, typename V>
Matthieu Dorier's avatar
Matthieu Dorier committed
904
    inline void list_keyvals(const database& db,
905 906 907 908 909
                const K& start_key,
                const K& prefix,
                std::vector<K>& keys,
                std::vector<V>& values) const {

Matthieu Dorier's avatar
Matthieu Dorier committed
910
        hg_size_t max_keys = std::min(keys.size(), values.size());
911
        std::vector<void*> kdata; kdata.reserve(keys.size());
Matthieu Dorier's avatar
Matthieu Dorier committed
912
        std::vector<hg_size_t> ksizes; ksizes.reserve(keys.size());
913
        std::vector<void*> vdata; vdata.reserve(values.size());
Matthieu Dorier's avatar
Matthieu Dorier committed
914
        std::vector<hg_size_t> vsizes; vsizes.reserve(values.size());
915
        for(auto& k : keys) {
Matthieu Dorier's avatar
Matthieu Dorier committed
916 917
            kdata.push_back(object_data(k));
            ksizes.push_back(object_size(k));
918 919
        }
        for(auto& v : values) {
Matthieu Dorier's avatar
Matthieu Dorier committed
920 921
            vdata.push_back(object_data(v));
            vsizes.push_back(object_size(v));
922 923
        }
        try {
Matthieu Dorier's avatar
Matthieu Dorier committed
924 925
            list_keyvals(db, object_data(start_key), object_size(start_key),
                object_data(prefix), object_size(prefix),
926 927 928 929 930
                kdata.data(), ksizes.data(), 
                vdata.data(), vsizes.data(), &max_keys);
        } catch(exception& e) {
            if(e.error() == SDSKV_ERR_SIZE) {
                for(unsigned i=0; i < max_keys; i++) {
Matthieu Dorier's avatar
Matthieu Dorier committed
931 932 933 934
                    object_resize(keys[i], ksizes[i]);
                    kdata[i] = object_data(keys[i]);
                    object_resize(values[i], vsizes[i]);
                    vdata[i] = object_data(values[i]);
935
                }
Matthieu Dorier's avatar
Matthieu Dorier committed
936 937
                list_keyvals(db, object_data(start_key), object_size(start_key),
                        object_data(prefix), object_size(prefix),
938 939 940 941 942 943 944
                        kdata.data(), ksizes.data(), 
                        vdata.data(), vsizes.data(), &max_keys);
            } else {
                throw;
            }
        }
        for(unsigned i=0; i < max_keys; i++) {
Matthieu Dorier's avatar
Matthieu Dorier committed
945 946
            object_resize(keys[i], ksizes[i]);
            object_resize(values[i], vsizes[i]);
947 948 949 950 951 952 953 954 955
        }
        keys.resize(max_keys);
        values.resize(max_keys);
    }

    //////////////////////////
    // MIGRATE_KEYS methods
    //////////////////////////
    
Matthieu Dorier's avatar
Matthieu Dorier committed
956 957 958 959 960 961 962 963 964 965
    /**
     * @brief Migrates a given set of keys from a source to a destination database.
     *
     * @param source_db Source database.
     * @param dest_db Destination database.
     * @param num_items Number of items
     * @param keys Array of keys.
     * @param key_sizes Array of key sizes.
     * @param flag SDSKV_KEEP_ORIGINAL or SDSKV_REMOVE_ORIGINAL.
     */
966
    void migrate(const database& source_db, const database& dest_db,
Matthieu Dorier's avatar
Matthieu Dorier committed
967 968
            hg_size_t num_items, const void* const* keys, const hg_size_t* key_sizes,
            int flag = SDSKV_KEEP_ORIGINAL) const;
969

Matthieu Dorier's avatar
Matthieu Dorier committed
970 971 972 973 974 975 976 977 978
    /**
     * @brief Migrates a given set of keys from a source to a destination database.
     *
     * @param source_db Source database.
     * @param dest_db Destination database.
     * @param keys Array of keys.
     * @param ksizes Array of key sizes.
     * @param flag SDSKV_KEEP_ORIGINAL or SDSKV_REMOVE_ORIGINAL.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
979
    inline void migrate(const database& source_db, const database& dest_db,
980
            const std::vector<const void*> keys, 
Matthieu Dorier's avatar
Matthieu Dorier committed
981
            const std::vector<hg_size_t> ksizes,
982 983 984 985 986 987 988
            int flag = SDSKV_KEEP_ORIGINAL) const {
        if(keys.size() != ksizes.size()) {
            throw std::length_error("Provided vectors should have the same size");
        }
        migrate(source_db, dest_db, keys.size(), keys.data(), ksizes.data(), flag);
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
989 990 991 992 993 994 995 996 997
    /**
     * @brief Migrate a set of keys from a source to a destination database.
     *
     * @tparam K Key type.
     * @param source_db Source database.
     * @param dest_db Destination database.
     * @param keys Vector of keys.
     * @param flag SDSKV_KEEP_ORIGINAL or SDSKV_REMOVE_ORIGINAL.
     */
998
    template<typename K>
Matthieu Dorier's avatar
Matthieu Dorier committed
999
    inline void migrate(const database& source_db, const database& dest_db,
1000
            const std::vector<K> keys, int flag = SDSKV_KEEP_ORIGINAL) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
1001
        std::vector<hg_size_t> ksizes; ksizes.reserve(keys.size());
1002 1003
        std::vector<const void*> kdata; kdata.reserve(keys.size());
        for(const auto& k : keys) {
Matthieu Dorier's avatar
Matthieu Dorier committed
1004 1005
            ksizes.push_back(object_size(k));
            kdata.push_back(object_data(k));
1006 1007 1008 1009 1010
        }
        migrate(source_db, dest_db,
                kdata, ksizes, flag);
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
1011 1012 1013 1014 1015 1016 1017 1018 1019
    /**
     * @brief Migrate a range of keys.
     *
     * @param source_db Source database.
     * @param dest_db Destination database.
     * @param key_range[2] Key range ] lb; ub [
     * @param key_sizes[2] Key sizes
     * @param flag SDSKV_KEEP_ORIGINAL or SDSKV_REMOVE_ORIGINAL.
     */
1020
    void migrate(const database& source_db, const database& dest_db,
Matthieu Dorier's avatar
Matthieu Dorier committed
1021 1022
            const void* key_range[2], const hg_size_t key_sizes[2],
            int flag = SDSKV_KEEP_ORIGINAL) const;
1023

Matthieu Dorier's avatar
Matthieu Dorier committed
1024 1025 1026 1027 1028 1029 1030 1031 1032
    /**
     * @brief Migrate a range of keys.
     *
     * @tparam K Key type.
     * @param source_db Source database.
     * @param dest_db Destination database.
     * @param key_range Key range ] lb; ub [.
     * @param flag SDSKV_KEEP_ORIGINAL or SDSKV_REMOVE_ORIGINAL.
     */
1033
    template<typename K>
Matthieu Dorier's avatar
Matthieu Dorier committed
1034
    inline void migrate(const database& source_db, const database& dest_db,
1035 1036
                 const std::pair<K,K>& key_range,
                 int flag = SDSKV_KEEP_ORIGINAL) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
1037 1038
        const void* key_range_arr[2] = { object_data(key_range.first), object_data(key_range.second) };
        const hg_size_t key_sizes_arr[2] = { object_size(key_range.first), object_size(key_range.second) };
1039 1040 1041
        migrate(source_db, dest_db, key_range_arr, key_sizes_arr, flag);
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
1042 1043 1044 1045 1046 1047 1048 1049 1050
    /**
     * @brief Migrate keys with a prefix.
     *
     * @param source_db Source database.
     * @param dest_db Destination database.
     * @param prefix Prefix.
     * @param prefix_size Prefix size.
     * @param flag SDSKV_KEEP_ORIGINAL or SDSKV_REMOVE_ORIGINAL.
     */
1051
    void migrate(const database& source_db, const database& dest_db,
Matthieu Dorier's avatar
Matthieu Dorier committed
1052 1053
            const void* prefix, hg_size_t prefix_size,
            int flag = SDSKV_KEEP_ORIGINAL) const;
1054

Matthieu Dorier's avatar
Matthieu Dorier committed
1055 1056 1057 1058 1059 1060 1061 1062 1063
    /**
     * @brief Migrate keys with a prefix.
     *
     * @tparam K Key type.
     * @param source_db Source database.
     * @param dest_db Destination database.
     * @param prefix Prefix.
     * @param flag SDSKV_KEEP_ORIGINAL or SDSKV_REMOVE_ORIGINAL.
     */
1064
    template<typename K>
Matthieu Dorier's avatar
Matthieu Dorier committed
1065
    inline void migrate(const database& source_db, const database& dest_db,
1066
                 const K& prefix, int flag = SDSKV_KEEP_ORIGINAL) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
1067
        migrate(source_db, dest_db, object_data(prefix), object_size(prefix), flag);
1068 1069
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
1070 1071 1072 1073 1074 1075 1076
    /**
     * @brief Migrate all keys from a database to another.
     *
     * @param source_db Source database.
     * @param dest_db Destination database.
     * @param flag SDSKV_KEEP_ORIGINAL or SDSKV_REMOVE_ORIGINAL.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
1077
    void migrate(const database& source_db, const database& dest_db, int flag = SDSKV_KEEP_ORIGINAL) const;
1078 1079 1080 1081 1082

    //////////////////////////
    // MIGRATE_DB method
    //////////////////////////

Matthieu Dorier's avatar
Matthieu Dorier committed
1083 1084 1085 1086 1087 1088 1089 1090 1091
    /**
     * @brief Migrates an entire database to another destination provider.
     *
     * @param source_db Source database (will be modified to point to the new provider).
     * @param dest_provider_addr Destination provider address.
     * @param dest_provider_id Destination provider id.
     * @param dest_root Path to the database in the new provider.
     * @param flag SDSKV_KEEP_ORIGINAL or SDSKV_REMOVE_ORIGINAL.
     */
1092 1093 1094 1095
    void migrate(database& source_db,
            const std::string& dest_provider_addr,
            uint16_t dest_provider_id,
            const std::string& dest_root,
Matthieu Dorier's avatar
Matthieu Dorier committed
1096
            int flag = SDSKV_KEEP_ORIGINAL) const;
1097 1098 1099 1100 1101

    //////////////////////////
    // SHUTDOWN method
    //////////////////////////
    
Matthieu Dorier's avatar
Matthieu Dorier committed
1102 1103 1104 1105 1106
    /**
     * @brief Shuts down a Margo instance in a remote node.
     *
     * @param addr Mercury address of the Margo instance to shut down.
     */
1107 1108 1109 1110 1111 1112
    void shutdown(hg_addr_t addr) const {
        int ret = sdskv_shutdown_service(m_client, addr);
        _CHECK_RET(ret);
    }
};

Matthieu Dorier's avatar
Matthieu Dorier committed
1113 1114 1115
/**
 * @brief The provider_handle class wraps and sdskv_provider_handle_t C handle.
 */
1116 1117 1118 1119 1120 1121
class provider_handle {

    friend class client;
    friend class database;

    sdskv_provider_handle_t m_ph = SDSKV_PROVIDER_HANDLE_NULL;
Matthieu Dorier's avatar
Matthieu Dorier committed
1122
    client*                 m_client;
1123 1124 1125

    public:

Matthieu Dorier's avatar
Matthieu Dorier committed
1126 1127 1128
    /**
     * @brief Default constructor produces an invalid provider_handle.
     */
1129 1130
    provider_handle() = default;

Matthieu Dorier's avatar
Matthieu Dorier committed
1131 1132 1133 1134 1135 1136 1137 1138
    /**
     * @brief Creates a provider handle from a client, using an address
     * and a provider id.
     *
     * @param c Client.
     * @param addr Mercury address.
     * @param provider_id Provider id.
     */
1139
    provider_handle(
Matthieu Dorier's avatar
Matthieu Dorier committed
1140
            client& c,
1141 1142
            hg_addr_t addr,
            uint16_t provider_id=0)
Matthieu Dorier's avatar
Matthieu Dorier committed
1143
    : m_client(&c)
1144 1145 1146 1147 1148
    {
        int ret = sdskv_provider_handle_create(c.m_client, addr, provider_id, &m_ph);
        _CHECK_RET(ret);
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
1149 1150 1151
    /**
     * @brief Copy constructor.
     */
1152
    provider_handle(const provider_handle& other)
Matthieu Dorier's avatar
Matthieu Dorier committed
1153 1154
    : m_client(other.m_client)
    , m_ph(other.m_ph) {
1155
        if(m_ph != SDSKV_PROVIDER_HANDLE_NULL) {
Matthieu Dorier's avatar
Matthieu Dorier committed
1156
            int ret = sdskv_provider_handle_ref_incr(m_ph);
1157 1158 1159 1160
            _CHECK_RET(ret);
        }
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
1161 1162 1163
    /**
     * @brief Move constructor.
     */
1164
    provider_handle(provider_handle&& other)
Matthieu Dorier's avatar
Matthieu Dorier committed
1165 1166
    : m_client(other.m_client)
    , m_ph(other.m_ph) {
1167 1168 1169
        other.m_ph = SDSKV_PROVIDER_HANDLE_NULL;
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
1170 1171 1172
    /**
     * @brief Copy assignment operator.
     */
1173
    provider_handle& operator=(const provider_handle& other) {
Matthieu Dorier's avatar
Matthieu Dorier committed
1174
        if(this == &other) return *this;
1175 1176 1177 1178 1179
        if(m_ph != SDSKV_PROVIDER_HANDLE_NULL) {
            int ret = sdskv_provider_handle_release(m_ph);
            _CHECK_RET(ret);
        }
        m_ph = other.m_ph;
Matthieu Dorier's avatar
Matthieu Dorier committed
1180
        m_client = other.m_client;
1181 1182 1183 1184 1185
        int ret = sdskv_provider_handle_ref_incr(m_ph);
        _CHECK_RET(ret);
        return *this;
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
1186 1187 1188
    /**
     * @brief Move assignment operator.
     */
1189
    provider_handle& operator=(provider_handle& other) {
Matthieu Dorier's avatar
Matthieu Dorier committed
1190
        if(this == &other) return *this;
1191 1192 1193 1194 1195
        if(m_ph != SDSKV_PROVIDER_HANDLE_NULL) {
            int ret = sdskv_provider_handle_release(m_ph);
            _CHECK_RET(ret);
        }
        m_ph = other.m_ph;
Matthieu Dorier's avatar
Matthieu Dorier committed
1196
        m_client = other.m_client;
1197
        other.m_ph = SDSKV_PROVIDER_HANDLE_NULL;
Matthieu Dorier's avatar
Matthieu Dorier committed
1198
        other.m_client = nullptr;
1199 1200 1201
        return *this;
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
1202 1203 1204
    /**
     * @brief Destructor.
     */
1205 1206 1207 1208 1209
    ~provider_handle() {
        if(m_ph != SDSKV_PROVIDER_HANDLE_NULL)
            sdskv_provider_handle_release(m_ph);
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
1210 1211 1212 1213 1214
    /**
     * @brief Cast operator to sdskv_provider_handle_t.
     *
     * @return The underlying sdskv_provider_handle_t.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
1215 1216 1217 1218
    operator sdskv_provider_handle_t() const {
        return m_ph;
    }

1219 1220
};

Matthieu Dorier's avatar
Matthieu Dorier committed
1221 1222 1223 1224
/**
 * @brief The database class wraps a sdskv_database_id_t C handle
 * and provides object-oriented access to the underlying provider's database.
 */
1225 1226 1227 1228 1229 1230 1231 1232
class database {
    
    friend class client;
    friend class provider_handle;

    provider_handle     m_ph;
    sdskv_database_id_t m_db_id;

Matthieu Dorier's avatar
Matthieu Dorier committed
1233 1234 1235 1236 1237 1238
    /**
     * @brief Private constructor used by client::open.
     *
     * @param ph Provider handle.
     * @param db_id Database id.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
1239 1240 1241 1242
    database(const provider_handle& ph, sdskv_database_id_t db_id)
    : m_ph(ph)
    , m_db_id(db_id) {}

1243 1244
    public:

Matthieu Dorier's avatar
Matthieu Dorier committed
1245 1246 1247
    /**
     * @brief Default constructor.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
1248
    database() = default;
Matthieu Dorier's avatar
Matthieu Dorier committed
1249 1250 1251 1252

    /**
     * @brief Default copy constructor.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
1253
    database(const database& other) = default;
Matthieu Dorier's avatar
Matthieu Dorier committed
1254 1255 1256 1257

    /**
     * @brief Default move constructor.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
1258
    database(database&& other) = default;
Matthieu Dorier's avatar
Matthieu Dorier committed
1259 1260 1261 1262

    /**
     * @brief Default copy assignment operator.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
1263
    database& operator=(const database& other) = default;
Matthieu Dorier's avatar
Matthieu Dorier committed
1264 1265 1266 1267

    /**
     * @brief Default move assignment operator.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
1268
    database& operator=(database&& other) = default;
Matthieu Dorier's avatar
Matthieu Dorier committed
1269 1270 1271 1272

    /**
     * @brief Default destructor.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
1273 1274
    ~database() = default;

Matthieu Dorier's avatar
Matthieu Dorier committed
1275 1276 1277 1278 1279
    /**
     * @brief Cast operator to underlying sdskv_database_id_t.
     *
     * @return The underlying sdskv_database_id_t.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
1280 1281 1282 1283
    operator sdskv_database_id_t() const {
        return m_db_id;
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
1284 1285 1286
    /**
     * @brief @see client::put.
     */
1287 1288
    template<typename ... T>
    void put(T&& ... args) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
1289
        m_ph.m_client->put(*this, std::forward<T>(args)...);
1290 1291
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
1292 1293 1294
    /**
     * @brief @see client::length.
     */
1295 1296
    template<typename ... T>
    decltype(auto) length(T&& ... args) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
1297
        return m_ph.m_client->length(*this, std::forward<T>(args)...);
1298 1299
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
1300 1301 1302
    /**
     * @brief @see client::get.
     */
1303 1304
    template<typename ... T>
    decltype(auto) get(T&& ... args) const {
Matthieu Dorier's avatar
Matthieu Dorier committed
1305
        return m_ph.m_client->get(*this, std::forward<T>(args)...);
1306 1307
    }