Draft: Resolve "Optimization: small files into metadata server"

Closes #373 (closed)

Merge request reports

Loading
+40 −3
Changes for include/client/rpc/forward_metadata.hpp: 40 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@
#include <string>
#include <memory>
#include <vector>
#include <cstdint>
/* Forward declaration */
namespace gkfs {
namespace filemap {
@@ -63,7 +64,13 @@ int
forward_create(const std::string& path, mode_t mode, const int copy);

int
forward_stat(const std::string& path, std::string& attr, const int copy);
forward_create_write_inline(const std::string& path, mode_t mode,
                            const std::string& data, uint64_t count,
                            const int copy);

int
forward_stat(const std::string& path, std::string& attr,
             std::string& inline_data, int copy, bool include_inline = false);

#ifdef HAS_RENAME
int
@@ -86,7 +93,7 @@ forward_update_metadentry(const std::string& path,
std::pair<int, off64_t>
forward_update_metadentry_size(const std::string& path, size_t size,
                               off64_t offset, bool append_flag,
                               const int num_copies);
                               bool clear_inline_flag, const int num_copies);

std::pair<int, off64_t>
forward_get_metadentry_size(const std::string& path, const int copy);
@@ -96,7 +103,9 @@ forward_get_dirents(const std::string& path);

std::pair<int, std::unique_ptr<std::vector<
                       std::tuple<const std::string, bool, size_t, time_t>>>>
forward_get_dirents_single(const std::string& path, int server);
forward_get_dirents_single(const std::string& path, int server,
                           const std::string& start_key = "",
                           bool get_all = true);

#ifdef HAS_SYMLINKS

@@ -105,6 +114,34 @@ forward_mk_symlink(const std::string& path, const std::string& target_path);

#endif

/**
 * @brief Send an RPC request to write a small amount of data directly
 * to the metadata server (inline).
 *
 * @param path The file path.
 * @param buf Pointer to the data buffer.
 * @param offset The file offset.
 * @param append_flag Whether to append to the file.
 * @return std::pair<int, off64_t> Error code and offset written.
 */
std::pair<int, off64_t>
forward_write_inline(const std::string& path, const void* buf, off64_t offset,
                     size_t write_size, bool append_flag);

/**
 * @brief Send an RPC request to read a small amount of data directly
 * from the metadata server (inline).
 *
 * @param path The file path.
 * @param buf Pointer to the destination buffer.
 * @param offset The file offset.
 * @param read_size The number of bytes to read.
 * @return std::pair<int, ssize_t> Error code and bytes read.
 */
std::pair<int, ssize_t>
forward_read_inline(const std::string& path, void* buf, off64_t offset,
                    size_t read_size);

} // namespace rpc
} // namespace gkfs

+376 −20
Changes for include/client/rpc/rpc_types.hpp: 376 added lines, 20 removed lines.
Original line number Diff line number Diff line
@@ -369,6 +369,147 @@ struct create {
    };
};

//==============================================================================
// definitions for create_write_inline
struct create_write_inline {

    // forward declarations of public input/output types for this RPC
    class input;

    class output;

    // traits used so that the engine knows what to do with the RPC
    using self_type = create_write_inline;
    using handle_type = hermes::rpc_handle<self_type>;
    using input_type = input;
    using output_type = output;
    using mercury_input_type = rpc_create_write_inline_in_t;
    using mercury_output_type = rpc_create_write_inline_out_t;

    // RPC public identifier
    constexpr static const uint64_t public_id = 7; // Custom ID

    // RPC internal Mercury identifier
    constexpr static const hg_id_t mercury_id = 0;

    // RPC name
    constexpr static const auto name = gkfs::rpc::tag::create_write_inline;

    // requires response?
    constexpr static const auto requires_response = true;

    // Mercury callback to serialize input arguments
    constexpr static const auto mercury_in_proc_cb =
            HG_GEN_PROC_NAME(rpc_create_write_inline_in_t);

    // Mercury callback to serialize output arguments
    constexpr static const auto mercury_out_proc_cb =
            HG_GEN_PROC_NAME(rpc_create_write_inline_out_t);

