Loading...
Searching...
No Matches
leveldb.cpp
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
21
22#include <glog/logging.h>
23
24#include "chain/storage/proto/kv.pb.h"
25
26namespace resdb {
27namespace storage {
28
29std::unique_ptr<Storage> NewResLevelDB(const std::string& path,
30 std::optional<LevelDBInfo> config) {
31 if (config == std::nullopt) {
32 config = LevelDBInfo();
33 }
34 (*config).set_path(path);
35 return std::make_unique<ResLevelDB>(config);
36}
37
38std::unique_ptr<Storage> NewResLevelDB(std::optional<LevelDBInfo> config) {
39 return std::make_unique<ResLevelDB>(config);
40}
41
42ResLevelDB::ResLevelDB(std::optional<LevelDBInfo> 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: "
49 << (*config).path();
50 path = (*config).path();
51 }
52 }
53 CreateDB(path);
54}
55
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_;
63
64 leveldb::DB* db = nullptr;
65 leveldb::Status status = leveldb::DB::Open(options, path, &db);
66 if (status.ok()) {
67 db_ = std::unique_ptr<leveldb::DB>(db);
68 }
69 assert(status.ok());
70 LOG(ERROR) << "Successfully opened LevelDB";
71}
72
74 if (db_) {
75 db_.reset();
76 }
77}
78
79int ResLevelDB::SetValue(const std::string& key, const std::string& value) {
80 batch_.Put(key, value);
81
82 if (batch_.ApproximateSize() >= write_batch_size_) {
83 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch_);
84 if (status.ok()) {
85 batch_.Clear();
86 return 0;
87 } else {
88 LOG(ERROR) << "flush buffer fail:" << status.ToString();
89 return -1;
90 }
91 }
92 return 0;
93}
94
95std::string ResLevelDB::GetValue(const std::string& key) {
96 std::string value = "";
97 leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value);
98 if (status.ok()) {
99 return value;
100 } else {
101 return "";
102 }
103}
104
105std::string ResLevelDB::GetAllValues(void) {
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());
113 }
114 values.append("]");
115
116 delete it;
117 return values;
118}
119
120std::string ResLevelDB::GetRange(const std::string& min_key,
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;
126 it->Next()) {
127 if (!first_iteration) values.append(",");
128 first_iteration = false;
129 values.append(it->value().ToString());
130 }
131 values.append("]");
132
133 delete it;
134 return values;
135}
136
138 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch_);
139 if (status.ok()) {
140 batch_.Clear();
141 return true;
142 }
143 LOG(ERROR) << "flush buffer fail:" << status.ToString();
144 return false;
145}
146
147int ResLevelDB::SetValueWithVersion(const std::string& key,
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";
153 return -2;
154 }
155
156 int last_v = 0;
157 if (history.value_size() > 0) {
158 last_v = history.value(history.value_size() - 1).version();
159 }
160
161 if (last_v != version) {
162 LOG(ERROR) << "version does not match:" << version
163 << " old version:" << last_v;
164 return -2;
165 }
166
167 Value* new_value = history.add_value();
168 new_value->set_value(value);
169 new_value->set_version(version + 1);
170
171 history.SerializeToString(&value_str);
172 return SetValue(key, value_str);
173}
174
175std::pair<std::string, int> ResLevelDB::GetValueWithVersion(
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);
182 }
183 if (history.value_size() == 0) {
184 return std::make_pair("", 0);
185 }
186 if (version > 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());
191 }
192 if (history.value(i).version() < version) {
193 break;
194 }
195 }
196 }
197 int last_idx = history.value_size() - 1;
198 return std::make_pair(history.value(last_idx).value(),
199 history.value(last_idx).version());
200}
201
202// Return a map of <key, <value, version>>
203std::map<std::string, std::pair<std::string, int>> ResLevelDB::GetAllItems() {
204 std::map<std::string, std::pair<std::string, int>> resp;
205
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";
212 continue;
213 }
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())));
217 }
218 delete it;
219
220 return resp;
221}
222
223std::map<std::string, std::pair<std::string, int>> ResLevelDB::GetKeyRange(
224 const std::string& min_key, const std::string& max_key) {
225 std::map<std::string, std::pair<std::string, int>> resp;
226
227 leveldb::Iterator* it = db_->NewIterator(leveldb::ReadOptions());
228 for (it->Seek(min_key); it->Valid() && it->key().ToString() <= max_key;
229 it->Next()) {
230 ValueHistory history;
231 if (!history.ParseFromString(it->value().ToString()) ||
232 history.value_size() == 0) {
233 LOG(ERROR) << "old_value parse fail";
234 continue;
235 }
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())));
239 }
240 delete it;
241
242 return resp;
243}
244
245// Return a list of <value, version>
246std::vector<std::pair<std::string, int>> ResLevelDB::GetHistory(
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";
253 return resp;
254 }
255
256 for (int i = history.value_size() - 1; i >= 0; --i) {
257 if (history.value(i).version() < min_version) {
258 break;
259 }
260 if (history.value(i).version() <= max_version) {
261 resp.push_back(
262 std::make_pair(history.value(i).value(), history.value(i).version()));
263 }
264 }
265
266 return resp;
267}
268
269// Return a list of <value, version>
270std::vector<std::pair<std::string, int>> ResLevelDB::GetTopHistory(
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";
277 return resp;
278 }
279
280 for (int i = history.value_size() - 1;
281 i >= 0 && resp.size() < static_cast<size_t>(top_number); --i) {
282 resp.push_back(
283 std::make_pair(history.value(i).value(), history.value(i).version()));
284 }
285
286 return resp;
287}
288
289} // namespace storage
290} // namespace resdb
std::map< std::string, std::pair< std::string, int > > GetKeyRange(const std::string &min_key, const std::string &max_key) override
Definition leveldb.cpp:223
std::string GetAllValues(void) override
Definition leveldb.cpp:105
std::map< std::string, std::pair< std::string, int > > GetAllItems() override
Definition leveldb.cpp:203
std::vector< std::pair< std::string, int > > GetTopHistory(const std::string &key, int top_number) override
Definition leveldb.cpp:270
ResLevelDB(std::optional< LevelDBInfo > config_data=std::nullopt)
Definition leveldb.cpp:42
std::vector< std::pair< std::string, int > > GetHistory(const std::string &key, int min_version, int max_version) override
Definition leveldb.cpp:246
std::pair< std::string, int > GetValueWithVersion(const std::string &key, int version) override
Definition leveldb.cpp:175
int SetValue(const std::string &key, const std::string &value) override
Definition leveldb.cpp:79
std::string GetRange(const std::string &min_key, const std::string &max_key) override
Definition leveldb.cpp:120
int SetValueWithVersion(const std::string &key, const std::string &value, int version) override
Definition leveldb.cpp:147
std::string GetValue(const std::string &key) override
Definition leveldb.cpp:95
bool Flush() override
Definition leveldb.cpp:137
std::unique_ptr< Storage > storage
std::unique_ptr< Storage > NewResLevelDB(const std::string &path, std::optional< LevelDBInfo > config)
Definition leveldb.cpp:29