2
3
6
7
8
12#include <restinio/impl/include_fmtlib.hpp>
14#include <restinio/utils/suppress_exceptions.hpp>
16#include <restinio/exception.hpp>
17#include <restinio/request_handler.hpp>
18#include <restinio/buffers.hpp>
45 return ctx.m_write_groups;
67 if( !m_write_groups.empty() &&
68 !m_write_groups.back().has_after_write_notificator() &&
69 std::size_t{ 0 } == wg.status_line_size() )
71 m_write_groups.back().merge( std::move( wg ) );
75 m_write_groups.emplace_back( std::move( wg ) );
81 bool empty()
const noexcept {
return m_write_groups.empty(); }
87 assert( !m_write_groups.empty() );
98 if constexpr(
noexcept(m_write_groups.erase(m_write_groups.begin())) )
101 m_write_groups.erase( m_write_groups.begin() );
107 m_write_groups.erase( m_write_groups.begin() );
135 return m_write_groups.empty() &&
136 response_parts_attr_t::final_parts ==
137 m_response_output_flags.m_response_parts;
163 m_contexts.resize( max_elements_count );
177 return m_contexts.size() == m_elements_exists;
184 return m_contexts[ m_first_element_index ];
192 (m_first_element_index + (m_elements_exists - 1) ) %
207 return &m_contexts[ get_real_index( req_id ) ];
216 "unable to insert context because "
217 "response_context_table is full" };
222 ( m_first_element_index + m_elements_exists ) % m_contexts.size()
225 ctx.reinit( req_id );
237 "unable to pop context because "
238 "response_context_table is empty" };
246
247
248
249
250
251
252
258 if( m_contexts.size() == m_first_element_index )
268 const auto distance_from_first =
271 return ( m_first_element_index + distance_from_first ) % m_contexts.size();
286
287
288
289
295 std::size_t max_req_count )
300
301
304 bool empty()
const noexcept {
return m_context_table.empty(); }
305 bool is_full()
const noexcept {
return m_context_table.is_full(); }
319 m_context_table.push_response_context( m_request_id_counter );
337 "unable to append response parts, "
338 "response coordinator is closed" };
340 auto * ctx = m_context_table.get_by_req_id( req_id );
348 "no context associated with request {}" ),
353 ctx->response_output_flags().m_response_parts )
357 "unable to append response, "
358 "it marked as complete" };
361 ctx->response_output_flags( response_output_flags );
363 ctx->enqueue_group( std::move( wg ) );
368
369
370
371
372
378 "unable to prepare output buffers, "
379 "response coordinator is closed" };
384 if( !m_context_table.empty() )
386 auto & current_ctx = m_context_table.front();
388 if( !current_ctx.empty() )
392 current_ctx.dequeue_group(),
393 current_ctx.request_id() );
395 if( current_ctx.is_complete() )
399 current_ctx.response_output_flags().m_response_parts )
401 current_ctx.response_output_flags().m_response_connection );
403 m_context_table.pop_response_context();
413
414
415
416
417
423 m_context_table.pop_response_context_nonchecked());
430 for(; !m_context_table.empty();
431 m_context_table.pop_response_context_nonchecked() )
437 auto & current_ctx = m_context_table.front();
438 while( !current_ctx.empty() )
440 auto wg = current_ctx.dequeue_group();
443 wg.invoke_after_write_notificator_if_exists( ec );
Exception class for all exceptions thrown by RESTinio.
exception_t(const char *err)
A context for a single response.
write_group_t dequeue_group() noexcept
Extract write group from data queue.
friend write_groups_container_t & utest_access(response_context_t &ctx)
Access write-groups container (used in unit tests)
request_id_t m_request_id
void reinit(request_id_t request_id) noexcept
Reinitialize context.
response_output_flags_t m_response_output_flags
Response flags.
auto response_output_flags() const noexcept
Get flags of corrent response data flow.
write_groups_container_t m_write_groups
Unsent responses parts.
auto request_id() const noexcept
Get id of associated request.
bool is_complete() const noexcept
Is response data of a given request is complete.
bool empty() const noexcept
Is context empty.
void enqueue_group(write_group_t wg)
Put write group to data queue.
void response_output_flags(response_output_flags_t flags) noexcept
Get flags of corrent response data flow.
Helper storage for responses' contexts.
response_context_t & back() noexcept
Get last context.
response_context_table_t(std::size_t max_elements_count)
response_context_t & front() noexcept
Get first context.
void pop_response_context()
Remove the first context from queue.
bool empty() const noexcept
If table is empty.
void pop_response_context_nonchecked() noexcept
Remove the first context from queue with the check for emptiness of the queue.
std::size_t get_real_index(request_id_t req_id) noexcept
std::size_t m_first_element_index
response_context_t * get_by_req_id(request_id_t req_id) noexcept
Get context of specified request.
std::size_t m_elements_exists
std::vector< response_context_t > m_contexts
void push_response_context(request_id_t req_id)
Insert new context into queue.
bool is_full() const noexcept
If table is full.
Coordinator for process of sending responses with respect to http pipeline technique and chunk transf...
void reset() noexcept
Remove all contexts.
request_id_t register_new_request()
Create a new request and reserve context for its response.
bool is_able_to_get_more_messages() const noexcept
Check if it is possible to accept more requests.
request_id_t m_request_id_counter
Counter for asigining id to new requests.
bool is_full() const noexcept
response_context_table_t m_context_table
A storage for resp-context items.
bool empty() const noexcept
bool m_connection_closed_response_occured
Indicate whether a response with connection close flag was emitted.
std::optional< std::pair< write_group_t, request_id_t > > pop_ready_buffers()
Extract a portion of data available for write.
bool closed() const noexcept
response_coordinator_t(std::size_t max_req_count)
void append_response(request_id_t req_id, response_output_flags_t response_output_flags, write_group_t wg)
Add outgoing data for specified request.
Group of writable items transported to the context of underlying connection as one solid piece.
#define RESTINIO_STATIC_ASSERT_NOEXCEPT(expr)
A wrapper around static_assert for checking that an expression is noexcept.
#define RESTINIO_FMT_FORMAT_STRING(s)
unsigned int request_id_t
Request id in scope of single connection.
asio_convertible_error_t
Enum for restinio errors that must presented as asio_ns::error_code value.
@ write_was_not_executed
After write notificator error: data was not sent, connection closed (or aborted) before a given piece...
response_connection_attr_t
Attribute for parts.
@ connection_close
This response says to close connection.
@ connection_keepalive
This response says to keep connection.
asio_ns::error_code make_asio_compaible_error(asio_convertible_error_t err) noexcept
Make restinio error_code compatible with asio_ns::error_code.
response_parts_attr_t
Attribute for parts.
@ final_parts
Final parts (response ands with these parts).
@ not_final_parts
Intermediate parts (more parts of response to follow).
Response output flags for buffers commited to response-coordinator.
response_output_flags_t(response_parts_attr_t response_parts, response_connection_attr_t response_connection) noexcept