1 | #pragma once |
2 | |
3 | #if defined(__linux__) || defined(__FreeBSD__) |
4 | |
5 | #include <IO/ReadBufferFromFileBase.h> |
6 | #include <IO/ReadBuffer.h> |
7 | #include <IO/BufferWithOwnMemory.h> |
8 | #include <IO/AIO.h> |
9 | #include <Core/Defines.h> |
10 | #include <Common/CurrentMetrics.h> |
11 | #include <string> |
12 | #include <limits> |
13 | #include <future> |
14 | #include <unistd.h> |
15 | #include <fcntl.h> |
16 | |
17 | |
18 | namespace CurrentMetrics |
19 | { |
20 | extern const Metric OpenFileForRead; |
21 | } |
22 | |
23 | namespace DB |
24 | { |
25 | |
26 | /** Class for asynchronous data reading. |
27 | */ |
28 | class ReadBufferAIO : public ReadBufferFromFileBase |
29 | { |
30 | public: |
31 | ReadBufferAIO(const std::string & filename_, size_t buffer_size_ = DBMS_DEFAULT_BUFFER_SIZE, int flags_ = -1, |
32 | char * existing_memory_ = nullptr); |
33 | ~ReadBufferAIO() override; |
34 | |
35 | ReadBufferAIO(const ReadBufferAIO &) = delete; |
36 | ReadBufferAIO & operator=(const ReadBufferAIO &) = delete; |
37 | |
38 | void setMaxBytes(size_t max_bytes_read_); |
39 | off_t getPositionInFile() override { return first_unread_pos_in_file - (working_buffer.end() - pos); } |
40 | std::string getFileName() const override { return filename; } |
41 | int getFD() const override { return fd; } |
42 | |
43 | private: |
44 | /// |
45 | bool nextImpl() override; |
46 | /// |
47 | off_t doSeek(off_t off, int whence) override; |
48 | /// Synchronously read the data. |
49 | void synchronousRead(); |
50 | /// Get data from an asynchronous request. |
51 | void receive(); |
52 | /// Ignore data from an asynchronous request. |
53 | void skip(); |
54 | /// Wait for the end of the current asynchronous task. |
55 | bool waitForAIOCompletion(); |
56 | /// Prepare the request. |
57 | void prepare(); |
58 | /// Prepare for reading a duplicate buffer containing data from |
59 | /// of the last request. |
60 | void finalize(); |
61 | |
62 | private: |
63 | /// Buffer for asynchronous data read operations. |
64 | BufferWithOwnMemory<ReadBuffer> fill_buffer; |
65 | |
66 | /// Description of the asynchronous read request. |
67 | iocb request{}; |
68 | std::future<ssize_t> future_bytes_read; |
69 | |
70 | const std::string filename; |
71 | |
72 | /// The maximum number of bytes that can be read. |
73 | size_t max_bytes_read = std::numeric_limits<size_t>::max(); |
74 | /// Number of bytes requested. |
75 | size_t requested_byte_count = 0; |
76 | /// The number of bytes read at the last request. |
77 | ssize_t bytes_read = 0; |
78 | /// The total number of bytes read. |
79 | size_t total_bytes_read = 0; |
80 | |
81 | /// The position of the first unread byte in the file. |
82 | off_t first_unread_pos_in_file = 0; |
83 | |
84 | /// The starting position of the aligned region of the disk from which the data is read. |
85 | off_t region_aligned_begin = 0; |
86 | /// Left offset to align the region of the disk. |
87 | size_t region_left_padding = 0; |
88 | /// The size of the aligned region of the disk. |
89 | size_t region_aligned_size = 0; |
90 | |
91 | /// The file descriptor for read. |
92 | int fd = -1; |
93 | |
94 | /// The buffer to which the received data is written. |
95 | Position buffer_begin = nullptr; |
96 | |
97 | /// The asynchronous read operation is not yet completed. |
98 | bool is_pending_read = false; |
99 | /// The end of the file is reached. |
100 | bool is_eof = false; |
101 | /// At least one read request was sent. |
102 | bool is_started = false; |
103 | /// Is the operation asynchronous? |
104 | bool is_aio = false; |
105 | /// Did the asynchronous operation fail? |
106 | bool aio_failed = false; |
107 | |
108 | CurrentMetrics::Increment metric_increment{CurrentMetrics::OpenFileForRead}; |
109 | }; |
110 | |
111 | } |
112 | |
113 | #endif |
114 | |