]> git.ipfire.org Git - thirdparty/squid.git/blame - src/DiskIO/DiskThreads/DiskThreadsDiskFile.cc
Source Maintenance: enforce #include statement block ordering
[thirdparty/squid.git] / src / DiskIO / DiskThreads / DiskThreadsDiskFile.cc
CommitLineData
b9ae18aa 1/*
b9ae18aa 2 * DEBUG: section 79 Disk IO Routines
3 * AUTHOR: Robert Collins
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.
26ac0430 21 *
b9ae18aa 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.
26ac0430 26 *
b9ae18aa 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
582c2af2 34#include "squid.h"
438b04d4 35#include "disk.h"
b9ae18aa 36#include "DiskThreadsDiskFile.h"
b9ae18aa 37#include "DiskIO/IORequestor.h"
38#include "DiskIO/ReadRequest.h"
39#include "DiskIO/WriteRequest.h"
c4ad1349 40#include "fd.h"
582c2af2
FC
41#include "Generic.h"
42#include "globals.h"
e4f1fdae 43#include "StatCounters.h"
582c2af2 44#include "Store.h"
b9ae18aa 45
21d845b1
FC
46#if HAVE_ERRNO_H
47#include <errno.h>
48#endif
49
b9ae18aa 50/* === PUBLIC =========================================================== */
51
52CBDATA_CLASS_INIT(DiskThreadsDiskFile);
b9ae18aa 53
63be0a78 54DiskThreadsDiskFile::DiskThreadsDiskFile(char const *aPath, DiskThreadsIOStrategy *anIO):fd(-1), errorOccured (false), IO(anIO),
b9ae18aa 55 inProgressIOs (0)
56{
57 assert (aPath);
bf8fe701 58 debugs(79, 3, "UFSFile::UFSFile: " << aPath);
b9ae18aa 59 path_ = xstrdup (aPath);
60}
61
62DiskThreadsDiskFile::~DiskThreadsDiskFile()
63{
64 safe_free (path_);
65 doClose();
66}
67
68void
63be0a78 69DiskThreadsDiskFile::open(int flags, mode_t mode, RefCount<IORequestor> callback)
b9ae18aa 70{
e4f1fdae 71 ++statCounter.syscalls.disk.opens;
b9ae18aa 72#if !ASYNC_OPEN
73
74 fd = file_open(path_, flags);
75
76 if (fd < 0) {
bf8fe701 77 debugs(79, 3, "DiskThreadsDiskFile::open: got failure (" << errno << ")");
b9ae18aa 78 errorOccured = true;
79 return;
80 }
81
82#endif
cb4185f1 83 ++Opening_FD;
b9ae18aa 84
85 ioRequestor = callback;
86
87 ++inProgressIOs;
88
89#if ASYNC_OPEN
90
91 aioOpen(path_, flags, mode, DiskThreadsDiskFile::OpenDone, this);
92
93#else
94
95 openDone(fd, NULL, fd, 0);
96
97#endif
98}
99
100void
101DiskThreadsDiskFile::read(ReadRequest * request)
102{
103 debugs(79, 3, "DiskThreadsDiskFile::read: " << this << ", size " << request->len);
104 assert (fd > -1);
105 assert (ioRequestor.getRaw());
e4f1fdae 106 ++statCounter.syscalls.disk.reads;
b9ae18aa 107 ++inProgressIOs;
108#if ASYNC_READ
109
110 aioRead(fd, request->offset, request->len, ReadDone, new IoResult<ReadRequest>(this, request));
111#else
112
113 file_read(fd, request->buf, request->len, request->offset, ReadDone, new IoResult<ReadRequest>(this, request));
114#endif
115}
116
117void
63be0a78 118DiskThreadsDiskFile::create(int flags, mode_t mode, RefCount<IORequestor> callback)
b9ae18aa 119{
e4f1fdae 120 ++statCounter.syscalls.disk.opens;
b9ae18aa 121#if !ASYNC_CREATE
122
123 int fd = file_open(path_, flags);
124
125 if (fd < 0) {
bf8fe701 126 debugs(79, 3, "DiskThreadsDiskFile::create: got failure (" << errno << ")");
b9ae18aa 127 errorOccured = true;
128 return;
129 }
130
131#endif
cb4185f1 132 ++Opening_FD;
b9ae18aa 133
134 ioRequestor = callback;
135
136 ++inProgressIOs;
137
138#if ASYNC_CREATE
139
140 aioOpen(path_, flags, mode, DiskThreadsDiskFile::OpenDone, this);
141
142#else
143
144 openDone (fd, NULL, fd, 0);
145
146#endif
147}
148
149bool
150DiskThreadsDiskFile::error() const
151{
152 return errorOccured;
153}
154
155void
156DiskThreadsDiskFile::OpenDone(int fd, void *cbdata, const char *buf, int aio_return, int aio_errno)
157{
158 DiskThreadsDiskFile *myFile = static_cast<DiskThreadsDiskFile *>(cbdata);
159 myFile->openDone (fd, buf, aio_return, aio_errno);
160}
161
162void
163DiskThreadsDiskFile::openDone(int unused, const char *unused2, int anFD, int errflag)
164{
bf8fe701 165 debugs(79, 3, "DiskThreadsDiskFile::openDone: FD " << anFD << ", errflag " << errflag);
5e263176 166 --Opening_FD;
b9ae18aa 167
168 fd = anFD;
169
170 if (errflag || fd < 0) {
171 errno = errflag;
fa84c01d 172 debugs(79, DBG_CRITICAL, "DiskThreadsDiskFile::openDone: " << xstrerror());
e0236918 173 debugs(79, DBG_IMPORTANT, "\t" << path_);
b9ae18aa 174 errorOccured = true;
175 } else {
cb4185f1 176 ++store_open_disk_fd;
b9ae18aa 177 commSetCloseOnExec(fd);
178 fd_open(fd, FD_FILE, path_);
179 }
180
b9ae18aa 181 IORequestor::Pointer t = ioRequestor;
182 --inProgressIOs;
183 t->ioCompletedNotification();
ac97716e 184
bf8fe701 185 debugs(79, 3, "DiskThreadsDiskFile::openDone: exiting");
b9ae18aa 186}
187
188void DiskThreadsDiskFile::doClose()
189{
190 if (fd > -1) {
e4f1fdae 191 ++statCounter.syscalls.disk.closes;
d06925a4 192#if ASYNC_CLOSE
193
b9ae18aa 194 aioClose(fd);
195 fd_close(fd);
d06925a4 196#else
197
198 aioCancel(fd);
199 file_close(fd);
200#endif
201
5e263176 202 --store_open_disk_fd;
b9ae18aa 203 fd = -1;
204 }
205}
206
207void
63be0a78 208DiskThreadsDiskFile::close()
b9ae18aa 209{
bf8fe701 210 debugs(79, 3, "DiskThreadsDiskFile::close: " << this << " closing for " << ioRequestor.getRaw());
b9ae18aa 211
212 if (!ioInProgress()) {
213 doClose();
ac97716e 214 assert (ioRequestor != NULL);
b9ae18aa 215 ioRequestor->closeCompleted();
ac97716e 216 return;
217 } else {
fa84c01d 218 debugs(79, DBG_CRITICAL, HERE << "DiskThreadsDiskFile::close: " <<
ac97716e 219 "did NOT close because ioInProgress() is true. now what?");
b9ae18aa 220 }
221}
222
223bool
224DiskThreadsDiskFile::canRead() const
225{
bf8fe701 226 debugs(79, 3, "DiskThreadsDiskFile::canRead: fd is " << fd);
b9ae18aa 227 return fd > -1;
228}
229
230void
231DiskThreadsDiskFile::write(WriteRequest * writeRequest)
232{
bf8fe701 233 debugs(79, 3, "DiskThreadsDiskFile::write: FD " << fd);
e4f1fdae 234 ++statCounter.syscalls.disk.writes;
b9ae18aa 235 ++inProgressIOs;
236#if ASYNC_WRITE
237
238 aioWrite(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult<WriteRequest>(this, writeRequest),
239 writeRequest->free_func);
240#else
241
242 file_write(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult<WriteRequest>(this, writeRequest),
243 writeRequest->free_func);
244#endif
245}
246
247bool
248DiskThreadsDiskFile::canWrite() const
249{
250 return fd > -1;
251}
252
253bool
63be0a78 254DiskThreadsDiskFile::ioInProgress() const
b9ae18aa 255{
256 return inProgressIOs > 0;
257}
258
259/* === STATIC =========================================================== */
260
261#if ASYNC_READ
262void
263DiskThreadsDiskFile::ReadDone(int fd, void *my_data, const char *buf, int len, int errflag)
264#else
265void
266DiskThreadsDiskFile::ReadDone(int fd, const char *buf, int len, int errflag, void *my_data)
267#endif
268{
269 IoResult<ReadRequest> * result = static_cast<IoResult<ReadRequest> *>(my_data);
270 assert (result);
271 result->file->readDone(fd, buf, len, errflag, result->request);
272 delete result;
273}
274
275void
63be0a78 276DiskThreadsDiskFile::readDone(int rvfd, const char *buf, int len, int errflag, RefCount<ReadRequest> request)
b9ae18aa 277{
bf8fe701 278 debugs(79, 3, "DiskThreadsDiskFile::readDone: FD " << rvfd);
b9ae18aa 279 assert (fd == rvfd);
280
281 ssize_t rlen;
282
283 if (errflag) {
bf8fe701 284 debugs(79, 3, "DiskThreadsDiskFile::readDone: got failure (" << errflag << ")");
b9ae18aa 285 rlen = -1;
286 } else {
287 rlen = (ssize_t) len;
288 }
289
290#if ASYNC_READ
291 /* translate errflag from errno to Squid disk error */
292 errno = errflag;
293
294 if (errflag)
295 errflag = DISK_ERROR;
296 else
297 errflag = DISK_OK;
298
299#else
300
301 if (errflag == DISK_EOF)
302 errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */
303
304#endif
305
306 --inProgressIOs;
307
308 ioRequestor->readCompleted(buf, rlen, errflag, request);
309}
310
311void
312DiskThreadsDiskFile::
313#if ASYNC_WRITE
a37ea9a1 314WriteDone(int fd, void *my_data, const char *buf, int len, int errflag)
b9ae18aa 315#else
316WriteDone(int fd, int errflag, size_t len, void *my_data)
317#endif
318{
319 IoResult<WriteRequest> * result = static_cast<IoResult<WriteRequest> *>(my_data);
320 assert (result);
321 result->file->writeDone(fd, errflag, len, result->request);
322 delete result;
323}
324
325void
63be0a78 326DiskThreadsDiskFile::writeDone(int rvfd, int errflag, size_t len, RefCount<WriteRequest> request)
b9ae18aa 327{
328 assert (rvfd == fd);
329 static int loop_detect = 0;
b9ae18aa 330
331#if ASYNC_WRITE
332 /* Translate from errno to Squid disk error */
b9ae18aa 333
334 if (errflag)
a37ea9a1 335 errflag = errflag == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR;
b9ae18aa 336 else
337 errflag = DISK_OK;
338
339#endif
340
4a7a3d56 341 debugs(79, 3, "DiskThreadsDiskFile::writeDone: FD " << fd << ", len " << len << ", err=" << errflag);
a37ea9a1 342
7f56277d
AJ
343 ++loop_detect;
344 assert(loop_detect < 10);
b9ae18aa 345
346 --inProgressIOs;
347
348 ioRequestor->writeCompleted(errflag, len, request);
349
350 --loop_detect;
351}
352
d85b8894 353/** \cond AUTODOCS-IGNORE */
b9ae18aa 354template <class RT>
355cbdata_type IoResult<RT>::CBDATA_IoResult = CBDATA_UNKNOWN;
d85b8894 356/** \endcond */