From 0ddf5f73ec6918adfa4b07940a59c3c1cc478ac7 Mon Sep 17 00:00:00 2001 From: sdong Date: Fri, 16 Jan 2015 15:12:54 -0800 Subject: [PATCH] memenv: normalize file path Summary: Now using memenv, DB will not able to be reopened, since a "//" in the file name. Fix it by normalizing file path. Test Plan: Add a unit test that used to fail and now pass. Reviewers: rven, yhchiang, igor Reviewed By: igor Subscribers: leveldb, dhruba Differential Revision: https://reviews.facebook.net/D31767 --- helpers/memenv/memenv.cc | 57 ++++++++++++++++++++++++++--------- helpers/memenv/memenv_test.cc | 9 ++++++ 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/helpers/memenv/memenv.cc b/helpers/memenv/memenv.cc index b6499f4e0..d13fa55eb 100644 --- a/helpers/memenv/memenv.cc +++ b/helpers/memenv/memenv.cc @@ -15,6 +15,26 @@ namespace rocksdb { namespace { +std::string NormalizeFileName(const std::string fname) { + if (fname.find("//") == std::string::npos) { + return fname; + } + std::string out_name = ""; + bool is_slash = false; + for (char c : fname) { + if (c == '/' && is_slash) { + continue; + } + out_name.append(1, c); + if (c == '/') { + is_slash = true; + } else { + is_slash = false; + } + } + return out_name; +} + class FileState { public: // FileStates are reference counted. The initial reference count is zero @@ -238,40 +258,43 @@ class InMemoryEnv : public EnvWrapper { virtual Status NewSequentialFile(const std::string& fname, unique_ptr* result, const EnvOptions& soptions) { + std::string nfname = NormalizeFileName(fname); MutexLock lock(&mutex_); if (file_map_.find(fname) == file_map_.end()) { *result = NULL; return Status::IOError(fname, "File not found"); } - result->reset(new SequentialFileImpl(file_map_[fname])); + result->reset(new SequentialFileImpl(file_map_[nfname])); return Status::OK(); } virtual Status NewRandomAccessFile(const std::string& fname, unique_ptr* result, const EnvOptions& soptions) { + std::string nfname = NormalizeFileName(fname); MutexLock lock(&mutex_); - if (file_map_.find(fname) == file_map_.end()) { + if (file_map_.find(nfname) == file_map_.end()) { *result = NULL; return Status::IOError(fname, "File not found"); } - result->reset(new RandomAccessFileImpl(file_map_[fname])); + result->reset(new RandomAccessFileImpl(file_map_[nfname])); return Status::OK(); } virtual Status NewWritableFile(const std::string& fname, unique_ptr* result, const EnvOptions& soptions) { + std::string nfname = NormalizeFileName(fname); MutexLock lock(&mutex_); - if (file_map_.find(fname) != file_map_.end()) { - DeleteFileInternal(fname); + if (file_map_.find(nfname) != file_map_.end()) { + DeleteFileInternal(nfname); } FileState* file = new FileState(); file->Ref(); - file_map_[fname] = file; + file_map_[nfname] = file; result->reset(new WritableFileImpl(file)); return Status::OK(); @@ -284,8 +307,9 @@ class InMemoryEnv : public EnvWrapper { } virtual bool FileExists(const std::string& fname) { + std::string nfname = NormalizeFileName(fname); MutexLock lock(&mutex_); - return file_map_.find(fname) != file_map_.end(); + return file_map_.find(nfname) != file_map_.end(); } virtual Status GetChildren(const std::string& dir, @@ -315,12 +339,13 @@ class InMemoryEnv : public EnvWrapper { } virtual Status DeleteFile(const std::string& fname) { + std::string nfname = NormalizeFileName(fname); MutexLock lock(&mutex_); - if (file_map_.find(fname) == file_map_.end()) { + if (file_map_.find(nfname) == file_map_.end()) { return Status::IOError(fname, "File not found"); } - DeleteFileInternal(fname); + DeleteFileInternal(nfname); return Status::OK(); } @@ -337,12 +362,14 @@ class InMemoryEnv : public EnvWrapper { } virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) { + std::string nfname = NormalizeFileName(fname); MutexLock lock(&mutex_); - if (file_map_.find(fname) == file_map_.end()) { + + if (file_map_.find(nfname) == file_map_.end()) { return Status::IOError(fname, "File not found"); } - *file_size = file_map_[fname]->Size(); + *file_size = file_map_[nfname]->Size(); return Status::OK(); } @@ -352,14 +379,16 @@ class InMemoryEnv : public EnvWrapper { } virtual Status RenameFile(const std::string& src, const std::string& dest) { + std::string nsrc = NormalizeFileName(src); + std::string ndest = NormalizeFileName(dest); MutexLock lock(&mutex_); - if (file_map_.find(src) == file_map_.end()) { + if (file_map_.find(nsrc) == file_map_.end()) { return Status::IOError(src, "File not found"); } DeleteFileInternal(dest); - file_map_[dest] = file_map_[src]; - file_map_.erase(src); + file_map_[ndest] = file_map_[nsrc]; + file_map_.erase(nsrc); return Status::OK(); } diff --git a/helpers/memenv/memenv_test.cc b/helpers/memenv/memenv_test.cc index ea3ed61a0..6154893f0 100644 --- a/helpers/memenv/memenv_test.cc +++ b/helpers/memenv/memenv_test.cc @@ -222,6 +222,15 @@ TEST(MemEnvTest, DBTest) { } delete db; + + options.create_if_missing = false; + ASSERT_OK(DB::Open(options, "/dir/db", &db)); + for (size_t i = 0; i < 3; ++i) { + std::string res; + ASSERT_OK(db->Get(ReadOptions(), keys[i], &res)); + ASSERT_TRUE(res == vals[i]); + } + delete db; } } // namespace rocksdb