]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/util/fault_injection_test_env.h
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / rocksdb / util / fault_injection_test_env.h
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under the BSD-style license found in the
3 // LICENSE file in the root directory of this source tree. An additional grant
4 // of patent rights can be found in the PATENTS file in the same directory.
5 //
6 // Copyright 2014 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9
10 // This test uses a custom Env to keep track of the state of a filesystem as of
11 // the last "sync". It then checks for data loss errors by purposely dropping
12 // file data (or entire files) not protected by a "sync".
13
14 #ifndef UTIL_FAULT_INJECTION_TEST_ENV_H_
15 #define UTIL_FAULT_INJECTION_TEST_ENV_H_
16
17 #include <map>
18 #include <set>
19 #include <string>
20
21 #include "db/version_set.h"
22 #include "env/mock_env.h"
23 #include "rocksdb/db.h"
24 #include "rocksdb/env.h"
25 #include "util/filename.h"
26 #include "util/mutexlock.h"
27 #include "util/random.h"
28
29 namespace rocksdb {
30
31 class TestWritableFile;
32 class FaultInjectionTestEnv;
33
34 struct FileState {
35 std::string filename_;
36 ssize_t pos_;
37 ssize_t pos_at_last_sync_;
38 ssize_t pos_at_last_flush_;
39
40 explicit FileState(const std::string& filename)
41 : filename_(filename),
42 pos_(-1),
43 pos_at_last_sync_(-1),
44 pos_at_last_flush_(-1) {}
45
46 FileState() : pos_(-1), pos_at_last_sync_(-1), pos_at_last_flush_(-1) {}
47
48 bool IsFullySynced() const { return pos_ <= 0 || pos_ == pos_at_last_sync_; }
49
50 Status DropUnsyncedData(Env* env) const;
51
52 Status DropRandomUnsyncedData(Env* env, Random* rand) const;
53 };
54
55 // A wrapper around WritableFileWriter* file
56 // is written to or sync'ed.
57 class TestWritableFile : public WritableFile {
58 public:
59 explicit TestWritableFile(const std::string& fname,
60 unique_ptr<WritableFile>&& f,
61 FaultInjectionTestEnv* env);
62 virtual ~TestWritableFile();
63 virtual Status Append(const Slice& data) override;
64 virtual Status Truncate(uint64_t size) override {
65 return target_->Truncate(size);
66 }
67 virtual Status Close() override;
68 virtual Status Flush() override;
69 virtual Status Sync() override;
70 virtual bool IsSyncThreadSafe() const override { return true; }
71
72 private:
73 FileState state_;
74 unique_ptr<WritableFile> target_;
75 bool writable_file_opened_;
76 FaultInjectionTestEnv* env_;
77 };
78
79 class TestDirectory : public Directory {
80 public:
81 explicit TestDirectory(FaultInjectionTestEnv* env, std::string dirname,
82 Directory* dir)
83 : env_(env), dirname_(dirname), dir_(dir) {}
84 ~TestDirectory() {}
85
86 virtual Status Fsync() override;
87
88 private:
89 FaultInjectionTestEnv* env_;
90 std::string dirname_;
91 unique_ptr<Directory> dir_;
92 };
93
94 class FaultInjectionTestEnv : public EnvWrapper {
95 public:
96 explicit FaultInjectionTestEnv(Env* base)
97 : EnvWrapper(base), filesystem_active_(true) {}
98 virtual ~FaultInjectionTestEnv() {}
99
100 Status NewDirectory(const std::string& name,
101 unique_ptr<Directory>* result) override;
102
103 Status NewWritableFile(const std::string& fname,
104 unique_ptr<WritableFile>* result,
105 const EnvOptions& soptions) override;
106
107 virtual Status DeleteFile(const std::string& f) override;
108
109 virtual Status RenameFile(const std::string& s,
110 const std::string& t) override;
111
112 void WritableFileClosed(const FileState& state);
113
114 // For every file that is not fully synced, make a call to `func` with
115 // FileState of the file as the parameter.
116 Status DropFileData(std::function<Status(Env*, FileState)> func);
117
118 Status DropUnsyncedFileData();
119
120 Status DropRandomUnsyncedFileData(Random* rnd);
121
122 Status DeleteFilesCreatedAfterLastDirSync();
123
124 void ResetState();
125
126 void UntrackFile(const std::string& f);
127
128 void SyncDir(const std::string& dirname) {
129 MutexLock l(&mutex_);
130 dir_to_new_files_since_last_sync_.erase(dirname);
131 }
132
133 // Setting the filesystem to inactive is the test equivalent to simulating a
134 // system reset. Setting to inactive will freeze our saved filesystem state so
135 // that it will stop being recorded. It can then be reset back to the state at
136 // the time of the reset.
137 bool IsFilesystemActive() {
138 MutexLock l(&mutex_);
139 return filesystem_active_;
140 }
141 void SetFilesystemActiveNoLock(bool active) { filesystem_active_ = active; }
142 void SetFilesystemActive(bool active) {
143 MutexLock l(&mutex_);
144 SetFilesystemActiveNoLock(active);
145 }
146 void AssertNoOpenFile() { assert(open_files_.empty()); }
147
148 private:
149 port::Mutex mutex_;
150 std::map<std::string, FileState> db_file_state_;
151 std::set<std::string> open_files_;
152 std::unordered_map<std::string, std::set<std::string>>
153 dir_to_new_files_since_last_sync_;
154 bool filesystem_active_; // Record flushes, syncs, writes
155 };
156
157 } // namespace rocksdb
158
159 #endif // UTIL_FAULT_INJECTION_TEST_ENV_H_