Commit a8be39fd authored by Marc Vef's avatar Marc Vef
Browse files

Removing metadata and dentries is now handled by rocksdb

parent f2d2e5d5
Loading
Loading
Loading
Loading
+38 −10
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ using namespace rocksdb;
using namespace std;

inline const string db_get_mdata_helper(const string& key) {
    auto db = ADAFS_DATA->rdb().get();
    auto db = ADAFS_DATA->rdb();
    string val_str;
    db->Get(ReadOptions(), key, &val_str);
    return val_str;
@@ -31,19 +31,19 @@ unsigned int db_get_mdata<unsigned int>(const string& key) {
    return static_cast<unsigned int>(stoul(db_get_mdata_helper(key)));
}

//void db_delete_mdata() {
//    auto db = ADAFS_DATA->rdb().get();
//    db->DeleteRange()
//}
bool db_delete_mdata(const string& key) {
    auto db = ADAFS_DATA->rdb();
    return db->Delete(WriteOptions(), key).ok();
}

bool db_dentry_exists(const fuse_ino_t p_inode, const string& name, string& val) {
    auto db = ADAFS_DATA->rdb().get();
    auto db = ADAFS_DATA->rdb();
    auto key = "d_"s + fmt::FormatInt(p_inode).str() + "_"s + name;
    return db->Get(rocksdb::ReadOptions(), key, &val).ok();
}

bool db_mdata_exists(const fuse_ino_t inode) {
    auto db = ADAFS_DATA->rdb().get();
    auto db = ADAFS_DATA->rdb();
    string val_str;
    return db->Get(ReadOptions(),
                   fmt::FormatInt(inode).str() + std::get<to_underlying(Md_fields::atime)>(md_field_map),
@@ -51,7 +51,7 @@ bool db_mdata_exists(const fuse_ino_t inode) {
}

bool db_put_dentry(const string& key, const string& val) {
    auto db = ADAFS_DATA->rdb().get();
    auto db = ADAFS_DATA->rdb();
    return db->Put(rocksdb::WriteOptions(), key, val).ok();
}

@@ -81,11 +81,39 @@ void db_get_dentries(vector<Dentry>& dentries, const fuse_ino_t dir_inode) {
        val.erase(0, pos + 1); // Erase inode + delim
        dentry.mode(static_cast<mode_t>(stoul(val))); // val holds only mode
        // append dentry to dentries vector
        ADAFS_DATA->spdlogger()->info("Retrieved dentry: name {} inode {} mode {}", dentry.name(), dentry.inode(),
        ADAFS_DATA->spdlogger()->trace("Retrieved dentry: name {} inode {} mode {}", dentry.name(), dentry.inode(),
                                       dentry.mode());
        dentries.push_back(dentry);
    }
}

pair<bool, fuse_ino_t> db_delete_dentry_get_inode(const fuse_ino_t p_inode, const string& name) {
    auto key = "d_"s + fmt::FormatInt(p_inode).str() + "_"s + name;
    auto db = ADAFS_DATA->rdb();
    string val;
    db->Get(ReadOptions(), key, &val);
    auto pos = val.find("_");

    return make_pair(db->Delete(WriteOptions(), key).ok() ? 0 : 1, static_cast<fuse_ino_t>(stoul(val.substr(0, pos))));
}

/**
 * Returns true if no dentries can be found for the prefix <d_ParentInode>
 * @param inode
 * @return bool
 */
bool db_is_dir_empty(const fuse_ino_t inode) {
    auto dir_empty = true;
    auto db = ADAFS_DATA->rdb();
    auto prefix = "d_"s + fmt::FormatInt(inode).str();
    auto dentry_iter = db->NewIterator(rocksdb::ReadOptions());
    for (dentry_iter->Seek(prefix);
         dentry_iter->Valid() && dentry_iter->key().starts_with(prefix); dentry_iter->Next()) {
        dir_empty = false;
        break;
    }
    return dir_empty;
}


+6 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ bool db_put_mdata(const std::string& key, const T val) {
template<typename T>
T db_get_mdata(const std::string& key);

bool db_delete_mdata(const std::string& key);

bool db_dentry_exists(const fuse_ino_t p_inode, const std::string& name, std::string& val);

bool db_mdata_exists(const fuse_ino_t inode);
@@ -26,4 +28,8 @@ bool db_put_dentry(const std::string& key, const std::string& val);

void db_get_dentries(std::vector<Dentry>& dentries, const fuse_ino_t dir_inode);

std::pair<bool, fuse_ino_t> db_delete_dentry_get_inode(const fuse_ino_t p_inode, const std::string& name);

bool db_is_dir_empty(const fuse_ino_t inode);

#endif //LFS_DB_OPS_HPP
+5 −28
Original line number Diff line number Diff line
@@ -2,13 +2,9 @@
// Created by evie on 3/17/17.
//

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include "dentry_ops.hpp"
#include "db_ops.hpp"

#include "../classes/dentry.h"

using namespace std;

/**
@@ -132,29 +128,16 @@ int create_dentry(const fuse_ino_t p_inode, const fuse_ino_t inode, const string
}

/**
 * Removes a dentry from the parent directory. It is not tested if the parent inode path exists. This should have been
 * Removes a dentry from the parent directory. It is not tested if the parent inode exists. This should have been
 * done by do_lookup preceeding this call (impicit or explicit).
 * Currently just a wrapper for the db operation
 * @param p_inode
 * @param name
 * @return pair<err, inode>
 */
// XXX errorhandling
pair<int, fuse_ino_t> remove_dentry(const fuse_ino_t p_inode, const string& name) {
    int inode; // file inode to be read from dentry before deletion
    auto d_path = bfs::path(ADAFS_DATA->dentry_path());
    d_path /= fmt::FormatInt(p_inode).c_str();
    d_path /= name;

    // retrieve inode number of dentry
    bfs::ifstream ifs{d_path};
    boost::archive::binary_iarchive ba(ifs);
    ba >> inode;

    bfs::remove(d_path);

    // XXX make sure dentry has been deleted

    return make_pair(0, inode);
    return db_delete_dentry_get_inode(p_inode, name);
}

/**
@@ -163,11 +146,5 @@ pair<int, fuse_ino_t> remove_dentry(const fuse_ino_t p_inode, const string &name
 * @return err
 */
int is_dir_empty(const fuse_ino_t inode) {
    auto d_path = bfs::path(ADAFS_DATA->dentry_path());
    d_path /= fmt::FormatInt(inode).c_str();
    if (bfs::is_empty(d_path))
        return 0;
    else
        return ENOTEMPTY;

    return db_is_dir_empty(inode) ? 0 : ENOTEMPTY;
}
+28 −24
Original line number Diff line number Diff line
@@ -6,9 +6,8 @@
#include "dentry_ops.hpp"



// TODO error handling. Each read_metadata_field should check for boolean, i.e., if I/O failed.
bool write_all_metadata(const Metadata& md, const fuse_ino_t inode) {
// TODO error handling.
int write_all_metadata(const Metadata& md, const fuse_ino_t inode) {
    auto inode_key = fmt::FormatInt(inode).str();

    db_put_mdata(inode_key + std::get<to_underlying(Md_fields::atime)>(md_field_map), md.atime());
@@ -21,11 +20,11 @@ bool write_all_metadata(const Metadata& md, const fuse_ino_t inode) {
    db_put_mdata(inode_key + std::get<to_underlying(Md_fields::link_count)>(md_field_map), md.link_count());
    db_put_mdata(inode_key + std::get<to_underlying(Md_fields::size)>(md_field_map), md.size());
    db_put_mdata(inode_key + std::get<to_underlying(Md_fields::blocks)>(md_field_map), md.blocks());
    return true;
    return 0;
}

// TODO error handling. Each read_metadata_field should check for nullptr, i.e., if I/O failed.
bool read_all_metadata(Metadata& md, const fuse_ino_t inode) {
// TODO error handling.
int read_all_metadata(Metadata& md, const fuse_ino_t inode) {
    auto inode_key = fmt::FormatInt(inode).str();

    md.atime(db_get_mdata<time_t>(inode_key + std::get<to_underlying(Md_fields::atime)>(md_field_map)));
@@ -38,7 +37,29 @@ bool read_all_metadata(Metadata& md, const fuse_ino_t inode) {
    md.link_count(db_get_mdata<nlink_t>(inode_key + std::get<to_underlying(Md_fields::link_count)>(md_field_map)));
    md.size(db_get_mdata<off_t>(inode_key + std::get<to_underlying(Md_fields::size)>(md_field_map)));
    md.blocks(db_get_mdata<blkcnt_t>(inode_key + std::get<to_underlying(Md_fields::blocks)>(md_field_map)));
    return true;
    return 0;
}

/**
 * Removes the metadata of a file based on the inode. The function does not check if the inode exists. This should
 * be done by the get_metadata() (implicit or explicit)
 * @param inode
 * @return err
 */
int remove_all_metadata(const fuse_ino_t inode) {
    // TODO error handling
    auto inode_key = fmt::FormatInt(inode).str();
    db_delete_mdata(inode_key + std::get<to_underlying(Md_fields::atime)>(md_field_map));
    db_delete_mdata(inode_key + std::get<to_underlying(Md_fields::mtime)>(md_field_map));
    db_delete_mdata(inode_key + std::get<to_underlying(Md_fields::ctime)>(md_field_map));
    db_delete_mdata(inode_key + std::get<to_underlying(Md_fields::uid)>(md_field_map));
    db_delete_mdata(inode_key + std::get<to_underlying(Md_fields::gid)>(md_field_map));
    db_delete_mdata(inode_key + std::get<to_underlying(Md_fields::mode)>(md_field_map));
    db_delete_mdata(inode_key + std::get<to_underlying(Md_fields::inode_no)>(md_field_map));
    db_delete_mdata(inode_key + std::get<to_underlying(Md_fields::link_count)>(md_field_map));
    db_delete_mdata(inode_key + std::get<to_underlying(Md_fields::size)>(md_field_map));
    db_delete_mdata(inode_key + std::get<to_underlying(Md_fields::blocks)>(md_field_map));
    return 0;
}

/**
@@ -90,23 +111,6 @@ void metadata_to_stat(const Metadata& md, struct stat& attr) {
    attr.st_ctim.tv_sec = md.ctime();
}

/**
 * Removes the metadata of a file based on the inode. The function does not check if the inode path exists. This should
 * be done by the get_metadata() (implicit or explicit)
 * @param inode
 * @return err
 */
int remove_metadata(const fuse_ino_t inode) {
    // XXX Errorhandling
    auto i_path = bfs::path(ADAFS_DATA->inode_path());
    i_path /= fmt::FormatInt(inode).c_str();

    bfs::remove_all(i_path);
    // XXX make sure metadata has been deleted

    return 0;
}

/**
 * Creates a new node (file or directory) in the file system. Fills given fuse_entry_param.
 * @param req
+3 −39
Original line number Diff line number Diff line
@@ -9,9 +9,6 @@
#include "../classes/metadata.h"
#include "db_ops.hpp"

#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>

using namespace std;

template <typename E>
@@ -26,42 +23,11 @@ const std::array<std::string, 10> md_field_map = {
        "_atime"s, "_mtime"s, "_ctime"s, "_uid"s, "_gid"s, "_mode"s, "_inodeno"s, "_lnkcnt"s, "_size"s, "_blkcnt"s
};

bool write_all_metadata(const Metadata& md, const fuse_ino_t inode);

// TODO error handling.
template<typename T>
bool write_metadata_field(const T& field, const string& field_name, const fuse_ino_t inode) {
    auto i_path = bfs::path(ADAFS_DATA->inode_path());
    i_path /= fmt::FormatInt(inode).c_str();
    bfs::create_directories(i_path);
    i_path /= field_name;

    bfs::ofstream ofs{i_path};
    // write to disk in binary form
    boost::archive::binary_oarchive ba(ofs);
    ba << field;

    return true;
}

bool read_all_metadata(Metadata& md, const fuse_ino_t inode);
int write_all_metadata(const Metadata& md, const fuse_ino_t inode);

// TODO error handling
template<typename T>
unique_ptr<T> read_metadata_field(const string& field_name, const fuse_ino_t inode) {
    auto path = bfs::path(ADAFS_DATA->inode_path());
    path /= fmt::FormatInt(inode).c_str();
    path /= field_name;
    if (!bfs::exists(path)) return nullptr;
int read_all_metadata(Metadata& md, const fuse_ino_t inode);

    bfs::ifstream ifs{path};
    //fast error checking
    //ifs.good()
    boost::archive::binary_iarchive ba(ifs);
    auto field = make_unique<T>();
    ba >> *field;
    return field;
}
int remove_all_metadata(const fuse_ino_t inode);

int get_metadata(Metadata& md, const fuse_ino_t inode);

@@ -69,8 +35,6 @@ int get_attr(struct stat& attr, const fuse_ino_t inode);

void metadata_to_stat(const Metadata& md, struct stat& attr);

int remove_metadata(const fuse_ino_t inode);

int create_node(fuse_req_t& req, struct fuse_entry_param& fep, fuse_ino_t parent, const string& name, mode_t mode);

#endif //FS_METADATA_OPS_H
Loading