    class input {

        template <typename ExecutionContext>
        friend hg_return_t
        hermes::detail::post_to_mercury(ExecutionContext*);

    public:
        input(const std::string& path, uint32_t mode, const std::string& data,
              uint64_t count)
            : m_path(path), m_mode(mode), m_data(data), m_count(count) {}

        input(input&& rhs) = default;

        input(const input& other) = default;

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

        input&
        operator=(const input& other) = default;

        std::string
        path() const {
            return m_path;
        }

        uint32_t
        mode() const {
            return m_mode;
        }

        std::string
        data() const {
            return m_data;
        }

        uint64_t
        count() const {
            return m_count;
        }

        explicit input(const rpc_create_write_inline_in_t& other)
            : m_path(other.path), m_mode(other.mode),
              m_data(static_cast<char*>(other.data.data), other.data.size),
              m_count(other.count) {}

        explicit
        operator rpc_create_write_inline_in_t() {
            return {m_path.c_str(),
                    m_mode,
                    {(void*) m_data.c_str(), m_data.size()},
                    m_count};
        }

    private:
        std::string m_path;
        uint32_t m_mode;
        std::string m_data;
        uint64_t m_count;
    };

    class output {

        template <typename ExecutionContext>
        friend hg_return_t
        hermes::detail::post_to_mercury(ExecutionContext*);

    public:
        output() : m_err(), m_io_size() {}

        output(int32_t err, uint64_t io_size)
            : m_err(err), m_io_size(io_size) {}

        output(output&& rhs) = default;

        output(const output& other) = default;

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

        output&
        operator=(const output& other) = default;

        explicit output(const rpc_create_write_inline_out_t& out) {
            m_err = out.err;
            m_io_size = out.io_size;
        }

        int32_t
        err() const {
            return m_err;
        }

        uint64_t
        io_size() const {
            return m_io_size;
        }

    private:
        int32_t m_err;
        uint64_t m_io_size;
    };
};

//==============================================================================
// definitions for stat
struct stat {
@@ -415,7 +556,8 @@ struct stat {
        hermes::detail::post_to_mercury(ExecutionContext*);

    public:
        input(const std::string& path) : m_path(path) {}
        input(const std::string& path, bool include_inline = false)
            : m_path(path), m_include_inline(include_inline) {}

        input(input&& rhs) = default;

@@ -432,15 +574,22 @@ struct stat {
            return m_path;
        }

        explicit input(const rpc_path_only_in_t& other) : m_path(other.path) {}
        bool
        include_inline() const {
            return m_include_inline;
        }

        explicit input(const rpc_path_only_in_t& other)
            : m_path(other.path), m_include_inline(other.include_inline) {}

        explicit
        operator rpc_path_only_in_t() {
            return {m_path.c_str()};
            return {m_path.c_str(), static_cast<hg_bool_t>(m_include_inline)};
        }

    private:
        std::string m_path;
        bool m_include_inline;
    };

    class output {
@@ -452,8 +601,9 @@ struct stat {
    public:
        output() : m_err(), m_db_val() {}

        output(int32_t err, const std::string& db_val)
            : m_err(err), m_db_val(db_val) {}
        output(int32_t err, const std::string& db_val,
               const std::string& inline_data)
            : m_err(err), m_db_val(db_val), m_inline_data(inline_data) {}

        output(output&& rhs) = default;

@@ -471,6 +621,11 @@ struct stat {
            if(out.db_val != nullptr) {
                m_db_val = out.db_val;
            }

            if(out.inline_data.data != nullptr && out.inline_data.size > 0) {
                m_inline_data.assign((char*) out.inline_data.data,
                                     out.inline_data.size);
            }
        }

        int32_t
@@ -483,9 +638,15 @@ struct stat {
            return m_db_val;
        }

        std::string
        inline_data() const {
            return m_inline_data;
        }

    private:
        int32_t m_err;
        std::string m_db_val;
        std::string m_inline_data;
    };
};

@@ -1130,8 +1291,9 @@ struct update_metadentry_size {

    public:
        input(const std::string& path, uint64_t size, int64_t offset,
              bool append)
            : m_path(path), m_size(size), m_offset(offset), m_append(append) {}
              bool append, bool clear_inline = false)
            : m_path(path), m_size(size), m_offset(offset), m_append(append),
              m_clear_inline(clear_inline) {}

