]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | /* |
2 | * This file is open source software, licensed to you under the terms | |
3 | * of the Apache License, Version 2.0 (the "License"). See the NOTICE file | |
4 | * distributed with this work for additional information regarding copyright | |
5 | * ownership. You may not use this file except in compliance with the License. | |
6 | * | |
7 | * You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, | |
12 | * software distributed under the License is distributed on an | |
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
14 | * KIND, either express or implied. See the License for the | |
15 | * specific language governing permissions and limitations | |
16 | * under the License. | |
17 | */ | |
18 | /* | |
19 | * Copyright 2020 ScyllaDB | |
20 | */ | |
21 | ||
22 | #pragma once | |
23 | ||
24 | #include <seastar/core/sstring.hh> | |
25 | #include <seastar/core/linux-aio.hh> | |
26 | #include <seastar/core/internal/io_desc.hh> | |
20effc67 | 27 | #include <seastar/core/on_internal_error.hh> |
9f95a23c TL |
28 | #include <sys/types.h> |
29 | #include <sys/socket.h> | |
30 | ||
31 | namespace seastar { | |
20effc67 TL |
32 | extern logger io_log; |
33 | ||
9f95a23c TL |
34 | namespace internal { |
35 | ||
36 | class io_request { | |
37 | public: | |
38 | enum class operation { read, readv, write, writev, fdatasync, recv, recvmsg, send, sendmsg, accept, connect, poll_add, poll_remove, cancel }; | |
39 | private: | |
40 | operation _op; | |
41 | int _fd; | |
42 | union { | |
43 | uint64_t pos; | |
44 | int flags; | |
45 | int events; | |
46 | } _attr; | |
47 | // the upper layers give us void pointers, but storing void pointers here is just | |
48 | // dangerous. The constructors seem to be happy to convert other pointers to void*, | |
49 | // even if they are marked as explicit, and then you end up losing approximately 3 hours | |
50 | // and 15 minutes (hypothetically, of course), trying to chase the weirdest bug. | |
51 | // Let's store a char* for safety, and cast it back to void* in the accessor. | |
52 | union { | |
53 | char* addr; | |
54 | ::iovec* iovec; | |
55 | ::msghdr* msghdr; | |
56 | ::sockaddr* sockaddr; | |
57 | } _ptr; | |
58 | ||
59 | // accept wants a socklen_t*, connect wants a socklen_t | |
60 | union { | |
61 | size_t len; | |
62 | socklen_t* socklen_ptr; | |
63 | socklen_t socklen; | |
64 | } _size; | |
20effc67 TL |
65 | |
66 | bool _nowait_works; | |
9f95a23c TL |
67 | |
68 | explicit io_request(operation op, int fd, int flags, ::msghdr* msg) | |
69 | : _op(op) | |
70 | , _fd(fd) | |
71 | { | |
72 | _attr.flags = flags; | |
73 | _ptr.msghdr = msg; | |
74 | } | |
75 | ||
76 | explicit io_request(operation op, int fd, sockaddr* sa, socklen_t sl) | |
77 | : _op(op) | |
78 | , _fd(fd) | |
79 | { | |
80 | _ptr.sockaddr = sa; | |
81 | _size.socklen = sl; | |
82 | } | |
83 | ||
84 | explicit io_request(operation op, int fd, int flags, sockaddr* sa, socklen_t* sl) | |
85 | : _op(op) | |
86 | , _fd(fd) | |
87 | { | |
88 | _attr.flags = flags; | |
89 | _ptr.sockaddr = sa; | |
90 | _size.socklen_ptr = sl; | |
91 | } | |
92 | explicit io_request(operation op, int fd, uint64_t pos, char* ptr, size_t size) | |
93 | : _op(op) | |
94 | , _fd(fd) | |
95 | { | |
96 | _attr.pos = pos; | |
97 | _ptr.addr = ptr; | |
98 | _size.len = size; | |
99 | } | |
100 | ||
20effc67 TL |
101 | explicit io_request(operation op, int fd, uint64_t pos, char* ptr, size_t size, bool nowait_works) |
102 | : _op(op) | |
103 | , _fd(fd) | |
104 | , _nowait_works(nowait_works) | |
105 | { | |
106 | _attr.pos = pos; | |
107 | _ptr.addr = ptr; | |
108 | _size.len = size; | |
109 | } | |
110 | ||
111 | explicit io_request(operation op, int fd, uint64_t pos, iovec* ptr, size_t size, bool nowait_works) | |
9f95a23c TL |
112 | : _op(op) |
113 | , _fd(fd) | |
20effc67 | 114 | , _nowait_works(nowait_works) |
9f95a23c TL |
115 | { |
116 | _attr.pos = pos; | |
117 | _ptr.iovec = ptr; | |
118 | _size.len = size; | |
119 | } | |
120 | ||
121 | explicit io_request(operation op, int fd) | |
122 | : _op(op) | |
123 | , _fd(fd) | |
124 | {} | |
125 | explicit io_request(operation op, int fd, int events) | |
126 | : _op(op) | |
127 | , _fd(fd) | |
128 | { | |
129 | _attr.events = events; | |
130 | } | |
131 | ||
132 | explicit io_request(operation op, int fd, char *ptr) | |
133 | : _op(op) | |
134 | , _fd(fd) | |
135 | { | |
136 | _ptr.addr = ptr; | |
137 | } | |
138 | public: | |
139 | bool is_read() const { | |
140 | switch (_op) { | |
141 | case operation::read: | |
142 | case operation::readv: | |
143 | case operation::recvmsg: | |
144 | case operation::recv: | |
145 | return true; | |
146 | default: | |
147 | return false; | |
148 | } | |
149 | } | |
150 | ||
151 | bool is_write() const { | |
152 | switch (_op) { | |
153 | case operation::write: | |
154 | case operation::writev: | |
155 | case operation::send: | |
156 | case operation::sendmsg: | |
157 | return true; | |
158 | default: | |
159 | return false; | |
160 | } | |
161 | } | |
162 | ||
163 | sstring opname() const; | |
164 | ||
165 | operation opcode() const { | |
166 | return _op; | |
167 | } | |
168 | ||
169 | int fd() const { | |
170 | return _fd; | |
171 | } | |
172 | ||
173 | uint64_t pos() const { | |
174 | return _attr.pos; | |
175 | } | |
176 | ||
177 | int flags() const { | |
178 | return _attr.flags; | |
179 | } | |
180 | ||
181 | int events() const { | |
182 | return _attr.events; | |
183 | } | |
184 | ||
185 | void* address() const { | |
186 | return reinterpret_cast<void*>(_ptr.addr); | |
187 | } | |
188 | ||
189 | iovec* iov() const { | |
190 | return _ptr.iovec; | |
191 | } | |
192 | ||
193 | ::sockaddr* posix_sockaddr() const { | |
194 | return _ptr.sockaddr; | |
195 | } | |
196 | ||
197 | ::msghdr* msghdr() const { | |
198 | return _ptr.msghdr; | |
199 | } | |
200 | ||
201 | size_t size() const { | |
202 | return _size.len; | |
203 | } | |
204 | ||
205 | size_t iov_len() const { | |
206 | return _size.len; | |
207 | } | |
208 | ||
209 | socklen_t socklen() const { | |
210 | return _size.socklen; | |
211 | } | |
212 | ||
213 | socklen_t* socklen_ptr() const { | |
214 | return _size.socklen_ptr; | |
215 | } | |
216 | ||
20effc67 TL |
217 | bool nowait_works() const { |
218 | return _nowait_works; | |
9f95a23c TL |
219 | } |
220 | ||
20effc67 TL |
221 | static io_request make_read(int fd, uint64_t pos, void* address, size_t size, bool nowait_works) { |
222 | return io_request(operation::read, fd, pos, reinterpret_cast<char*>(address), size, nowait_works); | |
9f95a23c TL |
223 | } |
224 | ||
20effc67 TL |
225 | static io_request make_readv(int fd, uint64_t pos, std::vector<iovec>& iov, bool nowait_works) { |
226 | return io_request(operation::readv, fd, pos, iov.data(), iov.size(), nowait_works); | |
9f95a23c TL |
227 | } |
228 | ||
229 | static io_request make_recv(int fd, void* address, size_t size, int flags) { | |
230 | return io_request(operation::recv, fd, flags, reinterpret_cast<char*>(address), size); | |
231 | } | |
232 | ||
233 | static io_request make_recvmsg(int fd, ::msghdr* msg, int flags) { | |
234 | return io_request(operation::recvmsg, fd, flags, msg); | |
235 | } | |
236 | ||
237 | static io_request make_send(int fd, const void* address, size_t size, int flags) { | |
238 | return io_request(operation::send, fd, flags, const_cast<char*>(reinterpret_cast<const char*>(address)), size); | |
239 | } | |
240 | ||
241 | static io_request make_sendmsg(int fd, ::msghdr* msg, int flags) { | |
242 | return io_request(operation::sendmsg, fd, flags, msg); | |
243 | } | |
244 | ||
20effc67 TL |
245 | static io_request make_write(int fd, uint64_t pos, const void* address, size_t size, bool nowait_works) { |
246 | return io_request(operation::write, fd, pos, const_cast<char*>(reinterpret_cast<const char*>(address)), size, nowait_works); | |
9f95a23c TL |
247 | } |
248 | ||
20effc67 TL |
249 | static io_request make_writev(int fd, uint64_t pos, std::vector<iovec>& iov, bool nowait_works) { |
250 | return io_request(operation::writev, fd, pos, iov.data(), iov.size(), nowait_works); | |
9f95a23c TL |
251 | } |
252 | ||
253 | static io_request make_fdatasync(int fd) { | |
254 | return io_request(operation::fdatasync, fd); | |
255 | } | |
256 | ||
257 | static io_request make_accept(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) { | |
258 | return io_request(operation::accept, fd, flags, addr, addrlen); | |
259 | } | |
260 | ||
261 | static io_request make_connect(int fd, struct sockaddr* addr, socklen_t addrlen) { | |
262 | return io_request(operation::connect, fd, addr, addrlen); | |
263 | } | |
264 | ||
265 | static io_request make_poll_add(int fd, int events) { | |
266 | return io_request(operation::poll_add, fd, events); | |
267 | } | |
268 | ||
269 | static io_request make_poll_remove(int fd, void *addr) { | |
270 | return io_request(operation::poll_remove, fd, reinterpret_cast<char*>(addr)); | |
271 | } | |
272 | static io_request make_cancel(int fd, void *addr) { | |
273 | return io_request(operation::cancel, fd, reinterpret_cast<char*>(addr)); | |
274 | } | |
275 | }; | |
20effc67 TL |
276 | |
277 | // Helper pair of IO direction and length | |
278 | struct io_direction_and_length { | |
279 | size_t _directed_length; // bit 0 is R/W flag | |
280 | ||
281 | public: | |
282 | io_direction_and_length(const io_request& rq, size_t val) { | |
283 | _directed_length = val << 1; | |
284 | if (rq.is_read()) { | |
285 | _directed_length |= 0x1; | |
286 | } else if (!rq.is_write()) { | |
287 | on_internal_error(io_log, fmt::format("Unrecognized request passing through I/O queue {}", rq.opname())); | |
288 | } | |
289 | } | |
290 | ||
291 | bool is_read() const noexcept { return (_directed_length & 0x1) == 1; } | |
292 | bool is_write() const noexcept { return (_directed_length & 0x1) == 0; } | |
293 | size_t length() const noexcept { return _directed_length >> 1; } | |
294 | int rw_idx() const noexcept { return _directed_length & 0x1; } | |
295 | static constexpr int read_idx = 1; | |
296 | static constexpr int write_idx = 0; | |
297 | }; | |
298 | ||
9f95a23c TL |
299 | } |
300 | } |