]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/AIO/aio_win32.cc
Merged from trunk
[thirdparty/squid.git] / src / DiskIO / AIO / aio_win32.cc
1
2 /*
3 * DEBUG: section 81 aio_xxx() POSIX emulation on Windows
4 * AUTHOR: Guido Serassio <serassio@squid-cache.org>
5 *
6 * SQUID Web Proxy Cache http://www.squid-cache.org/
7 * ----------------------------------------------------------
8 *
9 * Squid is the result of efforts by numerous individuals from
10 * the Internet community; see the CONTRIBUTORS file for full
11 * details. Many organizations have provided support for Squid's
12 * development; see the SPONSORS file for full details. Squid is
13 * Copyrighted (C) 2001 by the Regents of the University of
14 * California; see the COPYRIGHT file for full details. Squid
15 * incorporates software developed and/or copyrighted by other
16 * sources; see the CREDITS file for full details.
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
31 *
32 */
33
34 #include "squid.h"
35 #include "DiskIO/AIO/aio_win32.h"
36 #include "comm.h"
37 #include "fd.h"
38 #include "StatCounters.h"
39 #include "win32.h"
40
41 #if HAVE_ERRNO_H
42 #include <errno.h>
43 #endif
44
45 #if _SQUID_WINDOWS_
46 VOID CALLBACK IoCompletionRoutine(DWORD dwErrorCode,
47 DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
48 {
49
50 struct aiocb *aiocbp = (struct aiocb *) lpOverlapped->hEvent;
51
52 aiocbp->aio_sigevent.sigev_notify = dwErrorCode;
53 aiocbp->aio_sigevent.sigev_signo = dwNumberOfBytesTransfered;
54 debugs(81, 7, "AIO operation complete: errorcode=" << dwErrorCode << " nbytes=" << dwNumberOfBytesTransfered);
55 xfree(lpOverlapped);
56 }
57
58 int aio_read(struct aiocb *aiocbp)
59 {
60 LPOVERLAPPED Overlapped;
61 BOOL IoOperationStatus;
62
63 /* Allocate an overlapped structure. */
64 Overlapped = (LPOVERLAPPED) xcalloc(1, sizeof(OVERLAPPED));
65
66 if (!Overlapped) {
67 errno = ENOMEM;
68 return -1;
69 }
70
71 #if _FILE_OFFSET_BITS==64
72 #ifdef __GNUC__
73 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000LL);
74
75 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000LL);
76
77 #else
78
79 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000);
80
81 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000);
82
83 #endif
84 #else
85
86 Overlapped->Offset = aiocbp->aio_offset;
87
88 Overlapped->OffsetHigh = 0;
89
90 #endif
91
92 Overlapped->hEvent = aiocbp;
93
94 aiocbp->aio_sigevent.sigev_notify = EINPROGRESS;
95
96 aiocbp->aio_sigevent.sigev_signo = -1;
97
98 IoOperationStatus = ReadFileEx((HANDLE)_get_osfhandle(aiocbp->aio_fildes),
99 aiocbp->aio_buf,
100 aiocbp->aio_nbytes,
101 Overlapped,
102 IoCompletionRoutine);
103
104 /* Test to see if the I/O was queued successfully. */
105 if (!IoOperationStatus) {
106 errno = GetLastError();
107 debugs(81, DBG_IMPORTANT, "aio_read: GetLastError=" << errno );
108 return -1;
109 }
110
111 /* The I/O queued successfully. Go back into the
112 alertable wait for I/O completion or for
113 more I/O requests. */
114 return 0;
115 }
116
117 int aio_read64(struct aiocb64 *aiocbp)
118 {
119 LPOVERLAPPED Overlapped;
120 BOOL IoOperationStatus;
121
122 /* Allocate an overlapped structure. */
123 Overlapped = (LPOVERLAPPED) xcalloc(1, sizeof(OVERLAPPED));
124
125 if (!Overlapped) {
126 errno = ENOMEM;
127 return -1;
128 }
129
130 #ifdef __GNUC__
131 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000LL);
132
133 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000LL);
134
135 #else
136
137 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000);
138
139 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000);
140
141 #endif
142
143 Overlapped->hEvent = aiocbp;
144
145 aiocbp->aio_sigevent.sigev_notify = EINPROGRESS;
146
147 aiocbp->aio_sigevent.sigev_signo = -1;
148
149 IoOperationStatus = ReadFileEx((HANDLE)_get_osfhandle(aiocbp->aio_fildes),
150 aiocbp->aio_buf,
151 aiocbp->aio_nbytes,
152 Overlapped,
153 IoCompletionRoutine);
154
155 /* Test to see if the I/O was queued successfully. */
156 if (!IoOperationStatus) {
157 errno = GetLastError();
158 debugs(81, DBG_IMPORTANT, "aio_read: GetLastError=" << errno );
159 return -1;
160 }
161
162 /* The I/O queued successfully. Go back into the
163 alertable wait for I/O completion or for
164 more I/O requests. */
165 return 0;
166 }
167
168 int aio_write(struct aiocb *aiocbp)
169 {
170 LPOVERLAPPED Overlapped;
171 BOOL IoOperationStatus;
172
173 /* Allocate an overlapped structure. */
174 Overlapped = (LPOVERLAPPED) xcalloc(1, sizeof(OVERLAPPED));
175
176 if (!Overlapped) {
177 errno = ENOMEM;
178 return -1;
179 }
180
181 #if _FILE_OFFSET_BITS==64
182 #ifdef __GNUC__
183 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000LL);
184
185 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000LL);
186
187 #else
188
189 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000);
190
191 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000);
192
193 #endif
194 #else
195
196 Overlapped->Offset = aiocbp->aio_offset;
197
198 Overlapped->OffsetHigh = 0;
199
200 #endif
201
202 Overlapped->hEvent = aiocbp;
203
204 aiocbp->aio_sigevent.sigev_notify = EINPROGRESS;
205
206 aiocbp->aio_sigevent.sigev_signo = -1;
207
208 IoOperationStatus = WriteFileEx((HANDLE)_get_osfhandle(aiocbp->aio_fildes),
209 aiocbp->aio_buf,
210 aiocbp->aio_nbytes,
211 Overlapped,
212 IoCompletionRoutine);
213
214 /* Test to see if the I/O was queued successfully. */
215 if (!IoOperationStatus) {
216 errno = GetLastError();
217 debugs(81, DBG_IMPORTANT, "aio_write: GetLastError=" << errno );
218 return -1;
219 }
220
221 /* The I/O queued successfully. Go back into the
222 alertable wait for I/O completion or for
223 more I/O requests. */
224 return 0;
225 }
226
227 int aio_write64(struct aiocb64 *aiocbp)
228 {
229 LPOVERLAPPED Overlapped;
230 BOOL IoOperationStatus;
231
232 /* Allocate an overlapped structure. */
233 Overlapped = (LPOVERLAPPED) xcalloc(1, sizeof(OVERLAPPED));
234
235 if (!Overlapped) {
236 errno = ENOMEM;
237 return -1;
238 }
239
240 #ifdef __GNUC__
241 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000LL);
242
243 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000LL);
244
245 #else
246
247 Overlapped->Offset = (DWORD) (aiocbp->aio_offset % 0x100000000);
248
249 Overlapped->OffsetHigh = (DWORD) (aiocbp->aio_offset / 0x100000000);
250
251 #endif
252
253 Overlapped->hEvent = aiocbp;
254
255 aiocbp->aio_sigevent.sigev_notify = EINPROGRESS;
256
257 aiocbp->aio_sigevent.sigev_signo = -1;
258
259 IoOperationStatus = WriteFileEx((HANDLE)_get_osfhandle(aiocbp->aio_fildes),
260 aiocbp->aio_buf,
261 aiocbp->aio_nbytes,
262 Overlapped,
263 IoCompletionRoutine);
264
265 /* Test to see if the I/O was queued successfully. */
266 if (!IoOperationStatus) {
267 errno = GetLastError();
268 debugs(81, DBG_IMPORTANT, "aio_write: GetLastError=" << errno );
269 return -1;
270 }
271
272 /* The I/O queued successfully. Go back into the
273 alertable wait for I/O completion or for
274 more I/O requests. */
275 return 0;
276 }
277
278 int aio_error(const struct aiocb * aiocbp)
279 {
280 return aiocbp->aio_sigevent.sigev_notify;
281 }
282
283 int aio_error64(const struct aiocb64 * aiocbp)
284 {
285 return aiocbp->aio_sigevent.sigev_notify;
286 }
287
288 int aio_open(const char *path, int mode)
289 {
290 HANDLE hndl;
291 DWORD dwCreationDisposition;
292 DWORD dwDesiredAccess;
293 int fd;
294
295 if (mode & O_WRONLY)
296 mode |= O_APPEND;
297
298 mode |= O_BINARY;
299
300 errno = 0;
301
302 if (mode & O_WRONLY)
303 dwDesiredAccess = GENERIC_WRITE;
304 else
305 dwDesiredAccess = (mode & O_RDONLY) ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE;
306
307 if (mode & O_TRUNC)
308 dwCreationDisposition = CREATE_ALWAYS;
309 else
310 dwCreationDisposition = (mode & O_CREAT) ? OPEN_ALWAYS : OPEN_EXISTING;
311
312 if ((hndl = CreateFile(path, /* file name */
313 dwDesiredAccess, /* access mode */
314 0, /* share mode */
315 NULL, /* SD */
316 dwCreationDisposition, /* how to create */
317 FILE_FLAG_OVERLAPPED, /* file attributes */
318 NULL /* handle to template file */
319 )) != INVALID_HANDLE_VALUE) {
320 ++ statCounter.syscalls.disk.opens;
321 fd = _open_osfhandle((long) hndl, 0);
322 commSetCloseOnExec(fd);
323 fd_open(fd, FD_FILE, path);
324 } else {
325 errno = GetLastError();
326 fd = DISK_ERROR;
327 }
328
329 return fd;
330 }
331
332 void aio_close(int fd)
333 {
334 CloseHandle((HANDLE)_get_osfhandle(fd));
335 fd_close(fd);
336 ++ statCounter.syscalls.disk.closes;
337 }
338
339 ssize_t aio_return(struct aiocb * aiocbp)
340 {
341 return aiocbp->aio_sigevent.sigev_signo;
342 }
343
344 ssize_t aio_return64(struct aiocb64 * aiocbp)
345
346 {
347 return aiocbp->aio_sigevent.sigev_signo;
348 }
349 #endif /* _SQUID_WINDOWS_ */