        input(input&& rhs) = default;

@@ -1163,9 +1325,14 @@ struct update_metadentry_size {
            return m_append;
        }

        bool
        clear_inline() const {
            return m_clear_inline;
        }

        explicit input(const rpc_update_metadentry_size_in_t& other)
            : m_path(other.path), m_size(other.size), m_offset(other.offset),
              m_append(other.append) {}
              m_append(other.append), m_clear_inline(other.clear_inline) {}

        explicit
        operator rpc_update_metadentry_size_in_t() {
@@ -1177,6 +1344,7 @@ struct update_metadentry_size {
        uint64_t m_size;
        int64_t m_offset;
        bool m_append;
        bool m_clear_inline;
    };

    class output {
@@ -2112,8 +2280,9 @@ struct get_dirents {
        hermes::detail::post_to_mercury(ExecutionContext*);

    public:
        input(const std::string& path, const hermes::exposed_memory& buffers)
            : m_path(path), m_buffers(buffers) {}
        input(const std::string& path, const hermes::exposed_memory& buffers,
              const std::string& start_key = "")
            : m_path(path), m_buffers(buffers), m_start_key(start_key) {}

        input(input&& rhs) = default;

@@ -2135,17 +2304,24 @@ struct get_dirents {
            return m_buffers;
        }

        std::string
        start_key() const {
            return m_start_key;
        }

        explicit input(const rpc_get_dirents_in_t& other)
            : m_path(other.path), m_buffers(other.bulk_handle) {}
            : m_path(other.path), m_buffers(other.bulk_handle),
              m_start_key(other.start_key) {}

        explicit
        operator rpc_get_dirents_in_t() {
            return {m_path.c_str(), hg_bulk_t(m_buffers)};
            return {m_path.c_str(), m_start_key.c_str(), hg_bulk_t(m_buffers)};
        }

    private:
        std::string m_path;
        hermes::exposed_memory m_buffers;
        std::string m_start_key;
    };

    class output {
@@ -2237,8 +2413,9 @@ struct get_dirents_extended {
        hermes::detail::post_to_mercury(ExecutionContext*);

    public:
        input(const std::string& path, const hermes::exposed_memory& buffers)
            : m_path(path), m_buffers(buffers) {}
        input(const std::string& path, const hermes::exposed_memory& buffers,
              const std::string& start_key = "")
            : m_path(path), m_buffers(buffers), m_start_key(start_key) {}

        input(input&& rhs) = default;

@@ -2261,17 +2438,24 @@ struct get_dirents_extended {
            return m_buffers;
        }

        std::string
        start_key() const {
            return m_start_key;
        }

        explicit input(const rpc_get_dirents_in_t& other)
            : m_path(other.path), m_buffers(other.bulk_handle) {}
            : m_path(other.path), m_buffers(other.bulk_handle),
              m_start_key(other.start_key) {}

        explicit
        operator rpc_get_dirents_in_t() {
            return {m_path.c_str(), hg_bulk_t(m_buffers)};
            return {m_path.c_str(), m_start_key.c_str(), hg_bulk_t(m_buffers)};
        }

    private:
        std::string m_path;
        hermes::exposed_memory m_buffers;
        std::string m_start_key;
    };

    class output {
@@ -2452,6 +2636,168 @@ struct chunk_stat {
    };
};

struct write_data_inline {
    class input;
    class output;

    using self_type = write_data_inline;
    using handle_type = hermes::rpc_handle<self_type>;
    using input_type = input;
    using output_type = output;
    using mercury_input_type = rpc_write_inline_in_t;
    using mercury_output_type = rpc_write_inline_out_t;

    constexpr static const uint64_t public_id = 60; // Unique ID
    constexpr static const hg_id_t mercury_id = 0;
    constexpr static const auto name = gkfs::rpc::tag::write_data_inline;
    constexpr static const auto requires_response = true;
    constexpr static const auto mercury_in_proc_cb =
            HG_GEN_PROC_NAME(rpc_write_inline_in_t);
    constexpr static const auto mercury_out_proc_cb =
            HG_GEN_PROC_NAME(rpc_write_inline_out_t);

    class input {
        template <typename ExecutionContext>
        friend hg_return_t
        hermes::detail::post_to_mercury(ExecutionContext*);

    public:
        input(const std::string& path, uint64_t offset, const std::string& data,
              uint64_t count, bool append)
            : m_path(path), m_offset(offset), m_data(data), m_count(count),
              m_append(append) {}

        explicit input(const rpc_write_inline_in_t& other)
            : m_path(other.path), m_offset(other.offset),
              m_data(static_cast<char*>(other.data.data), other.data.size),
              m_count(other.count), m_append(other.append) {}

        explicit
        operator rpc_write_inline_in_t() {
            return {m_path.c_str(),
                    m_offset,
                    {(void*) m_data.c_str(), m_data.size()},
                    m_count,
                    static_cast<hg_bool_t>(m_append)};
        }

    private:
        std::string m_path;
        uint64_t m_offset;
        std::string m_data;
        uint64_t m_count;
        bool m_append;
    };

    class output {
        template <typename ExecutionContext>
        friend hg_return_t
        hermes::detail::post_to_mercury(ExecutionContext*);

    public:
        output() : m_err(0), m_ret_offset(0), m_io_size(0) {}
        explicit output(const rpc_write_inline_out_t& out)
            : m_err(out.err), m_ret_offset(out.ret_offset),
              m_io_size(out.io_size) {}
        int32_t
        err() const {
            return m_err;
        }
        int64_t
        ret_offset() const {
            return m_ret_offset;
        }
        size_t
        io_size() const {
            return m_io_size;
        }

    private:
        int32_t m_err;
        int64_t m_ret_offset;
        size_t m_io_size;
    };
};

//==============================================================================
// definitions for read_data_inline
struct read_data_inline {
    class input;
    class output;

    using self_type = read_data_inline;
    using handle_type = hermes::rpc_handle<self_type>;
    using input_type = input;
    using output_type = output;
    using mercury_input_type = rpc_read_inline_in_t;
    using mercury_output_type = rpc_read_inline_out_t;

    constexpr static const uint64_t public_id = 61; // Unique ID
    constexpr static const hg_id_t mercury_id = 0;
    constexpr static const auto name = gkfs::rpc::tag::read_data_inline;
    constexpr static const auto requires_response = true;
    constexpr static const auto mercury_in_proc_cb =
            HG_GEN_PROC_NAME(rpc_read_inline_in_t);
    constexpr static const auto mercury_out_proc_cb =
            HG_GEN_PROC_NAME(rpc_read_inline_out_t);

    class input {
        template <typename ExecutionContext>
        friend hg_return_t
        hermes::detail::post_to_mercury(ExecutionContext*);

    public:
        input(const std::string& path, uint64_t offset, uint64_t count)
            : m_path(path), m_offset(offset), m_count(count) {}

        explicit input(const rpc_read_inline_in_t& other)
            : m_path(other.path), m_offset(other.offset), m_count(other.count) {
        }

        explicit
        operator rpc_read_inline_in_t() {
            return {m_path.c_str(), m_offset, m_count};
        }

    private:
        std::string m_path;
        uint64_t m_offset;
        uint64_t m_count;
    };

    class output {
        template <typename ExecutionContext>
        friend hg_return_t
        hermes::detail::post_to_mercury(ExecutionContext*);

    public:
        output() : m_err(0), m_count(0) {}
        explicit output(const rpc_read_inline_out_t& out)
            : m_err(out.err),
              m_data(out.data.data
                             ? std::string((char*) out.data.data, out.data.size)
                             : ""),
              m_count(out.count) {}

        int32_t
        err() const {
            return m_err;
        }
        const std::string&
        data() const {
            return m_data;
        }
        uint64_t
        count() const {
            return m_count;
        }

    private:
        int32_t m_err;
        std::string m_data;
        uint64_t m_count;
    };
};
//==============================================================================
// definitions for write_data
struct write_data_proxy {
@@ -3762,15 +4108,16 @@ struct get_dirents_extended_proxy {
            HG_GEN_PROC_NAME(rpc_get_dirents_out_t);

    class input {

        template <typename ExecutionContext>
        friend hg_return_t
        hermes::detail::post_to_mercury(ExecutionContext*);

    public:
        input(const std::string& path, int32_t server,
              const std::string& start_key,
              const hermes::exposed_memory& buffers)
            : m_path(path), m_server(server), m_buffers(buffers) {}
            : m_path(path), m_server(server), m_start_key(start_key),
              m_buffers(buffers) {}

        input(input&& rhs) = default;

@@ -3792,6 +4139,11 @@ struct get_dirents_extended_proxy {
            return m_server;
        }

        std::string
        start_key() const {
            return m_start_key;
        }

        hermes::exposed_memory
        buffers() const {
            return m_buffers;
@@ -3799,16 +4151,18 @@ struct get_dirents_extended_proxy {

        explicit input(const rpc_proxy_get_dirents_in_t& other)
            : m_path(other.path), m_server(other.server),
              m_buffers(other.bulk_handle) {}
              m_start_key(other.start_key), m_buffers(other.bulk_handle) {}

        explicit
        operator rpc_proxy_get_dirents_in_t() {
            return {m_path.c_str(), m_server, hg_bulk_t(m_buffers)};
            return {m_path.c_str(), m_server, m_start_key.c_str(),
                    hg_bulk_t(m_buffers)};
        }

    private:
        std::string m_path;
        int32_t m_server;
        std::string m_start_key;
        hermes::exposed_memory m_buffers;
    };

@@ -4180,6 +4534,8 @@ struct expand_finalize {
};

} // namespace malleable::rpc


} // namespace gkfs


+8 −0
Changes for include/client/cache.hpp: 8 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -167,6 +167,14 @@ public:
    std::pair<size_t, size_t>
    record(std::string path, size_t size);

    /**
     * @brief Get the cached size for a given path
     * @param path
     * @return [size_update counter, current cached size]
     */
    std::pair<size_t, size_t>
    get(const std::string& path);

    /**
     * @brief reset entry from the cache
     * @param path
+25 −0
Changes for include/client/open_file_map.hpp: 25 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -61,6 +61,8 @@ enum class OpenFile_flags {
    wronly,
    rdwr,
    cloexec,
    created,          // indicates if the file was created during open
    creation_pending, // indicates if the file creation is delayed
    flag_count // this is purely used as a size variable of this enum class
};

@@ -75,6 +77,7 @@ protected:
    unsigned long pos_;
    std::mutex pos_mutex_;
    std::mutex flag_mutex_;
    mode_t mode_;

public:
    // multiple threads may want to update the file position if fd has been
@@ -106,6 +109,28 @@ public:

    FileType
    type() const;

    mode_t
    mode() const;

    void
    mode(mode_t mode_);

    std::string
    inline_data() const;

    void
    inline_data(const std::string& data);

    size_t
    inline_data_size() const;

    void
    inline_data_size(size_t size);

private:
    std::string inline_data_;
    size_t inline_data_size_{0};
};


+3 −2
Changes for include/client/preload_util.hpp: 3 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -82,7 +82,8 @@ to_underlying(E e) {
}

std::optional<gkfs::metadata::Metadata>
get_metadata(const std::string& path, bool follow_links = false);
get_metadata(const std::string& path, bool follow_links = false,
             bool include_inline = false);

int
metadata_to_stat(const std::string& path, const gkfs::metadata::Metadata& md,
@@ -98,7 +99,7 @@ metadata_to_stat(const std::string& path, const gkfs::metadata::Metadata& md,
 */
std::pair<int, off64_t>
update_file_size(const std::string& path, size_t count, off64_t offset,
                 bool is_append);
                 bool is_append, bool clear_inline_flag = false);

void
load_hosts();
Loading
Loading