]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/AIO/AIODiskFile.cc
Merged from trunk
[thirdparty/squid.git] / src / DiskIO / AIO / AIODiskFile.cc
1 /*
2 * AUTHOR: Adrian Chadd <adrian@squid-cache.org>
3 * DEBUG: section 79 Disk IO Routines
4 *
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
7 *
8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
30 *
31 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
32 */
33
34 /**
35 *
36 \par
37 * These routines are simple plugin replacements for the file_* routines
38 * in disk.c . They back-end into the POSIX AIO routines to provide
39 * a nice and simple async IO framework for COSS.
40 *
41 \par
42 * AIO is suitable for COSS - the only sync operations that the standard
43 * supports are read/write, and since COSS works on a single file
44 * per storedir it should work just fine.
45 */
46
47 #include "squid.h"
48 #include "AIODiskFile.h"
49 #include "AIODiskIOStrategy.h"
50 #include "DiskIO/IORequestor.h"
51 #include "DiskIO/ReadRequest.h"
52 #include "DiskIO/WriteRequest.h"
53 #include "disk.h"
54 #include "globals.h"
55
56 #if HAVE_ERRNO_H
57 #include <errno.h>
58 #endif
59
60 CBDATA_CLASS_INIT(AIODiskFile);
61 void *
62 AIODiskFile::operator new(size_t unused)
63 {
64 CBDATA_INIT_TYPE(AIODiskFile);
65 return cbdataAlloc(AIODiskFile);
66 }
67
68 void
69 AIODiskFile::operator delete(void *address)
70 {
71 cbdataFree(address);
72 }
73
74 AIODiskFile::AIODiskFile(char const *aPath, AIODiskIOStrategy *aStrategy) : fd(-1), closed(true), error_(false)
75 {
76 assert (aPath);
77 path = aPath;
78 strategy = aStrategy;
79 debugs(79, 3, "AIODiskFile::AIODiskFile: " << aPath);
80 }
81
82 AIODiskFile::~AIODiskFile()
83 {}
84
85 void
86 AIODiskFile::error(bool const &aBool)
87 {
88 error_ = aBool;
89 }
90
91 void
92 AIODiskFile::open(int flags, mode_t mode, RefCount<IORequestor> callback)
93 {
94 /* Simulate async calls */
95 #if _SQUID_WINDOWS_
96 fd = aio_open(path.termedBuf(), flags);
97 #else
98 fd = file_open(path.termedBuf() , flags);
99 #endif
100
101 ioRequestor = callback;
102
103 if (fd < 0) {
104 debugs(79, 3, HERE << ": got failure (" << errno << ")");
105 error(true);
106 } else {
107 closed = false;
108 ++store_open_disk_fd;
109 debugs(79, 3, HERE << ": opened FD " << fd);
110 }
111
112 callback->ioCompletedNotification();
113 }
114
115 void
116 AIODiskFile::create(int flags, mode_t mode, RefCount<IORequestor> callback)
117 {
118 /* We use the same logic path for open */
119 open(flags, mode, callback);
120 }
121
122 void
123 AIODiskFile::read(ReadRequest *request)
124 {
125 int slot;
126 async_queue_entry_t *qe;
127
128 assert(strategy->aq.aq_state == AQ_STATE_SETUP);
129
130 /* Find a free slot */
131 slot = strategy->findSlot();
132
133 if (slot < 0) {
134 /* No free slot? Callback error, and return */
135 fatal("Aiee! out of aiocb slots! - FIXME and wrap file_read\n");
136 debugs(79, DBG_IMPORTANT, "WARNING: out of aiocb slots!");
137 /* fall back to blocking method */
138 // file_read(fd, request->buf, request->len, request->offset, callback, data);
139 return;
140 }
141
142 /* Mark slot as ours */
143 qe = &strategy->aq.aq_queue[slot];
144
145 qe->aq_e_state = AQ_ENTRY_USED;
146
147 qe->aq_e_callback_data = cbdataReference(request);
148
149 qe->theFile = cbdataReference(this);
150
151 qe->aq_e_type = AQ_ENTRY_READ;
152
153 qe->aq_e_free = NULL;
154
155 qe->aq_e_buf = request->buf;
156
157 qe->aq_e_fd = getFD();
158
159 qe->aq_e_aiocb.aio_fildes = getFD();
160
161 qe->aq_e_aiocb.aio_nbytes = request->len;
162
163 qe->aq_e_aiocb.aio_offset = request->offset;
164
165 qe->aq_e_aiocb.aio_buf = request->buf;
166
167 /* Account */
168 ++ strategy->aq.aq_numpending;
169
170 /* Initiate aio */
171 if (aio_read(&qe->aq_e_aiocb) < 0) {
172 fatalf("Aiee! aio_read() returned error (%d) FIXME and wrap file_read !\n", errno);
173 debugs(79, DBG_IMPORTANT, "WARNING: aio_read() returned error: " << xstrerror());
174 /* fall back to blocking method */
175 // file_read(fd, request->buf, request->len, request->offset, callback, data);
176 }
177
178 }
179
180 void
181 AIODiskFile::write(WriteRequest *request)
182 {
183 int slot;
184 async_queue_entry_t *qe;
185
186 assert(strategy->aq.aq_state == AQ_STATE_SETUP);
187
188 /* Find a free slot */
189 slot = strategy->findSlot();
190
191 if (slot < 0) {
192 /* No free slot? Callback error, and return */
193 fatal("Aiee! out of aiocb slots FIXME and wrap file_write !\n");
194 debugs(79, DBG_IMPORTANT, "WARNING: out of aiocb slots!");
195 /* fall back to blocking method */
196 // file_write(fd, offset, buf, len, callback, data, freefunc);
197 return;
198 }
199
200 /* Mark slot as ours */
201 qe = &strategy->aq.aq_queue[slot];
202
203 qe->aq_e_state = AQ_ENTRY_USED;
204
205 qe->aq_e_callback_data = cbdataReference(request);
206
207 qe->theFile = cbdataReference(this);
208
209 qe->aq_e_type = AQ_ENTRY_WRITE;
210
211 qe->aq_e_free = request->free_func;
212
213 qe->aq_e_buf = (void *)request->buf;
214
215 qe->aq_e_fd = fd;
216
217 qe->aq_e_aiocb.aio_fildes = fd;
218
219 qe->aq_e_aiocb.aio_nbytes = request->len;
220
221 qe->aq_e_aiocb.aio_offset = request->offset;
222
223 qe->aq_e_aiocb.aio_buf = (void *)request->buf;
224
225 /* Account */
226 ++strategy->aq.aq_numpending;
227
228 /* Initiate aio */
229 if (aio_write(&qe->aq_e_aiocb) < 0) {
230 fatalf("Aiee! aio_write() returned error (%d) FIXME and wrap file_write !\n", errno);
231 debugs(79, DBG_IMPORTANT, "WARNING: aio_write() returned error: " << xstrerror());
232 /* fall back to blocking method */
233 // file_write(fd, offset, buf, len, callback, data, freefunc);
234 }
235 }
236
237 void
238 AIODiskFile::close ()
239 {
240 assert (!closed);
241 #if _SQUID_WINDOWS_
242 aio_close(fd);
243 #else
244 file_close(fd);
245 #endif
246
247 fd = -1;
248 closed = true;
249 assert (ioRequestor != NULL);
250 ioRequestor->closeCompleted();
251 }
252
253 bool
254 AIODiskFile::canRead() const
255 {
256 return true;
257 }
258
259 bool
260 AIODiskFile::canWrite() const
261 {
262 return true;
263 }
264
265 int
266 AIODiskFile::getFD() const
267 {
268 return fd;
269 }
270
271 bool
272 AIODiskFile::error() const
273 {
274 return error_;
275 }
276
277 bool
278 AIODiskFile::ioInProgress() const
279 {
280 return false;
281 }