RESTinio
write_group_output_ctx.hpp
Go to the documentation of this file.
1/*
2 restinio
3*/
4
9#pragma once
10
11#include <vector>
12
14
15#include <restinio/buffers.hpp>
16#include <restinio/optional.hpp>
17#include <restinio/variant.hpp>
19
21
22namespace restinio
23{
24
25namespace impl
26{
27
28using asio_bufs_container_t = std::vector< asio_ns::const_buffer >;
29
30//
31// write_group_output_ctx_t
32//
33
35
80{
83 static constexpr auto
84 max_iov_len() noexcept
85 {
86 using len_t = decltype( asio_ns::detail::max_iov_len );
87 return static_cast< asio_bufs_container_t::size_type >(
88 std::min< len_t >( asio_ns::detail::max_iov_len, 64 ) );
89 }
90
91 public:
93 /*
94 Space for m_asio_bufs is reserved to be ready to store max_iov_len() asio bufs.
95 */
97 {
98 m_asio_bufs.reserve( max_iov_len() );
99 }
100
102
106 {
108
111 const asio_bufs_container_t & asio_bufs,
113 std::size_t total_size ) noexcept
114 : m_asio_bufs{ &asio_bufs }
115 , m_total_size{ total_size }
116 {}
117
118 public:
121
124
126 const std::vector< asio_ns::const_buffer > &
128 {
129 return *m_asio_bufs;
130 }
131
133 auto size() const noexcept { return m_total_size; }
134
135 private:
138 };
139
142 {
144
147 sendfile_operation_shared_ptr_t & sendfile_operation ) noexcept
148 : m_sendfile{ &sendfile }
149 , m_sendfile_operation{ &sendfile_operation }
150 {}
151
152 public:
155
158
160
165 template< typename Socket, typename After_Write_CB >
166 void
168 default_asio_executor executor,
169 Socket & socket,
170 After_Write_CB after_sendfile_cb )
171 {
172 assert( m_sendfile->is_valid() );
173
174 if( !m_sendfile->is_valid() )
175 {
176 // This must never happen.
177 throw exception_t{ "invalid file descriptor in sendfile operation." };
178 }
179
180 auto sendfile_operation =
181 std::make_shared< sendfile_operation_runner_t< Socket > >(
182 *m_sendfile,
183 std::move( executor ),
184 socket,
185 std::move( after_sendfile_cb ) );
186
187 *m_sendfile_operation = std::move( sendfile_operation );
188 (*m_sendfile_operation)->start();
189 }
190
192 auto
193 timelimit() const noexcept
194 {
195 assert( m_sendfile->is_valid() );
196
197 return m_sendfile->timelimit();
198 }
199
201
205 void
206 reset() noexcept
207 {
209 }
210
212 auto size() const noexcept { return m_sendfile->size(); }
213
214 private:
216 sendfile_t * m_sendfile; // Pointer is used to be able to copy/assign.
217
219
224 };
225
227
233
235 bool transmitting() const noexcept { return static_cast< bool >( m_current_wg ); }
236
238 void
240 {
241 m_current_wg = std::move( next_wg );
242 }
243
246 variant_t<
250
254 {
255 assert( m_current_wg );
256
258
259 if( m_next_writable_item_index < m_current_wg->items_count() )
260 {
261 // Has writable items.
262 const auto next_wi_type =
263 m_current_wg->items()[ m_next_writable_item_index ].write_type();
264
266 {
267 // Trivial buffers.
269 }
270 else
271 {
272 // Sendfile.
273 assert( writable_item_type_t::file_write_operation == next_wi_type );
274 result = prepare_sendfile_wo();
275 }
276 }
277
278 return result;
279 }
280
282 void
283 fail_write_group( const asio_ns::error_code & ec )
284 {
285 assert( m_current_wg );
286
288 m_current_wg.reset();
289 m_sendfile_operation.reset();
290 }
291
293 void
295 {
296 assert( m_current_wg );
297
298 invoke_after_write_notificator_if_necessary( asio_ns::error_code{} );
300 }
301
302 private:
304 void
306 {
307 m_current_wg.reset();
309 }
310
312 void
313 invoke_after_write_notificator_if_necessary( const asio_ns::error_code & ec )
314 {
315 try
316 {
317 m_current_wg->invoke_after_write_notificator_if_exists( ec );
318 }
319 catch( const std::exception & ex )
320 {
321 // Actualy no need to reset m_current_wg as a thrown exception
322 // will break working circle of connection.
323 // But as it is used as flag for transmitting()
324 // we reset the object.
326
327 throw exception_t{
328 fmt::format( "after write callback failed: {}", ex.what() ) };
329 }
330 }
331
333 trivial_write_operation_t
335 {
336 m_asio_bufs.clear();
337
338 const auto & items = m_current_wg->items();
339 std::size_t total_size{ 0 };
340
341 for( ;m_next_writable_item_index < items.size() &&
343 items[ m_next_writable_item_index ].write_type() &&
344 max_iov_len() > m_asio_bufs.size();
346 {
347 const auto & item = items[ m_next_writable_item_index ];
348 m_asio_bufs.emplace_back( item.buf() );
349 total_size += item.size();
350 }
351
352 assert( !m_asio_bufs.empty() );
353 return trivial_write_operation_t{ m_asio_bufs, total_size };
354 }
355
357 file_write_operation_t
359 {
360 auto & sf =
361 m_current_wg->items()[ m_next_writable_item_index++ ].sendfile_operation();
362
364 }
365
368
370
375
378
381};
382
383} /* namespace impl */
384
385} /* namespace restinio */
Exception class for all exceptions thrown by RESTinio.
Definition: exception.hpp:26
sendfile_operation_shared_ptr_t * m_sendfile_operation
A curernt sendfile operation.
file_write_operation_t & operator=(const file_write_operation_t &)=default
file_write_operation_t(sendfile_t &sendfile, sendfile_operation_shared_ptr_t &sendfile_operation) noexcept
file_write_operation_t(const file_write_operation_t &)=default
auto timelimit() const noexcept
Get the timelimit on this sendfile operation.
void start_sendfile_operation(default_asio_executor executor, Socket &socket, After_Write_CB after_sendfile_cb)
Start a sendfile operation.
auto size() const noexcept
Get the size of sendfile operation.
trivial_write_operation_t(trivial_write_operation_t &&)=default
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(const asio_bufs_container_t &asio_bufs, std::size_t total_size) noexcept
auto size() const noexcept
The size of data within this operation.
const std::vector< asio_ns::const_buffer > & get_trivial_bufs() const noexcept
Get buffer "iovec" for performing gather write.
Helper class for writting response data.
void fail_write_group(const asio_ns::error_code &ec)
Handle current group write process failed.
solid_write_operation_variant_t extract_next_write_operation()
et an object with next write operation to perform.
std::size_t m_next_writable_item_index
Keeps track of the next writable item stored in m_current_wg.
trivial_write_operation_t prepare_trivial_buffers_wo()
Prepare write operation for trivial buffers.
void finish_write_group()
Finish writing group normally.
sendfile_operation_shared_ptr_t m_sendfile_operation
Sendfile operation storage context.
asio_bufs_container_t m_asio_bufs
Asio buffers storage.
void invoke_after_write_notificator_if_necessary(const asio_ns::error_code &ec)
Execute notification callback if necessary.
void start_next_write_group(optional_t< write_group_t > next_wg) noexcept
Start handlong next write group.
static constexpr auto max_iov_len() noexcept
Get the maximum number of buffers that can be written with gather write operation.
void reset_write_group()
Reset the write group and associated context.
bool transmitting() const noexcept
Check if data is trunsmitting now.
optional_t< write_group_t > m_current_wg
Real buffers with data.
file_write_operation_t prepare_sendfile_wo()
Prepare write operation for sendfile.
Send file write operation description.
Definition: sendfile.hpp:226
auto size() const noexcept
Get size of data to write.
Definition: sendfile.hpp:306
auto timelimit() const noexcept
Definition: sendfile.hpp:376
bool is_valid() const noexcept
Check if file is valid.
Definition: sendfile.hpp:294
Detection of compiler version and absence of various features.
#define RESTINIO_ENSURE_NOEXCEPT_CALL(expr)
A wrapper around static_assert for checking that an expression is noexcept and execution of that expr...
std::vector< asio_ns::const_buffer > asio_bufs_container_t
std::shared_ptr< sendfile_operation_base_t > sendfile_operation_shared_ptr_t
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:468
asio_ns::executor default_asio_executor
@ trivial_write_operation
Item is a buffer and must be written trivially.
@ file_write_operation
Item is a sendfile operation and implicates file write operation.
#define const
Definition: zconf.h:230