Loading...
Searching...
No Matches
rocksdb.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> NewResRocksDB(const std::string& path,
30 std::optional<RocksDBInfo> config) {
31 if (config == std::nullopt) {
32 config = RocksDBInfo();
33 }
34 (*config).set_path(path);
35 return std::make_unique<ResRocksDB>(config);
36}
37
38std::unique_ptr<Storage> NewResRocksDB(std::optional<RocksDBInfo> config) {
39 return std::make_unique<ResRocksDB>(config);
40}
41
42ResRocksDB::ResRocksDB(std::optional<RocksDBInfo> config) {
43 std::string path = "/tmp/nexres-rocksdb";
44 if (config.has_value()) {
45 num_threads_ = (*config).num_threads();
46 write_buffer_size_ = (*config).write_buffer_size_mb() << 20;
47 write_batch_size_ = (*config).write_batch_size();
48 if ((*config).path() != "") {
49 LOG(ERROR) << "Custom path for RocksDB provided in config: "
50 << (*config).path();
51 path = (*config).path();
52 }
53 }
54 CreateDB(path);
55}
56
57void ResRocksDB::CreateDB(const std::string& path) {
58 rocksdb::Options options;
59 options.create_if_missing = true;
60 if (num_threads_ > 1) options.IncreaseParallelism(num_threads_);
61 options.OptimizeLevelStyleCompaction();
62 options.write_buffer_size = write_buffer_size_;
63
64 rocksdb::DB* db = nullptr;
65 rocksdb::Status status = rocksdb::DB::Open(options, path, &db);
66 if (status.ok()) {
67 db_ = std::unique_ptr<rocksdb::DB>(db);
68 LOG(ERROR) << "Successfully opened RocksDB in path: " << path;
69 } else {
70 LOG(ERROR) << "RocksDB status fail";
71 }
72 assert(status.ok());
73 LOG(ERROR) << "Successfully opened RocksDB";
74}
75
77 if (db_) {
78 db_.reset();
79 }
80}
81
82int ResRocksDB::SetValue(const std::string& key, const std::string& value) {
83 batch_.Put(key, value);
84
85 if (batch_.Count() >= write_batch_size_) {
86 rocksdb::Status status = db_->Write(rocksdb::WriteOptions(), &batch_);
87 if (status.ok()) {
88 batch_.Clear();
89 } else {
90 LOG(ERROR) << "write value fail:" << status.ToString();
91 return -1;
92 }
93 }
94 return 0;
95}
96
97std::string ResRocksDB::GetValue(const std::string& key) {
98 std::string value = "";
99 rocksdb::Status status = db_->Get(rocksdb::ReadOptions(), key, &value);
100 if (status.ok()) {
101 return value;
102 } else {
103 return "";
104 }
105}
106
107std::string ResRocksDB::GetAllValues(void) {
108 std::string values = "[";
109 rocksdb::Iterator* itr = db_->NewIterator(rocksdb::ReadOptions());
110 bool first_iteration = true;
111 for (itr->SeekToFirst(); itr->Valid(); itr->Next()) {
112 if (!first_iteration) values.append(",");
113 first_iteration = false;
114 values.append(itr->value().ToString());
115 }
116 values.append("]");
117
118 delete itr;
119 return values;
120}
121
122std::string ResRocksDB::GetRange(const std::string& min_key,
123 const std::string& max_key) {
124 std::string values = "[";
125 rocksdb::Iterator* itr = db_->NewIterator(rocksdb::ReadOptions());
126 bool first_iteration = true;
127 for (itr->Seek(min_key); itr->Valid() && itr->key().ToString() <= max_key;
128 itr->Next()) {
129 if (!first_iteration) values.append(",");
130 first_iteration = false;
131 values.append(itr->value().ToString());
132 }
133 values.append("]");
134
135 delete itr;
136 return values;
137}
138
140 rocksdb::Status status = db_->Write(rocksdb::WriteOptions(), &batch_);
141 if (status.ok()) {
142 batch_.Clear();
143 return true;
144 }
145 LOG(ERROR) << "write value fail:" << status.ToString();
146 return false;
147}
148int ResRocksDB::SetValueWithVersion(const std::string& key,
149 const std::string& value, int version) {
150 std::string value_str = GetValue(key);
151 ValueHistory history;
152 if (!history.ParseFromString(value_str)) {
153 LOG(ERROR) << "old_value parse fail";
154 return -2;
155 }
156
157 int last_v = 0;
158 if (history.value_size() > 0) {
159 last_v = history.value(history.value_size() - 1).version();
160 }
161
162 if (last_v != version) {
163 LOG(ERROR) << "version does not match:" << version
164 << " old version:" << last_v;
165 return -2;
166 }
167
168 Value* new_value = history.add_value();
169 new_value->set_value(value);
170 new_value->set_version(version + 1);
171
172 history.SerializeToString(&value_str);
173 return SetValue(key, value_str);
174}
175
176std::pair<std::string, int> ResRocksDB::GetValueWithVersion(
177 const std::string& key, int version) {
178 std::string value_str = GetValue(key);
179 ValueHistory history;
180 if (!history.ParseFromString(value_str)) {
181 LOG(ERROR) << "old_value parse fail";
182 return std::make_pair("", 0);
183 }
184 if (history.value_size() == 0) {
185 return std::make_pair("", 0);
186 }
187 if (version > 0) {
188 for (int i = history.value_size() - 1; i >= 0; --i) {
189 if (history.value(i).version() == version) {
190 return std::make_pair(history.value(i).value(),
191 history.value(i).version());
192 }
193 if (history.value(i).version() < version) {
194 break;
195 }
196 }
197 }
198 int last_idx = history.value_size() - 1;
199 return std::make_pair(history.value(last_idx).value(),
200 history.value(last_idx).version());
201}
202
203// Return a map of <key, <value, version>>
204std::map<std::string, std::pair<std::string, int>> ResRocksDB::GetAllItems() {
205 std::map<std::string, std::pair<std::string, int>> resp;
206
207 rocksdb::Iterator* it = db_->NewIterator(rocksdb::ReadOptions());
208 for (it->SeekToFirst(); it->Valid(); it->Next()) {
209 ValueHistory history;
210 if (!history.ParseFromString(it->value().ToString()) ||
211 history.value_size() == 0) {
212 LOG(ERROR) << "old_value parse fail";
213 continue;
214 }
215 const Value& value = history.value(history.value_size() - 1);
216 resp.insert(std::make_pair(it->key().ToString(),
217 std::make_pair(value.value(), value.version())));
218 }
219 delete it;
220
221 return resp;
222}
223
224std::map<std::string, std::pair<std::string, int>> ResRocksDB::GetKeyRange(
225 const std::string& min_key, const std::string& max_key) {
226 std::map<std::string, std::pair<std::string, int>> resp;
227
228 rocksdb::Iterator* it = db_->NewIterator(rocksdb::ReadOptions());
229 for (it->Seek(min_key); it->Valid() && it->key().ToString() <= max_key;
230 it->Next()) {
231 ValueHistory history;
232 if (!history.ParseFromString(it->value().ToString()) ||
233 history.value_size() == 0) {
234 LOG(ERROR) << "old_value parse fail";
235 continue;
236 }
237 const Value& value = history.value(history.value_size() - 1);
238 resp.insert(std::make_pair(it->key().ToString(),
239 std::make_pair(value.value(), value.version())));
240 }
241 delete it;
242
243 return resp;
244}
245
246// Return a list of <value, version>
247std::vector<std::pair<std::string, int>> ResRocksDB::GetHistory(
248 const std::string& key, int min_version, int max_version) {
249 std::vector<std::pair<std::string, int>> resp;
250 std::string value_str = GetValue(key);
251 ValueHistory history;
252 if (!history.ParseFromString(value_str)) {
253 LOG(ERROR) << "old_value parse fail";
254 return resp;
255 }
256
257 for (int i = history.value_size() - 1; i >= 0; --i) {
258 if (history.value(i).version() < min_version) {
259 break;
260 }
261 if (history.value(i).version() <= max_version) {
262 resp.push_back(
263 std::make_pair(history.value(i).value(), history.value(i).version()));
264 }
265 }
266
267 return resp;
268}
269
270// Return a list of <value, version>
271std::vector<std::pair<std::string, int>> ResRocksDB::GetTopHistory(
272 const std::string& key, int top_number) {
273 std::vector<std::pair<std::string, int>> resp;
274 std::string value_str = GetValue(key);
275 ValueHistory history;
276 if (!history.ParseFromString(value_str)) {
277 LOG(ERROR) << "old_value parse fail";
278 return resp;
279 }
280
281 for (int i = history.value_size() - 1;
282 i >= 0 && resp.size() < static_cast<size_t>(top_number); --i) {
283 resp.push_back(
284 std::make_pair(history.value(i).value(), history.value(i).version()));
285 }
286
287 return resp;
288}
289
290} // namespace storage
291} // namespace resdb
std::pair< std::string, int > GetValueWithVersion(const std::string &key, int version) override
Definition rocksdb.cpp:176
int SetValue(const std::string &key, const std::string &value) override
Definition rocksdb.cpp:82
std::map< std::string, std::pair< std::string, int > > GetKeyRange(const std::string &min_key, const std::string &max_key) override
Definition rocksdb.cpp:224
std::vector< std::pair< std::string, int > > GetHistory(const std::string &key, int min_version, int max_version) override
Definition rocksdb.cpp:247
int SetValueWithVersion(const std::string &key, const std::string &value, int version) override
Definition rocksdb.cpp:148
bool Flush() override
Definition rocksdb.cpp:139
std::string GetValue(const std::string &key) override
Definition rocksdb.cpp:97
std::string GetAllValues(void) override
Definition rocksdb.cpp:107
ResRocksDB(std::optional< RocksDBInfo > config_data=std::nullopt)
Definition rocksdb.cpp:42
std::vector< std::pair< std::string, int > > GetTopHistory(const std::string &key, int top_number) override
Definition rocksdb.cpp:271
std::string GetRange(const std::string &min_key, const std::string &max_key) override
Definition rocksdb.cpp:122
std::map< std::string, std::pair< std::string, int > > GetAllItems() override
Definition rocksdb.cpp:204
std::unique_ptr< Storage > storage
std::unique_ptr< Storage > NewResRocksDB(const std::string &path, std::optional< RocksDBInfo > config)
Definition rocksdb.cpp:29