/* * Copyright (C) 2022-present ScyllaDB */ /* * SPDX-License-Identifier: AGPL-3.0-or-later */ #include #include #include #include #include #include "utils/s3/creds.hh" using namespace seastar; class memory_data_sink_buffers; namespace s3 { using s3_clock = std::chrono::steady_clock; struct range { uint64_t off; size_t len; }; struct tag { std::string key; std::string value; auto operator<=>(const tag&) const = default; }; using tag_set = std::vector; struct stats { uint64_t size; std::time_t last_modified; }; future<> ignore_reply(const http::reply& rep, input_stream&& in_); class client : public enable_shared_from_this { class upload_sink_base; class upload_sink; class upload_jumbo_sink; class readable_file; std::string _host; endpoint_config_ptr _cfg; struct io_stats { uint64_t ops = 0; uint64_t bytes = 0; std::chrono::duration duration = std::chrono::duration(0); void update(uint64_t len, std::chrono::duration lat) { ops++; bytes += len; duration += lat; } }; struct group_client { http::experimental::client http; io_stats read_stats; io_stats write_stats; seastar::metrics::metric_groups metrics; group_client(std::unique_ptr f, unsigned max_conn); void register_metrics(std::string class_name, std::string host); }; std::unordered_map _https; using global_factory = std::function(std::string)>; global_factory _gf; semaphore& _memory; struct private_tag {}; future> claim_memory(size_t mem); void authorize(http::request&); group_client& find_or_create_client(); future<> make_request(http::request req, http::experimental::client::reply_handler handle = ignore_reply, http::reply::status_type expected = http::reply::status_type::ok); using reply_handler_ext = noncopyable_function(group_client&, const http::reply&, input_stream&& body)>; future<> make_request(http::request req, reply_handler_ext handle, http::reply::status_type expected = http::reply::status_type::ok); future<> get_object_header(sstring object_name, http::experimental::client::reply_handler handler); public: explicit client(std::string host, endpoint_config_ptr cfg, semaphore& mem, global_factory gf, private_tag); static shared_ptr make(std::string endpoint, endpoint_config_ptr cfg, semaphore& memory, global_factory gf = {}); future get_object_size(sstring object_name); future get_object_stats(sstring object_name); future get_object_tagging(sstring object_name); future<> put_object_tagging(sstring object_name, tag_set tagging); future<> delete_object_tagging(sstring object_name); future> get_object_contiguous(sstring object_name, std::optional range = {}); future<> put_object(sstring object_name, temporary_buffer buf); future<> put_object(sstring object_name, ::memory_data_sink_buffers bufs); future<> delete_object(sstring object_name); file make_readable_file(sstring object_name); data_sink make_upload_sink(sstring object_name); data_sink make_upload_jumbo_sink(sstring object_name, std::optional max_parts_per_piece = {}); void update_config(endpoint_config_ptr); struct handle { std::string _host; global_factory _gf; public: handle(const client& cln) : _host(cln._host) , _gf(cln._gf) {} shared_ptr to_client() && { return _gf(std::move(_host)); } }; future<> close(); }; } // s3 namespace