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 #ifndef ROCKSDB_LITE
7 
8 #include "rocksdb/utilities/options_util.h"
9 
10 #include "env/composite_env_wrapper.h"
11 #include "file/filename.h"
12 #include "options/options_parser.h"
13 #include "rocksdb/options.h"
14 
15 namespace ROCKSDB_NAMESPACE {
LoadOptionsFromFile(const std::string & file_name,Env * env,DBOptions * db_options,std::vector<ColumnFamilyDescriptor> * cf_descs,bool ignore_unknown_options,std::shared_ptr<Cache> * cache)16 Status LoadOptionsFromFile(const std::string& file_name, Env* env,
17                            DBOptions* db_options,
18                            std::vector<ColumnFamilyDescriptor>* cf_descs,
19                            bool ignore_unknown_options,
20                            std::shared_ptr<Cache>* cache) {
21   RocksDBOptionsParser parser;
22   LegacyFileSystemWrapper fs(env);
23   Status s = parser.Parse(file_name, &fs, ignore_unknown_options,
24                           0 /* file_readahead_size */);
25   if (!s.ok()) {
26     return s;
27   }
28   *db_options = *parser.db_opt();
29   const std::vector<std::string>& cf_names = *parser.cf_names();
30   const std::vector<ColumnFamilyOptions>& cf_opts = *parser.cf_opts();
31   cf_descs->clear();
32   for (size_t i = 0; i < cf_opts.size(); ++i) {
33     cf_descs->push_back({cf_names[i], cf_opts[i]});
34     if (cache != nullptr) {
35       TableFactory* tf = cf_opts[i].table_factory.get();
36       if (tf != nullptr && tf->GetOptions() != nullptr &&
37           tf->Name() == BlockBasedTableFactory().Name()) {
38         auto* loaded_bbt_opt =
39             reinterpret_cast<BlockBasedTableOptions*>(tf->GetOptions());
40         loaded_bbt_opt->block_cache = *cache;
41       }
42     }
43   }
44   return Status::OK();
45 }
46 
GetLatestOptionsFileName(const std::string & dbpath,Env * env,std::string * options_file_name)47 Status GetLatestOptionsFileName(const std::string& dbpath,
48                                 Env* env, std::string* options_file_name) {
49   Status s;
50   std::string latest_file_name;
51   uint64_t latest_time_stamp = 0;
52   std::vector<std::string> file_names;
53   s = env->GetChildren(dbpath, &file_names);
54   if (!s.ok()) {
55     return s;
56   }
57   for (auto& file_name : file_names) {
58     uint64_t time_stamp;
59     FileType type;
60     if (ParseFileName(file_name, &time_stamp, &type) && type == kOptionsFile) {
61       if (time_stamp > latest_time_stamp) {
62         latest_time_stamp = time_stamp;
63         latest_file_name = file_name;
64       }
65     }
66   }
67   if (latest_file_name.size() == 0) {
68     return Status::NotFound("No options files found in the DB directory.");
69   }
70   *options_file_name = latest_file_name;
71   return Status::OK();
72 }
73 
LoadLatestOptions(const std::string & dbpath,Env * env,DBOptions * db_options,std::vector<ColumnFamilyDescriptor> * cf_descs,bool ignore_unknown_options,std::shared_ptr<Cache> * cache)74 Status LoadLatestOptions(const std::string& dbpath, Env* env,
75                          DBOptions* db_options,
76                          std::vector<ColumnFamilyDescriptor>* cf_descs,
77                          bool ignore_unknown_options,
78                          std::shared_ptr<Cache>* cache) {
79   std::string options_file_name;
80   Status s = GetLatestOptionsFileName(dbpath, env, &options_file_name);
81   if (!s.ok()) {
82     return s;
83   }
84   return LoadOptionsFromFile(dbpath + "/" + options_file_name, env, db_options,
85                              cf_descs, ignore_unknown_options, cache);
86 }
87 
CheckOptionsCompatibility(const std::string & dbpath,Env * env,const DBOptions & db_options,const std::vector<ColumnFamilyDescriptor> & cf_descs,bool ignore_unknown_options)88 Status CheckOptionsCompatibility(
89     const std::string& dbpath, Env* env, const DBOptions& db_options,
90     const std::vector<ColumnFamilyDescriptor>& cf_descs,
91     bool ignore_unknown_options) {
92   std::string options_file_name;
93   Status s = GetLatestOptionsFileName(dbpath, env, &options_file_name);
94   if (!s.ok()) {
95     return s;
96   }
97 
98   std::vector<std::string> cf_names;
99   std::vector<ColumnFamilyOptions> cf_opts;
100   for (const auto& cf_desc : cf_descs) {
101     cf_names.push_back(cf_desc.name);
102     cf_opts.push_back(cf_desc.options);
103   }
104 
105   const OptionsSanityCheckLevel kDefaultLevel = kSanityLevelLooselyCompatible;
106   LegacyFileSystemWrapper fs(env);
107 
108   return RocksDBOptionsParser::VerifyRocksDBOptionsFromFile(
109       db_options, cf_names, cf_opts, dbpath + "/" + options_file_name, &fs,
110       kDefaultLevel, ignore_unknown_options);
111 }
112 
113 }  // namespace ROCKSDB_NAMESPACE
114 #endif  // !ROCKSDB_LITE
115