--------------------- PatchSet 3695 Date: 2006/09/05 21:00:08 Author: serassio Branch: nt Tag: (none) Log: Merged Windows Threads support into DiskThreads Disk module, dropped awin32 and WinDiskThreads Members: configure.in:1.26.2.100->1.26.2.101 src/Makefile.am:1.26.2.91->1.26.2.92 src/DiskIO/DiskThreads/aiops_win32.cc:1.1->1.1.2.1 src/DiskIO/WinDiskThreads/.cvsignore:1.1.2.1->1.1.2.2(DEAD) src/DiskIO/WinDiskThreads/WinDiskThreads.h:1.1.2.2->1.1.2.3(DEAD) src/DiskIO/WinDiskThreads/WinDiskThreadsDiskFile.cc:1.1.2.3->1.1.2.4(DEAD) src/DiskIO/WinDiskThreads/WinDiskThreadsDiskFile.h:1.1.2.2->1.1.2.3(DEAD) src/DiskIO/WinDiskThreads/WinDiskThreadsDiskIOModule.cc:1.1.2.2->1.1.2.3(DEAD) src/DiskIO/WinDiskThreads/WinDiskThreadsDiskIOModule.h:1.1.2.2->1.1.2.3(DEAD) src/DiskIO/WinDiskThreads/WinDiskThreadsIOStrategy.cc:1.1.2.6->1.1.2.7(DEAD) src/DiskIO/WinDiskThreads/WinDiskThreadsIOStrategy.h:1.1.2.3->1.1.2.4(DEAD) src/DiskIO/WinDiskThreads/aiops.cc:1.1.2.8->1.1.2.9(DEAD) src/DiskIO/WinDiskThreads/async_io.cc:1.1.2.3->1.1.2.4(DEAD) Index: squid3/configure.in =================================================================== RCS file: /cvsroot/squid-sf//squid3/configure.in,v retrieving revision 1.26.2.100 retrieving revision 1.26.2.101 diff -u -r1.26.2.100 -r1.26.2.101 --- squid3/configure.in 4 Sep 2006 21:02:26 -0000 1.26.2.100 +++ squid3/configure.in 5 Sep 2006 21:00:08 -0000 1.26.2.101 @@ -1,7 +1,7 @@ dnl Configuration input file for Squid dnl -dnl $Id: configure.in,v 1.26.2.100 2006/09/04 21:02:26 serassio Exp $ +dnl $Id: configure.in,v 1.26.2.101 2006/09/05 21:00:08 serassio Exp $ dnl dnl dnl @@ -11,7 +11,7 @@ AC_CONFIG_AUX_DIR(cfgaux) AC_CONFIG_SRCDIR([src/main.cc]) AM_INIT_AUTOMAKE([tar-ustar]) -AC_REVISION($Revision: 1.26.2.100 $)dnl +AC_REVISION($Revision: 1.26.2.101 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AM_MAINTAINER_MODE @@ -485,7 +485,6 @@ NEED_BLOCKING= NEED_DISKDAEMON= NEED_DISKTHREADS= -NEED_WINDISKTHREADS= NEED_AIO= STORE_TESTS= for fs in $STORE_MODULES none; do @@ -499,13 +498,7 @@ 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" dnl @@ -524,12 +517,11 @@ done STORE_OBJS= STORE_LIBS= -dnl We have 'fake' modules - aufs, awin32 and diskd - legacy. +dnl We have 'fake' modules - aufs 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" @@ -606,9 +598,6 @@ DiskThreads) FOUND_DISKTHREADS="true" ;; - WinDiskThreads) - FOUND_WINDISKTHREADS="true" - ;; AIO) FOUND_AIO="true" ;; @@ -632,24 +621,13 @@ DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/DiskDaemon/DiskDaemonDiskIOModule.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_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 - ;; -esac + 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" @@ -662,8 +640,17 @@ case "$fs" in DiskThreads) if test -z "$with_pthreads"; then - echo "DiskThreads IO Module used, pthreads support automatically enabled" - with_pthreads=yes + case "$host_os" in + mingw|mingw32|cygwin|cygwin32) + AM_CONDITIONAL(USE_AIOPS_WIN32, true) + echo "DiskThreads IO Module used, Windows threads support automatically enabled" + ;; + *) + AM_CONDITIONAL(USE_AIOPS_WIN32, false) + echo "DiskThreads IO Module used, pthreads support automatically enabled" + with_pthreads=yes + ;; + esac fi ;; AIO) Index: squid3/src/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Makefile.am,v retrieving revision 1.26.2.91 retrieving revision 1.26.2.92 diff -u -r1.26.2.91 -r1.26.2.92 --- squid3/src/Makefile.am 4 Sep 2006 19:59:28 -0000 1.26.2.91 +++ squid3/src/Makefile.am 5 Sep 2006 21:00:09 -0000 1.26.2.92 @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.am,v 1.26.2.91 2006/09/04 19:59:28 serassio Exp $ +# $Id: Makefile.am,v 1.26.2.92 2006/09/05 21:00:09 serassio Exp $ # # Uncomment and customize the following to suit your needs: # @@ -162,6 +162,12 @@ AIO_WIN32_SOURCES = endif +if USE_AIOPS_WIN32 +AIOPS_SOURCE = DiskIO/DiskThreads/aiops_win32.cc +else +AIOPS_SOURCE = DiskIO/DiskThreads/aiops.cc +endif + IDENT_ALL_SOURCE = ACLIdent.cc ACLIdent.h ident.cc if ENABLE_IDENT IDENT_SOURCE = $(IDENT_ALL_SOURCE) @@ -179,7 +185,7 @@ AM_CFLAGS = @SQUID_CFLAGS@ AM_CXXFLAGS = @SQUID_CXXFLAGS@ -EXTRA_LIBRARIES = libAIO.a libBlocking.a libDiskDaemon.a libDiskThreads.a libWinDiskThreads.a ICAP/libicap.a +EXTRA_LIBRARIES = libAIO.a libBlocking.a libDiskDaemon.a libDiskThreads.a ICAP/libicap.a noinst_LIBRARIES = @DISK_LIBS@ @ICAP_LIBS@ noinst_LTLIBRARIES = libsquid.la libauth.la @@ -225,15 +231,13 @@ fs/coss/StoreFScoss.cc \ fs/diskd/StoreFSdiskd.cc \ fs/null/StoreFSnull.cc \ - fs/ufs/StoreFSufs.cc \ - fs/awin32/StoreFSawin32.cc + fs/ufs/StoreFSufs.cc all_DISKIOMODULES = \ DiskIO/AIO/AIODiskIOModule.cc \ DiskIO/Blocking/BlockingDiskIOModule.cc \ DiskIO/DiskDaemon/DiskDaemonDiskIOModule.cc \ - DiskIO/DiskThreads/DiskThreadsDiskIOModule.cc \ - DiskIO/WinDiskThreads/WinDiskThreadsDiskIOModule.cc + DiskIO/DiskThreads/DiskThreadsDiskIOModule.cc DISKIO_SOURCE = \ DiskIO/DiskIOModule.cc \ @@ -280,7 +284,9 @@ $(SNMP_ALL_SOURCE) \ unlinkd.cc \ $(SSL_ALL_SOURCE) \ - $(WIN32_ALL_SOURCE) + $(WIN32_ALL_SOURCE) \ + DiskIO/DiskThreads/aiops.cc \ + DiskIO/DiskThreads/aiops_win32.cc squid_ACLSOURCES = \ $(ARP_ACL_SOURCE) \ @@ -940,24 +946,14 @@ DiskIO/DiskDaemon/DiskDaemonDiskIOModule.h libDiskThreads_a_SOURCES = \ - DiskIO/DiskThreads/aiops.cc \ - DiskIO/DiskThreads/async_io.cc \ - DiskIO/DiskThreads/DiskThreads.h \ - DiskIO/DiskThreads/DiskThreadsDiskFile.cc \ - DiskIO/DiskThreads/DiskThreadsDiskFile.h \ - DiskIO/DiskThreads/DiskThreadsDiskIOModule.h \ - 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 + $(AIOPS_SOURCE) \ + DiskIO/DiskThreads/async_io.cc \ + DiskIO/DiskThreads/DiskThreads.h \ + DiskIO/DiskThreads/DiskThreadsDiskFile.cc \ + DiskIO/DiskThreads/DiskThreadsDiskFile.h \ + DiskIO/DiskThreads/DiskThreadsDiskIOModule.h \ + DiskIO/DiskThreads/DiskThreadsIOStrategy.cc \ + DiskIO/DiskThreads/DiskThreadsIOStrategy.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:37:19 2007 +++ squid3/src/DiskIO/DiskThreads/aiops_win32.cc Wed Feb 14 13:37:51 2007 @@ -0,0 +1,1226 @@ +/* + * $Id: aiops_win32.cc,v 1.1.2.1 2006/09/05 21:00:10 serassio Exp $ + * + * DEBUG: section 43 AIOPS + * AUTHOR: Stewart Forster + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" +#include "squid_windows.h" +#include "DiskThreads.h" + +#include +#include +#include +#include +#include +#include +#include +#include "CommIO.h" +#include "SquidTime.h" +#include "Store.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_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 *); +#if USE_TRUNCATE +static void squidaio_do_truncate(squidaio_request_t *); +#else +static void squidaio_do_unlink(squidaio_request_t *); +#endif +#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 MemAllocator *squidaio_large_bufs = NULL; /* 16K */ +static MemAllocator *squidaio_medium_bufs = NULL; /* 8K */ +static MemAllocator *squidaio_small_bufs = NULL; /* 4K */ +static MemAllocator *squidaio_tiny_bufs = NULL; /* 2K */ +static MemAllocator *squidaio_micro_bufs = NULL; /* 128K */ + +static int request_queue_len = 0; +static MemAllocator *squidaio_request_pool = NULL; +static MemAllocator *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 MemAllocator * +squidaio_get_pool(int size) +{ + if (size <= AIO_LARGE_BUFS) { + if (size <= AIO_MICRO_BUFS) + return squidaio_micro_bufs; + else if (size <= AIO_TINY_BUFS) + return squidaio_tiny_bufs; + else if (size <= AIO_SMALL_BUFS) + return squidaio_small_bufs; + else if (size <= AIO_MEDIUM_BUFS) + return squidaio_medium_bufs; + else + return squidaio_large_bufs; + } + + return NULL; +} + +void * +squidaio_xmalloc(int size) +{ + void *p; + MemAllocator *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) +{ + MemAllocator *pool; + + if ((pool = squidaio_get_pool(size)) != NULL) { + pool->free(p); + } else + xfree(p); +} + +static void +squidaio_xstrfree(char *str) +{ + MemAllocator *pool; + int len = strlen(str) + 1; + + if ((pool = squidaio_get_pool(len)) != NULL) { + pool->free(str); + } else + xfree(str); +} + +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; + + CommIO::NotifyIOCompleted(); + + /* Create threads and get them to sit in their wait loop */ + squidaio_thread_pool = memPoolCreate("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 = memPoolCreate("aio_request", sizeof(squidaio_request_t)); + + squidaio_large_bufs = memPoolCreate("squidaio_large_bufs", AIO_LARGE_BUFS); + + squidaio_medium_bufs = memPoolCreate("squidaio_medium_bufs", AIO_MEDIUM_BUFS); + + squidaio_small_bufs = memPoolCreate("squidaio_small_bufs", AIO_SMALL_BUFS); + + squidaio_tiny_bufs = memPoolCreate("squidaio_tiny_bufs", AIO_TINY_BUFS); + + squidaio_micro_bufs = memPoolCreate("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; + + /* This is the same as in squidaio_sync */ + do { + squidaio_poll_queues(); + } while (request_queue_len > 0); + + 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); + CommIO::NotifyIOClose(); + + 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; + +#if USE_TRUNCATE + + case _AIO_OP_TRUNCATE: + squidaio_do_truncate(request); + break; +#else + + case _AIO_OP_UNLINK: + squidaio_do_unlink(request); + break; + +#endif +#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: + 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_init(); + squidaio_request_t *requestp; + + 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; + + 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); + + if (!ReadFile((HANDLE)_get_osfhandle(requestp->fd), requestp->bufferp, + requestp->buflen, (LPDWORD)&requestp->ret, NULL)) { + WIN32_maperror(GetLastError()); + requestp->ret = -1; + } + + 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; + + 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_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) +{ + if (!WriteFile((HANDLE)_get_osfhandle(requestp->fd), requestp->bufferp, + requestp->buflen, (LPDWORD)&requestp->ret, NULL)) { + WIN32_maperror(GetLastError()); + requestp->ret = -1; + } + + requestp->err = errno; +} + + +int +squidaio_close(int fd, squidaio_result_t * resultp) +{ + squidaio_request_t *requestp; + + 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_init(); + squidaio_request_t *requestp; + + 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; +} + + +#if USE_TRUNCATE +int +squidaio_truncate(const char *path, off_t length, squidaio_result_t * resultp) +{ + squidaio_init(); + squidaio_request_t *requestp; + + 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; +} + + +#else +int +squidaio_unlink(const char *path, squidaio_result_t * resultp) +{ + squidaio_init(); + squidaio_request_t *requestp; + + 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; +} + +#endif + +#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; + + 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/DiskIO/WinDiskThreads/.cvsignore Wed Feb 14 13:37:51 2007 +++ /dev/null Wed Feb 14 13:37:19 2007 @@ -1,2 +0,0 @@ -.deps -.dirstamp --- squid3/src/DiskIO/WinDiskThreads/WinDiskThreads.h Wed Feb 14 13:37:51 2007 +++ /dev/null Wed Feb 14 13:37:19 2007 @@ -1,126 +0,0 @@ -/* - * 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; -}; - -void squidaio_init(void); -void squidaio_shutdown(void); -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_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 --- squid3/src/DiskIO/WinDiskThreads/WinDiskThreadsDiskFile.cc Wed Feb 14 13:37:51 2007 +++ /dev/null Wed Feb 14 13:37:19 2007 @@ -1,387 +0,0 @@ - -/* - * $Id: WinDiskThreadsDiskFile.cc,v 1.1.2.3 2006/06/17 16:51:47 serassio Exp $ - * - * DEBUG: section 79 Disk IO Routines - * AUTHOR: Robert Collins - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - * Copyright (c) 2003, Robert Collins - */ - - -#include "squid.h" -#include "WinDiskThreadsDiskFile.h" -#include "Store.h" -#include "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); - /* - * We used to call squidaio_init() here, but if the first transaction - * is to unlink a file (e.g., if Squid starts up over the disk space - * limit) then "squidaio" won't be initialized yet. - */ - - return result; -} - -void -WinDiskThreadsDiskFile::operator delete (void *address) -{ - WinDiskThreadsDiskFile *t = static_cast(address); - cbdataFree(t); -} - -WinDiskThreadsDiskFile::WinDiskThreadsDiskFile (char const *aPath, WinDiskThreadsIOStrategy *anIO):fd(-1), errorOccured (false), IO(anIO), - inProgressIOs (0) -{ - assert (aPath); - debug (79,3)("UFSFile::UFSFile: %s\n", aPath); - path_ = xstrdup (aPath); -} - -WinDiskThreadsDiskFile::~WinDiskThreadsDiskFile() -{ - safe_free (path_); - doClose(); -} - -void -WinDiskThreadsDiskFile::open (int flags, mode_t mode, IORequestor::Pointer callback) -{ - statCounter.syscalls.disk.opens++; -#if !ASYNC_OPEN - - fd = file_open(path_, flags); - - if (fd < 0) { - debug(79, 3) ("WinDiskThreadsDiskFile::open: got failure (%d)\n", errno); - errorOccured = true; - return; - } - -#endif - Opening_FD++; - - ioRequestor = callback; - - ++inProgressIOs; - -#if ASYNC_OPEN - - aioOpen(path_, flags, mode, WinDiskThreadsDiskFile::OpenDone, this); - -#else - - openDone(fd, NULL, fd, 0); - -#endif -} - -void -WinDiskThreadsDiskFile::read(ReadRequest * request) -{ - debugs(79, 3, "WinDiskThreadsDiskFile::read: " << this << ", size " << request->len); - assert (fd > -1); - assert (ioRequestor.getRaw()); - statCounter.syscalls.disk.reads++; - ++inProgressIOs; -#if ASYNC_READ - - aioRead(fd, request->offset, request->len, ReadDone, new IoResult(this, request)); -#else - - file_read(fd, request->buf, request->len, request->offset, ReadDone, new IoResult(this, request)); -#endif -} - -void -WinDiskThreadsDiskFile::create (int flags, mode_t mode, IORequestor::Pointer callback) -{ - statCounter.syscalls.disk.opens++; -#if !ASYNC_CREATE - - int fd = file_open(path_, flags); - - if (fd < 0) { - debug(79, 3) ("WinDiskThreadsDiskFile::create: got failure (%d)\n", errno); - errorOccured = true; - return; - } - -#endif - Opening_FD++; - - ioRequestor = callback; - - ++inProgressIOs; - -#if ASYNC_CREATE - - aioOpen(path_, flags, mode, WinDiskThreadsDiskFile::OpenDone, this); - -#else - - openDone (fd, NULL, fd, 0); - -#endif -} - -bool -WinDiskThreadsDiskFile::error() const -{ - return errorOccured; -} - -void -WinDiskThreadsDiskFile::OpenDone(int fd, void *cbdata, const char *buf, int aio_return, int aio_errno) -{ - WinDiskThreadsDiskFile *myFile = static_cast(cbdata); - myFile->openDone (fd, buf, aio_return, aio_errno); -} - -void -WinDiskThreadsDiskFile::openDone(int unused, const char *unused2, int anFD, int errflag) -{ - debug(79, 3) ("WinDiskThreadsDiskFile::openDone: FD %d, errflag %d\n", anFD, errflag); - Opening_FD--; - - fd = anFD; - - if (errflag || fd < 0) { - errno = errflag; - debug(79, 0) ("WinDiskThreadsDiskFile::openDone: %s\n", xstrerror()); - debug(79, 1) ("\t%s\n", path_); - errorOccured = true; - } else { - store_open_disk_fd++; - commSetCloseOnExec(fd); - fd_open(fd, FD_FILE, path_); - } - - IORequestor::Pointer t = ioRequestor; - --inProgressIOs; - t->ioCompletedNotification(); - - debug(79, 3) ("WinDiskThreadsDiskFile::openDone: exiting\n"); -} - -void WinDiskThreadsDiskFile::doClose() -{ - if (fd > -1) { - statCounter.syscalls.disk.closes++; -#if ASYNC_CLOSE - - aioClose(fd); - fd_close(fd); -#else - - aioCancel(fd); - file_close(fd); -#endif - - 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 != NULL); - ioRequestor->closeCompleted(); - return; - } else { - debugs(79,0,HERE << "WinDiskThreadsDiskFile::close: " << - "did NOT close because ioInProgress() is true. now what?"); - } -} - -bool -WinDiskThreadsDiskFile::canRead() const -{ - debug (79,3)("WinDiskThreadsDiskFile::canRead: fd is %d\n",fd); - return fd > -1; -} - -void -WinDiskThreadsDiskFile::write(WriteRequest * writeRequest) -{ - debug(79, 3) ("WinDiskThreadsDiskFile::write: FD %d\n", fd); - statCounter.syscalls.disk.writes++; - ++inProgressIOs; -#if ASYNC_WRITE - - aioWrite(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult(this, writeRequest), - writeRequest->free_func); -#else - - file_write(fd, writeRequest->offset, (char *)writeRequest->buf, writeRequest->len, WriteDone, new IoResult(this, writeRequest), - writeRequest->free_func); -#endif -} - -bool -WinDiskThreadsDiskFile::canWrite() const -{ - return fd > -1; -} - -bool -WinDiskThreadsDiskFile::ioInProgress()const -{ - return inProgressIOs > 0; -} - -/* === STATIC =========================================================== */ - -#if ASYNC_READ -void -WinDiskThreadsDiskFile::ReadDone(int fd, void *my_data, const char *buf, int len, int errflag) -#else -void -WinDiskThreadsDiskFile::ReadDone(int fd, const char *buf, int len, int errflag, void *my_data) -#endif -{ - IoResult * result = static_cast *>(my_data); - assert (result); - result->file->readDone(fd, buf, len, errflag, result->request); - delete result; -} - -void -WinDiskThreadsDiskFile::readDone(int rvfd, const char *buf, int len, int errflag, ReadRequest::Pointer request) -{ - debug (79,3)("WinDiskThreadsDiskFile::readDone: FD %d\n",rvfd); - assert (fd == rvfd); - - ssize_t rlen; - - if (errflag) { - debug(79, 3) ("WinDiskThreadsDiskFile::readDone: got failure (%d)\n", errflag); - rlen = -1; - } else { - rlen = (ssize_t) len; - } - -#if ASYNC_READ - /* translate errflag from errno to Squid disk error */ - errno = errflag; - - if (errflag) - errflag = DISK_ERROR; - else - errflag = DISK_OK; - -#else - - if (errflag == DISK_EOF) - errflag = DISK_OK; /* EOF is signalled by len == 0, not errors... */ - -#endif - - --inProgressIOs; - - ioRequestor->readCompleted(buf, rlen, errflag, request); -} - -void -WinDiskThreadsDiskFile:: -#if ASYNC_WRITE -WriteDone(int fd, void *my_data, const char *buf, int len, int errflag) -#else -WriteDone(int fd, int errflag, size_t len, void *my_data) -#endif -{ - IoResult * result = static_cast *>(my_data); - assert (result); - result->file->writeDone(fd, errflag, len, result->request); - delete result; -} - -void -WinDiskThreadsDiskFile::writeDone (int rvfd, int errflag, size_t len, WriteRequest::Pointer request) -{ - assert (rvfd == fd); - static int loop_detect = 0; - -#if ASYNC_WRITE - /* Translate from errno to Squid disk error */ - - if (errflag) - errflag = errflag == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR; - else - errflag = DISK_OK; - -#endif - - debug(79, 3) ("WinDiskThreadsDiskFile::writeDone: FD %d, len %ld, err=%d\n", - fd, (long int) len, errflag); - - assert(++loop_detect < 10); - - --inProgressIOs; - - ioRequestor->writeCompleted(errflag, len, request); - - --loop_detect; -} - -template -cbdata_type IoResult::CBDATA_IoResult = CBDATA_UNKNOWN; - -template -void * -IoResult::operator new (size_t) -{ - CBDATA_INIT_TYPE(IoResult); - IoResult *result = cbdataAlloc(IoResult); - return result; -} - -template -void -IoResult::operator delete (void *address) -{ - cbdataFree(address); -} - --- squid3/src/DiskIO/WinDiskThreads/WinDiskThreadsDiskFile.h Wed Feb 14 13:37:51 2007 +++ /dev/null Wed Feb 14 13:37:19 2007 @@ -1,117 +0,0 @@ - -/* - * $Id: WinDiskThreadsDiskFile.h,v 1.1.2.2 2006/08/29 20:13:50 serassio Exp $ - * - * DEBUG: section 79 Disk IO Routines - * AUTHOR: Robert Collins - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - * Copyright (c) 2003, Robert Collins - */ - -#ifndef SQUID_DISKTHREADSDISKFILE_H -#define SQUID_DISKTHREADSDISKFILE_H -#include "cbdata.h" -#include "DiskIO/DiskFile.h" -#include "WinDiskThreads.h" - -class WinDiskThreadsDiskFile : public DiskFile -{ - -public: - void * operator new (size_t); - void operator delete (void *); - WinDiskThreadsDiskFile (char const *path, WinDiskThreadsIOStrategy *); - ~WinDiskThreadsDiskFile(); - virtual void open (int, mode_t, RefCount); - virtual void create (int, mode_t, RefCount); - virtual void read(ReadRequest *); - virtual void write(WriteRequest *); - virtual void close (); - virtual bool error() const; - virtual int getFD() const { return fd;} - - virtual bool canRead() const; - virtual bool canWrite() const; - virtual bool ioInProgress()const; - -private: -#if ASYNC_READ - - static AIOCB ReadDone; -#else - - static DRCB ReadDone; -#endif -#if ASYNC_WRITE - - static AIOCB WriteDone; -#else - - static DWCB WriteDone; -#endif - - int fd; - bool errorOccured; - char const *path_; - WinDiskThreadsIOStrategy *IO; - size_t inProgressIOs; - static AIOCB OpenDone; - void openDone(int fd, const char *buf, int aio_return, int aio_errno); - RefCount ioRequestor; - CBDATA_CLASS(WinDiskThreadsDiskFile); - void doClose(); - - void readDone(int fd, const char *buf, int len, int errflag, RefCount); - void writeDone (int fd, int errflag, size_t len, RefCount); -}; - -#include "DiskIO/ReadRequest.h" - -template - -class IoResult -{ - -public: - void * operator new (size_t); - void operator delete (void *); - IoResult(RefCount aFile, RefCount aRequest) : file(aFile), request(aRequest){} - - RefCount file; - RefCount request; - -private: - CBDATA_CLASS(IoResult); -}; - -template -IoResult -IOResult(RefCount aRequest, RefCount aFile) { return IoResult(aFile, aRequest);} - -#endif /* SQUID_DISKTHREADSDISKFILE_H */ --- squid3/src/DiskIO/WinDiskThreads/WinDiskThreadsDiskIOModule.cc Wed Feb 14 13:37:51 2007 +++ /dev/null Wed Feb 14 13:37:19 2007 @@ -1,78 +0,0 @@ - -/* - * $Id: WinDiskThreadsDiskIOModule.cc,v 1.1.2.2 2006/06/17 16:51:47 serassio Exp $ - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - * Copyright (c) 2003, Robert Collins - */ - -#include "squid.h" -#include "WinDiskThreadsDiskIOModule.h" -#include "WinDiskThreadsIOStrategy.h" - -WinDiskThreadsDiskIOModule WinDiskThreadsDiskIOModule::Instance; -WinDiskThreadsDiskIOModule & -WinDiskThreadsDiskIOModule::GetInstance() -{ - return Instance; -} - -WinDiskThreadsDiskIOModule::WinDiskThreadsDiskIOModule() -{ - ModuleAdd(*this); -} - -void -WinDiskThreadsDiskIOModule::init() -{ - WinDiskThreadsIOStrategy::Instance.init(); -} - -void -WinDiskThreadsDiskIOModule::registerWithCacheManager(CacheManager & manager) -{ - WinDiskThreadsIOStrategy::Instance.registerWithCacheManager(manager); -} - -void -WinDiskThreadsDiskIOModule::shutdown() -{ - WinDiskThreadsIOStrategy::Instance.done(); -} - -DiskIOStrategy * -WinDiskThreadsDiskIOModule::createStrategy() -{ - return new SingletonIOStrategy(&WinDiskThreadsIOStrategy::Instance); -} - -char const * -WinDiskThreadsDiskIOModule::type () const -{ - return "WinDiskThreads"; -} --- squid3/src/DiskIO/WinDiskThreads/WinDiskThreadsDiskIOModule.h Wed Feb 14 13:37:52 2007 +++ /dev/null Wed Feb 14 13:37:19 2007 @@ -1,56 +0,0 @@ - -/* - * $Id: WinDiskThreadsDiskIOModule.h,v 1.1.2.2 2006/06/17 16:51:47 serassio Exp $ - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - * Copyright (c) 2003, Robert Collins - */ - -#ifndef SQUID_DISKTHREADSDISKIOMODULE_H -#define SQUID_DISKTHREADSDISKIOMODULE_H - -#include "DiskIO/DiskIOModule.h" - -class WinDiskThreadsDiskIOModule : public DiskIOModule -{ - -public: - static WinDiskThreadsDiskIOModule &GetInstance(); - WinDiskThreadsDiskIOModule(); - virtual void init(); - virtual void registerWithCacheManager(CacheManager & manager); - virtual void shutdown(); - virtual char const *type () const; - virtual DiskIOStrategy* createStrategy(); - -private: - static WinDiskThreadsDiskIOModule Instance; -}; - - -#endif /* SQUID_DISKTHREADSDISKIOMODULE_H */ --- squid3/src/DiskIO/WinDiskThreads/WinDiskThreadsIOStrategy.cc Wed Feb 14 13:37:52 2007 +++ /dev/null Wed Feb 14 13:37:19 2007 @@ -1,269 +0,0 @@ - -/* - * $Id: WinDiskThreadsIOStrategy.cc,v 1.1.2.6 2006/06/17 16:51:47 serassio Exp $ - * - * DEBUG: section 79 Squid-side Disk I/O functions. - * AUTHOR: Robert Collins - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - * Copyright (c) 2003, Robert Collins - */ - -#include "squid.h" - -#include "CacheManager.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)); - - initialised = true; - - /* - * We'd like to call squidaio_init() here, but the configuration - * hasn't been parsed yet and we don't know how many cache_dirs - * there are, which means we don't know how many threads to start. - */ -} - -void -WinDiskThreadsIOStrategy::registerWithCacheManager(CacheManager & manager) -{ - manager.registerAction("squidaio_counts", "Async IO Function Counters", - aioStats, 0, 1); -} - -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); - - 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); -} - -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 - - aioTruncate(path, NULL, NULL); -#else - - aioUnlink(path, NULL, NULL); -#endif -} --- squid3/src/DiskIO/WinDiskThreads/WinDiskThreadsIOStrategy.h Wed Feb 14 13:37:52 2007 +++ /dev/null Wed Feb 14 13:37:19 2007 @@ -1,73 +0,0 @@ - -/* - * $Id: WinDiskThreadsIOStrategy.h,v 1.1.2.3 2006/06/17 16:51:48 serassio Exp $ - * - * DEBUG: section 79 Squid-side Disk I/O functions. - * AUTHOR: Robert Collins - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - * Copyright (c) 2003, Robert Collins - */ - -#ifndef __STORE_DISKTHREADEDIOSTRATEGY_H__ -#define __STORE_DISKTHREADEDIOSTRATEGY_H__ - -#define _AIO_OPEN 0 -#define _AIO_READ 1 -#define _AIO_WRITE 2 -#define _AIO_CLOSE 3 -#define _AIO_UNLINK 4 -#define _AIO_TRUNCATE 4 -#define _AIO_OPENDIR 5 -#define _AIO_STAT 6 -#include "DiskIO/DiskIOStrategy.h" - -class WinDiskThreadsIOStrategy : public DiskIOStrategy -{ - -public: - WinDiskThreadsIOStrategy(); - virtual bool shedLoad(); - virtual int load(); - virtual RefCount newFile(char const *path); - virtual void unlinkFile (char const *); - virtual int callback(); - virtual void sync(); - virtual void init(); - virtual void registerWithCacheManager(CacheManager & manager); - void done(); - /* Todo: add access limitations */ - bool initialised; - static WinDiskThreadsIOStrategy Instance; - MemAllocatorProxy *squidaio_ctrl_pool; - -private: - static void aioStats(StoreEntry * sentry); -}; - -#endif --- squid3/src/DiskIO/WinDiskThreads/aiops.cc Wed Feb 14 13:37:52 2007 +++ /dev/null Wed Feb 14 13:37:19 2007 @@ -1,1242 +0,0 @@ -/* - * $Id: aiops.cc,v 1.1.2.8 2006/08/29 20:13:50 serassio Exp $ - * - * DEBUG: section 43 AIOPS - * AUTHOR: Stewart Forster - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "squid_windows.h" -#include "WinDiskThreads.h" - -#include -#include -#include -#include -#include -#include -#include -#include "CommIO.h" -#include "SquidTime.h" -#include "Store.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_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 *); -#if USE_TRUNCATE -static void squidaio_do_truncate(squidaio_request_t *); -#else -static void squidaio_do_unlink(squidaio_request_t *); -#endif -#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); -} - -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; - - CommIO::NotifyIOCompleted(); - - /* 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; - - /* This is the same as in squidaio_sync */ - do { - squidaio_poll_queues(); - } while (request_queue_len > 0); - - 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); - CommIO::NotifyIOClose(); - - 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; - -#if USE_TRUNCATE - - case _AIO_OP_TRUNCATE: - squidaio_do_truncate(request); - break; -#else - - case _AIO_OP_UNLINK: - squidaio_do_unlink(request); - break; - -#endif -#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: - 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_init(); - squidaio_request_t *requestp; - - 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; - - 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; - - 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_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->bufferp, - requestp->buflen, (LPDWORD)&requestp->ret, NULL)) { - WIN32_maperror(GetLastError()); - requestp->ret = -1; - } - -#else - requestp->ret = write(requestp->fd, requestp->bufferp, requestp->buflen); - -#endif - - requestp->err = errno; -} - - -int -squidaio_close(int fd, squidaio_result_t * resultp) -{ - squidaio_request_t *requestp; - - 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_init(); - squidaio_request_t *requestp; - - 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; -} - - -#if USE_TRUNCATE -int -squidaio_truncate(const char *path, off_t length, squidaio_result_t * resultp) -{ - squidaio_init(); - squidaio_request_t *requestp; - - 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; -} - - -#else -int -squidaio_unlink(const char *path, squidaio_result_t * resultp) -{ - squidaio_init(); - squidaio_request_t *requestp; - - 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; -} - -#endif - -#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; - - 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/DiskIO/WinDiskThreads/async_io.cc Wed Feb 14 13:37:52 2007 +++ /dev/null Wed Feb 14 13:37:19 2007 @@ -1,254 +0,0 @@ - -/* - * $Id: async_io.cc,v 1.1.2.3 2005/08/21 07:43:52 serassio Exp $ - * - * DEBUG: section 32 Asynchronous Disk I/O - * AUTHOR: Pete Bentley - * AUTHOR: Stewart Forster - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "WinDiskThreads.h" -#include "Store.h" -#include "fde.h" -#include "WinDiskThreadsIOStrategy.h" -#include "Generic.h" - -AIOCounts squidaio_counts; - -typedef struct squidaio_unlinkq_t -{ - char *path; - - struct squidaio_unlinkq_t *next; -} - -squidaio_unlinkq_t; - -dlink_list used_list; - -void -aioOpen(const char *path, int oflag, mode_t mode, AIOCB * callback, void *callback_data) -{ - squidaio_ctrl_t *ctrlp; - - assert(WinDiskThreadsIOStrategy::Instance.initialised); - squidaio_counts.open_start++; - ctrlp = (squidaio_ctrl_t *)WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->alloc(); - ctrlp->fd = -2; - ctrlp->done_handler = callback; - ctrlp->done_handler_data = cbdataReference(callback_data); - ctrlp->operation = _AIO_OPEN; - ctrlp->result.data = ctrlp; - squidaio_open(path, oflag, mode, &ctrlp->result); - dlinkAdd(ctrlp, &ctrlp->node, &used_list); - return; -} - -void -aioClose(int fd) -{ - squidaio_ctrl_t *ctrlp; - - assert(WinDiskThreadsIOStrategy::Instance.initialised); - squidaio_counts.close_start++; - aioCancel(fd); - ctrlp = (squidaio_ctrl_t *)WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->alloc(); - ctrlp->fd = fd; - ctrlp->done_handler = NULL; - ctrlp->done_handler_data = NULL; - ctrlp->operation = _AIO_CLOSE; - ctrlp->result.data = ctrlp; - squidaio_close(fd, &ctrlp->result); - dlinkAdd(ctrlp, &ctrlp->node, &used_list); - return; -} - -void -aioCancel(int fd) -{ - squidaio_ctrl_t *ctrlp; - dlink_node *m, *next; - - assert(WinDiskThreadsIOStrategy::Instance.initialised); - squidaio_counts.cancel++; - - for (m = used_list.head; m; m = next) { - next = m->next; - ctrlp = (squidaio_ctrl_t *)m->data; - - if (ctrlp->fd != fd) - continue; - - squidaio_cancel(&ctrlp->result); - - if (ctrlp->done_handler) { - AIOCB *callback = ctrlp->done_handler; - void *cbdata; - ctrlp->done_handler = NULL; - debug(32, 1) ("this be aioCancel. Danger ahead!\n"); - - if (cbdataReferenceValidDone(ctrlp->done_handler_data, &cbdata)) - callback(fd, cbdata, NULL, -2, -2); - - /* free data if requested to aioWrite() */ - if (ctrlp->free_func) - ctrlp->free_func(ctrlp->bufp); - - /* free temporary read buffer */ - if (ctrlp->operation == _AIO_READ) - squidaio_xfree(ctrlp->bufp, ctrlp->len); - } - - dlinkDelete(m, &used_list); - WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->free(ctrlp); - } -} - - -void -aioWrite(int fd, int offset, char *bufp, int len, AIOCB * callback, void *callback_data, FREE * free_func) -{ - squidaio_ctrl_t *ctrlp; - int seekmode; - - assert(WinDiskThreadsIOStrategy::Instance.initialised); - squidaio_counts.write_start++; - ctrlp = (squidaio_ctrl_t *)WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->alloc(); - ctrlp->fd = fd; - ctrlp->done_handler = callback; - ctrlp->done_handler_data = cbdataReference(callback_data); - ctrlp->operation = _AIO_WRITE; - ctrlp->bufp = bufp; - ctrlp->free_func = free_func; - - if (offset >= 0) - seekmode = SEEK_SET; - else { - seekmode = SEEK_END; - offset = 0; - } - - ctrlp->result.data = ctrlp; - squidaio_write(fd, bufp, len, offset, seekmode, &ctrlp->result); - dlinkAdd(ctrlp, &ctrlp->node, &used_list); -} /* aioWrite */ - - -void -aioRead(int fd, int offset, int len, AIOCB * callback, void *callback_data) -{ - squidaio_ctrl_t *ctrlp; - int seekmode; - - assert(WinDiskThreadsIOStrategy::Instance.initialised); - squidaio_counts.read_start++; - ctrlp = (squidaio_ctrl_t *)WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->alloc(); - ctrlp->fd = fd; - ctrlp->done_handler = callback; - ctrlp->done_handler_data = cbdataReference(callback_data); - ctrlp->operation = _AIO_READ; - ctrlp->len = len; - ctrlp->bufp = (char *)squidaio_xmalloc(len); - - if (offset >= 0) - seekmode = SEEK_SET; - else { - seekmode = SEEK_CUR; - offset = 0; - } - - ctrlp->result.data = ctrlp; - squidaio_read(fd, ctrlp->bufp, len, offset, seekmode, &ctrlp->result); - dlinkAdd(ctrlp, &ctrlp->node, &used_list); - return; -} /* aioRead */ - -void - -aioStat(char *path, struct stat *sb, AIOCB * callback, void *callback_data) -{ - squidaio_ctrl_t *ctrlp; - - assert(WinDiskThreadsIOStrategy::Instance.initialised); - squidaio_counts.stat_start++; - ctrlp = (squidaio_ctrl_t *)WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->alloc(); - ctrlp->fd = -2; - ctrlp->done_handler = callback; - ctrlp->done_handler_data = cbdataReference(callback_data); - ctrlp->operation = _AIO_STAT; - ctrlp->result.data = ctrlp; - squidaio_stat(path, sb, &ctrlp->result); - dlinkAdd(ctrlp, &ctrlp->node, &used_list); - return; -} /* aioStat */ - -#if USE_TRUNCATE -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 */ - -#else - -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 */ - -#endif - -int -aioQueueSize(void) -{ - return WinDiskThreadsIOStrategy::Instance.squidaio_ctrl_pool->inUseCount(); -}