Commit f00581ef authored by Marc Vef's avatar Marc Vef Committed by Alberto Miranda
Browse files

daemon: Added file handle for ChunkStorage, created central logging instance for backend data

parent 9700cccd
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -43,7 +43,6 @@ public:

class ChunkStorage {
private:
    static constexpr const char* LOGGER_NAME = "ChunkStorage";

    std::shared_ptr<spdlog::logger> log_;

+53 −0
Original line number Diff line number Diff line
/*
  Copyright 2018-2020, Barcelona Supercomputing Center (BSC), Spain
  Copyright 2015-2020, Johannes Gutenberg Universitaet Mainz, Germany

  This software was partially supported by the
  EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu).

  This software was partially supported by the
  ADA-FS project under the SPPEXA project funded by the DFG.

  SPDX-License-Identifier: MIT
*/

#ifndef GEKKOFS_DAEMON_DATA_LOGGING_HPP
#define GEKKOFS_DAEMON_DATA_LOGGING_HPP

#include <spdlog/spdlog.h>

namespace gkfs {
namespace data {

class DataModule {

private:
    DataModule() {}

    std::shared_ptr<spdlog::logger> log_;

public:

    static constexpr const char* LOGGER_NAME = "DataModule";

    static DataModule* getInstance() {
        static DataModule instance;
        return &instance;
    }

    DataModule(DataModule const&) = delete;

    void operator=(DataModule const&) = delete;

    const std::shared_ptr<spdlog::logger>& log() const;

    void log(const std::shared_ptr<spdlog::logger>& log);

};

#define GKFS_DATA_MOD (static_cast<gkfs::data::DataModule*>(gkfs::data::DataModule::getInstance()))

} // namespace data
} // namespace gkfs

#endif //GEKKOFS_DAEMON_DATA_LOGGING_HPP
+99 −0
Original line number Diff line number Diff line
/*
  Copyright 2018-2020, Barcelona Supercomputing Center (BSC), Spain
  Copyright 2015-2020, Johannes Gutenberg Universitaet Mainz, Germany

  This software was partially supported by the
  EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu).

  This software was partially supported by the
  ADA-FS project under the SPPEXA project funded by the DFG.

  SPDX-License-Identifier: MIT
*/

#ifndef GEKKOFS_DAEMON_FILE_HANDLE_HPP
#define GEKKOFS_DAEMON_FILE_HANDLE_HPP

#include <daemon/backend/data/data_module.hpp>

extern "C" {
#include <unistd.h>
}

namespace gkfs {
namespace data {

/**
 * File handle to encapsulate a file descriptor, allowing RAII closing of the file descriptor
 */
class FileHandle {

private:

    constexpr static const int init_value{-1};

    int fd_{init_value};
    std::string path_{};

public:

    FileHandle() = default;

    explicit FileHandle(int fd, std::string path) noexcept :
            fd_(fd) {}

    FileHandle(FileHandle&& rhs) = default;

    FileHandle(const FileHandle& other) = delete;

    FileHandle& operator=(FileHandle&& rhs) = default;

    FileHandle& operator=(const FileHandle& other) = delete;

    explicit operator bool() const noexcept {
        return valid();
    }

    bool operator!() const noexcept {
        return !valid();
    }

    bool
    valid() const noexcept {
        return fd_ != init_value;
    }

    int
    native() const noexcept {
        return fd_;
    }

    /**
     * Closes file descriptor and resets it to initial value
     * @return
     */
    bool close() noexcept {
        if (fd_ != init_value) {
            if (::close(fd_) < 0) {
                GKFS_DATA_MOD->log()->warn("{}() Failed to close file descriptor '{}' path '{}' errno '{}'", __func__,
                                           fd_, path_, ::strerror(errno));
                return false;
            }
        }
        fd_ = init_value;
        return true;
    }

