Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
lmdb_store.cpp
Go to the documentation of this file.
7#include "lmdb.h"
8#include <algorithm>
9#include <cstdint>
10#include <memory>
11#include <mutex>
12#include <optional>
13#include <set>
14#include <stdexcept>
15
16namespace bb::lmdblib {
17LMDBStore::LMDBStore(std::string directory, uint64_t mapSizeKb, uint64_t maxNumReaders, uint64_t maxDbs)
18 : LMDBStoreBase(std::move(directory), mapSizeKb, maxNumReaders, maxDbs)
19{}
20
21void LMDBStore::open_database(const std::string& name, bool duplicateKeysPermitted)
22{
24 {
26 try {
27 db = std::make_shared<LMDBDatabase>(_environment, *tx, name, false, false, duplicateKeysPermitted);
28 tx->commit();
29 } catch (std::exception& e) {
30 tx->try_abort();
31 throw std::runtime_error(format("Unable to create database: ", name, " Error: ", e.what()));
32 }
33 }
34 // if we are here then we successfully created the database
36 databases[name] = db;
37}
38
39void LMDBStore::close_database(const std::string& name)
40{
42 {
44 const auto it = databases.find(name);
45 if (it == databases.end()) {
46 throw std::runtime_error(format("Database ", name, " not found"));
47 }
48 db = it->second;
49 databases.erase(it);
50 }
51}
52
54{
56 const auto it = databases.find(name);
57 if (it == databases.end()) {
58 throw std::runtime_error(format("Database ", name, " not found"));
59 }
60 return it->second;
61}
62
64{
67 dbs.reserve(databases.size());
68 for (const auto& db : databases) {
69 dbs.push_back(db.second);
70 }
71 return dbs;
72}
73
75{
78 dbs.reserve(puts.size());
79 for (const auto& p : puts) {
80 const auto it = databases.find(p.name);
81 if (it == databases.end()) {
82 throw std::runtime_error(format("Database ", p.name, " not found"));
83 }
84 dbs.push_back(it->second);
85 }
86 return dbs;
87}
88
90{
93 for (const auto& db : dbs) {
94 stats.push_back(db->get_stats(*tx));
95 }
96 return { _environment->get_map_size(), _environment->get_data_file_size() };
97}
98
100{
103 try {
104 for (size_t i = 0; i < data.size(); i++) {
105 put(data[i].toWrite, data[i].toDelete, *dbs[i], *tx);
106 }
107 tx->commit();
108 } catch (std::exception& e) {
109 tx->try_abort();
110 throw std::runtime_error(format("Failed to commit data", " Error: ", e.what()));
111 }
112}
113
114void LMDBStore::get(KeysVector& keys, OptionalValuesVector& values, const std::string& name)
115{
116 get(keys, values, get_database(name));
117}
118
120 KeyOptionalValuesVector& toDelete,
121 const LMDBDatabase& db,
123{
124 for (auto& kd : toWrite) {
125 for (auto& p : kd.second) {
126 tx.put_value(kd.first, p, db);
127 }
128 }
129 for (auto& kd : toDelete) {
130 if (!kd.second.has_value()) {
131 tx.delete_value(kd.first, db);
132 continue;
133 }
134 for (auto& p : kd.second.value()) {
135 tx.delete_value(kd.first, p, db);
136 }
137 }
138}
140{
141 values.reserve(keys.size());
143 if (!db->duplicate_keys_permitted()) {
144 const LMDBDatabase& dbRef = *db;
145 for (auto& k : keys) {
147 Value value;
148 bool result = tx->get_value(k, value, dbRef);
150 values.emplace_back(optional);
151 }
152 return;
153 }
154 {
155 Cursor::Ptr cursor = std::make_unique<Cursor>(tx, db, _environment->getNextId());
156 for (auto& k : keys) {
157 if (!cursor->set_at_key(k)) {
158 values.emplace_back(std::nullopt);
159 continue;
160 }
162 cursor->read_next(1, keyValuePairs);
163 if (keyValuePairs.empty()) {
164 // this shouldn't happen but return the null optional anyway
165 values.emplace_back(std::nullopt);
166 continue;
167 }
169 values.reserve(keyValuePairs.size());
170 for (auto& kv : keyValuePairs) {
171 for (auto& vals : kv.second) {
172 retrievedValues.push_back(std::move(vals));
173 }
174 }
176 values.emplace_back(optionalValues);
177 }
178 }
179}
180
181void LMDBStore::has(const KeyOptionalValuesVector& entries, std::vector<bool>& results, const std::string& name)
182{
183 auto string_cmp = [](const Key& a, const Key& b) {
184 return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
185 };
186
187 std::set<Key, decltype(string_cmp)> key_set(string_cmp);
188 for (const auto& entry : entries) {
189 key_set.insert(entry.first);
190 }
191
192 KeysVector keys(key_set.begin(), key_set.end());
194 get(keys, vals, name);
195
196 results.reserve(entries.size());
197
198 for (const auto& entry : entries) {
199 const auto& key = entry.first;
200 const auto& requested_values = entry.second;
201
202 const auto key_it = std::find(keys.begin(), keys.end(), key);
203 if (key_it == keys.end()) {
204 results.push_back(false);
205 continue;
206 }
207
208 const auto& values = vals[static_cast<size_t>(key_it - keys.begin())];
209
210 if (!values.has_value()) {
211 results.push_back(false);
212 continue;
213 }
214
215 if (!requested_values.has_value()) {
216 results.push_back(true);
217 continue;
218 }
219
220 results.push_back(std::all_of(requested_values->begin(), requested_values->end(), [&](const auto& val) {
221 return std::find(values->begin(), values->end(), val) != values->end();
222 }));
223 }
224}
225
227{
229 return std::make_unique<Cursor>(tx, db, _environment->getNextId());
230}
231} // namespace bb::lmdblib
std::unique_ptr< LMDBCursor > Ptr
std::unique_ptr< LMDBDatabaseCreationTransaction > Ptr
std::shared_ptr< LMDBDatabase > SharedPtr
std::shared_ptr< LMDBReadTransaction > SharedPtr
LMDBEnvironment::SharedPtr _environment
LMDBDatabaseCreationTransaction::Ptr create_db_transaction() const
WriteTransaction::Ptr create_write_transaction() const
ReadTransaction::Ptr create_read_transaction() const
std::vector< Database::SharedPtr > get_databases() const
Database::SharedPtr get_database(const std::string &name)
void open_database(const std::string &name, bool duplicateKeysPermitted=false)
std::pair< uint64_t, uint64_t > get_stats(std::vector< DBStats > &stats) const
void close_database(const std::string &name)
LMDBStore(std::string directory, uint64_t mapSizeKb, uint64_t maxNumReaders, uint64_t maxDbs)
void put(std::vector< PutData > &data)
std::unordered_map< std::string, LMDBDatabase::SharedPtr > databases
void has(const KeyOptionalValuesVector &entries, std::vector< bool > &results, const std::string &name)
Cursor::Ptr create_cursor(ReadTransaction::SharedPtr tx, const std::string &dbName)
void get(KeysVector &keys, OptionalValuesVector &values, const std::string &name)
std::unique_ptr< LMDBWriteTransaction > Ptr
void put_value(T &key, Value &data, const LMDBDatabase &db)
void delete_value(T &key, const LMDBDatabase &db)
std::string format(Args... args)
Definition log.hpp:23
const std::vector< MemoryValue > data
FF a
FF b
std::vector< Key > KeysVector
Definition types.hpp:13
std::vector< uint8_t > Key
Definition types.hpp:11
std::vector< uint8_t > Value
Definition types.hpp:12
std::vector< KeyValuesPair > KeyDupValuesVector
Definition types.hpp:18
std::vector< OptionalValues > OptionalValuesVector
Definition types.hpp:17
std::vector< Value > ValuesVector
Definition types.hpp:14
std::vector< KeyOptionalValuesPair > KeyOptionalValuesVector
Definition types.hpp:20
std::optional< ValuesVector > OptionalValues
Definition types.hpp:16
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13