Loading...
Searching...
No Matches
write_group_output_ctx.hpp
Go to the documentation of this file.
/*
restinio
*/
#pragma once
#include <vector>
#include <restinio/asio_include.hpp>
#include <restinio/buffers.hpp>
#include <restinio/optional.hpp>
#include <restinio/variant.hpp>
#include <restinio/impl/sendfile_operation.hpp>
#include <restinio/compiler_features.hpp>
namespace restinio
{
namespace impl
{
using asio_bufs_container_t = std::vector< asio_ns::const_buffer >;
//
// write_group_output_ctx_t
//
class write_group_output_ctx_t
{
static constexpr auto
max_iov_len() noexcept
{
using len_t = decltype( asio_ns::detail::max_iov_len );
return static_cast< asio_bufs_container_t::size_type >(
std::min< len_t >( asio_ns::detail::max_iov_len, 64 ) );
}
public:
/*
Space for m_asio_bufs is reserved to be ready to store max_iov_len() asio bufs.
*/
write_group_output_ctx_t()
{
m_asio_bufs.reserve( max_iov_len() );
}
class trivial_write_operation_t
{
friend class write_group_output_ctx_t;
explicit trivial_write_operation_t(
const asio_bufs_container_t & asio_bufs,
std::size_t total_size ) noexcept
: m_asio_bufs{ &asio_bufs }
, m_total_size{ total_size }
{}
public:
trivial_write_operation_t( const trivial_write_operation_t & ) = default;
trivial_write_operation_t & operator = ( const trivial_write_operation_t & ) = default;
trivial_write_operation_t( trivial_write_operation_t && ) = default;
trivial_write_operation_t & operator = ( trivial_write_operation_t && ) = default;
const std::vector< asio_ns::const_buffer > &
get_trivial_bufs() const noexcept
{
return *m_asio_bufs;
}
auto size() const noexcept { return m_total_size; }
private:
const asio_bufs_container_t * m_asio_bufs;
size_t m_total_size;
};
class file_write_operation_t
{
friend class write_group_output_ctx_t;
explicit file_write_operation_t(
sendfile_t & sendfile,
sendfile_operation_shared_ptr_t & sendfile_operation ) noexcept
: m_sendfile{ &sendfile }
, m_sendfile_operation{ &sendfile_operation }
{}
public:
file_write_operation_t( const file_write_operation_t & ) = default;
file_write_operation_t & operator = ( const file_write_operation_t & ) = default;
file_write_operation_t( file_write_operation_t && ) = default;
file_write_operation_t & operator = ( file_write_operation_t && ) = default;
template< typename Socket, typename After_Write_CB >
void
start_sendfile_operation(
default_asio_executor executor,
Socket & socket,
After_Write_CB after_sendfile_cb )
{
assert( m_sendfile->is_valid() );
if( !m_sendfile->is_valid() )
{
// This must never happen.
throw exception_t{ "invalid file descriptor in sendfile operation." };
}
auto sendfile_operation =
std::make_shared< sendfile_operation_runner_t< Socket > >(
*m_sendfile,
std::move( executor ),
socket,
std::move( after_sendfile_cb ) );
*m_sendfile_operation = std::move( sendfile_operation );
(*m_sendfile_operation)->start();
}
auto
timelimit() const noexcept
{
assert( m_sendfile->is_valid() );
return m_sendfile->timelimit();
}
void
reset() noexcept
{
RESTINIO_ENSURE_NOEXCEPT_CALL( m_sendfile_operation->reset() );
}
auto size() const noexcept { return m_sendfile->size(); }
private:
sendfile_t * m_sendfile; // Pointer is used to be able to copy/assign.
sendfile_operation_shared_ptr_t * m_sendfile_operation;
};
struct none_write_operation_t {};
bool transmitting() const noexcept { return static_cast< bool >( m_current_wg ); }
void
start_next_write_group( optional_t< write_group_t > next_wg ) noexcept
{
m_current_wg = std::move( next_wg );
}
using solid_write_operation_variant_t =
variant_t<
none_write_operation_t,
trivial_write_operation_t,
file_write_operation_t >;
solid_write_operation_variant_t
extract_next_write_operation()
{
assert( m_current_wg );
solid_write_operation_variant_t result{ none_write_operation_t{} };
if( m_next_writable_item_index < m_current_wg->items_count() )
{
// Has writable items.
const auto next_wi_type =
m_current_wg->items()[ m_next_writable_item_index ].write_type();
if( writable_item_type_t::trivial_write_operation == next_wi_type )
{
// Trivial buffers.
result = prepare_trivial_buffers_wo();
}
else
{
// Sendfile.
assert( writable_item_type_t::file_write_operation == next_wi_type );
result = prepare_sendfile_wo();
}
}
return result;
}
void
fail_write_group( const asio_ns::error_code & ec )
{
assert( m_current_wg );
invoke_after_write_notificator_if_necessary( ec );
m_current_wg.reset();
m_sendfile_operation.reset();
}
void
finish_write_group()
{
assert( m_current_wg );
invoke_after_write_notificator_if_necessary( asio_ns::error_code{} );
reset_write_group();
}
private:
void
reset_write_group()
{
m_current_wg.reset();
m_next_writable_item_index = 0;
}
void
invoke_after_write_notificator_if_necessary( const asio_ns::error_code & ec )
{
try
{
m_current_wg->invoke_after_write_notificator_if_exists( ec );
}
catch( const std::exception & ex )
{
// Actualy no need to reset m_current_wg as a thrown exception
// will break working circle of connection.
// But as it is used as flag for transmitting()
// we reset the object.
reset_write_group();
throw exception_t{
fmt::format(
RESTINIO_FMT_FORMAT_STRING( "after write callback failed: {}" ),
ex.what() ) };
}
}
trivial_write_operation_t
prepare_trivial_buffers_wo()
{
m_asio_bufs.clear();
const auto & items = m_current_wg->items();
std::size_t total_size{ 0 };
for( ;m_next_writable_item_index < items.size() &&
writable_item_type_t::trivial_write_operation ==
items[ m_next_writable_item_index ].write_type() &&
max_iov_len() > m_asio_bufs.size();
++m_next_writable_item_index )
{
const auto & item = items[ m_next_writable_item_index ];
m_asio_bufs.emplace_back( item.buf() );
total_size += item.size();
}
assert( !m_asio_bufs.empty() );
return trivial_write_operation_t{ m_asio_bufs, total_size };
}
file_write_operation_t
prepare_sendfile_wo()
{
auto & sf =
m_current_wg->items()[ m_next_writable_item_index++ ].sendfile_operation();
return file_write_operation_t{ sf, m_sendfile_operation };
}
optional_t< write_group_t > m_current_wg;
std::size_t m_next_writable_item_index{ 0 };
asio_bufs_container_t m_asio_bufs;
sendfile_operation_shared_ptr_t m_sendfile_operation;
};
} /* namespace impl */
} /* namespace restinio */
asio_include.hpp
buffers.hpp
nonstd::optional_lite::optional
class optional
Definition: optional.hpp:932
nonstd::variants::variant
Definition: variant.hpp:1304
restinio::exception_t
Exception class for all exceptions thrown by RESTinio.
Definition: exception.hpp:26
restinio::impl::write_group_output_ctx_t::file_write_operation_t
Write operaton using sendfile.
Definition: write_group_output_ctx.hpp:142
restinio::impl::write_group_output_ctx_t::file_write_operation_t::m_sendfile_operation
sendfile_operation_shared_ptr_t * m_sendfile_operation
A curernt sendfile operation.
Definition: write_group_output_ctx.hpp:223
restinio::impl::write_group_output_ctx_t::file_write_operation_t::operator=
file_write_operation_t & operator=(const file_write_operation_t &)=default
restinio::impl::write_group_output_ctx_t::file_write_operation_t::file_write_operation_t
file_write_operation_t(sendfile_t &sendfile, sendfile_operation_shared_ptr_t &sendfile_operation) noexcept
Definition: write_group_output_ctx.hpp:145
restinio::impl::write_group_output_ctx_t::file_write_operation_t::file_write_operation_t
file_write_operation_t(const file_write_operation_t &)=default
restinio::impl::write_group_output_ctx_t::file_write_operation_t::reset
void reset() noexcept
Reset write operation context.
Definition: write_group_output_ctx.hpp:206
restinio::impl::write_group_output_ctx_t::file_write_operation_t::timelimit
auto timelimit() const noexcept
Get the timelimit on this sendfile operation.
Definition: write_group_output_ctx.hpp:193
restinio::impl::write_group_output_ctx_t::file_write_operation_t::start_sendfile_operation
void start_sendfile_operation(default_asio_executor executor, Socket &socket, After_Write_CB after_sendfile_cb)
Start a sendfile operation.
Definition: write_group_output_ctx.hpp:167
restinio::impl::write_group_output_ctx_t::file_write_operation_t::m_sendfile
sendfile_t * m_sendfile
A pointer to sendfile.
Definition: write_group_output_ctx.hpp:216
restinio::impl::write_group_output_ctx_t::file_write_operation_t::size
auto size() const noexcept
Get the size of sendfile operation.
Definition: write_group_output_ctx.hpp:212
restinio::impl::write_group_output_ctx_t::file_write_operation_t::file_write_operation_t
file_write_operation_t(file_write_operation_t &&)=default
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t
Trivial write operaton.
Definition: write_group_output_ctx.hpp:106
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t::trivial_write_operation_t
trivial_write_operation_t(trivial_write_operation_t &&)=default
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t::m_asio_bufs
const asio_bufs_container_t * m_asio_bufs
Definition: write_group_output_ctx.hpp:136
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t::trivial_write_operation_t
trivial_write_operation_t(const trivial_write_operation_t &)=default
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t::operator=
trivial_write_operation_t & operator=(const trivial_write_operation_t &)=default
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t::trivial_write_operation_t
trivial_write_operation_t(const asio_bufs_container_t &asio_bufs, std::size_t total_size) noexcept
Definition: write_group_output_ctx.hpp:109
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t::size
auto size() const noexcept
The size of data within this operation.
Definition: write_group_output_ctx.hpp:133
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t::m_total_size
size_t m_total_size
Definition: write_group_output_ctx.hpp:137
restinio::impl::write_group_output_ctx_t::trivial_write_operation_t::get_trivial_bufs
const std::vector< asio_ns::const_buffer > & get_trivial_bufs() const noexcept
Get buffer "iovec" for performing gather write.
Definition: write_group_output_ctx.hpp:127
restinio::impl::write_group_output_ctx_t
Helper class for writting response data.
Definition: write_group_output_ctx.hpp:80
restinio::impl::write_group_output_ctx_t::fail_write_group
void fail_write_group(const asio_ns::error_code &ec)
Handle current group write process failed.
Definition: write_group_output_ctx.hpp:283
restinio::impl::write_group_output_ctx_t::extract_next_write_operation
solid_write_operation_variant_t extract_next_write_operation()
et an object with next write operation to perform.
Definition: write_group_output_ctx.hpp:253
restinio::impl::write_group_output_ctx_t::m_next_writable_item_index
std::size_t m_next_writable_item_index
Keeps track of the next writable item stored in m_current_wg.
Definition: write_group_output_ctx.hpp:376
restinio::impl::write_group_output_ctx_t::prepare_trivial_buffers_wo
trivial_write_operation_t prepare_trivial_buffers_wo()
Prepare write operation for trivial buffers.
Definition: write_group_output_ctx.hpp:336
restinio::impl::write_group_output_ctx_t::write_group_output_ctx_t
write_group_output_ctx_t()
Contruct an object.
Definition: write_group_output_ctx.hpp:96
restinio::impl::write_group_output_ctx_t::finish_write_group
void finish_write_group()
Finish writing group normally.
Definition: write_group_output_ctx.hpp:294
restinio::impl::write_group_output_ctx_t::m_sendfile_operation
sendfile_operation_shared_ptr_t m_sendfile_operation
Sendfile operation storage context.
Definition: write_group_output_ctx.hpp:382
restinio::impl::write_group_output_ctx_t::m_asio_bufs
asio_bufs_container_t m_asio_bufs
Asio buffers storage.
Definition: write_group_output_ctx.hpp:379
restinio::impl::write_group_output_ctx_t::invoke_after_write_notificator_if_necessary
void invoke_after_write_notificator_if_necessary(const asio_ns::error_code &ec)
Execute notification callback if necessary.
Definition: write_group_output_ctx.hpp:313
restinio::impl::write_group_output_ctx_t::start_next_write_group
void start_next_write_group(optional_t< write_group_t > next_wg) noexcept
Start handlong next write group.
Definition: write_group_output_ctx.hpp:239
restinio::impl::write_group_output_ctx_t::max_iov_len
static constexpr auto max_iov_len() noexcept
Get the maximum number of buffers that can be written with gather write operation.
Definition: write_group_output_ctx.hpp:84
restinio::impl::write_group_output_ctx_t::reset_write_group
void reset_write_group()
Reset the write group and associated context.
Definition: write_group_output_ctx.hpp:305
restinio::impl::write_group_output_ctx_t::transmitting
bool transmitting() const noexcept
Check if data is trunsmitting now.
Definition: write_group_output_ctx.hpp:235
restinio::impl::write_group_output_ctx_t::m_current_wg
optional_t< write_group_t > m_current_wg
Real buffers with data.
Definition: write_group_output_ctx.hpp:369
restinio::impl::write_group_output_ctx_t::prepare_sendfile_wo
file_write_operation_t prepare_sendfile_wo()
Prepare write operation for sendfile.
Definition: write_group_output_ctx.hpp:360
restinio::sendfile_t
Send file write operation description.
Definition: sendfile.hpp:226
restinio::sendfile_t::size
auto size() const noexcept
Get size of data to write.
Definition: sendfile.hpp:306
restinio::sendfile_t::timelimit
auto timelimit() const noexcept
Definition: sendfile.hpp:377
restinio::sendfile_t::is_valid
bool is_valid() const noexcept
Check if file is valid.
Definition: sendfile.hpp:294
compiler_features.hpp
Detection of compiler version and absence of various features.
RESTINIO_ENSURE_NOEXCEPT_CALL
#define RESTINIO_ENSURE_NOEXCEPT_CALL(expr)
A wrapper around static_assert for checking that an expression is noexcept and execution of that expr...
Definition: compiler_features.hpp:70
RESTINIO_FMT_FORMAT_STRING
#define RESTINIO_FMT_FORMAT_STRING(s)
Definition: include_fmtlib.hpp:92
restinio::impl::asio_bufs_container_t
std::vector< asio_ns::const_buffer > asio_bufs_container_t
Definition: write_group_output_ctx.hpp:28
restinio::impl::sendfile_operation_shared_ptr_t
std::shared_ptr< sendfile_operation_base_t > sendfile_operation_shared_ptr_t
Definition: sendfile_operation.hpp:36
restinio
Definition: asio_include.hpp:21
restinio::sendfile
sendfile_t sendfile(file_descriptor_holder_t fd, file_meta_t meta, file_size_t chunk_size=sendfile_default_chunk_size) noexcept
Definition: sendfile.hpp:469
restinio::default_asio_executor
asio_ns::executor default_asio_executor
Definition: asio_include.hpp:224
restinio::writable_item_type_t::trivial_write_operation
@ trivial_write_operation
Item is a buffer and must be written trivially.
restinio::writable_item_type_t::file_write_operation
@ file_write_operation
Item is a sendfile operation and implicates file write operation.
optional.hpp
sendfile_operation.hpp
restinio::impl::write_group_output_ctx_t::none_write_operation_t
None write operation.
Definition: write_group_output_ctx.hpp:232
variant.hpp
const
#define const
Definition: zconf.h:230