---------------------
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 <robertc@squid-cache.org>
+ */
+
+
+#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<WinDiskThreadsDiskFile *>(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<ReadRequest>(this, request));
+#else
+
+    file_read(fd, request->buf, request->len, request->offset, ReadDone, new IoResult<ReadRequest>(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<WinDiskThreadsDiskFile *>(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<WriteRequest>(this, writeRequest),
+             writeRequest->free_func);
+#else
+
+    file_write(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult<WriteRequest>(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<ReadRequest> * result = static_cast<IoResult<ReadRequest> *>(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<WriteRequest> * result = static_cast<IoResult<WriteRequest> *>(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 <class RT>
+cbdata_type IoResult<RT>::CBDATA_IoResult = CBDATA_UNKNOWN;
+
+template<class RT>
+void *
+IoResult<RT>::operator new (size_t)
+{
+    CBDATA_INIT_TYPE(IoResult);
+    IoResult<RT> *result = cbdataAlloc(IoResult);
+    return result;
+}
+
+template <class RT>
+void
+IoResult<RT>::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 <robertc@squid-cache.org>
+ */
+
+#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<IORequestor>);
+    virtual void create (int, mode_t, RefCount<IORequestor>);
+    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> ioRequestor;
+    CBDATA_CLASS(WinDiskThreadsDiskFile);
+    void doClose();
+
+    void readDone(int fd, const char *buf, int len, int errflag, RefCount<ReadRequest>);
+    void writeDone (int fd, int errflag, size_t len, RefCount<WriteRequest>);
+};
+
+#include "DiskIO/ReadRequest.h"
+
+template <class RT>
+
+class IoResult
+{
+
+public:
+    void * operator new (size_t);
+    void operator delete (void *);
+    IoResult(RefCount<WinDiskThreadsDiskFile> aFile, RefCount<RT> aRequest) : file(aFile), request(aRequest){}
+
+    RefCount<WinDiskThreadsDiskFile> file;
+    RefCount<RT> request;
+
+private:
+    CBDATA_CLASS(IoResult);
+};
+
+template <class RT>
+IoResult<RT>
+IOResult(RefCount<RT> aRequest, RefCount<WinDiskThreadsDiskFile> aFile) { return IoResult<RT>(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 <robertc@squid-cache.org>
+ */
+
+#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 <robertc@squid-cache.org>
+ */
+
+#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 <robertc@squid-cache.org>
+ */
+
+#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 <robertc@squid-cache.org>
+ */
+
+#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<DiskFile> 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 <slf@connect.com.au>
+ *
+ * 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	<stdio.h>
+#include	<sys/types.h>
+#include	<sys/stat.h>
+#include	<fcntl.h>
+#include	<errno.h>
+#include	<dirent.h>
+#include	<signal.h>
+#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 <pete@demon.net>
+ * AUTHOR: Stewart Forster <slf@connect.com.au>
+ *
+ * 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<UFSSwapDir> AufsInstance(AufsIOModule::GetInstance(), "awin32");
+static StoreFSufs<UFSSwapDir> 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 <slf@connect.com.au>
- *
- * 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	<stdio.h>
-#include	<sys/types.h>
-#include	<sys/stat.h>
-#include	<fcntl.h>
-#include	<errno.h>
-#include	<dirent.h>
-#include	<signal.h>
-#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 <pete@demon.net>
- * AUTHOR: Stewart Forster <slf@connect.com.au>
- *
- * 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>(&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<AUFSFile *>(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<AUFSFile *>(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 <UFSStrategy *>(((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 <UFSStrategy *>(((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<AUFSFile *>(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<AUFSFile *>(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;
-}
-
