From 970891ccb43914cab8dbea785fecc451937e4df6 Mon Sep 17 00:00:00 2001 From: Cunyin Chang Date: Thu, 17 Aug 2017 09:54:11 +0800 Subject: [PATCH] lib/rocksdb: Add support for subdirectory. Change-Id: I280bc8f9c0c4a79d70e16231e019fba0aa445f51 Signed-off-by: Cunyin Chang Reviewed-on: https://review.gerrithub.io/374558 Tested-by: SPDK Automated Test System Reviewed-by: Jim Harris Reviewed-by: Daniel Verkamp --- lib/rocksdb/env_spdk.cc | 102 +++++++++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 21 deletions(-) diff --git a/lib/rocksdb/env_spdk.cc b/lib/rocksdb/env_spdk.cc index a7657bb3b..0b74169f4 100644 --- a/lib/rocksdb/env_spdk.cc +++ b/lib/rocksdb/env_spdk.cc @@ -32,6 +32,7 @@ */ #include "rocksdb/env.h" +#include extern "C" { #include "spdk/env.h" @@ -76,6 +77,38 @@ __send_request(fs_request_fn fn, void *arg) spdk_event_call(event); } +static std::string +sanitize_path(const std::string &input, const std::string &mount_directory) +{ + int index = 0; + std::string name; + std::string input_tmp; + + input_tmp = input.substr(mount_directory.length(), input.length()); + for (const char &c : input_tmp) { + if (index == 0) { + if (c != '/') { + name = name.insert(index, 1, '/'); + index++; + } + name = name.insert(index, 1, c); + index++; + } else { + if (name[index - 1] == '/' && c == '/') { + continue; + } else { + name = name.insert(index, 1, c); + index++; + } + } + } + + if (name[name.size() - 1] == '/') { + name = name.erase(name.size() - 1, 1); + } + return name; +} + class SpdkSequentialFile : public SequentialFile { struct spdk_file *mFile; @@ -89,12 +122,6 @@ public: virtual Status InvalidateCache(size_t offset, size_t length) override; }; -static std::string -basename(std::string full) -{ - return full.substr(full.rfind("/") + 1); -} - SpdkSequentialFile::~SpdkSequentialFile(void) { spdk_file_close(mFile, g_sync_args.channel); @@ -288,8 +315,9 @@ public: struct spdk_file *file; int rc; + std::string name = sanitize_path(fname, mDirectory); rc = spdk_fs_open_file(g_fs, g_sync_args.channel, - basename(fname).c_str(), 0, &file); + name.c_str(), 0, &file); if (rc == 0) { result->reset(new SpdkSequentialFile(file)); return Status::OK(); @@ -299,7 +327,7 @@ public: * support MySQL, set the errno to right value. */ errno = -rc; - return Status::IOError(fname, strerror(errno)); + return Status::IOError(name, strerror(errno)); } } else { return EnvWrapper::NewSequentialFile(fname, result, options); @@ -311,7 +339,8 @@ public: const EnvOptions &options) override { if (fname.compare(0, mDirectory.length(), mDirectory) == 0) { - result->reset(new SpdkRandomAccessFile(basename(fname), options)); + std::string name = sanitize_path(fname, mDirectory); + result->reset(new SpdkRandomAccessFile(name, options)); return Status::OK(); } else { return EnvWrapper::NewRandomAccessFile(fname, result, options); @@ -323,7 +352,8 @@ public: const EnvOptions &options) override { if (fname.compare(0, mDirectory.length(), mDirectory) == 0) { - result->reset(new SpdkWritableFile(basename(fname), options)); + std::string name = sanitize_path(fname, mDirectory); + result->reset(new SpdkWritableFile(name, options)); return Status::OK(); } else { return EnvWrapper::NewWritableFile(fname, result, options); @@ -347,10 +377,10 @@ public: virtual Status FileExists(const std::string &fname) override { struct spdk_file_stat stat; - std::string fname_base = basename(fname); int rc; + std::string name = sanitize_path(fname, mDirectory); - rc = spdk_fs_file_stat(g_fs, g_sync_args.channel, fname_base.c_str(), &stat); + rc = spdk_fs_file_stat(g_fs, g_sync_args.channel, name.c_str(), &stat); if (rc == 0) { return Status::OK(); } @@ -358,12 +388,12 @@ public: } virtual Status RenameFile(const std::string &src, const std::string &target) override { - std::string target_base = basename(target); - std::string src_base = basename(src); int rc; + std::string src_name = sanitize_path(src, mDirectory); + std::string target_name = sanitize_path(target, mDirectory); rc = spdk_fs_rename_file(g_fs, g_sync_args.channel, - src_base.c_str(), target_base.c_str()); + src_name.c_str(), target_name.c_str()); if (rc == -ENOENT) { return EnvWrapper::RenameFile(src, target); } @@ -376,10 +406,10 @@ public: virtual Status GetFileSize(const std::string &fname, uint64_t *size) override { struct spdk_file_stat stat; - std::string fname_base = basename(fname); int rc; + std::string name = sanitize_path(fname, mDirectory); - rc = spdk_fs_file_stat(g_fs, g_sync_args.channel, fname_base.c_str(), &stat); + rc = spdk_fs_file_stat(g_fs, g_sync_args.channel, name.c_str(), &stat); if (rc == -ENOENT) { return EnvWrapper::GetFileSize(fname, size); } @@ -389,8 +419,9 @@ public: virtual Status DeleteFile(const std::string &fname) override { int rc; - std::string fname_base = basename(fname); - rc = spdk_fs_delete_file(g_fs, g_sync_args.channel, fname_base.c_str()); + std::string name = sanitize_path(fname, mDirectory); + + rc = spdk_fs_delete_file(g_fs, g_sync_args.channel, name.c_str()); if (rc == -ENOENT) { return EnvWrapper::DeleteFile(fname); } @@ -399,7 +430,9 @@ public: virtual void StartThread(void (*function)(void *arg), void *arg) override; virtual Status LockFile(const std::string &fname, FileLock **lock) override { - spdk_fs_open_file(g_fs, g_sync_args.channel, basename(fname).c_str(), + std::string name = sanitize_path(fname, mDirectory); + + spdk_fs_open_file(g_fs, g_sync_args.channel, name.c_str(), SPDK_BLOBFS_OPEN_CREATE, (struct spdk_file **)lock); return Status::OK(); } @@ -411,19 +444,46 @@ public: virtual Status GetChildren(const std::string &dir, std::vector *result) override { + std::string::size_type pos; + std::set dir_and_file_set; + std::string full_path; + std::string filename; + std::string dir_name; + if (dir.find("archive") != std::string::npos) { return Status::OK(); } if (dir.compare(0, mDirectory.length(), mDirectory) == 0) { spdk_fs_iter iter; struct spdk_file *file; + dir_name = sanitize_path(dir, mDirectory); iter = spdk_fs_iter_first(g_fs); while (iter != NULL) { file = spdk_fs_iter_get_file(iter); - result->push_back(std::string(spdk_file_get_name(file))); + full_path = spdk_file_get_name(file); + if (strncmp(dir_name.c_str(), full_path.c_str(), dir_name.length())) { + iter = spdk_fs_iter_next(iter); + continue; + } + pos = full_path.find("/", dir_name.length() + 1); + + if (pos != std::string::npos) { + filename = full_path.substr(dir_name.length() + 1, pos - dir_name.length() - 1); + } else { + filename = full_path.substr(dir_name.length() + 1); + } + dir_and_file_set.insert(filename); iter = spdk_fs_iter_next(iter); } + + for (auto &s : dir_and_file_set) { + result->push_back(s); + } + + result->push_back("."); + result->push_back(".."); + return Status::OK(); } return EnvWrapper::GetChildren(dir, result);