37 static std::string
GetDirName(
const std::string filename) {
38 size_t found = filename.find_last_of(
"/\\");
39 if (found == std::string::npos) {
42 return filename.substr(0, found);
60 char* scratch =
new char[length];
62 s = orig_file->
Read(length, &result, scratch);
65 std::string tmp_name =
GetDirName(filename) +
"/truncate.tmp";
69 s = tmp_file->
Append(result);
91 : filename_(filename),
93 pos_at_last_sync_(-1),
94 pos_at_last_flush_(-1) { }
96 FileState() : pos_(-1), pos_at_last_sync_(-1), pos_at_last_flush_(-1) {}
98 bool IsFullySynced()
const {
return pos_ <= 0 || pos_ == pos_at_last_sync_; }
100 Status DropUnsyncedData()
const;
164 writable_file_opened_(true),
220 if (s.
ok() && !ps.
ok()) {
230 Status s = target()->NewWritableFile(fname, &actual_writable_file);
232 FileState state(fname);
240 new_files_since_last_dir_sync_.insert(fname);
248 Status s = target()->NewAppendableFile(fname, &actual_writable_file);
250 FileState state(fname);
254 if (db_file_state_.count(fname) == 0) {
255 new_files_since_last_dir_sync_.insert(fname);
257 state = db_file_state_[fname];
268 for (std::map<std::string, FileState>::const_iterator it =
269 db_file_state_.begin();
270 s.
ok() && it != db_file_state_.end(); ++it) {
271 const FileState& state = it->second;
272 if (!state.IsFullySynced()) {
273 s = state.DropUnsyncedData();
281 new_files_since_last_dir_sync_.clear();
285 const std::string& filename) {
287 return new_files_since_last_dir_sync_.find(filename) !=
288 new_files_since_last_dir_sync_.end();
293 db_file_state_.erase(f);
294 new_files_since_last_dir_sync_.erase(f);
307 const std::string& t) {
312 if (db_file_state_.find(s) != db_file_state_.end()) {
313 db_file_state_[t] = db_file_state_[s];
314 db_file_state_.erase(s);
317 if (new_files_since_last_dir_sync_.erase(s) != 0) {
318 assert(new_files_since_last_dir_sync_.find(t) ==
319 new_files_since_last_dir_sync_.end());
320 new_files_since_last_dir_sync_.insert(t);
332 SetFilesystemActive(
true);
338 std::set<std::string> new_files(new_files_since_last_dir_sync_.begin(),
339 new_files_since_last_dir_sync_.end());
342 std::set<std::string>::const_iterator it;
343 for (it = new_files.begin(); s.
ok() && it != new_files.end(); ++it) {
351 db_file_state_[state.filename_] = state;
354 Status FileState::DropUnsyncedData()
const {
355 ssize_t sync_pos = pos_at_last_sync_ == -1 ? 0 : pos_at_last_sync_;
356 return Truncate(filename_, sync_pos);
362 enum ResetMethod { RESET_DROP_UNSYNCED_DATA, RESET_DELETE_UNSYNCED_FILES };
394 void Build(
int start_idx,
int num_vals) {
395 std::string key_space, value_space;
397 for (
int i = start_idx; i < start_idx + num_vals; i++) {
400 batch.
Put(key,
Value(i, &value_space));
407 std::string key_space, value_space;
409 Value(i, &value_space);
411 return db_->
Get(options, key, val);
417 std::string value_space;
419 for (
int i = start_idx; i < start_idx + num_vals && s.
ok(); i++) {
420 Value(i, &value_space);
421 s = ReadValue(i, &val);
422 if (expected == VAL_EXPECT_NO_ERROR) {
427 fprintf(stderr,
"Expected an error at %d, but was OK\n", i);
439 snprintf(buf,
sizeof(buf),
"%016d", i);
440 storage->assign(buf, strlen(buf));
441 return Slice(*storage);
454 return DB::Open(options_, dbname_, &db_);
473 switch (reset_method) {
474 case RESET_DROP_UNSYNCED_DATA:
477 case RESET_DELETE_UNSYNCED_FILES:
487 Build(0, num_pre_sync);
489 Build(num_pre_sync, num_post_sync);
497 ResetDBState(reset_method);
508 ResetDBState(reset_method);
516 int num_pre_sync = rnd.
Uniform(kMaxNumValues);
517 int num_post_sync = rnd.
Uniform(kMaxNumValues);
519 PartialCompactTestPreFault(num_pre_sync, num_post_sync);
520 PartialCompactTestReopenWithFault(RESET_DROP_UNSYNCED_DATA,
524 NoWriteTestPreFault();
525 NoWriteTestReopenWithFault(RESET_DROP_UNSYNCED_DATA);
527 PartialCompactTestPreFault(num_pre_sync, num_post_sync);
530 PartialCompactTestReopenWithFault(RESET_DELETE_UNSYNCED_FILES,
531 num_pre_sync + num_post_sync,
534 NoWriteTestPreFault();
535 NoWriteTestReopenWithFault(RESET_DELETE_UNSYNCED_FILES);
552 int main(
int argc,
char** argv) {
static const size_t kNumIterations
bool IsFileCreatedSinceLastDirSync(const std::string &filename)
ssize_t pos_at_last_flush_
virtual Slice key() const =0
virtual void CompactRange(const Slice *begin, const Slice *end)=0
static const int kMaxNumValues
Status DeleteFilesCreatedAfterLastDirSync()
Status ReadValue(int i, std::string *val) const
virtual void SeekToFirst()=0
virtual Status Append(const Slice &data)
void NoWriteTestReopenWithFault(ResetMethod reset_method)
static const int kValueSize
virtual Status NewWritableFile(const std::string &fname, WritableFile **result)=0
Status DestroyDB(const std::string &dbname, const Options &options)
void PartialCompactTestReopenWithFault(ResetMethod reset_method, int num_pre_sync, int num_post_sync)
FaultInjectionTestEnv * env_
Status Truncate(const std::string &filename, uint64_t length)
int main(int argc, char **argv)
Status Verify(int start_idx, int num_vals, ExpectedVerifResult expected) const
virtual Status Delete(const WriteOptions &options, const Slice &key)=0
ssize_t pos_at_last_sync_
static std::string GetDirName(const std::string filename)
virtual Status Get(const ReadOptions &options, const Slice &key, std::string *value)=0
static Status Open(const Options &options, const std::string &name, DB **dbptr)
bool IsFilesystemActive() const
virtual Status NewWritableFile(const std::string &fname, WritableFile **result)
void WritableFileClosed(const FileState &state)
Status RenameFile(const std::string &s, const std::string &t)
Status SyncDir(const std::string &dir)
void ResetDBState(ResetMethod reset_method)
TEST(AutoCompactTest, ReadAll)
Status DeleteFile(const std::string &f)
Status DropUnsyncedFileData()
virtual Status RenameFile(const std::string &src, const std::string &target)=0
Slice Value(int k, std::string *storage) const
void Build(int start_idx, int num_vals)
Slice Key(int i, std::string *storage) const
void ReuseLogs(bool reuse)
virtual Status NewAppendableFile(const std::string &fname, WritableFile **result)
virtual Status Write(const WriteOptions &options, WriteBatch *updates)=0
virtual Status Read(size_t n, Slice *result, char *scratch)=0
Cache * NewLRUCache(size_t capacity)
std::map< std::string, FileState > db_file_state_
uint32_t Value(const char *data, size_t n)
virtual Status NewSequentialFile(const std::string &fname, SequentialFile **result)=0
FileState(const std::string &filename)
virtual ~FaultInjectionTestEnv()
void PartialCompactTestPreFault(int num_pre_sync, int num_post_sync)
virtual Iterator * NewIterator(const ReadOptions &options)=0
virtual Status DeleteFile(const std::string &f)
std::set< std::string > new_files_since_last_dir_sync_
void UntrackFile(const std::string &f)
virtual Status Append(const Slice &data)=0
TestWritableFile(const FileState &state, WritableFile *f, FaultInjectionTestEnv *env)
bool writable_file_opened_
virtual ~TestWritableFile()
void SetFilesystemActive(bool active)
Slice RandomString(Random *rnd, int len, std::string *dst)
virtual Status DeleteFile(const std::string &fname)=0
static Status IOError(const Slice &msg, const Slice &msg2=Slice())
void NoWriteTestPreFault()
virtual bool Valid() const =0
void Put(const Slice &key, const Slice &value)
virtual Status RenameFile(const std::string &s, const std::string &t)
bool IsFullySynced() const
FaultInjectionTestEnv * env_