RESTinio
Loading...
Searching...
No Matches
sendfile.hpp
Go to the documentation of this file.
1/*
2 restinio
3*/
4
11#pragma once
12
14
18
20
21#include <array>
22#include <chrono>
23#include <filesystem>
24#include <string>
25
26/*
27 Defenitions for:
28 file_descriptor_t
29 file_offset_t
30 file_size_t
31*/
32
33#if defined(RESTINIO_OS_WINDOWS)
34 #include "sendfile_defs_win.hpp"
35#elif defined(RESTINIO_OS_UNIX) || defined(RESTINIO_OS_APPLE)
37#else
38 #if defined (RESTINIO_ENABLE_SENDFILE_DEFAULT_IMPL)
40 #else
41 #error "Sendfile not supported, to enable default implementation define RESTINIO_ENABLE_SENDFILE_DEFAULT_IMPL macro"
42 #endif
43#endif
44
45namespace restinio
46{
47
51
54constexpr file_size_t sendfile_max_chunk_size = 1024 * 1024 * 1024;
55
56//
57// sendfile_chunk_size_guarded_value_t
58//
59
61
68{
70 /*
71 - If chunk_size_value is zero returns 1.
72 - If chunk_size_value is greater than sendfile_max_chunk_size returns sendfile_max_chunk_size.
73 - Otherwise returns chunk_size_value itself.
74 */
75 static constexpr file_size_t
86
87 public:
88
92
94 [[nodiscard]]
95 constexpr auto value() const noexcept { return m_chunk_size; }
96
97 private:
100};
101
102//
103// file_descriptor_holder_t
104//
105
107/*
108 Class is responsible for managing file descriptor as resource.
109
110 @since v.0.4.3
111*/
113{
114 public:
116 friend void
118 {
119 using std::swap;
120 swap( left.m_file_descriptor, right.m_file_descriptor );
121 }
122
127
135
137 : m_file_descriptor{ fdh.m_file_descriptor }
138 {
139 fdh.release();
140 }
141
143 {
144 file_descriptor_holder_t tmp{ std::move( fdh ) };
145 swap( *this, tmp );
146
147 return *this;
148 }
149
155
157 [[nodiscard]]
159 {
161 }
162
163 //Get file descriptor.
164 [[nodiscard]]
169
170 // Release stored descriptor.
175
176 private:
179};
180
181//
182// file_meta_t
183//
184
187{
188 public:
189 friend void
190 swap( file_meta_t & r, file_meta_t & l ) noexcept
191 {
192 std::swap( r.m_file_total_size, l.m_file_total_size );
193 std::swap( r.m_last_modified_at, l.m_last_modified_at );
194 }
195
198
205
206 [[nodiscard]]
208
209 [[nodiscard]]
211
212 private:
215
217 std::chrono::system_clock::time_point m_last_modified_at{};
218};
219
220//
221// sendfile_t
222//
223
225
232{
233 friend sendfile_t sendfile(
236 file_size_t ) noexcept;
237
245 : m_file_descriptor{ std::move( fdh ) }
246 , m_meta{ meta }
247 , m_offset{ 0 }
249 , m_chunk_size{ chunk.value() }
250 , m_timelimit{ std::chrono::steady_clock::duration::zero() }
251 {}
252
253 public:
254 friend void
256 {
257 using std::swap;
258 swap( left.m_file_descriptor, right.m_file_descriptor );
259 swap( left.m_meta, right.m_meta );
260 swap( left.m_offset, right.m_offset );
261 swap( left.m_size, right.m_size );
262 swap( left.m_chunk_size, right.m_chunk_size );
263 swap( left.m_timelimit, right.m_timelimit );
264 }
265
270 sendfile_t( const sendfile_t & ) = delete;
271 sendfile_t & operator = ( const sendfile_t & ) = delete;
273
279 : m_file_descriptor{ std::move( sf.m_file_descriptor ) }
280 , m_meta{ sf.m_meta }
281 , m_offset{ sf.m_offset }
282 , m_size{ sf.m_size }
283 , m_chunk_size{ sf.m_chunk_size }
284 , m_timelimit{ sf.m_timelimit }
285 {}
286
288 {
289 sendfile_t tmp{ std::move( sf ) };
290 swap( *this, tmp );
291
292 return *this;
293 }
295
297 [[nodiscard]]
299
301 [[nodiscard]]
302 const file_meta_t & meta() const
303 {
304 return m_meta;
305 }
306
308 [[nodiscard]]
309 auto offset() const noexcept { return m_offset; }
310
312 [[nodiscard]]
313 auto size() const noexcept { return m_size; }
314
325 sendfile_t &
328 file_size_t size_value = std::numeric_limits< file_size_t >::max() ) &
329 {
331
332 if( static_cast< file_size_t >( offset_value ) > m_meta.file_total_size() )
333 {
334 throw exception_t{
335 fmt::format(
337 "invalid file offset: {}, while file size is {}" ),
340 }
341
343 m_size =
344 std::min< file_size_t >(
345 m_meta.file_total_size() - static_cast< file_size_t >( offset_value ),
346 size_value );
347
348 return *this;
349 }
350
351 sendfile_t &&
354 file_size_t size_value = std::numeric_limits< file_size_t >::max() ) &&
355 {
356 return std::move( this->offset_and_size( offset_value, size_value ) );
357 }
359
360 [[nodiscard]]
362
368 sendfile_t &
370 {
372
373 m_chunk_size = chunk.value();
374 return *this;
375 }
376
378 sendfile_t &&
380 {
381 return std::move( this->chunk_size( chunk ) );
382 }
384
385 [[nodiscard]]
387
393 sendfile_t &
394 timelimit( std::chrono::steady_clock::duration timelimit_value ) &
395 {
397
398 m_timelimit = std::max( timelimit_value, std::chrono::steady_clock::duration::zero() );
399 return *this;
400 }
401
402 sendfile_t &&
403 timelimit( std::chrono::steady_clock::duration timelimit_value ) &&
404 {
405 return std::move( this->timelimit( timelimit_value ) );
406 }
408
410 [[nodiscard]]
413 {
414 return m_file_descriptor.fd();
415 }
416
418
430 [[nodiscard]]
433 {
434 return std::move(target.m_file_descriptor);
435 }
436
437 private:
439 void
441 {
442 if( !is_valid() )
443 {
444 throw exception_t{ "invalid file descriptor" };
445 }
446 }
447
450
453
458
461
463
466 std::chrono::steady_clock::duration m_timelimit{ std::chrono::steady_clock::duration::zero() };
467};
468
469//
470// sendfile()
471//
472
479[[nodiscard]]
480inline sendfile_t
487 file_size_t chunk_size = sendfile_default_chunk_size ) noexcept
488{
489 return sendfile_t{ std::move( fd ), meta, chunk_size };
490}
491
492[[nodiscard]]
493inline sendfile_t
496 const char * file_path,
499{
501
502 auto meta = get_file_meta< file_meta_t >( fd.fd() );
503
504 return sendfile( std::move( fd ), meta, chunk_size );
505}
506
507[[nodiscard]]
508inline sendfile_t
511 const std::string & file_path,
514{
515 return sendfile( file_path.c_str(), chunk_size );
516}
517
518[[nodiscard]]
519inline sendfile_t
525{
526 return
527 sendfile(
528 std::string{ file_path.data(), file_path.size() },
529 chunk_size );
530}
531
532//FIXME: document this!
536[[nodiscard]]
537inline sendfile_t
540 const std::filesystem::path & file_path,
543{
545
546 auto meta = get_file_meta< file_meta_t >( fd.fd() );
547
548 return sendfile( std::move( fd ), meta, chunk_size );
549}
551
552} /* namespace restinio */
553
Exception class for all exceptions thrown by RESTinio.
Definition exception.hpp:26
Wrapper class for working with native file handler.
Definition sendfile.hpp:113
file_descriptor_holder_t & operator=(const file_descriptor_holder_t &)=delete
file_descriptor_holder_t(file_descriptor_holder_t &&fdh) noexcept
Definition sendfile.hpp:136
friend void swap(file_descriptor_holder_t &left, file_descriptor_holder_t &right) noexcept
Swap two descriptors.
Definition sendfile.hpp:117
file_descriptor_t m_file_descriptor
Target file descriptor.
Definition sendfile.hpp:178
bool is_valid() const noexcept
Check if file descriptor is valid.
Definition sendfile.hpp:158
file_descriptor_holder_t(const file_descriptor_holder_t &)=delete
file_descriptor_t fd() const noexcept
Definition sendfile.hpp:165
file_descriptor_holder_t(file_descriptor_t fd) noexcept
Init constructor.
Definition sendfile.hpp:124
Meta data of the file.
Definition sendfile.hpp:187
std::chrono::system_clock::time_point m_last_modified_at
Last modification date.
Definition sendfile.hpp:217
file_meta_t(file_size_t file_total_size, std::chrono::system_clock::time_point last_modified_at) noexcept
Definition sendfile.hpp:199
auto last_modified_at() const noexcept
Definition sendfile.hpp:210
file_size_t file_total_size() const noexcept
Definition sendfile.hpp:207
friend void swap(file_meta_t &r, file_meta_t &l) noexcept
Definition sendfile.hpp:190
file_size_t m_file_total_size
Total file size.
Definition sendfile.hpp:214
A guard class for setting chunk size.
Definition sendfile.hpp:68
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:76
constexpr sendfile_chunk_size_guarded_value_t(file_size_t chunk_size_value) noexcept
Definition sendfile.hpp:89
constexpr auto value() const noexcept
Get the valid value of a chunk size.
Definition sendfile.hpp:95
const file_size_t m_chunk_size
Valid value of the chunk size.
Definition sendfile.hpp:99
Send file write operation description.
Definition sendfile.hpp:232
friend file_descriptor_holder_t takeaway_file_descriptor(sendfile_t &target)
Take away the file description form sendfile object.
Definition sendfile.hpp:432
sendfile_t && chunk_size(sendfile_chunk_size_guarded_value_t chunk) &&
Set prefered chunk size to use in write operation.
Definition sendfile.hpp:379
void check_file_is_valid() const
Check if stored file descriptor is valid, and throws if it is not.
Definition sendfile.hpp:440
file_meta_t m_meta
File meta data.
Definition sendfile.hpp:452
file_descriptor_holder_t m_file_descriptor
Native file descriptor.
Definition sendfile.hpp:449
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:326
sendfile_t & timelimit(std::chrono::steady_clock::duration timelimit_value) &
Definition sendfile.hpp:394
file_descriptor_t file_descriptor() const noexcept
Get the file descriptor of a given sendfile operation.
Definition sendfile.hpp:412
sendfile_t && timelimit(std::chrono::steady_clock::duration timelimit_value) &&
Definition sendfile.hpp:403
sendfile_t & chunk_size(sendfile_chunk_size_guarded_value_t chunk) &
Definition sendfile.hpp:369
file_size_t m_chunk_size
A prefered chunk size for a single write call.
Definition sendfile.hpp:460
auto size() const noexcept
Get size of data to write.
Definition sendfile.hpp:313
friend void swap(sendfile_t &left, sendfile_t &right) noexcept
Definition sendfile.hpp:255
auto chunk_size() const noexcept
Definition sendfile.hpp:361
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:352
auto timelimit() const noexcept
Definition sendfile.hpp:386
sendfile_t(file_descriptor_holder_t fdh, file_meta_t meta, sendfile_chunk_size_guarded_value_t chunk) noexcept
Definition sendfile.hpp:238
bool is_valid() const noexcept
Check if file is valid.
Definition sendfile.hpp:298
sendfile_t(const sendfile_t &)=delete
sendfile_t & operator=(const sendfile_t &)=delete
sendfile_t(sendfile_t &&sf) noexcept
Definition sendfile.hpp:278
file_offset_t m_offset
Data offset within the file.
Definition sendfile.hpp:455
const file_meta_t & meta() const
Get file meta data.
Definition sendfile.hpp:302
auto offset() const noexcept
Get offset of data to write.
Definition sendfile.hpp:309
friend sendfile_t sendfile(file_descriptor_holder_t, file_meta_t, file_size_t) noexcept
Definition sendfile.hpp:481
std::chrono::steady_clock::duration m_timelimit
Timelimit for writing all the given data.
Definition sendfile.hpp:466
file_size_t m_size
The size of data portion in file.
Definition sendfile.hpp:457
Helper macros for detection of compiler/platform.
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:54
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:481
constexpr file_descriptor_t null_file_descriptor()
Get file descriptor which stands for null.
run_on_this_thread_settings_t< Traits > on_this_thread()
A special marker for the case when http_server must be run on the context of the current thread.
std::string_view string_view_t
void close_file(file_descriptor_t fd)
Close file by its descriptor.
file_descriptor_t open_file(const char *file_path)
Open file.
std::FILE * file_descriptor_t
constexpr file_size_t sendfile_default_chunk_size
Default chunk size for sendfile operation.
Definition sendfile.hpp:50
std::int64_t file_offset_t
std::uint64_t file_size_t