Add new namespace to define a file path of a storage

This commit is contained in:
payemo 2023-04-18 00:29:42 +03:00
parent 77d66aaf3e
commit 8305d32eea
4 changed files with 195 additions and 0 deletions

View File

@ -37,6 +37,8 @@
namespace leveldb { namespace leveldb {
using namespace filesystem;
const int kNumNonTableCacheFiles = 10; const int kNumNonTableCacheFiles = 10;
// Information kept for every waiting writer // Information kept for every waiting writer
@ -132,6 +134,7 @@ DBImpl::DBImpl(const Options& raw_options, const std::string& dbname)
owns_info_log_(options_.info_log != raw_options.info_log), owns_info_log_(options_.info_log != raw_options.info_log),
owns_cache_(options_.block_cache != raw_options.block_cache), owns_cache_(options_.block_cache != raw_options.block_cache),
dbname_(dbname), dbname_(dbname),
path_(PathFactory::Create(dbname)),
table_cache_(new TableCache(dbname_, options_, TableCacheSize(options_))), table_cache_(new TableCache(dbname_, options_, TableCacheSize(options_))),
db_lock_(nullptr), db_lock_(nullptr),
shutting_down_(false), shutting_down_(false),
@ -176,6 +179,9 @@ DBImpl::~DBImpl() {
if (owns_cache_) { if (owns_cache_) {
delete options_.block_cache; delete options_.block_cache;
} }
if (path_ != nullptr) {
delete path_;
}
} }
Status DBImpl::NewDB() { Status DBImpl::NewDB() {
@ -295,6 +301,10 @@ Status DBImpl::Recover(VersionEdit* edit, bool* save_manifest) {
// Ignore error from CreateDir since the creation of the DB is // Ignore error from CreateDir since the creation of the DB is
// committed only when the descriptor is created, and this directory // committed only when the descriptor is created, and this directory
// may already exist from a previous failed creation attempt. // may already exist from a previous failed creation attempt.
if (path_->IsDirectory()) {
path_->CreateDirectories();
}
env_->CreateDir(dbname_); env_->CreateDir(dbname_);
assert(db_lock_ == nullptr); assert(db_lock_ == nullptr);
Status s = env_->LockFile(LockFileName(dbname_), &db_lock_); Status s = env_->LockFile(LockFileName(dbname_), &db_lock_);

View File

@ -17,9 +17,12 @@
#include "leveldb/env.h" #include "leveldb/env.h"
#include "port/port.h" #include "port/port.h"
#include "port/thread_annotations.h" #include "port/thread_annotations.h"
#include "leveldb/filesystem.h"
namespace leveldb { namespace leveldb {
using namespace filesystem;
class MemTable; class MemTable;
class TableCache; class TableCache;
class Version; class Version;
@ -162,7 +165,9 @@ class DBImpl : public DB {
const Options options_; // options_.comparator == &internal_comparator_ const Options options_; // options_.comparator == &internal_comparator_
const bool owns_info_log_; const bool owns_info_log_;
const bool owns_cache_; const bool owns_cache_;
// TODO: replace with Path;
const std::string dbname_; const std::string dbname_;
Path* const path_;
// table_cache_ provides its own synchronization // table_cache_ provides its own synchronization
TableCache* const table_cache_; TableCache* const table_cache_;

View File

@ -0,0 +1,109 @@
#ifndef STORAGE_LEVELDB_INCLUDE_FILE_SYSTEM_H_
#define STORAGE_LEVELDB_INCLUDE_FILE_SYSTEM_H_
#include <cstdint>
#include <string>
#include "leveldb/export.h"
namespace leveldb {
namespace filesystem {
bool IsDirectorySeparator(const char c);
class Path {
public:
// Constants
static const char kDirectorySeparator = '\\';
static const char kAltDirecttorySeparator = '/';
static const char kVolumeSeparatorChar = ':';
Path() : isDir_{false}, path_("") {}
Path(const std::string& path) : path_(path) {
isDir_ = !IsEmpty() && IsDirectorySeparator(path_[Size() - 1]);
}
virtual ~Path() {}
const std::string& ToString() const { return path_; }
const char* ToCString() const { return path_.c_str(); }
virtual bool IsAbsolute() const = 0;
virtual bool IsRelative() const = 0;
virtual bool CreateDirectories() = 0;
virtual bool CreateDirectory() = 0;
inline size_t Size() const { return path_.size(); }
inline bool IsEmpty() const { return path_.empty(); }
inline bool IsDirectory() const { return isDir_; }
// Utility functions
inline bool HasExtension() {
if (!IsEmpty()) {
std::string::reverse_iterator& path_iter = path_.rbegin();
while (path_iter != path_.rend()) {
char c = *path_iter;
if (c == '.') {
return true;
}
if (IsDirectorySeparator(c)) {
break;
}
}
}
return false;
}
protected:
bool isDir_;
std::string path_;
virtual void Normalize() = 0;
};
#ifdef LEVELDB_PLATFORM_WINDOWS
class WindowsFilePath : public Path {
public:
explicit WindowsFilePath(const std::string& path) : Path(path) {
Normalize();
}
~WindowsFilePath() {}
bool IsAbsolute() const override;
bool IsRelative() const override;
bool CreateDirectories() override;
bool CreateDirectory() override;
protected:
void Normalize() override;
};
inline bool IsValidDriveChar(const char c) {
const char drive_char = std::toupper(c);
return drive_char >= 'A' && drive_char <= 'Z';
}
#endif
// Factory
class PathFactory {
public:
static Path* Create(const std::string& path);
private:
PathFactory() {}
~PathFactory() {}
};
} // namespace filesystem
} // namespace leveldb
#endif // STORAGE_LEVELDB_INCLUDE_FILE_SYSTEM_H_

71
util/filesystem.cc Normal file
View File

@ -0,0 +1,71 @@
#include "leveldb/filesystem.h"
namespace leveldb {
namespace filesystem {
bool IsDirectorySeparator(const char c) {
return (c == Path::kDirectorySeparator || c == Path::kAltDirecttorySeparator);
}
Path* PathFactory::Create(const std::string& path)
{
#ifdef LEVELDB_PLATFORM_WINDOWS
return new WindowsFilePath(path);
#elif LEVELDB_PLATFORM_POSIX
return nullptr;
#endif
return nullptr;
}
#ifdef LEVELDB_PLATFORM_WINDOWS
bool WindowsFilePath::IsAbsolute() const {
return path_.size() >= 3 && IsValidDriveChar(path_[0]) &&
path_[1] == Path::kVolumeSeparatorChar;
};
bool WindowsFilePath::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] == Path::kVolumeSeparatorChar &&
IsDirectorySeparator(path_[2])) {
return IsValidDriveChar(path_[0]);
}
return true;
};
void WindowsFilePath::Normalize() {
auto out = path_.begin();
for (const char c : path_) {
if (!IsDirectorySeparator(c)) {
*(out++) = c;
} else if (out == path_.begin() || IsDirectorySeparator(*std::prev(out))) {
*(out++) = Path::kDirectorySeparator;
} else {
continue;
}
}
path_.erase(out, path_.end());
}
bool WindowsFilePath::CreateDirectories() { return true; }
bool WindowsFilePath::CreateDirectory() { return true; }
#endif
}
}