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

File create: move exist check from client to daemon. Configuration added

parent 3656d5a9
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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 {
+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

+3 −1
Original line number Diff line number Diff line
@@ -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);
+49 −47
Original line number Diff line number Diff line
@@ -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()) {
@@ -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));
}
+70 −1
Original line number Diff line number Diff line
@@ -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();
@@ -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());

@@ -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);
@@ -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));
@@ -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()) {
@@ -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);
@@ -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
@@ -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());
@@ -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());
@@ -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;
@@ -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