]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/DiskThreads/DiskThreadsDiskFile.cc
4 * DEBUG: section 79 Disk IO Routines
5 * AUTHOR: Robert Collins
7 * SQUID Web Proxy Cache http://www.squid-cache.org/
8 * ----------------------------------------------------------
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.
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.
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.
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.
33 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
38 #include "DiskThreadsDiskFile.h"
39 #include "DiskIO/IORequestor.h"
40 #include "DiskIO/ReadRequest.h"
41 #include "DiskIO/WriteRequest.h"
44 #include "StatCounters.h"
52 /* === PUBLIC =========================================================== */
54 CBDATA_CLASS_INIT(DiskThreadsDiskFile
);
56 DiskThreadsDiskFile::operator new (size_t)
58 CBDATA_INIT_TYPE(DiskThreadsDiskFile
);
59 DiskThreadsDiskFile
*result
= cbdataAlloc(DiskThreadsDiskFile
);
61 * We used to call squidaio_init() here, but if the first transaction
62 * is to unlink a file (e.g., if Squid starts up over the disk space
63 * limit) then "squidaio" won't be initialized yet.
70 DiskThreadsDiskFile::operator delete(void *address
)
72 DiskThreadsDiskFile
*t
= static_cast<DiskThreadsDiskFile
*>(address
);
76 DiskThreadsDiskFile::DiskThreadsDiskFile(char const *aPath
, DiskThreadsIOStrategy
*anIO
):fd(-1), errorOccured (false), IO(anIO
),
80 debugs(79, 3, "UFSFile::UFSFile: " << aPath
);
81 path_
= xstrdup (aPath
);
84 DiskThreadsDiskFile::~DiskThreadsDiskFile()
91 DiskThreadsDiskFile::open(int flags
, mode_t mode
, RefCount
<IORequestor
> callback
)
93 ++statCounter
.syscalls
.disk
.opens
;
96 fd
= file_open(path_
, flags
);
99 debugs(79, 3, "DiskThreadsDiskFile::open: got failure (" << errno
<< ")");
107 ioRequestor
= callback
;
113 aioOpen(path_
, flags
, mode
, DiskThreadsDiskFile::OpenDone
, this);
117 openDone(fd
, NULL
, fd
, 0);
123 DiskThreadsDiskFile::read(ReadRequest
* request
)
125 debugs(79, 3, "DiskThreadsDiskFile::read: " << this << ", size " << request
->len
);
127 assert (ioRequestor
.getRaw());
128 ++statCounter
.syscalls
.disk
.reads
;
132 aioRead(fd
, request
->offset
, request
->len
, ReadDone
, new IoResult
<ReadRequest
>(this, request
));
135 file_read(fd
, request
->buf
, request
->len
, request
->offset
, ReadDone
, new IoResult
<ReadRequest
>(this, request
));
140 DiskThreadsDiskFile::create(int flags
, mode_t mode
, RefCount
<IORequestor
> callback
)
142 ++statCounter
.syscalls
.disk
.opens
;
145 int fd
= file_open(path_
, flags
);
148 debugs(79, 3, "DiskThreadsDiskFile::create: got failure (" << errno
<< ")");
156 ioRequestor
= callback
;
162 aioOpen(path_
, flags
, mode
, DiskThreadsDiskFile::OpenDone
, this);
166 openDone (fd
, NULL
, fd
, 0);
172 DiskThreadsDiskFile::error() const
178 DiskThreadsDiskFile::OpenDone(int fd
, void *cbdata
, const char *buf
, int aio_return
, int aio_errno
)
180 DiskThreadsDiskFile
*myFile
= static_cast<DiskThreadsDiskFile
*>(cbdata
);
181 myFile
->openDone (fd
, buf
, aio_return
, aio_errno
);
185 DiskThreadsDiskFile::openDone(int unused
, const char *unused2
, int anFD
, int errflag
)
187 debugs(79, 3, "DiskThreadsDiskFile::openDone: FD " << anFD
<< ", errflag " << errflag
);
192 if (errflag
|| fd
< 0) {
194 debugs(79, DBG_CRITICAL
, "DiskThreadsDiskFile::openDone: " << xstrerror());
195 debugs(79, DBG_IMPORTANT
, "\t" << path_
);
198 ++store_open_disk_fd
;
199 commSetCloseOnExec(fd
);
200 fd_open(fd
, FD_FILE
, path_
);
203 IORequestor::Pointer t
= ioRequestor
;
205 t
->ioCompletedNotification();
207 debugs(79, 3, "DiskThreadsDiskFile::openDone: exiting");
210 void DiskThreadsDiskFile::doClose()
213 ++statCounter
.syscalls
.disk
.closes
;
224 --store_open_disk_fd
;
230 DiskThreadsDiskFile::close()
232 debugs(79, 3, "DiskThreadsDiskFile::close: " << this << " closing for " << ioRequestor
.getRaw());
234 if (!ioInProgress()) {
236 assert (ioRequestor
!= NULL
);
237 ioRequestor
->closeCompleted();
240 debugs(79, DBG_CRITICAL
, HERE
<< "DiskThreadsDiskFile::close: " <<
241 "did NOT close because ioInProgress() is true. now what?");
246 DiskThreadsDiskFile::canRead() const
248 debugs(79, 3, "DiskThreadsDiskFile::canRead: fd is " << fd
);
253 DiskThreadsDiskFile::write(WriteRequest
* writeRequest
)
255 debugs(79, 3, "DiskThreadsDiskFile::write: FD " << fd
);
256 ++statCounter
.syscalls
.disk
.writes
;
260 aioWrite(fd
, writeRequest
->offset
, (char *)writeRequest
->buf
, writeRequest
->len
, WriteDone
, new IoResult
<WriteRequest
>(this, writeRequest
),
261 writeRequest
->free_func
);
264 file_write(fd
, writeRequest
->offset
, (char *)writeRequest
->buf
, writeRequest
->len
, WriteDone
, new IoResult
<WriteRequest
>(this, writeRequest
),
265 writeRequest
->free_func
);
270 DiskThreadsDiskFile::canWrite() const
276 DiskThreadsDiskFile::ioInProgress() const
278 return inProgressIOs
> 0;
281 /* === STATIC =========================================================== */
285 DiskThreadsDiskFile::ReadDone(int fd
, void *my_data
, const char *buf
, int len
, int errflag
)
288 DiskThreadsDiskFile::ReadDone(int fd
, const char *buf
, int len
, int errflag
, void *my_data
)
291 IoResult
<ReadRequest
> * result
= static_cast<IoResult
<ReadRequest
> *>(my_data
);
293 result
->file
->readDone(fd
, buf
, len
, errflag
, result
->request
);
298 DiskThreadsDiskFile::readDone(int rvfd
, const char *buf
, int len
, int errflag
, RefCount
<ReadRequest
> request
)
300 debugs(79, 3, "DiskThreadsDiskFile::readDone: FD " << rvfd
);
306 debugs(79, 3, "DiskThreadsDiskFile::readDone: got failure (" << errflag
<< ")");
309 rlen
= (ssize_t
) len
;
313 /* translate errflag from errno to Squid disk error */
317 errflag
= DISK_ERROR
;
323 if (errflag
== DISK_EOF
)
324 errflag
= DISK_OK
; /* EOF is signalled by len == 0, not errors... */
330 ioRequestor
->readCompleted(buf
, rlen
, errflag
, request
);
334 DiskThreadsDiskFile::
336 WriteDone(int fd
, void *my_data
, const char *buf
, int len
, int errflag
)
338 WriteDone(int fd
, int errflag
, size_t len
, void *my_data
)
341 IoResult
<WriteRequest
> * result
= static_cast<IoResult
<WriteRequest
> *>(my_data
);
343 result
->file
->writeDone(fd
, errflag
, len
, result
->request
);
348 DiskThreadsDiskFile::writeDone(int rvfd
, int errflag
, size_t len
, RefCount
<WriteRequest
> request
)
351 static int loop_detect
= 0;
354 /* Translate from errno to Squid disk error */
357 errflag
= errflag
== ENOSPC
? DISK_NO_SPACE_LEFT
: DISK_ERROR
;
363 debugs(79, 3, "DiskThreadsDiskFile::writeDone: FD " << fd
<< ", len " << len
<< ", err=" << errflag
);
365 assert(++loop_detect
< 10);
369 ioRequestor
->writeCompleted(errflag
, len
, request
);
374 /** \cond AUTODOCS-IGNORE */
376 cbdata_type IoResult
<RT
>::CBDATA_IoResult
= CBDATA_UNKNOWN
;
381 IoResult
<RT
>::operator new(size_t unused
)
383 CBDATA_INIT_TYPE(IoResult
);
384 IoResult
<RT
> *result
= cbdataAlloc(IoResult
);
390 IoResult
<RT
>::operator delete(void *address
)