<commit_before>/**
 * @file IStorageHelper.h
 * @author <NAME>
 * @copyright (C) 2013 ACK CYFRONET AGH
 * @copyright This software is released under the MIT license cited in
 * 'LICENSE.txt'
 */

#ifndef HELPERS_I_STORAGE_HELPER_H
#define HELPERS_I_STORAGE_HELPER_H

#include <fuse.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <asio/buffer.hpp>
#include <boost/any.hpp>
#include <boost/filesystem/path.hpp>
#include <tbb/concurrent_hash_map.h>

#include <chrono>
#include <future>
#include <memory>
#include <string>
#include <system_error>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace one {
namespace helpers {

using error_t = std::error_code;

namespace {
constexpr std::chrono::seconds ASYNC_OPS_TIMEOUT{2};
const error_t SUCCESS_CODE;
}

enum class Flag {
    NONBLOCK,
    APPEND,
    ASYNC,
    FSYNC,
    NOFOLLOW,
    CREAT,
    TRUNC,
    EXCL,
    RDONLY,
    WRONLY,
    RDWR,
    IFREG,
    IFCHR,
    IFBLK,
    IFIFO,
    IFSOCK
};

struct FlagHash {
    template <typename T> std::size_t operator()(T t) const
    {
        return static_cast<std::size_t>(t);
    }
};

using FlagsSet = std::unordered_set<Flag, FlagHash>;

class IStorageHelperCTX {
public:
    /**
     * Creates a context with given parameters.
     * @param params The parameters of file context.
     */
    IStorageHelperCTX(std::unordered_map<std::string, std::string> params)
        : m_params{std::move(params)}
    {
    }

    virtual ~IStorageHelperCTX() = default;

    /**
     * Sets user context parameters.
     * @param args Map with parameters required to set user context.
     */
    virtual void setUserCTX(std::unordered_map<std::string, std::string> args)
    {
    }

    /**
     * Returns user context parameters.
     * @return map used to create user context.
     */
    virtual std::unordered_map<std::string, std::string> getUserCTX()
    {
        throw std::system_error{
            std::make_error_code(std::errc::function_not_supported)};
    }

    /**
     * Returns parameters set in constructor.
     */
    const std::unordered_map<std::string, std::string> &parameters() const
    {
        return m_params;
    }

protected:
    static error_t makePosixError(int posixCode)
    {
        posixCode = posixCode > 0 ? posixCode : -posixCode;
        return error_t(posixCode, std::system_category());
    }

private:
    std::unordered_map<std::string, std::string> m_params;
};

using CTXPtr = std::shared_ptr<IStorageHelperCTX>;

template <class... T>
using GeneralCallback = std::function<void(T..., error_t)>;
using VoidCallback = GeneralCallback<>;

template <class T> using future_t = std::future<T>;
template <class T> using promise_t = std::promise<T>;

/**
 * The IStorageHelper interface.
 * Base class of all storage helpers. Unifies their interface.
 * All callback have their equivalent in FUSE API and should be used in that
 * matter.
 */
class IStorageHelper {
public:
    virtual ~IStorageHelper() = default;

    virtual CTXPtr createCTX(
        std::unordered_map<std::string, std::string> params)
    {
        return std::make_shared<IStorageHelperCTX>(std::move(params));
    }

