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.
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.
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".
14 #ifndef UTIL_FAULT_INJECTION_TEST_ENV_H_
15 #define UTIL_FAULT_INJECTION_TEST_ENV_H_
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"
31 class TestWritableFile
;
32 class FaultInjectionTestEnv
;
35 std::string filename_
;
37 ssize_t pos_at_last_sync_
;
38 ssize_t pos_at_last_flush_
;
40 explicit FileState(const std::string
& filename
)
41 : filename_(filename
),
43 pos_at_last_sync_(-1),
44 pos_at_last_flush_(-1) {}
46 FileState() : pos_(-1), pos_at_last_sync_(-1), pos_at_last_flush_(-1) {}
48 bool IsFullySynced() const { return pos_
<= 0 || pos_
== pos_at_last_sync_
; }
50 Status
DropUnsyncedData(Env
* env
) const;
52 Status
DropRandomUnsyncedData(Env
* env
, Random
* rand
) const;
55 // A wrapper around WritableFileWriter* file
56 // is written to or sync'ed.
57 class TestWritableFile
: public WritableFile
{
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
);
67 virtual Status
Close() override
;
68 virtual Status
Flush() override
;
69 virtual Status
Sync() override
;
70 virtual bool IsSyncThreadSafe() const override
{ return true; }
74 unique_ptr
<WritableFile
> target_
;
75 bool writable_file_opened_
;
76 FaultInjectionTestEnv
* env_
;
79 class TestDirectory
: public Directory
{
81 explicit TestDirectory(FaultInjectionTestEnv
* env
, std::string dirname
,
83 : env_(env
), dirname_(dirname
), dir_(dir
) {}
86 virtual Status
Fsync() override
;
89 FaultInjectionTestEnv
* env_
;
91 unique_ptr
<Directory
> dir_
;
94 class FaultInjectionTestEnv
: public EnvWrapper
{
96 explicit FaultInjectionTestEnv(Env
* base
)
97 : EnvWrapper(base
), filesystem_active_(true) {}
98 virtual ~FaultInjectionTestEnv() {}
100 Status
NewDirectory(const std::string
& name
,
101 unique_ptr
<Directory
>* result
) override
;
103 Status
NewWritableFile(const std::string
& fname
,
104 unique_ptr
<WritableFile
>* result
,
105 const EnvOptions
& soptions
) override
;
107 virtual Status
DeleteFile(const std::string
& f
) override
;
109 virtual Status
RenameFile(const std::string
& s
,
110 const std::string
& t
) override
;
112 void WritableFileClosed(const FileState
& state
);
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
);
118 Status
DropUnsyncedFileData();
120 Status
DropRandomUnsyncedFileData(Random
* rnd
);
122 Status
DeleteFilesCreatedAfterLastDirSync();
126 void UntrackFile(const std::string
& f
);
128 void SyncDir(const std::string
& dirname
) {
129 MutexLock
l(&mutex_
);
130 dir_to_new_files_since_last_sync_
.erase(dirname
);
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_
;
141 void SetFilesystemActiveNoLock(bool active
) { filesystem_active_
= active
; }
142 void SetFilesystemActive(bool active
) {
143 MutexLock
l(&mutex_
);
144 SetFilesystemActiveNoLock(active
);
146 void AssertNoOpenFile() { assert(open_files_
.empty()); }
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
157 } // namespace rocksdb
159 #endif // UTIL_FAULT_INJECTION_TEST_ENV_H_