// A basic file truncation function suitable for this test.
Status Truncate(Env* env, const std::string& filename, uint64_t length) {
- unique_ptr<SequentialFile> orig_file;
+ std::unique_ptr<SequentialFile> orig_file;
const EnvOptions options;
Status s = env->NewSequentialFile(filename, &orig_file, options);
if (!s.ok()) {
- fprintf(stderr, "Cannot truncate file %s: %s\n", filename.c_str(),
- s.ToString().c_str());
+ fprintf(stderr, "Cannot open file %s for truncation: %s\n",
+ filename.c_str(), s.ToString().c_str());
return s;
}
#endif
if (s.ok()) {
std::string tmp_name = GetDirName(filename) + "/truncate.tmp";
- unique_ptr<WritableFile> tmp_file;
+ std::unique_ptr<WritableFile> tmp_file;
s = env->NewWritableFile(tmp_name, &tmp_file, options);
if (s.ok()) {
s = tmp_file->Append(result);
}
TestWritableFile::TestWritableFile(const std::string& fname,
- unique_ptr<WritableFile>&& f,
+ std::unique_ptr<WritableFile>&& f,
FaultInjectionTestEnv* env)
: state_(fname),
target_(std::move(f)),
Status s = target_->Append(data);
if (s.ok()) {
state_.pos_ += data.size();
+ env_->WritableFileAppended(state_);
}
return s;
}
}
// No need to actual sync.
state_.pos_at_last_sync_ = state_.pos_;
+ env_->WritableFileSynced(state_);
return Status::OK();
}
Status FaultInjectionTestEnv::NewDirectory(const std::string& name,
- unique_ptr<Directory>* result) {
- unique_ptr<Directory> r;
+ std::unique_ptr<Directory>* result) {
+ std::unique_ptr<Directory> r;
Status s = target()->NewDirectory(name, &r);
assert(s.ok());
if (!s.ok()) {
return Status::OK();
}
-Status FaultInjectionTestEnv::NewWritableFile(const std::string& fname,
- unique_ptr<WritableFile>* result,
- const EnvOptions& soptions) {
+Status FaultInjectionTestEnv::NewWritableFile(
+ const std::string& fname, std::unique_ptr<WritableFile>* result,
+ const EnvOptions& soptions) {
if (!IsFilesystemActive()) {
return GetError();
}
return s;
}
+Status FaultInjectionTestEnv::ReopenWritableFile(
+ const std::string& fname, std::unique_ptr<WritableFile>* result,
+ const EnvOptions& soptions) {
+ if (!IsFilesystemActive()) {
+ return GetError();
+ }
+ Status s = target()->ReopenWritableFile(fname, result, soptions);
+ if (s.ok()) {
+ result->reset(new TestWritableFile(fname, std::move(*result), this));
+ // WritableFileWriter* file is opened
+ // again then it will be truncated - so forget our saved state.
+ UntrackFile(fname);
+ MutexLock l(&mutex_);
+ open_files_.insert(fname);
+ auto dir_and_name = GetDirAndName(fname);
+ auto& list = dir_to_new_files_since_last_sync_[dir_and_name.first];
+ list.insert(dir_and_name.second);
+ }
+ return s;
+}
+
Status FaultInjectionTestEnv::NewRandomAccessFile(
const std::string& fname, std::unique_ptr<RandomAccessFile>* result,
const EnvOptions& soptions) {
}
}
+void FaultInjectionTestEnv::WritableFileSynced(const FileState& state) {
+ MutexLock l(&mutex_);
+ if (open_files_.find(state.filename_) != open_files_.end()) {
+ if (db_file_state_.find(state.filename_) == db_file_state_.end()) {
+ db_file_state_.insert(std::make_pair(state.filename_, state));
+ } else {
+ db_file_state_[state.filename_] = state;
+ }
+ }
+}
+
+void FaultInjectionTestEnv::WritableFileAppended(const FileState& state) {
+ MutexLock l(&mutex_);
+ if (open_files_.find(state.filename_) != open_files_.end()) {
+ if (db_file_state_.find(state.filename_) == db_file_state_.end()) {
+ db_file_state_.insert(std::make_pair(state.filename_, state));
+ } else {
+ db_file_state_[state.filename_] = state;
+ }
+ }
+}
+
// For every file that is not fully synced, make a call to `func` with
// FileState of the file as the parameter.
Status FaultInjectionTestEnv::DropFileData(