]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/util/fault_injection_test_env.h
bump version to 12.2.12-pve1
[ceph.git] / ceph / src / rocksdb / util / fault_injection_test_env.h
CommitLineData
7c673cae
FG
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
29namespace rocksdb {
30
31class TestWritableFile;
32class FaultInjectionTestEnv;
33
34struct 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.
57class 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
79class 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
94class 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_