lmdb++
Loading...
Searching...
No Matches
lmdb++.h
Go to the documentation of this file.
1/* This is free and unencumbered software released into the public domain. */
2
3#ifndef LMDBXX_H
4#define LMDBXX_H
5
13
14#ifndef __cplusplus
15#error "<lmdb++.h> requires a C++ compiler"
16#endif
17
18#if __cplusplus < 201703L
19#error "<lmdb++.h> requires a C++17 compiler (CXXFLAGS='-std=c++17')"
20#endif
21
23
24#include <lmdb.h> /* for MDB_*, mdb_*() */
25
26#ifdef LMDBXX_DEBUG
27#include <cassert> /* for assert() */
28#endif
29#include <cstddef> /* for std::size_t */
30#include <cstdio> /* for std::snprintf() */
31#include <cstring> /* for std::memcpy() */
32#include <stdexcept> /* for std::runtime_error */
33#include <string> /* for std::string */
34#include <string_view> /* for std::string_view */
35#include <limits> /* for std::numeric_limits<> */
36#include <memory> /* for std::addressof */
37
38namespace lmdb {
39 using mode = mdb_mode_t;
40}
41
43/* Error Handling */
44
45namespace lmdb {
46 class error;
47 class logic_error;
48 class fatal_error;
49 class runtime_error;
50 class key_exist_error;
51 class not_found_error;
52 class corrupted_error;
53 class panic_error;
54 class version_mismatch_error;
55 class map_full_error;
56 class bad_dbi_error;
57}
58
64class lmdb::error : public std::runtime_error {
65protected:
66 const int _code;
67
68public:
72 [[noreturn]] static inline void raise(const char* origin, int rc);
73
77 error(const char* const origin,
78 const int rc) noexcept
80 _code{rc} {}
81
85 int code() const noexcept {
86 return _code;
87 }
88
92 const char* origin() const noexcept {
93 return runtime_error::what();
94 }
95
99 virtual const char* what() const noexcept {
100 static thread_local char buffer[1024];
101 std::snprintf(buffer, sizeof(buffer),
102 "%s: %s", origin(), ::mdb_strerror(code()));
103 return buffer;
104 }
105};
106
111public:
112 using error::error;
113};
114
119public:
120 using error::error;
121};
122
127public:
128 using error::error;
129};
130
137public:
138 using runtime_error::runtime_error;
139};
140
147public:
148 using runtime_error::runtime_error;
149};
150
157public:
158 using fatal_error::fatal_error;
159};
160
167public:
168 using fatal_error::fatal_error;
169};
170
177public:
178 using fatal_error::fatal_error;
179};
180
187public:
188 using runtime_error::runtime_error;
189};
190
198public:
199 using runtime_error::runtime_error;
200};
201
202inline void
203lmdb::error::raise(const char* const origin,
204 const int rc) {
205 switch (rc) {
206 case MDB_KEYEXIST: throw key_exist_error{origin, rc};
207 case MDB_NOTFOUND: throw not_found_error{origin, rc};
208 case MDB_CORRUPTED: throw corrupted_error{origin, rc};
209 case MDB_PANIC: throw panic_error{origin, rc};
210 case MDB_VERSION_MISMATCH: throw version_mismatch_error{origin, rc};
211 case MDB_MAP_FULL: throw map_full_error{origin, rc};
212#ifdef MDB_BAD_DBI
213 case MDB_BAD_DBI: throw bad_dbi_error{origin, rc};
214#endif
215 default: throw lmdb::runtime_error{origin, rc};
216 }
217}
218
220/* Procedural Interface: Metadata */
221
222namespace lmdb {
223 // TODO: mdb_version()
224 // TODO: mdb_strerror()
225}
226
228/* Procedural Interface: Environment */
229
230namespace lmdb {
231 static inline void env_create(MDB_env** env);
232 static inline void env_open(MDB_env* env,
233 const char* path, unsigned int flags, mode mode);
234#if MDB_VERSION_FULL >= MDB_VERINT(0, 9, 14)
235 static inline void env_copy(MDB_env* env, const char* path, unsigned int flags);
236 static inline void env_copy_fd(MDB_env* env, mdb_filehandle_t fd, unsigned int flags);
237#else
238 static inline void env_copy(MDB_env* env, const char* path);
239 static inline void env_copy_fd(MDB_env* env, mdb_filehandle_t fd);
240#endif
241 static inline void env_stat(MDB_env* env, MDB_stat* stat);
242 static inline void env_info(MDB_env* env, MDB_envinfo* stat);
243 static inline void env_sync(MDB_env* env, bool force);
244 static inline void env_close(MDB_env* env) noexcept;
245 static inline void env_set_flags(MDB_env* env, unsigned int flags, bool onoff);
246 static inline void env_get_flags(MDB_env* env, unsigned int* flags);
247 static inline void env_get_path(MDB_env* env, const char** path);
248 static inline void env_get_fd(MDB_env* env, mdb_filehandle_t* fd);
249 static inline void env_set_mapsize(MDB_env* env, std::size_t size);
250 static inline void env_set_max_readers(MDB_env* env, unsigned int count);
251 static inline void env_get_max_readers(MDB_env* env, unsigned int* count);
252 static inline void env_set_max_dbs(MDB_env* env, MDB_dbi count);
253 static inline unsigned int env_get_max_keysize(MDB_env* env);
254#if MDB_VERSION_FULL >= MDB_VERINT(0, 9, 11)
255 static inline void env_set_userctx(MDB_env* env, void* ctx);
256 static inline void* env_get_userctx(MDB_env* env);
257#endif
258 // TODO: mdb_env_set_assert()
259 // TODO: mdb_reader_list()
260 static inline void reader_check(MDB_env *env, int *dead);
261}
262
267static inline void
269 const int rc = ::mdb_env_create(env);
270 if (rc != MDB_SUCCESS) {
271 error::raise("mdb_env_create", rc);
272 }
273}
274
279static inline void
280lmdb::env_open(MDB_env* const env,
281 const char* const path,
282 const unsigned int flags,
283 const mode mode) {
284 const int rc = ::mdb_env_open(env, path, flags, mode);
285 if (rc != MDB_SUCCESS) {
286 error::raise("mdb_env_open", rc);
287 }
288}
289
295static inline void
296lmdb::env_copy(MDB_env* const env,
297#if MDB_VERSION_FULL >= MDB_VERINT(0, 9, 14)
298 const char* const path,
299 const unsigned int flags = 0) {
300 const int rc = ::mdb_env_copy2(env, path, flags);
301#else
302 const char* const path) {
303 const int rc = ::mdb_env_copy(env, path);
304#endif
305 if (rc != MDB_SUCCESS) {
306 error::raise("mdb_env_copy2", rc);
307 }
308}
309
315static inline void
316lmdb::env_copy_fd(MDB_env* const env,
317#if MDB_VERSION_FULL >= MDB_VERINT(0, 9, 14)
318 const mdb_filehandle_t fd,
319 const unsigned int flags = 0) {
320 const int rc = ::mdb_env_copyfd2(env, fd, flags);
321#else
322 const mdb_filehandle_t fd) {
323 const int rc = ::mdb_env_copyfd(env, fd);
324#endif
325 if (rc != MDB_SUCCESS) {
326 error::raise("mdb_env_copyfd2", rc);
327 }
328}
329
334static inline void
335lmdb::env_stat(MDB_env* const env,
336 MDB_stat* const stat) {
337 const int rc = ::mdb_env_stat(env, stat);
338 if (rc != MDB_SUCCESS) {
339 error::raise("mdb_env_stat", rc);
340 }
341}
342
347static inline void
348lmdb::env_info(MDB_env* const env,
349 MDB_envinfo* const stat) {
350 const int rc = ::mdb_env_info(env, stat);
351 if (rc != MDB_SUCCESS) {
352 error::raise("mdb_env_info", rc);
353 }
354}
355
360static inline void
361lmdb::env_sync(MDB_env* const env,
362 const bool force = true) {
363 const int rc = ::mdb_env_sync(env, force);
364 if (rc != MDB_SUCCESS) {
365 error::raise("mdb_env_sync", rc);
366 }
367}
368
372static inline void
373lmdb::env_close(MDB_env* const env) noexcept {
374 ::mdb_env_close(env);
375}
376
381static inline void
383 const unsigned int flags,
384 const bool onoff = true) {
385 const int rc = ::mdb_env_set_flags(env, flags, onoff ? 1 : 0);
386 if (rc != MDB_SUCCESS) {
387 error::raise("mdb_env_set_flags", rc);
388 }
389}
390
395static inline void
397 unsigned int* const flags) {
398 const int rc = ::mdb_env_get_flags(env, flags);
399 if (rc != MDB_SUCCESS) {
400 error::raise("mdb_env_get_flags", rc);
401 }
402}
403
408static inline void
409lmdb::env_get_path(MDB_env* const env,
410 const char** path) {
411 const int rc = ::mdb_env_get_path(env, path);
412 if (rc != MDB_SUCCESS) {
413 error::raise("mdb_env_get_path", rc);
414 }
415}
416
421static inline void
422lmdb::env_get_fd(MDB_env* const env,
423 mdb_filehandle_t* const fd) {
424 const int rc = ::mdb_env_get_fd(env, fd);
425 if (rc != MDB_SUCCESS) {
426 error::raise("mdb_env_get_fd", rc);
427 }
428}
429
434static inline void
436 const std::size_t size) {
437 const int rc = ::mdb_env_set_mapsize(env, size);
438 if (rc != MDB_SUCCESS) {
439 error::raise("mdb_env_set_mapsize", rc);
440 }
441}
442
447static inline void
449 const unsigned int count) {
450 const int rc = ::mdb_env_set_maxreaders(env, count);
451 if (rc != MDB_SUCCESS) {
452 error::raise("mdb_env_set_maxreaders", rc);
453 }
454}
455
460static inline void
462 unsigned int* const count) {
463 const int rc = ::mdb_env_get_maxreaders(env, count);
464 if (rc != MDB_SUCCESS) {
465 error::raise("mdb_env_get_maxreaders", rc);
466 }
467}
468
473static inline void
475 const MDB_dbi count) {
476 const int rc = ::mdb_env_set_maxdbs(env, count);
477 if (rc != MDB_SUCCESS) {
478 error::raise("mdb_env_set_maxdbs", rc);
479 }
480}
481
485static inline unsigned int
487 const int rc = ::mdb_env_get_maxkeysize(env);
488#ifdef LMDBXX_DEBUG
489 assert(rc >= 0);
490#endif
491 return static_cast<unsigned int>(rc);
492}
493
494#if MDB_VERSION_FULL >= MDB_VERINT(0, 9, 11)
500static inline void
502 void* const ctx) {
503 const int rc = ::mdb_env_set_userctx(env, ctx);
504 if (rc != MDB_SUCCESS) {
505 error::raise("mdb_env_set_userctx", rc);
506 }
507}
508#endif
509
510#if MDB_VERSION_FULL >= MDB_VERINT(0, 9, 11)
515static inline void*
516lmdb::env_get_userctx(MDB_env* const env) {
517 return ::mdb_env_get_userctx(env);
518}
519#endif
520
521static inline void
522lmdb::reader_check(MDB_env *env, int *dead) {
523 const int rc = ::mdb_reader_check(env, dead);
524 if (rc != MDB_SUCCESS) {
525 error::raise("reader_check", rc);
526 }
527}
528
530/* Procedural Interface: Transactions */
531
532namespace lmdb {
533 static inline void txn_begin(
534 MDB_env* env, MDB_txn* parent, unsigned int flags, MDB_txn** txn);
535 static inline MDB_env* txn_env(MDB_txn* txn) noexcept;
536#ifdef LMDBXX_TXN_ID
537 static inline std::size_t txn_id(MDB_txn* txn) noexcept;
538#endif
539 static inline void txn_commit(MDB_txn* txn);
540 static inline void txn_abort(MDB_txn* txn) noexcept;
541 static inline void txn_reset(MDB_txn* txn) noexcept;
542 static inline void txn_renew(MDB_txn* txn);
543}
544
549static inline void
550lmdb::txn_begin(MDB_env* const env,
551 MDB_txn* const parent,
552 const unsigned int flags,
553 MDB_txn** txn) {
554 const int rc = ::mdb_txn_begin(env, parent, flags, txn);
555 if (rc != MDB_SUCCESS) {
556 error::raise("mdb_txn_begin", rc);
557 }
558}
559
563static inline MDB_env*
564lmdb::txn_env(MDB_txn* const txn) noexcept {
565 return ::mdb_txn_env(txn);
566}
567
568#ifdef LMDBXX_TXN_ID
572static inline std::size_t
573lmdb::txn_id(MDB_txn* const txn) noexcept {
574 return ::mdb_txn_id(txn);
575}
576#endif
577
582static inline void
583lmdb::txn_commit(MDB_txn* const txn) {
584 const int rc = ::mdb_txn_commit(txn);
585 if (rc != MDB_SUCCESS) {
586 error::raise("mdb_txn_commit", rc);
587 }
588}
589
593static inline void
594lmdb::txn_abort(MDB_txn* const txn) noexcept {
595 ::mdb_txn_abort(txn);
596}
597
601static inline void
602lmdb::txn_reset(MDB_txn* const txn) noexcept {
603 ::mdb_txn_reset(txn);
604}
605
610static inline void
611lmdb::txn_renew(MDB_txn* const txn) {
612 const int rc = ::mdb_txn_renew(txn);
613 if (rc != MDB_SUCCESS) {
614 error::raise("mdb_txn_renew", rc);
615 }
616}
617
619/* Procedural Interface: Databases */
620
621namespace lmdb {
622 static inline void dbi_open(
623 MDB_txn* txn, const char* name, unsigned int flags, MDB_dbi* dbi);
624 static inline void dbi_stat(MDB_txn* txn, MDB_dbi dbi, MDB_stat* stat);
625 static inline void dbi_flags(MDB_txn* txn, MDB_dbi dbi, unsigned int* flags);
626 static inline void dbi_close(MDB_env* env, MDB_dbi dbi) noexcept;
627 static inline void dbi_drop(MDB_txn* txn, MDB_dbi dbi, bool del);
628 static inline void dbi_set_compare(MDB_txn* txn, MDB_dbi dbi, MDB_cmp_func* cmp);
629 static inline void dbi_set_dupsort(MDB_txn* txn, MDB_dbi dbi, MDB_cmp_func* cmp);
630 static inline void dbi_set_relfunc(MDB_txn* txn, MDB_dbi dbi, MDB_rel_func* rel);
631 static inline void dbi_set_relctx(MDB_txn* txn, MDB_dbi dbi, void* ctx);
632 static inline bool dbi_get(MDB_txn* txn, MDB_dbi dbi, const MDB_val* key, MDB_val* data);
633 static inline bool dbi_put(MDB_txn* txn, MDB_dbi dbi, const MDB_val* key, MDB_val* data, unsigned int flags);
634 static inline bool dbi_del(MDB_txn* txn, MDB_dbi dbi, const MDB_val* key, const MDB_val* data);
635 // TODO: mdb_cmp()
636 // TODO: mdb_dcmp()
637}
638
643static inline void
644lmdb::dbi_open(MDB_txn* const txn,
645 const char* const name,
646 const unsigned int flags,
647 MDB_dbi* const dbi) {
648 const int rc = ::mdb_dbi_open(txn, name, flags, dbi);
649 if (rc != MDB_SUCCESS) {
650 error::raise("mdb_dbi_open", rc);
651 }
652}
653
658static inline void
659lmdb::dbi_stat(MDB_txn* const txn,
660 const MDB_dbi dbi,
661 MDB_stat* const result) {
662 const int rc = ::mdb_stat(txn, dbi, result);
663 if (rc != MDB_SUCCESS) {
664 error::raise("mdb_stat", rc);
665 }
666}
667
672static inline void
673lmdb::dbi_flags(MDB_txn* const txn,
674 const MDB_dbi dbi,
675 unsigned int* const flags) {
676 const int rc = ::mdb_dbi_flags(txn, dbi, flags);
677 if (rc != MDB_SUCCESS) {
678 error::raise("mdb_dbi_flags", rc);
679 }
680}
681
685static inline void
686lmdb::dbi_close(MDB_env* const env,
687 const MDB_dbi dbi) noexcept {
688 ::mdb_dbi_close(env, dbi);
689}
690
694static inline void
695lmdb::dbi_drop(MDB_txn* const txn,
696 const MDB_dbi dbi,
697 const bool del = false) {
698 const int rc = ::mdb_drop(txn, dbi, del ? 1 : 0);
699 if (rc != MDB_SUCCESS) {
700 error::raise("mdb_drop", rc);
701 }
702}
703
708static inline void
710 const MDB_dbi dbi,
711 MDB_cmp_func* const cmp = nullptr) {
712 const int rc = ::mdb_set_compare(txn, dbi, cmp);
713 if (rc != MDB_SUCCESS) {
714 error::raise("mdb_set_compare", rc);
715 }
716}
717
722static inline void
724 const MDB_dbi dbi,
725 MDB_cmp_func* const cmp = nullptr) {
726 const int rc = ::mdb_set_dupsort(txn, dbi, cmp);
727 if (rc != MDB_SUCCESS) {
728 error::raise("mdb_set_dupsort", rc);
729 }
730}
731
736static inline void
738 const MDB_dbi dbi,
739 MDB_rel_func* const rel) {
740 const int rc = ::mdb_set_relfunc(txn, dbi, rel);
741 if (rc != MDB_SUCCESS) {
742 error::raise("mdb_set_relfunc", rc);
743 }
744}
745
750static inline void
752 const MDB_dbi dbi,
753 void* const ctx) {
754 const int rc = ::mdb_set_relctx(txn, dbi, ctx);
755 if (rc != MDB_SUCCESS) {
756 error::raise("mdb_set_relctx", rc);
757 }
758}
759
765static inline bool
766lmdb::dbi_get(MDB_txn* const txn,
767 const MDB_dbi dbi,
768 const MDB_val* const key,
769 MDB_val* const data) {
770 const int rc = ::mdb_get(txn, dbi, const_cast<MDB_val*>(key), data);
771 if (rc != MDB_SUCCESS && rc != MDB_NOTFOUND) {
772 error::raise("mdb_get", rc);
773 }
774 return (rc == MDB_SUCCESS);
775}
776
782static inline bool
783lmdb::dbi_put(MDB_txn* const txn,
784 const MDB_dbi dbi,
785 const MDB_val* const key,
786 MDB_val* const data,
787 const unsigned int flags = 0) {
788 const int rc = ::mdb_put(txn, dbi, const_cast<MDB_val*>(key), data, flags);
789 if (rc != MDB_SUCCESS && rc != MDB_KEYEXIST) {
790 error::raise("mdb_put", rc);
791 }
792 return (rc == MDB_SUCCESS);
793}
794
800static inline bool
801lmdb::dbi_del(MDB_txn* const txn,
802 const MDB_dbi dbi,
803 const MDB_val* const key,
804 const MDB_val* const data = nullptr) {
805 const int rc = ::mdb_del(txn, dbi, const_cast<MDB_val*>(key), const_cast<MDB_val*>(data));
806 if (rc != MDB_SUCCESS && rc != MDB_NOTFOUND) {
807 error::raise("mdb_del", rc);
808 }
809 return (rc == MDB_SUCCESS);
810}
811
813/* Procedural Interface: Cursors */
814
815namespace lmdb {
816 static inline void cursor_open(MDB_txn* txn, MDB_dbi dbi, MDB_cursor** cursor);
817 static inline void cursor_close(MDB_cursor* cursor) noexcept;
818 static inline void cursor_renew(MDB_txn* txn, MDB_cursor* cursor);
819 static inline MDB_txn* cursor_txn(MDB_cursor* cursor) noexcept;
820 static inline MDB_dbi cursor_dbi(MDB_cursor* cursor) noexcept;
821 static inline bool cursor_get(MDB_cursor* cursor, MDB_val* key, MDB_val* data, MDB_cursor_op op);
822 static inline bool cursor_put(MDB_cursor* cursor, MDB_val* key, MDB_val* data, unsigned int flags);
823 static inline void cursor_del(MDB_cursor* cursor, unsigned int flags);
824 static inline void cursor_count(MDB_cursor* cursor, std::size_t& count);
825}
826
831static inline void
832lmdb::cursor_open(MDB_txn* const txn,
833 const MDB_dbi dbi,
834 MDB_cursor** const cursor) {
835 const int rc = ::mdb_cursor_open(txn, dbi, cursor);
836 if (rc != MDB_SUCCESS) {
837 error::raise("mdb_cursor_open", rc);
838 }
839}
840
844static inline void
845lmdb::cursor_close(MDB_cursor* const cursor) noexcept {
846 ::mdb_cursor_close(cursor);
847}
848
853static inline void
854lmdb::cursor_renew(MDB_txn* const txn,
855 MDB_cursor* const cursor) {
856 const int rc = ::mdb_cursor_renew(txn, cursor);
857 if (rc != MDB_SUCCESS) {
858 error::raise("mdb_cursor_renew", rc);
859 }
860}
861
865static inline MDB_txn*
866lmdb::cursor_txn(MDB_cursor* const cursor) noexcept {
867 return ::mdb_cursor_txn(cursor);
868}
869
873static inline MDB_dbi
874lmdb::cursor_dbi(MDB_cursor* const cursor) noexcept {
875 return ::mdb_cursor_dbi(cursor);
876}
877
882static inline bool
883lmdb::cursor_get(MDB_cursor* const cursor,
884 MDB_val* const key,
885 MDB_val* const data,
886 const MDB_cursor_op op) {
887 const int rc = ::mdb_cursor_get(cursor, key, data, op);
888 if (rc != MDB_SUCCESS && rc != MDB_NOTFOUND) {
889 error::raise("mdb_cursor_get", rc);
890 }
891 return (rc == MDB_SUCCESS);
892}
893
898static inline bool
899lmdb::cursor_put(MDB_cursor* const cursor,
900 MDB_val* const key,
901 MDB_val* const data,
902 const unsigned int flags = 0) {
903 const int rc = ::mdb_cursor_put(cursor, key, data, flags);
904 if (rc != MDB_SUCCESS && rc != MDB_KEYEXIST) {
905 error::raise("mdb_cursor_put", rc);
906 }
907 return (rc == MDB_SUCCESS);
908}
909
914static inline void
915lmdb::cursor_del(MDB_cursor* const cursor,
916 const unsigned int flags = 0) {
917 const int rc = ::mdb_cursor_del(cursor, flags);
918 if (rc != MDB_SUCCESS) {
919 error::raise("mdb_cursor_del", rc);
920 }
921}
922
927static inline void
928lmdb::cursor_count(MDB_cursor* const cursor,
929 std::size_t& count) {
930 const int rc = ::mdb_cursor_count(cursor, &count);
931 if (rc != MDB_SUCCESS) {
932 error::raise("mdb_cursor_count", rc);
933 }
934}
935
937/* Resource Interface: Environment */
938
939namespace lmdb {
940 class env;
941}
942
950protected:
951 MDB_env* _handle{nullptr};
952
953public:
954 static constexpr unsigned int default_flags = 0;
955 static constexpr mode default_mode = 0644; /* -rw-r--r-- */
956
963 static env create(const unsigned int flags = default_flags) {
964 MDB_env* handle{nullptr};
966#ifdef LMDBXX_DEBUG
967 assert(handle != nullptr);
968#endif
969 if (flags) {
970 try {
972 }
973 catch (const lmdb::error&) {
975 throw;
976 }
977 }
978 return env{handle};
979 }
980
986 env(MDB_env* const handle) noexcept
987 : _handle{handle} {}
988
992 env(env&& other) noexcept {
993 std::swap(_handle, other._handle);
994 }
995
999 env& operator=(env&& other) noexcept {
1000 if (this != &other) {
1001 std::swap(_handle, other._handle);
1002 }
1003 return *this;
1004 }
1005
1009 ~env() noexcept {
1010 try { close(); } catch (...) {}
1011 }
1012
1016 operator MDB_env*() const noexcept {
1017 return _handle;
1018 }
1019
1023 MDB_env* handle() const noexcept {
1024 return _handle;
1025 }
1026
1033 void sync(const bool force = true) {
1034 lmdb::env_sync(handle(), force);
1035 }
1036
1043 void close() noexcept {
1044 if (handle()) {
1046 _handle = nullptr;
1047 }
1048 }
1049
1051 int dead;
1052 lmdb::reader_check(handle(), &dead);
1053 return dead;
1054 }
1055
1064 env& open(const char* const path,
1065 const unsigned int flags = default_flags,
1066 const mode mode = default_mode) {
1067 lmdb::env_open(handle(), path, flags, mode);
1068 return *this;
1069 }
1070
1076 env& set_flags(const unsigned int flags,
1077 const bool onoff = true) {
1078 lmdb::env_set_flags(handle(), flags, onoff);
1079 return *this;
1080 }
1081
1086 env& set_mapsize(const std::size_t size) {
1088 return *this;
1089 }
1090
1095 env& set_max_readers(const unsigned int count) {
1097 return *this;
1098 }
1099
1104 env& set_max_dbs(const MDB_dbi count) {
1105 lmdb::env_set_max_dbs(handle(), count);
1106 return *this;
1107 }
1108
1109 mdb_filehandle_t get_fd() {
1110 mdb_filehandle_t fd;
1111 lmdb::env_get_fd(handle(), &fd);
1112 return fd;
1113 }
1114
1118 std::string_view get_internal_map() {
1119 if constexpr (sizeof(int) != 4 || sizeof(long) != 8 || sizeof(void*) != 8) error::raise("get_internal_map: only LP64 supported", 0);
1120
1121 // This is a hack that depends on the internal layout of LMDB's MDB_env struct. Hopefully there
1122 // will be a better way to get me_map at some point.
1123
1124 char *me_map = *(char**)(((char*)_handle) + 56);
1125
1126 MDB_envinfo arg;
1127 mdb_env_info(_handle, &arg);
1128
1129 return std::string_view(me_map, arg.me_mapsize);
1130 }
1131};
1132
1134/* Resource Interface: Transactions */
1135
1136namespace lmdb {
1137 class txn;
1138}
1139
1147protected:
1148 MDB_txn* _handle{nullptr};
1149
1150public:
1151 static constexpr unsigned int default_flags = 0;
1152
1161 static txn begin(MDB_env* const env,
1162 MDB_txn* const parent = nullptr,
1163 const unsigned int flags = default_flags) {
1164 MDB_txn* handle{nullptr};
1165 lmdb::txn_begin(env, parent, flags, &handle);
1166#ifdef LMDBXX_DEBUG
1167 assert(handle != nullptr);
1168#endif
1169 return txn{handle};
1170 }
1171
1177 txn(MDB_txn* const handle) noexcept
1178 : _handle{handle} {}
1179
1183 txn(txn&& other) noexcept {
1184 std::swap(_handle, other._handle);
1185 }
1186
1190 txn& operator=(txn&& other) noexcept {
1191 if (this != &other) {
1192 std::swap(_handle, other._handle);
1193 }
1194 return *this;
1195 }
1196
1200 ~txn() noexcept {
1201 if (_handle) {
1202 try { abort(); } catch (...) {}
1203 _handle = nullptr;
1204 }
1205 }
1206
1210 operator MDB_txn*() const noexcept {
1211 return _handle;
1212 }
1213
1217 MDB_txn* handle() const noexcept {
1218 return _handle;
1219 }
1220
1224 MDB_env* env() const noexcept {
1225 return lmdb::txn_env(handle());
1226 }
1227
1234 void commit() {
1235 auto h = _handle;
1236 _handle = nullptr;
1238 }
1239
1245 void abort() noexcept {
1246 auto h = _handle;
1247 _handle = nullptr;
1248 lmdb::txn_abort(h);
1249 }
1250
1254 void reset() noexcept {
1256 }
1257
1263 void renew() {
1265 }
1266};
1267
1269/* Resource Interface: Databases */
1270
1271namespace lmdb {
1272 class dbi;
1273}
1274
1281protected:
1282 MDB_dbi _handle{(std::numeric_limits<MDB_dbi>::max)()};
1283
1284public:
1285 static constexpr unsigned int default_flags = 0;
1286 static constexpr unsigned int default_put_flags = 0;
1287
1296 static dbi
1297 open(MDB_txn* const txn,
1298 const char* const name = nullptr,
1299 const unsigned int flags = default_flags) {
1300 MDB_dbi handle{};
1301 lmdb::dbi_open(txn, name, flags, &handle);
1302 return dbi{handle};
1303 }
1304
1305 /*
1306 * This overload is so that DBI names can be passed in as string_views, which can be
1307 * useful when storing the names of DBIs in the database itself. We need to convert it
1308 * to a std::string to ensure that it is NUL-byte terminated. This overload comes after
1309 * the const char* one above so that in that case there is no std::string overhead.
1310 */
1311
1312 static dbi
1313 open(MDB_txn* const txn,
1314 std::string_view name,
1315 const unsigned int flags = default_flags) {
1316 MDB_dbi handle{};
1317 std::string nameStr(name);
1318 lmdb::dbi_open(txn, nameStr.c_str(), flags, &handle);
1319 return dbi{handle};
1320 }
1321
1327 dbi() noexcept
1328 : _handle{(std::numeric_limits<MDB_dbi>::max)()} {}
1329
1335 dbi(const MDB_dbi handle) noexcept
1336 : _handle{handle} {}
1337
1341 ~dbi() noexcept {
1342 if (_handle) {
1343 /* No need to call close() here. */
1344 }
1345 }
1346
1350 operator MDB_dbi() const noexcept {
1351 return _handle;
1352 }
1353
1357 MDB_dbi handle() const noexcept {
1358 return _handle;
1359 }
1360
1367 MDB_stat stat(MDB_txn* const txn) const {
1368 MDB_stat result;
1369 lmdb::dbi_stat(txn, handle(), &result);
1370 return result;
1371 }
1372
1379 unsigned int flags(MDB_txn* const txn) const {
1380 unsigned int result{};
1381 lmdb::dbi_flags(txn, handle(), &result);
1382 return result;
1383 }
1384
1391 std::size_t size(MDB_txn* const txn) const {
1392 return stat(txn).ms_entries;
1393 }
1394
1400 void drop(MDB_txn* const txn,
1401 const bool del = false) {
1403 }
1404
1412 dbi& set_compare(MDB_txn* const txn,
1413 MDB_cmp_func* const cmp = nullptr) {
1415 return *this;
1416 }
1417
1426
1427 bool get(MDB_txn* const txn,
1428 const std::string_view key,
1429 std::string_view& data) {
1430 const MDB_val keyV{key.size(), const_cast<char*>(key.data())};
1431 MDB_val dataV{data.size(), const_cast<char*>(data.data())};
1432 bool ret = lmdb::dbi_get(txn, handle(), &keyV, &dataV);
1433 if (ret) {
1434 data = std::string_view(static_cast<char*>(dataV.mv_data), dataV.mv_size);
1435 }
1436 return ret;
1437 }
1438
1448 bool put(MDB_txn* const txn,
1449 const std::string_view key,
1450 std::string_view data,
1451 const unsigned int flags = default_put_flags) {
1452 const MDB_val keyV{key.size(), const_cast<char*>(key.data())};
1453 MDB_val dataV{data.size(), const_cast<char*>(data.data())};
1454 return lmdb::dbi_put(txn, handle(), &keyV, &dataV, flags);
1455 }
1456
1464 bool del(MDB_txn* const txn,
1465 const std::string_view key) {
1466 const MDB_val keyV{key.size(), const_cast<char*>(key.data())};
1467 return lmdb::dbi_del(txn, handle(), &keyV);
1468 }
1469
1478 bool del(MDB_txn* const txn,
1479 const std::string_view key,
1480 const std::string_view val) {
1481 const MDB_val keyV{key.size(), const_cast<char*>(key.data())};
1482 const MDB_val valV{val.size(), const_cast<char*>(val.data())};
1483 return lmdb::dbi_del(txn, handle(), &keyV, &valV);
1484 }
1485};
1486
1488/* Resource Interface: Cursors */
1489
1490namespace lmdb {
1491 class cursor;
1492}
1493
1501protected:
1502 MDB_cursor* _handle{nullptr};
1503
1504public:
1505 static constexpr unsigned int default_flags = 0;
1506
1514 static cursor
1515 open(MDB_txn* const txn,
1516 const MDB_dbi dbi) {
1517 MDB_cursor* handle{};
1519#ifdef LMDBXX_DEBUG
1520 assert(handle != nullptr);
1521#endif
1522 return cursor{handle};
1523 }
1524
1530 cursor(MDB_cursor* const handle) noexcept
1531 : _handle{handle} {}
1532
1536 cursor(cursor&& other) noexcept {
1537 std::swap(_handle, other._handle);
1538 }
1539
1543 cursor& operator=(cursor&& other) noexcept {
1544 if (this != &other) {
1545 std::swap(_handle, other._handle);
1546 }
1547 return *this;
1548 }
1549
1553 ~cursor() noexcept {
1554 try { close(); } catch (...) {}
1555 }
1556
1560 operator MDB_cursor*() const noexcept {
1561 return _handle;
1562 }
1563
1567 MDB_cursor* handle() const noexcept {
1568 return _handle;
1569 }
1570
1577 void close() noexcept {
1578 if (_handle) {
1580 _handle = nullptr;
1581 }
1582 }
1583
1590 void renew(MDB_txn* const txn) {
1592 }
1593
1597 MDB_txn* txn() const noexcept {
1598 return lmdb::cursor_txn(handle());
1599 }
1600
1604 MDB_dbi dbi() const noexcept {
1605 return lmdb::cursor_dbi(handle());
1606 }
1607
1615 bool get(std::string_view &key,
1616 const MDB_cursor_op op) {
1617 MDB_val keyV{key.size(), const_cast<char*>(key.data())};
1618 bool ret = lmdb::cursor_get(handle(), &keyV, nullptr, op);
1619 if (ret) {
1620 key = std::string_view(static_cast<char*>(keyV.mv_data), keyV.mv_size);
1621 }
1622 return ret;
1623 }
1624
1633 bool get(std::string_view &key,
1634 std::string_view &val,
1635 const MDB_cursor_op op) {
1636 MDB_val keyV{key.size(), const_cast<char*>(key.data())};
1637 MDB_val valV{val.size(), const_cast<char*>(val.data())};
1638 bool ret = lmdb::cursor_get(handle(), &keyV, &valV, op);
1639 if (ret) {
1640 key = std::string_view(static_cast<char*>(keyV.mv_data), keyV.mv_size);
1641 val = std::string_view(static_cast<char*>(valV.mv_data), valV.mv_size);
1642 }
1643 return ret;
1644 }
1645
1656 bool put(const std::string_view &key,
1657 const std::string_view &val,
1658 const unsigned int flags = 0) {
1659 MDB_val keyV{key.size(), const_cast<char*>(key.data())};
1660 MDB_val valV{val.size(), const_cast<char*>(val.data())};
1661 return lmdb::cursor_put(handle(), &keyV, &valV, flags);
1662 }
1663
1670 void del(unsigned int flags = 0) {
1671 lmdb::cursor_del(handle(), flags);
1672 }
1673
1677 size_t count() {
1678 std::size_t countp;
1679 lmdb::cursor_count(handle(), countp);
1680 return countp;
1681 }
1682};
1683
1684namespace lmdb {
1690 template<typename T>
1691 static inline std::string_view ptr_to_sv(T* v) {
1692 return std::string_view(reinterpret_cast<char*>(v), sizeof(*v));
1693 }
1694
1700 template<typename T>
1701 static inline std::string_view to_sv(const T &v) {
1702 return std::string_view(reinterpret_cast<const char*>(std::addressof(v)), sizeof(v));
1703 }
1704
1710 template<typename T>
1711 static inline T* ptr_from_sv(std::string_view v) {
1712 if (v.size() != sizeof(T)) error::raise("ptr_from_sv", MDB_BAD_VALSIZE);
1713 return reinterpret_cast<T*>(const_cast<char*>(v.data()));
1714 }
1715
1721 template<typename T>
1722 static inline T from_sv(std::string_view v) {
1723 if (v.size() != sizeof(T)) error::raise("from_sv", MDB_BAD_VALSIZE);
1724 T ret;
1725 std::memcpy(&ret, const_cast<char*>(v.data()), sizeof(T));
1726 return ret;
1727 }
1728}
1729
1731
1732#endif /* LMDBXX_H */
Exception class for MDB_BAD_DBI errors.
Definition lmdb++.h:197
Exception class for MDB_CORRUPTED errors.
Definition lmdb++.h:156
Resource class for MDB_cursor* handles.
Definition lmdb++.h:1500
MDB_cursor * handle() const noexcept
Returns the underlying MDB_cursor* handle.
Definition lmdb++.h:1567
static constexpr unsigned int default_flags
Definition lmdb++.h:1505
MDB_cursor * _handle
Definition lmdb++.h:1502
void close() noexcept
Closes this cursor.
Definition lmdb++.h:1577
~cursor() noexcept
Destructor.
Definition lmdb++.h:1553
bool put(const std::string_view &key, const std::string_view &val, const unsigned int flags=0)
Stores key/data pairs into the database.
Definition lmdb++.h:1656
bool get(std::string_view &key, std::string_view &val, const MDB_cursor_op op)
Retrieves a key/value pair from the database.
Definition lmdb++.h:1633
MDB_txn * txn() const noexcept
Returns the cursor's transaction handle.
Definition lmdb++.h:1597
size_t count()
Return count of duplicates for current key.
Definition lmdb++.h:1677
cursor(cursor &&other) noexcept
Move constructor.
Definition lmdb++.h:1536
MDB_dbi dbi() const noexcept
Returns the cursor's database handle.
Definition lmdb++.h:1604
static cursor open(MDB_txn *const txn, const MDB_dbi dbi)
Creates an LMDB cursor.
Definition lmdb++.h:1515
cursor & operator=(cursor &&other) noexcept
Move assignment operator.
Definition lmdb++.h:1543
cursor(MDB_cursor *const handle) noexcept
Constructor.
Definition lmdb++.h:1530
void del(unsigned int flags=0)
Delete current key/data pair.
Definition lmdb++.h:1670
bool get(std::string_view &key, const MDB_cursor_op op)
Retrieves a key from the database.
Definition lmdb++.h:1615
void renew(MDB_txn *const txn)
Renews this cursor.
Definition lmdb++.h:1590
Resource class for MDB_dbi handles.
Definition lmdb++.h:1280
bool put(MDB_txn *const txn, const std::string_view key, std::string_view data, const unsigned int flags=default_put_flags)
Stores a key/value pair into this database.
Definition lmdb++.h:1448
std::size_t size(MDB_txn *const txn) const
Returns the number of records in this database.
Definition lmdb++.h:1391
static constexpr unsigned int default_put_flags
Definition lmdb++.h:1286
dbi(const MDB_dbi handle) noexcept
Constructor.
Definition lmdb++.h:1335
bool del(MDB_txn *const txn, const std::string_view key)
Removes a key from this database.
Definition lmdb++.h:1464
dbi & set_compare(MDB_txn *const txn, MDB_cmp_func *const cmp=nullptr)
Sets a custom key comparison function for this database.
Definition lmdb++.h:1412
~dbi() noexcept
Destructor.
Definition lmdb++.h:1341
static dbi open(MDB_txn *const txn, std::string_view name, const unsigned int flags=default_flags)
Definition lmdb++.h:1313
MDB_stat stat(MDB_txn *const txn) const
Returns statistics for this database.
Definition lmdb++.h:1367
unsigned int flags(MDB_txn *const txn) const
Retrieves the flags for this database handle.
Definition lmdb++.h:1379
dbi() noexcept
Constructor.
Definition lmdb++.h:1327
static dbi open(MDB_txn *const txn, const char *const name=nullptr, const unsigned int flags=default_flags)
Opens a database handle.
Definition lmdb++.h:1297
static constexpr unsigned int default_flags
Definition lmdb++.h:1285
bool del(MDB_txn *const txn, const std::string_view key, const std::string_view val)
Removes a key/value pair from this database.
Definition lmdb++.h:1478
void drop(MDB_txn *const txn, const bool del=false)
Definition lmdb++.h:1400
MDB_dbi _handle
Definition lmdb++.h:1282
MDB_dbi handle() const noexcept
Returns the underlying MDB_dbi handle.
Definition lmdb++.h:1357
bool get(MDB_txn *const txn, const std::string_view key, std::string_view &data)
Retrieves a key/value pair from this database.
Definition lmdb++.h:1427
Resource class for MDB_env* handles.
Definition lmdb++.h:949
env & set_flags(const unsigned int flags, const bool onoff=true)
Definition lmdb++.h:1076
void close() noexcept
Closes this environment, releasing the memory map.
Definition lmdb++.h:1043
static constexpr mode default_mode
Definition lmdb++.h:955
env & set_mapsize(const std::size_t size)
Definition lmdb++.h:1086
env & set_max_dbs(const MDB_dbi count)
Definition lmdb++.h:1104
~env() noexcept
Destructor.
Definition lmdb++.h:1009
MDB_env * _handle
Definition lmdb++.h:951
env(MDB_env *const handle) noexcept
Constructor.
Definition lmdb++.h:986
env(env &&other) noexcept
Move constructor.
Definition lmdb++.h:992
void sync(const bool force=true)
Flushes data buffers to disk.
Definition lmdb++.h:1033
MDB_env * handle() const noexcept
Returns the underlying MDB_env* handle.
Definition lmdb++.h:1023
static constexpr unsigned int default_flags
Definition lmdb++.h:954
env & operator=(env &&other) noexcept
Move assignment operator.
Definition lmdb++.h:999
static env create(const unsigned int flags=default_flags)
Creates a new LMDB environment.
Definition lmdb++.h:963
env & open(const char *const path, const unsigned int flags=default_flags, const mode mode=default_mode)
Opens this environment.
Definition lmdb++.h:1064
int reader_check()
Definition lmdb++.h:1050
env & set_max_readers(const unsigned int count)
Definition lmdb++.h:1095
mdb_filehandle_t get_fd()
Definition lmdb++.h:1109
std::string_view get_internal_map()
@notice WARNING: This is a function to access LMDB's internal memory map, use at your own risk!
Definition lmdb++.h:1118
Base class for LMDB exception conditions.
Definition lmdb++.h:64
const char * origin() const noexcept
Returns the origin of the LMDB error.
Definition lmdb++.h:92
const int _code
Definition lmdb++.h:66
virtual const char * what() const noexcept
Returns the underlying LMDB error code.
Definition lmdb++.h:99
error(const char *const origin, const int rc) noexcept
Constructor.
Definition lmdb++.h:77
static void raise(const char *origin, int rc)
Throws an error based on the given LMDB return code.
Definition lmdb++.h:203
int code() const noexcept
Returns the underlying LMDB error code.
Definition lmdb++.h:85
Base class for fatal error conditions.
Definition lmdb++.h:118
Exception class for MDB_KEYEXIST errors.
Definition lmdb++.h:136
Base class for logic error conditions.
Definition lmdb++.h:110
Exception class for MDB_MAP_FULL errors.
Definition lmdb++.h:186
Exception class for MDB_NOTFOUND errors.
Definition lmdb++.h:146
Exception class for MDB_PANIC errors.
Definition lmdb++.h:166
Base class for runtime error conditions.
Definition lmdb++.h:126
Resource class for MDB_txn* handles.
Definition lmdb++.h:1146
MDB_txn * handle() const noexcept
Returns the underlying MDB_txn* handle.
Definition lmdb++.h:1217
void commit()
Commits this transaction.
Definition lmdb++.h:1234
MDB_env * env() const noexcept
Returns the transaction's MDB_env* handle.
Definition lmdb++.h:1224
void abort() noexcept
Aborts this transaction.
Definition lmdb++.h:1245
MDB_txn * _handle
Definition lmdb++.h:1148
void reset() noexcept
Resets this read-only transaction.
Definition lmdb++.h:1254
static constexpr unsigned int default_flags
Definition lmdb++.h:1151
txn & operator=(txn &&other) noexcept
Move assignment operator.
Definition lmdb++.h:1190
~txn() noexcept
Destructor.
Definition lmdb++.h:1200
void renew()
Renews this read-only transaction.
Definition lmdb++.h:1263
txn(txn &&other) noexcept
Move constructor.
Definition lmdb++.h:1183
txn(MDB_txn *const handle) noexcept
Constructor.
Definition lmdb++.h:1177
static txn begin(MDB_env *const env, MDB_txn *const parent=nullptr, const unsigned int flags=default_flags)
Creates a new LMDB transaction.
Definition lmdb++.h:1161
Exception class for MDB_VERSION_MISMATCH errors.
Definition lmdb++.h:176
<lmdb++.h> - C++17 wrapper for LMDB.
Definition lmdb++.h:38
static void env_info(MDB_env *env, MDB_envinfo *stat)
Definition lmdb++.h:348
static void * env_get_userctx(MDB_env *env)
Definition lmdb++.h:516
static void dbi_flags(MDB_txn *txn, MDB_dbi dbi, unsigned int *flags)
Definition lmdb++.h:673
static void cursor_renew(MDB_txn *txn, MDB_cursor *cursor)
Definition lmdb++.h:854
static void env_copy_fd(MDB_env *env, mdb_filehandle_t fd, unsigned int flags)
Definition lmdb++.h:316
static void txn_commit(MDB_txn *txn)
Definition lmdb++.h:583
static void env_open(MDB_env *env, const char *path, unsigned int flags, mode mode)
Definition lmdb++.h:280
static MDB_txn * cursor_txn(MDB_cursor *cursor) noexcept
Definition lmdb++.h:866
static void dbi_drop(MDB_txn *txn, MDB_dbi dbi, bool del)
Definition lmdb++.h:695
static bool dbi_put(MDB_txn *txn, MDB_dbi dbi, const MDB_val *key, MDB_val *data, unsigned int flags)
Definition lmdb++.h:783
static void env_create(MDB_env **env)
Definition lmdb++.h:268
static std::string_view to_sv(const T &v)
Creates a std::string_view that points to the memory occupied by v.
Definition lmdb++.h:1701
static unsigned int env_get_max_keysize(MDB_env *env)
Definition lmdb++.h:486
static void cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **cursor)
Definition lmdb++.h:832
static void reader_check(MDB_env *env, int *dead)
Definition lmdb++.h:522
static void env_get_fd(MDB_env *env, mdb_filehandle_t *fd)
Definition lmdb++.h:422
static void cursor_del(MDB_cursor *cursor, unsigned int flags)
Definition lmdb++.h:915
static T from_sv(std::string_view v)
Takes a std::string_view and dereferences it, returning a value of the parameterized type.
Definition lmdb++.h:1722
static void dbi_set_relfunc(MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel)
Definition lmdb++.h:737
static void dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *dbi)
Definition lmdb++.h:644
static void dbi_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
Definition lmdb++.h:709
static void env_set_max_readers(MDB_env *env, unsigned int count)
Definition lmdb++.h:448
static MDB_env * txn_env(MDB_txn *txn) noexcept
Definition lmdb++.h:564
static void env_set_mapsize(MDB_env *env, std::size_t size)
Definition lmdb++.h:435
static void env_set_max_dbs(MDB_env *env, MDB_dbi count)
Definition lmdb++.h:474
static void env_close(MDB_env *env) noexcept
Definition lmdb++.h:373
static void env_set_flags(MDB_env *env, unsigned int flags, bool onoff)
Definition lmdb++.h:382
static void txn_renew(MDB_txn *txn)
Definition lmdb++.h:611
static bool cursor_put(MDB_cursor *cursor, MDB_val *key, MDB_val *data, unsigned int flags)
Definition lmdb++.h:899
static void cursor_close(MDB_cursor *cursor) noexcept
Definition lmdb++.h:845
static bool cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data, MDB_cursor_op op)
Definition lmdb++.h:883
static void cursor_count(MDB_cursor *cursor, std::size_t &count)
Definition lmdb++.h:928
static void env_get_max_readers(MDB_env *env, unsigned int *count)
Definition lmdb++.h:461
static MDB_dbi cursor_dbi(MDB_cursor *cursor) noexcept
Definition lmdb++.h:874
static void txn_abort(MDB_txn *txn) noexcept
Definition lmdb++.h:594
static void env_get_path(MDB_env *env, const char **path)
Definition lmdb++.h:409
static void dbi_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *stat)
Definition lmdb++.h:659
static bool dbi_del(MDB_txn *txn, MDB_dbi dbi, const MDB_val *key, const MDB_val *data)
Definition lmdb++.h:801
static bool dbi_get(MDB_txn *txn, MDB_dbi dbi, const MDB_val *key, MDB_val *data)
Definition lmdb++.h:766
static void env_copy(MDB_env *env, const char *path, unsigned int flags)
Definition lmdb++.h:296
static void txn_reset(MDB_txn *txn) noexcept
Definition lmdb++.h:602
static void env_set_userctx(MDB_env *env, void *ctx)
Definition lmdb++.h:501
static void dbi_close(MDB_env *env, MDB_dbi dbi) noexcept
Definition lmdb++.h:686
static void env_stat(MDB_env *env, MDB_stat *stat)
Definition lmdb++.h:335
static T * ptr_from_sv(std::string_view v)
Takes a std::string_view and casts its pointer as a pointer to the parameterized type.
Definition lmdb++.h:1711
static void env_sync(MDB_env *env, bool force)
Definition lmdb++.h:361
static void dbi_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
Definition lmdb++.h:723
static void env_get_flags(MDB_env *env, unsigned int *flags)
Definition lmdb++.h:396
static void txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **txn)
Definition lmdb++.h:550
mdb_mode_t mode
Definition lmdb++.h:39
static std::string_view ptr_to_sv(T *v)
Creates a std::string_view that points to the memory pointed to by v.
Definition lmdb++.h:1691
static void dbi_set_relctx(MDB_txn *txn, MDB_dbi dbi, void *ctx)
Definition lmdb++.h:751