]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/AIO/aio_win32.cc
834504a4121849e2ad5303e8dfb6f7f6f5378b42
[thirdparty/squid.git] / src / DiskIO / AIO / aio_win32.cc
1 /*
2 * Copyright (C) 1996-2019 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section 81 aio_xxx() POSIX emulation on Windows */
10
11 #include "squid.h"
12 #include "comm.h"
13 #include "DiskIO/AIO/aio_win32.h"
14 #include "fd.h"
15 #include "StatCounters.h"
16 #include "win32.h"
17
18 #include <cerrno>
19
20 #if _SQUID_WINDOWS_
21 VOID CALLBACK IoCompletionRoutine(DWORD dwErrorCode,
22 DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
23 {
24
25 struct aiocb *aiocbp = (struct aiocb *) lpOverlapped->hEvent;
26
27 aiocbp->aio_sigevent.sigev_notify = dwErrorCode;
28 aiocbp->aio_sigevent.sigev_signo = dwNumberOfBytesTransfered;
29 debugs(81, 7, "AIO operation complete: errorcode=" << dwErrorCode << " nbytes=" << dwNumberOfBytesTransfered);
30 xfree(lpOverlapped);
31 }
32
33 int aio_read(struct aiocb *aiocbp)
34 {
35 LPOVERLAPPED Overlapped;
36 BOOL IoOperationStatus;
37
38 /* Allocate an overlapped structure. */
39 Overlapped = (LPOVERLAPPED) xcalloc(1, sizeof(OVERLAPPED));
40
41 if (!Overlapped) {
42 errno = ENOMEM;
43 return -1;
44 }
45
46 #if _FILE_OFFSET_BITS==64
47 #ifdef __GNUC__
48 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000LL);
49
50 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000LL);
51
52 #else
53
54 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000);
55
56 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000);
57
58 #endif
59 #else
60
61 Overlapped->Offset = aiocbp->aio_offset;
62
63 Overlapped->OffsetHigh = 0;
64
65 #endif
66
67 Overlapped->hEvent = aiocbp;
68
69 aiocbp->aio_sigevent.sigev_notify = EINPROGRESS;
70
71 aiocbp->aio_sigevent.sigev_signo = -1;
72
73 IoOperationStatus = ReadFileEx((HANDLE)_get_osfhandle(aiocbp->aio_fildes),
74 aiocbp->aio_buf,
75 aiocbp->aio_nbytes,
76 Overlapped,
77 IoCompletionRoutine);
78
79 /* Test to see if the I/O was queued successfully. */
80 if (!IoOperationStatus) {
81 errno = GetLastError();
82 debugs(81, DBG_IMPORTANT, "aio_read: GetLastError=" << errno );
83 return -1;
84 }
85
86 /* The I/O queued successfully. Go back into the
87 alertable wait for I/O completion or for
88 more I/O requests. */
89 return 0;
90 }
91
92 int aio_read64(struct aiocb64 *aiocbp)
93 {
94 LPOVERLAPPED Overlapped;
95 BOOL IoOperationStatus;
96
97 /* Allocate an overlapped structure. */
98 Overlapped = (LPOVERLAPPED) xcalloc(1, sizeof(OVERLAPPED));
99
100 if (!Overlapped) {
101 errno = ENOMEM;
102 return -1;
103 }
104
105 #ifdef __GNUC__
106 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000LL);
107
108 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000LL);
109
110 #else
111
112 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000);
113
114 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000);
115
116 #endif
117
118 Overlapped->hEvent = aiocbp;
119
120 aiocbp->aio_sigevent.sigev_notify = EINPROGRESS;
121
122 aiocbp->aio_sigevent.sigev_signo = -1;
123
124 IoOperationStatus = ReadFileEx((HANDLE)_get_osfhandle(aiocbp->aio_fildes),
125 aiocbp->aio_buf,
126 aiocbp->aio_nbytes,
127 Overlapped,
128 IoCompletionRoutine);
129
130 /* Test to see if the I/O was queued successfully. */
131 if (!IoOperationStatus) {
132 errno = GetLastError();
133 debugs(81, DBG_IMPORTANT, "aio_read: GetLastError=" << errno );
134 return -1;
135 }
136
137 /* The I/O queued successfully. Go back into the
138 alertable wait for I/O completion or for
139 more I/O requests. */
140 return 0;
141 }
142
143 int aio_write(struct aiocb *aiocbp)
144 {
145 LPOVERLAPPED Overlapped;
146 BOOL IoOperationStatus;
147
148 /* Allocate an overlapped structure. */
149 Overlapped = (LPOVERLAPPED) xcalloc(1, sizeof(OVERLAPPED));
150
151 if (!Overlapped) {
152 errno = ENOMEM;
153 return -1;
154 }
155
156 #if _FILE_OFFSET_BITS==64
157 #ifdef __GNUC__
158 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000LL);
159
160 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000LL);
161
162 #else
163
164 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000);
165
166 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000);
167
168 #endif
169 #else
170
171 Overlapped->Offset = aiocbp->aio_offset;
172
173 Overlapped->OffsetHigh = 0;
174
175 #endif
176
177 Overlapped->hEvent = aiocbp;
178
179 aiocbp->aio_sigevent.sigev_notify = EINPROGRESS;
180
181 aiocbp->aio_sigevent.sigev_signo = -1;
182
183 IoOperationStatus = WriteFileEx((HANDLE)_get_osfhandle(aiocbp->aio_fildes),
184 aiocbp->aio_buf,
185 aiocbp->aio_nbytes,
186 Overlapped,
187 IoCompletionRoutine);
188
189 /* Test to see if the I/O was queued successfully. */
190 if (!IoOperationStatus) {
191 errno = GetLastError();
192 debugs(81, DBG_IMPORTANT, "aio_write: GetLastError=" << errno );
193 return -1;
194 }
195
196 /* The I/O queued successfully. Go back into the
197 alertable wait for I/O completion or for
198 more I/O requests. */
199 return 0;
200 }
201
202 int aio_write64(struct aiocb64 *aiocbp)
203 {
204 LPOVERLAPPED Overlapped;
205 BOOL IoOperationStatus;
206
207 /* Allocate an overlapped structure. */
208 Overlapped = (LPOVERLAPPED) xcalloc(1, sizeof(OVERLAPPED));
209
210 if (!Overlapped) {
211 errno = ENOMEM;
212 return -1;
213 }
214
215 #ifdef __GNUC__
216 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000LL);
217
218 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000LL);
219
220 #else
221
222 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000);
223
224 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000);
225
226 #endif
227
228 Overlapped->hEvent = aiocbp;
229
230 aiocbp->aio_sigevent.sigev_notify = EINPROGRESS;
231
232 aiocbp->aio_sigevent.sigev_signo = -1;
233
234 IoOperationStatus = WriteFileEx((HANDLE)_get_osfhandle(aiocbp->aio_fildes),
235 aiocbp->aio_buf,
236 aiocbp->aio_nbytes,
237 Overlapped,
238 IoCompletionRoutine);
239
240 /* Test to see if the I/O was queued successfully. */
241 if (!IoOperationStatus) {
242 errno = GetLastError();
243 debugs(81, DBG_IMPORTANT, "aio_write: GetLastError=" << errno );
244 return -1;
245 }
246
247 /* The I/O queued successfully. Go back into the
248 alertable wait for I/O completion or for
249 more I/O requests. */
250 return 0;
251 }
252
253 int aio_error(const struct aiocb * aiocbp)
254 {
255 return aiocbp->aio_sigevent.sigev_notify;
256 }
257
258 int aio_error64(const struct aiocb64 * aiocbp)
259 {
260 return aiocbp->aio_sigevent.sigev_notify;
261 }
262
263 int aio_open(const char *path, int mode)
264 {
265 HANDLE hndl;
266 DWORD dwCreationDisposition;
267 DWORD dwDesiredAccess;
268 int fd;
269
270 if (mode & O_WRONLY)
271 mode |= O_APPEND;
272
273 mode |= O_BINARY;
274
275 errno = 0;
276
277 if (mode & O_WRONLY)
278 dwDesiredAccess = GENERIC_WRITE;
279 else
280 dwDesiredAccess = (mode & O_RDONLY) ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE;
281
282 if (mode & O_TRUNC)
283 dwCreationDisposition = CREATE_ALWAYS;
284 else
285 dwCreationDisposition = (mode & O_CREAT) ? OPEN_ALWAYS : OPEN_EXISTING;
286
287 if ((hndl = CreateFile(path, /* file name */
288 dwDesiredAccess, /* access mode */
289 0, /* share mode */
290 NULL, /* SD */
291 dwCreationDisposition, /* how to create */
292 FILE_FLAG_OVERLAPPED, /* file attributes */
293 NULL /* handle to template file */
294 )) != INVALID_HANDLE_VALUE) {
295 ++ statCounter.syscalls.disk.opens;
296 fd = _open_osfhandle((long) hndl, 0);
297 commSetCloseOnExec(fd);
298 fd_open(fd, FD_FILE, path);
299 } else {
300 errno = GetLastError();
301 fd = DISK_ERROR;
302 }
303
304 return fd;
305 }
306
307 void aio_close(int fd)
308 {
309 CloseHandle((HANDLE)_get_osfhandle(fd));
310 fd_close(fd);
311 ++ statCounter.syscalls.disk.closes;
312 }
313
314 ssize_t aio_return(struct aiocb * aiocbp)
315 {
316 return aiocbp->aio_sigevent.sigev_signo;
317 }
318
319 ssize_t aio_return64(struct aiocb64 * aiocbp)
320
321 {
322 return aiocbp->aio_sigevent.sigev_signo;
323 }
324 #endif /* _SQUID_WINDOWS_ */
325