From c82ca583c667c41a572bc51d0a5dda771e76ee66 Mon Sep 17 00:00:00 2001 From: payemo Date: Thu, 27 Apr 2023 00:38:09 +0300 Subject: [PATCH] Reimplement path manipulation functionality in a more static way and extend CreateDir function to deal with dir's hierarchy --- db/db_impl.cc | 10 +-- db/db_impl.h | 4 +- include/leveldb/db_path.h | 74 +++--------------- include/leveldb/env.h | 5 -- util/db_path.cc | 154 +++++++++++++++++++++----------------- util/env_windows.cc | 26 +++---- 6 files changed, 108 insertions(+), 165 deletions(-) diff --git a/db/db_impl.cc b/db/db_impl.cc index 3fef554..eb56f1f 100644 --- a/db/db_impl.cc +++ b/db/db_impl.cc @@ -127,14 +127,13 @@ static int TableCacheSize(const Options& sanitized_options) { DBImpl::DBImpl(const Options& raw_options, const std::string& dbname) : env_(raw_options.env), + dbname_(path::Normalize(dbname)), internal_comparator_(raw_options.comparator), internal_filter_policy_(raw_options.filter_policy), - options_(SanitizeOptions(dbname, &internal_comparator_, + options_(SanitizeOptions(dbname_, &internal_comparator_, &internal_filter_policy_, raw_options)), owns_info_log_(options_.info_log != raw_options.info_log), owns_cache_(options_.block_cache != raw_options.block_cache), - dbname_(dbname), - path_(PathFactory::Create(dbname)), table_cache_(new TableCache(dbname_, options_, TableCacheSize(options_))), db_lock_(nullptr), shutting_down_(false), @@ -179,9 +178,6 @@ DBImpl::~DBImpl() { if (owns_cache_) { delete options_.block_cache; } - if (path_) { - delete path_; - } } Status DBImpl::NewDB() { @@ -301,7 +297,7 @@ Status DBImpl::Recover(VersionEdit* edit, bool* save_manifest) { // Ignore error from CreateDir since the creation of the DB is // committed only when the descriptor is created, and this directory // may already exist from a previous failed creation attempt. - env_->CreateDir(path_->ToString()); + env_->CreateDir(dbname_); assert(db_lock_ == nullptr); Status s = env_->LockFile(LockFileName(dbname_), &db_lock_); if (!s.ok()) { diff --git a/db/db_impl.h b/db/db_impl.h index 030b673..30f4054 100644 --- a/db/db_impl.h +++ b/db/db_impl.h @@ -160,14 +160,12 @@ class DBImpl : public DB { // Constant after construction Env* const env_; + const std::string dbname_; const InternalKeyComparator internal_comparator_; const InternalFilterPolicy internal_filter_policy_; const Options options_; // options_.comparator == &internal_comparator_ const bool owns_info_log_; const bool owns_cache_; - // TODO: replace with Path; - const std::string dbname_; - DbPath* const path_; // table_cache_ provides its own synchronization TableCache* const table_cache_; diff --git a/include/leveldb/db_path.h b/include/leveldb/db_path.h index f04989d..4edb008 100644 --- a/include/leveldb/db_path.h +++ b/include/leveldb/db_path.h @@ -8,77 +8,25 @@ namespace leveldb { namespace path { -class DbPath { -public: - // Constants - static const char kDirectorySeparator = '\\'; - static const char kAltDirecttorySeparator = '/'; - static const char kVolumeSeparatorChar = ':'; +const char kDirectorySeparator = '\\'; +const char kAltDirecttorySeparator = '/'; +const char kVolumeSeparatorChar = ':'; - virtual ~DbPath() {} +bool IsAbsolute(const std::string& path); - const std::string& ToString() const { return path_; } - const char* ToCString() const { return path_.c_str(); } +bool IsRelative(const std::string& path); - const char operator[](size_t i) const { return path_[i]; } +size_t RootLength(const std::string& path); - static bool IsDirectorySeparator(const char c); +const std::string& GetRootDirectory(const std::string& path); - virtual bool IsAbsolute() const = 0; - virtual bool IsRelative() const = 0; - virtual size_t RootLength() const = 0; +std::string Normalize(const std::string& path); - inline size_t Size() const { return path_.size(); } - inline bool IsEmpty() const { return path_.empty(); } - inline const std::string Substring(size_t from, size_t to) const { - return path_.substr(from, to); - } - inline const std::string GetRootDirectory() const { - return path_.substr(0, RootLength()); - } +bool IsDirectorySeparator(const char c); -protected: - DbPath() : path_("") {} - DbPath(const std::string& path) : path_(path) {} +static bool IsValidDriveChar(const char c); - virtual void Normalize() = 0; - - bool StartsWith(const std::string& value, bool ignore_case = false) const; - - std::string path_; -}; - -// Win path -class WindowsDbPath : public DbPath { -public: - explicit WindowsDbPath(const std::string& path) : DbPath(path) { - Normalize(); - } - ~WindowsDbPath() {} - - bool IsAbsolute() const override; - bool IsRelative() const override; - size_t RootLength() const override; - -protected: - static bool IsValidDriveChar(const char c); - - void Normalize() override; - -private: - const char* kExtendedPathPrefix = "\\\\?\\"; - const char* kUncExtendedPathPrefix = "\\\\?\\UNC\\"; -}; - - -// Factory -class PathFactory { -public: - PathFactory() = delete; - ~PathFactory() = delete; - - static DbPath* Create(const std::string& path); -}; +static bool StartsWith(const std::string& path, const std::string& search, bool ignore_case = false); } // namespace path } // namespace leveldb diff --git a/include/leveldb/env.h b/include/leveldb/env.h index ef83ae2..d63241d 100644 --- a/include/leveldb/env.h +++ b/include/leveldb/env.h @@ -145,8 +145,6 @@ class LEVELDB_EXPORT Env { // Create the specified directory. virtual Status CreateDir(const std::string& dirname) = 0; - virtual Status CreateDir(const path::DbPath& dbpath) = 0; - // Delete the specified directory. // // The default implementation calls DeleteDir, to support legacy Env @@ -377,9 +375,6 @@ class LEVELDB_EXPORT EnvWrapper : public Env { Status CreateDir(const std::string& d) override { return target_->CreateDir(d); } - Status CreateDir(const path::DbPath& d) override { - return target_->CreateDir(d); - } Status RemoveDir(const std::string& d) override { return target_->RemoveDir(d); } diff --git a/util/db_path.cc b/util/db_path.cc index e3618e5..a2422f5 100644 --- a/util/db_path.cc +++ b/util/db_path.cc @@ -3,59 +3,65 @@ namespace leveldb { namespace path { -bool DbPath::IsDirectorySeparator(const char c) { - return (c == DbPath::kDirectorySeparator || c == DbPath::kAltDirecttorySeparator); -} +#ifdef LEVELDB_PLATFORM_WINDOWS -bool DbPath::StartsWith(const std::string& value, bool ignore_case) const { - if (value.size() > path_.size()) { - return false; - } - if (ignore_case) { - auto ignore_case_cmp_func = [](char a, char b) { return std::tolower(a) == std::tolower(b); }; - return std::equal(value.begin(), value.end(), path_.begin(), ignore_case_cmp_func); - } - return std::equal(value.begin(), value.end(), path_.begin()); -} +const char* kExtendedPathPrefix = "\\\\?\\"; +const char* kUncExtendedPathPrefix = "\\\\?\\UNC\\"; -// Windows - -bool WindowsDbPath::IsAbsolute() const { - return path_.size() >= 3 && IsValidDriveChar(path_[0]) && - path_[1] == DbPath::kVolumeSeparatorChar; -}; - -bool WindowsDbPath::IsRelative() const { - if (path_.size() < 2) { - return true; - } - - if (IsDirectorySeparator(path_[0])) { - if (path_[1] != '?') { - return !IsDirectorySeparator(path_[1]); - } - return false; - } - if (path_.size() >= 3 && path_[1] == DbPath::kVolumeSeparatorChar && - IsDirectorySeparator(path_[2])) { - return IsValidDriveChar(path_[0]); - } - return true; -}; - -bool WindowsDbPath::IsValidDriveChar(const char c) { +bool IsValidDriveChar(const char c) { const char drive_char = std::toupper(c); return drive_char >= 'A' && drive_char <= 'Z'; } -size_t WindowsDbPath::RootLength() const { - size_t path_length = path_.size(); +#elif LEVELDB_PLATFORM_POSIX + +#endif + +bool IsDirectorySeparator(const char c) { + return (c == kDirectorySeparator || c == kAltDirecttorySeparator); +} + +const std::string& GetRootDirectory(const std::string& path) { + return path.substr(0, RootLength(path)); +} + +bool IsAbsolute(const std::string& path) { +#ifdef LEVELDB_PLATFORM_WINDOWS + return path.size() >= 3 && IsValidDriveChar(path[0]) && + path[1] == kVolumeSeparatorChar; +#endif +} + +bool IsRelative(const std::string& path) { + if (path.size() < 2) { + return true; + } + + if (IsDirectorySeparator(path[0])) { + if (path[1] != '?') { + return !IsDirectorySeparator(path[1]); + } + return false; + } + if (path.size() >= 3 && path[1] == kVolumeSeparatorChar && + IsDirectorySeparator(path[2])) { + #ifdef LEVELDB_PLATFORM_WINDOWS + return IsValidDriveChar(path[0]); + #elif LEVELDB_PLATFORM_POSIX + + #endif + } + return true; +} + +size_t RootLength(const std::string& path) { + size_t path_length = path.size(); size_t root_length = 0; size_t volume_separator_length = 2; size_t unc_root_length = 2; - bool extended_syntax = StartsWith(kExtendedPathPrefix); - bool extended_unc_syntax = StartsWith(kUncExtendedPathPrefix); + bool extended_syntax = StartsWith(path, std::string(kExtendedPathPrefix)); + bool extended_unc_syntax = StartsWith(path, std::string(kUncExtendedPathPrefix)); if (extended_syntax) { if (extended_unc_syntax) { @@ -65,22 +71,24 @@ size_t WindowsDbPath::RootLength() const { } } - if ((!extended_syntax || extended_unc_syntax) && path_length != 0 && IsDirectorySeparator(path_[0])) { + if ((!extended_syntax || extended_unc_syntax) && path_length != 0 && + IsDirectorySeparator(path[0])) { root_length = 1; - if (extended_unc_syntax || (path_length > 1 && IsDirectorySeparator(path_[1]))) { + if (extended_unc_syntax || + (path_length > 1 && IsDirectorySeparator(path[1]))) { root_length = unc_root_length; int n = 2; // maximum separators to skip while (root_length < path_length && - (!IsDirectorySeparator(path_[root_length]) || --n > 0)) { + (!IsDirectorySeparator(path[root_length]) || --n > 0)) { ++root_length; } } } else if (path_length >= volume_separator_length && - path_[volume_separator_length - 1] == kVolumeSeparatorChar) { + path[volume_separator_length - 1] == kVolumeSeparatorChar) { root_length = volume_separator_length; if (path_length >= volume_separator_length && - IsDirectorySeparator(path_[volume_separator_length])) { + IsDirectorySeparator(path[volume_separator_length])) { ++root_length; } } @@ -88,34 +96,40 @@ size_t WindowsDbPath::RootLength() const { return root_length; } -void WindowsDbPath::Normalize() { - auto out = path_.begin(); +bool StartsWith(const std::string& path, const std::string& search, + bool ignore_case) { + if (search.size() > path.size()) { + return false; + } + if (ignore_case) { + auto ignore_case_cmp_func = [](char a, char b) { + return std::tolower(a) == std::tolower(b); + }; + return std::equal(search.begin(), search.end(), path.begin(), + ignore_case_cmp_func); + } + return std::equal(search.begin(), search.end(), path.begin()); +} - for (const char c : path_) { +std::string Normalize(const std::string& path) { + std::string out; + auto path_it = path.begin(); + + for (const char c : path) { if (!IsDirectorySeparator(c)) { - *(out++) = c; - } else if (out == path_.begin() || !IsDirectorySeparator(*std::prev(out))) { - *(out++) = kDirectorySeparator; + out += c; + path_it++; + } else if (path_it == path.begin() || + !IsDirectorySeparator(*std::prev(path_it))) { + out += kDirectorySeparator; + path_it++; } else { continue; } } - path_.erase(out, path_.end()); + return out; } -// Windows path - -DbPath* PathFactory::Create(const std::string& path) { -#ifdef LEVELDB_PLATFORM_WINDOWS - return new WindowsDbPath(path); -#elif LEVELDB_PLATFORM_POSIX - return nullptr; -#endif - return nullptr; -} - -} -} - - +} // namespace path +} // namespace leveldb \ No newline at end of file diff --git a/util/env_windows.cc b/util/env_windows.cc index f6751b2..7683939 100644 --- a/util/env_windows.cc +++ b/util/env_windows.cc @@ -536,41 +536,33 @@ class WindowsEnv : public Env { } Status CreateDir(const std::string& dirname) override { - if (!::CreateDirectoryA(dirname.c_str(), nullptr)) { - return WindowsError(dirname, ::GetLastError()); - } - return Status::OK(); - } + size_t path_length = dirname.size(); - Status CreateDir(const DbPath& dirpath) override { - size_t path_length = dirpath.Size(); - - if (path_length >= 2 && DbPath::IsDirectorySeparator(dirpath[path_length - 1])) { + if (path_length >= 2 && path::IsDirectorySeparator(dirname[path_length - 1])) { --path_length; } - if (DirectoryExists(dirpath.ToString())) { + if (DirectoryExists(dirname)) { return Status::OK(); } std::vector stackDir; bool path_exists = false; - size_t root_length = dirpath.RootLength(); + size_t root_length = path::RootLength(dirname); - if (path_length > root_length) { // Special case root (fullpath = X:\\) + if (path_length > root_length) { // Special case root (fullpath = X:\\) size_t i = path_length - 1; while (i >= root_length && !path_exists) { - const std::string dir = dirpath.Substring(0, i + 1); + const std::string dir = dirname.substr(0, i + 1); if (!DirectoryExists(dir)) { stackDir.push_back(dir); - } - else { + } else { path_exists = true; } - while (i > root_length && dirpath[i] != DbPath::kDirectorySeparator && dirpath[i] != DbPath::kAltDirecttorySeparator) + while (i > root_length && dirname[i] != path::kDirectorySeparator && dirname[i] != path::kAltDirecttorySeparator) --i; --i; } @@ -586,7 +578,7 @@ class WindowsEnv : public Env { } } } - + return Status::OK(); }