2016-02-09 23:12:00 +00:00
|
|
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
2014-09-17 19:46:32 +00:00
|
|
|
// This source code is licensed under the BSD-style license found in the
|
|
|
|
// LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
// of patent rights can be found in the PATENTS file in the same directory.
|
Add options.compaction_measure_io_stats to print write I/O stats in compactions
Summary:
Add options.compaction_measure_io_stats to print out / pass to listener accumulated time spent on write calls. Example outputs in info logs:
2015/08/12-16:27:59.463944 7fd428bff700 (Original Log Time 2015/08/12-16:27:59.463922) EVENT_LOG_v1 {"time_micros": 1439422079463897, "job": 6, "event": "compaction_finished", "output_level": 1, "num_output_files": 4, "total_output_size": 6900525, "num_input_records": 111483, "num_output_records": 106877, "file_write_nanos": 15663206, "file_range_sync_nanos": 649588, "file_fsync_nanos": 349614797, "file_prepare_write_nanos": 1505812, "lsm_state": [2, 4, 0, 0, 0, 0, 0]}
Add two more counters in iostats_context.
Also add a parameter of db_bench.
Test Plan: Add a unit test. Also manually verify LOG outputs in db_bench
Subscribers: leveldb, dhruba
Differential Revision: https://reviews.facebook.net/D44115
2015-08-13 00:24:45 +00:00
|
|
|
#include "util/options_helper.h"
|
2014-09-17 19:46:32 +00:00
|
|
|
|
|
|
|
#include <cassert>
|
2014-10-10 17:00:12 +00:00
|
|
|
#include <cctype>
|
2015-04-24 02:17:57 +00:00
|
|
|
#include <cstdlib>
|
2014-10-01 23:19:16 +00:00
|
|
|
#include <unordered_set>
|
2015-10-02 22:35:32 +00:00
|
|
|
#include <vector>
|
2014-12-22 21:18:57 +00:00
|
|
|
#include "rocksdb/cache.h"
|
2015-10-02 22:35:32 +00:00
|
|
|
#include "rocksdb/compaction_filter.h"
|
2015-07-15 21:51:51 +00:00
|
|
|
#include "rocksdb/convenience.h"
|
2014-12-22 21:18:57 +00:00
|
|
|
#include "rocksdb/filter_policy.h"
|
2015-10-02 22:35:32 +00:00
|
|
|
#include "rocksdb/memtablerep.h"
|
|
|
|
#include "rocksdb/merge_operator.h"
|
2014-09-17 19:46:32 +00:00
|
|
|
#include "rocksdb/options.h"
|
2015-03-06 22:21:15 +00:00
|
|
|
#include "rocksdb/rate_limiter.h"
|
2015-01-15 23:33:12 +00:00
|
|
|
#include "rocksdb/slice_transform.h"
|
2014-12-22 21:18:57 +00:00
|
|
|
#include "rocksdb/table.h"
|
2015-02-20 03:11:14 +00:00
|
|
|
#include "table/block_based_table_factory.h"
|
2015-10-28 17:46:01 +00:00
|
|
|
#include "table/plain_table_factory.h"
|
2015-04-24 02:17:57 +00:00
|
|
|
#include "util/logging.h"
|
2015-08-18 20:30:18 +00:00
|
|
|
#include "util/string_util.h"
|
2014-09-17 19:46:32 +00:00
|
|
|
|
|
|
|
namespace rocksdb {
|
|
|
|
|
2014-11-13 19:39:30 +00:00
|
|
|
#ifndef ROCKSDB_LITE
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
bool isSpecialChar(const char c) {
|
|
|
|
if (c == '\\' || c == '#' || c == ':' || c == '\r' || c == '\n') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
char UnescapeChar(const char c) {
|
|
|
|
static const std::unordered_map<char, char> convert_map = {{'r', '\r'},
|
|
|
|
{'n', '\n'}};
|
|
|
|
|
|
|
|
auto iter = convert_map.find(c);
|
|
|
|
if (iter == convert_map.end()) {
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
return iter->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
char EscapeChar(const char c) {
|
|
|
|
static const std::unordered_map<char, char> convert_map = {{'\n', 'n'},
|
|
|
|
{'\r', 'r'}};
|
|
|
|
|
|
|
|
auto iter = convert_map.find(c);
|
|
|
|
if (iter == convert_map.end()) {
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
return iter->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string EscapeOptionString(const std::string& raw_string) {
|
|
|
|
std::string output;
|
|
|
|
for (auto c : raw_string) {
|
|
|
|
if (isSpecialChar(c)) {
|
|
|
|
output += '\\';
|
|
|
|
output += EscapeChar(c);
|
|
|
|
} else {
|
|
|
|
output += c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string UnescapeOptionString(const std::string& escaped_string) {
|
|
|
|
bool escaped = false;
|
|
|
|
std::string output;
|
|
|
|
|
|
|
|
for (auto c : escaped_string) {
|
|
|
|
if (escaped) {
|
|
|
|
output += UnescapeChar(c);
|
|
|
|
escaped = false;
|
|
|
|
} else {
|
|
|
|
if (c == '\\') {
|
|
|
|
escaped = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
output += c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return output;
|
|
|
|
}
|
2014-11-13 19:39:30 +00:00
|
|
|
|
2014-09-17 19:46:32 +00:00
|
|
|
namespace {
|
2015-10-02 22:35:32 +00:00
|
|
|
std::string trim(const std::string& str) {
|
|
|
|
if (str.empty()) return std::string();
|
|
|
|
size_t start = 0;
|
|
|
|
size_t end = str.size() - 1;
|
|
|
|
while (isspace(str[start]) != 0 && start <= end) {
|
|
|
|
++start;
|
|
|
|
}
|
|
|
|
while (isspace(str[end]) != 0 && start <= end) {
|
|
|
|
--end;
|
|
|
|
}
|
|
|
|
if (start <= end) {
|
|
|
|
return str.substr(start, end - start + 1);
|
|
|
|
}
|
|
|
|
return std::string();
|
|
|
|
}
|
|
|
|
|
2015-11-18 00:41:54 +00:00
|
|
|
template <typename T>
|
|
|
|
bool ParseEnum(const std::unordered_map<std::string, T>& type_map,
|
2015-10-30 22:58:46 +00:00
|
|
|
const std::string& type, T* value) {
|
|
|
|
auto iter = type_map.find(type);
|
|
|
|
if (iter != type_map.end()) {
|
|
|
|
*value = iter->second;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-11-18 00:41:54 +00:00
|
|
|
template <typename T>
|
|
|
|
bool SerializeEnum(const std::unordered_map<std::string, T>& type_map,
|
2015-10-30 22:58:46 +00:00
|
|
|
const T& type, std::string* value) {
|
|
|
|
for (const auto& pair : type_map) {
|
|
|
|
if (pair.second == type) {
|
|
|
|
*value = pair.first;
|
2015-10-02 22:35:32 +00:00
|
|
|
return true;
|
2015-10-30 22:58:46 +00:00
|
|
|
}
|
2015-10-02 22:35:32 +00:00
|
|
|
}
|
2015-10-30 22:58:46 +00:00
|
|
|
return false;
|
2015-10-02 22:35:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool SerializeVectorCompressionType(const std::vector<CompressionType>& types,
|
|
|
|
std::string* value) {
|
|
|
|
std::stringstream ss;
|
|
|
|
bool result;
|
|
|
|
for (size_t i = 0; i < types.size(); ++i) {
|
|
|
|
if (i > 0) {
|
|
|
|
ss << ':';
|
|
|
|
}
|
|
|
|
std::string string_type;
|
2015-10-30 22:58:46 +00:00
|
|
|
result = SerializeEnum<CompressionType>(compression_type_string_map,
|
2015-11-18 00:41:54 +00:00
|
|
|
types[i], &string_type);
|
2015-10-02 22:35:32 +00:00
|
|
|
if (result == false) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
ss << string_type;
|
|
|
|
}
|
|
|
|
*value = ss.str();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-09-17 19:46:32 +00:00
|
|
|
bool ParseBoolean(const std::string& type, const std::string& value) {
|
|
|
|
if (value == "true" || value == "1") {
|
|
|
|
return true;
|
|
|
|
} else if (value == "false" || value == "0") {
|
|
|
|
return false;
|
|
|
|
}
|
2014-12-22 21:18:57 +00:00
|
|
|
throw std::invalid_argument(type);
|
2014-09-17 19:46:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t ParseUint64(const std::string& value) {
|
2014-11-17 21:47:51 +00:00
|
|
|
size_t endchar;
|
2015-04-24 02:17:57 +00:00
|
|
|
#ifndef CYGWIN
|
2014-11-17 21:47:51 +00:00
|
|
|
uint64_t num = std::stoull(value.c_str(), &endchar);
|
2015-04-24 02:17:57 +00:00
|
|
|
#else
|
|
|
|
char* endptr;
|
|
|
|
uint64_t num = std::strtoul(value.c_str(), &endptr, 0);
|
|
|
|
endchar = endptr - value.c_str();
|
|
|
|
#endif
|
2014-11-17 21:47:51 +00:00
|
|
|
|
|
|
|
if (endchar < value.length()) {
|
|
|
|
char c = value[endchar];
|
|
|
|
if (c == 'k' || c == 'K')
|
|
|
|
num <<= 10LL;
|
|
|
|
else if (c == 'm' || c == 'M')
|
|
|
|
num <<= 20LL;
|
|
|
|
else if (c == 'g' || c == 'G')
|
|
|
|
num <<= 30LL;
|
|
|
|
else if (c == 't' || c == 'T')
|
|
|
|
num <<= 40LL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return num;
|
2014-09-17 19:46:32 +00:00
|
|
|
}
|
|
|
|
|
2014-11-13 19:39:30 +00:00
|
|
|
size_t ParseSizeT(const std::string& value) {
|
|
|
|
return static_cast<size_t>(ParseUint64(value));
|
2014-09-17 19:46:32 +00:00
|
|
|
}
|
|
|
|
|
2014-11-17 21:47:51 +00:00
|
|
|
uint32_t ParseUint32(const std::string& value) {
|
|
|
|
uint64_t num = ParseUint64(value);
|
|
|
|
if ((num >> 32LL) == 0) {
|
|
|
|
return static_cast<uint32_t>(num);
|
|
|
|
} else {
|
|
|
|
throw std::out_of_range(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int ParseInt(const std::string& value) {
|
|
|
|
size_t endchar;
|
2015-04-24 02:17:57 +00:00
|
|
|
#ifndef CYGWIN
|
2014-11-17 21:47:51 +00:00
|
|
|
int num = std::stoi(value.c_str(), &endchar);
|
2015-04-24 02:17:57 +00:00
|
|
|
#else
|
|
|
|
char* endptr;
|
|
|
|
int num = std::strtoul(value.c_str(), &endptr, 0);
|
|
|
|
endchar = endptr - value.c_str();
|
|
|
|
#endif
|
2014-11-17 21:47:51 +00:00
|
|
|
|
|
|
|
if (endchar < value.length()) {
|
|
|
|
char c = value[endchar];
|
|
|
|
if (c == 'k' || c == 'K')
|
|
|
|
num <<= 10;
|
|
|
|
else if (c == 'm' || c == 'M')
|
|
|
|
num <<= 20;
|
|
|
|
else if (c == 'g' || c == 'G')
|
|
|
|
num <<= 30;
|
|
|
|
}
|
|
|
|
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
2014-09-17 19:46:32 +00:00
|
|
|
double ParseDouble(const std::string& value) {
|
2015-04-24 02:17:57 +00:00
|
|
|
#ifndef CYGWIN
|
2014-09-17 19:46:32 +00:00
|
|
|
return std::stod(value);
|
2015-04-24 02:17:57 +00:00
|
|
|
#else
|
|
|
|
return std::strtod(value.c_str(), 0);
|
|
|
|
#endif
|
2014-09-17 19:46:32 +00:00
|
|
|
}
|
2015-08-26 23:13:56 +00:00
|
|
|
|
2015-10-02 22:35:32 +00:00
|
|
|
bool ParseVectorCompressionType(
|
|
|
|
const std::string& value,
|
|
|
|
std::vector<CompressionType>* compression_per_level) {
|
|
|
|
compression_per_level->clear();
|
|
|
|
size_t start = 0;
|
|
|
|
while (start < value.size()) {
|
|
|
|
size_t end = value.find(':', start);
|
|
|
|
bool is_ok;
|
|
|
|
CompressionType type;
|
|
|
|
if (end == std::string::npos) {
|
2015-11-18 00:41:54 +00:00
|
|
|
is_ok = ParseEnum<CompressionType>(compression_type_string_map,
|
|
|
|
value.substr(start), &type);
|
2015-10-02 22:35:32 +00:00
|
|
|
if (!is_ok) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
compression_per_level->emplace_back(type);
|
|
|
|
break;
|
|
|
|
} else {
|
2015-11-18 00:41:54 +00:00
|
|
|
is_ok = ParseEnum<CompressionType>(
|
|
|
|
compression_type_string_map, value.substr(start, end - start), &type);
|
2015-10-02 22:35:32 +00:00
|
|
|
if (!is_ok) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
compression_per_level->emplace_back(type);
|
|
|
|
start = end + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ParseSliceTransformHelper(
|
|
|
|
const std::string& kFixedPrefixName, const std::string& kCappedPrefixName,
|
|
|
|
const std::string& value,
|
|
|
|
std::shared_ptr<const SliceTransform>* slice_transform) {
|
2015-10-11 19:17:42 +00:00
|
|
|
static const std::string kNullptrString = "nullptr";
|
2015-10-02 22:35:32 +00:00
|
|
|
auto& pe_value = value;
|
|
|
|
if (pe_value.size() > kFixedPrefixName.size() &&
|
|
|
|
pe_value.compare(0, kFixedPrefixName.size(), kFixedPrefixName) == 0) {
|
|
|
|
int prefix_length = ParseInt(trim(value.substr(kFixedPrefixName.size())));
|
|
|
|
slice_transform->reset(NewFixedPrefixTransform(prefix_length));
|
|
|
|
} else if (pe_value.size() > kCappedPrefixName.size() &&
|
|
|
|
pe_value.compare(0, kCappedPrefixName.size(), kCappedPrefixName) ==
|
|
|
|
0) {
|
|
|
|
int prefix_length =
|
|
|
|
ParseInt(trim(pe_value.substr(kCappedPrefixName.size())));
|
|
|
|
slice_transform->reset(NewCappedPrefixTransform(prefix_length));
|
2015-10-11 19:17:42 +00:00
|
|
|
} else if (value == kNullptrString) {
|
2015-10-02 22:35:32 +00:00
|
|
|
slice_transform->reset();
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ParseSliceTransform(
|
|
|
|
const std::string& value,
|
|
|
|
std::shared_ptr<const SliceTransform>* slice_transform) {
|
|
|
|
// While we normally don't convert the string representation of a
|
|
|
|
// pointer-typed option into its instance, here we do so for backward
|
|
|
|
// compatibility as we allow this action in SetOption().
|
|
|
|
|
|
|
|
// TODO(yhchiang): A possible better place for these serialization /
|
|
|
|
// deserialization is inside the class definition of pointer-typed
|
|
|
|
// option itself, but this requires a bigger change of public API.
|
|
|
|
bool result =
|
|
|
|
ParseSliceTransformHelper("fixed:", "capped:", value, slice_transform);
|
|
|
|
if (result) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
result = ParseSliceTransformHelper(
|
|
|
|
"rocksdb.FixedPrefix.", "rocksdb.CappedPrefix.", value, slice_transform);
|
|
|
|
if (result) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
// TODO(yhchiang): we can further support other default
|
|
|
|
// SliceTransforms here.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-08-26 23:13:56 +00:00
|
|
|
bool ParseOptionHelper(char* opt_address, const OptionType& opt_type,
|
|
|
|
const std::string& value) {
|
|
|
|
switch (opt_type) {
|
|
|
|
case OptionType::kBoolean:
|
|
|
|
*reinterpret_cast<bool*>(opt_address) = ParseBoolean("", value);
|
|
|
|
break;
|
|
|
|
case OptionType::kInt:
|
|
|
|
*reinterpret_cast<int*>(opt_address) = ParseInt(value);
|
|
|
|
break;
|
|
|
|
case OptionType::kUInt:
|
|
|
|
*reinterpret_cast<unsigned int*>(opt_address) = ParseUint32(value);
|
|
|
|
break;
|
|
|
|
case OptionType::kUInt32T:
|
|
|
|
*reinterpret_cast<uint32_t*>(opt_address) = ParseUint32(value);
|
|
|
|
break;
|
|
|
|
case OptionType::kUInt64T:
|
|
|
|
*reinterpret_cast<uint64_t*>(opt_address) = ParseUint64(value);
|
|
|
|
break;
|
|
|
|
case OptionType::kSizeT:
|
|
|
|
*reinterpret_cast<size_t*>(opt_address) = ParseSizeT(value);
|
|
|
|
break;
|
|
|
|
case OptionType::kString:
|
|
|
|
*reinterpret_cast<std::string*>(opt_address) = value;
|
|
|
|
break;
|
|
|
|
case OptionType::kDouble:
|
|
|
|
*reinterpret_cast<double*>(opt_address) = ParseDouble(value);
|
|
|
|
break;
|
|
|
|
case OptionType::kCompactionStyle:
|
2015-11-18 00:41:54 +00:00
|
|
|
return ParseEnum<CompactionStyle>(
|
|
|
|
compaction_style_string_map, value,
|
|
|
|
reinterpret_cast<CompactionStyle*>(opt_address));
|
2015-10-02 22:35:32 +00:00
|
|
|
case OptionType::kCompressionType:
|
2015-11-18 00:41:54 +00:00
|
|
|
return ParseEnum<CompressionType>(
|
|
|
|
compression_type_string_map, value,
|
|
|
|
reinterpret_cast<CompressionType*>(opt_address));
|
2015-10-02 22:35:32 +00:00
|
|
|
case OptionType::kVectorCompressionType:
|
|
|
|
return ParseVectorCompressionType(
|
|
|
|
value, reinterpret_cast<std::vector<CompressionType>*>(opt_address));
|
|
|
|
case OptionType::kSliceTransform:
|
|
|
|
return ParseSliceTransform(
|
|
|
|
value, reinterpret_cast<std::shared_ptr<const SliceTransform>*>(
|
|
|
|
opt_address));
|
2015-10-11 19:17:42 +00:00
|
|
|
case OptionType::kChecksumType:
|
2015-11-18 00:41:54 +00:00
|
|
|
return ParseEnum<ChecksumType>(
|
|
|
|
checksum_type_string_map, value,
|
|
|
|
reinterpret_cast<ChecksumType*>(opt_address));
|
2015-10-11 19:17:42 +00:00
|
|
|
case OptionType::kBlockBasedTableIndexType:
|
2015-10-30 22:58:46 +00:00
|
|
|
return ParseEnum<BlockBasedTableOptions::IndexType>(
|
2015-11-18 00:41:54 +00:00
|
|
|
block_base_table_index_type_string_map, value,
|
|
|
|
reinterpret_cast<BlockBasedTableOptions::IndexType*>(opt_address));
|
2015-10-28 17:46:01 +00:00
|
|
|
case OptionType::kEncodingType:
|
2015-11-18 00:41:54 +00:00
|
|
|
return ParseEnum<EncodingType>(
|
|
|
|
encoding_type_string_map, value,
|
|
|
|
reinterpret_cast<EncodingType*>(opt_address));
|
2016-03-02 18:34:14 +00:00
|
|
|
case OptionType::kWALRecoveryMode:
|
|
|
|
return ParseEnum<WALRecoveryMode>(
|
|
|
|
wal_recovery_mode_string_map, value,
|
|
|
|
reinterpret_cast<WALRecoveryMode*>(opt_address));
|
|
|
|
case OptionType::kAccessHint:
|
|
|
|
return ParseEnum<DBOptions::AccessHint>(
|
|
|
|
access_hint_string_map, value,
|
|
|
|
reinterpret_cast<DBOptions::AccessHint*>(opt_address));
|
|
|
|
case OptionType::kInfoLogLevel:
|
|
|
|
return ParseEnum<InfoLogLevel>(
|
|
|
|
info_log_level_string_map, value,
|
|
|
|
reinterpret_cast<InfoLogLevel*>(opt_address));
|
2015-08-26 23:13:56 +00:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-10-02 22:35:32 +00:00
|
|
|
} // anonymouse namespace
|
|
|
|
|
2015-08-26 23:13:56 +00:00
|
|
|
bool SerializeSingleOptionHelper(const char* opt_address,
|
|
|
|
const OptionType opt_type,
|
|
|
|
std::string* value) {
|
2015-10-12 00:40:50 +00:00
|
|
|
static const std::string kNullptrString = "nullptr";
|
2015-08-26 23:13:56 +00:00
|
|
|
assert(value);
|
|
|
|
switch (opt_type) {
|
|
|
|
case OptionType::kBoolean:
|
|
|
|
*value = *(reinterpret_cast<const bool*>(opt_address)) ? "true" : "false";
|
|
|
|
break;
|
|
|
|
case OptionType::kInt:
|
|
|
|
*value = ToString(*(reinterpret_cast<const int*>(opt_address)));
|
|
|
|
break;
|
|
|
|
case OptionType::kUInt:
|
|
|
|
*value = ToString(*(reinterpret_cast<const unsigned int*>(opt_address)));
|
|
|
|
break;
|
|
|
|
case OptionType::kUInt32T:
|
|
|
|
*value = ToString(*(reinterpret_cast<const uint32_t*>(opt_address)));
|
|
|
|
break;
|
|
|
|
case OptionType::kUInt64T:
|
|
|
|
*value = ToString(*(reinterpret_cast<const uint64_t*>(opt_address)));
|
|
|
|
break;
|
|
|
|
case OptionType::kSizeT:
|
|
|
|
*value = ToString(*(reinterpret_cast<const size_t*>(opt_address)));
|
|
|
|
break;
|
|
|
|
case OptionType::kDouble:
|
|
|
|
*value = ToString(*(reinterpret_cast<const double*>(opt_address)));
|
|
|
|
break;
|
|
|
|
case OptionType::kString:
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
*value = EscapeOptionString(
|
|
|
|
*(reinterpret_cast<const std::string*>(opt_address)));
|
2015-08-26 23:13:56 +00:00
|
|
|
break;
|
|
|
|
case OptionType::kCompactionStyle:
|
2015-11-18 00:41:54 +00:00
|
|
|
return SerializeEnum<CompactionStyle>(
|
|
|
|
compaction_style_string_map,
|
2015-10-30 22:58:46 +00:00
|
|
|
*(reinterpret_cast<const CompactionStyle*>(opt_address)), value);
|
2015-10-02 22:35:32 +00:00
|
|
|
case OptionType::kCompressionType:
|
2015-11-18 00:41:54 +00:00
|
|
|
return SerializeEnum<CompressionType>(
|
|
|
|
compression_type_string_map,
|
2015-10-02 22:35:32 +00:00
|
|
|
*(reinterpret_cast<const CompressionType*>(opt_address)), value);
|
|
|
|
case OptionType::kVectorCompressionType:
|
|
|
|
return SerializeVectorCompressionType(
|
|
|
|
*(reinterpret_cast<const std::vector<CompressionType>*>(opt_address)),
|
|
|
|
value);
|
|
|
|
break;
|
|
|
|
case OptionType::kSliceTransform: {
|
|
|
|
const auto* slice_transform_ptr =
|
|
|
|
reinterpret_cast<const std::shared_ptr<const SliceTransform>*>(
|
|
|
|
opt_address);
|
|
|
|
*value = slice_transform_ptr->get() ? slice_transform_ptr->get()->Name()
|
2015-10-11 19:17:42 +00:00
|
|
|
: kNullptrString;
|
2015-10-02 22:35:32 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OptionType::kTableFactory: {
|
|
|
|
const auto* table_factory_ptr =
|
|
|
|
reinterpret_cast<const std::shared_ptr<const TableFactory>*>(
|
|
|
|
opt_address);
|
|
|
|
*value = table_factory_ptr->get() ? table_factory_ptr->get()->Name()
|
2015-10-11 19:17:42 +00:00
|
|
|
: kNullptrString;
|
2015-10-02 22:35:32 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OptionType::kComparator: {
|
|
|
|
// it's a const pointer of const Comparator*
|
|
|
|
const auto* ptr = reinterpret_cast<const Comparator* const*>(opt_address);
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
// Since the user-specified comparator will be wrapped by
|
|
|
|
// InternalKeyComparator, we should persist the user-specified one
|
|
|
|
// instead of InternalKeyComparator.
|
|
|
|
const auto* internal_comparator =
|
|
|
|
dynamic_cast<const InternalKeyComparator*>(*ptr);
|
|
|
|
if (internal_comparator != nullptr) {
|
|
|
|
*value = internal_comparator->user_comparator()->Name();
|
|
|
|
} else {
|
|
|
|
*value = *ptr ? (*ptr)->Name() : kNullptrString;
|
|
|
|
}
|
2015-10-02 22:35:32 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OptionType::kCompactionFilter: {
|
|
|
|
// it's a const pointer of const CompactionFilter*
|
|
|
|
const auto* ptr =
|
|
|
|
reinterpret_cast<const CompactionFilter* const*>(opt_address);
|
2015-10-11 19:17:42 +00:00
|
|
|
*value = *ptr ? (*ptr)->Name() : kNullptrString;
|
2015-10-02 22:35:32 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OptionType::kCompactionFilterFactory: {
|
|
|
|
const auto* ptr =
|
|
|
|
reinterpret_cast<const std::shared_ptr<CompactionFilterFactory>*>(
|
|
|
|
opt_address);
|
2015-10-11 19:17:42 +00:00
|
|
|
*value = ptr->get() ? ptr->get()->Name() : kNullptrString;
|
2015-10-02 22:35:32 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OptionType::kMemTableRepFactory: {
|
|
|
|
const auto* ptr =
|
|
|
|
reinterpret_cast<const std::shared_ptr<MemTableRepFactory>*>(
|
|
|
|
opt_address);
|
2015-10-11 19:17:42 +00:00
|
|
|
*value = ptr->get() ? ptr->get()->Name() : kNullptrString;
|
2015-10-02 22:35:32 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OptionType::kMergeOperator: {
|
|
|
|
const auto* ptr =
|
|
|
|
reinterpret_cast<const std::shared_ptr<MergeOperator>*>(opt_address);
|
2015-10-11 19:17:42 +00:00
|
|
|
*value = ptr->get() ? ptr->get()->Name() : kNullptrString;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OptionType::kFilterPolicy: {
|
|
|
|
const auto* ptr =
|
|
|
|
reinterpret_cast<const std::shared_ptr<FilterPolicy>*>(opt_address);
|
|
|
|
*value = ptr->get() ? ptr->get()->Name() : kNullptrString;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case OptionType::kChecksumType:
|
2015-11-18 00:41:54 +00:00
|
|
|
return SerializeEnum<ChecksumType>(
|
|
|
|
checksum_type_string_map,
|
2015-10-11 19:17:42 +00:00
|
|
|
*reinterpret_cast<const ChecksumType*>(opt_address), value);
|
|
|
|
case OptionType::kBlockBasedTableIndexType:
|
2015-10-30 22:58:46 +00:00
|
|
|
return SerializeEnum<BlockBasedTableOptions::IndexType>(
|
|
|
|
block_base_table_index_type_string_map,
|
2015-10-11 19:17:42 +00:00
|
|
|
*reinterpret_cast<const BlockBasedTableOptions::IndexType*>(
|
|
|
|
opt_address),
|
|
|
|
value);
|
|
|
|
case OptionType::kFlushBlockPolicyFactory: {
|
|
|
|
const auto* ptr =
|
|
|
|
reinterpret_cast<const std::shared_ptr<FlushBlockPolicyFactory>*>(
|
|
|
|
opt_address);
|
|
|
|
*value = ptr->get() ? ptr->get()->Name() : kNullptrString;
|
2015-10-02 22:35:32 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-10-28 17:46:01 +00:00
|
|
|
case OptionType::kEncodingType:
|
2015-11-18 00:41:54 +00:00
|
|
|
return SerializeEnum<EncodingType>(
|
|
|
|
encoding_type_string_map,
|
2015-10-28 17:46:01 +00:00
|
|
|
*reinterpret_cast<const EncodingType*>(opt_address), value);
|
2016-03-02 18:34:14 +00:00
|
|
|
case OptionType::kWALRecoveryMode:
|
|
|
|
return SerializeEnum<WALRecoveryMode>(
|
|
|
|
wal_recovery_mode_string_map,
|
|
|
|
*reinterpret_cast<const WALRecoveryMode*>(opt_address), value);
|
|
|
|
case OptionType::kAccessHint:
|
|
|
|
return SerializeEnum<DBOptions::AccessHint>(
|
|
|
|
access_hint_string_map,
|
|
|
|
*reinterpret_cast<const DBOptions::AccessHint*>(opt_address), value);
|
|
|
|
case OptionType::kInfoLogLevel:
|
|
|
|
return SerializeEnum<InfoLogLevel>(
|
|
|
|
info_log_level_string_map,
|
|
|
|
*reinterpret_cast<const InfoLogLevel*>(opt_address), value);
|
2015-08-26 23:13:56 +00:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-09-17 19:46:32 +00:00
|
|
|
|
2014-09-17 19:49:13 +00:00
|
|
|
template<typename OptionsType>
|
2014-10-01 23:19:16 +00:00
|
|
|
bool ParseMemtableOptions(const std::string& name, const std::string& value,
|
|
|
|
OptionsType* new_options) {
|
2014-09-17 19:49:13 +00:00
|
|
|
if (name == "write_buffer_size") {
|
2014-11-13 19:39:30 +00:00
|
|
|
new_options->write_buffer_size = ParseSizeT(value);
|
2014-09-17 19:49:13 +00:00
|
|
|
} else if (name == "arena_block_size") {
|
2014-11-13 19:39:30 +00:00
|
|
|
new_options->arena_block_size = ParseSizeT(value);
|
2014-09-17 19:49:13 +00:00
|
|
|
} else if (name == "memtable_prefix_bloom_bits") {
|
2016-06-04 00:02:10 +00:00
|
|
|
// deprecated
|
|
|
|
} else if (name == "memtable_prefix_bloom_size_ratio") {
|
|
|
|
new_options->memtable_prefix_bloom_size_ratio = ParseDouble(value);
|
2014-09-17 19:49:13 +00:00
|
|
|
} else if (name == "memtable_prefix_bloom_probes") {
|
2016-06-04 00:02:10 +00:00
|
|
|
// Deprecated
|
2014-09-17 19:49:13 +00:00
|
|
|
} else if (name == "memtable_prefix_bloom_huge_page_tlb_size") {
|
|
|
|
new_options->memtable_prefix_bloom_huge_page_tlb_size =
|
2014-11-13 19:39:30 +00:00
|
|
|
ParseSizeT(value);
|
2014-09-17 19:49:13 +00:00
|
|
|
} else if (name == "max_successive_merges") {
|
2014-11-13 19:39:30 +00:00
|
|
|
new_options->max_successive_merges = ParseSizeT(value);
|
2014-09-17 19:49:13 +00:00
|
|
|
} else if (name == "filter_deletes") {
|
2016-06-08 00:25:06 +00:00
|
|
|
// Deprecated
|
2014-10-16 23:57:59 +00:00
|
|
|
} else if (name == "max_write_buffer_number") {
|
|
|
|
new_options->max_write_buffer_number = ParseInt(value);
|
2014-10-27 19:10:13 +00:00
|
|
|
} else if (name == "inplace_update_num_locks") {
|
2014-11-13 19:39:30 +00:00
|
|
|
new_options->inplace_update_num_locks = ParseSizeT(value);
|
2014-09-17 19:49:13 +00:00
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-10-01 23:19:16 +00:00
|
|
|
template<typename OptionsType>
|
|
|
|
bool ParseCompactionOptions(const std::string& name, const std::string& value,
|
|
|
|
OptionsType* new_options) {
|
2014-10-17 00:14:17 +00:00
|
|
|
if (name == "disable_auto_compactions") {
|
|
|
|
new_options->disable_auto_compactions = ParseBoolean(name, value);
|
2014-10-17 00:21:31 +00:00
|
|
|
} else if (name == "soft_rate_limit") {
|
2015-11-19 02:10:20 +00:00
|
|
|
// Deprecated options but still leave it here to avoid older options
|
|
|
|
// strings can be consumed.
|
|
|
|
} else if (name == "soft_pending_compaction_bytes_limit") {
|
|
|
|
new_options->soft_pending_compaction_bytes_limit = ParseUint64(value);
|
2015-09-11 21:31:23 +00:00
|
|
|
} else if (name == "hard_pending_compaction_bytes_limit") {
|
|
|
|
new_options->hard_pending_compaction_bytes_limit = ParseUint64(value);
|
2014-10-17 00:21:31 +00:00
|
|
|
} else if (name == "hard_rate_limit") {
|
2015-09-11 21:31:23 +00:00
|
|
|
// Deprecated options but still leave it here to avoid older options
|
|
|
|
// strings can be consumed.
|
2014-10-17 00:14:17 +00:00
|
|
|
} else if (name == "level0_file_num_compaction_trigger") {
|
2014-10-01 23:19:16 +00:00
|
|
|
new_options->level0_file_num_compaction_trigger = ParseInt(value);
|
|
|
|
} else if (name == "level0_slowdown_writes_trigger") {
|
|
|
|
new_options->level0_slowdown_writes_trigger = ParseInt(value);
|
|
|
|
} else if (name == "level0_stop_writes_trigger") {
|
|
|
|
new_options->level0_stop_writes_trigger = ParseInt(value);
|
|
|
|
} else if (name == "max_grandparent_overlap_factor") {
|
|
|
|
new_options->max_grandparent_overlap_factor = ParseInt(value);
|
|
|
|
} else if (name == "expanded_compaction_factor") {
|
|
|
|
new_options->expanded_compaction_factor = ParseInt(value);
|
|
|
|
} else if (name == "source_compaction_factor") {
|
|
|
|
new_options->source_compaction_factor = ParseInt(value);
|
|
|
|
} else if (name == "target_file_size_base") {
|
|
|
|
new_options->target_file_size_base = ParseInt(value);
|
|
|
|
} else if (name == "target_file_size_multiplier") {
|
|
|
|
new_options->target_file_size_multiplier = ParseInt(value);
|
|
|
|
} else if (name == "max_bytes_for_level_base") {
|
|
|
|
new_options->max_bytes_for_level_base = ParseUint64(value);
|
|
|
|
} else if (name == "max_bytes_for_level_multiplier") {
|
|
|
|
new_options->max_bytes_for_level_multiplier = ParseInt(value);
|
|
|
|
} else if (name == "max_bytes_for_level_multiplier_additional") {
|
|
|
|
new_options->max_bytes_for_level_multiplier_additional.clear();
|
|
|
|
size_t start = 0;
|
|
|
|
while (true) {
|
2014-12-22 21:18:57 +00:00
|
|
|
size_t end = value.find(':', start);
|
2014-10-01 23:19:16 +00:00
|
|
|
if (end == std::string::npos) {
|
|
|
|
new_options->max_bytes_for_level_multiplier_additional.push_back(
|
|
|
|
ParseInt(value.substr(start)));
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
new_options->max_bytes_for_level_multiplier_additional.push_back(
|
|
|
|
ParseInt(value.substr(start, end - start)));
|
|
|
|
start = end + 1;
|
|
|
|
}
|
|
|
|
}
|
2014-11-18 18:20:10 +00:00
|
|
|
} else if (name == "verify_checksums_in_compaction") {
|
|
|
|
new_options->verify_checksums_in_compaction = ParseBoolean(name, value);
|
2014-10-01 23:19:16 +00:00
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-10-23 22:34:21 +00:00
|
|
|
template<typename OptionsType>
|
|
|
|
bool ParseMiscOptions(const std::string& name, const std::string& value,
|
|
|
|
OptionsType* new_options) {
|
|
|
|
if (name == "max_sequential_skip_in_iterations") {
|
|
|
|
new_options->max_sequential_skip_in_iterations = ParseUint64(value);
|
2015-04-17 22:26:50 +00:00
|
|
|
} else if (name == "paranoid_file_checks") {
|
|
|
|
new_options->paranoid_file_checks = ParseBoolean(name, value);
|
2016-05-17 20:11:56 +00:00
|
|
|
} else if (name == "report_bg_io_stats") {
|
|
|
|
new_options->report_bg_io_stats = ParseBoolean(name, value);
|
|
|
|
} else if (name == "compression") {
|
|
|
|
bool is_ok = ParseEnum<CompressionType>(compression_type_string_map, value,
|
|
|
|
&new_options->compression);
|
|
|
|
if (!is_ok) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else if (name == "min_partial_merge_operands") {
|
|
|
|
new_options->min_partial_merge_operands = ParseUint32(value);
|
2014-10-23 22:34:21 +00:00
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-11-05 00:23:05 +00:00
|
|
|
Status GetMutableOptionsFromStrings(
|
2014-09-17 19:49:13 +00:00
|
|
|
const MutableCFOptions& base_options,
|
|
|
|
const std::unordered_map<std::string, std::string>& options_map,
|
|
|
|
MutableCFOptions* new_options) {
|
|
|
|
assert(new_options);
|
|
|
|
*new_options = base_options;
|
2014-12-22 21:18:57 +00:00
|
|
|
for (const auto& o : options_map) {
|
|
|
|
try {
|
2014-10-01 23:19:16 +00:00
|
|
|
if (ParseMemtableOptions(o.first, o.second, new_options)) {
|
|
|
|
} else if (ParseCompactionOptions(o.first, o.second, new_options)) {
|
2014-10-23 22:34:21 +00:00
|
|
|
} else if (ParseMiscOptions(o.first, o.second, new_options)) {
|
2014-09-17 19:49:13 +00:00
|
|
|
} else {
|
2014-11-05 00:23:05 +00:00
|
|
|
return Status::InvalidArgument(
|
|
|
|
"unsupported dynamic option: " + o.first);
|
2014-09-17 19:49:13 +00:00
|
|
|
}
|
2015-07-08 14:35:56 +00:00
|
|
|
} catch (std::exception& e) {
|
2014-12-22 21:18:57 +00:00
|
|
|
return Status::InvalidArgument("error parsing " + o.first + ":" +
|
|
|
|
std::string(e.what()));
|
2014-09-17 19:49:13 +00:00
|
|
|
}
|
|
|
|
}
|
2014-11-05 00:23:05 +00:00
|
|
|
return Status::OK();
|
2014-09-17 19:49:13 +00:00
|
|
|
}
|
|
|
|
|
2014-12-22 21:18:57 +00:00
|
|
|
Status StringToMap(const std::string& opts_str,
|
|
|
|
std::unordered_map<std::string, std::string>* opts_map) {
|
2014-10-10 17:00:12 +00:00
|
|
|
assert(opts_map);
|
|
|
|
// Example:
|
2014-12-22 21:18:57 +00:00
|
|
|
// opts_str = "write_buffer_size=1024;max_write_buffer_number=2;"
|
|
|
|
// "nested_opt={opt1=1;opt2=2};max_bytes_for_level_base=100"
|
2014-10-10 17:00:12 +00:00
|
|
|
size_t pos = 0;
|
|
|
|
std::string opts = trim(opts_str);
|
|
|
|
while (pos < opts.size()) {
|
|
|
|
size_t eq_pos = opts.find('=', pos);
|
|
|
|
if (eq_pos == std::string::npos) {
|
2014-12-22 21:18:57 +00:00
|
|
|
return Status::InvalidArgument("Mismatched key value pair, '=' expected");
|
2014-10-10 17:00:12 +00:00
|
|
|
}
|
|
|
|
std::string key = trim(opts.substr(pos, eq_pos - pos));
|
2014-12-22 21:18:57 +00:00
|
|
|
if (key.empty()) {
|
|
|
|
return Status::InvalidArgument("Empty key found");
|
|
|
|
}
|
2014-10-10 17:00:12 +00:00
|
|
|
|
2014-12-22 21:18:57 +00:00
|
|
|
// skip space after '=' and look for '{' for possible nested options
|
|
|
|
pos = eq_pos + 1;
|
|
|
|
while (pos < opts.size() && isspace(opts[pos])) {
|
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
// Empty value at the end
|
|
|
|
if (pos >= opts.size()) {
|
|
|
|
(*opts_map)[key] = "";
|
2014-10-10 17:00:12 +00:00
|
|
|
break;
|
2014-12-22 21:18:57 +00:00
|
|
|
}
|
|
|
|
if (opts[pos] == '{') {
|
|
|
|
int count = 1;
|
|
|
|
size_t brace_pos = pos + 1;
|
|
|
|
while (brace_pos < opts.size()) {
|
|
|
|
if (opts[brace_pos] == '{') {
|
|
|
|
++count;
|
|
|
|
} else if (opts[brace_pos] == '}') {
|
|
|
|
--count;
|
|
|
|
if (count == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++brace_pos;
|
|
|
|
}
|
|
|
|
// found the matching closing brace
|
|
|
|
if (count == 0) {
|
|
|
|
(*opts_map)[key] = trim(opts.substr(pos + 1, brace_pos - pos - 1));
|
|
|
|
// skip all whitespace and move to the next ';'
|
|
|
|
// brace_pos points to the next position after the matching '}'
|
|
|
|
pos = brace_pos + 1;
|
|
|
|
while (pos < opts.size() && isspace(opts[pos])) {
|
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
if (pos < opts.size() && opts[pos] != ';') {
|
|
|
|
return Status::InvalidArgument(
|
|
|
|
"Unexpected chars after nested options");
|
|
|
|
}
|
|
|
|
++pos;
|
|
|
|
} else {
|
|
|
|
return Status::InvalidArgument(
|
|
|
|
"Mismatched curly braces for nested options");
|
|
|
|
}
|
2014-10-10 17:00:12 +00:00
|
|
|
} else {
|
2014-12-22 21:18:57 +00:00
|
|
|
size_t sc_pos = opts.find(';', pos);
|
|
|
|
if (sc_pos == std::string::npos) {
|
|
|
|
(*opts_map)[key] = trim(opts.substr(pos));
|
|
|
|
// It either ends with a trailing semi-colon or the last key-value pair
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
(*opts_map)[key] = trim(opts.substr(pos, sc_pos - pos));
|
|
|
|
}
|
|
|
|
pos = sc_pos + 1;
|
2014-10-10 17:00:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-22 21:18:57 +00:00
|
|
|
return Status::OK();
|
2014-10-10 17:00:12 +00:00
|
|
|
}
|
|
|
|
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
Status ParseColumnFamilyOption(const std::string& name,
|
|
|
|
const std::string& org_value,
|
|
|
|
ColumnFamilyOptions* new_options,
|
|
|
|
bool input_strings_escaped = false) {
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
const std::string& value =
|
2015-10-28 17:46:01 +00:00
|
|
|
input_strings_escaped ? UnescapeOptionString(org_value) : org_value;
|
2015-02-20 03:11:14 +00:00
|
|
|
try {
|
2015-08-26 23:13:56 +00:00
|
|
|
if (name == "max_bytes_for_level_multiplier_additional") {
|
|
|
|
new_options->max_bytes_for_level_multiplier_additional.clear();
|
|
|
|
size_t start = 0;
|
|
|
|
while (true) {
|
|
|
|
size_t end = value.find(':', start);
|
|
|
|
if (end == std::string::npos) {
|
|
|
|
new_options->max_bytes_for_level_multiplier_additional.push_back(
|
|
|
|
ParseInt(value.substr(start)));
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
new_options->max_bytes_for_level_multiplier_additional.push_back(
|
|
|
|
ParseInt(value.substr(start, end - start)));
|
|
|
|
start = end + 1;
|
|
|
|
}
|
|
|
|
}
|
2015-02-20 03:11:14 +00:00
|
|
|
} else if (name == "block_based_table_factory") {
|
|
|
|
// Nested options
|
|
|
|
BlockBasedTableOptions table_opt, base_table_options;
|
|
|
|
auto block_based_table_factory = dynamic_cast<BlockBasedTableFactory*>(
|
|
|
|
new_options->table_factory.get());
|
|
|
|
if (block_based_table_factory != nullptr) {
|
2015-10-30 22:58:46 +00:00
|
|
|
base_table_options = block_based_table_factory->table_options();
|
2015-02-20 03:11:14 +00:00
|
|
|
}
|
|
|
|
Status table_opt_s = GetBlockBasedTableOptionsFromString(
|
|
|
|
base_table_options, value, &table_opt);
|
|
|
|
if (!table_opt_s.ok()) {
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return Status::InvalidArgument(
|
|
|
|
"unable to parse the specified CF option " + name);
|
2015-02-20 03:11:14 +00:00
|
|
|
}
|
|
|
|
new_options->table_factory.reset(NewBlockBasedTableFactory(table_opt));
|
2015-10-28 17:46:01 +00:00
|
|
|
} else if (name == "plain_table_factory") {
|
|
|
|
// Nested options
|
|
|
|
PlainTableOptions table_opt, base_table_options;
|
|
|
|
auto plain_table_factory = dynamic_cast<PlainTableFactory*>(
|
|
|
|
new_options->table_factory.get());
|
|
|
|
if (plain_table_factory != nullptr) {
|
2015-10-30 22:58:46 +00:00
|
|
|
base_table_options = plain_table_factory->table_options();
|
2015-10-28 17:46:01 +00:00
|
|
|
}
|
|
|
|
Status table_opt_s = GetPlainTableOptionsFromString(
|
|
|
|
base_table_options, value, &table_opt);
|
|
|
|
if (!table_opt_s.ok()) {
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return Status::InvalidArgument(
|
|
|
|
"unable to parse the specified CF option " + name);
|
2015-10-28 17:46:01 +00:00
|
|
|
}
|
|
|
|
new_options->table_factory.reset(NewPlainTableFactory(table_opt));
|
2015-11-17 22:29:01 +00:00
|
|
|
} else if (name == "memtable") {
|
|
|
|
std::unique_ptr<MemTableRepFactory> new_mem_factory;
|
|
|
|
Status mem_factory_s =
|
|
|
|
GetMemTableRepFactoryFromString(value, &new_mem_factory);
|
|
|
|
if (!mem_factory_s.ok()) {
|
|
|
|
return Status::InvalidArgument(
|
|
|
|
"unable to parse the specified CF option " + name);
|
|
|
|
}
|
|
|
|
new_options->memtable_factory.reset(new_mem_factory.release());
|
2015-02-20 03:11:14 +00:00
|
|
|
} else if (name == "compression_opts") {
|
|
|
|
size_t start = 0;
|
|
|
|
size_t end = value.find(':');
|
|
|
|
if (end == std::string::npos) {
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return Status::InvalidArgument(
|
|
|
|
"unable to parse the specified CF option " + name);
|
2015-02-20 03:11:14 +00:00
|
|
|
}
|
|
|
|
new_options->compression_opts.window_bits =
|
|
|
|
ParseInt(value.substr(start, end - start));
|
|
|
|
start = end + 1;
|
|
|
|
end = value.find(':', start);
|
|
|
|
if (end == std::string::npos) {
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return Status::InvalidArgument(
|
|
|
|
"unable to parse the specified CF option " + name);
|
2015-02-20 03:11:14 +00:00
|
|
|
}
|
|
|
|
new_options->compression_opts.level =
|
|
|
|
ParseInt(value.substr(start, end - start));
|
|
|
|
start = end + 1;
|
2016-05-06 18:27:28 +00:00
|
|
|
if (start >= value.size()) {
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return Status::InvalidArgument(
|
|
|
|
"unable to parse the specified CF option " + name);
|
2015-02-20 03:11:14 +00:00
|
|
|
}
|
2016-05-06 18:27:28 +00:00
|
|
|
end = value.find(':', start);
|
2015-02-20 03:11:14 +00:00
|
|
|
new_options->compression_opts.strategy =
|
|
|
|
ParseInt(value.substr(start, value.size() - start));
|
2016-05-06 18:27:28 +00:00
|
|
|
// max_dict_bytes is optional for backwards compatibility
|
|
|
|
if (end != std::string::npos) {
|
|
|
|
start = end + 1;
|
|
|
|
if (start >= value.size()) {
|
|
|
|
return Status::InvalidArgument(
|
|
|
|
"unable to parse the specified CF option " + name);
|
|
|
|
}
|
|
|
|
new_options->compression_opts.max_dict_bytes =
|
|
|
|
ParseInt(value.substr(start, value.size() - start));
|
Shared dictionary compression using reference block
Summary:
This adds a new metablock containing a shared dictionary that is used
to compress all data blocks in the SST file. The size of the shared dictionary
is configurable in CompressionOptions and defaults to 0. It's currently only
used for zlib/lz4/lz4hc, but the block will be stored in the SST regardless of
the compression type if the user chooses a nonzero dictionary size.
During compaction, computes the dictionary by randomly sampling the first
output file in each subcompaction. It pre-computes the intervals to sample
by assuming the output file will have the maximum allowable length. In case
the file is smaller, some of the pre-computed sampling intervals can be beyond
end-of-file, in which case we skip over those samples and the dictionary will
be a bit smaller. After the dictionary is generated using the first file in a
subcompaction, it is loaded into the compression library before writing each
block in each subsequent file of that subcompaction.
On the read path, gets the dictionary from the metablock, if it exists. Then,
loads that dictionary into the compression library before reading each block.
Test Plan: new unit test
Reviewers: yhchiang, IslamAbdelRahman, cyan, sdong
Reviewed By: sdong
Subscribers: andrewkr, yoshinorim, kradhakrishnan, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D52287
2016-04-28 00:36:03 +00:00
|
|
|
}
|
2015-02-20 03:11:14 +00:00
|
|
|
} else if (name == "compaction_options_fifo") {
|
|
|
|
new_options->compaction_options_fifo.max_table_files_size =
|
|
|
|
ParseUint64(value);
|
|
|
|
} else {
|
2015-08-26 23:13:56 +00:00
|
|
|
auto iter = cf_options_type_info.find(name);
|
|
|
|
if (iter == cf_options_type_info.end()) {
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return Status::InvalidArgument(
|
|
|
|
"Unable to parse the specified CF option " + name);
|
2015-08-26 23:13:56 +00:00
|
|
|
}
|
|
|
|
const auto& opt_info = iter->second;
|
2016-06-17 11:52:53 +00:00
|
|
|
if (opt_info.verification != OptionVerificationType::kDeprecated &&
|
|
|
|
ParseOptionHelper(
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
reinterpret_cast<char*>(new_options) + opt_info.offset,
|
|
|
|
opt_info.type, value)) {
|
|
|
|
return Status::OK();
|
|
|
|
}
|
|
|
|
switch (opt_info.verification) {
|
|
|
|
case OptionVerificationType::kByName:
|
2016-02-19 22:42:24 +00:00
|
|
|
case OptionVerificationType::kByNameAllowNull:
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return Status::NotSupported(
|
|
|
|
"Deserializing the specified CF option " + name +
|
|
|
|
" is not supported");
|
|
|
|
case OptionVerificationType::kDeprecated:
|
|
|
|
return Status::OK();
|
|
|
|
default:
|
|
|
|
return Status::InvalidArgument(
|
|
|
|
"Unable to parse the specified CF option " + name);
|
|
|
|
}
|
2015-02-20 03:11:14 +00:00
|
|
|
}
|
2015-11-02 22:11:28 +00:00
|
|
|
} catch (const std::exception&) {
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return Status::InvalidArgument(
|
|
|
|
"unable to parse the specified option " + name);
|
2015-02-20 03:11:14 +00:00
|
|
|
}
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return Status::OK();
|
2015-02-20 03:11:14 +00:00
|
|
|
}
|
|
|
|
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
bool SerializeSingleDBOption(std::string* opt_string,
|
|
|
|
const DBOptions& db_options,
|
|
|
|
const std::string& name,
|
|
|
|
const std::string& delimiter) {
|
2015-08-18 20:30:18 +00:00
|
|
|
auto iter = db_options_type_info.find(name);
|
|
|
|
if (iter == db_options_type_info.end()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto& opt_info = iter->second;
|
|
|
|
const char* opt_address =
|
|
|
|
reinterpret_cast<const char*>(&db_options) + opt_info.offset;
|
|
|
|
std::string value;
|
2015-08-26 23:13:56 +00:00
|
|
|
bool result = SerializeSingleOptionHelper(opt_address, opt_info.type, &value);
|
|
|
|
if (result) {
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
*opt_string = name + "=" + value + delimiter;
|
2015-08-18 20:30:18 +00:00
|
|
|
}
|
2015-08-26 23:13:56 +00:00
|
|
|
return result;
|
2015-08-18 20:30:18 +00:00
|
|
|
}
|
|
|
|
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
Status GetStringFromDBOptions(std::string* opt_string,
|
|
|
|
const DBOptions& db_options,
|
|
|
|
const std::string& delimiter) {
|
2015-08-18 20:30:18 +00:00
|
|
|
assert(opt_string);
|
|
|
|
opt_string->clear();
|
|
|
|
for (auto iter = db_options_type_info.begin();
|
|
|
|
iter != db_options_type_info.end(); ++iter) {
|
2015-09-30 00:58:00 +00:00
|
|
|
if (iter->second.verification == OptionVerificationType::kDeprecated) {
|
|
|
|
// If the option is no longer used in rocksdb and marked as deprecated,
|
|
|
|
// we skip it in the serialization.
|
|
|
|
continue;
|
|
|
|
}
|
2015-08-18 20:30:18 +00:00
|
|
|
std::string single_output;
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
bool result = SerializeSingleDBOption(&single_output, db_options,
|
|
|
|
iter->first, delimiter);
|
2015-08-18 20:30:18 +00:00
|
|
|
assert(result);
|
|
|
|
if (result) {
|
|
|
|
opt_string->append(single_output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Status::OK();
|
|
|
|
}
|
|
|
|
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
bool SerializeSingleColumnFamilyOption(std::string* opt_string,
|
|
|
|
const ColumnFamilyOptions& cf_options,
|
2015-08-26 23:13:56 +00:00
|
|
|
const std::string& name,
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
const std::string& delimiter) {
|
2015-08-26 23:13:56 +00:00
|
|
|
auto iter = cf_options_type_info.find(name);
|
|
|
|
if (iter == cf_options_type_info.end()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto& opt_info = iter->second;
|
|
|
|
const char* opt_address =
|
|
|
|
reinterpret_cast<const char*>(&cf_options) + opt_info.offset;
|
|
|
|
std::string value;
|
|
|
|
bool result = SerializeSingleOptionHelper(opt_address, opt_info.type, &value);
|
|
|
|
if (result) {
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
*opt_string = name + "=" + value + delimiter;
|
2015-08-26 23:13:56 +00:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
Status GetStringFromColumnFamilyOptions(std::string* opt_string,
|
|
|
|
const ColumnFamilyOptions& cf_options,
|
|
|
|
const std::string& delimiter) {
|
2015-08-26 23:13:56 +00:00
|
|
|
assert(opt_string);
|
|
|
|
opt_string->clear();
|
|
|
|
for (auto iter = cf_options_type_info.begin();
|
|
|
|
iter != cf_options_type_info.end(); ++iter) {
|
2015-09-30 00:13:02 +00:00
|
|
|
if (iter->second.verification == OptionVerificationType::kDeprecated) {
|
2015-09-30 00:58:00 +00:00
|
|
|
// If the option is no longer used in rocksdb and marked as deprecated,
|
|
|
|
// we skip it in the serialization.
|
2015-09-30 00:13:02 +00:00
|
|
|
continue;
|
|
|
|
}
|
2015-08-26 23:13:56 +00:00
|
|
|
std::string single_output;
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
bool result = SerializeSingleColumnFamilyOption(&single_output, cf_options,
|
|
|
|
iter->first, delimiter);
|
2015-08-26 23:13:56 +00:00
|
|
|
if (result) {
|
|
|
|
opt_string->append(single_output);
|
|
|
|
} else {
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
return Status::InvalidArgument("failed to serialize %s\n",
|
|
|
|
iter->first.c_str());
|
2015-08-26 23:13:56 +00:00
|
|
|
}
|
|
|
|
assert(result);
|
|
|
|
}
|
|
|
|
return Status::OK();
|
|
|
|
}
|
|
|
|
|
2016-05-18 22:03:21 +00:00
|
|
|
Status GetStringFromCompressionType(std::string* compression_str,
|
|
|
|
CompressionType compression_type) {
|
|
|
|
bool ok = SerializeEnum<CompressionType>(compression_type_string_map,
|
|
|
|
compression_type, compression_str);
|
|
|
|
if (ok) {
|
|
|
|
return Status::OK();
|
|
|
|
} else {
|
|
|
|
return Status::InvalidArgument("Invalid compression types");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-11 19:17:42 +00:00
|
|
|
bool SerializeSingleBlockBasedTableOption(
|
|
|
|
std::string* opt_string, const BlockBasedTableOptions& bbt_options,
|
|
|
|
const std::string& name, const std::string& delimiter) {
|
|
|
|
auto iter = block_based_table_type_info.find(name);
|
|
|
|
if (iter == block_based_table_type_info.end()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto& opt_info = iter->second;
|
|
|
|
const char* opt_address =
|
|
|
|
reinterpret_cast<const char*>(&bbt_options) + opt_info.offset;
|
|
|
|
std::string value;
|
|
|
|
bool result = SerializeSingleOptionHelper(opt_address, opt_info.type, &value);
|
|
|
|
if (result) {
|
|
|
|
*opt_string = name + "=" + value + delimiter;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status GetStringFromBlockBasedTableOptions(
|
|
|
|
std::string* opt_string, const BlockBasedTableOptions& bbt_options,
|
|
|
|
const std::string& delimiter) {
|
|
|
|
assert(opt_string);
|
|
|
|
opt_string->clear();
|
|
|
|
for (auto iter = block_based_table_type_info.begin();
|
|
|
|
iter != block_based_table_type_info.end(); ++iter) {
|
|
|
|
if (iter->second.verification == OptionVerificationType::kDeprecated) {
|
|
|
|
// If the option is no longer used in rocksdb and marked as deprecated,
|
|
|
|
// we skip it in the serialization.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
std::string single_output;
|
|
|
|
bool result = SerializeSingleBlockBasedTableOption(
|
|
|
|
&single_output, bbt_options, iter->first, delimiter);
|
|
|
|
assert(result);
|
|
|
|
if (result) {
|
|
|
|
opt_string->append(single_output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Status::OK();
|
|
|
|
}
|
|
|
|
|
|
|
|
Status GetStringFromTableFactory(std::string* opts_str, const TableFactory* tf,
|
|
|
|
const std::string& delimiter) {
|
|
|
|
const auto* bbtf = dynamic_cast<const BlockBasedTableFactory*>(tf);
|
|
|
|
opts_str->clear();
|
|
|
|
if (bbtf != nullptr) {
|
2015-11-18 00:41:54 +00:00
|
|
|
return GetStringFromBlockBasedTableOptions(opts_str, bbtf->table_options(),
|
|
|
|
delimiter);
|
2015-10-11 19:17:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return Status::OK();
|
|
|
|
}
|
|
|
|
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
Status ParseDBOption(const std::string& name,
|
|
|
|
const std::string& org_value,
|
|
|
|
DBOptions* new_options,
|
|
|
|
bool input_strings_escaped = false) {
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
const std::string& value =
|
2015-10-28 17:46:01 +00:00
|
|
|
input_strings_escaped ? UnescapeOptionString(org_value) : org_value;
|
2015-02-20 03:11:14 +00:00
|
|
|
try {
|
2015-08-18 20:30:18 +00:00
|
|
|
if (name == "rate_limiter_bytes_per_sec") {
|
2015-03-06 22:21:15 +00:00
|
|
|
new_options->rate_limiter.reset(
|
|
|
|
NewGenericRateLimiter(static_cast<int64_t>(ParseUint64(value))));
|
2015-02-20 03:11:14 +00:00
|
|
|
} else {
|
2015-08-18 20:30:18 +00:00
|
|
|
auto iter = db_options_type_info.find(name);
|
|
|
|
if (iter == db_options_type_info.end()) {
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return Status::InvalidArgument("Unrecognized option DBOptions:", name);
|
2015-08-18 20:30:18 +00:00
|
|
|
}
|
2015-08-26 23:13:56 +00:00
|
|
|
const auto& opt_info = iter->second;
|
2016-06-17 11:52:53 +00:00
|
|
|
if (opt_info.verification != OptionVerificationType::kDeprecated &&
|
|
|
|
ParseOptionHelper(
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
reinterpret_cast<char*>(new_options) + opt_info.offset,
|
|
|
|
opt_info.type, value)) {
|
|
|
|
return Status::OK();
|
|
|
|
}
|
|
|
|
switch (opt_info.verification) {
|
|
|
|
case OptionVerificationType::kByName:
|
2016-02-19 22:42:24 +00:00
|
|
|
case OptionVerificationType::kByNameAllowNull:
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return Status::NotSupported(
|
|
|
|
"Deserializing the specified DB option " + name +
|
|
|
|
" is not supported");
|
|
|
|
case OptionVerificationType::kDeprecated:
|
|
|
|
return Status::OK();
|
|
|
|
default:
|
|
|
|
return Status::InvalidArgument(
|
|
|
|
"Unable to parse the specified DB option " + name);
|
2015-10-02 22:35:32 +00:00
|
|
|
}
|
2015-02-20 03:11:14 +00:00
|
|
|
}
|
2015-11-02 22:11:28 +00:00
|
|
|
} catch (const std::exception&) {
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return Status::InvalidArgument("Unable to parse DBOptions:", name);
|
2015-02-20 03:11:14 +00:00
|
|
|
}
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return Status::OK();
|
2015-02-20 03:11:14 +00:00
|
|
|
}
|
2014-10-10 17:00:12 +00:00
|
|
|
|
2015-10-11 19:17:42 +00:00
|
|
|
std::string ParseBlockBasedTableOption(const std::string& name,
|
|
|
|
const std::string& org_value,
|
|
|
|
BlockBasedTableOptions* new_options,
|
2015-10-28 17:46:01 +00:00
|
|
|
bool input_strings_escaped = false) {
|
2015-10-11 19:17:42 +00:00
|
|
|
const std::string& value =
|
2015-10-28 17:46:01 +00:00
|
|
|
input_strings_escaped ? UnescapeOptionString(org_value) : org_value;
|
|
|
|
if (!input_strings_escaped) {
|
2015-10-11 19:17:42 +00:00
|
|
|
// if the input string is not escaped, it means this function is
|
|
|
|
// invoked from SetOptions, which takes the old format.
|
|
|
|
if (name == "block_cache") {
|
|
|
|
new_options->block_cache = NewLRUCache(ParseSizeT(value));
|
|
|
|
return "";
|
|
|
|
} else if (name == "block_cache_compressed") {
|
|
|
|
new_options->block_cache_compressed = NewLRUCache(ParseSizeT(value));
|
|
|
|
return "";
|
|
|
|
} else if (name == "filter_policy") {
|
|
|
|
// Expect the following format
|
|
|
|
// bloomfilter:int:bool
|
|
|
|
const std::string kName = "bloomfilter:";
|
|
|
|
if (value.compare(0, kName.size(), kName) != 0) {
|
|
|
|
return "Invalid filter policy name";
|
|
|
|
}
|
|
|
|
size_t pos = value.find(':', kName.size());
|
|
|
|
if (pos == std::string::npos) {
|
|
|
|
return "Invalid filter policy config, missing bits_per_key";
|
|
|
|
}
|
|
|
|
int bits_per_key =
|
|
|
|
ParseInt(trim(value.substr(kName.size(), pos - kName.size())));
|
|
|
|
bool use_block_based_builder =
|
|
|
|
ParseBoolean("use_block_based_builder", trim(value.substr(pos + 1)));
|
|
|
|
new_options->filter_policy.reset(
|
|
|
|
NewBloomFilterPolicy(bits_per_key, use_block_based_builder));
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const auto iter = block_based_table_type_info.find(name);
|
|
|
|
if (iter == block_based_table_type_info.end()) {
|
|
|
|
return "Unrecognized option";
|
|
|
|
}
|
|
|
|
const auto& opt_info = iter->second;
|
|
|
|
if (!ParseOptionHelper(reinterpret_cast<char*>(new_options) + opt_info.offset,
|
|
|
|
opt_info.type, value)) {
|
|
|
|
return "Invalid value";
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2015-10-28 17:46:01 +00:00
|
|
|
std::string ParsePlainTableOptions(const std::string& name,
|
|
|
|
const std::string& org_value,
|
|
|
|
PlainTableOptions* new_option,
|
|
|
|
bool input_strings_escaped = false) {
|
2015-11-16 20:56:21 +00:00
|
|
|
const std::string& value =
|
2015-10-28 17:46:01 +00:00
|
|
|
input_strings_escaped ? UnescapeOptionString(org_value) : org_value;
|
|
|
|
const auto iter = plain_table_type_info.find(name);
|
|
|
|
if (iter == plain_table_type_info.end()) {
|
|
|
|
return "Unrecognized option";
|
|
|
|
}
|
|
|
|
const auto& opt_info = iter->second;
|
|
|
|
if (!ParseOptionHelper(reinterpret_cast<char*>(new_option) + opt_info.offset,
|
|
|
|
opt_info.type, value)) {
|
|
|
|
return "Invalid value";
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2014-12-22 21:18:57 +00:00
|
|
|
Status GetBlockBasedTableOptionsFromMap(
|
|
|
|
const BlockBasedTableOptions& table_options,
|
|
|
|
const std::unordered_map<std::string, std::string>& opts_map,
|
2015-10-11 19:17:42 +00:00
|
|
|
BlockBasedTableOptions* new_table_options, bool input_strings_escaped) {
|
2014-12-22 21:18:57 +00:00
|
|
|
assert(new_table_options);
|
|
|
|
*new_table_options = table_options;
|
|
|
|
for (const auto& o : opts_map) {
|
2015-10-11 19:17:42 +00:00
|
|
|
auto error_message = ParseBlockBasedTableOption(
|
|
|
|
o.first, o.second, new_table_options, input_strings_escaped);
|
|
|
|
if (error_message != "") {
|
|
|
|
const auto iter = block_based_table_type_info.find(o.first);
|
|
|
|
if (iter == block_based_table_type_info.end() ||
|
|
|
|
!input_strings_escaped || // !input_strings_escaped indicates
|
|
|
|
// the old API, where everything is
|
|
|
|
// parsable.
|
|
|
|
(iter->second.verification != OptionVerificationType::kByName &&
|
2016-02-19 22:42:24 +00:00
|
|
|
iter->second.verification !=
|
|
|
|
OptionVerificationType::kByNameAllowNull &&
|
2015-10-11 19:17:42 +00:00
|
|
|
iter->second.verification != OptionVerificationType::kDeprecated)) {
|
|
|
|
return Status::InvalidArgument("Can't parse BlockBasedTableOptions:",
|
|
|
|
o.first + " " + error_message);
|
2014-12-22 21:18:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Status::OK();
|
|
|
|
}
|
|
|
|
|
|
|
|
Status GetBlockBasedTableOptionsFromString(
|
|
|
|
const BlockBasedTableOptions& table_options,
|
|
|
|
const std::string& opts_str,
|
|
|
|
BlockBasedTableOptions* new_table_options) {
|
|
|
|
std::unordered_map<std::string, std::string> opts_map;
|
|
|
|
Status s = StringToMap(opts_str, &opts_map);
|
|
|
|
if (!s.ok()) {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
return GetBlockBasedTableOptionsFromMap(table_options, opts_map,
|
|
|
|
new_table_options);
|
|
|
|
}
|
|
|
|
|
2015-07-01 23:13:49 +00:00
|
|
|
Status GetPlainTableOptionsFromMap(
|
|
|
|
const PlainTableOptions& table_options,
|
|
|
|
const std::unordered_map<std::string, std::string>& opts_map,
|
2015-10-28 17:46:01 +00:00
|
|
|
PlainTableOptions* new_table_options, bool input_strings_escaped) {
|
2015-07-01 23:13:49 +00:00
|
|
|
assert(new_table_options);
|
|
|
|
*new_table_options = table_options;
|
|
|
|
for (const auto& o : opts_map) {
|
2015-10-28 17:46:01 +00:00
|
|
|
auto error_message = ParsePlainTableOptions(
|
|
|
|
o.first, o.second, new_table_options, input_strings_escaped);
|
|
|
|
if (error_message != "") {
|
|
|
|
const auto iter = plain_table_type_info.find(o.first);
|
|
|
|
if (iter == plain_table_type_info.end() ||
|
2016-02-19 22:42:24 +00:00
|
|
|
!input_strings_escaped || // !input_strings_escaped indicates
|
|
|
|
// the old API, where everything is
|
|
|
|
// parsable.
|
2015-10-28 17:46:01 +00:00
|
|
|
(iter->second.verification != OptionVerificationType::kByName &&
|
2016-02-19 22:42:24 +00:00
|
|
|
iter->second.verification !=
|
|
|
|
OptionVerificationType::kByNameAllowNull &&
|
2015-10-28 17:46:01 +00:00
|
|
|
iter->second.verification != OptionVerificationType::kDeprecated)) {
|
|
|
|
return Status::InvalidArgument("Can't parse PlainTableOptions:",
|
|
|
|
o.first + " " + error_message);
|
2015-07-01 23:13:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Status::OK();
|
|
|
|
}
|
|
|
|
|
2015-10-28 17:46:01 +00:00
|
|
|
Status GetPlainTableOptionsFromString(
|
|
|
|
const PlainTableOptions& table_options,
|
|
|
|
const std::string& opts_str,
|
|
|
|
PlainTableOptions* new_table_options) {
|
|
|
|
std::unordered_map<std::string, std::string> opts_map;
|
|
|
|
Status s = StringToMap(opts_str, &opts_map);
|
|
|
|
if (!s.ok()) {
|
|
|
|
return s;
|
|
|
|
}
|
2015-11-16 20:56:21 +00:00
|
|
|
return GetPlainTableOptionsFromMap(table_options, opts_map,
|
2015-10-28 17:46:01 +00:00
|
|
|
new_table_options);
|
|
|
|
}
|
|
|
|
|
2015-11-17 22:29:01 +00:00
|
|
|
Status GetMemTableRepFactoryFromString(const std::string& opts_str,
|
|
|
|
std::unique_ptr<MemTableRepFactory>* new_mem_factory) {
|
|
|
|
std::vector<std::string> opts_list = StringSplit(opts_str, ':');
|
|
|
|
size_t len = opts_list.size();
|
|
|
|
|
|
|
|
if (opts_list.size() <= 0 || opts_list.size() > 2) {
|
|
|
|
return Status::InvalidArgument("Can't parse memtable_factory option ",
|
|
|
|
opts_str);
|
|
|
|
}
|
|
|
|
|
|
|
|
MemTableRepFactory* mem_factory = nullptr;
|
|
|
|
|
|
|
|
if (opts_list[0] == "skip_list") {
|
|
|
|
// Expecting format
|
|
|
|
// skip_list:<lookahead>
|
|
|
|
if (2 == len) {
|
|
|
|
size_t lookahead = ParseSizeT(opts_list[1]);
|
|
|
|
mem_factory = new SkipListFactory(lookahead);
|
|
|
|
} else if (1 == len) {
|
|
|
|
mem_factory = new SkipListFactory();
|
|
|
|
}
|
|
|
|
} else if (opts_list[0] == "prefix_hash") {
|
|
|
|
// Expecting format
|
|
|
|
// prfix_hash:<hash_bucket_count>
|
|
|
|
if (2 == len) {
|
|
|
|
size_t hash_bucket_count = ParseSizeT(opts_list[1]);
|
|
|
|
mem_factory = NewHashSkipListRepFactory(hash_bucket_count);
|
|
|
|
} else if (1 == len) {
|
|
|
|
mem_factory = NewHashSkipListRepFactory();
|
|
|
|
}
|
|
|
|
} else if (opts_list[0] == "hash_linkedlist") {
|
|
|
|
// Expecting format
|
|
|
|
// hash_linkedlist:<hash_bucket_count>
|
|
|
|
if (2 == len) {
|
|
|
|
size_t hash_bucket_count = ParseSizeT(opts_list[1]);
|
|
|
|
mem_factory = NewHashLinkListRepFactory(hash_bucket_count);
|
|
|
|
} else if (1 == len) {
|
|
|
|
mem_factory = NewHashLinkListRepFactory();
|
|
|
|
}
|
|
|
|
} else if (opts_list[0] == "vector") {
|
|
|
|
// Expecting format
|
|
|
|
// vector:<count>
|
|
|
|
if (2 == len) {
|
|
|
|
size_t count = ParseSizeT(opts_list[1]);
|
|
|
|
mem_factory = new VectorRepFactory(count);
|
|
|
|
} else if (1 == len) {
|
|
|
|
mem_factory = new VectorRepFactory();
|
|
|
|
}
|
|
|
|
} else if (opts_list[0] == "cuckoo") {
|
|
|
|
// Expecting format
|
|
|
|
// cuckoo:<write_buffer_size>
|
|
|
|
if (2 == len) {
|
|
|
|
size_t write_buffer_size = ParseSizeT(opts_list[1]);
|
|
|
|
mem_factory= NewHashCuckooRepFactory(write_buffer_size);
|
|
|
|
} else if (1 == len) {
|
|
|
|
return Status::InvalidArgument("Can't parse memtable_factory option ",
|
|
|
|
opts_str);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return Status::InvalidArgument("Unrecognized memtable_factory option ",
|
|
|
|
opts_str);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mem_factory != nullptr){
|
|
|
|
new_mem_factory->reset(mem_factory);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status::OK();
|
|
|
|
}
|
|
|
|
|
2014-12-22 21:18:57 +00:00
|
|
|
Status GetColumnFamilyOptionsFromMap(
|
2014-10-10 17:00:12 +00:00
|
|
|
const ColumnFamilyOptions& base_options,
|
|
|
|
const std::unordered_map<std::string, std::string>& opts_map,
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
ColumnFamilyOptions* new_options, bool input_strings_escaped) {
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return GetColumnFamilyOptionsFromMapInternal(
|
|
|
|
base_options, opts_map, new_options, input_strings_escaped);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status GetColumnFamilyOptionsFromMapInternal(
|
|
|
|
const ColumnFamilyOptions& base_options,
|
|
|
|
const std::unordered_map<std::string, std::string>& opts_map,
|
|
|
|
ColumnFamilyOptions* new_options, bool input_strings_escaped,
|
|
|
|
std::vector<std::string>* unsupported_options_names) {
|
2014-09-17 19:46:32 +00:00
|
|
|
assert(new_options);
|
|
|
|
*new_options = base_options;
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
if (unsupported_options_names) {
|
|
|
|
unsupported_options_names->clear();
|
|
|
|
}
|
2014-10-10 17:00:12 +00:00
|
|
|
for (const auto& o : opts_map) {
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
auto s = ParseColumnFamilyOption(o.first, o.second, new_options,
|
|
|
|
input_strings_escaped);
|
|
|
|
if (!s.ok()) {
|
|
|
|
if (s.IsNotSupported()) {
|
|
|
|
// If the deserialization of the specified option is not supported
|
|
|
|
// and an output vector of unsupported_options is provided, then
|
|
|
|
// we log the name of the unsupported option and proceed.
|
|
|
|
if (unsupported_options_names != nullptr) {
|
|
|
|
unsupported_options_names->push_back(o.first);
|
|
|
|
}
|
|
|
|
// Note that we still return Status::OK in such case to maintain
|
|
|
|
// the backward compatibility in the old public API defined in
|
|
|
|
// rocksdb/convenience.h
|
|
|
|
} else {
|
|
|
|
return s;
|
2015-10-02 22:35:32 +00:00
|
|
|
}
|
2014-10-10 17:00:12 +00:00
|
|
|
}
|
|
|
|
}
|
2014-12-22 21:18:57 +00:00
|
|
|
return Status::OK();
|
2014-10-10 17:00:12 +00:00
|
|
|
}
|
|
|
|
|
2014-12-22 21:18:57 +00:00
|
|
|
Status GetColumnFamilyOptionsFromString(
|
2014-10-10 17:00:12 +00:00
|
|
|
const ColumnFamilyOptions& base_options,
|
|
|
|
const std::string& opts_str,
|
|
|
|
ColumnFamilyOptions* new_options) {
|
|
|
|
std::unordered_map<std::string, std::string> opts_map;
|
2014-12-22 21:18:57 +00:00
|
|
|
Status s = StringToMap(opts_str, &opts_map);
|
|
|
|
if (!s.ok()) {
|
|
|
|
return s;
|
2014-10-10 17:00:12 +00:00
|
|
|
}
|
|
|
|
return GetColumnFamilyOptionsFromMap(base_options, opts_map, new_options);
|
|
|
|
}
|
|
|
|
|
2014-12-22 21:18:57 +00:00
|
|
|
Status GetDBOptionsFromMap(
|
2014-10-10 17:00:12 +00:00
|
|
|
const DBOptions& base_options,
|
|
|
|
const std::unordered_map<std::string, std::string>& opts_map,
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
DBOptions* new_options, bool input_strings_escaped) {
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
return GetDBOptionsFromMapInternal(
|
|
|
|
base_options, opts_map, new_options, input_strings_escaped);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status GetDBOptionsFromMapInternal(
|
|
|
|
const DBOptions& base_options,
|
|
|
|
const std::unordered_map<std::string, std::string>& opts_map,
|
|
|
|
DBOptions* new_options, bool input_strings_escaped,
|
|
|
|
std::vector<std::string>* unsupported_options_names) {
|
2014-10-10 17:00:12 +00:00
|
|
|
assert(new_options);
|
|
|
|
*new_options = base_options;
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
if (unsupported_options_names) {
|
|
|
|
unsupported_options_names->clear();
|
|
|
|
}
|
2014-10-10 17:00:12 +00:00
|
|
|
for (const auto& o : opts_map) {
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
auto s = ParseDBOption(o.first, o.second,
|
|
|
|
new_options, input_strings_escaped);
|
|
|
|
if (!s.ok()) {
|
|
|
|
if (s.IsNotSupported()) {
|
|
|
|
// If the deserialization of the specified option is not supported
|
|
|
|
// and an output vector of unsupported_options is provided, then
|
|
|
|
// we log the name of the unsupported option and proceed.
|
|
|
|
if (unsupported_options_names != nullptr) {
|
|
|
|
unsupported_options_names->push_back(o.first);
|
|
|
|
}
|
|
|
|
// Note that we still return Status::OK in such case to maintain
|
|
|
|
// the backward compatibility in the old public API defined in
|
|
|
|
// rocksdb/convenience.h
|
|
|
|
} else {
|
|
|
|
return s;
|
|
|
|
}
|
2014-09-17 19:46:32 +00:00
|
|
|
}
|
|
|
|
}
|
2014-12-22 21:18:57 +00:00
|
|
|
return Status::OK();
|
2014-09-17 19:46:32 +00:00
|
|
|
}
|
|
|
|
|
2014-12-22 21:18:57 +00:00
|
|
|
Status GetDBOptionsFromString(
|
2014-10-10 17:00:12 +00:00
|
|
|
const DBOptions& base_options,
|
|
|
|
const std::string& opts_str,
|
|
|
|
DBOptions* new_options) {
|
|
|
|
std::unordered_map<std::string, std::string> opts_map;
|
2014-12-22 21:18:57 +00:00
|
|
|
Status s = StringToMap(opts_str, &opts_map);
|
|
|
|
if (!s.ok()) {
|
|
|
|
return s;
|
2014-10-10 17:00:12 +00:00
|
|
|
}
|
|
|
|
return GetDBOptionsFromMap(base_options, opts_map, new_options);
|
|
|
|
}
|
|
|
|
|
2015-02-20 03:11:14 +00:00
|
|
|
Status GetOptionsFromString(const Options& base_options,
|
|
|
|
const std::string& opts_str, Options* new_options) {
|
|
|
|
std::unordered_map<std::string, std::string> opts_map;
|
|
|
|
Status s = StringToMap(opts_str, &opts_map);
|
|
|
|
if (!s.ok()) {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
DBOptions new_db_options(base_options);
|
|
|
|
ColumnFamilyOptions new_cf_options(base_options);
|
|
|
|
for (const auto& o : opts_map) {
|
Add OptionsUtil::LoadOptionsFromFile() API
Summary:
This patch adds OptionsUtil::LoadOptionsFromFile() and
OptionsUtil::LoadLatestOptionsFromDB(), which allow developers
to construct DBOptions and ColumnFamilyOptions from a RocksDB
options file. Note that most pointer-typed options such as
merge_operator will not be constructed.
With this API, developers no longer need to remember all the
options in order to reopen an existing rocksdb instance like
the following:
DBOptions db_options;
std::vector<std::string> cf_names;
std::vector<ColumnFamilyOptions> cf_opts;
// Load primitive-typed options from an existing DB
OptionsUtil::LoadLatestOptionsFromDB(
dbname, &db_options, &cf_names, &cf_opts);
// Initialize necessary pointer-typed options
cf_opts[0].merge_operator.reset(new MyMergeOperator());
...
// Construct the vector of ColumnFamilyDescriptor
std::vector<ColumnFamilyDescriptor> cf_descs;
for (size_t i = 0; i < cf_opts.size(); ++i) {
cf_descs.emplace_back(cf_names[i], cf_opts[i]);
}
// Open the DB
DB* db = nullptr;
std::vector<ColumnFamilyHandle*> cf_handles;
auto s = DB::Open(db_options, dbname, cf_descs,
&handles, &db);
Test Plan:
Augment existing tests in column_family_test
options_test
db_test
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D49095
2015-11-12 14:52:43 +00:00
|
|
|
if (ParseDBOption(o.first, o.second, &new_db_options).ok()) {
|
|
|
|
} else if (ParseColumnFamilyOption(
|
|
|
|
o.first, o.second, &new_cf_options).ok()) {
|
2015-02-20 03:11:14 +00:00
|
|
|
} else {
|
|
|
|
return Status::InvalidArgument("Can't parse option " + o.first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*new_options = Options(new_db_options, new_cf_options);
|
|
|
|
return Status::OK();
|
|
|
|
}
|
|
|
|
|
2015-10-11 19:17:42 +00:00
|
|
|
Status GetTableFactoryFromMap(
|
|
|
|
const std::string& factory_name,
|
|
|
|
const std::unordered_map<std::string, std::string>& opt_map,
|
|
|
|
std::shared_ptr<TableFactory>* table_factory) {
|
|
|
|
Status s;
|
|
|
|
if (factory_name == BlockBasedTableFactory().Name()) {
|
|
|
|
BlockBasedTableOptions bbt_opt;
|
|
|
|
s = GetBlockBasedTableOptionsFromMap(BlockBasedTableOptions(), opt_map,
|
|
|
|
&bbt_opt, true);
|
|
|
|
if (!s.ok()) {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
table_factory->reset(new BlockBasedTableFactory(bbt_opt));
|
|
|
|
return Status::OK();
|
2015-10-28 17:46:01 +00:00
|
|
|
} else if (factory_name == PlainTableFactory().Name()) {
|
|
|
|
PlainTableOptions pt_opt;
|
2015-11-16 20:56:21 +00:00
|
|
|
s = GetPlainTableOptionsFromMap(PlainTableOptions(), opt_map, &pt_opt,
|
|
|
|
true);
|
2015-10-28 17:46:01 +00:00
|
|
|
if (!s.ok()) {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
table_factory->reset(new PlainTableFactory(pt_opt));
|
|
|
|
return Status::OK();
|
2015-10-11 19:17:42 +00:00
|
|
|
}
|
|
|
|
// Return OK for not supported table factories as TableFactory
|
|
|
|
// Deserialization is optional.
|
|
|
|
table_factory->reset();
|
|
|
|
return Status::OK();
|
|
|
|
}
|
|
|
|
|
2015-11-11 06:58:01 +00:00
|
|
|
ColumnFamilyOptions BuildColumnFamilyOptions(
|
|
|
|
const Options& options, const MutableCFOptions& mutable_cf_options) {
|
|
|
|
ColumnFamilyOptions cf_opts(options);
|
|
|
|
|
|
|
|
// Memtable related options
|
|
|
|
cf_opts.write_buffer_size = mutable_cf_options.write_buffer_size;
|
|
|
|
cf_opts.max_write_buffer_number = mutable_cf_options.max_write_buffer_number;
|
|
|
|
cf_opts.arena_block_size = mutable_cf_options.arena_block_size;
|
2016-06-04 00:02:10 +00:00
|
|
|
cf_opts.memtable_prefix_bloom_size_ratio =
|
|
|
|
mutable_cf_options.memtable_prefix_bloom_size_ratio;
|
2015-11-11 06:58:01 +00:00
|
|
|
cf_opts.memtable_prefix_bloom_huge_page_tlb_size =
|
|
|
|
mutable_cf_options.memtable_prefix_bloom_huge_page_tlb_size;
|
|
|
|
cf_opts.max_successive_merges = mutable_cf_options.max_successive_merges;
|
|
|
|
cf_opts.inplace_update_num_locks =
|
|
|
|
mutable_cf_options.inplace_update_num_locks;
|
|
|
|
|
|
|
|
// Compaction related options
|
|
|
|
cf_opts.disable_auto_compactions =
|
|
|
|
mutable_cf_options.disable_auto_compactions;
|
|
|
|
cf_opts.level0_file_num_compaction_trigger =
|
|
|
|
mutable_cf_options.level0_file_num_compaction_trigger;
|
|
|
|
cf_opts.level0_slowdown_writes_trigger =
|
|
|
|
mutable_cf_options.level0_slowdown_writes_trigger;
|
|
|
|
cf_opts.level0_stop_writes_trigger =
|
|
|
|
mutable_cf_options.level0_stop_writes_trigger;
|
|
|
|
cf_opts.max_grandparent_overlap_factor =
|
|
|
|
mutable_cf_options.max_grandparent_overlap_factor;
|
|
|
|
cf_opts.expanded_compaction_factor =
|
|
|
|
mutable_cf_options.expanded_compaction_factor;
|
|
|
|
cf_opts.source_compaction_factor =
|
|
|
|
mutable_cf_options.source_compaction_factor;
|
|
|
|
cf_opts.target_file_size_base = mutable_cf_options.target_file_size_base;
|
|
|
|
cf_opts.target_file_size_multiplier =
|
|
|
|
mutable_cf_options.target_file_size_multiplier;
|
|
|
|
cf_opts.max_bytes_for_level_base =
|
|
|
|
mutable_cf_options.max_bytes_for_level_base;
|
|
|
|
cf_opts.max_bytes_for_level_multiplier =
|
|
|
|
mutable_cf_options.max_bytes_for_level_multiplier;
|
|
|
|
|
|
|
|
cf_opts.max_bytes_for_level_multiplier_additional.clear();
|
|
|
|
for (auto value :
|
|
|
|
mutable_cf_options.max_bytes_for_level_multiplier_additional) {
|
|
|
|
cf_opts.max_bytes_for_level_multiplier_additional.emplace_back(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
cf_opts.verify_checksums_in_compaction =
|
|
|
|
mutable_cf_options.verify_checksums_in_compaction;
|
|
|
|
|
|
|
|
// Misc options
|
|
|
|
cf_opts.max_sequential_skip_in_iterations =
|
|
|
|
mutable_cf_options.max_sequential_skip_in_iterations;
|
|
|
|
cf_opts.paranoid_file_checks = mutable_cf_options.paranoid_file_checks;
|
2016-04-14 20:56:29 +00:00
|
|
|
cf_opts.report_bg_io_stats = mutable_cf_options.report_bg_io_stats;
|
2015-11-11 06:58:01 +00:00
|
|
|
|
|
|
|
cf_opts.table_factory = options.table_factory;
|
|
|
|
// TODO(yhchiang): find some way to handle the following derived options
|
|
|
|
// * max_file_size
|
|
|
|
|
|
|
|
return cf_opts;
|
|
|
|
}
|
|
|
|
|
RocksDB Options file format and its serialization / deserialization.
Summary:
This patch defines the format of RocksDB options file, which
follows the INI file format, and implements functions for its
serialization and deserialization. An example RocksDB options
file can be found in examples/rocksdb_option_file_example.ini.
A typical RocksDB options file has three sections, which are
Version, DBOptions, and more than one CFOptions. The RocksDB
options file in general follows the basic INI file format
with the following extensions / modifications:
* Escaped characters
We escaped the following characters:
- \n -- line feed - new line
- \r -- carriage return
- \\ -- backslash \
- \: -- colon symbol :
- \# -- hash tag #
* Comments
We support # style comments. Comments can appear at the ending
part of a line.
* Statements
A statement is of the form option_name = value.
Each statement contains a '=', where extra white-spaces
are supported. However, we don't support multi-lined statement.
Furthermore, each line can only contain at most one statement.
* Section
Sections are of the form [SecitonTitle "SectionArgument"],
where section argument is optional.
* List
We use colon-separated string to represent a list.
For instance, n1:n2:n3:n4 is a list containing four values.
Below is an example of a RocksDB options file:
[Version]
rocksdb_version=4.0.0
options_file_version=1.0
[DBOptions]
max_open_files=12345
max_background_flushes=301
[CFOptions "default"]
[CFOptions "the second column family"]
[CFOptions "the third column family"]
Test Plan: Added many tests in options_test.cc
Reviewers: igor, IslamAbdelRahman, sdong, anthony
Reviewed By: anthony
Subscribers: maykov, dhruba, leveldb
Differential Revision: https://reviews.facebook.net/D46059
2015-09-29 21:42:40 +00:00
|
|
|
#endif // !ROCKSDB_LITE
|
2014-09-17 19:46:32 +00:00
|
|
|
} // namespace rocksdb
|