1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. 2 // This source code is licensed under both the GPLv2 (found in the 3 // COPYING file in the root directory) and Apache 2.0 License 4 // (found in the LICENSE.Apache file in the root directory). 5 // 6 #pragma once 7 8 #ifndef ROCKSDB_LITE 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <algorithm> 13 #include <functional> 14 #include <map> 15 #include <sstream> 16 #include <string> 17 #include <vector> 18 19 #include "rocksdb/env.h" 20 #include "rocksdb/iterator.h" 21 #include "rocksdb/ldb_tool.h" 22 #include "rocksdb/options.h" 23 #include "rocksdb/slice.h" 24 #include "rocksdb/utilities/db_ttl.h" 25 #include "rocksdb/utilities/ldb_cmd_execute_result.h" 26 27 namespace ROCKSDB_NAMESPACE { 28 29 class LDBCommand { 30 public: 31 // Command-line arguments 32 static const std::string ARG_ENV_URI; 33 static const std::string ARG_DB; 34 static const std::string ARG_PATH; 35 static const std::string ARG_SECONDARY_PATH; 36 static const std::string ARG_HEX; 37 static const std::string ARG_KEY_HEX; 38 static const std::string ARG_VALUE_HEX; 39 static const std::string ARG_CF_NAME; 40 static const std::string ARG_TTL; 41 static const std::string ARG_TTL_START; 42 static const std::string ARG_TTL_END; 43 static const std::string ARG_TIMESTAMP; 44 static const std::string ARG_TRY_LOAD_OPTIONS; 45 static const std::string ARG_IGNORE_UNKNOWN_OPTIONS; 46 static const std::string ARG_FROM; 47 static const std::string ARG_TO; 48 static const std::string ARG_MAX_KEYS; 49 static const std::string ARG_BLOOM_BITS; 50 static const std::string ARG_FIX_PREFIX_LEN; 51 static const std::string ARG_COMPRESSION_TYPE; 52 static const std::string ARG_COMPRESSION_MAX_DICT_BYTES; 53 static const std::string ARG_BLOCK_SIZE; 54 static const std::string ARG_AUTO_COMPACTION; 55 static const std::string ARG_DB_WRITE_BUFFER_SIZE; 56 static const std::string ARG_WRITE_BUFFER_SIZE; 57 static const std::string ARG_FILE_SIZE; 58 static const std::string ARG_CREATE_IF_MISSING; 59 static const std::string ARG_NO_VALUE; 60 61 struct ParsedParams { 62 std::string cmd; 63 std::vector<std::string> cmd_params; 64 std::map<std::string, std::string> option_map; 65 std::vector<std::string> flags; 66 }; 67 68 static LDBCommand* SelectCommand(const ParsedParams& parsed_parms); 69 70 static LDBCommand* InitFromCmdLineArgs( 71 const std::vector<std::string>& args, const Options& options, 72 const LDBOptions& ldb_options, 73 const std::vector<ColumnFamilyDescriptor>* column_families, 74 const std::function<LDBCommand*(const ParsedParams&)>& selector = 75 SelectCommand); 76 77 static LDBCommand* InitFromCmdLineArgs( 78 int argc, char** argv, const Options& options, 79 const LDBOptions& ldb_options, 80 const std::vector<ColumnFamilyDescriptor>* column_families); 81 82 bool ValidateCmdLineOptions(); 83 84 virtual Options PrepareOptionsForOpenDB(); 85 SetDBOptions(Options options)86 virtual void SetDBOptions(Options options) { options_ = options; } 87 SetColumnFamilies(const std::vector<ColumnFamilyDescriptor> * column_families)88 virtual void SetColumnFamilies( 89 const std::vector<ColumnFamilyDescriptor>* column_families) { 90 if (column_families != nullptr) { 91 column_families_ = *column_families; 92 } else { 93 column_families_.clear(); 94 } 95 } 96 SetLDBOptions(const LDBOptions & ldb_options)97 void SetLDBOptions(const LDBOptions& ldb_options) { 98 ldb_options_ = ldb_options; 99 } 100 TEST_GetOptionMap()101 const std::map<std::string, std::string>& TEST_GetOptionMap() { 102 return option_map_; 103 } 104 TEST_GetFlags()105 const std::vector<std::string>& TEST_GetFlags() { return flags_; } 106 NoDBOpen()107 virtual bool NoDBOpen() { return false; } 108 ~LDBCommand()109 virtual ~LDBCommand() { CloseDB(); } 110 111 /* Run the command, and return the execute result. */ 112 void Run(); 113 114 virtual void DoCommand() = 0; 115 GetExecuteState()116 LDBCommandExecuteResult GetExecuteState() { return exec_state_; } 117 ClearPreviousRunState()118 void ClearPreviousRunState() { exec_state_.Reset(); } 119 120 // Consider using Slice::DecodeHex directly instead if you don't need the 121 // 0x prefix 122 static std::string HexToString(const std::string& str); 123 124 // Consider using Slice::ToString(true) directly instead if 125 // you don't need the 0x prefix 126 static std::string StringToHex(const std::string& str); 127 128 static const char* DELIM; 129 130 protected: 131 LDBCommandExecuteResult exec_state_; 132 std::string env_uri_; 133 std::string db_path_; 134 // If empty, open DB as primary. If non-empty, open the DB as secondary 135 // with this secondary path. When running against a database opened by 136 // another process, ldb wll leave the source directory completely intact. 137 std::string secondary_path_; 138 std::string column_family_name_; 139 DB* db_; 140 DBWithTTL* db_ttl_; 141 std::map<std::string, ColumnFamilyHandle*> cf_handles_; 142 143 /** 144 * true implies that this command can work if the db is opened in read-only 145 * mode. 146 */ 147 bool is_read_only_; 148 149 /** If true, the key is input/output as hex in get/put/scan/delete etc. */ 150 bool is_key_hex_; 151 152 /** If true, the value is input/output as hex in get/put/scan/delete etc. */ 153 bool is_value_hex_; 154 155 /** If true, the value is treated as timestamp suffixed */ 156 bool is_db_ttl_; 157 158 // If true, the kvs are output with their insert/modify timestamp in a ttl db 159 bool timestamp_; 160 161 // If true, try to construct options from DB's option files. 162 bool try_load_options_; 163 164 bool ignore_unknown_options_; 165 166 bool create_if_missing_; 167 168 /** 169 * Map of options passed on the command-line. 170 */ 171 const std::map<std::string, std::string> option_map_; 172 173 /** 174 * Flags passed on the command-line. 175 */ 176 const std::vector<std::string> flags_; 177 178 /** List of command-line options valid for this command */ 179 const std::vector<std::string> valid_cmd_line_options_; 180 181 /** Shared pointer to underlying environment if applicable **/ 182 std::shared_ptr<Env> env_guard_; 183 184 bool ParseKeyValue(const std::string& line, std::string* key, 185 std::string* value, bool is_key_hex, bool is_value_hex); 186 187 LDBCommand(const std::map<std::string, std::string>& options, 188 const std::vector<std::string>& flags, bool is_read_only, 189 const std::vector<std::string>& valid_cmd_line_options); 190 191 void OpenDB(); 192 193 void CloseDB(); 194 195 ColumnFamilyHandle* GetCfHandle(); 196 197 static std::string PrintKeyValue(const std::string& key, 198 const std::string& value, bool is_key_hex, 199 bool is_value_hex); 200 201 static std::string PrintKeyValue(const std::string& key, 202 const std::string& value, bool is_hex); 203 204 /** 205 * Return true if the specified flag is present in the specified flags vector 206 */ IsFlagPresent(const std::vector<std::string> & flags,const std::string & flag)207 static bool IsFlagPresent(const std::vector<std::string>& flags, 208 const std::string& flag) { 209 return (std::find(flags.begin(), flags.end(), flag) != flags.end()); 210 } 211 212 static std::string HelpRangeCmdArgs(); 213 214 /** 215 * A helper function that returns a list of command line options 216 * used by this command. It includes the common options and the ones 217 * passed in. 218 */ 219 static std::vector<std::string> BuildCmdLineOptions( 220 std::vector<std::string> options); 221 222 bool ParseIntOption(const std::map<std::string, std::string>& options, 223 const std::string& option, int& value, 224 LDBCommandExecuteResult& exec_state); 225 226 bool ParseStringOption(const std::map<std::string, std::string>& options, 227 const std::string& option, std::string* value); 228 229 /** 230 * Returns the value of the specified option as a boolean. 231 * default_val is used if the option is not found in options. 232 * Throws an exception if the value of the option is not 233 * "true" or "false" (case insensitive). 234 */ 235 bool ParseBooleanOption(const std::map<std::string, std::string>& options, 236 const std::string& option, bool default_val); 237 238 Options options_; 239 std::vector<ColumnFamilyDescriptor> column_families_; 240 LDBOptions ldb_options_; 241 242 private: 243 /** 244 * Interpret command line options and flags to determine if the key 245 * should be input/output in hex. 246 */ 247 bool IsKeyHex(const std::map<std::string, std::string>& options, 248 const std::vector<std::string>& flags); 249 250 /** 251 * Interpret command line options and flags to determine if the value 252 * should be input/output in hex. 253 */ 254 bool IsValueHex(const std::map<std::string, std::string>& options, 255 const std::vector<std::string>& flags); 256 257 /** 258 * Converts val to a boolean. 259 * val must be either true or false (case insensitive). 260 * Otherwise an exception is thrown. 261 */ 262 bool StringToBool(std::string val); 263 }; 264 265 class LDBCommandRunner { 266 public: 267 static void PrintHelp(const LDBOptions& ldb_options, const char* exec_name); 268 269 // Returns the status code to return. 0 is no error. 270 static int RunCommand( 271 int argc, char** argv, Options options, const LDBOptions& ldb_options, 272 const std::vector<ColumnFamilyDescriptor>* column_families); 273 }; 274 275 } // namespace ROCKSDB_NAMESPACE 276 277 #endif // ROCKSDB_LITE 278