]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/util/fault_injection_test_env.h
import 14.2.4 nautilus point release
[ceph.git] / ceph / src / rocksdb / util / fault_injection_test_env.h
CommitLineData
7c673cae 1// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
11fdf7f2
TL
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).
7c673cae
FG
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
11fdf7f2 14#pragma once
7c673cae
FG
15
16#include <map>
17#include <set>
18#include <string>
19
20#include "db/version_set.h"
21#include "env/mock_env.h"
22#include "rocksdb/db.h"
23#include "rocksdb/env.h"
24#include "util/filename.h"
25#include "util/mutexlock.h"
26#include "util/random.h"
27
28namespace rocksdb {
29
30class TestWritableFile;
31class FaultInjectionTestEnv;
32
33struct FileState {
34 std::string filename_;
35 ssize_t pos_;
36 ssize_t pos_at_last_sync_;
37 ssize_t pos_at_last_flush_;
38
39 explicit FileState(const std::string& filename)
40 : filename_(filename),
41 pos_(-1),
42 pos_at_last_sync_(-1),
43 pos_at_last_flush_(-1) {}
44
45 FileState() : pos_(-1), pos_at_last_sync_(-1), pos_at_last_flush_(-1) {}
46
47 bool IsFullySynced() const { return pos_ <= 0 || pos_ == pos_at_last_sync_; }
48
49 Status DropUnsyncedData(Env* env) const;
50
51 Status DropRandomUnsyncedData(Env* env, Random* rand) const;
52};
53
54// A wrapper around WritableFileWriter* file
55// is written to or sync'ed.
56class TestWritableFile : public WritableFile {
57 public:
58 explicit TestWritableFile(const std::string& fname,
494da23a 59 std::unique_ptr<WritableFile>&& f,
7c673cae
FG
60 FaultInjectionTestEnv* env);
61 virtual ~TestWritableFile();
62 virtual Status Append(const Slice& data) override;
63 virtual Status Truncate(uint64_t size) override {
64 return target_->Truncate(size);
65 }
66 virtual Status Close() override;
67 virtual Status Flush() override;
68 virtual Status Sync() override;
69 virtual bool IsSyncThreadSafe() const override { return true; }
11fdf7f2
TL
70 virtual Status PositionedAppend(const Slice& data,
71 uint64_t offset) override {
72 return target_->PositionedAppend(data, offset);
73 }
74 virtual bool use_direct_io() const override {
75 return target_->use_direct_io();
76 };
7c673cae
FG
77
78 private:
79 FileState state_;
494da23a 80 std::unique_ptr<WritableFile> target_;
7c673cae
FG
81 bool writable_file_opened_;
82 FaultInjectionTestEnv* env_;
83};
84
85class TestDirectory : public Directory {
86 public:
87 explicit TestDirectory(FaultInjectionTestEnv* env, std::string dirname,
88 Directory* dir)
89 : env_(env), dirname_(dirname), dir_(dir) {}
90 ~TestDirectory() {}
91
92 virtual Status Fsync() override;
93
94 private:
95 FaultInjectionTestEnv* env_;
96 std::string dirname_;
494da23a 97 std::unique_ptr<Directory> dir_;
7c673cae
FG
98};
99
100class FaultInjectionTestEnv : public EnvWrapper {
101 public:
102 explicit FaultInjectionTestEnv(Env* base)
103 : EnvWrapper(base), filesystem_active_(true) {}
104 virtual ~FaultInjectionTestEnv() {}
105
106 Status NewDirectory(const std::string& name,
494da23a 107 std::unique_ptr<Directory>* result) override;
7c673cae
FG
108
109 Status NewWritableFile(const std::string& fname,
494da23a 110 std::unique_ptr<WritableFile>* result,
7c673cae
FG
111 const EnvOptions& soptions) override;
112
494da23a
TL
113 Status ReopenWritableFile(const std::string& fname,
114 std::unique_ptr<WritableFile>* result,
115 const EnvOptions& soptions) override;
116
11fdf7f2
TL
117 Status NewRandomAccessFile(const std::string& fname,
118 std::unique_ptr<RandomAccessFile>* result,
119 const EnvOptions& soptions) override;
120
7c673cae
FG
121 virtual Status DeleteFile(const std::string& f) override;
122
123 virtual Status RenameFile(const std::string& s,
124 const std::string& t) override;
125
11fdf7f2
TL
126 virtual Status GetFreeSpace(const std::string& path,
127 uint64_t* disk_free) override {
128 if (!IsFilesystemActive() && error_ == Status::NoSpace()) {
129 *disk_free = 0;
130 return Status::OK();
131 } else {
132 return target()->GetFreeSpace(path, disk_free);
133 }
134 }
135
7c673cae
FG
136 void WritableFileClosed(const FileState& state);
137
494da23a
TL
138 void WritableFileSynced(const FileState& state);
139
140 void WritableFileAppended(const FileState& state);
141
7c673cae
FG
142 // For every file that is not fully synced, make a call to `func` with
143 // FileState of the file as the parameter.
144 Status DropFileData(std::function<Status(Env*, FileState)> func);
145
146 Status DropUnsyncedFileData();
147
148 Status DropRandomUnsyncedFileData(Random* rnd);
149
150 Status DeleteFilesCreatedAfterLastDirSync();
151
152 void ResetState();
153
154 void UntrackFile(const std::string& f);
155
156 void SyncDir(const std::string& dirname) {
157 MutexLock l(&mutex_);
158 dir_to_new_files_since_last_sync_.erase(dirname);
159 }
160
161 // Setting the filesystem to inactive is the test equivalent to simulating a
162 // system reset. Setting to inactive will freeze our saved filesystem state so
163 // that it will stop being recorded. It can then be reset back to the state at
164 // the time of the reset.
165 bool IsFilesystemActive() {
166 MutexLock l(&mutex_);
167 return filesystem_active_;
168 }
11fdf7f2
TL
169 void SetFilesystemActiveNoLock(bool active,
170 Status error = Status::Corruption("Not active")) {
171 filesystem_active_ = active;
172 if (!active) {
173 error_ = error;
174 }
175 }
176 void SetFilesystemActive(bool active,
177 Status error = Status::Corruption("Not active")) {
7c673cae 178 MutexLock l(&mutex_);
11fdf7f2 179 SetFilesystemActiveNoLock(active, error);
7c673cae
FG
180 }
181 void AssertNoOpenFile() { assert(open_files_.empty()); }
11fdf7f2 182 Status GetError() { return error_; }
7c673cae
FG
183
184 private:
185 port::Mutex mutex_;
186 std::map<std::string, FileState> db_file_state_;
187 std::set<std::string> open_files_;
188 std::unordered_map<std::string, std::set<std::string>>
189 dir_to_new_files_since_last_sync_;
190 bool filesystem_active_; // Record flushes, syncs, writes
11fdf7f2 191 Status error_;
7c673cae
FG
192};
193
194} // namespace rocksdb