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 #include <string>
8 
9 #include "db/db_impl/db_impl.h"
10 #include "db/db_test_util.h"
11 #include "rocksdb/options.h"
12 #include "rocksdb/table.h"
13 #include "test_util/testharness.h"
14 
15 namespace ROCKSDB_NAMESPACE {
16 class OptionsFileTest : public testing::Test {
17  public:
OptionsFileTest()18   OptionsFileTest() : dbname_(test::PerThreadDBPath("options_file_test")) {}
19 
20   std::string dbname_;
21 };
22 
23 namespace {
UpdateOptionsFiles(DB * db,std::unordered_set<std::string> * filename_history,int * options_files_count)24 void UpdateOptionsFiles(DB* db,
25                         std::unordered_set<std::string>* filename_history,
26                         int* options_files_count) {
27   std::vector<std::string> filenames;
28   db->GetEnv()->GetChildren(db->GetName(), &filenames);
29   uint64_t number;
30   FileType type;
31   *options_files_count = 0;
32   for (auto filename : filenames) {
33     if (ParseFileName(filename, &number, &type) && type == kOptionsFile) {
34       filename_history->insert(filename);
35       (*options_files_count)++;
36     }
37   }
38 }
39 
40 // Verify whether the current Options Files are the latest ones.
VerifyOptionsFileName(DB * db,const std::unordered_set<std::string> & past_filenames)41 void VerifyOptionsFileName(
42     DB* db, const std::unordered_set<std::string>& past_filenames) {
43   std::vector<std::string> filenames;
44   std::unordered_set<std::string> current_filenames;
45   db->GetEnv()->GetChildren(db->GetName(), &filenames);
46   uint64_t number;
47   FileType type;
48   for (auto filename : filenames) {
49     if (ParseFileName(filename, &number, &type) && type == kOptionsFile) {
50       current_filenames.insert(filename);
51     }
52   }
53   for (auto past_filename : past_filenames) {
54     if (current_filenames.find(past_filename) != current_filenames.end()) {
55       continue;
56     }
57     for (auto filename : current_filenames) {
58       ASSERT_GT(filename, past_filename);
59     }
60   }
61 }
62 }  // namespace
63 
TEST_F(OptionsFileTest,NumberOfOptionsFiles)64 TEST_F(OptionsFileTest, NumberOfOptionsFiles) {
65   const int kReopenCount = 20;
66   Options opt;
67   opt.create_if_missing = true;
68   DestroyDB(dbname_, opt);
69   std::unordered_set<std::string> filename_history;
70   DB* db;
71   for (int i = 0; i < kReopenCount; ++i) {
72     ASSERT_OK(DB::Open(opt, dbname_, &db));
73     int num_options_files = 0;
74     UpdateOptionsFiles(db, &filename_history, &num_options_files);
75     ASSERT_GT(num_options_files, 0);
76     ASSERT_LE(num_options_files, 2);
77     // Make sure we always keep the latest option files.
78     VerifyOptionsFileName(db, filename_history);
79     delete db;
80   }
81 }
82 
TEST_F(OptionsFileTest,OptionsFileName)83 TEST_F(OptionsFileTest, OptionsFileName) {
84   const uint64_t kOptionsFileNum = 12345;
85   uint64_t number;
86   FileType type;
87 
88   auto options_file_name = OptionsFileName("", kOptionsFileNum);
89   ASSERT_TRUE(ParseFileName(options_file_name, &number, &type, nullptr));
90   ASSERT_EQ(type, kOptionsFile);
91   ASSERT_EQ(number, kOptionsFileNum);
92 
93   const uint64_t kTempOptionsFileNum = 54352;
94   auto temp_options_file_name = TempOptionsFileName("", kTempOptionsFileNum);
95   ASSERT_TRUE(ParseFileName(temp_options_file_name, &number, &type, nullptr));
96   ASSERT_NE(temp_options_file_name.find(kTempFileNameSuffix),
97             std::string::npos);
98   ASSERT_EQ(type, kTempFile);
99   ASSERT_EQ(number, kTempOptionsFileNum);
100 }
101 }  // namespace ROCKSDB_NAMESPACE
102 
main(int argc,char ** argv)103 int main(int argc, char** argv) {
104 #if !(defined NDEBUG) || !defined(OS_WIN)
105   ::testing::InitGoogleTest(&argc, argv);
106   return RUN_ALL_TESTS();
107 #else
108   return 0;
109 #endif  // !(defined NDEBUG) || !defined(OS_WIN)
110 }
111 #else
112 
113 #include <cstdio>
114 
main(int,char **)115 int main(int /*argc*/, char** /*argv*/) {
116   printf("Skipped as Options file is not supported in RocksDBLite.\n");
117   return 0;
118 }
119 #endif  // !ROCKSDB_LITE
120