    ~FileHandle() {
        if (fd_ != init_value)
            close();
    }


};

} // namespace data
} // namespace gkfs


#endif //GEKKOFS_DAEMON_FILE_HANDLE_HPP
+3 −0
Original line number Diff line number Diff line
@@ -6,7 +6,10 @@ target_sources(storage
    PRIVATE
    ${INCLUDE_DIR}/global/path_util.hpp
    ${INCLUDE_DIR}/global/global_defs.hpp
    ${INCLUDE_DIR}/daemon/backend/data/data_module.hpp
    ${INCLUDE_DIR}/daemon/backend/data/file_handle.hpp
    ${CMAKE_CURRENT_LIST_DIR}/chunk_storage.cpp
    ${CMAKE_CURRENT_LIST_DIR}/data_module.cpp
    )

target_link_libraries(storage
+22 −27
Original line number Diff line number Diff line
@@ -11,11 +11,12 @@
  SPDX-License-Identifier: MIT
*/

#include <daemon/backend/data/data_module.hpp>
#include <daemon/backend/data/chunk_storage.hpp>
#include <daemon/backend/data/file_handle.hpp>
#include <global/path_util.hpp>

#include <cerrno>
#include <utility>

#include <boost/filesystem.hpp>
#include <spdlog/spdlog.h>
@@ -75,8 +76,10 @@ void ChunkStorage::init_chunk_space(const string& file_path) const {
ChunkStorage::ChunkStorage(string& path, const size_t chunksize) :
        root_path_(path),
        chunksize_(chunksize) {
    /* Initialize logger */
    log_ = spdlog::get(LOGGER_NAME);
    /* Get logger instance and set it for data module and chunk storage */
    GKFS_DATA_MOD->log(spdlog::get(GKFS_DATA_MOD->LOGGER_NAME));
    assert(GKFS_DATA_MOD->log());
    log_ = spdlog::get(GKFS_DATA_MOD->LOGGER_NAME);
    assert(log_);
    assert(gkfs::path::is_absolute(root_path_));
    // Verify that we have sufficient access for chunk directories
@@ -129,25 +132,21 @@ ChunkStorage::write_chunk(const string& file_path, gkfs::rpc::chnk_id_t chunk_id
    init_chunk_space(file_path);

    auto chunk_path = absolute(get_chunk_path(file_path, chunk_id));
    int fd = open(chunk_path.c_str(), O_WRONLY | O_CREAT, 0640);
    if (fd < 0) {
        auto err_str = fmt::format("Failed to open chunk file for write. File: '{}', Error: '{}'", chunk_path,
                                   ::strerror(errno));

    FileHandle fh(open(chunk_path.c_str(), O_WRONLY | O_CREAT, 0640), chunk_path);
    if (!fh.valid()) {
        auto err_str = fmt::format("{}() Failed to open chunk file for write. File: '{}', Error: '{}'", __func__,
                                   chunk_path, ::strerror(errno));
        throw ChunkStorageException(errno, err_str);
    }

    auto wrote = pwrite(fd, buff, size, offset);
    auto wrote = pwrite(fh.native(), buff, size, offset);
    if (wrote < 0) {
        auto err_str = fmt::format("Failed to write chunk file. File: '{}', size: '{}', offset: '{}', Error: '{}'",
                                   chunk_path, size, offset, ::strerror(errno));
        auto err_str = fmt::format("{}() Failed to write chunk file. File: '{}', size: '{}', offset: '{}', Error: '{}'",
                                   __func__, chunk_path, size, offset, ::strerror(errno));
        throw ChunkStorageException(errno, err_str);
    }

    // if close fails we just write an entry into the log erroring out
    if (close(fd) < 0) {
        log_->warn("Failed to close chunk file after write. File: '{}', Error: '{}'",
                   chunk_path, ::strerror(errno));
    }
    // file is closed via the file handle's destructor.
    return wrote;
}

@@ -169,17 +168,18 @@ ChunkStorage::read_chunk(const string& file_path, gkfs::rpc::chnk_id_t chunk_id,
                         off64_t offset) const {
    assert((offset + size) <= chunksize_);
    auto chunk_path = absolute(get_chunk_path(file_path, chunk_id));
    int fd = open(chunk_path.c_str(), O_RDONLY);
    if (fd < 0) {
        auto err_str = fmt::format("Failed to open chunk file for read. File: '{}', Error: '{}'", chunk_path,
                                   ::strerror(errno));

    FileHandle fh(open(chunk_path.c_str(), O_RDONLY), chunk_path);
    if (!fh.valid()) {
        auto err_str = fmt::format("{}() Failed to open chunk file for read. File: '{}', Error: '{}'", __func__,
                                   chunk_path, ::strerror(errno));
        throw ChunkStorageException(errno, err_str);
    }
    size_t tot_read = 0;
    ssize_t read = 0;

    do {
        read = pread64(fd,
        read = pread64(fh.native(),
                       buf + tot_read,
                       size - tot_read,
                       offset + tot_read);
@@ -209,12 +209,7 @@ ChunkStorage::read_chunk(const string& file_path, gkfs::rpc::chnk_id_t chunk_id,
        tot_read += read;
    } while (tot_read != size);


    // if close fails we just write an entry into the log erroring out
    if (close(fd) < 0) {
        log_->warn("Failed to close chunk file after read. File: '{}', Error: '{}'",
                   chunk_path, ::strerror(errno));
    }
    // file is closed via the file handle's destructor.
    return tot_read;
}

Loading