Ethereum  PoC-8
The C++ Implementation of Ethereum
RocksDB.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #include "RocksDB.h"
19 #include "Assertions.h"
20 
21 namespace dev
22 {
23 namespace db
24 {
25 namespace
26 {
27 
28 using errinfo_rocksdbStatusCode = boost::error_info<struct tag_rocksdbStatusCode, rocksdb::Status::Code>;
29 using errinfo_rocksdbStatusSubCode = boost::error_info<struct tag_rocksdbStatusSubCode, rocksdb::Status::SubCode>;
30 
31 DatabaseStatus toDatabaseStatus(rocksdb::Status const& _status)
32 {
33  switch (_status.code())
34  {
35  case rocksdb::Status::kOk:
36  return DatabaseStatus::Ok;
37  case rocksdb::Status::kNotFound:
39  case rocksdb::Status::kCorruption:
41  case rocksdb::Status::kNotSupported:
43  case rocksdb::Status::kInvalidArgument:
45  case rocksdb::Status::kIOError:
47  default:
49  }
50 }
51 
52 void checkStatus(rocksdb::Status const& _status, boost::filesystem::path const& _path = {})
53 {
54  if (_status.ok())
55  return;
56 
57  DatabaseError ex;
58  ex << errinfo_dbStatusCode(toDatabaseStatus(_status))
59  << errinfo_rocksdbStatusCode(_status.code())
60  << errinfo_rocksdbStatusSubCode(_status.subcode())
61  << errinfo_dbStatusString(_status.ToString());
62  if (!_path.empty())
63  ex << errinfo_path(_path.string());
64 
65  BOOST_THROW_EXCEPTION(ex);
66 }
67 
68 class RocksDBWriteBatch : public WriteBatchFace
69 {
70 public:
71  void insert(Slice _key, Slice _value) override;
72  void kill(Slice _key) override;
73 
74  rocksdb::WriteBatch const& writeBatch() const { return m_writeBatch; }
75  rocksdb::WriteBatch& writeBatch() { return m_writeBatch; }
76 
77 private:
78  rocksdb::WriteBatch m_writeBatch;
79 };
80 
81 void RocksDBWriteBatch::insert(Slice _key, Slice _value)
82 {
83  auto const status = m_writeBatch.Put(
84  rocksdb::Slice(_key.data(), _key.size()),
85  rocksdb::Slice(_value.data(), _value.size())
86  );
87  checkStatus(status);
88 }
89 
90 void RocksDBWriteBatch::kill(Slice _key)
91 {
92  auto const status = m_writeBatch.Delete(rocksdb::Slice(_key.data(), _key.size()));
93  checkStatus(status);
94 }
95 
96 } // namespace
97 
98 rocksdb::ReadOptions RocksDB::defaultReadOptions()
99 {
100  return rocksdb::ReadOptions();
101 }
102 
103 rocksdb::WriteOptions RocksDB::defaultWriteOptions()
104 {
105  return rocksdb::WriteOptions();
106 }
107 
108 rocksdb::Options RocksDB::defaultDBOptions()
109 {
110  rocksdb::Options options;
111  options.create_if_missing = true;
112  options.max_open_files = 256;
113  return options;
114 }
115 
116 RocksDB::RocksDB(boost::filesystem::path const& _path, rocksdb::ReadOptions _readOptions,
117  rocksdb::WriteOptions _writeOptions, rocksdb::Options _dbOptions)
118  : m_db(nullptr), m_readOptions(std::move(_readOptions)), m_writeOptions(std::move(_writeOptions))
119 {
120  auto db = static_cast<rocksdb::DB*>(nullptr);
121  auto const status = rocksdb::DB::Open(_dbOptions, _path.string(), &db);
122  checkStatus(status, _path);
123 
124  assert(db);
125  m_db.reset(db);
126 }
127 
128 std::string RocksDB::lookup(Slice _key) const
129 {
130  rocksdb::Slice const key(_key.data(), _key.size());
131  std::string value;
132  auto const status = m_db->Get(m_readOptions, key, &value);
133  if (status.IsNotFound())
134  return std::string();
135 
136  checkStatus(status);
137  return value;
138 }
139 
140 bool RocksDB::exists(Slice _key) const
141 {
142  std::string value;
143  rocksdb::Slice const key(_key.data(), _key.size());
144  if (!m_db->KeyMayExist(m_readOptions, key, &value, nullptr))
145  return false;
146 
147  auto const status = m_db->Get(m_readOptions, key, &value);
148  if (status.IsNotFound())
149  return false;
150 
151  checkStatus(status);
152  return true;
153 }
154 
155 void RocksDB::insert(Slice _key, Slice _value)
156 {
157  rocksdb::Slice const key(_key.data(), _key.size());
158  rocksdb::Slice const value(_value.data(), _value.size());
159  auto const status = m_db->Put(m_writeOptions, key, value);
160  checkStatus(status);
161 }
162 
164 {
165  rocksdb::Slice const key(_key.data(), _key.size());
166  auto const status = m_db->Delete(m_writeOptions, key);
167  checkStatus(status);
168 }
169 
170 std::unique_ptr<WriteBatchFace> RocksDB::createWriteBatch() const
171 {
172  return std::unique_ptr<WriteBatchFace>(new RocksDBWriteBatch());
173 }
174 
175 void RocksDB::commit(std::unique_ptr<WriteBatchFace> _batch)
176 {
177  if (!_batch)
178  BOOST_THROW_EXCEPTION(DatabaseError() << errinfo_comment("Cannot commit null batch"));
179 
180  auto* batchPtr = dynamic_cast<RocksDBWriteBatch*>(_batch.get());
181  if (!batchPtr)
182  BOOST_THROW_EXCEPTION(DatabaseError() << errinfo_comment("Invalid batch type passed to rocksdb::commit"));
183 
184  auto const status = m_db->Write(m_writeOptions, &batchPtr->writeBatch());
185  checkStatus(status);
186 }
187 
188 void RocksDB::forEach(std::function<bool(Slice, Slice)> f) const
189 {
190  std::unique_ptr<rocksdb::Iterator> itr(m_db->NewIterator(m_readOptions));
191  if (itr == nullptr)
192  BOOST_THROW_EXCEPTION(DatabaseError() << errinfo_comment("null iterator"));
193 
194  auto keepIterating = true;
195  for (itr->SeekToFirst(); keepIterating && itr->Valid(); itr->Next())
196  {
197  auto const dbKey = itr->key();
198  auto const dbValue = itr->value();
199  Slice const key(dbKey.data(), dbKey.size());
200  Slice const value(dbValue.data(), dbValue.size());
201  keepIterating = f(key, value);
202  }
203 }
204 
205 } // namespace db
206 } // namespace dev
dev::vector_ref
Definition: vector_ref.h:22
dev::db::DatabaseStatus::NotSupported
@ NotSupported
dev::db::errinfo_dbStatusCode
boost::error_info< struct tag_dbStatusCode, DatabaseStatus > errinfo_dbStatusCode
Definition: db.h:86
dev::db::RocksDB::defaultWriteOptions
static rocksdb::WriteOptions defaultWriteOptions()
Definition: RocksDB.cpp:103
dev::db::errinfo_dbStatusString
boost::error_info< struct tag_dbStatusString, std::string > errinfo_dbStatusString
Definition: db.h:87
dev::db::DatabaseStatus::Unknown
@ Unknown
dev::db::RocksDB::forEach
void forEach(std::function< bool(Slice, Slice)> f) const override
Definition: RocksDB.cpp:188
dev::db::RocksDB::defaultDBOptions
static rocksdb::Options defaultDBOptions()
Definition: RocksDB.cpp:108
dev::db::DatabaseStatus::Corruption
@ Corruption
dev::errinfo_path
boost::error_info< struct tag_path, std::string > errinfo_path
Definition: Exceptions.h:96
dev::db::DatabaseStatus::Ok
@ Ok
dev::db::DatabaseStatus::NotFound
@ NotFound
dev::db::RocksDB::RocksDB
RocksDB(boost::filesystem::path const &_path, rocksdb::ReadOptions _readOptions=defaultReadOptions(), rocksdb::WriteOptions _writeOptions=defaultWriteOptions(), rocksdb::Options _dbOptions=defaultDBOptions())
Definition: RocksDB.cpp:116
dev::db::RocksDB::defaultReadOptions
static rocksdb::ReadOptions defaultReadOptions()
Definition: RocksDB.cpp:98
dev::db::RocksDB::kill
void kill(Slice _key) override
Definition: RocksDB.cpp:163
dev::db::RocksDB::createWriteBatch
std::unique_ptr< WriteBatchFace > createWriteBatch() const override
Definition: RocksDB.cpp:170
dev::db::RocksDB::insert
void insert(Slice _key, Slice _value) override
Definition: RocksDB.cpp:155
dev::db::DatabaseStatus::IOError
@ IOError
dev::db::RocksDB::lookup
std::string lookup(Slice _key) const override
Definition: RocksDB.cpp:128
dev::vector_ref::data
_T * data() const
Definition: vector_ref.h:49
dev::vector_ref::size
size_t size() const
Definition: vector_ref.h:53
dev::db::RocksDB::commit
void commit(std::unique_ptr< WriteBatchFace > _batch) override
Definition: RocksDB.cpp:175
dev::db::DatabaseStatus
DatabaseStatus
Definition: db.h:76
Assertions.h
std
Definition: FixedHash.h:393
dev
Definition: Address.cpp:21
RocksDB.h
dev::errinfo_comment
boost::error_info< struct tag_comment, std::string > errinfo_comment
Definition: Assertions.h:69
dev::db::Slice
vector_ref< char const > Slice
Definition: dbfwd.h:26
dev::db::DatabaseStatus::InvalidArgument
@ InvalidArgument
dev::db::RocksDB::exists
bool exists(Slice _key) const override
Definition: RocksDB.cpp:140