--------------------- PatchSet 1152 Date: 2005/01/01 18:50:17 Author: serassio Branch: nt Tag: (none) Log: Refactoring of awin32, added WinDiskThreads DISKIO module Members: configure.in:1.26.2.41->1.26.2.42 src/Makefile.am:1.26.2.36->1.26.2.37 src/DiskIO/WinDiskThreads/WinDiskThreads.h:1.1->1.1.2.1 src/DiskIO/WinDiskThreads/WinDiskThreadsDiskFile.cc:1.1->1.1.2.1 src/DiskIO/WinDiskThreads/WinDiskThreadsDiskFile.h:1.1->1.1.2.1 src/DiskIO/WinDiskThreads/WinDiskThreadsDiskIOModule.cc:1.1->1.1.2.1 src/DiskIO/WinDiskThreads/WinDiskThreadsDiskIOModule.h:1.1->1.1.2.1 src/DiskIO/WinDiskThreads/WinDiskThreadsIOStrategy.cc:1.1->1.1.2.1 src/DiskIO/WinDiskThreads/WinDiskThreadsIOStrategy.h:1.1->1.1.2.1 src/DiskIO/WinDiskThreads/aiops.cc:1.1->1.1.2.1 src/DiskIO/WinDiskThreads/async_io.cc:1.1->1.1.2.1 src/fs/Makefile.am:1.5.2.9->1.5.2.10 src/fs/awin32/.ccvsignore:1.2.18.1->1.2.18.2(DEAD) src/fs/awin32/.cvsignore:1.1->1.1.2.1 src/fs/awin32/StoreFSawin32.cc:1.1.2.1->1.1.2.2 src/fs/awin32/aiops.cc:1.2.18.5->1.2.18.6(DEAD) src/fs/awin32/async_io.cc:1.2.18.4->1.2.18.5(DEAD) src/fs/awin32/store_asyncufs.h:1.2.18.3->1.2.18.4(DEAD) src/fs/awin32/store_io_aufs.cc:1.2.18.3->1.2.18.4(DEAD) Index: squid3/configure.in =================================================================== RCS file: /cvsroot/squid-sf//squid3/configure.in,v retrieving revision 1.26.2.41 retrieving revision 1.26.2.42 diff -u -r1.26.2.41 -r1.26.2.42 --- squid3/configure.in 28 Dec 2004 17:17:50 -0000 1.26.2.41 +++ squid3/configure.in 1 Jan 2005 18:59:37 -0000 1.26.2.42 @@ -3,7 +3,7 @@ dnl dnl Duane Wessels, wessels@nlanr.net, February 1996 (autoconf v2.9) dnl -dnl $Id: configure.in,v 1.26.2.41 2004/12/28 17:17:50 serassio Exp $ +dnl $Id: configure.in,v 1.26.2.42 2005/01/01 18:59:37 serassio Exp $ dnl dnl dnl @@ -13,7 +13,7 @@ AC_CONFIG_AUX_DIR(cfgaux) AM_INIT_AUTOMAKE(squid, 3.0-PRE3-CVS-NT) AM_CONFIG_HEADER(include/autoconf.h) -AC_REVISION($Revision: 1.26.2.41 $)dnl +AC_REVISION($Revision: 1.26.2.42 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AM_MAINTAINER_MODE @@ -468,6 +468,7 @@ NEED_BLOCKING= NEED_DISKDAEMON= NEED_DISKTHREADS= +NEED_WINDISKTHREADS= NEED_AIO= NEED_WINAIO= for fs in $STORE_MODULES none; do @@ -481,7 +482,13 @@ NEED_UFS="true" NEED_BLOCKING="true" NEED_DISKTHREADS="true" + NEED_WINDISKTHREADS="true" ;; + awin32) + NEED_UFS="true" + NEED_BLOCKING="true" + NEED_WINDISKTHREADS="true" + ;; coss) NEED_AIO="true" NEED_WINAIO="true" @@ -492,11 +499,12 @@ done STORE_OBJS= STORE_LIBS= -dnl We have 'fake' modules - aufs and diskd - legacy. +dnl We have 'fake' modules - aufs, awin32 and diskd - legacy. for fs in $STORE_MODULES; do case "$fs" in diskd);; aufs);; + awin32);; *) STORE_OBJS="$STORE_OBJS fs/lib${fs}.a" STORE_LIBS="$STORE_LIBS lib${fs}.a" @@ -567,6 +575,9 @@ DiskThreads) FOUND_DISKTHREADS="true" ;; + WinDiskThreads) + FOUND_WINDISKTHREADS="true" + ;; AIO) FOUND_AIO="true" ;; @@ -593,14 +604,14 @@ DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/DiskDaemon/DiskDaemonDiskIOModule.o" fi -if test -z "$FOUND_DISKTHREADS" && test -n "$NEED_DISKTHREADS"; then - echo "adding DiskThreads, as it is used by an active, legacy Store Module" - DISK_LIBS="$DISK_LIBS libDiskThreads.a" - DISK_MODULES="$DISK_MODULES DiskThreads" - DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/DiskThreads/DiskThreadsDiskIOModule.o" -fi case "$host_os" in mingw|mingw32|cygwin|cygwin32) + if test -z "$FOUND_WINDISKTHREADS" && test -n "$NEED_WINDISKTHREADS"; then + echo "adding WinDiskThreads, as it is used by an active, legacy Store Module" + DISK_LIBS="$DISK_LIBS libWinDiskThreads.a" + DISK_MODULES="$DISK_MODULES WinDiskThreads" + DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/WinDiskThreads/WinDiskThreadsDiskIOModule.o" + fi if test -z "$FOUND_WINAIO" && test -n "$NEED_WINAIO"; then echo "adding WinAIO, as it is used by an active, legacy Store Module" DISK_LIBS="$DISK_LIBS libWinAIO.a" @@ -609,6 +620,12 @@ fi ;; *) + if test -z "$FOUND_DISKTHREADS" && test -n "$NEED_DISKTHREADS"; then + echo "adding DiskThreads, as it is used by an active, legacy Store Module" + DISK_LIBS="$DISK_LIBS libDiskThreads.a" + DISK_MODULES="$DISK_MODULES DiskThreads" + DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/DiskThreads/DiskThreadsDiskIOModule.o" + fi if test -z "$FOUND_AIO" && test -n "$NEED_AIO"; then echo "adding AIO, as it is used by an active, legacy Store Module" DISK_LIBS="$DISK_LIBS libAIO.a" Index: squid3/src/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Makefile.am,v retrieving revision 1.26.2.36 retrieving revision 1.26.2.37 diff -u -r1.26.2.36 -r1.26.2.37 --- squid3/src/Makefile.am 26 Dec 2004 09:24:13 -0000 1.26.2.36 +++ squid3/src/Makefile.am 1 Jan 2005 18:55:28 -0000 1.26.2.37 @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.am,v 1.26.2.36 2004/12/26 09:24:13 serassio Exp $ +# $Id: Makefile.am,v 1.26.2.37 2005/01/01 18:55:28 serassio Exp $ # # Uncomment and customize the following to suit your needs: # @@ -175,7 +175,7 @@ SUBDIRS = fs repl auth -EXTRA_LIBRARIES = libAIO.a libWinAIO.a libBlocking.a libDiskDaemon.a libDiskThreads.a +EXTRA_LIBRARIES = libAIO.a libWinAIO.a libBlocking.a libDiskDaemon.a libDiskThreads.a libWinDiskThreads.a noinst_LIBRARIES = @DISK_LIBS@ INCLUDES = $(MINGWINCLUDES) -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include -I$(top_srcdir)/lib/libTrie/include @@ -217,7 +217,8 @@ fs/coss/StoreFScoss.cc \ fs/diskd/StoreFSdiskd.cc \ fs/null/StoreFSnull.cc \ - fs/ufs/StoreFSufs.cc + fs/ufs/StoreFSufs.cc \ + fs/awin32/StoreFSawin32.cc all_DISKIOMODULES = \ DiskIO/AIO/AIODiskIOModule.cc \ @@ -837,6 +838,16 @@ DiskIO/DiskThreads/DiskThreadsIOStrategy.cc \ DiskIO/DiskThreads/DiskThreadsIOStrategy.h +libWinDiskThreads_a_SOURCES = \ + DiskIO/WinDiskThreads/aiops.cc \ + DiskIO/WinDiskThreads/async_io.cc \ + DiskIO/WinDiskThreads/WinDiskThreads.h \ + DiskIO/WinDiskThreads/WinDiskThreadsDiskFile.cc \ + DiskIO/WinDiskThreads/WinDiskThreadsDiskFile.h \ + DiskIO/WinDiskThreads/WinDiskThreadsDiskIOModule.h \ + DiskIO/WinDiskThreads/WinDiskThreadsIOStrategy.cc \ + DiskIO/WinDiskThreads/WinDiskThreadsIOStrategy.h + DiskIO_DiskDaemon_diskd_SOURCES = DiskIO/DiskDaemon/diskd.cc DiskIO_DiskDaemon_diskd_LDADD = $(top_builddir)/lib/libmiscutil.a @XTRA_LIBS@ --- /dev/null Wed Feb 14 13:33:00 2007 +++ squid3/src/DiskIO/WinDiskThreads/WinDiskThreads.h Wed Feb 14 13:34:04 2007 @@ -0,0 +1,125 @@ +/* + * WinDiskThreads.h + * + * Internal declarations for the WinDiskThreads routines + */ + +#ifndef __DISKTHREADS_H__ +#define __DISKTHREADS_H__ + +#ifdef AUFS_IO_THREADS +#define NUMTHREADS AUFS_IO_THREADS +#else +#define NUMTHREADS (Config.cacheSwap.n_configured*16) +#endif + +/* Queue limit where swapouts are deferred (load calculation) */ +#define MAGIC1 (NUMTHREADS*Config.cacheSwap.n_configured*5) +/* Queue limit where swapins are deferred (open/create fails) */ +#define MAGIC2 (NUMTHREADS*Config.cacheSwap.n_configured*20) + +/* Which operations to run async */ +#define ASYNC_OPEN 1 +#define ASYNC_CLOSE 0 +#define ASYNC_CREATE 1 +#define ASYNC_WRITE 0 +#define ASYNC_READ 1 + +enum _squidaio_request_type { + _AIO_OP_NONE = 0, + _AIO_OP_OPEN, + _AIO_OP_READ, + _AIO_OP_WRITE, + _AIO_OP_CLOSE, + _AIO_OP_UNLINK, + _AIO_OP_TRUNCATE, + _AIO_OP_OPENDIR, + _AIO_OP_STAT +}; +typedef enum _squidaio_request_type squidaio_request_type; + +typedef void AIOCB(int fd, void *cbdata, const char *buf, int aio_return, int aio_errno); + +struct squidaio_result_t +{ + int aio_return; + int aio_errno; + enum _squidaio_request_type result_type; + void *_data; /* Internal housekeeping */ + void *data; /* Available to the caller */ +}; + +struct squidaio_ctrl_t +{ + + struct squidaio_ctrl_t *next; + int fd; + int operation; + AIOCB *done_handler; + void *done_handler_data; + squidaio_result_t result; + int len; + char *bufp; + FREE *free_func; + dlink_node node; +}; + +int squidaio_cancel(squidaio_result_t *); +int squidaio_open(const char *, int, mode_t, squidaio_result_t *); +int squidaio_read(int, char *, int, off_t, int, squidaio_result_t *); +int squidaio_write(int, char *, int, off_t, int, squidaio_result_t *); +int squidaio_close(int, squidaio_result_t *); + +int squidaio_stat(const char *, struct stat *, squidaio_result_t *); +int squidaio_unlink(const char *, squidaio_result_t *); +int squidaio_truncate(const char *, off_t length, squidaio_result_t *); +int squidaio_opendir(const char *, squidaio_result_t *); +squidaio_result_t *squidaio_poll_done(void); +int squidaio_operations_pending(void); +int squidaio_sync(void); +int squidaio_get_queue_len(void); +void *squidaio_xmalloc(int size); +void squidaio_xfree(void *p, int size); +void squidaio_shutdown(void); +void squidaio_stats(StoreEntry *); + +void aioInit(void); +void aioDone(void); +void aioCancel(int); +void aioOpen(const char *, int, mode_t, AIOCB *, void *); +void aioClose(int); +void aioWrite(int, int offset, char *, int size, AIOCB *, void *, FREE *); +void aioRead(int, int offset, int size, AIOCB *, void *); + +void aioStat(char *, struct stat *, AIOCB *, void *); +void aioUnlink(const char *, AIOCB *, void *); +void aioTruncate(const char *, off_t length, AIOCB *, void *); +int aioQueueSize(void); + +#include "DiskIO/DiskFile.h" + +class WinDiskThreadsIOStrategy; + +struct AIOCounts +{ + int open_start; + int open_finish; + int close_start; + int close_finish; + int cancel; + int write_start; + int write_finish; + int read_start; + int read_finish; + int stat_start; + int stat_finish; + int unlink_start; + int unlink_finish; + int check_callback; +}; + +extern AIOCounts squidaio_counts; +extern dlink_list used_list; + + +#endif --- /dev/null Wed Feb 14 13:33:00 2007 +++ squid3/src/DiskIO/WinDiskThreads/WinDiskThreadsDiskFile.cc Wed Feb 14 13:34:04 2007 @@ -0,0 +1,370 @@ + +/* + * $Id: WinDiskThreadsDiskFile.cc,v 1.1.2.1 2005/01/01 18:54:31 serassio Exp $ + * + * DEBUG: section 79 Disk IO Routines + * AUTHOR: Robert Collins + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + * Copyright (c) 2003, Robert Collins + */ + + +#include "squid.h" +#include "WinDiskThreadsDiskFile.h" +#include "Store.h" +#include "SwapDir.h" +#include "Generic.h" +#include "DiskIO/IORequestor.h" +#include "DiskIO/ReadRequest.h" +#include "DiskIO/WriteRequest.h" + +/* === PUBLIC =========================================================== */ + +CBDATA_CLASS_INIT(WinDiskThreadsDiskFile); +void * +WinDiskThreadsDiskFile::operator new (size_t) +{ + CBDATA_INIT_TYPE(WinDiskThreadsDiskFile); + WinDiskThreadsDiskFile *result = cbdataAlloc(WinDiskThreadsDiskFile); + return result; +} + +void +WinDiskThreadsDiskFile::operator delete (void *address) +{ + WinDiskThreadsDiskFile *t = static_cast(address); + cbdataFree(t); +} + +WinDiskThreadsDiskFile::WinDiskThreadsDiskFile (char const *aPath, WinDiskThreadsIOStrategy *anIO):fd(-1), errorOccured (false), IO(anIO), + inProgressIOs (0) +{ + assert (aPath); + debug (79,3)("UFSFile::UFSFile: %s\n", aPath); + path_ = xstrdup (aPath); +} + +WinDiskThreadsDiskFile::~WinDiskThreadsDiskFile() +{ + safe_free (path_); + doClose(); +} + +void +WinDiskThreadsDiskFile::open (int flags, mode_t mode, IORequestor::Pointer callback) +{ + statCounter.syscalls.disk.opens++; +#if !ASYNC_OPEN + + fd = file_open(path_, flags); + + if (fd < 0) { + debug(79, 3) ("WinDiskThreadsDiskFile::open: got failure (%d)\n", errno); + errorOccured = true; + return; + } + +#endif + Opening_FD++; + + ioRequestor = callback; + + ++inProgressIOs; + +#if ASYNC_OPEN + + aioOpen(path_, flags, mode, WinDiskThreadsDiskFile::OpenDone, this); + +#else + + openDone(fd, NULL, fd, 0); + +#endif +} + +void +WinDiskThreadsDiskFile::read(ReadRequest * request) +{ + debugs(79, 3, "WinDiskThreadsDiskFile::read: " << this << ", size " << request->len); + assert (fd > -1); + assert (ioRequestor.getRaw()); + statCounter.syscalls.disk.reads++; + ++inProgressIOs; +#if ASYNC_READ + + aioRead(fd, request->offset, request->len, ReadDone, new IoResult(this, request)); +#else + + file_read(fd, request->buf, request->len, request->offset, ReadDone, new IoResult(this, request)); +#endif +} + +void +WinDiskThreadsDiskFile::create (int flags, mode_t mode, IORequestor::Pointer callback) +{ + statCounter.syscalls.disk.opens++; +#if !ASYNC_CREATE + + int fd = file_open(path_, flags); + + if (fd < 0) { + debug(79, 3) ("WinDiskThreadsDiskFile::create: got failure (%d)\n", errno); + errorOccured = true; + return; + } + +#endif + Opening_FD++; + + ioRequestor = callback; + + ++inProgressIOs; + +#if ASYNC_CREATE + + aioOpen(path_, flags, mode, WinDiskThreadsDiskFile::OpenDone, this); + +#else + + openDone (fd, NULL, fd, 0); + +#endif +} + +bool +WinDiskThreadsDiskFile::error() const +{ + return errorOccured; +} + +void +WinDiskThreadsDiskFile::OpenDone(int fd, void *cbdata, const char *buf, int aio_return, int aio_errno) +{ + WinDiskThreadsDiskFile *myFile = static_cast(cbdata); + myFile->openDone (fd, buf, aio_return, aio_errno); +} + +void +WinDiskThreadsDiskFile::openDone(int unused, const char *unused2, int anFD, int errflag) +{ + debug(79, 3) ("WinDiskThreadsDiskFile::openDone: FD %d, errflag %d\n", anFD, errflag); + Opening_FD--; + + fd = anFD; + + if (errflag || fd < 0) { + errno = errflag; + debug(79, 0) ("WinDiskThreadsDiskFile::openDone: %s\n", xstrerror()); + debug(79, 1) ("\t%s\n", path_); + errorOccured = true; + } else { + store_open_disk_fd++; + commSetCloseOnExec(fd); + fd_open(fd, FD_FILE, path_); + } + + debug(79, 3) ("WinDiskThreadsDiskFile::openDone: exiting\n"); + + IORequestor::Pointer t = ioRequestor; + --inProgressIOs; + t->ioCompletedNotification(); +} + +void WinDiskThreadsDiskFile::doClose() +{ + if (fd > -1) { + statCounter.syscalls.disk.closes++; + aioClose(fd); + fd_close(fd); + store_open_disk_fd--; + fd = -1; + } +} + +void +WinDiskThreadsDiskFile::close () +{ + debug (79,3)("WinDiskThreadsDiskFile::close: %p closing for %p\n", this, ioRequestor.getRaw()); + + if (!ioInProgress()) { + doClose(); + assert (ioRequestor.getRaw()); + ioRequestor->closeCompleted(); + } +} + +bool +WinDiskThreadsDiskFile::canRead() const +{ + debug (79,3)("WinDiskThreadsDiskFile::canRead: fd is %d\n",fd); + return fd > -1; +} + +void +WinDiskThreadsDiskFile::write(WriteRequest * writeRequest) +{ + debug(79, 3) ("WinDiskThreadsDiskFile::write: FD %d\n", fd); + statCounter.syscalls.disk.writes++; + ++inProgressIOs; +#if ASYNC_WRITE + + aioWrite(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult(this, writeRequest), + writeRequest->free_func); +#else + + file_write(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult(this, writeRequest), + writeRequest->free_func); +#endif +} + +bool +WinDiskThreadsDiskFile::canWrite() const +{ + return fd > -1; +} + +bool +WinDiskThreadsDiskFile::ioInProgress()const +{ + return inProgressIOs > 0; +} + +/* === STATIC =========================================================== */ + +#if ASYNC_READ +void +WinDiskThreadsDiskFile::ReadDone(int fd, void *my_data, const char *buf, int len, int errflag) +#else +void +WinDiskThreadsDiskFile::ReadDone(int fd, const char *buf, int len, int errflag, void *my_data) +#endif +{ + IoResult * result = static_cast *>(my_data); + assert (result); + result->file->readDone(fd, buf, len, errflag, result->request); + delete result; +} + +void +WinDiskThreadsDiskFile::readDone(int rvfd, const char *buf, int len, int errflag, ReadRequest::Pointer request) +{ + debug (79,3)("WinDiskThreadsDiskFile::readDone: FD %d\n",rvfd); + assert (fd == rvfd); + + ssize_t rlen; + + if (errflag) { + debug(79, 3) ("WinDiskThreadsDiskFile::readDone: got failure (%d)\n", errflag); + rlen = -1; + } else { + rlen = (ssize_t) len; + } + +#if ASYNC_READ + /* translate errflag from errno to Squid disk error */ + errno = errflag; + + if (errflag) + errflag = DISK_ERROR; + else + errflag = DISK_OK; + +#else + + if (errflag == DISK_EOF) + errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */ + +#endif + + --inProgressIOs; + + ioRequestor->readCompleted(buf, rlen, errflag, request); +} + +void +WinDiskThreadsDiskFile:: +#if ASYNC_WRITE +WriteDone(int fd, void *my_data, int len, int errflag) +#else +WriteDone(int fd, int errflag, size_t len, void *my_data) +#endif +{ + IoResult * result = static_cast *>(my_data); + assert (result); + result->file->writeDone(fd, errflag, len, result->request); + delete result; +} + +void +WinDiskThreadsDiskFile::writeDone (int rvfd, int errflag, size_t len, WriteRequest::Pointer request) +{ + assert (rvfd == fd); + static int loop_detect = 0; + debug(79, 3) ("WinDiskThreadsDiskFile::writeDone: FD %d, len %ld, err=%d\n", + fd, (long int) len, errflag); + +#if ASYNC_WRITE + /* Translate from errno to Squid disk error */ + errno = errflag; + + if (errflag) + errflag = errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR; + else + errflag = DISK_OK; + +#endif + + assert(++loop_detect < 10); + + --inProgressIOs; + + ioRequestor->writeCompleted(errflag, len, request); + + --loop_detect; +} + +template +cbdata_type IoResult::CBDATA_IoResult = CBDATA_UNKNOWN; + +template +void * +IoResult::operator new (size_t) +{ + CBDATA_INIT_TYPE(IoResult); + IoResult *result = cbdataAlloc(IoResult); + return result; +} + +template +void +IoResult::operator delete (void *address) +{ + cbdataFree(address); +} + --- /dev/null Wed Feb 14 13:33:00 2007 +++ squid3/src/DiskIO/WinDiskThreads/WinDiskThreadsDiskFile.h Wed Feb 14 13:34:04 2007 @@ -0,0 +1,116 @@ + +/* + * $Id: WinDiskThreadsDiskFile.h,v 1.1.2.1 2005/01/01 18:54:31 serassio Exp $ + * + * DEBUG: section 79 Disk IO Routines + * AUTHOR: Robert Collins + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + * Copyright (c) 2003, Robert Collins + */ + +#ifndef SQUID_DISKTHREADSDISKFILE_H +#define SQUID_DISKTHREADSDISKFILE_H +#include "DiskIO/DiskFile.h" +#include "WinDiskThreads.h" + +class WinDiskThreadsDiskFile : public DiskFile +{ + +public: + void * operator new (size_t); + void operator delete (void *); + WinDiskThreadsDiskFile (char const *path, WinDiskThreadsIOStrategy *); + ~WinDiskThreadsDiskFile(); + virtual void open (int, mode_t, RefCount); + virtual void create (int, mode_t, RefCount); + virtual void read(ReadRequest *); + virtual void write(WriteRequest *); + virtual void close (); + virtual bool error() const; + virtual int getFD() const { return fd;} + + virtual bool canRead() const; + virtual bool canWrite() const; + virtual bool ioInProgress()const; + +private: +#if ASYNC_READ + + static AIOCB ReadDone; +#else + + static DRCB ReadDone; +#endif +#if ASYNC_WRITE + + static AIOCB WriteDone; +#else + + static DWCB WriteDone; +#endif + + int fd; + bool errorOccured; + char const *path_; + WinDiskThreadsIOStrategy *IO; + size_t inProgressIOs; + static AIOCB OpenDone; + void openDone(int fd, const char *buf, int aio_return, int aio_errno); + RefCount ioRequestor; + CBDATA_CLASS(WinDiskThreadsDiskFile); + void doClose(); + + void readDone(int fd, const char *buf, int len, int errflag, RefCount); + void writeDone (int fd, int errflag, size_t len, RefCount); +}; + +#include "DiskIO/ReadRequest.h" + +template + +class IoResult +{ + +public: + void * operator new (size_t); + void operator delete (void *); + IoResult(RefCount aFile, RefCount aRequest) : file(aFile), request(aRequest){} + + RefCount file; + RefCount request; + +private: + CBDATA_CLASS(IoResult); +}; + +template +IoResult +IOResult(RefCount aRequest, RefCount aFile) { return IoResult(aFile, aRequest);} + +#endif /* SQUID_DISKTHREADSDISKFILE_H */ --- /dev/null Wed Feb 14 13:33:00 2007 +++ squid3/src/DiskIO/WinDiskThreads/WinDiskThreadsDiskIOModule.cc Wed Feb 14 13:34:04 2007 @@ -0,0 +1,72 @@ + +/* + * $Id: WinDiskThreadsDiskIOModule.cc,v 1.1.2.1 2005/01/01 18:54:31 serassio Exp $ + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + * Copyright (c) 2003, Robert Collins + */ + +#include "squid.h" +#include "WinDiskThreadsDiskIOModule.h" +#include "WinDiskThreadsIOStrategy.h" + +WinDiskThreadsDiskIOModule WinDiskThreadsDiskIOModule::Instance; +WinDiskThreadsDiskIOModule & +WinDiskThreadsDiskIOModule::GetInstance() +{ + return Instance; +} + +WinDiskThreadsDiskIOModule::WinDiskThreadsDiskIOModule() +{ + ModuleAdd(*this); +} + +void +WinDiskThreadsDiskIOModule::init() +{ + WinDiskThreadsIOStrategy::Instance.init(); +} + +void +WinDiskThreadsDiskIOModule::shutdown() +{ + WinDiskThreadsIOStrategy::Instance.done(); +} + +DiskIOStrategy * +WinDiskThreadsDiskIOModule::createStrategy() +{ + return new SingletonIOStrategy(&WinDiskThreadsIOStrategy::Instance); +} + +char const * +WinDiskThreadsDiskIOModule::type () const +{ + return "WinDiskThreads"; +} --- /dev/null Wed Feb 14 13:33:00 2007 +++ squid3/src/DiskIO/WinDiskThreads/WinDiskThreadsDiskIOModule.h Wed Feb 14 13:34:04 2007 @@ -0,0 +1,55 @@ + +/* + * $Id: WinDiskThreadsDiskIOModule.h,v 1.1.2.1 2005/01/01 18:54:31 serassio Exp $ + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + * Copyright (c) 2003, Robert Collins + */ + +#ifndef SQUID_DISKTHREADSDISKIOMODULE_H +#define SQUID_DISKTHREADSDISKIOMODULE_H + +#include "DiskIO/DiskIOModule.h" + +class WinDiskThreadsDiskIOModule : public DiskIOModule +{ + +public: + static WinDiskThreadsDiskIOModule &GetInstance(); + WinDiskThreadsDiskIOModule(); + virtual void init(); + virtual void shutdown(); + virtual char const *type () const; + virtual DiskIOStrategy* createStrategy(); + +private: + static WinDiskThreadsDiskIOModule Instance; +}; + + +#endif /* SQUID_DISKTHREADSDISKIOMODULE_H */ --- /dev/null Wed Feb 14 13:33:00 2007 +++ squid3/src/DiskIO/WinDiskThreads/WinDiskThreadsIOStrategy.cc Wed Feb 14 13:34:04 2007 @@ -0,0 +1,267 @@ + +/* + * $Id: WinDiskThreadsIOStrategy.cc,v 1.1.2.1 2005/01/01 18:54:31 serassio Exp $ + * + * DEBUG: section 79 Squid-side Disk I/O functions. + * AUTHOR: Robert Collins + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + * Copyright (c) 2003, Robert Collins + */ + +#include "squid.h" + +#include "WinDiskThreadsIOStrategy.h" +#include "WinDiskThreadsDiskFile.h" +/* for statfs */ +#include "Store.h" +#include "fde.h" + +//static MemAllocatorProxy *squidaio_ctrl_pool; + +void +WinDiskThreadsIOStrategy::init(void) +{ + if (initialised) + return; + + squidaio_ctrl_pool = new MemAllocatorProxy("aio_ctrl", sizeof(squidaio_ctrl_t)); + + cachemgrRegister("squidaio_counts", "Async IO Function Counters", + aioStats, 0, 1); + + initialised = true; +} + +void +WinDiskThreadsIOStrategy::done(void) +{ + if (!initialised) + return; + + squidaio_shutdown(); + delete squidaio_ctrl_pool; + + squidaio_ctrl_pool = NULL; + + initialised = false; +} + +int +WinDiskThreadsIOStrategy::callback() +{ + squidaio_result_t *resultp; + squidaio_ctrl_t *ctrlp; + int retval = 0; + + assert(initialised); + squidaio_counts.check_callback++; + + for (;;) { + if ((resultp = squidaio_poll_done()) == NULL) + break; + + ctrlp = (squidaio_ctrl_t *) resultp->data; + + switch (resultp->result_type) { + + case _AIO_OP_NONE: + + case _AIO_OP_TRUNCATE: + + case _AIO_OP_OPENDIR: + break; + + case _AIO_OP_OPEN: + ++squidaio_counts.open_finish; + break; + + case _AIO_OP_READ: + ++squidaio_counts.read_finish; + break; + + case _AIO_OP_WRITE: + ++squidaio_counts.write_finish; + break; + + case _AIO_OP_CLOSE: + ++squidaio_counts.close_finish; + break; + + case _AIO_OP_UNLINK: + ++squidaio_counts.unlink_finish; + break; + + case _AIO_OP_STAT: + ++squidaio_counts.stat_finish; + break; + } + + if (ctrlp == NULL) + continue; /* XXX Should not happen */ + + dlinkDelete(&ctrlp->node, &used_list); + + if (ctrlp->done_handler) { + AIOCB *callback = ctrlp->done_handler; + void *cbdata; + ctrlp->done_handler = NULL; + + if (cbdataReferenceValidDone(ctrlp->done_handler_data, &cbdata)) { + retval = 1; /* Return that we've actually done some work */ + callback(ctrlp->fd, cbdata, ctrlp->bufp, + ctrlp->result.aio_return, ctrlp->result.aio_errno); + } else { + if (ctrlp->operation == _AIO_OPEN) { + /* The open operation was aborted.. */ + int fd = ctrlp->result.aio_return; + + if (fd >= 0) + aioClose(fd); + } + } + } + + /* free data if requested to aioWrite() */ + if (ctrlp->free_func) + ctrlp->free_func(ctrlp->bufp); + + /* free temporary read buffer */ + if (ctrlp->operation == _AIO_READ) + squidaio_xfree(ctrlp->bufp, ctrlp->len); + + if (ctrlp->operation == _AIO_CLOSE) + aioFDWasClosed(ctrlp->fd); + + squidaio_ctrl_pool->free(ctrlp); + } + + return retval; +} + +/* Flush all pending I/O */ +void +WinDiskThreadsIOStrategy::sync() +{ + if (!initialised) + return; /* nothing to do then */ + + /* Flush all pending operations */ + debug(32, 1) ("aioSync: flushing pending I/O operations\n"); + + do { + callback(); + } while (squidaio_sync()); + + debug(32, 1) ("aioSync: done\n"); +} + +WinDiskThreadsIOStrategy::WinDiskThreadsIOStrategy() : initialised (false) {} + +void +WinDiskThreadsIOStrategy::aioStats(StoreEntry * sentry) +{ + storeAppendPrintf(sentry, "ASYNC IO Counters:\n"); + storeAppendPrintf(sentry, "Operation\t# Requests\tNumber serviced\n"); + storeAppendPrintf(sentry, "open\t%d\t%d\n", squidaio_counts.open_start, squidaio_counts.open_finish); + storeAppendPrintf(sentry, "close\t%d\t%d\n", squidaio_counts.close_start, squidaio_counts.close_finish); + storeAppendPrintf(sentry, "cancel\t%d\t-\n", squidaio_counts.cancel); + storeAppendPrintf(sentry, "write\t%d\t%d\n", squidaio_counts.write_start, squidaio_counts.write_finish); + storeAppendPrintf(sentry, "read\t%d\t%d\n", squidaio_counts.read_start, squidaio_counts.read_finish); + storeAppendPrintf(sentry, "stat\t%d\t%d\n", squidaio_counts.stat_start, squidaio_counts.stat_finish); + storeAppendPrintf(sentry, "unlink\t%d\t%d\n", squidaio_counts.unlink_start, squidaio_counts.unlink_finish); + storeAppendPrintf(sentry, "check_callback\t%d\t-\n", squidaio_counts.check_callback); + storeAppendPrintf(sentry, "queue\t%d\t-\n", squidaio_get_queue_len()); + squidaio_stats(sentry); +} + +void +WinDiskThreadsIOStrategy::aioFDWasClosed(int fd) +{ + if (fd_table[fd].flags.closing) + fd_close(fd); +} + +WinDiskThreadsIOStrategy WinDiskThreadsIOStrategy::Instance; +bool +WinDiskThreadsIOStrategy::shedLoad() +{ + /* + * we should detect some 'too many files open' condition and return + * NULL here. + */ +#ifdef MAGIC2 + + if (aioQueueSize() > MAGIC2) + return true; + +#endif + + return false; +} + +int +WinDiskThreadsIOStrategy::load() +{ + int loadav; + int ql; + + ql = aioQueueSize(); + + if (ql == 0) + loadav = 0; + + loadav = ql * 1000 / MAGIC1; + + debug(47, 9) ("storeAufsDirCheckObj: load=%d\n", loadav); + + return loadav; +} + +DiskFile::Pointer +WinDiskThreadsIOStrategy::newFile (char const *path) +{ + if (shedLoad()) { + return NULL; + } + + return new WinDiskThreadsDiskFile (path, this); +} + +void +WinDiskThreadsIOStrategy::unlinkFile(char const *path) +{ + statCounter.syscalls.disk.unlinks++; +#if USE_TRUNCATE_NOT_UNLINK + + aioTruncate(path, NULL, NULL); +#else + + aioUnlink(path, NULL, NULL); +#endif +} --- /dev/null Wed Feb 14 13:33:00 2007 +++ squid3/src/DiskIO/WinDiskThreads/WinDiskThreadsIOStrategy.h Wed Feb 14 13:34:04 2007 @@ -0,0 +1,73 @@ + +/* + * $Id: WinDiskThreadsIOStrategy.h,v 1.1.2.1 2005/01/01 18:54:31 serassio Exp $ + * + * DEBUG: section 79 Squid-side Disk I/O functions. + * AUTHOR: Robert Collins + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + * Copyright (c) 2003, Robert Collins + */ + +#ifndef __STORE_DISKTHREADEDIOSTRATEGY_H__ +#define __STORE_DISKTHREADEDIOSTRATEGY_H__ + +#define _AIO_OPEN 0 +#define _AIO_READ 1 +#define _AIO_WRITE 2 +#define _AIO_CLOSE 3 +#define _AIO_UNLINK 4 +#define _AIO_TRUNCATE 4 +#define _AIO_OPENDIR 5 +#define _AIO_STAT 6 +#include "DiskIO/DiskIOStrategy.h" + +class WinDiskThreadsIOStrategy : public DiskIOStrategy +{ + +public: + WinDiskThreadsIOStrategy(); + virtual bool shedLoad(); + virtual int load(); + virtual RefCount newFile(char const *path); + virtual void unlinkFile (char const *); + virtual int callback(); + virtual void sync(); + virtual void init(); + void done(); + /* Todo: add access limitations */ + bool initialised; + static WinDiskThreadsIOStrategy Instance; + MemAllocatorProxy *squidaio_ctrl_pool; + +private: + static void aioStats(StoreEntry * sentry); + void aioFDWasClosed(int fd); +}; + +#endif --- /dev/null Wed Feb 14 13:33:00 2007 +++ squid3/src/DiskIO/WinDiskThreads/aiops.cc Wed Feb 14 13:34:04 2007 @@ -0,0 +1,1209 @@ +/* + * $Id: aiops.cc,v 1.1.2.1 2005/01/01 18:54:31 serassio Exp $ + * + * DEBUG: section 43 AIOPS + * AUTHOR: Stewart Forster + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" +#include "squid_windows.h" +#include "WinDiskThreads.h" + +#include +#include +#include +#include +#include +#include +#include +#include "comm.h" + +#define RIDICULOUS_LENGTH 4096 + +enum _squidaio_thread_status { + _THREAD_STARTING = 0, + _THREAD_WAITING, + _THREAD_BUSY, + _THREAD_FAILED, + _THREAD_DONE +}; +typedef enum _squidaio_thread_status squidaio_thread_status; + +typedef struct squidaio_request_t +{ + + struct squidaio_request_t *next; + squidaio_request_type request_type; + int cancelled; + char *path; + int oflag; + mode_t mode; + int fd; + char *bufferp; + char *tmpbufp; + int buflen; + off_t offset; + int whence; + int ret; + int err; + + struct stat *tmpstatp; + + struct stat *statp; + squidaio_result_t *resultp; +} + +squidaio_request_t; + +typedef struct squidaio_request_queue_t +{ + HANDLE mutex; + HANDLE cond; /* See Event objects */ + squidaio_request_t *volatile head; + squidaio_request_t *volatile *volatile tailp; + unsigned long requests; + unsigned long blocked; /* main failed to lock the queue */ +} + +squidaio_request_queue_t; + +typedef struct squidaio_thread_t squidaio_thread_t; + +struct squidaio_thread_t +{ + squidaio_thread_t *next; + HANDLE thread; + DWORD dwThreadId; /* thread ID */ + squidaio_thread_status status; + + struct squidaio_request_t *current_req; + unsigned long requests; + int volatile exit; +}; + +static void squidaio_init(void); +static void squidaio_queue_request(squidaio_request_t *); +static void squidaio_cleanup_request(squidaio_request_t *); +static DWORD WINAPI squidaio_thread_loop( LPVOID lpParam ); +static void squidaio_do_open(squidaio_request_t *); +static void squidaio_do_read(squidaio_request_t *); +static void squidaio_do_write(squidaio_request_t *); +static void squidaio_do_close(squidaio_request_t *); +static void squidaio_do_stat(squidaio_request_t *); +static void squidaio_do_unlink(squidaio_request_t *); +static void squidaio_do_truncate(squidaio_request_t *); +#if AIO_OPENDIR +static void *squidaio_do_opendir(squidaio_request_t *); +#endif +static void squidaio_debug(squidaio_request_t *); +static void squidaio_poll_queues(void); + +static squidaio_thread_t *threads = NULL; +static int squidaio_initialised = 0; + + +#define AIO_LARGE_BUFS 16384 +#define AIO_MEDIUM_BUFS AIO_LARGE_BUFS >> 1 +#define AIO_SMALL_BUFS AIO_LARGE_BUFS >> 2 +#define AIO_TINY_BUFS AIO_LARGE_BUFS >> 3 +#define AIO_MICRO_BUFS 128 + +static MemAllocatorProxy *squidaio_large_bufs = NULL; /* 16K */ +static MemAllocatorProxy *squidaio_medium_bufs = NULL; /* 8K */ +static MemAllocatorProxy *squidaio_small_bufs = NULL; /* 4K */ +static MemAllocatorProxy *squidaio_tiny_bufs = NULL; /* 2K */ +static MemAllocatorProxy *squidaio_micro_bufs = NULL; /* 128K */ + +static int request_queue_len = 0; +static MemAllocatorProxy *squidaio_request_pool = NULL; +static MemAllocatorProxy *squidaio_thread_pool = NULL; +static squidaio_request_queue_t request_queue; + +static struct +{ + squidaio_request_t *head, **tailp; +} + +request_queue2 = { + + NULL, &request_queue2.head + }; +static squidaio_request_queue_t done_queue; + +static struct +{ + squidaio_request_t *head, **tailp; +} + +done_requests = { + + NULL, &done_requests.head + }; + +static HANDLE main_thread; + +static MemAllocatorProxy * +squidaio_get_pool(int size) +{ + MemAllocatorProxy *p; + + if (size <= AIO_LARGE_BUFS) { + if (size <= AIO_MICRO_BUFS) + p = squidaio_micro_bufs; + else if (size <= AIO_TINY_BUFS) + p = squidaio_tiny_bufs; + else if (size <= AIO_SMALL_BUFS) + p = squidaio_small_bufs; + else if (size <= AIO_MEDIUM_BUFS) + p = squidaio_medium_bufs; + else + p = squidaio_large_bufs; + } else + p = NULL; + + return p; +} + +void * +squidaio_xmalloc(int size) +{ + void *p; + MemAllocatorProxy *pool; + + if ((pool = squidaio_get_pool(size)) != NULL) { + p = pool->alloc(); + } else + p = xmalloc(size); + + return p; +} + +static char * +squidaio_xstrdup(const char *str) +{ + char *p; + int len = strlen(str) + 1; + + p = (char *)squidaio_xmalloc(len); + strncpy(p, str, len); + + return p; +} + +void +squidaio_xfree(void *p, int size) +{ + MemAllocatorProxy *pool; + + if ((pool = squidaio_get_pool(size)) != NULL) { + pool->free(p); + } else + xfree(p); +} + +static void +squidaio_xstrfree(char *str) +{ + MemAllocatorProxy *pool; + int len = strlen(str) + 1; + + if ((pool = squidaio_get_pool(len)) != NULL) { + pool->free(str); + } else + xfree(str); +} + +static void +squidaio_init(void) +{ + int i; + squidaio_thread_t *threadp; + + if (squidaio_initialised) + return; + + if (!DuplicateHandle(GetCurrentProcess(), /* pseudo handle, don't close */ + GetCurrentThread(), /* pseudo handle to copy */ + GetCurrentProcess(), /* pseudo handle, don't close */ + &main_thread, + 0, /* required access */ + FALSE, /* child process's don't inherit the handle */ + DUPLICATE_SAME_ACCESS)) { + /* spit errors */ + fatal("Couldn't get current thread handle"); + } + + /* Initialize request queue */ + if ((request_queue.mutex = CreateMutex(NULL, /* no inheritance */ + FALSE, /* start unowned (as per mutex_init) */ + NULL) /* no name */ + ) == NULL) { + fatal("Failed to create mutex"); + } + + if ((request_queue.cond = CreateEvent(NULL, /* no inheritance */ + FALSE, /* auto signal reset - which I think is pthreads like ? */ + FALSE, /* start non signaled */ + NULL) /* no name */ + ) == NULL) { + fatal("Failed to create condition variable"); + } + + request_queue.head = NULL; + + request_queue.tailp = &request_queue.head; + + request_queue.requests = 0; + + request_queue.blocked = 0; + + /* Initialize done queue */ + if ((done_queue.mutex = CreateMutex(NULL, /* no inheritance */ + FALSE, /* start unowned (as per mutex_init) */ + NULL) /* no name */ + ) == NULL) { + fatal("Failed to create mutex"); + } + + if ((done_queue.cond = CreateEvent(NULL, /* no inheritance */ + TRUE, /* manually signaled - which I think is pthreads like ? */ + FALSE, /* start non signaled */ + NULL) /* no name */ + ) == NULL) { + fatal("Failed to create condition variable"); + } + + done_queue.head = NULL; + + done_queue.tailp = &done_queue.head; + + done_queue.requests = 0; + + done_queue.blocked = 0; + + /* Create threads and get them to sit in their wait loop */ + squidaio_thread_pool = new MemAllocatorProxy("aio_thread", sizeof(squidaio_thread_t)); + + assert(NUMTHREADS); + + for (i = 0; i < NUMTHREADS; i++) { + threadp = (squidaio_thread_t *)squidaio_thread_pool->alloc(); + threadp->status = _THREAD_STARTING; + threadp->current_req = NULL; + threadp->requests = 0; + threadp->next = threads; + threads = threadp; + + if ((threadp->thread = CreateThread(NULL, /* no security attributes */ + 0, /* use default stack size */ + squidaio_thread_loop, /* thread function */ + threadp, /* argument to thread function */ + 0, /* use default creation flags */ + &(threadp->dwThreadId)) /* returns the thread identifier */ + ) == NULL) { + fprintf(stderr, "Thread creation failed\n"); + threadp->status = _THREAD_FAILED; + continue; + } + + /* Set the new thread priority above parent process */ + SetThreadPriority(threadp->thread,THREAD_PRIORITY_ABOVE_NORMAL); + } + + /* Create request pool */ + squidaio_request_pool = new MemAllocatorProxy("aio_request", sizeof(squidaio_request_t)); + + squidaio_large_bufs = new MemAllocatorProxy("squidaio_large_bufs", AIO_LARGE_BUFS); + + squidaio_medium_bufs = new MemAllocatorProxy("squidaio_medium_bufs", AIO_MEDIUM_BUFS); + + squidaio_small_bufs = new MemAllocatorProxy("squidaio_small_bufs", AIO_SMALL_BUFS); + + squidaio_tiny_bufs = new MemAllocatorProxy("squidaio_tiny_bufs", AIO_TINY_BUFS); + + squidaio_micro_bufs = new MemAllocatorProxy("squidaio_micro_bufs", AIO_MICRO_BUFS); + + squidaio_initialised = 1; +} + +void +squidaio_shutdown(void) +{ + squidaio_thread_t *threadp; + int i; + HANDLE * hthreads; + + if (!squidaio_initialised) + return; + + hthreads = (HANDLE *) xcalloc (NUMTHREADS, sizeof (HANDLE)); + threadp = threads; + for (i = 0; i < NUMTHREADS; i++) { + threadp->exit = 1; + hthreads[i] = threadp->thread; + threadp = threadp->next; + } + ReleaseMutex(request_queue.mutex); + ResetEvent(request_queue.cond); + ReleaseMutex(done_queue.mutex); + ResetEvent(done_queue.cond); + Sleep(0); + + WaitForMultipleObjects(NUMTHREADS, hthreads, TRUE, 2000); + for (i = 0; i < NUMTHREADS; i++) { + CloseHandle(hthreads[i]); + } + CloseHandle(main_thread); + squidaio_initialised = 0; + xfree(hthreads); +} + +static DWORD WINAPI +squidaio_thread_loop(LPVOID lpParam) +{ + squidaio_thread_t *threadp = (squidaio_thread_t *)lpParam; + squidaio_request_t *request; + HANDLE cond; /* local copy of the event queue because win32 event handles + * don't atomically release the mutex as cond variables do. */ + + /* lock the thread info */ + if (WAIT_FAILED == WaitForSingleObject(request_queue.mutex, INFINITE)) { + fatal("Can't get ownership of mutex\n"); + } + /* duplicate the handle */ + if (!DuplicateHandle(GetCurrentProcess(), /* pseudo handle, don't close */ + request_queue.cond, /* handle to copy */ + GetCurrentProcess(), /* pseudo handle, don't close */ + &cond, + 0, /* required access */ + FALSE, /* child process's don't inherit the handle */ + DUPLICATE_SAME_ACCESS)) + fatal("Can't duplicate mutex handle\n"); + if (!ReleaseMutex(request_queue.mutex)) { + CloseHandle(cond); + fatal("Can't release mutex\n"); + } + Sleep(0); + + while (1) { + DWORD rv; + threadp->current_req = request = NULL; + request = NULL; + /* Get a request to process */ + threadp->status = _THREAD_WAITING; + if (threadp->exit) { + CloseHandle(request_queue.mutex); + CloseHandle(cond); + return 0; + } + rv = WaitForSingleObject(request_queue.mutex, INFINITE); + if (rv == WAIT_FAILED) { + CloseHandle(cond); + return 1; + } + + while (!request_queue.head) { + if (!ReleaseMutex(request_queue.mutex)) { + CloseHandle(cond); + threadp->status = _THREAD_FAILED; + return 1; + } + Sleep(0); + rv = WaitForSingleObject(cond, INFINITE); + if (rv == WAIT_FAILED) { + CloseHandle(cond); + return 1; + } + rv = WaitForSingleObject(request_queue.mutex, INFINITE); + if (rv == WAIT_FAILED) { + CloseHandle(cond); + return 1; + } + } + + request = request_queue.head; + + if (request) + request_queue.head = request->next; + + if (!request_queue.head) + request_queue.tailp = &request_queue.head; + + if (!ReleaseMutex(request_queue.mutex)) { + CloseHandle(cond); + return 1; + } + + Sleep(0); + + /* process the request */ + threadp->status = _THREAD_BUSY; + + request->next = NULL; + + threadp->current_req = request; + + errno = 0; + + if (!request->cancelled) { + switch (request->request_type) { + + case _AIO_OP_OPEN: + squidaio_do_open(request); + break; + + case _AIO_OP_READ: + squidaio_do_read(request); + break; + + case _AIO_OP_WRITE: + squidaio_do_write(request); + break; + + case _AIO_OP_CLOSE: + squidaio_do_close(request); + break; + + case _AIO_OP_UNLINK: + squidaio_do_unlink(request); + break; + + case _AIO_OP_TRUNCATE: + squidaio_do_truncate(request); + break; +#if AIO_OPENDIR /* Opendir not implemented yet */ + + case _AIO_OP_OPENDIR: + squidaio_do_opendir(request); + break; +#endif + + case _AIO_OP_STAT: + squidaio_do_stat(request); + break; + + default: + request->ret = -1; + request->err = EINVAL; + break; + } + } else { /* cancelled */ + request->ret = -1; + request->err = EINTR; + } + + threadp->status = _THREAD_DONE; + /* put the request in the done queue */ + rv = WaitForSingleObject(done_queue.mutex, INFINITE); + if (rv == WAIT_FAILED) { + CloseHandle(cond); + return 1; + } + + *done_queue.tailp = request; + done_queue.tailp = &request->next; + if (!ReleaseMutex(done_queue.mutex)) { + CloseHandle(cond); + return 1; + } + + CommIO::NotifyIOCompleted(); + Sleep(0); + threadp->requests++; + } /* while forever */ + + CloseHandle(cond); + return 0; +} /* squidaio_thread_loop */ + +static void +squidaio_queue_request(squidaio_request_t * request) +{ + static int high_start = 0; + debug(43, 9) ("squidaio_queue_request: %p type=%d result=%p\n", + request, request->request_type, request->resultp); + /* Mark it as not executed (failing result, no error) */ + request->ret = -1; + request->err = 0; + /* Internal housekeeping */ + request_queue_len += 1; + request->resultp->_data = request; + /* Play some tricks with the request_queue2 queue */ + request->next = NULL; + + if (WaitForSingleObject(request_queue.mutex, 0) == WAIT_OBJECT_0) { + if (request_queue2.head) { + /* Grab blocked requests */ + *request_queue.tailp = request_queue2.head; + request_queue.tailp = request_queue2.tailp; + } + + /* Enqueue request */ + *request_queue.tailp = request; + + request_queue.tailp = &request->next; + + if (!SetEvent(request_queue.cond)) + fatal("Couldn't push queue"); + + if (!ReleaseMutex(request_queue.mutex)) { + /* unexpected error */ + fatal("Couldn't push queue"); + } + + Sleep(0); + + if (request_queue2.head) { + /* Clear queue of blocked requests */ + request_queue2.head = NULL; + request_queue2.tailp = &request_queue2.head; + } + } else { + /* Oops, the request queue is blocked, use request_queue2 */ + *request_queue2.tailp = request; + request_queue2.tailp = &request->next; + } + + if (request_queue2.head) { + static int filter = 0; + static int filter_limit = 8; + + if (++filter >= filter_limit) { + filter_limit += filter; + filter = 0; + debug(43, 1) ("squidaio_queue_request: WARNING - Queue congestion\n"); + } + } + + /* Warn if out of threads */ + if (request_queue_len > MAGIC1) { + static int last_warn = 0; + static int queue_high, queue_low; + + if (high_start == 0) { + high_start = (int)squid_curtime; + queue_high = request_queue_len; + queue_low = request_queue_len; + } + + if (request_queue_len > queue_high) + queue_high = request_queue_len; + + if (request_queue_len < queue_low) + queue_low = request_queue_len; + + if (squid_curtime >= (last_warn + 15) && + squid_curtime >= (high_start + 5)) { + debug(43, 1) ("squidaio_queue_request: WARNING - Disk I/O overloading\n"); + + if (squid_curtime >= (high_start + 15)) + debug(43, 1) ("squidaio_queue_request: Queue Length: current=%d, high=%d, low=%d, duration=%ld\n", + request_queue_len, queue_high, queue_low, (long int) (squid_curtime - high_start)); + + last_warn = (int)squid_curtime; + } + } else { + high_start = 0; + } + + /* Warn if seriously overloaded */ + if (request_queue_len > RIDICULOUS_LENGTH) { + debug(43, 0) ("squidaio_queue_request: Async request queue growing uncontrollably!\n"); + debug(43, 0) ("squidaio_queue_request: Syncing pending I/O operations.. (blocking)\n"); + squidaio_sync(); + debug(43, 0) ("squidaio_queue_request: Synced\n"); + } +} /* squidaio_queue_request */ + +static void +squidaio_cleanup_request(squidaio_request_t * requestp) +{ + squidaio_result_t *resultp = requestp->resultp; + int cancelled = requestp->cancelled; + + /* Free allocated structures and copy data back to user space if the */ + /* request hasn't been cancelled */ + + switch (requestp->request_type) { + + case _AIO_OP_STAT: + + if (!cancelled && requestp->ret == 0) + + xmemcpy(requestp->statp, requestp->tmpstatp, sizeof(struct stat)); + + squidaio_xfree(requestp->tmpstatp, sizeof(struct stat)); + + squidaio_xstrfree(requestp->path); + + break; + + case _AIO_OP_OPEN: + if (cancelled && requestp->ret >= 0) + /* The open() was cancelled but completed */ + close(requestp->ret); + + squidaio_xstrfree(requestp->path); + + break; + + case _AIO_OP_CLOSE: + if (cancelled && requestp->ret < 0) + /* The close() was cancelled and never got executed */ + close(requestp->fd); + + break; + + case _AIO_OP_UNLINK: + + case _AIO_OP_TRUNCATE: + + case _AIO_OP_OPENDIR: + squidaio_xstrfree(requestp->path); + + break; + + case _AIO_OP_READ: + break; + + case _AIO_OP_WRITE: + squidaio_xfree(requestp->tmpbufp, requestp->buflen); + + break; + + default: + break; + } + + if (resultp != NULL && !cancelled) { + resultp->aio_return = requestp->ret; + resultp->aio_errno = requestp->err; + } + + squidaio_request_pool->free(requestp); +} /* squidaio_cleanup_request */ + + +int +squidaio_cancel(squidaio_result_t * resultp) +{ + squidaio_request_t *request = (squidaio_request_t *)resultp->_data; + + if (request && request->resultp == resultp) { + debug(43, 9) ("squidaio_cancel: %p type=%d result=%p\n", + request, request->request_type, request->resultp); + request->cancelled = 1; + request->resultp = NULL; + resultp->_data = NULL; + resultp->result_type = _AIO_OP_NONE; + return 0; + } + + return 1; +} /* squidaio_cancel */ + + +int +squidaio_open(const char *path, int oflag, mode_t mode, squidaio_result_t * resultp) +{ + squidaio_request_t *requestp; + + if (!squidaio_initialised) + squidaio_init(); + + requestp = (squidaio_request_t *)squidaio_request_pool->alloc(); + + requestp->path = (char *) squidaio_xstrdup(path); + + requestp->oflag = oflag; + + requestp->mode = mode; + + requestp->resultp = resultp; + + requestp->request_type = _AIO_OP_OPEN; + + requestp->cancelled = 0; + + resultp->result_type = _AIO_OP_OPEN; + + squidaio_queue_request(requestp); + + return 0; +} + + +static void +squidaio_do_open(squidaio_request_t * requestp) +{ + requestp->ret = open(requestp->path, requestp->oflag, requestp->mode); + requestp->err = errno; +} + + +int +squidaio_read(int fd, char *bufp, int bufs, off_t offset, int whence, squidaio_result_t * resultp) +{ + squidaio_request_t *requestp; + + if (!squidaio_initialised) + squidaio_init(); + + requestp = (squidaio_request_t *)squidaio_request_pool->alloc(); + + requestp->fd = fd; + + requestp->bufferp = bufp; + + requestp->buflen = bufs; + + requestp->offset = offset; + + requestp->whence = whence; + + requestp->resultp = resultp; + + requestp->request_type = _AIO_OP_READ; + + requestp->cancelled = 0; + + resultp->result_type = _AIO_OP_READ; + + squidaio_queue_request(requestp); + + return 0; +} + + +static void +squidaio_do_read(squidaio_request_t * requestp) +{ + lseek(requestp->fd, requestp->offset, requestp->whence); +#ifdef _SQUID_MSWIN_ + if (!ReadFile((HANDLE)_get_osfhandle(requestp->fd), requestp->bufferp, + requestp->buflen, (LPDWORD)&requestp->ret, NULL)) { + WIN32_maperror(GetLastError()); + requestp->ret = -1; + } +#else + requestp->ret = read(requestp->fd, requestp->bufferp, requestp->buflen); +#endif + requestp->err = errno; +} + + +int +squidaio_write(int fd, char *bufp, int bufs, off_t offset, int whence, squidaio_result_t * resultp) +{ + squidaio_request_t *requestp; + + if (!squidaio_initialised) + squidaio_init(); + + requestp = (squidaio_request_t *)squidaio_request_pool->alloc(); + + requestp->fd = fd; + + requestp->tmpbufp = (char *) squidaio_xmalloc(bufs); + + xmemcpy(requestp->tmpbufp, bufp, bufs); + + requestp->buflen = bufs; + + requestp->offset = offset; + + requestp->whence = whence; + + requestp->resultp = resultp; + + requestp->request_type = _AIO_OP_WRITE; + + requestp->cancelled = 0; + + resultp->result_type = _AIO_OP_WRITE; + + squidaio_queue_request(requestp); + + return 0; +} + + +static void +squidaio_do_write(squidaio_request_t * requestp) +{ +#ifdef _SQUID_MSWIN_ + if (!WriteFile((HANDLE)_get_osfhandle(requestp->fd), requestp->tmpbufp, + requestp->buflen, (LPDWORD)&requestp->ret, NULL)) { + WIN32_maperror(GetLastError()); + requestp->ret = -1; + } +#else + requestp->ret = write(requestp->fd, requestp->tmpbufp, requestp->buflen); +#endif + requestp->err = errno; +} + + +int +squidaio_close(int fd, squidaio_result_t * resultp) +{ + squidaio_request_t *requestp; + + if (!squidaio_initialised) + squidaio_init(); + + requestp = (squidaio_request_t *)squidaio_request_pool->alloc(); + + requestp->fd = fd; + + requestp->resultp = resultp; + + requestp->request_type = _AIO_OP_CLOSE; + + requestp->cancelled = 0; + + resultp->result_type = _AIO_OP_CLOSE; + + squidaio_queue_request(requestp); + + return 0; +} + + +static void +squidaio_do_close(squidaio_request_t * requestp) +{ + if((requestp->ret = close(requestp->fd)) < 0) { + debug(43, 0) ("squidaio_do_close: FD %d, errno %d\n", requestp->fd, errno); + close(requestp->fd); + } + requestp->err = errno; +} + + +int + +squidaio_stat(const char *path, struct stat *sb, squidaio_result_t * resultp) +{ + squidaio_request_t *requestp; + + if (!squidaio_initialised) + squidaio_init(); + + requestp = (squidaio_request_t *)squidaio_request_pool->alloc(); + + requestp->path = (char *) squidaio_xstrdup(path); + + requestp->statp = sb; + + requestp->tmpstatp = (struct stat *) squidaio_xmalloc(sizeof(struct stat)); + + requestp->resultp = resultp; + + requestp->request_type = _AIO_OP_STAT; + + requestp->cancelled = 0; + + resultp->result_type = _AIO_OP_STAT; + + squidaio_queue_request(requestp); + + return 0; +} + + +static void +squidaio_do_stat(squidaio_request_t * requestp) +{ + requestp->ret = stat(requestp->path, requestp->tmpstatp); + requestp->err = errno; +} + + +int +squidaio_unlink(const char *path, squidaio_result_t * resultp) +{ + squidaio_request_t *requestp; + + if (!squidaio_initialised) + squidaio_init(); + + requestp = (squidaio_request_t *)squidaio_request_pool->alloc(); + + requestp->path = squidaio_xstrdup(path); + + requestp->resultp = resultp; + + requestp->request_type = _AIO_OP_UNLINK; + + requestp->cancelled = 0; + + resultp->result_type = _AIO_OP_UNLINK; + + squidaio_queue_request(requestp); + + return 0; +} + + +static void +squidaio_do_unlink(squidaio_request_t * requestp) +{ + requestp->ret = unlink(requestp->path); + requestp->err = errno; +} + +int +squidaio_truncate(const char *path, off_t length, squidaio_result_t * resultp) +{ + squidaio_request_t *requestp; + + if (!squidaio_initialised) + squidaio_init(); + + requestp = (squidaio_request_t *)squidaio_request_pool->alloc(); + + requestp->path = (char *) squidaio_xstrdup(path); + + requestp->offset = length; + + requestp->resultp = resultp; + + requestp->request_type = _AIO_OP_TRUNCATE; + + requestp->cancelled = 0; + + resultp->result_type = _AIO_OP_TRUNCATE; + + squidaio_queue_request(requestp); + + return 0; +} + + +static void +squidaio_do_truncate(squidaio_request_t * requestp) +{ + requestp->ret = truncate(requestp->path, requestp->offset); + requestp->err = errno; +} + + +#if AIO_OPENDIR +/* XXX squidaio_opendir NOT implemented yet.. */ + +int +squidaio_opendir(const char *path, squidaio_result_t * resultp) +{ + squidaio_request_t *requestp; + int len; + + if (!squidaio_initialised) + squidaio_init(); + + requestp = squidaio_request_pool->alloc(); + + resultp->result_type = _AIO_OP_OPENDIR; + + return -1; +} + +static void +squidaio_do_opendir(squidaio_request_t * requestp) +{ + /* NOT IMPLEMENTED */ +} + +#endif + +static void +squidaio_poll_queues(void) +{ + /* kick "overflow" request queue */ + + if (request_queue2.head && + (WaitForSingleObject(request_queue.mutex, 0 )== WAIT_OBJECT_0)) { + *request_queue.tailp = request_queue2.head; + request_queue.tailp = request_queue2.tailp; + if (!SetEvent(request_queue.cond)) + fatal("couldn't push queue\n"); + if (!ReleaseMutex(request_queue.mutex)) { + /* unexpected error */ + } + + Sleep(0); + request_queue2.head = NULL; + request_queue2.tailp = &request_queue2.head; + } + + /* poll done queue */ + if (done_queue.head && + (WaitForSingleObject(done_queue.mutex, 0)==WAIT_OBJECT_0)) { + + struct squidaio_request_t *requests = done_queue.head; + done_queue.head = NULL; + done_queue.tailp = &done_queue.head; + if (!ReleaseMutex(done_queue.mutex)) { + /* unexpected error */ + } + Sleep(0); + *done_requests.tailp = requests; + request_queue_len -= 1; + + while (requests->next) { + requests = requests->next; + request_queue_len -= 1; + } + + done_requests.tailp = &requests->next; + } +} + +squidaio_result_t * +squidaio_poll_done(void) +{ + squidaio_request_t *request; + squidaio_result_t *resultp; + int cancelled; + int polled = 0; + +AIO_REPOLL: + request = done_requests.head; + + if (request == NULL && !polled) { + CommIO::ResetNotifications(); + squidaio_poll_queues(); + polled = 1; + request = done_requests.head; + } + + if (!request) { + return NULL; + } + + debug(43, 9) ("squidaio_poll_done: %p type=%d result=%p\n", + request, request->request_type, request->resultp); + done_requests.head = request->next; + + if (!done_requests.head) + done_requests.tailp = &done_requests.head; + + resultp = request->resultp; + + cancelled = request->cancelled; + + squidaio_debug(request); + + debug(43, 5) ("DONE: %d -> %d\n", request->ret, request->err); + + squidaio_cleanup_request(request); + + if (cancelled) + goto AIO_REPOLL; + + return resultp; +} /* squidaio_poll_done */ + +int +squidaio_operations_pending(void) +{ + return request_queue_len + (done_requests.head ? 1 : 0); +} + +int +squidaio_sync(void) +{ + /* XXX This might take a while if the queue is large.. */ + + do { + squidaio_poll_queues(); + } while (request_queue_len > 0); + + return squidaio_operations_pending(); +} + +int +squidaio_get_queue_len(void) +{ + return request_queue_len; +} + +static void +squidaio_debug(squidaio_request_t * request) +{ + switch (request->request_type) { + + case _AIO_OP_OPEN: + debug(43, 5) ("OPEN of %s to FD %d\n", request->path, request->ret); + break; + + case _AIO_OP_READ: + debug(43, 5) ("READ on fd: %d\n", request->fd); + break; + + case _AIO_OP_WRITE: + debug(43, 5) ("WRITE on fd: %d\n", request->fd); + break; + + case _AIO_OP_CLOSE: + debug(43, 5) ("CLOSE of fd: %d\n", request->fd); + break; + + case _AIO_OP_UNLINK: + debug(43, 5) ("UNLINK of %s\n", request->path); + break; + + case _AIO_OP_TRUNCATE: + debug(43, 5) ("UNLINK of %s\n", request->path); + break; + + default: + break; + } +} + +void +squidaio_stats(StoreEntry * sentry) +{ + squidaio_thread_t *threadp; + int i; + + if (!squidaio_initialised) + return; + + storeAppendPrintf(sentry, "\n\nThreads Status:\n"); + storeAppendPrintf(sentry, "#\tID\t# Requests\n"); + + threadp = threads; + for (i = 0; i < NUMTHREADS; i++) { + storeAppendPrintf(sentry, "%i\t0x%lx\t%ld\n", i + 1, threadp->dwThreadId, threadp->requests); + threadp = threadp->next; + } +} --- /dev/null Wed Feb 14 13:33:00 2007 +++ squid3/src/DiskIO/WinDiskThreads/async_io.cc Wed Feb 14 13:34:04 2007 @@ -0,0 +1,249 @@ + +/* + * $Id: async_io.cc,v 1.1.2.1 2005/01/01 18:54:31 serassio Exp $ + * + * DEBUG: section 32 Asynchronous Disk I/O + * AUTHOR: Pete Bentley + * AUTHOR: Stewart Forster + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" +#include "WinDiskThreads.h" +#include "Store.h" +#include "fde.h" +#include "WinDiskThreadsIOStrategy.h" +#include "Generic.h" + +AIOCounts squidaio_counts; + +typedef struct squidaio_unlinkq_t +{ + char *path; + + struct squidaio_unlinkq_t *next; +} + +squidaio_unlinkq_t; + +dlink_list used_list; + +void +aioOpen(const char *path, int oflag, mode_t mode, AIOCB * callback, void *callback_data) +{ + squidaio_ctrl_t *ctrlp; + + assert(WinDiskThreadsIOStrategy::Instance.initialised); + squidaio_counts.open_start++; + ctrlp = (squidaio_ctrl_t *)WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->alloc(); + ctrlp->fd = -2; + ctrlp->done_handler = callback; + ctrlp->done_handler_data = cbdataReference(callback_data); + ctrlp->operation = _AIO_OPEN; + ctrlp->result.data = ctrlp; + squidaio_open(path, oflag, mode, &ctrlp->result); + dlinkAdd(ctrlp, &ctrlp->node, &used_list); + return; +} + +void +aioClose(int fd) +{ + squidaio_ctrl_t *ctrlp; + + assert(WinDiskThreadsIOStrategy::Instance.initialised); + squidaio_counts.close_start++; + aioCancel(fd); + ctrlp = (squidaio_ctrl_t *)WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->alloc(); + ctrlp->fd = fd; + ctrlp->done_handler = NULL; + ctrlp->done_handler_data = NULL; + ctrlp->operation = _AIO_CLOSE; + ctrlp->result.data = ctrlp; + squidaio_close(fd, &ctrlp->result); + dlinkAdd(ctrlp, &ctrlp->node, &used_list); + return; +} + +void +aioCancel(int fd) +{ + squidaio_ctrl_t *ctrlp; + dlink_node *m, *next; + + assert(WinDiskThreadsIOStrategy::Instance.initialised); + squidaio_counts.cancel++; + + for (m = used_list.head; m; m = next) { + next = m->next; + ctrlp = (squidaio_ctrl_t *)m->data; + + if (ctrlp->fd != fd) + continue; + + squidaio_cancel(&ctrlp->result); + + if (ctrlp->done_handler) { + AIOCB *callback = ctrlp->done_handler; + void *cbdata; + ctrlp->done_handler = NULL; + debug(32, 1) ("this be aioCancel. Danger ahead!\n"); + + if (cbdataReferenceValidDone(ctrlp->done_handler_data, &cbdata)) + callback(fd, cbdata, NULL, -2, -2); + + /* free data if requested to aioWrite() */ + if (ctrlp->free_func) + ctrlp->free_func(ctrlp->bufp); + + /* free temporary read buffer */ + if (ctrlp->operation == _AIO_READ) + squidaio_xfree(ctrlp->bufp, ctrlp->len); + } + + dlinkDelete(m, &used_list); + WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->free(ctrlp); + } +} + + +void +aioWrite(int fd, int offset, char *bufp, int len, AIOCB * callback, void *callback_data, FREE * free_func) +{ + squidaio_ctrl_t *ctrlp; + int seekmode; + + assert(WinDiskThreadsIOStrategy::Instance.initialised); + squidaio_counts.write_start++; + ctrlp = (squidaio_ctrl_t *)WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->alloc(); + ctrlp->fd = fd; + ctrlp->done_handler = callback; + ctrlp->done_handler_data = cbdataReference(callback_data); + ctrlp->operation = _AIO_WRITE; + ctrlp->bufp = bufp; + ctrlp->free_func = free_func; + + if (offset >= 0) + seekmode = SEEK_SET; + else { + seekmode = SEEK_END; + offset = 0; + } + + ctrlp->result.data = ctrlp; + squidaio_write(fd, bufp, len, offset, seekmode, &ctrlp->result); + dlinkAdd(ctrlp, &ctrlp->node, &used_list); +} /* aioWrite */ + + +void +aioRead(int fd, int offset, int len, AIOCB * callback, void *callback_data) +{ + squidaio_ctrl_t *ctrlp; + int seekmode; + + assert(WinDiskThreadsIOStrategy::Instance.initialised); + squidaio_counts.read_start++; + ctrlp = (squidaio_ctrl_t *)WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->alloc(); + ctrlp->fd = fd; + ctrlp->done_handler = callback; + ctrlp->done_handler_data = cbdataReference(callback_data); + ctrlp->operation = _AIO_READ; + ctrlp->len = len; + ctrlp->bufp = (char *)squidaio_xmalloc(len); + + if (offset >= 0) + seekmode = SEEK_SET; + else { + seekmode = SEEK_CUR; + offset = 0; + } + + ctrlp->result.data = ctrlp; + squidaio_read(fd, ctrlp->bufp, len, offset, seekmode, &ctrlp->result); + dlinkAdd(ctrlp, &ctrlp->node, &used_list); + return; +} /* aioRead */ + +void + +aioStat(char *path, struct stat *sb, AIOCB * callback, void *callback_data) +{ + squidaio_ctrl_t *ctrlp; + + assert(WinDiskThreadsIOStrategy::Instance.initialised); + squidaio_counts.stat_start++; + ctrlp = (squidaio_ctrl_t *)WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->alloc(); + ctrlp->fd = -2; + ctrlp->done_handler = callback; + ctrlp->done_handler_data = cbdataReference(callback_data); + ctrlp->operation = _AIO_STAT; + ctrlp->result.data = ctrlp; + squidaio_stat(path, sb, &ctrlp->result); + dlinkAdd(ctrlp, &ctrlp->node, &used_list); + return; +} /* aioStat */ + +void +aioUnlink(const char *path, AIOCB * callback, void *callback_data) +{ + squidaio_ctrl_t *ctrlp; + assert(WinDiskThreadsIOStrategy::Instance.initialised); + squidaio_counts.unlink_start++; + ctrlp = (squidaio_ctrl_t *)WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->alloc(); + ctrlp->fd = -2; + ctrlp->done_handler = callback; + ctrlp->done_handler_data = cbdataReference(callback_data); + ctrlp->operation = _AIO_UNLINK; + ctrlp->result.data = ctrlp; + squidaio_unlink(path, &ctrlp->result); + dlinkAdd(ctrlp, &ctrlp->node, &used_list); +} /* aioUnlink */ + +void +aioTruncate(const char *path, off_t length, AIOCB * callback, void *callback_data) +{ + squidaio_ctrl_t *ctrlp; + assert(WinDiskThreadsIOStrategy::Instance.initialised); + squidaio_counts.unlink_start++; + ctrlp = (squidaio_ctrl_t *)WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->alloc(); + ctrlp->fd = -2; + ctrlp->done_handler = callback; + ctrlp->done_handler_data = cbdataReference(callback_data); + ctrlp->operation = _AIO_TRUNCATE; + ctrlp->result.data = ctrlp; + squidaio_truncate(path, length, &ctrlp->result); + dlinkAdd(ctrlp, &ctrlp->node, &used_list); +} /* aioTruncate */ + +int +aioQueueSize(void) +{ + return WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->inUseCount(); +} Index: squid3/src/fs/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/fs/Makefile.am,v retrieving revision 1.5.2.9 retrieving revision 1.5.2.10 diff -u -r1.5.2.9 -r1.5.2.10 --- squid3/src/fs/Makefile.am 28 Dec 2004 17:18:22 -0000 1.5.2.9 +++ squid3/src/fs/Makefile.am 1 Jan 2005 18:51:04 -0000 1.5.2.10 @@ -1,19 +1,15 @@ # Makefile for storage modules in the Squid Object Cache server # -# $Id: Makefile.am,v 1.5.2.9 2004/12/28 17:18:22 serassio Exp $ +# $Id: Makefile.am,v 1.5.2.10 2005/01/01 18:51:04 serassio Exp $ # AUTOMAKE_OPTIONS = subdir-objects AM_CFLAGS = @SQUID_CFLAGS@ AM_CXXFLAGS = @SQUID_CXXFLAGS@ +##DIST_SUBDIRS = coss null ufs -## FIX AWIN32 !!! SG -##DIST_SUBDIRS = awin32 coss null ufs - - - -EXTRA_LIBRARIES = libcoss.a libnull.a libufs.a libawin32.a +EXTRA_LIBRARIES = libcoss.a libnull.a libufs.a noinst_LIBRARIES = @STORE_LIBS@ if ENABLE_WIN32SPECIFIC @@ -24,8 +20,6 @@ -I$(top_srcdir)/src/ endif -libawin32_a_SOURCES = awin32/aiops.cc awin32/async_io.cc awin32/store_asyncufs.h \ - awin32/store_io_aufs.cc libcoss_a_SOURCES = \ coss/store_coss.h \ coss/store_io_coss.cc \ @@ -52,5 +46,3 @@ null/clean: clean ufs/all: libufs.a ufs/clean: clean -awin32/all: libawin32.a -awin32/clean: clean --- squid3/src/fs/awin32/.ccvsignore Wed Feb 14 13:34:04 2007 +++ /dev/null Wed Feb 14 13:33:00 2007 @@ -1,2 +0,0 @@ -.cvsignore -Makefile.in --- /dev/null Wed Feb 14 13:33:00 2007 +++ squid3/src/fs/awin32/.cvsignore Wed Feb 14 13:34:04 2007 @@ -0,0 +1,2 @@ +.cvsignore +Makefile.in Index: squid3/src/fs/awin32/StoreFSawin32.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/fs/awin32/Attic/StoreFSawin32.cc,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- squid3/src/fs/awin32/StoreFSawin32.cc 3 Aug 2003 16:32:02 -0000 1.1.2.1 +++ squid3/src/fs/awin32/StoreFSawin32.cc 1 Jan 2005 18:50:17 -0000 1.1.2.2 @@ -1,6 +1,6 @@ /* - * $Id: StoreFSawin32.cc,v 1.1.2.1 2003/08/03 16:32:02 serassio Exp $ + * $Id: StoreFSawin32.cc,v 1.1.2.2 2005/01/01 18:50:17 serassio Exp $ * * DEBUG: section 47 Store Directory Routines * AUTHOR: Robert Collins @@ -37,6 +37,6 @@ #include "squid.h" #include "StoreFileSystem.h" #include "fs/ufs/StoreFSufs.h" -#include "fs/awin32/store_asyncufs.h" +#include "DiskIO/DiskIOModule.h" -static StoreFSufs AufsInstance(AufsIOModule::GetInstance(), "awin32"); +static StoreFSufs AufsInstance("WinDiskThreads", "awin32"); --- squid3/src/fs/awin32/aiops.cc Wed Feb 14 13:34:04 2007 +++ /dev/null Wed Feb 14 13:33:00 2007 @@ -1,1209 +0,0 @@ -/* - * $Id: aiops.cc,v 1.2.18.5 2004/10/03 11:56:47 serassio Exp $ - * - * DEBUG: section 43 AIOPS - * AUTHOR: Stewart Forster - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "squid_windows.h" -#include "store_asyncufs.h" - -#include -#include -#include -#include -#include -#include -#include -#include "comm.h" - -#define RIDICULOUS_LENGTH 4096 - -enum _squidaio_thread_status { - _THREAD_STARTING = 0, - _THREAD_WAITING, - _THREAD_BUSY, - _THREAD_FAILED, - _THREAD_DONE -}; -typedef enum _squidaio_thread_status squidaio_thread_status; - -typedef struct squidaio_request_t -{ - - struct squidaio_request_t *next; - squidaio_request_type request_type; - int cancelled; - char *path; - int oflag; - mode_t mode; - int fd; - char *bufferp; - char *tmpbufp; - int buflen; - off_t offset; - int whence; - int ret; - int err; - - struct stat *tmpstatp; - - struct stat *statp; - squidaio_result_t *resultp; -} - -squidaio_request_t; - -typedef struct squidaio_request_queue_t -{ - HANDLE mutex; - HANDLE cond; /* See Event objects */ - squidaio_request_t *volatile head; - squidaio_request_t *volatile *volatile tailp; - unsigned long requests; - unsigned long blocked; /* main failed to lock the queue */ -} - -squidaio_request_queue_t; - -typedef struct squidaio_thread_t squidaio_thread_t; - -struct squidaio_thread_t -{ - squidaio_thread_t *next; - HANDLE thread; - DWORD dwThreadId; /* thread ID */ - squidaio_thread_status status; - - struct squidaio_request_t *current_req; - unsigned long requests; - int volatile exit; -}; - -static void squidaio_init(void); -static void squidaio_queue_request(squidaio_request_t *); -static void squidaio_cleanup_request(squidaio_request_t *); -static DWORD WINAPI squidaio_thread_loop( LPVOID lpParam ); -static void squidaio_do_open(squidaio_request_t *); -static void squidaio_do_read(squidaio_request_t *); -static void squidaio_do_write(squidaio_request_t *); -static void squidaio_do_close(squidaio_request_t *); -static void squidaio_do_stat(squidaio_request_t *); -static void squidaio_do_unlink(squidaio_request_t *); -static void squidaio_do_truncate(squidaio_request_t *); -#if AIO_OPENDIR -static void *squidaio_do_opendir(squidaio_request_t *); -#endif -static void squidaio_debug(squidaio_request_t *); -static void squidaio_poll_queues(void); - -static squidaio_thread_t *threads = NULL; -static int squidaio_initialised = 0; - - -#define AIO_LARGE_BUFS 16384 -#define AIO_MEDIUM_BUFS AIO_LARGE_BUFS >> 1 -#define AIO_SMALL_BUFS AIO_LARGE_BUFS >> 2 -#define AIO_TINY_BUFS AIO_LARGE_BUFS >> 3 -#define AIO_MICRO_BUFS 128 - -static MemAllocatorProxy *squidaio_large_bufs = NULL; /* 16K */ -static MemAllocatorProxy *squidaio_medium_bufs = NULL; /* 8K */ -static MemAllocatorProxy *squidaio_small_bufs = NULL; /* 4K */ -static MemAllocatorProxy *squidaio_tiny_bufs = NULL; /* 2K */ -static MemAllocatorProxy *squidaio_micro_bufs = NULL; /* 128K */ - -static int request_queue_len = 0; -static MemAllocatorProxy *squidaio_request_pool = NULL; -static MemAllocatorProxy *squidaio_thread_pool = NULL; -static squidaio_request_queue_t request_queue; - -static struct -{ - squidaio_request_t *head, **tailp; -} - -request_queue2 = { - - NULL, &request_queue2.head - }; -static squidaio_request_queue_t done_queue; - -static struct -{ - squidaio_request_t *head, **tailp; -} - -done_requests = { - - NULL, &done_requests.head - }; - -static HANDLE main_thread; - -static MemAllocatorProxy * -squidaio_get_pool(int size) -{ - MemAllocatorProxy *p; - - if (size <= AIO_LARGE_BUFS) { - if (size <= AIO_MICRO_BUFS) - p = squidaio_micro_bufs; - else if (size <= AIO_TINY_BUFS) - p = squidaio_tiny_bufs; - else if (size <= AIO_SMALL_BUFS) - p = squidaio_small_bufs; - else if (size <= AIO_MEDIUM_BUFS) - p = squidaio_medium_bufs; - else - p = squidaio_large_bufs; - } else - p = NULL; - - return p; -} - -void * -squidaio_xmalloc(int size) -{ - void *p; - MemAllocatorProxy *pool; - - if ((pool = squidaio_get_pool(size)) != NULL) { - p = pool->alloc(); - } else - p = xmalloc(size); - - return p; -} - -static char * -squidaio_xstrdup(const char *str) -{ - char *p; - int len = strlen(str) + 1; - - p = (char *)squidaio_xmalloc(len); - strncpy(p, str, len); - - return p; -} - -void -squidaio_xfree(void *p, int size) -{ - MemAllocatorProxy *pool; - - if ((pool = squidaio_get_pool(size)) != NULL) { - pool->free(p); - } else - xfree(p); -} - -static void -squidaio_xstrfree(char *str) -{ - MemAllocatorProxy *pool; - int len = strlen(str) + 1; - - if ((pool = squidaio_get_pool(len)) != NULL) { - pool->free(str); - } else - xfree(str); -} - -static void -squidaio_init(void) -{ - int i; - squidaio_thread_t *threadp; - - if (squidaio_initialised) - return; - - if (!DuplicateHandle(GetCurrentProcess(), /* pseudo handle, don't close */ - GetCurrentThread(), /* pseudo handle to copy */ - GetCurrentProcess(), /* pseudo handle, don't close */ - &main_thread, - 0, /* required access */ - FALSE, /* child process's don't inherit the handle */ - DUPLICATE_SAME_ACCESS)) { - /* spit errors */ - fatal("Couldn't get current thread handle"); - } - - /* Initialize request queue */ - if ((request_queue.mutex = CreateMutex(NULL, /* no inheritance */ - FALSE, /* start unowned (as per mutex_init) */ - NULL) /* no name */ - ) == NULL) { - fatal("Failed to create mutex"); - } - - if ((request_queue.cond = CreateEvent(NULL, /* no inheritance */ - FALSE, /* auto signal reset - which I think is pthreads like ? */ - FALSE, /* start non signaled */ - NULL) /* no name */ - ) == NULL) { - fatal("Failed to create condition variable"); - } - - request_queue.head = NULL; - - request_queue.tailp = &request_queue.head; - - request_queue.requests = 0; - - request_queue.blocked = 0; - - /* Initialize done queue */ - if ((done_queue.mutex = CreateMutex(NULL, /* no inheritance */ - FALSE, /* start unowned (as per mutex_init) */ - NULL) /* no name */ - ) == NULL) { - fatal("Failed to create mutex"); - } - - if ((done_queue.cond = CreateEvent(NULL, /* no inheritance */ - TRUE, /* manually signaled - which I think is pthreads like ? */ - FALSE, /* start non signaled */ - NULL) /* no name */ - ) == NULL) { - fatal("Failed to create condition variable"); - } - - done_queue.head = NULL; - - done_queue.tailp = &done_queue.head; - - done_queue.requests = 0; - - done_queue.blocked = 0; - - /* Create threads and get them to sit in their wait loop */ - squidaio_thread_pool = new MemAllocatorProxy("aio_thread", sizeof(squidaio_thread_t)); - - assert(NUMTHREADS); - - for (i = 0; i < NUMTHREADS; i++) { - threadp = (squidaio_thread_t *)squidaio_thread_pool->alloc(); - threadp->status = _THREAD_STARTING; - threadp->current_req = NULL; - threadp->requests = 0; - threadp->next = threads; - threads = threadp; - - if ((threadp->thread = CreateThread(NULL, /* no security attributes */ - 0, /* use default stack size */ - squidaio_thread_loop, /* thread function */ - threadp, /* argument to thread function */ - 0, /* use default creation flags */ - &(threadp->dwThreadId)) /* returns the thread identifier */ - ) == NULL) { - fprintf(stderr, "Thread creation failed\n"); - threadp->status = _THREAD_FAILED; - continue; - } - - /* Set the new thread priority above parent process */ - SetThreadPriority(threadp->thread,THREAD_PRIORITY_ABOVE_NORMAL); - } - - /* Create request pool */ - squidaio_request_pool = new MemAllocatorProxy("aio_request", sizeof(squidaio_request_t)); - - squidaio_large_bufs = new MemAllocatorProxy("squidaio_large_bufs", AIO_LARGE_BUFS); - - squidaio_medium_bufs = new MemAllocatorProxy("squidaio_medium_bufs", AIO_MEDIUM_BUFS); - - squidaio_small_bufs = new MemAllocatorProxy("squidaio_small_bufs", AIO_SMALL_BUFS); - - squidaio_tiny_bufs = new MemAllocatorProxy("squidaio_tiny_bufs", AIO_TINY_BUFS); - - squidaio_micro_bufs = new MemAllocatorProxy("squidaio_micro_bufs", AIO_MICRO_BUFS); - - squidaio_initialised = 1; -} - -void -squidaio_shutdown(void) -{ - squidaio_thread_t *threadp; - int i; - HANDLE * hthreads; - - if (!squidaio_initialised) - return; - - hthreads = (HANDLE *) xcalloc (NUMTHREADS, sizeof (HANDLE)); - threadp = threads; - for (i = 0; i < NUMTHREADS; i++) { - threadp->exit = 1; - hthreads[i] = threadp->thread; - threadp = threadp->next; - } - ReleaseMutex(request_queue.mutex); - ResetEvent(request_queue.cond); - ReleaseMutex(done_queue.mutex); - ResetEvent(done_queue.cond); - Sleep(0); - - WaitForMultipleObjects(NUMTHREADS, hthreads, TRUE, 2000); - for (i = 0; i < NUMTHREADS; i++) { - CloseHandle(hthreads[i]); - } - CloseHandle(main_thread); - squidaio_initialised = 0; - xfree(hthreads); -} - -static DWORD WINAPI -squidaio_thread_loop(LPVOID lpParam) -{ - squidaio_thread_t *threadp = (squidaio_thread_t *)lpParam; - squidaio_request_t *request; - HANDLE cond; /* local copy of the event queue because win32 event handles - * don't atomically release the mutex as cond variables do. */ - - /* lock the thread info */ - if (WAIT_FAILED == WaitForSingleObject(request_queue.mutex, INFINITE)) { - fatal("Can't get ownership of mutex\n"); - } - /* duplicate the handle */ - if (!DuplicateHandle(GetCurrentProcess(), /* pseudo handle, don't close */ - request_queue.cond, /* handle to copy */ - GetCurrentProcess(), /* pseudo handle, don't close */ - &cond, - 0, /* required access */ - FALSE, /* child process's don't inherit the handle */ - DUPLICATE_SAME_ACCESS)) - fatal("Can't duplicate mutex handle\n"); - if (!ReleaseMutex(request_queue.mutex)) { - CloseHandle(cond); - fatal("Can't release mutex\n"); - } - Sleep(0); - - while (1) { - DWORD rv; - threadp->current_req = request = NULL; - request = NULL; - /* Get a request to process */ - threadp->status = _THREAD_WAITING; - if (threadp->exit) { - CloseHandle(request_queue.mutex); - CloseHandle(cond); - return 0; - } - rv = WaitForSingleObject(request_queue.mutex, INFINITE); - if (rv == WAIT_FAILED) { - CloseHandle(cond); - return 1; - } - - while (!request_queue.head) { - if (!ReleaseMutex(request_queue.mutex)) { - CloseHandle(cond); - threadp->status = _THREAD_FAILED; - return 1; - } - Sleep(0); - rv = WaitForSingleObject(cond, INFINITE); - if (rv == WAIT_FAILED) { - CloseHandle(cond); - return 1; - } - rv = WaitForSingleObject(request_queue.mutex, INFINITE); - if (rv == WAIT_FAILED) { - CloseHandle(cond); - return 1; - } - } - - request = request_queue.head; - - if (request) - request_queue.head = request->next; - - if (!request_queue.head) - request_queue.tailp = &request_queue.head; - - if (!ReleaseMutex(request_queue.mutex)) { - CloseHandle(cond); - return 1; - } - - Sleep(0); - - /* process the request */ - threadp->status = _THREAD_BUSY; - - request->next = NULL; - - threadp->current_req = request; - - errno = 0; - - if (!request->cancelled) { - switch (request->request_type) { - - case _AIO_OP_OPEN: - squidaio_do_open(request); - break; - - case _AIO_OP_READ: - squidaio_do_read(request); - break; - - case _AIO_OP_WRITE: - squidaio_do_write(request); - break; - - case _AIO_OP_CLOSE: - squidaio_do_close(request); - break; - - case _AIO_OP_UNLINK: - squidaio_do_unlink(request); - break; - - case _AIO_OP_TRUNCATE: - squidaio_do_truncate(request); - break; -#if AIO_OPENDIR /* Opendir not implemented yet */ - - case _AIO_OP_OPENDIR: - squidaio_do_opendir(request); - break; -#endif - - case _AIO_OP_STAT: - squidaio_do_stat(request); - break; - - default: - request->ret = -1; - request->err = EINVAL; - break; - } - } else { /* cancelled */ - request->ret = -1; - request->err = EINTR; - } - - threadp->status = _THREAD_DONE; - /* put the request in the done queue */ - rv = WaitForSingleObject(done_queue.mutex, INFINITE); - if (rv == WAIT_FAILED) { - CloseHandle(cond); - return 1; - } - - *done_queue.tailp = request; - done_queue.tailp = &request->next; - if (!ReleaseMutex(done_queue.mutex)) { - CloseHandle(cond); - return 1; - } - - CommIO::NotifyIOCompleted(); - Sleep(0); - threadp->requests++; - } /* while forever */ - - CloseHandle(cond); - return 0; -} /* squidaio_thread_loop */ - -static void -squidaio_queue_request(squidaio_request_t * request) -{ - static int high_start = 0; - debug(43, 9) ("squidaio_queue_request: %p type=%d result=%p\n", - request, request->request_type, request->resultp); - /* Mark it as not executed (failing result, no error) */ - request->ret = -1; - request->err = 0; - /* Internal housekeeping */ - request_queue_len += 1; - request->resultp->_data = request; - /* Play some tricks with the request_queue2 queue */ - request->next = NULL; - - if (WaitForSingleObject(request_queue.mutex, 0) == WAIT_OBJECT_0) { - if (request_queue2.head) { - /* Grab blocked requests */ - *request_queue.tailp = request_queue2.head; - request_queue.tailp = request_queue2.tailp; - } - - /* Enqueue request */ - *request_queue.tailp = request; - - request_queue.tailp = &request->next; - - if (!SetEvent(request_queue.cond)) - fatal("Couldn't push queue"); - - if (!ReleaseMutex(request_queue.mutex)) { - /* unexpected error */ - fatal("Couldn't push queue"); - } - - Sleep(0); - - if (request_queue2.head) { - /* Clear queue of blocked requests */ - request_queue2.head = NULL; - request_queue2.tailp = &request_queue2.head; - } - } else { - /* Oops, the request queue is blocked, use request_queue2 */ - *request_queue2.tailp = request; - request_queue2.tailp = &request->next; - } - - if (request_queue2.head) { - static int filter = 0; - static int filter_limit = 8; - - if (++filter >= filter_limit) { - filter_limit += filter; - filter = 0; - debug(43, 1) ("squidaio_queue_request: WARNING - Queue congestion\n"); - } - } - - /* Warn if out of threads */ - if (request_queue_len > MAGIC1) { - static int last_warn = 0; - static int queue_high, queue_low; - - if (high_start == 0) { - high_start = squid_curtime; - queue_high = request_queue_len; - queue_low = request_queue_len; - } - - if (request_queue_len > queue_high) - queue_high = request_queue_len; - - if (request_queue_len < queue_low) - queue_low = request_queue_len; - - if (squid_curtime >= (last_warn + 15) && - squid_curtime >= (high_start + 5)) { - debug(43, 1) ("squidaio_queue_request: WARNING - Disk I/O overloading\n"); - - if (squid_curtime >= (high_start + 15)) - debug(43, 1) ("squidaio_queue_request: Queue Length: current=%d, high=%d, low=%d, duration=%ld\n", - request_queue_len, queue_high, queue_low, (long int) (squid_curtime - high_start)); - - last_warn = squid_curtime; - } - } else { - high_start = 0; - } - - /* Warn if seriously overloaded */ - if (request_queue_len > RIDICULOUS_LENGTH) { - debug(43, 0) ("squidaio_queue_request: Async request queue growing uncontrollably!\n"); - debug(43, 0) ("squidaio_queue_request: Syncing pending I/O operations.. (blocking)\n"); - squidaio_sync(); - debug(43, 0) ("squidaio_queue_request: Synced\n"); - } -} /* squidaio_queue_request */ - -static void -squidaio_cleanup_request(squidaio_request_t * requestp) -{ - squidaio_result_t *resultp = requestp->resultp; - int cancelled = requestp->cancelled; - - /* Free allocated structures and copy data back to user space if the */ - /* request hasn't been cancelled */ - - switch (requestp->request_type) { - - case _AIO_OP_STAT: - - if (!cancelled && requestp->ret == 0) - - xmemcpy(requestp->statp, requestp->tmpstatp, sizeof(struct stat)); - - squidaio_xfree(requestp->tmpstatp, sizeof(struct stat)); - - squidaio_xstrfree(requestp->path); - - break; - - case _AIO_OP_OPEN: - if (cancelled && requestp->ret >= 0) - /* The open() was cancelled but completed */ - close(requestp->ret); - - squidaio_xstrfree(requestp->path); - - break; - - case _AIO_OP_CLOSE: - if (cancelled && requestp->ret < 0) - /* The close() was cancelled and never got executed */ - close(requestp->fd); - - break; - - case _AIO_OP_UNLINK: - - case _AIO_OP_TRUNCATE: - - case _AIO_OP_OPENDIR: - squidaio_xstrfree(requestp->path); - - break; - - case _AIO_OP_READ: - break; - - case _AIO_OP_WRITE: - squidaio_xfree(requestp->tmpbufp, requestp->buflen); - - break; - - default: - break; - } - - if (resultp != NULL && !cancelled) { - resultp->aio_return = requestp->ret; - resultp->aio_errno = requestp->err; - } - - squidaio_request_pool->free(requestp); -} /* squidaio_cleanup_request */ - - -int -squidaio_cancel(squidaio_result_t * resultp) -{ - squidaio_request_t *request = (squidaio_request_t *)resultp->_data; - - if (request && request->resultp == resultp) { - debug(43, 9) ("squidaio_cancel: %p type=%d result=%p\n", - request, request->request_type, request->resultp); - request->cancelled = 1; - request->resultp = NULL; - resultp->_data = NULL; - resultp->result_type = _AIO_OP_NONE; - return 0; - } - - return 1; -} /* squidaio_cancel */ - - -int -squidaio_open(const char *path, int oflag, mode_t mode, squidaio_result_t * resultp) -{ - squidaio_request_t *requestp; - - if (!squidaio_initialised) - squidaio_init(); - - requestp = (squidaio_request_t *)squidaio_request_pool->alloc(); - - requestp->path = (char *) squidaio_xstrdup(path); - - requestp->oflag = oflag; - - requestp->mode = mode; - - requestp->resultp = resultp; - - requestp->request_type = _AIO_OP_OPEN; - - requestp->cancelled = 0; - - resultp->result_type = _AIO_OP_OPEN; - - squidaio_queue_request(requestp); - - return 0; -} - - -static void -squidaio_do_open(squidaio_request_t * requestp) -{ - requestp->ret = open(requestp->path, requestp->oflag, requestp->mode); - requestp->err = errno; -} - - -int -squidaio_read(int fd, char *bufp, int bufs, off_t offset, int whence, squidaio_result_t * resultp) -{ - squidaio_request_t *requestp; - - if (!squidaio_initialised) - squidaio_init(); - - requestp = (squidaio_request_t *)squidaio_request_pool->alloc(); - - requestp->fd = fd; - - requestp->bufferp = bufp; - - requestp->buflen = bufs; - - requestp->offset = offset; - - requestp->whence = whence; - - requestp->resultp = resultp; - - requestp->request_type = _AIO_OP_READ; - - requestp->cancelled = 0; - - resultp->result_type = _AIO_OP_READ; - - squidaio_queue_request(requestp); - - return 0; -} - - -static void -squidaio_do_read(squidaio_request_t * requestp) -{ - lseek(requestp->fd, requestp->offset, requestp->whence); -#ifdef _SQUID_MSWIN_ - if (!ReadFile((HANDLE)_get_osfhandle(requestp->fd), requestp->bufferp, - requestp->buflen, (LPDWORD)&requestp->ret, NULL)) { - WIN32_maperror(GetLastError()); - requestp->ret = -1; - } -#else - requestp->ret = read(requestp->fd, requestp->bufferp, requestp->buflen); -#endif - requestp->err = errno; -} - - -int -squidaio_write(int fd, char *bufp, int bufs, off_t offset, int whence, squidaio_result_t * resultp) -{ - squidaio_request_t *requestp; - - if (!squidaio_initialised) - squidaio_init(); - - requestp = (squidaio_request_t *)squidaio_request_pool->alloc(); - - requestp->fd = fd; - - requestp->tmpbufp = (char *) squidaio_xmalloc(bufs); - - xmemcpy(requestp->tmpbufp, bufp, bufs); - - requestp->buflen = bufs; - - requestp->offset = offset; - - requestp->whence = whence; - - requestp->resultp = resultp; - - requestp->request_type = _AIO_OP_WRITE; - - requestp->cancelled = 0; - - resultp->result_type = _AIO_OP_WRITE; - - squidaio_queue_request(requestp); - - return 0; -} - - -static void -squidaio_do_write(squidaio_request_t * requestp) -{ -#ifdef _SQUID_MSWIN_ - if (!WriteFile((HANDLE)_get_osfhandle(requestp->fd), requestp->tmpbufp, - requestp->buflen, (LPDWORD)&requestp->ret, NULL)) { - WIN32_maperror(GetLastError()); - requestp->ret = -1; - } -#else - requestp->ret = write(requestp->fd, requestp->tmpbufp, requestp->buflen); -#endif - requestp->err = errno; -} - - -int -squidaio_close(int fd, squidaio_result_t * resultp) -{ - squidaio_request_t *requestp; - - if (!squidaio_initialised) - squidaio_init(); - - requestp = (squidaio_request_t *)squidaio_request_pool->alloc(); - - requestp->fd = fd; - - requestp->resultp = resultp; - - requestp->request_type = _AIO_OP_CLOSE; - - requestp->cancelled = 0; - - resultp->result_type = _AIO_OP_CLOSE; - - squidaio_queue_request(requestp); - - return 0; -} - - -static void -squidaio_do_close(squidaio_request_t * requestp) -{ - if((requestp->ret = close(requestp->fd)) < 0) { - debug(43, 0) ("squidaio_do_close: FD %d, errno %d\n", requestp->fd, errno); - close(requestp->fd); - } - requestp->err = errno; -} - - -int - -squidaio_stat(const char *path, struct stat *sb, squidaio_result_t * resultp) -{ - squidaio_request_t *requestp; - - if (!squidaio_initialised) - squidaio_init(); - - requestp = (squidaio_request_t *)squidaio_request_pool->alloc(); - - requestp->path = (char *) squidaio_xstrdup(path); - - requestp->statp = sb; - - requestp->tmpstatp = (struct stat *) squidaio_xmalloc(sizeof(struct stat)); - - requestp->resultp = resultp; - - requestp->request_type = _AIO_OP_STAT; - - requestp->cancelled = 0; - - resultp->result_type = _AIO_OP_STAT; - - squidaio_queue_request(requestp); - - return 0; -} - - -static void -squidaio_do_stat(squidaio_request_t * requestp) -{ - requestp->ret = stat(requestp->path, requestp->tmpstatp); - requestp->err = errno; -} - - -int -squidaio_unlink(const char *path, squidaio_result_t * resultp) -{ - squidaio_request_t *requestp; - - if (!squidaio_initialised) - squidaio_init(); - - requestp = (squidaio_request_t *)squidaio_request_pool->alloc(); - - requestp->path = squidaio_xstrdup(path); - - requestp->resultp = resultp; - - requestp->request_type = _AIO_OP_UNLINK; - - requestp->cancelled = 0; - - resultp->result_type = _AIO_OP_UNLINK; - - squidaio_queue_request(requestp); - - return 0; -} - - -static void -squidaio_do_unlink(squidaio_request_t * requestp) -{ - requestp->ret = unlink(requestp->path); - requestp->err = errno; -} - -int -squidaio_truncate(const char *path, off_t length, squidaio_result_t * resultp) -{ - squidaio_request_t *requestp; - - if (!squidaio_initialised) - squidaio_init(); - - requestp = (squidaio_request_t *)squidaio_request_pool->alloc(); - - requestp->path = (char *) squidaio_xstrdup(path); - - requestp->offset = length; - - requestp->resultp = resultp; - - requestp->request_type = _AIO_OP_TRUNCATE; - - requestp->cancelled = 0; - - resultp->result_type = _AIO_OP_TRUNCATE; - - squidaio_queue_request(requestp); - - return 0; -} - - -static void -squidaio_do_truncate(squidaio_request_t * requestp) -{ - requestp->ret = truncate(requestp->path, requestp->offset); - requestp->err = errno; -} - - -#if AIO_OPENDIR -/* XXX squidaio_opendir NOT implemented yet.. */ - -int -squidaio_opendir(const char *path, squidaio_result_t * resultp) -{ - squidaio_request_t *requestp; - int len; - - if (!squidaio_initialised) - squidaio_init(); - - requestp = squidaio_request_pool->alloc(); - - resultp->result_type = _AIO_OP_OPENDIR; - - return -1; -} - -static void -squidaio_do_opendir(squidaio_request_t * requestp) -{ - /* NOT IMPLEMENTED */ -} - -#endif - -static void -squidaio_poll_queues(void) -{ - /* kick "overflow" request queue */ - - if (request_queue2.head && - (WaitForSingleObject(request_queue.mutex, 0 )== WAIT_OBJECT_0)) { - *request_queue.tailp = request_queue2.head; - request_queue.tailp = request_queue2.tailp; - if (!SetEvent(request_queue.cond)) - fatal("couldn't push queue\n"); - if (!ReleaseMutex(request_queue.mutex)) { - /* unexpected error */ - } - - Sleep(0); - request_queue2.head = NULL; - request_queue2.tailp = &request_queue2.head; - } - - /* poll done queue */ - if (done_queue.head && - (WaitForSingleObject(done_queue.mutex, 0)==WAIT_OBJECT_0)) { - - struct squidaio_request_t *requests = done_queue.head; - done_queue.head = NULL; - done_queue.tailp = &done_queue.head; - if (!ReleaseMutex(done_queue.mutex)) { - /* unexpected error */ - } - Sleep(0); - *done_requests.tailp = requests; - request_queue_len -= 1; - - while (requests->next) { - requests = requests->next; - request_queue_len -= 1; - } - - done_requests.tailp = &requests->next; - } -} - -squidaio_result_t * -squidaio_poll_done(void) -{ - squidaio_request_t *request; - squidaio_result_t *resultp; - int cancelled; - int polled = 0; - -AIO_REPOLL: - request = done_requests.head; - - if (request == NULL && !polled) { - CommIO::ResetNotifications(); - squidaio_poll_queues(); - polled = 1; - request = done_requests.head; - } - - if (!request) { - return NULL; - } - - debug(43, 9) ("squidaio_poll_done: %p type=%d result=%p\n", - request, request->request_type, request->resultp); - done_requests.head = request->next; - - if (!done_requests.head) - done_requests.tailp = &done_requests.head; - - resultp = request->resultp; - - cancelled = request->cancelled; - - squidaio_debug(request); - - debug(43, 5) ("DONE: %d -> %d\n", request->ret, request->err); - - squidaio_cleanup_request(request); - - if (cancelled) - goto AIO_REPOLL; - - return resultp; -} /* squidaio_poll_done */ - -int -squidaio_operations_pending(void) -{ - return request_queue_len + (done_requests.head ? 1 : 0); -} - -int -squidaio_sync(void) -{ - /* XXX This might take a while if the queue is large.. */ - - do { - squidaio_poll_queues(); - } while (request_queue_len > 0); - - return squidaio_operations_pending(); -} - -int -squidaio_get_queue_len(void) -{ - return request_queue_len; -} - -static void -squidaio_debug(squidaio_request_t * request) -{ - switch (request->request_type) { - - case _AIO_OP_OPEN: - debug(43, 5) ("OPEN of %s to FD %d\n", request->path, request->ret); - break; - - case _AIO_OP_READ: - debug(43, 5) ("READ on fd: %d\n", request->fd); - break; - - case _AIO_OP_WRITE: - debug(43, 5) ("WRITE on fd: %d\n", request->fd); - break; - - case _AIO_OP_CLOSE: - debug(43, 5) ("CLOSE of fd: %d\n", request->fd); - break; - - case _AIO_OP_UNLINK: - debug(43, 5) ("UNLINK of %s\n", request->path); - break; - - case _AIO_OP_TRUNCATE: - debug(43, 5) ("UNLINK of %s\n", request->path); - break; - - default: - break; - } -} - -void -squidaio_stats(StoreEntry * sentry) -{ - squidaio_thread_t *threadp; - int i; - - if (!squidaio_initialised) - return; - - storeAppendPrintf(sentry, "\n\nThreads Status:\n"); - storeAppendPrintf(sentry, "#\tID\t# Requests\n"); - - threadp = threads; - for (i = 0; i < NUMTHREADS; i++) { - storeAppendPrintf(sentry, "%i\t0x%lx\t%ld\n", i + 1, threadp->dwThreadId, threadp->requests); - threadp = threadp->next; - } -} --- squid3/src/fs/awin32/async_io.cc Wed Feb 14 13:34:04 2007 +++ /dev/null Wed Feb 14 13:33:00 2007 @@ -1,458 +0,0 @@ - -/* - * $Id: async_io.cc,v 1.2.18.4 2004/10/03 11:56:47 serassio Exp $ - * - * DEBUG: section 32 Asynchronous Disk I/O - * AUTHOR: Pete Bentley - * AUTHOR: Stewart Forster - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "store_asyncufs.h" -#include "Store.h" -#include "fde.h" - -#define _AIO_OPEN 0 -#define _AIO_READ 1 -#define _AIO_WRITE 2 -#define _AIO_CLOSE 3 -#define _AIO_UNLINK 4 -#define _AIO_TRUNCATE 4 -#define _AIO_OPENDIR 5 -#define _AIO_STAT 6 - -typedef struct squidaio_ctrl_t -{ - - struct squidaio_ctrl_t *next; - int fd; - int operation; - AIOCB *done_handler; - void *done_handler_data; - squidaio_result_t result; - int len; - char *bufp; - FREE *free_func; - dlink_node node; -} - -squidaio_ctrl_t; - -static struct -{ - int open_start; - int open_finish; - int close_start; - int close_finish; - int cancel; - int write_start; - int write_finish; - int read_start; - int read_finish; - int stat_start; - int stat_finish; - int unlink_start; - int unlink_finish; - int check_callback; -} - -squidaio_counts; - -typedef struct squidaio_unlinkq_t -{ - char *path; - - struct squidaio_unlinkq_t *next; -} - -squidaio_unlinkq_t; - -static dlink_list used_list; -static OBJH aioStats; -static MemAllocatorProxy *squidaio_ctrl_pool; -static void aioFDWasClosed(int fd); - -static void -aioFDWasClosed(int fd) -{ - if (fd_table[fd].flags.closing) - fd_close(fd); -} - -void -AufsIO::init(void) -{ - if (initialised) - return; - - squidaio_ctrl_pool = new MemAllocatorProxy("aio_ctrl", sizeof(squidaio_ctrl_t)); - - cachemgrRegister("squidaio_counts", "Async IO Function Counters", - aioStats, 0, 1); - - initialised = true; -} - -void -AufsIO::done(void) -{ - if (!initialised) - return; - - squidaio_shutdown(); - delete squidaio_ctrl_pool; - - squidaio_ctrl_pool = NULL; - - initialised = false; -} - -void -aioOpen(const char *path, int oflag, mode_t mode, AIOCB * callback, void *callback_data) -{ - squidaio_ctrl_t *ctrlp; - - assert(AufsIO::Instance.initialised); - squidaio_counts.open_start++; - ctrlp = (squidaio_ctrl_t *)squidaio_ctrl_pool->alloc(); - ctrlp->fd = -2; - ctrlp->done_handler = callback; - ctrlp->done_handler_data = cbdataReference(callback_data); - ctrlp->operation = _AIO_OPEN; - ctrlp->result.data = ctrlp; - squidaio_open(path, oflag, mode, &ctrlp->result); - dlinkAdd(ctrlp, &ctrlp->node, &used_list); - return; -} - -void -aioClose(int fd) -{ - squidaio_ctrl_t *ctrlp; - - assert(AufsIO::Instance.initialised); - squidaio_counts.close_start++; - aioCancel(fd); - ctrlp = (squidaio_ctrl_t *)squidaio_ctrl_pool->alloc(); - ctrlp->fd = fd; - ctrlp->done_handler = NULL; - ctrlp->done_handler_data = NULL; - ctrlp->operation = _AIO_CLOSE; - ctrlp->result.data = ctrlp; - squidaio_close(fd, &ctrlp->result); - dlinkAdd(ctrlp, &ctrlp->node, &used_list); - return; -} - -void -aioCancel(int fd) -{ - squidaio_ctrl_t *ctrlp; - dlink_node *m, *next; - - assert(AufsIO::Instance.initialised); - squidaio_counts.cancel++; - - for (m = used_list.head; m; m = next) { - next = m->next; - ctrlp = (squidaio_ctrl_t *)m->data; - - if (ctrlp->fd != fd) - continue; - - squidaio_cancel(&ctrlp->result); - - if (ctrlp->done_handler) { - AIOCB *callback = ctrlp->done_handler; - void *cbdata; - ctrlp->done_handler = NULL; - debug(32, 1) ("this be aioCancel. Danger ahead!\n"); - - if (cbdataReferenceValidDone(ctrlp->done_handler_data, &cbdata)) - callback(fd, cbdata, NULL, -2, -2); - - /* free data if requested to aioWrite() */ - if (ctrlp->free_func) - ctrlp->free_func(ctrlp->bufp); - - /* free temporary read buffer */ - if (ctrlp->operation == _AIO_READ) - squidaio_xfree(ctrlp->bufp, ctrlp->len); - } - - dlinkDelete(m, &used_list); - squidaio_ctrl_pool->free(ctrlp); - } -} - - -void -aioWrite(int fd, int offset, char *bufp, int len, AIOCB * callback, void *callback_data, FREE * free_func) -{ - squidaio_ctrl_t *ctrlp; - int seekmode; - - assert(AufsIO::Instance.initialised); - squidaio_counts.write_start++; - ctrlp = (squidaio_ctrl_t *)squidaio_ctrl_pool->alloc(); - ctrlp->fd = fd; - ctrlp->done_handler = callback; - ctrlp->done_handler_data = cbdataReference(callback_data); - ctrlp->operation = _AIO_WRITE; - ctrlp->bufp = bufp; - ctrlp->free_func = free_func; - - if (offset >= 0) - seekmode = SEEK_SET; - else { - seekmode = SEEK_END; - offset = 0; - } - - ctrlp->result.data = ctrlp; - squidaio_write(fd, bufp, len, offset, seekmode, &ctrlp->result); - dlinkAdd(ctrlp, &ctrlp->node, &used_list); -} /* aioWrite */ - - -void -aioRead(int fd, int offset, int len, AIOCB * callback, void *callback_data) -{ - squidaio_ctrl_t *ctrlp; - int seekmode; - - assert(AufsIO::Instance.initialised); - squidaio_counts.read_start++; - ctrlp = (squidaio_ctrl_t *)squidaio_ctrl_pool->alloc(); - ctrlp->fd = fd; - ctrlp->done_handler = callback; - ctrlp->done_handler_data = cbdataReference(callback_data); - ctrlp->operation = _AIO_READ; - ctrlp->len = len; - ctrlp->bufp = (char *)squidaio_xmalloc(len); - - if (offset >= 0) - seekmode = SEEK_SET; - else { - seekmode = SEEK_CUR; - offset = 0; - } - - ctrlp->result.data = ctrlp; - squidaio_read(fd, ctrlp->bufp, len, offset, seekmode, &ctrlp->result); - dlinkAdd(ctrlp, &ctrlp->node, &used_list); - return; -} /* aioRead */ - -void - -aioStat(char *path, struct stat *sb, AIOCB * callback, void *callback_data) -{ - squidaio_ctrl_t *ctrlp; - - assert(AufsIO::Instance.initialised); - squidaio_counts.stat_start++; - ctrlp = (squidaio_ctrl_t *)squidaio_ctrl_pool->alloc(); - ctrlp->fd = -2; - ctrlp->done_handler = callback; - ctrlp->done_handler_data = cbdataReference(callback_data); - ctrlp->operation = _AIO_STAT; - ctrlp->result.data = ctrlp; - squidaio_stat(path, sb, &ctrlp->result); - dlinkAdd(ctrlp, &ctrlp->node, &used_list); - return; -} /* aioStat */ - -void -aioUnlink(const char *path, AIOCB * callback, void *callback_data) -{ - squidaio_ctrl_t *ctrlp; - assert(AufsIO::Instance.initialised); - squidaio_counts.unlink_start++; - ctrlp = (squidaio_ctrl_t *)squidaio_ctrl_pool->alloc(); - ctrlp->fd = -2; - ctrlp->done_handler = callback; - ctrlp->done_handler_data = cbdataReference(callback_data); - ctrlp->operation = _AIO_UNLINK; - ctrlp->result.data = ctrlp; - squidaio_unlink(path, &ctrlp->result); - dlinkAdd(ctrlp, &ctrlp->node, &used_list); -} /* aioUnlink */ - -void -aioTruncate(const char *path, off_t length, AIOCB * callback, void *callback_data) -{ - squidaio_ctrl_t *ctrlp; - assert(AufsIO::Instance.initialised); - squidaio_counts.unlink_start++; - ctrlp = (squidaio_ctrl_t *)squidaio_ctrl_pool->alloc(); - ctrlp->fd = -2; - ctrlp->done_handler = callback; - ctrlp->done_handler_data = cbdataReference(callback_data); - ctrlp->operation = _AIO_TRUNCATE; - ctrlp->result.data = ctrlp; - squidaio_truncate(path, length, &ctrlp->result); - dlinkAdd(ctrlp, &ctrlp->node, &used_list); -} /* aioTruncate */ - - -int -AufsIO::callback() -{ - squidaio_result_t *resultp; - squidaio_ctrl_t *ctrlp; - int retval = 0; - - assert(initialised); - squidaio_counts.check_callback++; - - for (;;) { - if ((resultp = squidaio_poll_done()) == NULL) - break; - - ctrlp = (squidaio_ctrl_t *) resultp->data; - - switch (resultp->result_type) { - - case _AIO_OP_NONE: - - case _AIO_OP_TRUNCATE: - - case _AIO_OP_OPENDIR: - break; - - case _AIO_OP_OPEN: - ++squidaio_counts.open_finish; - break; - - case _AIO_OP_READ: - ++squidaio_counts.read_finish; - break; - - case _AIO_OP_WRITE: - ++squidaio_counts.write_finish; - break; - - case _AIO_OP_CLOSE: - ++squidaio_counts.close_finish; - break; - - case _AIO_OP_UNLINK: - ++squidaio_counts.unlink_finish; - break; - - case _AIO_OP_STAT: - ++squidaio_counts.stat_finish; - break; - } - - if (ctrlp == NULL) - continue; /* XXX Should not happen */ - - dlinkDelete(&ctrlp->node, &used_list); - - if (ctrlp->done_handler) { - AIOCB *callback = ctrlp->done_handler; - void *cbdata; - ctrlp->done_handler = NULL; - - if (cbdataReferenceValidDone(ctrlp->done_handler_data, &cbdata)) { - retval = 1; /* Return that we've actually done some work */ - callback(ctrlp->fd, cbdata, ctrlp->bufp, - ctrlp->result.aio_return, ctrlp->result.aio_errno); - } else { - if (ctrlp->operation == _AIO_OPEN) { - /* The open operation was aborted.. */ - int fd = ctrlp->result.aio_return; - - if (fd >= 0) - aioClose(fd); - } - } - } - - /* free data if requested to aioWrite() */ - if (ctrlp->free_func) - ctrlp->free_func(ctrlp->bufp); - - /* free temporary read buffer */ - if (ctrlp->operation == _AIO_READ) - squidaio_xfree(ctrlp->bufp, ctrlp->len); - - if (ctrlp->operation == _AIO_CLOSE) - aioFDWasClosed(ctrlp->fd); - - squidaio_ctrl_pool->free(ctrlp); - } - - return retval; -} - -void -aioStats(StoreEntry * sentry) -{ - storeAppendPrintf(sentry, "ASYNC IO Counters:\n"); - storeAppendPrintf(sentry, "Operation\t# Requests\tNumber serviced\n"); - storeAppendPrintf(sentry, "open\t%d\t%d\n", squidaio_counts.open_start, squidaio_counts.open_finish); - storeAppendPrintf(sentry, "close\t%d\t%d\n", squidaio_counts.close_start, squidaio_counts.close_finish); - storeAppendPrintf(sentry, "cancel\t%d\t-\n", squidaio_counts.cancel); - storeAppendPrintf(sentry, "write\t%d\t%d\n", squidaio_counts.write_start, squidaio_counts.write_finish); - storeAppendPrintf(sentry, "read\t%d\t%d\n", squidaio_counts.read_start, squidaio_counts.read_finish); - storeAppendPrintf(sentry, "stat\t%d\t%d\n", squidaio_counts.stat_start, squidaio_counts.stat_finish); - storeAppendPrintf(sentry, "unlink\t%d\t%d\n", squidaio_counts.unlink_start, squidaio_counts.unlink_finish); - storeAppendPrintf(sentry, "check_callback\t%d\t-\n", squidaio_counts.check_callback); - storeAppendPrintf(sentry, "queue\t%d\t-\n", squidaio_get_queue_len()); - squidaio_stats(sentry); -} - -/* Flush all pending I/O */ -void -AufsIO::sync() -{ - if (!initialised) - return; /* nothing to do then */ - - /* Flush all pending operations */ - debug(32, 1) ("aioSync: flushing pending I/O operations\n"); - - do { - callback(); - } while (squidaio_sync()); - - debug(32, 1) ("aioSync: done\n"); -} - -AufsIO::AufsIO() : initialised (false) {} - -int -aioQueueSize(void) -{ - return squidaio_ctrl_pool->inUseCount(); -} --- squid3/src/fs/awin32/store_asyncufs.h Wed Feb 14 13:34:04 2007 +++ /dev/null Wed Feb 14 13:33:00 2007 @@ -1,181 +0,0 @@ -/* - * store_aufs.h - * - * Internal declarations for the aufs routines - */ - -#ifndef __STORE_ASYNCUFS_H__ -#define __STORE_ASYNCUFS_H__ - -#ifdef AUFS_IO_THREADS -#define NUMTHREADS AUFS_IO_THREADS -#else -#define NUMTHREADS (Config.cacheSwap.n_configured*16) -#endif - -/* Queue limit where swapouts are deferred (load calculation) */ -#define MAGIC1 (NUMTHREADS*Config.cacheSwap.n_configured*5) -/* Queue limit where swapins are deferred (open/create fails) */ -#define MAGIC2 (NUMTHREADS*Config.cacheSwap.n_configured*20) - -/* Which operations to run async */ -#define ASYNC_OPEN 1 -#define ASYNC_CLOSE 0 -#define ASYNC_CREATE 1 -#define ASYNC_WRITE 0 -#define ASYNC_READ 1 - -enum _squidaio_request_type { - _AIO_OP_NONE = 0, - _AIO_OP_OPEN, - _AIO_OP_READ, - _AIO_OP_WRITE, - _AIO_OP_CLOSE, - _AIO_OP_UNLINK, - _AIO_OP_TRUNCATE, - _AIO_OP_OPENDIR, - _AIO_OP_STAT -}; -typedef enum _squidaio_request_type squidaio_request_type; - -struct _squidaio_result_t -{ - int aio_return; - int aio_errno; - enum _squidaio_request_type result_type; - void *_data; /* Internal housekeeping */ - void *data; /* Available to the caller */ -}; - -typedef struct _squidaio_result_t squidaio_result_t; - -typedef void AIOCB(int fd, void *cbdata, const char *buf, int aio_return, int aio_errno); - -int squidaio_cancel(squidaio_result_t *); -int squidaio_open(const char *, int, mode_t, squidaio_result_t *); -int squidaio_read(int, char *, int, off_t, int, squidaio_result_t *); -int squidaio_write(int, char *, int, off_t, int, squidaio_result_t *); -int squidaio_close(int, squidaio_result_t *); - -int squidaio_stat(const char *, struct stat *, squidaio_result_t *); -int squidaio_unlink(const char *, squidaio_result_t *); -int squidaio_truncate(const char *, off_t length, squidaio_result_t *); -int squidaio_opendir(const char *, squidaio_result_t *); -squidaio_result_t *squidaio_poll_done(void); -int squidaio_operations_pending(void); -int squidaio_sync(void); -int squidaio_get_queue_len(void); -void *squidaio_xmalloc(int size); -void squidaio_xfree(void *p, int size); -void squidaio_shutdown(void); -void squidaio_stats(StoreEntry *); - -void aioInit(void); -void aioDone(void); -void aioCancel(int); -void aioOpen(const char *, int, mode_t, AIOCB *, void *); -void aioClose(int); -void aioWrite(int, int offset, char *, int size, AIOCB *, void *, FREE *); -void aioRead(int, int offset, int size, AIOCB *, void *); - -void aioStat(char *, struct stat *, AIOCB *, void *); -void aioUnlink(const char *, AIOCB *, void *); -void aioTruncate(const char *, off_t length, AIOCB *, void *); -int aioQueueSize(void); - -#include "ufscommon.h" - -class AufsIO; - -class AUFSFile : public DiskFile -{ - -public: - void * operator new (size_t); - void operator delete (void *); - AUFSFile (char const *path, AufsIO *); - ~AUFSFile(); - virtual void open (int, mode_t, IORequestor::Pointer); - virtual void create (int, mode_t, IORequestor::Pointer); - virtual void read(char *, off_t, size_t); - virtual void write(char const *buf, size_t size, off_t offset, FREE *free_func); - virtual void close (); - virtual bool error() const; - virtual int getFD() const { return fd;} - - virtual bool canRead() const; - virtual bool canWrite() const; - virtual bool ioInProgress()const; - -private: -#if ASYNC_READ - - static AIOCB ReadDone; -#else - - static DRCB ReadDone; -#endif -#if ASYNC_WRITE - - static AIOCB WriteDone; -#else - - static DWCB WriteDone; -#endif - - int fd; - bool errorOccured; - char const *path_; - AufsIO* IO; - size_t inProgressIOs; - static AIOCB OpenDone; - void openDone(int fd, const char *buf, int aio_return, int aio_errno); - IORequestor::Pointer ioRequestor; - CBDATA_CLASS(AUFSFile); - void doClose(); - - void readDone(int fd, const char *buf, int len, int errflag); - void writeDone (int fd, int errflag, size_t len); -}; - -/* - * Store IO stuff - */ - -class SwapDir; - -#include "fs/ufs/IOModule.h" - -class AufsIOModule : public IOModule -{ - -public: - static AufsIOModule &GetInstance(); - virtual void init(); - virtual void shutdown(); - virtual UFSStrategy *createSwapDirIOStrategy(); - -private: - static AufsIOModule *Instance; -}; - -class AufsIO : public UFSStrategy -{ - -public: - AufsIO(); - virtual bool shedLoad(); - virtual int load(); - virtual StoreIOState::Pointer createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const; - virtual DiskFile::Pointer newFile(char const *path); - virtual void unlinkFile (char const *); - virtual void sync(); - virtual int callback(); - void init(); - void done(); - static AufsIO Instance; - bool initialised; -}; - - -#endif --- squid3/src/fs/awin32/store_io_aufs.cc Wed Feb 14 13:34:04 2007 +++ /dev/null Wed Feb 14 13:33:00 2007 @@ -1,461 +0,0 @@ - -/* - * $Id: store_io_aufs.cc,v 1.2.18.3 2004/06/21 21:35:07 serassio Exp $ - * - * DEBUG: section 79 Storage Manager awin32 Interface - * AUTHOR: Robert Collins - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "store_asyncufs.h" -#include "Store.h" -#include "ufscommon.h" -#include "SwapDir.h" - -/* === PUBLIC =========================================================== */ - - - - -AufsIO AufsIO::Instance; -bool -AufsIO::shedLoad() -{ - /* - * we should detect some 'too many files open' condition and return - * NULL here. - */ -#ifdef MAGIC2 - - if (aioQueueSize() > MAGIC2) - return true; - -#endif - - return false; -} - -int -AufsIO::load() -{ - int loadav; - int ql; - - ql = aioQueueSize(); - - if (ql == 0) - loadav = 0; - - loadav = ql * 1000 / MAGIC1; - - debug(47, 9) ("storeAufsDirCheckObj: load=%d\n", loadav); - - return loadav; -} - -StoreIOState::Pointer -AufsIO::createState(SwapDir *SD, StoreEntry *e, STIOCB * callback, void *callback_data) const -{ - return new UFSStoreState (SD, e, callback, callback_data); -} - -DiskFile::Pointer -AufsIO::newFile (char const *path) -{ - return new AUFSFile (path, this); -} - -void -AufsIO::unlinkFile(char const *path) -{ - statCounter.syscalls.disk.unlinks++; -#if USE_TRUNCATE_NOT_UNLINK - - aioTruncate(path, NULL, NULL); -#else - - aioUnlink(path, NULL, NULL); -#endif -} - -AufsIOModule *AufsIOModule::Instance = NULL; -AufsIOModule & -AufsIOModule::GetInstance() -{ - if (!Instance) - Instance = new AufsIOModule; - - return *Instance; -} - -void -AufsIOModule::init() -{ - AufsIO::Instance.init(); -} - -void -AufsIOModule::shutdown() -{ - AufsIO::Instance.done(); -} - -UFSStrategy * -AufsIOModule::createSwapDirIOStrategy() -{ - return new InstanceToSingletonAdapter(&AufsIO::Instance); -} - -CBDATA_CLASS_INIT(AUFSFile); -void * -AUFSFile::operator new (size_t) -{ - CBDATA_INIT_TYPE(AUFSFile); - AUFSFile *result = cbdataAlloc(AUFSFile); - /* Mark result as being owned - we want the refcounter to do the delete - * call */ - cbdataReference(result); - return result; -} - -void -AUFSFile::operator delete (void *address) -{ - AUFSFile *t = static_cast(address); - cbdataFree(address); - /* And allow the memory to be freed */ - cbdataReferenceDone (t); -} - -AUFSFile::AUFSFile (char const *aPath, AufsIO *anIO):fd(-1), errorOccured (false), IO(anIO), - inProgressIOs (0) -{ - assert (aPath); - debug (79,3)("UFSFile::UFSFile: %s\n", aPath); - path_ = xstrdup (aPath); -} - -AUFSFile::~AUFSFile() -{ - safe_free (path_); - doClose(); -} - -void -AUFSFile::open (int flags, mode_t mode, IORequestor::Pointer callback) -{ - statCounter.syscalls.disk.opens++; -#if !ASYNC_OPEN - - fd = file_open(path_, flags); - - if (fd < 0) { - debug(79, 3) ("AUFSFile::open: got failure (%d)\n", errno); - errorOccured = true; - return; - } - -#endif - Opening_FD++; - - ioRequestor = callback; - - ++inProgressIOs; - -#if ASYNC_OPEN - - aioOpen(path_, flags, mode, AUFSFile::OpenDone, this); - -#else - - openDone(fd, NULL, fd, 0); - -#endif -} - -void -AUFSFile::read(char *buf, off_t offset, size_t size) -{ - debugs(79, 3, "AUFSFile::read: " << this << ", size " << size); - assert (fd > -1); - assert (ioRequestor.getRaw()); - statCounter.syscalls.disk.reads++; - ++inProgressIOs; -#if ASYNC_READ - - aioRead(fd, offset, size, ReadDone, this); -#else - - file_read(fd, buf, size, offset, ReadDone, this); -#endif -} - -void -AUFSFile::create (int flags, mode_t mode, IORequestor::Pointer callback) -{ - statCounter.syscalls.disk.opens++; -#if !ASYNC_CREATE - - int fd = file_open(path_, flags); - - if (fd < 0) { - debug(79, 3) ("storeAufsCreate: got failure (%d)\n", errno); - errorOccured = true; - return; - } - -#endif - Opening_FD++; - - ioRequestor = callback; - - ++inProgressIOs; - -#if ASYNC_CREATE - - aioOpen(path_, flags, mode, AUFSFile::OpenDone, this); - -#else - - openDone (fd, NULL, fd, 0); - -#endif -} - -bool -AUFSFile::error() const -{ - return errorOccured; -} - -void -AUFSFile::OpenDone(int fd, void *cbdata, const char *buf, int aio_return, int aio_errno) -{ - AUFSFile *myFile = static_cast(cbdata); - myFile->openDone (fd, buf, aio_return, aio_errno); -} - -void -AUFSFile::openDone(int unused, const char *unused2, int anFD, int errflag) -{ - debug(79, 3) ("AUFSFile::openDone: FD %d, errflag %d\n", anFD, errflag); - Opening_FD--; - - fd = anFD; - - if (errflag || fd < 0) { - errno = errflag; - debug(79, 0) ("AUFSFile::openDone: %s\n", xstrerror()); - debug(79, 1) ("\t%s\n", path_); - errorOccured = true; - } else { - store_open_disk_fd++; - commSetCloseOnExec(fd); - fd_open(fd, FD_FILE, path_); - } - - debug(79, 3) ("AUFSFile::openDone: exiting\n"); - - IORequestor::Pointer t = ioRequestor; - --inProgressIOs; - t->ioCompletedNotification(); -} - -void AUFSFile::doClose() -{ - if (fd > -1) { - statCounter.syscalls.disk.closes++; - aioClose(fd); - fd_close(fd); - store_open_disk_fd--; - fd = -1; - } -} - -/* open for reading */ -StoreIOState::Pointer -storeAufsOpen(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, - STIOCB * callback, void *callback_data) -{ - UFSStrategy *IO = dynamic_cast (((UFSSwapDir *)SD)->IO); - assert (IO); - return IO->open (SD, e, file_callback, callback, callback_data); -} - -/* open for creating */ -StoreIOState::Pointer -storeAufsCreate(SwapDir * SD, StoreEntry * e, STFNCB * file_callback, STIOCB * callback, void *callback_data) -{ - UFSStrategy *IO = dynamic_cast (((UFSSwapDir *)SD)->IO); - assert (IO); - return IO->create (SD, e, file_callback, callback, callback_data); -} - - -void -AUFSFile::close () -{ - debug (79,3)("AUFSFile::close: %p closing for %p\n", this, ioRequestor.getRaw()); - - if (!ioInProgress()) { - doClose(); - assert (ioRequestor.getRaw()); - ioRequestor->closeCompleted(); - } -} - -bool -AUFSFile::canRead() const -{ - debug (79,3)("AUFSFile::canRead: fd is %d\n",fd); - return fd > -1; -} - -void -AUFSFile::write(char const *buf, size_t size, off_t offset, FREE *free_func) -{ - debug(79, 3) ("storeAufsWrite: FD %d\n", fd); - statCounter.syscalls.disk.writes++; - ++inProgressIOs; -#if ASYNC_WRITE - - aioWrite(fd, offset, (char *)buf, size, WriteDone, this, - free_func); -#else - - file_write(fd, offset, (char *)buf, size, WriteDone, this, - free_func); -#endif -} - -bool -AUFSFile::canWrite() const -{ - return fd > -1; -} - -bool -AUFSFile::ioInProgress()const -{ - return inProgressIOs > 0; -} - -/* === STATIC =========================================================== */ - -#if ASYNC_READ -void -AUFSFile::ReadDone(int fd, void *my_data, const char *buf, int len, int errflag) -#else -void -AUFSFile::ReadDone(int fd, const char *buf, int len, int errflag, void *my_data) -#endif -{ - AUFSFile *myFile = static_cast(my_data); - assert (myFile); - myFile->readDone (fd, buf, len, errflag); -} - -void -AUFSFile::readDone(int rvfd, const char *buf, int len, int errflag) -{ - debug (79,3)("AUFSFile::readDone: FD %d\n",rvfd); - assert (fd == rvfd); - - ssize_t rlen; - - if (errflag) { - debug(79, 3) ("AUFSFile::readDone: got failure (%d)\n", errflag); - rlen = -1; - } else { - rlen = (ssize_t) len; - } - -#if ASYNC_READ - /* translate errflag from errno to Squid disk error */ - errno = errflag; - - if (errflag) - errflag = DISK_ERROR; - else - errflag = DISK_OK; - -#else - - if (errflag == DISK_EOF) - errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */ - -#endif - - --inProgressIOs; - - ioRequestor->readCompleted(buf, rlen, errflag); -} - -void -AUFSFile:: -#if ASYNC_WRITE -WriteDone(int fd, void *my_data, int len, int errflag) -#else -WriteDone(int fd, int errflag, size_t len, void *my_data) -#endif -{ - AUFSFile *aFile = static_cast(my_data); - assert (aFile); - aFile->writeDone (fd, errflag, len); -} - -void -AUFSFile::writeDone (int rvfd, int errflag, size_t len) -{ - assert (rvfd == fd); - static int loop_detect = 0; - debug(79, 3) ("storeAufsWriteDone: FD %d, len %ld, err=%d\n", - fd, (long int) len, errflag); - -#if ASYNC_WRITE - /* Translate from errno to Squid disk error */ - errno = errflag; - - if (errflag) - errflag = errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR; - else - errflag = DISK_OK; - -#endif - - assert(++loop_detect < 10); - - --inProgressIOs; - - ioRequestor->writeCompleted(errflag, len); - - --loop_detect; -} -