Loading include/config.hpp +4 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,10 @@ constexpr auto use_ctime = false; constexpr auto use_mtime = false; constexpr auto use_link_cnt = false; constexpr auto use_blocks = false; // metadata logic // Check for existence of file metadata before create. This done on RocksDB level constexpr auto create_exist_check = true; } // namespace metadata namespace rpc { Loading include/daemon/backend/exceptions.hpp +5 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,11 @@ public: explicit NotFoundException(const std::string& s) : DBException(s) {}; }; class ExistsException : public DBException { public: explicit ExistsException(const std::string& s) : DBException(s) {}; }; } // namespace metadata } // namespace gkfs Loading include/daemon/backend/metadata/db.hpp +3 −1 Original line number Diff line number Diff line Loading @@ -35,12 +35,14 @@ private: public: static inline void throw_rdb_status_excpt(const rdb::Status& s); MetadataDB(const std::string& path); explicit MetadataDB(const std::string& path); std::string get(const std::string& key) const; void put(const std::string& key, const std::string& val); void put_if_not_exist(const std::string& key, const std::string& val); void remove(const std::string& key); bool exists(const std::string& key); Loading src/client/gkfs_functions.cpp +49 −47 Original line number Diff line number Diff line Loading @@ -114,46 +114,49 @@ int gkfs_open(const std::string& path, mode_t mode, int flags) { return -1; } bool exists = true; auto md = gkfs::util::get_metadata(path); if (!md) { if (errno == ENOENT) { exists = false; } else { LOG(ERROR, "Error while retriving stat to file"); return -1; } } if (!exists) { if (!(flags & O_CREAT)) { // file doesn't exists and O_CREAT was not set errno = ENOENT; return -1; } /*** CREATION ***/ assert(flags & O_CREAT); // dummy metadata creation std::shared_ptr<gkfs::metadata::Metadata> md = nullptr; if (flags & O_CREAT) { if (flags & O_DIRECTORY) { LOG(ERROR, "O_DIRECTORY use with O_CREAT. NOT SUPPORTED"); errno = ENOTSUP; return -1; } // no access check required here. If one is using our FS they have the permissions. if (gkfs_create(path, mode | S_IFREG)) { LOG(ERROR, "Error creating non-existent file: '{}'", strerror(errno)); int err = gkfs_create(path, mode | S_IFREG); if (err) { if (errno == EEXIST) { // file exists, O_CREAT was set if (flags & O_EXCL) { // File exists and O_EXCL & O_CREAT was set errno = EEXIST; return -1; } // file exists, O_CREAT was set O_EXCL wasnt, so function does not fail // this case is actually undefined as per `man 2 open` md = gkfs::util::get_metadata(path); } else { /* File already exists */ if (flags & O_EXCL) { // File exists and O_EXCL was set errno = EEXIST; LOG(ERROR, "Error creating file: '{}'", strerror(errno)); return -1; } } else { // file was successfully created. Add to filemap return CTX->file_map()->add(std::make_shared<gkfs::filemap::OpenFile>(path, flags)); } } else { md = gkfs::util::get_metadata(path); if (!md) { if (errno == ENOENT) { // file doesn't exists and O_CREAT was not set return -1; } else { LOG(ERROR, "Error stating existing file"); return -1; } } } // **file exists** #ifdef HAS_SYMLINKS if (md->is_link()) { Loading @@ -180,7 +183,6 @@ int gkfs_open(const std::string& path, mode_t mode, int flags) { return -1; } } } return CTX->file_map()->add(std::make_shared<gkfs::filemap::OpenFile>(path, flags)); } Loading src/daemon/backend/metadata/db.cpp +70 −1 Original line number Diff line number Diff line Loading @@ -26,6 +26,10 @@ namespace gkfs { namespace metadata { /** * Called when the daemon is started: Connects to the KV store * @param path where KV store data is stored */ MetadataDB::MetadataDB(const std::string& path) : path(path) { // Optimize RocksDB. This is the easiest way to get RocksDB to perform well options.IncreaseParallelism(); Loading @@ -43,6 +47,12 @@ MetadataDB::MetadataDB(const std::string& path) : path(path) { this->db.reset(rdb_ptr); } /** * Exception wrapper on Status object. Throws NotFoundException if s.IsNotFound(), * general DBException otherwise * @param RocksDB status * @throws DBException */ void MetadataDB::throw_rdb_status_excpt(const rdb::Status& s) { assert(!s.ok()); Loading @@ -53,6 +63,12 @@ void MetadataDB::throw_rdb_status_excpt(const rdb::Status& s) { } } /** * Gets a KV store value for a key * @param key * @return value * @throws DBException on failure, NotFoundException if entry doesn't exist */ std::string MetadataDB::get(const std::string& key) const { std::string val; auto s = db->Get(rdb::ReadOptions(), key, &val); Loading @@ -62,6 +78,12 @@ std::string MetadataDB::get(const std::string& key) const { return val; } /** * Puts an entry into the KV store * @param key * @param val * @throws DBException on failure */ void MetadataDB::put(const std::string& key, const std::string& val) { assert(gkfs::path::is_absolute(key)); assert(key == "/" || !gkfs::path::has_trailing_slash(key)); Loading @@ -73,6 +95,23 @@ void MetadataDB::put(const std::string& key, const std::string& val) { } } /** * Puts an entry into the KV store if it doesn't exist. This function does not use a mutex. * @param key * @param val * @throws DBException on failure, ExistException if entry already exists */ void MetadataDB::put_if_not_exist(const std::string& key, const std::string& val) { if (exists(key)) throw ExistsException(""); put(key, val); } /** * Removes an entry from the KV store * @param key * @throws DBException on failure, NotFoundException if entry doesn't exist */ void MetadataDB::remove(const std::string& key) { auto s = db->Delete(write_opts, key); if (!s.ok()) { Loading @@ -80,6 +119,12 @@ void MetadataDB::remove(const std::string& key) { } } /** * checks for existence of an entry * @param key * @return true if exists * @throws DBException on failure */ bool MetadataDB::exists(const std::string& key) { std::string val; auto s = db->Get(rdb::ReadOptions(), key, &val); Loading @@ -98,7 +143,7 @@ bool MetadataDB::exists(const std::string& key) { * @param old_key * @param new_key * @param val * @return * @throws DBException on failure, NotFoundException if entry doesn't exist */ void MetadataDB::update(const std::string& old_key, const std::string& new_key, const std::string& val) { //TODO use rdb::Put() method Loading @@ -111,6 +156,14 @@ void MetadataDB::update(const std::string& old_key, const std::string& new_key, } } /** * Increases only the size part of the metadentry via a RocksDB Operand Operation. * E.g., called before a write() call * @param key * @param size * @param append * @throws DBException on failure */ void MetadataDB::increase_size(const std::string& key, size_t size, bool append) { auto uop = IncreaseSizeOperand(size, append); auto s = db->Merge(write_opts, key, uop.serialize()); Loading @@ -119,6 +172,13 @@ void MetadataDB::increase_size(const std::string& key, size_t size, bool append) } } /** * Decreases only the size part of the metadentry via a RocksDB Operand Operation * E.g., called before a truncate() call * @param key * @param size * @throws DBException on failure */ void MetadataDB::decrease_size(const std::string& key, size_t size) { auto uop = DecreaseSizeOperand(size); auto s = db->Merge(write_opts, key, uop.serialize()); Loading Loading @@ -179,6 +239,9 @@ std::vector<std::pair<std::string, bool>> MetadataDB::get_dirents(const std::str return entries; } /** * Code example for iterating all entries in KV store. This is for debug only as it is too expensive */ void MetadataDB::iterate_all() { std::string key; std::string val; Loading @@ -190,6 +253,12 @@ void MetadataDB::iterate_all() { } } /** * Called when RocksDB connection is established. * Used for setting KV store settings * see here: https://github.com/facebook/rocksdb/wiki/RocksDB-Tuning-Guide * @param options */ void MetadataDB::optimize_rocksdb_options(rdb::Options& options) { options.max_successive_merges = 128; } Loading Loading
include/config.hpp +4 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,10 @@ constexpr auto use_ctime = false; constexpr auto use_mtime = false; constexpr auto use_link_cnt = false; constexpr auto use_blocks = false; // metadata logic // Check for existence of file metadata before create. This done on RocksDB level constexpr auto create_exist_check = true; } // namespace metadata namespace rpc { Loading
include/daemon/backend/exceptions.hpp +5 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,11 @@ public: explicit NotFoundException(const std::string& s) : DBException(s) {}; }; class ExistsException : public DBException { public: explicit ExistsException(const std::string& s) : DBException(s) {}; }; } // namespace metadata } // namespace gkfs Loading
include/daemon/backend/metadata/db.hpp +3 −1 Original line number Diff line number Diff line Loading @@ -35,12 +35,14 @@ private: public: static inline void throw_rdb_status_excpt(const rdb::Status& s); MetadataDB(const std::string& path); explicit MetadataDB(const std::string& path); std::string get(const std::string& key) const; void put(const std::string& key, const std::string& val); void put_if_not_exist(const std::string& key, const std::string& val); void remove(const std::string& key); bool exists(const std::string& key); Loading
src/client/gkfs_functions.cpp +49 −47 Original line number Diff line number Diff line Loading @@ -114,46 +114,49 @@ int gkfs_open(const std::string& path, mode_t mode, int flags) { return -1; } bool exists = true; auto md = gkfs::util::get_metadata(path); if (!md) { if (errno == ENOENT) { exists = false; } else { LOG(ERROR, "Error while retriving stat to file"); return -1; } } if (!exists) { if (!(flags & O_CREAT)) { // file doesn't exists and O_CREAT was not set errno = ENOENT; return -1; } /*** CREATION ***/ assert(flags & O_CREAT); // dummy metadata creation std::shared_ptr<gkfs::metadata::Metadata> md = nullptr; if (flags & O_CREAT) { if (flags & O_DIRECTORY) { LOG(ERROR, "O_DIRECTORY use with O_CREAT. NOT SUPPORTED"); errno = ENOTSUP; return -1; } // no access check required here. If one is using our FS they have the permissions. if (gkfs_create(path, mode | S_IFREG)) { LOG(ERROR, "Error creating non-existent file: '{}'", strerror(errno)); int err = gkfs_create(path, mode | S_IFREG); if (err) { if (errno == EEXIST) { // file exists, O_CREAT was set if (flags & O_EXCL) { // File exists and O_EXCL & O_CREAT was set errno = EEXIST; return -1; } // file exists, O_CREAT was set O_EXCL wasnt, so function does not fail // this case is actually undefined as per `man 2 open` md = gkfs::util::get_metadata(path); } else { /* File already exists */ if (flags & O_EXCL) { // File exists and O_EXCL was set errno = EEXIST; LOG(ERROR, "Error creating file: '{}'", strerror(errno)); return -1; } } else { // file was successfully created. Add to filemap return CTX->file_map()->add(std::make_shared<gkfs::filemap::OpenFile>(path, flags)); } } else { md = gkfs::util::get_metadata(path); if (!md) { if (errno == ENOENT) { // file doesn't exists and O_CREAT was not set return -1; } else { LOG(ERROR, "Error stating existing file"); return -1; } } } // **file exists** #ifdef HAS_SYMLINKS if (md->is_link()) { Loading @@ -180,7 +183,6 @@ int gkfs_open(const std::string& path, mode_t mode, int flags) { return -1; } } } return CTX->file_map()->add(std::make_shared<gkfs::filemap::OpenFile>(path, flags)); } Loading
src/daemon/backend/metadata/db.cpp +70 −1 Original line number Diff line number Diff line Loading @@ -26,6 +26,10 @@ namespace gkfs { namespace metadata { /** * Called when the daemon is started: Connects to the KV store * @param path where KV store data is stored */ MetadataDB::MetadataDB(const std::string& path) : path(path) { // Optimize RocksDB. This is the easiest way to get RocksDB to perform well options.IncreaseParallelism(); Loading @@ -43,6 +47,12 @@ MetadataDB::MetadataDB(const std::string& path) : path(path) { this->db.reset(rdb_ptr); } /** * Exception wrapper on Status object. Throws NotFoundException if s.IsNotFound(), * general DBException otherwise * @param RocksDB status * @throws DBException */ void MetadataDB::throw_rdb_status_excpt(const rdb::Status& s) { assert(!s.ok()); Loading @@ -53,6 +63,12 @@ void MetadataDB::throw_rdb_status_excpt(const rdb::Status& s) { } } /** * Gets a KV store value for a key * @param key * @return value * @throws DBException on failure, NotFoundException if entry doesn't exist */ std::string MetadataDB::get(const std::string& key) const { std::string val; auto s = db->Get(rdb::ReadOptions(), key, &val); Loading @@ -62,6 +78,12 @@ std::string MetadataDB::get(const std::string& key) const { return val; } /** * Puts an entry into the KV store * @param key * @param val * @throws DBException on failure */ void MetadataDB::put(const std::string& key, const std::string& val) { assert(gkfs::path::is_absolute(key)); assert(key == "/" || !gkfs::path::has_trailing_slash(key)); Loading @@ -73,6 +95,23 @@ void MetadataDB::put(const std::string& key, const std::string& val) { } } /** * Puts an entry into the KV store if it doesn't exist. This function does not use a mutex. * @param key * @param val * @throws DBException on failure, ExistException if entry already exists */ void MetadataDB::put_if_not_exist(const std::string& key, const std::string& val) { if (exists(key)) throw ExistsException(""); put(key, val); } /** * Removes an entry from the KV store * @param key * @throws DBException on failure, NotFoundException if entry doesn't exist */ void MetadataDB::remove(const std::string& key) { auto s = db->Delete(write_opts, key); if (!s.ok()) { Loading @@ -80,6 +119,12 @@ void MetadataDB::remove(const std::string& key) { } } /** * checks for existence of an entry * @param key * @return true if exists * @throws DBException on failure */ bool MetadataDB::exists(const std::string& key) { std::string val; auto s = db->Get(rdb::ReadOptions(), key, &val); Loading @@ -98,7 +143,7 @@ bool MetadataDB::exists(const std::string& key) { * @param old_key * @param new_key * @param val * @return * @throws DBException on failure, NotFoundException if entry doesn't exist */ void MetadataDB::update(const std::string& old_key, const std::string& new_key, const std::string& val) { //TODO use rdb::Put() method Loading @@ -111,6 +156,14 @@ void MetadataDB::update(const std::string& old_key, const std::string& new_key, } } /** * Increases only the size part of the metadentry via a RocksDB Operand Operation. * E.g., called before a write() call * @param key * @param size * @param append * @throws DBException on failure */ void MetadataDB::increase_size(const std::string& key, size_t size, bool append) { auto uop = IncreaseSizeOperand(size, append); auto s = db->Merge(write_opts, key, uop.serialize()); Loading @@ -119,6 +172,13 @@ void MetadataDB::increase_size(const std::string& key, size_t size, bool append) } } /** * Decreases only the size part of the metadentry via a RocksDB Operand Operation * E.g., called before a truncate() call * @param key * @param size * @throws DBException on failure */ void MetadataDB::decrease_size(const std::string& key, size_t size) { auto uop = DecreaseSizeOperand(size); auto s = db->Merge(write_opts, key, uop.serialize()); Loading Loading @@ -179,6 +239,9 @@ std::vector<std::pair<std::string, bool>> MetadataDB::get_dirents(const std::str return entries; } /** * Code example for iterating all entries in KV store. This is for debug only as it is too expensive */ void MetadataDB::iterate_all() { std::string key; std::string val; Loading @@ -190,6 +253,12 @@ void MetadataDB::iterate_all() { } } /** * Called when RocksDB connection is established. * Used for setting KV store settings * see here: https://github.com/facebook/rocksdb/wiki/RocksDB-Tuning-Guide * @param options */ void MetadataDB::optimize_rocksdb_options(rdb::Options& options) { options.max_successive_merges = 128; } Loading