Electroneum
database.h
Go to the documentation of this file.
1 // Copyright (c) 2018, The Monero Project
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without modification, are
5 // permitted provided that the following conditions are met:
6 //
7 // 1. Redistributions of source code must retain the above copyright notice, this list of
8 // conditions and the following disclaimer.
9 //
10 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 // of conditions and the following disclaimer in the documentation and/or other
12 // materials provided with the distribution.
13 //
14 // 3. Neither the name of the copyright holder nor the names of its contributors may be
15 // used to endorse or promote products derived from this software without specific
16 // prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
19 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #pragma once
28 
29 #include <atomic>
30 #include <cstddef>
31 #include <lmdb.h>
32 #include <memory>
33 #include <type_traits>
34 
35 #include "common/expect.h"
36 #include "lmdb/error.h"
37 #include "lmdb/transaction.h"
38 
39 namespace lmdb
40 {
42  struct close_env
43  {
44  void operator()(MDB_env* ptr) const noexcept
45  {
46  if (ptr)
47  mdb_env_close(ptr);
48  }
49  };
50 
51  using environment = std::unique_ptr<MDB_env, close_env>;
52 
54  expect<environment> open_environment(const char* path, MDB_dbi max_dbs) noexcept;
55 
57  struct context
58  {
59  std::atomic<std::size_t> active;
60  std::atomic_flag lock;
61  };
62 
64  class database
65  {
68 
70  MDB_env* handle() const noexcept { return env.get(); }
71 
72  expect<write_txn> do_create_txn(unsigned int flags) noexcept;
73 
74  public:
76 
77  database(database&&) = delete;
78  database(database const&) = delete;
79 
80  virtual ~database() noexcept;
81 
82  database& operator=(database&&) = delete;
83  database& operator=(database const&) = delete;
84 
89  expect<void> resize() noexcept;
90 
92  expect<read_txn> create_read_txn(suspended_txn txn = nullptr) noexcept;
93 
95  expect<suspended_txn> reset_txn(read_txn txn) noexcept;
96 
98  expect<write_txn> create_write_txn() noexcept;
99 
101  expect<void> commit(write_txn txn) noexcept;
102 
112  template<typename F>
113  typename std::result_of<F(MDB_txn&)>::type try_write(F f, unsigned attempts = 3)
114  {
115  for (unsigned i = 0; i < attempts; ++i)
116  {
118  if (!txn)
119  return txn.error();
120 
121  ELECTRONEUM_PRECOND(*txn != nullptr);
122  const auto wrote = f(*(*txn));
123  if (wrote)
124  {
125  ELECTRONEUM_CHECK(commit(std::move(*txn)));
126  return wrote;
127  }
128  if (wrote != lmdb::error(MDB_MAP_FULL))
129  return wrote;
130 
131  txn->reset();
132  ELECTRONEUM_CHECK(this->resize());
133  }
134  return {lmdb::error(MDB_MAP_FULL)};
135  }
136  };
137 } // lmdb
138 
Definition: expect.h:133
std::error_code error() const noexcept
Definition: expect.h:276
Manages a LMDB environment for safe memory-map resizing. Thread-safe.
Definition: database.h:65
database(database const &)=delete
expect< suspended_txn > reset_txn(read_txn txn) noexcept
Definition: database.cpp:166
MDB_env * handle() const noexcept
Definition: database.h:70
expect< void > commit(write_txn txn) noexcept
Commit the read-write transaction.
Definition: database.cpp:179
expect< write_txn > create_write_txn() noexcept
Definition: database.cpp:174
database(database &&)=delete
expect< void > resize() noexcept
Definition: database.cpp:129
virtual ~database() noexcept
Definition: database.cpp:124
context ctx
Definition: database.h:67
expect< read_txn > create_read_txn(suspended_txn txn=nullptr) noexcept
Definition: database.cpp:147
database(environment env)
Definition: database.cpp:113
std::result_of< F(MDB_txn &)>::type try_write(F f, unsigned attempts=3)
Definition: database.h:113
environment env
Definition: database.h:66
expect< write_txn > do_create_txn(unsigned int flags) noexcept
Definition: database.cpp:91
#define ELECTRONEUM_PRECOND(...)
If precondition fails, return ::error::kInvalidArgument in current scope.
Definition: expect.h:39
#define ELECTRONEUM_CHECK(...)
Check expect<void> and return errors in current scope.
Definition: expect.h:47
const
Definition: build_protob.py:9
Definition: database.cpp:46
std::unique_ptr< MDB_txn, abort_txn > suspended_txn
Definition: transaction.h:92
std::unique_ptr< MDB_env, close_env > environment
Definition: database.h:51
std::unique_ptr< MDB_txn, release_read_txn > read_txn
Definition: transaction.h:93
std::unique_ptr< MDB_txn, abort_write_txn > write_txn
Definition: transaction.h:94
error
Tracks LMDB error codes.
Definition: error.h:45
expect< environment > open_environment(const char *path, MDB_dbi max_dbs) noexcept
Definition: database.cpp:78
Definition: blockchain_ancestry.cpp:73
#define F(w, k)
Definition: sha512-blocks.c:61
Closes LMDB environment handle.
Definition: database.h:43
void operator()(MDB_env *ptr) const noexcept
Definition: database.h:44
Context given to LMDB.
Definition: database.h:58
std::atomic< std::size_t > active
Definition: database.h:59
std::atomic_flag lock
Definition: database.h:60