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 
22 namespace restinio
23 {
24 
25 namespace impl
26 {
27 
28 using 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:
137  size_t m_total_size;
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 
265  if( writable_item_type_t::trivial_write_operation == next_wi_type )
266  {
267  // Trivial buffers.
268  result = prepare_trivial_buffers_wo();
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() &&
342  writable_item_type_t::trivial_write_operation ==
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 
374  std::size_t m_next_writable_item_index{ 0 };
375 
378 
381 };
382 
383 } /* namespace impl */
384 
385 } /* namespace restinio */
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::exception_t
Exception class for all exceptions thrown by RESTinio.
Definition: exception.hpp:26
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::operator=
trivial_write_operation_t & operator=(const trivial_write_operation_t &)=default
buffers.hpp
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::file_write_operation_t::file_write_operation_t
file_write_operation_t(file_write_operation_t &&)=default
nonstd::optional_lite::std11::move
T & move(T &t)
Definition: optional.hpp:421
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
Helper class for writting response data.
Definition: write_group_output_ctx.hpp:80
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::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
asio_include.hpp
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::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::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_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:60
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::default_asio_executor
asio_ns::executor default_asio_executor
Definition: asio_include.hpp:224
restinio::impl::write_group_output_ctx_t::none_write_operation_t
None write operation.
Definition: write_group_output_ctx.hpp:232
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:468
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:374
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::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::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::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::m_current_wg
optional_t< write_group_t > m_current_wg
Real buffers with data.
Definition: write_group_output_ctx.hpp:367
nonstd::optional_lite::optional
class optional
Definition: optional.hpp:839
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::trivial_write_operation_t::trivial_write_operation_t
trivial_write_operation_t(const trivial_write_operation_t &)=default
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::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::sendfile_t::timelimit
auto timelimit() const noexcept
Definition: sendfile.hpp:376
restinio
Definition: asio_include.hpp:21
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:380
sendfile_operation.hpp
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::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::trivial_write_operation_t::size
auto size() const noexcept
The size of data within this operation.
Definition: write_group_output_ctx.hpp:133
restinio::sendfile_t::is_valid
bool is_valid() const noexcept
Check if file is valid.
Definition: sendfile.hpp:294
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::m_asio_bufs
asio_bufs_container_t m_asio_bufs
Asio buffers storage.
Definition: write_group_output_ctx.hpp:377
restinio::sendfile_t::size
auto size() const noexcept
Get size of data to write.
Definition: sendfile.hpp:306
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:358
compiler_features.hpp
Detection of compiler version and absence of various features.
restinio::impl::asio_bufs_container_t
std::vector< asio_ns::const_buffer > asio_bufs_container_t
Definition: write_group_output_ctx.hpp:28
variant.hpp
restinio::writable_item_type_t::trivial_write_operation
@ trivial_write_operation
Item is a buffer and must be written trivially.
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::prepare_trivial_buffers_wo
trivial_write_operation_t prepare_trivial_buffers_wo()
Prepare write operation for trivial buffers.
Definition: write_group_output_ctx.hpp:334
restinio::sendfile_t
Send file write operation description.
Definition: sendfile.hpp:226
nonstd::variants::variant
Definition: variant.hpp:1209
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::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
const
#define const
Definition: zconf.h:230
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::file_write_operation_t
Write operaton using sendfile.
Definition: write_group_output_ctx.hpp:142
optional.hpp