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