1 // Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 #pragma once
7 
8 #include <map>
9 #include <string>
10 #include <vector>
11 
12 #include "options/options_sanity_check.h"
13 #include "rocksdb/env.h"
14 #include "rocksdb/options.h"
15 #include "table/block_based/block_based_table_factory.h"
16 
17 namespace ROCKSDB_NAMESPACE {
18 
19 #ifndef ROCKSDB_LITE
20 
21 #define ROCKSDB_OPTION_FILE_MAJOR 1
22 #define ROCKSDB_OPTION_FILE_MINOR 1
23 
24 enum OptionSection : char {
25   kOptionSectionVersion = 0,
26   kOptionSectionDBOptions,
27   kOptionSectionCFOptions,
28   kOptionSectionTableOptions,
29   kOptionSectionUnknown
30 };
31 
32 static const std::string opt_section_titles[] = {
33     "Version", "DBOptions", "CFOptions", "TableOptions/", "Unknown"};
34 
35 Status PersistRocksDBOptions(const DBOptions& db_opt,
36                              const std::vector<std::string>& cf_names,
37                              const std::vector<ColumnFamilyOptions>& cf_opts,
38                              const std::string& file_name, FileSystem* fs);
39 
40 extern bool AreEqualOptions(
41     const char* opt1, const char* opt2, const OptionTypeInfo& type_info,
42     const std::string& opt_name,
43     const std::unordered_map<std::string, std::string>* opt_map);
44 
45 class RocksDBOptionsParser {
46  public:
47   explicit RocksDBOptionsParser();
~RocksDBOptionsParser()48   ~RocksDBOptionsParser() {}
49   void Reset();
50 
51   // `file_readahead_size` is used for readahead for the option file.
52   // If 0 is given, a default value will be used.
53   Status Parse(const std::string& file_name, FileSystem* fs,
54                bool ignore_unknown_options, size_t file_readahead_size);
55   static std::string TrimAndRemoveComment(const std::string& line,
56                                           const bool trim_only = false);
57 
db_opt()58   const DBOptions* db_opt() const { return &db_opt_; }
db_opt_map()59   const std::unordered_map<std::string, std::string>* db_opt_map() const {
60     return &db_opt_map_;
61   }
cf_opts()62   const std::vector<ColumnFamilyOptions>* cf_opts() const { return &cf_opts_; }
cf_names()63   const std::vector<std::string>* cf_names() const { return &cf_names_; }
cf_opt_maps()64   const std::vector<std::unordered_map<std::string, std::string>>* cf_opt_maps()
65       const {
66     return &cf_opt_maps_;
67   }
68 
GetCFOptions(const std::string & name)69   const ColumnFamilyOptions* GetCFOptions(const std::string& name) {
70     return GetCFOptionsImpl(name);
71   }
NumColumnFamilies()72   size_t NumColumnFamilies() { return cf_opts_.size(); }
73 
74   static Status VerifyRocksDBOptionsFromFile(
75       const DBOptions& db_opt, const std::vector<std::string>& cf_names,
76       const std::vector<ColumnFamilyOptions>& cf_opts,
77       const std::string& file_name, FileSystem* fs,
78       OptionsSanityCheckLevel sanity_check_level = kSanityLevelExactMatch,
79       bool ignore_unknown_options = false);
80 
81   static Status VerifyDBOptions(
82       const DBOptions& base_opt, const DBOptions& new_opt,
83       const std::unordered_map<std::string, std::string>* new_opt_map = nullptr,
84       OptionsSanityCheckLevel sanity_check_level = kSanityLevelExactMatch);
85 
86   static Status VerifyCFOptions(
87       const ColumnFamilyOptions& base_opt, const ColumnFamilyOptions& new_opt,
88       const std::unordered_map<std::string, std::string>* new_opt_map = nullptr,
89       OptionsSanityCheckLevel sanity_check_level = kSanityLevelExactMatch);
90 
91   static Status VerifyTableFactory(
92       const TableFactory* base_tf, const TableFactory* file_tf,
93       OptionsSanityCheckLevel sanity_check_level = kSanityLevelExactMatch);
94 
95   static Status ExtraParserCheck(const RocksDBOptionsParser& input_parser);
96 
97  protected:
98   bool IsSection(const std::string& line);
99   Status ParseSection(OptionSection* section, std::string* title,
100                       std::string* argument, const std::string& line,
101                       const int line_num);
102 
103   Status CheckSection(const OptionSection section,
104                       const std::string& section_arg, const int line_num);
105 
106   Status ParseStatement(std::string* name, std::string* value,
107                         const std::string& line, const int line_num);
108 
109   Status EndSection(const OptionSection section, const std::string& title,
110                     const std::string& section_arg,
111                     const std::unordered_map<std::string, std::string>& opt_map,
112                     bool ignore_unknown_options);
113 
114   Status ValidityCheck();
115 
116   Status InvalidArgument(const int line_num, const std::string& message);
117 
118   Status ParseVersionNumber(const std::string& ver_name,
119                             const std::string& ver_string, const int max_count,
120                             int* version);
121 
GetCFOptionsImpl(const std::string & name)122   ColumnFamilyOptions* GetCFOptionsImpl(const std::string& name) {
123     assert(cf_names_.size() == cf_opts_.size());
124     for (size_t i = 0; i < cf_names_.size(); ++i) {
125       if (cf_names_[i] == name) {
126         return &cf_opts_[i];
127       }
128     }
129     return nullptr;
130   }
131 
132  private:
133   DBOptions db_opt_;
134   std::unordered_map<std::string, std::string> db_opt_map_;
135   std::vector<std::string> cf_names_;
136   std::vector<ColumnFamilyOptions> cf_opts_;
137   std::vector<std::unordered_map<std::string, std::string>> cf_opt_maps_;
138   bool has_version_section_;
139   bool has_db_options_;
140   bool has_default_cf_options_;
141   int db_version[3];
142   int opt_file_version[3];
143 };
144 
145 #endif  // !ROCKSDB_LITE
146 
147 }  // namespace ROCKSDB_NAMESPACE
148