    virtual void ash_getattr(CTXPtr ctx, const boost::filesystem::path &p,
        GeneralCallback<struct stat> callback)
    {
        callback({}, std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_access(CTXPtr ctx, const boost::filesystem::path &p,
        int mask, VoidCallback callback)
    {
        callback({});
    }

    virtual void ash_readlink(CTXPtr ctx, const boost::filesystem::path &p,
        GeneralCallback<std::string> callback)
    {
        callback({}, std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_readdir(CTXPtr ctx, const boost::filesystem::path &p,
        off_t offset, size_t count,
        GeneralCallback<const std::vector<std::string> &> callback)
    {
        callback({}, std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_mknod(CTXPtr ctx, const boost::filesystem::path &p,
        mode_t mode, FlagsSet flags, dev_t rdev, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_mkdir(CTXPtr ctx, const boost::filesystem::path &p,
        mode_t mode, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_unlink(
        CTXPtr ctx, const boost::filesystem::path &p, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_rmdir(
        CTXPtr ctx, const boost::filesystem::path &p, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_symlink(CTXPtr ctx, const boost::filesystem::path &from,
        const boost::filesystem::path &to, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_rename(CTXPtr ctx, const boost::filesystem::path &from,
        const boost::filesystem::path &to, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_link(CTXPtr ctx, const boost::filesystem::path &from,
        const boost::filesystem::path &to, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_chmod(CTXPtr ctx, const boost::filesystem::path &p,
        mode_t mode, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_chown(CTXPtr ctx, const boost::filesystem::path &p,
        uid_t uid, gid_t gid, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_truncate(CTXPtr ctx, const boost::filesystem::path &p,
        off_t size, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_open(CTXPtr ctx, const boost::filesystem::path &p,
        FlagsSet flags, GeneralCallback<int> callback)
    {
        ash_open(std::move(ctx), p, flagsToMask(std::move(flags)),
            std::move(callback));
    }

    virtual void ash_open(CTXPtr ctx, const boost::filesystem::path &p,
        int flags, GeneralCallback<int> callback)
    {
        callback({}, SUCCESS_CODE);
    }

    virtual void ash_read(CTXPtr ctx, const boost::filesystem::path &p,
        asio::mutable_buffer buf, off_t offset,
        GeneralCallback<asio::mutable_buffer> callback)
    {
        callback({}, std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_write(CTXPtr ctx, const boost::filesystem::path &p,
        asio::const_buffer buf, off_t offset,
        GeneralCallback<std::size_t> callback)
    {
        callback({}, std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_release(
        CTXPtr ctx, const boost::filesystem::path &p, VoidCallback callback)
    {
        callback(SUCCESS_CODE);
    }

    virtual void ash_flush(
        CTXPtr ctx, const boost::filesystem::path &p, VoidCallback callback)
    {
        callback({});
    }

    virtual void ash_fsync(CTXPtr ctx, const boost::filesystem::path &p,
        bool isDataSync, VoidCallback callback)
    {
        callback({});
    }

    virtual void sh_fsync(
        CTXPtr ctx, const boost::filesystem::path &p, bool isDataSync)
    {
        sync(&IStorageHelper::ash_fsync, std::move(ctx), p, isDataSync);
    }

    virtual void sh_flush(CTXPtr ctx, const boost::filesystem::path &p)
    {
        sync(&IStorageHelper::ash_flush, std::move(ctx), p);
    }

    virtual asio::mutable_buffer sh_read(CTXPtr ctx,
        const boost::filesystem::path &p, asio::mutable_buffer buf,
        off_t offset)
    {
        return sync<asio::mutable_buffer>(
            &IStorageHelper::ash_read, std::move(ctx), p, buf, offset);
    }

    virtual std::size_t sh_write(CTXPtr ctx, const boost::filesystem::path &p,
        asio::const_buffer buf, off_t offset)
    {
        return sync<std::size_t>(
            &IStorageHelper::ash_write, std::move(ctx), p, buf, offset);
    }

    virtual int sh_open(CTXPtr ctx, const boost::filesystem::path &p, int flags)
    {
        return sync<int>(
            static_cast<void (IStorageHelper::*)(CTXPtr,
                const boost::filesystem::path &, int, GeneralCallback<int>)>(
                &IStorageHelper::ash_open),
            std::move(ctx), p, flags);
    }

    virtual void sh_release(CTXPtr ctx, const boost::filesystem::path &p)
    {
        sync(&IStorageHelper::ash_release, std::move(ctx), p);
    }

    virtual bool needsDataConsistencyCheck() { return false; }

    static int flagsToMask(FlagsSet flags)
    {
        int value = 0;

        for (auto flag : flags) {
            auto searchResult = s_flagTranslation.find(flag);
            assert(searchResult != s_flagTranslation.end());
            value |= searchResult->second;
        }
        return value;
    }

    static FlagsSet maskToFlags(int mask)
    {
        FlagsSet flags;

        // get permission flags
        auto searchResult = s_maskTranslation.at(mask & O_ACCMODE);
        flags.insert(searchResult->second);

        // get other flags
        for (auto entry : s_maskTranslation) {
            auto entry_mask = entry.first;
            auto entry_flag = entry.second;

            if (entry_flag != Flag::RDONLY && entry_flag != Flag::WRONLY &&
                entry_flag != Flag::RDWR && (entry_mask & mask) == entry_mask) {
                searchResult = s_maskTranslation.at(entry_mask);
                flags.insert(searchResult->second);
            }
        }

        return flags;
    }

protected:
    static error_t makePosixError(int posixCode)<commit_msg>Squashed 'helpers/' changes from 967ccb4..902c889<commit_after>/**
 * @file IStorageHelper.h
 * @author <NAME>
 * @copyright (C) 2013 ACK CYFRONET AGH
 * @copyright This software is released under the MIT license cited in
 * 'LICENSE.txt'
 */

#ifndef HELPERS_I_STORAGE_HELPER_H
#define HELPERS_I_STORAGE_HELPER_H

#include <fuse.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <asio/buffer.hpp>
#include <boost/any.hpp>
#include <boost/filesystem/path.hpp>
#include <tbb/concurrent_hash_map.h>

#include <chrono>
#include <future>
#include <memory>
#include <string>
#include <system_error>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace one {
namespace helpers {

using error_t = std::error_code;

namespace {
constexpr std::chrono::seconds ASYNC_OPS_TIMEOUT{2};
const error_t SUCCESS_CODE;
}

enum class Flag {
    NONBLOCK,
    APPEND,
    ASYNC,
    FSYNC,
    NOFOLLOW,
    CREAT,
    TRUNC,
    EXCL,
    RDONLY,
    WRONLY,
    RDWR,
    IFREG,
    IFCHR,
    IFBLK,
    IFIFO,
    IFSOCK
};

struct FlagHash {
    template <typename T> std::size_t operator()(T t) const
    {
        return static_cast<std::size_t>(t);
    }
};

using FlagsSet = std::unordered_set<Flag, FlagHash>;

class IStorageHelperCTX {
public:
    /**
     * Creates a context with given parameters.
     * @param params The parameters of file context.
     */
    IStorageHelperCTX(std::unordered_map<std::string, std::string> params)
        : m_params{std::move(params)}
    {
    }

    virtual ~IStorageHelperCTX() = default;

    /**
     * Sets user context parameters.
     * @param args Map with parameters required to set user context.
     */
    virtual void setUserCTX(std::unordered_map<std::string, std::string> args)
    {
    }

    /**
     * Returns user context parameters.
     * @return map used to create user context.
     */
    virtual std::unordered_map<std::string, std::string> getUserCTX()
    {
        throw std::system_error{
            std::make_error_code(std::errc::function_not_supported)};
    }

    /**
     * Returns parameters set in constructor.
     */
    const std::unordered_map<std::string, std::string> &parameters() const
    {
        return m_params;
    }

protected:
    static error_t makePosixError(int posixCode)
    {
        posixCode = posixCode > 0 ? posixCode : -posixCode;
        return error_t(posixCode, std::system_category());
    }

private:
    std::unordered_map<std::string, std::string> m_params;
};

using CTXPtr = std::shared_ptr<IStorageHelperCTX>;

template <class... T>
using GeneralCallback = std::function<void(T..., error_t)>;
using VoidCallback = GeneralCallback<>;

template <class T> using future_t = std::future<T>;
template <class T> using promise_t = std::promise<T>;

/**
 * The IStorageHelper interface.
 * Base class of all storage helpers. Unifies their interface.
 * All callback have their equivalent in FUSE API and should be used in that
 * matter.
 */
class IStorageHelper {
public:
    virtual ~IStorageHelper() = default;

    virtual CTXPtr createCTX(
        std::unordered_map<std::string, std::string> params)
    {
        return std::make_shared<IStorageHelperCTX>(std::move(params));
    }

    virtual void ash_getattr(CTXPtr ctx, const boost::filesystem::path &p,
        GeneralCallback<struct stat> callback)
    {
        callback({}, std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_access(CTXPtr ctx, const boost::filesystem::path &p,
        int mask, VoidCallback callback)
    {
        callback({});
    }

    virtual void ash_readlink(CTXPtr ctx, const boost::filesystem::path &p,
        GeneralCallback<std::string> callback)
    {
        callback({}, std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_readdir(CTXPtr ctx, const boost::filesystem::path &p,
        off_t offset, size_t count,
        GeneralCallback<const std::vector<std::string> &> callback)
    {
        callback({}, std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_mknod(CTXPtr ctx, const boost::filesystem::path &p,
        mode_t mode, FlagsSet flags, dev_t rdev, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_mkdir(CTXPtr ctx, const boost::filesystem::path &p,
        mode_t mode, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_unlink(
        CTXPtr ctx, const boost::filesystem::path &p, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_rmdir(
        CTXPtr ctx, const boost::filesystem::path &p, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_symlink(CTXPtr ctx, const boost::filesystem::path &from,
        const boost::filesystem::path &to, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_rename(CTXPtr ctx, const boost::filesystem::path &from,
        const boost::filesystem::path &to, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_link(CTXPtr ctx, const boost::filesystem::path &from,
        const boost::filesystem::path &to, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_chmod(CTXPtr ctx, const boost::filesystem::path &p,
        mode_t mode, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_chown(CTXPtr ctx, const boost::filesystem::path &p,
        uid_t uid, gid_t gid, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_truncate(CTXPtr ctx, const boost::filesystem::path &p,
        off_t size, VoidCallback callback)
    {
        callback(std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_open(CTXPtr ctx, const boost::filesystem::path &p,
        FlagsSet flags, GeneralCallback<int> callback)
    {
        ash_open(std::move(ctx), p, flagsToMask(std::move(flags)),
            std::move(callback));
    }

    virtual void ash_open(CTXPtr ctx, const boost::filesystem::path &p,
        int flags, GeneralCallback<int> callback)
    {
        callback({}, SUCCESS_CODE);
    }

    virtual void ash_read(CTXPtr ctx, const boost::filesystem::path &p,
        asio::mutable_buffer buf, off_t offset,
        GeneralCallback<asio::mutable_buffer> callback)
    {
        callback({}, std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_write(CTXPtr ctx, const boost::filesystem::path &p,
        asio::const_buffer buf, off_t offset,
        GeneralCallback<std::size_t> callback)
    {
        callback({}, std::make_error_code(std::errc::function_not_supported));
    }

    virtual void ash_release(
        CTXPtr ctx, const boost::filesystem::path &p, VoidCallback callback)
    {
        callback(SUCCESS_CODE);
    }

    virtual void ash_flush(
        CTXPtr ctx, const boost::filesystem::path &p, VoidCallback callback)
    {
        callback({});
    }

    virtual void ash_fsync(CTXPtr ctx, const boost::filesystem::path &p,
        bool isDataSync, VoidCallback callback)
    {
        callback({});
    }

    virtual void sh_fsync(
        CTXPtr ctx, const boost::filesystem::path &p, bool isDataSync)
    {
        sync(&IStorageHelper::ash_fsync, std::move(ctx), p, isDataSync);
    }

    virtual void sh_flush(CTXPtr ctx, const boost::filesystem::path &p)
    {
        sync(&IStorageHelper::ash_flush, std::move(ctx), p);
    }

    virtual asio::mutable_buffer sh_read(CTXPtr ctx,
        const boost::filesystem::path &p, asio::mutable_buffer buf,
        off_t offset)
    {
        return sync<asio::mutable_buffer>(
            &IStorageHelper::ash_read, std::move(ctx), p, buf, offset);
    }

    virtual std::size_t sh_write(CTXPtr ctx, const boost::filesystem::path &p,
        asio::const_buffer buf, off_t offset)
    {
        return sync<std::size_t>(
            &IStorageHelper::ash_write, std::move(ctx), p, buf, offset);
    }

    virtual int sh_open(CTXPtr ctx, const boost::filesystem::path &p, int flags)
    {
        return sync<int>(
            static_cast<void (IStorageHelper::*)(CTXPtr,
                const boost::filesystem::path &, int, GeneralCallback<int>)>(
                &IStorageHelper::ash_open),
            std::move(ctx), p, flags);
    }

    virtual void sh_release(CTXPtr ctx, const boost::filesystem::path &p)
    {
        sync(&IStorageHelper::ash_release, std::move(ctx), p);
    }

    virtual bool needsDataConsistencyCheck() { return false; }

    static int flagsToMask(FlagsSet flags)
    {
        int value = 0;

        for (auto flag : flags) {
            auto searchResult = s_flagTranslation.find(flag);
            assert(searchResult != s_flagTranslation.end());
            value |= searchResult->second;
        }
        return value;
    }

    static FlagsSet maskToFlags(int mask)
    {
        FlagsSet flags;

        // get permission flags
        flags.insert(s_maskTranslation.at(mask & O_ACCMODE));

        // get other flags
        for (auto entry : s_maskTranslation) {
            auto entry_mask = entry.first;
            auto entry_flag = entry.second;

            if (entry_flag != Flag::RDONLY && entry_flag != Flag::WRONLY &&
                entry_flag != Flag::RDWR && (entry_mask & mask) == entry_mask)
                flags.insert(s_maskTranslation.at(entry_mask));
        }

        return flags;
    }

protected:
    static error_t makePosixError(int posixCode)
{'fraction_non_alphanumeric': 0.11954402279886006, 'fraction_numerical': 0.00119994000299985, 'mean_word_length': 3.201218231463978, 'pattern_counts': {'":': 0, '<': 97, '<?xml version=': 0, '>': 103, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4485061', 'n_tokens_mistral': 6337, 'n_tokens_neox': 6164, 'n_words': 1384}