]> git.ipfire.org Git - thirdparty/squid.git/blame - src/DiskIO/DiskThreads/DiskThreadsDiskFile.cc
Make mk-globals-c.awk more permissive on the input it accepts
[thirdparty/squid.git] / src / DiskIO / DiskThreads / DiskThreadsDiskFile.cc
CommitLineData
b9ae18aa 1/*
262a0e14 2 * $Id$
b9ae18aa 3 *
4 * DEBUG: section 79 Disk IO Routines
5 * AUTHOR: Robert Collins
6 *
7 * SQUID Web Proxy Cache http://www.squid-cache.org/
8 * ----------------------------------------------------------
9 *
10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
26ac0430 23 *
b9ae18aa 24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
26ac0430 28 *
b9ae18aa 29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
32 *
33 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
34 */
35
36
582c2af2 37#include "squid.h"
b9ae18aa 38#include "DiskThreadsDiskFile.h"
b9ae18aa 39#include "DiskIO/IORequestor.h"
40#include "DiskIO/ReadRequest.h"
41#include "DiskIO/WriteRequest.h"
582c2af2
FC
42#include "Generic.h"
43#include "globals.h"
e4f1fdae 44#include "StatCounters.h"
582c2af2
FC
45#include "Store.h"
46#include "protos.h"
b9ae18aa 47
48/* === PUBLIC =========================================================== */
49
50CBDATA_CLASS_INIT(DiskThreadsDiskFile);
51void *
52DiskThreadsDiskFile::operator new (size_t)
53{
54 CBDATA_INIT_TYPE(DiskThreadsDiskFile);
55 DiskThreadsDiskFile *result = cbdataAlloc(DiskThreadsDiskFile);
e65c313f 56 /*
57 * We used to call squidaio_init() here, but if the first transaction
58 * is to unlink a file (e.g., if Squid starts up over the disk space
59 * limit) then "squidaio" won't be initialized yet.
60 */
d06925a4 61
aa625860 62 return result;
b9ae18aa 63}
64
65void
63be0a78 66DiskThreadsDiskFile::operator delete(void *address)
b9ae18aa 67{
68 DiskThreadsDiskFile *t = static_cast<DiskThreadsDiskFile *>(address);
aa625860 69 cbdataFree(t);
b9ae18aa 70}
71
63be0a78 72DiskThreadsDiskFile::DiskThreadsDiskFile(char const *aPath, DiskThreadsIOStrategy *anIO):fd(-1), errorOccured (false), IO(anIO),
b9ae18aa 73 inProgressIOs (0)
74{
75 assert (aPath);
bf8fe701 76 debugs(79, 3, "UFSFile::UFSFile: " << aPath);
b9ae18aa 77 path_ = xstrdup (aPath);
78}
79
80DiskThreadsDiskFile::~DiskThreadsDiskFile()
81{
82 safe_free (path_);
83 doClose();
84}
85
86void
63be0a78 87DiskThreadsDiskFile::open(int flags, mode_t mode, RefCount<IORequestor> callback)
b9ae18aa 88{
e4f1fdae 89 ++statCounter.syscalls.disk.opens;
b9ae18aa 90#if !ASYNC_OPEN
91
92 fd = file_open(path_, flags);
93
94 if (fd < 0) {
bf8fe701 95 debugs(79, 3, "DiskThreadsDiskFile::open: got failure (" << errno << ")");
b9ae18aa 96 errorOccured = true;
97 return;
98 }
99
100#endif
cb4185f1 101 ++Opening_FD;
b9ae18aa 102
103 ioRequestor = callback;
104
105 ++inProgressIOs;
106
107#if ASYNC_OPEN
108
109 aioOpen(path_, flags, mode, DiskThreadsDiskFile::OpenDone, this);
110
111#else
112
113 openDone(fd, NULL, fd, 0);
114
115#endif
116}
117
118void
119DiskThreadsDiskFile::read(ReadRequest * request)
120{
121 debugs(79, 3, "DiskThreadsDiskFile::read: " << this << ", size " << request->len);
122 assert (fd > -1);
123 assert (ioRequestor.getRaw());
e4f1fdae 124 ++statCounter.syscalls.disk.reads;
b9ae18aa 125 ++inProgressIOs;
126#if ASYNC_READ
127
128 aioRead(fd, request->offset, request->len, ReadDone, new IoResult<ReadRequest>(this, request));
129#else
130
131 file_read(fd, request->buf, request->len, request->offset, ReadDone, new IoResult<ReadRequest>(this, request));
132#endif
133}
134
135void
63be0a78 136DiskThreadsDiskFile::create(int flags, mode_t mode, RefCount<IORequestor> callback)
b9ae18aa 137{
e4f1fdae 138 ++statCounter.syscalls.disk.opens;
b9ae18aa 139#if !ASYNC_CREATE
140
141 int fd = file_open(path_, flags);
142
143 if (fd < 0) {
bf8fe701 144 debugs(79, 3, "DiskThreadsDiskFile::create: got failure (" << errno << ")");
b9ae18aa 145 errorOccured = true;
146 return;
147 }
148
149#endif
cb4185f1 150 ++Opening_FD;
b9ae18aa 151
152 ioRequestor = callback;
153
154 ++inProgressIOs;
155
156#if ASYNC_CREATE
157
158 aioOpen(path_, flags, mode, DiskThreadsDiskFile::OpenDone, this);
159
160#else
161
162 openDone (fd, NULL, fd, 0);
163
164#endif
165}
166
167bool
168DiskThreadsDiskFile::error() const
169{
170 return errorOccured;
171}
172
173void
174DiskThreadsDiskFile::OpenDone(int fd, void *cbdata, const char *buf, int aio_return, int aio_errno)
175{
176 DiskThreadsDiskFile *myFile = static_cast<DiskThreadsDiskFile *>(cbdata);
177 myFile->openDone (fd, buf, aio_return, aio_errno);
178}
179
180void
181DiskThreadsDiskFile::openDone(int unused, const char *unused2, int anFD, int errflag)
182{
bf8fe701 183 debugs(79, 3, "DiskThreadsDiskFile::openDone: FD " << anFD << ", errflag " << errflag);
5e263176 184 --Opening_FD;
b9ae18aa 185
186 fd = anFD;
187
188 if (errflag || fd < 0) {
189 errno = errflag;
fa84c01d 190 debugs(79, DBG_CRITICAL, "DiskThreadsDiskFile::openDone: " << xstrerror());
e0236918 191 debugs(79, DBG_IMPORTANT, "\t" << path_);
b9ae18aa 192 errorOccured = true;
193 } else {
cb4185f1 194 ++store_open_disk_fd;
b9ae18aa 195 commSetCloseOnExec(fd);
196 fd_open(fd, FD_FILE, path_);
197 }
198
b9ae18aa 199 IORequestor::Pointer t = ioRequestor;
200 --inProgressIOs;
201 t->ioCompletedNotification();
ac97716e 202
bf8fe701 203 debugs(79, 3, "DiskThreadsDiskFile::openDone: exiting");
b9ae18aa 204}
205
206void DiskThreadsDiskFile::doClose()
207{
208 if (fd > -1) {
e4f1fdae 209 ++statCounter.syscalls.disk.closes;
d06925a4 210#if ASYNC_CLOSE
211
b9ae18aa 212 aioClose(fd);
213 fd_close(fd);
d06925a4 214#else
215
216 aioCancel(fd);
217 file_close(fd);
218#endif
219
5e263176 220 --store_open_disk_fd;
b9ae18aa 221 fd = -1;
222 }
223}
224
225void
63be0a78 226DiskThreadsDiskFile::close()
b9ae18aa 227{
bf8fe701 228 debugs(79, 3, "DiskThreadsDiskFile::close: " << this << " closing for " << ioRequestor.getRaw());
b9ae18aa 229
230 if (!ioInProgress()) {
231 doClose();
ac97716e 232 assert (ioRequestor != NULL);
b9ae18aa 233 ioRequestor->closeCompleted();
ac97716e 234 return;
235 } else {
fa84c01d 236 debugs(79, DBG_CRITICAL, HERE << "DiskThreadsDiskFile::close: " <<
ac97716e 237 "did NOT close because ioInProgress() is true. now what?");
b9ae18aa 238 }
239}
240
241bool
242DiskThreadsDiskFile::canRead() const
243{
bf8fe701 244 debugs(79, 3, "DiskThreadsDiskFile::canRead: fd is " << fd);
b9ae18aa 245 return fd > -1;
246}
247
248void
249DiskThreadsDiskFile::write(WriteRequest * writeRequest)
250{
bf8fe701 251 debugs(79, 3, "DiskThreadsDiskFile::write: FD " << fd);
e4f1fdae 252 ++statCounter.syscalls.disk.writes;
b9ae18aa 253 ++inProgressIOs;
254#if ASYNC_WRITE
255
256 aioWrite(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult<WriteRequest>(this, writeRequest),
257 writeRequest->free_func);
258#else
259
260 file_write(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult<WriteRequest>(this, writeRequest),
261 writeRequest->free_func);
262#endif
263}
264
265bool
266DiskThreadsDiskFile::canWrite() const
267{
268 return fd > -1;
269}
270
271bool
63be0a78 272DiskThreadsDiskFile::ioInProgress() const
b9ae18aa 273{
274 return inProgressIOs > 0;
275}
276
277/* === STATIC =========================================================== */
278
279#if ASYNC_READ
280void
281DiskThreadsDiskFile::ReadDone(int fd, void *my_data, const char *buf, int len, int errflag)
282#else
283void
284DiskThreadsDiskFile::ReadDone(int fd, const char *buf, int len, int errflag, void *my_data)
285#endif
286{
287 IoResult<ReadRequest> * result = static_cast<IoResult<ReadRequest> *>(my_data);
288 assert (result);
289 result->file->readDone(fd, buf, len, errflag, result->request);
290 delete result;
291}
292
293void
63be0a78 294DiskThreadsDiskFile::readDone(int rvfd, const char *buf, int len, int errflag, RefCount<ReadRequest> request)
b9ae18aa 295{
bf8fe701 296 debugs(79, 3, "DiskThreadsDiskFile::readDone: FD " << rvfd);
b9ae18aa 297 assert (fd == rvfd);
298
299 ssize_t rlen;
300
301 if (errflag) {
bf8fe701 302 debugs(79, 3, "DiskThreadsDiskFile::readDone: got failure (" << errflag << ")");
b9ae18aa 303 rlen = -1;
304 } else {
305 rlen = (ssize_t) len;
306 }
307
308#if ASYNC_READ
309 /* translate errflag from errno to Squid disk error */
310 errno = errflag;
311
312 if (errflag)
313 errflag = DISK_ERROR;
314 else
315 errflag = DISK_OK;
316
317#else
318
319 if (errflag == DISK_EOF)
320 errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */
321
322#endif
323
324 --inProgressIOs;
325
326 ioRequestor->readCompleted(buf, rlen, errflag, request);
327}
328
329void
330DiskThreadsDiskFile::
331#if ASYNC_WRITE
a37ea9a1 332WriteDone(int fd, void *my_data, const char *buf, int len, int errflag)
b9ae18aa 333#else
334WriteDone(int fd, int errflag, size_t len, void *my_data)
335#endif
336{
337 IoResult<WriteRequest> * result = static_cast<IoResult<WriteRequest> *>(my_data);
338 assert (result);
339 result->file->writeDone(fd, errflag, len, result->request);
340 delete result;
341}
342
343void
63be0a78 344DiskThreadsDiskFile::writeDone(int rvfd, int errflag, size_t len, RefCount<WriteRequest> request)
b9ae18aa 345{
346 assert (rvfd == fd);
347 static int loop_detect = 0;
b9ae18aa 348
349#if ASYNC_WRITE
350 /* Translate from errno to Squid disk error */
b9ae18aa 351
352 if (errflag)
a37ea9a1 353 errflag = errflag == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR;
b9ae18aa 354 else
355 errflag = DISK_OK;
356
357#endif
358
4a7a3d56 359 debugs(79, 3, "DiskThreadsDiskFile::writeDone: FD " << fd << ", len " << len << ", err=" << errflag);
a37ea9a1 360
b9ae18aa 361 assert(++loop_detect < 10);
362
363 --inProgressIOs;
364
365 ioRequestor->writeCompleted(errflag, len, request);
366
367 --loop_detect;
368}
369
d85b8894 370/** \cond AUTODOCS-IGNORE */
b9ae18aa 371template <class RT>
372cbdata_type IoResult<RT>::CBDATA_IoResult = CBDATA_UNKNOWN;
d85b8894 373/** \endcond */
b9ae18aa 374
375template<class RT>
376void *
63be0a78 377IoResult<RT>::operator new(size_t unused)
b9ae18aa 378{
379 CBDATA_INIT_TYPE(IoResult);
380 IoResult<RT> *result = cbdataAlloc(IoResult);
381 return result;
382}
383
384template <class RT>
385void
63be0a78 386IoResult<RT>::operator delete(void *address)
b9ae18aa 387{
388 cbdataFree(address);
389}