]>
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>
37 #include "DiskThreadsDiskFile.h"
38 #include "DiskIO/IORequestor.h"
39 #include "DiskIO/ReadRequest.h"
40 #include "DiskIO/WriteRequest.h"
43 #include "StatCounters.h"
51 /* === PUBLIC =========================================================== */
53 CBDATA_CLASS_INIT(DiskThreadsDiskFile
);
55 DiskThreadsDiskFile::operator new (size_t)
57 CBDATA_INIT_TYPE(DiskThreadsDiskFile
);
58 DiskThreadsDiskFile
*result
= cbdataAlloc(DiskThreadsDiskFile
);
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.
69 DiskThreadsDiskFile::operator delete(void *address
)
71 DiskThreadsDiskFile
*t
= static_cast<DiskThreadsDiskFile
*>(address
);
75 DiskThreadsDiskFile::DiskThreadsDiskFile(char const *aPath
, DiskThreadsIOStrategy
*anIO
):fd(-1), errorOccured (false), IO(anIO
),
79 debugs(79, 3, "UFSFile::UFSFile: " << aPath
);
80 path_
= xstrdup (aPath
);
83 DiskThreadsDiskFile::~DiskThreadsDiskFile()
90 DiskThreadsDiskFile::open(int flags
, mode_t mode
, RefCount
<IORequestor
> callback
)
92 ++statCounter
.syscalls
.disk
.opens
;
95 fd
= file_open(path_
, flags
);
98 debugs(79, 3, "DiskThreadsDiskFile::open: got failure (" << errno
<< ")");
106 ioRequestor
= callback
;
112 aioOpen(path_
, flags
, mode
, DiskThreadsDiskFile::OpenDone
, this);
116 openDone(fd
, NULL
, fd
, 0);
122 DiskThreadsDiskFile::read(ReadRequest
* request
)
124 debugs(79, 3, "DiskThreadsDiskFile::read: " << this << ", size " << request
->len
);
126 assert (ioRequestor
.getRaw());
127 ++statCounter
.syscalls
.disk
.reads
;
131 aioRead(fd
, request
->offset
, request
->len
, ReadDone
, new IoResult
<ReadRequest
>(this, request
));
134 file_read(fd
, request
->buf
, request
->len
, request
->offset
, ReadDone
, new IoResult
<ReadRequest
>(this, request
));
139 DiskThreadsDiskFile::create(int flags
, mode_t mode
, RefCount
<IORequestor
> callback
)
141 ++statCounter
.syscalls
.disk
.opens
;
144 int fd
= file_open(path_
, flags
);
147 debugs(79, 3, "DiskThreadsDiskFile::create: got failure (" << errno
<< ")");
155 ioRequestor
= callback
;
161 aioOpen(path_
, flags
, mode
, DiskThreadsDiskFile::OpenDone
, this);
165 openDone (fd
, NULL
, fd
, 0);
171 DiskThreadsDiskFile::error() const
177 DiskThreadsDiskFile::OpenDone(int fd
, void *cbdata
, const char *buf
, int aio_return
, int aio_errno
)
179 DiskThreadsDiskFile
*myFile
= static_cast<DiskThreadsDiskFile
*>(cbdata
);
180 myFile
->openDone (fd
, buf
, aio_return
, aio_errno
);
184 DiskThreadsDiskFile::openDone(int unused
, const char *unused2
, int anFD
, int errflag
)
186 debugs(79, 3, "DiskThreadsDiskFile::openDone: FD " << anFD
<< ", errflag " << errflag
);
191 if (errflag
|| fd
< 0) {
193 debugs(79, DBG_CRITICAL
, "DiskThreadsDiskFile::openDone: " << xstrerror());
194 debugs(79, DBG_IMPORTANT
, "\t" << path_
);
197 ++store_open_disk_fd
;
198 commSetCloseOnExec(fd
);
199 fd_open(fd
, FD_FILE
, path_
);
202 IORequestor::Pointer t
= ioRequestor
;
204 t
->ioCompletedNotification();
206 debugs(79, 3, "DiskThreadsDiskFile::openDone: exiting");
209 void DiskThreadsDiskFile::doClose()
212 ++statCounter
.syscalls
.disk
.closes
;
223 --store_open_disk_fd
;
229 DiskThreadsDiskFile::close()
231 debugs(79, 3, "DiskThreadsDiskFile::close: " << this << " closing for " << ioRequestor
.getRaw());
233 if (!ioInProgress()) {
235 assert (ioRequestor
!= NULL
);
236 ioRequestor
->closeCompleted();
239 debugs(79, DBG_CRITICAL
, HERE
<< "DiskThreadsDiskFile::close: " <<
240 "did NOT close because ioInProgress() is true. now what?");
245 DiskThreadsDiskFile::canRead() const
247 debugs(79, 3, "DiskThreadsDiskFile::canRead: fd is " << fd
);
252 DiskThreadsDiskFile::write(WriteRequest
* writeRequest
)
254 debugs(79, 3, "DiskThreadsDiskFile::write: FD " << fd
);
255 ++statCounter
.syscalls
.disk
.writes
;
259 aioWrite(fd
, writeRequest
->offset
, (char *)writeRequest
->buf
, writeRequest
->len
, WriteDone
, new IoResult
<WriteRequest
>(this, writeRequest
),
260 writeRequest
->free_func
);
263 file_write(fd
, writeRequest
->offset
, (char *)writeRequest
->buf
, writeRequest
->len
, WriteDone
, new IoResult
<WriteRequest
>(this, writeRequest
),
264 writeRequest
->free_func
);
269 DiskThreadsDiskFile::canWrite() const
275 DiskThreadsDiskFile::ioInProgress() const
277 return inProgressIOs
> 0;
280 /* === STATIC =========================================================== */
284 DiskThreadsDiskFile::ReadDone(int fd
, void *my_data
, const char *buf
, int len
, int errflag
)
287 DiskThreadsDiskFile::ReadDone(int fd
, const char *buf
, int len
, int errflag
, void *my_data
)
290 IoResult
<ReadRequest
> * result
= static_cast<IoResult
<ReadRequest
> *>(my_data
);
292 result
->file
->readDone(fd
, buf
, len
, errflag
, result
->request
);
297 DiskThreadsDiskFile::readDone(int rvfd
, const char *buf
, int len
, int errflag
, RefCount
<ReadRequest
> request
)
299 debugs(79, 3, "DiskThreadsDiskFile::readDone: FD " << rvfd
);
305 debugs(79, 3, "DiskThreadsDiskFile::readDone: got failure (" << errflag
<< ")");
308 rlen
= (ssize_t
) len
;
312 /* translate errflag from errno to Squid disk error */
316 errflag
= DISK_ERROR
;
322 if (errflag
== DISK_EOF
)
323 errflag
= DISK_OK
; /* EOF is signalled by len == 0, not errors... */
329 ioRequestor
->readCompleted(buf
, rlen
, errflag
, request
);
333 DiskThreadsDiskFile::
335 WriteDone(int fd
, void *my_data
, const char *buf
, int len
, int errflag
)
337 WriteDone(int fd
, int errflag
, size_t len
, void *my_data
)
340 IoResult
<WriteRequest
> * result
= static_cast<IoResult
<WriteRequest
> *>(my_data
);
342 result
->file
->writeDone(fd
, errflag
, len
, result
->request
);
347 DiskThreadsDiskFile::writeDone(int rvfd
, int errflag
, size_t len
, RefCount
<WriteRequest
> request
)
350 static int loop_detect
= 0;
353 /* Translate from errno to Squid disk error */
356 errflag
= errflag
== ENOSPC
? DISK_NO_SPACE_LEFT
: DISK_ERROR
;
362 debugs(79, 3, "DiskThreadsDiskFile::writeDone: FD " << fd
<< ", len " << len
<< ", err=" << errflag
);
364 assert(++loop_detect
< 10);
368 ioRequestor
->writeCompleted(errflag
, len
, request
);
373 /** \cond AUTODOCS-IGNORE */
375 cbdata_type IoResult
<RT
>::CBDATA_IoResult
= CBDATA_UNKNOWN
;
380 IoResult
<RT
>::operator new(size_t unused
)
382 CBDATA_INIT_TYPE(IoResult
);
383 IoResult
<RT
> *result
= cbdataAlloc(IoResult
);
389 IoResult
<RT
>::operator delete(void *address
)