summaryrefslogtreecommitdiffstats
path: root/src/rocksdb/options/customizable.cc
blob: cd39550e524f8941f9b6040055fea9678abc37c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
//  This source code is licensed under both the GPLv2 (found in the
//  COPYING file in the root directory) and Apache 2.0 License
//  (found in the LICENSE.Apache file in the root directory).

#include "rocksdb/customizable.h"

#include <sstream>

#include "options/options_helper.h"
#include "port/port.h"
#include "rocksdb/convenience.h"
#include "rocksdb/status.h"
#include "rocksdb/utilities/options_type.h"
#include "util/string_util.h"

namespace ROCKSDB_NAMESPACE {

std::string Customizable::GetOptionName(const std::string& long_name) const {
  const std::string& name = Name();
  size_t name_len = name.size();
  if (long_name.size() > name_len + 1 &&
      long_name.compare(0, name_len, name) == 0 &&
      long_name.at(name_len) == '.') {
    return long_name.substr(name_len + 1);
  } else {
    return Configurable::GetOptionName(long_name);
  }
}

std::string Customizable::GenerateIndividualId() const {
  std::ostringstream ostr;
  ostr << Name() << "@" << static_cast<const void*>(this) << "#"
       << port::GetProcessID();
  return ostr.str();
}

#ifndef ROCKSDB_LITE
Status Customizable::GetOption(const ConfigOptions& config_options,
                               const std::string& opt_name,
                               std::string* value) const {
  if (opt_name == OptionTypeInfo::kIdPropName()) {
    *value = GetId();
    return Status::OK();
  } else {
    return Configurable::GetOption(config_options, opt_name, value);
  }
}

std::string Customizable::SerializeOptions(const ConfigOptions& config_options,
                                           const std::string& prefix) const {
  std::string result;
  std::string parent;
  std::string id = GetId();
  if (!config_options.IsShallow() && !id.empty()) {
    parent = Configurable::SerializeOptions(config_options, "");
  }
  if (parent.empty()) {
    result = id;
  } else {
    result.append(prefix);
    result.append(OptionTypeInfo::kIdPropName());
    result.append("=");
    result.append(id);
    result.append(config_options.delimiter);
    result.append(parent);
  }
  return result;
}

#endif  // ROCKSDB_LITE

bool Customizable::AreEquivalent(const ConfigOptions& config_options,
                                 const Configurable* other,
                                 std::string* mismatch) const {
  if (config_options.sanity_level > ConfigOptions::kSanityLevelNone &&
      this != other) {
    const Customizable* custom = reinterpret_cast<const Customizable*>(other);
    if (custom == nullptr) {  // Cast failed
      return false;
    } else if (GetId() != custom->GetId()) {
      *mismatch = OptionTypeInfo::kIdPropName();
      return false;
    } else if (config_options.sanity_level >
               ConfigOptions::kSanityLevelLooselyCompatible) {
      bool matches =
          Configurable::AreEquivalent(config_options, other, mismatch);
      return matches;
    }
  }
  return true;
}

Status Customizable::GetOptionsMap(
    const ConfigOptions& config_options, const Customizable* customizable,
    const std::string& value, std::string* id,
    std::unordered_map<std::string, std::string>* props) {
  Status status;
  if (value.empty() || value == kNullptrString) {
    *id = "";
    props->clear();
  } else if (customizable != nullptr) {
    status =
        Configurable::GetOptionsMap(value, customizable->GetId(), id, props);
#ifdef ROCKSDB_LITE
    (void)config_options;
#else
    if (status.ok() && customizable->IsInstanceOf(*id)) {
      // The new ID and the old ID match, so the objects are the same type.
      // Try to get the existing options, ignoring any errors
      ConfigOptions embedded = config_options;
      embedded.delimiter = ";";
      std::string curr_opts;
      if (customizable->GetOptionString(embedded, &curr_opts).ok()) {
        std::unordered_map<std::string, std::string> curr_props;
        if (StringToMap(curr_opts, &curr_props).ok()) {
          props->insert(curr_props.begin(), curr_props.end());
        }
      }
    }
#endif  // ROCKSDB_LITE
  } else {
    status = Configurable::GetOptionsMap(value, "", id, props);
  }
  return status;
}

Status Customizable::ConfigureNewObject(
    const ConfigOptions& config_options, Customizable* object,
    const std::unordered_map<std::string, std::string>& opt_map) {
  Status status;
  if (object != nullptr) {
    status = object->ConfigureFromMap(config_options, opt_map);
  } else if (!opt_map.empty()) {
    status = Status::InvalidArgument("Cannot configure null object ");
  }
  return status;
}
}  // namespace ROCKSDB_NAMESPACE