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