Electroneum
table.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <utility>
4 
5 #include "common/expect.h"
6 #include "lmdb/error.h"
7 #include "lmdb/key_stream.h"
8 #include "lmdb/util.h"
9 #include "lmdb/value_stream.h"
10 
11 namespace lmdb
12 {
14  struct table
15  {
16  char const* const name;
17  const unsigned flags;
20 
22  expect<MDB_dbi> open(MDB_txn& write_txn) const noexcept;
23  };
24 
26  template<typename K, typename V>
27  struct basic_table : table
28  {
29  using key_type = K;
30  using value_type = V;
31 
33  static constexpr unsigned compute_flags(const unsigned flags) noexcept
34  {
35  return flags | ((flags & MDB_DUPSORT) ? MDB_DUPFIXED : 0);
36  }
37 
38  constexpr explicit basic_table(const char* name, unsigned flags = 0, MDB_cmp_func value_cmp = nullptr) noexcept
39  : table{name, compute_flags(flags), &lmdb::less<lmdb::native_type<K>>, value_cmp}
40  {}
41 
54  template<typename U, typename F = U, std::size_t offset = 0>
55  static expect<F> get_value(MDB_val value) noexcept
56  {
57  static_assert(std::is_same<U, V>(), "bad ELECTRONEUM_FIELD?");
58  static_assert(std::is_pod<F>(), "F must be POD");
59  static_assert(sizeof(F) + offset <= sizeof(U), "bad field type and/or offset");
60 
61  if (value.mv_size != sizeof(U))
62  return {lmdb::error(MDB_BAD_VALSIZE)};
63 
64  F out;
65  std::memcpy(std::addressof(out), static_cast<char*>(value.mv_data) + offset, sizeof(out));
66  return out;
67  }
68 
76  template<typename D>
78  static get_key_stream(std::unique_ptr<MDB_cursor, D> cur) noexcept
79  {
80  ELECTRONEUM_PRECOND(cur != nullptr);
81 
82  MDB_val key;
83  MDB_val value;
84  const int err = mdb_cursor_get(cur.get(), &key, &value, MDB_FIRST);
85  if (err)
86  {
87  if (err != MDB_NOTFOUND)
88  return {lmdb::error(err)};
89  cur.reset(); // return empty set
90  }
91  return key_stream<K, V, D>{std::move(cur)};
92  }
93 
101  template<typename D>
103  static get_value_stream(K const& key, std::unique_ptr<MDB_cursor, D> cur) noexcept
104  {
105  ELECTRONEUM_PRECOND(cur != nullptr);
106 
107  MDB_val key_bytes = lmdb::to_val(key);
108  MDB_val value;
109  const int err = mdb_cursor_get(cur.get(), &key_bytes, &value, MDB_SET);
110  if (err)
111  {
112  if (err != MDB_NOTFOUND)
113  return {lmdb::error(err)};
114  cur.reset(); // return empty set
115  }
116  return value_stream<V, D>{std::move(cur)};
117  }
118  };
119 } // lmdb
120 
#define MDB_NOTFOUND
Definition: lmdb.h:439
const unsigned flags
Definition: table.h:17
MDB_cmp_func *const key_cmp
Definition: table.h:18
static constexpr unsigned compute_flags(const unsigned flags) noexcept
Definition: table.h:33
int() MDB_cmp_func(const MDB_val *a, const MDB_val *b)
A callback function used to compare two keys in a database.
Definition: lmdb.h:292
const char * key
Definition: hmac_keccak.cpp:39
#define MDB_BAD_VALSIZE
Definition: lmdb.h:480
std::unique_ptr< MDB_txn, abort_write_txn > write_txn
Definition: transaction.h:94
MDB_cmp_func *const value_cmp
Definition: table.h:19
static expect< F > get_value(MDB_val value) noexcept
Definition: table.h:55
struct MDB_txn MDB_txn
Opaque structure for a transaction handle.
Definition: lmdb.h:267
char const *const name
Definition: table.h:16
static expect< key_stream< K, V, D > > get_key_stream(std::unique_ptr< MDB_cursor, D > cur) noexcept
Definition: table.h:78
constexpr basic_table(const char *name, unsigned flags=0, MDB_cmp_func value_cmp=nullptr) noexcept
Definition: table.h:38
Definition: expect.h:70
Definition: lmdb.h:422
Helper for grouping typical LMDB DBI options when key and value are fixed types.
Definition: table.h:27
#define MDB_DUPFIXED
Definition: lmdb.h:351
int mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data, MDB_cursor_op op)
Retrieve by cursor.
Generic structure used for passing keys and data in and out of the database.
Definition: lmdb.h:286
const T & move(const T &t)
Definition: gtest-port.h:1317
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
void * memcpy(void *a, const void *b, size_t c)
#define ELECTRONEUM_PRECOND(...)
If precondition fails, return ::error::kInvalidArgument in current scope.
Definition: expect.h:39
MDB_val to_val(T &&value) noexcept
Definition: util.h:88
#define F(s)
Helper for grouping typical LMDB DBI options.
Definition: table.h:14
static expect< value_stream< V, D > > get_value_stream(K const &key, std::unique_ptr< MDB_cursor, D > cur) noexcept
Definition: table.h:103
#define MDB_DUPSORT
Definition: lmdb.h:345
error
Tracks LMDB error codes.
Definition: error.h:44
expect< MDB_dbi > open(MDB_txn &write_txn) const noexcept
Definition: table.cpp:31