From: Radoslaw Zarzynski Date: Tue, 11 Oct 2016 19:46:20 +0000 (+0200) Subject: rgw: ONLY move rgw_client_io_decoimpl.h to rgw_client_io_filters.h. X-Git-Tag: v11.1.0~454^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5da12f60d683b8ea41b6c1c60c3f043915d1dbb3;p=ceph.git rgw: ONLY move rgw_client_io_decoimpl.h to rgw_client_io_filters.h. Signed-off-by: Radoslaw Zarzynski --- diff --git a/src/rgw/rgw_civetweb_frontend.cc b/src/rgw/rgw_civetweb_frontend.cc index e0adeb8040f6..27f1518a591e 100644 --- a/src/rgw/rgw_civetweb_frontend.cc +++ b/src/rgw/rgw_civetweb_frontend.cc @@ -7,7 +7,7 @@ #include #include "rgw_frontend.h" -#include "rgw_client_io_decoimpl.h" +#include "rgw_client_io_filters.h" #define dout_subsys ceph_subsys_rgw diff --git a/src/rgw/rgw_client_io.h b/src/rgw/rgw_client_io.h index 82460d0d1021..6bc6c939970e 100644 --- a/src/rgw/rgw_client_io.h +++ b/src/rgw/rgw_client_io.h @@ -184,7 +184,7 @@ public: * mixing interfaces with implementation. Additionally, those classes derive * from RGWRestfulIO defined here. I believe that including in the middle of * file is still better than polluting it directly. */ -#include "rgw_client_io_decoimpl.h" +#include "rgw_client_io_filters.h" /* RGWRestfulIO: high level interface to interact with RESTful clients. What diff --git a/src/rgw/rgw_client_io_decoimpl.h b/src/rgw/rgw_client_io_decoimpl.h deleted file mode 100644 index f573af8eccaf..000000000000 --- a/src/rgw/rgw_client_io_decoimpl.h +++ /dev/null @@ -1,404 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#ifndef CEPH_RGW_CLIENT_IO_DECOIMPL_H -#define CEPH_RGW_CLIENT_IO_DECOIMPL_H - -#include - -#include - -#include "rgw_common.h" -#include "rgw_client_io.h" - -namespace rgw { -namespace io { - -template -class AccountingFilter : public DecoratedRestfulClient, - public Accounter { - bool enabled; - uint64_t total_sent; - uint64_t total_received; - -public: - template - AccountingFilter(U&& decoratee) - : DecoratedRestfulClient(std::forward(decoratee)), - enabled(false), - total_sent(0), - total_received(0) { - } - - size_t send_status(const int status, - const char* const status_name) override { - const auto sent = DecoratedRestfulClient::send_status(status, - status_name); - if (enabled) { - total_sent += sent; - } - return sent; - } - - size_t send_100_continue() override { - const auto sent = DecoratedRestfulClient::send_100_continue(); - if (enabled) { - total_sent += sent; - } - return sent; - } - - size_t send_header(const boost::string_ref& name, - const boost::string_ref& value) override { - const auto sent = DecoratedRestfulClient::send_header(name, value); - if (enabled) { - total_sent += sent; - } - return sent; - } - - size_t send_content_length(const uint64_t len) override { - const auto sent = DecoratedRestfulClient::send_content_length(len); - if (enabled) { - total_sent += sent; - } - return sent; - } - - size_t send_chunked_transfer_encoding() override { - const auto sent = DecoratedRestfulClient::send_chunked_transfer_encoding(); - if (enabled) { - total_sent += sent; - } - return sent; - } - - size_t complete_header() override { - const auto sent = DecoratedRestfulClient::complete_header(); - if (enabled) { - total_sent += sent; - } - return sent; - } - - size_t recv_body(char* buf, size_t max) override { - const auto received = DecoratedRestfulClient::recv_body(buf, max); - if (enabled) { - total_received += received; - } - return received; - } - - size_t send_body(const char* const buf, - const size_t len) override { - const auto sent = DecoratedRestfulClient::send_body(buf, len); - if (enabled) { - total_sent += sent; - } - return sent; - } - - uint64_t get_bytes_sent() const override { - return total_sent; - } - - uint64_t get_bytes_received() const override { - return total_received; - } - - void set_account(bool enabled) override { - this->enabled = enabled; - } -}; - - -/* Filter for in-memory buffering incoming data and calculating the content - * length header if it isn't present. */ -template -class BufferingFilter : public DecoratedRestfulClient { - template friend class DecoratedRestfulClient; -protected: - ceph::bufferlist data; - - bool has_content_length; - bool buffer_data; - -public: - template - BufferingFilter(U&& decoratee) - : DecoratedRestfulClient(std::forward(decoratee)), - has_content_length(false), - buffer_data(false) { - } - - size_t send_content_length(const uint64_t len) override; - size_t send_chunked_transfer_encoding() override; - size_t complete_header() override; - size_t send_body(const char* buf, size_t len) override; - size_t complete_request() override; -}; - -template -size_t BufferingFilter::send_body(const char* const buf, - const size_t len) -{ - if (buffer_data) { - data.append(buf, len); - return 0; - } - - return DecoratedRestfulClient::send_body(buf, len); -} - -template -size_t BufferingFilter::send_content_length(const uint64_t len) -{ - has_content_length = true; - return DecoratedRestfulClient::send_content_length(len); -} - -template -size_t BufferingFilter::send_chunked_transfer_encoding() -{ - has_content_length = true; - return DecoratedRestfulClient::send_chunked_transfer_encoding(); -} - -template -size_t BufferingFilter::complete_header() -{ - if (! has_content_length) { - /* We will dump everything in complete_request(). */ - buffer_data = true; - return 0; - } - - return DecoratedRestfulClient::complete_header(); -} - -template -size_t BufferingFilter::complete_request() -{ - size_t sent = 0; - - if (! has_content_length) { - sent += DecoratedRestfulClient::send_content_length(data.length()); - sent += DecoratedRestfulClient::complete_header(); - } - - if (buffer_data) { - /* We are sending each buffer separately to avoid extra memory shuffling - * that would occur on data.c_str() to provide a continuous memory area. */ - for (const auto& ptr : data.buffers()) { - sent += DecoratedRestfulClient::send_body(ptr.c_str(), - ptr.length()); - } - data.clear(); - buffer_data = false; - } - - return sent + DecoratedRestfulClient::complete_request(); -} - -template static inline -BufferingFilter add_buffering(T&& t) { - return BufferingFilter(std::forward(t)); -} - - -template -class ChunkingFilter : public DecoratedRestfulClient { - template friend class DecoratedRestfulClient; -protected: - bool has_content_length; - bool chunking_enabled; - -public: - template - ChunkingFilter(U&& decoratee) - : DecoratedRestfulClient(std::forward(decoratee)), - has_content_length(false), - chunking_enabled(false) { - } - - size_t send_content_length(const uint64_t len) override { - has_content_length = true; - return DecoratedRestfulClient::send_content_length(len); - } - - size_t send_chunked_transfer_encoding() override { - has_content_length = false; - chunking_enabled = true; - return DecoratedRestfulClient::send_header("Transfer-Encoding", - "chunked"); - } - - size_t send_body(const char* buf, - const size_t len) override { - if (! chunking_enabled) { - return DecoratedRestfulClient::send_body(buf, len); - } else { - static constexpr char HEADER_END[] = "\r\n"; - char sizebuf[32]; - const auto slen = snprintf(sizebuf, sizeof(buf), "%" PRIx64 "\r\n", len); - size_t sent = 0; - - sent += DecoratedRestfulClient::send_body(sizebuf, slen); - sent += DecoratedRestfulClient::send_body(buf, len); - sent += DecoratedRestfulClient::send_body(HEADER_END, - sizeof(HEADER_END) - 1); - return sent; - } - } - - size_t complete_request() override { - size_t sent = 0; - - if (chunking_enabled) { - static constexpr char CHUNKED_RESP_END[] = "0\r\n\r\n"; - sent += DecoratedRestfulClient::send_body(CHUNKED_RESP_END, - sizeof(CHUNKED_RESP_END) - 1); - } - - return sent + DecoratedRestfulClient::complete_request(); - } -}; - -template static inline -ChunkingFilter add_chunking(T&& t) { - return ChunkingFilter(std::forward(t)); -} - - -/* Class that controls and inhibits the process of sending Content-Length HTTP - * header where RFC 7230 requests so. The cases worth our attention are 204 No - * Content as well as 304 Not Modified. */ -template -class ConLenControllingFilter : public DecoratedRestfulClient { -protected: - enum class ContentLengthAction { - FORWARD, - INHIBIT, - UNKNOWN - } action; - -public: - template - ConLenControllingFilter(U&& decoratee) - : DecoratedRestfulClient(std::forward(decoratee)), - action(ContentLengthAction::UNKNOWN) { - } - - size_t send_status(const int status, - const char* const status_name) override { - if (204 == status || 304 == status) { - action = ContentLengthAction::INHIBIT; - } else { - action = ContentLengthAction::FORWARD; - } - - return DecoratedRestfulClient::send_status(status, status_name); - } - - size_t send_content_length(const uint64_t len) override { - switch(action) { - case ContentLengthAction::FORWARD: - return DecoratedRestfulClient::send_content_length(len); - case ContentLengthAction::INHIBIT: - return 0; - case ContentLengthAction::UNKNOWN: - default: - return -EINVAL; - } - } -}; - -template static inline -ConLenControllingFilter add_conlen_controlling(T&& t) { - return ConLenControllingFilter(std::forward(t)); -} - - -/* Filter that rectifies the wrong behaviour of some clients of the RGWRestfulIO - * interface. Should be removed after fixing those clients. */ -template -class ReorderingFilter : public DecoratedRestfulClient { -protected: - enum class ReorderState { - RGW_EARLY_HEADERS, /* Got headers sent before calling send_status. */ - RGW_STATUS_SEEN, /* Status has been seen. */ - RGW_DATA /* Header has been completed. */ - } phase; - - boost::optional content_length; - - std::vector> headers; - - size_t send_header(const boost::string_ref& name, - const boost::string_ref& value) override { - switch (phase) { - case ReorderState::RGW_EARLY_HEADERS: - case ReorderState::RGW_STATUS_SEEN: - headers.emplace_back(std::make_pair(name.to_string(), - value.to_string())); - return 0; - case ReorderState::RGW_DATA: - return DecoratedRestfulClient::send_header(name, value); - } - - return -EIO; - } - -public: - template - ReorderingFilter(U&& decoratee) - : DecoratedRestfulClient(std::forward(decoratee)), - phase(ReorderState::RGW_EARLY_HEADERS) { - } - - size_t send_status(const int status, - const char* const status_name) override { - phase = ReorderState::RGW_STATUS_SEEN; - - return DecoratedRestfulClient::send_status(status, status_name); - } - - size_t send_content_length(const uint64_t len) override { - if (ReorderState::RGW_EARLY_HEADERS == phase) { - /* Oh great, someone tries to send content length before status. */ - content_length = len; - return 0; - } else { - return DecoratedRestfulClient::send_content_length(len); - } - } - - size_t complete_header() override { - size_t sent = 0; - - /* Change state in order to immediately send everything we get. */ - phase = ReorderState::RGW_DATA; - - /* Sent content length if necessary. */ - if (content_length) { - sent += DecoratedRestfulClient::send_content_length(*content_length); - } - - /* Header data in buffers are already counted. */ - for (const auto& kv : headers) { - sent += DecoratedRestfulClient::send_header(kv.first, kv.second); - } - headers.clear(); - - return sent + DecoratedRestfulClient::complete_header(); - } -}; - -template static inline -ReorderingFilter add_reordering(T&& t) { - return ReorderingFilter(std::forward(t)); -} - -} /* namespace io */ -} /* namespace rgw */ -#endif /* CEPH_RGW_CLIENT_IO_DECOIMPL_H */ diff --git a/src/rgw/rgw_client_io_filters.h b/src/rgw/rgw_client_io_filters.h new file mode 100644 index 000000000000..f573af8eccaf --- /dev/null +++ b/src/rgw/rgw_client_io_filters.h @@ -0,0 +1,404 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_RGW_CLIENT_IO_DECOIMPL_H +#define CEPH_RGW_CLIENT_IO_DECOIMPL_H + +#include + +#include + +#include "rgw_common.h" +#include "rgw_client_io.h" + +namespace rgw { +namespace io { + +template +class AccountingFilter : public DecoratedRestfulClient, + public Accounter { + bool enabled; + uint64_t total_sent; + uint64_t total_received; + +public: + template + AccountingFilter(U&& decoratee) + : DecoratedRestfulClient(std::forward(decoratee)), + enabled(false), + total_sent(0), + total_received(0) { + } + + size_t send_status(const int status, + const char* const status_name) override { + const auto sent = DecoratedRestfulClient::send_status(status, + status_name); + if (enabled) { + total_sent += sent; + } + return sent; + } + + size_t send_100_continue() override { + const auto sent = DecoratedRestfulClient::send_100_continue(); + if (enabled) { + total_sent += sent; + } + return sent; + } + + size_t send_header(const boost::string_ref& name, + const boost::string_ref& value) override { + const auto sent = DecoratedRestfulClient::send_header(name, value); + if (enabled) { + total_sent += sent; + } + return sent; + } + + size_t send_content_length(const uint64_t len) override { + const auto sent = DecoratedRestfulClient::send_content_length(len); + if (enabled) { + total_sent += sent; + } + return sent; + } + + size_t send_chunked_transfer_encoding() override { + const auto sent = DecoratedRestfulClient::send_chunked_transfer_encoding(); + if (enabled) { + total_sent += sent; + } + return sent; + } + + size_t complete_header() override { + const auto sent = DecoratedRestfulClient::complete_header(); + if (enabled) { + total_sent += sent; + } + return sent; + } + + size_t recv_body(char* buf, size_t max) override { + const auto received = DecoratedRestfulClient::recv_body(buf, max); + if (enabled) { + total_received += received; + } + return received; + } + + size_t send_body(const char* const buf, + const size_t len) override { + const auto sent = DecoratedRestfulClient::send_body(buf, len); + if (enabled) { + total_sent += sent; + } + return sent; + } + + uint64_t get_bytes_sent() const override { + return total_sent; + } + + uint64_t get_bytes_received() const override { + return total_received; + } + + void set_account(bool enabled) override { + this->enabled = enabled; + } +}; + + +/* Filter for in-memory buffering incoming data and calculating the content + * length header if it isn't present. */ +template +class BufferingFilter : public DecoratedRestfulClient { + template friend class DecoratedRestfulClient; +protected: + ceph::bufferlist data; + + bool has_content_length; + bool buffer_data; + +public: + template + BufferingFilter(U&& decoratee) + : DecoratedRestfulClient(std::forward(decoratee)), + has_content_length(false), + buffer_data(false) { + } + + size_t send_content_length(const uint64_t len) override; + size_t send_chunked_transfer_encoding() override; + size_t complete_header() override; + size_t send_body(const char* buf, size_t len) override; + size_t complete_request() override; +}; + +template +size_t BufferingFilter::send_body(const char* const buf, + const size_t len) +{ + if (buffer_data) { + data.append(buf, len); + return 0; + } + + return DecoratedRestfulClient::send_body(buf, len); +} + +template +size_t BufferingFilter::send_content_length(const uint64_t len) +{ + has_content_length = true; + return DecoratedRestfulClient::send_content_length(len); +} + +template +size_t BufferingFilter::send_chunked_transfer_encoding() +{ + has_content_length = true; + return DecoratedRestfulClient::send_chunked_transfer_encoding(); +} + +template +size_t BufferingFilter::complete_header() +{ + if (! has_content_length) { + /* We will dump everything in complete_request(). */ + buffer_data = true; + return 0; + } + + return DecoratedRestfulClient::complete_header(); +} + +template +size_t BufferingFilter::complete_request() +{ + size_t sent = 0; + + if (! has_content_length) { + sent += DecoratedRestfulClient::send_content_length(data.length()); + sent += DecoratedRestfulClient::complete_header(); + } + + if (buffer_data) { + /* We are sending each buffer separately to avoid extra memory shuffling + * that would occur on data.c_str() to provide a continuous memory area. */ + for (const auto& ptr : data.buffers()) { + sent += DecoratedRestfulClient::send_body(ptr.c_str(), + ptr.length()); + } + data.clear(); + buffer_data = false; + } + + return sent + DecoratedRestfulClient::complete_request(); +} + +template static inline +BufferingFilter add_buffering(T&& t) { + return BufferingFilter(std::forward(t)); +} + + +template +class ChunkingFilter : public DecoratedRestfulClient { + template friend class DecoratedRestfulClient; +protected: + bool has_content_length; + bool chunking_enabled; + +public: + template + ChunkingFilter(U&& decoratee) + : DecoratedRestfulClient(std::forward(decoratee)), + has_content_length(false), + chunking_enabled(false) { + } + + size_t send_content_length(const uint64_t len) override { + has_content_length = true; + return DecoratedRestfulClient::send_content_length(len); + } + + size_t send_chunked_transfer_encoding() override { + has_content_length = false; + chunking_enabled = true; + return DecoratedRestfulClient::send_header("Transfer-Encoding", + "chunked"); + } + + size_t send_body(const char* buf, + const size_t len) override { + if (! chunking_enabled) { + return DecoratedRestfulClient::send_body(buf, len); + } else { + static constexpr char HEADER_END[] = "\r\n"; + char sizebuf[32]; + const auto slen = snprintf(sizebuf, sizeof(buf), "%" PRIx64 "\r\n", len); + size_t sent = 0; + + sent += DecoratedRestfulClient::send_body(sizebuf, slen); + sent += DecoratedRestfulClient::send_body(buf, len); + sent += DecoratedRestfulClient::send_body(HEADER_END, + sizeof(HEADER_END) - 1); + return sent; + } + } + + size_t complete_request() override { + size_t sent = 0; + + if (chunking_enabled) { + static constexpr char CHUNKED_RESP_END[] = "0\r\n\r\n"; + sent += DecoratedRestfulClient::send_body(CHUNKED_RESP_END, + sizeof(CHUNKED_RESP_END) - 1); + } + + return sent + DecoratedRestfulClient::complete_request(); + } +}; + +template static inline +ChunkingFilter add_chunking(T&& t) { + return ChunkingFilter(std::forward(t)); +} + + +/* Class that controls and inhibits the process of sending Content-Length HTTP + * header where RFC 7230 requests so. The cases worth our attention are 204 No + * Content as well as 304 Not Modified. */ +template +class ConLenControllingFilter : public DecoratedRestfulClient { +protected: + enum class ContentLengthAction { + FORWARD, + INHIBIT, + UNKNOWN + } action; + +public: + template + ConLenControllingFilter(U&& decoratee) + : DecoratedRestfulClient(std::forward(decoratee)), + action(ContentLengthAction::UNKNOWN) { + } + + size_t send_status(const int status, + const char* const status_name) override { + if (204 == status || 304 == status) { + action = ContentLengthAction::INHIBIT; + } else { + action = ContentLengthAction::FORWARD; + } + + return DecoratedRestfulClient::send_status(status, status_name); + } + + size_t send_content_length(const uint64_t len) override { + switch(action) { + case ContentLengthAction::FORWARD: + return DecoratedRestfulClient::send_content_length(len); + case ContentLengthAction::INHIBIT: + return 0; + case ContentLengthAction::UNKNOWN: + default: + return -EINVAL; + } + } +}; + +template static inline +ConLenControllingFilter add_conlen_controlling(T&& t) { + return ConLenControllingFilter(std::forward(t)); +} + + +/* Filter that rectifies the wrong behaviour of some clients of the RGWRestfulIO + * interface. Should be removed after fixing those clients. */ +template +class ReorderingFilter : public DecoratedRestfulClient { +protected: + enum class ReorderState { + RGW_EARLY_HEADERS, /* Got headers sent before calling send_status. */ + RGW_STATUS_SEEN, /* Status has been seen. */ + RGW_DATA /* Header has been completed. */ + } phase; + + boost::optional content_length; + + std::vector> headers; + + size_t send_header(const boost::string_ref& name, + const boost::string_ref& value) override { + switch (phase) { + case ReorderState::RGW_EARLY_HEADERS: + case ReorderState::RGW_STATUS_SEEN: + headers.emplace_back(std::make_pair(name.to_string(), + value.to_string())); + return 0; + case ReorderState::RGW_DATA: + return DecoratedRestfulClient::send_header(name, value); + } + + return -EIO; + } + +public: + template + ReorderingFilter(U&& decoratee) + : DecoratedRestfulClient(std::forward(decoratee)), + phase(ReorderState::RGW_EARLY_HEADERS) { + } + + size_t send_status(const int status, + const char* const status_name) override { + phase = ReorderState::RGW_STATUS_SEEN; + + return DecoratedRestfulClient::send_status(status, status_name); + } + + size_t send_content_length(const uint64_t len) override { + if (ReorderState::RGW_EARLY_HEADERS == phase) { + /* Oh great, someone tries to send content length before status. */ + content_length = len; + return 0; + } else { + return DecoratedRestfulClient::send_content_length(len); + } + } + + size_t complete_header() override { + size_t sent = 0; + + /* Change state in order to immediately send everything we get. */ + phase = ReorderState::RGW_DATA; + + /* Sent content length if necessary. */ + if (content_length) { + sent += DecoratedRestfulClient::send_content_length(*content_length); + } + + /* Header data in buffers are already counted. */ + for (const auto& kv : headers) { + sent += DecoratedRestfulClient::send_header(kv.first, kv.second); + } + headers.clear(); + + return sent + DecoratedRestfulClient::complete_header(); + } +}; + +template static inline +ReorderingFilter add_reordering(T&& t) { + return ReorderingFilter(std::forward(t)); +} + +} /* namespace io */ +} /* namespace rgw */ +#endif /* CEPH_RGW_CLIENT_IO_DECOIMPL_H */ diff --git a/src/rgw/rgw_fcgi_process.cc b/src/rgw/rgw_fcgi_process.cc index 5dffbfb0f8c2..b585db2272c6 100644 --- a/src/rgw/rgw_fcgi_process.cc +++ b/src/rgw/rgw_fcgi_process.cc @@ -12,7 +12,7 @@ #include "rgw_process.h" #include "rgw_loadgen.h" #include "rgw_client_io.h" -#include "rgw_client_io_decoimpl.h" +#include "rgw_client_io_filters.h" #define dout_subsys ceph_subsys_rgw