diff -u -r -N squid-3.2.0.12/ChangeLog squid-3.2.0.13/ChangeLog --- squid-3.2.0.12/ChangeLog 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/ChangeLog 2011-10-14 14:42:56.000000000 +1300 @@ -1,3 +1,25 @@ +Changes to squid-3.2.0.13 (14 Oct 2011): + + - Regression Bug 3363: never_direct always 'unable to forward this request at this time' + - Regression Bug 3351: FTP timeout causing "store_status == STORE_PENDING" assertion + - Regression Bug 3336: reconfigure assertion 'hlp->childs.n_running > 0' + - Regression fix: always_direct/never_direct failures + - Regression fix: stop an SSL header file being included after --disable-ssl + - Regression fix: parse HTTP list headers with embedded 8-bit characters + - Bug 3355: configure setting --with-swapdir ignored + - Bug 3325: option to selectively enable strict host verify checks + - Bug 3337: HTTP status 200 is not accepted for deny_info + - Bug 3077: '\' in url query strings cause Digest authentication to fail + - Support SMP worker shared memory cache + - Support SMP worker shared disk cache (rock) + - ext_session_acl: version 1.1 + - Fix Host verify: do not pinn destination IP if URL re-write has been done + - Fix IPF interception + - Fix ssl_crtd "Cannot add certificate to db" when updating expired cert + - Fix ssl_crtd CertificateDB locking scheme + - ... and all changes from 3.1.16 + - ... and many compile and polishing fixes + Changes to squid-3.2.0.12 (17 Sep 2011): - Regression Bug 3335: ICAP service is down @@ -264,6 +286,19 @@ - ... and a great many testing improvements - ... and many documentation updates +Changes to squid-3.1.16 (14 Oct 2011): + + - Bug 3373: invalid URL in ERR_CACHE_ACCESS_DENIED + - Bug 3368: Unhandled exceptions are not logged (workaround) + - Bug 3326: miss_access incorrect default + - Bug 3320: miss_access description confusing + - Bug 3241: squid_kerb_auth cross compilation fix + - Bug 3237: seq fault in free() from rfc1035RRDestroy + - Bug 3190: Large HTTP POST stuck after early ICAP 400 error response + - db_auth: display available DSN drivers on connect error + - Updated OpenSSL 1.0.0 version checks + - ... and several documentation fixes + Changes to squid-3.1.15 (28 Aug 2011): - Regression fix: vhost and defaultsite causing vport to be ignored diff -u -r -N squid-3.2.0.12/compat/Makefile.am squid-3.2.0.13/compat/Makefile.am --- squid-3.2.0.12/compat/Makefile.am 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/compat/Makefile.am 2011-10-14 14:42:56.000000000 +1300 @@ -31,6 +31,7 @@ initgroups.h \ osdetect.h \ psignal.h \ + shm.h \ stdio.h \ stdvarargs.h \ strnstr.cc \ diff -u -r -N squid-3.2.0.12/compat/Makefile.in squid-3.2.0.13/compat/Makefile.in --- squid-3.2.0.12/compat/Makefile.in 2011-09-16 23:38:07.000000000 +1200 +++ squid-3.2.0.13/compat/Makefile.in 2011-10-14 14:46:37.000000000 +1300 @@ -353,6 +353,7 @@ initgroups.h \ osdetect.h \ psignal.h \ + shm.h \ stdio.h \ stdvarargs.h \ strnstr.cc \ diff -u -r -N squid-3.2.0.12/compat/shm.h squid-3.2.0.13/compat/shm.h --- squid-3.2.0.12/compat/shm.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/compat/shm.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,45 @@ +/* + * $Id$ + */ +#ifndef SQUID_COMPAT_SHM_H +#define SQUID_COMPAT_SHM_H + +#if HAVE_SHM + +#if HAVE_SYS_STAT_H +#include /* for mode constants */ +#endif + +#if HAVE_FCNTL_H +#include /* for O_* constants */ +#endif + +#if HAVE_SYS_MMAN_H +#include +#endif + +#else /* HAVE_SHM */ + +#if HAVE_ERRNO_H +#include +#endif + +extern "C" { + + inline int + shm_open(const char *, int, mode_t) { + errno = ENOTSUP; + return -1; + } + + inline int + shm_unlink(const char *) { + errno = ENOTSUP; + return -1; + } + +} /* extern "C" */ + +#endif /* HAVE_SHM */ + +#endif /* SQUID_COMPAT_CPU_H */ diff -u -r -N squid-3.2.0.12/configure squid-3.2.0.13/configure --- squid-3.2.0.12/configure 2011-09-16 23:38:35.000000000 +1200 +++ squid-3.2.0.13/configure 2011-10-14 14:49:52.000000000 +1300 @@ -1,7 +1,7 @@ #! /bin/sh # From configure.ac Revision. # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for Squid Web Proxy 3.2.0.12. +# Generated by GNU Autoconf 2.68 for Squid Web Proxy 3.2.0.13. # # Report bugs to . # @@ -575,8 +575,8 @@ # Identity of this package. PACKAGE_NAME='Squid Web Proxy' PACKAGE_TARNAME='squid' -PACKAGE_VERSION='3.2.0.12' -PACKAGE_STRING='Squid Web Proxy 3.2.0.12' +PACKAGE_VERSION='3.2.0.13' +PACKAGE_STRING='Squid Web Proxy 3.2.0.13' PACKAGE_BUGREPORT='http://www.squid-cache.org/bugs/' PACKAGE_URL='' @@ -1570,7 +1570,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures Squid Web Proxy 3.2.0.12 to adapt to many kinds of systems. +\`configure' configures Squid Web Proxy 3.2.0.13 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1640,7 +1640,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Squid Web Proxy 3.2.0.12:";; + short | recursive ) echo "Configuration of Squid Web Proxy 3.2.0.13:";; esac cat <<\_ACEOF @@ -2018,7 +2018,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Squid Web Proxy configure 3.2.0.12 +Squid Web Proxy configure 3.2.0.13 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -3114,7 +3114,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by Squid Web Proxy $as_me 3.2.0.12, which was +It was created by Squid Web Proxy $as_me 3.2.0.13, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -3933,7 +3933,7 @@ # Define the identity of the package. PACKAGE='squid' - VERSION='3.2.0.12' + VERSION='3.2.0.13' cat >>confdefs.h <<_ACEOF @@ -18667,6 +18667,45 @@ # to be used by sub-commands export enable_inline +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic operations support" >&5 +$as_echo_n "checking for atomic operations support... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + int n = 0; + +int +main () +{ + + __sync_add_and_fetch(&n, 10); // n becomes 10 + __sync_fetch_and_add(&n, 20); // n becomes 30 + __sync_sub_and_fetch(&n, 15); // n becomes 15 + __sync_bool_compare_and_swap(&n, 15, 201); // n becomes 201 + __sync_fetch_and_and(&n, 200); // n becomes 200 + return (n == 200) ? 0 : -1; + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + + +$as_echo "#define HAVE_ATOMIC_OPS 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + # Check whether --enable-debug-cbdata was given. if test "${enable_debug_cbdata+set}" = set; then : enableval=$enable_debug_cbdata; @@ -18779,6 +18818,68 @@ $as_echo "$as_me: With dl" >&6;} fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing shm_open" >&5 +$as_echo_n "checking for library containing shm_open... " >&6; } +if ${ac_cv_search_shm_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shm_open (); +int +main () +{ +return shm_open (); + ; + return 0; +} +_ACEOF +for ac_lib in '' rt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_shm_open=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_shm_open+:} false; then : + break +fi +done +if ${ac_cv_search_shm_open+:} false; then : + +else + ac_cv_search_shm_open=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_shm_open" >&5 +$as_echo "$ac_cv_search_shm_open" >&6; } +ac_res=$ac_cv_search_shm_open +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +if test "x$ac_cv_search_shm_open" != "xno" ; then + +$as_echo "#define HAVE_SHM 1" >>confdefs.h + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DiskIO modules to be enabled" >&5 $as_echo_n "checking for DiskIO modules to be enabled... " >&6; } squid_disk_module_candidates="" @@ -18837,6 +18938,10 @@ fi done + if test "x$ac_cv_search_shm_open" = "xno" ; then + # disable IpcIo + squid_disk_module_candidates=`echo $squid_disk_module_candidates|sed 's/IpcIo//'` + fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${squid_disk_module_candidates:-none}" >&5 @@ -19318,6 +19423,28 @@ fi ;; + Mmapped) + { $as_echo "$as_me:${as_lineno-$LINENO}: Enabling Mmapped DiskIO module" >&5 +$as_echo "$as_me: Enabling Mmapped DiskIO module" >&6;} + DISK_LIBS="$DISK_LIBS libMmapped.a" + DISK_MODULES="$DISK_MODULES Mmapped" + DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/Mmapped/MmappedDiskIOModule.o" + ;; + + IpcIo) + { $as_echo "$as_me:${as_lineno-$LINENO}: Enabling IpcIo DiskIO module" >&5 +$as_echo "$as_me: Enabling IpcIo DiskIO module" >&6;} + if test "x$ac_cv_search_shm_open" = "xno" ; then + as_fn_error $? "DiskIO IpcIo module requires shared memory support" "$LINENO" 5 + fi + DISK_LIBS="$DISK_LIBS libIpcIo.a" + DISK_MODULES="$DISK_MODULES IpcIo" + DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/IpcIo/IpcIoDiskIOModule.o" + +$as_echo "#define USE_DISKIO_IPCIO 1" >>confdefs.h + + ;; + Blocking) { $as_echo "$as_me:${as_lineno-$LINENO}: Enabling Blocking DiskIO module" >&5 $as_echo "$as_me: Enabling Blocking DiskIO module" >&6;} @@ -19462,6 +19589,12 @@ # for STORE_TESTS substition STORE_TESTS="$STORE_TESTS tests/testCoss$EXEEXT" ;; + rock) + if test "x$squid_disk_module_candidates_IpcIo" != "xyes" -a \ + "x$squid_disk_module_candidates_Blocking" != "xyes"; then + as_fn_error $? "Storage module Rock requires IpcIo or Blocking DiskIO module" "$LINENO" 5 + fi + ;; ufs) STORE_TESTS="$STORE_TESTS tests/testUfs$EXEEXT" esac @@ -19473,6 +19606,7 @@ + STORE_LIBS_TO_BUILD= STORE_LIBS_TO_ADD= for fs in $squid_storeio_module_candidates; do @@ -23993,6 +24127,7 @@ sys/param.h \ sys/prctl.h \ sys/md5.h \ + sys/mman.h \ sys/msg.h \ sys/resource.h \ sys/select.h \ @@ -30543,7 +30678,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by Squid Web Proxy $as_me 3.2.0.12, which was +This file was extended by Squid Web Proxy $as_me 3.2.0.13, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -30609,7 +30744,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -Squid Web Proxy config.status 3.2.0.12 +Squid Web Proxy config.status 3.2.0.13 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" diff -u -r -N squid-3.2.0.12/configure.ac squid-3.2.0.13/configure.ac --- squid-3.2.0.12/configure.ac 2011-09-16 23:38:35.000000000 +1200 +++ squid-3.2.0.13/configure.ac 2011-10-14 14:49:52.000000000 +1300 @@ -3,7 +3,7 @@ dnl dnl dnl -AC_INIT([Squid Web Proxy],[3.2.0.12],[http://www.squid-cache.org/bugs/],[squid]) +AC_INIT([Squid Web Proxy],[3.2.0.13],[http://www.squid-cache.org/bugs/],[squid]) AC_PREREQ(2.61) AC_CONFIG_HEADERS([include/autoconf.h]) AC_CONFIG_AUX_DIR(cfgaux) @@ -367,6 +367,29 @@ # to be used by sub-commands export enable_inline +dnl +dnl Check for atomic operations support in the compiler +dnl +AC_MSG_CHECKING([for atomic operations support]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + int n = 0; +]],[[ + __sync_add_and_fetch(&n, 10); // n becomes 10 + __sync_fetch_and_add(&n, 20); // n becomes 30 + __sync_sub_and_fetch(&n, 15); // n becomes 15 + __sync_bool_compare_and_swap(&n, 15, 201); // n becomes 201 + __sync_fetch_and_and(&n, 200); // n becomes 200 + return (n == 200) ? 0 : -1; +]])], +[ + AC_DEFINE(HAVE_ATOMIC_OPS,1, + [Define to 1 if you have __sync_add_and_fetch() and such]) + AC_MSG_RESULT(yes) +],[ + AC_MSG_RESULT(no) +]) + + AC_ARG_ENABLE(debug-cbdata, AS_HELP_STRING([--enable-debug-cbdata], [Provide some debug information in cbdata]), [ @@ -439,6 +462,11 @@ AC_MSG_NOTICE([With dl]) fi +AC_SEARCH_LIBS([shm_open], [rt]) +if test "x$ac_cv_search_shm_open" != "xno" ; then + AC_DEFINE(HAVE_SHM,1,[Support shared memory features]) +fi + AC_MSG_CHECKING([for DiskIO modules to be enabled]) squid_disk_module_candidates="" squid_opt_enable_diskio="auto" #values: no, yes, "auto"(=yes+detect modules) @@ -469,6 +497,10 @@ if test "x$squid_opt_enable_diskio" = "xauto"; then squid_opt_enable_diskio="yes" SQUID_LOOK_FOR_MODULES([$srcdir/src/DiskIO],[squid_disk_module_candidates]) + if test "x$ac_cv_search_shm_open" = "xno" ; then + # disable IpcIo + squid_disk_module_candidates=`echo $squid_disk_module_candidates|sed 's/IpcIo//'` + fi fi AC_MSG_RESULT([${squid_disk_module_candidates:-none}]) @@ -635,6 +667,24 @@ fi ;; + Mmapped) + AC_MSG_NOTICE([Enabling Mmapped DiskIO module]) + DISK_LIBS="$DISK_LIBS libMmapped.a" + DISK_MODULES="$DISK_MODULES Mmapped" + DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/Mmapped/MmappedDiskIOModule.o" + ;; + + IpcIo) + AC_MSG_NOTICE([Enabling IpcIo DiskIO module]) + if test "x$ac_cv_search_shm_open" = "xno" ; then + AC_MSG_ERROR([DiskIO IpcIo module requires shared memory support]) + fi + DISK_LIBS="$DISK_LIBS libIpcIo.a" + DISK_MODULES="$DISK_MODULES IpcIo" + DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/IpcIo/IpcIoDiskIOModule.o" + AC_DEFINE(USE_DISKIO_IPCIO, 1, [Enable DiskIO IpcIo module.]) + ;; + Blocking) AC_MSG_NOTICE([Enabling Blocking DiskIO module]) DISK_LIBS="$DISK_LIBS libBlocking.a" @@ -722,6 +772,12 @@ # for STORE_TESTS substition STORE_TESTS="$STORE_TESTS tests/testCoss$EXEEXT" ;; + rock) + if test "x$squid_disk_module_candidates_IpcIo" != "xyes" -a \ + "x$squid_disk_module_candidates_Blocking" != "xyes"; then + AC_MSG_ERROR([Storage module Rock requires IpcIo or Blocking DiskIO module]) + fi + ;; ufs) STORE_TESTS="$STORE_TESTS tests/testUfs$EXEEXT" esac @@ -733,6 +789,7 @@ AH_TEMPLATE(HAVE_FS_AUFS, "Define to 1 if aufs filesystem module is build") AH_TEMPLATE(HAVE_FS_DISKD, "Define to 1 if diskd filesystem module is build") AH_TEMPLATE(HAVE_FS_COSS, "Define to 1 if coss filesystem module is build") +AH_TEMPLATE(HAVE_FS_ROCK, "Define to 1 if rock filesystem module is build") dnl got final squid_storeio_module_candidates, build library lists @@ -2297,6 +2354,7 @@ sys/param.h \ sys/prctl.h \ sys/md5.h \ + sys/mman.h \ sys/msg.h \ sys/resource.h \ sys/select.h \ diff -u -r -N squid-3.2.0.12/doc/debug-sections.txt squid-3.2.0.13/doc/debug-sections.txt --- squid-3.2.0.12/doc/debug-sections.txt 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/doc/debug-sections.txt 2011-10-14 14:42:56.000000000 +1300 @@ -36,6 +36,7 @@ section 17 Request Forwarding section 18 Cache Manager Statistics section 19 Store Memory Primitives +section 20 Memory Cache section 20 Storage Manager section 20 Storage Manager Heap-based replacement section 20 Storage Manager Logging Functions diff -u -r -N squid-3.2.0.12/errors/af/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/af/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/af/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:39:41.000000000 +1200 +++ squid-3.2.0.13/errors/af/ERR_CACHE_ACCESS_DENIED 2011-10-14 14:59:30.000000000 +1300 @@ -1 +1 @@ - FOUT: Cache Access Denied

ERROR

Cache Toegang geweier.


Die volgende fout is teëgekom tydens verkryging van die URL: %U

Toegang tot kasgeheue geweier.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself or change your default password.



\ No newline at end of file + FOUT: Cache Access Denied

ERROR

Cache Toegang geweier.


Die volgende fout is teëgekom tydens verkryging van die URL: %U

Toegang tot kasgeheue geweier.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/af/error-details.txt squid-3.2.0.13/errors/af/error-details.txt --- squid-3.2.0.12/errors/af/error-details.txt 2011-09-16 23:39:59.000000000 +1200 +++ squid-3.2.0.13/errors/af/error-details.txt 2011-10-14 15:01:29.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_FOUT_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_FOUT_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_FOUT_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_FOUT_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/ar/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/ar/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/ar/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:40:01.000000000 +1200 +++ squid-3.2.0.13/errors/ar/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:01:46.000000000 +1300 @@ -1 +1 @@ - خطأ: Cache Access Denied

ERROR

Cache Access Denied.


The following error was encountered while trying to retrieve the URL: %U

Cache Access Denied.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself or change your default password.



\ No newline at end of file + خطأ: Cache Access Denied

ERROR

Cache Access Denied.


The following error was encountered while trying to retrieve the URL: %U

Cache Access Denied.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/ar/error-details.txt squid-3.2.0.13/errors/ar/error-details.txt --- squid-3.2.0.12/errors/ar/error-details.txt 2011-09-16 23:40:18.000000000 +1200 +++ squid-3.2.0.13/errors/ar/error-details.txt 2011-10-14 15:04:09.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_خطأ_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_خطأ_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_خطأ_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_خطأ_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/az/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/az/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/az/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:40:20.000000000 +1200 +++ squid-3.2.0.13/errors/az/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:04:25.000000000 +1300 @@ -1 +1 @@ - SƏHV: Cache Access Denied

ERROR

Cache Giriş qadağandır.


The following error was encountered while trying to retrieve the URL: %U

Keşdən istifadə qadağandır

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

İdentifikasiya ilə çətinlik olduğu halda, xahiş edirik, KEŞİN sistem administratoru ilə əlaqə saxlayın və ya şifrənizi dəyişdirin.



\ No newline at end of file + SƏHV: Cache Access Denied

ERROR

Cache Giriş qadağandır.


The following error was encountered while trying to retrieve the URL: %U

Keşdən istifadə qadağandır

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/az/error-details.txt squid-3.2.0.13/errors/az/error-details.txt --- squid-3.2.0.12/errors/az/error-details.txt 2011-09-16 23:40:38.000000000 +1200 +++ squid-3.2.0.13/errors/az/error-details.txt 2011-10-14 15:06:24.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_SƏHV_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_SƏHV_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_SƏHV_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_SƏHV_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/bg/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/bg/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/bg/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:40:39.000000000 +1200 +++ squid-3.2.0.13/errors/bg/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:06:35.000000000 +1300 @@ -1 +1 @@ - ГРЕШКА: Cache Access Denied

ERROR

Cache Отказан достъп


Възникна следната грешка при опит за достъп до: %U

Отказан достъп до кешираните данни.

Съжалявам, не Ви е позволен достъп до %U от този кеш докато не представите своето име и парола за достъп.

Моля обърнете се към администратора ако имате проблем с достъпа или сменете паролата си.



\ No newline at end of file + ГРЕШКА: Cache Access Denied

ERROR

Cache Отказан достъп


Възникна следната грешка при опит за достъп до: %U

Отказан достъп до кешираните данни.

Съжалявам, не Ви е позволен достъп до %U от този кеш докато не представите своето име и парола за достъп.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/bg/error-details.txt squid-3.2.0.13/errors/bg/error-details.txt --- squid-3.2.0.12/errors/bg/error-details.txt 2011-09-16 23:40:57.000000000 +1200 +++ squid-3.2.0.13/errors/bg/error-details.txt 2011-10-14 15:08:37.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_ГРЕШКА_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_ГРЕШКА_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_ГРЕШКА_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_ГРЕШКА_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/ca/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/ca/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/ca/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:40:59.000000000 +1200 +++ squid-3.2.0.13/errors/ca/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:08:48.000000000 +1300 @@ -1 +1 @@ - ERROR: Accés denegat a la cache

ERROR

Cache Accés no autoritzat.


The following error was encountered while trying to retrieve the URL: %U

Accés denegat a la cache

L'accés a l'objecte %U no està permès sense autentificació prèvia.

Contacteu ambel vostre administrador de cache si teniudificultats per a autentificar-vos o canvieu la vostra contrasenya.



\ No newline at end of file + ERROR: Accés denegat a la cache

ERROR

Cache Accés no autoritzat.


The following error was encountered while trying to retrieve the URL: %U

Accés denegat a la cache

L'accés a l'objecte %U no està permès sense autentificació prèvia.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/cs/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/cs/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/cs/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:41:18.000000000 +1200 +++ squid-3.2.0.13/errors/cs/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:10:35.000000000 +1300 @@ -1 +1 @@ - CHYBA: Cache Access Denied

ERROR

Cache Přístup odepřen.


The following error was encountered while trying to retrieve the URL: %U

Přístup k cache odepřen.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

V případě problému se prosím obraťte na cache administratora nebo si změňte heslo.



\ No newline at end of file + CHYBA: Cache Access Denied

ERROR

Cache Přístup odepřen.


The following error was encountered while trying to retrieve the URL: %U

Přístup k cache odepřen.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/cs/error-details.txt squid-3.2.0.13/errors/cs/error-details.txt --- squid-3.2.0.12/errors/cs/error-details.txt 2011-09-16 23:41:36.000000000 +1200 +++ squid-3.2.0.13/errors/cs/error-details.txt 2011-10-14 15:12:14.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_CHYBA_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_CHYBA_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_CHYBA_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_CHYBA_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/da/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/da/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/da/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:41:38.000000000 +1200 +++ squid-3.2.0.13/errors/da/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:12:24.000000000 +1300 @@ -1 +1 @@ - FEJL: Cache Access Denied

ERROR

Cache Adgang Nægtet.


The following error was encountered while trying to retrieve the URL: %U

Cache Adgang Nægtet.

Du har desværre ikke lov til at hente %U fra denne cache førend du har autenticieret dig selv.

Kontakt cache administratoren hvis du har problemer med at autenticiere dig eller skift dit password.



\ No newline at end of file + FEJL: Cache Access Denied

ERROR

Cache Adgang Nægtet.


The following error was encountered while trying to retrieve the URL: %U

Cache Adgang Nægtet.

Du har desværre ikke lov til at hente %U fra denne cache førend du har autenticieret dig selv.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/da/error-details.txt squid-3.2.0.13/errors/da/error-details.txt --- squid-3.2.0.12/errors/da/error-details.txt 2011-09-16 23:41:55.000000000 +1200 +++ squid-3.2.0.13/errors/da/error-details.txt 2011-10-14 15:13:41.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_FEJL_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_FEJL_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_FEJL_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_FEJL_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/de/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/de/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/de/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:41:57.000000000 +1200 +++ squid-3.2.0.13/errors/de/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:13:49.000000000 +1300 @@ -1 +1 @@ - FEHLER: Cache Access Denied

ERROR

Cache Zugriff verweigert.


Der folgende Fehler wurde beim Versuch die URL %U zu holen festgestellt:

Cache Zugriff verweigert.

Sie sind momentan nicht berechtigt %U von diesem Cache abzurufen, bis sie sich authentifiziert haben.

Bitte kontaktieren sie den Cache Administrator Falls sie Schwierigkeiten haben sich zu authentifizieren oder ändern sie ihr Standardpasswort.



\ No newline at end of file + FEHLER: Cache Access Denied

ERROR

Cache Zugriff verweigert.


Der folgende Fehler wurde beim Versuch die URL %U zu holen festgestellt:

Cache Zugriff verweigert.

Sie sind momentan nicht berechtigt %U von diesem Cache abzurufen, bis sie sich authentifiziert haben.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/de/error-details.txt squid-3.2.0.13/errors/de/error-details.txt --- squid-3.2.0.12/errors/de/error-details.txt 2011-09-16 23:42:14.000000000 +1200 +++ squid-3.2.0.13/errors/de/error-details.txt 2011-10-14 15:15:15.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_FEHLER_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_FEHLER_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_FEHLER_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_FEHLER_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/el/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/el/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/el/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:42:16.000000000 +1200 +++ squid-3.2.0.13/errors/el/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:15:27.000000000 +1300 @@ -1 +1 @@ - ΣΦΑΛΜΑ: Cache Access Denied

ERROR

Cache Απαγορεύεται η Πρόσβαση.


The following error was encountered while trying to retrieve the URL: %U

Απαγορεύεται η Πρόσβαση στο Μεσολαβητή.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Επικοινωνήστε με τον διαχειριστή του μεσολαβητή σας αν αντιμετωπίζετε δυσκολία να πιστοποιήσετε τον λογαριασμό σας ή να αλλάξτε τον κωδικό σας.



\ No newline at end of file + ΣΦΑΛΜΑ: Cache Access Denied

ERROR

Cache Απαγορεύεται η Πρόσβαση.


The following error was encountered while trying to retrieve the URL: %U

Απαγορεύεται η Πρόσβαση στο Μεσολαβητή.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/el/error-details.txt squid-3.2.0.13/errors/el/error-details.txt --- squid-3.2.0.12/errors/el/error-details.txt 2011-09-16 23:42:34.000000000 +1200 +++ squid-3.2.0.13/errors/el/error-details.txt 2011-10-14 15:17:23.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_ΣΦΑΛΜΑ_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_ΣΦΑΛΜΑ_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_ΣΦΑΛΜΑ_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_ΣΦΑΛΜΑ_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/en/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/en/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/en/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:42:36.000000000 +1200 +++ squid-3.2.0.13/errors/en/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:17:33.000000000 +1300 @@ -1 +1 @@ - ERROR: Cache Access Denied

ERROR

Cache Access Denied.


The following error was encountered while trying to retrieve the URL: %U

Cache Access Denied.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself or change your default password.



\ No newline at end of file + ERROR: Cache Access Denied

ERROR

Cache Access Denied.


The following error was encountered while trying to retrieve the URL: %U

Cache Access Denied.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/es/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/es/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/es/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:42:55.000000000 +1200 +++ squid-3.2.0.13/errors/es/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:18:53.000000000 +1300 @@ -1 +1 @@ - ERROR: Acceso Denegado a la Caché

ERROR

Cache Acceso Denegado


Se encontró el siguiente error al intentar recuperar la dirección URL: %U

Acceso Denegado a la Caché

Lo lamento, tu no estás autorizado a solicitar %U de este caché hasta que te hayas autenticado.

Por favor contacte al administrador del caché si tiene dificultad para autenticarse o cambie su password.



\ No newline at end of file + ERROR: Acceso Denegado a la Caché

ERROR

Cache Acceso Denegado


Se encontró el siguiente error al intentar recuperar la dirección URL: %U

Acceso Denegado a la Caché

Lo lamento, tu no estás autorizado a solicitar %U de este caché hasta que te hayas autenticado.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/et/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/et/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/et/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:43:14.000000000 +1200 +++ squid-3.2.0.13/errors/et/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:20:55.000000000 +1300 @@ -1 +1 @@ - VIGA: Cache Access Denied

ERROR

Cache Juurdepääs keelatud.


The following error was encountered while trying to retrieve the URL: %U

Vahemälu serveri kasutamine keelatud.

abandust, teil pole õigust päringule %U kuni te pole läbinud autoriseerimist.

Palun kontakteeruge vahemälu serveri administraatoriga, kui teil on probleeme autoriseerimisega võivahetage oma parool.



\ No newline at end of file + VIGA: Cache Access Denied

ERROR

Cache Juurdepääs keelatud.


The following error was encountered while trying to retrieve the URL: %U

Vahemälu serveri kasutamine keelatud.

abandust, teil pole õigust päringule %U kuni te pole läbinud autoriseerimist.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/et/error-details.txt squid-3.2.0.13/errors/et/error-details.txt --- squid-3.2.0.12/errors/et/error-details.txt 2011-09-16 23:43:32.000000000 +1200 +++ squid-3.2.0.13/errors/et/error-details.txt 2011-10-14 15:22:55.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_VIGA_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_VIGA_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_VIGA_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_VIGA_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/fa/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/fa/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/fa/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:43:34.000000000 +1200 +++ squid-3.2.0.13/errors/fa/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:23:06.000000000 +1300 @@ -1 +1 @@ - خطا: Cache Access Denied

ERROR

Cache دسترسی رد شد.


The following error was encountered while trying to retrieve the URL: %U

دسترسی به نهانگاه رد شد.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

لطفا در صورت داشتن مشکلاتی در زمینه شناسایی خودتان با cache administrator تماس حاصل فرمایید یا از طریق تغییر رمز خود مشکل را حل نمایید.



\ No newline at end of file + خطا: Cache Access Denied

ERROR

Cache دسترسی رد شد.


The following error was encountered while trying to retrieve the URL: %U

دسترسی به نهانگاه رد شد.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/fa/error-details.txt squid-3.2.0.13/errors/fa/error-details.txt --- squid-3.2.0.12/errors/fa/error-details.txt 2011-09-16 23:43:52.000000000 +1200 +++ squid-3.2.0.13/errors/fa/error-details.txt 2011-10-14 15:24:44.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_خطا_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_خطا_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_خطا_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_خطا_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/fi/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/fi/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/fi/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:43:53.000000000 +1200 +++ squid-3.2.0.13/errors/fi/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:24:55.000000000 +1300 @@ -1 +1 @@ - VIRHE: Cache Access Denied

ERROR

Cache Pääsy evätty.


The following error was encountered while trying to retrieve the URL: %U

Pääsy välityspalvelimeen evätty.

Sinulla ei tällä hetkellä ole oikeutta pyytää osoitetta %U tästä välityspalvelimesta ennen kuin olet todentanut henkilöllisyytesi.

Jos sinulla on hankaluuksia hekilöllisyytesi todentamisessa, ota yhteyttä välityspalvelimen ylläpitoon tai vaihda oletussalasanasi.



\ No newline at end of file + VIRHE: Cache Access Denied

ERROR

Cache Pääsy evätty.


The following error was encountered while trying to retrieve the URL: %U

Pääsy välityspalvelimeen evätty.

Sinulla ei tällä hetkellä ole oikeutta pyytää osoitetta %U tästä välityspalvelimesta ennen kuin olet todentanut henkilöllisyytesi.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/fi/error-details.txt squid-3.2.0.13/errors/fi/error-details.txt --- squid-3.2.0.12/errors/fi/error-details.txt 2011-09-16 23:44:11.000000000 +1200 +++ squid-3.2.0.13/errors/fi/error-details.txt 2011-10-14 15:26:48.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_VIRHE_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_VIRHE_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_VIRHE_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_VIRHE_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/fr/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/fr/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/fr/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:44:13.000000000 +1200 +++ squid-3.2.0.13/errors/fr/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:27:04.000000000 +1300 @@ -1 +1 @@ - ERREUR: Cache Access Denied

ERROR

Cache Accès interdit.


L'erreur suivante s'est produite en essayant d'accéder à l'URL : %U

Accès au cache interdit.

Désolé, vous n'êtes pas autorisé à demander la requête %U de ce cache tant que vous ne vous serez pas identifié.

S'il vous plait, contacter l'administrateur du proxy si vous avez des difficultés pour vous authentifier ou pour changez votre mot de passe par défaut.



\ No newline at end of file + ERREUR: Cache Access Denied

ERROR

Cache Accès interdit.


L'erreur suivante s'est produite en essayant d'accéder à l'URL : %U

Accès au cache interdit.

Désolé, vous n'êtes pas autorisé à demander la requête %U de ce cache tant que vous ne vous serez pas identifié.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/fr/error-details.txt squid-3.2.0.13/errors/fr/error-details.txt --- squid-3.2.0.12/errors/fr/error-details.txt 2011-09-16 23:44:30.000000000 +1200 +++ squid-3.2.0.13/errors/fr/error-details.txt 2011-10-14 15:28:55.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_ERREUR_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_ERREUR_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_ERREUR_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_ERREUR_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/he/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/he/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/he/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:44:32.000000000 +1200 +++ squid-3.2.0.13/errors/he/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:29:07.000000000 +1300 @@ -1 +1 @@ - שגיאה: Cache Access Denied

ERROR

Cache הגישה נדחית


The following error was encountered while trying to retrieve the URL: %U

גישה ל-Cache נדחית

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself or change your default password.



\ No newline at end of file + שגיאה: Cache Access Denied

ERROR

Cache הגישה נדחית


The following error was encountered while trying to retrieve the URL: %U

גישה ל-Cache נדחית

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/he/error-details.txt squid-3.2.0.13/errors/he/error-details.txt --- squid-3.2.0.12/errors/he/error-details.txt 2011-09-16 23:44:49.000000000 +1200 +++ squid-3.2.0.13/errors/he/error-details.txt 2011-10-14 15:30:40.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_שגיאה_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_שגיאה_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_שגיאה_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_שגיאה_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/hu/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/hu/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/hu/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:44:51.000000000 +1200 +++ squid-3.2.0.13/errors/hu/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:30:50.000000000 +1300 @@ -1 +1 @@ - HIBA: Cache Access Denied

ERROR

Cache Hozzáférés megtagadva.


The following error was encountered while trying to retrieve the URL: %U

Cache hozzáférés megtagadva.

Sajnos az alábbi URL-t nem töltheti le cache szerverünktől %U amíg nem jelentkezik be rendszerünkbe.

Kérjük, forduljon a cache adminisztrátorhoz amennyiben nem sikerül bejelentkeznie vagy megváltoztatniaeredetileg beállított jelszavát.



\ No newline at end of file + HIBA: Cache Access Denied

ERROR

Cache Hozzáférés megtagadva.


The following error was encountered while trying to retrieve the URL: %U

Cache hozzáférés megtagadva.

Sajnos az alábbi URL-t nem töltheti le cache szerverünktől %U amíg nem jelentkezik be rendszerünkbe.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/hu/error-details.txt squid-3.2.0.13/errors/hu/error-details.txt --- squid-3.2.0.12/errors/hu/error-details.txt 2011-09-16 23:45:09.000000000 +1200 +++ squid-3.2.0.13/errors/hu/error-details.txt 2011-10-14 15:32:50.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_HIBA_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_HIBA_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_HIBA_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_HIBA_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/hy/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/hy/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/hy/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:45:11.000000000 +1200 +++ squid-3.2.0.13/errors/hy/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:33:01.000000000 +1300 @@ -1 +1 @@ - ՍԽԱԼ: Cache Access Denied

ERROR

Cache Մուտքն արգելված է.


URL-ի ստացման ընթացքում առաջացավ հետևյալ սխալը: %U

Մուտքը քեշին արգելված է.

Ներողություն,Դուք չեք կարող իրականացնել հետևյալ հարցումը %U մինչև աութենտիֆիկացիան չանցնեք.

Խնդիրներ առաջանալու դեպքում խնդրվում է դիմելքեշի կառավարիչին կամ փոխել Ձեր ընթացիկ գաղտնաբառը.



\ No newline at end of file + ՍԽԱԼ: Cache Access Denied

ERROR

Cache Մուտքն արգելված է.


URL-ի ստացման ընթացքում առաջացավ հետևյալ սխալը: %U

Մուտքը քեշին արգելված է.

Ներողություն,Դուք չեք կարող իրականացնել հետևյալ հարցումը %U մինչև աութենտիֆիկացիան չանցնեք.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/hy/error-details.txt squid-3.2.0.13/errors/hy/error-details.txt --- squid-3.2.0.12/errors/hy/error-details.txt 2011-09-16 23:45:28.000000000 +1200 +++ squid-3.2.0.13/errors/hy/error-details.txt 2011-10-14 15:34:50.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_ՍԽԱԼ_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_ՍԽԱԼ_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_ՍԽԱԼ_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_ՍԽԱԼ_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/id/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/id/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/id/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:45:30.000000000 +1200 +++ squid-3.2.0.13/errors/id/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:35:05.000000000 +1300 @@ -1 +1 @@ - ERROR: Cache Access Denied

ERROR

Cache Akses Ditolak


The following error was encountered while trying to retrieve the URL: %U

Akses Cache Ditolak

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself or change your default password.



\ No newline at end of file + ERROR: Cache Access Denied

ERROR

Cache Akses Ditolak


The following error was encountered while trying to retrieve the URL: %U

Akses Cache Ditolak

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/it/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/it/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/it/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:45:49.000000000 +1200 +++ squid-3.2.0.13/errors/it/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:37:18.000000000 +1300 @@ -1 +1 @@ - ERRORE: Cache Access Denied

ERROR

Cache Accesso negato.


Mentre si cercava di accedere alla URL %U si è presentato il seguente errore:

Accesso alla cache negato.

Per richiedere %U da questa cache è necessario prima identificarsi.

Si prega di contattare il gestore del vostro proxy se avete diffcoltà nell'identificarvi per l'accesso al servizio, o di cambiare la vostra password iniziale.



\ No newline at end of file + ERRORE: Cache Access Denied

ERROR

Cache Accesso negato.


Mentre si cercava di accedere alla URL %U si è presentato il seguente errore:

Accesso alla cache negato.

Per richiedere %U da questa cache è necessario prima identificarsi.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/it/error-details.txt squid-3.2.0.13/errors/it/error-details.txt --- squid-3.2.0.12/errors/it/error-details.txt 2011-09-16 23:46:07.000000000 +1200 +++ squid-3.2.0.13/errors/it/error-details.txt 2011-10-14 15:39:07.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_ERRORE_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_ERRORE_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_ERRORE_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_ERRORE_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/ja/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/ja/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/ja/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:46:09.000000000 +1200 +++ squid-3.2.0.13/errors/ja/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:39:18.000000000 +1300 @@ -1 +1 @@ - エラー: Cache Access Denied

ERROR

Cache アクセスを拒否されました。


The following error was encountered while trying to retrieve the URL: %U

キャッシュへのアクセスを拒否されました.

申し訳ありませんが、あなた自身の認証を済ませるまで、このキャッシュに %U をリクエストすることは現在許可されていません。

あなた自身の認証やデフォルトのパスワードの変更困難な場合は、キャッシュの管理者に連絡してください。



\ No newline at end of file + エラー: Cache Access Denied

ERROR

Cache アクセスを拒否されました。


The following error was encountered while trying to retrieve the URL: %U

キャッシュへのアクセスを拒否されました.

申し訳ありませんが、あなた自身の認証を済ませるまで、このキャッシュに %U をリクエストすることは現在許可されていません。

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/ja/error-details.txt squid-3.2.0.13/errors/ja/error-details.txt --- squid-3.2.0.12/errors/ja/error-details.txt 2011-09-16 23:46:26.000000000 +1200 +++ squid-3.2.0.13/errors/ja/error-details.txt 2011-10-14 15:41:12.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_エラー_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_エラー_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_エラー_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_エラー_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/ko/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/ko/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/ko/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:46:28.000000000 +1200 +++ squid-3.2.0.13/errors/ko/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:41:27.000000000 +1300 @@ -1 +1 @@ - 에러: Cache Access Denied

ERROR

Cache 서버 이용 요구가 거절되었습니다.


The following error was encountered while trying to retrieve the URL: %U

캐쉬 이용 요청이 거절되었습니다.

죄송합니다. 이 캐쉬를 통해 다음 서비스를 받기 위해서는 %U 인증절차를 거쳐야 합니다.

Please contact the cache administrator if you have difficulties authenticating yourself or change your default password.



\ No newline at end of file + 에러: Cache Access Denied

ERROR

Cache 서버 이용 요구가 거절되었습니다.


The following error was encountered while trying to retrieve the URL: %U

캐쉬 이용 요청이 거절되었습니다.

죄송합니다. 이 캐쉬를 통해 다음 서비스를 받기 위해서는 %U 인증절차를 거쳐야 합니다.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/ko/error-details.txt squid-3.2.0.13/errors/ko/error-details.txt --- squid-3.2.0.12/errors/ko/error-details.txt 2011-09-16 23:46:45.000000000 +1200 +++ squid-3.2.0.13/errors/ko/error-details.txt 2011-10-14 15:44:17.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_에러_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_에러_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_에러_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_에러_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/lt/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/lt/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/lt/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:46:47.000000000 +1200 +++ squid-3.2.0.13/errors/lt/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:44:37.000000000 +1300 @@ -1 +1 @@ - KLAIDA: Cache Access Denied

ERROR

Cache Priėjimas draudžiamas.


The following error was encountered while trying to retrieve the URL: %U

Priėjimas prie kešo uždraustas.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Prašome susisiekti su proxy administratoriumi, jei jums kils sunkumai prisistatant arba pakeisti savo slaptažodį.



\ No newline at end of file + KLAIDA: Cache Access Denied

ERROR

Cache Priėjimas draudžiamas.


The following error was encountered while trying to retrieve the URL: %U

Priėjimas prie kešo uždraustas.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/lt/error-details.txt squid-3.2.0.13/errors/lt/error-details.txt --- squid-3.2.0.12/errors/lt/error-details.txt 2011-09-16 23:47:05.000000000 +1200 +++ squid-3.2.0.13/errors/lt/error-details.txt 2011-10-14 15:47:50.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_KLAIDA_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_KLAIDA_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_KLAIDA_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_KLAIDA_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/lv/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/lv/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/lv/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:47:07.000000000 +1200 +++ squid-3.2.0.13/errors/lv/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:48:12.000000000 +1300 @@ -1 +1 @@ - Kļūda: Cache Access Denied

ERROR

Cache Pieeja liegta


Iestājusies sekojoša kļūda mēģinot atvērt adresi: %U

Kešatmiņas pieeja liegta

Atvainojiet, Jums nav atļauts pieprasīt %U no kešatmiņas pirms neesat autentificējies.

Lūdzu sazinieties kešatmiņas administratoru, ja Jums ir problēmas ar autentifikāciju vai nomainiet Jūsu paroli.



\ No newline at end of file + Kļūda: Cache Access Denied

ERROR

Cache Pieeja liegta


Iestājusies sekojoša kļūda mēģinot atvērt adresi: %U

Kešatmiņas pieeja liegta

Atvainojiet, Jums nav atļauts pieprasīt %U no kešatmiņas pirms neesat autentificējies.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/lv/error-details.txt squid-3.2.0.13/errors/lv/error-details.txt --- squid-3.2.0.12/errors/lv/error-details.txt 2011-09-16 23:47:24.000000000 +1200 +++ squid-3.2.0.13/errors/lv/error-details.txt 2011-10-14 15:50:53.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_Kļūda_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_Kļūda_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_Kļūda_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_Kļūda_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/Makefile.am squid-3.2.0.13/errors/Makefile.am --- squid-3.2.0.12/errors/Makefile.am 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/errors/Makefile.am 2011-10-14 14:42:56.000000000 +1300 @@ -50,7 +50,7 @@ page=`basename $$f`; \ $(PO2HTML) $(NOTIDY) --progress=none -i $(top_srcdir)/errors/$$lang.po -t $(top_srcdir)/errors/$$f >$(top_builddir)/errors/$$lang/$$page || exit 1; \ done; \ - $(PO2TEXT) -t $(top_srcdir)/errors/templates/error-details.txt -i $(top_srcdir)/errors/$$lang.po > $(top_builddir)/errors/$$lang/error-details.txt || exit 1; \ + cp $(top_srcdir)/errors/templates/error-details.txt $(top_builddir)/errors/$$lang/error-details.txt || exit 1; \ echo "done."; \ fi; \ touch $@ diff -u -r -N squid-3.2.0.12/errors/Makefile.in squid-3.2.0.13/errors/Makefile.in --- squid-3.2.0.12/errors/Makefile.in 2011-09-16 23:38:07.000000000 +1200 +++ squid-3.2.0.13/errors/Makefile.in 2011-10-14 14:46:41.000000000 +1300 @@ -582,7 +582,7 @@ page=`basename $$f`; \ $(PO2HTML) $(NOTIDY) --progress=none -i $(top_srcdir)/errors/$$lang.po -t $(top_srcdir)/errors/$$f >$(top_builddir)/errors/$$lang/$$page || exit 1; \ done; \ - $(PO2TEXT) -t $(top_srcdir)/errors/templates/error-details.txt -i $(top_srcdir)/errors/$$lang.po > $(top_builddir)/errors/$$lang/error-details.txt || exit 1; \ + cp $(top_srcdir)/errors/templates/error-details.txt $(top_builddir)/errors/$$lang/error-details.txt || exit 1; \ echo "done."; \ fi; \ touch $@ diff -u -r -N squid-3.2.0.12/errors/ms/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/ms/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/ms/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:47:26.000000000 +1200 +++ squid-3.2.0.13/errors/ms/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:51:16.000000000 +1300 @@ -1 +1 @@ - RALAT: Cache Access Denied

ERROR

Cache Akses Disekat


The following error was encountered while trying to retrieve the URL: %U

Akses ke Cache disekat

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself or change your default password.



\ No newline at end of file + RALAT: Cache Access Denied

ERROR

Cache Akses Disekat


The following error was encountered while trying to retrieve the URL: %U

Akses ke Cache disekat

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/ms/error-details.txt squid-3.2.0.13/errors/ms/error-details.txt --- squid-3.2.0.12/errors/ms/error-details.txt 2011-09-16 23:47:43.000000000 +1200 +++ squid-3.2.0.13/errors/ms/error-details.txt 2011-10-14 15:53:51.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_RALAT_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_RALAT_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_RALAT_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_RALAT_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/nl/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/nl/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/nl/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:47:45.000000000 +1200 +++ squid-3.2.0.13/errors/nl/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:54:09.000000000 +1300 @@ -1 +1 @@ - FOUT: Cache Access Denied

ERROR

Cache Toegang niet toegestaan.


De volgende fout is opgetreden tijdens het ophalen van URL: %U

Cache toegang niet toegestaan.

Sorry, het is u niet toegestaan om %U van deze cache op te vragen totdat u zich geidentificeerd hebt.

Neem contact op met de cache beheerder als u problemen heeft met authenticatie of verander hier uw standaard wachtwoord.



\ No newline at end of file + FOUT: Cache Access Denied

ERROR

Cache Toegang niet toegestaan.


De volgende fout is opgetreden tijdens het ophalen van URL: %U

Cache toegang niet toegestaan.

Sorry, het is u niet toegestaan om %U van deze cache op te vragen totdat u zich geidentificeerd hebt.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/nl/error-details.txt squid-3.2.0.13/errors/nl/error-details.txt --- squid-3.2.0.12/errors/nl/error-details.txt 2011-09-16 23:48:03.000000000 +1200 +++ squid-3.2.0.13/errors/nl/error-details.txt 2011-10-14 15:56:40.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_FOUT_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_FOUT_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_FOUT_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_FOUT_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/oc/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/oc/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/oc/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:48:05.000000000 +1200 +++ squid-3.2.0.13/errors/oc/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:57:04.000000000 +1300 @@ -1 +1 @@ - ERROR: Cache Access Denied

ERROR

Cache Accès interdich.


L'error seguenta s'es producha en ensajant d'accedir a l'URL : %U

Accès a l'amagatal interdich.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself or change your default password.



\ No newline at end of file + ERROR: Cache Access Denied

ERROR

Cache Accès interdich.


L'error seguenta s'es producha en ensajant d'accedir a l'URL : %U

Accès a l'amagatal interdich.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/pl/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/pl/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/pl/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:48:25.000000000 +1200 +++ squid-3.2.0.13/errors/pl/ERR_CACHE_ACCESS_DENIED 2011-10-14 15:59:50.000000000 +1300 @@ -1 +1 @@ - BŁĄD: Cache Access Denied

ERROR

Cache Dostęp zabroniony.


The following error was encountered while trying to retrieve the URL: %U

Dostęp do serwera cache zabroniony.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Skontaktuj się z administratorem serwera cache jeśli masz trudności z autoryzacją lub zmień haslo.



\ No newline at end of file + BŁĄD: Cache Access Denied

ERROR

Cache Dostęp zabroniony.


The following error was encountered while trying to retrieve the URL: %U

Dostęp do serwera cache zabroniony.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/pl/error-details.txt squid-3.2.0.13/errors/pl/error-details.txt --- squid-3.2.0.12/errors/pl/error-details.txt 2011-09-16 23:48:42.000000000 +1200 +++ squid-3.2.0.13/errors/pl/error-details.txt 2011-10-14 16:02:31.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_BŁĄD_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_BŁĄD_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_BŁĄD_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_BŁĄD_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/pt/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/pt/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/pt/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:49:03.000000000 +1200 +++ squid-3.2.0.13/errors/pt/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:05:23.000000000 +1300 @@ -1 +1 @@ - ERRO: Cache Access Denied

ERROR

Cache Proibido o Acesso.


The following error was encountered while trying to retrieve the URL: %U

Proibido o acesso ao Cache.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Por favor, contate o administrador do cache se você tiver dificuldades para se autenticar ou, altere sua senha.



\ No newline at end of file + ERRO: Cache Access Denied

ERROR

Cache Proibido o Acesso.


The following error was encountered while trying to retrieve the URL: %U

Proibido o acesso ao Cache.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/pt/error-details.txt squid-3.2.0.13/errors/pt/error-details.txt --- squid-3.2.0.12/errors/pt/error-details.txt 2011-09-16 23:49:21.000000000 +1200 +++ squid-3.2.0.13/errors/pt/error-details.txt 2011-10-14 16:08:12.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_ERRO_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_ERRO_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_ERRO_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_ERRO_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/pt-br/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/pt-br/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/pt-br/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:48:44.000000000 +1200 +++ squid-3.2.0.13/errors/pt-br/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:02:49.000000000 +1300 @@ -1 +1 @@ - ERRO: Cache Access Denied

ERROR

Cache Acesso Negado.


O seguinte erro foi encontrado ao tentar recuperar a URL: %U

Acesso negado ao cache.

Desculpe. Atualmente, você não está permitido a requisitar %U desse cache até que você tenha se autenticado.

Por favor, contate o administrador do cache se você está tendo dificuldades em se autenticar ou mude sua senha.



\ No newline at end of file + ERRO: Cache Access Denied

ERROR

Cache Acesso Negado.


O seguinte erro foi encontrado ao tentar recuperar a URL: %U

Acesso negado ao cache.

Desculpe. Atualmente, você não está permitido a requisitar %U desse cache até que você tenha se autenticado.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/pt-br/error-details.txt squid-3.2.0.13/errors/pt-br/error-details.txt --- squid-3.2.0.12/errors/pt-br/error-details.txt 2011-09-16 23:49:01.000000000 +1200 +++ squid-3.2.0.13/errors/pt-br/error-details.txt 2011-10-14 16:05:12.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_ERRO_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_ERRO_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_ERRO_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_ERRO_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/ro/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/ro/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/ro/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:49:23.000000000 +1200 +++ squid-3.2.0.13/errors/ro/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:08:29.000000000 +1300 @@ -1 +1 @@ - EROARE: Cache Access Denied

ERROR

Cache Acces interzis.


S-a recepţionat următoarea eroare când se încerca accesarea URL-ului: %U

Interzis accesul la cache.

Ne pare rău, nu aveţi momentan permisiunea să accesaţi %U din acest cache până când nu vă autentificaţi.

Vă rugăm contactaţi administratorul cache-ului dacă aveţi dificultăţi în a vă autentifica sau schimbaţi-vă parola implicită.



\ No newline at end of file + EROARE: Cache Access Denied

ERROR

Cache Acces interzis.


S-a recepţionat următoarea eroare când se încerca accesarea URL-ului: %U

Interzis accesul la cache.

Ne pare rău, nu aveţi momentan permisiunea să accesaţi %U din acest cache până când nu vă autentificaţi.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/ro/error-details.txt squid-3.2.0.13/errors/ro/error-details.txt --- squid-3.2.0.12/errors/ro/error-details.txt 2011-09-16 23:49:40.000000000 +1200 +++ squid-3.2.0.13/errors/ro/error-details.txt 2011-10-14 16:11:21.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_EROARE_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_EROARE_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_EROARE_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_EROARE_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/ru/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/ru/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/ru/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:49:42.000000000 +1200 +++ squid-3.2.0.13/errors/ru/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:11:44.000000000 +1300 @@ -1 +1 @@ - ОШИБКА: Cache Access Denied

ERROR

Cache Доступ запрещён.


При получении URL %U произошла следующая ошибка

Доступ к кэшу запрещён.

Извините, Вы не можете запросить %U из этого кэша до тех пор, пока не пройдёте аутентификацию.

Если у Вас возникли проблемы с аутентификацией, пожалуйста, свяжитесь с администратором кэша или смените Ваш пароль по умолчанию.



\ No newline at end of file + ОШИБКА: Cache Access Denied

ERROR

Cache Доступ запрещён.


При получении URL %U произошла следующая ошибка

Доступ к кэшу запрещён.

Извините, Вы не можете запросить %U из этого кэша до тех пор, пока не пройдёте аутентификацию.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/ru/error-details.txt squid-3.2.0.13/errors/ru/error-details.txt --- squid-3.2.0.12/errors/ru/error-details.txt 2011-09-16 23:49:59.000000000 +1200 +++ squid-3.2.0.13/errors/ru/error-details.txt 2011-10-14 16:13:50.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_ОШИБКА_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_ОШИБКА_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_ОШИБКА_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_ОШИБКА_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/sk/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/sk/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/sk/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:50:02.000000000 +1200 +++ squid-3.2.0.13/errors/sk/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:14:00.000000000 +1300 @@ -1 +1 @@ - CHYBA: Cache Access Denied

ERROR

Cache Prístup zamietnutý.


Pri pokuse o získanie URL sa vyskytla nasledovná chyba: %U

Prístup ku cache zamietnutý.

Ľutujeme, prístup k dokumentu %U z cache vám bude povolený až po tom ako sa autentifikujete.

Ak máte problém pri autentifikácii, kontaktujte prosím správcu cache alebo si zmeňte svoje predvolené heslo.



\ No newline at end of file + CHYBA: Cache Access Denied

ERROR

Cache Prístup zamietnutý.


Pri pokuse o získanie URL sa vyskytla nasledovná chyba: %U

Prístup ku cache zamietnutý.

Ľutujeme, prístup k dokumentu %U z cache vám bude povolený až po tom ako sa autentifikujete.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/sk/error-details.txt squid-3.2.0.13/errors/sk/error-details.txt --- squid-3.2.0.12/errors/sk/error-details.txt 2011-09-16 23:50:21.000000000 +1200 +++ squid-3.2.0.13/errors/sk/error-details.txt 2011-10-14 16:15:39.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_CHYBA_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_CHYBA_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_CHYBA_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_CHYBA_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/sl/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/sl/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/sl/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:50:23.000000000 +1200 +++ squid-3.2.0.13/errors/sl/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:15:54.000000000 +1300 @@ -1 +1 @@ - NAPAKA: Cache Access Denied

ERROR

Cache Dostop zavrnjen.


Prišlo je do napake med poskusom nalaganja naslova URL: %U

Dostop do predpomnilnika zavrnjen.

Žal trenutno ne morete zahtevati %U od tega predpomnilnika, dokler ne potrdite svoje istovetnosti.

Obrnite se na skrbnika predpomnilnika, če imate težave pri avtentikaciji, ali pa spremenite svoje privzeto geslo.



\ No newline at end of file + NAPAKA: Cache Access Denied

ERROR

Cache Dostop zavrnjen.


Prišlo je do napake med poskusom nalaganja naslova URL: %U

Dostop do predpomnilnika zavrnjen.

Žal trenutno ne morete zahtevati %U od tega predpomnilnika, dokler ne potrdite svoje istovetnosti.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/sl/error-details.txt squid-3.2.0.13/errors/sl/error-details.txt --- squid-3.2.0.12/errors/sl/error-details.txt 2011-09-16 23:50:41.000000000 +1200 +++ squid-3.2.0.13/errors/sl/error-details.txt 2011-10-14 16:17:39.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_NAPAKA_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_NAPAKA_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_NAPAKA_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_NAPAKA_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/sr-cyrl/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/sr-cyrl/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/sr-cyrl/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:50:43.000000000 +1200 +++ squid-3.2.0.13/errors/sr-cyrl/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:17:50.000000000 +1300 @@ -1 +1 @@ - ERROR: Cache Access Denied

ERROR

Cache Access Denied.


The following error was encountered while trying to retrieve the URL: %U

Cache Access Denied.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself or change your default password.



\ No newline at end of file + ERROR: Cache Access Denied

ERROR

Cache Access Denied.


The following error was encountered while trying to retrieve the URL: %U

Cache Access Denied.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/sr-latn/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/sr-latn/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/sr-latn/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:51:06.000000000 +1200 +++ squid-3.2.0.13/errors/sr-latn/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:19:16.000000000 +1300 @@ -1 +1 @@ - GREŠKA: Cache Access Denied

ERROR

Cache Pristup nije dozvoljen.


Greška učitavanja podataka sa adrese (URL): %U

Pristup proksi/keš serveru nije dozvoljen.

Na žalost nije vam dozvoljen da zahtev %U od ovog proksi servera ukoliko se ne autentifikujete.

Molimo kontaktirajte keš administratora ako imate problema sa autentifikacijom ili promenite vašu šifru.



\ No newline at end of file + GREŠKA: Cache Access Denied

ERROR

Cache Pristup nije dozvoljen.


Greška učitavanja podataka sa adrese (URL): %U

Pristup proksi/keš serveru nije dozvoljen.

Na žalost nije vam dozvoljen da zahtev %U od ovog proksi servera ukoliko se ne autentifikujete.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/sr-latn/error-details.txt squid-3.2.0.13/errors/sr-latn/error-details.txt --- squid-3.2.0.12/errors/sr-latn/error-details.txt 2011-09-16 23:51:25.000000000 +1200 +++ squid-3.2.0.13/errors/sr-latn/error-details.txt 2011-10-14 16:20:57.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_GREŠKA_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_GREŠKA_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_GREŠKA_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_GREŠKA_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/sv/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/sv/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/sv/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:51:27.000000000 +1200 +++ squid-3.2.0.13/errors/sv/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:21:22.000000000 +1300 @@ -1 +1 @@ - FEL: Cache Access Denied

ERROR

Cache Tillträde Nekas.


Följande fel påträffades vid hämtning av URL: %U

Tillträde till Cache Nekas.

Ledsen, Ni är förnärvarande ej berättigad att begära %U från denna cache tills det att Ni har autentifierat Er.

Vänligen kontakta cacheadministratorn om Ni har svårigh eter med att autentifiera Er själv, eller byt Ert lösenord.



\ No newline at end of file + FEL: Cache Access Denied

ERROR

Cache Tillträde Nekas.


Följande fel påträffades vid hämtning av URL: %U

Tillträde till Cache Nekas.

Ledsen, Ni är förnärvarande ej berättigad att begära %U från denna cache tills det att Ni har autentifierat Er.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/sv/error-details.txt squid-3.2.0.13/errors/sv/error-details.txt --- squid-3.2.0.12/errors/sv/error-details.txt 2011-09-16 23:51:45.000000000 +1200 +++ squid-3.2.0.13/errors/sv/error-details.txt 2011-10-14 16:23:51.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_FEL_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_FEL_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_FEL_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_FEL_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/templates/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/templates/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/templates/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/errors/templates/ERR_CACHE_ACCESS_DENIED 2011-10-14 14:42:56.000000000 +1300 @@ -25,7 +25,7 @@

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

-

Please contact the cache administrator if you have difficulties authenticating yourself or change your default password.

+

Please contact the cache administrator if you have difficulties authenticating yourself.


diff -u -r -N squid-3.2.0.12/errors/th/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/th/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/th/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:51:48.000000000 +1200 +++ squid-3.2.0.13/errors/th/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:24:08.000000000 +1300 @@ -1 +1 @@ - ERROR: การเรียกใช้ระบบแคชไม่ได้รับอนุญาต

ERROR

การเรียกใช้ระบบแคชไม่ได้รับอนุญาต


พบความผิดพลาดดังต่อไปนี้ระหว่างที่พยายามเรียกดู URL: %U

Cache Access Denied.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself or change your default password.



\ No newline at end of file + ERROR: การเรียกใช้ระบบแคชไม่ได้รับอนุญาต

ERROR

การเรียกใช้ระบบแคชไม่ได้รับอนุญาต


พบความผิดพลาดดังต่อไปนี้ระหว่างที่พยายามเรียกดู URL: %U

Cache Access Denied.

Sorry, you are not currently allowed to request %U from this cache until you have authenticated yourself.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/tr/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/tr/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/tr/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:52:07.000000000 +1200 +++ squid-3.2.0.13/errors/tr/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:27:20.000000000 +1300 @@ -1 +1 @@ - HATA: Cache Access Denied

ERROR

Cache Erişim Yasak.


URL adresine erişilmeye çalışıyorken hata meydana geldi: %U

Cache Sunucusunu Kullanamazsınız.

Özür dilerim, istediğiniz %U adresine bu Cache Sunucusunu kullanarak ulaşamazsınız.

Lütfen Cache Yöneticisi ile bağlantıya geçin, veya şifrenizi değiştirmek için buraya tıklayın.



\ No newline at end of file + HATA: Cache Access Denied

ERROR

Cache Erişim Yasak.


URL adresine erişilmeye çalışıyorken hata meydana geldi: %U

Cache Sunucusunu Kullanamazsınız.

Özür dilerim, istediğiniz %U adresine bu Cache Sunucusunu kullanarak ulaşamazsınız.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/tr/error-details.txt squid-3.2.0.13/errors/tr/error-details.txt --- squid-3.2.0.12/errors/tr/error-details.txt 2011-09-16 23:52:25.000000000 +1200 +++ squid-3.2.0.13/errors/tr/error-details.txt 2011-10-14 16:30:11.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_HATA_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_HATA_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_HATA_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_HATA_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/uk/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/uk/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/uk/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:52:27.000000000 +1200 +++ squid-3.2.0.13/errors/uk/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:30:30.000000000 +1300 @@ -1 +1 @@ - ПОМИЛКА: Cache Access Denied

ERROR

Cache Доступ заборонено


При отриманні URL: %U виникла помилка.

Доступ до кешу заборонено

Вибачте, Вам зараз не дозволено запитувати %U з цього кешу. Спочатку авторизуйтеся.

Будь-ласка, зв'яжіться з Адміністратором кешу, якщо у Вас виникли труднощі з авторизацією, або змініть Ваш пароль.



\ No newline at end of file + ПОМИЛКА: Cache Access Denied

ERROR

Cache Доступ заборонено


При отриманні URL: %U виникла помилка.

Доступ до кешу заборонено

Вибачте, Вам зараз не дозволено запитувати %U з цього кешу. Спочатку авторизуйтеся.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/uk/error-details.txt squid-3.2.0.13/errors/uk/error-details.txt --- squid-3.2.0.12/errors/uk/error-details.txt 2011-09-16 23:52:44.000000000 +1200 +++ squid-3.2.0.13/errors/uk/error-details.txt 2011-10-14 16:33:33.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_ПОМИЛКА_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_ПОМИЛКА_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_ПОМИЛКА_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_ПОМИЛКА_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/uz/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/uz/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/uz/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:52:46.000000000 +1200 +++ squid-3.2.0.13/errors/uz/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:33:49.000000000 +1300 @@ -1 +1 @@ - ХАТО: Cache Access Denied

ERROR

Cache Рухсат берилмаган.


The following error was encountered while trying to retrieve the URL: %U

Cache Access Denied.

Кечирасиз, сизнинг %U сўровингизга ушбу кеш томонидан тасдиқдан ўтмагунингизча рухсат берилмайди.

Агар сиз тасдиқдан ўтишда ёки андоза махфий сўзингизни ўзгартиришдақийналаётган бўлсангиз, марҳамат, кеш адмнистратори билан боғланинг.



\ No newline at end of file + ХАТО: Cache Access Denied

ERROR

Cache Рухсат берилмаган.


The following error was encountered while trying to retrieve the URL: %U

Cache Access Denied.

Кечирасиз, сизнинг %U сўровингизга ушбу кеш томонидан тасдиқдан ўтмагунингизча рухсат берилмайди.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/uz/error-details.txt squid-3.2.0.13/errors/uz/error-details.txt --- squid-3.2.0.12/errors/uz/error-details.txt 2011-09-16 23:53:03.000000000 +1200 +++ squid-3.2.0.13/errors/uz/error-details.txt 2011-10-14 16:36:42.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_ХАТО_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_ХАТО_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_ХАТО_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_ХАТО_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/vi/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/vi/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/vi/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:53:05.000000000 +1200 +++ squid-3.2.0.13/errors/vi/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:37:02.000000000 +1300 @@ -1 +1 @@ - LỖI: Cache Access Denied

ERROR

Cache Truy cập bị từ chối.


The following error was encountered while trying to retrieve the URL: %U

Truy cập đến vùng nhớ tạm bị từ chối.

Để yêu cầu %U từ vùng nhớ tạm này thì trước tiên bạn cần phải tự xác thực.

Hãy liên lạc với quản trị vùng nhớ tạm nếu bạn gặp khó khăn trong việc tự xác thực, hoặc bạn thay đổi mật khẩu mặc định của mình.



\ No newline at end of file + LỖI: Cache Access Denied

ERROR

Cache Truy cập bị từ chối.


The following error was encountered while trying to retrieve the URL: %U

Truy cập đến vùng nhớ tạm bị từ chối.

Để yêu cầu %U từ vùng nhớ tạm này thì trước tiên bạn cần phải tự xác thực.

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/vi/error-details.txt squid-3.2.0.13/errors/vi/error-details.txt --- squid-3.2.0.12/errors/vi/error-details.txt 2011-09-16 23:53:23.000000000 +1200 +++ squid-3.2.0.13/errors/vi/error-details.txt 2011-10-14 16:40:18.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_LỖI_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_LỖI_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_LỖI_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_LỖI_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/zh-cn/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/zh-cn/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/zh-cn/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:53:25.000000000 +1200 +++ squid-3.2.0.13/errors/zh-cn/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:40:37.000000000 +1300 @@ -1 +1 @@ - 错误: Cache Access Denied

ERROR

Cache 访问被拒绝。


当尝试取回该 URL 时遇到下面的错误:%U

缓存访问被拒绝。

抱歉,您不被允许通过本网络缓存服务器访问下列位置 %U 除非您通过了我们的身份验证。

如果您在身份验证上 发生困难,请与 管理者 联系。 或是更改您的密码。



\ No newline at end of file + 错误: Cache Access Denied

ERROR

Cache 访问被拒绝。


当尝试取回该 URL 时遇到下面的错误:%U

缓存访问被拒绝。

抱歉,您不被允许通过本网络缓存服务器访问下列位置 %U 除非您通过了我们的身份验证。

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/zh-cn/error-details.txt squid-3.2.0.13/errors/zh-cn/error-details.txt --- squid-3.2.0.12/errors/zh-cn/error-details.txt 2011-09-16 23:53:42.000000000 +1200 +++ squid-3.2.0.13/errors/zh-cn/error-details.txt 2011-10-14 16:43:58.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_错误_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_错误_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_错误_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_错误_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/errors/zh-tw/ERR_CACHE_ACCESS_DENIED squid-3.2.0.13/errors/zh-tw/ERR_CACHE_ACCESS_DENIED --- squid-3.2.0.12/errors/zh-tw/ERR_CACHE_ACCESS_DENIED 2011-09-16 23:53:44.000000000 +1200 +++ squid-3.2.0.13/errors/zh-tw/ERR_CACHE_ACCESS_DENIED 2011-10-14 16:44:22.000000000 +1300 @@ -1 +1 @@ - 錯誤: Cache Access Denied

ERROR

Cache 存取被拒絕


The following error was encountered while trying to retrieve the URL: %U

快取伺服器存取被拒絕

抱歉,您不被允許透過我們這個網路快取伺服器傳回下列位置 %U 除非您通過了我們的身份驗證。

如果您在身份驗證上發生困難,請與 管理者 聯繫。或是更改您的密碼。



\ No newline at end of file + 錯誤: Cache Access Denied

ERROR

Cache 存取被拒絕


The following error was encountered while trying to retrieve the URL: %U

快取伺服器存取被拒絕

抱歉,您不被允許透過我們這個網路快取伺服器傳回下列位置 %U 除非您通過了我們的身份驗證。

Please contact the cache administrator if you have difficulties authenticating yourself.



\ No newline at end of file diff -u -r -N squid-3.2.0.12/errors/zh-tw/error-details.txt squid-3.2.0.13/errors/zh-tw/error-details.txt --- squid-3.2.0.12/errors/zh-tw/error-details.txt 2011-09-16 23:54:01.000000000 +1200 +++ squid-3.2.0.13/errors/zh-tw/error-details.txt 2011-10-14 16:47:36.000000000 +1300 @@ -46,19 +46,19 @@ detail: "%ssl_error_descr: %ssl_subject" descr: "CRL has expired" -name: X509_V_ERR_錯誤_IN_CERT_NOT_BEFORE_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD detail: "SSL Certificate has invalid start date (the 'not before' field): %ssl_subject" descr: "Format error in certificate's notBefore field" -name: X509_V_ERR_錯誤_IN_CERT_NOT_AFTER_FIELD +name: X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD detail: "SSL Certificate has invalid expiration date (the 'not after' field): %ssl_subject" descr: "Format error in certificate's notAfter field" -name: X509_V_ERR_錯誤_IN_CRL_LAST_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's lastUpdate field" -name: X509_V_ERR_錯誤_IN_CRL_NEXT_UPDATE_FIELD +name: X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD detail: "%ssl_error_descr: %ssl_subject" descr: "Format error in CRL's nextUpdate field" diff -u -r -N squid-3.2.0.12/helpers/basic_auth/DB/basic_db_auth.8 squid-3.2.0.13/helpers/basic_auth/DB/basic_db_auth.8 --- squid-3.2.0.12/helpers/basic_auth/DB/basic_db_auth.8 2011-09-16 23:54:03.000000000 +1200 +++ squid-3.2.0.13/helpers/basic_auth/DB/basic_db_auth.8 2011-10-14 16:47:52.000000000 +1300 @@ -124,7 +124,7 @@ .\" ======================================================================== .\" .IX Title "BASIC_DB_AUTH 1" -.TH BASIC_DB_AUTH 1 "2011-09-16" "perl v5.10.1" "User Contributed Perl Documentation" +.TH BASIC_DB_AUTH 1 "2011-10-13" "perl v5.10.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff -u -r -N squid-3.2.0.12/helpers/external_acl/session/ext_session_acl.8 squid-3.2.0.13/helpers/external_acl/session/ext_session_acl.8 --- squid-3.2.0.12/helpers/external_acl/session/ext_session_acl.8 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/helpers/external_acl/session/ext_session_acl.8 2011-10-14 14:42:56.000000000 +1300 @@ -1,11 +1,11 @@ -.if !'po4a'hide' .TH ext_session_acl 8 "19 March 2006" +.if !'po4a'hide' .TH ext_session_acl 8 "19 September 2011" . .SH NAME .if !'po4a'hide' .B ext_session_acl .if !'po4a'hide' \- Squid session tracking external acl helper. .PP -Version 1.0 +Version 1.1 . .SH SYNOPSIS .if !'po4a'hide' .B ext_session_acl @@ -18,23 +18,43 @@ .SH DESCRIPTION .B ext_session_acl maintains a concept of sessions by monitoring requests -and timing out sessions if no requests have been seen for the idle timeout -timer. -.PP -Intended use is for displaying "terms of use" pages, ad popups etc. +and timing out sessions. The timeout is based either on idle use ( +.B \-t +) or a fixed period of time ( +.B \-T +). The former is suitable for displaying terms and conditions to a user; the +latter is suitable for the display of advertisments or other notices (both as a +splash page \- see config examples in the wiki online). The session helper can also be used +to force users to re\-authenticate if the +.B %LOGIN +and +.B \-a +are both used. . .SH OPTIONS .if !'po4a'hide' .TP 12 .if !'po4a'hide' .B "\-t timeout" -.B Timeout -for any session. If not specified the default is 3600 seconds. +Idle timeout for any session. The default if not specified (set to 3600 seconds). +. +.if !'po4a'hide' .TP +.if !'po4a'hide' .B "\-T timeout" +Fixed timeout for any session. This will end the session after the timeout regardless +of a user's activity. If used with +.B active +mode, this will terminate the user's session after +.B timeout +, after which another +.B LOGIN +will be required. +.B LOGOUT +will reset the session and timeout. . .if !'po4a'hide' .TP .if !'po4a'hide' .B "\-b path" .B Path to persistent database. If not specified the session details will be kept in memory only and all sessions will reset each time -Squid restarts it's helpers (Squid restart or rotation of logs). +Squid restarts its helpers (Squid restart or rotation of logs). . .if !'po4a'hide' .TP .if !'po4a'hide' .B \-a @@ -42,13 +62,17 @@ acl with the argument .B LOGIN , or terminated by the argument -.B LOGOUT -.PP +.B LOGOUT . Without this flag the helper automatically starts the session after the first request. -. .SH CONFIGURATION .PP +The +.B ext_session_acl +helper is a concurrent helper; therefore, the concurrency= option +.B must +be specified in the configuration. +.PP Configuration example using the default automatic mode .if !'po4a'hide' .RS .if !'po4a'hide' .B external_acl_type session ttl=300 negative_ttl=0 children=1 concurrency=200 %LOGIN /usr/local/squid/libexec/ext_session_acl diff -u -r -N squid-3.2.0.12/helpers/external_acl/session/ext_session_acl.cc squid-3.2.0.13/helpers/external_acl/session/ext_session_acl.cc --- squid-3.2.0.12/helpers/external_acl/session/ext_session_acl.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/helpers/external_acl/session/ext_session_acl.cc 2011-10-14 14:42:56.000000000 +1300 @@ -52,6 +52,7 @@ #endif static int session_ttl = 3600; +static int fixed_timeout = 0; char *db_path = NULL; const char *program_name; @@ -101,6 +102,7 @@ data.data = &now; data.size = sizeof(now); db->put(db, &key, &data, 0); + db->sync(db, 0); } static void session_logout(const char *details, size_t len) @@ -113,8 +115,9 @@ static void usage(void) { - fprintf(stderr, "Usage: %s [-t session_timeout] [-b dbpath] [-a]\n", program_name); - fprintf(stderr, " -t sessiontimeout Idle timeout after which sessions will be forgotten\n"); + fprintf(stderr, "Usage: %s [-t|-T session_timeout] [-b dbpath] [-a]\n", program_name); + fprintf(stderr, " -t sessiontimeout Idle timeout after which sessions will be forgotten (user activity will reset)\n"); + fprintf(stderr, " -T sessiontimeout Fixed timeout after which sessions will be forgotten (regardless of user activity)\n"); fprintf(stderr, " -b dbpath Path where persistent session database will be kept\n"); fprintf(stderr, " -a Active mode requiring LOGIN argument to start a session\n"); } @@ -126,8 +129,10 @@ program_name = argv[0]; - while ((opt = getopt(argc, argv, "t:b:a?")) != -1) { + while ((opt = getopt(argc, argv, "t:T:b:a?")) != -1) { switch (opt) { + case 'T': + fixed_timeout = 1; case 't': session_ttl = strtol(optarg, NULL, 0); break; @@ -150,8 +155,13 @@ while (fgets(request, HELPER_INPUT_BUFFER, stdin)) { int action = 0; - const char *user_key = strtok(request, " \n"); + const char *channel_id = strtok(request, " "); const char *detail = strtok(NULL, "\n"); + if (detail == NULL) { + // Only 1 paramater supplied. We are expecting at least 2 (including the channel ID) + fprintf(stderr, "FATAL: %s is concurrent and requires the concurrency option to be specified.\n", program_name); + exit(1); + } const char *lastdetail = strrchr(detail, ' '); size_t detail_len = strlen(detail); if (lastdetail) { @@ -165,18 +175,20 @@ } if (action == -1) { session_logout(detail, detail_len); - printf("%s OK message=\"Bye\"\n", user_key); + printf("%s OK message=\"Bye\"\n", channel_id); } else if (action == 1) { session_login(detail, detail_len); - printf("%s OK message=\"Welcome\"\n", user_key); + printf("%s OK message=\"Welcome\"\n", channel_id); } else if (session_active(detail, detail_len)) { - session_login(detail, detail_len); - printf("%s OK\n", user_key); + if (fixed_timeout == 0) { + session_login(detail, detail_len); + } + printf("%s OK\n", channel_id); } else if (default_action == 1) { session_login(detail, detail_len); - printf("%s ERR message=\"Welcome\"\n", user_key); + printf("%s ERR message=\"Welcome\"\n", channel_id); } else { - printf("%s ERR message=\"No session available\"\n", user_key); + printf("%s ERR message=\"No session available\"\n", channel_id); } } shutdown_db(); diff -u -r -N squid-3.2.0.12/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8 squid-3.2.0.13/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8 --- squid-3.2.0.12/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8 2011-09-16 23:54:05.000000000 +1200 +++ squid-3.2.0.13/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8 2011-10-14 16:48:15.000000000 +1300 @@ -124,7 +124,7 @@ .\" ======================================================================== .\" .IX Title "EXT_WBINFO_GROUP_ACL.PL.IN 1" -.TH EXT_WBINFO_GROUP_ACL.PL.IN 1 "2011-09-16" "perl v5.10.1" "User Contributed Perl Documentation" +.TH EXT_WBINFO_GROUP_ACL.PL.IN 1 "2011-10-13" "perl v5.10.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l diff -u -r -N squid-3.2.0.12/include/autoconf.h.in squid-3.2.0.13/include/autoconf.h.in --- squid-3.2.0.12/include/autoconf.h.in 2011-09-16 23:38:04.000000000 +1200 +++ squid-3.2.0.13/include/autoconf.h.in 2011-10-14 14:46:18.000000000 +1300 @@ -79,6 +79,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_ASSERT_H +/* Define to 1 if you have __sync_add_and_fetch() and such */ +#undef HAVE_ATOMIC_OPS + /* Basic auth module is built */ #undef HAVE_AUTH_MODULE_BASIC @@ -235,6 +238,9 @@ /* "Define to 1 if diskd filesystem module is build" */ #undef HAVE_FS_DISKD +/* "Define to 1 if rock filesystem module is build" */ +#undef HAVE_FS_ROCK + /* "Define to 1 if ufs filesystem module is build" */ #undef HAVE_FS_UFS @@ -773,6 +779,9 @@ /* Define if you have the shl_load function. */ #undef HAVE_SHL_LOAD +/* Support shared memory features */ +#undef HAVE_SHM + /* Define to 1 if you have the `sigaction' function. */ #undef HAVE_SIGACTION @@ -933,6 +942,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MD5_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MOUNT_H @@ -1221,6 +1233,9 @@ /* Whether pthreads support is needed. Automatic */ #undef USE_DISKIO_DISKTHREADS +/* Enable DiskIO IpcIo module. */ +#undef USE_DISKIO_IPCIO + /* Use dnsserver processes instead of the internal DNS protocol support */ #undef USE_DNSSERVERS diff -u -r -N squid-3.2.0.12/include/version.h squid-3.2.0.13/include/version.h --- squid-3.2.0.12/include/version.h 2011-09-16 23:38:35.000000000 +1200 +++ squid-3.2.0.13/include/version.h 2011-10-14 14:49:52.000000000 +1300 @@ -9,7 +9,7 @@ */ #ifndef SQUID_RELEASE_TIME -#define SQUID_RELEASE_TIME 1316173049 +#define SQUID_RELEASE_TIME 1318556567 #endif #ifndef APP_SHORTNAME diff -u -r -N squid-3.2.0.12/lib/rfc1035.c squid-3.2.0.13/lib/rfc1035.c --- squid-3.2.0.12/lib/rfc1035.c 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/lib/rfc1035.c 2011-10-14 14:42:56.000000000 +1300 @@ -519,11 +519,11 @@ void rfc1035RRDestroy(rfc1035_rr ** rr, int n) { - if (*rr == NULL || n < 1) { + if (*rr == NULL) { return; } - while (n--) { + while (n-- > 0) { if ((*rr)[n].rdata) xfree((*rr)[n].rdata); } diff -u -r -N squid-3.2.0.12/RELEASENOTES.html squid-3.2.0.13/RELEASENOTES.html --- squid-3.2.0.12/RELEASENOTES.html 2011-09-16 23:54:10.000000000 +1200 +++ squid-3.2.0.13/RELEASENOTES.html 2011-10-14 16:49:16.000000000 +1300 @@ -2,10 +2,10 @@ - Squid 3.2.0.12 release notes + Squid 3.2.0.13 release notes -

Squid 3.2.0.12 release notes

+

Squid 3.2.0.13 release notes

Squid Developers


@@ -73,7 +73,7 @@

1. Notice

-

The Squid Team are pleased to announce the release of Squid-3.2.0.12 for testing.

+

The Squid Team are pleased to announce the release of Squid-3.2.0.13 for testing.

This new release is available for download from http://www.squid-cache.org/Versions/v3/3.2/ or the mirrors.

@@ -176,13 +176,11 @@

Workers can share logs.

-

Workers cannot share caches, for now. Cache_dir options must be adjusted to -point each disk-caching worker to its own disk area. ICP and HTCP responses -are based on the responding worker cache state. Overall, SMP Squid behaves -as a Squid farm behind a load-balancer with no cache affinity awareness. -This is perfect for non-caching Squids but inappropriate for Squids that -must coordinate caching activities (in-between environments are in a gray -area requiring case-by-case analysis).

+

Workers can share caches. Memory cache is automatically shared when multiple +workers are used. Cache_dir are shared when configured with the rock +storage type. Cache_dir of other types must be adjusted to point each +disk-caching worker to its own disk area. ICP and HTCP responses are based +on the responding worker cache state.

Cache manager statistics are reported from a worker point of view, for now. Though some reports are combined. SNMP statistics are combined across all diff -u -r -N squid-3.2.0.12/src/adaptation/ecap/XactionRep.cc squid-3.2.0.13/src/adaptation/ecap/XactionRep.cc --- squid-3.2.0.12/src/adaptation/ecap/XactionRep.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/adaptation/ecap/XactionRep.cc 2011-10-14 14:42:56.000000000 +1300 @@ -133,6 +133,7 @@ const libecap::Area Adaptation::Ecap::XactionRep::usernameValue() const { +#if USE_AUTH const HttpRequest *request = dynamic_cast(theCauseRep ? theCauseRep->raw().header : theVirginRep.raw().header); Must(request); @@ -140,6 +141,7 @@ if (char const *name = request->auth_user_request->username()) return libecap::Area::FromTempBuffer(name, strlen(name)); } +#endif return libecap::Area(); } diff -u -r -N squid-3.2.0.12/src/adaptation/ServiceConfig.cc squid-3.2.0.13/src/adaptation/ServiceConfig.cc --- squid-3.2.0.12/src/adaptation/ServiceConfig.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/adaptation/ServiceConfig.cc 2011-10-14 14:42:56.000000000 +1300 @@ -6,6 +6,7 @@ #include "ConfigParser.h" #include "adaptation/ServiceConfig.h" #include "ip/tools.h" +#include Adaptation::ServiceConfig::ServiceConfig(): port(-1), method(methodNone), point(pointNone), @@ -69,29 +70,41 @@ bypass = routing = false; // handle optional service name=value parameters - const char *lastOption = NULL; bool grokkedUri = false; bool onOverloadSet = false; + std::set options; + while (char *option = strtok(NULL, w_space)) { + const char *name = option; + const char *value = ""; if (strcmp(option, "0") == 0) { // backward compatibility - bypass = false; - continue; - } - if (strcmp(option, "1") == 0) { // backward compatibility - bypass = true; - continue; + name = "bypass"; + value = "off"; + debugs(3, opt_parse_cfg_only?0:1, "UPGRADE: Please use 'bypass=off' option to disable service bypass"); + } else if (strcmp(option, "1") == 0) { // backward compatibility + name = "bypass"; + value = "on"; + debugs(3, opt_parse_cfg_only?0:1, "UPGRADE: Please use 'bypass=on' option to enable service bypass"); + } else { + char *eq = strstr(option, "="); + const char *sffx = strstr(option, "://"); + if (!eq || (sffx && sffx < eq)) { //no "=" or has the form "icap://host?arg=val" + name = "uri"; + value = option; + } else { // a normal name=value option + *eq = '\0'; // terminate option name + value = eq + 1; // skip '=' + } } - const char *name = option; - char *value = strstr(option, "="); - if (!value) { - lastOption = option; - break; + // Check if option is set twice + if (options.find(name) != options.end()) { + debugs(3, DBG_CRITICAL, cfg_filename << ':' << config_lineno << ": " << + "Duplicate option \"" << name << "\" in adaptation service definition"); + return false; } - *value = '\0'; // terminate option name - ++value; // skip '=' + options.insert(name); - // TODO: warn if option is set twice? bool grokked = false; if (strcmp(name, "bypass") == 0) { grokked = grokBool(bypass, name, value); @@ -119,14 +132,10 @@ if (!onOverloadSet) onOverload = bypass ? srvBypass : srvWait; - // what is left must be the service URI - if (!grokkedUri && !grokUri(lastOption)) - return false; - - // there should be nothing else left - if (const char *tail = strtok(NULL, w_space)) { - debugs(3, 0, cfg_filename << ':' << config_lineno << ": " << - "garbage after adaptation service URI: " << tail); + // is the service URI set? + if (!grokkedUri) { + debugs(3, DBG_CRITICAL, cfg_filename << ':' << config_lineno << ": " << + "No \"uri\" option in adaptation service definition"); return false; } diff -u -r -N squid-3.2.0.12/src/auth/basic/auth_basic.cc squid-3.2.0.13/src/auth/basic/auth_basic.cc --- squid-3.2.0.12/src/auth/basic/auth_basic.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/auth/basic/auth_basic.cc 2011-10-14 14:42:56.000000000 +1300 @@ -354,7 +354,7 @@ basicauthenticators->cmdline = authenticateProgram; - basicauthenticators->childs = authenticateChildren; + basicauthenticators->childs.updateLimits(authenticateChildren); basicauthenticators->ipc_type = IPC_STREAM; diff -u -r -N squid-3.2.0.12/src/auth/digest/auth_digest.cc squid-3.2.0.13/src/auth/digest/auth_digest.cc --- squid-3.2.0.12/src/auth/digest/auth_digest.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/auth/digest/auth_digest.cc 2011-10-14 14:42:56.000000000 +1300 @@ -46,6 +46,7 @@ #include "auth/Gadgets.h" #include "auth/State.h" #include "base64.h" +#include "base/StringArea.h" #include "event.h" #include "mgr/Registration.h" #include "Store.h" @@ -583,7 +584,7 @@ digestauthenticators->cmdline = authenticateProgram; - digestauthenticators->childs = authenticateChildren; + digestauthenticators->childs.updateLimits(authenticateChildren); digestauthenticators->ipc_type = IPC_STREAM; @@ -814,10 +815,28 @@ vlen = 0; } - /* parse value. auth-param = token "=" ( token | quoted-string ) */ + StringArea keyName(item, nlen-1); String value; + if (vlen > 0) { - if (*p == '"') { + // see RFC 2617 section 3.2.1 and 3.2.2 for details on the BNF + + if (keyName == StringArea("domain",6) || keyName == StringArea("uri",3)) { + // domain is Special. Not a quoted-string, must not be de-quoted. But is wrapped in '"' + // BUG 3077: uri= can also be sent to us in a mangled (invalid!) form like domain + if (*p == '"' && *(p + vlen -1) == '"') { + value.limitInit(p+1, vlen-2); + } + } else if (keyName == StringArea("qop",3)) { + // qop is more special. + // On request this must not be quoted-string de-quoted. But is several values wrapped in '"' + // On response this is a single un-quoted token. + if (*p == '"' && *(p + vlen -1) == '"') { + value.limitInit(p+1, vlen-2); + } else { + value.limitInit(p, vlen); + } + } else if (*p == '"') { if (!httpHeaderParseQuotedString(p, vlen, &value)) { debugs(29, 9, "authDigestDecodeAuth: Failed to parse attribute '" << item << "' in '" << temp << "'"); continue; diff -u -r -N squid-3.2.0.12/src/auth/negotiate/auth_negotiate.cc squid-3.2.0.13/src/auth/negotiate/auth_negotiate.cc --- squid-3.2.0.12/src/auth/negotiate/auth_negotiate.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/auth/negotiate/auth_negotiate.cc 2011-10-14 14:42:56.000000000 +1300 @@ -176,7 +176,7 @@ negotiateauthenticators->cmdline = authenticateProgram; - negotiateauthenticators->childs = authenticateChildren; + negotiateauthenticators->childs.updateLimits(authenticateChildren); negotiateauthenticators->ipc_type = IPC_STREAM; diff -u -r -N squid-3.2.0.12/src/auth/ntlm/auth_ntlm.cc squid-3.2.0.13/src/auth/ntlm/auth_ntlm.cc --- squid-3.2.0.12/src/auth/ntlm/auth_ntlm.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/auth/ntlm/auth_ntlm.cc 2011-10-14 14:42:56.000000000 +1300 @@ -163,7 +163,7 @@ ntlmauthenticators->cmdline = authenticateProgram; - ntlmauthenticators->childs = authenticateChildren; + ntlmauthenticators->childs.updateLimits(authenticateChildren); ntlmauthenticators->ipc_type = IPC_STREAM; diff -u -r -N squid-3.2.0.12/src/base/Makefile.am squid-3.2.0.13/src/base/Makefile.am --- squid-3.2.0.12/src/base/Makefile.am 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/base/Makefile.am 2011-10-14 14:42:56.000000000 +1300 @@ -19,4 +19,5 @@ RunnersRegistry.h \ Subscription.h \ TextException.cc \ - TextException.h + TextException.h \ + StringArea.h diff -u -r -N squid-3.2.0.12/src/base/Makefile.in squid-3.2.0.13/src/base/Makefile.in --- squid-3.2.0.12/src/base/Makefile.in 2011-09-16 23:38:18.000000000 +1200 +++ squid-3.2.0.13/src/base/Makefile.in 2011-10-14 14:48:00.000000000 +1300 @@ -324,7 +324,8 @@ RunnersRegistry.h \ Subscription.h \ TextException.cc \ - TextException.h + TextException.h \ + StringArea.h all: all-am diff -u -r -N squid-3.2.0.12/src/base/RunnersRegistry.cc squid-3.2.0.13/src/base/RunnersRegistry.cc --- squid-3.2.0.12/src/base/RunnersRegistry.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/base/RunnersRegistry.cc 2011-10-14 14:42:56.000000000 +1300 @@ -44,7 +44,6 @@ DeactivateRegistered(const RunnerRegistry ®istryId) { Runners &runners = GetRunners(registryId); - typedef Runners::iterator RRI; while (!runners.empty()) { delete runners.back(); runners.pop_back(); diff -u -r -N squid-3.2.0.12/src/base/StringArea.h squid-3.2.0.13/src/base/StringArea.h --- squid-3.2.0.12/src/base/StringArea.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/base/StringArea.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,66 @@ +/* + * StringArea.h + * + * + * 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. + */ + +#ifndef SQUID_STRINGAREA_H +#define SQUID_STRINGAREA_H + +#if HAVE_CSTRING +#include +#endif + +/** A char* plus length combination. Useful for temporary storing + * and quickly looking up strings. + * + * The pointed-to string may not be null-terminated. + * The pointed-to string is not copied. + * + * Not meant for stand-alone storage. Validity of the + * pointed-to string is responsibility of the caller. + */ +class StringArea +{ +public: + /// build a StringArea by explicitly assigning pointed-to area and and length + StringArea(const char * ptr, size_t len): theStart(ptr), theLen(len) {} + bool operator==(const StringArea &s) const { return theLen==s.theLen && memcmp(theStart,s.theStart,theLen)==0; } + bool operator!=(const StringArea &s) const { return !operator==(s); } + bool operator< ( const StringArea &s) const { + return (theLen < s.theLen || (theLen == s.theLen && memcmp(theStart,s.theStart,theLen) < 0)) ; + } + +private: + /// pointed to the externally-managed memory area + const char *theStart; + /// length of the string + size_t theLen; +}; + +#endif /* SQUID_STRINGAREA_H */ diff -u -r -N squid-3.2.0.12/src/cache_cf.cc squid-3.2.0.13/src/cache_cf.cc --- squid-3.2.0.12/src/cache_cf.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/cache_cf.cc 2011-10-14 14:42:56.000000000 +1300 @@ -56,6 +56,7 @@ #endif #include "ConfigParser.h" #include "CpuAffinityMap.h" +#include "DiskIO/DiskIOModule.h" #include "eui/Config.h" #if USE_SQUID_ESI #include "esi/Parser.h" @@ -599,6 +600,12 @@ /* Memory-only cache probably in effect. */ /* turn off the cache rebuild delays... */ StoreController::store_dirs_rebuilding = 0; + } else if (InDaemonMode()) { // no diskers in non-daemon mode + for (int i = 0; i < Config.cacheSwap.n_configured; ++i) { + const RefCount sd = Config.cacheSwap.swapDirs[i]; + if (sd->needsDiskStrand()) + sd->disker = Config.workers + (++Config.cacheSwap.n_strands); + } } if (Debug::rotateNumber < 0) { @@ -614,7 +621,7 @@ if (0 == Store::Root().maxSize()) /* people might want a zero-sized cache on purpose */ (void) 0; - else if (Store::Root().maxSize() < (Config.memMaxSize >> 10)) + else if (Store::Root().maxSize() < Config.memMaxSize) /* This is bogus. folk with NULL caches will want this */ debugs(3, 0, "WARNING cache_mem is larger than total disk cache space!"); @@ -1921,18 +1928,6 @@ static void parse_cachedir(SquidConfig::_cacheSwap * swap) { - // The workers option must preceed cache_dir for the IamWorkerProcess check - // below to work. TODO: Redo IamWorkerProcess to work w/o Config and remove - if (KidIdentifier > 1 && Config.workers == 1) { - debugs(3, DBG_CRITICAL, - "FATAL: cache_dir found before the workers option. Reorder."); - self_destruct(); - } - - // Among all processes, only workers may need and can handle cache_dir. - if (!IamWorkerProcess()) - return; - char *type_str; char *path_str; RefCount sd; @@ -1965,13 +1960,13 @@ sd = dynamic_cast(swap->swapDirs[i].getRaw()); - if (sd->type() != StoreFileSystem::FileSystems().items[fs]->type()) { + if (strcmp(sd->type(), StoreFileSystem::FileSystems().items[fs]->type()) != 0) { debugs(3, 0, "ERROR: Can't change type of existing cache_dir " << sd->type() << " " << sd->path << " to " << type_str << ". Restart required"); return; } - sd->reconfigure (i, path_str); + sd->reconfigure(); update_maxobjsize(); @@ -3358,6 +3353,40 @@ storeAppendPrintf(entry, "\n"); } +void +YesNoNone::configure(bool beSet) +{ + option = beSet ? +1 : -1; +} + +YesNoNone::operator void*() const +{ + assert(option != 0); // must call configure() first + return option > 0 ? (void*)this : NULL; +} + + +inline void +free_YesNoNone(YesNoNone *) +{ + // do nothing: no explicit cleanup is required +} + +static void +parse_YesNoNone(YesNoNone *option) +{ + int value = 0; + parse_onoff(&value); + option->configure(value > 0); +} + +static void +dump_YesNoNone(StoreEntry * entry, const char *name, YesNoNone &option) +{ + if (option.configured()) + dump_onoff(entry, name, option ? 1 : 0); +} + static void free_memcachemode(SquidConfig * config) { diff -u -r -N squid-3.2.0.12/src/cf.data.depend squid-3.2.0.13/src/cf.data.depend --- squid-3.2.0.12/src/cf.data.depend 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/cf.data.depend 2011-10-14 14:42:56.000000000 +1300 @@ -45,6 +45,7 @@ kb_int64_t kb_size_t logformat +YesNoNone memcachemode obsolete onoff diff -u -r -N squid-3.2.0.12/src/cf.data.pre squid-3.2.0.13/src/cf.data.pre --- squid-3.2.0.12/src/cf.data.pre 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/cf.data.pre 2011-10-14 14:42:56.000000000 +1300 @@ -1775,6 +1775,34 @@ DOC_END +NAME: host_verify_strict +TYPE: onoff +DEFAULT: off +LOC: Config.onoff.hostStrictVerify +DOC_START + Regardless of this option setting, when dealing with intercepted + traffic, Squid always verifies that the destination IP address matches + the Host header domain or IP (called 'authority form URL'). Squid + responds with an HTTP 409 (Conflict) error page and logs a security + warning if there is no match. + + When set to ON, Squid verifies that the destination IP address matches + the Host header for forward-proxy and reverse-proxy traffic as well. For + those traffic types, Squid also enables the following checks, comparing + the corresponding Host header and Request-URI components: + + * The host names (domain or IP) must be identical, + but valueless or missing Host header disables all checks. + For the two host names to match, both must be either IP or FQDN. + + * Port numbers must be identical, + but if a port is missing, the scheme-default port is assumed. + + This enforcement is performed to satisfy a MUST-level requirement in + RFC 2616 section 14.23: "The Host field value MUST represent the naming + authority of the origin server or gateway given by the original URL". +DOC_END + NAME: client_dst_passthru TYPE: onoff DEFAULT: on @@ -2558,6 +2586,11 @@ decreases, blocks will be freed until the high-water mark is reached. Thereafter, blocks will be used to store hot objects. + + If shared memory caching is enabled, Squid does not use the shared + cache space for in-transit objects, but they still consume as much + local memory as they need. For more details about the shared memory + cache, see memory_cache_shared. DOC_END NAME: maximum_object_size_in_memory @@ -2572,6 +2605,34 @@ enough to keep larger objects from hoarding cache_mem. DOC_END +NAME: memory_cache_shared +COMMENT: on|off +TYPE: YesNoNone +LOC: Config.memShared +DEFAULT: none +DEFAULT_DOC: "on" where supported if doing memory caching with multiple SMP workers. +DOC_START + Controls whether the memory cache is shared among SMP workers. + + The shared memory cache is meant to occupy cache_mem bytes and replace + the non-shared memory cache, although some entities may still be + cached locally by workers for now (e.g., internal and in-transit + objects may be served from a local memory cache even if shared memory + caching is enabled). + + By default, the memory cache is shared if and only if all of the + following conditions are satisfied: Squid runs in SMP mode with + multiple workers, cache_mem is positive, and Squid environment + supports required IPC primitives (e.g., POSIX shared memory segments + and GCC-style atomic operations). + + To avoid blocking locks, shared memory uses opportunistic algorithms + that do not guarantee that every cachable entity that could have been + shared among SMP workers will actually be shared. + + Currently, entities exceeding 32KB in size cannot be shared. +DOC_END + NAME: memory_cache_mode TYPE: memcachemode LOC: Config @@ -2724,6 +2785,36 @@ higher hit ratio at the expense of an increase in response time. + The rock store type: + + cache_dir rock Directory-Name Mbytes [options] + + The Rock Store type is a database-style storage. All cached + entries are stored in a "database" file, using fixed-size slots, + one entry per slot. The database size is specified in MB. The + slot size is specified in bytes using the max-size option. See + below for more info on the max-size option. + + swap-timeout=msec: Squid will not start writing a miss to or + reading a hit from disk if it estimates that the swap operation + will take more than the specified number of milliseconds. By + default and when set to zero, disables the disk I/O time limit + enforcement. Ignored when using blocking I/O module because + blocking synchronous I/O does not allow Squid to estimate the + expected swap wait time. + + max-swap-rate=swaps/sec: Artificially limits disk access using + the specified I/O rate limit. Swap in and swap out requests that + would cause the average I/O rate to exceed the limit are + delayed. This is necessary on file systems that buffer "too + many" writes and then start blocking Squid and other processes + while committing those writes to disk. Usually used together + with swap-timeout to avoid excessive delays and queue overflows + when disk demand exceeds available disk "bandwidth". By default + and when set to zero, disables the disk I/O rate limit + enforcement. Currently supported by IpcIo module only. + + The coss store type: NP: COSS filesystem in Squid-3 has been deemed too unstable for @@ -3393,7 +3484,7 @@ NAME: netdb_filename TYPE: string -DEFAULT: @DEFAULT_NETDB_FILE@ +DEFAULT: stdio:@DEFAULT_NETDB_FILE@ LOC: Config.netdbFilename IFDEF: USE_ICMP DOC_START @@ -4069,8 +4160,8 @@ DOC_END NAME: store_avg_object_size -COMMENT: (kbytes) -TYPE: kb_int64_t +COMMENT: (bytes) +TYPE: b_int64_t DEFAULT: 13 KB LOC: Config.Store.avgObjectSize DOC_START @@ -6543,17 +6634,19 @@ DOC_START Defines a single ICAP service using the following format: - icap_service service_name vectoring_point [options] service_url + icap_service id vectoring_point uri [option ...] - service_name: ID - an opaque identifier which must be unique in squid.conf + id: ID + an opaque identifier or name which is used to direct traffic to + this specific service. Must be unique among all adaptation + services in squid.conf. vectoring_point: reqmod_precache|reqmod_postcache|respmod_precache|respmod_postcache This specifies at which point of transaction processing the ICAP service should be activated. *_postcache vectoring points are not yet supported. - service_url: icap://servername:port/servicepath + uri: icap://servername:port/servicepath ICAP server and service location. ICAP does not allow a single service to handle both REQMOD and RESPMOD @@ -6622,8 +6715,8 @@ deprecated but supported for backward compatibility. Example: -icap_service svcBlocker reqmod_precache bypass=0 icap://icap1.mydomain.net:1344/reqmod -icap_service svcLogger reqmod_precache routing=on icap://icap2.mydomain.net:1344/respmod +icap_service svcBlocker reqmod_precache icap://icap1.mydomain.net:1344/reqmod bypass=0 +icap_service svcLogger reqmod_precache icap://icap2.mydomain.net:1344/respmod routing=on DOC_END NAME: icap_class @@ -6675,25 +6768,56 @@ DOC_START Defines a single eCAP service - ecap_service servicename vectoring_point bypass service_url + ecap_service id vectoring_point uri [option ...] + + id: ID + an opaque identifier or name which is used to direct traffic to + this specific service. Must be unique among all adaptation + services in squid.conf. - vectoring_point = reqmod_precache|reqmod_postcache|respmod_precache|respmod_postcache + vectoring_point: reqmod_precache|reqmod_postcache|respmod_precache|respmod_postcache This specifies at which point of transaction processing the eCAP service should be activated. *_postcache vectoring points are not yet supported. - bypass = 1|0 - If set to 1, the eCAP service is treated as optional. If the - service cannot be reached or malfunctions, Squid will try to - ignore any errors and process the message as if the service + + uri: ecap://vendor/service_name?custom&cgi=style¶meters=optional + Squid uses the eCAP service URI to match this configuration + line with one of the dynamically loaded services. Each loaded + eCAP service must have a unique URI. Obtain the right URI from + the service provider. + + + Service options are separated by white space. eCAP services support + the following name=value options: + + bypass=on|off|1|0 + If set to 'on' or '1', the eCAP service is treated as optional. + If the service cannot be reached or malfunctions, Squid will try + to ignore any errors and process the message as if the service was not enabled. No all eCAP errors can be bypassed. - If set to 0, the eCAP service is treated as essential and all - eCAP errors will result in an error page returned to the + If set to 'off' or '0', the eCAP service is treated as essential + and all eCAP errors will result in an error page returned to the HTTP client. - service_url = ecap://vendor/service_name?custom&cgi=style¶meters=optional + + Bypass is off by default: services are treated as essential. + + routing=on|off|1|0 + If set to 'on' or '1', the eCAP service is allowed to + dynamically change the current message adaptation plan by + returning a chain of services to be used next. + + Dynamic adaptation plan may cross or cover multiple supported + vectoring points in their natural processing order. + + Routing is not allowed by default. + + Older ecap_service format without optional named parameters is + deprecated but supported for backward compatibility. + Example: -ecap_service service_1 reqmod_precache 0 ecap://filters-R-us/leakDetector?on_error=block -ecap_service service_2 respmod_precache 1 icap://filters-R-us/virusFilter?config=/etc/vf.cfg +ecap_service s1 reqmod_precache ecap://filters.R.us/leakDetector?on_error=block bypass=off +ecap_service s2 respmod_precache ecap://filters.R.us/virusFilter config=/etc/vf.cfg bypass=on DOC_END NAME: loadable_modules @@ -7145,6 +7269,25 @@ *) May negatively impact connection delay times. DOC_END +NAME: dns_v4_first +TYPE: onoff +DEFAULT: off +LOC: Config.dns.v4_first +IFDEF: !USE_DNSSERVERS +DOC_START + With the IPv6 Internet being as fast or faster than IPv4 Internet + for most networks Squid prefers to contact websites over IPv6. + + This option reverses the order of preference to make Squid contact + dual-stack websites over IPv4 first. Squid will still perform both + IPv6 and IPv4 DNS lookups before connecting. + + WARNING: + This option will restrict the situations under which IPv6 + connectivity is used (and tested). Hiding network problems + which would otherwise be detected and warned about. +DOC_END + NAME: ipcache_size COMMENT: (number of entries) TYPE: int diff -u -r -N squid-3.2.0.12/src/client_side.cc squid-3.2.0.13/src/client_side.cc --- squid-3.2.0.12/src/client_side.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/client_side.cc 2011-10-14 14:42:56.000000000 +1300 @@ -1821,11 +1821,11 @@ void ClientSocketContext::writeComplete(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, comm_err_t errflag) { - StoreEntry *entry = http->storeEntry(); + const StoreEntry *entry = http->storeEntry(); http->out.size += size; debugs(33, 5, HERE << conn << ", sz " << size << ", err " << errflag << ", off " << http->out.size << ", len " << - entry ? entry->objectLen() : 0); + (entry ? entry->objectLen() : 0)); clientUpdateSocketStats(http->logType, size); /* Bail out quickly on COMM_ERR_CLOSING - close handlers will tidy up */ @@ -2301,8 +2301,10 @@ int ConnStateData::getAvailableBufferLength() const { - int result = in.allocatedSize - in.notYetUsed - 1; - assert (result >= 0); + assert (in.allocatedSize > in.notYetUsed); // allocated more than used + const size_t result = in.allocatedSize - in.notYetUsed - 1; + // huge request_header_max_size may lead to more than INT_MAX unused space + assert (static_cast(result) <= INT_MAX); return result; } @@ -3936,6 +3938,15 @@ bodyPipe->enableAutoConsumption(); } +void +ConnStateData::expectNoForwarding() +{ + if (bodyPipe != NULL) { + debugs(33, 4, HERE << "no consumer for virgin body " << bodyPipe->status()); + bodyPipe->expectNoConsumption(); + } +} + /// initialize dechunking state void ConnStateData::startDechunkingRequest() diff -u -r -N squid-3.2.0.12/src/client_side.h squid-3.2.0.13/src/client_side.h --- squid-3.2.0.12/src/client_side.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/client_side.h 2011-10-14 14:42:56.000000000 +1300 @@ -262,6 +262,7 @@ bool closing() const; void startClosing(const char *reason); + void expectNoForwarding(); ///< cleans up virgin request [body] forwarding state BodyPipe::Pointer expectRequestBody(int64_t size); virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer); diff -u -r -N squid-3.2.0.12/src/client_side_reply.cc squid-3.2.0.13/src/client_side_reply.cc --- squid-3.2.0.12/src/client_side_reply.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/client_side_reply.cc 2011-10-14 14:42:56.000000000 +1300 @@ -1044,6 +1044,8 @@ int clientReplyContext::storeOKTransferDone() const { + assert(http->storeEntry()->objectLen() >= 0); + assert(http->storeEntry()->objectLen() >= headers_sz); if (http->out.offset >= http->storeEntry()->objectLen() - headers_sz) { debugs(88,3,HERE << "storeOKTransferDone " << " out.offset=" << http->out.offset << diff -u -r -N squid-3.2.0.12/src/client_side_request.cc squid-3.2.0.13/src/client_side_request.cc --- squid-3.2.0.12/src/client_side_request.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/client_side_request.cc 2011-10-14 14:42:56.000000000 +1300 @@ -67,6 +67,7 @@ #include "compat/inet_pton.h" #include "fde.h" #include "format/Tokens.h" +#include "HttpHdrCc.h" #include "HttpReply.h" #include "HttpRequest.h" #include "ip/QosConfig.h" @@ -194,7 +195,7 @@ { assert(request); return request->cache_control && - EBIT_TEST(request->cache_control->mask, CC_ONLY_IF_CACHED); + request->cache_control->onlyIfCached(); } /* @@ -633,6 +634,9 @@ // verify the destination DNS is one of the Host: headers IPs ipcache_nbgethostbyname(host, hostHeaderIpVerifyWrapper, this); } + } else if (Config.onoff.hostStrictVerify) { + debugs(85, 3, HERE << "validate skipped."); + http->doCallouts(); } else if (strlen(host) != strlen(http->request->GetHost())) { // Verify forward-proxy requested URL domain matches the Host: header debugs(85, 3, HERE << "FAIL on validate URL domain length " << http->request->GetHost() << " matches Host: " << host); @@ -1016,7 +1020,7 @@ } if (request->cache_control) - if (EBIT_TEST(request->cache_control->mask, CC_NO_CACHE)) + if (request->cache_control->noCache()) no_cache++; /* @@ -1787,6 +1791,7 @@ request->detailError(ERR_ICAP_FAILURE, errDetail); c->flags.readMore = true; + c->expectNoForwarding(); node = (clientStreamNode *)client_stream.tail->data; clientStreamRead(node, this, node->readBuffer); } diff -u -r -N squid-3.2.0.12/src/comm/Makefile.am squid-3.2.0.13/src/comm/Makefile.am --- squid-3.2.0.12/src/comm/Makefile.am 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/comm/Makefile.am 2011-10-14 14:42:56.000000000 +1300 @@ -27,5 +27,3 @@ Write.h \ \ comm_internal.h - -EXTRA_DIST= stub_libcomm.cc diff -u -r -N squid-3.2.0.12/src/comm/Makefile.in squid-3.2.0.13/src/comm/Makefile.in --- squid-3.2.0.12/src/comm/Makefile.in 2011-09-16 23:38:19.000000000 +1200 +++ squid-3.2.0.13/src/comm/Makefile.in 2011-10-14 14:48:02.000000000 +1300 @@ -335,7 +335,6 @@ \ comm_internal.h -EXTRA_DIST = stub_libcomm.cc all: all-am .SUFFIXES: diff -u -r -N squid-3.2.0.12/src/comm/stub_libcomm.cc squid-3.2.0.13/src/comm/stub_libcomm.cc --- squid-3.2.0.12/src/comm/stub_libcomm.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/comm/stub_libcomm.cc 1970-01-01 12:00:00.000000000 +1200 @@ -1,60 +0,0 @@ -#include "config.h" -#include "base/AsyncJob.h" -#include "structs.h" - -#define STUB_API "comm/libcomm.la" -#include "tests/STUB.h" - -#include "AcceptLimiter.h" -Comm::AcceptLimiter dummy; -Comm::AcceptLimiter & Comm::AcceptLimiter::Instance() STUB_RETVAL(dummy) -void Comm::AcceptLimiter::defer(Comm::TcpAcceptor *afd) STUB -void Comm::AcceptLimiter::removeDead(const Comm::TcpAcceptor *afd) STUB -void Comm::AcceptLimiter::kick() STUB - -#include "comm/Connection.h" -Comm::Connection::Connection() STUB -Comm::Connection::~Connection() STUB -Comm::ConnectionPointer Comm::Connection::copyDetails() const STUB_RETVAL(NULL) -void Comm::Connection::close() STUB -peer * Comm::Connection::getPeer() const STUB_RETVAL(NULL) -void Comm::Connection::setPeer(peer * p) STUB - -#include "comm/ConnOpener.h" -bool Comm::ConnOpener::doneAll() const STUB_RETVAL(false) -//Comm::ConnOpener::ConnOpener(Comm::ConnectionPointer &, AsyncCall::Pointer &, time_t) STUB -//Comm::ConnOpener::~ConnOpener() STUB -void Comm::ConnOpener::setHost(const char *) STUB -const char * Comm::ConnOpener::getHost() const STUB_RETVAL(NULL) - -#include "comm/forward.h" -bool Comm::IsConnOpen(const Comm::ConnectionPointer &) STUB_RETVAL(false) - -#include "comm/IoCallback.h" -void Comm::IoCallback::setCallback(iocb_type type, AsyncCall::Pointer &cb, char *buf, FREE *func, int sz) STUB -void Comm::IoCallback::selectOrQueueWrite() STUB -void Comm::IoCallback::cancel(const char *reason) STUB -void Comm::IoCallback::finish(comm_err_t code, int xerrn) STUB -Comm::CbEntry *Comm::iocb_table = NULL; -void Comm::CallbackTableInit() STUB -void Comm::CallbackTableDestruct() STUB - -#include "comm/Loops.h" -void Comm::SelectLoopInit(void) STUB -void Comm::SetSelect(int, unsigned int, PF *, void *, time_t) STUB -void Comm::ResetSelect(int) STUB -comm_err_t Comm::DoSelect(int) STUB_RETVAL(COMM_ERROR) -void Comm::QuickPollRequired(void) STUB - -#include "comm/TcpAcceptor.h" -//Comm::TcpAcceptor(const Comm::ConnectionPointer &conn, const char *note, const Subscription::Pointer &aSub) STUB -void Comm::TcpAcceptor::subscribe(const Subscription::Pointer &aSub) STUB -void Comm::TcpAcceptor::unsubscribe(const char *) STUB -void Comm::TcpAcceptor::acceptNext() STUB -void Comm::TcpAcceptor::notify(const comm_err_t flag, const Comm::ConnectionPointer &) const STUB - -#include "comm/Write.h" -void Comm::Write(const Comm::ConnectionPointer &, const char *, int, AsyncCall::Pointer &, FREE *) STUB -void Comm::Write(const Comm::ConnectionPointer &conn, MemBuf *mb, AsyncCall::Pointer &callback) STUB -void Comm::WriteCancel(const Comm::ConnectionPointer &conn, const char *reason) STUB -//PF Comm::HandleWrite STUB diff -u -r -N squid-3.2.0.12/src/disk.cc squid-3.2.0.13/src/disk.cc --- squid-3.2.0.12/src/disk.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/disk.cc 2011-10-14 14:42:56.000000000 +1300 @@ -231,12 +231,14 @@ assert(fdd->write_q->len > fdd->write_q->buf_offset); - debugs(6, 3, "diskHandleWrite: FD " << fd << " writing " << (fdd->write_q->len - fdd->write_q->buf_offset) << " bytes"); + debugs(6, 3, "diskHandleWrite: FD " << fd << " writing " << + (fdd->write_q->len - fdd->write_q->buf_offset) << " bytes at " << + fdd->write_q->file_offset); errno = 0; if (fdd->write_q->file_offset != -1) - lseek(fd, fdd->write_q->file_offset, SEEK_SET); + lseek(fd, fdd->write_q->file_offset, SEEK_SET); /* XXX ignore return? */ len = FD_WRITE_METHOD(fd, fdd->write_q->buf + fdd->write_q->buf_offset, @@ -433,7 +435,11 @@ PROF_start(diskHandleRead); +#if WRITES_MAINTAIN_DISK_OFFSET if (F->disk.offset != ctrl_dat->offset) { +#else + { +#endif debugs(6, 3, "diskHandleRead: FD " << fd << " seeking to offset " << ctrl_dat->offset); lseek(fd, ctrl_dat->offset, SEEK_SET); /* XXX ignore return? */ statCounter.syscalls.disk.seeks++; diff -u -r -N squid-3.2.0.12/src/DiskIO/Blocking/BlockingFile.cc squid-3.2.0.13/src/DiskIO/Blocking/BlockingFile.cc --- squid-3.2.0.12/src/DiskIO/Blocking/BlockingFile.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/DiskIO/Blocking/BlockingFile.cc 2011-10-14 14:42:56.000000000 +1300 @@ -146,6 +146,7 @@ assert (fd > -1); assert (ioRequestor.getRaw()); readRequest = aRequest; + debugs(79, 3, HERE << aRequest->len << " for FD " << fd << " at " << aRequest->offset); file_read(fd, aRequest->buf, aRequest->len, aRequest->offset, ReadDone, this); } @@ -160,7 +161,7 @@ void BlockingFile::write(WriteRequest *aRequest) { - debugs(79, 3, "storeUfsWrite: FD " << fd); + debugs(79, 3, HERE << aRequest->len << " for FD " << fd << " at " << aRequest->offset); writeRequest = aRequest; file_write(fd, aRequest->offset, @@ -216,7 +217,7 @@ BlockingFile::writeDone(int rvfd, int errflag, size_t len) { assert (rvfd == fd); - debugs(79, 3, "storeUfsWriteDone: FD " << fd << ", len " << len); + debugs(79, 3, HERE << "FD " << fd << ", len " << len); WriteRequest::Pointer result = writeRequest; writeRequest = NULL; diff -u -r -N squid-3.2.0.12/src/DiskIO/DiskFile.h squid-3.2.0.13/src/DiskIO/DiskFile.h --- squid-3.2.0.12/src/DiskIO/DiskFile.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/DiskIO/DiskFile.h 2011-10-14 14:42:56.000000000 +1300 @@ -47,8 +47,25 @@ { public: + + /// generally useful configuration options supported by some children + class Config + { + public: + Config(): ioTimeout(0), ioRate(-1) {} + + /// canRead/Write should return false if expected I/O delay exceeds it + time_msec_t ioTimeout; // not enforced if zero, which is the default + + /// shape I/O request stream to approach that many per second + int ioRate; // not enforced if negative, which is the default + }; + typedef RefCount Pointer; + /// notes supported configuration options; kids must call this first + virtual void configure(const Config &cfg) {} + virtual void open(int flags, mode_t mode, RefCount callback) = 0; virtual void create(int flags, mode_t mode, RefCount callback) = 0; virtual void read(ReadRequest *) = 0; diff -u -r -N squid-3.2.0.12/src/DiskIO/IpcIo/IpcIoDiskIOModule.cc squid-3.2.0.13/src/DiskIO/IpcIo/IpcIoDiskIOModule.cc --- squid-3.2.0.12/src/DiskIO/IpcIo/IpcIoDiskIOModule.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/DiskIO/IpcIo/IpcIoDiskIOModule.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,37 @@ +#include "squid.h" +#include "IpcIoDiskIOModule.h" +#include "IpcIoIOStrategy.h" + +IpcIoDiskIOModule::IpcIoDiskIOModule() +{ + ModuleAdd(*this); +} + +IpcIoDiskIOModule & +IpcIoDiskIOModule::GetInstance() +{ + return Instance; +} + +void +IpcIoDiskIOModule::init() +{} + +void +IpcIoDiskIOModule::shutdown() +{} + + +DiskIOStrategy* +IpcIoDiskIOModule::createStrategy() +{ + return new IpcIoIOStrategy(); +} + +IpcIoDiskIOModule IpcIoDiskIOModule::Instance; + +char const * +IpcIoDiskIOModule::type () const +{ + return "IpcIo"; +} diff -u -r -N squid-3.2.0.12/src/DiskIO/IpcIo/IpcIoDiskIOModule.h squid-3.2.0.13/src/DiskIO/IpcIo/IpcIoDiskIOModule.h --- squid-3.2.0.12/src/DiskIO/IpcIo/IpcIoDiskIOModule.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/DiskIO/IpcIo/IpcIoDiskIOModule.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,21 @@ +#ifndef SQUID_IPC_IODISKIOMODULE_H +#define SQUID_IPC_IODISKIOMODULE_H + +#include "DiskIO/DiskIOModule.h" + +class IpcIoDiskIOModule : public DiskIOModule +{ + +public: + static IpcIoDiskIOModule &GetInstance(); + IpcIoDiskIOModule(); + virtual void init(); + virtual void shutdown(); + virtual char const *type () const; + virtual DiskIOStrategy* createStrategy(); + +private: + static IpcIoDiskIOModule Instance; +}; + +#endif /* SQUID_IPC_IODISKIOMODULE_H */ diff -u -r -N squid-3.2.0.12/src/DiskIO/IpcIo/IpcIoFile.cc squid-3.2.0.13/src/DiskIO/IpcIo/IpcIoFile.cc --- squid-3.2.0.12/src/DiskIO/IpcIo/IpcIoFile.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/DiskIO/IpcIo/IpcIoFile.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,866 @@ +/* + * $Id$ + * + * DEBUG: section 47 Store Directory Routines + */ + +#include "config.h" +#include "base/RunnersRegistry.h" +#include "base/TextException.h" +#include "DiskIO/IORequestor.h" +#include "DiskIO/IpcIo/IpcIoFile.h" +#include "DiskIO/ReadRequest.h" +#include "DiskIO/WriteRequest.h" +#include "ipc/Messages.h" +#include "ipc/Port.h" +#include "ipc/Queue.h" +#include "ipc/StrandSearch.h" +#include "ipc/UdsOp.h" +#include "ipc/mem/Pages.h" +#include "SquidTime.h" + +CBDATA_CLASS_INIT(IpcIoFile); + +/// shared memory segment path to use for IpcIoFile maps +static const char *const ShmLabel = "io_file"; + +const double IpcIoFile::Timeout = 7; // seconds; XXX: ALL,9 may require more +IpcIoFile::IpcIoFileList IpcIoFile::WaitingForOpen; +IpcIoFile::IpcIoFilesMap IpcIoFile::IpcIoFiles; +std::auto_ptr IpcIoFile::queue; + +bool IpcIoFile::DiskerHandleMoreRequestsScheduled = false; + +static bool DiskerOpen(const String &path, int flags, mode_t mode); +static void DiskerClose(const String &path); + +/// IpcIo wrapper for debugs() streams; XXX: find a better class name +struct SipcIo { + SipcIo(int aWorker, const IpcIoMsg &aMsg, int aDisker): + worker(aWorker), msg(aMsg), disker(aDisker) {} + + int worker; + const IpcIoMsg &msg; + int disker; +}; + +std::ostream & +operator <<(std::ostream &os, const SipcIo &sio) +{ + return os << "ipcIo" << sio.worker << '.' << sio.msg.requestId << + (sio.msg.command == IpcIo::cmdRead ? 'r' : 'w') << sio.disker; +} + + +IpcIoFile::IpcIoFile(char const *aDb): + dbName(aDb), diskId(-1), error_(false), lastRequestId(0), + olderRequests(&requestMap1), newerRequests(&requestMap2), + timeoutCheckScheduled(false) +{ +} + +IpcIoFile::~IpcIoFile() +{ + if (diskId >= 0) { + const IpcIoFilesMap::iterator i = IpcIoFiles.find(diskId); + // XXX: warn and continue? + Must(i != IpcIoFiles.end()); + Must(i->second == this); + IpcIoFiles.erase(i); + } +} + +void +IpcIoFile::configure(const Config &cfg) +{ + DiskFile::configure(cfg); + config = cfg; +} + +void +IpcIoFile::open(int flags, mode_t mode, RefCount callback) +{ + ioRequestor = callback; + Must(diskId < 0); // we do not know our disker yet + + if (!queue.get()) + queue.reset(new Queue(ShmLabel, IamWorkerProcess() ? Queue::groupA : Queue::groupB, KidIdentifier)); + + if (IamDiskProcess()) { + error_ = !DiskerOpen(dbName, flags, mode); + if (error_) + return; + + diskId = KidIdentifier; + const bool inserted = + IpcIoFiles.insert(std::make_pair(diskId, this)).second; + Must(inserted); + + queue->localRateLimit() = + static_cast(config.ioRate); + + Ipc::HereIamMessage ann(Ipc::StrandCoord(KidIdentifier, getpid())); + ann.strand.tag = dbName; + Ipc::TypedMsgHdr message; + ann.pack(message); + SendMessage(Ipc::coordinatorAddr, message); + + ioRequestor->ioCompletedNotification(); + return; + } + + Ipc::StrandSearchRequest request; + request.requestorId = KidIdentifier; + request.tag = dbName; + + Ipc::TypedMsgHdr msg; + request.pack(msg); + Ipc::SendMessage(Ipc::coordinatorAddr, msg); + + WaitingForOpen.push_back(this); + + eventAdd("IpcIoFile::OpenTimeout", &IpcIoFile::OpenTimeout, + this, Timeout, 0, false); // "this" pointer is used as id +} + +void +IpcIoFile::openCompleted(const Ipc::StrandSearchResponse *const response) +{ + Must(diskId < 0); // we do not know our disker yet + + if (!response) { + debugs(79,1, HERE << "error: timeout"); + error_ = true; + } else { + diskId = response->strand.kidId; + if (diskId >= 0) { + const bool inserted = + IpcIoFiles.insert(std::make_pair(diskId, this)).second; + Must(inserted); + } else { + error_ = true; + debugs(79,1, HERE << "error: no disker claimed " << dbName); + } + } + + ioRequestor->ioCompletedNotification(); +} + +/** + * Alias for IpcIoFile::open(...) + \copydoc IpcIoFile::open(int flags, mode_t mode, RefCount callback) + */ +void +IpcIoFile::create(int flags, mode_t mode, RefCount callback) +{ + assert(false); // check + /* We use the same logic path for open */ + open(flags, mode, callback); +} + +void +IpcIoFile::close() +{ + assert(ioRequestor != NULL); + + if (IamDiskProcess()) + DiskerClose(dbName); + // XXX: else nothing to do? + + ioRequestor->closeCompleted(); +} + +bool +IpcIoFile::canRead() const +{ + return diskId >= 0 && canWait(); +} + +bool +IpcIoFile::canWrite() const +{ + return diskId >= 0 && canWait(); +} + +bool +IpcIoFile::error() const +{ + return error_; +} + +void +IpcIoFile::read(ReadRequest *readRequest) +{ + debugs(79,3, HERE << "(disker" << diskId << ", " << readRequest->len << ", " << + readRequest->offset << ")"); + + assert(ioRequestor != NULL); + assert(readRequest->offset >= 0); + Must(!error_); + + //assert(minOffset < 0 || minOffset <= readRequest->offset); + //assert(maxOffset < 0 || readRequest->offset + readRequest->len <= (uint64_t)maxOffset); + + IpcIoPendingRequest *const pending = new IpcIoPendingRequest(this); + pending->readRequest = readRequest; + push(pending); +} + +void +IpcIoFile::readCompleted(ReadRequest *readRequest, + IpcIoMsg *const response) +{ + bool ioError = false; + if (!response) { + debugs(79, 3, HERE << "error: timeout"); + ioError = true; // I/O timeout does not warrant setting error_? + } else { + if (response->xerrno) { + debugs(79,1, HERE << "error: " << xstrerr(response->xerrno)); + ioError = error_ = true; + } else if (!response->page) { + debugs(79,1, HERE << "error: run out of shared memory pages"); + ioError = true; + } else { + const char *const buf = Ipc::Mem::PagePointer(response->page); + memcpy(readRequest->buf, buf, response->len); + } + + Ipc::Mem::PutPage(response->page); + } + + const ssize_t rlen = ioError ? -1 : (ssize_t)readRequest->len; + const int errflag = ioError ? DISK_ERROR :DISK_OK; + ioRequestor->readCompleted(readRequest->buf, rlen, errflag, readRequest); +} + +void +IpcIoFile::write(WriteRequest *writeRequest) +{ + debugs(79,3, HERE << "(disker" << diskId << ", " << writeRequest->len << ", " << + writeRequest->offset << ")"); + + assert(ioRequestor != NULL); + assert(writeRequest->len > 0); // TODO: work around mmap failures on zero-len? + assert(writeRequest->offset >= 0); + Must(!error_); + + //assert(minOffset < 0 || minOffset <= writeRequest->offset); + //assert(maxOffset < 0 || writeRequest->offset + writeRequest->len <= (uint64_t)maxOffset); + + IpcIoPendingRequest *const pending = new IpcIoPendingRequest(this); + pending->writeRequest = writeRequest; + push(pending); +} + +void +IpcIoFile::writeCompleted(WriteRequest *writeRequest, + const IpcIoMsg *const response) +{ + bool ioError = false; + if (!response) { + debugs(79, 3, HERE << "error: timeout"); + ioError = true; // I/O timeout does not warrant setting error_? + } else if (response->xerrno) { + debugs(79,1, HERE << "error: " << xstrerr(response->xerrno)); + ioError = error_ = true; + } else if (response->len != writeRequest->len) { + debugs(79,1, HERE << "problem: " << response->len << " < " << writeRequest->len); + error_ = true; + } + + if (writeRequest->free_func) + (writeRequest->free_func)(const_cast(writeRequest->buf)); // broken API? + + if (!ioError) { + debugs(79,5, HERE << "wrote " << writeRequest->len << " to disker" << + diskId << " at " << writeRequest->offset); + } + + const ssize_t rlen = ioError ? 0 : (ssize_t)writeRequest->len; + const int errflag = ioError ? DISK_ERROR :DISK_OK; + ioRequestor->writeCompleted(errflag, rlen, writeRequest); +} + +bool +IpcIoFile::ioInProgress() const +{ + return !olderRequests->empty() || !newerRequests->empty(); +} + +/// track a new pending request +void +IpcIoFile::trackPendingRequest(IpcIoPendingRequest *const pending) +{ + newerRequests->insert(std::make_pair(lastRequestId, pending)); + if (!timeoutCheckScheduled) + scheduleTimeoutCheck(); +} + +/// push an I/O request to disker +void +IpcIoFile::push(IpcIoPendingRequest *const pending) +{ + // prevent queue overflows: check for responses to earlier requests + HandleResponses("before push"); + + debugs(47, 7, HERE); + Must(diskId >= 0); + Must(pending); + Must(pending->readRequest || pending->writeRequest); + + IpcIoMsg ipcIo; + try { + ipcIo.requestId = lastRequestId; + ipcIo.start = current_time; + if (pending->readRequest) { + ipcIo.command = IpcIo::cmdRead; + ipcIo.offset = pending->readRequest->offset; + ipcIo.len = pending->readRequest->len; + } else { // pending->writeRequest + Must(pending->writeRequest->len <= Ipc::Mem::PageSize()); + if (!Ipc::Mem::GetPage(Ipc::Mem::PageId::ioPage, ipcIo.page)) { + ipcIo.len = 0; + throw TexcHere("run out of shared memory pages for IPC I/O"); + } + ipcIo.command = IpcIo::cmdWrite; + ipcIo.offset = pending->writeRequest->offset; + ipcIo.len = pending->writeRequest->len; + char *const buf = Ipc::Mem::PagePointer(ipcIo.page); + memcpy(buf, pending->writeRequest->buf, ipcIo.len); // optimize away + } + + debugs(47, 7, HERE << "pushing " << SipcIo(KidIdentifier, ipcIo, diskId)); + + if (queue->push(diskId, ipcIo)) + Notify(diskId); // must notify disker + trackPendingRequest(pending); + } catch (const Queue::Full &) { + debugs(47, DBG_IMPORTANT, "Worker I/O push queue overflow: " << + SipcIo(KidIdentifier, ipcIo, diskId)); // TODO: report queue len + // TODO: grow queue size + + pending->completeIo(NULL); + delete pending; + } catch (const TextException &e) { + debugs(47, DBG_IMPORTANT, HERE << e.what()); + pending->completeIo(NULL); + delete pending; + } +} + +/// whether we think there is enough time to complete the I/O +bool +IpcIoFile::canWait() const +{ + if (!config.ioTimeout) + return true; // no timeout specified + + IpcIoMsg oldestIo; + if (!queue->peek(diskId, oldestIo) || oldestIo.start.tv_sec <= 0) + return true; // we cannot estimate expected wait time; assume it is OK + + const int expectedWait = tvSubMsec(oldestIo.start, current_time); + if (expectedWait < 0 || + static_cast(expectedWait) < config.ioTimeout) + return true; // expected wait time is acceptible + + debugs(47,2, HERE << "cannot wait: " << expectedWait << + " oldest: " << SipcIo(KidIdentifier, oldestIo, diskId)); + return false; // do not want to wait that long +} + +/// called when coordinator responds to worker open request +void +IpcIoFile::HandleOpenResponse(const Ipc::StrandSearchResponse &response) +{ + debugs(47, 7, HERE << "coordinator response to open request"); + for (IpcIoFileList::iterator i = WaitingForOpen.begin(); + i != WaitingForOpen.end(); ++i) { + if (response.strand.tag == (*i)->dbName) { + (*i)->openCompleted(&response); + WaitingForOpen.erase(i); + return; + } + } + + debugs(47, 4, HERE << "LATE disker response to open for " << + response.strand.tag); + // nothing we can do about it; completeIo() has been called already +} + +void +IpcIoFile::HandleResponses(const char *const when) +{ + debugs(47, 4, HERE << "popping all " << when); + IpcIoMsg ipcIo; + // get all responses we can: since we are not pushing, this will stop + int diskId; + while (queue->pop(diskId, ipcIo)) { + const IpcIoFilesMap::const_iterator i = IpcIoFiles.find(diskId); + Must(i != IpcIoFiles.end()); // TODO: warn but continue + i->second->handleResponse(ipcIo); + } +} + +void +IpcIoFile::handleResponse(IpcIoMsg &ipcIo) +{ + const int requestId = ipcIo.requestId; + debugs(47, 7, HERE << "popped disker response: " << + SipcIo(KidIdentifier, ipcIo, diskId)); + + Must(requestId); + if (IpcIoPendingRequest *const pending = dequeueRequest(requestId)) { + pending->completeIo(&ipcIo); + delete pending; // XXX: leaking if throwing + } else { + debugs(47, 4, HERE << "LATE disker response to " << ipcIo.command << + "; ipcIo" << KidIdentifier << '.' << requestId); + // nothing we can do about it; completeIo() has been called already + } +} + +void +IpcIoFile::Notify(const int peerId) +{ + // TODO: Count and report the total number of notifications, pops, pushes. + debugs(47, 7, HERE << "kid" << peerId); + Ipc::TypedMsgHdr msg; + msg.setType(Ipc::mtIpcIoNotification); // TODO: add proper message type? + msg.putInt(KidIdentifier); + const String addr = Ipc::Port::MakeAddr(Ipc::strandAddrPfx, peerId); + Ipc::SendMessage(addr, msg); +} + +void +IpcIoFile::HandleNotification(const Ipc::TypedMsgHdr &msg) +{ + const int from = msg.getInt(); + debugs(47, 7, HERE << "from " << from); + queue->clearReaderSignal(from); + if (IamDiskProcess()) + DiskerHandleRequests(); + else + HandleResponses("after notification"); +} + +/// handles open request timeout +void +IpcIoFile::OpenTimeout(void *const param) +{ + Must(param); + // the pointer is used for comparison only and not dereferenced + const IpcIoFile *const ipcIoFile = + reinterpret_cast(param); + for (IpcIoFileList::iterator i = WaitingForOpen.begin(); + i != WaitingForOpen.end(); ++i) { + if (*i == ipcIoFile) { + (*i)->openCompleted(NULL); + WaitingForOpen.erase(i); + break; + } + } +} + +/// IpcIoFile::checkTimeouts wrapper +void +IpcIoFile::CheckTimeouts(void *const param) +{ + Must(param); + const int diskId = reinterpret_cast(param); + debugs(47, 7, HERE << "diskId=" << diskId); + const IpcIoFilesMap::const_iterator i = IpcIoFiles.find(diskId); + if (i != IpcIoFiles.end()) + i->second->checkTimeouts(); +} + +void +IpcIoFile::checkTimeouts() +{ + timeoutCheckScheduled = false; + + // last chance to recover in case a notification message was lost, etc. + const RequestMap::size_type timeoutsBefore = olderRequests->size(); + HandleResponses("before timeout"); + const RequestMap::size_type timeoutsNow = olderRequests->size(); + + if (timeoutsBefore > timeoutsNow) { // some requests were rescued + // notification message lost or significantly delayed? + debugs(47, DBG_IMPORTANT, "WARNING: communication with disker " << + "may be too slow or disrupted for about " << + Timeout << "s; rescued " << (timeoutsBefore - timeoutsNow) << + " out of " << timeoutsBefore << " I/Os"); + } + + if (timeoutsNow) { + debugs(47, DBG_IMPORTANT, "WARNING: abandoning " << + timeoutsNow << " I/Os after at least " << + Timeout << "s timeout"); + } + + // any old request would have timed out by now + typedef RequestMap::const_iterator RMCI; + for (RMCI i = olderRequests->begin(); i != olderRequests->end(); ++i) { + IpcIoPendingRequest *const pending = i->second; + + const unsigned int requestId = i->first; + debugs(47, 7, HERE << "disker timeout; ipcIo" << + KidIdentifier << '.' << requestId); + + pending->completeIo(NULL); // no response + delete pending; // XXX: leaking if throwing + } + olderRequests->clear(); + + swap(olderRequests, newerRequests); // switches pointers around + if (!olderRequests->empty() && !timeoutCheckScheduled) + scheduleTimeoutCheck(); +} + +/// prepare to check for timeouts in a little while +void +IpcIoFile::scheduleTimeoutCheck() +{ + // we check all older requests at once so some may be wait for 2*Timeout + eventAdd("IpcIoFile::CheckTimeouts", &IpcIoFile::CheckTimeouts, + reinterpret_cast(diskId), Timeout, 0, false); + timeoutCheckScheduled = true; +} + +/// returns and forgets the right IpcIoFile pending request +IpcIoPendingRequest * +IpcIoFile::dequeueRequest(const unsigned int requestId) +{ + Must(requestId != 0); + + RequestMap *map = NULL; + RequestMap::iterator i = requestMap1.find(requestId); + + if (i != requestMap1.end()) + map = &requestMap1; + else { + i = requestMap2.find(requestId); + if (i != requestMap2.end()) + map = &requestMap2; + } + + if (!map) // not found in both maps + return NULL; + + IpcIoPendingRequest *pending = i->second; + map->erase(i); + return pending; +} + +int +IpcIoFile::getFD() const +{ + assert(false); // not supported; TODO: remove this method from API + return -1; +} + + +/* IpcIoMsg */ + +IpcIoMsg::IpcIoMsg(): + requestId(0), offset(0), len(0), command(IpcIo::cmdNone), xerrno(0) +{ + start.tv_sec = 0; +} + +/* IpcIoPendingRequest */ + +IpcIoPendingRequest::IpcIoPendingRequest(const IpcIoFile::Pointer &aFile): + file(aFile), readRequest(NULL), writeRequest(NULL) +{ + Must(file != NULL); + if (++file->lastRequestId == 0) // don't use zero value as requestId + ++file->lastRequestId; +} + +void +IpcIoPendingRequest::completeIo(IpcIoMsg *const response) +{ + if (readRequest) + file->readCompleted(readRequest, response); + else if (writeRequest) + file->writeCompleted(writeRequest, response); + else { + Must(!response); // only timeouts are handled here + file->openCompleted(NULL); + } +} + + + +/* XXX: disker code that should probably be moved elsewhere */ + +static int TheFile = -1; ///< db file descriptor + +static void +diskerRead(IpcIoMsg &ipcIo) +{ + if (!Ipc::Mem::GetPage(Ipc::Mem::PageId::ioPage, ipcIo.page)) { + ipcIo.len = 0; + debugs(47,2, HERE << "run out of shared memory pages for IPC I/O"); + return; + } + + char *const buf = Ipc::Mem::PagePointer(ipcIo.page); + const ssize_t read = pread(TheFile, buf, min(ipcIo.len, Ipc::Mem::PageSize()), ipcIo.offset); + statCounter.syscalls.disk.reads++; + fd_bytes(TheFile, read, FD_READ); + + if (read >= 0) { + ipcIo.xerrno = 0; + const size_t len = static_cast(read); // safe because read > 0 + debugs(47,8, HERE << "disker" << KidIdentifier << " read " << + (len == ipcIo.len ? "all " : "just ") << read); + ipcIo.len = len; + } else { + ipcIo.xerrno = errno; + ipcIo.len = 0; + debugs(47,5, HERE << "disker" << KidIdentifier << " read error: " << + ipcIo.xerrno); + } +} + +static void +diskerWrite(IpcIoMsg &ipcIo) +{ + const char *const buf = Ipc::Mem::PagePointer(ipcIo.page); + const ssize_t wrote = pwrite(TheFile, buf, min(ipcIo.len, Ipc::Mem::PageSize()), ipcIo.offset); + statCounter.syscalls.disk.writes++; + fd_bytes(TheFile, wrote, FD_WRITE); + + if (wrote >= 0) { + ipcIo.xerrno = 0; + const size_t len = static_cast(wrote); // safe because wrote > 0 + debugs(47,8, HERE << "disker" << KidIdentifier << " wrote " << + (len == ipcIo.len ? "all " : "just ") << wrote); + ipcIo.len = len; + } else { + ipcIo.xerrno = errno; + ipcIo.len = 0; + debugs(47,5, HERE << "disker" << KidIdentifier << " write error: " << + ipcIo.xerrno); + } + + Ipc::Mem::PutPage(ipcIo.page); +} + + +void +IpcIoFile::DiskerHandleMoreRequests(void *source) +{ + debugs(47, 7, HERE << "resuming handling requests after " << + static_cast(source)); + DiskerHandleMoreRequestsScheduled = false; + IpcIoFile::DiskerHandleRequests(); +} + +bool +IpcIoFile::WaitBeforePop() +{ + const Ipc::QueueReader::Rate::Value ioRate = queue->localRateLimit(); + const double maxRate = ioRate/1e3; // req/ms + + // do we need to enforce configured I/O rate? + if (maxRate <= 0) + return false; + + // is there an I/O request we could potentially delay? + if (!queue->popReady()) { + // unlike pop(), popReady() is not reliable and does not block reader + // so we must proceed with pop() even if it is likely to fail + return false; + } + + static timeval LastIo = current_time; + + const double ioDuration = 1.0 / maxRate; // ideal distance between two I/Os + // do not accumulate more than 100ms or 100 I/Os, whichever is smaller + const int64_t maxImbalance = min(static_cast(100), static_cast(100 * ioDuration)); + + const double credit = ioDuration; // what the last I/O should have cost us + const double debit = tvSubMsec(LastIo, current_time); // actual distance from the last I/O + LastIo = current_time; + + Ipc::QueueReader::Balance &balance = queue->localBalance(); + balance += static_cast(credit - debit); + + debugs(47, 7, HERE << "rate limiting balance: " << balance << " after +" << credit << " -" << debit); + + if (balance > maxImbalance) { + // if we accumulated too much time for future slow I/Os, + // then shed accumulated time to keep just half of the excess + const int64_t toSpend = balance - maxImbalance/2; + + if (toSpend/1e3 > Timeout) + debugs(47, DBG_IMPORTANT, "WARNING: Rock disker delays I/O " << + "requests for " << (toSpend/1e3) << " seconds to obey " << + ioRate << "/sec rate limit"); + + debugs(47, 3, HERE << "rate limiting by " << toSpend << " ms to get" << + (1e3*maxRate) << "/sec rate"); + eventAdd("IpcIoFile::DiskerHandleMoreRequests", + &IpcIoFile::DiskerHandleMoreRequests, + const_cast("rate limiting"), + toSpend/1e3, 0, false); + DiskerHandleMoreRequestsScheduled = true; + return true; + } else if (balance < -maxImbalance) { + // do not owe "too much" to avoid "too large" bursts of I/O + balance = -maxImbalance; + } + + return false; +} + +void +IpcIoFile::DiskerHandleRequests() +{ + // Balance our desire to maximize the number of concurrent I/O requests + // (reordred by OS to minimize seek time) with a requirement to + // send 1st-I/O notification messages, process Coordinator events, etc. + const int maxSpentMsec = 10; // keep small: most RAM I/Os are under 1ms + const timeval loopStart = current_time; + + int popped = 0; + int workerId = 0; + IpcIoMsg ipcIo; + while (!WaitBeforePop() && queue->pop(workerId, ipcIo)) { + ++popped; + + // at least one I/O per call is guaranteed if the queue is not empty + DiskerHandleRequest(workerId, ipcIo); + + getCurrentTime(); + const double elapsedMsec = tvSubMsec(loopStart, current_time); + if (elapsedMsec > maxSpentMsec || elapsedMsec < 0) { + if (!DiskerHandleMoreRequestsScheduled) { + // the gap must be positive for select(2) to be given a chance + const double minBreakSecs = 0.001; + eventAdd("IpcIoFile::DiskerHandleMoreRequests", + &IpcIoFile::DiskerHandleMoreRequests, + const_cast("long I/O loop"), + minBreakSecs, 0, false); + DiskerHandleMoreRequestsScheduled = true; + } + debugs(47, 3, HERE << "pausing after " << popped << " I/Os in " << + elapsedMsec << "ms; " << (elapsedMsec/popped) << "ms per I/O"); + break; + } + } + + // TODO: consider using O_DIRECT with "elevator" optimization where we pop + // requests first, then reorder the popped requests to optimize seek time, + // then do I/O, then take a break, and come back for the next set of I/O + // requests. +} + +/// called when disker receives an I/O request +void +IpcIoFile::DiskerHandleRequest(const int workerId, IpcIoMsg &ipcIo) +{ + if (ipcIo.command != IpcIo::cmdRead && ipcIo.command != IpcIo::cmdWrite) { + debugs(0,0, HERE << "disker" << KidIdentifier << + " should not receive " << ipcIo.command << + " ipcIo" << workerId << '.' << ipcIo.requestId); + return; + } + + debugs(47,5, HERE << "disker" << KidIdentifier << + (ipcIo.command == IpcIo::cmdRead ? " reads " : " writes ") << + ipcIo.len << " at " << ipcIo.offset << + " ipcIo" << workerId << '.' << ipcIo.requestId); + + if (ipcIo.command == IpcIo::cmdRead) + diskerRead(ipcIo); + else // ipcIo.command == IpcIo::cmdWrite + diskerWrite(ipcIo); + + debugs(47, 7, HERE << "pushing " << SipcIo(workerId, ipcIo, KidIdentifier)); + + try { + if (queue->push(workerId, ipcIo)) + Notify(workerId); // must notify worker + } catch (const Queue::Full &) { + // The worker queue should not overflow because the worker should pop() + // before push()ing and because if disker pops N requests at a time, + // we should make sure the worker pop() queue length is the worker + // push queue length plus N+1. XXX: implement the N+1 difference. + debugs(47, DBG_IMPORTANT, "BUG: Worker I/O pop queue overflow: " << + SipcIo(workerId, ipcIo, KidIdentifier)); // TODO: report queue len + + // the I/O request we could not push will timeout + } +} + +static bool +DiskerOpen(const String &path, int flags, mode_t mode) +{ + assert(TheFile < 0); + + TheFile = file_open(path.termedBuf(), flags); + + if (TheFile < 0) { + const int xerrno = errno; + debugs(47,0, HERE << "rock db error opening " << path << ": " << + xstrerr(xerrno)); + return false; + } + + store_open_disk_fd++; + debugs(79,3, HERE << "rock db opened " << path << ": FD " << TheFile); + return true; +} + +static void +DiskerClose(const String &path) +{ + if (TheFile >= 0) { + file_close(TheFile); + debugs(79,3, HERE << "rock db closed " << path << ": FD " << TheFile); + TheFile = -1; + store_open_disk_fd--; + } +} + + +/// initializes shared memory segments used by IpcIoFile +class IpcIoRr: public Ipc::Mem::RegisteredRunner +{ +public: + /* RegisteredRunner API */ + IpcIoRr(): owner(NULL) {} + virtual ~IpcIoRr(); + +protected: + virtual void create(const RunnerRegistry &); + +private: + Ipc::FewToFewBiQueue::Owner *owner; +}; + +RunnerRegistrationEntry(rrAfterConfig, IpcIoRr); + + +void IpcIoRr::create(const RunnerRegistry &) +{ + if (!UsingSmp()) + return; + + Must(!owner); + // XXX: make capacity configurable + owner = Ipc::FewToFewBiQueue::Init(ShmLabel, Config.workers, 1, + Config.cacheSwap.n_strands, + 1 + Config.workers, sizeof(IpcIoMsg), + 1024); +} + +IpcIoRr::~IpcIoRr() +{ + delete owner; +} diff -u -r -N squid-3.2.0.12/src/DiskIO/IpcIo/IpcIoFile.h squid-3.2.0.13/src/DiskIO/IpcIo/IpcIoFile.h --- squid-3.2.0.12/src/DiskIO/IpcIo/IpcIoFile.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/DiskIO/IpcIo/IpcIoFile.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,163 @@ +#ifndef SQUID_IPC_IOFILE_H +#define SQUID_IPC_IOFILE_H + +#include "base/AsyncCall.h" +#include "cbdata.h" +#include "DiskIO/DiskFile.h" +#include "DiskIO/IORequestor.h" +#include "ipc/forward.h" +#include "ipc/mem/Page.h" +#include +#include +#include + +namespace Ipc +{ +class FewToFewBiQueue; +} // Ipc + +// TODO: expand to all classes +namespace IpcIo +{ + +/// what kind of I/O the disker needs to do or have done +typedef enum { cmdNone, cmdOpen, cmdRead, cmdWrite } Command; + +} // namespace IpcIo + + +/// converts DiskIO requests to IPC queue messages +class IpcIoMsg +{ +public: + IpcIoMsg(); + +public: + unsigned int requestId; ///< unique for requestor; matches request w/ response + + off_t offset; + size_t len; + Ipc::Mem::PageId page; + + IpcIo::Command command; ///< what disker is supposed to do or did + struct timeval start; ///< when the I/O request was converted to IpcIoMsg + + int xerrno; ///< I/O error code or zero +}; + +class IpcIoPendingRequest; + +class IpcIoFile: public DiskFile +{ + +public: + typedef RefCount Pointer; + + IpcIoFile(char const *aDb); + virtual ~IpcIoFile(); + + /* DiskFile API */ + virtual void configure(const Config &cfg); + virtual void open(int flags, mode_t mode, RefCount callback); + virtual void create(int flags, mode_t mode, RefCount callback); + virtual void read(ReadRequest *); + virtual void write(WriteRequest *); + virtual void close(); + virtual bool error() const; + virtual int getFD() const; + virtual bool canRead() const; + virtual bool canWrite() const; + virtual bool ioInProgress() const; + + /// handle open response from coordinator + static void HandleOpenResponse(const Ipc::StrandSearchResponse &response); + + /// handle queue push notifications from worker or disker + static void HandleNotification(const Ipc::TypedMsgHdr &msg); + + DiskFile::Config config; ///< supported configuration options + +protected: + friend class IpcIoPendingRequest; + void openCompleted(const Ipc::StrandSearchResponse *const response); + void readCompleted(ReadRequest *readRequest, IpcIoMsg *const response); + void writeCompleted(WriteRequest *writeRequest, const IpcIoMsg *const response); + bool canWait() const; + +private: + void trackPendingRequest(IpcIoPendingRequest *const pending); + void push(IpcIoPendingRequest *const pending); + IpcIoPendingRequest *dequeueRequest(const unsigned int requestId); + + static void Notify(const int peerId); + + static void OpenTimeout(void *const param); + static void CheckTimeouts(void *const param); + void checkTimeouts(); + void scheduleTimeoutCheck(); + + static void HandleResponses(const char *const when); + void handleResponse(IpcIoMsg &ipcIo); + + static void DiskerHandleMoreRequests(void*); + static void DiskerHandleRequests(); + static void DiskerHandleRequest(const int workerId, IpcIoMsg &ipcIo); + static bool WaitBeforePop(); + +private: + const String dbName; ///< the name of the file we are managing + int diskId; ///< the process ID of the disker we talk to + RefCount ioRequestor; + + bool error_; ///< whether we have seen at least one I/O error (XXX) + + unsigned int lastRequestId; ///< last requestId used + + /// maps requestId to the handleResponse callback + typedef std::map RequestMap; + RequestMap requestMap1; ///< older (or newer) pending requests + RequestMap requestMap2; ///< newer (or older) pending requests + RequestMap *olderRequests; ///< older requests (map1 or map2) + RequestMap *newerRequests; ///< newer requests (map2 or map1) + bool timeoutCheckScheduled; ///< we expect a CheckTimeouts() call + + static const double Timeout; ///< timeout value in seconds + + typedef std::list IpcIoFileList; + static IpcIoFileList WaitingForOpen; ///< pending open requests + + ///< maps diskerId to IpcIoFile, cleared in destructor + typedef std::map IpcIoFilesMap; + static IpcIoFilesMap IpcIoFiles; + + typedef Ipc::FewToFewBiQueue Queue; + static std::auto_ptr queue; ///< IPC queue + + /// whether we are waiting for an event to handle still queued I/O requests + static bool DiskerHandleMoreRequestsScheduled; + + CBDATA_CLASS2(IpcIoFile); +}; + + +/// keeps original I/O request parameters while disker is handling the request +class IpcIoPendingRequest +{ +public: + IpcIoPendingRequest(const IpcIoFile::Pointer &aFile); + + /// called when response is received and, with a nil response, on timeouts + void completeIo(IpcIoMsg *const response); + +public: + const IpcIoFile::Pointer file; ///< the file object waiting for the response + ReadRequest *readRequest; ///< set if this is a read requests + WriteRequest *writeRequest; ///< set if this is a write request + +private: + IpcIoPendingRequest(const IpcIoPendingRequest &d); // not implemented + IpcIoPendingRequest &operator =(const IpcIoPendingRequest &d); // ditto +}; + + +#endif /* SQUID_IPC_IOFILE_H */ diff -u -r -N squid-3.2.0.12/src/DiskIO/IpcIo/IpcIoIOStrategy.cc squid-3.2.0.13/src/DiskIO/IpcIo/IpcIoIOStrategy.cc --- squid-3.2.0.12/src/DiskIO/IpcIo/IpcIoIOStrategy.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/DiskIO/IpcIo/IpcIoIOStrategy.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,39 @@ + +/* + * $Id$ + * + * DEBUG: section 47 Store Directory Routines + */ + +#include "config.h" +#include "IpcIoFile.h" +#include "IpcIoIOStrategy.h" + +bool +IpcIoIOStrategy::shedLoad() +{ + return false; +} + +int +IpcIoIOStrategy::load() +{ + /* Return 999 (99.9%) constant load */ + return 999; +} + +DiskFile::Pointer +IpcIoIOStrategy::newFile (char const *path) +{ + return new IpcIoFile (path); +} + +void +IpcIoIOStrategy::unlinkFile(char const *path) +{ +#if USE_UNLINKD + unlinkdUnlink(path); +#else + ::unlink(path); +#endif +} diff -u -r -N squid-3.2.0.12/src/DiskIO/IpcIo/IpcIoIOStrategy.h squid-3.2.0.13/src/DiskIO/IpcIo/IpcIoIOStrategy.h --- squid-3.2.0.12/src/DiskIO/IpcIo/IpcIoIOStrategy.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/DiskIO/IpcIo/IpcIoIOStrategy.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,15 @@ +#ifndef SQUID_IPC_IOIOSTRATEGY_H +#define SQUID_IPC_IOIOSTRATEGY_H +#include "DiskIO/DiskIOStrategy.h" + +class IpcIoIOStrategy : public DiskIOStrategy +{ + +public: + virtual bool shedLoad(); + virtual int load(); + virtual RefCount newFile(char const *path); + virtual void unlinkFile (char const *); +}; + +#endif /* SQUID_IPC_IOIOSTRATEGY_H */ diff -u -r -N squid-3.2.0.12/src/DiskIO/Mmapped/MmappedDiskIOModule.cc squid-3.2.0.13/src/DiskIO/Mmapped/MmappedDiskIOModule.cc --- squid-3.2.0.12/src/DiskIO/Mmapped/MmappedDiskIOModule.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/DiskIO/Mmapped/MmappedDiskIOModule.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,37 @@ +#include "squid.h" +#include "MmappedDiskIOModule.h" +#include "MmappedIOStrategy.h" + +MmappedDiskIOModule::MmappedDiskIOModule() +{ + ModuleAdd(*this); +} + +MmappedDiskIOModule & +MmappedDiskIOModule::GetInstance() +{ + return Instance; +} + +void +MmappedDiskIOModule::init() +{} + +void +MmappedDiskIOModule::shutdown() +{} + + +DiskIOStrategy* +MmappedDiskIOModule::createStrategy() +{ + return new MmappedIOStrategy(); +} + +MmappedDiskIOModule MmappedDiskIOModule::Instance; + +char const * +MmappedDiskIOModule::type () const +{ + return "Mmapped"; +} diff -u -r -N squid-3.2.0.12/src/DiskIO/Mmapped/MmappedDiskIOModule.h squid-3.2.0.13/src/DiskIO/Mmapped/MmappedDiskIOModule.h --- squid-3.2.0.12/src/DiskIO/Mmapped/MmappedDiskIOModule.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/DiskIO/Mmapped/MmappedDiskIOModule.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,21 @@ +#ifndef SQUID_MMAPPEDDISKIOMODULE_H +#define SQUID_MMAPPEDDISKIOMODULE_H + +#include "DiskIO/DiskIOModule.h" + +class MmappedDiskIOModule : public DiskIOModule +{ + +public: + static MmappedDiskIOModule &GetInstance(); + MmappedDiskIOModule(); + virtual void init(); + virtual void shutdown(); + virtual char const *type () const; + virtual DiskIOStrategy* createStrategy(); + +private: + static MmappedDiskIOModule Instance; +}; + +#endif /* SQUID_MMAPPEDDISKIOMODULE_H */ diff -u -r -N squid-3.2.0.12/src/DiskIO/Mmapped/MmappedFile.cc squid-3.2.0.13/src/DiskIO/Mmapped/MmappedFile.cc --- squid-3.2.0.12/src/DiskIO/Mmapped/MmappedFile.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/DiskIO/Mmapped/MmappedFile.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,270 @@ +/* + * $Id$ + * + * DEBUG: section 47 Store Directory Routines + */ + +#include "config.h" +#include "DiskIO/IORequestor.h" +#include "DiskIO/Mmapped/MmappedFile.h" +#include "DiskIO/ReadRequest.h" +#include "DiskIO/WriteRequest.h" +#include + +CBDATA_CLASS_INIT(MmappedFile); + +// helper class to deal with mmap(2) offset alignment and other low-level specs +class Mmapping +{ +public: + Mmapping(int fd, size_t length, int prot, int flags, off_t offset); + ~Mmapping(); + + void *map(); ///< calls mmap(2); returns usable buffer or nil on failure + bool unmap(); ///< unmaps previously mapped buffer, if any + +private: + const int fd; ///< descriptor of the mmapped file + const size_t length; ///< user-requested data length, needed for munmap + const int prot; ///< mmap(2) "protection" flags + const int flags; ///< other mmap(2) flags + const off_t offset; ///< user-requested data offset + + off_t delta; ///< mapped buffer increment to hit user offset + void *buf; ///< buffer returned by mmap, needed for munmap +}; + + +void * +MmappedFile::operator new(size_t sz) +{ + CBDATA_INIT_TYPE(MmappedFile); + MmappedFile *result = cbdataAlloc(MmappedFile); + /* Mark result as being owned - we want the refcounter to do the delete + * call */ + return result; +} + +void +MmappedFile::operator delete(void *address) +{ + MmappedFile *t = static_cast(address); + cbdataFree(t); +} + +MmappedFile::MmappedFile(char const *aPath): fd(-1), + minOffset(0), maxOffset(-1), error_(false) +{ + assert(aPath); + path_ = xstrdup(aPath); + debugs(79,5, HERE << this << ' ' << path_); +} + +MmappedFile::~MmappedFile() +{ + safe_free(path_); + doClose(); +} + +// XXX: almost a copy of BlockingFile::open +void +MmappedFile::open(int flags, mode_t mode, RefCount callback) +{ + assert(fd < 0); + + /* Simulate async calls */ + fd = file_open(path_ , flags); + ioRequestor = callback; + + if (fd < 0) { + debugs(79,3, HERE << "open error: " << xstrerror()); + error_ = true; + } else { + store_open_disk_fd++; + debugs(79,3, HERE << "FD " << fd); + + // setup mapping boundaries + struct stat sb; + if (fstat(fd, &sb) == 0) + maxOffset = sb.st_size; // we do not expect it to change + } + + callback->ioCompletedNotification(); +} + +/** + * Alias for MmappedFile::open(...) + \copydoc MmappedFile::open(int flags, mode_t mode, RefCount callback) + */ +void +MmappedFile::create(int flags, mode_t mode, RefCount callback) +{ + /* We use the same logic path for open */ + open(flags, mode, callback); +} + +void MmappedFile::doClose() +{ + if (fd >= 0) { + file_close(fd); + fd = -1; + store_open_disk_fd--; + } +} + +void +MmappedFile::close() +{ + debugs(79, 3, HERE << this << " closing for " << ioRequestor); + doClose(); + assert(ioRequestor != NULL); + ioRequestor->closeCompleted(); +} + +bool +MmappedFile::canRead() const +{ + return fd >= 0; +} + +bool +MmappedFile::canWrite() const +{ + return fd >= 0; +} + +bool +MmappedFile::error() const +{ + return error_; +} + +void +MmappedFile::read(ReadRequest *aRequest) +{ + debugs(79,3, HERE << "(FD " << fd << ", " << aRequest->len << ", " << + aRequest->offset << ")"); + + assert(fd >= 0); + assert(ioRequestor != NULL); + assert(aRequest->len > 0); // TODO: work around mmap failures on zero-len? + assert(aRequest->offset >= 0); + assert(!error_); // TODO: propagate instead? + + assert(minOffset < 0 || minOffset <= aRequest->offset); + assert(maxOffset < 0 || static_cast(aRequest->offset + aRequest->len) <= static_cast(maxOffset)); + + Mmapping mapping(fd, aRequest->len, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, + aRequest->offset); + + bool done = false; + if (void *buf = mapping.map()) { + memcpy(aRequest->buf, buf, aRequest->len); + done = mapping.unmap(); + } + error_ = !done; + + const ssize_t rlen = error_ ? -1 : (ssize_t)aRequest->len; + const int errflag = error_ ? DISK_ERROR :DISK_OK; + ioRequestor->readCompleted(aRequest->buf, rlen, errflag, aRequest); +} + +void +MmappedFile::write(WriteRequest *aRequest) +{ + debugs(79,3, HERE << "(FD " << fd << ", " << aRequest->len << ", " << + aRequest->offset << ")"); + + assert(fd >= 0); + assert(ioRequestor != NULL); + assert(aRequest->len > 0); // TODO: work around mmap failures on zero-len? + assert(aRequest->offset >= 0); + assert(!error_); // TODO: propagate instead? + + assert(minOffset < 0 || minOffset <= aRequest->offset); + assert(maxOffset < 0 || static_cast(aRequest->offset + aRequest->len) <= static_cast(maxOffset)); + + const ssize_t written = + pwrite(fd, aRequest->buf, aRequest->len, aRequest->offset); + if (written < 0) { + debugs(79,1, HERE << "error: " << xstrerr(errno)); + error_ = true; + } else if (static_cast(written) != aRequest->len) { + debugs(79,1, HERE << "problem: " << written << " < " << aRequest->len); + error_ = true; + } + + if (aRequest->free_func) + (aRequest->free_func)(const_cast(aRequest->buf)); // broken API? + + if (!error_) { + debugs(79,5, HERE << "wrote " << aRequest->len << " to FD " << fd << " at " << aRequest->offset); + } else { + doClose(); + } + + const ssize_t rlen = error_ ? 0 : (ssize_t)aRequest->len; + const int errflag = error_ ? DISK_ERROR :DISK_OK; + ioRequestor->writeCompleted(errflag, rlen, aRequest); +} + +/// we only support blocking I/O +bool +MmappedFile::ioInProgress() const +{ + return false; +} + +Mmapping::Mmapping(int aFd, size_t aLength, int aProt, int aFlags, off_t anOffset): + fd(aFd), length(aLength), prot(aProt), flags(aFlags), offset(anOffset), + delta(-1), buf(NULL) +{ +} + +Mmapping::~Mmapping() +{ + if (buf) + unmap(); +} + +void * +Mmapping::map() +{ + // mmap(2) requires that offset is a multiple of the page size + static const int pageSize = getpagesize(); + delta = offset % pageSize; + + buf = mmap(NULL, length + delta, prot, flags, fd, offset - delta); + + if (buf == MAP_FAILED) { + const int errNo = errno; + debugs(79,3, HERE << "error FD " << fd << "mmap(" << length << '+' << + delta << ", " << offset << '-' << delta << "): " << xstrerr(errNo)); + buf = NULL; + return NULL; + } + + return static_cast(buf) + delta; +} + +bool +Mmapping::unmap() +{ + debugs(79,9, HERE << "FD " << fd << + " munmap(" << buf << ", " << length << '+' << delta << ')'); + + if (!buf) // forgot or failed to map + return false; + + const bool error = munmap(buf, length + delta) != 0; + if (error) { + const int errNo = errno; + debugs(79,3, HERE << "error FD " << fd << + " munmap(" << buf << ", " << length << '+' << delta << "): " << + "): " << xstrerr(errNo)); + } + buf = NULL; + return !error; +} + +// TODO: check MAP_NORESERVE, consider MAP_POPULATE and MAP_FIXED diff -u -r -N squid-3.2.0.12/src/DiskIO/Mmapped/MmappedFile.h squid-3.2.0.13/src/DiskIO/Mmapped/MmappedFile.h --- squid-3.2.0.12/src/DiskIO/Mmapped/MmappedFile.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/DiskIO/Mmapped/MmappedFile.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,46 @@ +#ifndef SQUID_MMAPPEDFILE_H +#define SQUID_MMAPPEDFILE_H + +#include "cbdata.h" +#include "DiskIO/DiskFile.h" +#include "DiskIO/IORequestor.h" + +class MmappedFile : public DiskFile +{ + +public: + void *operator new(size_t); + void operator delete(void *); + MmappedFile(char const *path); + ~MmappedFile(); + virtual void open(int flags, mode_t mode, RefCount callback); + virtual void create(int flags, mode_t mode, RefCount callback); + 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: + CBDATA_CLASS(MmappedFile); + + char const *path_; + RefCount ioRequestor; + //RefCount readRequest; + //RefCount writeRequest; + int fd; + + // mmapped memory leads to SEGV and bus errors if it maps beyond file + int64_t minOffset; ///< enforced if not negative (to preserve file headers) + int64_t maxOffset; ///< enforced if not negative (to avoid crashes) + + bool error_; + + void doClose(); +}; + +#endif /* SQUID_MMAPPEDFILE_H */ diff -u -r -N squid-3.2.0.12/src/DiskIO/Mmapped/MmappedIOStrategy.cc squid-3.2.0.13/src/DiskIO/Mmapped/MmappedIOStrategy.cc --- squid-3.2.0.12/src/DiskIO/Mmapped/MmappedIOStrategy.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/DiskIO/Mmapped/MmappedIOStrategy.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,39 @@ + +/* + * $Id$ + * + * DEBUG: section 47 Store Directory Routines + */ + +#include "config.h" +#include "MmappedFile.h" +#include "MmappedIOStrategy.h" + +bool +MmappedIOStrategy::shedLoad() +{ + return false; +} + +int +MmappedIOStrategy::load() +{ + /* Return 999 (99.9%) constant load */ + return 999; +} + +DiskFile::Pointer +MmappedIOStrategy::newFile (char const *path) +{ + return new MmappedFile (path); +} + +void +MmappedIOStrategy::unlinkFile(char const *path) +{ +#if USE_UNLINKD + unlinkdUnlink(path); +#else + ::unlink(path); +#endif +} diff -u -r -N squid-3.2.0.12/src/DiskIO/Mmapped/MmappedIOStrategy.h squid-3.2.0.13/src/DiskIO/Mmapped/MmappedIOStrategy.h --- squid-3.2.0.12/src/DiskIO/Mmapped/MmappedIOStrategy.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/DiskIO/Mmapped/MmappedIOStrategy.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,15 @@ +#ifndef SQUID_MMAPPEDIOSTRATEGY_H +#define SQUID_MMAPPEDIOSTRATEGY_H +#include "DiskIO/DiskIOStrategy.h" + +class MmappedIOStrategy : public DiskIOStrategy +{ + +public: + virtual bool shedLoad(); + virtual int load(); + virtual RefCount newFile(char const *path); + virtual void unlinkFile (char const *); +}; + +#endif /* SQUID_MMAPPEDIOSTRATEGY_H */ diff -u -r -N squid-3.2.0.12/src/dns.cc squid-3.2.0.13/src/dns.cc --- squid-3.2.0.12/src/dns.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/dns.cc 2011-10-14 14:42:56.000000000 +1300 @@ -74,7 +74,7 @@ if (dnsservers == NULL) dnsservers = new helper("dnsserver"); - dnsservers->childs = Config.dnsChildren; + dnsservers->childs.updateLimits(Config.dnsChildren); dnsservers->ipc_type = IPC_STREAM; diff -u -r -N squid-3.2.0.12/src/dns_internal.cc squid-3.2.0.13/src/dns_internal.cc --- squid-3.2.0.12/src/dns_internal.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/dns_internal.cc 2011-10-14 14:42:56.000000000 +1300 @@ -1217,25 +1217,35 @@ debugs(78, 6, HERE << "Merging DNS results " << q->name << " AAAA has " << q->initial_AAAA.count << " RR, A has " << n << " RR"); + if (Config.dns.v4_first) { + memcpy( tmp, message->answer, (sizeof(rfc1035_rr)*n) ); + tmp += n; + /* free the RR object without freeing its child strings (they are now taken by the copy above) */ + safe_free(message->answer); + } + memcpy(tmp, q->initial_AAAA.answers, (sizeof(rfc1035_rr)*(q->initial_AAAA.count)) ); tmp += q->initial_AAAA.count; /* free the RR object without freeing its child strings (they are now taken by the copy above) */ safe_free(q->initial_AAAA.answers); - memcpy( tmp, message->answer, (sizeof(rfc1035_rr)*n) ); - /* free the RR object without freeing its child strings (they are now taken by the copy above) */ - safe_free(message->answer); + if (!Config.dns.v4_first) { + memcpy( tmp, message->answer, (sizeof(rfc1035_rr)*n) ); + /* free the RR object without freeing its child strings (they are now taken by the copy above) */ + safe_free(message->answer); + } - message->answer = result; - message->ancount += q->initial_AAAA.count; n += q->initial_AAAA.count; - q->initial_AAAA.count=0; + q->initial_AAAA.count = 0; + message->answer = result; + message->ancount = n; } else if (q->initial_AAAA.count > 0 && n <= 0) { /* initial of dual queries was the only result set. */ debugs(78, 6, HERE << "Merging DNS results " << q->name << " AAAA has " << q->initial_AAAA.count << " RR, A has " << n << " RR"); rfc1035RRDestroy(&(message->answer), n); message->answer = q->initial_AAAA.answers; n = q->initial_AAAA.count; + message->ancount = n; } /* else initial results were empty. just use the final set as authoritative */ diff -u -r -N squid-3.2.0.12/src/enums.h squid-3.2.0.13/src/enums.h --- squid-3.2.0.12/src/enums.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/enums.h 2011-10-14 14:42:56.000000000 +1300 @@ -218,7 +218,6 @@ MEM_DLINK_NODE, MEM_DREAD_CTRL, MEM_DWRITE_Q, - MEM_HTTP_HDR_CC, MEM_HTTP_HDR_CONTENT_RANGE, MEM_MD5_DIGEST, MEM_NETDBENTRY, diff -u -r -N squid-3.2.0.12/src/errorpage.cc squid-3.2.0.13/src/errorpage.cc --- squid-3.2.0.12/src/errorpage.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/errorpage.cc 2011-10-14 14:42:56.000000000 +1300 @@ -39,7 +39,9 @@ #include "auth/UserRequest.h" #endif #include "SquidTime.h" +#if USE_SSL #include "ssl/ErrorDetailManager.h" +#endif #include "Store.h" #include "html_quote.h" #include "HttpReply.h" @@ -1136,7 +1138,7 @@ const char *name = errorPageName(page_id); /* no LMT for error pages; error pages expire immediately */ - if (name[0] == '3' || (name[0] != '4' && name[0] != '5' && strchr(name, ':'))) { + if (name[0] == '3' || (name[0] != '2' && name[0] != '4' && name[0] != '5' && strchr(name, ':'))) { /* Redirection */ http_status status = HTTP_MOVED_TEMPORARILY; // Use configured 3xx reply status if set. diff -u -r -N squid-3.2.0.12/src/external_acl.cc squid-3.2.0.13/src/external_acl.cc --- squid-3.2.0.12/src/external_acl.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/external_acl.cc 2011-10-14 14:42:56.000000000 +1300 @@ -1508,7 +1508,7 @@ p->theHelper->cmdline = p->cmdline; - p->theHelper->childs = p->children; + p->theHelper->childs.updateLimits(p->children); p->theHelper->ipc_type = IPC_TCP_SOCKET; diff -u -r -N squid-3.2.0.12/src/forward.cc squid-3.2.0.13/src/forward.cc --- squid-3.2.0.12/src/forward.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/forward.cc 2011-10-14 14:42:56.000000000 +1300 @@ -120,7 +120,7 @@ // Bug 3243: CVE 2009-0801 // Bypass of browser same-origin access control in intercepted communication // To resolve this we must force DIRECT and only to the original client destination. - if (Config.onoff.client_dst_passthru && request && + if (Config.onoff.client_dst_passthru && request && !request->flags.redirected && (request->flags.intercepted || request->flags.spoof_client_ip)) { Comm::ConnectionPointer p = new Comm::Connection(); p->remote = clientConn->local; @@ -146,6 +146,11 @@ flags.forward_completed = 1; + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { + debugs(17, 3, HERE << "entry aborted"); + return ; + } + #if URL_CHECKSUM_DEBUG entry->mem_obj->checkUrlChecksum(); @@ -361,7 +366,6 @@ void FwdState::complete() { - assert(entry->store_status == STORE_PENDING); debugs(17, 3, HERE << entry->url() << "\n\tstatus " << entry->getReply()->sline.status ); #if URL_CHECKSUM_DEBUG @@ -1017,6 +1021,12 @@ { StoreEntry *e = entry; http_status s; + + if (EBIT_TEST(e->flags, ENTRY_ABORTED)) { + debugs(17, 3, HERE << "entry aborted"); + return 0; + } + assert(e->store_status == STORE_PENDING); assert(e->mem_obj); #if URL_CHECKSUM_DEBUG diff -u -r -N squid-3.2.0.12/src/fs/coss/CossSwapDir.h squid-3.2.0.13/src/fs/coss/CossSwapDir.h --- squid-3.2.0.12/src/fs/coss/CossSwapDir.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/fs/coss/CossSwapDir.h 2011-10-14 14:42:56.000000000 +1300 @@ -37,7 +37,7 @@ virtual StoreSearch *search(String const url, HttpRequest *); virtual void unlink (StoreEntry &); virtual void statfs (StoreEntry &)const; - virtual int canStore(StoreEntry const &)const; + virtual bool canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const; virtual int callback(); virtual void sync(); virtual StoreIOState::Pointer createStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *); @@ -48,7 +48,10 @@ virtual void writeCleanDone(); virtual void logEntry(const StoreEntry & e, int op) const; virtual void parse (int index, char *path); - virtual void reconfigure (int, char *); + virtual void reconfigure(); + virtual void swappedOut(const StoreEntry &e); + virtual uint64_t currentSize() const { return cur_size; } + virtual uint64_t currentCount() const { return n_disk_objects; } /* internals */ virtual off_t storeCossFilenoToDiskOffset(sfileno); virtual sfileno storeCossDiskOffsetToFileno(off_t); @@ -76,6 +79,16 @@ CossMemBuf *createMemBuf(off_t start, sfileno curfn, int *collision); sfileno allocate(const StoreEntry * e, int which); void startMembuf(); + StoreEntry *addDiskRestore(const cache_key *const key, + int file_number, + uint64_t swap_file_sz, + time_t expires, + time_t timestamp, + time_t lastref, + time_t lastmod, + uint32_t refcount, + uint16_t flags, + int clean); private: void changeIO(DiskIOModule *module); @@ -88,6 +101,8 @@ const char *ioModule; mutable ConfigOptionVector *currentIOOptions; const char *stripe_path; + uint64_t cur_size; ///< currently used space in the storage area + uint64_t n_disk_objects; ///< total number of objects stored }; /// \ingroup COSS diff -u -r -N squid-3.2.0.12/src/fs/coss/store_coss.h squid-3.2.0.13/src/fs/coss/store_coss.h --- squid-3.2.0.12/src/fs/coss/store_coss.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/fs/coss/store_coss.h 2011-10-14 14:42:56.000000000 +1300 @@ -79,7 +79,7 @@ off_t st_size; void read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data); void write(char const *buf, size_t size, off_t offset, FREE * free_func); - void close(); + virtual void close(int); void doCallback(int errflag); void lockMemBuf(); diff -u -r -N squid-3.2.0.12/src/fs/coss/store_dir_coss.cc squid-3.2.0.13/src/fs/coss/store_dir_coss.cc --- squid-3.2.0.12/src/fs/coss/store_dir_coss.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/fs/coss/store_dir_coss.cc 2011-10-14 14:42:56.000000000 +1300 @@ -49,7 +49,7 @@ #include "StoreFScoss.h" #include "Parsing.h" #include "swap_log_op.h" -//#include "SquidMath.h" +#include "SquidMath.h" #define STORE_META_BUFSZ 4096 @@ -74,16 +74,6 @@ static char *storeCossDirSwapLogFile(SwapDir *, const char *); static EVH storeCossRebuildFromSwapLog; -static StoreEntry *storeCossAddDiskRestore(CossSwapDir * SD, const cache_key * key, - int file_number, - uint64_t swap_file_sz, - time_t expires, - time_t timestamp, - time_t lastref, - time_t lastmod, - uint32_t refcount, - uint16_t flags, - int clean); static void storeCossDirRebuild(CossSwapDir * sd); static void storeCossDirCloseTmpSwapLog(CossSwapDir * sd); static FILE *storeCossDirOpenTmpSwapLog(CossSwapDir *, int *, int *); @@ -358,7 +348,7 @@ CossIndexNode *coss_node = (CossIndexNode *)e->repl.data; e->repl.data = NULL; dlinkDelete(&coss_node->node, &sd->cossindex); - coss_index_pool->free(coss_node); + coss_index_pool->freeOne(coss_node); sd->count -= 1; } @@ -427,9 +417,8 @@ /* * Make sure we don't unlink the file, it might be * in use by a subsequent entry. Also note that - * we don't have to subtract from store_swap_size - * because adding to store_swap_size happens in - * the cleanup procedure. + * we don't have to subtract from cur_size because + * adding to cur_size happens in the cleanup procedure. */ e->expireNow(); e->releaseRequest(); @@ -481,19 +470,18 @@ continue; } - /* update store_swap_size */ rb->counts.objcount++; - e = storeCossAddDiskRestore(rb->sd, s.key, - s.swap_filen, - s.swap_file_sz, - s.expires, - s.timestamp, - s.lastref, - s.lastmod, - s.refcount, - s.flags, - (int) rb->flags.clean); + e = rb->sd->addDiskRestore(s.key, + s.swap_filen, + s.swap_file_sz, + s.expires, + s.timestamp, + s.lastref, + s.lastmod, + s.refcount, + s.flags, + (int) rb->flags.clean); storeDirSwapLog(e, SWAP_LOG_ADD); } @@ -503,17 +491,17 @@ /* Add a new object to the cache with empty memory copy and pointer to disk * use to rebuild store from disk. */ -static StoreEntry * -storeCossAddDiskRestore(CossSwapDir * SD, const cache_key * key, - int file_number, - uint64_t swap_file_sz, - time_t expires, - time_t timestamp, - time_t lastref, - time_t lastmod, - uint32_t refcount, - uint16_t flags, - int clean) +StoreEntry * +CossSwapDir::addDiskRestore(const cache_key *const key, + int file_number, + uint64_t swap_file_sz, + time_t expires, + time_t timestamp, + time_t lastref, + time_t lastmod, + uint32_t refcount, + uint16_t flags, + int clean) { StoreEntry *e = NULL; debugs(47, 5, "storeCossAddDiskRestore: " << storeKeyText(key) << @@ -524,7 +512,7 @@ * already in use! */ e = new StoreEntry(); e->store_status = STORE_OK; - e->swap_dirn = SD->index; + e->swap_dirn = index; e->setMemStatus(NOT_IN_MEMORY); e->swap_status = SWAPOUT_DONE; e->swap_filen = file_number; @@ -541,8 +529,10 @@ EBIT_CLR(e->flags, KEY_PRIVATE); e->ping_status = PING_NONE; EBIT_CLR(e->flags, ENTRY_VALIDATED); + cur_size += fs.blksize * sizeInBlocks(e->swap_file_sz); + ++n_disk_objects; e->hashInsert(key); /* do it after we clear KEY_PRIVATE */ - storeCossAdd(SD, e); + storeCossAdd(this, e); assert(e->swap_filen >= 0); return e; } @@ -925,13 +915,12 @@ swap = open(stripePath(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600); /* TODO just set the file size */ - /* swap size is in K */ - char *block[1024]; + char block[1024]; + Must(maxSize() % sizeof(block) == 0); + memset(block, '\0', sizeof(block)); - memset(&block, '\0', 1024); - - for (off_t offset = 0; offset < max_size; ++offset) { - if (write (swap, block, 1024) < 1024) { + for (uint64_t offset = 0; offset < maxSize(); offset += sizeof(block)) { + if (write (swap, block, sizeof(block)) != sizeof(block)) { debugs (47, 0, "Failed to create COSS swap space in " << path); } } @@ -959,26 +948,14 @@ safe_free(stripe_path); } -/* - * storeCossDirCheckObj - * - * This routine is called by storeDirSelectSwapDir to see if the given - * object is able to be stored on this filesystem. COSS filesystems will - * not store everything. We don't check for maxobjsize here since its - * done by the upper layers. - */ -int -CossSwapDir::canStore(StoreEntry const &e)const +bool +CossSwapDir::canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const { + if (!SwapDir::canStore(e, diskSpaceNeeded, load)) + return false; - /* Check if the object is a special object, we can't cache these */ - - if (EBIT_TEST(e.flags, ENTRY_SPECIAL)) - return -1; - - /* Otherwise, we're ok */ - /* Return load, cs->aq.aq_numpending out of MAX_ASYNCOP */ - return io->load(); + load = io->load(); + return true; } /* @@ -996,10 +973,10 @@ CossSwapDir::statfs(StoreEntry & sentry) const { storeAppendPrintf(&sentry, "\n"); - storeAppendPrintf(&sentry, "Maximum Size: %lu KB\n", max_size); - storeAppendPrintf(&sentry, "Current Size: %lu KB\n", cur_size); + storeAppendPrintf(&sentry, "Maximum Size: %"PRIu64" KB\n", maxSize() >> 10); + storeAppendPrintf(&sentry, "Current Size: %.2f KB\n", currentSize() / 1024.0); storeAppendPrintf(&sentry, "Percent Used: %0.2f%%\n", - (100.0 * (double)cur_size / (double)max_size) ); + Math::doublePercent(currentSize(), maxSize()) ); storeAppendPrintf(&sentry, "Number of object collisions: %d\n", (int) numcollisions); #if 0 /* is this applicable? I Hope not .. */ @@ -1023,21 +1000,15 @@ void CossSwapDir::parse(int anIndex, char *aPath) { - unsigned int i; - unsigned int size; - off_t max_offset; - - i = GetInteger(); - size = i << 10; /* Mbytes to Kbytes */ - - if (size <= 0) + const int i = GetInteger(); + if (i <= 0) fatal("storeCossDirParse: invalid size value"); index = anIndex; path = xstrdup(aPath); - max_size = size; + max_size = static_cast(i) << 20; // MBytes to Bytes parseOptions(0); @@ -1052,38 +1023,31 @@ fatalf("COSS max-size option must be less than COSS_MEMBUF_SZ (%d)\n", COSS_MEMBUF_SZ); - /* - * check that we won't overflow sfileno later. 0xFFFFFF is the - * largest possible sfileno, assuming sfileno is a 25-bit - * signed integer, as defined in structs.h. - */ - max_offset = (off_t) 0xFFFFFF << blksz_bits; + // check that we won't overflow sfileno later. + const uint64_t max_offset = (uint64_t)SwapFilenMax << blksz_bits; - if ((off_t)max_size > (max_offset>>10)) { + if (maxSize() > max_offset) { debugs(47, 0, "COSS block-size = " << (1<(i) << 20; // MBytes to Bytes + + if (size == maxSize()) + debugs(3, 1, "Cache COSS dir '" << path << "' size remains unchanged at " << i << " MB"); else { - debugs(3, 1, "Cache COSS dir '" << path << "' size changed to " << size << " KB"); + debugs(3, 1, "Cache COSS dir '" << path << "' size changed to " << i << " MB"); max_size = size; } @@ -1093,13 +1057,20 @@ } void +CossSwapDir::swappedOut(const StoreEntry &e) +{ + cur_size += fs.blksize * sizeInBlocks(e.swap_file_sz); + ++n_disk_objects; +} + +void CossSwapDir::dump(StoreEntry &entry)const { - storeAppendPrintf(&entry, " %lu", (max_size >> 10)); + storeAppendPrintf(&entry, " %"PRIu64, maxSize() >> 20); dumpOptions(&entry); } -CossSwapDir::CossSwapDir() : SwapDir ("coss"), swaplog_fd(-1), count(0), current_membuf (NULL), current_offset(0), numcollisions(0), blksz_bits(0), io (NULL), ioModule(NULL), currentIOOptions(new ConfigOptionVector()), stripe_path(NULL) +CossSwapDir::CossSwapDir() : SwapDir ("coss"), swaplog_fd(-1), count(0), current_membuf (NULL), current_offset(0), numcollisions(0), blksz_bits(0), io (NULL), ioModule(NULL), currentIOOptions(new ConfigOptionVector()), stripe_path(NULL), cur_size(0), n_disk_objects(0) { membufs.head = NULL; membufs.tail = NULL; diff -u -r -N squid-3.2.0.12/src/fs/coss/store_io_coss.cc squid-3.2.0.13/src/fs/coss/store_io_coss.cc --- squid-3.2.0.12/src/fs/coss/store_io_coss.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/fs/coss/store_io_coss.cc 2011-10-14 14:42:56.000000000 +1300 @@ -83,8 +83,7 @@ allocsize = e->objectLen() + e->mem_obj->swap_hdr_sz; /* Check if we have overflowed the disk .. */ - /* max_size is int, so cast to (off_t) *before* bit-shifting */ - if ((current_offset + allocsize) > ((off_t)max_size << 10)) { + if (current_offset + allocsize > static_cast(maxSize())) { /* * tried to allocate past the end of the disk, so wrap * back to the beginning @@ -134,6 +133,10 @@ CossSwapDir::unlink(StoreEntry & e) { debugs(79, 3, "storeCossUnlink: offset " << e.swap_filen); + if (e.swap_status == SWAPOUT_DONE && EBIT_TEST(e.flags, ENTRY_VALIDATED)) { + cur_size -= fs.blksize * sizeInBlocks(e.swap_file_sz); + --n_disk_objects; + } StoreFScoss::GetInstance().stats.unlink.ops++; StoreFScoss::GetInstance().stats.unlink.success++; storeCossRemove(this, &e); @@ -275,8 +278,9 @@ return sio; } +/// COSS does not distinguish different closure types void -CossState::close() +CossState::close(int) { debugs(79, 3, "storeCossClose: offset " << swap_filen); diff -u -r -N squid-3.2.0.12/src/fs/Makefile.am squid-3.2.0.13/src/fs/Makefile.am --- squid-3.2.0.12/src/fs/Makefile.am 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/fs/Makefile.am 2011-10-14 14:42:56.000000000 +1300 @@ -1,6 +1,6 @@ include $(top_srcdir)/src/Common.am -EXTRA_LTLIBRARIES = libaufs.la libdiskd.la libcoss.la libufs.la +EXTRA_LTLIBRARIES = libaufs.la libdiskd.la libcoss.la libufs.la librock.la noinst_LTLIBRARIES = $(STORE_LIBS_TO_BUILD) libfs.la # aufs is a "fake" legacy store @@ -28,6 +28,19 @@ ufs/ufscommon.cc \ ufs/ufscommon.h +librock_la_SOURCES = \ + rock/RockDbCell.h \ + rock/RockIoState.cc \ + rock/RockIoState.h \ + rock/RockIoRequests.cc \ + rock/RockIoRequests.h \ + rock/RockRebuild.cc \ + rock/RockRebuild.h \ + rock/RockStoreFileSystem.cc \ + rock/RockStoreFileSystem.h \ + rock/RockSwapDir.cc \ + rock/RockSwapDir.h + libfs_la_SOURCES = Module.cc Module.h libfs_la_LIBADD = $(STORE_LIBS_TO_BUILD) libfs_la_DEPENDENCIES = $(STORE_LIBS_TO_BUILD) @@ -44,13 +57,15 @@ coss/clean: clean ufs/all: libufs.la ufs/clean: clean +rock/all: librock.la +rock/clean: clean TESTS += testHeaders ## Special Universal .h dependency test script ## aborts if error encountered -testHeaders: $(srcdir)/ufs/*.h $(srcdir)/coss/*.h +testHeaders: $(srcdir)/ufs/*.h $(srcdir)/coss/*.h $(srcdir)/rock/*.h $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" $^ || exit 1 ## diskd/ has no .h files ## aufs/ has no .h files diff -u -r -N squid-3.2.0.12/src/fs/Makefile.in squid-3.2.0.13/src/fs/Makefile.in --- squid-3.2.0.12/src/fs/Makefile.in 2011-09-16 23:38:19.000000000 +1200 +++ squid-3.2.0.13/src/fs/Makefile.in 2011-10-14 14:48:07.000000000 +1300 @@ -68,6 +68,10 @@ am__DEPENDENCIES_1 = am_libfs_la_OBJECTS = Module.lo libfs_la_OBJECTS = $(am_libfs_la_OBJECTS) +librock_la_LIBADD = +am_librock_la_OBJECTS = RockIoState.lo RockIoRequests.lo \ + RockRebuild.lo RockStoreFileSystem.lo RockSwapDir.lo +librock_la_OBJECTS = $(am_librock_la_OBJECTS) libufs_la_LIBADD = am_libufs_la_OBJECTS = StoreFSufs.lo store_dir_ufs.lo store_io_ufs.lo \ ufscommon.lo @@ -96,10 +100,10 @@ $(LDFLAGS) -o $@ SOURCES = $(libaufs_la_SOURCES) $(libcoss_la_SOURCES) \ $(libdiskd_la_SOURCES) $(libfs_la_SOURCES) \ - $(libufs_la_SOURCES) + $(librock_la_SOURCES) $(libufs_la_SOURCES) DIST_SOURCES = $(libaufs_la_SOURCES) $(libcoss_la_SOURCES) \ $(libdiskd_la_SOURCES) $(libfs_la_SOURCES) \ - $(libufs_la_SOURCES) + $(librock_la_SOURCES) $(libufs_la_SOURCES) ETAGS = etags CTAGS = ctags am__tty_colors = \ @@ -325,7 +329,7 @@ @ENABLE_XPROF_STATS_TRUE@LIBPROFILER = $(top_builddir)/lib/profiler/libprofiler.la COMPAT_LIB = -L$(top_builddir)/compat -lcompat-squid $(LIBPROFILER) subst_perlshell = sed -e 's,[@]PERL[@],$(PERL),g' <$(srcdir)/$@.pl.in >$@ || ($(RM) -f $@ ; exit 1) -EXTRA_LTLIBRARIES = libaufs.la libdiskd.la libcoss.la libufs.la +EXTRA_LTLIBRARIES = libaufs.la libdiskd.la libcoss.la libufs.la librock.la noinst_LTLIBRARIES = $(STORE_LIBS_TO_BUILD) libfs.la # aufs is a "fake" legacy store @@ -354,6 +358,19 @@ ufs/ufscommon.cc \ ufs/ufscommon.h +librock_la_SOURCES = \ + rock/RockDbCell.h \ + rock/RockIoState.cc \ + rock/RockIoState.h \ + rock/RockIoRequests.cc \ + rock/RockIoRequests.h \ + rock/RockRebuild.cc \ + rock/RockRebuild.h \ + rock/RockStoreFileSystem.cc \ + rock/RockStoreFileSystem.h \ + rock/RockSwapDir.cc \ + rock/RockSwapDir.h + libfs_la_SOURCES = Module.cc Module.h libfs_la_LIBADD = $(STORE_LIBS_TO_BUILD) libfs_la_DEPENDENCIES = $(STORE_LIBS_TO_BUILD) @@ -411,6 +428,8 @@ $(CXXLINK) $(libdiskd_la_OBJECTS) $(libdiskd_la_LIBADD) $(LIBS) libfs.la: $(libfs_la_OBJECTS) $(libfs_la_DEPENDENCIES) $(CXXLINK) $(libfs_la_OBJECTS) $(libfs_la_LIBADD) $(LIBS) +librock.la: $(librock_la_OBJECTS) $(librock_la_DEPENDENCIES) + $(CXXLINK) $(librock_la_OBJECTS) $(librock_la_LIBADD) $(LIBS) libufs.la: $(libufs_la_OBJECTS) $(libufs_la_DEPENDENCIES) $(CXXLINK) $(libufs_la_OBJECTS) $(libufs_la_LIBADD) $(LIBS) @@ -430,6 +449,11 @@ -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Module.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RockIoRequests.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RockIoState.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RockRebuild.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RockStoreFileSystem.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RockSwapDir.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StoreFSaufs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StoreFScoss.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StoreFSdiskd.Plo@am__quote@ @@ -496,6 +520,41 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o StoreFSdiskd.lo `test -f 'diskd/StoreFSdiskd.cc' || echo '$(srcdir)/'`diskd/StoreFSdiskd.cc +RockIoState.lo: rock/RockIoState.cc +@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT RockIoState.lo -MD -MP -MF $(DEPDIR)/RockIoState.Tpo -c -o RockIoState.lo `test -f 'rock/RockIoState.cc' || echo '$(srcdir)/'`rock/RockIoState.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/RockIoState.Tpo $(DEPDIR)/RockIoState.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='rock/RockIoState.cc' object='RockIoState.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o RockIoState.lo `test -f 'rock/RockIoState.cc' || echo '$(srcdir)/'`rock/RockIoState.cc + +RockIoRequests.lo: rock/RockIoRequests.cc +@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT RockIoRequests.lo -MD -MP -MF $(DEPDIR)/RockIoRequests.Tpo -c -o RockIoRequests.lo `test -f 'rock/RockIoRequests.cc' || echo '$(srcdir)/'`rock/RockIoRequests.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/RockIoRequests.Tpo $(DEPDIR)/RockIoRequests.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='rock/RockIoRequests.cc' object='RockIoRequests.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o RockIoRequests.lo `test -f 'rock/RockIoRequests.cc' || echo '$(srcdir)/'`rock/RockIoRequests.cc + +RockRebuild.lo: rock/RockRebuild.cc +@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT RockRebuild.lo -MD -MP -MF $(DEPDIR)/RockRebuild.Tpo -c -o RockRebuild.lo `test -f 'rock/RockRebuild.cc' || echo '$(srcdir)/'`rock/RockRebuild.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/RockRebuild.Tpo $(DEPDIR)/RockRebuild.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='rock/RockRebuild.cc' object='RockRebuild.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o RockRebuild.lo `test -f 'rock/RockRebuild.cc' || echo '$(srcdir)/'`rock/RockRebuild.cc + +RockStoreFileSystem.lo: rock/RockStoreFileSystem.cc +@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT RockStoreFileSystem.lo -MD -MP -MF $(DEPDIR)/RockStoreFileSystem.Tpo -c -o RockStoreFileSystem.lo `test -f 'rock/RockStoreFileSystem.cc' || echo '$(srcdir)/'`rock/RockStoreFileSystem.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/RockStoreFileSystem.Tpo $(DEPDIR)/RockStoreFileSystem.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='rock/RockStoreFileSystem.cc' object='RockStoreFileSystem.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o RockStoreFileSystem.lo `test -f 'rock/RockStoreFileSystem.cc' || echo '$(srcdir)/'`rock/RockStoreFileSystem.cc + +RockSwapDir.lo: rock/RockSwapDir.cc +@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT RockSwapDir.lo -MD -MP -MF $(DEPDIR)/RockSwapDir.Tpo -c -o RockSwapDir.lo `test -f 'rock/RockSwapDir.cc' || echo '$(srcdir)/'`rock/RockSwapDir.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/RockSwapDir.Tpo $(DEPDIR)/RockSwapDir.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='rock/RockSwapDir.cc' object='RockSwapDir.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o RockSwapDir.lo `test -f 'rock/RockSwapDir.cc' || echo '$(srcdir)/'`rock/RockSwapDir.cc + StoreFSufs.lo: ufs/StoreFSufs.cc @am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT StoreFSufs.lo -MD -MP -MF $(DEPDIR)/StoreFSufs.Tpo -c -o StoreFSufs.lo `test -f 'ufs/StoreFSufs.cc' || echo '$(srcdir)/'`ufs/StoreFSufs.cc @am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/StoreFSufs.Tpo $(DEPDIR)/StoreFSufs.Plo @@ -830,8 +889,10 @@ coss/clean: clean ufs/all: libufs.la ufs/clean: clean +rock/all: librock.la +rock/clean: clean -testHeaders: $(srcdir)/ufs/*.h $(srcdir)/coss/*.h +testHeaders: $(srcdir)/ufs/*.h $(srcdir)/coss/*.h $(srcdir)/rock/*.h $(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" $^ || exit 1 .PHONY: testHeaders diff -u -r -N squid-3.2.0.12/src/fs/Module.cc squid-3.2.0.13/src/fs/Module.cc --- squid-3.2.0.12/src/fs/Module.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/fs/Module.cc 2011-10-14 14:42:56.000000000 +1300 @@ -22,6 +22,12 @@ static StoreFSufs *DiskdInstance; #endif +#if HAVE_FS_ROCK +#include "fs/rock/RockStoreFileSystem.h" +static Rock::StoreFileSystem *RockInstance = NULL; +#endif + + /* TODO: Modify coss code to: * (a) remove the StoreFScoss::GetInstance method, * (b) declare the StoreFScoss::stats as static and @@ -48,6 +54,10 @@ DiskdInstance = new StoreFSufs("DiskDaemon", "diskd");; #endif +#if HAVE_FS_ROCK + RockInstance = new Rock::StoreFileSystem(); +#endif + } @@ -66,4 +76,8 @@ delete DiskdInstance; #endif +#if HAVE_FS_ROCK + delete RockInstance; +#endif + } diff -u -r -N squid-3.2.0.12/src/fs/rock/RockDbCell.h squid-3.2.0.13/src/fs/rock/RockDbCell.h --- squid-3.2.0.12/src/fs/rock/RockDbCell.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/fs/rock/RockDbCell.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,25 @@ +#ifndef SQUID_FS_ROCK_DB_CELL_H +#define SQUID_FS_ROCK_DB_CELL_H + +namespace Rock +{ + +/** \ingroup Rock + * Meta-information at the beginning of every db cell. + * Stored on disk and used as sizeof() argument so it must remain POD. + */ +class DbCellHeader +{ +public: + DbCellHeader(): payloadSize(0), reserved(0) {} + + /// whether the freshly loaded header fields make sense + bool sane() const { return payloadSize >= 0 && reserved == 0; } + + int64_t payloadSize; ///< cell contents size excluding this header + int64_t reserved; ///< reserved for future use (next cell pointer?) +}; + +} // namespace Rock + +#endif /* SQUID_FS_ROCK_DB_CELL_H */ diff -u -r -N squid-3.2.0.12/src/fs/rock/RockIoRequests.cc squid-3.2.0.13/src/fs/rock/RockIoRequests.cc --- squid-3.2.0.12/src/fs/rock/RockIoRequests.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/fs/rock/RockIoRequests.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,25 @@ +/* + * $Id$ + * + * DEBUG: section 79 Disk IO Routines + */ + +#include "config.h" +#include "fs/rock/RockIoRequests.h" + +CBDATA_NAMESPACED_CLASS_INIT(Rock, ReadRequest); +CBDATA_NAMESPACED_CLASS_INIT(Rock, WriteRequest); + +Rock::ReadRequest::ReadRequest(const ::ReadRequest &base, + const IoState::Pointer &anSio): + ::ReadRequest(base), + sio(anSio) +{ +} + +Rock::WriteRequest::WriteRequest(const ::WriteRequest &base, + const IoState::Pointer &anSio): + ::WriteRequest(base), + sio(anSio) +{ +} diff -u -r -N squid-3.2.0.12/src/fs/rock/RockIoRequests.h squid-3.2.0.13/src/fs/rock/RockIoRequests.h --- squid-3.2.0.12/src/fs/rock/RockIoRequests.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/fs/rock/RockIoRequests.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,39 @@ +#ifndef SQUID_FS_ROCK_IO_REQUESTS_H +#define SQUID_FS_ROCK_IO_REQUESTS_H + +#include "DiskIO/ReadRequest.h" +#include "DiskIO/WriteRequest.h" +#include "fs/rock/RockIoState.h" + +class DiskFile; + +namespace Rock +{ + +/// \ingroup Rock +class ReadRequest: public ::ReadRequest +{ +public: + ReadRequest(const ::ReadRequest &base, const IoState::Pointer &anSio); + IoState::Pointer sio; + +private: + CBDATA_CLASS2(ReadRequest); +}; + + +/// \ingroup Rock +class WriteRequest: public ::WriteRequest +{ +public: + WriteRequest(const ::WriteRequest &base, const IoState::Pointer &anSio); + IoState::Pointer sio; + +private: + CBDATA_CLASS2(WriteRequest); +}; + + +} // namespace Rock + +#endif /* SQUID_FS_ROCK_IO_REQUESTS_H */ diff -u -r -N squid-3.2.0.12/src/fs/rock/RockIoState.cc squid-3.2.0.13/src/fs/rock/RockIoState.cc --- squid-3.2.0.12/src/fs/rock/RockIoState.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/fs/rock/RockIoState.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,210 @@ +/* + * $Id$ + * + * DEBUG: section 79 Disk IO Routines + */ + +#include "config.h" +#include "MemObject.h" +#include "Parsing.h" +#include "DiskIO/DiskIOModule.h" +#include "DiskIO/DiskIOStrategy.h" +#include "DiskIO/WriteRequest.h" +#include "fs/rock/RockIoState.h" +#include "fs/rock/RockIoRequests.h" +#include "fs/rock/RockSwapDir.h" + +Rock::IoState::IoState(SwapDir *dir, + StoreEntry *anEntry, + StoreIOState::STFNCB *cbFile, + StoreIOState::STIOCB *cbIo, + void *data): + slotSize(0), + diskOffset(-1), + payloadEnd(-1) +{ + e = anEntry; + // swap_filen, swap_dirn, diskOffset, and payloadEnd are set by the caller + slotSize = dir->max_objsize; + file_callback = cbFile; + callback = cbIo; + callback_data = cbdataReference(data); + ++store_open_disk_fd; // TODO: use a dedicated counter? + //theFile is set by SwapDir because it depends on DiskIOStrategy +} + +Rock::IoState::~IoState() +{ + --store_open_disk_fd; + if (callback_data) + cbdataReferenceDone(callback_data); + theFile = NULL; +} + +void +Rock::IoState::file(const RefCount &aFile) +{ + assert(!theFile); + assert(aFile != NULL); + theFile = aFile; +} + +void +Rock::IoState::read_(char *buf, size_t len, off_t coreOff, STRCB *cb, void *data) +{ + assert(theFile != NULL); + assert(coreOff >= 0); + offset_ = coreOff; + + // we skip our cell header; it is only read when building the map + const int64_t cellOffset = sizeof(DbCellHeader) + + static_cast(coreOff); + assert(cellOffset <= payloadEnd); + + // Core specifies buffer length, but we must not exceed stored entry size + if (cellOffset + (int64_t)len > payloadEnd) + len = payloadEnd - cellOffset; + + assert(read.callback == NULL); + assert(read.callback_data == NULL); + read.callback = cb; + read.callback_data = cbdataReference(data); + + theFile->read(new ReadRequest( + ::ReadRequest(buf, diskOffset + cellOffset, len), this)); +} + +// We only buffer data here; we actually write when close() is called. +// We buffer, in part, to avoid forcing OS to _read_ old unwritten portions +// of the slot when the write does not end at the page or sector boundary. +void +Rock::IoState::write(char const *buf, size_t size, off_t coreOff, FREE *dtor) +{ + // TODO: move to create? + if (!coreOff) { + assert(theBuf.isNull()); + assert(payloadEnd <= slotSize); + theBuf.init(min(payloadEnd, slotSize), slotSize); + // start with our header; TODO: consider making it a trailer + DbCellHeader header; + assert(static_cast(sizeof(header)) <= payloadEnd); + header.payloadSize = payloadEnd - sizeof(header); + theBuf.append(reinterpret_cast(&header), sizeof(header)); + } else { + // Core uses -1 offset as "append". Sigh. + assert(coreOff == -1); + assert(!theBuf.isNull()); + } + + theBuf.append(buf, size); + offset_ += size; // so that Core thinks we wrote it + + if (dtor) + (dtor)(const_cast(buf)); // cast due to a broken API? +} + +// write what was buffered during write() calls +void +Rock::IoState::startWriting() +{ + assert(theFile != NULL); + assert(!theBuf.isNull()); + + // TODO: if DiskIO module is mmap-based, we should be writing whole pages + // to avoid triggering read-page;new_head+old_tail;write-page overheads + + debugs(79, 5, HERE << swap_filen << " at " << diskOffset << '+' << + theBuf.contentSize()); + + assert(theBuf.contentSize() <= slotSize); + // theFile->write may call writeCompleted immediatelly + theFile->write(new WriteRequest(::WriteRequest(theBuf.content(), + diskOffset, theBuf.contentSize(), theBuf.freeFunc()), this)); +} + +// +void +Rock::IoState::finishedWriting(const int errFlag) +{ + // we incremented offset_ while accumulating data in write() + callBack(errFlag); +} + +void +Rock::IoState::close(int how) +{ + debugs(79, 3, HERE << swap_filen << " accumulated: " << offset_ << + " how=" << how); + if (how == wroteAll && !theBuf.isNull()) + startWriting(); + else + callBack(how == writerGone ? DISK_ERROR : 0); // TODO: add DISK_CALLER_GONE +} + +/// close callback (STIOCB) dialer: breaks dependencies and +/// counts IOState concurrency level +class StoreIOStateCb: public CallDialer +{ +public: + StoreIOStateCb(StoreIOState::STIOCB *cb, void *data, int err, const Rock::IoState::Pointer &anSio): + callback(NULL), + callback_data(NULL), + errflag(err), + sio(anSio) { + + callback = cb; + callback_data = cbdataReference(data); + } + + StoreIOStateCb(const StoreIOStateCb &cb): + callback(NULL), + callback_data(NULL), + errflag(cb.errflag), + sio(cb.sio) { + + callback = cb.callback; + callback_data = cbdataReference(cb.callback_data); + } + + virtual ~StoreIOStateCb() { + cbdataReferenceDone(callback_data); // may be nil already + } + + void dial(AsyncCall &call) { + void *cbd; + if (cbdataReferenceValidDone(callback_data, &cbd) && callback) + callback(cbd, errflag, sio.getRaw()); + } + + bool canDial(AsyncCall &call) const { + return cbdataReferenceValid(callback_data) && callback; + } + + virtual void print(std::ostream &os) const { + os << '(' << callback_data << ", err=" << errflag << ')'; + } + +private: + StoreIOStateCb &operator =(const StoreIOStateCb &cb); // not defined + + StoreIOState::STIOCB *callback; + void *callback_data; + int errflag; + Rock::IoState::Pointer sio; +}; + + +void +Rock::IoState::callBack(int errflag) +{ + debugs(79,3, HERE << "errflag=" << errflag); + theFile = NULL; + + AsyncCall::Pointer call = asyncCall(79,3, "SomeIoStateCloseCb", + StoreIOStateCb(callback, callback_data, errflag, this)); + ScheduleCallHere(call); + + callback = NULL; + cbdataReferenceDone(callback_data); +} + diff -u -r -N squid-3.2.0.12/src/fs/rock/RockIoState.h squid-3.2.0.13/src/fs/rock/RockIoState.h --- squid-3.2.0.12/src/fs/rock/RockIoState.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/fs/rock/RockIoState.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,54 @@ +#ifndef SQUID_FS_ROCK_IO_STATE_H +#define SQUID_FS_ROCK_IO_STATE_H + +#include "MemBuf.h" +#include "SwapDir.h" + +class DiskFile; + +namespace Rock +{ + +class SwapDir; + +/// \ingroup Rock +class IoState: public ::StoreIOState +{ +public: + typedef RefCount Pointer; + + IoState(SwapDir *dir, StoreEntry *e, StoreIOState::STFNCB *cbFile, StoreIOState::STIOCB *cbIo, void *data); + virtual ~IoState(); + + void file(const RefCount &aFile); + + // ::StoreIOState API + virtual void read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data); + virtual void write(char const *buf, size_t size, off_t offset, FREE * free_func); + virtual void close(int how); + + /// called by SwapDir when writing is done + void finishedWriting(int errFlag); + + int64_t slotSize; ///< db cell size + int64_t diskOffset; ///< the start of this cell inside the db file + + /// when reading: number of bytes previously written to the db cell; + /// when writing: maximum payload offset in a db cell + int64_t payloadEnd; + + MEMPROXY_CLASS(IoState); + +private: + void startWriting(); + void callBack(int errflag); + + RefCount theFile; // "file" responsible for this I/O + MemBuf theBuf; // use for write content accumulation only +}; + +MEMPROXY_CLASS_INLINE(IoState); + +} // namespace Rock + +#endif /* SQUID_FS_ROCK_IO_STATE_H */ diff -u -r -N squid-3.2.0.12/src/fs/rock/RockRebuild.cc squid-3.2.0.13/src/fs/rock/RockRebuild.cc --- squid-3.2.0.12/src/fs/rock/RockRebuild.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/fs/rock/RockRebuild.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,202 @@ +/* + * $Id$ + * + * DEBUG: section 79 Disk IO Routines + */ + +#include "config.h" +#include "fs/rock/RockRebuild.h" +#include "fs/rock/RockSwapDir.h" +#include "fs/rock/RockDbCell.h" +#include "SquidTime.h" + +CBDATA_NAMESPACED_CLASS_INIT(Rock, Rebuild); + +Rock::Rebuild::Rebuild(SwapDir *dir): AsyncJob("Rock::Rebuild"), + sd(dir), + dbSize(0), + dbEntrySize(0), + dbEntryLimit(0), + fd(-1), + dbOffset(0), + filen(0) +{ + assert(sd); + memset(&counts, 0, sizeof(counts)); + dbSize = sd->diskOffsetLimit(); // we do not care about the trailer waste + dbEntrySize = sd->max_objsize; + dbEntryLimit = sd->entryLimit(); +} + +Rock::Rebuild::~Rebuild() +{ + if (fd >= 0) + file_close(fd); +} + +/// prepares and initiates entry loading sequence +void +Rock::Rebuild::start() +{ + // in SMP mode, only the disker is responsible for populating the map + if (UsingSmp() && !IamDiskProcess()) { + debugs(47, 2, "Non-disker skips rebuilding of cache_dir #" << + sd->index << " from " << sd->filePath); + mustStop("non-disker"); + return; + } + + debugs(47, DBG_IMPORTANT, "Loading cache_dir #" << sd->index << + " from " << sd->filePath); + + fd = file_open(sd->filePath, O_RDONLY | O_BINARY); + if (fd < 0) + failure("cannot open db", errno); + + char buf[SwapDir::HeaderSize]; + if (read(fd, buf, sizeof(buf)) != SwapDir::HeaderSize) + failure("cannot read db header", errno); + + dbOffset = SwapDir::HeaderSize; + filen = 0; + + checkpoint(); +} + +/// continues after a pause if not done +void +Rock::Rebuild::checkpoint() +{ + if (!done()) + eventAdd("Rock::Rebuild", Rock::Rebuild::Steps, this, 0.01, 1, true); +} + +bool +Rock::Rebuild::doneAll() const +{ + return dbOffset >= dbSize && AsyncJob::doneAll(); +} + +void +Rock::Rebuild::Steps(void *data) +{ + // use async call to enable job call protection that time events lack + CallJobHere(47, 5, static_cast(data), Rock::Rebuild, steps); +} + +void +Rock::Rebuild::steps() +{ + debugs(47,5, HERE << sd->index << " filen " << filen << " at " << + dbOffset << " <= " << dbSize); + + // Balance our desire to maximize the number of entries processed at once + // (and, hence, minimize overheads and total rebuild time) with a + // requirement to also process Coordinator events, disk I/Os, etc. + const int maxSpentMsec = 50; // keep small: most RAM I/Os are under 1ms + const timeval loopStart = current_time; + + int loaded = 0; + while (loaded < dbEntryLimit && dbOffset < dbSize) { + doOneEntry(); + dbOffset += dbEntrySize; + ++filen; + ++loaded; + + if (counts.scancount % 1000 == 0) + storeRebuildProgress(sd->index, dbEntryLimit, counts.scancount); + + if (opt_foreground_rebuild) + continue; // skip "few entries at a time" check below + + getCurrentTime(); + const double elapsedMsec = tvSubMsec(loopStart, current_time); + if (elapsedMsec > maxSpentMsec || elapsedMsec < 0) { + debugs(47, 5, HERE << "pausing after " << loaded << " entries in " << + elapsedMsec << "ms; " << (elapsedMsec/loaded) << "ms per entry"); + break; + } + } + + checkpoint(); +} + +void +Rock::Rebuild::doOneEntry() +{ + debugs(47,5, HERE << sd->index << " filen " << filen << " at " << + dbOffset << " <= " << dbSize); + + ++counts.scancount; + + if (lseek(fd, dbOffset, SEEK_SET) < 0) + failure("cannot seek to db entry", errno); + + MemBuf buf; + buf.init(SM_PAGE_SIZE, SM_PAGE_SIZE); + + if (!storeRebuildLoadEntry(fd, sd->index, buf, counts)) + return; + + // get our header + DbCellHeader header; + if (buf.contentSize() < static_cast(sizeof(header))) { + debugs(47, DBG_IMPORTANT, "WARNING: cache_dir[" << sd->index << "]: " << + "Ignoring truncated cache entry meta data at " << dbOffset); + counts.invalid++; + return; + } + memcpy(&header, buf.content(), sizeof(header)); + + if (!header.sane()) { + debugs(47, DBG_IMPORTANT, "WARNING: cache_dir[" << sd->index << "]: " << + "Ignoring malformed cache entry meta data at " << dbOffset); + counts.invalid++; + return; + } + buf.consume(sizeof(header)); // optimize to avoid memmove() + + cache_key key[SQUID_MD5_DIGEST_LENGTH]; + StoreEntry loadedE; + if (!storeRebuildParseEntry(buf, loadedE, key, counts, header.payloadSize)) { + // skip empty slots + if (loadedE.swap_filen > 0 || loadedE.swap_file_sz > 0) { + counts.invalid++; + //sd->unlink(filen); leave garbage on disk, it should not hurt + } + return; + } + + assert(loadedE.swap_filen < dbEntryLimit); + if (!storeRebuildKeepEntry(loadedE, key, counts)) + return; + + counts.objcount++; + // loadedE->dump(5); + + sd->addEntry(filen, header, loadedE); +} + +void +Rock::Rebuild::swanSong() +{ + debugs(47,3, HERE << "cache_dir #" << sd->index << " rebuild level: " << + StoreController::store_dirs_rebuilding); + --StoreController::store_dirs_rebuilding; + storeRebuildComplete(&counts); +} + +void +Rock::Rebuild::failure(const char *msg, int errNo) +{ + debugs(47,5, HERE << sd->index << " filen " << filen << " at " << + dbOffset << " <= " << dbSize); + + if (errNo) + debugs(47, DBG_CRITICAL, "ERROR: Rock cache_dir rebuild failure: " << xstrerr(errNo)); + debugs(47, DBG_CRITICAL, "Do you need to run 'squid -z' to initialize storage?"); + + assert(sd); + fatalf("Rock cache_dir[%d] rebuild of %s failed: %s.", + sd->index, sd->filePath, msg); +} diff -u -r -N squid-3.2.0.12/src/fs/rock/RockRebuild.h squid-3.2.0.13/src/fs/rock/RockRebuild.h --- squid-3.2.0.12/src/fs/rock/RockRebuild.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/fs/rock/RockRebuild.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,51 @@ +#ifndef SQUID_FS_ROCK_REBUILD_H +#define SQUID_FS_ROCK_REBUILD_H + +#include "base/AsyncJob.h" +#include "structs.h" + +namespace Rock +{ + +class SwapDir; + +/// \ingroup Rock +/// manages store rebuild process: loading meta information from db on disk +class Rebuild: public AsyncJob +{ +public: + Rebuild(SwapDir *dir); + ~Rebuild(); + +protected: + /* AsyncJob API */ + virtual void start(); + virtual bool doneAll() const; + virtual void swanSong(); + +private: + void checkpoint(); + void steps(); + void doOneEntry(); + void failure(const char *msg, int errNo = 0); + + SwapDir *sd; + + int64_t dbSize; + int dbEntrySize; + int dbEntryLimit; + + int fd; // store db file descriptor + int64_t dbOffset; + int filen; + + struct _store_rebuild_data counts; + + static void Steps(void *data); + + CBDATA_CLASS2(Rebuild); +}; + +} // namespace Rock + +#endif /* SQUID_FS_ROCK_REBUILD_H */ diff -u -r -N squid-3.2.0.12/src/fs/rock/RockStoreFileSystem.cc squid-3.2.0.13/src/fs/rock/RockStoreFileSystem.cc --- squid-3.2.0.12/src/fs/rock/RockStoreFileSystem.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/fs/rock/RockStoreFileSystem.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,54 @@ +/* + * $Id$ + * + * DEBUG: section 92 Storage File System + */ + +#include "config.h" +#include "fs/rock/RockStoreFileSystem.h" +#include "fs/rock/RockSwapDir.h" + + +Rock::StoreFileSystem::StoreFileSystem() +{ + FsAdd(*this); +} + +Rock::StoreFileSystem::~StoreFileSystem() +{ +} + +char const * +Rock::StoreFileSystem::type() const +{ + return "rock"; +} + +SwapDir * +Rock::StoreFileSystem::createSwapDir() +{ + return new SwapDir(); +} + +void +Rock::StoreFileSystem::done() +{ +} + +void +Rock::StoreFileSystem::registerWithCacheManager() +{ + assert(false); // XXX: implement +} + +void +Rock::StoreFileSystem::setup() +{ + debugs(92,2, HERE << "Will use Rock FS"); +} + +void +Rock::StoreFileSystem::Stats(StoreEntry *sentry) +{ + assert(false); // XXX: implement +} diff -u -r -N squid-3.2.0.12/src/fs/rock/RockStoreFileSystem.h squid-3.2.0.13/src/fs/rock/RockStoreFileSystem.h --- squid-3.2.0.12/src/fs/rock/RockStoreFileSystem.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/fs/rock/RockStoreFileSystem.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,34 @@ +#ifndef SQUID_FS_ROCK_FS_H +#define SQUID_FS_ROCK_FS_H + +#include "StoreFileSystem.h" + +namespace Rock +{ + +/// \ingroup Rock, FileSystems +class StoreFileSystem: public ::StoreFileSystem +{ + +public: + static void Stats(StoreEntry * sentry); + + StoreFileSystem(); + virtual ~StoreFileSystem(); + + virtual char const *type() const; + virtual SwapDir *createSwapDir(); + virtual void done(); + virtual void registerWithCacheManager(); + virtual void setup(); + +private: + //static Stats Stats_; + + StoreFileSystem(const StoreFileSystem &); // not implemented + StoreFileSystem &operator=(const StoreFileSystem &); // not implemented +}; + +} // namespace Rock + +#endif /* SQUID_FS_ROCK_FS_H */ diff -u -r -N squid-3.2.0.12/src/fs/rock/RockSwapDir.cc squid-3.2.0.13/src/fs/rock/RockSwapDir.cc --- squid-3.2.0.12/src/fs/rock/RockSwapDir.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/fs/rock/RockSwapDir.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,847 @@ +/* + * $Id$ + * + * DEBUG: section 47 Store Directory Routines + */ + +#include "config.h" +#include "base/RunnersRegistry.h" +#include "ConfigOption.h" +#include "DiskIO/DiskIOModule.h" +#include "DiskIO/DiskIOStrategy.h" +#include "DiskIO/ReadRequest.h" +#include "DiskIO/WriteRequest.h" +#include "fs/rock/RockSwapDir.h" +#include "fs/rock/RockIoState.h" +#include "fs/rock/RockIoRequests.h" +#include "fs/rock/RockRebuild.h" +#include "ipc/mem/Pages.h" +#include "MemObject.h" +#include "Parsing.h" +#include "SquidMath.h" +#include + +const int64_t Rock::SwapDir::HeaderSize = 16*1024; + +Rock::SwapDir::SwapDir(): ::SwapDir("rock"), filePath(NULL), io(NULL), map(NULL) +{ +} + +Rock::SwapDir::~SwapDir() +{ + delete io; + delete map; + safe_free(filePath); +} + +StoreSearch * +Rock::SwapDir::search(String const url, HttpRequest *) +{ + assert(false); + return NULL; // XXX: implement +} + +void +Rock::SwapDir::get(String const key, STOREGETCLIENT cb, void *data) +{ + ::SwapDir::get(key, cb, data); +} + +// called when Squid core needs a StoreEntry with a given key +StoreEntry * +Rock::SwapDir::get(const cache_key *key) +{ + if (!map || !theFile || !theFile->canRead()) + return NULL; + + sfileno filen; + const Ipc::StoreMapSlot *const slot = map->openForReading(key, filen); + if (!slot) + return NULL; + + const Ipc::StoreMapSlot::Basics &basics = slot->basics; + + // create a brand new store entry and initialize it with stored basics + StoreEntry *e = new StoreEntry(); + e->lock_count = 0; + e->swap_dirn = index; + e->swap_filen = filen; + e->swap_file_sz = basics.swap_file_sz; + e->lastref = basics.lastref; + e->timestamp = basics.timestamp; + e->expires = basics.expires; + e->lastmod = basics.lastmod; + e->refcount = basics.refcount; + e->flags = basics.flags; + e->store_status = STORE_OK; + e->setMemStatus(NOT_IN_MEMORY); + e->swap_status = SWAPOUT_DONE; + e->ping_status = PING_NONE; + EBIT_SET(e->flags, ENTRY_CACHABLE); + EBIT_CLR(e->flags, RELEASE_REQUEST); + EBIT_CLR(e->flags, KEY_PRIVATE); + EBIT_SET(e->flags, ENTRY_VALIDATED); + e->hashInsert(key); + trackReferences(*e); + + return e; + // the disk entry remains open for reading, protected from modifications +} + +void Rock::SwapDir::disconnect(StoreEntry &e) +{ + assert(e.swap_dirn == index); + assert(e.swap_filen >= 0); + // cannot have SWAPOUT_NONE entry with swap_filen >= 0 + assert(e.swap_status != SWAPOUT_NONE); + + // do not rely on e.swap_status here because there is an async delay + // before it switches from SWAPOUT_WRITING to SWAPOUT_DONE. + + // since e has swap_filen, its slot is locked for either reading or writing + map->abortIo(e.swap_filen); + e.swap_dirn = -1; + e.swap_filen = -1; + e.swap_status = SWAPOUT_NONE; +} + +uint64_t +Rock::SwapDir::currentSize() const +{ + return HeaderSize + max_objsize * currentCount(); +} + +uint64_t +Rock::SwapDir::currentCount() const +{ + return map ? map->entryCount() : 0; +} + +/// In SMP mode only the disker process reports stats to avoid +/// counting the same stats by multiple processes. +bool +Rock::SwapDir::doReportStat() const +{ + return ::SwapDir::doReportStat() && (!UsingSmp() || IamDiskProcess()); +} + +void +Rock::SwapDir::swappedOut(const StoreEntry &) +{ + // stats are not stored but computed when needed +} + +int64_t +Rock::SwapDir::entryLimitAllowed() const +{ + const int64_t eLimitLo = map ? map->entryLimit() : 0; // dynamic shrinking unsupported + const int64_t eWanted = (maxSize() - HeaderSize)/maxObjectSize(); + return min(max(eLimitLo, eWanted), entryLimitHigh()); +} + +// TODO: encapsulate as a tool; identical to CossSwapDir::create() +void +Rock::SwapDir::create() +{ + assert(path); + assert(filePath); + + if (UsingSmp() && !IamDiskProcess()) { + debugs (47,3, HERE << "disker will create in " << path); + return; + } + + debugs (47,3, HERE << "creating in " << path); + + struct stat swap_sb; + if (::stat(path, &swap_sb) < 0) { + debugs (47, DBG_IMPORTANT, "Creating Rock db directory: " << path); + const int res = mkdir(path, 0700); + if (res != 0) { + debugs(47, DBG_CRITICAL, "Failed to create Rock db dir " << path << + ": " << xstrerror()); + fatal("Rock Store db creation error"); + } + } + +#if SLOWLY_FILL_WITH_ZEROS + char block[1024]; + Must(maxSize() % sizeof(block) == 0); + memset(block, '\0', sizeof(block)); + + const int swap = open(filePath, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600); + for (off_t offset = 0; offset < maxSize(); offset += sizeof(block)) { + if (write(swap, block, sizeof(block)) != sizeof(block)) { + debugs(47, DBG_CRITICAL, "ERROR: Failed to create Rock Store db in " << filePath << + ": " << xstrerror()); + fatal("Rock Store db creation error"); + } + } + close(swap); +#else + const int swap = open(filePath, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600); + if (swap < 0) { + debugs(47, DBG_CRITICAL, "ERROR: Failed to initialize Rock Store db in " << filePath << + "; create error: " << xstrerror()); + fatal("Rock Store db creation error"); + } + + if (ftruncate(swap, maxSize()) != 0) { + debugs(47, DBG_CRITICAL, "ERROR: Failed to initialize Rock Store db in " << filePath << + "; truncate error: " << xstrerror()); + fatal("Rock Store db creation error"); + } + + char header[HeaderSize]; + memset(header, '\0', sizeof(header)); + if (write(swap, header, sizeof(header)) != sizeof(header)) { + debugs(47, DBG_CRITICAL, "ERROR: Failed to initialize Rock Store db in " << filePath << + "; write error: " << xstrerror()); + fatal("Rock Store db initialization error"); + } + close(swap); +#endif +} + +void +Rock::SwapDir::init() +{ + debugs(47,2, HERE); + + // XXX: SwapDirs aren't refcounted. We make IORequestor calls, which + // are refcounted. We up our count once to avoid implicit delete's. + RefCountReference(); + + Must(!map); + map = new DirMap(path); + + const char *ioModule = needsDiskStrand() ? "IpcIo" : "Blocking"; + if (DiskIOModule *m = DiskIOModule::Find(ioModule)) { + debugs(47,2, HERE << "Using DiskIO module: " << ioModule); + io = m->createStrategy(); + io->init(); + } else { + debugs(47, DBG_CRITICAL, "FATAL: Rock store is missing DiskIO module: " << + ioModule); + fatal("Rock Store missing a required DiskIO module"); + } + + theFile = io->newFile(filePath); + theFile->configure(fileConfig); + theFile->open(O_RDWR, 0644, this); + + // Increment early. Otherwise, if one SwapDir finishes rebuild before + // others start, storeRebuildComplete() will think the rebuild is over! + // TODO: move store_dirs_rebuilding hack to store modules that need it. + ++StoreController::store_dirs_rebuilding; +} + +bool +Rock::SwapDir::needsDiskStrand() const +{ + const bool wontEvenWorkWithoutDisker = Config.workers > 1; + const bool wouldWorkBetterWithDisker = DiskIOModule::Find("IpcIo"); + return InDaemonMode() && (wontEvenWorkWithoutDisker || + wouldWorkBetterWithDisker); +} + +void +Rock::SwapDir::parse(int anIndex, char *aPath) +{ + index = anIndex; + + path = xstrdup(aPath); + + // cache store is located at path/db + String fname(path); + fname.append("/rock"); + filePath = xstrdup(fname.termedBuf()); + + parseSize(false); + parseOptions(0); + + // Current openForWriting() code overwrites the old slot if needed + // and possible, so proactively removing old slots is probably useless. + assert(!repl); // repl = createRemovalPolicy(Config.replPolicy); + + validateOptions(); +} + +void +Rock::SwapDir::reconfigure() +{ + parseSize(true); + parseOptions(1); + // TODO: can we reconfigure the replacement policy (repl)? + validateOptions(); +} + +/// parse maximum db disk size +void +Rock::SwapDir::parseSize(const bool reconfiguring) +{ + const int i = GetInteger(); + if (i < 0) + fatal("negative Rock cache_dir size value"); + const uint64_t new_max_size = + static_cast(i) << 20; // MBytes to Bytes + if (!reconfiguring) + max_size = new_max_size; + else if (new_max_size != max_size) { + debugs(3, DBG_IMPORTANT, "WARNING: cache_dir '" << path << "' size " + "cannot be changed dynamically, value left unchanged (" << + (max_size >> 20) << " MB)"); + } +} + +ConfigOption * +Rock::SwapDir::getOptionTree() const +{ + ConfigOptionVector *vector = dynamic_cast(::SwapDir::getOptionTree()); + assert(vector); + vector->options.push_back(new ConfigOptionAdapter(*const_cast(this), &SwapDir::parseTimeOption, &SwapDir::dumpTimeOption)); + vector->options.push_back(new ConfigOptionAdapter(*const_cast(this), &SwapDir::parseRateOption, &SwapDir::dumpRateOption)); + return vector; +} + +bool +Rock::SwapDir::allowOptionReconfigure(const char *const option) const +{ + return strcmp(option, "max-size") != 0 && + ::SwapDir::allowOptionReconfigure(option); +} + +/// parses time-specific options; mimics ::SwapDir::optionObjectSizeParse() +bool +Rock::SwapDir::parseTimeOption(char const *option, const char *value, int reconfiguring) +{ + // TODO: ::SwapDir or, better, Config should provide time-parsing routines, + // including time unit handling. Same for size. + + time_msec_t *storedTime; + if (strcmp(option, "swap-timeout") == 0) + storedTime = &fileConfig.ioTimeout; + else + return false; + + if (!value) + self_destruct(); + + // TODO: handle time units and detect parsing errors better + const int64_t parsedValue = strtoll(value, NULL, 10); + if (parsedValue < 0) { + debugs(3, DBG_CRITICAL, "FATAL: cache_dir " << path << ' ' << option << " must not be negative but is: " << parsedValue); + self_destruct(); + } + + const time_msec_t newTime = static_cast(parsedValue); + + if (reconfiguring && *storedTime != newTime) + debugs(3, DBG_IMPORTANT, "cache_dir " << path << ' ' << option << " is now " << newTime); + + *storedTime = newTime; + + return true; +} + +/// reports time-specific options; mimics ::SwapDir::optionObjectSizeDump() +void +Rock::SwapDir::dumpTimeOption(StoreEntry * e) const +{ + if (fileConfig.ioTimeout) + storeAppendPrintf(e, " swap-timeout=%"PRId64, + static_cast(fileConfig.ioTimeout)); +} + +/// parses rate-specific options; mimics ::SwapDir::optionObjectSizeParse() +bool +Rock::SwapDir::parseRateOption(char const *option, const char *value, int isaReconfig) +{ + int *storedRate; + if (strcmp(option, "max-swap-rate") == 0) + storedRate = &fileConfig.ioRate; + else + return false; + + if (!value) + self_destruct(); + + // TODO: handle time units and detect parsing errors better + const int64_t parsedValue = strtoll(value, NULL, 10); + if (parsedValue < 0) { + debugs(3, DBG_CRITICAL, "FATAL: cache_dir " << path << ' ' << option << " must not be negative but is: " << parsedValue); + self_destruct(); + } + + const int newRate = static_cast(parsedValue); + + if (newRate < 0) { + debugs(3, DBG_CRITICAL, "FATAL: cache_dir " << path << ' ' << option << " must not be negative but is: " << newRate); + self_destruct(); + } + + if (isaReconfig && *storedRate != newRate) + debugs(3, DBG_IMPORTANT, "cache_dir " << path << ' ' << option << " is now " << newRate); + + *storedRate = newRate; + + return true; +} + +/// reports rate-specific options; mimics ::SwapDir::optionObjectSizeDump() +void +Rock::SwapDir::dumpRateOption(StoreEntry * e) const +{ + if (fileConfig.ioRate >= 0) + storeAppendPrintf(e, " max-swap-rate=%d", fileConfig.ioRate); +} + +/// check the results of the configuration; only level-0 debugging works here +void +Rock::SwapDir::validateOptions() +{ + if (max_objsize <= 0) + fatal("Rock store requires a positive max-size"); + + const int64_t maxSizeRoundingWaste = 1024 * 1024; // size is configured in MB + const int64_t maxObjectSizeRoundingWaste = maxObjectSize(); + const int64_t maxRoundingWaste = + max(maxSizeRoundingWaste, maxObjectSizeRoundingWaste); + const int64_t usableDiskSize = diskOffset(entryLimitAllowed()); + const int64_t diskWasteSize = maxSize() - usableDiskSize; + Must(diskWasteSize >= 0); + + // warn if maximum db size is not reachable due to sfileno limit + if (entryLimitAllowed() == entryLimitHigh() && + diskWasteSize >= maxRoundingWaste) { + debugs(47, DBG_CRITICAL, "Rock store cache_dir[" << index << "] '" << path << "':"); + debugs(47, DBG_CRITICAL, "\tmaximum number of entries: " << entryLimitAllowed()); + debugs(47, DBG_CRITICAL, "\tmaximum object size: " << maxObjectSize() << " Bytes"); + debugs(47, DBG_CRITICAL, "\tmaximum db size: " << maxSize() << " Bytes"); + debugs(47, DBG_CRITICAL, "\tusable db size: " << usableDiskSize << " Bytes"); + debugs(47, DBG_CRITICAL, "\tdisk space waste: " << diskWasteSize << " Bytes"); + debugs(47, DBG_CRITICAL, "WARNING: Rock store config wastes space."); + } +} + +void +Rock::SwapDir::rebuild() +{ + //++StoreController::store_dirs_rebuilding; // see Rock::SwapDir::init() + AsyncJob::Start(new Rebuild(this)); +} + +/* Add a new object to the cache with empty memory copy and pointer to disk + * use to rebuild store from disk. Based on UFSSwapDir::addDiskRestore */ +bool +Rock::SwapDir::addEntry(const int filen, const DbCellHeader &header, const StoreEntry &from) +{ + debugs(47, 8, HERE << &from << ' ' << from.getMD5Text() << + ", filen="<< std::setfill('0') << std::hex << std::uppercase << + std::setw(8) << filen); + + sfileno newLocation = 0; + if (Ipc::StoreMapSlot *slot = map->openForWriting(reinterpret_cast(from.key), newLocation)) { + if (filen == newLocation) { + slot->set(from); + map->extras(filen) = header; + } // else some other, newer entry got into our cell + map->closeForWriting(newLocation, false); + return filen == newLocation; + } + + return false; +} + + +bool +Rock::SwapDir::canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const +{ + if (!::SwapDir::canStore(e, sizeof(DbCellHeader)+diskSpaceNeeded, load)) + return false; + + if (!theFile || !theFile->canWrite()) + return false; + + if (!map) + return false; + + // Do not start I/O transaction if there are less than 10% free pages left. + // TODO: reserve page instead + if (needsDiskStrand() && + Ipc::Mem::PageLevel(Ipc::Mem::PageId::ioPage) >= 0.9 * Ipc::Mem::PageLimit(Ipc::Mem::PageId::ioPage)) { + debugs(47, 5, HERE << "too few shared pages for IPC I/O left"); + return false; + } + + if (io->shedLoad()) + return false; + + load = io->load(); + return true; +} + +StoreIOState::Pointer +Rock::SwapDir::createStoreIO(StoreEntry &e, StoreIOState::STFNCB *cbFile, StoreIOState::STIOCB *cbIo, void *data) +{ + if (!theFile || theFile->error()) { + debugs(47,4, HERE << theFile); + return NULL; + } + + // compute payload size for our cell header, using StoreEntry info + // careful: e.objectLen() may still be negative here + const int64_t expectedReplySize = e.mem_obj->expectedReplySize(); + assert(expectedReplySize >= 0); // must know to prevent cell overflows + assert(e.mem_obj->swap_hdr_sz > 0); + DbCellHeader header; + header.payloadSize = e.mem_obj->swap_hdr_sz + expectedReplySize; + const int64_t payloadEnd = sizeof(DbCellHeader) + header.payloadSize; + assert(payloadEnd <= max_objsize); + + sfileno filen; + Ipc::StoreMapSlot *const slot = + map->openForWriting(reinterpret_cast(e.key), filen); + if (!slot) { + debugs(47, 5, HERE << "map->add failed"); + return NULL; + } + e.swap_file_sz = header.payloadSize; // and will be copied to the map + slot->set(e); + map->extras(filen) = header; + + // XXX: We rely on our caller, storeSwapOutStart(), to set e.fileno. + // If that does not happen, the entry will not decrement the read level! + + IoState *sio = new IoState(this, &e, cbFile, cbIo, data); + + sio->swap_dirn = index; + sio->swap_filen = filen; + sio->payloadEnd = payloadEnd; + sio->diskOffset = diskOffset(sio->swap_filen); + + debugs(47,5, HERE << "dir " << index << " created new filen " << + std::setfill('0') << std::hex << std::uppercase << std::setw(8) << + sio->swap_filen << std::dec << " at " << sio->diskOffset); + + assert(sio->diskOffset + payloadEnd <= diskOffsetLimit()); + + sio->file(theFile); + + trackReferences(e); + return sio; +} + +int64_t +Rock::SwapDir::diskOffset(int filen) const +{ + assert(filen >= 0); + return HeaderSize + max_objsize*filen; +} + +int64_t +Rock::SwapDir::diskOffsetLimit() const +{ + assert(map); + return diskOffset(map->entryLimit()); +} + +// tries to open an old or being-written-to entry with swap_filen for reading +StoreIOState::Pointer +Rock::SwapDir::openStoreIO(StoreEntry &e, StoreIOState::STFNCB *cbFile, StoreIOState::STIOCB *cbIo, void *data) +{ + if (!theFile || theFile->error()) { + debugs(47,4, HERE << theFile); + return NULL; + } + + if (e.swap_filen < 0) { + debugs(47,4, HERE << e); + return NULL; + } + + // Do not start I/O transaction if there are less than 10% free pages left. + // TODO: reserve page instead + if (needsDiskStrand() && + Ipc::Mem::PageLevel(Ipc::Mem::PageId::ioPage) >= 0.9 * Ipc::Mem::PageLimit(Ipc::Mem::PageId::ioPage)) { + debugs(47, 5, HERE << "too few shared pages for IPC I/O left"); + return NULL; + } + + // The are two ways an entry can get swap_filen: our get() locked it for + // reading or our storeSwapOutStart() locked it for writing. Peeking at our + // locked entry is safe, but no support for reading a filling entry. + const Ipc::StoreMapSlot *slot = map->peekAtReader(e.swap_filen); + if (!slot) + return NULL; // we were writing afterall + + IoState *sio = new IoState(this, &e, cbFile, cbIo, data); + + sio->swap_dirn = index; + sio->swap_filen = e.swap_filen; + sio->payloadEnd = sizeof(DbCellHeader) + map->extras(e.swap_filen).payloadSize; + assert(sio->payloadEnd <= max_objsize); // the payload fits the slot + + debugs(47,5, HERE << "dir " << index << " has old filen: " << + std::setfill('0') << std::hex << std::uppercase << std::setw(8) << + sio->swap_filen); + + assert(slot->basics.swap_file_sz > 0); + assert(slot->basics.swap_file_sz == e.swap_file_sz); + + sio->diskOffset = diskOffset(sio->swap_filen); + assert(sio->diskOffset + sio->payloadEnd <= diskOffsetLimit()); + + sio->file(theFile); + return sio; +} + +void +Rock::SwapDir::ioCompletedNotification() +{ + if (!theFile) + fatalf("Rock cache_dir failed to initialize db file: %s", filePath); + + if (theFile->error()) + fatalf("Rock cache_dir at %s failed to open db file: %s", filePath, + xstrerror()); + + debugs(47, 2, "Rock cache_dir[" << index << "] limits: " << + std::setw(12) << maxSize() << " disk bytes and " << + std::setw(7) << map->entryLimit() << " entries"); + + rebuild(); +} + +void +Rock::SwapDir::closeCompleted() +{ + theFile = NULL; +} + +void +Rock::SwapDir::readCompleted(const char *buf, int rlen, int errflag, RefCount< ::ReadRequest> r) +{ + ReadRequest *request = dynamic_cast(r.getRaw()); + assert(request); + IoState::Pointer sio = request->sio; + + if (errflag == DISK_OK && rlen > 0) + sio->offset_ += rlen; + assert(sio->diskOffset + sio->offset_ <= diskOffsetLimit()); // post-factum + + StoreIOState::STRCB *callback = sio->read.callback; + assert(callback); + sio->read.callback = NULL; + void *cbdata; + if (cbdataReferenceValidDone(sio->read.callback_data, &cbdata)) + callback(cbdata, r->buf, rlen, sio.getRaw()); +} + +void +Rock::SwapDir::writeCompleted(int errflag, size_t rlen, RefCount< ::WriteRequest> r) +{ + Rock::WriteRequest *request = dynamic_cast(r.getRaw()); + assert(request); + assert(request->sio != NULL); + IoState &sio = *request->sio; + + if (errflag == DISK_OK) { + // close, assuming we only write once; the entry gets the read lock + map->closeForWriting(sio.swap_filen, true); + // do not increment sio.offset_ because we do it in sio->write() + } else { + // Do not abortWriting here. The entry should keep the write lock + // instead of losing association with the store and confusing core. + map->free(sio.swap_filen); // will mark as unusable, just in case + } + + assert(sio.diskOffset + sio.offset_ <= diskOffsetLimit()); // post-factum + + sio.finishedWriting(errflag); +} + +bool +Rock::SwapDir::full() const +{ + return map && map->full(); +} + +// storeSwapOutFileClosed calls this nethod on DISK_NO_SPACE_LEFT, +// but it should not happen for us +void +Rock::SwapDir::diskFull() +{ + debugs(20, DBG_IMPORTANT, "BUG: No space left with rock cache_dir: " << + filePath); +} + +/// purge while full(); it should be sufficient to purge just one +void +Rock::SwapDir::maintain() +{ + debugs(47,3, HERE << "cache_dir[" << index << "] guards: " << + !repl << !map << !full() << StoreController::store_dirs_rebuilding); + + if (!repl) + return; // no means (cannot find a victim) + + if (!map) + return; // no victims (yet) + + if (!full()) + return; // no need (to find a victim) + + // XXX: UFSSwapDir::maintain says we must quit during rebuild + if (StoreController::store_dirs_rebuilding) + return; + + debugs(47,3, HERE << "cache_dir[" << index << "] state: " << map->full() << + ' ' << currentSize() << " < " << diskOffsetLimit()); + + // Hopefully, we find a removable entry much sooner (TODO: use time?) + const int maxProbed = 10000; + RemovalPurgeWalker *walker = repl->PurgeInit(repl, maxProbed); + + // It really should not take that long, but this will stop "infinite" loops + const int maxFreed = 1000; + int freed = 0; + // TODO: should we purge more than needed to minimize overheads? + for (; freed < maxFreed && full(); ++freed) { + if (StoreEntry *e = walker->Next(walker)) + e->release(); // will call our unlink() method + else + break; // no more objects + } + + debugs(47,2, HERE << "Rock cache_dir[" << index << "] freed " << freed << + " scanned " << walker->scanned << '/' << walker->locked); + + walker->Done(walker); + + if (full()) { + debugs(47, DBG_CRITICAL, "ERROR: Rock cache_dir[" << index << "] " << + "is still full after freeing " << freed << " entries. A bug?"); + } +} + +void +Rock::SwapDir::reference(StoreEntry &e) +{ + debugs(47, 5, HERE << &e << ' ' << e.swap_dirn << ' ' << e.swap_filen); + if (repl && repl->Referenced) + repl->Referenced(repl, &e, &e.repl); +} + +bool +Rock::SwapDir::dereference(StoreEntry &e) +{ + debugs(47, 5, HERE << &e << ' ' << e.swap_dirn << ' ' << e.swap_filen); + if (repl && repl->Dereferenced) + repl->Dereferenced(repl, &e, &e.repl); + + // no need to keep e in the global store_table for us; we have our own map + return false; +} + +void +Rock::SwapDir::unlink(StoreEntry &e) +{ + debugs(47, 5, HERE << e); + ignoreReferences(e); + map->free(e.swap_filen); + disconnect(e); +} + +void +Rock::SwapDir::trackReferences(StoreEntry &e) +{ + debugs(47, 5, HERE << e); + if (repl) + repl->Add(repl, &e, &e.repl); +} + + +void +Rock::SwapDir::ignoreReferences(StoreEntry &e) +{ + debugs(47, 5, HERE << e); + if (repl) + repl->Remove(repl, &e, &e.repl); +} + +void +Rock::SwapDir::statfs(StoreEntry &e) const +{ + storeAppendPrintf(&e, "\n"); + storeAppendPrintf(&e, "Maximum Size: %"PRIu64" KB\n", maxSize() >> 10); + storeAppendPrintf(&e, "Current Size: %.2f KB %.2f%%\n", + currentSize() / 1024.0, + Math::doublePercent(currentSize(), maxSize())); + + if (map) { + const int limit = map->entryLimit(); + storeAppendPrintf(&e, "Maximum entries: %9d\n", limit); + if (limit > 0) { + const int entryCount = map->entryCount(); + storeAppendPrintf(&e, "Current entries: %9d %.2f%%\n", + entryCount, (100.0 * entryCount / limit)); + + if (limit < 100) { // XXX: otherwise too expensive to count + Ipc::ReadWriteLockStats stats; + map->updateStats(stats); + stats.dump(e); + } + } + } + + storeAppendPrintf(&e, "Pending operations: %d out of %d\n", + store_open_disk_fd, Config.max_open_disk_fds); + + storeAppendPrintf(&e, "Flags:"); + + if (flags.selected) + storeAppendPrintf(&e, " SELECTED"); + + if (flags.read_only) + storeAppendPrintf(&e, " READ-ONLY"); + + storeAppendPrintf(&e, "\n"); + +} + + +/// initializes shared memory segments used by Rock::SwapDir +class RockSwapDirRr: public Ipc::Mem::RegisteredRunner +{ +public: + /* RegisteredRunner API */ + virtual ~RockSwapDirRr(); + +protected: + virtual void create(const RunnerRegistry &); + +private: + Vector owners; +}; + +RunnerRegistrationEntry(rrAfterConfig, RockSwapDirRr); + + +void RockSwapDirRr::create(const RunnerRegistry &) +{ + Must(owners.empty()); + for (int i = 0; i < Config.cacheSwap.n_configured; ++i) { + if (const Rock::SwapDir *const sd = dynamic_cast(INDEXSD(i))) { + Rock::SwapDir::DirMap::Owner *const owner = + Rock::SwapDir::DirMap::Init(sd->path, sd->entryLimitAllowed()); + owners.push_back(owner); + } + } +} + +RockSwapDirRr::~RockSwapDirRr() +{ + for (size_t i = 0; i < owners.size(); ++i) + delete owners[i]; +} diff -u -r -N squid-3.2.0.12/src/fs/rock/RockSwapDir.h squid-3.2.0.13/src/fs/rock/RockSwapDir.h --- squid-3.2.0.12/src/fs/rock/RockSwapDir.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/fs/rock/RockSwapDir.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,101 @@ +#ifndef SQUID_FS_ROCK_SWAP_DIR_H +#define SQUID_FS_ROCK_SWAP_DIR_H + +#include "SwapDir.h" +#include "DiskIO/DiskFile.h" +#include "DiskIO/IORequestor.h" +#include "fs/rock/RockDbCell.h" +#include "ipc/StoreMap.h" + +class DiskIOStrategy; +class ReadRequest; +class WriteRequest; + +namespace Rock +{ + +class Rebuild; + +/// \ingroup Rock +class SwapDir: public ::SwapDir, public IORequestor +{ +public: + SwapDir(); + virtual ~SwapDir(); + + /* public ::SwapDir API */ + virtual void reconfigure(); + virtual StoreSearch *search(String const url, HttpRequest *); + virtual StoreEntry *get(const cache_key *key); + virtual void get(String const, STOREGETCLIENT, void * cbdata); + virtual void disconnect(StoreEntry &e); + virtual uint64_t currentSize() const; + virtual uint64_t currentCount() const; + virtual bool doReportStat() const; + virtual void swappedOut(const StoreEntry &e); + + int64_t entryLimitHigh() const { return SwapFilenMax; } ///< Core limit + int64_t entryLimitAllowed() const; + + typedef Ipc::StoreMapWithExtras DirMap; + +protected: + /* protected ::SwapDir API */ + virtual bool needsDiskStrand() const; + virtual void create(); + virtual void init(); + virtual ConfigOption *getOptionTree() const; + virtual bool allowOptionReconfigure(const char *const option) const; + virtual bool canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const; + virtual StoreIOState::Pointer createStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *); + virtual StoreIOState::Pointer openStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *); + virtual void maintain(); + virtual void diskFull(); + virtual void reference(StoreEntry &e); + virtual bool dereference(StoreEntry &e); + virtual void unlink(StoreEntry &e); + virtual void statfs(StoreEntry &e) const; + + /* IORequestor API */ + virtual void ioCompletedNotification(); + virtual void closeCompleted(); + virtual void readCompleted(const char *buf, int len, int errflag, RefCount< ::ReadRequest>); + virtual void writeCompleted(int errflag, size_t len, RefCount< ::WriteRequest>); + + virtual void parse(int index, char *path); + void parseSize(const bool reconfiguring); ///< parses anonymous cache_dir size option + void validateOptions(); ///< warns of configuration problems; may quit + bool parseTimeOption(char const *option, const char *value, int reconfiguring); + void dumpTimeOption(StoreEntry * e) const; + bool parseRateOption(char const *option, const char *value, int reconfiguring); + void dumpRateOption(StoreEntry * e) const; + + void rebuild(); ///< starts loading and validating stored entry metadata + ///< used to add entries successfully loaded during rebuild + bool addEntry(const int fileno, const DbCellHeader &header, const StoreEntry &from); + + bool full() const; ///< no more entries can be stored without purging + void trackReferences(StoreEntry &e); ///< add to replacement policy scope + void ignoreReferences(StoreEntry &e); ///< delete from repl policy scope + + int64_t diskOffset(int filen) const; + int64_t diskOffsetLimit() const; + int entryLimit() const { return map->entryLimit(); } + + friend class Rebuild; + const char *filePath; ///< location of cache storage file inside path/ + +private: + DiskIOStrategy *io; + RefCount theFile; ///< cache storage for this cache_dir + DirMap *map; + + /* configurable options */ + DiskFile::Config fileConfig; ///< file-level configuration options + + static const int64_t HeaderSize; ///< on-disk db header size +}; + +} // namespace Rock + +#endif /* SQUID_FS_ROCK_SWAP_DIR_H */ diff -u -r -N squid-3.2.0.12/src/fs/ufs/store_dir_ufs.cc squid-3.2.0.13/src/fs/ufs/store_dir_ufs.cc --- squid-3.2.0.12/src/fs/ufs/store_dir_ufs.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/fs/ufs/store_dir_ufs.cc 2011-10-14 14:42:56.000000000 +1300 @@ -57,13 +57,17 @@ * object is able to be stored on this filesystem. UFS filesystems will * happily store anything as long as the LRU time isn't too small. */ -int -UFSSwapDir::canStore(StoreEntry const &e)const +bool +UFSSwapDir::canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const { + if (!SwapDir::canStore(e, diskSpaceNeeded, load)) + return false; + if (IO->shedLoad()) - return -1; + return false; - return IO->load(); + load = IO->load(); + return true; } @@ -76,14 +80,14 @@ if (i <= 0) fatal("UFSSwapDir::parseSizeL1L2: invalid size value"); - size_t size = i << 10; /* Mbytes to kbytes */ + const uint64_t size = static_cast(i) << 20; // MBytes to Bytes /* just reconfigure it */ if (reconfiguring) { - if (size == max_size) - debugs(3, 2, "Cache dir '" << path << "' size remains unchanged at " << size << " KB"); + if (size == maxSize()) + debugs(3, 2, "Cache dir '" << path << "' size remains unchanged at " << i << " MB"); else - debugs(3, 1, "Cache dir '" << path << "' size changed to " << size << " KB"); + debugs(3, 1, "Cache dir '" << path << "' size changed to " << i << " MB"); } max_size = size; @@ -106,7 +110,7 @@ */ void -UFSSwapDir::reconfigure(int aIndex, char *aPath) +UFSSwapDir::reconfigure() { parseSizeL1L2(); parseOptions(1); @@ -242,7 +246,7 @@ createSwapSubDirs(); } -UFSSwapDir::UFSSwapDir(char const *aType, const char *anIOType) : SwapDir(aType), IO(NULL), map(file_map_create()), suggest(0), swaplog_fd (-1), currentIOOptions(new ConfigOptionVector()), ioType(xstrdup(anIOType)) +UFSSwapDir::UFSSwapDir(char const *aType, const char *anIOType) : SwapDir(aType), IO(NULL), map(file_map_create()), suggest(0), swaplog_fd (-1), currentIOOptions(new ConfigOptionVector()), ioType(xstrdup(anIOType)), cur_size(0), n_disk_objects(0) { /* modulename is only set to disk modules that are built, by configure, * so the Find call should never return NULL here. @@ -312,10 +316,10 @@ int x; storeAppendPrintf(&sentry, "First level subdirectories: %d\n", l1); storeAppendPrintf(&sentry, "Second level subdirectories: %d\n", l2); - storeAppendPrintf(&sentry, "Maximum Size: %"PRIu64" KB\n", max_size); - storeAppendPrintf(&sentry, "Current Size: %"PRIu64" KB\n", cur_size); + storeAppendPrintf(&sentry, "Maximum Size: %"PRIu64" KB\n", maxSize() >> 10); + storeAppendPrintf(&sentry, "Current Size: %.2f KB\n", currentSize() / 1024.0); storeAppendPrintf(&sentry, "Percent Used: %0.2f%%\n", - (double)(100.0 * cur_size) / (double)max_size); + Math::doublePercent(currentSize(), maxSize())); storeAppendPrintf(&sentry, "Filemap bits in use: %d of %d (%d%%)\n", map->n_files_in_map, map->max_n_files, Math::intPercent(map->n_files_in_map, map->max_n_files)); @@ -361,7 +365,7 @@ RemovalPurgeWalker *walker; - double f = (double) (cur_size - minSize()) / (max_size - minSize()); + double f = (double) (currentSize() - minSize()) / (maxSize() - minSize()); f = f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f; @@ -378,7 +382,7 @@ walker = repl->PurgeInit(repl, max_scan); while (1) { - if (cur_size < minSize()) + if (currentSize() < minSize()) break; if (removed >= max_remove) @@ -420,13 +424,15 @@ * This routine is called whenever the last reference to an object is * removed, to maintain replacement information within the storage fs. */ -void +bool UFSSwapDir::dereference(StoreEntry & e) { debugs(47, 3, "UFSSwapDir::dereference: referencing " << &e << " " << e.swap_dirn << "/" << e.swap_filen); if (repl->Dereferenced) repl->Dereferenced(repl, &e, &e.repl); + + return true; // keep e in the global store_table } StoreIOState::Pointer @@ -713,6 +719,8 @@ e->ping_status = PING_NONE; EBIT_CLR(e->flags, ENTRY_VALIDATED); mapBitSet(e->swap_filen); + cur_size += fs.blksize * sizeInBlocks(e->swap_file_sz); + ++n_disk_objects; e->hashInsert(key); /* do it after we clear KEY_PRIVATE */ replacementAdd (e); return e; @@ -1284,6 +1292,10 @@ { debugs(79, 3, "storeUfsUnlink: dirno " << index << ", fileno "<< std::setfill('0') << std::hex << std::uppercase << std::setw(8) << e.swap_filen); + if (e.swap_status == SWAPOUT_DONE && EBIT_TEST(e.flags, ENTRY_VALIDATED)) { + cur_size -= fs.blksize * sizeInBlocks(e.swap_file_sz); + --n_disk_objects; + } replacementRemove(&e); mapBitReset(e.swap_filen); UFSSwapDir::unlinkFile(e.swap_filen); @@ -1322,7 +1334,7 @@ void UFSSwapDir::dump(StoreEntry & entry) const { - storeAppendPrintf(&entry, " %"PRIu64" %d %d", (max_size >> 10), l1, l2); + storeAppendPrintf(&entry, " %"PRIu64" %d %d", maxSize() >> 20, l1, l2); dumpOptions(&entry); } @@ -1359,6 +1371,13 @@ IO->sync(); } +void +UFSSwapDir::swappedOut(const StoreEntry &e) +{ + cur_size += fs.blksize * sizeInBlocks(e.swap_file_sz); + ++n_disk_objects; +} + StoreSearch * UFSSwapDir::search(String const url, HttpRequest *request) { diff -u -r -N squid-3.2.0.12/src/fs/ufs/store_io_ufs.cc squid-3.2.0.13/src/fs/ufs/store_io_ufs.cc --- squid-3.2.0.12/src/fs/ufs/store_io_ufs.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/fs/ufs/store_io_ufs.cc 2011-10-14 14:42:56.000000000 +1300 @@ -190,11 +190,11 @@ * when it is safe to actually signal the lower layer for closing. */ void -UFSStoreState::close() +UFSStoreState::close(int) { debugs(79, 3, "UFSStoreState::close: dirno " << swap_dirn << ", fileno "<< std::setfill('0') << std::hex << std::uppercase << std::setw(8) << swap_filen); - tryClosing(); + tryClosing(); // UFS does not distinguish different closure types } void diff -u -r -N squid-3.2.0.12/src/fs/ufs/ufscommon.cc squid-3.2.0.13/src/fs/ufs/ufscommon.cc --- squid-3.2.0.12/src/fs/ufs/ufscommon.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/fs/ufs/ufscommon.cc 2011-10-14 14:42:56.000000000 +1300 @@ -362,63 +362,14 @@ rebuildFromDirectory(); } -struct InitStoreEntry : public unary_function { - InitStoreEntry(StoreEntry *anEntry, cache_key *aKey):what(anEntry),index(aKey) {} - - void operator()(StoreMeta const &x) { - switch (x.getType()) { - - case STORE_META_KEY: - assert(x.length == SQUID_MD5_DIGEST_LENGTH); - memcpy(index, x.value, SQUID_MD5_DIGEST_LENGTH); - break; - - case STORE_META_STD: - struct old_metahdr { - time_t timestamp; - time_t lastref; - time_t expires; - time_t lastmod; - size_t swap_file_sz; - uint16_t refcount; - uint16_t flags; - } *tmp; - tmp = (struct old_metahdr *)x.value; - assert(x.length == STORE_HDR_METASIZE_OLD); - what->timestamp = tmp->timestamp; - what->lastref = tmp->lastref; - what->expires = tmp->expires; - what->lastmod = tmp->lastmod; - what->swap_file_sz = tmp->swap_file_sz; - what->refcount = tmp->refcount; - what->flags = tmp->flags; - break; - - case STORE_META_STD_LFS: - assert(x.length == STORE_HDR_METASIZE); - memcpy(&what->timestamp, x.value, STORE_HDR_METASIZE); - break; - - default: - break; - } - } - - StoreEntry *what; - cache_key *index; -}; - void RebuildState::rebuildFromDirectory() { - LOCAL_ARRAY(char, hdr_buf, SM_PAGE_SIZE); currentEntry(NULL); cache_key key[SQUID_MD5_DIGEST_LENGTH]; struct stat sb; - int swap_hdr_len; int fd = -1; - StoreMeta *tlv_list; assert(this != NULL); debugs(47, 3, "commonUfsDirRebuildFromDirectory: DIR #" << sd->index); @@ -447,114 +398,27 @@ continue; } - if ((++counts.scancount & 0xFFFF) == 0) - debugs(47, 3, " " << sd->path << " " << std::setw(7) << counts.scancount << " files opened so far."); - debugs(47, 9, "file_in: fd=" << fd << " "<< std::setfill('0') << std::hex << std::uppercase << std::setw(8) << filn); - - - statCounter.syscalls.disk.reads++; - - int len; + MemBuf buf; + buf.init(SM_PAGE_SIZE, SM_PAGE_SIZE); + if (!storeRebuildLoadEntry(fd, sd->index, buf, counts)) + return; - if ((len = FD_READ_METHOD(fd, hdr_buf, SM_PAGE_SIZE)) < 0) { - debugs(47, 1, "commonUfsDirRebuildFromDirectory: read(FD " << fd << "): " << xstrerror()); - file_close(fd); - store_open_disk_fd--; - fd = -1; - continue; - } + StoreEntry tmpe; + const bool loaded = storeRebuildParseEntry(buf, tmpe, key, counts, + (int64_t)sb.st_size); file_close(fd); store_open_disk_fd--; fd = -1; - swap_hdr_len = 0; - - StoreMetaUnpacker aBuilder(hdr_buf, len, &swap_hdr_len); - - if (!aBuilder.isBufferSane()) { - debugs(47, 1, "commonUfsDirRebuildFromDirectory: Swap data buffer length is not sane."); - /* XXX shouldn't this be a call to commonUfsUnlink ? */ - sd->unlinkFile ( filn); - continue; - } - - tlv_list = aBuilder.createStoreMeta (); - if (tlv_list == NULL) { - debugs(47, 1, "commonUfsDirRebuildFromDirectory: failed to get meta data"); - /* XXX shouldn't this be a call to commonUfsUnlink ? */ - sd->unlinkFile (filn); + if (!loaded) { + // XXX: shouldn't this be a call to commonUfsUnlink? + sd->unlinkFile(filn); // should we unlink in all failure cases? continue; } - debugs(47, 3, "commonUfsDirRebuildFromDirectory: successful swap meta unpacking"); - memset(key, '\0', SQUID_MD5_DIGEST_LENGTH); - - StoreEntry tmpe; - InitStoreEntry visitor(&tmpe, key); - for_each(*tlv_list, visitor); - storeSwapTLVFree(tlv_list); - tlv_list = NULL; - - if (storeKeyNull(key)) { - debugs(47, 1, "commonUfsDirRebuildFromDirectory: NULL key"); - sd->unlinkFile(filn); + if (!storeRebuildKeepEntry(tmpe, key, counts)) continue; - } - - tmpe.key = key; - /* check sizes */ - - if (tmpe.swap_file_sz == 0) { - tmpe.swap_file_sz = (uint64_t) sb.st_size; - } else if (tmpe.swap_file_sz == (uint64_t)(sb.st_size - swap_hdr_len)) { - tmpe.swap_file_sz = (uint64_t) sb.st_size; - } else if (tmpe.swap_file_sz != (uint64_t)sb.st_size) { - debugs(47, 1, "commonUfsDirRebuildFromDirectory: SIZE MISMATCH " << - tmpe.swap_file_sz << "!=" << - sb.st_size); - - sd->unlinkFile(filn); - continue; - } - - if (EBIT_TEST(tmpe.flags, KEY_PRIVATE)) { - sd->unlinkFile(filn); - counts.badflags++; - continue; - } - - /* this needs to become - * 1) unpack url - * 2) make synthetic request with headers ?? or otherwise search - * for a matching object in the store - * TODO FIXME change to new async api - * TODO FIXME I think there is a race condition here with the - * async api : - * store A reads in object foo, searchs for it, and finds nothing. - * store B reads in object foo, searchs for it, finds nothing. - * store A gets called back with nothing, so registers the object - * store B gets called back with nothing, so registers the object, - * which will conflict when the in core index gets around to scanning - * store B. - * - * this suggests that rather than searching for duplicates, the - * index rebuild should just assume its the most recent accurate - * store entry and whoever indexes the stores handles duplicates. - */ - e = Store::Root().get(key); - - if (e && e->lastref >= tmpe.lastref) { - /* key already exists, current entry is newer */ - /* keep old, ignore new */ - counts.dupcount++; - continue; - } else if (NULL != e) { - /* URL already exists, this swapfile not being used */ - /* junk old, load new */ - e->release(); /* release old entry */ - counts.dupcount++; - } counts.objcount++; // tmpe.dump(5); @@ -644,9 +508,8 @@ /* * Make sure we don't unlink the file, it might be * in use by a subsequent entry. Also note that - * we don't have to subtract from store_swap_size - * because adding to store_swap_size happens in - * the cleanup procedure. + * we don't have to subtract from cur_size because + * adding to cur_size happens in the cleanup procedure. */ currentEntry()->expireNow(); currentEntry()->releaseRequest(); @@ -783,7 +646,6 @@ (void) 0; } - /* update store_swap_size */ counts.objcount++; currentEntry(sd->addDiskRestore(swapData.key, diff -u -r -N squid-3.2.0.12/src/fs/ufs/ufscommon.h squid-3.2.0.13/src/fs/ufs/ufscommon.h --- squid-3.2.0.12/src/fs/ufs/ufscommon.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/fs/ufs/ufscommon.h 2011-10-14 14:42:56.000000000 +1300 @@ -62,9 +62,9 @@ virtual void unlink(StoreEntry &); virtual void statfs(StoreEntry &)const; virtual void maintain(); - virtual int canStore(StoreEntry const &)const; + virtual bool canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const; virtual void reference(StoreEntry &); - virtual void dereference(StoreEntry &); + virtual bool dereference(StoreEntry &); virtual StoreIOState::Pointer createStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *); virtual StoreIOState::Pointer openStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *); virtual void openLog(); @@ -73,9 +73,12 @@ virtual void writeCleanDone(); virtual void logEntry(const StoreEntry & e, int op) const; virtual void parse(int index, char *path); - virtual void reconfigure(int, char *); + virtual void reconfigure(); virtual int callback(); virtual void sync(); + virtual void swappedOut(const StoreEntry &e); + virtual uint64_t currentSize() const { return cur_size; } + virtual uint64_t currentCount() const { return n_disk_objects; } void unlinkFile(sfileno f); // move down when unlink is a virtual method @@ -135,7 +138,8 @@ void optionIODump(StoreEntry * e) const; mutable ConfigOptionVector *currentIOOptions; char const *ioType; - + uint64_t cur_size; ///< currently used space in the storage area + uint64_t n_disk_objects; ///< total number of objects stored }; #include "RefCount.h" @@ -206,7 +210,7 @@ void operator delete (void *); UFSStoreState(SwapDir * SD, StoreEntry * anEntry, STIOCB * callback_, void *callback_data_); ~UFSStoreState(); - virtual void close(); + virtual void close(int how); virtual void closeCompleted(); // protected: virtual void ioCompletedNotification(); diff -u -r -N squid-3.2.0.12/src/ftp.cc squid-3.2.0.13/src/ftp.cc --- squid-3.2.0.12/src/ftp.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ftp.cc 2011-10-14 14:42:56.000000000 +1300 @@ -669,6 +669,9 @@ { debugs(9, 4, HERE << io.conn << ": '" << entry->url() << "'" ); + if (abortOnBadEntry("entry went bad while waiting for a timeout")) + return; + if (SENT_PASV == state && io.conn->fd == data.conn->fd) { /* stupid ftp.netscape.com */ flags.pasv_supported = false; diff -u -r -N squid-3.2.0.12/src/globals.h squid-3.2.0.13/src/globals.h --- squid-3.2.0.12/src/globals.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/globals.h 2011-10-14 14:42:56.000000000 +1300 @@ -108,7 +108,6 @@ extern int starting_up; /* 1 */ extern int shutting_down; /* 0 */ extern int reconfiguring; /* 0 */ - extern unsigned long store_swap_size; /* 0 */ extern time_t hit_only_mode_until; /* 0 */ extern StatCounters statCounter; extern double request_failure_ratio; /* 0.0 */ diff -u -r -N squid-3.2.0.12/src/HelperChildConfig.cc squid-3.2.0.13/src/HelperChildConfig.cc --- squid-3.2.0.12/src/HelperChildConfig.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/HelperChildConfig.cc 2011-10-14 14:42:56.000000000 +1300 @@ -4,22 +4,24 @@ #include -HelperChildConfig::HelperChildConfig(const unsigned int m, const unsigned int s, const unsigned int i, const unsigned int cc) : +HelperChildConfig::HelperChildConfig(const unsigned int m): n_max(m), - n_startup(s), - n_idle(i), - concurrency(cc), + n_startup(0), + n_idle(1), + concurrency(0), n_running(0), n_active(0) {} -HelperChildConfig::~HelperChildConfig() -{} - HelperChildConfig & -HelperChildConfig::operator =(const HelperChildConfig &rhs) +HelperChildConfig::updateLimits(const HelperChildConfig &rhs) { - memcpy(this, &rhs, sizeof(HelperChildConfig)); + // Copy the limits only. + // Preserve the local state values (n_running and n_active) + n_max = rhs.n_max; + n_startup = rhs.n_startup; + n_idle = rhs.n_idle; + concurrency = rhs.concurrency; return *this; } diff -u -r -N squid-3.2.0.12/src/HelperChildConfig.h squid-3.2.0.13/src/HelperChildConfig.h --- squid-3.2.0.12/src/HelperChildConfig.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/HelperChildConfig.h 2011-10-14 14:42:56.000000000 +1300 @@ -10,11 +10,9 @@ class HelperChildConfig { public: - HelperChildConfig(const unsigned int m=0, const unsigned int s=0, const unsigned int i=1, const unsigned int cc=0); - ~HelperChildConfig(); - HelperChildConfig &operator =(const HelperChildConfig &rhs); + explicit HelperChildConfig(const unsigned int m = 0); - /* + /** * When new helpers are needed call this to find out how many more * we are allowed to start. * \retval 0 No more helpers may be started right now. @@ -24,6 +22,13 @@ int needNew() const; void parseConfig(); + /** + * Update an existing set of details with new start/max/idle/concurrent limits. + * This is for parsing new child settings into an object incrementally then updating + * the running set without loosing any of the active state or causing races. + */ + HelperChildConfig &updateLimits(const HelperChildConfig &rhs); + /* values from squid.conf */ public: @@ -55,7 +60,6 @@ unsigned int concurrency; /* derived from active operations */ -public: /** * Total helper children objects currently existing. diff -u -r -N squid-3.2.0.12/src/http.cc squid-3.2.0.13/src/http.cc --- squid-3.2.0.12/src/http.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/http.cc 2011-10-14 14:42:56.000000000 +1300 @@ -58,6 +58,7 @@ #include "http.h" #include "HttpControlMsg.h" #include "HttpHdrContRange.h" +#include "HttpHdrCc.h" #include "HttpHdrSc.h" #include "HttpHdrScTarget.h" #include "HttpReply.h" @@ -330,7 +331,6 @@ { HttpReply const *rep = finalReply(); HttpHeader const *hdr = &rep->header; - const int cc_mask = (rep->cache_control) ? rep->cache_control->mask : 0; const char *v; #if USE_HTTP_VIOLATIONS @@ -353,22 +353,23 @@ // RFC 2616: do not cache replies to responses with no-store CC directive if (request && request->cache_control && - EBIT_TEST(request->cache_control->mask, CC_NO_STORE) && + request->cache_control->noStore() && !REFRESH_OVERRIDE(ignore_no_store)) return 0; - if (!ignoreCacheControl) { - if (EBIT_TEST(cc_mask, CC_PRIVATE)) { + if (!ignoreCacheControl && request->cache_control != NULL) { + const HttpHdrCc* cc=request->cache_control; + if (cc->Private()) { if (!REFRESH_OVERRIDE(ignore_private)) return 0; } - if (EBIT_TEST(cc_mask, CC_NO_CACHE)) { + if (cc->noCache()) { if (!REFRESH_OVERRIDE(ignore_no_cache)) return 0; } - if (EBIT_TEST(cc_mask, CC_NO_STORE)) { + if (cc->noStore()) { if (!REFRESH_OVERRIDE(ignore_no_store)) return 0; } @@ -381,7 +382,7 @@ * RFC 2068, sec 14.9.4 */ - if (!EBIT_TEST(cc_mask, CC_PUBLIC)) { + if (!request->cache_control->Public()) { if (!REFRESH_OVERRIDE(ignore_auth)) return 0; } @@ -925,9 +926,10 @@ no_cache: if (!ignoreCacheControl && rep->cache_control) { - if (EBIT_TEST(rep->cache_control->mask, CC_PROXY_REVALIDATE) || - EBIT_TEST(rep->cache_control->mask, CC_MUST_REVALIDATE) || - EBIT_TEST(rep->cache_control->mask, CC_S_MAXAGE)) + if (rep->cache_control->proxyRevalidate() || + rep->cache_control->mustRevalidate() || + rep->cache_control->hasSMaxAge() + ) EBIT_SET(entry->flags, ENTRY_REVALIDATE); } @@ -1185,7 +1187,7 @@ if (!continueAfterParsingHeader()) // parsing error or need more data return; // TODO: send errors to ICAP - adaptOrFinalizeReply(); + adaptOrFinalizeReply(); // may write to, abort, or "close" the entry } // kick more reads if needed and/or process the response body, if any @@ -1354,14 +1356,16 @@ * That means header content has been removed from readBuf and * it contains only body data. */ - if (flags.chunked) { - if (!decodeAndWriteReplyBody()) { - flags.do_next_read = 0; - serverComplete(); - return; - } - } else - writeReplyBody(); + if (entry->isAccepting()) { + if (flags.chunked) { + if (!decodeAndWriteReplyBody()) { + flags.do_next_read = 0; + serverComplete(); + return; + } + } else + writeReplyBody(); + } if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { /* @@ -1758,7 +1762,7 @@ HttpHdrCc *cc = hdr_in->getCc(); if (!cc) - cc = httpHdrCcCreate(); + cc = new HttpHdrCc(); #if 0 /* see bug 2330 */ /* Set no-cache if determined needed but not found */ @@ -1767,20 +1771,20 @@ #endif /* Add max-age only without no-cache */ - if (!EBIT_TEST(cc->mask, CC_MAX_AGE) && !EBIT_TEST(cc->mask, CC_NO_CACHE)) { + if (!cc->hasMaxAge() && !cc->noCache()) { const char *url = entry ? entry->url() : urlCanonical(request); - httpHdrCcSetMaxAge(cc, getMaxAge(url)); + cc->maxAge(getMaxAge(url)); } /* Enforce sibling relations */ if (flags.only_if_cached) - EBIT_SET(cc->mask, CC_ONLY_IF_CACHED); + cc->onlyIfCached(true); hdr_out->putCc(cc); - httpHdrCcDestroy(cc); + delete cc; } /* maybe append Connection: keep-alive */ diff -u -r -N squid-3.2.0.12/src/HttpHdrCc.cc squid-3.2.0.13/src/HttpHdrCc.cc --- squid-3.2.0.12/src/HttpHdrCc.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/HttpHdrCc.cc 2011-10-14 14:42:56.000000000 +1300 @@ -1,9 +1,6 @@ - /* - * $Id$ * * DEBUG: section 65 HTTP Cache Control Header - * AUTHOR: Alex Rousskov * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- @@ -34,30 +31,45 @@ */ #include "squid.h" +#include "base/StringArea.h" #include "Store.h" #include "HttpHeader.h" +#include "HttpHdrCc.h" -/* this table is used for parsing cache control header */ -static const HttpHeaderFieldAttrs CcAttrs[CC_ENUM_END] = { - {"public", (http_hdr_type)CC_PUBLIC}, - - {"private", (http_hdr_type)CC_PRIVATE}, - {"no-cache", (http_hdr_type)CC_NO_CACHE}, - {"no-store", (http_hdr_type)CC_NO_STORE}, - {"no-transform", (http_hdr_type)CC_NO_TRANSFORM}, - {"must-revalidate", (http_hdr_type)CC_MUST_REVALIDATE}, - {"proxy-revalidate", (http_hdr_type)CC_PROXY_REVALIDATE}, - {"only-if-cached", (http_hdr_type)CC_ONLY_IF_CACHED}, - {"max-age", (http_hdr_type)CC_MAX_AGE}, - {"s-maxage", (http_hdr_type)CC_S_MAXAGE}, - {"max-stale", (http_hdr_type)CC_MAX_STALE}, - {"stale-if-error", (http_hdr_type)CC_STALE_IF_ERROR}, - {"min-fresh", (http_hdr_type)CC_MIN_FRESH}, - {"Other,", (http_hdr_type)CC_OTHER} /* ',' will protect from matches */ +#if HAVE_MAP +#include +#endif + +/* a row in the table used for parsing cache control header and statistics */ +typedef struct { + const char *name; + http_hdr_cc_type id; + HttpHeaderFieldStat stat; +} HttpHeaderCcFields; + +/* order must match that of enum http_hdr_cc_type. The constraint is verified at initialization time */ +static HttpHeaderCcFields CcAttrs[CC_ENUM_END] = { + {"public", CC_PUBLIC}, + {"private", CC_PRIVATE}, + {"no-cache", CC_NO_CACHE}, + {"no-store", CC_NO_STORE}, + {"no-transform", CC_NO_TRANSFORM}, + {"must-revalidate", CC_MUST_REVALIDATE}, + {"proxy-revalidate", CC_PROXY_REVALIDATE}, + {"max-age", CC_MAX_AGE}, + {"s-maxage", CC_S_MAXAGE}, + {"max-stale", CC_MAX_STALE}, + {"min-fresh", CC_MIN_FRESH}, + {"only-if-cached", CC_ONLY_IF_CACHED}, + {"stale-if-error", CC_STALE_IF_ERROR}, + {"Other,", CC_OTHER} /* ',' will protect from matches */ }; -HttpHeaderFieldInfo *CcFieldsInfo = NULL; +/// Map an header name to its type, to expedite parsing +typedef std::map CcNameToIdMap_t; +static CcNameToIdMap_t CcNameToIdMap; +/// used to walk a table of http_header_cc_type structs http_hdr_cc_type &operator++ (http_hdr_cc_type &aHeader) { int tmp = (int)aHeader; @@ -66,52 +78,34 @@ } -/* local prototypes */ -static int httpHdrCcParseInit(HttpHdrCc * cc, const String * str); - - -/* module initialization */ - +/// Module initialization hook void httpHdrCcInitModule(void) { - CcFieldsInfo = httpHeaderBuildFieldsInfo(CcAttrs, CC_ENUM_END); + /* build lookup and accounting structures */ + for (int32_t i = 0; i < CC_ENUM_END; ++i) { + const HttpHeaderCcFields &f=CcAttrs[i]; + assert(i == f.id); /* verify assumption: the id is the key into the array */ + const StringArea k(f.name,strlen(f.name)); + CcNameToIdMap[k]=f.id; + } } +/// Module cleanup hook. void httpHdrCcCleanModule(void) { - httpHeaderDestroyFieldsInfo(CcFieldsInfo, CC_ENUM_END); - CcFieldsInfo = NULL; -} - -/* implementation */ - -HttpHdrCc * -httpHdrCcCreate(void) -{ - HttpHdrCc *cc = (HttpHdrCc *)memAllocate(MEM_HTTP_HDR_CC); - cc->max_age = cc->s_maxage = cc->max_stale = cc->min_fresh = -1; - return cc; + // HdrCcNameToIdMap is self-cleaning } -/* creates an cc object from a 0-terminating string */ -HttpHdrCc * -httpHdrCcParseCreate(const String * str) +void +HttpHdrCc::clear() { - HttpHdrCc *cc = httpHdrCcCreate(); - - if (!httpHdrCcParseInit(cc, str)) { - httpHdrCcDestroy(cc); - cc = NULL; - } - - return cc; + *this=HttpHdrCc(); } -/* parses a 0-terminating string and inits cc */ -static int -httpHdrCcParseInit(HttpHdrCc * cc, const String * str) +bool +HttpHdrCc::parse(const String & str) { const char *item; const char *p; /* '=' parameter */ @@ -119,11 +113,10 @@ http_hdr_cc_type type; int ilen; int nlen; - assert(cc && str); /* iterate through comma separated list */ - while (strListGetItem(str, ',', &item, &ilen, &pos)) { + while (strListGetItem(&str, ',', &item, &ilen, &pos)) { /* isolate directive name */ if ((p = (const char *)memchr(item, '=', ilen)) && (p - item < ilen)) @@ -132,82 +125,99 @@ nlen = ilen; /* find type */ - type = (http_hdr_cc_type ) httpHeaderIdByName(item, nlen, - CcFieldsInfo, CC_ENUM_END); - - if (type < 0) { - debugs(65, 2, "hdr cc: unknown cache-directive: near '" << item << "' in '" << str << "'"); - type = CC_OTHER; - } + const CcNameToIdMap_t::const_iterator i=CcNameToIdMap.find(StringArea(item,nlen)); + if (i==CcNameToIdMap.end()) + type=CC_OTHER; + else + type=i->second; // ignore known duplicate directives - if (EBIT_TEST(cc->mask, type)) { + if (isSet(type)) { if (type != CC_OTHER) { debugs(65, 2, "hdr cc: ignoring duplicate cache-directive: near '" << item << "' in '" << str << "'"); - CcFieldsInfo[type].stat.repCount++; + ++CcAttrs[type].stat.repCount; continue; } - } else { - EBIT_SET(cc->mask, type); } - /* post-processing special cases */ + /* special-case-parsing and attribute-setting */ switch (type) { case CC_MAX_AGE: - - if (!p || !httpHeaderParseInt(p, &cc->max_age)) { + if (!p || !httpHeaderParseInt(p, &max_age) || max_age < 0) { debugs(65, 2, "cc: invalid max-age specs near '" << item << "'"); - cc->max_age = -1; - EBIT_CLR(cc->mask, type); + clearMaxAge(); + } else { + setMask(type,true); } - break; case CC_S_MAXAGE: - - if (!p || !httpHeaderParseInt(p, &cc->s_maxage)) { + if (!p || !httpHeaderParseInt(p, &s_maxage) || s_maxage < 0) { debugs(65, 2, "cc: invalid s-maxage specs near '" << item << "'"); - cc->s_maxage = -1; - EBIT_CLR(cc->mask, type); + clearSMaxAge(); + } else { + setMask(type,true); } - break; case CC_MAX_STALE: - - if (!p || !httpHeaderParseInt(p, &cc->max_stale)) { + if (!p || !httpHeaderParseInt(p, &max_stale) || max_stale < 0) { debugs(65, 2, "cc: max-stale directive is valid without value"); - cc->max_stale = -1; + maxStale(MAX_STALE_ANY); + } else { + setMask(type,true); } - break; case CC_MIN_FRESH: - - if (!p || !httpHeaderParseInt(p, &cc->min_fresh)) { + if (!p || !httpHeaderParseInt(p, &min_fresh) || min_fresh < 0) { debugs(65, 2, "cc: invalid min-fresh specs near '" << item << "'"); - cc->min_fresh = -1; - EBIT_CLR(cc->mask, type); + clearMinFresh(); + } else { + setMask(type,true); } - break; case CC_STALE_IF_ERROR: - if (!p || !httpHeaderParseInt(p, &cc->stale_if_error)) { + if (!p || !httpHeaderParseInt(p, &stale_if_error) || stale_if_error < 0) { debugs(65, 2, "cc: invalid stale-if-error specs near '" << item << "'"); - cc->stale_if_error = -1; - EBIT_CLR(cc->mask, type); + clearStaleIfError(); + } else { + setMask(type,true); } break; - case CC_OTHER: - - if (cc->other.size()) - cc->other.append(", "); + case CC_PUBLIC: + Public(true); + break; + case CC_PRIVATE: + Private(true); + break; + case CC_NO_CACHE: + noCache(true); + break; + case CC_NO_STORE: + noStore(true); + break; + case CC_NO_TRANSFORM: + noTransform(true); + break; + case CC_MUST_REVALIDATE: + mustRevalidate(true); + break; + case CC_PROXY_REVALIDATE: + proxyRevalidate(true); + break; + case CC_ONLY_IF_CACHED: + onlyIfCached(true); + break; - cc->other.append(item, ilen); + case CC_OTHER: + if (other.size()) + other.append(", "); + other.append(item, ilen); break; default: @@ -216,95 +226,55 @@ } } - return cc->mask != 0; + return (mask != 0); } void -httpHdrCcDestroy(HttpHdrCc * cc) -{ - assert(cc); - - if (cc->other.defined()) - cc->other.clean(); - - memFree(cc, MEM_HTTP_HDR_CC); -} - -HttpHdrCc * -httpHdrCcDup(const HttpHdrCc * cc) +HttpHdrCc::packInto(Packer * p) const { - HttpHdrCc *dup; - assert(cc); - dup = httpHdrCcCreate(); - dup->mask = cc->mask; - dup->max_age = cc->max_age; - dup->s_maxage = cc->s_maxage; - dup->max_stale = cc->max_stale; - dup->min_fresh = cc->min_fresh; - return dup; -} + // optimization: if the mask is empty do nothing + if (mask==0) + return; -void -httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p) -{ http_hdr_cc_type flag; int pcount = 0; - assert(cc && p); + assert(p); for (flag = CC_PUBLIC; flag < CC_ENUM_END; ++flag) { - if (EBIT_TEST(cc->mask, flag) && flag != CC_OTHER) { - - /* print option name */ - packerPrintf(p, (pcount ? ", " SQUIDSTRINGPH : SQUIDSTRINGPH), - SQUIDSTRINGPRINT(CcFieldsInfo[flag].name)); - - /* handle options with values */ - - if (flag == CC_MAX_AGE) - packerPrintf(p, "=%d", (int) cc->max_age); + if (isSet(flag) && flag != CC_OTHER) { - if (flag == CC_S_MAXAGE) - packerPrintf(p, "=%d", (int) cc->s_maxage); + /* print option name for all options */ + packerPrintf(p, (pcount ? ", %s": "%s") , CcAttrs[flag].name); - if (flag == CC_MAX_STALE && cc->max_stale >= 0) - packerPrintf(p, "=%d", (int) cc->max_stale); - - if (flag == CC_MIN_FRESH) - packerPrintf(p, "=%d", (int) cc->min_fresh); + /* for all options having values, "=value" after the name */ + switch (flag) { + case CC_MAX_AGE: + packerPrintf(p, "=%d", (int) maxAge()); + break; + case CC_S_MAXAGE: + packerPrintf(p, "=%d", (int) sMaxAge()); + break; + case CC_MAX_STALE: + /* max-stale's value is optional. + If we didn't receive it, don't send it */ + if (maxStale()!=MAX_STALE_ANY) + packerPrintf(p, "=%d", (int) maxStale()); + break; + case CC_MIN_FRESH: + packerPrintf(p, "=%d", (int) minFresh()); + break; + default: + /* do nothing, directive was already printed */ + break; + } - pcount++; + ++pcount; } } - if (cc->other.size() != 0) + if (other.size() != 0) packerPrintf(p, (pcount ? ", " SQUIDSTRINGPH : SQUIDSTRINGPH), - SQUIDSTRINGPRINT(cc->other)); -} - -/* negative max_age will clean old max_Age setting */ -void -httpHdrCcSetMaxAge(HttpHdrCc * cc, int max_age) -{ - assert(cc); - cc->max_age = max_age; - - if (max_age >= 0) - EBIT_SET(cc->mask, CC_MAX_AGE); - else - EBIT_CLR(cc->mask, CC_MAX_AGE); -} - -/* negative s_maxage will clean old s-maxage setting */ -void -httpHdrCcSetSMaxAge(HttpHdrCc * cc, int s_maxage) -{ - assert(cc); - cc->s_maxage = s_maxage; - - if (s_maxage >= 0) - EBIT_SET(cc->mask, CC_S_MAXAGE); - else - EBIT_CLR(cc->mask, CC_S_MAXAGE); + SQUIDSTRINGPRINT(other)); } void @@ -314,7 +284,7 @@ assert(cc); for (c = CC_PUBLIC; c < CC_ENUM_END; ++c) - if (EBIT_TEST(cc->mask, c)) + if (cc->isSet(c)) statHistCount(hist, c); } @@ -324,9 +294,13 @@ extern const HttpHeaderStat *dump_stat; /* argh! */ const int id = (int) val; const int valid_id = id >= 0 && id < CC_ENUM_END; - const char *name = valid_id ? CcFieldsInfo[id].name.termedBuf() : "INVALID"; + const char *name = valid_id ? CcAttrs[id].name : "INVALID"; if (count || valid_id) storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n", id, name, count, xdiv(count, dump_stat->ccParsedCount)); } + +#if !_USE_INLINE_ +#include "HttpHdrCc.cci" +#endif diff -u -r -N squid-3.2.0.12/src/HttpHdrCc.cci squid-3.2.0.13/src/HttpHdrCc.cci --- squid-3.2.0.12/src/HttpHdrCc.cci 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/HttpHdrCc.cci 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,65 @@ +/* + * + * DEBUG: section 65 HTTP Cache Control Header + * + * 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. + * + */ +bool +HttpHdrCc::isSet(http_hdr_cc_type id) const +{ + assert(id>=CC_PUBLIC && id < CC_ENUM_END); + return EBIT_TEST(mask,id); +} + +void +HttpHdrCc::setMask(http_hdr_cc_type id, bool newval) +{ + if (newval) + EBIT_SET(mask,id); + else + EBIT_CLR(mask,id); +} + +/// set a data member to a new value, and set the corresponding mask-bit. +/// if setting is false, then the mask-bit is cleared. +void +HttpHdrCc::setValue(int32_t &value, int32_t new_value, http_hdr_cc_type hdr, bool setting) +{ + if (setting) { + if (new_value < 0) { + debugs(65,3,HERE << "rejecting negative-value Cache-Control directive " << hdr + << " value " << new_value ); + return; + } + } else { + new_value=-1; //rely on the convention that "unknown" is -1 + } + + value=new_value; + setMask(hdr,setting); +} diff -u -r -N squid-3.2.0.12/src/HttpHdrCc.h squid-3.2.0.13/src/HttpHdrCc.h --- squid-3.2.0.12/src/HttpHdrCc.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/HttpHdrCc.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,184 @@ +/* + * HttpHdrCc.h + * + * + * 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. + */ + +#ifndef SQUID_HTTPHDRCC_H +#define SQUID_HTTPHDRCC_H + +#include "config.h" +#include "MemPool.h" +#include "SquidString.h" + +/** Http Cache-Control header representation + * + * Store and parse the Cache-Control HTTP header. + */ +class HttpHdrCc +{ + +public: + static const int32_t MAX_AGE_UNKNOWN=-1; //max-age is unset + static const int32_t S_MAXAGE_UNKNOWN=-1; //s-maxage is unset + static const int32_t MAX_STALE_UNKNOWN=-1; //max-stale is unset + ///used to mark a valueless Cache-Control: max-stale directive, which instructs + /// us to treat responses of any age as fresh + static const int32_t MAX_STALE_ANY=0x7fffffff; + static const int32_t STALE_IF_ERROR_UNKNOWN=-1; //stale_if_error is unset + static const int32_t MIN_FRESH_UNKNOWN=-1; //min_fresh is unset + + HttpHdrCc() : + mask(0), max_age(MAX_AGE_UNKNOWN), s_maxage(S_MAXAGE_UNKNOWN), + max_stale(MAX_STALE_UNKNOWN), stale_if_error(STALE_IF_ERROR_UNKNOWN), + min_fresh(MIN_FRESH_UNKNOWN) {} + + /// reset data-members to default state + void clear(); + + /// parse a header-string and fill in appropriate values. + bool parse(const String & s); + + //manipulation for Cache-Control: public header + bool hasPublic() const {return isSet(CC_PUBLIC);} + bool Public() const {return isSet(CC_PUBLIC);} + void Public(bool v) {setMask(CC_PUBLIC,v);} + void clearPublic() {setMask(CC_PUBLIC,false);} + + //manipulation for Cache-Control: private header + bool hasPrivate() const {return isSet(CC_PRIVATE);} + bool Private() const {return isSet(CC_PRIVATE);} + void Private(bool v) {setMask(CC_PRIVATE,v);} + void clearPrivate() {setMask(CC_PRIVATE,false);} + + //manipulation for Cache-Control: no-cache header + bool hasNoCache() const {return isSet(CC_NO_CACHE);} + bool noCache() const {return isSet(CC_NO_CACHE);} + void noCache(bool v) {setMask(CC_NO_CACHE,v);} + void clearNoCache() {setMask(CC_NO_CACHE,false);} + + //manipulation for Cache-Control: no-store header + bool hasNoStore() const {return isSet(CC_NO_STORE);} + bool noStore() const {return isSet(CC_NO_STORE);} + void noStore(bool v) {setMask(CC_NO_STORE,v);} + void clearNoStore() {setMask(CC_NO_STORE,false);} + + //manipulation for Cache-Control: no-transform header + bool hasNoTransform() const {return isSet(CC_NO_TRANSFORM);} + bool noTransform() const {return isSet(CC_NO_TRANSFORM);} + void noTransform(bool v) {setMask(CC_NO_TRANSFORM,v);} + void clearNoTransform() {setMask(CC_NO_TRANSFORM,false);} + + //manipulation for Cache-Control: must-revalidate header + bool hasMustRevalidate() const {return isSet(CC_MUST_REVALIDATE);} + bool mustRevalidate() const {return isSet(CC_MUST_REVALIDATE);} + void mustRevalidate(bool v) {setMask(CC_MUST_REVALIDATE,v);} + void clearMustRevalidate() {setMask(CC_MUST_REVALIDATE,false);} + + //manipulation for Cache-Control: proxy-revalidate header + bool hasProxyRevalidate() const {return isSet(CC_PROXY_REVALIDATE);} + bool proxyRevalidate() const {return isSet(CC_PROXY_REVALIDATE);} + void proxyRevalidate(bool v) {setMask(CC_PROXY_REVALIDATE,v);} + void clearProxyRevalidate() {setMask(CC_PROXY_REVALIDATE,false);} + + //manipulation for Cache-Control: max-age header + bool hasMaxAge() const {return isSet(CC_MAX_AGE);} + int32_t maxAge() const { return max_age;} + void maxAge(int32_t v) {setValue(max_age,v,CC_MAX_AGE); } + void clearMaxAge() {setValue(max_age,MAX_AGE_UNKNOWN,CC_MAX_AGE,false);} + + //manipulation for Cache-Control: s-maxage header + bool hasSMaxAge() const {return isSet(CC_S_MAXAGE);} + int32_t sMaxAge() const { return s_maxage;} + void sMaxAge(int32_t v) {setValue(s_maxage,v,CC_S_MAXAGE); } + void clearSMaxAge() {setValue(s_maxage,MAX_AGE_UNKNOWN,CC_S_MAXAGE,false);} + + //manipulation for Cache-Control: max-stale header + bool hasMaxStale() const {return isSet(CC_MAX_STALE);} + int32_t maxStale() const { return max_stale;} + // max-stale has a special value (MAX_STALE_ANY) which correspond to having + // the directive without a numeric specification, and directs to consider the object + // as always-expired. + void maxStale(int32_t v) {setValue(max_stale,v,CC_MAX_STALE);} + void clearMaxStale() {setValue(max_stale,MAX_STALE_UNKNOWN,CC_MAX_STALE,false);} + + //manipulation for Cache-Control:min-fresh header + bool hasMinFresh() const {return isSet(CC_MIN_FRESH);} + int32_t minFresh() const { return min_fresh;} + void minFresh(int32_t v) {if (v < 0) return; setValue(min_fresh,v,CC_MIN_FRESH); } + void clearMinFresh() {setValue(min_fresh,MIN_FRESH_UNKNOWN,CC_MIN_FRESH,false);} + + //manipulation for Cache-Control: only-if-cached header + bool hasOnlyIfCached() const {return isSet(CC_ONLY_IF_CACHED);} + bool onlyIfCached() const {return isSet(CC_ONLY_IF_CACHED);} + void onlyIfCached(bool v) {setMask(CC_ONLY_IF_CACHED,v);} + void clearOnlyIfCached() {setMask(CC_ONLY_IF_CACHED,false);} + + //manipulation for Cache-Control: stale-if-error header + bool hasStaleIfError() const {return isSet(CC_STALE_IF_ERROR);} + int32_t staleIfError() const { return stale_if_error;} + void staleIfError(int32_t v) {setValue(stale_if_error,v,CC_STALE_IF_ERROR); } + void clearStaleIfError() {setValue(stale_if_error,STALE_IF_ERROR_UNKNOWN,CC_STALE_IF_ERROR,false);} + + /// check whether the attribute value supplied by id is set + _SQUID_INLINE_ bool isSet(http_hdr_cc_type id) const; + + void packInto(Packer * p) const; + + MEMPROXY_CLASS(HttpHdrCc); + + /** bit-mask representing what header values are set among those + * recognized by squid. + * + * managed via EBIT_SET/TEST/CLR + */ +private: + int32_t mask; + int32_t max_age; + int32_t s_maxage; + int32_t max_stale; + int32_t stale_if_error; + int32_t min_fresh; + /// low-level part of the public set method, performs no checks + _SQUID_INLINE_ void setMask(http_hdr_cc_type id, bool newval=true); + _SQUID_INLINE_ void setValue(int32_t &value, int32_t new_value, http_hdr_cc_type hdr, bool setting=true); + +public: + /**comma-separated representation of the header values which were + * received but are not recognized. + */ + String other; +}; + +MEMPROXY_CLASS_INLINE(HttpHdrCc); + +#if _USE_INLINE_ +#include "HttpHdrCc.cci" +#endif + +#endif /* SQUID_HTTPHDRCC_H */ diff -u -r -N squid-3.2.0.12/src/HttpHeader.cc squid-3.2.0.13/src/HttpHeader.cc --- squid-3.2.0.12/src/HttpHeader.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/HttpHeader.cc 2011-10-14 14:42:56.000000000 +1300 @@ -36,6 +36,7 @@ #include "squid.h" #include "base64.h" #include "HttpHdrContRange.h" +#include "HttpHdrCc.h" #include "HttpHdrSc.h" #include "HttpHeader.h" #include "MemBuf.h" @@ -1151,7 +1152,7 @@ /* pack into mb */ mb.init(); packerToMemInit(&p, &mb); - httpHdrCcPackInto(cc, &p); + cc->packInto(&p); /* put */ addEntry(new HttpHeaderEntry(HDR_CACHE_CONTROL, NULL, mb.buf)); /* cleanup */ @@ -1310,16 +1311,19 @@ HttpHdrCc * HttpHeader::getCc() const { - HttpHdrCc *cc; - String s; - if (!CBIT_TEST(mask, HDR_CACHE_CONTROL)) return NULL; PROF_start(HttpHeader_getCc); + String s; getList(HDR_CACHE_CONTROL, &s); - cc = httpHdrCcParseCreate(&s); + HttpHdrCc *cc=new HttpHdrCc(); + + if (!cc->parse(s)) { + delete cc; + cc = NULL; + } HttpHeaderStats[owner].ccParsedCount++; diff -u -r -N squid-3.2.0.12/src/HttpHeaderTools.cc squid-3.2.0.13/src/HttpHeaderTools.cc --- squid-3.2.0.12/src/HttpHeaderTools.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/HttpHeaderTools.cc 2011-10-14 14:42:56.000000000 +1300 @@ -377,9 +377,9 @@ } } end = pos; - while (end < (start+len) && *end != '\\' && *end != '\"' && *end > 0x1F && *end != 0x7F) + while (end < (start+len) && *end != '\\' && *end != '\"' && (unsigned char)*end > 0x1F && *end != 0x7F) end++; - if ((*end <= 0x1F && *end != '\r' && *end != '\n') || *end == 0x7F) { + if (((unsigned char)*end <= 0x1F && *end != '\r' && *end != '\n') || *end == 0x7F) { debugs(66, 2, HERE << "failed to parse a quoted-string header field with CTL octet " << (start-pos) << " bytes into '" << start << "'"); val->clean(); diff -u -r -N squid-3.2.0.12/src/HttpReply.cc squid-3.2.0.13/src/HttpReply.cc --- squid-3.2.0.12/src/HttpReply.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/HttpReply.cc 2011-10-14 14:42:56.000000000 +1300 @@ -38,6 +38,7 @@ #include "Store.h" #include "HttpReply.h" #include "HttpHdrContRange.h" +#include "HttpHdrCc.h" #include "HttpHdrSc.h" #include "acl/FilledChecklist.h" #include "HttpRequest.h" @@ -330,21 +331,21 @@ if (cache_control) { if (date >= 0) { - if (cache_control->s_maxage >= 0) - return date + cache_control->s_maxage; + if (cache_control->hasSMaxAge()) + return date + cache_control->sMaxAge(); - if (cache_control->max_age >= 0) - return date + cache_control->max_age; + if (cache_control->hasMaxAge()) + return date + cache_control->maxAge(); } else { /* * Conservatively handle the case when we have a max-age * header, but no Date for reference? */ - if (cache_control->s_maxage >= 0) + if (cache_control->hasSMaxAge()) return squid_curtime; - if (cache_control->max_age >= 0) + if (cache_control->hasMaxAge()) return squid_curtime; } } @@ -402,7 +403,7 @@ content_type.clean(); if (cache_control) { - httpHdrCcDestroy(cache_control); + delete cache_control; cache_control = NULL; } diff -u -r -N squid-3.2.0.12/src/HttpRequest.cc squid-3.2.0.13/src/HttpRequest.cc --- squid-3.2.0.12/src/HttpRequest.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/HttpRequest.cc 2011-10-14 14:42:56.000000000 +1300 @@ -37,6 +37,7 @@ #include "squid.h" #include "DnsLookupDetails.h" #include "HttpRequest.h" +#include "HttpHdrCc.h" #if USE_AUTH #include "auth/UserRequest.h" #endif @@ -145,7 +146,7 @@ header.clean(); if (cache_control) { - httpHdrCcDestroy(cache_control); + delete cache_control; cache_control = NULL; } diff -u -r -N squid-3.2.0.12/src/ip/Address.cc squid-3.2.0.13/src/ip/Address.cc --- squid-3.2.0.12/src/ip/Address.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ip/Address.cc 2011-10-14 14:42:56.000000000 +1300 @@ -185,7 +185,7 @@ bool Ip::Address::IsAnyAddr() const { - return IN6_IS_ADDR_UNSPECIFIED( &m_SocketAddr.sin6_addr ) || IN6_ARE_ADDR_EQUAL( &m_SocketAddr.sin6_addr, &v4_anyaddr); ; + return IN6_IS_ADDR_UNSPECIFIED(&m_SocketAddr.sin6_addr) || IN6_ARE_ADDR_EQUAL(&m_SocketAddr.sin6_addr, &v4_anyaddr); } /// NOTE: Does NOT clear the Port stored. Ony the Address and Type. diff -u -r -N squid-3.2.0.12/src/ip/Intercept.cc squid-3.2.0.13/src/ip/Intercept.cc --- squid-3.2.0.12/src/ip/Intercept.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ip/Intercept.cc 2011-10-14 14:42:56.000000000 +1300 @@ -204,7 +204,7 @@ natLookup.nl_inport = htons(newConn->local.GetPort()); newConn->local.GetInAddr(natLookup.nl_inip); - natLookup.nl_outport = htons(neConn->remote.GetPort()); + natLookup.nl_outport = htons(newConn->remote.GetPort()); newConn->remote.GetInAddr(natLookup.nl_outip); natLookup.nl_flags = IPN_TCP; diff -u -r -N squid-3.2.0.12/src/ipc/AtomicWord.h squid-3.2.0.13/src/ipc/AtomicWord.h --- squid-3.2.0.12/src/ipc/AtomicWord.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/AtomicWord.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,88 @@ +/* + * $Id$ + * + */ + +#ifndef SQUID_IPC_ATOMIC_WORD_H +#define SQUID_IPC_ATOMIC_WORD_H + +#if HAVE_ATOMIC_OPS +/// Supplies atomic operations for an integral Value in memory shared by kids. +/// Used to implement non-blocking shared locks, queues, tables, and pools. +template +class AtomicWordT +{ +public: + typedef ValueType Value; + + AtomicWordT() {} // leave value unchanged + AtomicWordT(Value aValue): value(aValue) {} // XXX: unsafe + + Value operator +=(int delta) { return __sync_add_and_fetch(&value, delta); } + Value operator -=(int delta) { return __sync_sub_and_fetch(&value, delta); } + Value operator ++() { return *this += 1; } + Value operator --() { return *this -= 1; } + Value operator ++(int) { return __sync_fetch_and_add(&value, 1); } + Value operator --(int) { return __sync_fetch_and_sub(&value, 1); } + + bool swap_if(const int comparand, const int replacement) { return __sync_bool_compare_and_swap(&value, comparand, replacement); } + + /// v1 = value; value &= v2; return v1; + Value fetchAndAnd(const Value v2) { return __sync_fetch_and_and(&value, v2); } + + // TODO: no need for __sync_bool_compare_and_swap here? + bool operator ==(int v2) { return __sync_bool_compare_and_swap(&value, v2, value); } + + // TODO: no need for __sync_fetch_and_add here? + Value get() const { return __sync_fetch_and_add(const_cast(&value), 0); } + operator Value () const { return get(); } + +private: + Value value; +}; + +enum { AtomicOperationsSupported = 1 }; + +#else +/// A wrapper to provide AtomicWordT API (and asserting implementation) +/// where we do not support atomic operations. This avoids ifdefs in core code. +template +class AtomicWordT +{ +public: + typedef ValueType Value; + + AtomicWordT() {} // leave value unchanged + AtomicWordT(Value aValue): value(aValue) {} // XXX: unsafe + + Value operator +=(int) { assert(false); return *this; } + Value operator ++() { return *this += 1; } + Value operator --() { return *this += -1; } + Value operator ++(int) { assert(false); return *this; } + Value operator --(int) { assert(false); return *this; } + + bool swap_if(const int comparand, const int replacement) + { assert(false); return false; } + + /// v1 = value; value &= v2; return v1; + Value fetchAndAnd(const Value v2) + { assert(false); return value; } + + // TODO: no need for __sync_bool_compare_and_swap here? + bool operator ==(int v2) { assert(false); return false; } + + // TODO: no need for __sync_fetch_and_add here? + Value get() const { assert(false); return value; } + operator Value () const { return get(); } + +private: + Value value; +}; + +enum { AtomicOperationsSupported = 0 }; + +#endif /* HAVE_ATOMIC_OPS */ + +typedef AtomicWordT AtomicWord; + +#endif // SQUID_IPC_ATOMIC_WORD_H diff -u -r -N squid-3.2.0.12/src/ipc/Coordinator.cc squid-3.2.0.13/src/ipc/Coordinator.cc --- squid-3.2.0.12/src/ipc/Coordinator.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ipc/Coordinator.cc 2011-10-14 14:42:56.000000000 +1300 @@ -49,10 +49,27 @@ void Ipc::Coordinator::registerStrand(const StrandCoord& strand) { - if (StrandCoord* found = findStrand(strand.kidId)) + debugs(54, 3, HERE << "registering kid" << strand.kidId << + ' ' << strand.tag); + if (StrandCoord* found = findStrand(strand.kidId)) { + const String oldTag = found->tag; *found = strand; - else + if (oldTag.size() && !strand.tag.size()) + found->tag = oldTag; // keep more detailed info (XXX?) + } else { strands_.push_back(strand); + } + + // notify searchers waiting for this new strand, if any + typedef Searchers::iterator SRI; + for (SRI i = searchers.begin(); i != searchers.end();) { + if (i->tag == strand.tag) { + notifySearcher(*i, strand); + i = searchers.erase(i); + } else { + ++i; + } + } } void Ipc::Coordinator::receive(const TypedMsgHdr& message) @@ -60,9 +77,17 @@ switch (message.type()) { case mtRegistration: debugs(54, 6, HERE << "Registration request"); - handleRegistrationRequest(StrandCoord(message)); + handleRegistrationRequest(HereIamMessage(message)); break; + case mtStrandSearchRequest: { + const StrandSearchRequest sr(message); + debugs(54, 6, HERE << "Strand search request: " << sr.requestorId << + " tag: " << sr.tag); + handleSearchRequest(sr); + break; + } + case mtSharedListenRequest: debugs(54, 6, HERE << "Shared listen request"); handleSharedListenRequest(SharedListenRequest(message)); @@ -104,14 +129,14 @@ } } -void Ipc::Coordinator::handleRegistrationRequest(const StrandCoord& strand) +void Ipc::Coordinator::handleRegistrationRequest(const HereIamMessage& msg) { - registerStrand(strand); + registerStrand(msg.strand); // send back an acknowledgement; TODO: remove as not needed? TypedMsgHdr message; - strand.pack(message); - SendMessage(MakeAddr(strandAddrPfx, strand.kidId), message); + msg.pack(message); + SendMessage(MakeAddr(strandAddrPfx, msg.strand.kidId), message); } void @@ -139,15 +164,25 @@ { debugs(54, 4, HERE); + try { + Mgr::Action::Pointer action = + CacheManager::GetInstance()->createRequestedAction(request.params); + AsyncJob::Start(new Mgr::Inquirer(action, request, strands_)); + } catch (const std::exception &ex) { + debugs(54, DBG_IMPORTANT, "BUG: cannot aggregate mgr:" << + request.params.actionName << ": " << ex.what()); + // TODO: Avoid half-baked Connections or teach them how to close. + ::close(request.conn->fd); + request.conn->fd = -1; + return; // the worker will timeout and close + } + // Let the strand know that we are now responsible for handling the request Mgr::Response response(request.requestId); TypedMsgHdr message; response.pack(message); SendMessage(MakeAddr(strandAddrPfx, request.requestorId), message); - Mgr::Action::Pointer action = - CacheManager::GetInstance()->createRequestedAction(request.params); - AsyncJob::Start(new Mgr::Inquirer(action, request, strands_)); } void @@ -156,6 +191,39 @@ Mgr::Inquirer::HandleRemoteAck(response); } +void +Ipc::Coordinator::handleSearchRequest(const Ipc::StrandSearchRequest &request) +{ + // do we know of a strand with the given search tag? + const StrandCoord *strand = NULL; + typedef StrandCoords::const_iterator SCCI; + for (SCCI i = strands_.begin(); !strand && i != strands_.end(); ++i) { + if (i->tag == request.tag) + strand = &(*i); + } + + if (strand) { + notifySearcher(request, *strand); + return; + } + + searchers.push_back(request); + debugs(54, 3, HERE << "cannot yet tell kid" << request.requestorId << + " who " << request.tag << " is"); +} + +void +Ipc::Coordinator::notifySearcher(const Ipc::StrandSearchRequest &request, + const StrandCoord& strand) +{ + debugs(54, 3, HERE << "tell kid" << request.requestorId << " that " << + request.tag << " is kid" << strand.kidId); + const StrandSearchResponse response(strand); + TypedMsgHdr message; + response.pack(message); + SendMessage(MakeAddr(strandAddrPfx, request.requestorId), message); +} + #if SQUID_SNMP void Ipc::Coordinator::handleSnmpRequest(const Snmp::Request& request) diff -u -r -N squid-3.2.0.12/src/ipc/Coordinator.h squid-3.2.0.13/src/ipc/Coordinator.h --- squid-3.2.0.12/src/ipc/Coordinator.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ipc/Coordinator.h 2011-10-14 14:42:56.000000000 +1300 @@ -14,10 +14,12 @@ #include "ipc/Port.h" #include "ipc/SharedListen.h" #include "ipc/StrandCoords.h" +#include "ipc/StrandSearch.h" #include "mgr/forward.h" #if SQUID_SNMP #include "snmp/forward.h" #endif +#include #include namespace Ipc @@ -42,7 +44,12 @@ StrandCoord* findStrand(int kidId); ///< registered strand or NULL void registerStrand(const StrandCoord &); ///< adds or updates existing - void handleRegistrationRequest(const StrandCoord &); ///< register,ACK + void handleRegistrationRequest(const HereIamMessage &); ///< register,ACK + + /// answer the waiting search request + void notifySearcher(const StrandSearchRequest &request, const StrandCoord&); + /// answers or queues the request if the answer is not yet known + void handleSearchRequest(const StrandSearchRequest &request); /// returns cached socket or calls openListenSocket() void handleSharedListenRequest(const SharedListenRequest& request); @@ -58,7 +65,10 @@ private: StrandCoords strands_; ///< registered processes and threads - typedef std::map Listeners; ///< params:fd map + typedef std::list Searchers; ///< search requests + Searchers searchers; ///< yet unanswered search requests in arrival order + + typedef std::map Listeners; ///< params:connection map Listeners listeners; ///< cached comm_open_listener() results static Coordinator* TheInstance; ///< the only class instance in existence diff -u -r -N squid-3.2.0.12/src/ipc/Forwarder.cc squid-3.2.0.13/src/ipc/Forwarder.cc --- squid-3.2.0.12/src/ipc/Forwarder.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ipc/Forwarder.cc 2011-10-14 14:42:56.000000000 +1300 @@ -92,6 +92,8 @@ { debugs(54, 3, HERE); request->requestId = 0; + // Do not clear ENTRY_FWD_HDR_WAIT or do entry->complete() because + // it will trigger our client side processing. Let job cleanup close. } /// Ipc::Forwarder::requestTimedOut wrapper diff -u -r -N squid-3.2.0.12/src/ipc/forward.h squid-3.2.0.13/src/ipc/forward.h --- squid-3.2.0.12/src/ipc/forward.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ipc/forward.h 2011-10-14 14:42:56.000000000 +1300 @@ -13,6 +13,8 @@ class TypedMsgHdr; class StrandCoord; +class HereIamMessage; +class StrandSearchResponse; class Forwarder; class Inquirer; class Request; diff -u -r -N squid-3.2.0.12/src/ipc/Kid.cc squid-3.2.0.13/src/ipc/Kid.cc --- squid-3.2.0.12/src/ipc/Kid.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ipc/Kid.cc 2011-10-14 14:42:56.000000000 +1300 @@ -13,6 +13,8 @@ #include #endif +int TheProcessKind = pkOther; + Kid::Kid(): badFailures(0), pid(-1), diff -u -r -N squid-3.2.0.12/src/ipc/Kid.h squid-3.2.0.13/src/ipc/Kid.h --- squid-3.2.0.12/src/ipc/Kid.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ipc/Kid.h 2011-10-14 14:42:56.000000000 +1300 @@ -85,4 +85,19 @@ status_type status; ///< exit status of a stopped kid }; + +// TODO: processes may not be kids; is there a better place to put this? + +/// process kinds +typedef enum { + pkOther = 0, ///< we do not know or do not care + pkCoordinator = 1, ///< manages all other kids + pkWorker = 2, ///< general-purpose worker bee + pkDisker = 4, ///< cache_dir manager +} ProcessKind; + +/// ProcessKind for the current process +extern int TheProcessKind; + + #endif /* SQUID_IPC_KID_H */ diff -u -r -N squid-3.2.0.12/src/ipc/Kids.cc squid-3.2.0.13/src/ipc/Kids.cc --- squid-3.2.0.12/src/ipc/Kids.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ipc/Kids.cc 2011-10-14 14:42:56.000000000 +1300 @@ -6,7 +6,9 @@ */ #include "config.h" +#include "base/TextException.h" #include "ipc/Kids.h" +#include "protos.h" Kids TheKids; KidName TheKidName; @@ -16,28 +18,34 @@ } /// maintain n kids -void Kids::init(size_t n) +void Kids::init() { - assert(n > 0); - if (storage.size() > 0) storage.clean(); - storage.reserve(n); + storage.reserve(NumberOfKids()); char kid_name[32]; - // add Kid records for all n main strands - for (size_t i = 1; i <= n; ++i) { - snprintf(kid_name, sizeof(kid_name), "(squid-%d)", (int)i); + // add Kid records for all workers + for (int i = 0; i < Config.workers; ++i) { + snprintf(kid_name, sizeof(kid_name), "(squid-%d)", (int)(storage.size()+1)); + storage.push_back(Kid(kid_name)); + } + + // add Kid records for all disk processes + for (int i = 0; i < Config.cacheSwap.n_strands; ++i) { + snprintf(kid_name, sizeof(kid_name), "(squid-disk-%d)", (int)(storage.size()+1)); storage.push_back(Kid(kid_name)); } // if coordination is needed, add a Kid record for Coordinator - if (n > 1) { - snprintf(kid_name, sizeof(kid_name), "(squid-coord-%d)", (int)(n + 1)); + if (storage.size() > 1) { + snprintf(kid_name, sizeof(kid_name), "(squid-coord-%d)", (int)(storage.size()+1)); storage.push_back(Kid(kid_name)); } + + Must(storage.size() == static_cast(NumberOfKids())); } /// returns kid by pid diff -u -r -N squid-3.2.0.12/src/ipc/Kids.h squid-3.2.0.13/src/ipc/Kids.h --- squid-3.2.0.12/src/ipc/Kids.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ipc/Kids.h 2011-10-14 14:42:56.000000000 +1300 @@ -21,8 +21,8 @@ Kids& operator= (const Kids&); ///< not implemented public: - /// maintain n kids - void init(size_t n); + /// initialize all kid records based on Config + void init(); /// returns kid by pid Kid* find(pid_t pid); diff -u -r -N squid-3.2.0.12/src/ipc/Makefile.am squid-3.2.0.13/src/ipc/Makefile.am --- squid-3.2.0.12/src/ipc/Makefile.am 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ipc/Makefile.am 2011-10-14 14:42:56.000000000 +1300 @@ -4,6 +4,7 @@ noinst_LTLIBRARIES = libipc.la libipc_la_SOURCES = \ + AtomicWord.h \ FdNotes.cc \ FdNotes.h \ Kid.cc \ @@ -11,11 +12,19 @@ Kids.cc \ Kids.h \ Messages.h \ + Queue.cc \ + Queue.h \ + ReadWriteLock.cc \ + ReadWriteLock.h \ StartListening.cc \ StartListening.h \ + StoreMap.cc \ + StoreMap.h \ StrandCoord.cc \ StrandCoord.h \ StrandCoords.h \ + StrandSearch.cc \ + StrandSearch.h \ SharedListen.cc \ SharedListen.h \ TypedMsgHdr.cc \ @@ -34,7 +43,19 @@ Inquirer.cc \ Inquirer.h \ Request.h \ - Response.h + Response.h \ + \ + mem/Page.cc \ + mem/Page.h \ + mem/PagePool.cc \ + mem/PagePool.h \ + mem/Pages.cc \ + mem/Pages.h \ + mem/PageStack.cc \ + mem/PageStack.h \ + mem/Pointer.h \ + mem/Segment.cc \ + mem/Segment.h DEFS += -DDEFAULT_STATEDIR=\"$(localstatedir)/run/squid\" diff -u -r -N squid-3.2.0.12/src/ipc/Makefile.in squid-3.2.0.13/src/ipc/Makefile.in --- squid-3.2.0.12/src/ipc/Makefile.in 2011-09-16 23:38:20.000000000 +1200 +++ squid-3.2.0.13/src/ipc/Makefile.in 2011-10-14 14:48:14.000000000 +1300 @@ -56,9 +56,11 @@ CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libipc_la_LIBADD = -am_libipc_la_OBJECTS = FdNotes.lo Kid.lo Kids.lo StartListening.lo \ - StrandCoord.lo SharedListen.lo TypedMsgHdr.lo Coordinator.lo \ - UdsOp.lo Port.lo Strand.lo Forwarder.lo Inquirer.lo +am_libipc_la_OBJECTS = FdNotes.lo Kid.lo Kids.lo Queue.lo \ + ReadWriteLock.lo StartListening.lo StoreMap.lo StrandCoord.lo \ + StrandSearch.lo SharedListen.lo TypedMsgHdr.lo Coordinator.lo \ + UdsOp.lo Port.lo Strand.lo Forwarder.lo Inquirer.lo Page.lo \ + PagePool.lo Pages.lo PageStack.lo Segment.lo libipc_la_OBJECTS = $(am_libipc_la_OBJECTS) DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/cfgaux/depcomp @@ -311,6 +313,7 @@ subst_perlshell = sed -e 's,[@]PERL[@],$(PERL),g' <$(srcdir)/$@.pl.in >$@ || ($(RM) -f $@ ; exit 1) noinst_LTLIBRARIES = libipc.la libipc_la_SOURCES = \ + AtomicWord.h \ FdNotes.cc \ FdNotes.h \ Kid.cc \ @@ -318,11 +321,19 @@ Kids.cc \ Kids.h \ Messages.h \ + Queue.cc \ + Queue.h \ + ReadWriteLock.cc \ + ReadWriteLock.h \ StartListening.cc \ StartListening.h \ + StoreMap.cc \ + StoreMap.h \ StrandCoord.cc \ StrandCoord.h \ StrandCoords.h \ + StrandSearch.cc \ + StrandSearch.h \ SharedListen.cc \ SharedListen.h \ TypedMsgHdr.cc \ @@ -341,7 +352,19 @@ Inquirer.cc \ Inquirer.h \ Request.h \ - Response.h + Response.h \ + \ + mem/Page.cc \ + mem/Page.h \ + mem/PagePool.cc \ + mem/PagePool.h \ + mem/Pages.cc \ + mem/Pages.h \ + mem/PageStack.cc \ + mem/PageStack.h \ + mem/Pointer.h \ + mem/Segment.cc \ + mem/Segment.h all: all-am @@ -410,11 +433,20 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Inquirer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Kid.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Kids.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Page.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PagePool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PageStack.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Pages.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Port.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Queue.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ReadWriteLock.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Segment.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SharedListen.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StartListening.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StoreMap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Strand.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StrandCoord.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StrandSearch.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TypedMsgHdr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UdsOp.Plo@am__quote@ @@ -439,6 +471,41 @@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< +Page.lo: mem/Page.cc +@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT Page.lo -MD -MP -MF $(DEPDIR)/Page.Tpo -c -o Page.lo `test -f 'mem/Page.cc' || echo '$(srcdir)/'`mem/Page.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/Page.Tpo $(DEPDIR)/Page.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='mem/Page.cc' object='Page.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o Page.lo `test -f 'mem/Page.cc' || echo '$(srcdir)/'`mem/Page.cc + +PagePool.lo: mem/PagePool.cc +@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT PagePool.lo -MD -MP -MF $(DEPDIR)/PagePool.Tpo -c -o PagePool.lo `test -f 'mem/PagePool.cc' || echo '$(srcdir)/'`mem/PagePool.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/PagePool.Tpo $(DEPDIR)/PagePool.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='mem/PagePool.cc' object='PagePool.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o PagePool.lo `test -f 'mem/PagePool.cc' || echo '$(srcdir)/'`mem/PagePool.cc + +Pages.lo: mem/Pages.cc +@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT Pages.lo -MD -MP -MF $(DEPDIR)/Pages.Tpo -c -o Pages.lo `test -f 'mem/Pages.cc' || echo '$(srcdir)/'`mem/Pages.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/Pages.Tpo $(DEPDIR)/Pages.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='mem/Pages.cc' object='Pages.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o Pages.lo `test -f 'mem/Pages.cc' || echo '$(srcdir)/'`mem/Pages.cc + +PageStack.lo: mem/PageStack.cc +@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT PageStack.lo -MD -MP -MF $(DEPDIR)/PageStack.Tpo -c -o PageStack.lo `test -f 'mem/PageStack.cc' || echo '$(srcdir)/'`mem/PageStack.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/PageStack.Tpo $(DEPDIR)/PageStack.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='mem/PageStack.cc' object='PageStack.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o PageStack.lo `test -f 'mem/PageStack.cc' || echo '$(srcdir)/'`mem/PageStack.cc + +Segment.lo: mem/Segment.cc +@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT Segment.lo -MD -MP -MF $(DEPDIR)/Segment.Tpo -c -o Segment.lo `test -f 'mem/Segment.cc' || echo '$(srcdir)/'`mem/Segment.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/Segment.Tpo $(DEPDIR)/Segment.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='mem/Segment.cc' object='Segment.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o Segment.lo `test -f 'mem/Segment.cc' || echo '$(srcdir)/'`mem/Segment.cc + mostlyclean-libtool: -rm -f *.lo diff -u -r -N squid-3.2.0.12/src/ipc/mem/Page.cc squid-3.2.0.13/src/ipc/mem/Page.cc --- squid-3.2.0.12/src/ipc/mem/Page.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/mem/Page.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,19 @@ +/* + * $Id$ + * + * DEBUG: section 54 Interprocess Communication + * + */ + +#include "config.h" +#include "ipc/mem/Page.h" + +#if HAVE_IOSTREAM +#include +#endif + + +std::ostream &Ipc::Mem::operator <<(std::ostream &os, const PageId &page) +{ + return os << "sh_page" << page.pool << '.' << page.number; +} diff -u -r -N squid-3.2.0.12/src/ipc/mem/Page.h squid-3.2.0.13/src/ipc/mem/Page.h --- squid-3.2.0.12/src/ipc/mem/Page.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/mem/Page.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,42 @@ +/* + * $Id$ + * + */ + +#ifndef SQUID_IPC_MEM_PAGE_H +#define SQUID_IPC_MEM_PAGE_H + +#if HAVE_IOSFWD +#include +#endif + +namespace Ipc +{ + +namespace Mem +{ + +/// Shared memory page identifier, address, or handler +class PageId +{ +public: + PageId(): pool(0), number(0), purpose(maxPurpose) {} + + operator bool() const { return pool && number; } + + uint32_t pool; ///< page pool ID within Squid + // uint32_t segment; ///< memory segment ID within the pool; unused for now + uint32_t number; ///< page number within the segment + + enum Purpose { cachePage, ioPage, maxPurpose }; + Purpose purpose; ///< page purpose +}; + +/// writes page address (e.g., "sh_page5.3"), for debugging +std::ostream &operator <<(std::ostream &os, const PageId &page); + +} // namespace Mem + +} // namespace Ipc + +#endif // SQUID_IPC_MEM_PAGE_H diff -u -r -N squid-3.2.0.12/src/ipc/mem/PagePool.cc squid-3.2.0.13/src/ipc/mem/PagePool.cc --- squid-3.2.0.12/src/ipc/mem/PagePool.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/mem/PagePool.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,70 @@ +/* + * $Id$ + * + * DEBUG: section 54 Interprocess Communication + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "ipc/mem/Page.h" +#include "ipc/mem/PagePool.h" + + +// Ipc::Mem::PagePool + +Ipc::Mem::PagePool::Owner * +Ipc::Mem::PagePool::Init(const char *const id, const unsigned int capacity, const size_t pageSize) +{ + static uint32_t LastPagePoolId = 0; + if (++LastPagePoolId == 0) + ++LastPagePoolId; // skip zero pool id + return shm_new(PageStack)(id, LastPagePoolId, capacity, pageSize); +} + +Ipc::Mem::PagePool::PagePool(const char *const id): + pageIndex(shm_old(PageStack)(id)), + theLevels(reinterpret_cast( + reinterpret_cast(pageIndex.getRaw()) + + pageIndex->stackSize())), + theBuf(reinterpret_cast(theLevels + PageId::maxPurpose)) +{ +} + +size_t +Ipc::Mem::PagePool::level(const int purpose) const +{ + Must(0 <= purpose && purpose < PageId::maxPurpose); + return theLevels[purpose]; +} + +bool +Ipc::Mem::PagePool::get(const PageId::Purpose purpose, PageId &page) +{ + Must(0 <= purpose && purpose < PageId::maxPurpose); + if (pageIndex->pop(page)) { + page.purpose = purpose; + ++theLevels[purpose]; + return true; + } + return false; +} + +void +Ipc::Mem::PagePool::put(PageId &page) +{ + if (!page) + return; + + Must(0 <= page.purpose && page.purpose < PageId::maxPurpose); + --theLevels[page.purpose]; + page.purpose = PageId::maxPurpose; + return pageIndex->push(page); +} + +char * +Ipc::Mem::PagePool::pagePointer(const PageId &page) +{ + Must(pageIndex->pageIdIsValid(page)); + return theBuf + pageSize() * (page.number - 1); +} diff -u -r -N squid-3.2.0.12/src/ipc/mem/PagePool.h squid-3.2.0.13/src/ipc/mem/PagePool.h --- squid-3.2.0.12/src/ipc/mem/PagePool.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/mem/PagePool.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,58 @@ +/* + * $Id$ + * + */ + +#ifndef SQUID_IPC_MEM_PAGE_POOL_H +#define SQUID_IPC_MEM_PAGE_POOL_H + +#include "ipc/mem/Page.h" +#include "ipc/mem/PageStack.h" +#include "ipc/mem/Pointer.h" + +namespace Ipc +{ + +namespace Mem +{ + +/// Atomic container of shared memory pages. Implemented using a collection of +/// Segments, each with a PageStack index of free pages. All pools must be +/// created by a single process. +class PagePool +{ +public: + typedef Ipc::Mem::Owner Owner; + + static Owner *Init(const char *const id, const unsigned int capacity, const size_t pageSize); + + PagePool(const char *const id); + + unsigned int capacity() const { return pageIndex->capacity(); } + size_t pageSize() const { return pageIndex->pageSize(); } + /// lower bound for the number of free pages + unsigned int size() const { return pageIndex->size(); } + /// approximate number of shared memory pages used now + size_t level() const { return capacity() - size(); } + /// approximate number of shared memory pages used now for given purpose + size_t level(const int purpose) const; + + /// sets page ID and returns true unless no free pages are found + bool get(const PageId::Purpose purpose, PageId &page); + /// makes identified page available as a free page to future get() callers + void put(PageId &page); + /// converts page handler into a temporary writeable shared memory pointer + char *pagePointer(const PageId &page); + +private: + Ipc::Mem::Pointer pageIndex; ///< free pages index + /// number of shared memory pages used now for each purpose + AtomicWord *const theLevels; + char *const theBuf; ///< pages storage +}; + +} // namespace Mem + +} // namespace Ipc + +#endif // SQUID_IPC_MEM_PAGE_POOL_H diff -u -r -N squid-3.2.0.12/src/ipc/mem/Pages.cc squid-3.2.0.13/src/ipc/mem/Pages.cc --- squid-3.2.0.12/src/ipc/mem/Pages.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/mem/Pages.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,151 @@ +/* + * $Id$ + * + * DEBUG: section 54 Interprocess Communication + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "base/RunnersRegistry.h" +#include "ipc/mem/PagePool.h" +#include "ipc/mem/Pages.h" +#include "structs.h" +#include "SwapDir.h" + +// Uses a single PagePool instance, for now. +// Eventually, we may have pools dedicated to memory caching, disk I/O, etc. + +// TODO: make pool id more unique so it does not conflict with other Squids? +static const char *PagePoolId = "squid-page-pool"; +static Ipc::Mem::PagePool *ThePagePool = 0; + +// TODO: make configurable to avoid waste when mem-cached objects are small/big +size_t +Ipc::Mem::PageSize() +{ + return 32*1024; +} + +bool +Ipc::Mem::GetPage(const PageId::Purpose purpose, PageId &page) +{ + return ThePagePool && PagesAvailable(purpose) > 0 ? + ThePagePool->get(purpose, page) : false; +} + +void +Ipc::Mem::PutPage(PageId &page) +{ + Must(ThePagePool); + ThePagePool->put(page); +} + +char * +Ipc::Mem::PagePointer(const PageId &page) +{ + Must(ThePagePool); + return ThePagePool->pagePointer(page); +} + +size_t +Ipc::Mem::PageLimit() +{ + size_t limit = 0; + for (int i = 0; i < PageId::maxPurpose; ++i) + limit += PageLimit(i); + return limit; +} + +size_t +Ipc::Mem::PageLimit(const int purpose) +{ + switch (purpose) { + case PageId::cachePage: + return Config.memMaxSize > 0 ? Config.memMaxSize / PageSize() : 0; + case PageId::ioPage: + // XXX: this should be independent from memory cache pages + return PageLimit(PageId::cachePage)/2; + default: + Must(false); + } + return 0; +} + +size_t +Ipc::Mem::PageLevel() +{ + return ThePagePool ? ThePagePool->level() : 0; +} + +size_t +Ipc::Mem::PageLevel(const int purpose) +{ + return ThePagePool ? ThePagePool->level(purpose) : 0; +} + +/// initializes shared memory pages +class SharedMemPagesRr: public Ipc::Mem::RegisteredRunner +{ +public: + /* RegisteredRunner API */ + SharedMemPagesRr(): owner(NULL) {} + virtual void run(const RunnerRegistry &); + virtual void create(const RunnerRegistry &); + virtual void open(const RunnerRegistry &); + virtual ~SharedMemPagesRr(); + +private: + Ipc::Mem::PagePool::Owner *owner; +}; + +RunnerRegistrationEntry(rrAfterConfig, SharedMemPagesRr); + + +void +SharedMemPagesRr::run(const RunnerRegistry &r) +{ + if (!UsingSmp()) + return; + + // When cache_dirs start using shared memory pages, they would + // need to communicate their needs to us somehow. + if (Config.memMaxSize <= 0) + return; + + if (Ipc::Mem::PageLimit() <= 0) { + if (IamMasterProcess()) { + debugs(54, DBG_IMPORTANT, "WARNING: mem-cache size is too small (" + << (Config.memMaxSize / 1024.0) << " KB), should be >= " << + (Ipc::Mem::PageSize() / 1024.0) << " KB"); + } + return; + } + + Ipc::Mem::RegisteredRunner::run(r); +} + +void +SharedMemPagesRr::create(const RunnerRegistry &) +{ + Must(!owner); + owner = Ipc::Mem::PagePool::Init(PagePoolId, Ipc::Mem::PageLimit(), + Ipc::Mem::PageSize()); +} + +void +SharedMemPagesRr::open(const RunnerRegistry &) +{ + Must(!ThePagePool); + ThePagePool = new Ipc::Mem::PagePool(PagePoolId); +} + +SharedMemPagesRr::~SharedMemPagesRr() +{ + if (!UsingSmp()) + return; + + delete ThePagePool; + ThePagePool = NULL; + delete owner; +} diff -u -r -N squid-3.2.0.12/src/ipc/mem/Pages.h squid-3.2.0.13/src/ipc/mem/Pages.h --- squid-3.2.0.12/src/ipc/mem/Pages.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/mem/Pages.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,58 @@ +/* + * $Id$ + * + */ + +#ifndef SQUID_IPC_MEM_PAGES_H +#define SQUID_IPC_MEM_PAGES_H + +#include "ipc/mem/Page.h" + +namespace Ipc +{ + +namespace Mem +{ + +/* Single page manipulation */ + +/// sets page ID and returns true unless no free pages are found +bool GetPage(const PageId::Purpose purpose, PageId &page); + +/// makes identified page available as a free page to future GetPage() callers +void PutPage(PageId &page); + +/// converts page handler into a temporary writeable shared memory pointer +char *PagePointer(const PageId &page); + + +/* Limits and statistics */ + +/// the total number of shared memory pages that can be in use at any time +size_t PageLimit(); + +/// the total number of shared memory pages that can be in use at any +/// time for given purpose +size_t PageLimit(const int purpose); + +/// approximate total number of shared memory pages used now +size_t PageLevel(); + +/// approximate total number of shared memory pages used now for given purpose +size_t PageLevel(const int purpose); + +/// approximate total number of shared memory pages we can allocate now +inline size_t PagesAvailable() { return PageLimit() - PageLevel(); } + +/// approximate total number of shared memory pages we can allocate +/// now for given purpose +inline size_t PagesAvailable(const int purpose) { return PageLimit(purpose) - PageLevel(purpose); } + +/// returns page size in bytes; all pages are assumed to be the same size +size_t PageSize(); + +} // namespace Mem + +} // namespace Ipc + +#endif // SQUID_IPC_MEM_PAGES_H diff -u -r -N squid-3.2.0.12/src/ipc/mem/PageStack.cc squid-3.2.0.13/src/ipc/mem/PageStack.cc --- squid-3.2.0.12/src/ipc/mem/PageStack.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/mem/PageStack.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,131 @@ +/* + * $Id$ + * + * DEBUG: section 54 Interprocess Communication + * + */ + +#include "config.h" + +#include "base/TextException.h" +#include "ipc/mem/Page.h" +#include "ipc/mem/PageStack.h" + +/// used to mark a stack slot available for storing free page offsets +const Ipc::Mem::PageStack::Value Writable = 0; + + +Ipc::Mem::PageStack::PageStack(const uint32_t aPoolId, const unsigned int aCapacity, const size_t aPageSize): + thePoolId(aPoolId), theCapacity(aCapacity), thePageSize(aPageSize), + theSize(theCapacity), + theLastReadable(prev(theSize)), theFirstWritable(next(theLastReadable)) +{ + // initially, all pages are free + for (Offset i = 0; i < theSize; ++i) + theItems[i] = i + 1; // skip page number zero to keep numbers positive +} + +/* + * TODO: We currently rely on the theLastReadable hint during each + * loop iteration. We could also use hint just for the start position: + * (const Offset start = theLastReadable) and then scan the stack + * sequentially regardless of theLastReadable changes by others. Which + * approach is better? Same for push(). + */ +bool +Ipc::Mem::PageStack::pop(PageId &page) +{ + Must(!page); + + // we may fail to dequeue, but be conservative to prevent long searches + --theSize; + + // find a Readable slot, starting with theLastReadable and going left + while (theSize >= 0) { + const Offset idx = theLastReadable; + // mark the slot at ids Writable while extracting its current value + const Value value = theItems[idx].fetchAndAnd(0); // works if Writable is 0 + const bool popped = value != Writable; + // theItems[idx] is probably not Readable [any more] + + // Whether we popped a Readable value or not, we should try going left + // to maintain the index (and make progress). + // We may fail if others already updated the index, but that is OK. + theLastReadable.swap_if(idx, prev(idx)); // may fail or lie + + if (popped) { + // the slot we emptied may already be filled, but that is OK + theFirstWritable = idx; // may lie + page.pool = thePoolId; + page.number = value; + return true; + } + // TODO: report suspiciously long loops + } + + ++theSize; + return false; +} + +void +Ipc::Mem::PageStack::push(PageId &page) +{ + if (!page) + return; + + Must(pageIdIsValid(page)); + // find a Writable slot, starting with theFirstWritable and going right + while (theSize < theCapacity) { + const Offset idx = theFirstWritable; + const bool pushed = theItems[idx].swap_if(Writable, page.number); + // theItems[idx] is probably not Writable [any more]; + + // Whether we pushed the page number or not, we should try going right + // to maintain the index (and make progress). + // We may fail if others already updated the index, but that is OK. + theFirstWritable.swap_if(idx, next(idx)); // may fail or lie + + if (pushed) { + // the enqueued value may already by gone, but that is OK + theLastReadable = idx; // may lie + ++theSize; + page = PageId(); + return; + } + // TODO: report suspiciously long loops + } + Must(false); // the number of pages cannot exceed theCapacity +} + +bool +Ipc::Mem::PageStack::pageIdIsValid(const PageId &page) const +{ + return page.pool == thePoolId && page.number != Writable && + page.number <= capacity(); +} + +size_t +Ipc::Mem::PageStack::sharedMemorySize() const +{ + return SharedMemorySize(thePoolId, theCapacity, thePageSize); +} + +size_t +Ipc::Mem::PageStack::SharedMemorySize(const uint32_t, const unsigned int capacity, const size_t pageSize) +{ + const size_t levelsSize = PageId::maxPurpose * sizeof(AtomicWord); + const size_t pagesDataSize = capacity * pageSize; + return StackSize(capacity) + pagesDataSize + levelsSize; +} + +size_t +Ipc::Mem::PageStack::StackSize(const unsigned int capacity) +{ + return sizeof(PageStack) + capacity * sizeof(Item); +} + +size_t +Ipc::Mem::PageStack::stackSize() const +{ + return StackSize(theCapacity); +} diff -u -r -N squid-3.2.0.12/src/ipc/mem/PageStack.h squid-3.2.0.13/src/ipc/mem/PageStack.h --- squid-3.2.0.12/src/ipc/mem/PageStack.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/mem/PageStack.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,77 @@ +/* + * $Id$ + * + */ + +#ifndef SQUID_IPC_MEM_PAGE_STACK_H +#define SQUID_IPC_MEM_PAGE_STACK_H + +#include "ipc/AtomicWord.h" + +namespace Ipc +{ + +namespace Mem +{ + +class PageId; + +/// Atomic container of "free" page numbers inside a single SharedMemory space. +/// Assumptions: all page numbers are unique, positive, have an known maximum, +/// and can be temporary unavailable as long as they are never trully lost. +class PageStack +{ +public: + typedef uint32_t Value; ///< stack item type (a free page number) + + PageStack(const uint32_t aPoolId, const unsigned int aCapacity, const size_t aPageSize); + + unsigned int capacity() const { return theCapacity; } + size_t pageSize() const { return thePageSize; } + /// lower bound for the number of free pages + unsigned int size() const { return max(0, theSize.get()); } + + /// sets value and returns true unless no free page numbers are found + bool pop(PageId &page); + /// makes value available as a free page number to future pop() callers + void push(PageId &page); + + bool pageIdIsValid(const PageId &page) const; + + /// total shared memory size required to share + static size_t SharedMemorySize(const uint32_t aPoolId, const unsigned int capacity, const size_t pageSize); + size_t sharedMemorySize() const; + + /// shared memory size required only by PageStack, excluding + /// shared counters and page data + static size_t StackSize(const unsigned int capacity); + size_t stackSize() const; + +private: + /// stack index and size type (may temporary go negative) + typedef int Offset; + + // these help iterate the stack in search of a free spot or a page + Offset next(const Offset idx) const { return (idx + 1) % theCapacity; } + Offset prev(const Offset idx) const { return (theCapacity + idx - 1) % theCapacity; } + + const uint32_t thePoolId; ///< pool ID + const Offset theCapacity; ///< stack capacity, i.e. theItems size + const size_t thePageSize; ///< page size, used to calculate shared memory size + /// lower bound for the number of free pages (may get negative!) + AtomicWordT theSize; + + /// last readable item index; just a hint, not a guarantee + AtomicWordT theLastReadable; + /// first writable item index; just a hint, not a guarantee + AtomicWordT theFirstWritable; + + typedef AtomicWordT Item; + Item theItems[]; ///< page number storage +}; + +} // namespace Mem + +} // namespace Ipc + +#endif // SQUID_IPC_MEM_PAGE_STACK_H diff -u -r -N squid-3.2.0.12/src/ipc/mem/Pointer.h squid-3.2.0.13/src/ipc/mem/Pointer.h --- squid-3.2.0.12/src/ipc/mem/Pointer.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/mem/Pointer.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,180 @@ +/* + * $Id$ + * + */ + +#ifndef SQUID_IPC_MEM_POINTER_H +#define SQUID_IPC_MEM_POINTER_H + +#include "base/TextException.h" +#include "ipc/mem/Segment.h" +#include "RefCount.h" + +namespace Ipc +{ + +namespace Mem +{ + +/// allocates/deallocates shared memory; creates and later destroys a +/// Class object using that memory +template +class Owner +{ +public: + static Owner *New(const char *const id); + template + static Owner *New(const char *const id, const P1 &p1); + template + static Owner *New(const char *const id, const P1 &p1, const P2 &p2); + template + static Owner *New(const char *const id, const P1 &p1, const P2 &p2, const P3 &p3); + template + static Owner *New(const char *const id, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4); + + ~Owner(); + +private: + Owner(const char *const id, const off_t sharedSize); + + // not implemented + Owner(const Owner &); + Owner &operator =(const Owner &); + + Segment theSegment; ///< shared memory segment that holds the object + Class *theObject; ///< shared object +}; + +template class Pointer; + +/// attaches to a shared memory segment with Class object owned by Owner +template +class Object: public RefCountable +{ +public: + static Pointer Old(const char *const id); + +private: + explicit Object(const char *const id); + + // not implemented + Object(const Object &); + Object &operator =(const Object &); + + Segment theSegment; ///< shared memory segment that holds the object + Class *theObject; ///< shared object + + friend class Pointer; +}; + +/// uses a refcounted pointer to Object as a parent, but +/// translates its API to return raw Class pointers +template +class Pointer: public RefCount< Object > +{ +private: + typedef RefCount< Object > Base; + +public: + explicit Pointer(Object *const anObject = NULL): Base(anObject) {} + + Class *operator ->() const { return Base::operator ->()->theObject; } + Class &operator *() const { return *Base::operator *().theObject; } + const Class *getRaw() const { return Base::getRaw()->theObject; } + Class *getRaw() { return Base::getRaw()->theObject; } +}; + +// Owner implementation + +template +Owner::Owner(const char *const id, const off_t sharedSize): + theSegment(id), theObject(NULL) +{ + theSegment.create(sharedSize); + Must(theSegment.mem()); +} + +template +Owner::~Owner() +{ + if (theObject) + theObject->~Class(); +} + +template +Owner * +Owner::New(const char *const id) +{ + const off_t sharedSize = Class::SharedMemorySize(); + Owner *const owner = new Owner(id, sharedSize); + owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class; + return owner; +} + +template template +Owner * +Owner::New(const char *const id, const P1 &p1) +{ + const off_t sharedSize = Class::SharedMemorySize(p1); + Owner *const owner = new Owner(id, sharedSize); + owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1); + return owner; +} + +template template +Owner * +Owner::New(const char *const id, const P1 &p1, const P2 &p2) +{ + const off_t sharedSize = Class::SharedMemorySize(p1, p2); + Owner *const owner = new Owner(id, sharedSize); + owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1, p2); + return owner; +} + +template template +Owner * +Owner::New(const char *const id, const P1 &p1, const P2 &p2, const P3 &p3) +{ + const off_t sharedSize = Class::SharedMemorySize(p1, p2, p3); + Owner *const owner = new Owner(id, sharedSize); + owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1, p2, p3); + return owner; +} + +template template +Owner * +Owner::New(const char *const id, const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4) +{ + const off_t sharedSize = Class::SharedMemorySize(p1, p2, p3, p4); + Owner *const owner = new Owner(id, sharedSize); + owner->theObject = new (owner->theSegment.reserve(sharedSize)) Class(p1, p2, p3, p4); + return owner; +} + +// Object implementation + +template +Object::Object(const char *const id): theSegment(id) +{ + theSegment.open(); + Must(theSegment.mem()); + theObject = reinterpret_cast(theSegment.mem()); + Must(static_cast(theObject->sharedMemorySize()) == theSegment.size()); +} + +template +Pointer +Object::Old(const char *const id) +{ + return Pointer(new Object(id)); +} + +// convenience macros for creating shared objects +#define shm_new(Class) Ipc::Mem::Owner::New +#define shm_old(Class) Ipc::Mem::Object::Old + +} // namespace Mem + +} // namespace Ipc + +#endif /* SQUID_IPC_MEM_POINTER_H */ diff -u -r -N squid-3.2.0.12/src/ipc/mem/Segment.cc squid-3.2.0.13/src/ipc/mem/Segment.cc --- squid-3.2.0.12/src/ipc/mem/Segment.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/mem/Segment.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,278 @@ +/* + * $Id$ + * + * DEBUG: section 54 Interprocess Communication + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "compat/shm.h" +#include "ipc/mem/Segment.h" +#include "protos.h" + +#include +#include +#include +#include + +void * +Ipc::Mem::Segment::reserve(size_t chunkSize) +{ + Must(theMem); + // check for overflows + // chunkSize >= 0 may result in warnings on systems where off_t is unsigned + assert(!chunkSize || static_cast(chunkSize) > 0); + assert(static_cast(chunkSize) <= theSize); + assert(theReserved <= theSize - static_cast(chunkSize)); + void *result = reinterpret_cast(theMem) + theReserved; + theReserved += chunkSize; + return result; +} + +#if HAVE_SHM + +Ipc::Mem::Segment::Segment(const char *const id): + theFD(-1), theName(GenerateName(id)), theMem(NULL), + theSize(0), theReserved(0), doUnlink(false) +{ +} + +Ipc::Mem::Segment::~Segment() +{ + if (theFD >= 0) { + detach(); + if (close(theFD) != 0) + debugs(54, 5, HERE << "close " << theName << ": " << xstrerror()); + } + if (doUnlink) + unlink(); +} + +// fake Ipc::Mem::Segment::Enabled (!HAVE_SHM) is more selective +bool +Ipc::Mem::Segment::Enabled() +{ + return true; +} + +void +Ipc::Mem::Segment::create(const off_t aSize) +{ + assert(aSize > 0); + assert(theFD < 0); + + theFD = shm_open(theName.termedBuf(), O_CREAT | O_RDWR | O_TRUNC, + S_IRUSR | S_IWUSR); + if (theFD < 0) { + debugs(54, 5, HERE << "shm_open " << theName << ": " << xstrerror()); + fatal("Ipc::Mem::Segment::create failed to shm_open"); + } + + if (ftruncate(theFD, aSize)) { + debugs(54, 5, HERE << "ftruncate " << theName << ": " << xstrerror()); + fatal("Ipc::Mem::Segment::create failed to ftruncate"); + } + + assert(statSize("Ipc::Mem::Segment::create") == aSize); // paranoid + + theSize = aSize; + theReserved = 0; + doUnlink = true; + + debugs(54, 3, HERE << "created " << theName << " segment: " << theSize); + + attach(); +} + +void +Ipc::Mem::Segment::open() +{ + assert(theFD < 0); + + theFD = shm_open(theName.termedBuf(), O_RDWR, 0); + if (theFD < 0) { + debugs(54, 5, HERE << "shm_open " << theName << ": " << xstrerror()); + String s = "Ipc::Mem::Segment::open failed to shm_open "; + s.append(theName); + fatal(s.termedBuf()); + } + + theSize = statSize("Ipc::Mem::Segment::open"); + + debugs(54, 3, HERE << "opened " << theName << " segment: " << theSize); + + attach(); +} + +/// Map the shared memory segment to the process memory space. +void +Ipc::Mem::Segment::attach() +{ + assert(theFD >= 0); + assert(!theMem); + + // mmap() accepts size_t for the size; we give it off_t which might + // be bigger; assert overflows until we support multiple mmap()s? + assert(theSize == static_cast(static_cast(theSize))); + + void *const p = + mmap(NULL, theSize, PROT_READ | PROT_WRITE, MAP_SHARED, theFD, 0); + if (p == MAP_FAILED) { + debugs(54, 5, HERE << "mmap " << theName << ": " << xstrerror()); + fatal("Ipc::Mem::Segment::attach failed to mmap"); + } + theMem = p; +} + +/// Unmap the shared memory segment from the process memory space. +void +Ipc::Mem::Segment::detach() +{ + if (!theMem) + return; + + if (munmap(theMem, theSize)) { + debugs(54, 5, HERE << "munmap " << theName << ": " << xstrerror()); + fatal("Ipc::Mem::Segment::detach failed to munmap"); + } + theMem = 0; +} + +void +Ipc::Mem::Segment::unlink() +{ + if (shm_unlink(theName.termedBuf()) != 0) + debugs(54, 5, HERE << "shm_unlink(" << theName << "): " << xstrerror()); + else + debugs(54, 3, HERE << "unlinked " << theName << " segment"); +} + +/// determines the size of the underlying "file" +off_t +Ipc::Mem::Segment::statSize(const char *context) const +{ + Must(theFD >= 0); + + struct stat s; + memset(&s, 0, sizeof(s)); + + if (fstat(theFD, &s) != 0) { + debugs(54, 5, HERE << "fstat " << theName << ": " << xstrerror()); + String s = context; + s.append("failed to fstat(2) "); + s.append(theName); + fatal(s.termedBuf()); + } + + return s.st_size; +} + +/// Generate name for shared memory segment. Replaces all slashes with dots. +String +Ipc::Mem::Segment::GenerateName(const char *id) +{ + String name("/squid-"); + for (const char *slash = strchr(id, '/'); slash; slash = strchr(id, '/')) { + if (id != slash) { + name.append(id, slash - id); + name.append('.'); + } + id = slash + 1; + } + name.append(id); + return name; +} + +#else // HAVE_SHM + +#include + +typedef std::map SegmentMap; +static SegmentMap Segments; + +Ipc::Mem::Segment::Segment(const char *const id): + theName(id), theMem(NULL), theSize(0), theReserved(0), doUnlink(false) +{ +} + +Ipc::Mem::Segment::~Segment() +{ + if (doUnlink) { + delete [] static_cast(theMem); + debugs(54, 3, HERE << "deleted " << theName << " segment"); + } +} + +bool +Ipc::Mem::Segment::Enabled() +{ + return !InDaemonMode() || (!UsingSmp() && IamWorkerProcess()); +} + +void +Ipc::Mem::Segment::create(const off_t aSize) +{ + assert(aSize > 0); + assert(!theMem); + checkSupport("Fake segment creation"); + + const bool inserted = Segments.insert(std::make_pair(theName, this)).second; + if (!inserted) + fatalf("Duplicate fake segment creation: %s", theName.termedBuf()); + + theMem = new char[aSize]; + theSize = aSize; + doUnlink = true; + + debugs(54, 3, HERE << "created " << theName << " fake segment: " << theSize); +} + +void +Ipc::Mem::Segment::open() +{ + assert(!theMem); + checkSupport("Fake segment open"); + + const SegmentMap::const_iterator i = Segments.find(theName); + if (i == Segments.end()) + fatalf("Fake segment not found: %s", theName.termedBuf()); + + const Segment &segment = *i->second; + theMem = segment.theMem; + theSize = segment.theSize; + + debugs(54, 3, HERE << "opened " << theName << " fake segment: " << theSize); +} + +void +Ipc::Mem::Segment::checkSupport(const char *const context) +{ + if (!Enabled()) { + debugs(54, 5, HERE << "True shared memory segments are not supported. " + "Cannot fake shared segments in SMP config."); + fatalf("%s failed", context); + } +} + +#endif // HAVE_SHM + +void +Ipc::Mem::RegisteredRunner::run(const RunnerRegistry &r) +{ + // If Squid is built with real segments, we create() real segments + // in the master process only. Otherwise, we create() fake + // segments in each worker process. We assume that only workers + // need and can work with fake segments. +#if HAVE_SHM + if (IamMasterProcess()) +#else + if (IamWorkerProcess()) +#endif + create(r); + + // we assume that master process does not need shared segments + // unless it is also a worker + if (!InDaemonMode() || !IamMasterProcess()) + open(r); +} diff -u -r -N squid-3.2.0.12/src/ipc/mem/Segment.h squid-3.2.0.13/src/ipc/mem/Segment.h --- squid-3.2.0.12/src/ipc/mem/Segment.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/mem/Segment.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,89 @@ +/* + * $Id$ + * + */ + +#ifndef SQUID_IPC_MEM_SEGMENT_H +#define SQUID_IPC_MEM_SEGMENT_H + +#include "base/RunnersRegistry.h" +#include "SquidString.h" + +namespace Ipc +{ + +namespace Mem +{ + +/// POSIX shared memory segment +class Segment +{ +public: + /// Create a shared memory segment. + Segment(const char *const id); + ~Segment(); + + /// Whether shared memory support is available + static bool Enabled(); + + /// Create a new shared memory segment. Unlinks the segment on destruction. + void create(const off_t aSize); + void open(); ///< Open an existing shared memory segment. + + const String &name() { return theName; } ///< shared memory segment name + off_t size() { return theSize; } ///< shared memory segment size + void *mem() { return reserve(0); } ///< pointer to the next chunk + void *reserve(size_t chunkSize); ///< reserve and return the next chunk + + +private: + + // not implemented + Segment(const Segment &); + Segment &operator =(const Segment &); + +#if HAVE_SHM + + void attach(); + void detach(); + void unlink(); ///< unlink the segment + off_t statSize(const char *context) const; + + static String GenerateName(const char *id); + + int theFD; ///< shared memory segment file descriptor + +#else // HAVE_SHM + + void checkSupport(const char *const context); + +#endif // HAVE_SHM + + const String theName; ///< shared memory segment file name + void *theMem; ///< pointer to mmapped shared memory segment + off_t theSize; ///< shared memory segment size + off_t theReserved; ///< the total number of reserve()d bytes + bool doUnlink; ///< whether the segment should be unlinked on destruction +}; + +/// Base class for runners that create and open shared memory segments. +/// First may run create() method and then open(). +class RegisteredRunner: public ::RegisteredRunner +{ +public: + /* RegisteredRunner API */ + virtual void run(const RunnerRegistry &r); + +protected: + /// called when the runner should create a new memory segment + virtual void create(const RunnerRegistry &) = 0; + /// called when the runner should open a previously created segment, + /// not needed if segments are opened in constructor or init methods + virtual void open(const RunnerRegistry &) {} +}; + +} // namespace Mem + +} // namespace Ipc + +#endif /* SQUID_IPC_MEM_SEGMENT_H */ diff -u -r -N squid-3.2.0.12/src/ipc/Messages.h squid-3.2.0.13/src/ipc/Messages.h --- squid-3.2.0.12/src/ipc/Messages.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ipc/Messages.h 2011-10-14 14:42:56.000000000 +1300 @@ -15,7 +15,9 @@ /// message class identifier typedef enum { mtNone = 0, mtRegistration, + mtStrandSearchRequest, mtStrandSearchResponse, mtSharedListenRequest, mtSharedListenResponse, + mtIpcIoNotification, mtCacheMgrRequest, mtCacheMgrResponse #if SQUID_SNMP , diff -u -r -N squid-3.2.0.12/src/ipc/Queue.cc squid-3.2.0.13/src/ipc/Queue.cc --- squid-3.2.0.12/src/ipc/Queue.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/Queue.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,285 @@ +/* + * $Id$ + * + * DEBUG: section 54 Interprocess Communication + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "Debug.h" +#include "globals.h" +#include "ipc/Queue.h" + +/// constructs Metadata ID from parent queue ID +static String +MetadataId(String id) +{ + id.append("__metadata"); + return id; +} + +/// constructs one-to-one queues ID from parent queue ID +static String +QueuesId(String id) +{ + id.append("__queues"); + return id; +} + +/// constructs QueueReaders ID from parent queue ID +static String +ReadersId(String id) +{ + id.append("__readers"); + return id; +} + + +/* QueueReader */ + +InstanceIdDefinitions(Ipc::QueueReader, "ipcQR"); + +Ipc::QueueReader::QueueReader(): popBlocked(1), popSignal(0), + rateLimit(0), balance(0) +{ + debugs(54, 7, HERE << "constructed " << id); +} + +/* QueueReaders */ + +Ipc::QueueReaders::QueueReaders(const int aCapacity): theCapacity(aCapacity) +{ + Must(theCapacity > 0); + new (theReaders) QueueReader[theCapacity]; +} + +size_t +Ipc::QueueReaders::sharedMemorySize() const +{ + return SharedMemorySize(theCapacity); +} + +size_t +Ipc::QueueReaders::SharedMemorySize(const int capacity) +{ + return sizeof(QueueReaders) + sizeof(QueueReader) * capacity; +} + + +// OneToOneUniQueue + +Ipc::OneToOneUniQueue::OneToOneUniQueue(const unsigned int aMaxItemSize, const int aCapacity): + theIn(0), theOut(0), theSize(0), theMaxItemSize(aMaxItemSize), + theCapacity(aCapacity) +{ + Must(theMaxItemSize > 0); + Must(theCapacity > 0); +} + +int +Ipc::OneToOneUniQueue::Bytes2Items(const unsigned int maxItemSize, int size) +{ + assert(maxItemSize > 0); + size -= sizeof(OneToOneUniQueue); + return size >= 0 ? size / maxItemSize : 0; +} + +int +Ipc::OneToOneUniQueue::Items2Bytes(const unsigned int maxItemSize, const int size) +{ + assert(size >= 0); + return sizeof(OneToOneUniQueue) + maxItemSize * size; +} + + +/* OneToOneUniQueues */ + +Ipc::OneToOneUniQueues::OneToOneUniQueues(const int aCapacity, const unsigned int maxItemSize, const int queueCapacity): theCapacity(aCapacity) +{ + Must(theCapacity > 0); + for (int i = 0; i < theCapacity; ++i) + new (&(*this)[i]) OneToOneUniQueue(maxItemSize, queueCapacity); +} + +size_t +Ipc::OneToOneUniQueues::sharedMemorySize() const +{ + return sizeof(*this) + theCapacity * front().sharedMemorySize(); +} + +size_t +Ipc::OneToOneUniQueues::SharedMemorySize(const int capacity, const unsigned int maxItemSize, const int queueCapacity) +{ + const int queueSize = + OneToOneUniQueue::Items2Bytes(maxItemSize, queueCapacity); + return sizeof(OneToOneUniQueues) + queueSize * capacity; +} + +const Ipc::OneToOneUniQueue & +Ipc::OneToOneUniQueues::operator [](const int index) const +{ + Must(0 <= index && index < theCapacity); + const size_t queueSize = index ? front().sharedMemorySize() : 0; + const char *const queue = + reinterpret_cast(this) + sizeof(*this) + index * queueSize; + return *reinterpret_cast(queue); +} + + +// FewToFewBiQueue + +Ipc::FewToFewBiQueue::Owner * +Ipc::FewToFewBiQueue::Init(const String &id, const int groupASize, const int groupAIdOffset, const int groupBSize, const int groupBIdOffset, const unsigned int maxItemSize, const int capacity) +{ + return new Owner(id, groupASize, groupAIdOffset, groupBSize, groupBIdOffset, maxItemSize, capacity); +} + +Ipc::FewToFewBiQueue::FewToFewBiQueue(const String &id, const Group aLocalGroup, const int aLocalProcessId): + metadata(shm_old(Metadata)(MetadataId(id).termedBuf())), + queues(shm_old(OneToOneUniQueues)(QueuesId(id).termedBuf())), + readers(shm_old(QueueReaders)(ReadersId(id).termedBuf())), + theLocalGroup(aLocalGroup), theLocalProcessId(aLocalProcessId), + theLastPopProcessId(readers->theCapacity) +{ + Must(queues->theCapacity == metadata->theGroupASize * metadata->theGroupBSize * 2); + Must(readers->theCapacity == metadata->theGroupASize + metadata->theGroupBSize); + + const QueueReader &localReader = reader(theLocalGroup, theLocalProcessId); + debugs(54, 7, HERE << "queue " << id << " reader: " << localReader.id); +} + +bool +Ipc::FewToFewBiQueue::validProcessId(const Group group, const int processId) const +{ + switch (group) { + case groupA: + return metadata->theGroupAIdOffset <= processId && + processId < metadata->theGroupAIdOffset + metadata->theGroupASize; + case groupB: + return metadata->theGroupBIdOffset <= processId && + processId < metadata->theGroupBIdOffset + metadata->theGroupBSize; + } + return false; +} + +int +Ipc::FewToFewBiQueue::oneToOneQueueIndex(const Group fromGroup, const int fromProcessId, const Group toGroup, const int toProcessId) const +{ + Must(fromGroup != toGroup); + assert(validProcessId(fromGroup, fromProcessId)); + assert(validProcessId(toGroup, toProcessId)); + int index1; + int index2; + int offset; + if (fromGroup == groupA) { + index1 = fromProcessId - metadata->theGroupAIdOffset; + index2 = toProcessId - metadata->theGroupBIdOffset; + offset = 0; + } else { + index1 = toProcessId - metadata->theGroupAIdOffset; + index2 = fromProcessId - metadata->theGroupBIdOffset; + offset = metadata->theGroupASize * metadata->theGroupBSize; + } + const int index = offset + index1 * metadata->theGroupBSize + index2; + return index; +} + +Ipc::OneToOneUniQueue & +Ipc::FewToFewBiQueue::oneToOneQueue(const Group fromGroup, const int fromProcessId, const Group toGroup, const int toProcessId) +{ + return (*queues)[oneToOneQueueIndex(fromGroup, fromProcessId, toGroup, toProcessId)]; +} + +const Ipc::OneToOneUniQueue & +Ipc::FewToFewBiQueue::oneToOneQueue(const Group fromGroup, const int fromProcessId, const Group toGroup, const int toProcessId) const +{ + return (*queues)[oneToOneQueueIndex(fromGroup, fromProcessId, toGroup, toProcessId)]; +} + +int +Ipc::FewToFewBiQueue::readerIndex(const Group group, const int processId) const +{ + Must(validProcessId(group, processId)); + return group == groupA ? + processId - metadata->theGroupAIdOffset : + metadata->theGroupASize + processId - metadata->theGroupBIdOffset; +} + +Ipc::QueueReader & +Ipc::FewToFewBiQueue::reader(const Group group, const int processId) +{ + return readers->theReaders[readerIndex(group, processId)]; +} + +const Ipc::QueueReader & +Ipc::FewToFewBiQueue::reader(const Group group, const int processId) const +{ + return readers->theReaders[readerIndex(group, processId)]; +} + +void +Ipc::FewToFewBiQueue::clearReaderSignal(const int remoteProcessId) +{ + QueueReader &localReader = reader(theLocalGroup, theLocalProcessId); + debugs(54, 7, HERE << "reader: " << localReader.id); + + Must(validProcessId(remoteGroup(), remoteProcessId)); + localReader.clearSignal(); + + // we got a hint; we could reposition iteration to try popping from the + // remoteProcessId queue first; but it does not seem to help much and might + // introduce some bias so we do not do that for now: + // theLastPopProcessId = remoteProcessId; +} + +bool +Ipc::FewToFewBiQueue::popReady() const +{ + // mimic FewToFewBiQueue::pop() but quit just before popping + int popProcessId = theLastPopProcessId; // preserve for future pop() + for (int i = 0; i < remoteGroupSize(); ++i) { + if (++popProcessId >= remoteGroupIdOffset() + remoteGroupSize()) + popProcessId = remoteGroupIdOffset(); + const OneToOneUniQueue &queue = oneToOneQueue(remoteGroup(), popProcessId, theLocalGroup, theLocalProcessId); + if (!queue.empty()) + return true; + } + return false; // most likely, no process had anything to pop +} + +Ipc::QueueReader::Balance & +Ipc::FewToFewBiQueue::localBalance() +{ + QueueReader &r = reader(theLocalGroup, theLocalProcessId); + return r.balance; +} + +Ipc::QueueReader::Rate & +Ipc::FewToFewBiQueue::localRateLimit() +{ + QueueReader &r = reader(theLocalGroup, theLocalProcessId); + return r.rateLimit; +} + +Ipc::FewToFewBiQueue::Metadata::Metadata(const int aGroupASize, const int aGroupAIdOffset, const int aGroupBSize, const int aGroupBIdOffset): + theGroupASize(aGroupASize), theGroupAIdOffset(aGroupAIdOffset), + theGroupBSize(aGroupBSize), theGroupBIdOffset(aGroupBIdOffset) +{ + Must(theGroupASize > 0); + Must(theGroupBSize > 0); +} + +Ipc::FewToFewBiQueue::Owner::Owner(const String &id, const int groupASize, const int groupAIdOffset, const int groupBSize, const int groupBIdOffset, const unsigned int maxItemSize, const int capacity): + metadataOwner(shm_new(Metadata)(MetadataId(id).termedBuf(), groupASize, groupAIdOffset, groupBSize, groupBIdOffset)), + queuesOwner(shm_new(OneToOneUniQueues)(QueuesId(id).termedBuf(), groupASize*groupBSize*2, maxItemSize, capacity)), + readersOwner(shm_new(QueueReaders)(ReadersId(id).termedBuf(), groupASize+groupBSize)) +{ +} + +Ipc::FewToFewBiQueue::Owner::~Owner() +{ + delete metadataOwner; + delete queuesOwner; + delete readersOwner; +} diff -u -r -N squid-3.2.0.12/src/ipc/Queue.h squid-3.2.0.13/src/ipc/Queue.h --- squid-3.2.0.12/src/ipc/Queue.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/Queue.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,373 @@ +/* + * $Id$ + * + */ + +#ifndef SQUID_IPC_QUEUE_H +#define SQUID_IPC_QUEUE_H + +#include "Array.h" +#include "Debug.h" +#include "base/InstanceId.h" +#include "ipc/AtomicWord.h" +#include "ipc/mem/Pointer.h" +#include "util.h" + +class String; + +namespace Ipc +{ + +/// State of the reading end of a queue (i.e., of the code calling pop()). +/// Multiple queues attached to one reader share this state. +class QueueReader +{ +public: + QueueReader(); // the initial state is "blocked without a signal" + + /// whether the reader is waiting for a notification signal + bool blocked() const { return popBlocked == 1; } + + /// marks the reader as blocked, waiting for a notification signal + void block() { popBlocked.swap_if(0, 1); } + + /// removes the block() effects + void unblock() { popBlocked.swap_if(1, 0); } + + /// if reader is blocked and not notified, marks the notification signal + /// as sent and not received, returning true; otherwise, returns false + bool raiseSignal() { return blocked() && popSignal.swap_if(0,1); } + + /// marks sent reader notification as received (also removes pop blocking) + void clearSignal() { unblock(); popSignal.swap_if(1,0); } + +private: + AtomicWord popBlocked; ///< whether the reader is blocked on pop() + AtomicWord popSignal; ///< whether writer has sent and reader has not received notification + +public: + typedef AtomicWord Rate; ///< pop()s per second + Rate rateLimit; ///< pop()s per second limit if positive + + // we need a signed atomic type because balance may get negative + typedef AtomicWordT AtomicSignedMsec; + typedef AtomicSignedMsec Balance; + /// how far ahead the reader is compared to a perfect read/sec event rate + Balance balance; + + /// unique ID for debugging which reader is used (works across processes) + const InstanceId id; +}; + +/// shared array of QueueReaders +class QueueReaders +{ +public: + QueueReaders(const int aCapacity); + size_t sharedMemorySize() const; + static size_t SharedMemorySize(const int capacity); + + const int theCapacity; /// number of readers + QueueReader theReaders[]; /// readers +}; + +/** + * Lockless fixed-capacity queue for a single writer and a single reader. + * + * If the queue is empty, the reader is considered "blocked" and needs + * an out-of-band notification message to notice the next pushed item. + * + * Current implementation assumes that the writer cannot get blocked: if the + * queue is full, the writer will just not push and come back later (with a + * different value). We can add support for blocked writers if needed. + */ +class OneToOneUniQueue +{ +public: + // pop() and push() exceptions; TODO: use TextException instead + class Full {}; + class ItemTooLarge {}; + + OneToOneUniQueue(const unsigned int aMaxItemSize, const int aCapacity); + + unsigned int maxItemSize() const { return theMaxItemSize; } + int size() const { return theSize; } + int capacity() const { return theCapacity; } + int sharedMemorySize() const { return Items2Bytes(theMaxItemSize, theCapacity); } + + bool empty() const { return !theSize; } + bool full() const { return theSize == theCapacity; } + + static int Bytes2Items(const unsigned int maxItemSize, int size); + static int Items2Bytes(const unsigned int maxItemSize, const int size); + + /// returns true iff the value was set; [un]blocks the reader as needed + template bool pop(Value &value, QueueReader *const reader = NULL); + + /// returns true iff the caller must notify the reader of the pushed item + template bool push(const Value &value, QueueReader *const reader = NULL); + + /// returns true iff the value was set; the value may be stale! + template bool peek(Value &value) const; + +private: + + unsigned int theIn; ///< input index, used only in push() + unsigned int theOut; ///< output index, used only in pop() + + AtomicWord theSize; ///< number of items in the queue + const unsigned int theMaxItemSize; ///< maximum item size + const int theCapacity; ///< maximum number of items, i.e. theBuffer size + + char theBuffer[]; +}; + +/// shared array of OneToOneUniQueues +class OneToOneUniQueues +{ +public: + OneToOneUniQueues(const int aCapacity, const unsigned int maxItemSize, const int queueCapacity); + + size_t sharedMemorySize() const; + static size_t SharedMemorySize(const int capacity, const unsigned int maxItemSize, const int queueCapacity); + + const OneToOneUniQueue &operator [](const int index) const; + inline OneToOneUniQueue &operator [](const int index); + +private: + inline const OneToOneUniQueue &front() const; + +public: + const int theCapacity; /// number of OneToOneUniQueues +}; + +/** + * Lockless fixed-capacity bidirectional queue for a limited number + * processes. Allows communication between two groups of processes: + * any process in one group may send data to and receive from any + * process in another group, but processes in the same group can not + * communicate. Process in each group has a unique integer ID in + * [groupIdOffset, groupIdOffset + groupSize) range. + */ +class FewToFewBiQueue +{ +public: + typedef OneToOneUniQueue::Full Full; + typedef OneToOneUniQueue::ItemTooLarge ItemTooLarge; + +private: + /// Shared metadata for FewToFewBiQueue + struct Metadata { + Metadata(const int aGroupASize, const int aGroupAIdOffset, const int aGroupBSize, const int aGroupBIdOffset); + size_t sharedMemorySize() const { return sizeof(*this); } + static size_t SharedMemorySize(const int, const int, const int, const int) { return sizeof(Metadata); } + + const int theGroupASize; + const int theGroupAIdOffset; + const int theGroupBSize; + const int theGroupBIdOffset; + }; + +public: + class Owner + { + public: + Owner(const String &id, const int groupASize, const int groupAIdOffset, const int groupBSize, const int groupBIdOffset, const unsigned int maxItemSize, const int capacity); + ~Owner(); + + private: + Mem::Owner *const metadataOwner; + Mem::Owner *const queuesOwner; + Mem::Owner *const readersOwner; + }; + + static Owner *Init(const String &id, const int groupASize, const int groupAIdOffset, const int groupBSize, const int groupBIdOffset, const unsigned int maxItemSize, const int capacity); + + enum Group { groupA = 0, groupB = 1 }; + FewToFewBiQueue(const String &id, const Group aLocalGroup, const int aLocalProcessId); + + Group localGroup() const { return theLocalGroup; } + Group remoteGroup() const { return theLocalGroup == groupA ? groupB : groupA; } + + /// clears the reader notification received by the local process from the remote process + void clearReaderSignal(const int remoteProcessId); + + /// picks a process and calls OneToOneUniQueue::pop() using its queue + template bool pop(int &remoteProcessId, Value &value); + + /// calls OneToOneUniQueue::push() using the given process queue + template bool push(const int remoteProcessId, const Value &value); + + // TODO: rename to findOldest() or some such + /// calls OneToOneUniQueue::peek() using the given process queue + template bool peek(const int remoteProcessId, Value &value) const; + + /// returns true if pop() would have probably succeeded but does not pop() + bool popReady() const; + + /// returns local reader's balance + QueueReader::Balance &localBalance(); + + /// returns local reader's rate limit + QueueReader::Rate &localRateLimit(); + +private: + bool validProcessId(const Group group, const int processId) const; + int oneToOneQueueIndex(const Group fromGroup, const int fromProcessId, const Group toGroup, const int toProcessId) const; + const OneToOneUniQueue &oneToOneQueue(const Group fromGroup, const int fromProcessId, const Group toGroup, const int toProcessId) const; + OneToOneUniQueue &oneToOneQueue(const Group fromGroup, const int fromProcessId, const Group toGroup, const int toProcessId); + QueueReader &reader(const Group group, const int processId); + const QueueReader &reader(const Group group, const int processId) const; + int readerIndex(const Group group, const int processId) const; + int remoteGroupSize() const { return theLocalGroup == groupA ? metadata->theGroupBSize : metadata->theGroupASize; } + int remoteGroupIdOffset() const { return theLocalGroup == groupA ? metadata->theGroupBIdOffset : metadata->theGroupAIdOffset; } + +private: + const Mem::Pointer metadata; ///< shared metadata + const Mem::Pointer queues; ///< unidirection one-to-one queues + const Mem::Pointer readers; ///< readers array + + const Group theLocalGroup; ///< group of this queue + const int theLocalProcessId; ///< process ID of this queue + int theLastPopProcessId; ///< the ID of the last process we tried to pop() from +}; + + +// OneToOneUniQueue + +template +bool +OneToOneUniQueue::pop(Value &value, QueueReader *const reader) +{ + if (sizeof(value) > theMaxItemSize) + throw ItemTooLarge(); + + // A writer might push between the empty test and block() below, so we do + // not return false right after calling block(), but test again. + if (empty()) { + if (!reader) + return false; + + reader->block(); + // A writer might push between the empty test and block() below, + // so we must test again as such a writer will not signal us. + if (empty()) + return false; + } + + if (reader) + reader->unblock(); + + const unsigned int pos = (theOut++ % theCapacity) * theMaxItemSize; + memcpy(&value, theBuffer + pos, sizeof(value)); + --theSize; + + return true; +} + +template +bool +OneToOneUniQueue::peek(Value &value) const +{ + if (sizeof(value) > theMaxItemSize) + throw ItemTooLarge(); + + if (empty()) + return false; + + // the reader may pop() before we copy; making this method imprecise + const unsigned int pos = (theOut % theCapacity) * theMaxItemSize; + memcpy(&value, theBuffer + pos, sizeof(value)); + return true; +} + +template +bool +OneToOneUniQueue::push(const Value &value, QueueReader *const reader) +{ + if (sizeof(value) > theMaxItemSize) + throw ItemTooLarge(); + + if (full()) + throw Full(); + + const bool wasEmpty = empty(); + const unsigned int pos = theIn++ % theCapacity * theMaxItemSize; + memcpy(theBuffer + pos, &value, sizeof(value)); + ++theSize; + + return wasEmpty && (!reader || reader->raiseSignal()); +} + + +// OneToOneUniQueues + +inline OneToOneUniQueue & +OneToOneUniQueues::operator [](const int index) +{ + return const_cast((*const_cast(this))[index]); +} + +inline const OneToOneUniQueue & +OneToOneUniQueues::front() const +{ + const char *const queue = + reinterpret_cast(this) + sizeof(*this); + return *reinterpret_cast(queue); +} + + +// FewToFewBiQueue + +template +bool +FewToFewBiQueue::pop(int &remoteProcessId, Value &value) +{ + // iterate all remote group processes, starting after the one we visited last + QueueReader &localReader = reader(theLocalGroup, theLocalProcessId); + for (int i = 0; i < remoteGroupSize(); ++i) { + if (++theLastPopProcessId >= remoteGroupIdOffset() + remoteGroupSize()) + theLastPopProcessId = remoteGroupIdOffset(); + OneToOneUniQueue &queue = oneToOneQueue(remoteGroup(), theLastPopProcessId, theLocalGroup, theLocalProcessId); + if (queue.pop(value, &localReader)) { + remoteProcessId = theLastPopProcessId; + debugs(54, 7, HERE << "popped from " << remoteProcessId << " to " << theLocalProcessId << " at " << queue.size()); + return true; + } + } + return false; // no process had anything to pop +} + +template +bool +FewToFewBiQueue::push(const int remoteProcessId, const Value &value) +{ + OneToOneUniQueue &remoteQueue = oneToOneQueue(theLocalGroup, theLocalProcessId, remoteGroup(), remoteProcessId); + QueueReader &remoteReader = reader(remoteGroup(), remoteProcessId); + debugs(54, 7, HERE << "pushing from " << theLocalProcessId << " to " << remoteProcessId << " at " << remoteQueue.size()); + return remoteQueue.push(value, &remoteReader); +} + +template +bool +FewToFewBiQueue::peek(const int remoteProcessId, Value &value) const +{ + // we may be called before remote process configured its queue end + if (!validProcessId(remoteGroup(), remoteProcessId)) + return false; + + // we need the oldest value, so start with the incoming, them-to-us queue: + const OneToOneUniQueue &inQueue = oneToOneQueue(remoteGroup(), remoteProcessId, theLocalGroup, theLocalProcessId); + debugs(54, 2, HERE << "peeking from " << remoteProcessId << " to " << theLocalProcessId << " at " << inQueue.size()); + if (inQueue.peek(value)) + return true; + + // if the incoming queue is empty, check the outgoing, us-to-them queue: + const OneToOneUniQueue &outQueue = oneToOneQueue(theLocalGroup, theLocalProcessId, remoteGroup(), remoteProcessId); + debugs(54, 2, HERE << "peeking from " << theLocalProcessId << " to " << remoteProcessId << " at " << outQueue.size()); + return outQueue.peek(value); +} + +} // namespace Ipc + +#endif // SQUID_IPC_QUEUE_H diff -u -r -N squid-3.2.0.12/src/ipc/ReadWriteLock.cc squid-3.2.0.13/src/ipc/ReadWriteLock.cc --- squid-3.2.0.12/src/ipc/ReadWriteLock.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/ReadWriteLock.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,97 @@ +/* + * $Id$ + * + * DEBUG: section 54 Interprocess Communication + */ + +#include "squid.h" + +#include "Store.h" +#include "ipc/ReadWriteLock.h" + +bool +Ipc::ReadWriteLock::lockShared() +{ + ++readers; // this locks "new" writers out + if (!writers) // there are no old writers + return true; + --readers; + return false; +} + +bool +Ipc::ReadWriteLock::lockExclusive() +{ + if (!writers++) { // we are the first writer + this locks "new" readers out + if (!readers) // there are no old readers + return true; + } + --writers; + return false; +} + +void +Ipc::ReadWriteLock::unlockShared() +{ + assert(readers-- > 0); +} + +void +Ipc::ReadWriteLock::unlockExclusive() +{ + assert(writers-- > 0); +} + +void +Ipc::ReadWriteLock::switchExclusiveToShared() +{ + ++readers; // must be done before we release exclusive control + unlockExclusive(); +} + +void +Ipc::ReadWriteLock::updateStats(ReadWriteLockStats &stats) const +{ + if (readers) { + ++stats.readable; + stats.readers += readers; + } else if (writers) { + ++stats.writeable; + stats.writers += writers; + } else { + ++stats.idle; + } + ++stats.count; +} + + +/* Ipc::ReadWriteLockStats */ + +Ipc::ReadWriteLockStats::ReadWriteLockStats() +{ + memset(this, 0, sizeof(*this)); +} + +void +Ipc::ReadWriteLockStats::dump(StoreEntry &e) const +{ + storeAppendPrintf(&e, "Available locks: %9d\n", count); + + if (!count) + return; + + storeAppendPrintf(&e, "Reading: %9d %6.2f%%\n", + readable, (100.0 * readable / count)); + storeAppendPrintf(&e, "Writing: %9d %6.2f%%\n", + writeable, (100.0 * writeable / count)); + storeAppendPrintf(&e, "Idle: %9d %6.2f%%\n", + idle, (100.0 * idle / count)); + + if (readers || writers) { + const int locked = readers + writers; + storeAppendPrintf(&e, "Readers: %9d %6.2f%%\n", + readers, (100.0 * readers / locked)); + storeAppendPrintf(&e, "Writers: %9d %6.2f%%\n", + writers, (100.0 * writers / locked)); + } +} diff -u -r -N squid-3.2.0.12/src/ipc/ReadWriteLock.h squid-3.2.0.13/src/ipc/ReadWriteLock.h --- squid-3.2.0.12/src/ipc/ReadWriteLock.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/ReadWriteLock.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,52 @@ +#ifndef SQUID_IPC_READ_WRITE_LOCK_H +#define SQUID_IPC_READ_WRITE_LOCK_H + +#include "ipc/AtomicWord.h" + +class StoreEntry; + +namespace Ipc +{ + +class ReadWriteLockStats; + +/// an atomic readers-writer or shared-exclusive lock suitable for maps/tables +class ReadWriteLock +{ +public: + // default constructor is OK because of shared memory zero-initialization + + bool lockShared(); ///< lock for reading or return false + bool lockExclusive(); ///< lock for modification or return false + void unlockShared(); ///< undo successful sharedLock() + void unlockExclusive(); ///< undo successful exclusiveLock() + void switchExclusiveToShared(); ///< stop writing, start reading + + /// adds approximate current stats to the supplied ones + void updateStats(ReadWriteLockStats &stats) const; + +public: + mutable AtomicWord readers; ///< number of users trying to read + AtomicWord writers; ///< number of writers trying to modify protected data +}; + + +/// approximate stats of a set of ReadWriteLocks +class ReadWriteLockStats +{ +public: + ReadWriteLockStats(); + + void dump(StoreEntry &e) const; + + int count; ///< the total number of locks + int readable; ///< number of locks locked for reading + int writeable; ///< number of locks locked for writing + int idle; ///< number of unlocked locks + int readers; ///< sum of lock.readers + int writers; ///< sum of lock.writers +}; + +} // namespace Ipc + +#endif /* SQUID_IPC_READ_WRITE_LOCK_H */ diff -u -r -N squid-3.2.0.12/src/ipc/StoreMap.cc squid-3.2.0.13/src/ipc/StoreMap.cc --- squid-3.2.0.12/src/ipc/StoreMap.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/StoreMap.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,324 @@ +/* + * $Id$ + * + * DEBUG: section 54 Interprocess Communication + */ + +#include "squid.h" + +#include "Store.h" +#include "ipc/StoreMap.h" + +Ipc::StoreMap::Owner * +Ipc::StoreMap::Init(const char *const path, const int limit, const size_t extrasSize) +{ + assert(limit > 0); // we should not be created otherwise + Owner *const owner = shm_new(Shared)(path, limit, extrasSize); + debugs(54, 5, HERE << "new map [" << path << "] created: " << limit); + return owner; +} + +Ipc::StoreMap::Owner * +Ipc::StoreMap::Init(const char *const path, const int limit) +{ + return Init(path, limit, 0); +} + +Ipc::StoreMap::StoreMap(const char *const aPath): cleaner(NULL), path(aPath), + shared(shm_old(Shared)(aPath)) +{ + assert(shared->limit > 0); // we should not be created otherwise + debugs(54, 5, HERE << "attached map [" << path << "] created: " << + shared->limit); +} + +Ipc::StoreMap::Slot * +Ipc::StoreMap::openForWriting(const cache_key *const key, sfileno &fileno) +{ + debugs(54, 5, HERE << " trying to open slot for key " << storeKeyText(key) + << " for writing in map [" << path << ']'); + const int idx = slotIndexByKey(key); + + Slot &s = shared->slots[idx]; + ReadWriteLock &lock = s.lock; + + if (lock.lockExclusive()) { + assert(s.state != Slot::Writeable); // until we start breaking locks + + // free if the entry was used, keeping the entry locked + if (s.waitingToBeFreed == true || s.state == Slot::Readable) + freeLocked(s, true); + + assert(s.state == Slot::Empty); + ++shared->count; + s.state = Slot::Writeable; + fileno = idx; + //s.setKey(key); // XXX: the caller should do that + debugs(54, 5, HERE << " opened slot at " << idx << + " for writing in map [" << path << ']'); + return &s; // and keep the entry locked + } + + debugs(54, 5, HERE << " failed to open slot at " << idx << + " for writing in map [" << path << ']'); + return NULL; +} + +void +Ipc::StoreMap::closeForWriting(const sfileno fileno, bool lockForReading) +{ + debugs(54, 5, HERE << " closing slot at " << fileno << " for writing and " + "openning for reading in map [" << path << ']'); + assert(valid(fileno)); + Slot &s = shared->slots[fileno]; + assert(s.state == Slot::Writeable); + s.state = Slot::Readable; + if (lockForReading) + s.lock.switchExclusiveToShared(); + else + s.lock.unlockExclusive(); +} + +/// terminate writing the entry, freeing its slot for others to use +void +Ipc::StoreMap::abortWriting(const sfileno fileno) +{ + debugs(54, 5, HERE << " abort writing slot at " << fileno << + " in map [" << path << ']'); + assert(valid(fileno)); + Slot &s = shared->slots[fileno]; + assert(s.state == Slot::Writeable); + freeLocked(s, false); +} + +void +Ipc::StoreMap::abortIo(const sfileno fileno) +{ + debugs(54, 5, HERE << " abort I/O for slot at " << fileno << + " in map [" << path << ']'); + assert(valid(fileno)); + Slot &s = shared->slots[fileno]; + + // The caller is a lock holder. Thus, if we are Writeable, then the + // caller must be the writer; otherwise the caller must be the reader. + if (s.state == Slot::Writeable) + abortWriting(fileno); + else + closeForReading(fileno); +} + +const Ipc::StoreMap::Slot * +Ipc::StoreMap::peekAtReader(const sfileno fileno) const +{ + assert(valid(fileno)); + const Slot &s = shared->slots[fileno]; + switch (s.state) { + case Slot::Readable: + return &s; // immediate access by lock holder so no locking + case Slot::Writeable: + return NULL; // cannot read the slot when it is being written + case Slot::Empty: + assert(false); // must be locked for reading or writing + } + assert(false); // not reachable + return NULL; +} + +void +Ipc::StoreMap::free(const sfileno fileno) +{ + debugs(54, 5, HERE << " marking slot at " << fileno << " to be freed in" + " map [" << path << ']'); + + assert(valid(fileno)); + Slot &s = shared->slots[fileno]; + + if (s.lock.lockExclusive()) + freeLocked(s, false); + else + s.waitingToBeFreed = true; // mark to free it later +} + +const Ipc::StoreMap::Slot * +Ipc::StoreMap::openForReading(const cache_key *const key, sfileno &fileno) +{ + debugs(54, 5, HERE << " trying to open slot for key " << storeKeyText(key) + << " for reading in map [" << path << ']'); + const int idx = slotIndexByKey(key); + if (const Slot *slot = openForReadingAt(idx)) { + if (slot->sameKey(key)) { + fileno = idx; + debugs(54, 5, HERE << " opened slot at " << fileno << " for key " + << storeKeyText(key) << " for reading in map [" << path << + ']'); + return slot; // locked for reading + } + slot->lock.unlockShared(); + } + debugs(54, 5, HERE << " failed to open slot for key " << storeKeyText(key) + << " for reading in map [" << path << ']'); + return NULL; +} + +const Ipc::StoreMap::Slot * +Ipc::StoreMap::openForReadingAt(const sfileno fileno) +{ + debugs(54, 5, HERE << " trying to open slot at " << fileno << " for " + "reading in map [" << path << ']'); + assert(valid(fileno)); + Slot &s = shared->slots[fileno]; + + if (!s.lock.lockShared()) { + debugs(54, 5, HERE << " failed to lock slot at " << fileno << " for " + "reading in map [" << path << ']'); + return NULL; + } + + if (s.state == Slot::Empty) { + s.lock.unlockShared(); + debugs(54, 7, HERE << " empty slot at " << fileno << " for " + "reading in map [" << path << ']'); + return NULL; + } + + if (s.waitingToBeFreed) { + s.lock.unlockShared(); + debugs(54, 7, HERE << " dirty slot at " << fileno << " for " + "reading in map [" << path << ']'); + return NULL; + } + + // cannot be Writing here if we got shared lock and checked Empty above + assert(s.state == Slot::Readable); + debugs(54, 5, HERE << " opened slot at " << fileno << " for reading in" + " map [" << path << ']'); + return &s; +} + +void +Ipc::StoreMap::closeForReading(const sfileno fileno) +{ + debugs(54, 5, HERE << " closing slot at " << fileno << " for reading in " + "map [" << path << ']'); + assert(valid(fileno)); + Slot &s = shared->slots[fileno]; + assert(s.state == Slot::Readable); + s.lock.unlockShared(); +} + +int +Ipc::StoreMap::entryLimit() const +{ + return shared->limit; +} + +int +Ipc::StoreMap::entryCount() const +{ + return shared->count; +} + +bool +Ipc::StoreMap::full() const +{ + return entryCount() >= entryLimit(); +} + +void +Ipc::StoreMap::updateStats(ReadWriteLockStats &stats) const +{ + for (int i = 0; i < shared->limit; ++i) + shared->slots[i].lock.updateStats(stats); +} + +bool +Ipc::StoreMap::valid(const int pos) const +{ + return 0 <= pos && pos < entryLimit(); +} + +int +Ipc::StoreMap::slotIndexByKey(const cache_key *const key) const +{ + const uint64_t *const k = reinterpret_cast(key); + // TODO: use a better hash function + return (k[0] + k[1]) % shared->limit; +} + +Ipc::StoreMap::Slot & +Ipc::StoreMap::slotByKey(const cache_key *const key) +{ + return shared->slots[slotIndexByKey(key)]; +} + +/// unconditionally frees the already exclusively locked slot and releases lock +void +Ipc::StoreMap::freeLocked(Slot &s, bool keepLocked) +{ + if (s.state == Slot::Readable && cleaner) + cleaner->cleanReadable(&s - shared->slots); + + s.waitingToBeFreed = false; + s.state = Slot::Empty; + if (!keepLocked) + s.lock.unlockExclusive(); + --shared->count; + debugs(54, 5, HERE << " freed slot at " << (&s - shared->slots) << + " in map [" << path << ']'); +} + + +/* Ipc::StoreMapSlot */ + +Ipc::StoreMapSlot::StoreMapSlot(): state(Empty) +{ + xmemset(&key, 0, sizeof(key)); + xmemset(&basics, 0, sizeof(basics)); +} + +void +Ipc::StoreMapSlot::setKey(const cache_key *const aKey) +{ + memcpy(key, aKey, sizeof(key)); +} + +bool +Ipc::StoreMapSlot::sameKey(const cache_key *const aKey) const +{ + const uint64_t *const k = reinterpret_cast(aKey); + return k[0] == key[0] && k[1] == key[1]; +} + +void +Ipc::StoreMapSlot::set(const StoreEntry &from) +{ + memcpy(key, from.key, sizeof(key)); + // XXX: header = aHeader; + basics.timestamp = from.timestamp; + basics.lastref = from.lastref; + basics.expires = from.expires; + basics.lastmod = from.lastmod; + basics.swap_file_sz = from.swap_file_sz; + basics.refcount = from.refcount; + basics.flags = from.flags; +} + +/* Ipc::StoreMap::Shared */ + +Ipc::StoreMap::Shared::Shared(const int aLimit, const size_t anExtrasSize): + limit(aLimit), extrasSize(anExtrasSize), count(0) +{ +} + +size_t +Ipc::StoreMap::Shared::sharedMemorySize() const +{ + return SharedMemorySize(limit, extrasSize); +} + +size_t +Ipc::StoreMap::Shared::SharedMemorySize(const int limit, const size_t extrasSize) +{ + return sizeof(Shared) + limit * (sizeof(Slot) + extrasSize); +} + diff -u -r -N squid-3.2.0.12/src/ipc/StoreMap.h squid-3.2.0.13/src/ipc/StoreMap.h --- squid-3.2.0.12/src/ipc/StoreMap.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/StoreMap.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,201 @@ +#ifndef SQUID_IPC_STORE_MAP_H +#define SQUID_IPC_STORE_MAP_H + +#include "ipc/ReadWriteLock.h" +#include "ipc/mem/Pointer.h" +#include "typedefs.h" + +namespace Ipc +{ + +/// a StoreMap element, holding basic shareable StoreEntry info +class StoreMapSlot +{ +public: + StoreMapSlot(); + + /// store StoreEntry key and basics + void set(const StoreEntry &anEntry); + + void setKey(const cache_key *const aKey); + bool sameKey(const cache_key *const aKey) const; + +public: + mutable ReadWriteLock lock; ///< protects slot data below + AtomicWordT waitingToBeFreed; ///< may be accessed w/o a lock + + uint64_t key[2]; ///< StoreEntry key + + // STORE_META_STD TLV field from StoreEntry + struct Basics { + time_t timestamp; + time_t lastref; + time_t expires; + time_t lastmod; + uint64_t swap_file_sz; + uint16_t refcount; + uint16_t flags; + } basics; + + /// possible persistent states + typedef enum { + Empty, ///< ready for writing, with nothing of value + Writeable, ///< transitions from Empty to Readable + Readable, ///< ready for reading + } State; + State state; ///< current state +}; + +class StoreMapCleaner; + +/// map of StoreMapSlots indexed by their keys, with read/write slot locking +/// kids extend to store custom data +class StoreMap +{ +public: + typedef StoreMapSlot Slot; + + /// data shared across maps in different processes + class Shared + { + public: + Shared(const int aLimit, const size_t anExtrasSize); + size_t sharedMemorySize() const; + static size_t SharedMemorySize(const int limit, const size_t anExtrasSize); + + const int limit; ///< maximum number of map slots + const size_t extrasSize; ///< size of slot extra data + AtomicWord count; ///< current number of map slots + Slot slots[]; ///< slots storage + }; + +public: + typedef Mem::Owner Owner; + + /// initialize shared memory + static Owner *Init(const char *const path, const int limit); + + StoreMap(const char *const aPath); + + /// finds, reservers space for writing a new entry or returns nil + Slot *openForWriting(const cache_key *const key, sfileno &fileno); + /// successfully finish writing the entry + void closeForWriting(const sfileno fileno, bool lockForReading = false); + + /// only works on locked entries; returns nil unless the slot is readable + const Slot *peekAtReader(const sfileno fileno) const; + + /// mark the slot as waiting to be freed and, if possible, free it + void free(const sfileno fileno); + + /// open slot for reading, increments read level + const Slot *openForReading(const cache_key *const key, sfileno &fileno); + /// open slot for reading, increments read level + const Slot *openForReadingAt(const sfileno fileno); + /// close slot after reading, decrements read level + void closeForReading(const sfileno fileno); + + /// called by lock holder to terminate either slot writing or reading + void abortIo(const sfileno fileno); + + bool full() const; ///< there are no empty slots left + bool valid(const int n) const; ///< whether n is a valid slot coordinate + int entryCount() const; ///< number of used slots + int entryLimit() const; ///< maximum number of slots that can be used + + /// adds approximate current stats to the supplied ones + void updateStats(ReadWriteLockStats &stats) const; + + StoreMapCleaner *cleaner; ///< notified before a readable entry is freed + +protected: + static Owner *Init(const char *const path, const int limit, const size_t extrasSize); + + const String path; ///< cache_dir path, used for logging + Mem::Pointer shared; + +private: + int slotIndexByKey(const cache_key *const key) const; + Slot &slotByKey(const cache_key *const key); + + Slot *openForReading(Slot &s); + void abortWriting(const sfileno fileno); + void freeIfNeeded(Slot &s); + void freeLocked(Slot &s, bool keepLocked); +}; + +/// StoreMap with extra slot data +/// Note: ExtrasT must be POD, it is initialized with zeroes, no +/// constructors or destructors are called +template +class StoreMapWithExtras: public StoreMap +{ +public: + typedef ExtrasT Extras; + + /// initialize shared memory + static Owner *Init(const char *const path, const int limit); + + StoreMapWithExtras(const char *const path); + + /// write access to the extras; call openForWriting() first! + ExtrasT &extras(const sfileno fileno); + /// read-only access to the extras; call openForReading() first! + const ExtrasT &extras(const sfileno fileno) const; + +protected: + + ExtrasT *sharedExtras; ///< pointer to extras in shared memory +}; + +/// API for adjusting external state when dirty map slot is being freed +class StoreMapCleaner +{ +public: + virtual ~StoreMapCleaner() {} + + /// adjust slot-linked state before a locked Readable slot is erased + virtual void cleanReadable(const sfileno fileno) = 0; +}; + +// StoreMapWithExtras implementation + +template +StoreMap::Owner * +StoreMapWithExtras::Init(const char *const path, const int limit) +{ + return StoreMap::Init(path, limit, sizeof(Extras)); +} + +template +StoreMapWithExtras::StoreMapWithExtras(const char *const path): + StoreMap(path) +{ + const size_t sharedSizeWithoutExtras = + Shared::SharedMemorySize(entryLimit(), 0); + sharedExtras = reinterpret_cast(reinterpret_cast(shared.getRaw()) + sharedSizeWithoutExtras); +} + +template +ExtrasT & +StoreMapWithExtras::extras(const sfileno fileno) +{ + return const_cast(const_cast(this)->extras(fileno)); +} + +template +const ExtrasT & +StoreMapWithExtras::extras(const sfileno fileno) const +{ + assert(sharedExtras); + assert(valid(fileno)); + return sharedExtras[fileno]; +} + + +} // namespace Ipc + +// We do not reuse struct _fileMap because we cannot control its size, +// resulting in sfilenos that are pointing beyond the database. + +#endif /* SQUID_IPC_STORE_MAP_H */ diff -u -r -N squid-3.2.0.12/src/ipc/Strand.cc squid-3.2.0.13/src/ipc/Strand.cc --- squid-3.2.0.12/src/ipc/Strand.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ipc/Strand.cc 2011-10-14 14:42:56.000000000 +1300 @@ -13,11 +13,16 @@ #include "ipc/StrandCoord.h" #include "ipc/Messages.h" #include "ipc/SharedListen.h" +#include "ipc/StrandSearch.h" #include "ipc/Kids.h" #include "mgr/Request.h" #include "mgr/Response.h" #include "mgr/Forwarder.h" +#include "SwapDir.h" /* XXX: scope boundary violation */ #include "CacheManager.h" +#if USE_DISKIO_IPCIO +#include "DiskIO/IpcIo/IpcIoFile.h" /* XXX: scope boundary violation */ +#endif #if SQUID_SNMP #include "snmp/Forwarder.h" #include "snmp/Request.h" @@ -43,8 +48,10 @@ { debugs(54, 6, HERE); Must(!isRegistered); + + HereIamMessage ann(StrandCoord(KidIdentifier, getpid())); TypedMsgHdr message; - StrandCoord(KidIdentifier, getpid()).pack(message); + ann.pack(message); SendMessage(coordinatorAddr, message); setTimeout(6, "Ipc::Strand::timeoutHandler"); // TODO: make 6 configurable? } @@ -55,13 +62,23 @@ switch (message.type()) { case mtRegistration: - handleRegistrationResponse(StrandCoord(message)); + handleRegistrationResponse(HereIamMessage(message)); break; case mtSharedListenResponse: SharedListenJoined(SharedListenResponse(message)); break; +#if USE_DISKIO_IPCIO + case mtStrandSearchResponse: + IpcIoFile::HandleOpenResponse(StrandSearchResponse(message)); + break; + + case mtIpcIoNotification: + IpcIoFile::HandleNotification(message); + break; +#endif /* USE_DISKIO_IPCIO */ + case mtCacheMgrRequest: { const Mgr::Request req(message); handleCacheMgrRequest(req); @@ -94,10 +111,10 @@ } } -void Ipc::Strand::handleRegistrationResponse(const StrandCoord &strand) +void Ipc::Strand::handleRegistrationResponse(const HereIamMessage &msg) { // handle registration response from the coordinator; it could be stale - if (strand.kidId == KidIdentifier && strand.pid == getpid()) { + if (msg.strand.kidId == KidIdentifier && msg.strand.pid == getpid()) { debugs(54, 6, "kid" << KidIdentifier << " registered"); clearTimeout(); // we are done } else { diff -u -r -N squid-3.2.0.12/src/ipc/StrandCoord.cc squid-3.2.0.13/src/ipc/StrandCoord.cc --- squid-3.2.0.12/src/ipc/StrandCoord.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ipc/StrandCoord.cc 2011-10-14 14:42:56.000000000 +1300 @@ -7,6 +7,7 @@ #include "config.h" +#include "Debug.h" #include "ipc/Messages.h" #include "ipc/StrandCoord.h" #include "ipc/TypedMsgHdr.h" @@ -20,14 +21,35 @@ { } -Ipc::StrandCoord::StrandCoord(const TypedMsgHdr &hdrMsg): kidId(-1), pid(0) +void +Ipc::StrandCoord::unpack(const TypedMsgHdr &hdrMsg) { - hdrMsg.checkType(mtRegistration); - hdrMsg.getPod(*this); + hdrMsg.getPod(kidId); + hdrMsg.getPod(pid); + hdrMsg.getString(tag); } void Ipc::StrandCoord::pack(TypedMsgHdr &hdrMsg) const { + hdrMsg.putPod(kidId); + hdrMsg.putPod(pid); + hdrMsg.putString(tag); +} + + +Ipc::HereIamMessage::HereIamMessage(const StrandCoord &aStrand): + strand(aStrand) +{ +} + +Ipc::HereIamMessage::HereIamMessage(const TypedMsgHdr &hdrMsg) +{ + hdrMsg.checkType(mtRegistration); + strand.unpack(hdrMsg); +} + +void Ipc::HereIamMessage::pack(TypedMsgHdr &hdrMsg) const +{ hdrMsg.setType(mtRegistration); - hdrMsg.putPod(*this); + strand.pack(hdrMsg); } diff -u -r -N squid-3.2.0.12/src/ipc/StrandCoord.h squid-3.2.0.13/src/ipc/StrandCoord.h --- squid-3.2.0.12/src/ipc/StrandCoord.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ipc/StrandCoord.h 2011-10-14 14:42:56.000000000 +1300 @@ -7,7 +7,7 @@ #define SQUID_IPC_STRAND_COORD_H #include "ipc/forward.h" -#include +#include "SquidString.h" namespace Ipc { @@ -17,15 +17,32 @@ { public: StrandCoord(); ///< unknown location - StrandCoord(int akidId, pid_t aPid); ///< from registrant - explicit StrandCoord(const TypedMsgHdr &hdrMsg); ///< from recvmsg() + StrandCoord(int akidId, pid_t aPid); + void pack(TypedMsgHdr &hdrMsg) const; ///< prepare for sendmsg() + void unpack(const TypedMsgHdr &hdrMsg); ///< from recvmsg() public: int kidId; ///< internal Squid process number pid_t pid; ///< OS process or thread identifier + + String tag; ///< optional unique well-known key (e.g., cache_dir path) }; +/// strand registration with Coordinator (also used as an ACK) +class HereIamMessage +{ +public: + explicit HereIamMessage(const StrandCoord &strand); ///< from registrant + explicit HereIamMessage(const TypedMsgHdr &hdrMsg); ///< from recvmsg() + void pack(TypedMsgHdr &hdrMsg) const; ///< prepare for sendmsg() + +public: + StrandCoord strand; ///< registrant coordinates and related details +}; + + + } // namespace Ipc; #endif /* SQUID_IPC_STRAND_COORD_H */ diff -u -r -N squid-3.2.0.12/src/ipc/Strand.h squid-3.2.0.13/src/ipc/Strand.h --- squid-3.2.0.12/src/ipc/Strand.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ipc/Strand.h 2011-10-14 14:42:56.000000000 +1300 @@ -8,6 +8,7 @@ #ifndef SQUID_IPC_STRAND_H #define SQUID_IPC_STRAND_H +#include "ipc/forward.h" #include "ipc/Port.h" #include "mgr/forward.h" #if SQUID_SNMP @@ -33,7 +34,7 @@ private: void registerSelf(); /// let Coordinator know this strand exists - void handleRegistrationResponse(const StrandCoord &strand); + void handleRegistrationResponse(const HereIamMessage &msg); void handleCacheMgrRequest(const Mgr::Request& request); void handleCacheMgrResponse(const Mgr::Response& response); #if SQUID_SNMP diff -u -r -N squid-3.2.0.12/src/ipc/StrandSearch.cc squid-3.2.0.13/src/ipc/StrandSearch.cc --- squid-3.2.0.12/src/ipc/StrandSearch.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/StrandSearch.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,52 @@ +/* + * $Id$ + * + * DEBUG: section 54 Interprocess Communication + * + */ + + +#include "config.h" +#include "ipc/Messages.h" +#include "ipc/StrandSearch.h" +#include "ipc/TypedMsgHdr.h" + + +Ipc::StrandSearchRequest::StrandSearchRequest(): requestorId(-1) +{ +} + +Ipc::StrandSearchRequest::StrandSearchRequest(const TypedMsgHdr &hdrMsg): + requestorId(-1) +{ + hdrMsg.checkType(mtStrandSearchRequest); + hdrMsg.getPod(requestorId); + hdrMsg.getString(tag); +} + +void Ipc::StrandSearchRequest::pack(TypedMsgHdr &hdrMsg) const +{ + hdrMsg.setType(mtStrandSearchRequest); + hdrMsg.putPod(requestorId); + hdrMsg.putString(tag); +} + + +/* StrandSearchResponse */ + +Ipc::StrandSearchResponse::StrandSearchResponse(const Ipc::StrandCoord &aStrand): + strand(aStrand) +{ +} + +Ipc::StrandSearchResponse::StrandSearchResponse(const TypedMsgHdr &hdrMsg) +{ + hdrMsg.checkType(mtStrandSearchResponse); + strand.unpack(hdrMsg); +} + +void Ipc::StrandSearchResponse::pack(TypedMsgHdr &hdrMsg) const +{ + hdrMsg.setType(mtStrandSearchResponse); + strand.pack(hdrMsg); +} diff -u -r -N squid-3.2.0.12/src/ipc/StrandSearch.h squid-3.2.0.13/src/ipc/StrandSearch.h --- squid-3.2.0.12/src/ipc/StrandSearch.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/ipc/StrandSearch.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,43 @@ +/* + * $Id$ + * + */ + +#ifndef SQUID_IPC_STRAND_SEARCH_H +#define SQUID_IPC_STRAND_SEARCH_H + +#include "ipc/forward.h" +#include "ipc/StrandCoord.h" +#include "SquidString.h" + +namespace Ipc +{ + +/// asynchronous strand search request +class StrandSearchRequest +{ +public: + StrandSearchRequest(); + explicit StrandSearchRequest(const TypedMsgHdr &hdrMsg); ///< from recvmsg() + void pack(TypedMsgHdr &hdrMsg) const; ///< prepare for sendmsg() + +public: + int requestorId; ///< sender-provided return address + String tag; ///< set when looking for a matching StrandCoord::tag +}; + +/// asynchronous strand search response +class StrandSearchResponse +{ +public: + StrandSearchResponse(const StrandCoord &strand); + explicit StrandSearchResponse(const TypedMsgHdr &hdrMsg); ///< from recvmsg() + void pack(TypedMsgHdr &hdrMsg) const; ///< prepare for sendmsg() + +public: + StrandCoord strand; ///< answer matching StrandSearchRequest criteria +}; + +} // namespace Ipc; + +#endif /* SQUID_IPC_STRAND_SEARCH_H */ diff -u -r -N squid-3.2.0.12/src/log/FormatSquidIcap.cc squid-3.2.0.13/src/log/FormatSquidIcap.cc --- squid-3.2.0.12/src/log/FormatSquidIcap.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/log/FormatSquidIcap.cc 2011-10-14 14:42:56.000000000 +1300 @@ -75,11 +75,12 @@ if (user && !*user) safe_free(user); - logfilePrintf(logfile, "%9ld.%03d %6d %s -/%03d %"PRId64" %s %s %s -/%s -\n", + logfilePrintf(logfile, "%9ld.%03d %6d %s %s/%03d %"PRId64" %s %s %s -/%s -\n", (long int) current_time.tv_sec, (int) current_time.tv_usec / 1000, al->icap.trTime, client, + al->icap.outcome, al->icap.resStatus, al->icap.bytesRead, Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod), diff -u -r -N squid-3.2.0.12/src/main.cc squid-3.2.0.13/src/main.cc --- squid-3.2.0.12/src/main.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/main.cc 2011-10-14 14:42:56.000000000 +1300 @@ -669,8 +669,8 @@ wccp2ConnectionOpen(); #endif } - // Coordinator does not start proxying services - if (!IamCoordinatorProcess()) { + // start various proxying services if we are responsible for them + if (IamWorkerProcess()) { clientOpenListenSockets(); icpConnectionsOpen(); #if USE_HTCP @@ -712,7 +712,7 @@ wccp2ConnectionClose(); #endif } - if (!IamCoordinatorProcess()) { + if (IamWorkerProcess()) { clientHttpConnectionsClose(); icpConnectionShutdown(); #if USE_HTCP @@ -1008,6 +1008,9 @@ #endif debugs(1, 1, "Process ID " << getpid()); + + debugs(1, 1, "Process Roles:" << ProcessRoles()); + setSystemLimits(); debugs(1, 1, "With " << Squid_MaxFD << " file descriptors available"); @@ -1243,10 +1246,11 @@ try { return SquidMain(argc, argv); } catch (const std::exception &e) { - std::cerr << "dying from an unhandled exception: " << e.what() << std::endl; + debugs(1, DBG_CRITICAL, "FATAL: dying from an unhandled exception: " << + e.what()); throw; } catch (...) { - std::cerr << "dying from an unhandled exception." << std::endl; + debugs(1, DBG_CRITICAL, "FATAL: dying from an unhandled exception."); throw; } return -1; // not reached @@ -1263,6 +1267,14 @@ const size_t nameLen = idStart - (processName + 1); assert(nameLen < sizeof(TheKidName)); xstrncpy(TheKidName, processName + 1, nameLen + 1); + if (!strcmp(TheKidName, "squid-coord")) + TheProcessKind = pkCoordinator; + else if (!strcmp(TheKidName, "squid")) + TheProcessKind = pkWorker; + else if (!strcmp(TheKidName, "squid-disk")) + TheProcessKind = pkDisker; + else + TheProcessKind = pkOther; // including coordinator } } else { xstrncpy(TheKidName, APP_SHORTNAME, sizeof(TheKidName)); @@ -1507,7 +1519,7 @@ if (IamCoordinatorProcess()) AsyncJob::Start(Ipc::Coordinator::Instance()); - else if (UsingSmp() && IamWorkerProcess()) + else if (UsingSmp() && (IamWorkerProcess() || IamDiskProcess())) AsyncJob::Start(new Ipc::Strand); /* at this point we are finished the synchronous startup. */ @@ -1720,7 +1732,9 @@ Config.workers); // but we keep going in hope that user knows best } - TheKids.init(Config.workers); + TheKids.init(); + + syslog(LOG_NOTICE, "Squid Parent: will start %d kids", (int)TheKids.count()); // keep [re]starting kids until it is time to quit for (;;) { @@ -1742,7 +1756,8 @@ } kid.start(pid); - syslog(LOG_NOTICE, "Squid Parent: child process %d started", pid); + syslog(LOG_NOTICE, "Squid Parent: %s process %d started", + kid.name().termedBuf(), pid); } /* parent */ @@ -1766,19 +1781,22 @@ kid->stop(status); if (kid->calledExit()) { syslog(LOG_NOTICE, - "Squid Parent: child process %d exited with status %d", + "Squid Parent: %s process %d exited with status %d", + kid->name().termedBuf(), kid->getPid(), kid->exitStatus()); } else if (kid->signaled()) { syslog(LOG_NOTICE, - "Squid Parent: child process %d exited due to signal %d with status %d", + "Squid Parent: %s process %d exited due to signal %d with status %d", + kid->name().termedBuf(), kid->getPid(), kid->termSignal(), kid->exitStatus()); } else { - syslog(LOG_NOTICE, "Squid Parent: child process %d exited", kid->getPid()); + syslog(LOG_NOTICE, "Squid Parent: %s process %d exited", + kid->name().termedBuf(), kid->getPid()); } if (kid->hopeless()) { - syslog(LOG_NOTICE, "Squid Parent: child process %d will not" + syslog(LOG_NOTICE, "Squid Parent: %s process %d will not" " be restarted due to repeated, frequent failures", - kid->getPid()); + kid->name().termedBuf(), kid->getPid()); } } else { syslog(LOG_NOTICE, "Squid Parent: unknown child process %d exited", pid); diff -u -r -N squid-3.2.0.12/src/Makefile.am squid-3.2.0.13/src/Makefile.am --- squid-3.2.0.12/src/Makefile.am 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/Makefile.am 2011-10-14 14:42:56.000000000 +1300 @@ -174,7 +174,8 @@ AIOPS_SOURCE = DiskIO/DiskThreads/aiops.cc endif -EXTRA_LIBRARIES = libAIO.a libBlocking.a libDiskDaemon.a libDiskThreads.a +EXTRA_LIBRARIES = libAIO.a libBlocking.a libDiskDaemon.a libDiskThreads.a \ + libMmapped.a libIpcIo.a noinst_LIBRARIES = $(DISK_LIBS) noinst_LTLIBRARIES = libsquid.la @@ -341,7 +342,9 @@ HttpStatusCode.h \ HttpStatusLine.cc \ HttpStatusLine.h \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrRange.cc \ HttpHdrSc.cc \ HttpHdrSc.h \ @@ -466,6 +469,8 @@ swap_log_op.h \ SwapDir.cc \ SwapDir.h \ + MemStore.cc \ + MemStore.h \ time.cc \ TimeOrTag.h \ tools.cc \ @@ -544,6 +549,7 @@ eui/libeui.la \ acl/libstate.la \ $(AUTH_LIBS) \ + $(DISK_LIBS) \ acl/libapi.la \ base/libbase.la \ libsquid.la \ @@ -560,7 +566,6 @@ $(XTRA_OBJS) \ $(DISK_LINKOBJS) \ $(REPL_OBJS) \ - $(DISK_LIBS) \ $(DISK_OS_LIBS) \ $(CRYPTLIB) \ $(REGEXLIB) \ @@ -779,6 +784,22 @@ DiskIO/Blocking/BlockingDiskIOModule.cc \ DiskIO/Blocking/BlockingDiskIOModule.h +libMmapped_a_SOURCES = \ + DiskIO/Mmapped/MmappedFile.cc \ + DiskIO/Mmapped/MmappedFile.h \ + DiskIO/Mmapped/MmappedIOStrategy.cc \ + DiskIO/Mmapped/MmappedIOStrategy.h \ + DiskIO/Mmapped/MmappedDiskIOModule.cc \ + DiskIO/Mmapped/MmappedDiskIOModule.h + +libIpcIo_a_SOURCES = \ + DiskIO/IpcIo/IpcIoFile.cc \ + DiskIO/IpcIo/IpcIoFile.h \ + DiskIO/IpcIo/IpcIoIOStrategy.cc \ + DiskIO/IpcIo/IpcIoIOStrategy.h \ + DiskIO/IpcIo/IpcIoDiskIOModule.cc \ + DiskIO/IpcIo/IpcIoDiskIOModule.h + libDiskDaemon_a_SOURCES = \ DiskIO/DiskDaemon/DiskdFile.cc \ DiskIO/DiskDaemon/DiskdFile.h \ @@ -824,7 +845,6 @@ DEFAULT_ACCESS_LOG = $(DEFAULT_LOG_PREFIX)/access.log DEFAULT_STORE_LOG = $(DEFAULT_LOG_PREFIX)/store.log DEFAULT_NETDB_FILE = $(DEFAULT_LOG_PREFIX)/netdb.state -DEFAULT_SWAP_DIR = $(localstatedir)/cache DEFAULT_SSL_DB_DIR = $(localstatedir)/lib/ssl_db DEFAULT_PINGER = $(libexecdir)/`echo pinger | sed '$(transform);s/$$/$(EXEEXT)/'` DEFAULT_UNLINKD = $(libexecdir)/`echo unlinkd | sed '$(transform);s/$$/$(EXEEXT)/'` @@ -1015,7 +1035,9 @@ cbdata.h \ ETag.cc \ HttpBody.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrContRange.h \ HttpHdrRange.cc \ @@ -1044,6 +1066,7 @@ SquidString.h \ SquidTime.h \ String.cc \ + tests/stub_cache_cf.cc \ tests/stub_cache_manager.cc \ tests/stub_debug.cc \ tests/stub_HelperChildConfig.cc \ @@ -1052,7 +1075,8 @@ tests/testHttpReply.cc \ tests/testHttpReply.h \ tests/testMain.cc \ - time.cc + time.cc \ + wordlist.cc nodist_tests_testHttpReply_SOURCES=\ $(TESTSOURCES) tests_testHttpReply_LDFLAGS = $(LIBADD_DL) @@ -1108,7 +1132,9 @@ HttpHeaderTools.cc \ HttpHdrContRange.cc \ HttpHdrRange.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpMsg.cc \ @@ -1146,10 +1172,12 @@ tests/stub_fd.cc \ tests/stub_HttpRequest.cc \ tests/stub_MemObject.cc \ + tests/stub_MemStore.cc \ tests/stub_mime.cc \ tests/stub_store.cc \ tests/stub_store_rebuild.cc \ tests/stub_store_swapout.cc \ + tests/stub_tools.cc \ tests/stub_cache_manager.cc \ tests/testACLMaxUserIP.cc \ tests/testACLMaxUserIP.h \ @@ -1179,6 +1207,7 @@ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ + $(DISK_OS_LIBS) \ $(REGEXLIB) \ $(SQUID_CPPUNIT_LIBS) \ $(SSLLIB) \ @@ -1244,6 +1273,7 @@ CpuAffinitySet.cc \ CpuAffinitySet.h \ $(DELAY_POOL_SOURCE) \ + $(DISKIO_SOURCE) \ disk.cc \ dlink.h \ dlink.cc \ @@ -1255,6 +1285,7 @@ ExternalACLEntry.cc \ fd.cc \ fde.cc \ + filemap.cc \ forward.cc \ fqdncache.cc \ ftp.cc \ @@ -1268,7 +1299,9 @@ HttpBody.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ @@ -1332,6 +1365,8 @@ tools.cc \ tunnel.cc \ SwapDir.cc \ + MemStore.cc \ + $(UNLINKDSOURCE) \ url.cc \ URLScheme.cc \ urn.cc \ @@ -1341,7 +1376,8 @@ $(WIN32_SOURCE) \ wordlist.cc nodist_tests_testCacheManager_SOURCES = \ - $(BUILT_SOURCES) + $(BUILT_SOURCES) \ + $(DISKIO_GEN_SOURCE) # comm.cc only requires comm/libcomm.la until fdc_table is dead. tests_testCacheManager_LDADD = \ $(AUTH_ACL_LIBS) \ @@ -1355,18 +1391,20 @@ libsquid.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la \ - mgr/libmgr.la \ - $(SNMP_LIBS) \ comm/libcomm.la \ icmp/libicmp.la icmp/libicmp-core.la \ log/liblog.la \ format/libformat.la \ $(REPL_OBJS) \ + $(DISK_LIBS) \ + $(DISK_OS_LIBS) \ $(ADAPTATION_LIBS) \ $(ESI_LIBS) \ $(SSL_LIBS) \ anyp/libanyp.la \ + ipc/libipc.la \ + mgr/libmgr.la \ + $(SNMP_LIBS) \ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ @@ -1399,7 +1437,9 @@ fd.cc \ filemap.cc \ HttpBody.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ @@ -1457,13 +1497,13 @@ tests/stub_ipc.cc \ tests/stub_ipcache.cc \ tests/stub_libicmp.cc \ + tests/stub_MemStore.cc \ tests/stub_mime.cc \ tests/stub_pconn.cc \ tests/stub_Port.cc \ tests/stub_store_client.cc \ tests/stub_store_rebuild.cc \ tests/stub_tools.cc \ - tests/stub_TypedMsgHdr.cc \ tests/stub_UdsOp.cc \ tests/testDiskIO.cc \ tests/testDiskIO.h \ @@ -1495,7 +1535,6 @@ $(AUTH_LIBS) \ libsquid.la \ comm/libcomm.la \ - base/libbase.la \ ip/libip.la \ fs/libfs.la \ ipc/libipc.la \ @@ -1504,6 +1543,8 @@ $(DISK_OS_LIBS) \ acl/libapi.la \ mgr/libmgr.la \ + ipc/libipc.la \ + base/libbase.la \ $(SSL_LIBS) \ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ @@ -1544,6 +1585,7 @@ CpuAffinitySet.h \ debug.cc \ $(DELAY_POOL_SOURCE) \ + $(DISKIO_SOURCE) \ disk.cc \ dlink.h \ dlink.cc \ @@ -1558,6 +1600,7 @@ FadingCounter.cc \ fd.cc \ fde.cc \ + filemap.cc \ forward.cc \ fqdncache.cc \ ftp.cc \ @@ -1571,7 +1614,9 @@ HttpBody.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ @@ -1650,6 +1695,8 @@ time.cc \ tools.cc \ tunnel.cc \ + MemStore.cc \ + $(UNLINKDSOURCE) \ url.cc \ URLScheme.cc \ urn.cc \ @@ -1658,7 +1705,8 @@ $(WIN32_SOURCE) \ wordlist.cc nodist_tests_testEvent_SOURCES = \ - $(BUILT_SOURCES) + $(BUILT_SOURCES) \ + $(DISKIO_GEN_SOURCE) tests_testEvent_LDADD = \ $(AUTH_ACL_LIBS) \ ident/libident.la \ @@ -1671,10 +1719,7 @@ libsquid.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la \ - mgr/libmgr.la \ anyp/libanyp.la \ - $(SNMP_LIBS) \ icmp/libicmp.la icmp/libicmp-core.la \ comm/libcomm.la \ log/liblog.la \ @@ -1686,6 +1731,11 @@ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ + $(DISK_LIBS) \ + $(DISK_OS_LIBS) \ + ipc/libipc.la \ + mgr/libmgr.la \ + $(SNMP_LIBS) \ $(REGEXLIB) \ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ @@ -1722,6 +1772,7 @@ CpuAffinitySet.h \ debug.cc \ $(DELAY_POOL_SOURCE) \ + $(DISKIO_SOURCE) \ disk.cc \ dlink.h \ dlink.cc \ @@ -1736,6 +1787,7 @@ FadingCounter.cc \ fd.cc \ fde.cc \ + filemap.cc \ forward.cc \ fqdncache.cc \ ftp.cc \ @@ -1749,7 +1801,9 @@ HttpBody.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ @@ -1827,6 +1881,8 @@ time.cc \ tools.cc \ tunnel.cc \ + MemStore.cc \ + $(UNLINKDSOURCE) \ url.cc \ URLScheme.cc \ urn.cc \ @@ -1835,7 +1891,8 @@ $(WIN32_SOURCE) \ wordlist.cc nodist_tests_testEventLoop_SOURCES = \ - $(BUILT_SOURCES) + $(BUILT_SOURCES) \ + $(DISKIO_GEN_SOURCE) tests_testEventLoop_LDADD = \ $(AUTH_ACL_LIBS) \ ident/libident.la \ @@ -1848,10 +1905,7 @@ libsquid.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la \ - mgr/libmgr.la \ anyp/libanyp.la \ - $(SNMP_LIBS) \ icmp/libicmp.la icmp/libicmp-core.la \ comm/libcomm.la \ log/liblog.la \ @@ -1863,6 +1917,11 @@ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ + $(DISK_LIBS) \ + $(DISK_OS_LIBS) \ + ipc/libipc.la \ + mgr/libmgr.la \ + $(SNMP_LIBS) \ $(REGEXLIB) \ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ @@ -1900,6 +1959,7 @@ CpuAffinitySet.h \ debug.cc \ $(DELAY_POOL_SOURCE) \ + $(DISKIO_SOURCE) \ disk.cc \ dlink.h \ dlink.cc \ @@ -1912,6 +1972,7 @@ FadingCounter.cc \ fd.cc \ fde.cc \ + filemap.cc \ forward.cc \ fqdncache.cc \ ftp.cc \ @@ -1923,7 +1984,9 @@ $(HTCPSOURCE) \ http.cc \ HttpBody.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ @@ -1996,9 +2059,11 @@ tests/test_http_range.cc \ tests/stub_ipc_Forwarder.cc \ tests/stub_main_cc.cc \ + tests/stub_MemStore.cc \ time.cc \ tools.cc \ tunnel.cc \ + $(UNLINKDSOURCE) \ url.cc \ URLScheme.cc \ urn.cc \ @@ -2007,7 +2072,8 @@ $(WIN32_SOURCE) \ wordlist.cc nodist_tests_test_http_range_SOURCES = \ - $(BUILT_SOURCES) + $(BUILT_SOURCES) \ + $(DISKIO_GEN_SOURCE) tests_test_http_range_LDADD = \ $(AUTH_ACL_LIBS) \ ident/libident.la \ @@ -2016,22 +2082,24 @@ acl/libstate.la \ $(AUTH_LIBS) \ acl/libapi.la \ - base/libbase.la \ libsquid.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la \ - mgr/libmgr.la \ anyp/libanyp.la \ - $(SNMP_LIBS) \ icmp/libicmp.la icmp/libicmp-core.la \ comm/libcomm.la \ log/liblog.la \ format/libformat.la \ $(REPL_OBJS) \ + $(DISK_LIBS) \ + $(DISK_OS_LIBS) \ $(ADAPTATION_LIBS) \ $(ESI_LIBS) \ $(SSL_LIBS) \ + ipc/libipc.la \ + base/libbase.la \ + mgr/libmgr.la \ + $(SNMP_LIBS) \ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ @@ -2054,7 +2122,9 @@ MemBuf.cc \ MemBuf.h \ mem.cc \ + String.cc \ structs.h \ + tests/stub_cache_cf.cc \ tests/stub_cache_manager.cc \ tests/stub_debug.cc \ tests/stub_event.cc \ @@ -2062,7 +2132,8 @@ tests/testHttpParser.cc \ tests/testHttpParser.h \ tests/testMain.cc \ - time.cc + time.cc \ + wordlist.cc nodist_tests_testHttpParser_SOURCES = \ $(TESTSOURCES) tests_testHttpParser_LDADD= \ @@ -2091,6 +2162,7 @@ tests/testHttpRequestMethod.h \ tests/testHttpRequestMethod.cc \ tests/testMain.cc \ + tests/stub_DiskIOModule.cc \ tests/stub_main_cc.cc \ tests/stub_ipc_Forwarder.cc \ time.cc \ @@ -2140,7 +2212,9 @@ HttpBody.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ @@ -2205,6 +2279,7 @@ tools.cc \ tunnel.cc \ SwapDir.cc \ + MemStore.cc \ url.cc \ URLScheme.cc \ urn.cc \ @@ -2223,11 +2298,11 @@ acl/libstate.la \ $(AUTH_LIBS) \ acl/libapi.la \ - base/libbase.la \ libsquid.la \ ip/libip.la \ fs/libfs.la \ ipc/libipc.la \ + base/libbase.la \ mgr/libmgr.la \ anyp/libanyp.la \ $(SNMP_LIBS) \ @@ -2242,6 +2317,7 @@ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ + $(DISK_OS_LIBS) \ $(REGEXLIB) \ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ @@ -2270,7 +2346,9 @@ event.cc \ EventLoop.cc \ filemap.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ @@ -2322,14 +2400,15 @@ tests/stub_http.cc \ tests/stub_HttpReply.cc \ tests/stub_HttpRequest.cc \ + tests/stub_libcomm.cc \ tests/stub_MemObject.cc \ + tests/stub_MemStore.cc \ tests/stub_mime.cc \ tests/stub_Port.cc \ tests/stub_store_client.cc \ tests/stub_store_rebuild.cc \ tests/stub_store_swapout.cc \ tests/stub_tools.cc \ - tests/stub_TypedMsgHdr.cc \ tests/stub_UdsOp.cc \ tests/testMain.cc \ tests/testStore.cc \ @@ -2367,8 +2446,8 @@ libsquid.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la \ mgr/libmgr.la \ + ipc/libipc.la \ anyp/libanyp.la \ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ @@ -2390,14 +2469,17 @@ tests_testString_SOURCES = \ ClientInfo.h \ mem.cc \ + MemBuf.cc \ String.cc \ tests/testMain.cc \ tests/testString.cc \ tests/testString.h \ + tests/stub_cache_cf.cc \ tests/stub_cache_manager.cc \ tests/stub_debug.cc \ tests/stub_HelperChildConfig.cc \ - time.cc + time.cc \ + wordlist.cc nodist_tests_testString_SOURCES = \ $(TESTSOURCES) tests_testString_LDADD = \ @@ -2442,9 +2524,9 @@ tests/stub_HelperChildConfig.cc \ tests/stub_icp.cc \ tests/stub_ipc.cc \ + tests/stub_MemStore.cc \ tests/stub_pconn.cc \ tests/stub_Port.cc \ - tests/stub_TypedMsgHdr.cc \ tests/stub_UdsOp.cc \ tests/stub_internal.cc \ tests/stub_store_rebuild.cc \ @@ -2504,7 +2586,9 @@ MemBuf.cc \ HttpHdrContRange.cc \ Packer.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ url.cc \ @@ -2540,17 +2624,17 @@ acl/libstate.la \ $(AUTH_LIBS) \ acl/libapi.la \ - base/libbase.la \ libsquid.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la \ mgr/libmgr.la \ $(REPL_OBJS) \ acl/libacls.la \ anyp/libanyp.la \ $(DISK_LIBS) \ $(DISK_OS_LIBS) \ + acl/libapi.la \ + ipc/libipc.la \ $(SSL_LIBS) \ comm/libcomm.la \ base/libbase.la \ @@ -2572,10 +2656,12 @@ tests/testMain.cc \ tests/testCoss.h \ tests/stub_cache_manager.cc \ + tests/stub_client_db.cc \ tests/stub_debug.cc \ tests/stub_HelperChildConfig.cc \ tests/stub_internal.cc \ - tests/stub_CommIO.cc \ + tests/stub_ipc.cc \ + tests/stub_pconn.cc \ tests/stub_store_rebuild.cc \ fd.cc \ disk.cc \ @@ -2620,8 +2706,6 @@ tests/stub_helper.cc \ cbdata.cc \ String.cc \ - tests/stub_comm.cc \ - tests/stub_debug.cc \ tests/stub_client_side_request.cc \ tests/stub_http.cc \ mem_node.cc \ @@ -2634,7 +2718,9 @@ MemBuf.cc \ HttpHdrContRange.cc \ Packer.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ url.cc \ @@ -2645,8 +2731,11 @@ tests/stub_HttpRequest.cc \ tests/stub_access_log.cc \ refresh.cc \ + tests/stub_MemStore.cc \ + tests/stub_Port.cc \ tests/stub_store_client.cc \ tests/stub_tools.cc \ + tests/stub_UdsOp.cc \ tests/testStoreSupport.cc \ tests/testStoreSupport.h \ time.cc \ @@ -2661,6 +2750,7 @@ $(TESTSOURCES) \ $(DISKIO_GEN_SOURCE) tests_testCoss_LDADD = \ + anyp/libanyp.la \ libsquid.la \ $(REGEXLIB) \ $(AUTH_ACL_LIBS) \ @@ -2670,18 +2760,19 @@ acl/libstate.la \ $(AUTH_LIBS) \ acl/libapi.la \ - base/libbase.la \ libsquid.la \ + comm/libcomm.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la \ mgr/libmgr.la \ $(REPL_OBJS) \ $(DISK_LIBS) \ $(DISK_OS_LIBS) \ $(COMMON_LIBS) \ - libsquid.la \ + $(SSL_LIBS) \ acl/libapi.la \ + ipc/libipc.la \ + base/libbase.la \ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ @@ -2758,7 +2849,9 @@ MemBuf.cc \ HttpHdrContRange.cc \ Packer.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ url.cc \ @@ -2860,7 +2953,9 @@ $(HTCPSOURCE) \ http.cc \ HttpBody.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ @@ -2932,6 +3027,7 @@ StoreSwapLogData.cc \ String.cc \ SwapDir.cc \ + MemStore.cc \ tests/stub_debug.cc \ tests/stub_DiskIOModule.cc \ tests/stub_main_cc.cc \ @@ -2973,6 +3069,7 @@ icmp/libicmp.la icmp/libicmp-core.la \ comm/libcomm.la \ log/liblog.la \ + $(DISK_OS_LIBS) \ format/libformat.la \ $(REGEXLIB) \ $(REPL_OBJS) \ diff -u -r -N squid-3.2.0.12/src/Makefile.in squid-3.2.0.13/src/Makefile.in --- squid-3.2.0.12/src/Makefile.in 2011-09-16 23:38:16.000000000 +1200 +++ squid-3.2.0.13/src/Makefile.in 2011-10-14 14:47:47.000000000 +1300 @@ -139,6 +139,18 @@ DiskIO/DiskThreads/DiskThreadsDiskIOModule.$(OBJEXT) \ DiskIO/DiskThreads/DiskThreadsIOStrategy.$(OBJEXT) libDiskThreads_a_OBJECTS = $(am_libDiskThreads_a_OBJECTS) +libIpcIo_a_AR = $(AR) $(ARFLAGS) +libIpcIo_a_LIBADD = +am_libIpcIo_a_OBJECTS = DiskIO/IpcIo/IpcIoFile.$(OBJEXT) \ + DiskIO/IpcIo/IpcIoIOStrategy.$(OBJEXT) \ + DiskIO/IpcIo/IpcIoDiskIOModule.$(OBJEXT) +libIpcIo_a_OBJECTS = $(am_libIpcIo_a_OBJECTS) +libMmapped_a_AR = $(AR) $(ARFLAGS) +libMmapped_a_LIBADD = +am_libMmapped_a_OBJECTS = DiskIO/Mmapped/MmappedFile.$(OBJEXT) \ + DiskIO/Mmapped/MmappedIOStrategy.$(OBJEXT) \ + DiskIO/Mmapped/MmappedDiskIOModule.$(OBJEXT) +libMmapped_a_OBJECTS = $(am_libMmapped_a_OBJECTS) LTLIBRARIES = $(noinst_LTLIBRARIES) libsquid_la_LIBADD = am_libsquid_la_OBJECTS = comm.lo CommCalls.lo DescriptorSet.lo \ @@ -222,42 +234,42 @@ HelperChildConfig.h HelperChildConfig.cc hier_code.h \ HierarchyLogEntry.h htcp.cc htcp.h http.cc http.h \ HttpStatusCode.h HttpStatusLine.cc HttpStatusLine.h \ - HttpHdrCc.cc HttpHdrRange.cc HttpHdrSc.cc HttpHdrSc.h \ - HttpHdrScTarget.cc HttpHdrScTarget.h HttpHdrContRange.cc \ - HttpHdrContRange.h HttpHeader.cc HttpHeader.h HttpHeaderMask.h \ - HttpHeaderRange.h HttpHeaderTools.cc HttpBody.cc \ - HttpControlMsg.h HttpMsg.cc HttpMsg.h HttpParser.cc \ - HttpParser.h HttpReply.cc HttpReply.h HttpRequest.cc \ - HttpRequest.h HttpRequestMethod.cc HttpRequestMethod.h \ - HttpVersion.h ICP.h icp_opcode.h icp_v2.cc icp_v3.cc int.cc \ - internal.cc ipc.cc ipc_win32.cc ipcache.cc ipcache.h \ - LeakFinder.cc list.cc lookup_t.h main.cc mem.cc mem_node.cc \ - mem_node.h Mem.h MemBuf.cc MemObject.cc MemObject.h mime.cc \ - mime_header.cc multicast.cc neighbors.cc Packer.cc Packer.h \ - Parsing.cc Parsing.h ProfStats.cc pconn.cc pconn.h \ - PeerDigest.h peer_digest.cc peer_proxy_negotiate_auth.cc \ - peer_select.cc peer_sourcehash.cc peer_userhash.cc \ - PeerSelectState.h PingData.h protos.h redirect.cc refresh.cc \ - RemovalPolicy.cc RemovalPolicy.h send-announce.cc \ - base/InstanceId.h MemBlob.h MemBlob.cc snmp_core.h \ - snmp_core.cc snmp_agent.cc squid.h SquidMath.h SquidMath.cc \ - SquidNew.cc stat.cc StatHist.cc String.cc stmem.cc stmem.h \ - store.cc Store.h StoreFileSystem.cc StoreFileSystem.h \ - StoreHashIndex.h store_io.cc StoreIOBuffer.h StoreIOState.cc \ - StoreIOState.h store_client.cc StoreClient.h store_digest.cc \ - store_dir.cc store_key_md5.cc store_log.cc store_rebuild.cc \ - store_swapin.cc store_swapmeta.cc store_swapout.cc \ - StoreMeta.cc StoreMeta.h StoreMetaMD5.cc StoreMetaMD5.h \ - StoreMetaSTD.cc StoreMetaSTD.h StoreMetaSTDLFS.cc \ - StoreMetaSTDLFS.h StoreMetaObjSize.h StoreMetaUnpacker.cc \ - StoreMetaUnpacker.h StoreMetaURL.cc StoreMetaURL.h \ - StoreMetaVary.cc StoreMetaVary.h StoreSearch.h \ + HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci HttpHdrRange.cc \ + HttpHdrSc.cc HttpHdrSc.h HttpHdrScTarget.cc HttpHdrScTarget.h \ + HttpHdrContRange.cc HttpHdrContRange.h HttpHeader.cc \ + HttpHeader.h HttpHeaderMask.h HttpHeaderRange.h \ + HttpHeaderTools.cc HttpBody.cc HttpControlMsg.h HttpMsg.cc \ + HttpMsg.h HttpParser.cc HttpParser.h HttpReply.cc HttpReply.h \ + HttpRequest.cc HttpRequest.h HttpRequestMethod.cc \ + HttpRequestMethod.h HttpVersion.h ICP.h icp_opcode.h icp_v2.cc \ + icp_v3.cc int.cc internal.cc ipc.cc ipc_win32.cc ipcache.cc \ + ipcache.h LeakFinder.cc list.cc lookup_t.h main.cc mem.cc \ + mem_node.cc mem_node.h Mem.h MemBuf.cc MemObject.cc \ + MemObject.h mime.cc mime_header.cc multicast.cc neighbors.cc \ + Packer.cc Packer.h Parsing.cc Parsing.h ProfStats.cc pconn.cc \ + pconn.h PeerDigest.h peer_digest.cc \ + peer_proxy_negotiate_auth.cc peer_select.cc peer_sourcehash.cc \ + peer_userhash.cc PeerSelectState.h PingData.h protos.h \ + redirect.cc refresh.cc RemovalPolicy.cc RemovalPolicy.h \ + send-announce.cc base/InstanceId.h MemBlob.h MemBlob.cc \ + snmp_core.h snmp_core.cc snmp_agent.cc squid.h SquidMath.h \ + SquidMath.cc SquidNew.cc stat.cc StatHist.cc String.cc \ + stmem.cc stmem.h store.cc Store.h StoreFileSystem.cc \ + StoreFileSystem.h StoreHashIndex.h store_io.cc StoreIOBuffer.h \ + StoreIOState.cc StoreIOState.h store_client.cc StoreClient.h \ + store_digest.cc store_dir.cc store_key_md5.cc store_log.cc \ + store_rebuild.cc store_swapin.cc store_swapmeta.cc \ + store_swapout.cc StoreMeta.cc StoreMeta.h StoreMetaMD5.cc \ + StoreMetaMD5.h StoreMetaSTD.cc StoreMetaSTD.h \ + StoreMetaSTDLFS.cc StoreMetaSTDLFS.h StoreMetaObjSize.h \ + StoreMetaUnpacker.cc StoreMetaUnpacker.h StoreMetaURL.cc \ + StoreMetaURL.h StoreMetaVary.cc StoreMetaVary.h StoreSearch.h \ StoreSwapLogData.cc StoreSwapLogData.h Server.cc Server.h \ - structs.h swap_log_op.h SwapDir.cc SwapDir.h time.cc \ - TimeOrTag.h tools.cc tunnel.cc typedefs.h unlinkd.cc url.cc \ - URL.h URLScheme.cc URLScheme.h urn.cc wccp.cc wccp2.cc \ - whois.cc wordlist.cc wordlist.h win32.cc WinSvc.cc \ - LoadableModule.h LoadableModule.cc LoadableModules.h \ + structs.h swap_log_op.h SwapDir.cc SwapDir.h MemStore.cc \ + MemStore.h time.cc TimeOrTag.h tools.cc tunnel.cc typedefs.h \ + unlinkd.cc url.cc URL.h URLScheme.cc URLScheme.h urn.cc \ + wccp.cc wccp2.cc whois.cc wordlist.cc wordlist.h win32.cc \ + WinSvc.cc LoadableModule.h LoadableModule.cc LoadableModules.h \ LoadableModules.cc am__objects_4 = AclRegs.$(OBJEXT) AuthReg.$(OBJEXT) am__objects_5 = delay_pools.$(OBJEXT) DelayId.$(OBJEXT) \ @@ -332,11 +344,12 @@ StoreMetaSTD.$(OBJEXT) StoreMetaSTDLFS.$(OBJEXT) \ StoreMetaUnpacker.$(OBJEXT) StoreMetaURL.$(OBJEXT) \ StoreMetaVary.$(OBJEXT) StoreSwapLogData.$(OBJEXT) \ - Server.$(OBJEXT) SwapDir.$(OBJEXT) time.$(OBJEXT) \ - tools.$(OBJEXT) tunnel.$(OBJEXT) $(am__objects_16) \ - url.$(OBJEXT) URLScheme.$(OBJEXT) urn.$(OBJEXT) wccp.$(OBJEXT) \ - wccp2.$(OBJEXT) whois.$(OBJEXT) wordlist.$(OBJEXT) \ - $(am__objects_17) $(am__objects_18) $(am__objects_20) + Server.$(OBJEXT) SwapDir.$(OBJEXT) MemStore.$(OBJEXT) \ + time.$(OBJEXT) tools.$(OBJEXT) tunnel.$(OBJEXT) \ + $(am__objects_16) url.$(OBJEXT) URLScheme.$(OBJEXT) \ + urn.$(OBJEXT) wccp.$(OBJEXT) wccp2.$(OBJEXT) whois.$(OBJEXT) \ + wordlist.$(OBJEXT) $(am__objects_17) $(am__objects_18) \ + $(am__objects_20) am__EXTRA_squid_SOURCES_DIST = DiskIO/AIO/aio_win32.cc \ DiskIO/AIO/aio_win32.h ConfigOption.h CommonPool.h \ CompositePoolNode.h delay_pools.cc DelayId.cc DelayId.h \ @@ -389,9 +402,10 @@ tests/stub_debug.$(OBJEXT) tests/stub_DelayId.$(OBJEXT) \ tests/stub_DiskIOModule.$(OBJEXT) tests/stub_fd.$(OBJEXT) \ tests/stub_HttpRequest.$(OBJEXT) \ - tests/stub_MemObject.$(OBJEXT) tests/stub_mime.$(OBJEXT) \ - tests/stub_store.$(OBJEXT) tests/stub_store_rebuild.$(OBJEXT) \ - tests/stub_store_swapout.$(OBJEXT) \ + tests/stub_MemObject.$(OBJEXT) tests/stub_MemStore.$(OBJEXT) \ + tests/stub_mime.$(OBJEXT) tests/stub_store.$(OBJEXT) \ + tests/stub_store_rebuild.$(OBJEXT) \ + tests/stub_store_swapout.$(OBJEXT) tests/stub_tools.$(OBJEXT) \ tests/stub_cache_manager.$(OBJEXT) \ tests/testACLMaxUserIP.$(OBJEXT) tests/testMain.$(OBJEXT) \ time.$(OBJEXT) url.$(OBJEXT) URLScheme.$(OBJEXT) mem.$(OBJEXT) \ @@ -429,14 +443,19 @@ DelayPools.h DelaySpec.cc DelaySpec.h DelayTagged.cc \ DelayTagged.h DelayUser.cc DelayUser.h DelayVector.cc \ DelayVector.h NullDelayId.cc NullDelayId.h \ - ClientDelayConfig.cc ClientDelayConfig.h disk.cc dlink.h \ - dlink.cc dns_internal.cc DnsLookupDetails.h \ - DnsLookupDetails.cc dns.cc errorpage.cc ETag.cc event.cc \ - external_acl.cc ExternalACLEntry.cc fd.cc fde.cc forward.cc \ - fqdncache.cc ftp.cc gopher.cc hier_code.h helper.cc \ - HelperChildConfig.h HelperChildConfig.cc htcp.cc htcp.h \ - http.cc HttpBody.cc HttpHeader.cc HttpHeaderTools.cc \ - HttpHdrCc.cc HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \ + ClientDelayConfig.cc ClientDelayConfig.h \ + DiskIO/DiskIOModule.cc DiskIO/ReadRequest.cc \ + DiskIO/ReadRequest.h DiskIO/WriteRequest.cc \ + DiskIO/WriteRequest.h DiskIO/DiskFile.h \ + DiskIO/DiskIOStrategy.h DiskIO/IORequestor.h \ + DiskIO/DiskIOModule.h disk.cc dlink.h dlink.cc dns_internal.cc \ + DnsLookupDetails.h DnsLookupDetails.cc dns.cc errorpage.cc \ + ETag.cc event.cc external_acl.cc ExternalACLEntry.cc fd.cc \ + fde.cc filemap.cc forward.cc fqdncache.cc ftp.cc gopher.cc \ + hier_code.h helper.cc HelperChildConfig.h HelperChildConfig.cc \ + htcp.cc htcp.h http.cc HttpBody.cc HttpHeader.cc \ + HttpHeaderTools.cc HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci \ + HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \ HttpHdrScTarget.cc HttpMsg.cc HttpReply.cc HttpStatusLine.cc \ icp_v2.cc icp_v3.cc ipc.cc ipc_win32.cc ipcache.cc int.cc \ internal.cc list.cc multicast.cc mem_node.cc MemBuf.cc \ @@ -452,8 +471,8 @@ StoreIOState.cc StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ StoreMetaSTDLFS.cc StoreMetaUnpacker.cc StoreMetaURL.cc \ StoreMetaVary.cc StoreSwapLogData.cc tools.cc tunnel.cc \ - SwapDir.cc url.cc URLScheme.cc urn.cc wccp2.cc whois.cc \ - FadingCounter.cc win32.cc wordlist.cc + SwapDir.cc MemStore.cc unlinkd.cc url.cc URLScheme.cc urn.cc \ + wccp2.cc whois.cc FadingCounter.cc win32.cc wordlist.cc am_tests_testCacheManager_OBJECTS = $(am__objects_4) debug.$(OBJEXT) \ HttpParser.$(OBJEXT) HttpRequest.$(OBJEXT) \ HttpRequestMethod.$(OBJEXT) mem.$(OBJEXT) String.$(OBJEXT) \ @@ -467,24 +486,24 @@ client_side_reply.$(OBJEXT) client_side_request.$(OBJEXT) \ clientStream.$(OBJEXT) ConfigOption.$(OBJEXT) \ ConfigParser.$(OBJEXT) CpuAffinityMap.$(OBJEXT) \ - CpuAffinitySet.$(OBJEXT) $(am__objects_6) disk.$(OBJEXT) \ - dlink.$(OBJEXT) $(am__objects_8) errorpage.$(OBJEXT) \ - ETag.$(OBJEXT) event.$(OBJEXT) external_acl.$(OBJEXT) \ - ExternalACLEntry.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) \ - forward.$(OBJEXT) fqdncache.$(OBJEXT) ftp.$(OBJEXT) \ - gopher.$(OBJEXT) helper.$(OBJEXT) HelperChildConfig.$(OBJEXT) \ - $(am__objects_9) http.$(OBJEXT) HttpBody.$(OBJEXT) \ - HttpHeader.$(OBJEXT) HttpHeaderTools.$(OBJEXT) \ - HttpHdrCc.$(OBJEXT) HttpHdrContRange.$(OBJEXT) \ - HttpHdrRange.$(OBJEXT) HttpHdrSc.$(OBJEXT) \ - HttpHdrScTarget.$(OBJEXT) HttpMsg.$(OBJEXT) \ - HttpReply.$(OBJEXT) HttpStatusLine.$(OBJEXT) icp_v2.$(OBJEXT) \ - icp_v3.$(OBJEXT) $(am__objects_10) ipcache.$(OBJEXT) \ - int.$(OBJEXT) internal.$(OBJEXT) list.$(OBJEXT) \ - multicast.$(OBJEXT) mem_node.$(OBJEXT) MemBuf.$(OBJEXT) \ - MemObject.$(OBJEXT) mime.$(OBJEXT) mime_header.$(OBJEXT) \ - neighbors.$(OBJEXT) Packer.$(OBJEXT) Parsing.$(OBJEXT) \ - pconn.$(OBJEXT) peer_digest.$(OBJEXT) \ + CpuAffinitySet.$(OBJEXT) $(am__objects_6) $(am__objects_7) \ + disk.$(OBJEXT) dlink.$(OBJEXT) $(am__objects_8) \ + errorpage.$(OBJEXT) ETag.$(OBJEXT) event.$(OBJEXT) \ + external_acl.$(OBJEXT) ExternalACLEntry.$(OBJEXT) fd.$(OBJEXT) \ + fde.$(OBJEXT) filemap.$(OBJEXT) forward.$(OBJEXT) \ + fqdncache.$(OBJEXT) ftp.$(OBJEXT) gopher.$(OBJEXT) \ + helper.$(OBJEXT) HelperChildConfig.$(OBJEXT) $(am__objects_9) \ + http.$(OBJEXT) HttpBody.$(OBJEXT) HttpHeader.$(OBJEXT) \ + HttpHeaderTools.$(OBJEXT) HttpHdrCc.$(OBJEXT) \ + HttpHdrContRange.$(OBJEXT) HttpHdrRange.$(OBJEXT) \ + HttpHdrSc.$(OBJEXT) HttpHdrScTarget.$(OBJEXT) \ + HttpMsg.$(OBJEXT) HttpReply.$(OBJEXT) HttpStatusLine.$(OBJEXT) \ + icp_v2.$(OBJEXT) icp_v3.$(OBJEXT) $(am__objects_10) \ + ipcache.$(OBJEXT) int.$(OBJEXT) internal.$(OBJEXT) \ + list.$(OBJEXT) multicast.$(OBJEXT) mem_node.$(OBJEXT) \ + MemBuf.$(OBJEXT) MemObject.$(OBJEXT) mime.$(OBJEXT) \ + mime_header.$(OBJEXT) neighbors.$(OBJEXT) Packer.$(OBJEXT) \ + Parsing.$(OBJEXT) pconn.$(OBJEXT) peer_digest.$(OBJEXT) \ peer_proxy_negotiate_auth.$(OBJEXT) peer_select.$(OBJEXT) \ peer_sourcehash.$(OBJEXT) peer_userhash.$(OBJEXT) \ redirect.$(OBJEXT) refresh.$(OBJEXT) RemovalPolicy.$(OBJEXT) \ @@ -500,10 +519,12 @@ StoreMetaSTDLFS.$(OBJEXT) StoreMetaUnpacker.$(OBJEXT) \ StoreMetaURL.$(OBJEXT) StoreMetaVary.$(OBJEXT) \ StoreSwapLogData.$(OBJEXT) tools.$(OBJEXT) tunnel.$(OBJEXT) \ - SwapDir.$(OBJEXT) url.$(OBJEXT) URLScheme.$(OBJEXT) \ - urn.$(OBJEXT) wccp2.$(OBJEXT) whois.$(OBJEXT) \ - FadingCounter.$(OBJEXT) $(am__objects_17) wordlist.$(OBJEXT) -nodist_tests_testCacheManager_OBJECTS = $(am__objects_22) + SwapDir.$(OBJEXT) MemStore.$(OBJEXT) $(am__objects_16) \ + url.$(OBJEXT) URLScheme.$(OBJEXT) urn.$(OBJEXT) \ + wccp2.$(OBJEXT) whois.$(OBJEXT) FadingCounter.$(OBJEXT) \ + $(am__objects_17) wordlist.$(OBJEXT) +nodist_tests_testCacheManager_OBJECTS = $(am__objects_22) \ + $(am__objects_21) tests_testCacheManager_OBJECTS = $(am_tests_testCacheManager_OBJECTS) \ $(nodist_tests_testCacheManager_OBJECTS) tests_testCacheManager_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ @@ -511,8 +532,9 @@ $(CXXFLAGS) $(tests_testCacheManager_LDFLAGS) $(LDFLAGS) -o $@ am__tests_testCoss_SOURCES_DIST = tests/testCoss.cc tests/testMain.cc \ tests/testCoss.h tests/stub_cache_manager.cc \ - tests/stub_debug.cc tests/stub_HelperChildConfig.cc \ - tests/stub_internal.cc tests/stub_CommIO.cc \ + tests/stub_client_db.cc tests/stub_debug.cc \ + tests/stub_HelperChildConfig.cc tests/stub_internal.cc \ + tests/stub_ipc.cc tests/stub_pconn.cc \ tests/stub_store_rebuild.cc fd.cc disk.cc filemap.cc \ HttpBody.cc HttpReply.cc HttpStatusLine.cc int.cc list.cc \ MemObject.cc StoreSwapLogData.cc StoreIOState.cc StoreMeta.cc \ @@ -531,14 +553,16 @@ HttpRequestMethod.cc store_key_md5.cc Parsing.cc \ ConfigOption.cc SwapDir.cc tests/stub_acl.cc \ tests/stub_cache_cf.cc tests/stub_helper.cc cbdata.cc \ - String.cc tests/stub_comm.cc tests/stub_client_side_request.cc \ - tests/stub_http.cc mem_node.cc stmem.cc tests/stub_mime.cc \ - HttpHeaderTools.cc HttpHeader.cc mem.cc ClientInfo.h MemBuf.cc \ - HttpHdrContRange.cc Packer.cc HttpHdrCc.cc HttpHdrSc.cc \ - HttpHdrScTarget.cc url.cc StatHist.cc HttpHdrRange.cc ETag.cc \ - tests/stub_errorpage.cc tests/stub_HttpRequest.cc \ - tests/stub_access_log.cc refresh.cc tests/stub_store_client.cc \ - tests/stub_tools.cc tests/testStoreSupport.cc \ + String.cc tests/stub_client_side_request.cc tests/stub_http.cc \ + mem_node.cc stmem.cc tests/stub_mime.cc HttpHeaderTools.cc \ + HttpHeader.cc mem.cc ClientInfo.h MemBuf.cc \ + HttpHdrContRange.cc Packer.cc HttpHdrCc.h HttpHdrCc.cc \ + HttpHdrCc.cci HttpHdrSc.cc HttpHdrScTarget.cc url.cc \ + StatHist.cc HttpHdrRange.cc ETag.cc tests/stub_errorpage.cc \ + tests/stub_HttpRequest.cc tests/stub_access_log.cc refresh.cc \ + tests/stub_MemStore.cc tests/stub_Port.cc \ + tests/stub_store_client.cc tests/stub_tools.cc \ + tests/stub_UdsOp.cc tests/testStoreSupport.cc \ tests/testStoreSupport.h time.cc URLScheme.cc wordlist.cc \ DiskIO/DiskIOModule.cc DiskIO/ReadRequest.cc \ DiskIO/ReadRequest.h DiskIO/WriteRequest.cc \ @@ -547,11 +571,12 @@ DiskIO/DiskIOModule.h am_tests_testCoss_OBJECTS = tests/testCoss.$(OBJEXT) \ tests/testMain.$(OBJEXT) tests/stub_cache_manager.$(OBJEXT) \ - tests/stub_debug.$(OBJEXT) \ + tests/stub_client_db.$(OBJEXT) tests/stub_debug.$(OBJEXT) \ tests/stub_HelperChildConfig.$(OBJEXT) \ - tests/stub_internal.$(OBJEXT) tests/stub_CommIO.$(OBJEXT) \ - tests/stub_store_rebuild.$(OBJEXT) fd.$(OBJEXT) disk.$(OBJEXT) \ - filemap.$(OBJEXT) HttpBody.$(OBJEXT) HttpReply.$(OBJEXT) \ + tests/stub_internal.$(OBJEXT) tests/stub_ipc.$(OBJEXT) \ + tests/stub_pconn.$(OBJEXT) tests/stub_store_rebuild.$(OBJEXT) \ + fd.$(OBJEXT) disk.$(OBJEXT) filemap.$(OBJEXT) \ + HttpBody.$(OBJEXT) HttpReply.$(OBJEXT) \ HttpStatusLine.$(OBJEXT) int.$(OBJEXT) list.$(OBJEXT) \ MemObject.$(OBJEXT) StoreSwapLogData.$(OBJEXT) \ StoreIOState.$(OBJEXT) StoreMeta.$(OBJEXT) \ @@ -568,7 +593,6 @@ Parsing.$(OBJEXT) ConfigOption.$(OBJEXT) SwapDir.$(OBJEXT) \ tests/stub_acl.$(OBJEXT) tests/stub_cache_cf.$(OBJEXT) \ tests/stub_helper.$(OBJEXT) cbdata.$(OBJEXT) String.$(OBJEXT) \ - tests/stub_comm.$(OBJEXT) tests/stub_debug.$(OBJEXT) \ tests/stub_client_side_request.$(OBJEXT) \ tests/stub_http.$(OBJEXT) mem_node.$(OBJEXT) stmem.$(OBJEXT) \ tests/stub_mime.$(OBJEXT) HttpHeaderTools.$(OBJEXT) \ @@ -580,9 +604,11 @@ tests/stub_errorpage.$(OBJEXT) \ tests/stub_HttpRequest.$(OBJEXT) \ tests/stub_access_log.$(OBJEXT) refresh.$(OBJEXT) \ + tests/stub_MemStore.$(OBJEXT) tests/stub_Port.$(OBJEXT) \ tests/stub_store_client.$(OBJEXT) tests/stub_tools.$(OBJEXT) \ - tests/testStoreSupport.$(OBJEXT) time.$(OBJEXT) \ - URLScheme.$(OBJEXT) wordlist.$(OBJEXT) $(am__objects_7) + tests/stub_UdsOp.$(OBJEXT) tests/testStoreSupport.$(OBJEXT) \ + time.$(OBJEXT) URLScheme.$(OBJEXT) wordlist.$(OBJEXT) \ + $(am__objects_7) nodist_tests_testCoss_OBJECTS = swap_log_op.$(OBJEXT) \ SquidMath.$(OBJEXT) $(am__objects_23) $(am__objects_21) tests_testCoss_OBJECTS = $(am_tests_testCoss_OBJECTS) \ @@ -603,31 +629,32 @@ DiskIO/WriteRequest.cc DiskIO/WriteRequest.h DiskIO/DiskFile.h \ DiskIO/DiskIOStrategy.h DiskIO/IORequestor.h \ DiskIO/DiskIOModule.h disk.cc ETag.cc EventLoop.cc event.cc \ - fd.cc filemap.cc HttpBody.cc HttpHdrCc.cc HttpHdrContRange.cc \ - HttpHdrSc.cc HttpHdrScTarget.cc HttpHdrRange.cc \ - HttpHeaderTools.cc HttpHeader.cc HttpMsg.cc HttpReply.cc \ - HttpRequestMethod.cc HttpStatusLine.cc int.cc list.cc \ - MemBuf.cc MemObject.cc mem_node.cc mem.cc Packer.cc Parsing.cc \ - refresh.cc RemovalPolicy.cc StatHist.cc stmem.cc \ - StoreFileSystem.cc StoreIOState.cc StoreMeta.cc \ - StoreMetaMD5.cc StoreMetaSTD.cc StoreMetaSTDLFS.cc \ - StoreMetaUnpacker.cc StoreMetaURL.cc StoreMetaVary.cc \ - StoreSwapLogData.cc store_dir.cc store_io.cc store_key_md5.cc \ - store_swapout.cc store_swapmeta.cc store.cc String.cc \ - SwapDir.cc tests/stub_access_log.cc tests/stub_acl.cc \ - tests/stub_cache_cf.cc tests/stub_cache_manager.cc \ - tests/stub_client_db.cc tests/stub_client_side_request.cc \ - tests/stub_debug.cc tests/stub_errorpage.cc \ - tests/stub_helper.cc tests/stub_HelperChildConfig.cc \ - tests/stub_HttpRequest.cc tests/stub_http.cc tests/stub_icp.cc \ - tests/stub_internal.cc tests/stub_ipc.cc tests/stub_ipcache.cc \ - tests/stub_libicmp.cc tests/stub_mime.cc tests/stub_pconn.cc \ + fd.cc filemap.cc HttpBody.cc HttpHdrCc.h HttpHdrCc.cc \ + HttpHdrCc.cci HttpHdrContRange.cc HttpHdrSc.cc \ + HttpHdrScTarget.cc HttpHdrRange.cc HttpHeaderTools.cc \ + HttpHeader.cc HttpMsg.cc HttpReply.cc HttpRequestMethod.cc \ + HttpStatusLine.cc int.cc list.cc MemBuf.cc MemObject.cc \ + mem_node.cc mem.cc Packer.cc Parsing.cc refresh.cc \ + RemovalPolicy.cc StatHist.cc stmem.cc StoreFileSystem.cc \ + StoreIOState.cc StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ + StoreMetaSTDLFS.cc StoreMetaUnpacker.cc StoreMetaURL.cc \ + StoreMetaVary.cc StoreSwapLogData.cc store_dir.cc store_io.cc \ + store_key_md5.cc store_swapout.cc store_swapmeta.cc store.cc \ + String.cc SwapDir.cc tests/stub_access_log.cc \ + tests/stub_acl.cc tests/stub_cache_cf.cc \ + tests/stub_cache_manager.cc tests/stub_client_db.cc \ + tests/stub_client_side_request.cc tests/stub_debug.cc \ + tests/stub_errorpage.cc tests/stub_helper.cc \ + tests/stub_HelperChildConfig.cc tests/stub_HttpRequest.cc \ + tests/stub_http.cc tests/stub_icp.cc tests/stub_internal.cc \ + tests/stub_ipc.cc tests/stub_ipcache.cc tests/stub_libicmp.cc \ + tests/stub_MemStore.cc tests/stub_mime.cc tests/stub_pconn.cc \ tests/stub_Port.cc tests/stub_store_client.cc \ tests/stub_store_rebuild.cc tests/stub_tools.cc \ - tests/stub_TypedMsgHdr.cc tests/stub_UdsOp.cc \ - tests/testDiskIO.cc tests/testDiskIO.h tests/testMain.cc \ - tests/testStoreSupport.cc tests/testStoreSupport.h time.cc \ - unlinkd.cc url.cc URLScheme.cc win32.cc wordlist.cc + tests/stub_UdsOp.cc tests/testDiskIO.cc tests/testDiskIO.h \ + tests/testMain.cc tests/testStoreSupport.cc \ + tests/testStoreSupport.h time.cc unlinkd.cc url.cc \ + URLScheme.cc win32.cc wordlist.cc am_tests_testDiskIO_OBJECTS = CacheDigest.$(OBJEXT) cbdata.$(OBJEXT) \ ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) $(am__objects_6) \ $(am__objects_7) disk.$(OBJEXT) ETag.$(OBJEXT) \ @@ -661,15 +688,14 @@ tests/stub_HttpRequest.$(OBJEXT) tests/stub_http.$(OBJEXT) \ tests/stub_icp.$(OBJEXT) tests/stub_internal.$(OBJEXT) \ tests/stub_ipc.$(OBJEXT) tests/stub_ipcache.$(OBJEXT) \ - tests/stub_libicmp.$(OBJEXT) tests/stub_mime.$(OBJEXT) \ - tests/stub_pconn.$(OBJEXT) tests/stub_Port.$(OBJEXT) \ - tests/stub_store_client.$(OBJEXT) \ + tests/stub_libicmp.$(OBJEXT) tests/stub_MemStore.$(OBJEXT) \ + tests/stub_mime.$(OBJEXT) tests/stub_pconn.$(OBJEXT) \ + tests/stub_Port.$(OBJEXT) tests/stub_store_client.$(OBJEXT) \ tests/stub_store_rebuild.$(OBJEXT) tests/stub_tools.$(OBJEXT) \ - tests/stub_TypedMsgHdr.$(OBJEXT) tests/stub_UdsOp.$(OBJEXT) \ - tests/testDiskIO.$(OBJEXT) tests/testMain.$(OBJEXT) \ - tests/testStoreSupport.$(OBJEXT) time.$(OBJEXT) \ - $(am__objects_16) url.$(OBJEXT) URLScheme.$(OBJEXT) \ - $(am__objects_17) wordlist.$(OBJEXT) + tests/stub_UdsOp.$(OBJEXT) tests/testDiskIO.$(OBJEXT) \ + tests/testMain.$(OBJEXT) tests/testStoreSupport.$(OBJEXT) \ + time.$(OBJEXT) $(am__objects_16) url.$(OBJEXT) \ + URLScheme.$(OBJEXT) $(am__objects_17) wordlist.$(OBJEXT) nodist_tests_testDiskIO_OBJECTS = $(am__objects_23) $(am__objects_21) \ SquidMath.$(OBJEXT) swap_log_op.$(OBJEXT) tests_testDiskIO_OBJECTS = $(am_tests_testDiskIO_OBJECTS) \ @@ -689,14 +715,19 @@ DelayPool.cc DelayPool.h DelayPools.h DelaySpec.cc DelaySpec.h \ DelayTagged.cc DelayTagged.h DelayUser.cc DelayUser.h \ DelayVector.cc DelayVector.h NullDelayId.cc NullDelayId.h \ - ClientDelayConfig.cc ClientDelayConfig.h disk.cc dlink.h \ - dlink.cc dns_internal.cc DnsLookupDetails.h \ - DnsLookupDetails.cc dns.cc errorpage.cc ETag.cc event.cc \ - EventLoop.h EventLoop.cc external_acl.cc ExternalACLEntry.cc \ - FadingCounter.cc fd.cc fde.cc forward.cc fqdncache.cc ftp.cc \ - gopher.cc helper.cc HelperChildConfig.h HelperChildConfig.cc \ - hier_code.h htcp.cc htcp.h http.cc HttpBody.cc HttpHeader.cc \ - HttpHeaderTools.cc HttpHdrCc.cc HttpHdrContRange.cc \ + ClientDelayConfig.cc ClientDelayConfig.h \ + DiskIO/DiskIOModule.cc DiskIO/ReadRequest.cc \ + DiskIO/ReadRequest.h DiskIO/WriteRequest.cc \ + DiskIO/WriteRequest.h DiskIO/DiskFile.h \ + DiskIO/DiskIOStrategy.h DiskIO/IORequestor.h \ + DiskIO/DiskIOModule.h disk.cc dlink.h dlink.cc dns_internal.cc \ + DnsLookupDetails.h DnsLookupDetails.cc dns.cc errorpage.cc \ + ETag.cc event.cc EventLoop.h EventLoop.cc external_acl.cc \ + ExternalACLEntry.cc FadingCounter.cc fd.cc fde.cc filemap.cc \ + forward.cc fqdncache.cc ftp.cc gopher.cc helper.cc \ + HelperChildConfig.h HelperChildConfig.cc hier_code.h htcp.cc \ + htcp.h http.cc HttpBody.cc HttpHeader.cc HttpHeaderTools.cc \ + HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci HttpHdrContRange.cc \ HttpHdrRange.cc HttpHdrSc.cc HttpHdrScTarget.cc HttpMsg.cc \ HttpParser.cc HttpParser.h HttpReply.cc HttpRequest.cc \ HttpRequestMethod.cc HttpStatusLine.cc icp_v2.cc icp_v3.cc \ @@ -717,8 +748,9 @@ StoreSwapLogData.cc String.cc SwapDir.cc \ tests/CapturingStoreEntry.h tests/testEvent.cc \ tests/testEvent.h tests/testMain.cc tests/stub_main_cc.cc \ - tests/stub_ipc_Forwarder.cc time.cc tools.cc tunnel.cc url.cc \ - URLScheme.cc urn.cc wccp2.cc whois.cc win32.cc wordlist.cc + tests/stub_ipc_Forwarder.cc time.cc tools.cc tunnel.cc \ + MemStore.cc unlinkd.cc url.cc URLScheme.cc urn.cc wccp2.cc \ + whois.cc win32.cc wordlist.cc am_tests_testEvent_OBJECTS = $(am__objects_4) BodyPipe.$(OBJEXT) \ CacheDigest.$(OBJEXT) cache_cf.$(OBJEXT) \ cache_manager.$(OBJEXT) carp.$(OBJEXT) cbdata.$(OBJEXT) \ @@ -727,49 +759,50 @@ client_side_request.$(OBJEXT) clientStream.$(OBJEXT) \ ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) \ CpuAffinityMap.$(OBJEXT) CpuAffinitySet.$(OBJEXT) \ - debug.$(OBJEXT) $(am__objects_6) disk.$(OBJEXT) \ - dlink.$(OBJEXT) $(am__objects_8) errorpage.$(OBJEXT) \ - ETag.$(OBJEXT) event.$(OBJEXT) EventLoop.$(OBJEXT) \ - external_acl.$(OBJEXT) ExternalACLEntry.$(OBJEXT) \ - FadingCounter.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) \ - forward.$(OBJEXT) fqdncache.$(OBJEXT) ftp.$(OBJEXT) \ - gopher.$(OBJEXT) helper.$(OBJEXT) HelperChildConfig.$(OBJEXT) \ - $(am__objects_9) http.$(OBJEXT) HttpBody.$(OBJEXT) \ - HttpHeader.$(OBJEXT) HttpHeaderTools.$(OBJEXT) \ - HttpHdrCc.$(OBJEXT) HttpHdrContRange.$(OBJEXT) \ - HttpHdrRange.$(OBJEXT) HttpHdrSc.$(OBJEXT) \ - HttpHdrScTarget.$(OBJEXT) HttpMsg.$(OBJEXT) \ - HttpParser.$(OBJEXT) HttpReply.$(OBJEXT) HttpRequest.$(OBJEXT) \ - HttpRequestMethod.$(OBJEXT) HttpStatusLine.$(OBJEXT) \ - icp_v2.$(OBJEXT) icp_v3.$(OBJEXT) $(am__objects_10) \ - ipcache.$(OBJEXT) int.$(OBJEXT) internal.$(OBJEXT) \ - list.$(OBJEXT) mem.$(OBJEXT) mem_node.$(OBJEXT) \ - MemBuf.$(OBJEXT) MemObject.$(OBJEXT) mime.$(OBJEXT) \ - mime_header.$(OBJEXT) multicast.$(OBJEXT) neighbors.$(OBJEXT) \ - Packer.$(OBJEXT) Parsing.$(OBJEXT) pconn.$(OBJEXT) \ - peer_digest.$(OBJEXT) peer_proxy_negotiate_auth.$(OBJEXT) \ - peer_select.$(OBJEXT) peer_sourcehash.$(OBJEXT) \ - peer_userhash.$(OBJEXT) ProtoPort.$(OBJEXT) redirect.$(OBJEXT) \ - refresh.$(OBJEXT) RemovalPolicy.$(OBJEXT) Server.$(OBJEXT) \ - $(am__objects_15) SquidMath.$(OBJEXT) stat.$(OBJEXT) \ - StatHist.$(OBJEXT) stmem.$(OBJEXT) store.$(OBJEXT) \ - store_client.$(OBJEXT) store_digest.$(OBJEXT) \ - store_dir.$(OBJEXT) store_io.$(OBJEXT) store_key_md5.$(OBJEXT) \ - store_log.$(OBJEXT) store_rebuild.$(OBJEXT) \ - store_swapin.$(OBJEXT) store_swapmeta.$(OBJEXT) \ - store_swapout.$(OBJEXT) StoreFileSystem.$(OBJEXT) \ - StoreIOState.$(OBJEXT) StoreMeta.$(OBJEXT) \ - StoreMetaMD5.$(OBJEXT) StoreMetaSTD.$(OBJEXT) \ - StoreMetaSTDLFS.$(OBJEXT) StoreMetaUnpacker.$(OBJEXT) \ - StoreMetaURL.$(OBJEXT) StoreMetaVary.$(OBJEXT) \ - StoreSwapLogData.$(OBJEXT) String.$(OBJEXT) SwapDir.$(OBJEXT) \ - tests/testEvent.$(OBJEXT) tests/testMain.$(OBJEXT) \ - tests/stub_main_cc.$(OBJEXT) \ + debug.$(OBJEXT) $(am__objects_6) $(am__objects_7) \ + disk.$(OBJEXT) dlink.$(OBJEXT) $(am__objects_8) \ + errorpage.$(OBJEXT) ETag.$(OBJEXT) event.$(OBJEXT) \ + EventLoop.$(OBJEXT) external_acl.$(OBJEXT) \ + ExternalACLEntry.$(OBJEXT) FadingCounter.$(OBJEXT) \ + fd.$(OBJEXT) fde.$(OBJEXT) filemap.$(OBJEXT) forward.$(OBJEXT) \ + fqdncache.$(OBJEXT) ftp.$(OBJEXT) gopher.$(OBJEXT) \ + helper.$(OBJEXT) HelperChildConfig.$(OBJEXT) $(am__objects_9) \ + http.$(OBJEXT) HttpBody.$(OBJEXT) HttpHeader.$(OBJEXT) \ + HttpHeaderTools.$(OBJEXT) HttpHdrCc.$(OBJEXT) \ + HttpHdrContRange.$(OBJEXT) HttpHdrRange.$(OBJEXT) \ + HttpHdrSc.$(OBJEXT) HttpHdrScTarget.$(OBJEXT) \ + HttpMsg.$(OBJEXT) HttpParser.$(OBJEXT) HttpReply.$(OBJEXT) \ + HttpRequest.$(OBJEXT) HttpRequestMethod.$(OBJEXT) \ + HttpStatusLine.$(OBJEXT) icp_v2.$(OBJEXT) icp_v3.$(OBJEXT) \ + $(am__objects_10) ipcache.$(OBJEXT) int.$(OBJEXT) \ + internal.$(OBJEXT) list.$(OBJEXT) mem.$(OBJEXT) \ + mem_node.$(OBJEXT) MemBuf.$(OBJEXT) MemObject.$(OBJEXT) \ + mime.$(OBJEXT) mime_header.$(OBJEXT) multicast.$(OBJEXT) \ + neighbors.$(OBJEXT) Packer.$(OBJEXT) Parsing.$(OBJEXT) \ + pconn.$(OBJEXT) peer_digest.$(OBJEXT) \ + peer_proxy_negotiate_auth.$(OBJEXT) peer_select.$(OBJEXT) \ + peer_sourcehash.$(OBJEXT) peer_userhash.$(OBJEXT) \ + ProtoPort.$(OBJEXT) redirect.$(OBJEXT) refresh.$(OBJEXT) \ + RemovalPolicy.$(OBJEXT) Server.$(OBJEXT) $(am__objects_15) \ + SquidMath.$(OBJEXT) stat.$(OBJEXT) StatHist.$(OBJEXT) \ + stmem.$(OBJEXT) store.$(OBJEXT) store_client.$(OBJEXT) \ + store_digest.$(OBJEXT) store_dir.$(OBJEXT) store_io.$(OBJEXT) \ + store_key_md5.$(OBJEXT) store_log.$(OBJEXT) \ + store_rebuild.$(OBJEXT) store_swapin.$(OBJEXT) \ + store_swapmeta.$(OBJEXT) store_swapout.$(OBJEXT) \ + StoreFileSystem.$(OBJEXT) StoreIOState.$(OBJEXT) \ + StoreMeta.$(OBJEXT) StoreMetaMD5.$(OBJEXT) \ + StoreMetaSTD.$(OBJEXT) StoreMetaSTDLFS.$(OBJEXT) \ + StoreMetaUnpacker.$(OBJEXT) StoreMetaURL.$(OBJEXT) \ + StoreMetaVary.$(OBJEXT) StoreSwapLogData.$(OBJEXT) \ + String.$(OBJEXT) SwapDir.$(OBJEXT) tests/testEvent.$(OBJEXT) \ + tests/testMain.$(OBJEXT) tests/stub_main_cc.$(OBJEXT) \ tests/stub_ipc_Forwarder.$(OBJEXT) time.$(OBJEXT) \ - tools.$(OBJEXT) tunnel.$(OBJEXT) url.$(OBJEXT) \ - URLScheme.$(OBJEXT) urn.$(OBJEXT) wccp2.$(OBJEXT) \ - whois.$(OBJEXT) $(am__objects_17) wordlist.$(OBJEXT) -nodist_tests_testEvent_OBJECTS = $(am__objects_22) + tools.$(OBJEXT) tunnel.$(OBJEXT) MemStore.$(OBJEXT) \ + $(am__objects_16) url.$(OBJEXT) URLScheme.$(OBJEXT) \ + urn.$(OBJEXT) wccp2.$(OBJEXT) whois.$(OBJEXT) \ + $(am__objects_17) wordlist.$(OBJEXT) +nodist_tests_testEvent_OBJECTS = $(am__objects_22) $(am__objects_21) tests_testEvent_OBJECTS = $(am_tests_testEvent_OBJECTS) \ $(nodist_tests_testEvent_OBJECTS) tests_testEvent_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ @@ -787,14 +820,19 @@ DelayPool.cc DelayPool.h DelayPools.h DelaySpec.cc DelaySpec.h \ DelayTagged.cc DelayTagged.h DelayUser.cc DelayUser.h \ DelayVector.cc DelayVector.h NullDelayId.cc NullDelayId.h \ - ClientDelayConfig.cc ClientDelayConfig.h disk.cc dlink.h \ - dlink.cc dns_internal.cc DnsLookupDetails.h \ - DnsLookupDetails.cc dns.cc errorpage.cc ETag.cc EventLoop.h \ - EventLoop.cc event.cc external_acl.cc ExternalACLEntry.cc \ - FadingCounter.cc fd.cc fde.cc forward.cc fqdncache.cc ftp.cc \ - gopher.cc helper.cc HelperChildConfig.h HelperChildConfig.cc \ - hier_code.h htcp.cc htcp.h http.cc HttpBody.cc HttpHeader.cc \ - HttpHeaderTools.cc HttpHdrCc.cc HttpHdrContRange.cc \ + ClientDelayConfig.cc ClientDelayConfig.h \ + DiskIO/DiskIOModule.cc DiskIO/ReadRequest.cc \ + DiskIO/ReadRequest.h DiskIO/WriteRequest.cc \ + DiskIO/WriteRequest.h DiskIO/DiskFile.h \ + DiskIO/DiskIOStrategy.h DiskIO/IORequestor.h \ + DiskIO/DiskIOModule.h disk.cc dlink.h dlink.cc dns_internal.cc \ + DnsLookupDetails.h DnsLookupDetails.cc dns.cc errorpage.cc \ + ETag.cc EventLoop.h EventLoop.cc event.cc external_acl.cc \ + ExternalACLEntry.cc FadingCounter.cc fd.cc fde.cc filemap.cc \ + forward.cc fqdncache.cc ftp.cc gopher.cc helper.cc \ + HelperChildConfig.h HelperChildConfig.cc hier_code.h htcp.cc \ + htcp.h http.cc HttpBody.cc HttpHeader.cc HttpHeaderTools.cc \ + HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci HttpHdrContRange.cc \ HttpHdrRange.cc HttpHdrSc.cc HttpHdrScTarget.cc HttpMsg.cc \ HttpParser.cc HttpParser.h HttpReply.cc HttpRequest.cc \ HttpRequestMethod.cc HttpStatusLine.cc icp_v2.cc icp_v3.cc \ @@ -814,8 +852,8 @@ StoreMetaVary.cc StoreSwapLogData.cc String.cc SwapDir.cc \ tests/testEventLoop.cc tests/testEventLoop.h tests/testMain.cc \ tests/stub_main_cc.cc tests/stub_ipc_Forwarder.cc time.cc \ - tools.cc tunnel.cc url.cc URLScheme.cc urn.cc wccp2.cc \ - whois.cc win32.cc wordlist.cc + tools.cc tunnel.cc MemStore.cc unlinkd.cc url.cc URLScheme.cc \ + urn.cc wccp2.cc whois.cc win32.cc wordlist.cc am_tests_testEventLoop_OBJECTS = $(am__objects_4) BodyPipe.$(OBJEXT) \ CacheDigest.$(OBJEXT) cache_manager.$(OBJEXT) \ cache_cf.$(OBJEXT) carp.$(OBJEXT) cbdata.$(OBJEXT) \ @@ -824,61 +862,65 @@ client_side_request.$(OBJEXT) clientStream.$(OBJEXT) \ ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) \ CpuAffinityMap.$(OBJEXT) CpuAffinitySet.$(OBJEXT) \ - debug.$(OBJEXT) $(am__objects_6) disk.$(OBJEXT) \ - dlink.$(OBJEXT) $(am__objects_8) errorpage.$(OBJEXT) \ - ETag.$(OBJEXT) EventLoop.$(OBJEXT) event.$(OBJEXT) \ - external_acl.$(OBJEXT) ExternalACLEntry.$(OBJEXT) \ - FadingCounter.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) \ - forward.$(OBJEXT) fqdncache.$(OBJEXT) ftp.$(OBJEXT) \ - gopher.$(OBJEXT) helper.$(OBJEXT) HelperChildConfig.$(OBJEXT) \ - $(am__objects_9) http.$(OBJEXT) HttpBody.$(OBJEXT) \ - HttpHeader.$(OBJEXT) HttpHeaderTools.$(OBJEXT) \ - HttpHdrCc.$(OBJEXT) HttpHdrContRange.$(OBJEXT) \ - HttpHdrRange.$(OBJEXT) HttpHdrSc.$(OBJEXT) \ - HttpHdrScTarget.$(OBJEXT) HttpMsg.$(OBJEXT) \ - HttpParser.$(OBJEXT) HttpReply.$(OBJEXT) HttpRequest.$(OBJEXT) \ - HttpRequestMethod.$(OBJEXT) HttpStatusLine.$(OBJEXT) \ - icp_v2.$(OBJEXT) icp_v3.$(OBJEXT) $(am__objects_10) \ - ipcache.$(OBJEXT) int.$(OBJEXT) internal.$(OBJEXT) \ - list.$(OBJEXT) MemBuf.$(OBJEXT) MemObject.$(OBJEXT) \ - mem.$(OBJEXT) mem_node.$(OBJEXT) mime.$(OBJEXT) \ - mime_header.$(OBJEXT) multicast.$(OBJEXT) neighbors.$(OBJEXT) \ - Packer.$(OBJEXT) Parsing.$(OBJEXT) pconn.$(OBJEXT) \ - peer_digest.$(OBJEXT) peer_proxy_negotiate_auth.$(OBJEXT) \ - peer_select.$(OBJEXT) peer_sourcehash.$(OBJEXT) \ - peer_userhash.$(OBJEXT) ProtoPort.$(OBJEXT) \ - RemovalPolicy.$(OBJEXT) redirect.$(OBJEXT) refresh.$(OBJEXT) \ - Server.$(OBJEXT) $(am__objects_15) SquidMath.$(OBJEXT) \ - stat.$(OBJEXT) StatHist.$(OBJEXT) stmem.$(OBJEXT) \ - store.$(OBJEXT) store_client.$(OBJEXT) store_digest.$(OBJEXT) \ - store_dir.$(OBJEXT) store_io.$(OBJEXT) store_key_md5.$(OBJEXT) \ - store_log.$(OBJEXT) store_rebuild.$(OBJEXT) \ - store_swapin.$(OBJEXT) store_swapmeta.$(OBJEXT) \ - store_swapout.$(OBJEXT) StoreFileSystem.$(OBJEXT) \ - StoreIOState.$(OBJEXT) StoreMeta.$(OBJEXT) \ - StoreMetaMD5.$(OBJEXT) StoreMetaSTD.$(OBJEXT) \ - StoreMetaSTDLFS.$(OBJEXT) StoreMetaUnpacker.$(OBJEXT) \ - StoreMetaURL.$(OBJEXT) StoreMetaVary.$(OBJEXT) \ - StoreSwapLogData.$(OBJEXT) String.$(OBJEXT) SwapDir.$(OBJEXT) \ + debug.$(OBJEXT) $(am__objects_6) $(am__objects_7) \ + disk.$(OBJEXT) dlink.$(OBJEXT) $(am__objects_8) \ + errorpage.$(OBJEXT) ETag.$(OBJEXT) EventLoop.$(OBJEXT) \ + event.$(OBJEXT) external_acl.$(OBJEXT) \ + ExternalACLEntry.$(OBJEXT) FadingCounter.$(OBJEXT) \ + fd.$(OBJEXT) fde.$(OBJEXT) filemap.$(OBJEXT) forward.$(OBJEXT) \ + fqdncache.$(OBJEXT) ftp.$(OBJEXT) gopher.$(OBJEXT) \ + helper.$(OBJEXT) HelperChildConfig.$(OBJEXT) $(am__objects_9) \ + http.$(OBJEXT) HttpBody.$(OBJEXT) HttpHeader.$(OBJEXT) \ + HttpHeaderTools.$(OBJEXT) HttpHdrCc.$(OBJEXT) \ + HttpHdrContRange.$(OBJEXT) HttpHdrRange.$(OBJEXT) \ + HttpHdrSc.$(OBJEXT) HttpHdrScTarget.$(OBJEXT) \ + HttpMsg.$(OBJEXT) HttpParser.$(OBJEXT) HttpReply.$(OBJEXT) \ + HttpRequest.$(OBJEXT) HttpRequestMethod.$(OBJEXT) \ + HttpStatusLine.$(OBJEXT) icp_v2.$(OBJEXT) icp_v3.$(OBJEXT) \ + $(am__objects_10) ipcache.$(OBJEXT) int.$(OBJEXT) \ + internal.$(OBJEXT) list.$(OBJEXT) MemBuf.$(OBJEXT) \ + MemObject.$(OBJEXT) mem.$(OBJEXT) mem_node.$(OBJEXT) \ + mime.$(OBJEXT) mime_header.$(OBJEXT) multicast.$(OBJEXT) \ + neighbors.$(OBJEXT) Packer.$(OBJEXT) Parsing.$(OBJEXT) \ + pconn.$(OBJEXT) peer_digest.$(OBJEXT) \ + peer_proxy_negotiate_auth.$(OBJEXT) peer_select.$(OBJEXT) \ + peer_sourcehash.$(OBJEXT) peer_userhash.$(OBJEXT) \ + ProtoPort.$(OBJEXT) RemovalPolicy.$(OBJEXT) redirect.$(OBJEXT) \ + refresh.$(OBJEXT) Server.$(OBJEXT) $(am__objects_15) \ + SquidMath.$(OBJEXT) stat.$(OBJEXT) StatHist.$(OBJEXT) \ + stmem.$(OBJEXT) store.$(OBJEXT) store_client.$(OBJEXT) \ + store_digest.$(OBJEXT) store_dir.$(OBJEXT) store_io.$(OBJEXT) \ + store_key_md5.$(OBJEXT) store_log.$(OBJEXT) \ + store_rebuild.$(OBJEXT) store_swapin.$(OBJEXT) \ + store_swapmeta.$(OBJEXT) store_swapout.$(OBJEXT) \ + StoreFileSystem.$(OBJEXT) StoreIOState.$(OBJEXT) \ + StoreMeta.$(OBJEXT) StoreMetaMD5.$(OBJEXT) \ + StoreMetaSTD.$(OBJEXT) StoreMetaSTDLFS.$(OBJEXT) \ + StoreMetaUnpacker.$(OBJEXT) StoreMetaURL.$(OBJEXT) \ + StoreMetaVary.$(OBJEXT) StoreSwapLogData.$(OBJEXT) \ + String.$(OBJEXT) SwapDir.$(OBJEXT) \ tests/testEventLoop.$(OBJEXT) tests/testMain.$(OBJEXT) \ tests/stub_main_cc.$(OBJEXT) \ tests/stub_ipc_Forwarder.$(OBJEXT) time.$(OBJEXT) \ - tools.$(OBJEXT) tunnel.$(OBJEXT) url.$(OBJEXT) \ - URLScheme.$(OBJEXT) urn.$(OBJEXT) wccp2.$(OBJEXT) \ - whois.$(OBJEXT) $(am__objects_17) wordlist.$(OBJEXT) -nodist_tests_testEventLoop_OBJECTS = $(am__objects_22) + tools.$(OBJEXT) tunnel.$(OBJEXT) MemStore.$(OBJEXT) \ + $(am__objects_16) url.$(OBJEXT) URLScheme.$(OBJEXT) \ + urn.$(OBJEXT) wccp2.$(OBJEXT) whois.$(OBJEXT) \ + $(am__objects_17) wordlist.$(OBJEXT) +nodist_tests_testEventLoop_OBJECTS = $(am__objects_22) \ + $(am__objects_21) tests_testEventLoop_OBJECTS = $(am_tests_testEventLoop_OBJECTS) \ $(nodist_tests_testEventLoop_OBJECTS) tests_testEventLoop_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(tests_testEventLoop_LDFLAGS) $(LDFLAGS) -o $@ am_tests_testHttpParser_OBJECTS = HttpParser.$(OBJEXT) \ - MemBuf.$(OBJEXT) mem.$(OBJEXT) \ + MemBuf.$(OBJEXT) mem.$(OBJEXT) String.$(OBJEXT) \ + tests/stub_cache_cf.$(OBJEXT) \ tests/stub_cache_manager.$(OBJEXT) tests/stub_debug.$(OBJEXT) \ tests/stub_event.$(OBJEXT) \ tests/stub_HelperChildConfig.$(OBJEXT) \ tests/testHttpParser.$(OBJEXT) tests/testMain.$(OBJEXT) \ - time.$(OBJEXT) + time.$(OBJEXT) wordlist.$(OBJEXT) nodist_tests_testHttpParser_OBJECTS = $(am__objects_23) tests_testHttpParser_OBJECTS = $(am_tests_testHttpParser_OBJECTS) \ $(nodist_tests_testHttpParser_OBJECTS) @@ -893,11 +935,12 @@ HttpMsg.$(OBJEXT) HttpReply.$(OBJEXT) HttpStatusLine.$(OBJEXT) \ mem.$(OBJEXT) MemBuf.$(OBJEXT) mime_header.$(OBJEXT) \ Packer.$(OBJEXT) String.$(OBJEXT) \ + tests/stub_cache_cf.$(OBJEXT) \ tests/stub_cache_manager.$(OBJEXT) tests/stub_debug.$(OBJEXT) \ tests/stub_HelperChildConfig.$(OBJEXT) \ tests/stub_StatHist.$(OBJEXT) tests/stub_store.$(OBJEXT) \ tests/testHttpReply.$(OBJEXT) tests/testMain.$(OBJEXT) \ - time.$(OBJEXT) + time.$(OBJEXT) wordlist.$(OBJEXT) nodist_tests_testHttpReply_OBJECTS = $(am__objects_23) tests_testHttpReply_OBJECTS = $(am_tests_testHttpReply_OBJECTS) \ $(nodist_tests_testHttpReply_OBJECTS) @@ -909,32 +952,33 @@ mem.cc String.cc tests/testHttpRequest.h \ tests/testHttpRequest.cc tests/testHttpRequestMethod.h \ tests/testHttpRequestMethod.cc tests/testMain.cc \ - tests/stub_main_cc.cc tests/stub_ipc_Forwarder.cc time.cc \ - BodyPipe.cc cache_manager.cc cache_cf.cc debug.cc ProtoPort.cc \ - ProtoPort.h CacheDigest.cc carp.cc cbdata.cc \ - ChunkedCodingParser.cc client_db.cc client_side.cc \ - client_side_reply.cc client_side_request.cc ClientInfo.h \ - clientStream.cc ConfigOption.cc ConfigParser.cc \ - CpuAffinityMap.cc CpuAffinityMap.h CpuAffinitySet.cc \ - CpuAffinitySet.h CommonPool.h CompositePoolNode.h \ - delay_pools.cc DelayId.cc DelayId.h DelayIdComposite.h \ - DelayBucket.cc DelayBucket.h DelayConfig.cc DelayConfig.h \ - DelayPool.cc DelayPool.h DelayPools.h DelaySpec.cc DelaySpec.h \ - DelayTagged.cc DelayTagged.h DelayUser.cc DelayUser.h \ - DelayVector.cc DelayVector.h NullDelayId.cc NullDelayId.h \ + tests/stub_DiskIOModule.cc tests/stub_main_cc.cc \ + tests/stub_ipc_Forwarder.cc time.cc BodyPipe.cc \ + cache_manager.cc cache_cf.cc debug.cc ProtoPort.cc ProtoPort.h \ + CacheDigest.cc carp.cc cbdata.cc ChunkedCodingParser.cc \ + client_db.cc client_side.cc client_side_reply.cc \ + client_side_request.cc ClientInfo.h clientStream.cc \ + ConfigOption.cc ConfigParser.cc CpuAffinityMap.cc \ + CpuAffinityMap.h CpuAffinitySet.cc CpuAffinitySet.h \ + CommonPool.h CompositePoolNode.h delay_pools.cc DelayId.cc \ + DelayId.h DelayIdComposite.h DelayBucket.cc DelayBucket.h \ + DelayConfig.cc DelayConfig.h DelayPool.cc DelayPool.h \ + DelayPools.h DelaySpec.cc DelaySpec.h DelayTagged.cc \ + DelayTagged.h DelayUser.cc DelayUser.h DelayVector.cc \ + DelayVector.h NullDelayId.cc NullDelayId.h \ ClientDelayConfig.cc ClientDelayConfig.h disk.cc dlink.h \ dlink.cc dns_internal.cc DnsLookupDetails.h \ DnsLookupDetails.cc dns.cc errorpage.cc ETag.cc \ external_acl.cc ExternalACLEntry.cc fd.cc fde.cc forward.cc \ fqdncache.cc ftp.cc gopher.cc helper.cc HelperChildConfig.h \ HelperChildConfig.cc hier_code.h htcp.cc htcp.h http.cc \ - HttpBody.cc HttpHeader.cc HttpHeaderTools.cc HttpHdrCc.cc \ - HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \ - HttpHdrScTarget.cc HttpMsg.cc HttpReply.cc HttpStatusLine.cc \ - icp_v2.cc icp_v3.cc ipc.cc ipc_win32.cc ipcache.cc int.cc \ - internal.cc list.cc multicast.cc mem_node.cc MemBuf.cc \ - MemObject.cc mime.cc mime_header.cc neighbors.cc Packer.cc \ - Parsing.cc pconn.cc peer_digest.cc \ + HttpBody.cc HttpHeader.cc HttpHeaderTools.cc HttpHdrCc.h \ + HttpHdrCc.cc HttpHdrCc.cci HttpHdrContRange.cc HttpHdrRange.cc \ + HttpHdrSc.cc HttpHdrScTarget.cc HttpMsg.cc HttpReply.cc \ + HttpStatusLine.cc icp_v2.cc icp_v3.cc ipc.cc ipc_win32.cc \ + ipcache.cc int.cc internal.cc list.cc multicast.cc mem_node.cc \ + MemBuf.cc MemObject.cc mime.cc mime_header.cc neighbors.cc \ + Packer.cc Parsing.cc pconn.cc peer_digest.cc \ peer_proxy_negotiate_auth.cc peer_select.cc peer_sourcehash.cc \ peer_userhash.cc redirect.cc refresh.cc RemovalPolicy.cc \ Server.cc snmp_core.h snmp_core.cc snmp_agent.cc SquidMath.h \ @@ -945,14 +989,14 @@ StoreIOState.cc StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ StoreMetaSTDLFS.cc StoreMetaUnpacker.cc StoreMetaURL.cc \ StoreMetaVary.cc StoreSwapLogData.cc event.cc tools.cc \ - tunnel.cc SwapDir.cc url.cc URLScheme.cc urn.cc wccp2.cc \ - whois.cc FadingCounter.cc win32.cc wordlist.cc + tunnel.cc SwapDir.cc MemStore.cc url.cc URLScheme.cc urn.cc \ + wccp2.cc whois.cc FadingCounter.cc win32.cc wordlist.cc am_tests_testHttpRequest_OBJECTS = $(am__objects_4) \ HttpParser.$(OBJEXT) HttpRequest.$(OBJEXT) \ HttpRequestMethod.$(OBJEXT) mem.$(OBJEXT) String.$(OBJEXT) \ tests/testHttpRequest.$(OBJEXT) \ tests/testHttpRequestMethod.$(OBJEXT) tests/testMain.$(OBJEXT) \ - tests/stub_main_cc.$(OBJEXT) \ + tests/stub_DiskIOModule.$(OBJEXT) tests/stub_main_cc.$(OBJEXT) \ tests/stub_ipc_Forwarder.$(OBJEXT) time.$(OBJEXT) \ BodyPipe.$(OBJEXT) cache_manager.$(OBJEXT) cache_cf.$(OBJEXT) \ debug.$(OBJEXT) ProtoPort.$(OBJEXT) CacheDigest.$(OBJEXT) \ @@ -994,10 +1038,10 @@ StoreMetaSTDLFS.$(OBJEXT) StoreMetaUnpacker.$(OBJEXT) \ StoreMetaURL.$(OBJEXT) StoreMetaVary.$(OBJEXT) \ StoreSwapLogData.$(OBJEXT) event.$(OBJEXT) tools.$(OBJEXT) \ - tunnel.$(OBJEXT) SwapDir.$(OBJEXT) url.$(OBJEXT) \ - URLScheme.$(OBJEXT) urn.$(OBJEXT) wccp2.$(OBJEXT) \ - whois.$(OBJEXT) FadingCounter.$(OBJEXT) $(am__objects_17) \ - wordlist.$(OBJEXT) + tunnel.$(OBJEXT) SwapDir.$(OBJEXT) MemStore.$(OBJEXT) \ + url.$(OBJEXT) URLScheme.$(OBJEXT) urn.$(OBJEXT) \ + wccp2.$(OBJEXT) whois.$(OBJEXT) FadingCounter.$(OBJEXT) \ + $(am__objects_17) wordlist.$(OBJEXT) nodist_tests_testHttpRequest_OBJECTS = $(am__objects_22) tests_testHttpRequest_OBJECTS = $(am_tests_testHttpRequest_OBJECTS) \ $(nodist_tests_testHttpRequest_OBJECTS) @@ -1028,15 +1072,15 @@ tests/stub_client_side_request.cc tests/stub_http.cc \ mem_node.cc stmem.cc tests/stub_mime.cc HttpHeaderTools.cc \ HttpHeader.cc mem.cc ClientInfo.h MemBuf.cc \ - HttpHdrContRange.cc Packer.cc HttpHdrCc.cc HttpHdrSc.cc \ - HttpHdrScTarget.cc url.cc StatHist.cc HttpHdrRange.cc ETag.cc \ - tests/stub_errorpage.cc tests/stub_HttpRequest.cc \ - tests/stub_access_log.cc refresh.cc tests/stub_store_client.cc \ - tests/stub_tools.cc tests/testStoreSupport.cc \ - tests/testStoreSupport.h time.cc URLScheme.cc wordlist.cc \ - DiskIO/DiskIOModule.cc DiskIO/ReadRequest.cc \ - DiskIO/ReadRequest.h DiskIO/WriteRequest.cc \ - DiskIO/WriteRequest.h DiskIO/DiskFile.h \ + HttpHdrContRange.cc Packer.cc HttpHdrCc.h HttpHdrCc.cc \ + HttpHdrCc.cci HttpHdrSc.cc HttpHdrScTarget.cc url.cc \ + StatHist.cc HttpHdrRange.cc ETag.cc tests/stub_errorpage.cc \ + tests/stub_HttpRequest.cc tests/stub_access_log.cc refresh.cc \ + tests/stub_store_client.cc tests/stub_tools.cc \ + tests/testStoreSupport.cc tests/testStoreSupport.h time.cc \ + URLScheme.cc wordlist.cc DiskIO/DiskIOModule.cc \ + DiskIO/ReadRequest.cc DiskIO/ReadRequest.h \ + DiskIO/WriteRequest.cc DiskIO/WriteRequest.h DiskIO/DiskFile.h \ DiskIO/DiskIOStrategy.h DiskIO/IORequestor.h \ DiskIO/DiskIOModule.h am_tests_testNull_OBJECTS = tests/testNull.$(OBJEXT) \ @@ -1091,34 +1135,35 @@ NullDelayId.cc NullDelayId.h ClientDelayConfig.cc \ ClientDelayConfig.h disk.cc DiskIO/ReadRequest.cc \ DiskIO/WriteRequest.cc ETag.cc event.cc EventLoop.cc \ - filemap.cc HttpHdrCc.cc HttpHdrContRange.cc HttpHdrRange.cc \ - HttpHdrSc.cc HttpHdrScTarget.cc HttpHeaderTools.cc \ - HttpHeader.cc HttpMsg.cc HttpRequestMethod.cc int.cc list.cc \ - mem.cc mem_node.cc MemBuf.cc Packer.cc Parsing.cc \ - RemovalPolicy.cc refresh.cc StatHist.cc stmem.cc store.cc \ - store_dir.cc store_io.cc store_swapout.cc StoreIOState.cc \ - StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ - StoreMetaSTDLFS.cc StoreMetaUnpacker.cc StoreMetaURL.cc \ - StoreMetaVary.cc StoreSwapLogData.cc store_key_md5.cc \ - String.cc SwapDir.cc tests/CapturingStoreEntry.h \ - tests/stub_access_log.cc tests/stub_acl.cc \ - tests/stub_cache_cf.cc tests/stub_cache_manager.cc \ - tests/stub_client_side_request.cc tests/stub_comm.cc \ - tests/stub_debug.cc tests/stub_DiskIOModule.cc \ - tests/stub_errorpage.cc tests/stub_fd.cc tests/stub_helper.cc \ + filemap.cc HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci \ + HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \ + HttpHdrScTarget.cc HttpHeaderTools.cc HttpHeader.cc HttpMsg.cc \ + HttpRequestMethod.cc int.cc list.cc mem.cc mem_node.cc \ + MemBuf.cc Packer.cc Parsing.cc RemovalPolicy.cc refresh.cc \ + StatHist.cc stmem.cc store.cc store_dir.cc store_io.cc \ + store_swapout.cc StoreIOState.cc StoreMeta.cc StoreMetaMD5.cc \ + StoreMetaSTD.cc StoreMetaSTDLFS.cc StoreMetaUnpacker.cc \ + StoreMetaURL.cc StoreMetaVary.cc StoreSwapLogData.cc \ + store_key_md5.cc String.cc SwapDir.cc \ + tests/CapturingStoreEntry.h tests/stub_access_log.cc \ + tests/stub_acl.cc tests/stub_cache_cf.cc \ + tests/stub_cache_manager.cc tests/stub_client_side_request.cc \ + tests/stub_comm.cc tests/stub_debug.cc \ + tests/stub_DiskIOModule.cc tests/stub_errorpage.cc \ + tests/stub_fd.cc tests/stub_helper.cc \ tests/stub_HelperChildConfig.cc tests/stub_http.cc \ tests/stub_HttpReply.cc tests/stub_HttpRequest.cc \ - tests/stub_MemObject.cc tests/stub_mime.cc tests/stub_Port.cc \ + tests/stub_libcomm.cc tests/stub_MemObject.cc \ + tests/stub_MemStore.cc tests/stub_mime.cc tests/stub_Port.cc \ tests/stub_store_client.cc tests/stub_store_rebuild.cc \ tests/stub_store_swapout.cc tests/stub_tools.cc \ - tests/stub_TypedMsgHdr.cc tests/stub_UdsOp.cc \ - tests/testMain.cc tests/testStore.cc tests/testStore.h \ - tests/testStoreEntryStream.cc tests/testStoreEntryStream.h \ - tests/testStoreController.cc tests/testStoreController.h \ - tests/testStoreHashIndex.cc tests/testStoreHashIndex.h \ - tests/testStoreSupport.cc tests/testStoreSupport.h \ - tests/TestSwapDir.cc tests/TestSwapDir.h time.cc url.cc \ - URLScheme.cc wordlist.cc + tests/stub_UdsOp.cc tests/testMain.cc tests/testStore.cc \ + tests/testStore.h tests/testStoreEntryStream.cc \ + tests/testStoreEntryStream.h tests/testStoreController.cc \ + tests/testStoreController.h tests/testStoreHashIndex.cc \ + tests/testStoreHashIndex.h tests/testStoreSupport.cc \ + tests/testStoreSupport.h tests/TestSwapDir.cc \ + tests/TestSwapDir.h time.cc url.cc URLScheme.cc wordlist.cc am_tests_testStore_OBJECTS = CacheDigest.$(OBJEXT) cbdata.$(OBJEXT) \ ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) $(am__objects_6) \ disk.$(OBJEXT) DiskIO/ReadRequest.$(OBJEXT) \ @@ -1149,14 +1194,14 @@ tests/stub_helper.$(OBJEXT) \ tests/stub_HelperChildConfig.$(OBJEXT) \ tests/stub_http.$(OBJEXT) tests/stub_HttpReply.$(OBJEXT) \ - tests/stub_HttpRequest.$(OBJEXT) \ - tests/stub_MemObject.$(OBJEXT) tests/stub_mime.$(OBJEXT) \ - tests/stub_Port.$(OBJEXT) tests/stub_store_client.$(OBJEXT) \ + tests/stub_HttpRequest.$(OBJEXT) tests/stub_libcomm.$(OBJEXT) \ + tests/stub_MemObject.$(OBJEXT) tests/stub_MemStore.$(OBJEXT) \ + tests/stub_mime.$(OBJEXT) tests/stub_Port.$(OBJEXT) \ + tests/stub_store_client.$(OBJEXT) \ tests/stub_store_rebuild.$(OBJEXT) \ tests/stub_store_swapout.$(OBJEXT) tests/stub_tools.$(OBJEXT) \ - tests/stub_TypedMsgHdr.$(OBJEXT) tests/stub_UdsOp.$(OBJEXT) \ - tests/testMain.$(OBJEXT) tests/testStore.$(OBJEXT) \ - tests/testStoreEntryStream.$(OBJEXT) \ + tests/stub_UdsOp.$(OBJEXT) tests/testMain.$(OBJEXT) \ + tests/testStore.$(OBJEXT) tests/testStoreEntryStream.$(OBJEXT) \ tests/testStoreController.$(OBJEXT) \ tests/testStoreHashIndex.$(OBJEXT) \ tests/testStoreSupport.$(OBJEXT) tests/TestSwapDir.$(OBJEXT) \ @@ -1169,10 +1214,12 @@ tests_testStore_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(tests_testStore_LDFLAGS) $(LDFLAGS) -o $@ -am_tests_testString_OBJECTS = mem.$(OBJEXT) String.$(OBJEXT) \ - tests/testMain.$(OBJEXT) tests/testString.$(OBJEXT) \ +am_tests_testString_OBJECTS = mem.$(OBJEXT) MemBuf.$(OBJEXT) \ + String.$(OBJEXT) tests/testMain.$(OBJEXT) \ + tests/testString.$(OBJEXT) tests/stub_cache_cf.$(OBJEXT) \ tests/stub_cache_manager.$(OBJEXT) tests/stub_debug.$(OBJEXT) \ - tests/stub_HelperChildConfig.$(OBJEXT) time.$(OBJEXT) + tests/stub_HelperChildConfig.$(OBJEXT) time.$(OBJEXT) \ + wordlist.$(OBJEXT) nodist_tests_testString_OBJECTS = $(am__objects_23) tests_testString_OBJECTS = $(am_tests_testString_OBJECTS) \ $(nodist_tests_testString_OBJECTS) @@ -1198,30 +1245,31 @@ ExternalACLEntry.cc fd.cc fde.cc filemap.cc forward.cc \ fqdncache.cc ftp.cc gopher.cc helper.cc HelperChildConfig.h \ HelperChildConfig.cc hier_code.h htcp.cc htcp.h http.cc \ - HttpBody.cc HttpHdrCc.cc HttpHdrContRange.cc HttpHdrRange.cc \ - HttpHdrSc.cc HttpHdrScTarget.cc HttpHeader.cc \ - HttpHeaderTools.cc HttpMsg.cc HttpParser.cc HttpParser.h \ - HttpReply.cc HttpRequest.cc HttpRequestMethod.cc \ - HttpStatusLine.cc icp_v2.cc icp_v3.cc ipc.cc ipc_win32.cc \ - ipcache.cc int.cc internal.cc list.cc multicast.cc mem.cc \ - mem_node.cc MemBuf.cc MemObject.cc mime.cc mime_header.cc \ - neighbors.cc Packer.cc Parsing.cc pconn.cc peer_digest.cc \ - peer_proxy_negotiate_auth.cc peer_select.cc peer_sourcehash.cc \ - peer_userhash.cc ProtoPort.cc ProtoPort.h redirect.cc \ - refresh.cc RemovalPolicy.cc Server.cc snmp_core.h snmp_core.cc \ - snmp_agent.cc SquidMath.h SquidMath.cc stat.cc StatHist.cc \ - stmem.cc store.cc store_client.cc store_digest.cc store_dir.cc \ - store_io.cc store_key_md5.cc store_log.cc store_rebuild.cc \ - store_swapin.cc store_swapmeta.cc store_swapout.cc \ - StoreFileSystem.cc StoreIOState.cc StoreMeta.cc \ - StoreMetaMD5.cc StoreMetaSTD.cc StoreMetaSTDLFS.cc \ - StoreMetaUnpacker.cc StoreMetaURL.cc StoreMetaVary.cc \ - StoreSwapLogData.cc String.cc SwapDir.cc tests/stub_debug.cc \ - tests/stub_DiskIOModule.cc tests/stub_main_cc.cc \ - tests/stub_ipc_Forwarder.cc tests/testURL.cc tests/testURL.h \ - tests/testURLScheme.cc tests/testURLScheme.h tests/testMain.cc \ - time.cc tools.cc tunnel.cc url.cc URLScheme.cc urn.cc wccp2.cc \ - whois.cc FadingCounter.cc win32.cc wordlist.cc + HttpBody.cc HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci \ + HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \ + HttpHdrScTarget.cc HttpHeader.cc HttpHeaderTools.cc HttpMsg.cc \ + HttpParser.cc HttpParser.h HttpReply.cc HttpRequest.cc \ + HttpRequestMethod.cc HttpStatusLine.cc icp_v2.cc icp_v3.cc \ + ipc.cc ipc_win32.cc ipcache.cc int.cc internal.cc list.cc \ + multicast.cc mem.cc mem_node.cc MemBuf.cc MemObject.cc mime.cc \ + mime_header.cc neighbors.cc Packer.cc Parsing.cc pconn.cc \ + peer_digest.cc peer_proxy_negotiate_auth.cc peer_select.cc \ + peer_sourcehash.cc peer_userhash.cc ProtoPort.cc ProtoPort.h \ + redirect.cc refresh.cc RemovalPolicy.cc Server.cc snmp_core.h \ + snmp_core.cc snmp_agent.cc SquidMath.h SquidMath.cc stat.cc \ + StatHist.cc stmem.cc store.cc store_client.cc store_digest.cc \ + store_dir.cc store_io.cc store_key_md5.cc store_log.cc \ + store_rebuild.cc store_swapin.cc store_swapmeta.cc \ + store_swapout.cc StoreFileSystem.cc StoreIOState.cc \ + StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ + StoreMetaSTDLFS.cc StoreMetaUnpacker.cc StoreMetaURL.cc \ + StoreMetaVary.cc StoreSwapLogData.cc String.cc SwapDir.cc \ + MemStore.cc tests/stub_debug.cc tests/stub_DiskIOModule.cc \ + tests/stub_main_cc.cc tests/stub_ipc_Forwarder.cc \ + tests/testURL.cc tests/testURL.h tests/testURLScheme.cc \ + tests/testURLScheme.h tests/testMain.cc time.cc tools.cc \ + tunnel.cc url.cc URLScheme.cc urn.cc wccp2.cc whois.cc \ + FadingCounter.cc win32.cc wordlist.cc am_tests_testURL_OBJECTS = $(am__objects_4) BodyPipe.$(OBJEXT) \ cache_cf.$(OBJEXT) cache_manager.$(OBJEXT) \ CacheDigest.$(OBJEXT) carp.$(OBJEXT) cbdata.$(OBJEXT) \ @@ -1265,8 +1313,9 @@ StoreMetaSTD.$(OBJEXT) StoreMetaSTDLFS.$(OBJEXT) \ StoreMetaUnpacker.$(OBJEXT) StoreMetaURL.$(OBJEXT) \ StoreMetaVary.$(OBJEXT) StoreSwapLogData.$(OBJEXT) \ - String.$(OBJEXT) SwapDir.$(OBJEXT) tests/stub_debug.$(OBJEXT) \ - tests/stub_DiskIOModule.$(OBJEXT) tests/stub_main_cc.$(OBJEXT) \ + String.$(OBJEXT) SwapDir.$(OBJEXT) MemStore.$(OBJEXT) \ + tests/stub_debug.$(OBJEXT) tests/stub_DiskIOModule.$(OBJEXT) \ + tests/stub_main_cc.$(OBJEXT) \ tests/stub_ipc_Forwarder.$(OBJEXT) tests/testURL.$(OBJEXT) \ tests/testURLScheme.$(OBJEXT) tests/testMain.$(OBJEXT) \ time.$(OBJEXT) tools.$(OBJEXT) tunnel.$(OBJEXT) url.$(OBJEXT) \ @@ -1282,40 +1331,39 @@ am__tests_testUfs_SOURCES_DIST = tests/testUfs.cc tests/testMain.cc \ tests/testUfs.h tests/stub_cache_manager.cc \ tests/stub_client_db.cc tests/stub_HelperChildConfig.cc \ - tests/stub_icp.cc tests/stub_ipc.cc tests/stub_pconn.cc \ - tests/stub_Port.cc tests/stub_TypedMsgHdr.cc \ - tests/stub_UdsOp.cc tests/stub_internal.cc \ - tests/stub_store_rebuild.cc fd.cc disk.cc filemap.cc \ - HttpBody.cc HttpReply.cc HttpStatusLine.cc int.cc list.cc \ - MemObject.cc StoreSwapLogData.cc StoreIOState.cc StoreMeta.cc \ - StoreMetaMD5.cc StoreMetaSTD.cc StoreMetaSTDLFS.cc \ - StoreMetaUnpacker.cc StoreMetaURL.cc StoreMetaVary.cc \ - StoreFileSystem.cc store_io.cc store_swapout.cc \ - store_swapmeta.cc unlinkd.cc win32.cc event.cc CommonPool.h \ - CompositePoolNode.h delay_pools.cc DelayId.cc DelayId.h \ - DelayIdComposite.h DelayBucket.cc DelayBucket.h DelayConfig.cc \ - DelayConfig.h DelayPool.cc DelayPool.h DelayPools.h \ - DelaySpec.cc DelaySpec.h DelayTagged.cc DelayTagged.h \ - DelayUser.cc DelayUser.h DelayVector.cc DelayVector.h \ - NullDelayId.cc NullDelayId.h ClientDelayConfig.cc \ - ClientDelayConfig.h CacheDigest.cc ConfigParser.cc \ - EventLoop.cc HttpMsg.cc RemovalPolicy.cc store_dir.cc store.cc \ - HttpRequestMethod.cc store_key_md5.cc Parsing.cc \ - ConfigOption.cc SwapDir.cc tests/stub_acl.cc \ + tests/stub_icp.cc tests/stub_ipc.cc tests/stub_MemStore.cc \ + tests/stub_pconn.cc tests/stub_Port.cc tests/stub_UdsOp.cc \ + tests/stub_internal.cc tests/stub_store_rebuild.cc fd.cc \ + disk.cc filemap.cc HttpBody.cc HttpReply.cc HttpStatusLine.cc \ + int.cc list.cc MemObject.cc StoreSwapLogData.cc \ + StoreIOState.cc StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ + StoreMetaSTDLFS.cc StoreMetaUnpacker.cc StoreMetaURL.cc \ + StoreMetaVary.cc StoreFileSystem.cc store_io.cc \ + store_swapout.cc store_swapmeta.cc unlinkd.cc win32.cc \ + event.cc CommonPool.h CompositePoolNode.h delay_pools.cc \ + DelayId.cc DelayId.h DelayIdComposite.h DelayBucket.cc \ + DelayBucket.h DelayConfig.cc DelayConfig.h DelayPool.cc \ + DelayPool.h DelayPools.h DelaySpec.cc DelaySpec.h \ + DelayTagged.cc DelayTagged.h DelayUser.cc DelayUser.h \ + DelayVector.cc DelayVector.h NullDelayId.cc NullDelayId.h \ + ClientDelayConfig.cc ClientDelayConfig.h CacheDigest.cc \ + ConfigParser.cc EventLoop.cc HttpMsg.cc RemovalPolicy.cc \ + store_dir.cc store.cc HttpRequestMethod.cc store_key_md5.cc \ + Parsing.cc ConfigOption.cc SwapDir.cc tests/stub_acl.cc \ tests/stub_cache_cf.cc tests/stub_helper.cc cbdata.cc \ String.cc tests/stub_debug.cc \ tests/stub_client_side_request.cc tests/stub_http.cc \ mem_node.cc stmem.cc tests/stub_mime.cc HttpHeaderTools.cc \ HttpHeader.cc mem.cc ClientInfo.h MemBuf.cc \ - HttpHdrContRange.cc Packer.cc HttpHdrCc.cc HttpHdrSc.cc \ - HttpHdrScTarget.cc url.cc StatHist.cc HttpHdrRange.cc ETag.cc \ - tests/stub_errorpage.cc tests/stub_HttpRequest.cc \ - tests/stub_access_log.cc refresh.cc tests/stub_store_client.cc \ - tests/stub_tools.cc tests/testStoreSupport.cc \ - tests/testStoreSupport.h time.cc URLScheme.cc wordlist.cc \ - DiskIO/DiskIOModule.cc DiskIO/ReadRequest.cc \ - DiskIO/ReadRequest.h DiskIO/WriteRequest.cc \ - DiskIO/WriteRequest.h DiskIO/DiskFile.h \ + HttpHdrContRange.cc Packer.cc HttpHdrCc.h HttpHdrCc.cc \ + HttpHdrCc.cci HttpHdrSc.cc HttpHdrScTarget.cc url.cc \ + StatHist.cc HttpHdrRange.cc ETag.cc tests/stub_errorpage.cc \ + tests/stub_HttpRequest.cc tests/stub_access_log.cc refresh.cc \ + tests/stub_store_client.cc tests/stub_tools.cc \ + tests/testStoreSupport.cc tests/testStoreSupport.h time.cc \ + URLScheme.cc wordlist.cc DiskIO/DiskIOModule.cc \ + DiskIO/ReadRequest.cc DiskIO/ReadRequest.h \ + DiskIO/WriteRequest.cc DiskIO/WriteRequest.h DiskIO/DiskFile.h \ DiskIO/DiskIOStrategy.h DiskIO/IORequestor.h \ DiskIO/DiskIOModule.h am_tests_testUfs_OBJECTS = tests/testUfs.$(OBJEXT) \ @@ -1323,8 +1371,8 @@ tests/stub_client_db.$(OBJEXT) \ tests/stub_HelperChildConfig.$(OBJEXT) \ tests/stub_icp.$(OBJEXT) tests/stub_ipc.$(OBJEXT) \ - tests/stub_pconn.$(OBJEXT) tests/stub_Port.$(OBJEXT) \ - tests/stub_TypedMsgHdr.$(OBJEXT) tests/stub_UdsOp.$(OBJEXT) \ + tests/stub_MemStore.$(OBJEXT) tests/stub_pconn.$(OBJEXT) \ + tests/stub_Port.$(OBJEXT) tests/stub_UdsOp.$(OBJEXT) \ tests/stub_internal.$(OBJEXT) \ tests/stub_store_rebuild.$(OBJEXT) fd.$(OBJEXT) disk.$(OBJEXT) \ filemap.$(OBJEXT) HttpBody.$(OBJEXT) HttpReply.$(OBJEXT) \ @@ -1379,23 +1427,28 @@ DelayPool.cc DelayPool.h DelayPools.h DelaySpec.cc DelaySpec.h \ DelayTagged.cc DelayTagged.h DelayUser.cc DelayUser.h \ DelayVector.cc DelayVector.h NullDelayId.cc NullDelayId.h \ - ClientDelayConfig.cc ClientDelayConfig.h disk.cc dlink.h \ - dlink.cc dns_internal.cc DnsLookupDetails.h \ - DnsLookupDetails.cc dns.cc errorpage.cc ETag.cc event.cc \ - external_acl.cc ExternalACLEntry.cc FadingCounter.cc fd.cc \ - fde.cc forward.cc fqdncache.cc ftp.cc gopher.cc helper.cc \ - HelperChildConfig.h HelperChildConfig.cc hier_code.h htcp.cc \ - htcp.h http.cc HttpBody.cc HttpHdrCc.cc HttpHdrContRange.cc \ - HttpHdrRange.cc HttpHdrSc.cc HttpHdrScTarget.cc HttpHeader.cc \ - HttpHeaderTools.cc HttpMsg.cc HttpParser.cc HttpParser.h \ - HttpReply.cc HttpRequest.cc HttpRequestMethod.cc \ - HttpStatusLine.cc icp_v2.cc icp_v3.cc int.cc internal.cc \ - ipc.cc ipc_win32.cc ipcache.cc list.cc MemBuf.cc MemObject.cc \ - mem.cc mem_node.cc mime.cc mime_header.cc multicast.cc \ - neighbors.cc Packer.cc Parsing.cc peer_digest.cc \ - peer_proxy_negotiate_auth.cc peer_select.cc peer_sourcehash.cc \ - peer_userhash.cc pconn.cc redirect.cc refresh.cc \ - RemovalPolicy.cc Server.cc snmp_core.h snmp_core.cc \ + ClientDelayConfig.cc ClientDelayConfig.h \ + DiskIO/DiskIOModule.cc DiskIO/ReadRequest.cc \ + DiskIO/ReadRequest.h DiskIO/WriteRequest.cc \ + DiskIO/WriteRequest.h DiskIO/DiskFile.h \ + DiskIO/DiskIOStrategy.h DiskIO/IORequestor.h \ + DiskIO/DiskIOModule.h disk.cc dlink.h dlink.cc dns_internal.cc \ + DnsLookupDetails.h DnsLookupDetails.cc dns.cc errorpage.cc \ + ETag.cc event.cc external_acl.cc ExternalACLEntry.cc \ + FadingCounter.cc fd.cc fde.cc filemap.cc forward.cc \ + fqdncache.cc ftp.cc gopher.cc helper.cc HelperChildConfig.h \ + HelperChildConfig.cc hier_code.h htcp.cc htcp.h http.cc \ + HttpBody.cc HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci \ + HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \ + HttpHdrScTarget.cc HttpHeader.cc HttpHeaderTools.cc HttpMsg.cc \ + HttpParser.cc HttpParser.h HttpReply.cc HttpRequest.cc \ + HttpRequestMethod.cc HttpStatusLine.cc icp_v2.cc icp_v3.cc \ + int.cc internal.cc ipc.cc ipc_win32.cc ipcache.cc list.cc \ + MemBuf.cc MemObject.cc mem.cc mem_node.cc mime.cc \ + mime_header.cc multicast.cc neighbors.cc Packer.cc Parsing.cc \ + peer_digest.cc peer_proxy_negotiate_auth.cc peer_select.cc \ + peer_sourcehash.cc peer_userhash.cc pconn.cc redirect.cc \ + refresh.cc RemovalPolicy.cc Server.cc snmp_core.h snmp_core.cc \ snmp_agent.cc SquidMath.h SquidMath.cc stat.cc StatHist.cc \ stmem.cc store.cc store_client.cc store_digest.cc store_dir.cc \ store_key_md5.cc store_io.cc store_log.cc store_rebuild.cc \ @@ -1405,8 +1458,9 @@ StoreMetaUnpacker.cc StoreMetaURL.cc StoreMetaVary.cc \ StoreSwapLogData.cc String.cc SwapDir.cc \ tests/test_http_range.cc tests/stub_ipc_Forwarder.cc \ - tests/stub_main_cc.cc time.cc tools.cc tunnel.cc url.cc \ - URLScheme.cc urn.cc wccp2.cc whois.cc win32.cc wordlist.cc + tests/stub_main_cc.cc tests/stub_MemStore.cc time.cc tools.cc \ + tunnel.cc unlinkd.cc url.cc URLScheme.cc urn.cc wccp2.cc \ + whois.cc win32.cc wordlist.cc am_tests_test_http_range_OBJECTS = $(am__objects_4) BodyPipe.$(OBJEXT) \ cache_cf.$(OBJEXT) ProtoPort.$(OBJEXT) cache_manager.$(OBJEXT) \ CacheDigest.$(OBJEXT) carp.$(OBJEXT) cbdata.$(OBJEXT) \ @@ -1415,14 +1469,15 @@ client_side_request.$(OBJEXT) clientStream.$(OBJEXT) \ ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) \ CpuAffinityMap.$(OBJEXT) CpuAffinitySet.$(OBJEXT) \ - debug.$(OBJEXT) $(am__objects_6) disk.$(OBJEXT) \ - dlink.$(OBJEXT) $(am__objects_8) errorpage.$(OBJEXT) \ - ETag.$(OBJEXT) event.$(OBJEXT) external_acl.$(OBJEXT) \ - ExternalACLEntry.$(OBJEXT) FadingCounter.$(OBJEXT) \ - fd.$(OBJEXT) fde.$(OBJEXT) forward.$(OBJEXT) \ - fqdncache.$(OBJEXT) ftp.$(OBJEXT) gopher.$(OBJEXT) \ - helper.$(OBJEXT) HelperChildConfig.$(OBJEXT) $(am__objects_9) \ - http.$(OBJEXT) HttpBody.$(OBJEXT) HttpHdrCc.$(OBJEXT) \ + debug.$(OBJEXT) $(am__objects_6) $(am__objects_7) \ + disk.$(OBJEXT) dlink.$(OBJEXT) $(am__objects_8) \ + errorpage.$(OBJEXT) ETag.$(OBJEXT) event.$(OBJEXT) \ + external_acl.$(OBJEXT) ExternalACLEntry.$(OBJEXT) \ + FadingCounter.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) \ + filemap.$(OBJEXT) forward.$(OBJEXT) fqdncache.$(OBJEXT) \ + ftp.$(OBJEXT) gopher.$(OBJEXT) helper.$(OBJEXT) \ + HelperChildConfig.$(OBJEXT) $(am__objects_9) http.$(OBJEXT) \ + HttpBody.$(OBJEXT) HttpHdrCc.$(OBJEXT) \ HttpHdrContRange.$(OBJEXT) HttpHdrRange.$(OBJEXT) \ HttpHdrSc.$(OBJEXT) HttpHdrScTarget.$(OBJEXT) \ HttpHeader.$(OBJEXT) HttpHeaderTools.$(OBJEXT) \ @@ -1452,11 +1507,13 @@ StoreSwapLogData.$(OBJEXT) String.$(OBJEXT) SwapDir.$(OBJEXT) \ tests/test_http_range.$(OBJEXT) \ tests/stub_ipc_Forwarder.$(OBJEXT) \ - tests/stub_main_cc.$(OBJEXT) time.$(OBJEXT) tools.$(OBJEXT) \ - tunnel.$(OBJEXT) url.$(OBJEXT) URLScheme.$(OBJEXT) \ + tests/stub_main_cc.$(OBJEXT) tests/stub_MemStore.$(OBJEXT) \ + time.$(OBJEXT) tools.$(OBJEXT) tunnel.$(OBJEXT) \ + $(am__objects_16) url.$(OBJEXT) URLScheme.$(OBJEXT) \ urn.$(OBJEXT) wccp2.$(OBJEXT) whois.$(OBJEXT) \ $(am__objects_17) wordlist.$(OBJEXT) -nodist_tests_test_http_range_OBJECTS = $(am__objects_22) +nodist_tests_test_http_range_OBJECTS = $(am__objects_22) \ + $(am__objects_21) tests_test_http_range_OBJECTS = $(am_tests_test_http_range_OBJECTS) \ $(nodist_tests_test_http_range_OBJECTS) tests_test_http_range_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ @@ -1510,6 +1567,7 @@ $(LDFLAGS) -o $@ SOURCES = $(libAIO_a_SOURCES) $(libBlocking_a_SOURCES) \ $(libDiskDaemon_a_SOURCES) $(libDiskThreads_a_SOURCES) \ + $(libIpcIo_a_SOURCES) $(libMmapped_a_SOURCES) \ $(libsquid_la_SOURCES) $(DiskIO_DiskDaemon_diskd_SOURCES) \ $(nodist_DiskIO_DiskDaemon_diskd_SOURCES) $(cf_gen_SOURCES) \ $(dnsserver_SOURCES) $(recv_announce_SOURCES) $(squid_SOURCES) \ @@ -1541,7 +1599,8 @@ $(nodist_ufsdump_SOURCES) $(unlinkd_SOURCES) DIST_SOURCES = $(am__libAIO_a_SOURCES_DIST) $(libBlocking_a_SOURCES) \ $(libDiskDaemon_a_SOURCES) \ - $(am__libDiskThreads_a_SOURCES_DIST) $(libsquid_la_SOURCES) \ + $(am__libDiskThreads_a_SOURCES_DIST) $(libIpcIo_a_SOURCES) \ + $(libMmapped_a_SOURCES) $(libsquid_la_SOURCES) \ $(DiskIO_DiskDaemon_diskd_SOURCES) $(cf_gen_SOURCES) \ $(dnsserver_SOURCES) $(recv_announce_SOURCES) \ $(am__squid_SOURCES_DIST) $(am__EXTRA_squid_SOURCES_DIST) \ @@ -1661,7 +1720,7 @@ DEFAULT_HOSTS = @DEFAULT_HOSTS@ DEFAULT_LOG_DIR = @DEFAULT_LOG_DIR@ DEFAULT_PID_FILE = @DEFAULT_PID_FILE@ -DEFAULT_SWAP_DIR = $(localstatedir)/cache +DEFAULT_SWAP_DIR = @DEFAULT_SWAP_DIR@ # Make location configure settings available to the code DEFS = @DEFS@ -DDEFAULT_CONFIG_FILE=\"$(DEFAULT_CONFIG_FILE)\" \ @@ -1958,7 +2017,9 @@ @USE_AIO_WIN32_TRUE@AIO_WIN32_SOURCES = $(AIO_WIN32_ALL_SOURCES) @USE_AIOPS_WIN32_FALSE@AIOPS_SOURCE = DiskIO/DiskThreads/aiops.cc @USE_AIOPS_WIN32_TRUE@AIOPS_SOURCE = DiskIO/DiskThreads/aiops_win32.cc -EXTRA_LIBRARIES = libAIO.a libBlocking.a libDiskDaemon.a libDiskThreads.a +EXTRA_LIBRARIES = libAIO.a libBlocking.a libDiskDaemon.a libDiskThreads.a \ + libMmapped.a libIpcIo.a + noinst_LIBRARIES = $(DISK_LIBS) noinst_LTLIBRARIES = libsquid.la cf_gen_SOURCES = cf_gen.cc @@ -2017,17 +2078,17 @@ HelperChildConfig.h HelperChildConfig.cc hier_code.h \ HierarchyLogEntry.h $(HTCPSOURCE) http.cc http.h \ HttpStatusCode.h HttpStatusLine.cc HttpStatusLine.h \ - HttpHdrCc.cc HttpHdrRange.cc HttpHdrSc.cc HttpHdrSc.h \ - HttpHdrScTarget.cc HttpHdrScTarget.h HttpHdrContRange.cc \ - HttpHdrContRange.h HttpHeader.cc HttpHeader.h HttpHeaderMask.h \ - HttpHeaderRange.h HttpHeaderTools.cc HttpBody.cc \ - HttpControlMsg.h HttpMsg.cc HttpMsg.h HttpParser.cc \ - HttpParser.h HttpReply.cc HttpReply.h HttpRequest.cc \ - HttpRequest.h HttpRequestMethod.cc HttpRequestMethod.h \ - HttpVersion.h ICP.h icp_opcode.h icp_v2.cc icp_v3.cc int.cc \ - internal.cc $(IPC_SOURCE) ipcache.cc ipcache.h \ - $(LEAKFINDERSOURCE) list.cc lookup_t.h main.cc mem.cc \ - mem_node.cc mem_node.h Mem.h MemBuf.cc MemObject.cc \ + HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci HttpHdrRange.cc \ + HttpHdrSc.cc HttpHdrSc.h HttpHdrScTarget.cc HttpHdrScTarget.h \ + HttpHdrContRange.cc HttpHdrContRange.h HttpHeader.cc \ + HttpHeader.h HttpHeaderMask.h HttpHeaderRange.h \ + HttpHeaderTools.cc HttpBody.cc HttpControlMsg.h HttpMsg.cc \ + HttpMsg.h HttpParser.cc HttpParser.h HttpReply.cc HttpReply.h \ + HttpRequest.cc HttpRequest.h HttpRequestMethod.cc \ + HttpRequestMethod.h HttpVersion.h ICP.h icp_opcode.h icp_v2.cc \ + icp_v3.cc int.cc internal.cc $(IPC_SOURCE) ipcache.cc \ + ipcache.h $(LEAKFINDERSOURCE) list.cc lookup_t.h main.cc \ + mem.cc mem_node.cc mem_node.h Mem.h MemBuf.cc MemObject.cc \ MemObject.h mime.cc mime_header.cc multicast.cc neighbors.cc \ Packer.cc Packer.h Parsing.cc Parsing.h $(XPROF_STATS_SOURCE) \ pconn.cc pconn.h PeerDigest.h peer_digest.cc \ @@ -2047,11 +2108,11 @@ StoreMetaUnpacker.cc StoreMetaUnpacker.h StoreMetaURL.cc \ StoreMetaURL.h StoreMetaVary.cc StoreMetaVary.h StoreSearch.h \ StoreSwapLogData.cc StoreSwapLogData.h Server.cc Server.h \ - structs.h swap_log_op.h SwapDir.cc SwapDir.h time.cc \ - TimeOrTag.h tools.cc tunnel.cc typedefs.h $(UNLINKDSOURCE) \ - url.cc URL.h URLScheme.cc URLScheme.h urn.cc wccp.cc wccp2.cc \ - whois.cc wordlist.cc wordlist.h $(WIN32_SOURCE) \ - $(WINSVC_SOURCE) $(am__append_8) + structs.h swap_log_op.h SwapDir.cc SwapDir.h MemStore.cc \ + MemStore.h time.cc TimeOrTag.h tools.cc tunnel.cc typedefs.h \ + $(UNLINKDSOURCE) url.cc URL.h URLScheme.cc URLScheme.h urn.cc \ + wccp.cc wccp2.cc whois.cc wordlist.cc wordlist.h \ + $(WIN32_SOURCE) $(WINSVC_SOURCE) $(am__append_8) EXTRA_squid_SOURCES = \ $(AIO_WIN32_ALL_SOURCES) \ $(all_AUTHMODULES) \ @@ -2103,12 +2164,12 @@ $(BUILT_SOURCES) squid_LDADD = $(AUTH_ACL_LIBS) ident/libident.la acl/libacls.la \ - eui/libeui.la acl/libstate.la $(AUTH_LIBS) acl/libapi.la \ - base/libbase.la libsquid.la ip/libip.la fs/libfs.la \ - ipc/libipc.la mgr/libmgr.la anyp/libanyp.la comm/libcomm.la \ - eui/libeui.la icmp/libicmp.la icmp/libicmp-core.la \ - log/liblog.la format/libformat.la $(XTRA_OBJS) \ - $(DISK_LINKOBJS) $(REPL_OBJS) $(DISK_LIBS) $(DISK_OS_LIBS) \ + eui/libeui.la acl/libstate.la $(AUTH_LIBS) $(DISK_LIBS) \ + acl/libapi.la base/libbase.la libsquid.la ip/libip.la \ + fs/libfs.la ipc/libipc.la mgr/libmgr.la anyp/libanyp.la \ + comm/libcomm.la eui/libeui.la icmp/libicmp.la \ + icmp/libicmp-core.la log/liblog.la format/libformat.la \ + $(XTRA_OBJS) $(DISK_LINKOBJS) $(REPL_OBJS) $(DISK_OS_LIBS) \ $(CRYPTLIB) $(REGEXLIB) $(ADAPTATION_LIBS) $(ESI_LIBS) \ $(SSL_LIBS) $(SNMP_LIBS) \ $(top_builddir)/lib/libmisccontainers.la \ @@ -2275,6 +2336,22 @@ DiskIO/Blocking/BlockingDiskIOModule.cc \ DiskIO/Blocking/BlockingDiskIOModule.h +libMmapped_a_SOURCES = \ + DiskIO/Mmapped/MmappedFile.cc \ + DiskIO/Mmapped/MmappedFile.h \ + DiskIO/Mmapped/MmappedIOStrategy.cc \ + DiskIO/Mmapped/MmappedIOStrategy.h \ + DiskIO/Mmapped/MmappedDiskIOModule.cc \ + DiskIO/Mmapped/MmappedDiskIOModule.h + +libIpcIo_a_SOURCES = \ + DiskIO/IpcIo/IpcIoFile.cc \ + DiskIO/IpcIo/IpcIoFile.h \ + DiskIO/IpcIo/IpcIoIOStrategy.cc \ + DiskIO/IpcIo/IpcIoIOStrategy.h \ + DiskIO/IpcIo/IpcIoDiskIOModule.cc \ + DiskIO/IpcIo/IpcIoDiskIOModule.h + libDiskDaemon_a_SOURCES = \ DiskIO/DiskDaemon/DiskdFile.cc \ DiskIO/DiskDaemon/DiskdFile.h \ @@ -2367,7 +2444,9 @@ cbdata.h \ ETag.cc \ HttpBody.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrContRange.h \ HttpHdrRange.cc \ @@ -2396,6 +2475,7 @@ SquidString.h \ SquidTime.h \ String.cc \ + tests/stub_cache_cf.cc \ tests/stub_cache_manager.cc \ tests/stub_debug.cc \ tests/stub_HelperChildConfig.cc \ @@ -2404,7 +2484,8 @@ tests/testHttpReply.cc \ tests/testHttpReply.h \ tests/testMain.cc \ - time.cc + time.cc \ + wordlist.cc nodist_tests_testHttpReply_SOURCES = \ $(TESTSOURCES) @@ -2441,7 +2522,9 @@ HttpHeaderTools.cc \ HttpHdrContRange.cc \ HttpHdrRange.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ HttpMsg.cc \ @@ -2479,10 +2562,12 @@ tests/stub_fd.cc \ tests/stub_HttpRequest.cc \ tests/stub_MemObject.cc \ + tests/stub_MemStore.cc \ tests/stub_mime.cc \ tests/stub_store.cc \ tests/stub_store_rebuild.cc \ tests/stub_store_swapout.cc \ + tests/stub_tools.cc \ tests/stub_cache_manager.cc \ tests/testACLMaxUserIP.cc \ tests/testACLMaxUserIP.h \ @@ -2514,6 +2599,7 @@ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ + $(DISK_OS_LIBS) \ $(REGEXLIB) \ $(SQUID_CPPUNIT_LIBS) \ $(SSLLIB) \ @@ -2580,6 +2666,7 @@ CpuAffinitySet.cc \ CpuAffinitySet.h \ $(DELAY_POOL_SOURCE) \ + $(DISKIO_SOURCE) \ disk.cc \ dlink.h \ dlink.cc \ @@ -2591,6 +2678,7 @@ ExternalACLEntry.cc \ fd.cc \ fde.cc \ + filemap.cc \ forward.cc \ fqdncache.cc \ ftp.cc \ @@ -2604,7 +2692,9 @@ HttpBody.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ @@ -2668,6 +2758,8 @@ tools.cc \ tunnel.cc \ SwapDir.cc \ + MemStore.cc \ + $(UNLINKDSOURCE) \ url.cc \ URLScheme.cc \ urn.cc \ @@ -2678,7 +2770,8 @@ wordlist.cc nodist_tests_testCacheManager_SOURCES = \ - $(BUILT_SOURCES) + $(BUILT_SOURCES) \ + $(DISKIO_GEN_SOURCE) # comm.cc only requires comm/libcomm.la until fdc_table is dead. tests_testCacheManager_LDADD = \ @@ -2693,18 +2786,20 @@ libsquid.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la \ - mgr/libmgr.la \ - $(SNMP_LIBS) \ comm/libcomm.la \ icmp/libicmp.la icmp/libicmp-core.la \ log/liblog.la \ format/libformat.la \ $(REPL_OBJS) \ + $(DISK_LIBS) \ + $(DISK_OS_LIBS) \ $(ADAPTATION_LIBS) \ $(ESI_LIBS) \ $(SSL_LIBS) \ anyp/libanyp.la \ + ipc/libipc.la \ + mgr/libmgr.la \ + $(SNMP_LIBS) \ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ @@ -2739,7 +2834,9 @@ fd.cc \ filemap.cc \ HttpBody.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ @@ -2797,13 +2894,13 @@ tests/stub_ipc.cc \ tests/stub_ipcache.cc \ tests/stub_libicmp.cc \ + tests/stub_MemStore.cc \ tests/stub_mime.cc \ tests/stub_pconn.cc \ tests/stub_Port.cc \ tests/stub_store_client.cc \ tests/stub_store_rebuild.cc \ tests/stub_tools.cc \ - tests/stub_TypedMsgHdr.cc \ tests/stub_UdsOp.cc \ tests/testDiskIO.cc \ tests/testDiskIO.h \ @@ -2837,7 +2934,6 @@ $(AUTH_LIBS) \ libsquid.la \ comm/libcomm.la \ - base/libbase.la \ ip/libip.la \ fs/libfs.la \ ipc/libipc.la \ @@ -2846,6 +2942,8 @@ $(DISK_OS_LIBS) \ acl/libapi.la \ mgr/libmgr.la \ + ipc/libipc.la \ + base/libbase.la \ $(SSL_LIBS) \ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ @@ -2885,6 +2983,7 @@ CpuAffinitySet.h \ debug.cc \ $(DELAY_POOL_SOURCE) \ + $(DISKIO_SOURCE) \ disk.cc \ dlink.h \ dlink.cc \ @@ -2899,6 +2998,7 @@ FadingCounter.cc \ fd.cc \ fde.cc \ + filemap.cc \ forward.cc \ fqdncache.cc \ ftp.cc \ @@ -2912,7 +3012,9 @@ HttpBody.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ @@ -2991,6 +3093,8 @@ time.cc \ tools.cc \ tunnel.cc \ + MemStore.cc \ + $(UNLINKDSOURCE) \ url.cc \ URLScheme.cc \ urn.cc \ @@ -3000,7 +3104,8 @@ wordlist.cc nodist_tests_testEvent_SOURCES = \ - $(BUILT_SOURCES) + $(BUILT_SOURCES) \ + $(DISKIO_GEN_SOURCE) tests_testEvent_LDADD = \ $(AUTH_ACL_LIBS) \ @@ -3014,10 +3119,7 @@ libsquid.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la \ - mgr/libmgr.la \ anyp/libanyp.la \ - $(SNMP_LIBS) \ icmp/libicmp.la icmp/libicmp-core.la \ comm/libcomm.la \ log/liblog.la \ @@ -3029,6 +3131,11 @@ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ + $(DISK_LIBS) \ + $(DISK_OS_LIBS) \ + ipc/libipc.la \ + mgr/libmgr.la \ + $(SNMP_LIBS) \ $(REGEXLIB) \ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ @@ -3065,6 +3172,7 @@ CpuAffinitySet.h \ debug.cc \ $(DELAY_POOL_SOURCE) \ + $(DISKIO_SOURCE) \ disk.cc \ dlink.h \ dlink.cc \ @@ -3079,6 +3187,7 @@ FadingCounter.cc \ fd.cc \ fde.cc \ + filemap.cc \ forward.cc \ fqdncache.cc \ ftp.cc \ @@ -3092,7 +3201,9 @@ HttpBody.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ @@ -3170,6 +3281,8 @@ time.cc \ tools.cc \ tunnel.cc \ + MemStore.cc \ + $(UNLINKDSOURCE) \ url.cc \ URLScheme.cc \ urn.cc \ @@ -3179,7 +3292,8 @@ wordlist.cc nodist_tests_testEventLoop_SOURCES = \ - $(BUILT_SOURCES) + $(BUILT_SOURCES) \ + $(DISKIO_GEN_SOURCE) tests_testEventLoop_LDADD = \ $(AUTH_ACL_LIBS) \ @@ -3193,10 +3307,7 @@ libsquid.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la \ - mgr/libmgr.la \ anyp/libanyp.la \ - $(SNMP_LIBS) \ icmp/libicmp.la icmp/libicmp-core.la \ comm/libcomm.la \ log/liblog.la \ @@ -3208,6 +3319,11 @@ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ + $(DISK_LIBS) \ + $(DISK_OS_LIBS) \ + ipc/libipc.la \ + mgr/libmgr.la \ + $(SNMP_LIBS) \ $(REGEXLIB) \ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ @@ -3246,6 +3362,7 @@ CpuAffinitySet.h \ debug.cc \ $(DELAY_POOL_SOURCE) \ + $(DISKIO_SOURCE) \ disk.cc \ dlink.h \ dlink.cc \ @@ -3258,6 +3375,7 @@ FadingCounter.cc \ fd.cc \ fde.cc \ + filemap.cc \ forward.cc \ fqdncache.cc \ ftp.cc \ @@ -3269,7 +3387,9 @@ $(HTCPSOURCE) \ http.cc \ HttpBody.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ @@ -3342,9 +3462,11 @@ tests/test_http_range.cc \ tests/stub_ipc_Forwarder.cc \ tests/stub_main_cc.cc \ + tests/stub_MemStore.cc \ time.cc \ tools.cc \ tunnel.cc \ + $(UNLINKDSOURCE) \ url.cc \ URLScheme.cc \ urn.cc \ @@ -3354,7 +3476,8 @@ wordlist.cc nodist_tests_test_http_range_SOURCES = \ - $(BUILT_SOURCES) + $(BUILT_SOURCES) \ + $(DISKIO_GEN_SOURCE) tests_test_http_range_LDADD = \ $(AUTH_ACL_LIBS) \ @@ -3364,22 +3487,24 @@ acl/libstate.la \ $(AUTH_LIBS) \ acl/libapi.la \ - base/libbase.la \ libsquid.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la \ - mgr/libmgr.la \ anyp/libanyp.la \ - $(SNMP_LIBS) \ icmp/libicmp.la icmp/libicmp-core.la \ comm/libcomm.la \ log/liblog.la \ format/libformat.la \ $(REPL_OBJS) \ + $(DISK_LIBS) \ + $(DISK_OS_LIBS) \ $(ADAPTATION_LIBS) \ $(ESI_LIBS) \ $(SSL_LIBS) \ + ipc/libipc.la \ + base/libbase.la \ + mgr/libmgr.la \ + $(SNMP_LIBS) \ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ @@ -3402,7 +3527,9 @@ MemBuf.cc \ MemBuf.h \ mem.cc \ + String.cc \ structs.h \ + tests/stub_cache_cf.cc \ tests/stub_cache_manager.cc \ tests/stub_debug.cc \ tests/stub_event.cc \ @@ -3410,7 +3537,8 @@ tests/testHttpParser.cc \ tests/testHttpParser.h \ tests/testMain.cc \ - time.cc + time.cc \ + wordlist.cc nodist_tests_testHttpParser_SOURCES = \ $(TESTSOURCES) @@ -3441,6 +3569,7 @@ tests/testHttpRequestMethod.h \ tests/testHttpRequestMethod.cc \ tests/testMain.cc \ + tests/stub_DiskIOModule.cc \ tests/stub_main_cc.cc \ tests/stub_ipc_Forwarder.cc \ time.cc \ @@ -3490,7 +3619,9 @@ HttpBody.cc \ HttpHeader.cc \ HttpHeaderTools.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ @@ -3555,6 +3686,7 @@ tools.cc \ tunnel.cc \ SwapDir.cc \ + MemStore.cc \ url.cc \ URLScheme.cc \ urn.cc \ @@ -3575,11 +3707,11 @@ acl/libstate.la \ $(AUTH_LIBS) \ acl/libapi.la \ - base/libbase.la \ libsquid.la \ ip/libip.la \ fs/libfs.la \ ipc/libipc.la \ + base/libbase.la \ mgr/libmgr.la \ anyp/libanyp.la \ $(SNMP_LIBS) \ @@ -3594,6 +3726,7 @@ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ + $(DISK_OS_LIBS) \ $(REGEXLIB) \ $(SQUID_CPPUNIT_LIBS) \ $(SQUID_CPPUNIT_LA) \ @@ -3621,7 +3754,9 @@ event.cc \ EventLoop.cc \ filemap.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ @@ -3673,14 +3808,15 @@ tests/stub_http.cc \ tests/stub_HttpReply.cc \ tests/stub_HttpRequest.cc \ + tests/stub_libcomm.cc \ tests/stub_MemObject.cc \ + tests/stub_MemStore.cc \ tests/stub_mime.cc \ tests/stub_Port.cc \ tests/stub_store_client.cc \ tests/stub_store_rebuild.cc \ tests/stub_store_swapout.cc \ tests/stub_tools.cc \ - tests/stub_TypedMsgHdr.cc \ tests/stub_UdsOp.cc \ tests/testMain.cc \ tests/testStore.cc \ @@ -3718,8 +3854,8 @@ libsquid.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la \ mgr/libmgr.la \ + ipc/libipc.la \ anyp/libanyp.la \ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ @@ -3739,14 +3875,17 @@ tests_testString_SOURCES = \ ClientInfo.h \ mem.cc \ + MemBuf.cc \ String.cc \ tests/testMain.cc \ tests/testString.cc \ tests/testString.h \ + tests/stub_cache_cf.cc \ tests/stub_cache_manager.cc \ tests/stub_debug.cc \ tests/stub_HelperChildConfig.cc \ - time.cc + time.cc \ + wordlist.cc nodist_tests_testString_SOURCES = \ $(TESTSOURCES) @@ -3794,9 +3933,9 @@ tests/stub_HelperChildConfig.cc \ tests/stub_icp.cc \ tests/stub_ipc.cc \ + tests/stub_MemStore.cc \ tests/stub_pconn.cc \ tests/stub_Port.cc \ - tests/stub_TypedMsgHdr.cc \ tests/stub_UdsOp.cc \ tests/stub_internal.cc \ tests/stub_store_rebuild.cc \ @@ -3856,7 +3995,9 @@ MemBuf.cc \ HttpHdrContRange.cc \ Packer.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ url.cc \ @@ -3893,17 +4034,17 @@ acl/libstate.la \ $(AUTH_LIBS) \ acl/libapi.la \ - base/libbase.la \ libsquid.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la \ mgr/libmgr.la \ $(REPL_OBJS) \ acl/libacls.la \ anyp/libanyp.la \ $(DISK_LIBS) \ $(DISK_OS_LIBS) \ + acl/libapi.la \ + ipc/libipc.la \ $(SSL_LIBS) \ comm/libcomm.la \ base/libbase.la \ @@ -3926,10 +4067,12 @@ tests/testMain.cc \ tests/testCoss.h \ tests/stub_cache_manager.cc \ + tests/stub_client_db.cc \ tests/stub_debug.cc \ tests/stub_HelperChildConfig.cc \ tests/stub_internal.cc \ - tests/stub_CommIO.cc \ + tests/stub_ipc.cc \ + tests/stub_pconn.cc \ tests/stub_store_rebuild.cc \ fd.cc \ disk.cc \ @@ -3974,8 +4117,6 @@ tests/stub_helper.cc \ cbdata.cc \ String.cc \ - tests/stub_comm.cc \ - tests/stub_debug.cc \ tests/stub_client_side_request.cc \ tests/stub_http.cc \ mem_node.cc \ @@ -3988,7 +4129,9 @@ MemBuf.cc \ HttpHdrContRange.cc \ Packer.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ url.cc \ @@ -3999,8 +4142,11 @@ tests/stub_HttpRequest.cc \ tests/stub_access_log.cc \ refresh.cc \ + tests/stub_MemStore.cc \ + tests/stub_Port.cc \ tests/stub_store_client.cc \ tests/stub_tools.cc \ + tests/stub_UdsOp.cc \ tests/testStoreSupport.cc \ tests/testStoreSupport.h \ time.cc \ @@ -4016,6 +4162,7 @@ $(DISKIO_GEN_SOURCE) tests_testCoss_LDADD = \ + anyp/libanyp.la \ libsquid.la \ $(REGEXLIB) \ $(AUTH_ACL_LIBS) \ @@ -4025,18 +4172,19 @@ acl/libstate.la \ $(AUTH_LIBS) \ acl/libapi.la \ - base/libbase.la \ libsquid.la \ + comm/libcomm.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la \ mgr/libmgr.la \ $(REPL_OBJS) \ $(DISK_LIBS) \ $(DISK_OS_LIBS) \ $(COMMON_LIBS) \ - libsquid.la \ + $(SSL_LIBS) \ acl/libapi.la \ + ipc/libipc.la \ + base/libbase.la \ $(top_builddir)/lib/libmisccontainers.la \ $(top_builddir)/lib/libmiscencoding.la \ $(top_builddir)/lib/libmiscutil.la \ @@ -4114,7 +4262,9 @@ MemBuf.cc \ HttpHdrContRange.cc \ Packer.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrSc.cc \ HttpHdrScTarget.cc \ url.cc \ @@ -4216,7 +4366,9 @@ $(HTCPSOURCE) \ http.cc \ HttpBody.cc \ + HttpHdrCc.h \ HttpHdrCc.cc \ + HttpHdrCc.cci \ HttpHdrContRange.cc \ HttpHdrRange.cc \ HttpHdrSc.cc \ @@ -4288,6 +4440,7 @@ StoreSwapLogData.cc \ String.cc \ SwapDir.cc \ + MemStore.cc \ tests/stub_debug.cc \ tests/stub_DiskIOModule.cc \ tests/stub_main_cc.cc \ @@ -4331,6 +4484,7 @@ icmp/libicmp.la icmp/libicmp-core.la \ comm/libcomm.la \ log/liblog.la \ + $(DISK_OS_LIBS) \ format/libformat.la \ $(REGEXLIB) \ $(REPL_OBJS) \ @@ -4478,6 +4632,41 @@ -rm -f libDiskThreads.a $(libDiskThreads_a_AR) libDiskThreads.a $(libDiskThreads_a_OBJECTS) $(libDiskThreads_a_LIBADD) $(RANLIB) libDiskThreads.a +DiskIO/IpcIo/$(am__dirstamp): + @$(MKDIR_P) DiskIO/IpcIo + @: > DiskIO/IpcIo/$(am__dirstamp) +DiskIO/IpcIo/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) DiskIO/IpcIo/$(DEPDIR) + @: > DiskIO/IpcIo/$(DEPDIR)/$(am__dirstamp) +DiskIO/IpcIo/IpcIoFile.$(OBJEXT): DiskIO/IpcIo/$(am__dirstamp) \ + DiskIO/IpcIo/$(DEPDIR)/$(am__dirstamp) +DiskIO/IpcIo/IpcIoIOStrategy.$(OBJEXT): DiskIO/IpcIo/$(am__dirstamp) \ + DiskIO/IpcIo/$(DEPDIR)/$(am__dirstamp) +DiskIO/IpcIo/IpcIoDiskIOModule.$(OBJEXT): \ + DiskIO/IpcIo/$(am__dirstamp) \ + DiskIO/IpcIo/$(DEPDIR)/$(am__dirstamp) +libIpcIo.a: $(libIpcIo_a_OBJECTS) $(libIpcIo_a_DEPENDENCIES) + -rm -f libIpcIo.a + $(libIpcIo_a_AR) libIpcIo.a $(libIpcIo_a_OBJECTS) $(libIpcIo_a_LIBADD) + $(RANLIB) libIpcIo.a +DiskIO/Mmapped/$(am__dirstamp): + @$(MKDIR_P) DiskIO/Mmapped + @: > DiskIO/Mmapped/$(am__dirstamp) +DiskIO/Mmapped/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) DiskIO/Mmapped/$(DEPDIR) + @: > DiskIO/Mmapped/$(DEPDIR)/$(am__dirstamp) +DiskIO/Mmapped/MmappedFile.$(OBJEXT): DiskIO/Mmapped/$(am__dirstamp) \ + DiskIO/Mmapped/$(DEPDIR)/$(am__dirstamp) +DiskIO/Mmapped/MmappedIOStrategy.$(OBJEXT): \ + DiskIO/Mmapped/$(am__dirstamp) \ + DiskIO/Mmapped/$(DEPDIR)/$(am__dirstamp) +DiskIO/Mmapped/MmappedDiskIOModule.$(OBJEXT): \ + DiskIO/Mmapped/$(am__dirstamp) \ + DiskIO/Mmapped/$(DEPDIR)/$(am__dirstamp) +libMmapped.a: $(libMmapped_a_OBJECTS) $(libMmapped_a_DEPENDENCIES) + -rm -f libMmapped.a + $(libMmapped_a_AR) libMmapped.a $(libMmapped_a_OBJECTS) $(libMmapped_a_LIBADD) + $(RANLIB) libMmapped.a clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @@ -4688,6 +4877,8 @@ tests/$(DEPDIR)/$(am__dirstamp) tests/stub_MemObject.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) +tests/stub_MemStore.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) tests/stub_mime.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/stub_store.$(OBJEXT): tests/$(am__dirstamp) \ @@ -4696,6 +4887,8 @@ tests/$(DEPDIR)/$(am__dirstamp) tests/stub_store_swapout.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) +tests/stub_tools.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) tests/stub_cache_manager.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/testACLMaxUserIP.$(OBJEXT): tests/$(am__dirstamp) \ @@ -4721,11 +4914,15 @@ $(tests_testCacheManager_LINK) $(tests_testCacheManager_OBJECTS) $(tests_testCacheManager_LDADD) $(LIBS) tests/testCoss.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) +tests/stub_client_db.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) tests/stub_HelperChildConfig.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/stub_internal.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) -tests/stub_CommIO.$(OBJEXT): tests/$(am__dirstamp) \ +tests/stub_ipc.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) +tests/stub_pconn.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/stub_acl.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) @@ -4737,33 +4934,23 @@ tests/$(DEPDIR)/$(am__dirstamp) tests/stub_errorpage.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) +tests/stub_Port.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) tests/stub_store_client.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) -tests/stub_tools.$(OBJEXT): tests/$(am__dirstamp) \ +tests/stub_UdsOp.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/testStoreSupport.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/testCoss$(EXEEXT): $(tests_testCoss_OBJECTS) $(tests_testCoss_DEPENDENCIES) tests/$(am__dirstamp) @rm -f tests/testCoss$(EXEEXT) $(tests_testCoss_LINK) $(tests_testCoss_OBJECTS) $(tests_testCoss_LDADD) $(LIBS) -tests/stub_client_db.$(OBJEXT): tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) tests/stub_icp.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) -tests/stub_ipc.$(OBJEXT): tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) tests/stub_ipcache.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/stub_libicmp.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) -tests/stub_pconn.$(OBJEXT): tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) -tests/stub_Port.$(OBJEXT): tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) -tests/stub_TypedMsgHdr.$(OBJEXT): tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) -tests/stub_UdsOp.$(OBJEXT): tests/$(am__dirstamp) \ - tests/$(DEPDIR)/$(am__dirstamp) tests/testDiskIO.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/testDiskIO$(EXEEXT): $(tests_testDiskIO_OBJECTS) $(tests_testDiskIO_DEPENDENCIES) tests/$(am__dirstamp) @@ -4802,11 +4989,15 @@ $(tests_testHttpRequest_LINK) $(tests_testHttpRequest_OBJECTS) $(tests_testHttpRequest_LDADD) $(LIBS) tests/testNull.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) +tests/stub_CommIO.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) tests/testNull$(EXEEXT): $(tests_testNull_OBJECTS) $(tests_testNull_DEPENDENCIES) tests/$(am__dirstamp) @rm -f tests/testNull$(EXEEXT) $(tests_testNull_LINK) $(tests_testNull_OBJECTS) $(tests_testNull_LDADD) $(LIBS) tests/stub_HttpReply.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) +tests/stub_libcomm.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) tests/testStore.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/testStoreEntryStream.$(OBJEXT): tests/$(am__dirstamp) \ @@ -4871,6 +5062,12 @@ -rm -f DiskIO/DiskThreads/aiops.$(OBJEXT) -rm -f DiskIO/DiskThreads/aiops_win32.$(OBJEXT) -rm -f DiskIO/DiskThreads/async_io.$(OBJEXT) + -rm -f DiskIO/IpcIo/IpcIoDiskIOModule.$(OBJEXT) + -rm -f DiskIO/IpcIo/IpcIoFile.$(OBJEXT) + -rm -f DiskIO/IpcIo/IpcIoIOStrategy.$(OBJEXT) + -rm -f DiskIO/Mmapped/MmappedDiskIOModule.$(OBJEXT) + -rm -f DiskIO/Mmapped/MmappedFile.$(OBJEXT) + -rm -f DiskIO/Mmapped/MmappedIOStrategy.$(OBJEXT) -rm -f DiskIO/ReadRequest.$(OBJEXT) -rm -f DiskIO/WriteRequest.$(OBJEXT) -rm -f tests/TestSwapDir.$(OBJEXT) @@ -4881,9 +5078,9 @@ -rm -f tests/stub_HttpReply.$(OBJEXT) -rm -f tests/stub_HttpRequest.$(OBJEXT) -rm -f tests/stub_MemObject.$(OBJEXT) + -rm -f tests/stub_MemStore.$(OBJEXT) -rm -f tests/stub_Port.$(OBJEXT) -rm -f tests/stub_StatHist.$(OBJEXT) - -rm -f tests/stub_TypedMsgHdr.$(OBJEXT) -rm -f tests/stub_UdsOp.$(OBJEXT) -rm -f tests/stub_access_log.$(OBJEXT) -rm -f tests/stub_acl.$(OBJEXT) @@ -4903,6 +5100,7 @@ -rm -f tests/stub_ipc.$(OBJEXT) -rm -f tests/stub_ipc_Forwarder.$(OBJEXT) -rm -f tests/stub_ipcache.$(OBJEXT) + -rm -f tests/stub_libcomm.$(OBJEXT) -rm -f tests/stub_libicmp.$(OBJEXT) -rm -f tests/stub_main_cc.$(OBJEXT) -rm -f tests/stub_mime.$(OBJEXT) @@ -4988,6 +5186,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MemBlob.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MemBuf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MemObject.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MemStore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NullDelayId.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Packer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Parsing.Po@am__quote@ @@ -5128,6 +5327,12 @@ @AMDEP_TRUE@@am__include@ @am__quote@DiskIO/DiskThreads/$(DEPDIR)/aiops.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@DiskIO/DiskThreads/$(DEPDIR)/aiops_win32.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@DiskIO/DiskThreads/$(DEPDIR)/async_io.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@DiskIO/IpcIo/$(DEPDIR)/IpcIoDiskIOModule.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@DiskIO/IpcIo/$(DEPDIR)/IpcIoFile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@DiskIO/IpcIo/$(DEPDIR)/IpcIoIOStrategy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@DiskIO/Mmapped/$(DEPDIR)/MmappedDiskIOModule.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@DiskIO/Mmapped/$(DEPDIR)/MmappedFile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@DiskIO/Mmapped/$(DEPDIR)/MmappedIOStrategy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/TestSwapDir.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_CommIO.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_DelayId.Po@am__quote@ @@ -5136,9 +5341,9 @@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_HttpReply.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_HttpRequest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_MemObject.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_MemStore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_Port.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_StatHist.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_TypedMsgHdr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_UdsOp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_access_log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_acl.Po@am__quote@ @@ -5158,6 +5363,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_ipc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_ipc_Forwarder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_ipcache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_libcomm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_libicmp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_main_cc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_mime.Po@am__quote@ @@ -5644,6 +5850,10 @@ -rm -f DiskIO/DiskDaemon/$(am__dirstamp) -rm -f DiskIO/DiskThreads/$(DEPDIR)/$(am__dirstamp) -rm -f DiskIO/DiskThreads/$(am__dirstamp) + -rm -f DiskIO/IpcIo/$(DEPDIR)/$(am__dirstamp) + -rm -f DiskIO/IpcIo/$(am__dirstamp) + -rm -f DiskIO/Mmapped/$(DEPDIR)/$(am__dirstamp) + -rm -f DiskIO/Mmapped/$(am__dirstamp) -rm -f tests/$(DEPDIR)/$(am__dirstamp) -rm -f tests/$(am__dirstamp) @@ -5659,7 +5869,7 @@ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-recursive - -rm -rf ./$(DEPDIR) DiskIO/$(DEPDIR) DiskIO/AIO/$(DEPDIR) DiskIO/Blocking/$(DEPDIR) DiskIO/DiskDaemon/$(DEPDIR) DiskIO/DiskThreads/$(DEPDIR) tests/$(DEPDIR) + -rm -rf ./$(DEPDIR) DiskIO/$(DEPDIR) DiskIO/AIO/$(DEPDIR) DiskIO/Blocking/$(DEPDIR) DiskIO/DiskDaemon/$(DEPDIR) DiskIO/DiskThreads/$(DEPDIR) DiskIO/IpcIo/$(DEPDIR) DiskIO/Mmapped/$(DEPDIR) tests/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -5706,7 +5916,7 @@ installcheck-am: maintainer-clean: maintainer-clean-recursive - -rm -rf ./$(DEPDIR) DiskIO/$(DEPDIR) DiskIO/AIO/$(DEPDIR) DiskIO/Blocking/$(DEPDIR) DiskIO/DiskDaemon/$(DEPDIR) DiskIO/DiskThreads/$(DEPDIR) tests/$(DEPDIR) + -rm -rf ./$(DEPDIR) DiskIO/$(DEPDIR) DiskIO/AIO/$(DEPDIR) DiskIO/Blocking/$(DEPDIR) DiskIO/DiskDaemon/$(DEPDIR) DiskIO/DiskThreads/$(DEPDIR) DiskIO/IpcIo/$(DEPDIR) DiskIO/Mmapped/$(DEPDIR) tests/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff -u -r -N squid-3.2.0.12/src/mem.cc squid-3.2.0.13/src/mem.cc --- squid-3.2.0.12/src/mem.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/mem.cc 2011-10-14 14:42:56.000000000 +1300 @@ -453,7 +453,6 @@ memDataInit(MEM_DLINK_NODE, "dlink_node", sizeof(dlink_node), 10); memDataInit(MEM_DREAD_CTRL, "dread_ctrl", sizeof(dread_ctrl), 0); memDataInit(MEM_DWRITE_Q, "dwrite_q", sizeof(dwrite_q), 0); - memDataInit(MEM_HTTP_HDR_CC, "HttpHdrCc", sizeof(HttpHdrCc), 0); memDataInit(MEM_HTTP_HDR_CONTENT_RANGE, "HttpHdrContRange", sizeof(HttpHdrContRange), 0); memDataInit(MEM_NETDBENTRY, "netdbEntry", sizeof(netdbEntry), 0); memDataInit(MEM_NET_DB_NAME, "net_db_name", sizeof(net_db_name), 0); @@ -521,7 +520,8 @@ memClean(void) { MemPoolGlobalStats stats; - MemPools::GetInstance().setIdleLimit(0); + if (Config.MemPools.limit > 0) // do not reset if disabled or same + MemPools::GetInstance().setIdleLimit(0); MemPools::GetInstance().clean(0); memPoolGetGlobalStats(&stats); diff -u -r -N squid-3.2.0.12/src/MemObject.cc squid-3.2.0.13/src/MemObject.cc --- squid-3.2.0.12/src/MemObject.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/MemObject.cc 2011-10-14 14:42:56.000000000 +1300 @@ -72,6 +72,15 @@ return Pool().inUseCount(); } +void +MemObject::resetUrls(char const *aUrl, char const *aLog_url) +{ + safe_free(url); + safe_free(log_url); /* XXX account log_url */ + log_url = xstrdup(aLog_url); + url = xstrdup(aUrl); +} + MemObject::MemObject(char const *aUrl, char const *aLog_url) { debugs(20, 3, HERE << "new MemObject " << this); @@ -91,6 +100,8 @@ object_sz = -1; /* XXX account log_url */ + + swapout.decision = SwapOut::swNeedsCheck; } MemObject::~MemObject() @@ -234,6 +245,15 @@ return data_hdr.endOffset(); } +void +MemObject::markEndOfReplyHeaders() +{ + const int hdr_sz = endOffset(); + assert(hdr_sz >= 0); + assert(_reply); + _reply->hdr_sz = hdr_sz; +} + int64_t MemObject::size() const { @@ -243,6 +263,23 @@ return object_sz; } +int64_t +MemObject::expectedReplySize() const +{ + debugs(20, 7, HERE << "object_sz: " << object_sz); + if (object_sz >= 0) // complete() has been called; we know the exact answer + return object_sz; + + if (_reply) { + const int64_t clen = _reply->bodySize(method); + debugs(20, 7, HERE << "clen: " << clen); + if (clen >= 0 && _reply->hdr_sz > 0) // yuck: HttpMsg sets hdr_sz to 0 + return clen + _reply->hdr_sz; + } + + return -1; // not enough information to predict +} + void MemObject::reset() { @@ -342,7 +379,7 @@ * there will be a chunk of the data which is not in memory * and is not yet on disk. * The -1 makes sure the page isn't freed until storeSwapOut has - * walked to the next page. (mem->swapout.memnode) + * walked to the next page. */ int64_t on_disk; diff -u -r -N squid-3.2.0.12/src/MemObject.h squid-3.2.0.13/src/MemObject.h --- squid-3.2.0.12/src/MemObject.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/MemObject.h 2011-10-14 14:42:56.000000000 +1300 @@ -58,12 +58,19 @@ MemObject(char const *, char const *); ~MemObject(); + /// replaces construction-time URLs with correct ones; see hidden_mem_obj + void resetUrls(char const *aUrl, char const *aLog_url); + void write(StoreIOBuffer, STMCB *, void *); void unlinkRequest(); HttpReply const *getReply() const; void replaceHttpReply(HttpReply *newrep); void stat (MemBuf * mb) const; int64_t endOffset () const; + void markEndOfReplyHeaders(); ///< sets _reply->hdr_sz to endOffset() + /// negative if unknown; otherwise, expected object_sz, expected endOffset + /// maximum, and stored reply headers+body size (all three are the same) + int64_t expectedReplySize() const; int64_t size() const; void reset(); int64_t lowestMemReaderOffset() const; @@ -106,9 +113,12 @@ { public: - int64_t queue_offset; /* relative to in-mem data */ - mem_node *memnode; /* which node we're currently paging out */ + int64_t queue_offset; ///< number of bytes sent to SwapDir for writing StoreIOState::Pointer sio; + + /// Decision states for StoreEntry::swapoutPossible() and related code. + typedef enum { swNeedsCheck = 0, swImpossible = -1, swPossible = +1 } Decision; + Decision decision; ///< current decision state }; SwapOut swapout; diff -u -r -N squid-3.2.0.12/src/MemStore.cc squid-3.2.0.13/src/MemStore.cc --- squid-3.2.0.12/src/MemStore.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/MemStore.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,399 @@ +/* + * $Id$ + * + * DEBUG: section 20 Memory Cache + * + */ + +#include "config.h" +#include "base/RunnersRegistry.h" +#include "ipc/mem/Page.h" +#include "ipc/mem/Pages.h" +#include "MemObject.h" +#include "MemStore.h" +#include "HttpReply.h" + +/// shared memory segment path to use for MemStore maps +static const char *ShmLabel = "cache_mem"; + +// XXX: support storage using more than one page per entry + +MemStore::MemStore(): map(NULL), theCurrentSize(0) +{ +} + +MemStore::~MemStore() +{ + delete map; +} + +void +MemStore::init() +{ + const int64_t entryLimit = EntryLimit(); + if (entryLimit <= 0) + return; // no memory cache configured or a misconfiguration + + const int64_t diskMaxSize = Store::Root().maxObjectSize(); + const int64_t memMaxSize = maxObjectSize(); + if (diskMaxSize == -1) { + debugs(20, DBG_IMPORTANT, "WARNING: disk-cache maximum object size " + "is unlimited but mem-cache maximum object size is " << + memMaxSize / 1024.0 << " KB"); + } else if (diskMaxSize > memMaxSize) { + debugs(20, DBG_IMPORTANT, "WARNING: disk-cache maximum object size " + "is too large for mem-cache: " << + diskMaxSize / 1024.0 << " KB > " << + memMaxSize / 1024.0 << " KB"); + } + + map = new MemStoreMap(ShmLabel); + map->cleaner = this; +} + +void +MemStore::stat(StoreEntry &e) const +{ + storeAppendPrintf(&e, "\n\nShared Memory Cache\n"); + + storeAppendPrintf(&e, "Maximum Size: %.0f KB\n", Config.memMaxSize/1024.0); + + if (map) { + const int limit = map->entryLimit(); + storeAppendPrintf(&e, "Maximum entries: %9d\n", limit); + if (limit > 0) { + storeAppendPrintf(&e, "Current entries: %"PRId64" %.2f%%\n", + currentCount(), (100.0 * currentCount() / limit)); + + if (limit < 100) { // XXX: otherwise too expensive to count + Ipc::ReadWriteLockStats stats; + map->updateStats(stats); + stats.dump(e); + } + } + } +} + +void +MemStore::maintain() +{ +} + +uint64_t +MemStore::minSize() const +{ + return 0; // XXX: irrelevant, but Store parent forces us to implement this +} + +uint64_t +MemStore::maxSize() const +{ + return 0; // XXX: make configurable +} + +uint64_t +MemStore::currentSize() const +{ + return theCurrentSize; +} + +uint64_t +MemStore::currentCount() const +{ + return map ? map->entryCount() : 0; +} + +int64_t +MemStore::maxObjectSize() const +{ + return Ipc::Mem::PageSize(); +} + +void +MemStore::reference(StoreEntry &) +{ +} + +bool +MemStore::dereference(StoreEntry &) +{ + // no need to keep e in the global store_table for us; we have our own map + return false; +} + +int +MemStore::callback() +{ + return 0; +} + +StoreSearch * +MemStore::search(String const, HttpRequest *) +{ + fatal("not implemented"); + return NULL; +} + +StoreEntry * +MemStore::get(const cache_key *key) +{ + if (!map) + return NULL; + + // XXX: replace sfileno with a bigger word (sfileno is only for cache_dirs) + sfileno index; + const Ipc::StoreMapSlot *const slot = map->openForReading(key, index); + if (!slot) + return NULL; + + const Ipc::StoreMapSlot::Basics &basics = slot->basics; + const MemStoreMap::Extras &extras = map->extras(index); + + // create a brand new store entry and initialize it with stored info + StoreEntry *e = new StoreEntry(); + e->lock_count = 0; + + e->swap_file_sz = basics.swap_file_sz; + e->lastref = basics.lastref; + e->timestamp = basics.timestamp; + e->expires = basics.expires; + e->lastmod = basics.lastmod; + e->refcount = basics.refcount; + e->flags = basics.flags; + + e->store_status = STORE_OK; + e->mem_status = IN_MEMORY; // setMemStatus(IN_MEMORY) requires mem_obj + //e->swap_status = set in StoreEntry constructor to SWAPOUT_NONE; + e->ping_status = PING_NONE; + + EBIT_SET(e->flags, ENTRY_CACHABLE); + EBIT_CLR(e->flags, RELEASE_REQUEST); + EBIT_CLR(e->flags, KEY_PRIVATE); + EBIT_SET(e->flags, ENTRY_VALIDATED); + + const bool copied = copyFromShm(*e, extras); + + // we copied everything we could to local memory; no more need to lock + map->closeForReading(index); + + if (copied) { + e->hashInsert(key); + return e; + } + + debugs(20, 3, HERE << "mem-loading failed; freeing " << index); + map->free(index); // do not let others into the same trap + return NULL; +} + +void +MemStore::get(String const key, STOREGETCLIENT aCallback, void *aCallbackData) +{ + // XXX: not needed but Store parent forces us to implement this + fatal("MemStore::get(key,callback,data) should not be called"); +} + +bool +MemStore::copyFromShm(StoreEntry &e, const MemStoreMap::Extras &extras) +{ + const Ipc::Mem::PageId &page = extras.page; + + StoreIOBuffer sourceBuf(extras.storedSize, 0, + static_cast(PagePointer(page))); + + // XXX: We do not know the URLs yet, only the key, but we need to parse and + // store the response for the Root().get() callers to be happy because they + // expect IN_MEMORY entries to already have the response headers and body. + // At least one caller calls createMemObject() if there is not one, so + // we hide the true object until that happens (to avoid leaking TBD URLs). + e.createMemObject("TBD", "TBD"); + + // emulate the usual Store code but w/o inapplicable checks and callbacks: + + // from store_client::readBody(): + HttpReply *rep = (HttpReply *)e.getReply(); + const ssize_t end = headersEnd(sourceBuf.data, sourceBuf.length); + if (!rep->parseCharBuf(sourceBuf.data, end)) { + debugs(20, DBG_IMPORTANT, "Could not parse mem-cached headers: " << e); + return false; + } + // local memory stores both headers and body + e.mem_obj->object_sz = sourceBuf.length; // from StoreEntry::complete() + + storeGetMemSpace(sourceBuf.length); // from StoreEntry::write() + + assert(e.mem_obj->data_hdr.write(sourceBuf)); // from MemObject::write() + const int64_t written = e.mem_obj->endOffset(); + // we should write all because StoreEntry::write() never fails + assert(written >= 0 && + static_cast(written) == sourceBuf.length); + // would be nice to call validLength() here, but it needs e.key + + debugs(20, 7, HERE << "mem-loaded all " << written << " bytes of " << e << + " from " << page); + + e.hideMemObject(); + + return true; +} + +void +MemStore::considerKeeping(StoreEntry &e) +{ + if (!e.memoryCachable()) { + debugs(20, 7, HERE << "Not memory cachable: " << e); + return; // cannot keep due to entry state or properties + } + + assert(e.mem_obj); + if (!willFit(e.mem_obj->endOffset())) { + debugs(20, 5, HERE << "No mem-cache space for " << e); + return; // failed to free enough space + } + + keep(e); // may still fail +} + +bool +MemStore::willFit(int64_t need) +{ + // TODO: obey configured maximum entry size (with page-based rounding) + return need <= static_cast(Ipc::Mem::PageSize()); +} + +/// allocates map slot and calls copyToShm to store the entry in shared memory +void +MemStore::keep(StoreEntry &e) +{ + if (!map) { + debugs(20, 5, HERE << "No map to mem-cache " << e); + return; + } + + sfileno index = 0; + Ipc::StoreMapSlot *slot = map->openForWriting(reinterpret_cast(e.key), index); + if (!slot) { + debugs(20, 5, HERE << "No room in mem-cache map to index " << e); + return; + } + + MemStoreMap::Extras &extras = map->extras(index); + if (copyToShm(e, extras)) { + slot->set(e); + map->closeForWriting(index, false); + } else { + map->abortIo(index); + } +} + +/// uses mem_hdr::copy() to copy local data to shared memory +bool +MemStore::copyToShm(StoreEntry &e, MemStoreMap::Extras &extras) +{ + Ipc::Mem::PageId page; + if (!Ipc::Mem::GetPage(Ipc::Mem::PageId::cachePage, page)) { + debugs(20, 5, HERE << "No mem-cache page for " << e); + return false; // GetPage is responsible for any cleanup on failures + } + + const int64_t bufSize = Ipc::Mem::PageSize(); + const int64_t eSize = e.mem_obj->endOffset(); + + StoreIOBuffer sharedSpace(bufSize, 0, + static_cast(PagePointer(page))); + + // check that we kept everything or purge incomplete/sparse cached entry + const ssize_t copied = e.mem_obj->data_hdr.copy(sharedSpace); + if (eSize != copied) { + debugs(20, 2, HERE << "Failed to mem-cache " << e << ": " << + eSize << "!=" << copied); + // cleanup + PutPage(page); + return false; + } + + debugs(20, 7, HERE << "mem-cached all " << eSize << " bytes of " << e << + " in " << page); + + theCurrentSize += Ipc::Mem::PageSize(); + // remember storage location and size + extras.page = page; + extras.storedSize = copied; + return true; +} + +void +MemStore::cleanReadable(const sfileno fileno) +{ + Ipc::Mem::PutPage(map->extras(fileno).page); + theCurrentSize -= Ipc::Mem::PageSize(); +} + +/// calculates maximum number of entries we need to store and map +int64_t +MemStore::EntryLimit() +{ + if (!Config.memMaxSize) + return 0; // no memory cache configured + + const int64_t entrySize = Ipc::Mem::PageSize(); // for now + const int64_t entryLimit = Config.memMaxSize / entrySize; + return entryLimit; +} + + +/// initializes shared memory segments used by MemStore +class MemStoreRr: public Ipc::Mem::RegisteredRunner +{ +public: + /* RegisteredRunner API */ + MemStoreRr(): owner(NULL) {} + virtual void run(const RunnerRegistry &); + virtual ~MemStoreRr(); + +protected: + virtual void create(const RunnerRegistry &); + +private: + MemStoreMap::Owner *owner; +}; + +RunnerRegistrationEntry(rrAfterConfig, MemStoreRr); + + +void MemStoreRr::run(const RunnerRegistry &r) +{ + // decide whether to use a shared memory cache if the user did not specify + if (!Config.memShared.configured()) { + Config.memShared.configure(AtomicOperationsSupported && + Ipc::Mem::Segment::Enabled() && UsingSmp() && + Config.memMaxSize > 0); + } else if (Config.memShared && !AtomicOperationsSupported) { + // bail if the user wants shared memory cache but we cannot support it + fatal("memory_cache_shared is on, but no support for atomic operations detected"); + } else if (Config.memShared && !Ipc::Mem::Segment::Enabled()) { + fatal("memory_cache_shared is on, but no support for shared memory detected"); + } else if (Config.memShared && !UsingSmp()) { + debugs(20, DBG_IMPORTANT, "WARNING: memory_cache_shared is on, but only" + " a single worker is running"); + } + + Ipc::Mem::RegisteredRunner::run(r); +} + +void MemStoreRr::create(const RunnerRegistry &) +{ + if (!Config.memShared) + return; + + Must(!owner); + const int64_t entryLimit = MemStore::EntryLimit(); + if (entryLimit <= 0) + return; // no memory cache configured or a misconfiguration + owner = MemStoreMap::Init(ShmLabel, entryLimit); +} + +MemStoreRr::~MemStoreRr() +{ + delete owner; +} diff -u -r -N squid-3.2.0.12/src/MemStore.h squid-3.2.0.13/src/MemStore.h --- squid-3.2.0.12/src/MemStore.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/MemStore.h 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,69 @@ +/* + * $Id$ + */ + +#ifndef SQUID_MEMSTORE_H +#define SQUID_MEMSTORE_H + +#include "ipc/mem/Page.h" +#include "ipc/StoreMap.h" +#include "Store.h" + +// StoreEntry restoration info not already stored by Ipc::StoreMap +struct MemStoreMapExtras { + Ipc::Mem::PageId page; ///< shared memory page with the entry content + int64_t storedSize; ///< total size of the stored entry content +}; +typedef Ipc::StoreMapWithExtras MemStoreMap; + +/// Stores HTTP entities in RAM. Current implementation uses shared memory. +/// Unlike a disk store (SwapDir), operations are synchronous (and fast). +class MemStore: public Store, public Ipc::StoreMapCleaner +{ +public: + MemStore(); + virtual ~MemStore(); + + /// cache the entry or forget about it until the next considerKeeping call + void considerKeeping(StoreEntry &e); + + /* Store API */ + virtual int callback(); + virtual StoreEntry * get(const cache_key *); + virtual void get(String const key , STOREGETCLIENT callback, void *cbdata); + virtual void init(); + virtual uint64_t maxSize() const; + virtual uint64_t minSize() const; + virtual uint64_t currentSize() const; + virtual uint64_t currentCount() const; + virtual int64_t maxObjectSize() const; + virtual void stat(StoreEntry &) const; + virtual StoreSearch *search(String const url, HttpRequest *); + virtual void reference(StoreEntry &); + virtual bool dereference(StoreEntry &); + virtual void maintain(); + + static int64_t EntryLimit(); + +protected: + bool willFit(int64_t needed); + void keep(StoreEntry &e); + + bool copyToShm(StoreEntry &e, MemStoreMap::Extras &extras); + bool copyFromShm(StoreEntry &e, const MemStoreMap::Extras &extras); + + // Ipc::StoreMapCleaner API + virtual void cleanReadable(const sfileno fileno); + +private: + MemStoreMap *map; ///< index of mem-cached entries + uint64_t theCurrentSize; ///< currently used space in the storage area +}; + +// Why use Store as a base? MemStore and SwapDir are both "caches". + +// Why not just use a SwapDir API? That would not help much because Store has +// to check/update memory cache separately from the disk cache. And same API +// would hurt because we can support synchronous get/put, unlike the disks. + +#endif /* SQUID_MEMSTORE_H */ diff -u -r -N squid-3.2.0.12/src/mgr/FunAction.cc squid-3.2.0.13/src/mgr/FunAction.cc --- squid-3.2.0.12/src/mgr/FunAction.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/mgr/FunAction.cc 2011-10-14 14:42:56.000000000 +1300 @@ -44,9 +44,9 @@ { debugs(16, 5, HERE); Must(entry != NULL); - if (UsingSmp() && IamWorkerProcess()) + if (UsingSmp()) storeAppendPrintf(entry, "by kid%d {\n", KidIdentifier); handler(entry); - if (atomic() && UsingSmp() && IamWorkerProcess()) + if (atomic() && UsingSmp()) storeAppendPrintf(entry, "} by kid%d\n\n", KidIdentifier); } diff -u -r -N squid-3.2.0.12/src/mgr/InfoAction.cc squid-3.2.0.13/src/mgr/InfoAction.cc --- squid-3.2.0.12/src/mgr/InfoAction.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/mgr/InfoAction.cc 2011-10-14 14:42:56.000000000 +1300 @@ -176,10 +176,10 @@ Must(entry != NULL); #if XMALLOC_STATISTICS - if (UsingSmp() && IamWorkerProcess()) + if (UsingSmp()) storeAppendPrintf(entry, "by kid%d {\n", KidIdentifier); DumpMallocStatistics(entry); - if (UsingSmp() && IamWorkerProcess()) + if (UsingSmp()) storeAppendPrintf(entry, "} by kid%d\n\n", KidIdentifier); #endif if (IamPrimaryProcess()) diff -u -r -N squid-3.2.0.12/src/mime.cc squid-3.2.0.13/src/mime.cc --- squid-3.2.0.12/src/mime.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/mime.cc 2011-10-14 14:42:56.000000000 +1300 @@ -34,6 +34,7 @@ */ #include "squid.h" +#include "HttpHdrCc.h" #include "Store.h" #include "StoreClient.h" #include "HttpReply.h" @@ -462,9 +463,9 @@ reply->setHeaders(HTTP_OK, NULL, mimeGetContentType(icon), sb.st_size, sb.st_mtime, -1); - reply->cache_control = httpHdrCcCreate(); + reply->cache_control = new HttpHdrCc(); - httpHdrCcSetMaxAge(reply->cache_control, 86400); + reply->cache_control->maxAge(86400); reply->header.putCc(reply->cache_control); diff -u -r -N squid-3.2.0.12/src/neighbors.cc squid-3.2.0.13/src/neighbors.cc --- squid-3.2.0.12/src/neighbors.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/neighbors.cc 2011-10-14 14:42:56.000000000 +1300 @@ -1025,6 +1025,7 @@ } if (entry->lock_count == 0) { + // TODO: many entries are unlocked; why is this reported at level 1? debugs(12, 1, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks"); neighborCountIgnored(p); return; @@ -1419,9 +1420,8 @@ cbdataReferenceDone(psstate->callback_data); - EBIT_SET(fake->flags, ENTRY_ABORTED); + fake->abort(); // sets ENTRY_ABORTED and initiates releated cleanup HTTPMSGUNLOCK(fake->mem_obj->request); - fake->releaseRequest(); fake->unlock(); HTTPMSGUNLOCK(psstate->request); cbdataFree(psstate); @@ -1729,6 +1729,7 @@ } if (e->lock_count == 0) { + // TODO: many entries are unlocked; why is this reported at level 1? debugs(12, 1, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks"); neighborCountIgnored(p); return; diff -u -r -N squid-3.2.0.12/src/peer_select.cc squid-3.2.0.13/src/peer_select.cc --- squid-3.2.0.12/src/peer_select.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/peer_select.cc 2011-10-14 14:42:56.000000000 +1300 @@ -177,15 +177,21 @@ psstate->never_direct = answer; switch (answer) { case ACCESS_ALLOWED: - /** if always_direct says YES, do that. */ - psstate->direct = DIRECT_YES; + /** if never_direct says YES, do that. */ + psstate->direct = DIRECT_NO; debugs(44, 3, HERE << "direct = " << DirectStr[psstate->direct] << " (never_direct allow)"); break; case ACCESS_DENIED: // not relevant. + case ACCESS_DUNNO: // not relevant. break; - default: // Oops. Failed to get a result. + case ACCESS_REQ_PROXY_AUTH: +#if WHEN_AUTH_CASES_PORT + case ACCESS_AUTH_REQUIRED: + case ACCESS_AUTH_EXPIRED_OK: + case ACCESS_AUTH_EXPIRED_BAD: +#endif debugs(44, DBG_IMPORTANT, "WARNING: never_direct resulted in " << answer << ". Username ACLs are not reliable here."); - assert(answer != ACCESS_DUNNO); + break; } peerSelectFoo(psstate); } @@ -204,10 +210,16 @@ debugs(44, 3, HERE << "direct = " << DirectStr[psstate->direct] << " (always_direct allow)"); break; case ACCESS_DENIED: // not relevant. + case ACCESS_DUNNO: // not relevant. break; - default: // Oops. Failed to get a result. + case ACCESS_REQ_PROXY_AUTH: +#if WHEN_AUTH_CASES_PORT + case ACCESS_AUTH_REQUIRED: + case ACCESS_AUTH_EXPIRED_OK: + case ACCESS_AUTH_EXPIRED_BAD: +#endif debugs(44, DBG_IMPORTANT, "WARNING: always_direct resulted in " << answer << ". Username ACLs are not reliable here."); - assert(answer != ACCESS_DUNNO); + break; } peerSelectFoo(psstate); } diff -u -r -N squid-3.2.0.12/src/protos.h squid-3.2.0.13/src/protos.h --- squid-3.2.0.12/src/protos.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/protos.h 2011-10-14 14:42:56.000000000 +1300 @@ -237,13 +237,6 @@ /* Http Cache Control Header Field */ SQUIDCEXTERN void httpHdrCcInitModule(void); SQUIDCEXTERN void httpHdrCcCleanModule(void); -SQUIDCEXTERN HttpHdrCc *httpHdrCcCreate(void); -SQUIDCEXTERN HttpHdrCc *httpHdrCcParseCreate(const String * str); -SQUIDCEXTERN void httpHdrCcDestroy(HttpHdrCc * cc); -SQUIDCEXTERN HttpHdrCc *httpHdrCcDup(const HttpHdrCc * cc); -SQUIDCEXTERN void httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p); -SQUIDCEXTERN void httpHdrCcSetMaxAge(HttpHdrCc * cc, int max_age); -SQUIDCEXTERN void httpHdrCcSetSMaxAge(HttpHdrCc * cc, int s_maxage); SQUIDCEXTERN void httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist); void httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count); @@ -511,6 +504,14 @@ SQUIDCEXTERN void storeRebuildComplete(struct _store_rebuild_data *); SQUIDCEXTERN void storeRebuildProgress(int sd_index, int total, int sofar); +/// loads entry from disk; fills supplied memory buffer on success +bool storeRebuildLoadEntry(int fd, int diskIndex, MemBuf &buf, struct _store_rebuild_data &counts); +/// parses entry buffer and validates entry metadata; fills e on success +bool storeRebuildParseEntry(MemBuf &buf, StoreEntry &e, cache_key *key, struct _store_rebuild_data &counts, uint64_t expectedSize); +/// checks whether the loaded entry should be kept; updates counters +bool storeRebuildKeepEntry(const StoreEntry &e, const cache_key *key, struct _store_rebuild_data &counts); + + /* * store_swapin.c */ @@ -559,12 +560,16 @@ SQUIDCEXTERN bool IamCoordinatorProcess(); /// whether the current process handles HTTP transactions and such SQUIDCEXTERN bool IamWorkerProcess(); +/// whether the current process is dedicated to managing a cache_dir +bool IamDiskProcess(); /// Whether we are running in daemon mode SQUIDCEXTERN bool InDaemonMode(); // try using specific Iam*() checks above first /// Whether there should be more than one worker process running SQUIDCEXTERN bool UsingSmp(); // try using specific Iam*() checks above first /// number of Kid processes as defined in src/ipc/Kid.h SQUIDCEXTERN int NumberOfKids(); +/// a string describing this process roles such as worker or coordinator +String ProcessRoles(); SQUIDCEXTERN int DebugSignal; /* AYJ debugs function to show locations being reset with memset() */ diff -u -r -N squid-3.2.0.12/src/redirect.cc squid-3.2.0.13/src/redirect.cc --- squid-3.2.0.12/src/redirect.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/redirect.cc 2011-10-14 14:42:56.000000000 +1300 @@ -251,7 +251,7 @@ redirectors->cmdline = Config.Program.redirect; - redirectors->childs = Config.redirectChildren; + redirectors->childs.updateLimits(Config.redirectChildren); redirectors->ipc_type = IPC_STREAM; diff -u -r -N squid-3.2.0.12/src/refresh.cc squid-3.2.0.13/src/refresh.cc --- squid-3.2.0.12/src/refresh.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/refresh.cc 2011-10-14 14:42:56.000000000 +1300 @@ -38,6 +38,7 @@ #endif #include "squid.h" +#include "HttpHdrCc.h" #include "mgr/Registration.h" #include "Store.h" #include "MemObject.h" @@ -267,14 +268,15 @@ if (request && !request->flags.ignore_cc) { const HttpHdrCc *const cc = request->cache_control; - if (cc && cc->min_fresh > 0) { + if (cc && cc->hasMinFresh()) { + const int32_t minFresh=cc->minFresh(); debugs(22, 3, "\tage + min-fresh:\t" << age << " + " << - cc->min_fresh << " = " << age + cc->min_fresh); + minFresh << " = " << age + minFresh); debugs(22, 3, "\tcheck_time + min-fresh:\t" << check_time << " + " - << cc->min_fresh << " = " << - mkrfc1123(check_time + cc->min_fresh)); - age += cc->min_fresh; - check_time += cc->min_fresh; + << minFresh << " = " << + mkrfc1123(check_time + minFresh)); + age += minFresh; + check_time += minFresh; } } @@ -286,8 +288,8 @@ // stale-if-error requires any failure be passed thru when its period is over. if (request && entry->mem_obj && entry->mem_obj->getReply() && entry->mem_obj->getReply()->cache_control && - EBIT_TEST(entry->mem_obj->getReply()->cache_control->mask, CC_STALE_IF_ERROR) && - entry->mem_obj->getReply()->cache_control->stale_if_error < staleness) { + entry->mem_obj->getReply()->cache_control->hasStaleIfError() && + entry->mem_obj->getReply()->cache_control->staleIfError() < staleness) { debugs(22, 3, "refreshCheck: stale-if-error period expired."); request->flags.fail_on_validation_err = 1; @@ -334,31 +336,31 @@ #endif if (NULL != cc) { - if (cc->max_age > -1) { + if (cc->hasMaxAge()) { #if USE_HTTP_VIOLATIONS - if (R->flags.ignore_reload && cc->max_age == 0) { + if (R->flags.ignore_reload && cc->maxAge() == 0) { debugs(22, 3, "refreshCheck: MAYBE: client-max-age = 0 and ignore-reload"); } else #endif { - if (cc->max_age == 0) { + if (cc->maxAge() == 0) { debugs(22, 3, "refreshCheck: YES: client-max-age = 0"); return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE; } - if (age > cc->max_age) { + if (age > cc->maxAge()) { debugs(22, 3, "refreshCheck: YES: age > client-max-age"); return STALE_EXCEEDS_REQUEST_MAX_AGE_VALUE; } } } - if (EBIT_TEST(cc->mask, CC_MAX_STALE) && staleness > -1) { - if (cc->max_stale < 0) { + if (cc->hasMaxStale() && staleness > -1) { + if (cc->maxStale()==HttpHdrCc::MAX_STALE_ANY) { /* max-stale directive without a value */ debugs(22, 3, "refreshCheck: NO: max-stale wildcard"); return FRESH_REQUEST_MAX_STALE_ALL; - } else if (staleness < cc->max_stale) { + } else if (staleness < cc->maxStale()) { debugs(22, 3, "refreshCheck: NO: staleness < max-stale"); return FRESH_REQUEST_MAX_STALE_VALUE; } diff -u -r -N squid-3.2.0.12/src/Server.cc squid-3.2.0.13/src/Server.cc --- squid-3.2.0.12/src/Server.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/Server.cc 2011-10-14 14:42:56.000000000 +1300 @@ -163,8 +163,10 @@ assert(rep); theFinalReply = HTTPMSGLOCK(rep); - entry->replaceHttpReply(theFinalReply); - haveParsedReplyHeaders(); + // give entry the reply because haveParsedReplyHeaders() expects it there + entry->replaceHttpReply(theFinalReply, false); // but do not write yet + haveParsedReplyHeaders(); // update the entry/reply (e.g., set timestamps) + entry->startWriting(); // write the updated entry to store return theFinalReply; } @@ -382,10 +384,10 @@ } if (io.flag) { - debugs(11, 1, "sentRequestBody error: FD " << io.fd << ": " << xstrerr(errno)); + debugs(11, 1, "sentRequestBody error: FD " << io.fd << ": " << xstrerr(io.xerrno)); ErrorState *err; err = errorCon(ERR_WRITE_ERROR, HTTP_BAD_GATEWAY, fwd->request); - err->xerrno = errno; + err->xerrno = io.xerrno; fwd->fail(err); abortTransaction("I/O error while sending request body"); return; @@ -520,7 +522,7 @@ purgeEntriesByHeader(request, reqUrl, theFinalReply, HDR_CONTENT_LOCATION); } -// called (usually by kids) when we have final (possibly adapted) reply headers +/// called when we have final (possibly adapted) reply headers; kids extend void ServerStateData::haveParsedReplyHeaders() { diff -u -r -N squid-3.2.0.12/src/snmp_agent.cc squid-3.2.0.13/src/snmp_agent.cc --- squid-3.2.0.12/src/snmp_agent.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/snmp_agent.cc 2011-10-14 14:42:56.000000000 +1300 @@ -67,7 +67,7 @@ case SYSSTOR: Answer = snmp_var_new_integer(Var->name, Var->name_length, - store_swap_size, + Store::Root().currentSize() >> 10, ASN_INTEGER); break; @@ -131,7 +131,7 @@ case CONF_ST_SWMAXSZ: Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) (Store::Root().maxSize() >> 10), + (snint) (Store::Root().maxSize() >> 20), ASN_INTEGER); break; @@ -531,7 +531,7 @@ case PERF_PROTOSTAT_AGGR_CURSWAP: Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) store_swap_size, + (snint) Store::Root().currentSize() >> 10, SMI_GAUGE32); break; diff -u -r -N squid-3.2.0.12/src/ssl/certificate_db.cc squid-3.2.0.13/src/ssl/certificate_db.cc --- squid-3.2.0.12/src/ssl/certificate_db.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ssl/certificate_db.cc 2011-10-14 14:42:56.000000000 +1300 @@ -4,6 +4,9 @@ #include "config.h" #include "ssl/certificate_db.h" +#if HAVE_ERRNO_H +#include +#endif #if HAVE_FSTREAM #include #endif @@ -20,33 +23,86 @@ #include #endif -Ssl::FileLocker::FileLocker(std::string const & filename) - : fd(-1) +#define HERE "(ssl_crtd) " << __FILE__ << ':' << __LINE__ << ": " + +Ssl::Lock::Lock(std::string const &aFilename) : + filename(aFilename), +#if _SQUID_MSWIN_ + hFile(INVALID_HANDLE_VALUE) +#else + fd(-1) +#endif +{ +} + +bool Ssl::Lock::locked() const +{ +#if _SQUID_MSWIN_ + return hFile != INVALID_HANDLE_VALUE; +#else + return fd != -1; +#endif +} + +void Ssl::Lock::lock() { + #if _SQUID_MSWIN_ hFile = CreateFile(TEXT(filename.c_str()), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile != INVALID_HANDLE_VALUE) - LockFile(hFile, 0, 0, 1, 0); + if (hFile == INVALID_HANDLE_VALUE) #else fd = open(filename.c_str(), 0); - if (fd != -1) - flock(fd, LOCK_EX); + if (fd == -1) #endif + throw std::runtime_error("Failed to open file " + filename); + + +#if _SQUID_MSWIN_ + if (!LockFile(hFile, 0, 0, 1, 0)) +#else + if (flock(fd, LOCK_EX) != 0) +#endif + throw std::runtime_error("Failed to get a lock of " + filename); } -Ssl::FileLocker::~FileLocker() +void Ssl::Lock::unlock() { #if _SQUID_MSWIN_ if (hFile != INVALID_HANDLE_VALUE) { UnlockFile(hFile, 0, 0, 1, 0); CloseHandle(hFile); + hFile = INVALID_HANDLE_VALUE; } #else if (fd != -1) { flock(fd, LOCK_UN); close(fd); + fd = -1; } #endif + else + throw std::runtime_error("Lock is already unlocked for " + filename); +} + +Ssl::Lock::~Lock() +{ + if (locked()) + unlock(); +} + +Ssl::Locker::Locker(Lock &aLock, const char *aFileName, int aLineNo): + weLocked(false), lock(aLock), fileName(aFileName), lineNo(aLineNo) +{ + if (!lock.locked()) { + lock.lock(); + weLocked = true; + } +} + +Ssl::Locker::~Locker() +{ + if (weLocked) + lock.unlock(); } Ssl::CertificateDb::Row::Row() @@ -130,26 +186,26 @@ db(NULL), max_db_size(aMax_db_size), fs_block_size(aFs_block_size), + dbLock(db_full), + dbSerialLock(serial_full), enabled_disk_store(true) { if (db_path.empty() && !max_db_size) enabled_disk_store = false; else if ((db_path.empty() && max_db_size) || (!db_path.empty() && !max_db_size)) throw std::runtime_error("ssl_crtd is missing the required parameter. There should be -s and -M parameters together."); - else - load(); } bool Ssl::CertificateDb::find(std::string const & host_name, Ssl::X509_Pointer & cert, Ssl::EVP_PKEY_Pointer & pkey) { - FileLocker db_locker(db_full); + const Locker locker(dbLock, Here); load(); return pure_find(host_name, cert, pkey); } bool Ssl::CertificateDb::addCertAndPrivateKey(Ssl::X509_Pointer & cert, Ssl::EVP_PKEY_Pointer & pkey) { - FileLocker db_locker(db_full); + const Locker locker(dbLock, Here); load(); if (!db || !cert || !pkey || min_db_size > max_db_size) return false; @@ -195,7 +251,6 @@ row.reset(); std::string filename(cert_full + "/" + serial_string + ".pem"); - FileLocker cert_locker(filename); if (!writeCertAndPrivateKeyToFile(cert, pkey, filename.c_str())) return false; addSize(filename); @@ -206,7 +261,7 @@ BIGNUM * Ssl::CertificateDb::getCurrentSerialNumber() { - FileLocker serial_locker(serial_full); + const Locker locker(dbSerialLock, Here); // load serial number from file. Ssl::BIO_Pointer file(BIO_new(BIO_s_file())); if (!file) @@ -297,11 +352,12 @@ void Ssl::CertificateDb::check(std::string const & db_path, size_t max_db_size) { CertificateDb db(db_path, max_db_size, 0); + db.load(); } std::string Ssl::CertificateDb::getSNString() const { - FileLocker serial_locker(serial_full); + const Locker locker(dbSerialLock, Here); std::ifstream file(serial_full.c_str()); if (!file) return ""; @@ -329,7 +385,6 @@ // read cert and pkey from file. std::string filename(cert_full + "/" + rrow[cnlSerial] + ".pem"); - FileLocker cert_locker(filename); readCertAndPrivateKeyFromFiles(cert, pkey, filename.c_str(), NULL); if (!cert || !pkey) return false; @@ -338,19 +393,16 @@ size_t Ssl::CertificateDb::size() const { - FileLocker size_locker(size_full); return readSize(); } void Ssl::CertificateDb::addSize(std::string const & filename) { - FileLocker size_locker(size_full); writeSize(readSize() + getFileSize(filename)); } void Ssl::CertificateDb::subSize(std::string const & filename) { - FileLocker size_locker(size_full); writeSize(readSize() - getFileSize(filename)); } @@ -427,6 +479,34 @@ throw std::runtime_error("Failed to write " + db_full + " file"); } +// Normally defined in defines.h file +#define countof(arr) (sizeof(arr)/sizeof(*arr)) +void Ssl::CertificateDb::deleteRow(const char **row, int rowIndex) +{ + const std::string filename(cert_full + "/" + row[cnlSerial] + ".pem"); +#if OPENSSL_VERSION_NUMBER >= 0x1000004fL + sk_OPENSSL_PSTRING_delete(db.get()->data, rowIndex); +#else + sk_delete(db.get()->data, rowIndex); +#endif + + const Columns db_indexes[]={cnlSerial, cnlName}; + for (unsigned int i = 0; i < countof(db_indexes); i++) { +#if OPENSSL_VERSION_NUMBER >= 0x1000004fL + if (LHASH_OF(OPENSSL_STRING) *fieldIndex = db.get()->index[db_indexes[i]]) + lh_OPENSSL_STRING_delete(fieldIndex, (char **)row); +#else + if (LHASH *fieldIndex = db.get()->index[db_indexes[i]]) + lh_delete(fieldIndex, row); +#endif + } + + subSize(filename); + int ret = remove(filename.c_str()); + if (ret < 0) + throw std::runtime_error("Failed to remove certficate file " + filename + " from db"); +} + bool Ssl::CertificateDb::deleteInvalidCertificate() { if (!db) @@ -442,15 +522,7 @@ #endif if (!sslDateIsInTheFuture(current_row[cnlExp_date])) { - std::string filename(cert_full + "/" + current_row[cnlSerial] + ".pem"); - FileLocker cert_locker(filename); -#if OPENSSL_VERSION_NUMBER >= 0x1000004fL - sk_OPENSSL_PSTRING_delete(db.get()->data, i); -#else - sk_delete(db.get()->data, i); -#endif - subSize(filename); - remove(filename.c_str()); + deleteRow(current_row, i); removed_one = true; break; } @@ -478,17 +550,8 @@ #else const char **row = (const char **)sk_value(db.get()->data, 0); #endif - std::string filename(cert_full + "/" + row[cnlSerial] + ".pem"); - FileLocker cert_locker(filename); - -#if OPENSSL_VERSION_NUMBER >= 0x1000004fL - sk_OPENSSL_PSTRING_delete(db.get()->data, 0); -#else - sk_delete(db.get()->data, 0); -#endif - subSize(filename); - remove(filename.c_str()); + deleteRow(row, 0); return true; } @@ -506,15 +569,7 @@ const char ** current_row = ((const char **)sk_value(db.get()->data, i)); #endif if (host == current_row[cnlName]) { - std::string filename(cert_full + "/" + current_row[cnlSerial] + ".pem"); - FileLocker cert_locker(filename); -#if OPENSSL_VERSION_NUMBER >= 0x1000004fL - sk_OPENSSL_PSTRING_delete(db.get()->data, i); -#else - sk_delete(db.get()->data, i); -#endif - subSize(filename); - remove(filename.c_str()); + deleteRow(current_row, i); return true; } } diff -u -r -N squid-3.2.0.12/src/ssl/certificate_db.h squid-3.2.0.13/src/ssl/certificate_db.h --- squid-3.2.0.12/src/ssl/certificate_db.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ssl/certificate_db.h 2011-10-14 14:42:56.000000000 +1300 @@ -16,15 +16,18 @@ namespace Ssl { -/// Cross platform file locker. -class FileLocker +/// maintains an exclusive blocking file-based lock +class Lock { public: - /// Lock file - FileLocker(std::string const & aFilename); - /// Unlock file - ~FileLocker(); + explicit Lock(std::string const &filename); ///< creates an unlocked lock + ~Lock(); ///< releases the lock if it is locked + void lock(); ///< locks the lock, may block + void unlock(); ///< unlocks locked lock or throws + bool locked() const; ///< whether our lock is locked + const char *name() const { return filename.c_str(); } private: + std::string filename; #if _SQUID_MSWIN_ HANDLE hFile; ///< Windows file handle. #else @@ -32,6 +35,24 @@ #endif }; +/// an exception-safe way to obtain and release a lock +class Locker +{ +public: + /// locks the lock if the lock was unlocked + Locker(Lock &lock, const char *aFileName, int lineNo); + /// unlocks the lock if it was locked by us + ~Locker(); +private: + bool weLocked; ///< whether we locked the lock + Lock &lock; ///< the lock we are operating on + const std::string fileName; ///< where the lock was needed + const int lineNo; ///< where the lock was needed +}; + +/// convenience macro to pass source code location to Locker and others +#define Here __FILE__, __LINE__ + /** * Database class for storing SSL certificates and their private keys. * A database consist by: @@ -98,6 +119,7 @@ /// Only find certificate in current db and return it. bool pure_find(std::string const & host_name, Ssl::X509_Pointer & cert, Ssl::EVP_PKEY_Pointer & pkey); + void deleteRow(const char **row, int rowIndex); ///< Delete a row from TXT_DB bool deleteInvalidCertificate(); ///< Delete invalid certificate. bool deleteOldestCertificate(); ///< Delete oldest certificate. bool deleteByHostname(std::string const & host); ///< Delete using host name. @@ -149,6 +171,8 @@ TXT_DB_Pointer db; ///< Database with certificates info. const size_t max_db_size; ///< Max size of db. const size_t fs_block_size; ///< File system block size. + mutable Lock dbLock; ///< protects the database file + mutable Lock dbSerialLock; ///< protects the serial number file bool enabled_disk_store; ///< The storage on the disk is enabled. }; diff -u -r -N squid-3.2.0.12/src/ssl/helper.cc squid-3.2.0.13/src/ssl/helper.cc --- squid-3.2.0.12/src/ssl/helper.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/ssl/helper.cc 2011-10-14 14:42:56.000000000 +1300 @@ -40,7 +40,7 @@ return; ssl_crtd = new helper("ssl_crtd"); - ssl_crtd->childs = Ssl::TheConfig.ssl_crtdChildren; + ssl_crtd->childs.updateLimits(Ssl::TheConfig.ssl_crtdChildren); ssl_crtd->ipc_type = IPC_STREAM; // The crtd messages may contain the eol ('\n') character. We are // going to use the '\1' char as the end-of-message mark. diff -u -r -N squid-3.2.0.12/src/stat.cc squid-3.2.0.13/src/stat.cc --- squid-3.2.0.12/src/stat.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/stat.cc 2011-10-14 14:42:56.000000000 +1300 @@ -548,14 +548,16 @@ stats.request_hit_disk_ratio5 = statRequestHitDiskRatio(5); stats.request_hit_disk_ratio60 = statRequestHitDiskRatio(60); - stats.store_swap_size = store_swap_size; + stats.store_swap_size = Store::Root().currentSize() / 1024.0; stats.store_swap_max_size = Store::Root().maxSize(); stats.store_mem_size = mem_node::StoreMemSize(); stats.store_pages_max = store_pages_max; stats.store_mem_used = mem_node::InUseCount(); - stats.objects_size = n_disk_objects ? (double) store_swap_size / n_disk_objects : 0.0; + stats.n_disk_objects = Store::Root().currentCount(); + stats.objects_size = stats.n_disk_objects > 0 ? + stats.store_swap_size / stats.n_disk_objects : 0.0; stats.unlink_requests = statCounter.unlink.requests; @@ -668,7 +670,6 @@ stats.store_entries = StoreEntry::inUseCount(); stats.store_mem_entries = MemObject::inUseCount(); stats.hot_obj_count = hot_obj_count; - stats.n_disk_objects = n_disk_objects; } void diff -u -r -N squid-3.2.0.12/src/stmem.cc squid-3.2.0.13/src/stmem.cc --- squid-3.2.0.12/src/stmem.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/stmem.cc 2011-10-14 14:42:56.000000000 +1300 @@ -85,6 +85,7 @@ { nodes.destroy(SplayNode::DefaultFree); inmem_hi = 0; + debugs(19, 9, HERE << this << " hi: " << inmem_hi); } bool @@ -144,12 +145,15 @@ memcpy(aNode->nodeBuffer.data + aNode->nodeBuffer.length, source, copyLen); + debugs(19, 9, HERE << this << " hi: " << inmem_hi); if (inmem_hi <= location) inmem_hi = location + copyLen; /* Adjust the ptr and len according to what was deposited in the page */ aNode->nodeBuffer.length += copyLen; + debugs(19, 9, HERE << this << " hi: " << inmem_hi); + debugs(19, 9, HERE << this << " hi: " << endOffset()); return copyLen; } @@ -176,7 +180,7 @@ void mem_hdr::internalAppend(const char *data, int len) { - debugs(19, 6, "memInternalAppend: len " << len); + debugs(19, 6, "memInternalAppend: " << this << " len " << len); while (len > 0) { makeAppendSpace(); @@ -194,6 +198,7 @@ mem_node * mem_hdr::getBlockContainingLocation (int64_t location) const { + // Optimize: do not create a whole mem_node just to store location mem_node target (location); target.nodeBuffer.length = 1; mem_node *const *result = nodes.find (&target, NodeCompare); @@ -245,7 +250,7 @@ { assert(target.range().end > target.range().start); - debugs(19, 6, "memCopy: " << target.range()); + debugs(19, 6, "memCopy: " << this << " " << target.range()); /* we shouldn't ever ask for absent offsets */ @@ -361,7 +366,7 @@ mem_hdr::write (StoreIOBuffer const &writeBuffer) { PROF_start(mem_hdr_write); - debugs(19, 6, "mem_hdr::write: " << writeBuffer.range() << " object end " << endOffset()); + debugs(19, 6, "mem_hdr::write: " << this << " " << writeBuffer.range() << " object end " << endOffset()); if (unionNotEmpty(writeBuffer)) { debugs(19,0,"mem_hdr::write: writeBuffer: " << writeBuffer.range()); @@ -391,7 +396,9 @@ } mem_hdr::mem_hdr() : inmem_hi(0) -{} +{ + debugs(19, 9, HERE << this << " hi: " << inmem_hi); +} mem_hdr::~mem_hdr() { diff -u -r -N squid-3.2.0.12/src/store.cc squid-3.2.0.13/src/store.cc --- squid-3.2.0.12/src/store.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/store.cc 2011-10-14 14:42:56.000000000 +1300 @@ -49,6 +49,7 @@ #include "mem_node.h" #include "StoreMeta.h" #include "SwapDir.h" +#include "StoreIOState.h" #if USE_DELAY_POOLS #include "DelayPools.h" #endif @@ -256,6 +257,16 @@ } + if (fd_table[conn->fd].closing()) { + // Readers must have closing callbacks if they want to be notified. No + // readers appeared to care around 2009/12/14 as they skipped reading + // for other reasons. Closing may already be true at the delyaAwareRead + // call time or may happen while we wait after delayRead() above. + debugs(20, 3, HERE << "wont read from closing " << conn << " for " << + callback); + return; // the read callback will never be called + } + comm_read(conn, buf, amountToRead, callback); } @@ -305,6 +316,13 @@ * offset 0 in the memory object is the HTTP headers. */ + if (mem_status == IN_MEMORY && UsingSmp()) { + // clients of an object cached in shared memory are memory clients + return STORE_MEM_CLIENT; + } + + assert(mem_obj); + if (mem_obj->inmem_lo) return STORE_DISK_CLIENT; @@ -319,6 +337,7 @@ if (mem_obj->inmem_lo == 0 && !isEmpty()) { if (swap_status == SWAPOUT_DONE) { + debugs(20,7, HERE << mem_obj << " lo: " << mem_obj->inmem_lo << " hi: " << mem_obj->endOffset() << " size: " << mem_obj->object_sz); if (mem_obj->endOffset() == mem_obj->object_sz) { /* hot object fully swapped in */ return STORE_MEM_CLIENT; @@ -354,28 +373,43 @@ return STORE_DISK_CLIENT; } -StoreEntry::StoreEntry() +StoreEntry::StoreEntry(): + hidden_mem_obj(NULL), + swap_file_sz(0) { debugs(20, 3, HERE << "new StoreEntry " << this); mem_obj = NULL; expires = lastmod = lastref = timestamp = -1; + swap_status = SWAPOUT_NONE; swap_filen = -1; swap_dirn = -1; } -StoreEntry::StoreEntry(const char *aUrl, const char *aLogUrl) +StoreEntry::StoreEntry(const char *aUrl, const char *aLogUrl): + hidden_mem_obj(NULL), + swap_file_sz(0) { debugs(20, 3, HERE << "new StoreEntry " << this); mem_obj = new MemObject(aUrl, aLogUrl); expires = lastmod = lastref = timestamp = -1; + swap_status = SWAPOUT_NONE; swap_filen = -1; swap_dirn = -1; } +StoreEntry::~StoreEntry() +{ + if (swap_filen >= 0) { + SwapDir &sd = dynamic_cast(*store()); + sd.disconnect(*this); + } + delete hidden_mem_obj; +} + void StoreEntry::destroyMemObject() { @@ -384,6 +418,18 @@ MemObject *mem = mem_obj; mem_obj = NULL; delete mem; + delete hidden_mem_obj; + hidden_mem_obj = NULL; +} + +void +StoreEntry::hideMemObject() +{ + debugs(20, 3, HERE << "hiding " << mem_obj); + assert(mem_obj); + assert(!hidden_mem_obj); + hidden_mem_obj = mem_obj; + mem_obj = NULL; } void @@ -504,22 +550,15 @@ assert(storePendingNClients(this) == 0); - if (EBIT_TEST(flags, RELEASE_REQUEST)) + if (EBIT_TEST(flags, RELEASE_REQUEST)) { this->release(); - else if (keepInMemory()) { - Store::Root().dereference(*this); - setMemStatus(IN_MEMORY); - mem_obj->unlinkRequest(); - } else { - Store::Root().dereference(*this); - - if (EBIT_TEST(flags, KEY_PRIVATE)) - debugs(20, 1, "WARNING: " << __FILE__ << ":" << __LINE__ << ": found KEY_PRIVATE"); - - /* StoreEntry::purgeMem may free e */ - purgeMem(); + return 0; } + if (EBIT_TEST(flags, KEY_PRIVATE)) + debugs(20, 1, "WARNING: " << __FILE__ << ":" << __LINE__ << ": found KEY_PRIVATE"); + + Store::Root().handleIdleEntry(*this); // may delete us return 0; } @@ -687,6 +726,8 @@ } } + // TODO: storeGetPublic() calls below may create unlocked entries. + // We should add/use storeHas() API or lock/unlock those entries. if (mem_obj->vary_headers && !storeGetPublic(mem_obj->url, mem_obj->method)) { /* Create "vary" base object */ String vary; @@ -776,9 +817,6 @@ e->store_status = STORE_PENDING; e->setMemStatus(NOT_IN_MEMORY); - e->swap_status = SWAPOUT_NONE; - e->swap_filen = -1; - e->swap_dirn = -1; e->refcount = 0; e->lastref = squid_curtime; e->timestamp = -1; /* set in StoreEntry::timestampsSet() */ @@ -925,6 +963,8 @@ return 0; } +// TODO: remove checks already performed by swapoutPossible() +// TODO: move "too many open..." checks outside -- we are called too early/late int StoreEntry::checkCachable() { @@ -1081,16 +1121,6 @@ store_status = STORE_OK; - /* - * We assign an object length here. The only other place we assign - * the object length is in storeComplete() - */ - /* RBC: What do we need an object length for? we've just aborted the - * request, the request is private and negatively cached. Surely - * the object length is inappropriate to set. - */ - mem_obj->object_sz = mem_obj->endOffset(); - /* Notify the server side */ /* @@ -1114,8 +1144,8 @@ /* Notify the client side */ invokeHandlers(); - /* Close any swapout file */ - swapOutFileClose(); + // abort swap out, invalidating what was created so far (release follows) + swapOutFileClose(StoreIOState::writerGone); unlock(); /* unlock */ } @@ -1204,10 +1234,11 @@ /* this should be emitted by the oversize dir, not globally */ - if (store_swap_size > Store::Root().maxSize()) { + if (Store::Root().currentSize() > Store::Root().maxSize()) { if (squid_curtime - last_warn_time > 10) { - debugs(20, 0, "WARNING: Disk space over limit: " << store_swap_size << " KB > " - << Store::Root().maxSize() << " KB"); + debugs(20, DBG_CRITICAL, "WARNING: Disk space over limit: " + << Store::Root().currentSize() / 1024.0 << " KB > " + << (Store::Root().maxSize() >> 10) << " KB"); last_warn_time = squid_curtime; } } @@ -1246,31 +1277,23 @@ lock_count++; setReleaseFlag(); LateReleaseStack.push_back(this); - PROF_stop(storeRelease); - return; } else { destroyStoreEntry(static_cast(this)); + // "this" is no longer valid } + + PROF_stop(storeRelease); + return; } storeLog(STORE_LOG_RELEASE, this); if (swap_filen > -1) { - unlink(); - - if (swap_status == SWAPOUT_DONE) - if (EBIT_TEST(flags, ENTRY_VALIDATED)) - store()->updateSize(swap_file_sz, -1); - + // log before unlink() below clears swap_filen if (!EBIT_TEST(flags, KEY_PRIVATE)) storeDirSwapLog(this, SWAP_LOG_DEL); -#if 0 - /* From 2.4. I think we do this in storeUnlink? */ - storeSwapFileNumberSet(this, -1); - -#endif - + unlink(); } setMemStatus(NOT_IN_MEMORY); @@ -1291,7 +1314,7 @@ } for (i = 0; i < 10; i++) { - e = LateReleaseStack.pop(); + e = LateReleaseStack.count ? LateReleaseStack.pop() : NULL; if (e == NULL) { /* done! */ @@ -1406,8 +1429,8 @@ store_pages_max = Config.memMaxSize / sizeof(mem_node); } -int -StoreEntry::keepInMemory() const +bool +StoreEntry::memoryCachable() const { if (mem_obj == NULL) return 0; @@ -1421,6 +1444,14 @@ if (!Config.onoff.memory_cache_first && swap_status == SWAPOUT_DONE && refcount == 1) return 0; + if (UsingSmp()) { + const int64_t expectedSize = mem_obj->expectedReplySize(); + // objects of unknown size are not allowed into memory cache, for now + if (expectedSize < 0 || + expectedSize > static_cast(Config.Store.maxInMemObjSize)) + return 0; + } + return 1; } @@ -1596,6 +1627,15 @@ if (new_status == mem_status) return; + if (UsingSmp()) { + assert(new_status != IN_MEMORY); // we do not call this otherwise + // This method was designed to update replacement policy, not to + // actually purge something from the memory cache (TODO: rename?). + // Shared memory cache does not have a policy that needs updates. + mem_status = new_status; + return; + } + assert(mem_obj != NULL); if (new_status == IN_MEMORY) { @@ -1605,10 +1645,10 @@ debugs(20, 4, "StoreEntry::setMemStatus: not inserting special " << mem_obj->url << " into policy"); } else { mem_policy->Add(mem_policy, this, &mem_obj->repl); - debugs(20, 4, "StoreEntry::setMemStatus: inserted mem node " << mem_obj->url); + debugs(20, 4, "StoreEntry::setMemStatus: inserted mem node " << mem_obj->url << " key: " << getMD5Text()); } - hot_obj_count++; + hot_obj_count++; // TODO: maintain for the shared hot cache as well } else { if (EBIT_TEST(flags, ENTRY_SPECIAL)) { debugs(20, 4, "StoreEntry::setMemStatus: special entry " << mem_obj->url); @@ -1640,6 +1680,14 @@ if (mem_obj) return; + if (hidden_mem_obj) { + debugs(20, 3, HERE << "restoring " << hidden_mem_obj); + mem_obj = hidden_mem_obj; + hidden_mem_obj = NULL; + mem_obj->resetUrls(aUrl, aLogUrl); + return; + } + mem_obj = new MemObject(aUrl, aLogUrl); } @@ -1781,10 +1829,9 @@ * a new reply. This eats the reply. */ void -StoreEntry::replaceHttpReply(HttpReply *rep) +StoreEntry::replaceHttpReply(HttpReply *rep, bool andStartWriting) { debugs(20, 3, "StoreEntry::replaceHttpReply: " << url()); - Packer p; if (!mem_obj) { debugs(20, 0, "Attempt to replace object with no in-memory representation"); @@ -1793,18 +1840,31 @@ mem_obj->replaceHttpReply(rep); + if (andStartWriting) + startWriting(); +} + + +void +StoreEntry::startWriting() +{ + Packer p; + /* TODO: when we store headers serparately remove the header portion */ /* TODO: mark the length of the headers ? */ /* We ONLY want the headers */ packerToStoreInit(&p, this); assert (isEmpty()); + assert(mem_obj); - getReply()->packHeadersInto(&p); + const HttpReply *rep = getReply(); + assert(rep); - rep->hdr_sz = mem_obj->endOffset(); + rep->packHeadersInto(&p); + mem_obj->markEndOfReplyHeaders(); - httpBodyPackInto(&getReply()->body, &p); + httpBodyPackInto(&rep->body, &p); packerClean(&p); } @@ -1825,21 +1885,87 @@ bool StoreEntry::swapoutPossible() { + if (!Config.cacheSwap.n_configured) + return false; + /* should we swap something out to disk? */ debugs(20, 7, "storeSwapOut: " << url()); debugs(20, 7, "storeSwapOut: store_status = " << storeStatusStr[store_status]); + assert(mem_obj); + MemObject::SwapOut::Decision &decision = mem_obj->swapout.decision; + + // if we decided that swapout is not possible, do not repeat same checks + if (decision == MemObject::SwapOut::swImpossible) { + debugs(20, 3, "storeSwapOut: already rejected"); + return false; + } + + // this flag may change so we must check it even if we already said "yes" if (EBIT_TEST(flags, ENTRY_ABORTED)) { assert(EBIT_TEST(flags, RELEASE_REQUEST)); - swapOutFileClose(); + // StoreEntry::abort() already closed the swap out file, if any + decision = MemObject::SwapOut::swImpossible; + return false; + } + + // if we decided that swapout is possible, do not repeat same checks + if (decision == MemObject::SwapOut::swPossible) { + debugs(20, 3, "storeSwapOut: already allowed"); + return true; + } + + // if we are swapping out already, do not repeat same checks + if (swap_status != SWAPOUT_NONE) { + debugs(20, 3, "storeSwapOut: already started"); + decision = MemObject::SwapOut::swPossible; + return true; + } + + if (!checkCachable()) { + debugs(20, 3, "storeSwapOut: not cachable"); + decision = MemObject::SwapOut::swImpossible; return false; } if (EBIT_TEST(flags, ENTRY_SPECIAL)) { debugs(20, 3, "storeSwapOut: " << url() << " SPECIAL"); + decision = MemObject::SwapOut::swImpossible; return false; } + // check cache_dir max-size limit if all cache_dirs have it + if (store_maxobjsize >= 0) { + // TODO: add estimated store metadata size to be conservative + + // use guaranteed maximum if it is known + const int64_t expectedEnd = mem_obj->expectedReplySize(); + debugs(20, 7, "storeSwapOut: expectedEnd = " << expectedEnd); + if (expectedEnd > store_maxobjsize) { + debugs(20, 3, "storeSwapOut: will not fit: " << expectedEnd << + " > " << store_maxobjsize); + decision = MemObject::SwapOut::swImpossible; + return false; // known to outgrow the limit eventually + } + + // use current minimum (always known) + const int64_t currentEnd = mem_obj->endOffset(); + if (currentEnd > store_maxobjsize) { + debugs(20, 3, "storeSwapOut: does not fit: " << currentEnd << + " > " << store_maxobjsize); + decision = MemObject::SwapOut::swImpossible; + return false; // already does not fit and may only get bigger + } + + // prevent default swPossible answer for yet unknown length + if (expectedEnd < 0) { + debugs(20, 3, "storeSwapOut: wait for more info: " << + store_maxobjsize); + return false; // may fit later, but will be rejected now + } + } + + decision = MemObject::SwapOut::swPossible; return true; } @@ -1956,7 +2082,7 @@ return matched; } -StorePointer +SwapDir::Pointer StoreEntry::store() const { assert(0 <= swap_dirn && swap_dirn < Config.cacheSwap.n_configured); @@ -1966,7 +2092,10 @@ void StoreEntry::unlink() { - store()->unlink(*this); + store()->unlink(*this); // implies disconnect() + swap_filen = -1; + swap_dirn = -1; + swap_status = SWAPOUT_NONE; } /* @@ -1985,6 +2114,13 @@ return true; } +std::ostream &operator <<(std::ostream &os, const StoreEntry &e) +{ + return os << e.swap_filen << '@' << e.swap_dirn << '=' << + e.mem_status << '/' << e.ping_status << '/' << e.store_status << '/' << + e.swap_status; +} + /* NullStoreEntry */ NullStoreEntry NullStoreEntry::_instance; diff -u -r -N squid-3.2.0.12/src/store_client.cc squid-3.2.0.13/src/store_client.cc --- squid-3.2.0.12/src/store_client.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/store_client.cc 2011-10-14 14:42:56.000000000 +1300 @@ -591,9 +591,14 @@ storeSwapTLVFree(tlv_list); + assert(swap_hdr_sz >= 0); + assert(entry->swap_file_sz > 0); + assert(entry->swap_file_sz >= static_cast(swap_hdr_sz)); entry->mem_obj->swap_hdr_sz = swap_hdr_sz; entry->mem_obj->object_sz = entry->swap_file_sz - swap_hdr_sz; - + debugs(90, 5, "store_client::unpackHeader: swap_file_sz=" << + entry->swap_file_sz << "( " << swap_hdr_sz << " + " << + entry->mem_obj->object_sz << ")"); } void @@ -696,7 +701,7 @@ e->swapOut(); if (sc->swapin_sio != NULL) { - storeClose(sc->swapin_sio); + storeClose(sc->swapin_sio, StoreIOState::readerDone); sc->swapin_sio = NULL; statCounter.swap.ins++; } diff -u -r -N squid-3.2.0.12/src/store_digest.cc squid-3.2.0.13/src/store_digest.cc --- squid-3.2.0.12/src/store_digest.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/store_digest.cc 2011-10-14 14:42:56.000000000 +1300 @@ -507,7 +507,7 @@ * number of _entries_ we want to pre-allocate for. */ const int hi_cap = Store::Root().maxSize() / Config.Store.avgObjectSize; - const int lo_cap = 1 + store_swap_size / Config.Store.avgObjectSize; + const int lo_cap = 1 + Store::Root().currentSize() / Config.Store.avgObjectSize; const int e_count = StoreEntry::inUseCount(); int cap = e_count ? e_count :hi_cap; debugs(71, 2, "storeDigestCalcCap: have: " << e_count << ", want " << cap << diff -u -r -N squid-3.2.0.12/src/store_dir.cc squid-3.2.0.13/src/store_dir.cc --- squid-3.2.0.12/src/store_dir.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/store_dir.cc 2011-10-14 14:42:56.000000000 +1300 @@ -36,6 +36,8 @@ #include "squid.h" #include "Store.h" #include "MemObject.h" +#include "MemStore.h" +#include "mem_node.h" #include "SquidMath.h" #include "SquidTime.h" #include "SwapDir.h" @@ -73,10 +75,13 @@ int StoreController::store_dirs_rebuilding = 1; StoreController::StoreController() : swapDir (new StoreHashIndex()) + , memStore(NULL) {} StoreController::~StoreController() -{} +{ + delete memStore; +} /* * This function pointer is set according to 'store_dir_select_algorithm' @@ -87,6 +92,11 @@ void StoreController::init() { + if (Config.memShared && IamWorkerProcess()) { + memStore = new MemStore; + memStore->init(); + } + swapDir->init(); if (0 == strcasecmp(Config.store_dir_select_algorithm, "round-robin")) { @@ -189,28 +199,20 @@ int load; RefCount sd; - ssize_t objsize = e->objectLen(); + // e->objectLen() is negative at this point when we are still STORE_PENDING + ssize_t objsize = e->mem_obj->expectedReplySize(); if (objsize != -1) objsize += e->mem_obj->swap_hdr_sz; - for (i = 0; i <= Config.cacheSwap.n_configured; i++) { + for (i = 0; i < Config.cacheSwap.n_configured; i++) { if (++dirn >= Config.cacheSwap.n_configured) dirn = 0; sd = dynamic_cast(INDEXSD(dirn)); - if (sd->flags.read_only) - continue; - - if (sd->cur_size > sd->max_size) + if (!sd->canStore(*e, objsize, load)) continue; - if (!sd->objectSizeIsAcceptable(objsize)) - continue; - - /* check for error or overload condition */ - load = sd->canStore(*e); - if (load < 0 || load > 1000) { continue; } @@ -237,8 +239,7 @@ static int storeDirSelectSwapDirLeastLoad(const StoreEntry * e) { - ssize_t objsize; - ssize_t most_free = 0, cur_free; + int64_t most_free = 0; ssize_t least_objsize = -1; int least_load = INT_MAX; int load; @@ -246,8 +247,8 @@ int i; RefCount SD; - /* Calculate the object size */ - objsize = e->objectLen(); + // e->objectLen() is negative at this point when we are still STORE_PENDING + ssize_t objsize = e->mem_obj->expectedReplySize(); if (objsize != -1) objsize += e->mem_obj->swap_hdr_sz; @@ -255,25 +256,17 @@ for (i = 0; i < Config.cacheSwap.n_configured; i++) { SD = dynamic_cast(INDEXSD(i)); SD->flags.selected = 0; - load = SD->canStore(*e); - - if (load < 0 || load > 1000) { - continue; - } - if (!SD->objectSizeIsAcceptable(objsize)) + if (!SD->canStore(*e, objsize, load)) continue; - if (SD->flags.read_only) - continue; - - if (SD->cur_size > SD->max_size) + if (load < 0 || load > 1000) continue; if (load > least_load) continue; - cur_free = SD->max_size - SD->cur_size; + const int64_t cur_free = SD->maxSize() - SD->currentSize(); /* If the load is equal, then look in more details */ if (load == least_load) { @@ -334,39 +327,21 @@ } void -StoreController::updateSize(int64_t size, int sign) -{ - fatal("StoreController has no independent size\n"); -} - -void -SwapDir::updateSize(int64_t size, int sign) -{ - int64_t blks = (size + fs.blksize - 1) / fs.blksize; - int64_t k = ((blks * fs.blksize) >> 10) * sign; - cur_size += k; - store_swap_size += k; - - if (sign > 0) - n_disk_objects++; - else if (sign < 0) - n_disk_objects--; -} - -void StoreController::stat(StoreEntry &output) const { storeAppendPrintf(&output, "Store Directory Statistics:\n"); storeAppendPrintf(&output, "Store Entries : %lu\n", (unsigned long int)StoreEntry::inUseCount()); storeAppendPrintf(&output, "Maximum Swap Size : %"PRIu64" KB\n", - maxSize()); - storeAppendPrintf(&output, "Current Store Swap Size: %8lu KB\n", - store_swap_size); - storeAppendPrintf(&output, "Current Capacity : %"PRId64"%% used, %"PRId64"%% free\n", - Math::int64Percent(store_swap_size, maxSize()), - Math::int64Percent((maxSize() - store_swap_size), maxSize())); - /* FIXME Here we should output memory statistics */ + maxSize() >> 10); + storeAppendPrintf(&output, "Current Store Swap Size: %.2f KB\n", + currentSize() / 1024.0); + storeAppendPrintf(&output, "Current Capacity : %.2f%% used, %.2f%% free\n", + Math::doublePercent(currentSize(), maxSize()), + Math::doublePercent((maxSize() - currentSize()), maxSize())); + + if (memStore) + memStore->stat(output); /* now the swapDir */ swapDir->stat(output); @@ -387,15 +362,33 @@ return swapDir->minSize(); } +uint64_t +StoreController::currentSize() const +{ + return swapDir->currentSize(); +} + +uint64_t +StoreController::currentCount() const +{ + return swapDir->currentCount(); +} + +int64_t +StoreController::maxObjectSize() const +{ + return swapDir->maxObjectSize(); +} + void SwapDir::diskFull() { - if (cur_size >= max_size) + if (currentSize() >= maxSize()) return; - max_size = cur_size; + max_size = currentSize(); - debugs(20, 1, "WARNING: Shrinking cache_dir #" << index << " to " << cur_size << " KB"); + debugs(20, 1, "WARNING: Shrinking cache_dir #" << index << " to " << currentSize() / 1024.0 << " KB"); } void @@ -518,10 +511,19 @@ return INDEXSD(x); } +SwapDir & +StoreHashIndex::dir(const int i) const +{ + SwapDir *sd = dynamic_cast(INDEXSD(i)); + assert(sd); + return *sd; +} + void StoreController::sync(void) { - /* sync mem cache? */ + if (memStore) + memStore->sync(); swapDir->sync(); } @@ -620,13 +622,12 @@ { if (swap->swapDirs == NULL) { swap->n_allocated = 4; - swap->swapDirs = static_cast(xcalloc(swap->n_allocated, sizeof(StorePointer))); + swap->swapDirs = static_cast(xcalloc(swap->n_allocated, sizeof(SwapDir::Pointer))); } if (swap->n_allocated == swap->n_configured) { - StorePointer *tmp; swap->n_allocated <<= 1; - tmp = static_cast(xcalloc(swap->n_allocated, sizeof(StorePointer))); + SwapDir::Pointer *const tmp = static_cast(xcalloc(swap->n_allocated, sizeof(SwapDir::Pointer))); memcpy(tmp, swap->swapDirs, swap->n_configured * sizeof(SwapDir *)); xfree(swap->swapDirs); swap->swapDirs = tmp; @@ -667,35 +668,83 @@ /* Notify the fs that we're referencing this object again */ if (e.swap_dirn > -1) - e.store()->reference(e); + swapDir->reference(e); + + // Notify the memory cache that we're referencing this object again + if (memStore && e.mem_status == IN_MEMORY) + memStore->reference(e); - /* Notify the memory cache that we're referencing this object again */ + // TODO: move this code to a non-shared memory cache class when we have it if (e.mem_obj) { if (mem_policy->Referenced) mem_policy->Referenced(mem_policy, &e, &e.mem_obj->repl); } } -void +bool StoreController::dereference(StoreEntry & e) { + bool keepInStoreTable = true; // keep if there are no objections + /* Notify the fs that we're not referencing this object any more */ if (e.swap_filen > -1) - e.store()->dereference(e); + keepInStoreTable = swapDir->dereference(e) && keepInStoreTable; - /* Notify the memory cache that we're not referencing this object any more */ + // Notify the memory cache that we're not referencing this object any more + if (memStore && e.mem_status == IN_MEMORY) + keepInStoreTable = memStore->dereference(e) && keepInStoreTable; + + // TODO: move this code to a non-shared memory cache class when we have it if (e.mem_obj) { if (mem_policy->Dereferenced) mem_policy->Dereferenced(mem_policy, &e, &e.mem_obj->repl); } + + return keepInStoreTable; } StoreEntry * StoreController::get(const cache_key *key) { + if (StoreEntry *e = swapDir->get(key)) { + // TODO: ignore and maybe handleIdleEntry() unlocked intransit entries + // because their backing store slot may be gone already. + debugs(20, 3, HERE << "got in-transit entry: " << *e); + return e; + } + + if (memStore) { + if (StoreEntry *e = memStore->get(key)) { + debugs(20, 3, HERE << "got mem-cached entry: " << *e); + return e; + } + } + + // TODO: this disk iteration is misplaced; move to StoreHashIndex when + // the global store_table is no longer used for in-transit objects. + if (const int cacheDirs = Config.cacheSwap.n_configured) { + // ask each cache_dir until the entry is found; use static starting + // point to avoid asking the same subset of disks more often + // TODO: coordinate with put() to be able to guess the right disk often + static int idx = 0; + for (int n = 0; n < cacheDirs; ++n) { + idx = (idx + 1) % cacheDirs; + SwapDir *sd = dynamic_cast(INDEXSD(idx)); + if (!sd->active()) + continue; + + if (StoreEntry *e = sd->get(key)) { + debugs(20, 3, HERE << "cache_dir " << idx << + " got cached entry: " << *e); + return e; + } + } + } - return swapDir->get(key); + debugs(20, 4, HERE << "none of " << Config.cacheSwap.n_configured << + " cache_dirs have " << storeKeyText(key)); + return NULL; } void @@ -704,6 +753,36 @@ fatal("not implemented"); } +void +StoreController::handleIdleEntry(StoreEntry &e) +{ + bool keepInLocalMemory = false; + if (memStore) { + memStore->considerKeeping(e); + // leave keepInLocalMemory false; memStore maintains its own cache + } else { + keepInLocalMemory = e.memoryCachable() && // entry is in good shape and + // the local memory cache is not overflowing + (mem_node::InUseCount() <= store_pages_max); + } + + // An idle, unlocked entry that belongs to a SwapDir which controls + // its own index, should not stay in the global store_table. + if (!dereference(e)) { + debugs(20, 5, HERE << "destroying unlocked entry: " << &e << ' ' << e); + destroyStoreEntry(static_cast(&e)); + return; + } + + // TODO: move this into [non-shared] memory cache class when we have one + if (keepInLocalMemory) { + e.setMemStatus(IN_MEMORY); + e.mem_obj->unlinkRequest(); + } else { + e.purgeMem(); // may free e + } +} + StoreHashIndex::StoreHashIndex() { if (store_table) @@ -755,8 +834,10 @@ void StoreHashIndex::create() { - for (int i = 0; i < Config.cacheSwap.n_configured; i++) - store(i)->create(); + for (int i = 0; i < Config.cacheSwap.n_configured; i++) { + if (dir(i).active()) + store(i)->create(); + } } /* Lookup an object in the cache. @@ -783,8 +864,8 @@ /* Calculate size of hash table (maximum currently 64k buckets). */ /* this is very bogus, its specific to the any Store maintaining an * in-core index, not global */ - size_t buckets = (Store::Root().maxSize() + ( Config.memMaxSize >> 10)) / Config.Store.avgObjectSize; - debugs(20, 1, "Swap maxSize " << Store::Root().maxSize() << + size_t buckets = (Store::Root().maxSize() + Config.memMaxSize) / Config.Store.avgObjectSize; + debugs(20, 1, "Swap maxSize " << (Store::Root().maxSize() >> 10) << " + " << ( Config.memMaxSize >> 10) << " KB, estimated " << buckets << " objects"); buckets /= Config.Store.objectsPerBucket; debugs(20, 1, "Target number of buckets: " << buckets); @@ -792,8 +873,9 @@ * moment it remains at approximately 24 hours. */ store_hash_buckets = storeKeyHashBuckets(buckets); debugs(20, 1, "Using " << store_hash_buckets << " Store buckets"); - debugs(20, 1, "Max Mem size: " << ( Config.memMaxSize >> 10) << " KB"); - debugs(20, 1, "Max Swap size: " << Store::Root().maxSize() << " KB"); + debugs(20, 1, "Max Mem size: " << ( Config.memMaxSize >> 10) << " KB" << + (Config.memShared ? " [shared]" : "")); + debugs(20, 1, "Max Swap size: " << (Store::Root().maxSize() >> 10) << " KB"); store_table = hash_create(storeKeyHashCmp, store_hash_buckets, storeKeyHashHash); @@ -813,7 +895,8 @@ * above * Step 3: have the hash index walk the searches itself. */ - store(i)->init(); + if (dir(i).active()) + store(i)->init(); } } @@ -822,8 +905,10 @@ { uint64_t result = 0; - for (int i = 0; i < Config.cacheSwap.n_configured; i++) - result += store(i)->maxSize(); + for (int i = 0; i < Config.cacheSwap.n_configured; i++) { + if (dir(i).doReportStat()) + result += store(i)->maxSize(); + } return result; } @@ -833,8 +918,49 @@ { uint64_t result = 0; - for (int i = 0; i < Config.cacheSwap.n_configured; i++) - result += store(i)->minSize(); + for (int i = 0; i < Config.cacheSwap.n_configured; i++) { + if (dir(i).doReportStat()) + result += store(i)->minSize(); + } + + return result; +} + +uint64_t +StoreHashIndex::currentSize() const +{ + uint64_t result = 0; + + for (int i = 0; i < Config.cacheSwap.n_configured; i++) { + if (dir(i).doReportStat()) + result += store(i)->currentSize(); + } + + return result; +} + +uint64_t +StoreHashIndex::currentCount() const +{ + uint64_t result = 0; + + for (int i = 0; i < Config.cacheSwap.n_configured; i++) { + if (dir(i).doReportStat()) + result += store(i)->currentCount(); + } + + return result; +} + +int64_t +StoreHashIndex::maxObjectSize() const +{ + int64_t result = -1; + + for (int i = 0; i < Config.cacheSwap.n_configured; i++) { + if (dir(i).active() && store(i)->maxObjectSize() > result) + result = store(i)->maxObjectSize(); + } return result; } @@ -853,12 +979,16 @@ } void -StoreHashIndex::reference(StoreEntry&) -{} +StoreHashIndex::reference(StoreEntry &e) +{ + e.store()->reference(e); +} -void -StoreHashIndex::dereference(StoreEntry&) -{} +bool +StoreHashIndex::dereference(StoreEntry &e) +{ + return e.store()->dereference(e); +} void StoreHashIndex::maintain() @@ -876,10 +1006,6 @@ } void -StoreHashIndex::updateSize(int64_t, int) -{} - -void StoreHashIndex::sync() { for (int i = 0; i < Config.cacheSwap.n_configured; ++i) diff -u -r -N squid-3.2.0.12/src/Store.h squid-3.2.0.13/src/Store.h --- squid-3.2.0.12/src/Store.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/Store.h 2011-10-14 14:42:56.000000000 +1300 @@ -58,8 +58,8 @@ class AsyncCall; class StoreClient; class MemObject; -class Store; class StoreSearch; +class SwapDir; typedef struct { @@ -73,6 +73,9 @@ extern StoreIoStats store_io_stats; +/// maximum number of entries per cache_dir +enum { SwapFilenMax = 0xFFFFFF }; // keep in sync with StoreEntry::swap_filen + /** \ingroup StoreAPI */ @@ -86,7 +89,7 @@ virtual const char *getMD5Text() const; StoreEntry(); StoreEntry(const char *url, const char *log_url); - virtual ~StoreEntry() {} + virtual ~StoreEntry(); virtual HttpReply const *getReply() const; virtual void write (StoreIOBuffer); @@ -96,7 +99,8 @@ virtual void complete(); virtual store_client_t storeClientType() const; virtual char const *getSerialisedMetaData(); - virtual void replaceHttpReply(HttpReply *); + void replaceHttpReply(HttpReply *, bool andStartWriting = true); + void startWriting(); ///< pack and write reply headers and, maybe, body virtual bool swapoutPossible(); virtual void trimMemory(); void abort(); @@ -111,16 +115,18 @@ void cacheNegatively(); /** \todo argh, why both? */ void invokeHandlers(); void purgeMem(); + void cacheInMemory(); ///< start or continue storing in memory cache void swapOut(); bool swapOutAble() const; - void swapOutFileClose(); + void swapOutFileClose(int how); const char *url() const; int checkCachable(); int checkNegativeHit() const; int locked() const; int validToSend() const; - int keepInMemory() const; + bool memoryCachable() const; ///< may be cached in memory void createMemObject(const char *, const char *); + void hideMemObject(); ///< no mem_obj for callers until createMemObject void dump(int debug_lvl) const; void hashDelete(); void hashInsert(const cache_key *); @@ -142,9 +148,10 @@ bool hasIfNoneMatchEtag(const HttpRequest &request) const; /** What store does this entry belong too ? */ - virtual RefCount store() const; + virtual RefCount store() const; MemObject *mem_obj; + MemObject *hidden_mem_obj; ///< mem_obj created before URLs were known RemovalPolicyNode repl; /* START OF ON-DISK STORE_META_STD TLV field */ time_t timestamp; @@ -156,7 +163,8 @@ uint16_t flags; /* END OF ON-DISK STORE_META_STD */ - sfileno swap_filen:25; + /// unique ID inside a cache_dir for swapped out entries; -1 for others + sfileno swap_filen:25; // keep in sync with SwapFilenMax sdirno swap_dirn:7; @@ -209,6 +217,8 @@ bool hasOneOfEtags(const String &reqETags, const bool allowWeakMatch) const; }; +std::ostream &operator <<(std::ostream &os, const StoreEntry &e); + /// \ingroup StoreAPI class NullStoreEntry:public StoreEntry { @@ -296,6 +306,15 @@ /** The minimum size the store will shrink to via normal housekeeping */ virtual uint64_t minSize() const = 0; + /** current store size */ + virtual uint64_t currentSize() const = 0; + + /** the total number of objects stored */ + virtual uint64_t currentCount() const = 0; + + /** the maximum object size that can be stored, -1 if unlimited */ + virtual int64_t maxObjectSize() const = 0; + /** * Output stats to the provided store entry. \todo make these calls asynchronous @@ -314,12 +333,15 @@ /* pulled up from SwapDir for migration.... probably do not belong here */ virtual void reference(StoreEntry &) = 0; /* Reference this object */ - virtual void dereference(StoreEntry &) = 0; /* Unreference this object */ + /// Undo reference(), returning false iff idle e should be destroyed + virtual bool dereference(StoreEntry &e) = 0; virtual void maintain() = 0; /* perform regular maintenance should be private and self registered ... */ - /* These should really be private */ - virtual void updateSize(int64_t size, int sign) = 0; + // XXX: This method belongs to Store::Root/StoreController, but it is here + // because test cases use non-StoreController derivatives as Root + /// called when the entry is no longer needed by any transaction + virtual void handleIdleEntry(StoreEntry &e) {} private: static RefCount CurrentRoot; diff -u -r -N squid-3.2.0.12/src/StoreHashIndex.h squid-3.2.0.13/src/StoreHashIndex.h --- squid-3.2.0.12/src/StoreHashIndex.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/StoreHashIndex.h 2011-10-14 14:42:56.000000000 +1300 @@ -67,21 +67,26 @@ virtual uint64_t minSize() const; + virtual uint64_t currentSize() const; + + virtual uint64_t currentCount() const; + + virtual int64_t maxObjectSize() const; + virtual void stat(StoreEntry&) const; virtual void reference(StoreEntry&); - virtual void dereference(StoreEntry&); + virtual bool dereference(StoreEntry&); virtual void maintain(); - virtual void updateSize(int64_t, int); - virtual StoreSearch *search(String const url, HttpRequest *); private: /* migration logic */ StorePointer store(int const x) const; + SwapDir &dir(int const idx) const; }; class StoreHashIndexEntry : public StoreEntry diff -u -r -N squid-3.2.0.12/src/store_io.cc squid-3.2.0.13/src/store_io.cc --- squid-3.2.0.12/src/store_io.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/store_io.cc 2011-10-14 14:42:56.000000000 +1300 @@ -15,31 +15,23 @@ storeCreate(StoreEntry * e, StoreIOState::STFNCB * file_callback, StoreIOState::STIOCB * close_callback, void *callback_data) { assert (e); - ssize_t objsize; - sdirno dirn; - RefCount SD; store_io_stats.create.calls++; - /* This is just done for logging purposes */ - objsize = e->objectLen(); - - if (objsize != -1) - objsize += e->mem_obj->swap_hdr_sz; /* * Pick the swapdir * We assume that the header has been packed by now .. */ - dirn = storeDirSelectSwapDir(e); + const sdirno dirn = storeDirSelectSwapDir(e); if (dirn == -1) { - debugs(20, 2, "storeCreate: no valid swapdirs for this object"); + debugs(20, 2, "storeCreate: no swapdirs for " << *e); store_io_stats.create.select_fail++; return NULL; } - debugs(20, 2, "storeCreate: Selected dir '" << dirn << "' for obj size '" << objsize << "'"); - SD = dynamic_cast(INDEXSD(dirn)); + debugs(20, 2, "storeCreate: Selected dir " << dirn << " for " << *e); + SwapDir *SD = dynamic_cast(INDEXSD(dirn)); /* Now that we have a fs to use, call its storeCreate function */ StoreIOState::Pointer sio = SD->createStoreIO(*e, file_callback, close_callback, callback_data); @@ -63,7 +55,7 @@ } void -storeClose(StoreIOState::Pointer sio) +storeClose(StoreIOState::Pointer sio, int how) { if (sio->flags.closing) { debugs(20,3,HERE << "storeClose: flags.closing already set, bailing"); @@ -72,8 +64,8 @@ sio->flags.closing = 1; - debugs(20,3,HERE << "storeClose: calling sio->close()"); - sio->close(); + debugs(20,3,HERE << "storeClose: calling sio->close(" << how << ")"); + sio->close(how); } void diff -u -r -N squid-3.2.0.12/src/StoreIOState.h squid-3.2.0.13/src/StoreIOState.h --- squid-3.2.0.12/src/StoreIOState.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/StoreIOState.h 2011-10-14 14:42:56.000000000 +1300 @@ -84,13 +84,19 @@ virtual void read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data) = 0; virtual void write(char const *buf, size_t size, off_t offset, FREE * free_func) = 0; - virtual void close() = 0; + + typedef enum { + wroteAll, ///< success: caller supplied all data it wanted to swap out + writerGone, ///< failure: caller left before swapping out everything + readerDone ///< success or failure: either way, stop swapping in + } CloseHow; + virtual void close(int how) = 0; ///< finish or abort swapping per CloseHow sdirno swap_dirn; sfileno swap_filen; StoreEntry *e; /* Need this so the FS layers can play god */ mode_t mode; - off_t offset_; /* current on-disk offset pointer */ + off_t offset_; ///< number of bytes written or read for this entry so far STFNCB *file_callback; /* called on delayed sfileno assignments */ STIOCB *callback; void *callback_data; @@ -107,7 +113,7 @@ StoreIOState::Pointer storeCreate(StoreEntry *, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *); StoreIOState::Pointer storeOpen(StoreEntry *, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *); -SQUIDCEXTERN void storeClose(StoreIOState::Pointer); +SQUIDCEXTERN void storeClose(StoreIOState::Pointer, int how); SQUIDCEXTERN void storeRead(StoreIOState::Pointer, char *, size_t, off_t, StoreIOState::STRCB *, void *); SQUIDCEXTERN void storeIOWrite(StoreIOState::Pointer, char const *, size_t, off_t, FREE *); diff -u -r -N squid-3.2.0.12/src/StoreMetaUnpacker.cc squid-3.2.0.13/src/StoreMetaUnpacker.cc --- squid-3.2.0.12/src/StoreMetaUnpacker.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/StoreMetaUnpacker.cc 2011-10-14 14:42:56.000000000 +1300 @@ -39,6 +39,24 @@ int const StoreMetaUnpacker::MinimumBufferLength = sizeof(char) + sizeof(int); +/// useful for meta stored in pre-initialized (with zeros) db files +bool +StoreMetaUnpacker::isBufferZero() +{ + // We could memcmp the entire buffer, but it is probably safe enough + // to test a few bytes because if we do not detect a corrupted entry + // it is not a big deal. Empty entries are not isBufferSane anyway. + const int depth = 10; + if (buflen < depth) + return false; // cannot be sure enough + + for (int i = 0; i < depth; ++i) { + if (buf[i]) + return false; + } + return true; +} + bool StoreMetaUnpacker::isBufferSane() { diff -u -r -N squid-3.2.0.12/src/StoreMetaUnpacker.h squid-3.2.0.13/src/StoreMetaUnpacker.h --- squid-3.2.0.12/src/StoreMetaUnpacker.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/StoreMetaUnpacker.h 2011-10-14 14:42:56.000000000 +1300 @@ -41,6 +41,7 @@ public: StoreMetaUnpacker (const char *buf, ssize_t bufferLength, int *hdrlen); StoreMeta *createStoreMeta(); + bool isBufferZero(); ///< all-zeros buffer, implies !isBufferSane bool isBufferSane(); private: diff -u -r -N squid-3.2.0.12/src/store_rebuild.cc squid-3.2.0.13/src/store_rebuild.cc --- squid-3.2.0.12/src/store_rebuild.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/store_rebuild.cc 2011-10-14 14:42:56.000000000 +1300 @@ -74,7 +74,6 @@ size_t statCount = 500; while (statCount-- && !currentSearch->isDone() && currentSearch->next()) { - ++validated; StoreEntry *e; e = currentSearch->currentItem(); @@ -99,7 +98,6 @@ * Only set the file bit if we know its a valid entry * otherwise, set it in the validation procedure */ - e->store()->updateSize(e->swap_file_sz, 1); if ((++validated & 0x3FFFF) == 0) /* TODO format the int with with a stream operator */ @@ -109,7 +107,7 @@ if (currentSearch->isDone()) { debugs(20, 1, " Completed Validation Procedure"); debugs(20, 1, " Validated " << validated << " Entries"); - debugs(20, 1, " store_swap_size = " << store_swap_size); + debugs(20, 1, " store_swap_size = " << Store::Root().currentSize() / 1024.0 << " KB"); StoreController::store_dirs_rebuilding--; assert(0 == StoreController::store_dirs_rebuilding); @@ -231,3 +229,188 @@ debugs(20, 1, "Store rebuilding is "<< std::setw(4)<< std::setprecision(2) << 100.0 * n / d << "% complete"); last_report = squid_curtime; } + +#include "fde.h" +#include "StoreMetaUnpacker.h" +#include "StoreMeta.h" +#include "Generic.h" + +struct InitStoreEntry : public unary_function { + InitStoreEntry(StoreEntry *anEntry, cache_key *aKey):what(anEntry),index(aKey) {} + + void operator()(StoreMeta const &x) { + switch (x.getType()) { + + case STORE_META_KEY: + assert(x.length == SQUID_MD5_DIGEST_LENGTH); + memcpy(index, x.value, SQUID_MD5_DIGEST_LENGTH); + break; + + case STORE_META_STD: + struct old_metahdr { + time_t timestamp; + time_t lastref; + time_t expires; + time_t lastmod; + size_t swap_file_sz; + uint16_t refcount; + uint16_t flags; + } *tmp; + tmp = (struct old_metahdr *)x.value; + assert(x.length == STORE_HDR_METASIZE_OLD); + what->timestamp = tmp->timestamp; + what->lastref = tmp->lastref; + what->expires = tmp->expires; + what->lastmod = tmp->lastmod; + what->swap_file_sz = tmp->swap_file_sz; + what->refcount = tmp->refcount; + what->flags = tmp->flags; + break; + + case STORE_META_STD_LFS: + assert(x.length == STORE_HDR_METASIZE); + memcpy(&what->timestamp, x.value, STORE_HDR_METASIZE); + break; + + default: + break; + } + } + + StoreEntry *what; + cache_key *index; +}; + +bool +storeRebuildLoadEntry(int fd, int diskIndex, MemBuf &buf, + struct _store_rebuild_data &counts) +{ + if (fd < 0) + return false; + + assert(buf.hasSpace()); // caller must allocate + + const int len = FD_READ_METHOD(fd, buf.space(), buf.spaceSize()); + statCounter.syscalls.disk.reads++; + if (len < 0) { + const int xerrno = errno; + debugs(47, DBG_IMPORTANT, "WARNING: cache_dir[" << diskIndex << "]: " << + "Ignoring cached entry after meta data read failure: " << xstrerr(xerrno)); + return false; + } + + buf.appended(len); + return true; +} + +bool +storeRebuildParseEntry(MemBuf &buf, StoreEntry &tmpe, cache_key *key, + struct _store_rebuild_data &counts, + uint64_t expectedSize) +{ + int swap_hdr_len = 0; + StoreMetaUnpacker aBuilder(buf.content(), buf.contentSize(), &swap_hdr_len); + if (aBuilder.isBufferZero()) { + debugs(47,5, HERE << "skipping empty record."); + return false; + } + + if (!aBuilder.isBufferSane()) { + debugs(47, DBG_IMPORTANT, "WARNING: Ignoring malformed cache entry."); + return false; + } + + StoreMeta *tlv_list = aBuilder.createStoreMeta(); + if (!tlv_list) { + debugs(47, DBG_IMPORTANT, "WARNING: Ignoring cache entry with invalid " << + "meta data"); + return false; + } + + // TODO: consume parsed metadata? + + debugs(47,7, HERE << "successful swap meta unpacking"); + memset(key, '\0', SQUID_MD5_DIGEST_LENGTH); + + InitStoreEntry visitor(&tmpe, key); + for_each(*tlv_list, visitor); + storeSwapTLVFree(tlv_list); + tlv_list = NULL; + + if (storeKeyNull(key)) { + debugs(47, DBG_IMPORTANT, "WARNING: Ignoring keyless cache entry"); + return false; + } + + tmpe.key = key; + /* check sizes */ + + if (expectedSize > 0) { + if (tmpe.swap_file_sz == 0) { + tmpe.swap_file_sz = expectedSize; + } else if (tmpe.swap_file_sz == (uint64_t)(expectedSize - swap_hdr_len)) { + tmpe.swap_file_sz = expectedSize; + } else if (tmpe.swap_file_sz != expectedSize) { + debugs(47, DBG_IMPORTANT, "WARNING: Ignoring cache entry due to a " << + "SIZE MISMATCH " << tmpe.swap_file_sz << "!=" << expectedSize); + return false; + } + } else if (tmpe.swap_file_sz <= 0) { + debugs(47, DBG_IMPORTANT, "WARNING: Ignoring cache entry with " << + "unknown size: " << tmpe); + return false; + } + + if (EBIT_TEST(tmpe.flags, KEY_PRIVATE)) { + counts.badflags++; + return false; + } + + return true; +} + +bool +storeRebuildKeepEntry(const StoreEntry &tmpe, const cache_key *key, + struct _store_rebuild_data &counts) +{ + /* this needs to become + * 1) unpack url + * 2) make synthetic request with headers ?? or otherwise search + * for a matching object in the store + * TODO FIXME change to new async api + * TODO FIXME I think there is a race condition here with the + * async api : + * store A reads in object foo, searchs for it, and finds nothing. + * store B reads in object foo, searchs for it, finds nothing. + * store A gets called back with nothing, so registers the object + * store B gets called back with nothing, so registers the object, + * which will conflict when the in core index gets around to scanning + * store B. + * + * this suggests that rather than searching for duplicates, the + * index rebuild should just assume its the most recent accurate + * store entry and whoever indexes the stores handles duplicates. + */ + if (StoreEntry *e = Store::Root().get(key)) { + + if (e->lastref >= tmpe.lastref) { + /* key already exists, old entry is newer */ + /* keep old, ignore new */ + counts.dupcount++; + + // For some stores, get() creates/unpacks a store entry. Signal + // such stores that we will no longer use the get() result: + e->lock(); + e->unlock(); + + return false; + } else { + /* URL already exists, this swapfile not being used */ + /* junk old, load new */ + e->release(); /* release old entry */ + counts.dupcount++; + } + } + + return true; +} diff -u -r -N squid-3.2.0.12/src/store_swapin.cc squid-3.2.0.13/src/store_swapin.cc --- squid-3.2.0.12/src/store_swapin.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/store_swapin.cc 2011-10-14 14:42:56.000000000 +1300 @@ -50,6 +50,9 @@ return; } + if (e->mem_status != NOT_IN_MEMORY) + debugs(20, 3, HERE << "already IN_MEMORY"); + debugs(20, 3, "storeSwapInStart: called for : " << e->swap_dirn << " " << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << e->swap_filen << " " << e->getMD5Text()); @@ -94,6 +97,7 @@ e->swap_dirn << " to " << sc->swapin_sio->swap_filen << "/" << sc->swapin_sio->swap_dirn); + assert(e->swap_filen < 0); // if this fails, call SwapDir::disconnect(e) e->swap_filen = sc->swapin_sio->swap_filen; e->swap_dirn = sc->swapin_sio->swap_dirn; } diff -u -r -N squid-3.2.0.12/src/store_swapmeta.cc squid-3.2.0.13/src/store_swapmeta.cc --- squid-3.2.0.12/src/store_swapmeta.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/store_swapmeta.cc 2011-10-14 14:42:56.000000000 +1300 @@ -61,8 +61,8 @@ tlv **T = &TLV; const char *url; const char *vary; - const int64_t objsize = e->objectLen(); assert(e->mem_obj != NULL); + const int64_t objsize = e->mem_obj->expectedReplySize(); assert(e->swap_status == SWAPOUT_WRITING); url = e->url(); debugs(20, 3, "storeSwapMetaBuild: " << url ); diff -u -r -N squid-3.2.0.12/src/store_swapout.cc squid-3.2.0.13/src/store_swapout.cc --- squid-3.2.0.12/src/store_swapout.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/store_swapout.cc 2011-10-14 14:42:56.000000000 +1300 @@ -85,6 +85,7 @@ if (sio == NULL) { e->swap_status = SWAPOUT_NONE; + mem->swapout.decision = MemObject::SwapOut::swImpossible; delete c; xfree((char*)buf); storeLog(STORE_LOG_SWAPOUTFAIL, e); @@ -115,6 +116,7 @@ assert(mem); assert(mem->swapout.sio == self); assert(errflag == 0); + assert(e->swap_filen < 0); // if this fails, call SwapDir::disconnect(e) e->swap_filen = mem->swapout.sio->swap_filen; e->swap_dirn = mem->swapout.sio->swap_dirn; } @@ -125,22 +127,16 @@ MemObject *mem = anEntry->mem_obj; do { - /* - * Evil hack time. - * We are paging out to disk in page size chunks. however, later on when - * we update the queue position, we might not have a page (I *think*), - * so we do the actual page update here. - */ - - if (mem->swapout.memnode == NULL) { - /* We need to swap out the first page */ - mem->swapout.memnode = const_cast(mem->data_hdr.start()); - } else { - /* We need to swap out the next page */ - /* 20030636 RBC - we don't have ->next anymore. - * But we do have the next location */ - mem->swapout.memnode = mem->data_hdr.getBlockContainingLocation (mem->swapout.memnode->end()); - } + // find the page containing the first byte we have not swapped out yet + mem_node *page = + mem->data_hdr.getBlockContainingLocation(mem->swapout.queue_offset); + + if (!page) + return; // wait for more data to become available + + // memNodeWriteComplete() and absence of buffer offset math below + // imply that we always write from the very beginning of the page + assert(page->start() == mem->swapout.queue_offset); /* * Get the length of this buffer. We are assuming(!) that the buffer @@ -150,7 +146,7 @@ * but we can look at this at a later date or whenever the code results * in bad swapouts, whichever happens first. :-) */ - ssize_t swap_buf_len = mem->swapout.memnode->nodeBuffer.length; + ssize_t swap_buf_len = page->nodeBuffer.length; debugs(20, 3, "storeSwapOut: swap_buf_len = " << swap_buf_len); @@ -161,7 +157,7 @@ mem->swapout.queue_offset += swap_buf_len; storeIOWrite(mem->swapout.sio, - mem->data_hdr.NodeGet(mem->swapout.memnode), + mem->data_hdr.NodeGet(page), swap_buf_len, -1, memNodeWriteComplete); @@ -194,6 +190,9 @@ if (!swapoutPossible()) return; + // Aborted entries have STORE_OK, but swapoutPossible rejects them. Thus, + // store_status == STORE_OK below means we got everything we wanted. + debugs(20, 7, HERE << "storeSwapOut: mem->inmem_lo = " << mem_obj->inmem_lo); debugs(20, 7, HERE << "storeSwapOut: mem->endOffset() = " << mem_obj->endOffset()); debugs(20, 7, HERE << "storeSwapOut: swapout.queue_offset = " << mem_obj->swapout.queue_offset); @@ -201,6 +200,7 @@ if (mem_obj->swapout.sio != NULL) debugs(20, 7, "storeSwapOut: storeOffset() = " << mem_obj->swapout.sio->offset() ); + // buffered bytes we have not swapped out yet int64_t swapout_maxsize = mem_obj->endOffset() - mem_obj->swapout.queue_offset; assert(swapout_maxsize >= 0); @@ -209,25 +209,29 @@ debugs(20, 7, HERE << "storeSwapOut: lowest_offset = " << lowest_offset); - /* - * Grab the swapout_size and check to see whether we're going to defer - * the swapout based upon size - */ - if ((store_status != STORE_OK) && (swapout_maxsize < store_maxobjsize)) { - /* - * NOTE: the store_maxobjsize here is the max of optional - * max-size values from 'cache_dir' lines. It is not the - * same as 'maximum_object_size'. By default, store_maxobjsize - * will be set to -1. However, I am worried that this - * deferance may consume a lot of memory in some cases. - * It would be good to make this decision based on reply - * content-length, rather than wait to accumulate huge - * amounts of object data in memory. - */ - debugs(20, 5, "storeSwapOut: Deferring starting swapping out"); - return; + // Check to see whether we're going to defer the swapout based upon size + if (store_status != STORE_OK) { + const int64_t expectedSize = mem_obj->expectedReplySize(); + const int64_t maxKnownSize = expectedSize < 0 ? + swapout_maxsize : expectedSize; + debugs(20, 7, HERE << "storeSwapOut: maxKnownSize= " << maxKnownSize); + + if (maxKnownSize < store_maxobjsize) { + /* + * NOTE: the store_maxobjsize here is the max of optional + * max-size values from 'cache_dir' lines. It is not the + * same as 'maximum_object_size'. By default, store_maxobjsize + * will be set to -1. However, I am worried that this + * deferance may consume a lot of memory in some cases. + * Should we add an option to limit this memory consumption? + */ + debugs(20, 5, "storeSwapOut: Deferring swapout start for " << + (store_maxobjsize - maxKnownSize) << " bytes"); + return; + } } +// TODO: it is better to trim as soon as we swap something out, not before trimMemory(); #if SIZEOF_OFF_T <= 4 @@ -246,11 +250,13 @@ debugs(20, 7, "storeSwapOut: swapout_size = " << swapout_maxsize); - if (swapout_maxsize == 0) { - if (store_status == STORE_OK) - swapOutFileClose(); - - return; /* Nevermore! */ + if (swapout_maxsize == 0) { // swapped everything we got + if (store_status == STORE_OK) { // got everything we wanted + assert(mem_obj->object_sz >= 0); + swapOutFileClose(StoreIOState::wroteAll); + } + // else need more data to swap out + return; } if (store_status == STORE_PENDING) { @@ -271,13 +277,7 @@ if (swap_status == SWAPOUT_NONE) { assert(mem_obj->swapout.sio == NULL); assert(mem_obj->inmem_lo == 0); - - if (checkCachable()) - storeSwapOutStart(this); - else - return; - - /* ENTRY_CACHABLE will be cleared and we'll never get here again */ + storeSwapOutStart(this); // sets SwapOut::swImpossible on failures } if (mem_obj->swapout.sio == NULL) @@ -295,22 +295,23 @@ * to the filesystem at this point because storeSwapOut() is * not going to be called again for this entry. */ + assert(mem_obj->object_sz >= 0); assert(mem_obj->endOffset() == mem_obj->swapout.queue_offset); - swapOutFileClose(); + swapOutFileClose(StoreIOState::wroteAll); } } void -StoreEntry::swapOutFileClose() +StoreEntry::swapOutFileClose(int how) { assert(mem_obj != NULL); - debugs(20, 3, "storeSwapOutFileClose: " << getMD5Text()); + debugs(20, 3, "storeSwapOutFileClose: " << getMD5Text() << " how=" << how); debugs(20, 3, "storeSwapOutFileClose: sio = " << mem_obj->swapout.sio.getRaw()); if (mem_obj->swapout.sio == NULL) return; - storeClose(mem_obj->swapout.sio); + storeClose(mem_obj->swapout.sio, how); } static void @@ -323,11 +324,11 @@ assert(e->swap_status == SWAPOUT_WRITING); cbdataFree(c); - if (errflag) { - debugs(20, 1, "storeSwapOutFileClosed: dirno " << e->swap_dirn << ", swapfile " << + // if object_size is still unknown, the entry was probably aborted + if (errflag || e->objectLen() < 0) { + debugs(20, 2, "storeSwapOutFileClosed: dirno " << e->swap_dirn << ", swapfile " << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << e->swap_filen << ", errflag=" << errflag); - debugs(20, 1, "\t" << xstrerror()); if (errflag == DISK_NO_SPACE_LEFT) { /* FIXME: this should be handle by the link from store IO to @@ -337,14 +338,10 @@ storeConfigure(); } - if (e->swap_filen > 0) + if (e->swap_filen >= 0) e->unlink(); - e->swap_filen = -1; - - e->swap_dirn = -1; - - e->swap_status = SWAPOUT_NONE; + assert(e->swap_status == SWAPOUT_NONE); e->releaseRequest(); } else { @@ -352,10 +349,17 @@ debugs(20, 3, "storeSwapOutFileClosed: SwapOut complete: '" << e->url() << "' to " << e->swap_dirn << ", " << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << e->swap_filen); + debugs(20, 5, HERE << "swap_file_sz = " << + e->objectLen() << " + " << mem->swap_hdr_sz); + e->swap_file_sz = e->objectLen() + mem->swap_hdr_sz; e->swap_status = SWAPOUT_DONE; - e->store()->updateSize(e->swap_file_sz, 1); + e->store()->swappedOut(*e); + // XXX: For some Stores, it is pointless to re-check cachability here + // and it leads to double counts in store_check_cachable_hist. We need + // another way to signal a completed but failed swapout. Or, better, + // each Store should handle its own logging and LOG state setting. if (e->checkCachable()) { storeLog(STORE_LOG_SWAPOUT, e); storeDirSwapLog(e, SWAP_LOG_ADD); diff -u -r -N squid-3.2.0.12/src/structs.h squid-3.2.0.13/src/structs.h --- squid-3.2.0.12/src/structs.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/structs.h 2011-10-14 14:42:56.000000000 +1300 @@ -144,7 +144,30 @@ class CpuAffinityMap; class RemovalPolicySettings; class external_acl; -class Store; +class SwapDir; + +/// Used for boolean enabled/disabled options with complex default logic. +/// Allows Squid to compute the right default after configuration. +/// Checks that not-yet-defined option values are not used. +class YesNoNone +{ +// TODO: generalize to non-boolean option types +public: + YesNoNone(): option(0) {} + + /// returns true iff enabled; asserts if the option has not been configured + operator void *() const; // TODO: use a fancy/safer version of the operator + + /// enables or disables the option; + void configure(bool beSet); + + /// whether the option was enabled or disabled, by user or Squid + bool configured() const { return option != 0; } + +private: + enum { optUnspecified = -1, optDisabled = 0, optEnabled = 1 }; + int option; ///< configured value or zero +}; struct SquidConfig { @@ -155,6 +178,8 @@ int highWaterMark; int lowWaterMark; } Swap; + + YesNoNone memShared; ///< whether the memory cache is shared among workers size_t memMaxSize; struct { @@ -435,6 +460,7 @@ int WIN32_IpAddrChangeMonitor; int memory_cache_first; int memory_cache_disk; + int hostStrictVerify; int client_dst_passthru; } onoff; @@ -496,9 +522,11 @@ refresh_t *Refresh; struct _cacheSwap { - RefCount *swapDirs; + RefCount *swapDirs; int n_allocated; int n_configured; + /// number of disk processes required to support all cache_dirs + int n_strands; } cacheSwap; /* * I'm sick of having to keep doing this .. @@ -617,6 +645,7 @@ int client_ip_max_connections; struct { + int v4_first; ///< Place IPv4 first in the order of DNS results. ssize_t packet_max; ///< maximum size EDNS advertised for DNS replies. } dns; }; @@ -696,21 +725,6 @@ String value; /* field-value from HTTP/1.1 */ }; -/* http cache control header field */ - -class HttpHdrCc -{ - -public: - int mask; - int max_age; - int s_maxage; - int max_stale; - int stale_if_error; - int min_fresh; - String other; -}; - /* per field statistics */ class HttpHeaderFieldStat diff -u -r -N squid-3.2.0.12/src/SwapDir.cc squid-3.2.0.13/src/SwapDir.cc --- squid-3.2.0.12/src/SwapDir.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/SwapDir.cc 2011-10-14 14:42:56.000000000 +1300 @@ -38,8 +38,18 @@ #include "StoreFileSystem.h" #include "ConfigOption.h" +SwapDir::SwapDir(char const *aType): theType(aType), + max_size(0), + path(NULL), index(-1), disker(-1), min_objsize(0), max_objsize (-1), + repl(NULL), removals(0), scanned(0), + cleanLog(NULL) +{ + fs.blksize = 1024; +} + SwapDir::~SwapDir() { + // TODO: should we delete repl? xfree(path); } @@ -61,6 +71,9 @@ void SwapDir::stat(StoreEntry &output) const { + if (!doReportStat()) + return; + storeAppendPrintf(&output, "Store Directory #%d (%s): %s\n", index, type(), path); storeAppendPrintf(&output, "FS Block Size %d Bytes\n", @@ -90,8 +103,11 @@ void SwapDir::reference(StoreEntry &) {} -void -SwapDir::dereference(StoreEntry &) {} +bool +SwapDir::dereference(StoreEntry &) +{ + return true; // keep in global store_table +} int SwapDir::callback() @@ -99,6 +115,30 @@ return 0; } +bool +SwapDir::canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const +{ + debugs(47,8, HERE << "cache_dir[" << index << "]: needs " << + diskSpaceNeeded << " maxSize()) + return false; // already overflowing + + /* Return 999 (99.9%) constant load; TODO: add a named constant for this */ + load = 999; + return true; // kids may provide more tests and should report true load +} + + void SwapDir::sync() {} @@ -151,6 +191,25 @@ return theType; } +bool +SwapDir::active() const +{ + if (IamWorkerProcess()) + return true; + + // we are inside a disker dedicated to this disk + if (KidIdentifier == disker) + return true; + + return false; // Coordinator, wrong disker, etc. +} + +bool +SwapDir::needsDiskStrand() const +{ + return false; +} + /* NOT performance critical. Really. Don't bother optimising for speed * - RBC 20030718 */ @@ -251,8 +310,17 @@ int64_t size = strtoll(value, NULL, 10); - if (isaReconfig && *val != size) - debugs(3, 1, "Cache dir '" << path << "' object " << option << " now " << size); + if (isaReconfig && *val != size) { + if (allowOptionReconfigure(option)) { + debugs(3, DBG_IMPORTANT, "cache_dir '" << path << "' object " << + option << " now " << size << " Bytes"); + } else { + debugs(3, DBG_IMPORTANT, "WARNING: cache_dir '" << path << "' " + "object " << option << " cannot be changed dynamically, " << + "value left unchanged (" << *val << " Bytes)"); + return true; + } + } *val = size; @@ -269,13 +337,11 @@ storeAppendPrintf(e, " max-size=%"PRId64, max_objsize); } -/* Swapdirs do not have an index of their own - thus they ask their parent.. - * but the parent child relationship isn't implemented yet - */ +// some SwapDirs may maintain their indexes and be able to lookup an entry key StoreEntry * SwapDir::get(const cache_key *key) { - return Store::Root().get(key); + return NULL; } void diff -u -r -N squid-3.2.0.12/src/SwapDir.h squid-3.2.0.13/src/SwapDir.h --- squid-3.2.0.12/src/SwapDir.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/SwapDir.h 2011-10-14 14:42:56.000000000 +1300 @@ -37,14 +37,14 @@ /* forward decls */ class RemovalPolicy; +class MemStore; /* Store dir configuration routines */ /* SwapDir *sd, char *path ( + char *opt later when the strtok mess is gone) */ class ConfigOption; -/* New class that replaces the static SwapDir methods as part of the Store overhaul */ - +/// hides memory/disk cache distinction from callers class StoreController : public Store { @@ -58,6 +58,9 @@ virtual void get(String const, STOREGETCLIENT, void * cbdata); + /* Store parent API */ + virtual void handleIdleEntry(StoreEntry &e); + virtual void init(); virtual void maintain(); /* perform regular maintenance should be private and self registered ... */ @@ -66,6 +69,12 @@ virtual uint64_t minSize() const; + virtual uint64_t currentSize() const; + + virtual uint64_t currentCount() const; + + virtual int64_t maxObjectSize() const; + virtual void stat(StoreEntry &) const; virtual void sync(); /* Sync the store prior to shutdown */ @@ -74,9 +83,7 @@ virtual void reference(StoreEntry &); /* Reference this object */ - virtual void dereference(StoreEntry &); /* Unreference this object */ - - virtual void updateSize(int64_t size, int sign); + virtual bool dereference(StoreEntry &); /* Unreference this object */ /* the number of store dirs being rebuilt. */ static int store_dirs_rebuilding; @@ -84,7 +91,8 @@ private: void createOneStore(Store &aStore); - StorePointer swapDir; + StorePointer swapDir; ///< summary view of all disk caches + MemStore *memStore; ///< memory cache }; /* migrating from the Config based list of swapdirs */ @@ -108,20 +116,23 @@ SQUIDCEXTERN int storeDirGetBlkSize(const char *path, int *blksize); SQUIDCEXTERN int storeDirGetUFSStats(const char *, int *, int *, int *, int *); - +/// manages a single cache_dir class SwapDir : public Store { public: - SwapDir(char const *aType) : theType (aType), cur_size(0), max_size(0), min_objsize(0), max_objsize(-1), cleanLog(NULL) { - fs.blksize = 1024; - path = NULL; - } + typedef RefCount Pointer; + SwapDir(char const *aType); virtual ~SwapDir(); - virtual void reconfigure(int, char *) = 0; + virtual void reconfigure() = 0; char const *type() const; + virtual bool needsDiskStrand() const; ///< needs a dedicated kid process + virtual bool active() const; ///< may be used in this strand + /// whether stat should be reported by this SwapDir + virtual bool doReportStat() const { return active(); } + /* official Store interface functions */ virtual void diskFull(); @@ -132,18 +143,28 @@ virtual uint64_t maxSize() const { return max_size;} virtual uint64_t minSize() const; + + virtual int64_t maxObjectSize() const { return max_objsize; } + virtual void stat (StoreEntry &anEntry) const; virtual StoreSearch *search(String const url, HttpRequest *) = 0; - virtual void updateSize(int64_t size, int sign); - /* migrated from store_dir.cc */ bool objectSizeIsAcceptable(int64_t objsize) const; + /// called when the entry is about to forget its association with cache_dir + virtual void disconnect(StoreEntry &) {} + + /// called when entry swap out is complete + virtual void swappedOut(const StoreEntry &e) = 0; + protected: void parseOptions(int reconfiguring); void dumpOptions(StoreEntry * e) const; virtual ConfigOption *getOptionTree() const; + virtual bool allowOptionReconfigure(const char *const) const { return true; } + + int64_t sizeInBlocks(const int64_t size) const { return (size + fs.blksize - 1) / fs.blksize; } private: bool optionReadOnlyParse(char const *option, const char *value, int reconfiguring); @@ -152,11 +173,13 @@ void optionObjectSizeDump(StoreEntry * e) const; char const *theType; -public: - uint64_t cur_size; ///< currently used space in the storage area +protected: uint64_t max_size; ///< maximum allocatable size of the storage area + +public: char *path; int index; /* This entry's index into the swapDirs array */ + int disker; ///< disker kid id dedicated to this SwapDir or -1 int64_t min_objsize; int64_t max_objsize; RemovalPolicy *repl; @@ -174,11 +197,11 @@ virtual bool doubleCheck(StoreEntry &); /* Double check the obj integrity */ virtual void statfs(StoreEntry &) const; /* Dump fs statistics */ virtual void maintain(); /* Replacement maintainence */ - /* <0 == error. > 1000 == error */ - virtual int canStore(StoreEntry const &)const = 0; /* Check if the fs will store an object */ + /// check whether we can store the entry; if we can, report current load + virtual bool canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const = 0; /* These two are notifications */ virtual void reference(StoreEntry &); /* Reference this object */ - virtual void dereference(StoreEntry &); /* Unreference this object */ + virtual bool dereference(StoreEntry &); /* Unreference this object */ virtual int callback(); /* Handle pending callbacks */ virtual void sync(); /* Sync the store prior to shutdown */ virtual StoreIOState::Pointer createStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *) = 0; diff -u -r -N squid-3.2.0.12/src/tests/stub_cache_cf.cc squid-3.2.0.13/src/tests/stub_cache_cf.cc --- squid-3.2.0.12/src/tests/stub_cache_cf.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/stub_cache_cf.cc 2011-10-14 14:42:56.000000000 +1300 @@ -115,6 +115,12 @@ fatal("not implemented 11"); } +YesNoNone::operator void*() const +{ + /* ignore this for testing */ + return NULL; +} + /* * DO NOT MODIFY: * arch-tag: 9bbc3b5f-8d7b-4fdc-af59-0b524a785307 diff -u -r -N squid-3.2.0.12/src/tests/stub_HelperChildConfig.cc squid-3.2.0.13/src/tests/stub_HelperChildConfig.cc --- squid-3.2.0.12/src/tests/stub_HelperChildConfig.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/stub_HelperChildConfig.cc 2011-10-14 14:42:56.000000000 +1300 @@ -4,25 +4,15 @@ #include -HelperChildConfig::HelperChildConfig(const unsigned int m, const unsigned int s, const unsigned int i, const unsigned int cc) : +HelperChildConfig::HelperChildConfig(const unsigned int m): n_max(m), - n_startup(s), - n_idle(i), - concurrency(cc), + n_startup(0), + n_idle(1), + concurrency(0), n_running(0), n_active(0) {} -HelperChildConfig::~HelperChildConfig() -{} - -HelperChildConfig & -HelperChildConfig::operator =(const HelperChildConfig &rhs) -{ - memcpy(this, &rhs, sizeof(HelperChildConfig)); - return *this; -} - int HelperChildConfig::needNew() const { diff -u -r -N squid-3.2.0.12/src/tests/stub_HttpReply.cc squid-3.2.0.13/src/tests/stub_HttpReply.cc --- squid-3.2.0.12/src/tests/stub_HttpReply.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/stub_HttpReply.cc 2011-10-14 14:42:56.000000000 +1300 @@ -122,3 +122,10 @@ fatal("Not implemented"); return false; } + +int64_t +HttpReply::bodySize(const HttpRequestMethod&) const +{ + fatal("Not implemented"); + return 0; +} diff -u -r -N squid-3.2.0.12/src/tests/stub_HttpRequest.cc squid-3.2.0.13/src/tests/stub_HttpRequest.cc --- squid-3.2.0.12/src/tests/stub_HttpRequest.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/stub_HttpRequest.cc 2011-10-14 14:42:56.000000000 +1300 @@ -108,6 +108,13 @@ return false; } +int64_t +HttpRequest::getRangeOffsetLimit() +{ + fatal("Not implemented"); + return 0; +} + /* * DO NOT MODIFY: * arch-tag: dd894aa8-63cc-4543-92d9-1079a18bee11 diff -u -r -N squid-3.2.0.12/src/tests/stub_libcomm.cc squid-3.2.0.13/src/tests/stub_libcomm.cc --- squid-3.2.0.12/src/tests/stub_libcomm.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/tests/stub_libcomm.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,60 @@ +#include "config.h" +#include "base/AsyncJob.h" +#include "structs.h" + +#define STUB_API "comm/libcomm.la" +#include "tests/STUB.h" + +#include "comm/AcceptLimiter.h" +Comm::AcceptLimiter dummy; +Comm::AcceptLimiter & Comm::AcceptLimiter::Instance() STUB_RETVAL(dummy) +void Comm::AcceptLimiter::defer(Comm::TcpAcceptor *afd) STUB +void Comm::AcceptLimiter::removeDead(const Comm::TcpAcceptor *afd) STUB +void Comm::AcceptLimiter::kick() STUB + +#include "comm/Connection.h" +Comm::Connection::Connection() STUB +Comm::Connection::~Connection() STUB +Comm::ConnectionPointer Comm::Connection::copyDetails() const STUB_RETVAL(NULL) +void Comm::Connection::close() STUB +peer * Comm::Connection::getPeer() const STUB_RETVAL(NULL) +void Comm::Connection::setPeer(peer * p) STUB + +#include "comm/ConnOpener.h" +bool Comm::ConnOpener::doneAll() const STUB_RETVAL(false) +//Comm::ConnOpener::ConnOpener(Comm::ConnectionPointer &, AsyncCall::Pointer &, time_t) STUB +//Comm::ConnOpener::~ConnOpener() STUB +void Comm::ConnOpener::setHost(const char *) STUB +const char * Comm::ConnOpener::getHost() const STUB_RETVAL(NULL) + +#include "comm/forward.h" +bool Comm::IsConnOpen(const Comm::ConnectionPointer &) STUB_RETVAL(false) + +#include "comm/IoCallback.h" +void Comm::IoCallback::setCallback(iocb_type type, AsyncCall::Pointer &cb, char *buf, FREE *func, int sz) STUB +void Comm::IoCallback::selectOrQueueWrite() STUB +void Comm::IoCallback::cancel(const char *reason) STUB +void Comm::IoCallback::finish(comm_err_t code, int xerrn) STUB +Comm::CbEntry *Comm::iocb_table = NULL; +void Comm::CallbackTableInit() STUB +void Comm::CallbackTableDestruct() STUB + +#include "comm/Loops.h" +void Comm::SelectLoopInit(void) STUB +void Comm::SetSelect(int, unsigned int, PF *, void *, time_t) STUB +void Comm::ResetSelect(int) STUB +comm_err_t Comm::DoSelect(int) STUB_RETVAL(COMM_ERROR) +void Comm::QuickPollRequired(void) STUB + +#include "comm/TcpAcceptor.h" +//Comm::TcpAcceptor(const Comm::ConnectionPointer &conn, const char *note, const Subscription::Pointer &aSub) STUB +void Comm::TcpAcceptor::subscribe(const Subscription::Pointer &aSub) STUB +void Comm::TcpAcceptor::unsubscribe(const char *) STUB +void Comm::TcpAcceptor::acceptNext() STUB +void Comm::TcpAcceptor::notify(const comm_err_t flag, const Comm::ConnectionPointer &) const STUB + +#include "comm/Write.h" +void Comm::Write(const Comm::ConnectionPointer &, const char *, int, AsyncCall::Pointer &, FREE *) STUB +void Comm::Write(const Comm::ConnectionPointer &conn, MemBuf *mb, AsyncCall::Pointer &callback) STUB +void Comm::WriteCancel(const Comm::ConnectionPointer &conn, const char *reason) STUB +//PF Comm::HandleWrite STUB diff -u -r -N squid-3.2.0.12/src/tests/stub_MemObject.cc squid-3.2.0.13/src/tests/stub_MemObject.cc --- squid-3.2.0.12/src/tests/stub_MemObject.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/stub_MemObject.cc 2011-10-14 14:42:56.000000000 +1300 @@ -180,3 +180,22 @@ fatal ("MemObject.cc required."); return false; } + +int64_t +MemObject::expectedReplySize() const +{ + fatal ("MemObject.cc required."); + return 0; +} + +void +MemObject::resetUrls(char const*, char const*) +{ + fatal ("MemObject.cc required."); +} + +void +MemObject::markEndOfReplyHeaders() +{ + fatal ("MemObject.cc required."); +} diff -u -r -N squid-3.2.0.12/src/tests/stub_MemStore.cc squid-3.2.0.13/src/tests/stub_MemStore.cc --- squid-3.2.0.12/src/tests/stub_MemStore.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.2.0.13/src/tests/stub_MemStore.cc 2011-10-14 14:42:56.000000000 +1300 @@ -0,0 +1,31 @@ +/* + * $Id$ + * + * DEBUG: section 84 Helper process maintenance + * + */ + +#include "config.h" +#include "MemStore.h" + +#define STUB_API "MemStore.cc" +#include "tests/STUB.h" + +MemStore::MemStore() STUB +MemStore::~MemStore() STUB +void MemStore::considerKeeping(StoreEntry &) STUB +void MemStore::reference(StoreEntry &) STUB +void MemStore::maintain() STUB +void MemStore::cleanReadable(const sfileno) STUB +void MemStore::get(String const, STOREGETCLIENT, void *) STUB +void MemStore::init() STUB +void MemStore::stat(StoreEntry &) const STUB +int MemStore::callback() STUB_RETVAL(0) +StoreEntry *MemStore::get(const cache_key *) STUB_RETVAL(NULL) +uint64_t MemStore::maxSize() const STUB_RETVAL(0) +uint64_t MemStore::minSize() const STUB_RETVAL(0) +uint64_t MemStore::currentSize() const STUB_RETVAL(0) +uint64_t MemStore::currentCount() const STUB_RETVAL(0) +int64_t MemStore::maxObjectSize() const STUB_RETVAL(0) +StoreSearch *MemStore::search(String const, HttpRequest *) STUB_RETVAL(NULL) +bool MemStore::dereference(StoreEntry &) STUB_RETVAL(false) diff -u -r -N squid-3.2.0.12/src/tests/stub_Port.cc squid-3.2.0.13/src/tests/stub_Port.cc --- squid-3.2.0.12/src/tests/stub_Port.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/stub_Port.cc 2011-10-14 14:42:56.000000000 +1300 @@ -1,4 +1,10 @@ #include "config.h" #include "ipc/Port.h" +#define STUB_API "ipc/Port.cc" +#include "tests/STUB.h" + const char Ipc::coordinatorAddr[] = ""; +const char Ipc::strandAddrPfx[] = ""; + +String Ipc::Port::MakeAddr(char const*, int) STUB_RETVAL("") diff -u -r -N squid-3.2.0.12/src/tests/stub_store.cc squid-3.2.0.13/src/tests/stub_store.cc --- squid-3.2.0.12/src/tests/stub_store.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/stub_store.cc 2011-10-14 14:42:56.000000000 +1300 @@ -17,6 +17,7 @@ const char *StoreEntry::getMD5Text() const STUB_RETVAL(NULL) StoreEntry::StoreEntry() STUB StoreEntry::StoreEntry(const char *url, const char *log_url) STUB +StoreEntry::~StoreEntry() STUB HttpReply const *StoreEntry::getReply() const STUB_RETVAL(NULL) void StoreEntry::write(StoreIOBuffer) STUB bool StoreEntry::isAccepting() const STUB_RETVAL(false) @@ -24,7 +25,7 @@ void StoreEntry::complete() STUB store_client_t StoreEntry::storeClientType() const STUB_RETVAL(STORE_NON_CLIENT) char const *StoreEntry::getSerialisedMetaData() STUB_RETVAL(NULL) -void StoreEntry::replaceHttpReply(HttpReply *) STUB +void StoreEntry::replaceHttpReply(HttpReply *, bool andStartWriting) STUB bool StoreEntry::swapoutPossible() STUB_RETVAL(false) void StoreEntry::trimMemory() STUB void StoreEntry::abort() STUB @@ -41,14 +42,15 @@ void StoreEntry::purgeMem() STUB void StoreEntry::swapOut() STUB bool StoreEntry::swapOutAble() const STUB_RETVAL(false) -void StoreEntry::swapOutFileClose() STUB +void StoreEntry::swapOutFileClose(int how) STUB const char *StoreEntry::url() const STUB_RETVAL(NULL) int StoreEntry::checkCachable() STUB_RETVAL(0) int StoreEntry::checkNegativeHit() const STUB_RETVAL(0) int StoreEntry::locked() const STUB_RETVAL(0) int StoreEntry::validToSend() const STUB_RETVAL(0) -int StoreEntry::keepInMemory() const STUB_RETVAL(0) +bool StoreEntry::memoryCachable() const STUB_RETVAL(false) void StoreEntry::createMemObject(const char *, const char *) STUB +void StoreEntry::hideMemObject() STUB void StoreEntry::dump(int debug_lvl) const STUB void StoreEntry::hashDelete() STUB void StoreEntry::hashInsert(const cache_key *) STUB @@ -64,7 +66,7 @@ bool StoreEntry::modifiedSince(HttpRequest * request) const STUB_RETVAL(false) bool StoreEntry::hasIfMatchEtag(const HttpRequest &request) const STUB_RETVAL(false) bool StoreEntry::hasIfNoneMatchEtag(const HttpRequest &request) const STUB_RETVAL(false) -RefCount StoreEntry::store() const STUB_RETVAL(StorePointer()) +RefCount StoreEntry::store() const STUB_RETVAL(NULL) size_t StoreEntry::inUseCount() STUB_RETVAL(0) void StoreEntry::getPublicByRequestMethod(StoreClient * aClient, HttpRequest * request, const HttpRequestMethod& method) STUB void StoreEntry::getPublicByRequest(StoreClient * aClient, HttpRequest * request) STUB @@ -103,6 +105,12 @@ void Store::sync() STUB void Store::unlink(StoreEntry &) STUB +std::ostream &operator <<(std::ostream &os, const StoreEntry &) +{ + STUB + return os; +} + SQUIDCEXTERN size_t storeEntryInUse() STUB_RETVAL(0) SQUIDCEXTERN const char *storeEntryFlags(const StoreEntry *) STUB_RETVAL(NULL) void storeEntryReplaceObject(StoreEntry *, HttpReply *) STUB diff -u -r -N squid-3.2.0.12/src/tests/stub_store_rebuild.cc squid-3.2.0.13/src/tests/stub_store_rebuild.cc --- squid-3.2.0.12/src/tests/stub_store_rebuild.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/stub_store_rebuild.cc 2011-10-14 14:42:56.000000000 +1300 @@ -45,3 +45,21 @@ storeRebuildComplete(struct _store_rebuild_data *dc) {} +bool +storeRebuildLoadEntry(int, int, MemBuf&, _store_rebuild_data&) +{ + return false; +} + +bool +storeRebuildKeepEntry(const StoreEntry &tmpe, const cache_key *key, + struct _store_rebuild_data &counts) +{ + return false; +} + +bool +storeRebuildParseEntry(MemBuf &, StoreEntry &, cache_key *, struct _store_rebuild_data &, uint64_t) +{ + return false; +} diff -u -r -N squid-3.2.0.12/src/tests/stub_tools.cc squid-3.2.0.13/src/tests/stub_tools.cc --- squid-3.2.0.12/src/tests/stub_tools.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/stub_tools.cc 2011-10-14 14:42:56.000000000 +1300 @@ -54,6 +54,41 @@ return memset(dst, val, sz); } +bool +IamWorkerProcess() +{ + fprintf(stderr, "Not implemented"); + return true; +} + +bool +IamDiskProcess() +{ + fprintf(stderr, "Not implemented"); + return false; +} + +bool +IamMasterProcess() +{ + fprintf(stderr, "Not implemented"); + return false; +} + +bool +InDaemonMode() +{ + fprintf(stderr, "Not implemented"); + return false; +} + +bool +UsingSmp() +{ + fprintf(stderr, "Not implemented"); + return false; +} + void logsFlush(void) { diff -u -r -N squid-3.2.0.12/src/tests/stub_TypedMsgHdr.cc squid-3.2.0.13/src/tests/stub_TypedMsgHdr.cc --- squid-3.2.0.12/src/tests/stub_TypedMsgHdr.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/stub_TypedMsgHdr.cc 1970-01-01 12:00:00.000000000 +1200 @@ -1,44 +0,0 @@ -#include "config.h" -#include "fatal.h" -#include "ipc/TypedMsgHdr.h" - -Ipc::TypedMsgHdr::TypedMsgHdr() -{ - fatal("Not implemented"); -} - -void -Ipc::TypedMsgHdr::getFixed(void *raw, size_t size) const -{ - fatal("Not implemented"); -} - -void -Ipc::TypedMsgHdr::putFixed(const void *raw, size_t size) -{ - fatal("Not implemented"); -} - -void -Ipc::TypedMsgHdr::getString(String &size) const -{ - fatal("Not implemented"); -} - -void -Ipc::TypedMsgHdr::putString(const String & size) -{ - fatal("Not implemented"); -} - -void -Ipc::TypedMsgHdr::checkType(int destType) const -{ - fatal("Not implemented"); -} - -void -Ipc::TypedMsgHdr::setType(int aType) -{ - fatal("Not implemented"); -} diff -u -r -N squid-3.2.0.12/src/tests/testCoss.cc squid-3.2.0.13/src/tests/testCoss.cc --- squid-3.2.0.12/src/tests/testCoss.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/testCoss.cc 2011-10-14 14:42:56.000000000 +1300 @@ -80,9 +80,7 @@ if (0 > system ("rm -rf " TESTDIR)) throw std::runtime_error("Failed to clean test work directory"); - StorePointer aRoot (new StoreController); - - Store::Root(aRoot); + Store::Root(new StoreController); SwapDirPointer aStore (new CossSwapDir()); @@ -111,10 +109,10 @@ /* TODO: check the size */ - free_cachedir(&Config.cacheSwap); - Store::Root(NULL); + free_cachedir(&Config.cacheSwap); + /* todo: here we should test a dirty rebuild */ // safe_free(Config.replPolicy->type); @@ -146,9 +144,7 @@ if (0 > system ("rm -rf " TESTDIR)) throw std::runtime_error("Failed to clean test work directory"); - StorePointer aRoot (new StoreController); - - Store::Root(aRoot); + Store::Root(new StoreController); SwapDirPointer aStore (new CossSwapDir()); @@ -257,10 +253,10 @@ CPPUNIT_ASSERT(search->isDone() == true); CPPUNIT_ASSERT(search->currentItem() == NULL); - free_cachedir(&Config.cacheSwap); - Store::Root(NULL); + free_cachedir(&Config.cacheSwap); + /* todo: here we should test a dirty rebuild */ //TODO: do this once, or each time. safe_free(Config.replPolicy->type); @@ -280,8 +276,7 @@ if (0 > system ("rm -rf " TESTDIR)) throw std::runtime_error("Failed to clean test work directory"); - StorePointer aRoot (new StoreController); - Store::Root(aRoot); + Store::Root(new StoreController); SwapDirPointer aStore (new CossSwapDir()); addSwapDir(aStore); commonInit(); @@ -294,8 +289,8 @@ safe_free(config_line); CPPUNIT_ASSERT(aStore->io != NULL); - free_cachedir(&Config.cacheSwap); Store::Root(NULL); + free_cachedir(&Config.cacheSwap); if (0 > system ("rm -rf " TESTDIR)) throw std::runtime_error("Failed to clean test work directory"); } diff -u -r -N squid-3.2.0.12/src/tests/testStore.cc squid-3.2.0.13/src/tests/testStore.cc --- squid-3.2.0.12/src/tests/testStore.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/testStore.cc 2011-10-14 14:42:56.000000000 +1300 @@ -6,9 +6,6 @@ CPPUNIT_TEST_SUITE_REGISTRATION( testStore ); -// Stubs so this test will link cleanly -#include "comm/stub_libcomm.cc" - int TestStore::callback() { @@ -41,6 +38,24 @@ { return 1; } + +uint64_t +TestStore::currentSize() const +{ + return 2; +} + +uint64_t +TestStore::currentCount() const +{ + return 2; +} + +int64_t +TestStore::maxObjectSize() const +{ + return 1; +} void TestStore::stat(StoreEntry &) const diff -u -r -N squid-3.2.0.12/src/tests/testStore.h squid-3.2.0.13/src/tests/testStore.h --- squid-3.2.0.12/src/tests/testStore.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/testStore.h 2011-10-14 14:42:56.000000000 +1300 @@ -59,13 +59,17 @@ virtual uint64_t minSize() const; + virtual uint64_t currentSize() const; + + virtual uint64_t currentCount() const; + + virtual int64_t maxObjectSize() const; + virtual void stat(StoreEntry &) const; /* output stats to the provided store entry */ virtual void reference(StoreEntry &) {} /* Reference this object */ - virtual void dereference(StoreEntry &) {} /* Unreference this object */ - - virtual void updateSize(int64_t size, int sign) {} + virtual bool dereference(StoreEntry &) { return true; } virtual StoreSearch *search(String const url, HttpRequest *); }; diff -u -r -N squid-3.2.0.12/src/tests/TestSwapDir.cc squid-3.2.0.13/src/tests/TestSwapDir.cc --- squid-3.2.0.12/src/tests/TestSwapDir.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/TestSwapDir.cc 2011-10-14 14:42:56.000000000 +1300 @@ -9,6 +9,18 @@ return 3; } +uint64_t +TestSwapDir::currentSize() const +{ + return 2; +} + +uint64_t +TestSwapDir::currentCount() const +{ + return 2; +} + void TestSwapDir::stat(StoreEntry &) const { @@ -16,16 +28,17 @@ } void -TestSwapDir::reconfigure(int, char*) +TestSwapDir::reconfigure() {} void TestSwapDir::init() {} -int -TestSwapDir::canStore(const StoreEntry&) const +bool +TestSwapDir::canStore(const StoreEntry &, int64_t, int &load) const { + load = 0; return true; } diff -u -r -N squid-3.2.0.12/src/tests/TestSwapDir.h squid-3.2.0.13/src/tests/TestSwapDir.h --- squid-3.2.0.12/src/tests/TestSwapDir.h 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/TestSwapDir.h 2011-10-14 14:42:56.000000000 +1300 @@ -13,11 +13,14 @@ bool statsCalled; virtual uint64_t maxSize() const; + virtual uint64_t currentSize() const; + virtual uint64_t currentCount() const; virtual void stat(StoreEntry &) const; /* output stats to the provided store entry */ + virtual void swappedOut(const StoreEntry &e) {} - virtual void reconfigure(int, char*); + virtual void reconfigure(); virtual void init(); - virtual int canStore(const StoreEntry&) const; + virtual bool canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const; virtual StoreIOState::Pointer createStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *); virtual StoreIOState::Pointer openStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *); virtual void parse(int, char*); diff -u -r -N squid-3.2.0.12/src/tests/testUfs.cc squid-3.2.0.13/src/tests/testUfs.cc --- squid-3.2.0.12/src/tests/testUfs.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tests/testUfs.cc 2011-10-14 14:42:56.000000000 +1300 @@ -87,9 +87,7 @@ if (0 > system ("rm -rf " TESTDIR)) throw std::runtime_error("Failed to clean test work directory"); - StorePointer aRoot (new StoreController); - - Store::Root(aRoot); + Store::Root(new StoreController); SwapDirPointer aStore (new UFSSwapDir("ufs", "Blocking")); @@ -205,11 +203,12 @@ CPPUNIT_ASSERT(search->isDone() == true); CPPUNIT_ASSERT(search->currentItem() == NULL); + Store::Root(NULL); + free_cachedir(&Config.cacheSwap); /* todo: here we should test a dirty rebuild */ - Store::Root(NULL); safe_free(Config.replPolicy->type); delete Config.replPolicy; @@ -232,8 +231,7 @@ // objects such as "StorePointer aRoot" from being called. CPPUNIT_ASSERT(!store_table); // or StoreHashIndex ctor will abort below - StorePointer aRoot (new StoreController); - Store::Root(aRoot); + Store::Root(new StoreController); SwapDirPointer aStore (new UFSSwapDir("ufs", "Blocking")); addSwapDir(aStore); commonInit(); @@ -249,8 +247,8 @@ safe_free(config_line); CPPUNIT_ASSERT(aStore->IO->io != NULL); - free_cachedir(&Config.cacheSwap); Store::Root(NULL); + free_cachedir(&Config.cacheSwap); safe_free(Config.replPolicy->type); delete Config.replPolicy; diff -u -r -N squid-3.2.0.12/src/tools.cc squid-3.2.0.13/src/tools.cc --- squid-3.2.0.12/src/tools.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/tools.cc 2011-10-14 14:42:56.000000000 +1300 @@ -821,7 +821,13 @@ if (opt_no_daemon || Config.workers == 0) return true; - return 0 < KidIdentifier && KidIdentifier <= Config.workers; + return TheProcessKind == pkWorker; +} + +bool +IamDiskProcess() +{ + return TheProcessKind == pkDisker; } bool @@ -833,13 +839,13 @@ bool UsingSmp() { - return !opt_no_daemon && Config.workers > 1; + return InDaemonMode() && NumberOfKids() > 1; } bool IamCoordinatorProcess() { - return UsingSmp() && KidIdentifier == Config.workers + 1; + return TheProcessKind == pkCoordinator; } bool @@ -851,7 +857,7 @@ // when there is a master and worker process, the master delegates // primary functions to its only kid - if (Config.workers == 1) + if (NumberOfKids() == 1) return IamWorkerProcess(); // in SMP mode, multiple kids delegate primary functions to the coordinator @@ -865,11 +871,27 @@ if (!InDaemonMode()) return 0; - // workers + the coordinator process - if (UsingSmp()) - return Config.workers + 1; + // XXX: detect and abort when called before workers/cache_dirs are parsed - return Config.workers; + const int rockDirs = Config.cacheSwap.n_strands; + + const bool needCoord = Config.workers > 1 || rockDirs > 0; + return (needCoord ? 1 : 0) + Config.workers + rockDirs; +} + +String +ProcessRoles() +{ + String roles = ""; + if (IamMasterProcess()) + roles.append(" master"); + if (IamCoordinatorProcess()) + roles.append(" coordinator"); + if (IamWorkerProcess()) + roles.append(" worker"); + if (IamDiskProcess()) + roles.append(" disker"); + return roles; } void diff -u -r -N squid-3.2.0.12/src/urn.cc squid-3.2.0.13/src/urn.cc --- squid-3.2.0.12/src/urn.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/src/urn.cc 2011-10-14 14:42:56.000000000 +1300 @@ -505,6 +505,8 @@ list[i].url = url; list[i].host = xstrdup(host); + // TODO: Use storeHas() or lock/unlock entry to avoid creating unlocked + // ones. list[i].flags.cached = storeGetPublic(url, m) ? 1 : 0; i++; } diff -u -r -N squid-3.2.0.12/tools/squidclient.cc squid-3.2.0.13/tools/squidclient.cc --- squid-3.2.0.12/tools/squidclient.cc 2011-09-16 23:37:30.000000000 +1200 +++ squid-3.2.0.13/tools/squidclient.cc 2011-10-14 14:42:56.000000000 +1300 @@ -211,7 +211,9 @@ int keep_alive = 0; int opt_noaccept = 0; int opt_verbose = 0; - int www_neg, proxy_neg; +#if HAVE_GSSAPI + int www_neg = 0, proxy_neg = 0; +#endif const char *hostname, *localhost; Ip::Address iaddr; char url[BUFSIZ], msg[MESSAGELEN], buf[BUFSIZ]; @@ -243,8 +245,6 @@ ping = 0; pcount = 0; ping_int = 1 * 1000; - www_neg = 0; - proxy_neg = 0; if (argc < 2) { usage(argv[0]); /* need URL */