RESTinio
Loading...
Searching...
No Matches
sendfile.hpp
Go to the documentation of this file.
1/*
2 restinio
3*/
4
11#pragma once
12
13#include <string>
14#include <chrono>
15#include <array>
16
18
22
23/*
24 Defenitions for:
25 file_descriptor_t
26 file_offset_t
27 file_size_t
28*/
29
30#if defined( _MSC_VER ) || defined(__MINGW32__)
31 #include "sendfile_defs_win.hpp"
32#elif (defined( __clang__ ) || defined( __GNUC__ )) && !defined(__WIN32__)
34#else
35 #if defined (RESTINIO_ENABLE_SENDFILE_DEFAULT_IMPL)
37 #else
38 #error "Sendfile not supported, to enable default implementation define RESTINIO_ENABLE_SENDFILE_DEFAULT_IMPL macro"
39 #endif
40#endif
41
42namespace restinio
43{
44
48
51constexpr file_size_t sendfile_max_chunk_size = 1024 * 1024 * 1024;
52
53//
54// sendfile_chunk_size_guarded_value_t
55//
56
58
65{
67 /*
68 - If chunk_size_value is zero returns 1.
69 - If chunk_size_value is greater than sendfile_max_chunk_size returns sendfile_max_chunk_size.
70 - Otherwise returns chunk_size_value itself.
71 */
72 static constexpr file_size_t
73 clarify_chunk_size( file_size_t chunk_size_value ) noexcept
74 {
75 if( 0 == chunk_size_value )
77
78 if( sendfile_max_chunk_size < chunk_size_value )
80
81 return chunk_size_value;
82 }
83
84 public:
85
86 constexpr sendfile_chunk_size_guarded_value_t( file_size_t chunk_size_value ) noexcept
87 : m_chunk_size{ clarify_chunk_size( chunk_size_value ) }
88 {}
89
91 constexpr auto value() const noexcept { return m_chunk_size; }
92
93 private:
96};
97
98//
99// file_descriptor_holder_t
100//
101
103/*
104 Class is responsible for managing file descriptor as resource.
105
106 @since v.0.4.3
107*/
109{
110 public:
112 friend void
114 {
115 using std::swap;
116 swap( left.m_file_descriptor, right.m_file_descriptor );
117 }
118
122 {}
123
131
133 : m_file_descriptor{ fdh.m_file_descriptor }
134 {
135 fdh.release();
136 }
137
139 {
140 if( this != &fdh )
141 {
142 file_descriptor_holder_t tmp{ std::move( fdh ) };
143 swap( *this, tmp );
144 }
145 return *this;
146 }
147
149 {
150 if( is_valid() )
152 }
153
155 bool is_valid() const noexcept
156 {
158 }
159
160 //Get file descriptor.
162 {
163 return m_file_descriptor;
164 }
165
166 // Release stored descriptor.
167 void release() noexcept
168 {
170 }
171
172 private:
175};
176
177//
178// file_meta_t
179//
180
183{
184 public:
185 friend void
186 swap( file_meta_t & r, file_meta_t & l ) noexcept
187 {
188 std::swap( r.m_file_total_size, l.m_file_total_size );
189 std::swap( r.m_last_modified_at, l.m_last_modified_at );
190 }
191
192 file_meta_t() noexcept
193 {}
194
197 std::chrono::system_clock::time_point last_modified_at ) noexcept
200 {}
201
203
204 auto last_modified_at() const noexcept { return m_last_modified_at; }
205
206 private:
209
211 std::chrono::system_clock::time_point m_last_modified_at{};
212};
213
214//
215// sendfile_t
216//
217
219
226{
227 friend sendfile_t sendfile(
230 file_size_t ) noexcept;
231
239 : m_file_descriptor{ std::move( fdh ) }
240 , m_meta{ meta }
241 , m_offset{ 0 }
243 , m_chunk_size{ chunk.value() }
244 , m_timelimit{ std::chrono::steady_clock::duration::zero() }
245 {}
246
247 public:
248 friend void
249 swap( sendfile_t & left, sendfile_t & right ) noexcept
250 {
251 using std::swap;
252 swap( left.m_file_descriptor, right.m_file_descriptor );
253 swap( left.m_meta, right.m_meta );
254 swap( left.m_offset, right.m_offset );
255 swap( left.m_size, right.m_size );
256 swap( left.m_chunk_size, right.m_chunk_size );
257 swap( left.m_timelimit, right.m_timelimit );
258 }
259
264 sendfile_t( const sendfile_t & ) = delete;
265 sendfile_t & operator = ( const sendfile_t & ) = delete;
267
272 sendfile_t( sendfile_t && sf ) noexcept
273 : m_file_descriptor{ std::move( sf.m_file_descriptor ) }
274 , m_meta{ sf.m_meta }
275 , m_offset{ sf.m_offset }
276 , m_size{ sf.m_size }
277 , m_chunk_size{ sf.m_chunk_size }
278 , m_timelimit{ sf.m_timelimit }
279 {}
280
282 {
283 if( this != &sf )
284 {
285 sendfile_t tmp{ std::move( sf ) };
286 swap( *this, tmp );
287 }
288
289 return *this;
290 }
292
294 bool is_valid() const noexcept { return m_file_descriptor.is_valid(); }
295
297 const file_meta_t & meta() const
298 {
299 return m_meta;
300 }
301
303 auto offset() const noexcept { return m_offset; }
304
306 auto size() const noexcept { return m_size; }
307
318 sendfile_t &
320 file_offset_t offset_value,
321 file_size_t size_value = std::numeric_limits< file_size_t >::max() ) &
322 {
324
325 if( static_cast< file_size_t >( offset_value ) > m_meta.file_total_size() )
326 {
327 throw exception_t{
328 fmt::format(
330 "invalid file offset: {}, while file size is {}" ),
331 offset_value,
333 }
334
335 m_offset = offset_value;
336 m_size =
337 std::min< file_size_t >(
338 m_meta.file_total_size() - static_cast< file_size_t >( offset_value ),
339 size_value );
340
341 return *this;
342 }
343
344 sendfile_t &&
346 file_offset_t offset_value,
347 file_size_t size_value = std::numeric_limits< file_size_t >::max() ) &&
348 {
349 return std::move( this->offset_and_size( offset_value, size_value ) );
350 }
352
353 auto chunk_size() const noexcept { return m_chunk_size; }
354
360 sendfile_t &
362 {
364
365 m_chunk_size = chunk.value();
366 return *this;
367 }
368
370 sendfile_t &&
372 {
373 return std::move( this->chunk_size( chunk ) );
374 }
376
377 auto timelimit() const noexcept { return m_timelimit; }
378
384 sendfile_t &
385 timelimit( std::chrono::steady_clock::duration timelimit_value ) &
386 {
388
389 m_timelimit = std::max( timelimit_value, std::chrono::steady_clock::duration::zero() );
390 return *this;
391 }
392
393 sendfile_t &&
394 timelimit( std::chrono::steady_clock::duration timelimit_value ) &&
395 {
396 return std::move( this->timelimit( timelimit_value ) );
397 }
399
403 {
404 return m_file_descriptor.fd();
405 }
406
408
422 {
423 return std::move(target.m_file_descriptor);
424 }
425
426 private:
428 void
430 {
431 if( !is_valid() )
432 {
433 throw exception_t{ "invalid file descriptor" };
434 }
435 }
436
439
442
447
450
452
455 std::chrono::steady_clock::duration m_timelimit{ std::chrono::steady_clock::duration::zero() };
456};
457
458//
459// sendfile()
460//
461
468inline sendfile_t
475 file_size_t chunk_size = sendfile_default_chunk_size ) noexcept
476{
477 return sendfile_t{ std::move( fd ), meta, chunk_size };
478}
479
480inline sendfile_t
483 const char * file_path,
486{
487 file_descriptor_holder_t fd{ open_file( file_path ) };
488
489 auto meta = get_file_meta< file_meta_t >( fd.fd() );
490
491 return sendfile( std::move( fd ), meta, chunk_size );
492}
493
494inline sendfile_t
497 const std::string & file_path,
500{
501 return sendfile( file_path.c_str(), chunk_size );
502}
503
504inline sendfile_t
507 string_view_t file_path,
510{
511 return
512 sendfile(
513 std::string{ file_path.data(), file_path.size() },
514 chunk_size );
515}
517
518} /* namespace restinio */
Exception class for all exceptions thrown by RESTinio.
Definition: exception.hpp:26
Wrapper class for working with native file handler.
Definition: sendfile.hpp:109
file_descriptor_holder_t & operator=(const file_descriptor_holder_t &)=delete
file_descriptor_holder_t(file_descriptor_holder_t &&fdh) noexcept
Definition: sendfile.hpp:132
friend void swap(file_descriptor_holder_t &left, file_descriptor_holder_t &right) noexcept
Swap two descriptors.
Definition: sendfile.hpp:113
file_descriptor_t m_file_descriptor
Target file descriptor.
Definition: sendfile.hpp:174
bool is_valid() const noexcept
Check if file descriptor is valid.
Definition: sendfile.hpp:155
file_descriptor_holder_t(const file_descriptor_holder_t &)=delete
file_descriptor_t fd() const noexcept
Definition: sendfile.hpp:161
file_descriptor_holder_t(file_descriptor_t fd) noexcept
Init constructor.
Definition: sendfile.hpp:120
Meta data of the file.
Definition: sendfile.hpp:183
std::chrono::system_clock::time_point m_last_modified_at
Last modification date.
Definition: sendfile.hpp:211
file_meta_t(file_size_t file_total_size, std::chrono::system_clock::time_point last_modified_at) noexcept
Definition: sendfile.hpp:195
auto last_modified_at() const noexcept
Definition: sendfile.hpp:204
file_size_t file_total_size() const noexcept
Definition: sendfile.hpp:202
friend void swap(file_meta_t &r, file_meta_t &l) noexcept
Definition: sendfile.hpp:186
file_size_t m_file_total_size
Total file size.
Definition: sendfile.hpp:208
file_meta_t() noexcept
Definition: sendfile.hpp:192
A guard class for setting chunk size.
Definition: sendfile.hpp:65
static constexpr file_size_t clarify_chunk_size(file_size_t chunk_size_value) noexcept
Checks chunk_size_value and returns a value in [1, sendfile_max_chunk_size].
Definition: sendfile.hpp:73
constexpr sendfile_chunk_size_guarded_value_t(file_size_t chunk_size_value) noexcept
Definition: sendfile.hpp:86
constexpr auto value() const noexcept
Get the valid value of a chunk size.
Definition: sendfile.hpp:91
const file_size_t m_chunk_size
Valid value of the chunk size.
Definition: sendfile.hpp:95
Send file write operation description.
Definition: sendfile.hpp:226
friend file_descriptor_holder_t takeaway_file_descriptor(sendfile_t &target)
Take away the file description form sendfile object.
Definition: sendfile.hpp:421
sendfile_t && chunk_size(sendfile_chunk_size_guarded_value_t chunk) &&
Set prefered chunk size to use in write operation.
Definition: sendfile.hpp:371
void check_file_is_valid() const
Check if stored file descriptor is valid, and throws if it is not.
Definition: sendfile.hpp:429
file_meta_t m_meta
File meta data.
Definition: sendfile.hpp:441
file_descriptor_holder_t m_file_descriptor
Native file descriptor.
Definition: sendfile.hpp:438
sendfile_t & offset_and_size(file_offset_t offset_value, file_size_t size_value=std::numeric_limits< file_size_t >::max()) &
Definition: sendfile.hpp:319
sendfile_t & timelimit(std::chrono::steady_clock::duration timelimit_value) &
Definition: sendfile.hpp:385
file_descriptor_t file_descriptor() const noexcept
Get the file descriptor of a given sendfile operation.
Definition: sendfile.hpp:402
sendfile_t && timelimit(std::chrono::steady_clock::duration timelimit_value) &&
Definition: sendfile.hpp:394
sendfile_t & chunk_size(sendfile_chunk_size_guarded_value_t chunk) &
Definition: sendfile.hpp:361
file_size_t m_chunk_size
A prefered chunk size for a single write call.
Definition: sendfile.hpp:449
auto size() const noexcept
Get size of data to write.
Definition: sendfile.hpp:306
friend void swap(sendfile_t &left, sendfile_t &right) noexcept
Definition: sendfile.hpp:249
auto chunk_size() const noexcept
Definition: sendfile.hpp:353
sendfile_t && offset_and_size(file_offset_t offset_value, file_size_t size_value=std::numeric_limits< file_size_t >::max()) &&
Definition: sendfile.hpp:345
auto timelimit() const noexcept
Definition: sendfile.hpp:377
sendfile_t(file_descriptor_holder_t fdh, file_meta_t meta, sendfile_chunk_size_guarded_value_t chunk) noexcept
Definition: sendfile.hpp:232
bool is_valid() const noexcept
Check if file is valid.
Definition: sendfile.hpp:294
sendfile_t(const sendfile_t &)=delete
sendfile_t & operator=(const sendfile_t &)=delete
sendfile_t(sendfile_t &&sf) noexcept
Definition: sendfile.hpp:272
file_offset_t m_offset
Data offset within the file.
Definition: sendfile.hpp:444
const file_meta_t & meta() const
Get file meta data.
Definition: sendfile.hpp:297
auto offset() const noexcept
Get offset of data to write.
Definition: sendfile.hpp:303
friend sendfile_t sendfile(file_descriptor_holder_t, file_meta_t, file_size_t) noexcept
Definition: sendfile.hpp:469
std::chrono::steady_clock::duration m_timelimit
Timelimit for writing all the given data.
Definition: sendfile.hpp:455
file_size_t m_size
The size of data portion in file.
Definition: sendfile.hpp:446
A special wrapper around fmtlib include files.
#define RESTINIO_FMT_FORMAT_STRING(s)
constexpr file_size_t sendfile_max_chunk_size
Maximum size of a chunk.
Definition: sendfile.hpp:51
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
constexpr file_descriptor_t null_file_descriptor()
Get file descriptor which stands for null.
std::uint64_t file_size_t
nonstd::string_view string_view_t
Definition: string_view.hpp:19
void close_file(file_descriptor_t fd)
Close file by its descriptor.
std::int64_t file_offset_t
std::FILE * file_descriptor_t
file_descriptor_t open_file(const char *file_path)
Open file.
constexpr file_size_t sendfile_default_chunk_size
Default chunk size for sendfile operation.
Definition: sendfile.hpp:47
#define const
Definition: zconf.h:230