22#include <glog/logging.h>
24#include "chain/storage/proto/kv.pb.h"
30 std::optional<LevelDBInfo> config) {
31 if (config == std::nullopt) {
32 config = LevelDBInfo();
34 (*config).set_path(path);
35 return std::make_unique<ResLevelDB>(config);
38std::unique_ptr<Storage>
NewResLevelDB(std::optional<LevelDBInfo> config) {
39 return std::make_unique<ResLevelDB>(config);
43 std::string path =
"/tmp/nexres-leveldb";
44 if (config.has_value()) {
45 write_buffer_size_ = (*config).write_buffer_size_mb() << 20;
46 write_batch_size_ = (*config).write_batch_size();
47 if (!(*config).path().empty()) {
48 LOG(ERROR) <<
"Custom path for ResLevelDB provided in config: "
50 path = (*config).path();
56void ResLevelDB::CreateDB(
const std::string& path) {
57 LOG(ERROR) <<
"ResLevelDB Create DB: path:" << path
58 <<
" write buffer size:" << write_buffer_size_
59 <<
" batch size:" << write_batch_size_;
60 leveldb::Options options;
61 options.create_if_missing =
true;
62 options.write_buffer_size = write_buffer_size_;
64 leveldb::DB* db =
nullptr;
65 leveldb::Status status = leveldb::DB::Open(options, path, &db);
67 db_ = std::unique_ptr<leveldb::DB>(db);
70 LOG(ERROR) <<
"Successfully opened LevelDB";
80 batch_.Put(key, value);
82 if (batch_.ApproximateSize() >= write_batch_size_) {
83 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch_);
88 LOG(ERROR) <<
"flush buffer fail:" << status.ToString();
96 std::string value =
"";
97 leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value);
106 std::string values =
"[";
107 leveldb::Iterator* it = db_->NewIterator(leveldb::ReadOptions());
108 bool first_iteration =
true;
109 for (it->SeekToFirst(); it->Valid(); it->Next()) {
110 if (!first_iteration) values.append(
",");
111 first_iteration =
false;
112 values.append(it->value().ToString());
121 const std::string& max_key) {
122 std::string values =
"[";
123 leveldb::Iterator* it = db_->NewIterator(leveldb::ReadOptions());
124 bool first_iteration =
true;
125 for (it->Seek(min_key); it->Valid() && it->key().ToString() <= max_key;
127 if (!first_iteration) values.append(
",");
128 first_iteration =
false;
129 values.append(it->value().ToString());
138 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch_);
143 LOG(ERROR) <<
"flush buffer fail:" << status.ToString();
148 const std::string& value,
int version) {
149 std::string value_str =
GetValue(key);
150 ValueHistory history;
151 if (!history.ParseFromString(value_str)) {
152 LOG(ERROR) <<
"old_value parse fail";
157 if (history.value_size() > 0) {
158 last_v = history.value(history.value_size() - 1).version();
161 if (last_v != version) {
162 LOG(ERROR) <<
"version does not match:" << version
163 <<
" old version:" << last_v;
167 Value* new_value = history.add_value();
168 new_value->set_value(value);
169 new_value->set_version(version + 1);
171 history.SerializeToString(&value_str);
176 const std::string& key,
int version) {
177 std::string value_str =
GetValue(key);
178 ValueHistory history;
179 if (!history.ParseFromString(value_str)) {
180 LOG(ERROR) <<
"old_value parse fail";
181 return std::make_pair(
"", 0);
183 if (history.value_size() == 0) {
184 return std::make_pair(
"", 0);
187 for (
int i = history.value_size() - 1; i >= 0; --i) {
188 if (history.value(i).version() == version) {
189 return std::make_pair(history.value(i).value(),
190 history.value(i).version());
192 if (history.value(i).version() < version) {
197 int last_idx = history.value_size() - 1;
198 return std::make_pair(history.value(last_idx).value(),
199 history.value(last_idx).version());
204 std::map<std::string, std::pair<std::string, int>> resp;
206 leveldb::Iterator* it = db_->NewIterator(leveldb::ReadOptions());
207 for (it->SeekToFirst(); it->Valid(); it->Next()) {
208 ValueHistory history;
209 if (!history.ParseFromString(it->value().ToString()) ||
210 history.value_size() == 0) {
211 LOG(ERROR) <<
"old_value parse fail";
214 const Value& value = history.value(history.value_size() - 1);
215 resp.insert(std::make_pair(it->key().ToString(),
216 std::make_pair(value.value(), value.version())));
224 const std::string& min_key,
const std::string& max_key) {
225 std::map<std::string, std::pair<std::string, int>> resp;
227 leveldb::Iterator* it = db_->NewIterator(leveldb::ReadOptions());
228 for (it->Seek(min_key); it->Valid() && it->key().ToString() <= max_key;
230 ValueHistory history;
231 if (!history.ParseFromString(it->value().ToString()) ||
232 history.value_size() == 0) {
233 LOG(ERROR) <<
"old_value parse fail";
236 const Value& value = history.value(history.value_size() - 1);
237 resp.insert(std::make_pair(it->key().ToString(),
238 std::make_pair(value.value(), value.version())));
247 const std::string& key,
int min_version,
int max_version) {
248 std::vector<std::pair<std::string, int>> resp;
249 std::string value_str =
GetValue(key);
250 ValueHistory history;
251 if (!history.ParseFromString(value_str)) {
252 LOG(ERROR) <<
"old_value parse fail";
256 for (
int i = history.value_size() - 1; i >= 0; --i) {
257 if (history.value(i).version() < min_version) {
260 if (history.value(i).version() <= max_version) {
262 std::make_pair(history.value(i).value(), history.value(i).version()));
271 const std::string& key,
int top_number) {
272 std::vector<std::pair<std::string, int>> resp;
273 std::string value_str =
GetValue(key);
274 ValueHistory history;
275 if (!history.ParseFromString(value_str)) {
276 LOG(ERROR) <<
"old_value parse fail";
280 for (
int i = history.value_size() - 1;
281 i >= 0 && resp.size() <
static_cast<size_t>(top_number); --i) {
283 std::make_pair(history.value(i).value(), history.value(i).version()));
std::map< std::string, std::pair< std::string, int > > GetKeyRange(const std::string &min_key, const std::string &max_key) override
std::string GetAllValues(void) override
std::map< std::string, std::pair< std::string, int > > GetAllItems() override
std::vector< std::pair< std::string, int > > GetTopHistory(const std::string &key, int top_number) override
ResLevelDB(std::optional< LevelDBInfo > config_data=std::nullopt)
std::vector< std::pair< std::string, int > > GetHistory(const std::string &key, int min_version, int max_version) override
std::pair< std::string, int > GetValueWithVersion(const std::string &key, int version) override
int SetValue(const std::string &key, const std::string &value) override
std::string GetRange(const std::string &min_key, const std::string &max_key) override
int SetValueWithVersion(const std::string &key, const std::string &value, int version) override
std::string GetValue(const std::string &key) override
std::unique_ptr< Storage > storage
std::unique_ptr< Storage > NewResLevelDB(const std::string &path, std::optional< LevelDBInfo > config)