Commit 29016c0f authored by Marc Vef's avatar Marc Vef
Browse files

Using pathnames for metadata keys for now. using hashing to write metadata. TODO read metadata.

Added hashmap for caching, Initializing root metadata if not there.
parent c0a072a1
Loading
Loading
Loading
Loading
+55 −17
Original line number Diff line number Diff line
@@ -7,14 +7,30 @@ static struct fuse_operations adafs_ops;

using namespace std;

//std::shared_ptr<Metadata> md;

int adafs_getattr(const char *path, struct stat *attr, struct fuse_file_info *fi){
    auto fpath = util::adafs_fullpath("meta/inodes"s);
    //FUSE_UNKNOWN_INO errorcode if attr->st_ino could not be resolved by VFS (This is unverified information
    // but Fuse initializes it with this value initially fuse.c:3303

//    if (attr->st_ino == -1) {
//        ADAFS_DATA->logger->info("st_ino = -1: "s + to_string(attr->st_ino));
//    } else {
//        ADAFS_DATA->logger->info("st_ino != -1: "s + to_string(attr->st_ino));
//    }

//    ADAFS_DATA->logger->info("adafs_getattr_enter1"s);
//    ADAFS_DATA->logger->info("st_ino: "s + to_string(attr->st_ino));
//    ADAFS_DATA->logger->info("adafs_getattr_enter2"s);
    // call lookup for *path, return int (use errorcodes), put pointer to Metadata object in parameter
    // if exist (i.e. == 0) use Metadata object, else return ENOENT
//    auto path_s = bfs::path(path);
//    ADAFS_DATA->logger->info(path_s);
//    ADAFS_DATA->logger->flush();
    auto md = make_shared<Metadata>();
    md->mode(S_IFDIR | 0755);
    md->inode_no(1);
    read_all_metadata(*md, 1, fpath);
//    md->mode(S_IFDIR | 0755);
//    md->inode_no(1);
//    get_metadata(*md, path_s);
//    read_all_metadata(*md, 1, fpath);
    if (strcmp(path, "/") == 0) {
        attr->st_ino = md->inode_no();
        attr->st_mode = md->mode();
@@ -31,6 +47,15 @@ int adafs_getattr(const char *path, struct stat *attr, struct fuse_file_info *fi
    }

    if (strcmp(path, "/file") == 0) {
        attr->st_mode = S_IFDIR | 0755;
        return 0;
    }
    if (strcmp(path, "/file/file2") == 0) {
        auto p_dir = make_shared<struct stat>();
        lstat("/", p_dir.get());
        ADAFS_DATA->logger->info(p_dir->st_ino);
        ADAFS_DATA->logger->flush();

        attr->st_mode = S_IFREG | 0755;
        attr->st_nlink = 1;
        attr->st_size = strlen("blubb");
@@ -46,26 +71,35 @@ void *adafs_init(struct fuse_conn_info *conn, struct fuse_config *cfg) {
//    ADAFS_DATA->logger->info("gid_: {}", fuse_get_context()->gid);
//    ADAFS_DATA->logger->info("pid: {0:d}", fuse_get_context()->pid);
//    ADAFS_DATA->logger->info("rootdir: {}", ((struct adafs_data*)fuse_get_context()->private_data)->rootdir);
    //Initialize directory structure for metadata.
    //Initialize directory structure for metadata. XXX We need this later for lowlevel when we split dentry from inodes
    boost::filesystem::create_directories(ADAFS_DATA->rootdir + "/meta/dentries"s);
    boost::filesystem::create_directories(ADAFS_DATA->rootdir + "/meta/inodes"s);
    boost::filesystem::create_directories(ADAFS_DATA->rootdir + "/data/chunks"s);

    // XXX Dunno if this is of any use
    cfg->use_ino = 1;

    //Init file system configuration
    ADAFS_DATA->blocksize = 4096;

    // Init unordered_map for caching metadata that was already looked up XXX use later
    ADAFS_DATA->hashmap = unordered_map<string, string>();
    ADAFS_DATA->hashf = hash<string>();

    //Init metadata
//    if (get_metadata("/") == -ENOENT) {
//        md = make_shared<Metadata>(S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO);
//        auto md = make_shared<Metadata>(S_IFDIR | 0755);
//    }
//    auto s = util::adafs_fullpath("meta/inodes");
//
    auto md = make_shared<Metadata>();

//    write_all_metadata(*md, s);
    // Check that root metadata exists. If not intiialize it
    if (get_metadata(*md, "/"s) == -ENOENT) {
        ADAFS_DATA->logger->info("Root metadata not found. Initializing..."s);
        md->init_ACM_time();
        md->mode(S_IFDIR | 0755);
        md->uid(fuse_get_context()->uid);
        md->gid(fuse_get_context()->gid);
        md->inode_no(ADAFS_ROOT_INODE);
        write_all_metadata(*md, ADAFS_DATA->hashf("/"s), ADAFS_DATA->inode_path);
        ADAFS_DATA->logger->info("Creating Metadata object"s);
    }

    ADAFS_DATA->logger->info("Survived creating Metadata object"s);
    ADAFS_DATA->logger->flush();

    return ADAFS_DATA;
@@ -89,7 +123,7 @@ int main(int argc, char *argv[]) {
    //Initialize the mapping of Fuse functions
    init_adafs_ops(&adafs_ops);

    // create the adafs_data object (struct)
    // create the private data struct
    auto a_data = make_shared<adafs_data>();
    //set the logger and initialize it with spdlog
    a_data->logger = spdlog::basic_logger_mt("basic_logger", "adafs.log");
@@ -98,8 +132,12 @@ int main(int argc, char *argv[]) {
    argv[argc-2] = argv[argc-1];
    argv[argc-1] = NULL;
    argc--;
    //init fuse and give the private data for further reference.
    //set all paths
    a_data->inode_path = a_data->rootdir + "meta/inodes"s;
    a_data->dentry_path = a_data->rootdir + "meta/dentries"s;
    a_data->chunk_path = a_data->rootdir + "data/chunks"s;
    //print version
    cout << "Fuse library version: "s + to_string(FUSE_MAJOR_VERSION) + to_string(FUSE_MINOR_VERSION) << endl;
    //init fuse and give the private data struct for further reference.
    return fuse_main(argc, argv, &adafs_ops, a_data.get());
}
+20 −6
Original line number Diff line number Diff line
@@ -12,25 +12,39 @@
#include <string>
#include <iostream>
#include <cstdint>
#include <unordered_map>

//boost libraries
#include <boost/filesystem.hpp>

#include "spdlog/spdlog.h"

namespace bfs = boost::filesystem;

struct adafs_data {
    std::string rootdir;
    // Below paths are needed for future version when we'll get rid of path hashing.
    std::string inode_path; // used
    std::string dentry_path; // unused
    std::string chunk_path; // unused

    // Caching
    std::unordered_map<std::string, std::string> hashmap;
    std::hash<std::string> hashf;

    // Housekeeping
    std::shared_ptr<spdlog::logger> logger;
    std::int64_t inode_count;
    std::mutex inode_mutex;
    // Later the blocksize will likely be coupled to the chunks to allow individually big chunk sizes.
    int32_t blocksize;
};

#define ADAFS_DATA ((struct adafs_data*) fuse_get_context()->private_data)
#define ADAFS_ROOT_INODE 1

namespace util {
    std::string adafs_fullpath(const std::string &path);
    boost::filesystem::path adafs_fullpath(const std::string& path);

    int reset_inode_no();

+3 −3
Original line number Diff line number Diff line
@@ -94,9 +94,9 @@ Metadata::Metadata() : atime_(),
                       gid_(),
                       mode_(),
                       inode_no_(),
                       link_count_(),
                       size_(),
                       blocks_() {}
                       link_count_(0),
                       size_(0),
                       blocks_(0) {}

Metadata::Metadata(mode_t mode) :
        atime_(),
+2 −1
Original line number Diff line number Diff line
@@ -19,13 +19,14 @@ private:
    uint32_t size_;              // size_ in bytes, might be computed instead of stored
    uint32_t blocks_;            // allocated file system blocks_

    void init_ACM_time();

public:
    Metadata();

    Metadata(mode_t mode);

    void init_ACM_time();

    //Getter and Setter
    time_t atime() const;

+79 −35
Original line number Diff line number Diff line
@@ -7,48 +7,51 @@
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>

namespace fs = boost::filesystem;

// 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 std::string &path_str) {
    write_metadata_field(md.atime(), md.inode_no(), "/atime"s, path_str);
    write_metadata_field(md.mtime(), md.inode_no(), "/mtime"s, path_str);
    write_metadata_field(md.ctime(), md.inode_no(), "/ctime"s, path_str);
    write_metadata_field(md.uid(), md.inode_no(), "/uid"s, path_str);
    write_metadata_field(md.gid(), md.inode_no(), "/gid"s, path_str);
    write_metadata_field(md.mode(), md.inode_no(), "/mode"s, path_str);
    write_metadata_field(md.inode_no(), md.inode_no(), "/inode_no"s, path_str);
    write_metadata_field(md.link_count(), md.inode_no(), "/link_count"s, path_str);
    write_metadata_field(md.size(), md.inode_no(), "/size"s, path_str);
    write_metadata_field(md.blocks(), md.inode_no(), "/blocks"s, path_str);
bool write_all_metadata(const Metadata& md, const unsigned long& hash, const bfs::path& i_path) {
    write_metadata_field(md.atime(), hash, "/atime"s, i_path);
    write_metadata_field(md.mtime(), hash, "/mtime"s, i_path);
    write_metadata_field(md.ctime(), hash, "/ctime"s, i_path);
    write_metadata_field(md.uid(), hash, "/uid"s, i_path);
    write_metadata_field(md.gid(), hash, "/gid"s, i_path);
    write_metadata_field(md.mode(), hash, "/mode"s, i_path);
    write_metadata_field(md.inode_no(), hash, "/inode_no"s, i_path);
    write_metadata_field(md.link_count(), hash, "/link_count"s, i_path);
    write_metadata_field(md.size(), hash, "/size"s, i_path);
    write_metadata_field(md.blocks(), hash, "/blocks"s, i_path);

    return true;
}

bool write_all_metadata(const Metadata& md, const unsigned long& hash, const string& i_path) {
    return write_all_metadata(md, hash, bfs::path(i_path));
}

// TODO error handling. Each read_metadata_field should check for nullptr, i.e., if I/O failed.
bool read_all_metadata(Metadata &md, const uint64_t &inode, const std::string &path_str) {
    md.atime(*read_metadata_field<time_t>(inode, "/atime"s, path_str));
    md.mtime(*read_metadata_field<time_t>(inode, "/mtime"s, path_str));
    md.ctime(*read_metadata_field<time_t>(inode, "/ctime"s, path_str));
    md.uid(*read_metadata_field<uint32_t>(inode, "/uid"s, path_str));
    md.gid(*read_metadata_field<uint32_t>(inode, "/gid"s, path_str));
    md.mode(*read_metadata_field<uint32_t>(inode, "/mode"s, path_str));
    md.inode_no(*read_metadata_field<uint64_t>(inode, "/inode_no"s, path_str));
    md.link_count(*read_metadata_field<uint32_t>(inode, "/link_count"s, path_str));
    md.size(*read_metadata_field<uint32_t>(inode, "/size"s, path_str));
    md.blocks(*read_metadata_field<uint32_t>(inode, "/blocks"s, path_str));
bool read_all_metadata(Metadata& md, const uint64_t& inode, const bfs::path& i_path) {
    md.atime(*read_metadata_field<time_t>(inode, "/atime"s, i_path));
    md.mtime(*read_metadata_field<time_t>(inode, "/mtime"s, i_path));
    md.ctime(*read_metadata_field<time_t>(inode, "/ctime"s, i_path));
    md.uid(*read_metadata_field<uint32_t>(inode, "/uid"s, i_path));
    md.gid(*read_metadata_field<uint32_t>(inode, "/gid"s, i_path));
    md.mode(*read_metadata_field<uint32_t>(inode, "/mode"s, i_path));
    md.inode_no(*read_metadata_field<uint64_t>(inode, "/inode_no"s, i_path));
    md.link_count(*read_metadata_field<uint32_t>(inode, "/link_count"s, i_path));
    md.size(*read_metadata_field<uint32_t>(inode, "/size"s, i_path));
    md.blocks(*read_metadata_field<uint32_t>(inode, "/blocks"s, i_path));
    return true;
}

// TODO error handling.
template<typename T>
bool write_metadata_field(const T &field, const uint64_t &inode, const string &fname, const string &p) {
    auto i_path = p + "/" + to_string(inode);
    fs::create_directories(i_path);
    auto file = fs::path{i_path + fname};
    // for some reason auto ofs = fs::ofstream(file); does not work. That is why I use the old style.
bool write_metadata_field(const T& field, const unsigned long& hash, const string& fname, bfs::path path) {
    path.append(to_string(hash));
    bfs::create_directories(path);

    path.append(fname);
    // for some reason auto ofs = bfs::ofstream(file); does not work. That is why I use the old style.
    // std::basic_ofstream does not encounter this problem
    fs::ofstream ofs{file};
    bfs::ofstream ofs{path};
    // write to disk in binary form
    boost::archive::binary_oarchive ba(ofs);
    ba << field;
@@ -57,11 +60,12 @@ bool write_metadata_field(const T &field, const uint64_t &inode, const string &f
}

template<typename T>
unique_ptr<T> read_metadata_field(const uint64_t &inode, const string &fname, const string &p) {
    auto i_path = p + "/" + to_string(inode);
    if (!fs::exists(i_path)) return nullptr;
    auto file = fs::path(i_path + fname);
    fs::ifstream ifs{file};
unique_ptr<T> read_metadata_field(const uint64_t& inode, const string& fname, bfs::path path) {
    path.append(to_string(inode));
    if (!bfs::exists(path)) return nullptr;

    path.append(fname);
    bfs::ifstream ifs{path};
    //fast error checking
    //ifs.good()
    boost::archive::binary_iarchive ba(ifs);
@@ -70,4 +74,44 @@ unique_ptr<T> read_metadata_field(const uint64_t &inode, const string &fname, co
    return field;
}

// Returns the inode for given path. ENOENT if not found
int read_dentry_inode(const std::string path) {
    return 0;
}

int get_metadata(Metadata& md, const std::string& path) {
    return get_metadata(md, bfs::path(path));
}

int get_metadata(Metadata& md, const bfs::path& path) {

//    // TODO HOW TO DO THE LOOKUP PROPERLY? SO NO INODE TYPE CLASH
//    auto inode = lookup(path);
//    ADAFS_DATA->logger->info("get_metadata() inode: {} for path: {}", inode, path);
//    if (inode == -ENOENT) {
//        // If no inode is found lookup father path
//        // <lookup father here>
//        // If still on return inode is not found, return ENOENT
//        return -ENOENT;
//    }
//    auto i_path = util::adafs_fullpath(ADAFS_DATA->inode_path + "/"s + to_string(inode));
//    read_all_metadata(md, inode, i_path);

    return -ENOENT;
}

//int lookup(const string& path) {
//    return lookup(bfs::path(path));
//}
//
int lookup(const bfs::path& path) {
//    if ("/"s.compare(path)) {
//        return ADAFS_ROOT_INODE;
//    } else {
//        return -ENOENT;
//    }
    return 0;
}


Loading