/Users/deen/code/yugabyte-db/src/yb/rocksdb/tools/ldb_cmd.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under the BSD-style license found in the |
3 | | // LICENSE file in the root directory of this source tree. An additional grant |
4 | | // of patent rights can be found in the PATENTS file in the same directory. |
5 | | // |
6 | | // The following only applies to changes made to this file as part of YugaByte development. |
7 | | // |
8 | | // Portions Copyright (c) YugaByte, Inc. |
9 | | // |
10 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
11 | | // in compliance with the License. You may obtain a copy of the License at |
12 | | // |
13 | | // http://www.apache.org/licenses/LICENSE-2.0 |
14 | | // |
15 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
16 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
17 | | // or implied. See the License for the specific language governing permissions and limitations |
18 | | // under the License. |
19 | | // |
20 | | #ifndef YB_ROCKSDB_TOOLS_LDB_CMD_H |
21 | | #define YB_ROCKSDB_TOOLS_LDB_CMD_H |
22 | | |
23 | | #pragma once |
24 | | |
25 | | #ifndef ROCKSDB_LITE |
26 | | |
27 | | #include <stdlib.h> |
28 | | #include <stdio.h> |
29 | | |
30 | | #include <string> |
31 | | #include <iostream> |
32 | | #include <sstream> |
33 | | #include <algorithm> |
34 | | #include <vector> |
35 | | #include <map> |
36 | | |
37 | | #include "yb/encryption/header_manager_impl.h" |
38 | | #include "yb/encryption/universe_key_manager.h" |
39 | | |
40 | | #include "yb/rocksdb/db/version_set.h" |
41 | | #include "yb/rocksdb/env.h" |
42 | | #include "yb/rocksdb/iterator.h" |
43 | | #include "yb/rocksdb/ldb_tool.h" |
44 | | #include "yb/rocksdb/options.h" |
45 | | #include "yb/rocksdb/utilities/db_ttl.h" |
46 | | #include "yb/rocksdb/tools/ldb_cmd_execute_result.h" |
47 | | #include "yb/rocksdb/util/logging.h" |
48 | | #include "yb/rocksdb/utilities/ttl/db_ttl_impl.h" |
49 | | #include "yb/util/slice.h" |
50 | | #include "yb/util/string_util.h" |
51 | | #include "yb/rocksutil/rocksdb_encrypted_file_factory.h" |
52 | | |
53 | | using std::string; |
54 | | using std::map; |
55 | | using std::vector; |
56 | | using std::ostringstream; |
57 | | |
58 | | namespace rocksdb { |
59 | | |
60 | | class LDBCommand { |
61 | | public: |
62 | | // Command-line arguments |
63 | | static const string ARG_DB; |
64 | | static const string ARG_PATH; |
65 | | static const string ARG_HEX; |
66 | | static const string ARG_KEY_HEX; |
67 | | static const string ARG_VALUE_HEX; |
68 | | static const string ARG_CF_NAME; |
69 | | static const string ARG_TTL; |
70 | | static const string ARG_TTL_START; |
71 | | static const string ARG_TTL_END; |
72 | | static const string ARG_TIMESTAMP; |
73 | | static const string ARG_FROM; |
74 | | static const string ARG_TO; |
75 | | static const string ARG_MAX_KEYS; |
76 | | static const string ARG_BLOOM_BITS; |
77 | | static const string ARG_FIX_PREFIX_LEN; |
78 | | static const string ARG_COMPRESSION_TYPE; |
79 | | static const string ARG_BLOCK_SIZE; |
80 | | static const string ARG_AUTO_COMPACTION; |
81 | | static const string ARG_DB_WRITE_BUFFER_SIZE; |
82 | | static const string ARG_WRITE_BUFFER_SIZE; |
83 | | static const string ARG_FILE_SIZE; |
84 | | static const string ARG_CREATE_IF_MISSING; |
85 | | static const string ARG_NO_VALUE; |
86 | | static const string ARG_UNIVERSE_KEY_FILE; |
87 | | static const string ARG_ONLY_VERIFY_CHECKSUMS; |
88 | | |
89 | | static LDBCommand* InitFromCmdLineArgs( |
90 | | const vector<string>& args, const Options& options, |
91 | | const LDBOptions& ldb_options, |
92 | | const std::vector<ColumnFamilyDescriptor>* column_families); |
93 | | |
94 | | static LDBCommand* InitFromCmdLineArgs( |
95 | | int argc, char** argv, const Options& options, |
96 | | const LDBOptions& ldb_options, |
97 | | const std::vector<ColumnFamilyDescriptor>* column_families); |
98 | | |
99 | | bool ValidateCmdLineOptions(); |
100 | | |
101 | | virtual Options PrepareOptionsForOpenDB(); |
102 | | |
103 | 12 | virtual void SetDBOptions(Options options) { |
104 | 12 | options_ = options; |
105 | 12 | } |
106 | | |
107 | | virtual void SetColumnFamilies( |
108 | 0 | const std::vector<ColumnFamilyDescriptor>* column_families) { |
109 | 0 | if (column_families != nullptr) { |
110 | 0 | column_families_ = *column_families; |
111 | 0 | } else { |
112 | 0 | column_families_.clear(); |
113 | 0 | } |
114 | 0 | } |
115 | | |
116 | 12 | void SetLDBOptions(const LDBOptions& ldb_options) { |
117 | 12 | ldb_options_ = ldb_options; |
118 | 12 | } |
119 | | |
120 | 4 | virtual bool NoDBOpen() { |
121 | 4 | return false; |
122 | 4 | } |
123 | | |
124 | 12 | virtual ~LDBCommand() { CloseDB(); } |
125 | | |
126 | | /* Run the command, and return the execute result. */ |
127 | 12 | void Run() { |
128 | 12 | if (!exec_state_.IsNotStarted()) { |
129 | 0 | return; |
130 | 0 | } |
131 | | |
132 | 12 | if (db_ == nullptr && !NoDBOpen()) { |
133 | 2 | OpenDB(); |
134 | 2 | } |
135 | | |
136 | | // We'll intentionally proceed even if the DB can't be opened because users |
137 | | // can also specify a filename, not just a directory. |
138 | 12 | DoCommand(); |
139 | | |
140 | 12 | if (exec_state_.IsNotStarted()) { |
141 | 12 | exec_state_ = LDBCommandExecuteResult::Succeed(""); |
142 | 12 | } |
143 | | |
144 | 12 | if (db_ != nullptr) { |
145 | 2 | CloseDB (); |
146 | 2 | } |
147 | 12 | } |
148 | | |
149 | | virtual void DoCommand() = 0; |
150 | | |
151 | 12 | LDBCommandExecuteResult GetExecuteState() { |
152 | 12 | return exec_state_; |
153 | 12 | } |
154 | | |
155 | 0 | void ClearPreviousRunState() { |
156 | 0 | exec_state_.Reset(); |
157 | 0 | } |
158 | | |
159 | 26 | static string HexToString(const string& str) { |
160 | 26 | std::string::size_type len = str.length(); |
161 | 26 | string parsed; |
162 | 26 | static const char* const hexas = "0123456789ABCDEF"; |
163 | 26 | parsed.reserve(len / 2); |
164 | | |
165 | 26 | if (len < 2 || str[0] != '0' || str[1] != 'x'22 ) { |
166 | 4 | fprintf(stderr, "Invalid hex input %s. Must start with 0x\n", |
167 | 4 | str.c_str()); |
168 | 4 | throw "Invalid hex input"; |
169 | 4 | } |
170 | | |
171 | 38 | for (unsigned int i = 2; 22 i < len; i += 216 ) { |
172 | 30 | char a = static_cast<char>(toupper(str[i])); |
173 | 30 | const char* p = std::lower_bound(hexas, hexas + 16, a); |
174 | 30 | if (*p != a) { |
175 | 8 | throw "Invalid hex value"; |
176 | 8 | } |
177 | | |
178 | 22 | if (i + 1 >= len) { |
179 | | // if odd number of chars than we just hit end of string |
180 | 4 | parsed.push_back(static_cast<char>(p - hexas)); |
181 | 4 | break; |
182 | 4 | } |
183 | | |
184 | 18 | char b = static_cast<char>(toupper(str[i + 1])); |
185 | 18 | const char* q = std::lower_bound(hexas, hexas + 16, b); |
186 | 18 | if (*q == b) { |
187 | | // pairwise compute decimal value from hex |
188 | 16 | parsed.push_back(static_cast<char>(((p - hexas) << 4) | (q - hexas))); |
189 | 16 | } else { |
190 | 2 | throw "Invalid hex value"; |
191 | 2 | } |
192 | 18 | } |
193 | 12 | return parsed; |
194 | 22 | } |
195 | | |
196 | 0 | static string StringToHex(const string& str) { |
197 | 0 | string result = "0x"; |
198 | 0 | char buf[10]; |
199 | 0 | for (size_t i = 0; i < str.length(); i++) { |
200 | 0 | snprintf(buf, sizeof(buf), "%02X", (unsigned char)str[i]); |
201 | 0 | result += buf; |
202 | 0 | } |
203 | 0 | return result; |
204 | 0 | } |
205 | | |
206 | | static const char* DELIM; |
207 | | |
208 | | protected: |
209 | | |
210 | | LDBCommandExecuteResult exec_state_; |
211 | | string db_path_; |
212 | | string column_family_name_; |
213 | | DB* db_; |
214 | | DBWithTTL* db_ttl_; |
215 | | std::map<std::string, ColumnFamilyHandle*> cf_handles_; |
216 | | |
217 | | /** |
218 | | * true implies that this command can work if the db is opened in read-only |
219 | | * mode. |
220 | | */ |
221 | | bool is_read_only_; |
222 | | |
223 | | /** If true, the key is input/output as hex in get/put/scan/delete etc. */ |
224 | | bool is_key_hex_; |
225 | | |
226 | | /** If true, the value is input/output as hex in get/put/scan/delete etc. */ |
227 | | bool is_value_hex_; |
228 | | |
229 | | /** If true, the value is treated as timestamp suffixed */ |
230 | | bool is_db_ttl_; |
231 | | |
232 | | // If true, the kvs are output with their insert/modify timestamp in a ttl db |
233 | | bool timestamp_; |
234 | | |
235 | | /** |
236 | | * Map of options passed on the command-line. |
237 | | */ |
238 | | const map<string, string> option_map_; |
239 | | |
240 | | /** |
241 | | * Flags passed on the command-line. |
242 | | */ |
243 | | const vector<string> flags_; |
244 | | |
245 | | /** List of command-line options valid for this command */ |
246 | | const vector<string> valid_cmd_line_options_; |
247 | | |
248 | | std::unique_ptr<yb::encryption::UniverseKeyManager> universe_key_manager_; |
249 | | std::unique_ptr<rocksdb::Env> env_; |
250 | | |
251 | | bool ParseKeyValue(const string& line, string* key, string* value, |
252 | | bool is_key_hex, bool is_value_hex); |
253 | | |
254 | | LDBCommand(const map<string, string>& options, const vector<string>& flags, |
255 | | bool is_read_only, const vector<string>& valid_cmd_line_options) : |
256 | | db_(nullptr), |
257 | | is_read_only_(is_read_only), |
258 | | is_key_hex_(false), |
259 | | is_value_hex_(false), |
260 | | is_db_ttl_(false), |
261 | | timestamp_(false), |
262 | | option_map_(options), |
263 | | flags_(flags), |
264 | 12 | valid_cmd_line_options_(valid_cmd_line_options) { |
265 | | |
266 | 12 | map<string, string>::const_iterator itr = options.find(ARG_DB); |
267 | 12 | if (itr != options.end()) { |
268 | 12 | db_path_ = itr->second; |
269 | 12 | } |
270 | | |
271 | 12 | itr = options.find(ARG_UNIVERSE_KEY_FILE); |
272 | 12 | if (itr != options.end()) { |
273 | 2 | vector<string> splits = StringSplit(itr->second, ':'); |
274 | 2 | if (splits.size() != 2) { |
275 | 0 | LOG(FATAL) << yb::Format("Could not split $0 by ':' into a key id and key file", |
276 | 0 | itr->second); |
277 | 0 | } |
278 | 2 | string key_data; |
279 | 2 | auto key_id = splits[0]; |
280 | 2 | auto key_path = splits[1]; |
281 | 2 | Status s = ReadFileToString(Env::Default(), key_path, &key_data); |
282 | 2 | if(!s.ok()) { |
283 | 0 | LOG(FATAL) << yb::Format("Could not read file at path $0: $1", key_path, s.ToString()); |
284 | 0 | } |
285 | 2 | auto res = yb::encryption::UniverseKeyManager::FromKey(key_id, yb::Slice(key_data)); |
286 | 2 | if (!res.ok()) { |
287 | 0 | LOG(FATAL) << "Could not create universe key manager: " << res.status().ToString(); |
288 | 0 | } |
289 | 2 | universe_key_manager_ = std::move(*res); |
290 | 2 | env_ = yb::NewRocksDBEncryptedEnv( |
291 | 2 | yb::encryption::DefaultHeaderManager(universe_key_manager_.get())); |
292 | 2 | } |
293 | | |
294 | 12 | itr = options.find(ARG_CF_NAME); |
295 | 12 | if (itr != options.end()) { |
296 | 0 | column_family_name_ = itr->second; |
297 | 12 | } else { |
298 | 12 | column_family_name_ = kDefaultColumnFamilyName; |
299 | 12 | } |
300 | | |
301 | 12 | is_key_hex_ = IsKeyHex(options, flags); |
302 | 12 | is_value_hex_ = IsValueHex(options, flags); |
303 | 12 | is_db_ttl_ = IsFlagPresent(flags, ARG_TTL); |
304 | 12 | timestamp_ = IsFlagPresent(flags, ARG_TIMESTAMP); |
305 | 12 | } |
306 | | |
307 | 7 | void OpenDB() { |
308 | 7 | Options opt = PrepareOptionsForOpenDB(); |
309 | 7 | if (!exec_state_.IsNotStarted()) { |
310 | 0 | return; |
311 | 0 | } |
312 | | // Open the DB. |
313 | 7 | Status st; |
314 | 7 | std::vector<ColumnFamilyHandle*> handles_opened; |
315 | 7 | if (is_db_ttl_) { |
316 | | // ldb doesn't yet support TTL DB with multiple column families |
317 | 0 | if (!column_family_name_.empty() || !column_families_.empty()) { |
318 | 0 | exec_state_ = LDBCommandExecuteResult::Failed( |
319 | 0 | "ldb doesn't support TTL DB with multiple column families"); |
320 | 0 | } |
321 | 0 | if (is_read_only_) { |
322 | 0 | st = DBWithTTL::Open(opt, db_path_, &db_ttl_, 0, true); |
323 | 0 | } else { |
324 | 0 | st = DBWithTTL::Open(opt, db_path_, &db_ttl_); |
325 | 0 | } |
326 | 0 | db_ = db_ttl_; |
327 | 7 | } else { |
328 | 7 | if (column_families_.empty()) { |
329 | | // Try to figure out column family lists |
330 | 7 | std::vector<std::string> cf_list; |
331 | 7 | st = DB::ListColumnFamilies(DBOptions(), db_path_, &cf_list); |
332 | | // There is possible the DB doesn't exist yet, for "create if not |
333 | | // "existing case". The failure is ignored here. We rely on DB::Open() |
334 | | // to give us the correct error message for problem with opening |
335 | | // existing DB. |
336 | 7 | if (st.ok() && cf_list.size() > 16 ) { |
337 | | // Ignore single column family DB. |
338 | 0 | for (auto cf_name : cf_list) { |
339 | 0 | column_families_.emplace_back(cf_name, opt); |
340 | 0 | } |
341 | 0 | } |
342 | 7 | } |
343 | 7 | if (is_read_only_) { |
344 | 2 | if (column_families_.empty()) { |
345 | 2 | st = DB::OpenForReadOnly(opt, db_path_, &db_); |
346 | 2 | } else { |
347 | 0 | st = DB::OpenForReadOnly(opt, db_path_, column_families_, |
348 | 0 | &handles_opened, &db_); |
349 | 0 | } |
350 | 5 | } else { |
351 | 5 | if (column_families_.empty()) { |
352 | 5 | st = DB::Open(opt, db_path_, &db_); |
353 | 5 | } else { |
354 | 0 | st = DB::Open(opt, db_path_, column_families_, &handles_opened, &db_); |
355 | 0 | } |
356 | 5 | } |
357 | 7 | } |
358 | 7 | if (!st.ok()) { |
359 | 0 | string msg = st.ToString(); |
360 | 0 | exec_state_ = LDBCommandExecuteResult::Failed(msg); |
361 | 7 | } else if (!handles_opened.empty()) { |
362 | 0 | assert(handles_opened.size() == column_families_.size()); |
363 | 0 | bool found_cf_name = false; |
364 | 0 | for (size_t i = 0; i < handles_opened.size(); i++) { |
365 | 0 | cf_handles_[column_families_[i].name] = handles_opened[i]; |
366 | 0 | if (column_family_name_ == column_families_[i].name) { |
367 | 0 | found_cf_name = true; |
368 | 0 | } |
369 | 0 | } |
370 | 0 | if (!found_cf_name) { |
371 | 0 | exec_state_ = LDBCommandExecuteResult::Failed( |
372 | 0 | "Non-existing column family " + column_family_name_); |
373 | 0 | CloseDB(); |
374 | 0 | } |
375 | 7 | } else { |
376 | | // We successfully opened DB in single column family mode. |
377 | 7 | assert(column_families_.empty()); |
378 | 7 | if (column_family_name_ != kDefaultColumnFamilyName) { |
379 | 0 | exec_state_ = LDBCommandExecuteResult::Failed( |
380 | 0 | "Non-existing column family " + column_family_name_); |
381 | 0 | CloseDB(); |
382 | 0 | } |
383 | 7 | } |
384 | | |
385 | 0 | options_ = opt; |
386 | 7 | } |
387 | | |
388 | 19 | void CloseDB () { |
389 | 19 | if (db_ != nullptr) { |
390 | 7 | for (auto& pair : cf_handles_) { |
391 | 0 | delete pair.second; |
392 | 0 | } |
393 | 7 | delete db_; |
394 | 7 | db_ = nullptr; |
395 | 7 | } |
396 | 19 | } |
397 | | |
398 | 7 | ColumnFamilyHandle* GetCfHandle() { |
399 | 7 | if (!cf_handles_.empty()) { |
400 | 0 | auto it = cf_handles_.find(column_family_name_); |
401 | 0 | if (it == cf_handles_.end()) { |
402 | 0 | exec_state_ = LDBCommandExecuteResult::Failed( |
403 | 0 | "Cannot find column family " + column_family_name_); |
404 | 0 | } else { |
405 | 0 | return it->second; |
406 | 0 | } |
407 | 0 | } |
408 | 7 | return db_->DefaultColumnFamily(); |
409 | 7 | } |
410 | | |
411 | | static string PrintKeyValue(const string& key, const string& value, |
412 | 0 | bool is_key_hex, bool is_value_hex) { |
413 | 0 | string result; |
414 | 0 | result.append(is_key_hex ? StringToHex(key) : key); |
415 | 0 | result.append(DELIM); |
416 | 0 | result.append(is_value_hex ? StringToHex(value) : value); |
417 | 0 | return result; |
418 | 0 | } |
419 | | |
420 | | static string PrintKeyValue(const string& key, const string& value, |
421 | 0 | bool is_hex) { |
422 | 0 | return PrintKeyValue(key, value, is_hex, is_hex); |
423 | 0 | } |
424 | | |
425 | | /** |
426 | | * Return true if the specified flag is present in the specified flags vector |
427 | | */ |
428 | 80 | static bool IsFlagPresent(const vector<string>& flags, const string& flag) { |
429 | 80 | return (std::find(flags.begin(), flags.end(), flag) != flags.end()); |
430 | 80 | } |
431 | | |
432 | 0 | static string HelpRangeCmdArgs() { |
433 | 0 | ostringstream str_stream; |
434 | 0 | str_stream << " "; |
435 | 0 | str_stream << "[--" << ARG_FROM << "] "; |
436 | 0 | str_stream << "[--" << ARG_TO << "] "; |
437 | 0 | return str_stream.str(); |
438 | 0 | } |
439 | | |
440 | | /** |
441 | | * A helper function that returns a list of command line options |
442 | | * used by this command. It includes the common options and the ones |
443 | | * passed in. |
444 | | */ |
445 | 12 | static vector<string> BuildCmdLineOptions(vector<string> options) { |
446 | 12 | vector<string> ret = {ARG_DB, ARG_BLOOM_BITS, ARG_BLOCK_SIZE, |
447 | 12 | ARG_AUTO_COMPACTION, ARG_COMPRESSION_TYPE, |
448 | 12 | ARG_WRITE_BUFFER_SIZE, ARG_FILE_SIZE, |
449 | 12 | ARG_FIX_PREFIX_LEN, ARG_CF_NAME, ARG_UNIVERSE_KEY_FILE}; |
450 | 12 | ret.insert(ret.end(), options.begin(), options.end()); |
451 | 12 | return ret; |
452 | 12 | } |
453 | | |
454 | | bool ParseIntOption(const map<string, string>& options, const string& option, |
455 | | int& value, LDBCommandExecuteResult& exec_state); // NOLINT |
456 | | |
457 | | bool ParseStringOption(const map<string, string>& options, |
458 | | const string& option, string* value); |
459 | | |
460 | | Options options_; |
461 | | std::vector<ColumnFamilyDescriptor> column_families_; |
462 | | LDBOptions ldb_options_; |
463 | | |
464 | | private: |
465 | | |
466 | | /** |
467 | | * Interpret command line options and flags to determine if the key |
468 | | * should be input/output in hex. |
469 | | */ |
470 | | bool IsKeyHex(const map<string, string>& options, |
471 | 12 | const vector<string>& flags) { |
472 | 12 | return (IsFlagPresent(flags, ARG_HEX) || |
473 | 12 | IsFlagPresent(flags, ARG_KEY_HEX) || |
474 | 12 | ParseBooleanOption(options, ARG_HEX, false) || |
475 | 12 | ParseBooleanOption(options, ARG_KEY_HEX, false)); |
476 | 12 | } |
477 | | |
478 | | /** |
479 | | * Interpret command line options and flags to determine if the value |
480 | | * should be input/output in hex. |
481 | | */ |
482 | | bool IsValueHex(const map<string, string>& options, |
483 | 12 | const vector<string>& flags) { |
484 | 12 | return (IsFlagPresent(flags, ARG_HEX) || |
485 | 12 | IsFlagPresent(flags, ARG_VALUE_HEX) || |
486 | 12 | ParseBooleanOption(options, ARG_HEX, false) || |
487 | 12 | ParseBooleanOption(options, ARG_VALUE_HEX, false)); |
488 | 12 | } |
489 | | |
490 | | /** |
491 | | * Returns the value of the specified option as a boolean. |
492 | | * default_val is used if the option is not found in options. |
493 | | * Throws an exception if the value of the option is not |
494 | | * "true" or "false" (case insensitive). |
495 | | */ |
496 | | bool ParseBooleanOption(const map<string, string>& options, |
497 | 48 | const string& option, bool default_val) { |
498 | | |
499 | 48 | map<string, string>::const_iterator itr = options.find(option); |
500 | 48 | if (itr != options.end()) { |
501 | 0 | string option_val = itr->second; |
502 | 0 | return StringToBool(itr->second); |
503 | 0 | } |
504 | 48 | return default_val; |
505 | 48 | } |
506 | | |
507 | | /** |
508 | | * Converts val to a boolean. |
509 | | * val must be either true or false (case insensitive). |
510 | | * Otherwise an exception is thrown. |
511 | | */ |
512 | 0 | bool StringToBool(string val) { |
513 | 0 | std::transform(val.begin(), val.end(), val.begin(), |
514 | 0 | [](char ch)->char { return static_cast<char>(::tolower(ch)); }); |
515 | |
|
516 | 0 | if (val == "true") { |
517 | 0 | return true; |
518 | 0 | } else if (val == "false") { |
519 | 0 | return false; |
520 | 0 | } else { |
521 | 0 | throw "Invalid value for boolean argument"; |
522 | 0 | } |
523 | 0 | } |
524 | | |
525 | | static LDBCommand* SelectCommand( |
526 | | const string& cmd, |
527 | | const vector<string>& cmdParams, |
528 | | const map<string, string>& option_map, |
529 | | const vector<string>& flags |
530 | | ); |
531 | | |
532 | | }; |
533 | | |
534 | | class CompactorCommand: public LDBCommand { |
535 | | public: |
536 | 10 | static string Name() { return "compact"; } |
537 | | |
538 | | CompactorCommand(const vector<string>& params, |
539 | | const map<string, string>& options, const vector<string>& flags); |
540 | | |
541 | | static void Help(string& ret); // NOLINT |
542 | | |
543 | | virtual void DoCommand() override; |
544 | | |
545 | | private: |
546 | | bool null_from_; |
547 | | string from_; |
548 | | bool null_to_; |
549 | | string to_; |
550 | | }; |
551 | | |
552 | | class DBFileDumperCommand : public LDBCommand { |
553 | | public: |
554 | 2 | static string Name() { return "dump_live_files"; } |
555 | | |
556 | | DBFileDumperCommand(const vector<string>& params, |
557 | | const map<string, string>& options, |
558 | | const vector<string>& flags); |
559 | | |
560 | | static void Help(string& ret); // NOLINT |
561 | | |
562 | | virtual void DoCommand() override; |
563 | | }; |
564 | | |
565 | | class DBDumperCommand: public LDBCommand { |
566 | | public: |
567 | 2 | static string Name() { return "dump"; } |
568 | | |
569 | | DBDumperCommand(const vector<string>& params, |
570 | | const map<string, string>& options, const vector<string>& flags); |
571 | | |
572 | | static void Help(string& ret); // NOLINT |
573 | | |
574 | | virtual void DoCommand() override; |
575 | | |
576 | | private: |
577 | | /** |
578 | | * Extract file name from the full path. We handle both the forward slash (/) |
579 | | * and backslash (\) to make sure that different OS-s are supported. |
580 | | */ |
581 | 0 | static string GetFileNameFromPath(const string& s) { |
582 | 0 | std::size_t n = s.find_last_of("/\\"); |
583 | |
|
584 | 0 | if (std::string::npos == n) { |
585 | 0 | return s; |
586 | 0 | } else { |
587 | 0 | return s.substr(n + 1); |
588 | 0 | } |
589 | 0 | } |
590 | | |
591 | | void DoDumpCommand(); |
592 | | |
593 | | bool null_from_; |
594 | | string from_; |
595 | | bool null_to_; |
596 | | string to_; |
597 | | int max_keys_; |
598 | | string delim_; |
599 | | bool count_only_; |
600 | | bool count_delim_; |
601 | | bool print_stats_; |
602 | | string path_; |
603 | | |
604 | | static const string ARG_COUNT_ONLY; |
605 | | static const string ARG_COUNT_DELIM; |
606 | | static const string ARG_STATS; |
607 | | static const string ARG_TTL_BUCKET; |
608 | | }; |
609 | | |
610 | | class InternalDumpCommand: public LDBCommand { |
611 | | public: |
612 | 2 | static string Name() { return "idump"; } |
613 | | |
614 | | InternalDumpCommand(const vector<string>& params, |
615 | | const map<string, string>& options, |
616 | | const vector<string>& flags); |
617 | | |
618 | | static void Help(string& ret); // NOLINT |
619 | | |
620 | | virtual void DoCommand() override; |
621 | | |
622 | | private: |
623 | | bool has_from_; |
624 | | string from_; |
625 | | bool has_to_; |
626 | | string to_; |
627 | | int max_keys_; |
628 | | string delim_; |
629 | | bool count_only_; |
630 | | bool count_delim_; |
631 | | bool print_stats_; |
632 | | bool is_input_key_hex_; |
633 | | |
634 | | static const string ARG_DELIM; |
635 | | static const string ARG_COUNT_ONLY; |
636 | | static const string ARG_COUNT_DELIM; |
637 | | static const string ARG_STATS; |
638 | | static const string ARG_INPUT_KEY_HEX; |
639 | | }; |
640 | | |
641 | | class DBLoaderCommand: public LDBCommand { |
642 | | public: |
643 | 2 | static string Name() { return "load"; } |
644 | | |
645 | | DBLoaderCommand(string& db_name, vector<string>& args); // NOLINT |
646 | | |
647 | | DBLoaderCommand(const vector<string>& params, |
648 | | const map<string, string>& options, const vector<string>& flags); |
649 | | |
650 | | static void Help(string& ret); // NOLINT |
651 | | virtual void DoCommand() override; |
652 | | |
653 | | virtual Options PrepareOptionsForOpenDB() override; |
654 | | |
655 | | private: |
656 | | bool create_if_missing_; |
657 | | bool disable_wal_; |
658 | | bool bulk_load_; |
659 | | bool compact_; |
660 | | |
661 | | static const string ARG_DISABLE_WAL; |
662 | | static const string ARG_BULK_LOAD; |
663 | | static const string ARG_COMPACT; |
664 | | }; |
665 | | |
666 | | class ManifestDumpCommand: public LDBCommand { |
667 | | public: |
668 | 2 | static string Name() { return "manifest_dump"; } |
669 | | |
670 | | ManifestDumpCommand(const vector<string>& params, |
671 | | const map<string, string>& options, const vector<string>& flags); |
672 | | |
673 | | static void Help(string& ret); // NOLINT |
674 | | virtual void DoCommand() override; |
675 | | |
676 | 0 | virtual bool NoDBOpen() override { return true; } |
677 | | |
678 | | private: |
679 | | bool verbose_; |
680 | | string path_; |
681 | | |
682 | | static const string ARG_VERBOSE; |
683 | | static const string ARG_JSON; |
684 | | static const string ARG_PATH; |
685 | | }; |
686 | | |
687 | | class ListColumnFamiliesCommand : public LDBCommand { |
688 | | public: |
689 | 2 | static string Name() { return "list_column_families"; } |
690 | | |
691 | | ListColumnFamiliesCommand(const vector<string>& params, |
692 | | const map<string, string>& options, |
693 | | const vector<string>& flags); |
694 | | |
695 | | static void Help(string& ret); // NOLINT |
696 | | virtual void DoCommand() override; |
697 | | |
698 | 0 | virtual bool NoDBOpen() override { return true; } |
699 | | |
700 | | private: |
701 | | string dbname_; |
702 | | }; |
703 | | |
704 | | class CreateColumnFamilyCommand : public LDBCommand { |
705 | | public: |
706 | 2 | static string Name() { return "create_column_family"; } |
707 | | |
708 | | CreateColumnFamilyCommand(const vector<string>& params, |
709 | | const map<string, string>& options, |
710 | | const vector<string>& flags); |
711 | | |
712 | | static void Help(string& ret); // NOLINT |
713 | | virtual void DoCommand() override; |
714 | | |
715 | 0 | virtual bool NoDBOpen() override { return false; } |
716 | | |
717 | | private: |
718 | | string new_cf_name_; |
719 | | }; |
720 | | |
721 | | class ReduceDBLevelsCommand : public LDBCommand { |
722 | | public: |
723 | 10 | static string Name() { return "reduce_levels"; } |
724 | | |
725 | | ReduceDBLevelsCommand(const vector<string>& params, |
726 | | const map<string, string>& options, const vector<string>& flags); |
727 | | |
728 | | virtual Options PrepareOptionsForOpenDB() override; |
729 | | |
730 | | virtual void DoCommand() override; |
731 | | |
732 | 8 | virtual bool NoDBOpen() override { return true; } |
733 | | |
734 | | static void Help(string& msg); // NOLINT |
735 | | |
736 | | static vector<string> PrepareArgs(const string& db_path, int new_levels, |
737 | | bool print_old_level = false); |
738 | | |
739 | | private: |
740 | | int old_levels_; |
741 | | int new_levels_; |
742 | | bool print_old_levels_; |
743 | | |
744 | | static const string ARG_NEW_LEVELS; |
745 | | static const string ARG_PRINT_OLD_LEVELS; |
746 | | |
747 | | Status GetOldNumOfLevels(Options& opt, int* levels); // NOLINT |
748 | | }; |
749 | | |
750 | | class ChangeCompactionStyleCommand : public LDBCommand { |
751 | | public: |
752 | 2 | static string Name() { return "change_compaction_style"; } |
753 | | |
754 | | ChangeCompactionStyleCommand(const vector<string>& params, |
755 | | const map<string, string>& options, const vector<string>& flags); |
756 | | |
757 | | virtual Options PrepareOptionsForOpenDB() override; |
758 | | |
759 | | virtual void DoCommand() override; |
760 | | |
761 | | static void Help(string& msg); // NOLINT |
762 | | |
763 | | private: |
764 | | int old_compaction_style_; |
765 | | int new_compaction_style_; |
766 | | |
767 | | static const string ARG_OLD_COMPACTION_STYLE; |
768 | | static const string ARG_NEW_COMPACTION_STYLE; |
769 | | }; |
770 | | |
771 | | class WALDumperCommand : public LDBCommand { |
772 | | public: |
773 | 10 | static string Name() { return "dump_wal"; } |
774 | | |
775 | | WALDumperCommand(const vector<string>& params, |
776 | | const map<string, string>& options, const vector<string>& flags); |
777 | | |
778 | 0 | virtual bool NoDBOpen() override { return true; } |
779 | | |
780 | | static void Help(string& ret); // NOLINT |
781 | | virtual void DoCommand() override; |
782 | | |
783 | | private: |
784 | | bool print_header_; |
785 | | string wal_file_; |
786 | | bool print_values_; |
787 | | |
788 | | static const string ARG_WAL_FILE; |
789 | | static const string ARG_PRINT_HEADER; |
790 | | static const string ARG_PRINT_VALUE; |
791 | | }; |
792 | | |
793 | | |
794 | | class GetCommand : public LDBCommand { |
795 | | public: |
796 | 12 | static string Name() { return "get"; } |
797 | | |
798 | | GetCommand(const vector<string>& params, const map<string, string>& options, |
799 | | const vector<string>& flags); |
800 | | |
801 | | virtual void DoCommand() override; |
802 | | |
803 | | static void Help(string& ret); // NOLINT |
804 | | |
805 | | private: |
806 | | string key_; |
807 | | }; |
808 | | |
809 | | class ApproxSizeCommand : public LDBCommand { |
810 | | public: |
811 | 10 | static string Name() { return "approxsize"; } |
812 | | |
813 | | ApproxSizeCommand(const vector<string>& params, |
814 | | const map<string, string>& options, const vector<string>& flags); |
815 | | |
816 | | virtual void DoCommand() override; |
817 | | |
818 | | static void Help(string& ret); // NOLINT |
819 | | |
820 | | private: |
821 | | string start_key_; |
822 | | string end_key_; |
823 | | }; |
824 | | |
825 | | class BatchPutCommand : public LDBCommand { |
826 | | public: |
827 | 12 | static string Name() { return "batchput"; } |
828 | | |
829 | | BatchPutCommand(const vector<string>& params, |
830 | | const map<string, string>& options, const vector<string>& flags); |
831 | | |
832 | | virtual void DoCommand() override; |
833 | | |
834 | | static void Help(string& ret); // NOLINT |
835 | | |
836 | | virtual Options PrepareOptionsForOpenDB() override; |
837 | | |
838 | | private: |
839 | | /** |
840 | | * The key-values to be inserted. |
841 | | */ |
842 | | vector<std::pair<string, string>> key_values_; |
843 | | }; |
844 | | |
845 | | class ScanCommand : public LDBCommand { |
846 | | public: |
847 | 12 | static string Name() { return "scan"; } |
848 | | |
849 | | ScanCommand(const vector<string>& params, const map<string, string>& options, |
850 | | const vector<string>& flags); |
851 | | |
852 | | virtual void DoCommand() override; |
853 | | |
854 | | static void Help(string& ret); // NOLINT |
855 | | |
856 | | private: |
857 | | string start_key_; |
858 | | string end_key_; |
859 | | bool start_key_specified_; |
860 | | bool end_key_specified_; |
861 | | int max_keys_scanned_; |
862 | | bool no_value_; |
863 | | bool only_verify_checksums_ = false; |
864 | | }; |
865 | | |
866 | | class DeleteCommand : public LDBCommand { |
867 | | public: |
868 | 10 | static string Name() { return "delete"; } |
869 | | |
870 | | DeleteCommand(const vector<string>& params, |
871 | | const map<string, string>& options, const vector<string>& flags); |
872 | | |
873 | | virtual void DoCommand() override; |
874 | | |
875 | | static void Help(string& ret); // NOLINT |
876 | | |
877 | | private: |
878 | | string key_; |
879 | | }; |
880 | | |
881 | | class PutCommand : public LDBCommand { |
882 | | public: |
883 | 12 | static string Name() { return "put"; } |
884 | | |
885 | | PutCommand(const vector<string>& params, const map<string, string>& options, |
886 | | const vector<string>& flags); |
887 | | |
888 | | virtual void DoCommand() override; |
889 | | |
890 | | static void Help(string& ret); // NOLINT |
891 | | |
892 | | virtual Options PrepareOptionsForOpenDB() override; |
893 | | |
894 | | private: |
895 | | string key_; |
896 | | string value_; |
897 | | }; |
898 | | |
899 | | /** |
900 | | * Command that starts up a REPL shell that allows |
901 | | * get/put/delete. |
902 | | */ |
903 | | class DBQuerierCommand: public LDBCommand { |
904 | | public: |
905 | 10 | static string Name() { return "query"; } |
906 | | |
907 | | DBQuerierCommand(const vector<string>& params, |
908 | | const map<string, string>& options, const vector<string>& flags); |
909 | | |
910 | | static void Help(string& ret); // NOLINT |
911 | | |
912 | | virtual void DoCommand() override; |
913 | | |
914 | | private: |
915 | | static const char* HELP_CMD; |
916 | | static const char* GET_CMD; |
917 | | static const char* PUT_CMD; |
918 | | static const char* DELETE_CMD; |
919 | | }; |
920 | | |
921 | | class CheckConsistencyCommand : public LDBCommand { |
922 | | public: |
923 | 2 | static string Name() { return "checkconsistency"; } |
924 | | |
925 | | CheckConsistencyCommand(const vector<string>& params, |
926 | | const map<string, string>& options, const vector<string>& flags); |
927 | | |
928 | | virtual void DoCommand() override; |
929 | | |
930 | 4 | virtual bool NoDBOpen() override { return true; } |
931 | | |
932 | | static void Help(string& ret); // NOLINT |
933 | | }; |
934 | | |
935 | | } // namespace rocksdb |
936 | | |
937 | | #endif // ROCKSDB_LITE |
938 | | #endif // YB_ROCKSDB_TOOLS_LDB_CMD_H |