Verified Commit f92a5275 authored by Marc Vef's avatar Marc Vef
Browse files

File create: exist check now done on daemon. Configuration added

parent 072f1209
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -48,6 +48,11 @@ 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 {
+5 −0
Original line number Diff line number Diff line
@@ -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

+4 −1
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ 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;
@@ -45,6 +45,9 @@ public:
    void
    put(const std::string& key, const std::string& val);

    void
    put_no_exist(const std::string& key, const std::string& val);

    void
    remove(const std::string& key);

+50 −50
Original line number Diff line number Diff line
@@ -128,49 +128,50 @@ gkfs_open(const std::string& path, mode_t mode, int flags) {
        errno = ENOTSUP;
        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);

    // metadata pointer assigned during create or stat
    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;
            }
        }
    }
    assert(md);

#ifdef HAS_SYMLINKS
    if(md->is_link()) {
@@ -197,7 +198,6 @@ 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));
+70 −1
Original line number Diff line number Diff line
@@ -24,6 +24,11 @@ extern "C" {

namespace gkfs::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();
@@ -41,6 +46,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());
@@ -52,6 +63,12 @@ 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;
@@ -62,6 +79,12 @@ 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));
@@ -74,6 +97,25 @@ 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_no_exist(const std::string& key, const std::string& val) {
    if(exists(key))
        throw ExistsException(key);
    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);
@@ -82,6 +124,12 @@ 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;
@@ -101,7 +149,7 @@ 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,
@@ -116,6 +164,14 @@ 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);
@@ -125,6 +181,13 @@ 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);
@@ -254,6 +317,12 @@ 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