diff -u -r -N squid-4.0.2/acinclude/lib-checks.m4 squid-4.0.3/acinclude/lib-checks.m4
--- squid-4.0.2/acinclude/lib-checks.m4	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/acinclude/lib-checks.m4	2015-11-28 07:30:57.000000000 -0800
@@ -93,7 +93,11 @@
     ],
     [
     SSLeay_add_ssl_algorithms();
-    SSL_CTX *sslContext = SSL_CTX_new(SSLv3_method());
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+    SSL_CTX *sslContext = SSL_CTX_new(TLS_method());
+#else
+    SSL_CTX *sslContext = SSL_CTX_new(SSLv23_method());
+#endif
     SSL *ssl = SSL_new(sslContext);
     X509* cert = SSL_get_certificate(ssl);
     return 0;
@@ -120,7 +124,11 @@
     ],
     [
     SSLeay_add_ssl_algorithms();
-    SSL_CTX *sslContext = SSL_CTX_new(SSLv3_method());
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+    SSL_CTX *sslContext = SSL_CTX_new(TLS_method());
+#else
+    SSL_CTX *sslContext = SSL_CTX_new(SSLv23_method());
+#endif
     X509 ***pCert = (X509 ***)sslContext->cert;
     X509 *sslCtxCert = pCert && *pCert ? **pCert : (X509 *)0x1;
     if (sslCtxCert != NULL)
diff -u -r -N squid-4.0.2/ChangeLog squid-4.0.3/ChangeLog
--- squid-4.0.2/ChangeLog	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/ChangeLog	2015-11-28 07:30:57.000000000 -0800
@@ -1,3 +1,15 @@
+Changes to squid-4.0.3 (28 Nov 2015):
+
+	- Bug 4372: missing template files
+	- Bug 4371: compile errors: no such file or directory: DiskIO/*/*DiskIOModule.o
+	- Bug 4368: A simpler and more robust HTTP request line parser
+	- Fix compile erorr on clang undefined reference to '__atomic_load_8'
+	- ext_kerberos_ldap_group_acl: Add missing workarounds for Heimdal Kerberos
+	- ext_ldap_group_acl: Allow unlimited LDAP search filter
+	- ext_unix_group_acl: Support -r parameter to strip @REALM from usernames
+	- ... and much code cleanup and polishing
+	- ... and all fixes from squid 3.5.11
+
 Changes to squid-4.0.2 (01 Nov 2015):
 
 	- Regression Bug 4351: compile errors when authentication modules disabled
@@ -60,6 +72,18 @@
 	- ... and many documentation changes
 	- ... and much code cleanup and polishing
 
+Changes to squid-3.5.12 (28 Nov 2015):
+
+	- Bug 4374: refresh_pattern config parser (%)
+	- Bug 4373: assertion 'calloutContext->redirect_state == REDIRECT_NONE'
+	- Bug 4228: links with krb5 libs despite --without options
+	- Fix SSL_get_certificate() problem detection
+	- Fix TLS handshake problem during Renegotiation
+	- Fix cache_peer forceddomain= in CONNECT
+	- Fix status code-based HTTP reason phrase for eCAP-generated messages
+	- Fix build errors in cpuafinity.cc
+	- ... and several documentation updates
+
 Changes to squid-3.5.11 (01 Nov 2015):
 
 	- Bug 3574: crashes on reconfigure and startup
diff -u -r -N squid-4.0.2/compat/cpu.h squid-4.0.3/compat/cpu.h
--- squid-4.0.2/compat/cpu.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/compat/cpu.h	2015-11-28 07:30:57.000000000 -0800
@@ -9,12 +9,42 @@
 #ifndef SQUID_COMPAT_CPU_H
 #define SQUID_COMPAT_CPU_H
 
-#if HAVE_CPU_AFFINITY
-
+#if HAVE_ERRNO_H
+#include <errno.h> /* for ENOTSUP */
+#endif
 #if HAVE_SCHED_H
 #include <sched.h>
 #endif
 
+#if !HAVE_CPU_AFFINITY
+/* failing replacements to minimize the number of if-HAVE_CPU_AFFINITYs */
+typedef struct {
+    int bits;
+} cpu_set_t;
+inline int sched_setaffinity(int, size_t, cpu_set_t *) { return ENOTSUP; }
+inline int sched_getaffinity(int, size_t, cpu_set_t *) { return ENOTSUP; }
+#endif /* HAVE_CPU_AFFINITY */
+
+#if !defined(CPU_SETSIZE)
+#define CPU_SETSIZE 0
+#endif
+
+#if !defined(CPU_ZERO)
+#define CPU_ZERO(set) (void)0
+#endif
+
+#if !defined(CPU_SET)
+#define CPU_SET(cpu, set) (void)0
+#endif
+
+#if !defined(CPU_CLR)
+#define CPU_CLR(cpu, set) (void)0
+#endif
+
+#if !defined(CPU_ISSET)
+#define CPU_ISSET(cpu, set) false
+#endif
+
 // glibc prior to 2.6 lacks CPU_COUNT
 #ifndef CPU_COUNT
 #define CPU_COUNT(set) CpuCount(set)
@@ -47,26 +77,5 @@
 }
 #endif /* CPU_AND */
 
-#else /* HAVE_CPU_AFFINITY */
-
-#if HAVE_ERRNO_H
-#include <errno.h> /* for ENOTSUP */
-#endif
-
-/* failing replacements to minimize the number of if-HAVE_CPU_AFFINITYs */
-typedef struct {
-    int bits;
-} cpu_set_t;
-#define CPU_SETSIZE 0
-#define CPU_COUNT(set) 0
-#define CPU_AND(destset, srcset1, srcset2) (void)0
-#define CPU_ZERO(set) (void)0
-#define CPU_SET(cpu, set) (void)0
-#define CPU_CLR(cpu, set) (void)0
-inline int sched_setaffinity(int, size_t, cpu_set_t *) { return ENOTSUP; }
-inline int sched_getaffinity(int, size_t, cpu_set_t *) { return ENOTSUP; }
-
-#endif /* HAVE_CPU_AFFINITY */
-
 #endif /* SQUID_COMPAT_CPU_H */
 
diff -u -r -N squid-4.0.2/compat/Makefile.in squid-4.0.3/compat/Makefile.in
--- squid-4.0.2/compat/Makefile.in	2015-11-01 04:18:49.000000000 -0800
+++ squid-4.0.3/compat/Makefile.in	2015-11-28 07:32:08.000000000 -0800
@@ -479,6 +479,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -512,7 +513,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/configure squid-4.0.3/configure
--- squid-4.0.2/configure	2015-11-01 04:19:43.000000000 -0800
+++ squid-4.0.3/configure	2015-11-28 07:33:06.000000000 -0800
@@ -1,7 +1,7 @@
 #! /bin/sh
 # From configure.ac Revision.
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Squid Web Proxy 4.0.2.
+# Generated by GNU Autoconf 2.69 for Squid Web Proxy 4.0.3.
 #
 # Report bugs to <http://bugs.squid-cache.org/>.
 #
@@ -595,8 +595,8 @@
 # Identity of this package.
 PACKAGE_NAME='Squid Web Proxy'
 PACKAGE_TARNAME='squid'
-PACKAGE_VERSION='4.0.2'
-PACKAGE_STRING='Squid Web Proxy 4.0.2'
+PACKAGE_VERSION='4.0.3'
+PACKAGE_STRING='Squid Web Proxy 4.0.3'
 PACKAGE_BUGREPORT='http://bugs.squid-cache.org/'
 PACKAGE_URL=''
 
@@ -783,9 +783,9 @@
 AIOLIB
 ENABLE_DISKIO_AIO_FALSE
 ENABLE_DISKIO_AIO_TRUE
-DISK_LINKOBJS
 DISK_LIBS
 DISK_MODULES
+ATOMICLIB
 BZR
 DEFAULT_SWAP_DIR
 DEFAULT_PID_FILE
@@ -1645,7 +1645,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 4.0.2 to adapt to many kinds of systems.
+\`configure' configures Squid Web Proxy 4.0.3 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1716,7 +1716,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of Squid Web Proxy 4.0.2:";;
+     short | recursive ) echo "Configuration of Squid Web Proxy 4.0.3:";;
    esac
   cat <<\_ACEOF
 
@@ -2123,7 +2123,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-Squid Web Proxy configure 4.0.2
+Squid Web Proxy configure 4.0.3
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -3227,7 +3227,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 4.0.2, which was
+It was created by Squid Web Proxy $as_me 4.0.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4094,7 +4094,7 @@
 
 # Define the identity of the package.
  PACKAGE='squid'
- VERSION='4.0.2'
+ VERSION='4.0.3'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -20362,6 +20362,65 @@
 $as_echo "$as_me: With dl" >&6;}
 fi
 
+## check for atomics library before anything that might need it
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing __atomic_load_8" >&5
+$as_echo_n "checking for library containing __atomic_load_8... " >&6; }
+if ${ac_cv_search___atomic_load_8+:} 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 __atomic_load_8 ();
+int
+main ()
+{
+return __atomic_load_8 ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' atomic; 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___atomic_load_8=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search___atomic_load_8+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search___atomic_load_8+:} false; then :
+
+else
+  ac_cv_search___atomic_load_8=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search___atomic_load_8" >&5
+$as_echo "$ac_cv_search___atomic_load_8" >&6; }
+ac_res=$ac_cv_search___atomic_load_8
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+  ATOMICLIB="-latomic"
+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 :
@@ -20538,7 +20597,7 @@
 
 DISK_LIBS=
 DISK_MODULES=
-DISK_LINKOBJS=
+
 
 
 
@@ -20677,7 +20736,6 @@
       fi
             if test "x$squid_opt_use_aio" = "xyes" ; then
         DISK_MODULES="$DISK_MODULES AIO"
-        DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/AIO/AIODiskIOModule.o"
 
 $as_echo "#define HAVE_DISKIO_MODULE_AIO 1" >>confdefs.h
 
@@ -20703,7 +20761,6 @@
       { $as_echo "$as_me:${as_lineno-$LINENO}: Enabling Blocking DiskIO module" >&5
 $as_echo "$as_me: Enabling Blocking DiskIO module" >&6;}
       DISK_MODULES="$DISK_MODULES Blocking"
-      DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/Blocking/BlockingDiskIOModule.o"
 
 $as_echo "#define HAVE_DISKIO_MODULE_BLOCKING 1" >>confdefs.h
 
@@ -20720,7 +20777,6 @@
           { $as_echo "$as_me:${as_lineno-$LINENO}: Enabling DiskDaemon DiskIO module" >&5
 $as_echo "$as_me: Enabling DiskDaemon DiskIO module" >&6;}
           DISK_MODULES="$DISK_MODULES DiskDaemon"
-          DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/DiskDaemon/DiskDaemonDiskIOModule.o"
 
 $as_echo "#define HAVE_DISKIO_MODULE_DISKDAEMON 1" >>confdefs.h
 
@@ -20956,7 +21012,6 @@
           { $as_echo "$as_me:${as_lineno-$LINENO}: Enabling DiskThreads DiskIO module" >&5
 $as_echo "$as_me: Enabling DiskThreads DiskIO module" >&6;}
           DISK_MODULES="$DISK_MODULES DiskThreads"
-          DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/DiskThreads/DiskThreadsDiskIOModule.o"
 
 $as_echo "#define HAVE_DISKIO_MODULE_DISKTHREADS 1" >>confdefs.h
 
@@ -20995,15 +21050,14 @@
       ;;
 
     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_echo "$as_me:${as_lineno-$LINENO}: DiskIO IpcIo module requires shared memory support" >&5
 $as_echo "$as_me: DiskIO IpcIo module requires shared memory support" >&6;}
         squid_disk_module_candidates_IpcIo=no
       else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Enabling IpcIo DiskIO module" >&5
+$as_echo "$as_me: Enabling IpcIo DiskIO module" >&6;}
         DISK_MODULES="$DISK_MODULES IpcIo"
-        DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/IpcIo/IpcIoDiskIOModule.o"
 
 $as_echo "#define HAVE_DISKIO_MODULE_IPCIO 1" >>confdefs.h
 
@@ -21019,7 +21073,6 @@
         { $as_echo "$as_me:${as_lineno-$LINENO}: Enabling Mmapped DiskIO module" >&5
 $as_echo "$as_me: Enabling Mmapped DiskIO module" >&6;}
         DISK_MODULES="$DISK_MODULES Mmapped"
-        DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/Mmapped/MmappedDiskIOModule.o"
 
 $as_echo "#define HAVE_DISKIO_MODULE_MMAPPED 1" >>confdefs.h
 
@@ -21031,7 +21084,6 @@
 $as_echo "$as_me: Enabling $module DiskIO module" >&6;}
       DISK_LIBS="$DISK_LIBS lib${module}.la"
       DISK_MODULES="$DISK_MODULES ${module}"
-      DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/${module}/${module}DiskIOModule.o"
       ;;
     esac
 done
@@ -21039,7 +21091,6 @@
 $as_echo "$as_me: IO Modules built: $DISK_MODULES" >&6;}
 
 
-
  if test "x$squid_disk_module_candidates_AIO" = "xyes"; then
   ENABLE_DISKIO_AIO_TRUE=
   ENABLE_DISKIO_AIO_FALSE='#'
@@ -23146,7 +23197,11 @@
 {
 
     SSLeay_add_ssl_algorithms();
-    SSL_CTX *sslContext = SSL_CTX_new(SSLv3_method());
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+    SSL_CTX *sslContext = SSL_CTX_new(TLS_method());
+#else
+    SSL_CTX *sslContext = SSL_CTX_new(SSLv23_method());
+#endif
     SSL *ssl = SSL_new(sslContext);
     X509* cert = SSL_get_certificate(ssl);
     return 0;
@@ -23196,7 +23251,11 @@
 {
 
     SSLeay_add_ssl_algorithms();
-    SSL_CTX *sslContext = SSL_CTX_new(SSLv3_method());
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+    SSL_CTX *sslContext = SSL_CTX_new(TLS_method());
+#else
+    SSL_CTX *sslContext = SSL_CTX_new(SSLv23_method());
+#endif
     X509 ***pCert = (X509 ***)sslContext->cert;
     X509 *sslCtxCert = pCert && *pCert ? **pCert : (X509 *)0x1;
     if (sslCtxCert != NULL)
@@ -23642,112 +23701,30 @@
 
 
 
-
-# Check whether --with-heimdal-krb5 was given.
-if test "${with_heimdal_krb5+set}" = set; then :
-  withval=$with_heimdal_krb5;
-case "$with_heimdal_krb5" in
-  yes|no)
-    : # Nothing special to do here
-    ;;
-  *)
-    if test ! -d "$withval" ; then
-      as_fn_error $? "--with-heimdal-krb5 path does not point to a directory" "$LINENO" 5
-    fi
-    if test -d "$with_heimdal_krb5/lib64" ; then
-      LIB_KRB5_PATH="-L$with_heimdal_krb5/lib64 -L$with_heimdal_krb5/lib"
-    else
-      LIB_KRB5_PATH="-L$with_heimdal_krb5/lib"
-    fi
-    CXXFLAGS="-I$with_heimdal_krb5/include $CXXFLAGS"
-    krb5confpath="$with_heimdal_krb5/bin"
-    with_heimdal_krb5=yes
-esac
-
-fi
-
-
-
-
-
-
-# Check whether --with-gnugss was given.
-if test "${with_gnugss+set}" = set; then :
-  withval=$with_gnugss;
-case "$with_gnugss" in
-  yes|no)
-    : # Nothing special to do here
-    ;;
-  *)
-    if test ! -d "$withval" ; then
-      as_fn_error $? "--with-gnugss path does not point to a directory" "$LINENO" 5
-    fi
-    if test ! -d "$with_gnugss/lib64" ; then
-      LIB_KRB5_PATH="-L$with_gnugss/lib64 -L$with_gnugss/lib"
-    else
-      LIB_KRB5_PATH="-L$with_gnugss/lib"
-    fi
-    CXXFLAGS="-I$with_gnugss/include $CXXFLAGS"
-    krb5confpath=
-    with_gnugss=yes
-esac
-
-fi
-
-
-
-# determine krb5 conflicts
-ac_with_krb5_count=0
-if test "x$with_mit_krb5" = "xyes"; then
- ac_with_krb5_count=`expr $ac_with_krb5_count + 1`
-fi
-if test "x$with_heimdal_krb5" = "xyes"; then
- ac_with_krb5_count=`expr $ac_with_krb5_count + 1`
-fi
-if test "x$with_gnugss" = "xyes"; then
- ac_with_krb5_count=`expr $ac_with_krb5_count + 1`
-fi
-
-if test $ac_with_krb5_count -gt 1 ; then
-  as_fn_error $? "Please choose only one Kerberos library." "$LINENO" 5
-elif test $ac_with_krb5_count -eq 0 ; then
+## find out if pkg-config or krb5-config will work
+if test "x$with_mit_krb5" != "xno"; then
   # find installed libs via pkg-config or krb5-config
+  squid_pc_krb5_name=
   if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gssapi-krb5 krb5\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gssapi-krb5 krb5") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"mit-krb5-gssapi mit-krb5\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "mit-krb5-gssapi mit-krb5") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  with_mit_krb5=yes
-fi
-  if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"heimdal-gssapi\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "heimdal-gssapi") 2>&5
+  squid_pc_krb5_name="mit-krb5-gssapi mit-krb5"
+else
+
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gssapi-krb5 krb5\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gssapi-krb5 krb5") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  with_heimdal_krb5=yes
+  squid_pc_krb5_name="gssapi-krb5 krb5"
 fi
-  if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gss\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gss") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  with_gnugss=yes
+
 fi
-  if test "x$with_mit_krb5" = "xyes"; then
-    ac_with_krb5_count=`expr $ac_with_krb5_count + 1`
-  fi
-  if test "x$with_heimdal_krb5" = "xyes"; then
-    ac_with_krb5_count=`expr $ac_with_krb5_count + 1`
-  fi
-  if test "x$with_gnugss" = "xyes"; then
-    ac_with_krb5_count=`expr $ac_with_krb5_count + 1`
-  fi
-  if test $ac_with_krb5_count -gt 1 ; then
-    as_fn_error $? "pkg-config found multiple Kerberos library. Please select one with --with-<kerberos package>" "$LINENO" 5
-  elif test $ac_with_krb5_count -eq 0 -a "$cross_compiling" = "no"; then
+  if test "x$squid_pc_krb5_name" = "x" -a "$cross_compiling" = "no"; then
     # Look for krb5-config (unless cross-compiling)
     # Extract the first word of "krb5-config", so it can be a program name with args.
 set dummy krb5-config; ac_word=$2
@@ -23795,30 +23772,28 @@
       ac_heimdal="`$ac_cv_path_krb5_config --version 2>/dev/null | grep -c -i heimdal`"
       ac_solaris="`$ac_cv_path_krb5_config --version 2>/dev/null | grep -c -i solaris`"
       ac_apple="`$ac_cv_path_krb5_config --vendor 2>/dev/null | grep -c -i apple`"
-      if test $ac_heimdal -gt 0 ; then
-	with_heimdal_krb5=yes
-        ac_with_krb5_count=1
-      fi
       if test $ac_solaris -gt 0 ; then
 	with_solaris_krb5=yes
-        ac_with_krb5_count=1
-      fi
-      if test $ac_apple -gt 0 ; then
+      elif test $ac_apple -gt 0 ; then
 	with_apple_krb5=yes
-        ac_with_krb5_count=1
-      fi
-      if test $ac_heimdal -eq 0 && test $ac_solaris -eq 0 && test $ac_apple -eq 0; then
-	with_mit_krb5=yes
-        ac_with_krb5_count=1
+      elif test $ac_heimdal -gt 0; then
+	with_mit_krb5=no
+        if test "x$with_mit_krb5" = "xyes"; then
+          as_fn_error $? "Could not find pkg-config or krb5-config for MIT Kerberos" "$LINENO" 5
+        fi
       fi
     else
-      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not find krb5-config in path" >&5
-$as_echo "$as_me: WARNING: Could not find krb5-config in path" >&2;}
+      if test "x$with_mit_krb5" = "xyes"; then
+        as_fn_error $? "Could not find krb5-config in path" "$LINENO" 5
+      else
+        with_mit_krb5=no
+      fi
     fi
   fi
 fi
 
-if test "x$with_mit_krb5" = "xyes" || test "x$with_apple_krb5" = "xyes" ; then
+# detect MIT Kerberos or Apple Kerberos dependencies
+if test "x$with_mit_krb5" != "xno" || test "x$with_apple_krb5" = "xyes" ; then
 
 # save state, key is squid_krb5_save
 squid_krb5_save_CFLAGS="${CFLAGS}"
@@ -23846,12 +23821,12 @@
     pkg_cv_LIB_KRB5_CFLAGS="$LIB_KRB5_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gssapi-krb5 krb5\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gssapi-krb5 krb5") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$squid_pc_krb5_name\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "$squid_pc_krb5_name") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_LIB_KRB5_CFLAGS=`$PKG_CONFIG --cflags "gssapi-krb5 krb5" 2>/dev/null`
+  pkg_cv_LIB_KRB5_CFLAGS=`$PKG_CONFIG --cflags "$squid_pc_krb5_name" 2>/dev/null`
 else
   pkg_failed=yes
 fi
@@ -23862,12 +23837,12 @@
     pkg_cv_LIB_KRB5_LIBS="$LIB_KRB5_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gssapi-krb5 krb5\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gssapi-krb5 krb5") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$squid_pc_krb5_name\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "$squid_pc_krb5_name") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_LIB_KRB5_LIBS=`$PKG_CONFIG --libs "gssapi-krb5 krb5" 2>/dev/null`
+  pkg_cv_LIB_KRB5_LIBS=`$PKG_CONFIG --libs "$squid_pc_krb5_name" 2>/dev/null`
 else
   pkg_failed=yes
 fi
@@ -23887,9 +23862,9 @@
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        LIB_KRB5_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "gssapi-krb5 krb5" 2>&1`
+	        LIB_KRB5_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$squid_pc_krb5_name" 2>&1`
         else
-	        LIB_KRB5_PKG_ERRORS=`$PKG_CONFIG --print-errors "gssapi-krb5 krb5" 2>&1`
+	        LIB_KRB5_PKG_ERRORS=`$PKG_CONFIG --print-errors "$squid_pc_krb5_name" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$LIB_KRB5_PKG_ERRORS" >&5
@@ -23973,6 +23948,7 @@
     eval "${squid_util_var_tosave2}=\"${squid_util_var_tosave}\""
 done
 
+      missing_required=
       { $as_echo "$as_me:${as_lineno-$LINENO}: Try to find Kerberos libraries in given path" >&5
 $as_echo "$as_me: Try to find Kerberos libraries in given path" >&6;}
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lcom_err" >&5
@@ -24009,7 +23985,9 @@
   LIB_KRB5_LIBS="-lcom_err $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'com_err' is required for MIT Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'com_err' is required for MIT Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'com_err' is required for MIT Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -24048,7 +24026,9 @@
   LIB_KRB5_LIBS="-lk5crypto $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'k5crypto' is required for MIT Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'k5crypto' is required for MIT Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'k5crypto' is required for MIT Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -24087,7 +24067,9 @@
   LIB_KRB5_LIBS="-lkrb5 $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'krb5' is required for MIT Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'krb5' is required for MIT Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'krb5' is required for MIT Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -24126,7 +24108,9 @@
   LIB_KRB5_LIBS="-lgssapi_krb5 $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'gssapi_krb5' is required for MIT Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'gssapi_krb5' is required for MIT Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'gssapi_krb5' is required for MIT Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -24157,9 +24141,11 @@
 done
 
 
+      if test "x$missing_required" = "xyes"; then
+        LIB_KRB5_LIBS=""
+      fi
     fi
 
-
 elif test $pkg_failed = untried; then
      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
@@ -24242,6 +24228,7 @@
     eval "${squid_util_var_tosave2}=\"${squid_util_var_tosave}\""
 done
 
+      missing_required=
       { $as_echo "$as_me:${as_lineno-$LINENO}: Try to find Kerberos libraries in given path" >&5
 $as_echo "$as_me: Try to find Kerberos libraries in given path" >&6;}
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lcom_err" >&5
@@ -24278,7 +24265,9 @@
   LIB_KRB5_LIBS="-lcom_err $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'com_err' is required for MIT Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'com_err' is required for MIT Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'com_err' is required for MIT Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -24317,7 +24306,9 @@
   LIB_KRB5_LIBS="-lk5crypto $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'k5crypto' is required for MIT Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'k5crypto' is required for MIT Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'k5crypto' is required for MIT Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -24356,7 +24347,9 @@
   LIB_KRB5_LIBS="-lkrb5 $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'krb5' is required for MIT Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'krb5' is required for MIT Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'krb5' is required for MIT Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -24395,7 +24388,9 @@
   LIB_KRB5_LIBS="-lgssapi_krb5 $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'gssapi_krb5' is required for MIT Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'gssapi_krb5' is required for MIT Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'gssapi_krb5' is required for MIT Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -24426,9 +24421,11 @@
 done
 
 
+      if test "x$missing_required" = "xyes"; then
+        LIB_KRB5_LIBS=""
+      fi
     fi
 
-
 else
 	LIB_KRB5_CFLAGS=$pkg_cv_LIB_KRB5_CFLAGS
 	LIB_KRB5_LIBS=$pkg_cv_LIB_KRB5_LIBS
@@ -25630,14 +25627,14 @@
 unset squid_tmp_define
 
 
-
   fi
-  if test "x$KRB5LIBS" = "x"; then
+  if test "x$with_mit_krb5" = "xyes" -a "x$KRB5LIBS" = "x"; then
     as_fn_error $? "Required Kerberos library not found" "$LINENO" 5
-    ac_with_krb5_count=0
+  elif test "x$KRB5LIBS" = "x"; then
+    with_mit_krb5=no
+    with_apple_krb5=no
   fi
 
-
 # rollback state, key is squid_krb5_save
 CFLAGS="${squid_krb5_save_CFLAGS}"
 CXXFLAGS="${squid_krb5_save_CXXFLAGS}"
@@ -25666,7 +25663,8 @@
 
 fi
 
-if test "x$with_solaris_krb5" = "xyes"; then
+# detect Solaris Kerberos dependencies
+if test "x$with_solaris_krb5" = "xyes" -a "x$KRB5LIBS" = "x"; then
 
 # save state, key is squid_krb5_save
 squid_krb5_save_CFLAGS="${CFLAGS}"
@@ -25769,6 +25767,7 @@
     eval "${squid_util_var_tosave2}=\"${squid_util_var_tosave}\""
 done
 
+    missing_required=
     { $as_echo "$as_me:${as_lineno-$LINENO}: Try to find Kerberos libraries in given path" >&5
 $as_echo "$as_me: Try to find Kerberos libraries in given path" >&6;}
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lkrb5" >&5
@@ -25805,7 +25804,9 @@
   LIB_KRB5_LIBS="-lkrb5 $LIB_KRB5_LIBS"
 else
 
-      as_fn_error $? "library 'krb5' is required for Solaris Kerberos" "$LINENO" 5
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'krb5' is required for Solaris Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'krb5' is required for Solaris Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -25844,7 +25845,9 @@
   LIB_KRB5_LIBS="-lgss $LIB_KRB5_LIBS"
 else
 
-      as_fn_error $? "library 'gss' is required for Solaris Kerberos" "$LINENO" 5
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'gss' is required for Solaris Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'gss' is required for Solaris Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -25875,6 +25878,9 @@
 done
 
 
+    if test "x$missing_required" = "xyes"; then
+      LIB_KRB5_LIBS=""
+    fi
   fi
 
   if test "x$LIB_KRB5_LIBS" != "x"; then
@@ -25991,7 +25997,6 @@
     fi
 
 
-
   ac_com_error_message=no
   if test "x$ac_cv_header_com_err_h" = "xyes" ; then
     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -27111,14 +27116,15 @@
 unset squid_tmp_define
 
 
-
   fi
-  if test "x$KRB5LIBS" = "x"; then
+  if test "x$with_mit_krb5" = "xyes" -a "x$KRB5LIBS" = "x"; then
+    # Error only if Solaris flavour was detected while looking for required MIT Kerberos
     as_fn_error $? "Required Kerberos library not found" "$LINENO" 5
-    ac_with_krb5_count=0
+  elif test "x$KRB5LIBS" = "x"; then
+    with_solaris_krb5=no
+    with_mit_krb5=no
   fi
 
-
 # rollback state, key is squid_krb5_save
 CFLAGS="${squid_krb5_save_CFLAGS}"
 CXXFLAGS="${squid_krb5_save_CXXFLAGS}"
@@ -27147,7 +27153,112 @@
 
 fi
 
-if test "x$with_heimdal_krb5" = "xyes"; then
+
+# Check whether --with-heimdal-krb5 was given.
+if test "${with_heimdal_krb5+set}" = set; then :
+  withval=$with_heimdal_krb5;
+case "$with_heimdal_krb5" in
+  yes|no)
+    : # Nothing special to do here
+    ;;
+  *)
+    if test ! -d "$withval" ; then
+      as_fn_error $? "--with-heimdal-krb5 path does not point to a directory" "$LINENO" 5
+    fi
+    if test -d "$with_heimdal_krb5/lib64" ; then
+      LIB_KRB5_PATH="-L$with_heimdal_krb5/lib64 -L$with_heimdal_krb5/lib"
+    else
+      LIB_KRB5_PATH="-L$with_heimdal_krb5/lib"
+    fi
+    CXXFLAGS="-I$with_heimdal_krb5/include $CXXFLAGS"
+    krb5confpath="$with_heimdal_krb5/bin"
+    with_heimdal_krb5=yes
+esac
+
+fi
+
+
+if test "x$with_heimdal_krb5" != "xno" -a "x$KRB5LIBS" = "x"; then
+  # find installed libs via pkg-config or krb5-config
+  if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"heimdal-krb5\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "heimdal-krb5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  squid_pc_krb5_name="heimdal-krb5"
+fi
+  if test "x$squid_pc_krb5_name" = "x"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"heimdal-gssapi\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "heimdal-gssapi") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  squid_pc_krb5_name="heimdal-gssapi"
+fi
+  fi
+  if test "x$squid_pc_krb5_name" != "x" -a "$cross_compiling" = "no"; then
+    # Look for krb5-config (unless cross-compiling)
+    # Extract the first word of "krb5-config", so it can be a program name with args.
+set dummy krb5-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_krb5_config+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $krb5_config in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_krb5_config="$krb5_config" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_krb5_config="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_krb5_config" && ac_cv_path_krb5_config="no"
+  ;;
+esac
+fi
+krb5_config=$ac_cv_path_krb5_config
+if test -n "$krb5_config"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $krb5_config" >&5
+$as_echo "$krb5_config" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    if test "x$ac_cv_path_krb5_config" != "xno" ; then
+      krb5confpath="`dirname $ac_cv_path_krb5_config`"
+      ac_heimdal="`$ac_cv_path_krb5_config --version 2>/dev/null | grep -c -i heimdal`"
+      if test "x$with_heimdal_krb5" = "xyes"; then
+        as_fn_error $? "Could not find pkg-config or krb5-config for Heimdal Kerberos" "$LINENO" 5
+      fi
+    else
+      if test "x$with_heimdal_krb5" = "xyes"; then
+        as_fn_error $? "Could not find krb5-config in path" "$LINENO" 5
+      else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not find krb5-config in path" >&5
+$as_echo "$as_me: WARNING: Could not find krb5-config in path" >&2;}
+        with_heimdal_krb5=no
+      fi
+    fi
+  fi
+fi
+if test "x$with_heimdal_krb5" != "xno" -a "x$KRB5LIBS" = "x"; then
 
 # save state, key is squid_krb5_save
 squid_krb5_save_CFLAGS="${CFLAGS}"
@@ -27175,12 +27286,12 @@
     pkg_cv_LIB_KRB5_CFLAGS="$LIB_KRB5_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"heimdal-gssapi\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "heimdal-gssapi") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$squid_pc_krb5_name\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "$squid_pc_krb5_name") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_LIB_KRB5_CFLAGS=`$PKG_CONFIG --cflags "heimdal-gssapi" 2>/dev/null`
+  pkg_cv_LIB_KRB5_CFLAGS=`$PKG_CONFIG --cflags "$squid_pc_krb5_name" 2>/dev/null`
 else
   pkg_failed=yes
 fi
@@ -27191,12 +27302,12 @@
     pkg_cv_LIB_KRB5_LIBS="$LIB_KRB5_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"heimdal-gssapi\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "heimdal-gssapi") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$squid_pc_krb5_name\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "$squid_pc_krb5_name") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_LIB_KRB5_LIBS=`$PKG_CONFIG --libs "heimdal-gssapi" 2>/dev/null`
+  pkg_cv_LIB_KRB5_LIBS=`$PKG_CONFIG --libs "$squid_pc_krb5_name" 2>/dev/null`
 else
   pkg_failed=yes
 fi
@@ -27216,9 +27327,9 @@
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        LIB_KRB5_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "heimdal-gssapi" 2>&1`
+	        LIB_KRB5_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$squid_pc_krb5_name" 2>&1`
         else
-	        LIB_KRB5_PKG_ERRORS=`$PKG_CONFIG --print-errors "heimdal-gssapi" 2>&1`
+	        LIB_KRB5_PKG_ERRORS=`$PKG_CONFIG --print-errors "$squid_pc_krb5_name" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$LIB_KRB5_PKG_ERRORS" >&5
@@ -27275,7 +27386,7 @@
         ac_krb5_config="$krb5confpath/krb5-config"
       fi
     fi
-    if test "x$ac_krb5_config" != "x" && test -x "$ac_krb5_config"; then
+    if test "x$ac_krb5_config" != "x" -a -x "$ac_krb5_config"; then
       # Get libs, etc
       { $as_echo "$as_me:${as_lineno-$LINENO}: Use krb5-config to get CXXFLAGS and LIBS" >&5
 $as_echo "$as_me: Use krb5-config to get CXXFLAGS and LIBS" >&6;}
@@ -27301,7 +27412,7 @@
     eval "${squid_util_var_tosave2}=\"${squid_util_var_tosave}\""
 done
 
-
+      missing_required=
       { $as_echo "$as_me:${as_lineno-$LINENO}: Try to find Kerberos libraries in given path" >&5
 $as_echo "$as_me: Try to find Kerberos libraries in given path" >&6;}
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lresolv" >&5
@@ -27338,7 +27449,9 @@
   LIB_KRB5_LIBS="-lresolv $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'resolv' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'resolv' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'resolv' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -27377,7 +27490,9 @@
   LIB_KRB5_LIBS="-lcrypt $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'crypt' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'crypt' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'crypt' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -27416,7 +27531,9 @@
   LIB_KRB5_LIBS="-lroken $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'roken' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'roken' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'roken' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -27535,7 +27652,9 @@
   LIB_KRB5_LIBS="-lcrypto $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'crypto' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'crypto' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'crypto' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -27574,7 +27693,9 @@
   LIB_KRB5_LIBS="-lcom_err $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'com_err' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'com_err' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'com_err' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -27653,7 +27774,9 @@
   LIB_KRB5_LIBS="-lasn1 $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'asn1' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'asn1' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'asn1' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -27692,7 +27815,9 @@
   LIB_KRB5_LIBS="-lkrb5 $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'krb5' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'krb5' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'krb5' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -27771,7 +27896,9 @@
   LIB_KRB5_LIBS="-lgssapi $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'gssapi' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'gssapi' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'gssapi' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -27802,9 +27929,11 @@
 done
 
 
+      if test "x$missing_required" = "xyes"; then
+        LIB_KRB5_LIBS=""
+      fi
     fi
 
-
 elif test $pkg_failed = untried; then
      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
@@ -27860,7 +27989,7 @@
         ac_krb5_config="$krb5confpath/krb5-config"
       fi
     fi
-    if test "x$ac_krb5_config" != "x" && test -x "$ac_krb5_config"; then
+    if test "x$ac_krb5_config" != "x" -a -x "$ac_krb5_config"; then
       # Get libs, etc
       { $as_echo "$as_me:${as_lineno-$LINENO}: Use krb5-config to get CXXFLAGS and LIBS" >&5
 $as_echo "$as_me: Use krb5-config to get CXXFLAGS and LIBS" >&6;}
@@ -27886,7 +28015,7 @@
     eval "${squid_util_var_tosave2}=\"${squid_util_var_tosave}\""
 done
 
-
+      missing_required=
       { $as_echo "$as_me:${as_lineno-$LINENO}: Try to find Kerberos libraries in given path" >&5
 $as_echo "$as_me: Try to find Kerberos libraries in given path" >&6;}
       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lresolv" >&5
@@ -27923,7 +28052,9 @@
   LIB_KRB5_LIBS="-lresolv $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'resolv' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'resolv' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'resolv' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -27962,7 +28093,9 @@
   LIB_KRB5_LIBS="-lcrypt $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'crypt' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'crypt' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'crypt' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -28001,7 +28134,9 @@
   LIB_KRB5_LIBS="-lroken $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'roken' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'roken' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'roken' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -28120,7 +28255,9 @@
   LIB_KRB5_LIBS="-lcrypto $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'crypto' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'crypto' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'crypto' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -28159,7 +28296,9 @@
   LIB_KRB5_LIBS="-lcom_err $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'com_err' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'com_err' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'com_err' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -28238,7 +28377,9 @@
   LIB_KRB5_LIBS="-lasn1 $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'asn1' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'asn1' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'asn1' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -28277,7 +28418,9 @@
   LIB_KRB5_LIBS="-lkrb5 $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'krb5' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'krb5' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'krb5' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -28356,7 +28499,9 @@
   LIB_KRB5_LIBS="-lgssapi $LIB_KRB5_LIBS"
 else
 
-        as_fn_error $? "library 'gssapi' is required for Heimdal Kerberos" "$LINENO" 5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'gssapi' is required for Heimdal Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'gssapi' is required for Heimdal Kerberos" >&2;}
+        missing_required=yes
 
 fi
 
@@ -28387,9 +28532,11 @@
 done
 
 
+      if test "x$missing_required" = "xyes"; then
+        LIB_KRB5_LIBS=""
+      fi
     fi
 
-
 else
 	LIB_KRB5_CFLAGS=$pkg_cv_LIB_KRB5_CFLAGS
 	LIB_KRB5_LIBS=$pkg_cv_LIB_KRB5_LIBS
@@ -28524,7 +28671,6 @@
     fi
 
 
-
   ac_com_error_message=no
   if test "x$ac_cv_header_com_err_h" = "xyes" ; then
     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -29644,14 +29790,16 @@
 unset squid_tmp_define
 
 
-
   fi
   if test "x$KRB5LIBS" = "x"; then
-    as_fn_error $? "Required Kerberos library not found" "$LINENO" 5
-    ac_with_krb5_count=0
+    if test test "x$with_heimdal_krb5" = "xyes"; then
+      as_fn_error $? "Required Heimdal Kerberos library not found" "$LINENO" 5
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Heimdal Kerberos library not found" >&5
+$as_echo "$as_me: WARNING: Heimdal Kerberos library not found" >&2;}
+    fi
   fi
 
-
 # rollback state, key is squid_krb5_save
 CFLAGS="${squid_krb5_save_CFLAGS}"
 CXXFLAGS="${squid_krb5_save_CXXFLAGS}"
@@ -29680,7 +29828,32 @@
 
 fi
 
-if test "x$with_gnugss" = "xyes"; then
+
+# Check whether --with-gnugss was given.
+if test "${with_gnugss+set}" = set; then :
+  withval=$with_gnugss;
+case "$with_gnugss" in
+  yes|no)
+    : # Nothing special to do here
+    ;;
+  *)
+    if test ! -d "$withval" ; then
+      as_fn_error $? "--with-gnugss path does not point to a directory" "$LINENO" 5
+    fi
+    if test ! -d "$with_gnugss/lib64" ; then
+      LIB_KRB5_PATH="-L$with_gnugss/lib64 -L$with_gnugss/lib"
+    else
+      LIB_KRB5_PATH="-L$with_gnugss/lib"
+    fi
+    CXXFLAGS="-I$with_gnugss/include $CXXFLAGS"
+    krb5confpath=
+    with_gnugss=yes
+esac
+
+fi
+
+
+if test "x$with_gnugss" != "xno" -a "x$KRB5LIBS" = "x"; then
 
 # save state, key is squid_krb5_save
 squid_krb5_save_CFLAGS="${CFLAGS}"
@@ -29796,12 +29969,12 @@
   LIB_KRB5_LIBS="-lgss $LIB_KRB5_LIBS"
 else
 
-      as_fn_error $? "library 'com_err' is required for GNU Kerberos" "$LINENO" 5
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'com_err' is required for GNU Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'com_err' is required for GNU Kerberos" >&2;}
 
 fi
 
 
-
 elif test $pkg_failed = untried; then
      	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
@@ -29845,12 +30018,12 @@
   LIB_KRB5_LIBS="-lgss $LIB_KRB5_LIBS"
 else
 
-      as_fn_error $? "library 'com_err' is required for GNU Kerberos" "$LINENO" 5
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: library 'com_err' is required for GNU Kerberos" >&5
+$as_echo "$as_me: WARNING: library 'com_err' is required for GNU Kerberos" >&2;}
 
 fi
 
 
-
 else
 	LIB_KRB5_CFLAGS=$pkg_cv_LIB_KRB5_CFLAGS
 	LIB_KRB5_LIBS=$pkg_cv_LIB_KRB5_LIBS
@@ -30132,14 +30305,16 @@
 
 unset squid_tmp_define
 
-
   fi
   if test "x$KRB5LIBS" = "x"; then
-    as_fn_error $? "Required Kerberos library not found" "$LINENO" 5
-    ac_with_krb5_count=0
+    if test test "x$with_gnugss" = "xyes"; then
+      as_fn_error $? "Required GNU GSS Kerberos library not found" "$LINENO" 5
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GNU GSS Kerberos library not found" >&5
+$as_echo "$as_me: WARNING: GNU GSS Kerberos library not found" >&2;}
+    fi
   fi
 
-
 # rollback state, key is squid_krb5_save
 CFLAGS="${squid_krb5_save_CFLAGS}"
 CXXFLAGS="${squid_krb5_save_CXXFLAGS}"
@@ -30167,7 +30342,8 @@
 
 
 fi
-if test $ac_with_krb5_count -gt 0 ; then
+
+if test "x$KRB5LIBS" != "x"; then
   with_krb5=yes
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: $KRB5_FLAVOUR Kerberos library support: ${with_krb5:=no} ${LIB_KRB5_PATH} ${LIB_KRB5_LIBS}" >&5
@@ -40627,7 +40803,7 @@
 
 rm -f core
 
-ac_config_files="$ac_config_files Makefile compat/Makefile contrib/Makefile doc/Makefile doc/manuals/Makefile doc/release-notes/Makefile errors/Makefile helpers/Makefile helpers/basic_auth/Makefile helpers/basic_auth/DB/Makefile helpers/basic_auth/fake/Makefile helpers/basic_auth/getpwnam/Makefile helpers/basic_auth/LDAP/Makefile helpers/basic_auth/NCSA/Makefile helpers/basic_auth/NIS/Makefile helpers/basic_auth/PAM/Makefile helpers/basic_auth/POP3/Makefile helpers/basic_auth/RADIUS/Makefile helpers/basic_auth/SASL/Makefile helpers/basic_auth/SMB/Makefile helpers/basic_auth/SMB_LM/Makefile helpers/basic_auth/SSPI/Makefile helpers/digest_auth/Makefile helpers/digest_auth/eDirectory/Makefile helpers/digest_auth/file/Makefile helpers/digest_auth/LDAP/Makefile helpers/external_acl/Makefile helpers/external_acl/AD_group/Makefile helpers/external_acl/delayer/Makefile helpers/external_acl/eDirectory_userip/Makefile helpers/external_acl/file_userip/Makefile helpers/external_acl/kerberos_ldap_group/Makefile helpers/external_acl/LDAP_group/Makefile helpers/external_acl/LM_group/Makefile helpers/external_acl/session/Makefile helpers/external_acl/SQL_session/Makefile helpers/external_acl/unix_group/Makefile helpers/external_acl/wbinfo_group/Makefile helpers/external_acl/time_quota/Makefile helpers/log_daemon/Makefile helpers/log_daemon/DB/Makefile helpers/log_daemon/file/Makefile helpers/negotiate_auth/Makefile helpers/negotiate_auth/kerberos/Makefile helpers/negotiate_auth/SSPI/Makefile helpers/negotiate_auth/wrapper/Makefile helpers/ntlm_auth/Makefile helpers/ntlm_auth/fake/Makefile helpers/ntlm_auth/smb_lm/Makefile helpers/ntlm_auth/SSPI/Makefile helpers/ssl/Makefile helpers/storeid_rewrite/Makefile helpers/storeid_rewrite/file/Makefile helpers/url_rewrite/Makefile helpers/url_rewrite/fake/Makefile helpers/url_rewrite/LFS/Makefile icons/Makefile lib/Makefile lib/libTrie/Makefile lib/libTrie/test/Makefile lib/ntlmauth/Makefile lib/profiler/Makefile lib/rfcnb/Makefile lib/smblib/Makefile lib/snmplib/Makefile scripts/Makefile src/Makefile src/acl/Makefile src/adaptation/Makefile src/adaptation/icap/Makefile src/adaptation/ecap/Makefile src/anyp/Makefile src/auth/Makefile src/auth/basic/Makefile src/auth/digest/Makefile src/auth/negotiate/Makefile src/auth/ntlm/Makefile src/base/Makefile src/clients/Makefile src/comm/Makefile src/dns/Makefile src/DiskIO/Makefile src/DiskIO/AIO/Makefile src/DiskIO/Blocking/Makefile src/DiskIO/DiskDaemon/Makefile src/DiskIO/DiskThreads/Makefile src/DiskIO/IpcIo/Makefile src/DiskIO/Mmapped/Makefile src/esi/Makefile src/eui/Makefile src/format/Makefile src/fs/Makefile src/ftp/Makefile src/helper/Makefile src/http/Makefile src/http/one/Makefile src/icmp/Makefile src/ident/Makefile src/ip/Makefile src/ipc/Makefile src/log/Makefile src/mem/Makefile src/mgr/Makefile src/parser/Makefile src/repl/Makefile src/security/Makefile src/servers/Makefile src/snmp/Makefile src/ssl/Makefile test-suite/Makefile tools/Makefile tools/helper-mux/Makefile tools/purge/Makefile tools/squidclient/Makefile tools/systemd/Makefile tools/sysvinit/Makefile"
+ac_config_files="$ac_config_files Makefile compat/Makefile contrib/Makefile doc/Makefile doc/manuals/Makefile doc/release-notes/Makefile errors/Makefile helpers/Makefile helpers/basic_auth/Makefile helpers/basic_auth/DB/Makefile helpers/basic_auth/fake/Makefile helpers/basic_auth/getpwnam/Makefile helpers/basic_auth/LDAP/Makefile helpers/basic_auth/NCSA/Makefile helpers/basic_auth/NIS/Makefile helpers/basic_auth/PAM/Makefile helpers/basic_auth/POP3/Makefile helpers/basic_auth/RADIUS/Makefile helpers/basic_auth/SASL/Makefile helpers/basic_auth/SMB/Makefile helpers/basic_auth/SMB_LM/Makefile helpers/basic_auth/SSPI/Makefile helpers/digest_auth/Makefile helpers/digest_auth/eDirectory/Makefile helpers/digest_auth/file/Makefile helpers/digest_auth/LDAP/Makefile helpers/external_acl/Makefile helpers/external_acl/AD_group/Makefile helpers/external_acl/delayer/Makefile helpers/external_acl/eDirectory_userip/Makefile helpers/external_acl/file_userip/Makefile helpers/external_acl/kerberos_ldap_group/Makefile helpers/external_acl/LDAP_group/Makefile helpers/external_acl/LM_group/Makefile helpers/external_acl/session/Makefile helpers/external_acl/SQL_session/Makefile helpers/external_acl/unix_group/Makefile helpers/external_acl/wbinfo_group/Makefile helpers/external_acl/time_quota/Makefile helpers/log_daemon/Makefile helpers/log_daemon/DB/Makefile helpers/log_daemon/file/Makefile helpers/negotiate_auth/Makefile helpers/negotiate_auth/kerberos/Makefile helpers/negotiate_auth/SSPI/Makefile helpers/negotiate_auth/wrapper/Makefile helpers/ntlm_auth/Makefile helpers/ntlm_auth/fake/Makefile helpers/ntlm_auth/smb_lm/Makefile helpers/ntlm_auth/SSPI/Makefile helpers/ssl/Makefile helpers/storeid_rewrite/Makefile helpers/storeid_rewrite/file/Makefile helpers/url_rewrite/Makefile helpers/url_rewrite/fake/Makefile helpers/url_rewrite/LFS/Makefile icons/Makefile lib/Makefile lib/libTrie/Makefile lib/libTrie/test/Makefile lib/ntlmauth/Makefile lib/profiler/Makefile lib/rfcnb/Makefile lib/smblib/Makefile lib/snmplib/Makefile scripts/Makefile src/Makefile src/acl/Makefile src/adaptation/Makefile src/adaptation/icap/Makefile src/adaptation/ecap/Makefile src/anyp/Makefile src/auth/Makefile src/auth/basic/Makefile src/auth/digest/Makefile src/auth/negotiate/Makefile src/auth/ntlm/Makefile src/base/Makefile src/clients/Makefile src/comm/Makefile src/dns/Makefile src/DiskIO/Makefile src/DiskIO/AIO/Makefile src/DiskIO/Blocking/Makefile src/DiskIO/DiskDaemon/Makefile src/DiskIO/DiskThreads/Makefile src/DiskIO/IpcIo/Makefile src/DiskIO/Mmapped/Makefile src/esi/Makefile src/eui/Makefile src/format/Makefile src/fs/Makefile src/ftp/Makefile src/helper/Makefile src/http/Makefile src/http/one/Makefile src/icmp/Makefile src/ident/Makefile src/ip/Makefile src/ipc/Makefile src/log/Makefile src/mem/Makefile src/mgr/Makefile src/parser/Makefile src/repl/Makefile src/security/Makefile src/servers/Makefile src/snmp/Makefile src/ssl/Makefile src/store/Makefile test-suite/Makefile tools/Makefile tools/helper-mux/Makefile tools/purge/Makefile tools/squidclient/Makefile tools/systemd/Makefile tools/sysvinit/Makefile"
 
 
 # must configure libltdl subdir unconditionally for "make distcheck" to work
@@ -41381,7 +41557,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 4.0.2, which was
+This file was extended by Squid Web Proxy $as_me 4.0.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -41447,7 +41623,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 4.0.2
+Squid Web Proxy config.status 4.0.3
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -42063,6 +42239,7 @@
     "src/servers/Makefile") CONFIG_FILES="$CONFIG_FILES src/servers/Makefile" ;;
     "src/snmp/Makefile") CONFIG_FILES="$CONFIG_FILES src/snmp/Makefile" ;;
     "src/ssl/Makefile") CONFIG_FILES="$CONFIG_FILES src/ssl/Makefile" ;;
+    "src/store/Makefile") CONFIG_FILES="$CONFIG_FILES src/store/Makefile" ;;
     "test-suite/Makefile") CONFIG_FILES="$CONFIG_FILES test-suite/Makefile" ;;
     "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;;
     "tools/helper-mux/Makefile") CONFIG_FILES="$CONFIG_FILES tools/helper-mux/Makefile" ;;
diff -u -r -N squid-4.0.2/configure.ac squid-4.0.3/configure.ac
--- squid-4.0.2/configure.ac	2015-11-01 04:19:43.000000000 -0800
+++ squid-4.0.3/configure.ac	2015-11-28 07:33:05.000000000 -0800
@@ -5,7 +5,7 @@
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
-AC_INIT([Squid Web Proxy],[4.0.2],[http://bugs.squid-cache.org/],[squid])
+AC_INIT([Squid Web Proxy],[4.0.3],[http://bugs.squid-cache.org/],[squid])
 AC_PREREQ(2.61)
 AC_CONFIG_HEADERS([include/autoconf.h])
 AC_CONFIG_AUX_DIR(cfgaux)
@@ -457,6 +457,10 @@
   AC_MSG_NOTICE([With dl])
 fi
 
+## check for atomics library before anything that might need it
+AC_SEARCH_LIBS([__atomic_load_8],[atomic],[ATOMICLIB="-latomic"],[])
+AC_SUBST(ATOMICLIB)
+
 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])
@@ -516,10 +520,10 @@
 dnl Setup the module paths etc.
 DISK_LIBS=
 DISK_MODULES=
-DISK_LINKOBJS=
 AH_TEMPLATE(HAVE_DISKIO_MODULE_AIO, [Whether POSIX AIO Disk I/O module is built])
 AH_TEMPLATE(HAVE_DISKIO_MODULE_BLOCKING, [Whether Blocking Disk I/O module is built])
 AH_TEMPLATE(HAVE_DISKIO_MODULE_DISKDAEMON, [Whether DiskDaemon Disk I/O module is built])
+AH_TEMPLATE(HAVE_DISKIO_MODULE_DISKTHREADS, [Whether DiskThreads Disk I/O module is built])
 AH_TEMPLATE(HAVE_DISKIO_MODULE_IPCIO, [Whether IpcIo Disk I/O module is built])
 AH_TEMPLATE(HAVE_DISKIO_MODULE_MMAPPED, [Whether Mmapped Disk I/O module is built])
 for module in $squid_disk_module_candidates none; do
@@ -567,7 +571,6 @@
       dnl Use the POSIX AIO pieces if we actually need them.
       if test "x$squid_opt_use_aio" = "xyes" ; then
         DISK_MODULES="$DISK_MODULES AIO"
-        DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/AIO/AIODiskIOModule.o"
         AC_DEFINE([HAVE_DISKIO_MODULE_AIO],1,[POSIX AIO Disk I/O module is built])
         case "$squid_host_os" in
           mingw)
@@ -587,7 +590,6 @@
     Blocking)
       AC_MSG_NOTICE([Enabling Blocking DiskIO module])
       DISK_MODULES="$DISK_MODULES Blocking"
-      DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/Blocking/BlockingDiskIOModule.o"
       AC_DEFINE([HAVE_DISKIO_MODULE_BLOCKING],1,[Blocking Disk I/O module is built])
       ;;
 
@@ -600,7 +602,6 @@
         *)
           AC_MSG_NOTICE([Enabling DiskDaemon DiskIO module])
           DISK_MODULES="$DISK_MODULES DiskDaemon"
-          DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/DiskDaemon/DiskDaemonDiskIOModule.o"
           AC_DEFINE([HAVE_DISKIO_MODULE_DISKDAEMON],1,[DiskDaemon Disk I/O module is built])
           ;;
         esac
@@ -677,7 +678,6 @@
         if test "x$squid_opt_use_diskthreads" = "xyes" ; then
           AC_MSG_NOTICE([Enabling DiskThreads DiskIO module])
           DISK_MODULES="$DISK_MODULES DiskThreads"
-          DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/DiskThreads/DiskThreadsDiskIOModule.o"
           AC_DEFINE([HAVE_DISKIO_MODULE_DISKTHREADS],1,[DiskThreads Disk I/O module is built])
         else
           AC_MSG_NOTICE([Native pthreads support disabled. DiskThreads module automaticaly disabled.])
@@ -687,13 +687,12 @@
       ;;
 
     IpcIo)
-      AC_MSG_NOTICE([Enabling IpcIo DiskIO module])
       if test "x$ac_cv_search_shm_open" = "xno" ; then
         AC_MSG_NOTICE([DiskIO IpcIo module requires shared memory support])
         squid_disk_module_candidates_IpcIo=no
       else
+        AC_MSG_NOTICE([Enabling IpcIo DiskIO module])
         DISK_MODULES="$DISK_MODULES IpcIo"
-        DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/IpcIo/IpcIoDiskIOModule.o"
         AC_DEFINE([HAVE_DISKIO_MODULE_IPCIO],1,[IpcIo Disk I/O module is built])
       fi
       ;;
@@ -707,7 +706,6 @@
       else
         AC_MSG_NOTICE([Enabling Mmapped DiskIO module])
         DISK_MODULES="$DISK_MODULES Mmapped"
-        DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/Mmapped/MmappedDiskIOModule.o"
         AC_DEFINE([HAVE_DISKIO_MODULE_MMAPPED],1,[Mmapped Disk I/O module is built])
       fi
       ;;
@@ -716,14 +714,12 @@
       AC_MSG_NOTICE([Enabling $module DiskIO module])
       DISK_LIBS="$DISK_LIBS lib${module}.la"
       DISK_MODULES="$DISK_MODULES ${module}"
-      DISK_LINKOBJS="$DISK_LINKOBJS DiskIO/${module}/${module}DiskIOModule.o"
       ;;
     esac
 done
 AC_MSG_NOTICE([IO Modules built: $DISK_MODULES])
 AC_SUBST(DISK_MODULES)
 AC_SUBST(DISK_LIBS)
-AC_SUBST(DISK_LINKOBJS)
 AM_CONDITIONAL([ENABLE_DISKIO_AIO], [test "x$squid_disk_module_candidates_AIO" = "xyes"])
 AC_SUBST(AIOLIB)
 AM_CONDITIONAL([ENABLE_WIN32_AIO], [test "x$squid_disk_module_candidates_AIO" = "xyes" -a "x$ENABLE_WIN32_AIO" = "x1"])
@@ -799,7 +795,7 @@
 	;;
     esac
 done
- 
+
 AM_CONDITIONAL(HAVE_FS_UFS,[test "x$squid_do_build_ufs" = "xtrue" ])
 AM_CONDITIONAL(HAVE_FS_ROCK,[test "x$squid_do_build_rock" = "xtrue" ])
 dnl hack: need to define those even if not used in the build system to
@@ -1377,87 +1373,14 @@
 AH_TEMPLATE(USE_MIT_KRB5,[MIT Kerberos support is available])
 AH_TEMPLATE(USE_SOLARIS_KRB5,[Solaris Kerberos support is available])
 
-dnl User may specify Heimdal Kerberos is needed from a non-standard location
-AC_ARG_WITH(heimdal-krb5,
-  AS_HELP_STRING([--without-heimdal-krb5],
-		 [Compile without Heimdal Kerberos support.]), [
-case "$with_heimdal_krb5" in
-  yes|no)
-    : # Nothing special to do here
-    ;;
-  *)
-    if test ! -d "$withval" ; then
-      AC_MSG_ERROR([--with-heimdal-krb5 path does not point to a directory])
-    fi
-    if test -d "$with_heimdal_krb5/lib64" ; then
-      LIB_KRB5_PATH="-L$with_heimdal_krb5/lib64 -L$with_heimdal_krb5/lib"
-    else 
-      LIB_KRB5_PATH="-L$with_heimdal_krb5/lib"
-    fi
-    CXXFLAGS="-I$with_heimdal_krb5/include $CXXFLAGS"
-    krb5confpath="$with_heimdal_krb5/bin"
-    with_heimdal_krb5=yes
-esac
-])
-AH_TEMPLATE(USE_HEIMDAL_KRB5,[Heimdal Kerberos support is available])
-
-
-
-dnl User may specify GNU gss is needed from a non-standard location
-AC_ARG_WITH(gnugss,
-  AS_HELP_STRING([--without-gnugss],
-		 [Compile without the GNU gss libraries.]), [
-case "$with_gnugss" in
-  yes|no)
-    : # Nothing special to do here
-    ;;
-  *)
-    if test ! -d "$withval" ; then
-      AC_MSG_ERROR([--with-gnugss path does not point to a directory])
-    fi
-    if test ! -d "$with_gnugss/lib64" ; then
-      LIB_KRB5_PATH="-L$with_gnugss/lib64 -L$with_gnugss/lib"
-    else
-      LIB_KRB5_PATH="-L$with_gnugss/lib"
-    fi
-    CXXFLAGS="-I$with_gnugss/include $CXXFLAGS"
-    krb5confpath=
-    with_gnugss=yes
-esac
-])
-AH_TEMPLATE(USE_GNUGSS,[GNU gss support is available])
-
-# determine krb5 conflicts
-ac_with_krb5_count=0
-if test "x$with_mit_krb5" = "xyes"; then
- ac_with_krb5_count=`expr $ac_with_krb5_count + 1`
-fi
-if test "x$with_heimdal_krb5" = "xyes"; then
- ac_with_krb5_count=`expr $ac_with_krb5_count + 1`
-fi
-if test "x$with_gnugss" = "xyes"; then
- ac_with_krb5_count=`expr $ac_with_krb5_count + 1`
-fi
-
-if test $ac_with_krb5_count -gt 1 ; then
-  AC_MSG_ERROR([Please choose only one Kerberos library.])
-elif test $ac_with_krb5_count -eq 0 ; then
+## find out if pkg-config or krb5-config will work
+if test "x$with_mit_krb5" != "xno"; then
   # find installed libs via pkg-config or krb5-config
-  PKG_CHECK_EXISTS(gssapi-krb5 krb5, [with_mit_krb5=yes])
-  PKG_CHECK_EXISTS(heimdal-gssapi, [with_heimdal_krb5=yes])
-  PKG_CHECK_EXISTS(gss, [with_gnugss=yes])
-  if test "x$with_mit_krb5" = "xyes"; then
-    ac_with_krb5_count=`expr $ac_with_krb5_count + 1`
-  fi
-  if test "x$with_heimdal_krb5" = "xyes"; then
-    ac_with_krb5_count=`expr $ac_with_krb5_count + 1`
-  fi
-  if test "x$with_gnugss" = "xyes"; then
-    ac_with_krb5_count=`expr $ac_with_krb5_count + 1`
-  fi
-  if test $ac_with_krb5_count -gt 1 ; then
-    AC_MSG_ERROR([pkg-config found multiple Kerberos library. Please select one with --with-<kerberos package>])
-  elif test $ac_with_krb5_count -eq 0 -a "$cross_compiling" = "no"; then
+  squid_pc_krb5_name=
+  PKG_CHECK_EXISTS(mit-krb5-gssapi mit-krb5, [squid_pc_krb5_name="mit-krb5-gssapi mit-krb5"],[
+    PKG_CHECK_EXISTS(gssapi-krb5 krb5, [squid_pc_krb5_name="gssapi-krb5 krb5"])
+  ])
+  if test "x$squid_pc_krb5_name" = "x" -a "$cross_compiling" = "no"; then
     # Look for krb5-config (unless cross-compiling)
     AC_PATH_PROG(krb5_config,krb5-config,no)
     if test "x$ac_cv_path_krb5_config" != "xno" ; then
@@ -1465,34 +1388,33 @@
       ac_heimdal="`$ac_cv_path_krb5_config --version 2>/dev/null | grep -c -i heimdal`"
       ac_solaris="`$ac_cv_path_krb5_config --version 2>/dev/null | grep -c -i solaris`"
       ac_apple="`$ac_cv_path_krb5_config --vendor 2>/dev/null | grep -c -i apple`"
-      if test $ac_heimdal -gt 0 ; then
-	with_heimdal_krb5=yes
-        ac_with_krb5_count=1
-      fi
       if test $ac_solaris -gt 0 ; then
 	with_solaris_krb5=yes
-        ac_with_krb5_count=1
-      fi
-      if test $ac_apple -gt 0 ; then
+      elif test $ac_apple -gt 0 ; then
 	with_apple_krb5=yes
-        ac_with_krb5_count=1
-      fi
-      if test $ac_heimdal -eq 0 && test $ac_solaris -eq 0 && test $ac_apple -eq 0; then
-	with_mit_krb5=yes
-        ac_with_krb5_count=1
+      elif test $ac_heimdal -gt 0; then
+	with_mit_krb5=no
+        if test "x$with_mit_krb5" = "xyes"; then
+          AC_MSG_ERROR([Could not find pkg-config or krb5-config for MIT Kerberos])
+        fi
       fi
     else
-      AC_MSG_WARN([Could not find krb5-config in path])
+      if test "x$with_mit_krb5" = "xyes"; then
+        AC_MSG_ERROR([Could not find krb5-config in path])
+      else
+        with_mit_krb5=no
+      fi
     fi
   fi
 fi
 
-if test "x$with_mit_krb5" = "xyes" || test "x$with_apple_krb5" = "xyes" ; then
+# detect MIT Kerberos or Apple Kerberos dependencies
+if test "x$with_mit_krb5" != "xno" || test "x$with_apple_krb5" = "xyes" ; then
   SQUID_STATE_SAVE([squid_krb5_save])
   LIBS="$LIBS $LIB_KRB5_PATH"
 
   # auto-detect using pkg-config
-  PKG_CHECK_MODULES([LIB_KRB5],[gssapi-krb5 krb5],,[
+  PKG_CHECK_MODULES([LIB_KRB5], $squid_pc_krb5_name,,[
     # look for krb5-config (unless cross-compiling)
     if test "$cross_compiling" = "no"; then
       if test "x$krb5confpath" = "x" ; then
@@ -1516,25 +1438,32 @@
       ## Detect libraries the hard way.
 
       SQUID_STATE_SAVE([squid_mit_save])
+      missing_required=
       AC_MSG_NOTICE([Try to find Kerberos libraries in given path])
       AC_CHECK_LIB(com_err, [main], [LIB_KRB5_LIBS="-lcom_err $LIB_KRB5_LIBS"],[
-        AC_MSG_ERROR([library 'com_err' is required for MIT Kerberos])
+        AC_MSG_WARN([library 'com_err' is required for MIT Kerberos])
+        missing_required=yes
       ])
       LIBS=$LIB_KRB5_LIBS
       AC_CHECK_LIB(k5crypto, [main], [LIB_KRB5_LIBS="-lk5crypto $LIB_KRB5_LIBS"],[
-        AC_MSG_ERROR([library 'k5crypto' is required for MIT Kerberos])
+        AC_MSG_WARN([library 'k5crypto' is required for MIT Kerberos])
+        missing_required=yes
       ])
       LIBS=$LIB_KRB5_LIBS
       AC_CHECK_LIB(krb5, [main], [LIB_KRB5_LIBS="-lkrb5 $LIB_KRB5_LIBS"],[
-        AC_MSG_ERROR([library 'krb5' is required for MIT Kerberos])
+        AC_MSG_WARN([library 'krb5' is required for MIT Kerberos])
+        missing_required=yes
       ])
       LIBS=$LIB_KRB5_LIBS
       AC_CHECK_LIB(gssapi_krb5, [main], [LIB_KRB5_LIBS="-lgssapi_krb5 $LIB_KRB5_LIBS"],[
-        AC_MSG_ERROR([library 'gssapi_krb5' is required for MIT Kerberos])
+        AC_MSG_WARN([library 'gssapi_krb5' is required for MIT Kerberos])
+        missing_required=yes
       ])
       SQUID_STATE_ROLLBACK([squid_mit_save])
+      if test "x$missing_required" = "xyes"; then
+        LIB_KRB5_LIBS=""
+      fi
     fi
-
   ])
 
   if test "x$LIB_KRB5_LIBS" != "x"; then
@@ -1559,17 +1488,18 @@
     AC_CHECK_HEADERS(profile.h)
 
     SQUID_CHECK_KRB5_FUNCS
-
   fi
-  if test "x$KRB5LIBS" = "x"; then
+  if test "x$with_mit_krb5" = "xyes" -a "x$KRB5LIBS" = "x"; then
     AC_MSG_ERROR([Required Kerberos library not found])
-    ac_with_krb5_count=0
+  elif test "x$KRB5LIBS" = "x"; then
+    with_mit_krb5=no
+    with_apple_krb5=no
   fi
-
   SQUID_STATE_ROLLBACK([squid_krb5_save])
 fi
 
-if test "x$with_solaris_krb5" = "xyes"; then
+# detect Solaris Kerberos dependencies
+if test "x$with_solaris_krb5" = "xyes" -a "x$KRB5LIBS" = "x"; then
   SQUID_STATE_SAVE([squid_krb5_save])
   LIBS="$LIBS $LIB_KRB5_PATH"
 
@@ -1603,15 +1533,21 @@
     CXXFLAGS="-I/usr/include/kerberosv5 $CXXFLAGS"
 
     SQUID_STATE_SAVE([squid_solaris_save])
+    missing_required=
     AC_MSG_NOTICE([Try to find Kerberos libraries in given path])
     AC_CHECK_LIB(krb5, [main], [LIB_KRB5_LIBS="-lkrb5 $LIB_KRB5_LIBS"],[
-      AC_MSG_ERROR([library 'krb5' is required for Solaris Kerberos])
+      AC_MSG_WARN([library 'krb5' is required for Solaris Kerberos])
+        missing_required=yes
     ])
     LIBS=$LIB_KRB5_LIBS
     AC_CHECK_LIB(gss, [main], [LIB_KRB5_LIBS="-lgss $LIB_KRB5_LIBS"],[
-      AC_MSG_ERROR([library 'gss' is required for Solaris Kerberos])
+      AC_MSG_WARN([library 'gss' is required for Solaris Kerberos])
+        missing_required=yes
     ])
     SQUID_STATE_ROLLBACK([squid_solaris_save])
+    if test "x$missing_required" = "xyes"; then
+      LIB_KRB5_LIBS=""
+    fi
   fi
 
   if test "x$LIB_KRB5_LIBS" != "x"; then
@@ -1636,24 +1572,72 @@
       AC_MSG_WARN([If you need Kerberos support you will have to patch])
       AC_MSG_WARN([your system. See contrib/solaris/solaris-krb5-include.patch])
     fi
-
     SQUID_CHECK_KRB5_FUNCS
-
   fi
-  if test "x$KRB5LIBS" = "x"; then
+  if test "x$with_mit_krb5" = "xyes" -a "x$KRB5LIBS" = "x"; then
+    # Error only if Solaris flavour was detected while looking for required MIT Kerberos
     AC_MSG_ERROR([Required Kerberos library not found])
-    ac_with_krb5_count=0
+  elif test "x$KRB5LIBS" = "x"; then
+    with_solaris_krb5=no
+    with_mit_krb5=no
   fi
-
   SQUID_STATE_ROLLBACK([squid_krb5_save])
 fi
 
-if test "x$with_heimdal_krb5" = "xyes"; then
+dnl User may specify Heimdal Kerberos is needed from a non-standard location
+AC_ARG_WITH(heimdal-krb5,
+  AS_HELP_STRING([--without-heimdal-krb5],
+		 [Compile without Heimdal Kerberos support.]), [
+case "$with_heimdal_krb5" in
+  yes|no)
+    : # Nothing special to do here
+    ;;
+  *)
+    if test ! -d "$withval" ; then
+      AC_MSG_ERROR([--with-heimdal-krb5 path does not point to a directory])
+    fi
+    if test -d "$with_heimdal_krb5/lib64" ; then
+      LIB_KRB5_PATH="-L$with_heimdal_krb5/lib64 -L$with_heimdal_krb5/lib"
+    else 
+      LIB_KRB5_PATH="-L$with_heimdal_krb5/lib"
+    fi
+    CXXFLAGS="-I$with_heimdal_krb5/include $CXXFLAGS"
+    krb5confpath="$with_heimdal_krb5/bin"
+    with_heimdal_krb5=yes
+esac
+])
+AH_TEMPLATE(USE_HEIMDAL_KRB5,[Heimdal Kerberos support is available])
+if test "x$with_heimdal_krb5" != "xno" -a "x$KRB5LIBS" = "x"; then
+  # find installed libs via pkg-config or krb5-config
+  PKG_CHECK_EXISTS(heimdal-krb5, [squid_pc_krb5_name="heimdal-krb5"])
+  if test "x$squid_pc_krb5_name" = "x"; then
+    PKG_CHECK_EXISTS(heimdal-gssapi, [squid_pc_krb5_name="heimdal-gssapi"])
+  fi
+  if test "x$squid_pc_krb5_name" != "x" -a "$cross_compiling" = "no"; then
+    # Look for krb5-config (unless cross-compiling)
+    AC_PATH_PROG(krb5_config,krb5-config,no)
+    if test "x$ac_cv_path_krb5_config" != "xno" ; then
+      krb5confpath="`dirname $ac_cv_path_krb5_config`"
+      ac_heimdal="`$ac_cv_path_krb5_config --version 2>/dev/null | grep -c -i heimdal`"
+      if test "x$with_heimdal_krb5" = "xyes"; then
+        AC_MSG_ERROR([Could not find pkg-config or krb5-config for Heimdal Kerberos])
+      fi
+    else
+      if test "x$with_heimdal_krb5" = "xyes"; then
+        AC_MSG_ERROR([Could not find krb5-config in path])
+      else
+        AC_MSG_WARN([Could not find krb5-config in path])
+        with_heimdal_krb5=no
+      fi
+    fi
+  fi
+fi
+if test "x$with_heimdal_krb5" != "xno" -a "x$KRB5LIBS" = "x"; then
   SQUID_STATE_SAVE([squid_krb5_save])
   LIBS="$LIBS $LIB_KRB5_PATH"
 
   # auto-detect using pkg-config
-  PKG_CHECK_MODULES([LIB_KRB5],[heimdal-gssapi],,[
+  PKG_CHECK_MODULES([LIB_KRB5], $squid_pc_krb5_name,,[
     # look for krb5-config (unless cross-compiling)
     if test "$cross_compiling" = "no"; then
       if test "x$krb5confpath" = "x" ; then
@@ -1665,7 +1649,7 @@
         ac_krb5_config="$krb5confpath/krb5-config"
       fi
     fi
-    if test "x$ac_krb5_config" != "x" && test -x "$ac_krb5_config"; then
+    if test "x$ac_krb5_config" != "x" -a -x "$ac_krb5_config"; then
       # Get libs, etc
       AC_MSG_NOTICE([Use krb5-config to get CXXFLAGS and LIBS])
       LIB_KRB5_CFLAGS="`$ac_krb5_config --cflags krb5 2>/dev/null`"
@@ -1676,18 +1660,21 @@
       ## For some OS pkg-config is broken or unavailable.
       ## Detect libraries the hard way.
       SQUID_STATE_SAVE([squid_heimdal_save])
-
+      missing_required=
       AC_MSG_NOTICE([Try to find Kerberos libraries in given path])
       AC_CHECK_LIB(resolv, [main], [LIB_KRB5_LIBS="-lresolv $LIB_KRB5_LIBS"],[
-        AC_MSG_ERROR([library 'resolv' is required for Heimdal Kerberos])
+        AC_MSG_WARN([library 'resolv' is required for Heimdal Kerberos])
+        missing_required=yes
       ])
       LIBS=$LIB_KRB5_LIBS
       AC_CHECK_LIB(crypt, [main], [LIB_KRB5_LIBS="-lcrypt $LIB_KRB5_LIBS"],[
-        AC_MSG_ERROR([library 'crypt' is required for Heimdal Kerberos])
+        AC_MSG_WARN([library 'crypt' is required for Heimdal Kerberos])
+        missing_required=yes
       ])
       LIBS=$LIB_KRB5_LIBS
       AC_CHECK_LIB(roken, [main], [LIB_KRB5_LIBS="-lroken $LIB_KRB5_LIBS"],[
-        AC_MSG_ERROR([library 'roken' is required for Heimdal Kerberos])
+        AC_MSG_WARN([library 'roken' is required for Heimdal Kerberos])
+        missing_required=yes
       ])
       LIBS=$LIB_KRB5_LIBS
       AC_CHECK_LIB(heimbase, [main], [LIB_KRB5_LIBS="-lheimbase $LIB_KRB5_LIBS"],[
@@ -1699,11 +1686,13 @@
       ])
       LIBS=$LIB_KRB5_LIBS
       AC_CHECK_LIB(crypto, [main], [LIB_KRB5_LIBS="-lcrypto $LIB_KRB5_LIBS"],[
-        AC_MSG_ERROR([library 'crypto' is required for Heimdal Kerberos])
+        AC_MSG_WARN([library 'crypto' is required for Heimdal Kerberos])
+        missing_required=yes
       ])
       LIBS=$LIB_KRB5_LIBS
       AC_CHECK_LIB(com_err, [main], [LIB_KRB5_LIBS="-lcom_err $LIB_KRB5_LIBS"],[
-        AC_MSG_ERROR([library 'com_err' is required for Heimdal Kerberos])
+        AC_MSG_WARN([library 'com_err' is required for Heimdal Kerberos])
+        missing_required=yes
       ])
       LIBS=$LIB_KRB5_LIBS
       AC_CHECK_LIB(hx509, [main], [LIB_KRB5_LIBS="-lhx509 $LIB_KRB5_LIBS"],[
@@ -1711,11 +1700,13 @@
       ])
       LIBS=$LIB_KRB5_LIBS
       AC_CHECK_LIB(asn1, [main], [LIB_KRB5_LIBS="-lasn1 $LIB_KRB5_LIBS"],[
-        AC_MSG_ERROR([library 'asn1' is required for Heimdal Kerberos])
+        AC_MSG_WARN([library 'asn1' is required for Heimdal Kerberos])
+        missing_required=yes
       ])
       LIBS=$LIB_KRB5_LIBS
       AC_CHECK_LIB(krb5, [main], [LIB_KRB5_LIBS="-lkrb5 $LIB_KRB5_LIBS"],[
-        AC_MSG_ERROR([library 'krb5' is required for Heimdal Kerberos])
+        AC_MSG_WARN([library 'krb5' is required for Heimdal Kerberos])
+        missing_required=yes
       ])
       LIBS=$LIB_KRB5_LIBS
       AC_CHECK_LIB(heimntlm, [main], [LIB_KRB5_LIBS="-lheimntlm $LIB_KRB5_LIBS"],[
@@ -1723,11 +1714,14 @@
       ])
       LIBS=$LIB_KRB5_LIBS
       AC_CHECK_LIB(gssapi, [main], [LIB_KRB5_LIBS="-lgssapi $LIB_KRB5_LIBS"],[
-        AC_MSG_ERROR([library 'gssapi' is required for Heimdal Kerberos])
+        AC_MSG_WARN([library 'gssapi' is required for Heimdal Kerberos])
+        missing_required=yes
       ])
       SQUID_STATE_ROLLBACK([squid_heimdal_save])
+      if test "x$missing_required" = "xyes"; then
+        LIB_KRB5_LIBS=""
+      fi
     fi
-
   ])
   if test "x$LIB_KRB5_LIBS" != "x"; then
     KRB5LIBS="$LIB_KRB5_PATH $LIB_KRB5_LIBS $KRB5LIBS"
@@ -1747,19 +1741,42 @@
     if test "x$squid_cv_broken_heimdal_krb5_h" = "xyes"; then
       AC_DEFINE(HAVE_BROKEN_HEIMDAL_KRB5_H, 1, [Define to 1 if Heimdal krb5.h is broken for C++])
     fi
-
     SQUID_CHECK_KRB5_FUNCS
-
   fi
   if test "x$KRB5LIBS" = "x"; then
-    AC_MSG_ERROR([Required Kerberos library not found])
-    ac_with_krb5_count=0
+    if test test "x$with_heimdal_krb5" = "xyes"; then
+      AC_MSG_ERROR([Required Heimdal Kerberos library not found])
+    else
+      AC_MSG_WARN([Heimdal Kerberos library not found])
+    fi
   fi
-
   SQUID_STATE_ROLLBACK([squid_krb5_save])
 fi
 
-if test "x$with_gnugss" = "xyes"; then
+dnl User may specify GNU gss is needed from a non-standard location
+AC_ARG_WITH(gnugss,
+  AS_HELP_STRING([--without-gnugss],
+		 [Compile without the GNU gss libraries.]), [
+case "$with_gnugss" in
+  yes|no)
+    : # Nothing special to do here
+    ;;
+  *)
+    if test ! -d "$withval" ; then
+      AC_MSG_ERROR([--with-gnugss path does not point to a directory])
+    fi
+    if test ! -d "$with_gnugss/lib64" ; then
+      LIB_KRB5_PATH="-L$with_gnugss/lib64 -L$with_gnugss/lib"
+    else
+      LIB_KRB5_PATH="-L$with_gnugss/lib"
+    fi
+    CXXFLAGS="-I$with_gnugss/include $CXXFLAGS"
+    krb5confpath=
+    with_gnugss=yes
+esac
+])
+AH_TEMPLATE(USE_GNUGSS,[GNU gss support is available])
+if test "x$with_gnugss" != "xno" -a "x$KRB5LIBS" = "x"; then
   SQUID_STATE_SAVE([squid_krb5_save])
   LIBS="$LIBS $LIB_KRB5_PATH"
 
@@ -1770,9 +1787,8 @@
 
     AC_MSG_NOTICE([Try to find Kerberos libraries in given path])
     AC_CHECK_LIB(gss, [main], [LIB_KRB5_LIBS="-lgss $LIB_KRB5_LIBS"],[
-      AC_MSG_ERROR([library 'com_err' is required for GNU Kerberos])
+      AC_MSG_WARN([library 'com_err' is required for GNU Kerberos])
     ])
-
   ])
 
   if test "x$LIB_KRB5_LIBS" != "x"; then
@@ -1796,16 +1812,18 @@
 
     SQUID_CHECK_WORKING_KRB5
     SQUID_DEFINE_BOOL(HAVE_KRB5,$squid_cv_working_krb5,[KRB5 support])
-
   fi
   if test "x$KRB5LIBS" = "x"; then
-    AC_MSG_ERROR([Required Kerberos library not found])
-    ac_with_krb5_count=0
+    if test test "x$with_gnugss" = "xyes"; then
+      AC_MSG_ERROR([Required GNU GSS Kerberos library not found])
+    else
+      AC_MSG_WARN([GNU GSS Kerberos library not found])
+    fi
   fi
-
   SQUID_STATE_ROLLBACK([squid_krb5_save])
 fi
-if test $ac_with_krb5_count -gt 0 ; then
+
+if test "x$KRB5LIBS" != "x"; then
   with_krb5=yes
 fi
 AC_MSG_NOTICE([$KRB5_FLAVOUR Kerberos library support: ${with_krb5:=no} ${LIB_KRB5_PATH} ${LIB_KRB5_LIBS}])
@@ -3861,6 +3879,7 @@
 	src/servers/Makefile
 	src/snmp/Makefile
 	src/ssl/Makefile
+	src/store/Makefile
 	test-suite/Makefile
 	tools/Makefile
 	tools/helper-mux/Makefile
diff -u -r -N squid-4.0.2/contrib/Makefile.in squid-4.0.3/contrib/Makefile.in
--- squid-4.0.2/contrib/Makefile.in	2015-11-01 04:18:49.000000000 -0800
+++ squid-4.0.3/contrib/Makefile.in	2015-11-28 07:32:08.000000000 -0800
@@ -190,6 +190,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -223,7 +224,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/doc/debug-sections.txt squid-4.0.3/doc/debug-sections.txt
--- squid-4.0.2/doc/debug-sections.txt	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/doc/debug-sections.txt	2015-11-28 07:30:57.000000000 -0800
@@ -49,6 +49,7 @@
 section 20    Storage Manager Swapfile Unpacker
 section 20    Storage Manager Swapin Functions
 section 20    Storage Manager Swapout Functions
+section 20    Store Controller
 section 20    Store Rebuild Routines
 section 20    Swap Dir base object
 section 21    Integer functions
@@ -69,6 +70,7 @@
 section 30    Ident (RFC 931)
 section 31    Hypertext Caching Protocol
 section 32    Asynchronous Disk I/O
+section 33    Client Request Pipeline
 section 33    Client-side Routines
 section 33    Transfer protocol servers
 section 35    FQDN Cache
@@ -92,6 +94,7 @@
 section 46    Access Log - Squid referer format
 section 46    Access Log - Squid useragent format
 section 47    Store Directory Routines
+section 47    Store Search
 section 48    Persistent Connections
 section 49    SNMP Interface
 section 49    SNMP support
diff -u -r -N squid-4.0.2/doc/Makefile.in squid-4.0.3/doc/Makefile.in
--- squid-4.0.2/doc/Makefile.in	2015-11-01 04:18:50.000000000 -0800
+++ squid-4.0.3/doc/Makefile.in	2015-11-28 07:32:08.000000000 -0800
@@ -245,6 +245,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -278,7 +279,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/doc/manuals/Makefile.in squid-4.0.3/doc/manuals/Makefile.in
--- squid-4.0.2/doc/manuals/Makefile.in	2015-11-01 04:18:50.000000000 -0800
+++ squid-4.0.3/doc/manuals/Makefile.in	2015-11-28 07:32:09.000000000 -0800
@@ -185,6 +185,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -218,7 +219,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/doc/release-notes/Makefile.in squid-4.0.3/doc/release-notes/Makefile.in
--- squid-4.0.2/doc/release-notes/Makefile.in	2015-11-01 04:18:50.000000000 -0800
+++ squid-4.0.3/doc/release-notes/Makefile.in	2015-11-28 07:32:09.000000000 -0800
@@ -185,6 +185,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -218,7 +219,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/doc/release-notes/release-4.html squid-4.0.3/doc/release-notes/release-4.html
--- squid-4.0.2/doc/release-notes/release-4.html	2015-11-01 05:13:09.000000000 -0800
+++ squid-4.0.3/doc/release-notes/release-4.html	2015-11-28 08:14:06.000000000 -0800
@@ -2,10 +2,10 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.71">
- <TITLE>Squid 4.0.2 release notes</TITLE>
+ <TITLE>Squid 4.0.3 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 4.0.2 release notes</H1>
+<H1>Squid 4.0.3 release notes</H1>
 
 <H2>Squid Developers</H2>
 <HR>
@@ -61,7 +61,7 @@
 <HR>
 <H2><A NAME="s1">1.</A> <A HREF="#toc1">Notice</A></H2>
 
-<P>The Squid Team are pleased to announce the release of Squid-4.0.2 for testing.</P>
+<P>The Squid Team are pleased to announce the release of Squid-4.0.3 for testing.</P>
 <P>This new release is available for download from 
 <A HREF="http://www.squid-cache.org/Versions/v4/">http://www.squid-cache.org/Versions/v4/</A> or the
 <A HREF="http://www.squid-cache.org/Download/http-mirrors.html">mirrors</A>.</P>
diff -u -r -N squid-4.0.2/errors/Makefile.in squid-4.0.3/errors/Makefile.in
--- squid-4.0.2/errors/Makefile.in	2015-11-01 04:18:50.000000000 -0800
+++ squid-4.0.3/errors/Makefile.in	2015-11-28 07:32:09.000000000 -0800
@@ -186,6 +186,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -219,7 +220,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/basic_auth/DB/basic_db_auth.8 squid-4.0.3/helpers/basic_auth/DB/basic_db_auth.8
--- squid-4.0.2/helpers/basic_auth/DB/basic_db_auth.8	2015-11-01 05:13:17.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/DB/basic_db_auth.8	2015-11-28 08:14:08.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_DB_AUTH 8"
-.TH BASIC_DB_AUTH 8 "2015-11-01" "perl v5.20.2" "User Contributed Perl Documentation"
+.TH BASIC_DB_AUTH 8 "2015-11-28" "perl v5.20.2" "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-4.0.2/helpers/basic_auth/DB/Makefile.in squid-4.0.3/helpers/basic_auth/DB/Makefile.in
--- squid-4.0.2/helpers/basic_auth/DB/Makefile.in	2015-11-01 04:18:50.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/DB/Makefile.in	2015-11-28 07:32:09.000000000 -0800
@@ -399,6 +399,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -432,7 +433,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/basic_auth/fake/Makefile.in squid-4.0.3/helpers/basic_auth/fake/Makefile.in
--- squid-4.0.2/helpers/basic_auth/fake/Makefile.in	2015-11-01 04:18:55.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/fake/Makefile.in	2015-11-28 07:32:14.000000000 -0800
@@ -446,6 +446,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -479,7 +480,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/basic_auth/getpwnam/Makefile.in squid-4.0.3/helpers/basic_auth/getpwnam/Makefile.in
--- squid-4.0.2/helpers/basic_auth/getpwnam/Makefile.in	2015-11-01 04:18:55.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/getpwnam/Makefile.in	2015-11-28 07:32:14.000000000 -0800
@@ -451,6 +451,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -484,7 +485,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/basic_auth/LDAP/Makefile.in squid-4.0.3/helpers/basic_auth/LDAP/Makefile.in
--- squid-4.0.2/helpers/basic_auth/LDAP/Makefile.in	2015-11-01 04:18:51.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/LDAP/Makefile.in	2015-11-28 07:32:10.000000000 -0800
@@ -452,6 +452,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -485,7 +486,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/basic_auth/Makefile.in squid-4.0.3/helpers/basic_auth/Makefile.in
--- squid-4.0.2/helpers/basic_auth/Makefile.in	2015-11-01 04:18:51.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/Makefile.in	2015-11-28 07:32:10.000000000 -0800
@@ -244,6 +244,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -277,7 +278,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/basic_auth/NCSA/Makefile.in squid-4.0.3/helpers/basic_auth/NCSA/Makefile.in
--- squid-4.0.2/helpers/basic_auth/NCSA/Makefile.in	2015-11-01 04:18:51.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/NCSA/Makefile.in	2015-11-28 07:32:10.000000000 -0800
@@ -473,6 +473,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -506,7 +507,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/basic_auth/NIS/Makefile.in squid-4.0.3/helpers/basic_auth/NIS/Makefile.in
--- squid-4.0.2/helpers/basic_auth/NIS/Makefile.in	2015-11-01 04:18:52.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/NIS/Makefile.in	2015-11-28 07:32:11.000000000 -0800
@@ -467,6 +467,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -500,7 +501,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/basic_auth/PAM/Makefile.in squid-4.0.3/helpers/basic_auth/PAM/Makefile.in
--- squid-4.0.2/helpers/basic_auth/PAM/Makefile.in	2015-11-01 04:18:52.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/PAM/Makefile.in	2015-11-28 07:32:11.000000000 -0800
@@ -450,6 +450,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -483,7 +484,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/basic_auth/POP3/basic_pop3_auth.8 squid-4.0.3/helpers/basic_auth/POP3/basic_pop3_auth.8
--- squid-4.0.2/helpers/basic_auth/POP3/basic_pop3_auth.8	2015-11-01 05:13:30.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/POP3/basic_pop3_auth.8	2015-11-28 08:14:14.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_POP3_AUTH 8"
-.TH BASIC_POP3_AUTH 8 "2015-11-01" "perl v5.20.2" "User Contributed Perl Documentation"
+.TH BASIC_POP3_AUTH 8 "2015-11-28" "perl v5.20.2" "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-4.0.2/helpers/basic_auth/POP3/Makefile.in squid-4.0.3/helpers/basic_auth/POP3/Makefile.in
--- squid-4.0.2/helpers/basic_auth/POP3/Makefile.in	2015-11-01 04:18:52.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/POP3/Makefile.in	2015-11-28 07:32:11.000000000 -0800
@@ -399,6 +399,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -432,7 +433,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/basic_auth/RADIUS/Makefile.in squid-4.0.3/helpers/basic_auth/RADIUS/Makefile.in
--- squid-4.0.2/helpers/basic_auth/RADIUS/Makefile.in	2015-11-01 04:18:53.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/RADIUS/Makefile.in	2015-11-28 07:32:12.000000000 -0800
@@ -472,6 +472,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -505,7 +506,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/basic_auth/SASL/Makefile.in squid-4.0.3/helpers/basic_auth/SASL/Makefile.in
--- squid-4.0.2/helpers/basic_auth/SASL/Makefile.in	2015-11-01 04:18:53.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/SASL/Makefile.in	2015-11-28 07:32:12.000000000 -0800
@@ -451,6 +451,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -484,7 +485,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/basic_auth/SMB/Makefile.in squid-4.0.3/helpers/basic_auth/SMB/Makefile.in
--- squid-4.0.2/helpers/basic_auth/SMB/Makefile.in	2015-11-01 04:18:54.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/SMB/Makefile.in	2015-11-28 07:32:13.000000000 -0800
@@ -455,6 +455,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -488,7 +489,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/basic_auth/SMB_LM/Makefile.in squid-4.0.3/helpers/basic_auth/SMB_LM/Makefile.in
--- squid-4.0.2/helpers/basic_auth/SMB_LM/Makefile.in	2015-11-01 04:18:54.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/SMB_LM/Makefile.in	2015-11-28 07:32:13.000000000 -0800
@@ -469,6 +469,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -502,7 +503,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/basic_auth/SSPI/Makefile.in squid-4.0.3/helpers/basic_auth/SSPI/Makefile.in
--- squid-4.0.2/helpers/basic_auth/SSPI/Makefile.in	2015-11-01 04:18:54.000000000 -0800
+++ squid-4.0.3/helpers/basic_auth/SSPI/Makefile.in	2015-11-28 07:32:14.000000000 -0800
@@ -476,6 +476,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -509,7 +510,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/digest_auth/eDirectory/Makefile.in squid-4.0.3/helpers/digest_auth/eDirectory/Makefile.in
--- squid-4.0.2/helpers/digest_auth/eDirectory/Makefile.in	2015-11-01 04:18:56.000000000 -0800
+++ squid-4.0.3/helpers/digest_auth/eDirectory/Makefile.in	2015-11-28 07:32:15.000000000 -0800
@@ -469,6 +469,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -502,7 +503,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/digest_auth/file/Makefile.in squid-4.0.3/helpers/digest_auth/file/Makefile.in
--- squid-4.0.2/helpers/digest_auth/file/Makefile.in	2015-11-01 04:18:57.000000000 -0800
+++ squid-4.0.3/helpers/digest_auth/file/Makefile.in	2015-11-28 07:32:16.000000000 -0800
@@ -473,6 +473,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -506,7 +507,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/digest_auth/LDAP/Makefile.in squid-4.0.3/helpers/digest_auth/LDAP/Makefile.in
--- squid-4.0.2/helpers/digest_auth/LDAP/Makefile.in	2015-11-01 04:18:56.000000000 -0800
+++ squid-4.0.3/helpers/digest_auth/LDAP/Makefile.in	2015-11-28 07:32:15.000000000 -0800
@@ -469,6 +469,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -502,7 +503,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/digest_auth/Makefile.in squid-4.0.3/helpers/digest_auth/Makefile.in
--- squid-4.0.2/helpers/digest_auth/Makefile.in	2015-11-01 04:18:56.000000000 -0800
+++ squid-4.0.3/helpers/digest_auth/Makefile.in	2015-11-28 07:32:15.000000000 -0800
@@ -244,6 +244,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -277,7 +278,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/external_acl/AD_group/Makefile.in squid-4.0.3/helpers/external_acl/AD_group/Makefile.in
--- squid-4.0.2/helpers/external_acl/AD_group/Makefile.in	2015-11-01 04:18:57.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/AD_group/Makefile.in	2015-11-28 07:32:16.000000000 -0800
@@ -451,6 +451,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -484,7 +485,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/external_acl/delayer/ext_delayer_acl.8 squid-4.0.3/helpers/external_acl/delayer/ext_delayer_acl.8
--- squid-4.0.2/helpers/external_acl/delayer/ext_delayer_acl.8	2015-11-01 05:13:47.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/delayer/ext_delayer_acl.8	2015-11-28 08:14:24.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_DELAYER_ACL 8"
-.TH EXT_DELAYER_ACL 8 "2015-11-01" "perl v5.20.2" "User Contributed Perl Documentation"
+.TH EXT_DELAYER_ACL 8 "2015-11-28" "perl v5.20.2" "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-4.0.2/helpers/external_acl/delayer/Makefile.in squid-4.0.3/helpers/external_acl/delayer/Makefile.in
--- squid-4.0.2/helpers/external_acl/delayer/Makefile.in	2015-11-01 04:18:58.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/delayer/Makefile.in	2015-11-28 07:32:18.000000000 -0800
@@ -399,6 +399,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -432,7 +433,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/external_acl/eDirectory_userip/Makefile.in squid-4.0.3/helpers/external_acl/eDirectory_userip/Makefile.in
--- squid-4.0.2/helpers/external_acl/eDirectory_userip/Makefile.in	2015-11-01 04:18:59.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/eDirectory_userip/Makefile.in	2015-11-28 07:32:18.000000000 -0800
@@ -453,6 +453,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -486,7 +487,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/external_acl/file_userip/Makefile.in squid-4.0.3/helpers/external_acl/file_userip/Makefile.in
--- squid-4.0.2/helpers/external_acl/file_userip/Makefile.in	2015-11-01 04:18:59.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/file_userip/Makefile.in	2015-11-28 07:32:18.000000000 -0800
@@ -452,6 +452,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -485,7 +486,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc squid-4.0.3/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc
--- squid-4.0.2/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc	2015-11-28 07:30:57.000000000 -0800
@@ -47,7 +47,20 @@
 
 #if HAVE_KRB5
 struct kstruct kparam;
+
+#if !HAVE_ERROR_MESSAGE && HAVE_KRB5_GET_ERROR_MESSAGE
+#define error_message(code) krb5_get_error_message(kparam.context,code)
+#elif !HAVE_ERROR_MESSAGE && HAVE_KRB5_GET_ERR_TEXT
+#define error_message(code) krb5_get_err_text(kparam.context,code)
+#elif !HAVE_ERROR_MESSAGE
+static char err_code[17];
+const char *KRB5_CALLCONV
+error_message(long code) {
+    snprintf(err_code,16,"%ld",code);
+    return err_code;
+}
 #endif
+#endif /* HAVE_KRB5 */
 
 void
 init_args(struct main_args *margs)
diff -u -r -N squid-4.0.2/helpers/external_acl/kerberos_ldap_group/Makefile.in squid-4.0.3/helpers/external_acl/kerberos_ldap_group/Makefile.in
--- squid-4.0.2/helpers/external_acl/kerberos_ldap_group/Makefile.in	2015-11-01 04:19:00.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/kerberos_ldap_group/Makefile.in	2015-11-28 07:32:19.000000000 -0800
@@ -522,6 +522,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -555,7 +556,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/external_acl/LDAP_group/ext_ldap_group_acl.cc squid-4.0.3/helpers/external_acl/LDAP_group/ext_ldap_group_acl.cc
--- squid-4.0.2/helpers/external_acl/LDAP_group/ext_ldap_group_acl.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/LDAP_group/ext_ldap_group_acl.cc	2015-11-28 07:30:57.000000000 -0800
@@ -44,8 +44,13 @@
 
 #define LDAP_DEPRECATED 1
 
+#include <algorithm>
 #include <cctype>
 #include <cstring>
+#include <iomanip>
+#include <iostream>
+#include <memory>
+#include <sstream>
 
 #if _SQUID_WINDOWS_ && !_SQUID_CYGWIN_
 
@@ -610,43 +615,30 @@
     return 0;
 }
 
-static int
-ldap_escape_value(char *escaped, int size, const char *src)
+static std::string
+ldap_escape_value(const std::string &src)
 {
-    int n = 0;
-    while (size > 4 && *src) {
-        switch (*src) {
+    std::stringstream str;
+    for (const auto &c : src) {
+        switch (c) {
         case '*':
         case '(':
         case ')':
         case '\\':
-            n += 3;
-            size -= 3;
-            if (size > 0) {
-                *escaped = '\\';
-                ++escaped;
-                snprintf(escaped, 3, "%02x", (unsigned char) *src);
-                ++src;
-                escaped += 2;
-            }
+            str << '\\' << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(c);
             break;
         default:
-            *escaped = *src;
-            ++escaped;
-            ++src;
-            ++n;
-            --size;
+            str << c;
         }
     }
-    *escaped = '\0';
-    return n;
+    return str.str();
 }
 
-static int
-build_filter(char *filter, int size, const char *templ, const char *user, const char *group)
+static bool
+build_filter(std::string &filter, const char *templ, const char *user, const char *group)
 {
-    int n;
-    while (*templ && size > 0) {
+    std::stringstream str;
+    while (*templ) {
         switch (*templ) {
         case '%':
             ++templ;
@@ -654,152 +646,142 @@
             case 'u':
             case 'v':
                 ++templ;
-                n = ldap_escape_value(filter, size, user);
-                size -= n;
-                filter += n;
+                str << ldap_escape_value(user);
                 break;
             case 'g':
             case 'a':
                 ++templ;
-                n = ldap_escape_value(filter, size, group);
-                size -= n;
-                filter += n;
+                str << ldap_escape_value(group);
                 break;
             default:
                 fprintf(stderr, "ERROR: Unknown filter template string %%%c\n", *templ);
-                return 1;
-                break;
+                filter = str.str();
+                return false;
             }
             break;
         case '\\':
             ++templ;
             if (*templ) {
-                *filter = *templ;
-                ++filter;
+                str << *templ;
                 ++templ;
-                --size;
             }
             break;
         default:
-            *filter = *templ;
-            ++filter;
+            str << *templ;
             ++templ;
-            --size;
             break;
         }
     }
-    if (size <= 0) {
-        fprintf(stderr, "ERROR: Filter too large\n");
-        return 1;
+    filter = str.str();
+    return true;
+}
+
+static std::string
+build_searchbase(const char *extension_dn, const char *base_dn)
+{
+    std::stringstream searchBaseStream;
+    if (extension_dn && *extension_dn)
+        searchBaseStream << extension_dn << ",";
+    searchBaseStream << basedn;
+    return searchBaseStream.str();
+}
+
+static bool ldap_search_ok(const int result)
+{
+    if (result == LDAP_SUCCESS)
+        return true;
+    if (noreferrals && result == LDAP_PARTIAL_RESULTS) {
+        /* Everything is fine. This is expected when referrals
+         * are disabled.
+         */
+        return true;
     }
-    *filter = '\0';
-    return 0;
+    std::cerr << PROGRAM_NAME << ": WARNING: LDAP search error '" <<
+              ldap_err2string(result) << "'" << std::endl;
+#if defined(NETSCAPE_SSL)
+    if (sslpath && ((result == LDAP_SERVER_DOWN) || (result == LDAP_CONNECT_ERROR))) {
+        int sslerr = PORT_GetError();
+        std::cerr << PROGRAM_NAME << ": WARNING: SSL error " << sslerr << " (" <<
+                  ldapssl_err2string(sslerr) << ")" << std::endl;
+    }
+#endif
+    return false;
 }
 
+typedef const std::unique_ptr<LDAPMessage, decltype(&ldap_msgfree)> LdapResult;
+
 static int
-searchLDAPGroup(LDAP * ld, char *group, char *member, char *extension_dn)
+searchLDAPGroup(LDAP * ld, const char *group, const char *member, const char *extension_dn)
 {
-    char filter[256];
-    static char searchbase[256];
+    std::string filter;
     LDAPMessage *res = NULL;
-    LDAPMessage *entry;
     int rc;
     char *searchattr[] = {(char *) LDAP_NO_ATTRS, NULL};
 
-    if (extension_dn && *extension_dn)
-        snprintf(searchbase, sizeof(searchbase), "%s,%s", extension_dn, basedn);
-    else
-        snprintf(searchbase, sizeof(searchbase), "%s", basedn);
-
-    if (build_filter(filter, sizeof(filter), searchfilter, member, group) != 0) {
-        fprintf(stderr, PROGRAM_NAME ": ERROR: Failed to construct LDAP search filter. filter=\"%s\", user=\"%s\", group=\"%s\"\n", filter, member, group);
+    const std::string searchbase = build_searchbase(extension_dn, basedn);
+    if (!build_filter(filter, searchfilter, member, group)) {
+        std::cerr << PROGRAM_NAME  << ": ERROR: Failed to construct LDAP search filter. filter=\"" <<
+                  filter.c_str() << "\", user=\"" << member << "\", group=\"" << group << "\"" << std::endl;
         return 1;
     }
-    debug("group filter '%s', searchbase '%s'\n", filter, searchbase);
+    debug("group filter '%s', searchbase '%s'\n", filter.c_str(), searchbase.c_str());
 
-    rc = ldap_search_s(ld, searchbase, searchscope, filter, searchattr, 1, &res);
-    if (rc != LDAP_SUCCESS) {
-        if (noreferrals && rc == LDAP_PARTIAL_RESULTS) {
-            /* Everything is fine. This is expected when referrals
-             * are disabled.
-             */
-        } else {
-            fprintf(stderr, PROGRAM_NAME ": WARNING: LDAP search error '%s'\n", ldap_err2string(rc));
-#if defined(NETSCAPE_SSL)
-            if (sslpath && ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR))) {
-                int sslerr = PORT_GetError();
-                fprintf(stderr, PROGRAM_NAME ": WARNING: SSL error %d (%s)\n", sslerr, ldapssl_err2string(sslerr));
-            }
-#endif
-            ldap_msgfree(res);
-            return 1;
-        }
-    }
-    entry = ldap_first_entry(ld, res);
-    if (!entry) {
-        ldap_msgfree(res);
+    rc = ldap_search_s(ld, searchbase.c_str(), searchscope, filter.c_str(), searchattr, 1, &res);
+    LdapResult ldapRes(res, ldap_msgfree);
+    if (!ldap_search_ok(rc))
         return 1;
+
+    return ldap_first_entry(ld, ldapRes.get()) ? 0 : 1;
+}
+
+static void
+formatWithString(std::string &formatted, const std::string &value)
+{
+    size_t start_pos = 0;
+    while ((start_pos = formatted.find("%s", start_pos)) != std::string::npos) {
+        formatted.replace(start_pos, 2, value);
+        start_pos += 2;
     }
-    ldap_msgfree(res);
-    return 0;
 }
 
 static int
 searchLDAP(LDAP * ld, char *group, char *login, char *extension_dn)
 {
 
+    const char *current_userdn = userbasedn ? userbasedn : basedn;
     if (usersearchfilter) {
-        char filter[8192];
-        char searchbase[8192];
-        char escaped_login[1024];
         LDAPMessage *res = NULL;
         LDAPMessage *entry;
         int rc;
         char *userdn;
         char *searchattr[] = {(char *) LDAP_NO_ATTRS, NULL};
-        if (extension_dn && *extension_dn)
-            snprintf(searchbase, sizeof(searchbase), "%s,%s", extension_dn, userbasedn ? userbasedn : basedn);
-        else
-            snprintf(searchbase, sizeof(searchbase), "%s", userbasedn ? userbasedn : basedn);
-        ldap_escape_value(escaped_login, sizeof(escaped_login), login);
-        snprintf(filter, sizeof(filter), usersearchfilter, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login);
-        debug("user filter '%s', searchbase '%s'\n", filter, searchbase);
-        rc = ldap_search_s(ld, searchbase, searchscope, filter, searchattr, 1, &res);
-        if (rc != LDAP_SUCCESS) {
-            if (noreferrals && rc == LDAP_PARTIAL_RESULTS) {
-                /* Everything is fine. This is expected when referrals
-                 * are disabled.
-                 */
-            } else {
-                fprintf(stderr, PROGRAM_NAME ": WARNING: LDAP search error '%s'\n", ldap_err2string(rc));
-#if defined(NETSCAPE_SSL)
-                if (sslpath && ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR))) {
-                    int sslerr = PORT_GetError();
-                    fprintf(stderr, PROGRAM_NAME ": WARNING: SSL error %d (%s)\n", sslerr, ldapssl_err2string(sslerr));
-                }
-#endif
-                ldap_msgfree(res);
-                return 1;
-            }
-        }
-        entry = ldap_first_entry(ld, res);
+        const std::string searchbase = build_searchbase(extension_dn, current_userdn);
+        std::string filter(usersearchfilter);
+        const std::string escaped_login = ldap_escape_value(login);
+        formatWithString(filter, escaped_login);
+
+        debug("user filter '%s', searchbase '%s'\n", filter.c_str(), searchbase.c_str());
+        rc = ldap_search_s(ld, searchbase.c_str(), searchscope, filter.c_str(), searchattr, 1, &res);
+        LdapResult ldapRes(res, ldap_msgfree);
+        if (!ldap_search_ok(rc))
+            return 1;
+        entry = ldap_first_entry(ld, ldapRes.get());
         if (!entry) {
-            fprintf(stderr, PROGRAM_NAME ": WARNING: User '%s' not found in '%s'\n", login, searchbase);
-            ldap_msgfree(res);
+            std::cerr << PROGRAM_NAME << ": WARNING: User '" << login <<
+                      " not found in '" << searchbase.c_str() << "'" << std::endl;
             return 1;
         }
         userdn = ldap_get_dn(ld, entry);
         rc = searchLDAPGroup(ld, group, userdn, extension_dn);
         squid_ldap_memfree(userdn);
-        ldap_msgfree(res);
         return rc;
     } else if (userdnattr) {
-        char dn[8192];
+        std::stringstream str;
+        str << userdnattr << "=" << login << ", ";
         if (extension_dn && *extension_dn)
-            snprintf(dn, 8192, "%s=%s, %s, %s", userdnattr, login, extension_dn, userbasedn ? userbasedn : basedn);
-        else
-            snprintf(dn, 8192, "%s=%s, %s", userdnattr, login, userbasedn ? userbasedn : basedn);
-        return searchLDAPGroup(ld, group, dn, extension_dn);
+            str << extension_dn << ", ";
+        str << current_userdn;
+        return searchLDAPGroup(ld, group, str.str().c_str(), extension_dn);
     } else {
         return searchLDAPGroup(ld, group, login, extension_dn);
     }
diff -u -r -N squid-4.0.2/helpers/external_acl/LDAP_group/Makefile.in squid-4.0.3/helpers/external_acl/LDAP_group/Makefile.in
--- squid-4.0.2/helpers/external_acl/LDAP_group/Makefile.in	2015-11-01 04:18:57.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/LDAP_group/Makefile.in	2015-11-28 07:32:16.000000000 -0800
@@ -454,6 +454,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -487,7 +488,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/external_acl/LM_group/Makefile.in squid-4.0.3/helpers/external_acl/LM_group/Makefile.in
--- squid-4.0.2/helpers/external_acl/LM_group/Makefile.in	2015-11-01 04:18:58.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/LM_group/Makefile.in	2015-11-28 07:32:17.000000000 -0800
@@ -452,6 +452,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -485,7 +486,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/external_acl/Makefile.in squid-4.0.3/helpers/external_acl/Makefile.in
--- squid-4.0.2/helpers/external_acl/Makefile.in	2015-11-01 04:18:58.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/Makefile.in	2015-11-28 07:32:17.000000000 -0800
@@ -244,6 +244,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -277,7 +278,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/external_acl/session/Makefile.in squid-4.0.3/helpers/external_acl/session/Makefile.in
--- squid-4.0.2/helpers/external_acl/session/Makefile.in	2015-11-01 04:19:00.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/session/Makefile.in	2015-11-28 07:32:19.000000000 -0800
@@ -451,6 +451,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -484,7 +485,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/external_acl/SQL_session/ext_sql_session_acl.8 squid-4.0.3/helpers/external_acl/SQL_session/ext_sql_session_acl.8
--- squid-4.0.2/helpers/external_acl/SQL_session/ext_sql_session_acl.8	2015-11-01 05:13:58.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/SQL_session/ext_sql_session_acl.8	2015-11-28 08:14:32.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_SQL_SESSION_ACL 8"
-.TH EXT_SQL_SESSION_ACL 8 "2015-11-01" "perl v5.20.2" "User Contributed Perl Documentation"
+.TH EXT_SQL_SESSION_ACL 8 "2015-11-28" "perl v5.20.2" "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-4.0.2/helpers/external_acl/SQL_session/Makefile.in squid-4.0.3/helpers/external_acl/SQL_session/Makefile.in
--- squid-4.0.2/helpers/external_acl/SQL_session/Makefile.in	2015-11-01 04:18:58.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/SQL_session/Makefile.in	2015-11-28 07:32:17.000000000 -0800
@@ -399,6 +399,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -432,7 +433,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/external_acl/time_quota/Makefile.in squid-4.0.3/helpers/external_acl/time_quota/Makefile.in
--- squid-4.0.2/helpers/external_acl/time_quota/Makefile.in	2015-11-01 04:19:00.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/time_quota/Makefile.in	2015-11-28 07:32:20.000000000 -0800
@@ -451,6 +451,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -485,7 +486,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/external_acl/unix_group/check_group.cc squid-4.0.3/helpers/external_acl/unix_group/check_group.cc
--- squid-4.0.2/helpers/external_acl/unix_group/check_group.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/unix_group/check_group.cc	2015-11-28 07:30:57.000000000 -0800
@@ -140,6 +140,8 @@
             "-p			Verify primary user group as well\n");
     fprintf(stderr,
             "-s			Strip NT domain from usernames\n");
+    fprintf(stderr,
+            "-r			Strip Kerberos realm from usernames\n");
 }
 
 int
@@ -148,13 +150,13 @@
     char *user, *suser, *p;
     char buf[HELPER_INPUT_BUFFER];
     char **grents = NULL;
-    int check_pw = 0, ch, ngroups = 0, i, j = 0, strip_dm = 0;
+    int check_pw = 0, ch, ngroups = 0, i, j = 0, strip_dm = 0, strip_rm = 0;
 
     /* make standard output line buffered */
     setvbuf(stdout, NULL, _IOLBF, 0);
 
     /* get user options */
-    while ((ch = getopt(argc, argv, "dspg:")) != -1) {
+    while ((ch = getopt(argc, argv, "dsrpg:")) != -1) {
         switch (ch) {
         case 'd':
             debug_enabled = 1;
@@ -162,6 +164,9 @@
         case 's':
             strip_dm = 1;
             break;
+        case 'r':
+            strip_rm = 1;
+            break;
         case 'p':
             check_pw = 1;
             break;
@@ -213,6 +218,10 @@
                 if (!suser) suser = strchr(user, '/');
                 if (suser && suser[1]) user = suser + 1;
             }
+            if (strip_rm) {
+                suser = strchr(user, '@');
+                if (suser) *suser = '\0';
+            }
             /* check groups supplied by Squid */
             while ((p = strtok(NULL, " ")) != NULL) {
                 rfc1738_unescape(p);
diff -u -r -N squid-4.0.2/helpers/external_acl/unix_group/Makefile.in squid-4.0.3/helpers/external_acl/unix_group/Makefile.in
--- squid-4.0.2/helpers/external_acl/unix_group/Makefile.in	2015-11-01 04:19:01.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/unix_group/Makefile.in	2015-11-28 07:32:20.000000000 -0800
@@ -452,6 +452,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -485,7 +486,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8 squid-4.0.3/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8
--- squid-4.0.2/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8	2015-11-01 05:14:03.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8	2015-11-28 08:14:35.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_WBINFO_GROUP_ACL 8"
-.TH EXT_WBINFO_GROUP_ACL 8 "2015-11-01" "perl v5.20.2" "User Contributed Perl Documentation"
+.TH EXT_WBINFO_GROUP_ACL 8 "2015-11-28" "perl v5.20.2" "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-4.0.2/helpers/external_acl/wbinfo_group/Makefile.in squid-4.0.3/helpers/external_acl/wbinfo_group/Makefile.in
--- squid-4.0.2/helpers/external_acl/wbinfo_group/Makefile.in	2015-11-01 04:19:01.000000000 -0800
+++ squid-4.0.3/helpers/external_acl/wbinfo_group/Makefile.in	2015-11-28 07:32:20.000000000 -0800
@@ -399,6 +399,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -432,7 +433,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/log_daemon/DB/log_db_daemon.8 squid-4.0.3/helpers/log_daemon/DB/log_db_daemon.8
--- squid-4.0.2/helpers/log_daemon/DB/log_db_daemon.8	2015-11-01 05:14:06.000000000 -0800
+++ squid-4.0.3/helpers/log_daemon/DB/log_db_daemon.8	2015-11-28 08:14:37.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "LOG_DB_DAEMON 8"
-.TH LOG_DB_DAEMON 8 "2015-11-01" "perl v5.20.2" "User Contributed Perl Documentation"
+.TH LOG_DB_DAEMON 8 "2015-11-28" "perl v5.20.2" "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-4.0.2/helpers/log_daemon/DB/Makefile.in squid-4.0.3/helpers/log_daemon/DB/Makefile.in
--- squid-4.0.2/helpers/log_daemon/DB/Makefile.in	2015-11-01 04:19:01.000000000 -0800
+++ squid-4.0.3/helpers/log_daemon/DB/Makefile.in	2015-11-28 07:32:21.000000000 -0800
@@ -399,6 +399,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -432,7 +433,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/log_daemon/file/Makefile.in squid-4.0.3/helpers/log_daemon/file/Makefile.in
--- squid-4.0.2/helpers/log_daemon/file/Makefile.in	2015-11-01 04:19:02.000000000 -0800
+++ squid-4.0.3/helpers/log_daemon/file/Makefile.in	2015-11-28 07:32:21.000000000 -0800
@@ -447,6 +447,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -480,7 +481,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/log_daemon/Makefile.in squid-4.0.3/helpers/log_daemon/Makefile.in
--- squid-4.0.2/helpers/log_daemon/Makefile.in	2015-11-01 04:19:01.000000000 -0800
+++ squid-4.0.3/helpers/log_daemon/Makefile.in	2015-11-28 07:32:21.000000000 -0800
@@ -244,6 +244,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -277,7 +278,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/Makefile.in squid-4.0.3/helpers/Makefile.in
--- squid-4.0.2/helpers/Makefile.in	2015-11-01 04:18:50.000000000 -0800
+++ squid-4.0.3/helpers/Makefile.in	2015-11-28 07:32:09.000000000 -0800
@@ -246,6 +246,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -279,7 +280,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/negotiate_auth/kerberos/Makefile.in squid-4.0.3/helpers/negotiate_auth/kerberos/Makefile.in
--- squid-4.0.2/helpers/negotiate_auth/kerberos/Makefile.in	2015-11-01 04:19:03.000000000 -0800
+++ squid-4.0.3/helpers/negotiate_auth/kerberos/Makefile.in	2015-11-28 07:32:22.000000000 -0800
@@ -534,6 +534,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -567,7 +568,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/negotiate_auth/Makefile.in squid-4.0.3/helpers/negotiate_auth/Makefile.in
--- squid-4.0.2/helpers/negotiate_auth/Makefile.in	2015-11-01 04:19:02.000000000 -0800
+++ squid-4.0.3/helpers/negotiate_auth/Makefile.in	2015-11-28 07:32:21.000000000 -0800
@@ -244,6 +244,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -277,7 +278,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/negotiate_auth/SSPI/Makefile.in squid-4.0.3/helpers/negotiate_auth/SSPI/Makefile.in
--- squid-4.0.2/helpers/negotiate_auth/SSPI/Makefile.in	2015-11-01 04:19:02.000000000 -0800
+++ squid-4.0.3/helpers/negotiate_auth/SSPI/Makefile.in	2015-11-28 07:32:22.000000000 -0800
@@ -449,6 +449,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -482,7 +483,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/negotiate_auth/wrapper/Makefile.in squid-4.0.3/helpers/negotiate_auth/wrapper/Makefile.in
--- squid-4.0.2/helpers/negotiate_auth/wrapper/Makefile.in	2015-11-01 04:19:03.000000000 -0800
+++ squid-4.0.3/helpers/negotiate_auth/wrapper/Makefile.in	2015-11-28 07:32:23.000000000 -0800
@@ -448,6 +448,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -481,7 +482,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/ntlm_auth/fake/Makefile.in squid-4.0.3/helpers/ntlm_auth/fake/Makefile.in
--- squid-4.0.2/helpers/ntlm_auth/fake/Makefile.in	2015-11-01 04:19:04.000000000 -0800
+++ squid-4.0.3/helpers/ntlm_auth/fake/Makefile.in	2015-11-28 07:32:24.000000000 -0800
@@ -450,6 +450,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -483,7 +484,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/ntlm_auth/Makefile.in squid-4.0.3/helpers/ntlm_auth/Makefile.in
--- squid-4.0.2/helpers/ntlm_auth/Makefile.in	2015-11-01 04:19:03.000000000 -0800
+++ squid-4.0.3/helpers/ntlm_auth/Makefile.in	2015-11-28 07:32:23.000000000 -0800
@@ -244,6 +244,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -277,7 +278,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/ntlm_auth/smb_lm/Makefile.in squid-4.0.3/helpers/ntlm_auth/smb_lm/Makefile.in
--- squid-4.0.2/helpers/ntlm_auth/smb_lm/Makefile.in	2015-11-01 04:19:05.000000000 -0800
+++ squid-4.0.3/helpers/ntlm_auth/smb_lm/Makefile.in	2015-11-28 07:32:24.000000000 -0800
@@ -452,6 +452,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -485,7 +486,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/ntlm_auth/SSPI/Makefile.in squid-4.0.3/helpers/ntlm_auth/SSPI/Makefile.in
--- squid-4.0.2/helpers/ntlm_auth/SSPI/Makefile.in	2015-11-01 04:19:04.000000000 -0800
+++ squid-4.0.3/helpers/ntlm_auth/SSPI/Makefile.in	2015-11-28 07:32:23.000000000 -0800
@@ -454,6 +454,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -487,7 +488,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/ssl/Makefile.in squid-4.0.3/helpers/ssl/Makefile.in
--- squid-4.0.2/helpers/ssl/Makefile.in	2015-11-01 04:19:05.000000000 -0800
+++ squid-4.0.3/helpers/ssl/Makefile.in	2015-11-28 07:32:24.000000000 -0800
@@ -394,6 +394,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -427,7 +428,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/storeid_rewrite/file/Makefile.in squid-4.0.3/helpers/storeid_rewrite/file/Makefile.in
--- squid-4.0.2/helpers/storeid_rewrite/file/Makefile.in	2015-11-01 04:19:05.000000000 -0800
+++ squid-4.0.3/helpers/storeid_rewrite/file/Makefile.in	2015-11-28 07:32:25.000000000 -0800
@@ -399,6 +399,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -432,7 +433,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/storeid_rewrite/file/storeid_file_rewrite.8 squid-4.0.3/helpers/storeid_rewrite/file/storeid_file_rewrite.8
--- squid-4.0.2/helpers/storeid_rewrite/file/storeid_file_rewrite.8	2015-11-01 05:14:24.000000000 -0800
+++ squid-4.0.3/helpers/storeid_rewrite/file/storeid_file_rewrite.8	2015-11-28 08:14:49.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "STOREID_FILE_REWRITE 8"
-.TH STOREID_FILE_REWRITE 8 "2015-11-01" "perl v5.20.2" "User Contributed Perl Documentation"
+.TH STOREID_FILE_REWRITE 8 "2015-11-28" "perl v5.20.2" "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-4.0.2/helpers/storeid_rewrite/Makefile.in squid-4.0.3/helpers/storeid_rewrite/Makefile.in
--- squid-4.0.2/helpers/storeid_rewrite/Makefile.in	2015-11-01 04:19:05.000000000 -0800
+++ squid-4.0.3/helpers/storeid_rewrite/Makefile.in	2015-11-28 07:32:24.000000000 -0800
@@ -244,6 +244,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -277,7 +278,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/url_rewrite/fake/Makefile.in squid-4.0.3/helpers/url_rewrite/fake/Makefile.in
--- squid-4.0.2/helpers/url_rewrite/fake/Makefile.in	2015-11-01 04:19:06.000000000 -0800
+++ squid-4.0.3/helpers/url_rewrite/fake/Makefile.in	2015-11-28 07:32:26.000000000 -0800
@@ -447,6 +447,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -480,7 +481,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/url_rewrite/LFS/Makefile.in squid-4.0.3/helpers/url_rewrite/LFS/Makefile.in
--- squid-4.0.2/helpers/url_rewrite/LFS/Makefile.in	2015-11-01 04:19:06.000000000 -0800
+++ squid-4.0.3/helpers/url_rewrite/LFS/Makefile.in	2015-11-28 07:32:25.000000000 -0800
@@ -399,6 +399,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -432,7 +433,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/helpers/url_rewrite/LFS/url_lfs_rewrite.8 squid-4.0.3/helpers/url_rewrite/LFS/url_lfs_rewrite.8
--- squid-4.0.2/helpers/url_rewrite/LFS/url_lfs_rewrite.8	2015-11-01 05:14:20.000000000 -0800
+++ squid-4.0.3/helpers/url_rewrite/LFS/url_lfs_rewrite.8	2015-11-28 08:14:47.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "URL_LFS_REWRITE 8"
-.TH URL_LFS_REWRITE 8 "2015-11-01" "perl v5.20.2" "User Contributed Perl Documentation"
+.TH URL_LFS_REWRITE 8 "2015-11-28" "perl v5.20.2" "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-4.0.2/helpers/url_rewrite/Makefile.in squid-4.0.3/helpers/url_rewrite/Makefile.in
--- squid-4.0.2/helpers/url_rewrite/Makefile.in	2015-11-01 04:19:06.000000000 -0800
+++ squid-4.0.3/helpers/url_rewrite/Makefile.in	2015-11-28 07:32:25.000000000 -0800
@@ -244,6 +244,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -277,7 +278,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/icons/Makefile.in squid-4.0.3/icons/Makefile.in
--- squid-4.0.2/icons/Makefile.in	2015-11-01 04:19:06.000000000 -0800
+++ squid-4.0.3/icons/Makefile.in	2015-11-28 07:32:26.000000000 -0800
@@ -215,6 +215,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -248,7 +249,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/include/version.h squid-4.0.3/include/version.h
--- squid-4.0.2/include/version.h	2015-11-01 04:19:43.000000000 -0800
+++ squid-4.0.3/include/version.h	2015-11-28 07:33:06.000000000 -0800
@@ -7,7 +7,7 @@
  */
 
 #ifndef SQUID_RELEASE_TIME
-#define SQUID_RELEASE_TIME 1446380250
+#define SQUID_RELEASE_TIME 1448724623
 #endif
 
 /*
diff -u -r -N squid-4.0.2/lib/libTrie/Makefile.in squid-4.0.3/lib/libTrie/Makefile.in
--- squid-4.0.2/lib/libTrie/Makefile.in	2015-11-01 04:19:07.000000000 -0800
+++ squid-4.0.3/lib/libTrie/Makefile.in	2015-11-28 07:32:27.000000000 -0800
@@ -509,6 +509,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -542,7 +543,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/lib/libTrie/test/Makefile.in squid-4.0.3/lib/libTrie/test/Makefile.in
--- squid-4.0.2/lib/libTrie/test/Makefile.in	2015-11-01 04:19:08.000000000 -0800
+++ squid-4.0.3/lib/libTrie/test/Makefile.in	2015-11-28 07:32:27.000000000 -0800
@@ -440,6 +440,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -473,7 +474,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/lib/Makefile.in squid-4.0.3/lib/Makefile.in
--- squid-4.0.2/lib/Makefile.in	2015-11-01 04:19:07.000000000 -0800
+++ squid-4.0.3/lib/Makefile.in	2015-11-28 07:32:26.000000000 -0800
@@ -547,6 +547,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -580,7 +581,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/lib/ntlmauth/Makefile.in squid-4.0.3/lib/ntlmauth/Makefile.in
--- squid-4.0.2/lib/ntlmauth/Makefile.in	2015-11-01 04:19:08.000000000 -0800
+++ squid-4.0.3/lib/ntlmauth/Makefile.in	2015-11-28 07:32:28.000000000 -0800
@@ -460,6 +460,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -493,7 +494,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/lib/profiler/Makefile.in squid-4.0.3/lib/profiler/Makefile.in
--- squid-4.0.2/lib/profiler/Makefile.in	2015-11-01 04:19:08.000000000 -0800
+++ squid-4.0.3/lib/profiler/Makefile.in	2015-11-28 07:32:28.000000000 -0800
@@ -464,6 +464,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -497,7 +498,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/lib/profiler/xprof_type.h squid-4.0.3/lib/profiler/xprof_type.h
--- squid-4.0.2/lib/profiler/xprof_type.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/lib/profiler/xprof_type.h	2015-11-28 07:30:57.000000000 -0800
@@ -70,7 +70,6 @@
     XPROF_storeClient_kickReads,
     XPROF_storeDirCallback,
     XPROF_StoreEntry_write,
-    XPROF_storeGet,
     XPROF_storeGetMemSpace,
     XPROF_storeMaintainSwapSpace,
     XPROF_storeRelease,
diff -u -r -N squid-4.0.2/lib/rfcnb/Makefile.in squid-4.0.3/lib/rfcnb/Makefile.in
--- squid-4.0.2/lib/rfcnb/Makefile.in	2015-11-01 04:19:09.000000000 -0800
+++ squid-4.0.3/lib/rfcnb/Makefile.in	2015-11-28 07:32:29.000000000 -0800
@@ -440,6 +440,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -473,7 +474,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/lib/smblib/Makefile.in squid-4.0.3/lib/smblib/Makefile.in
--- squid-4.0.2/lib/smblib/Makefile.in	2015-11-01 04:19:09.000000000 -0800
+++ squid-4.0.3/lib/smblib/Makefile.in	2015-11-28 07:32:29.000000000 -0800
@@ -441,6 +441,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -474,7 +475,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/lib/snmplib/Makefile.in squid-4.0.3/lib/snmplib/Makefile.in
--- squid-4.0.2/lib/snmplib/Makefile.in	2015-11-01 04:19:10.000000000 -0800
+++ squid-4.0.3/lib/snmplib/Makefile.in	2015-11-28 07:32:29.000000000 -0800
@@ -236,6 +236,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -269,7 +270,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/Makefile.in squid-4.0.3/Makefile.in
--- squid-4.0.2/Makefile.in	2015-11-01 04:18:49.000000000 -0800
+++ squid-4.0.3/Makefile.in	2015-11-28 07:32:07.000000000 -0800
@@ -272,6 +272,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -305,7 +306,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/RELEASENOTES.html squid-4.0.3/RELEASENOTES.html
--- squid-4.0.2/RELEASENOTES.html	2015-11-01 05:13:09.000000000 -0800
+++ squid-4.0.3/RELEASENOTES.html	2015-11-28 08:14:06.000000000 -0800
@@ -2,10 +2,10 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.71">
- <TITLE>Squid 4.0.2 release notes</TITLE>
+ <TITLE>Squid 4.0.3 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 4.0.2 release notes</H1>
+<H1>Squid 4.0.3 release notes</H1>
 
 <H2>Squid Developers</H2>
 <HR>
@@ -61,7 +61,7 @@
 <HR>
 <H2><A NAME="s1">1.</A> <A HREF="#toc1">Notice</A></H2>
 
-<P>The Squid Team are pleased to announce the release of Squid-4.0.2 for testing.</P>
+<P>The Squid Team are pleased to announce the release of Squid-4.0.3 for testing.</P>
 <P>This new release is available for download from 
 <A HREF="http://www.squid-cache.org/Versions/v4/">http://www.squid-cache.org/Versions/v4/</A> or the
 <A HREF="http://www.squid-cache.org/Download/http-mirrors.html">mirrors</A>.</P>
diff -u -r -N squid-4.0.2/scripts/Makefile.in squid-4.0.3/scripts/Makefile.in
--- squid-4.0.2/scripts/Makefile.in	2015-11-01 04:19:10.000000000 -0800
+++ squid-4.0.3/scripts/Makefile.in	2015-11-28 07:32:29.000000000 -0800
@@ -188,6 +188,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -221,7 +222,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/acl/FilledChecklist.cc squid-4.0.3/src/acl/FilledChecklist.cc
--- squid-4.0.2/src/acl/FilledChecklist.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/acl/FilledChecklist.cc	2015-11-28 07:30:57.000000000 -0800
@@ -70,7 +70,7 @@
 showDebugWarning(const char *msg)
 {
     static uint16_t count = 0;
-    if (count > 100)
+    if (count > 10)
         return;
 
     ++count;
diff -u -r -N squid-4.0.2/src/acl/Makefile.in squid-4.0.3/src/acl/Makefile.in
--- squid-4.0.2/src/acl/Makefile.in	2015-11-01 04:19:16.000000000 -0800
+++ squid-4.0.3/src/acl/Makefile.in	2015-11-28 07:32:36.000000000 -0800
@@ -526,6 +526,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -559,7 +560,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/adaptation/ecap/Makefile.in squid-4.0.3/src/adaptation/ecap/Makefile.in
--- squid-4.0.2/src/adaptation/ecap/Makefile.in	2015-11-01 04:19:17.000000000 -0800
+++ squid-4.0.3/src/adaptation/ecap/Makefile.in	2015-11-28 07:32:37.000000000 -0800
@@ -467,6 +467,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -500,7 +501,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/adaptation/ecap/MessageRep.cc squid-4.0.3/src/adaptation/ecap/MessageRep.cc
--- squid-4.0.2/src/adaptation/ecap/MessageRep.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/adaptation/ecap/MessageRep.cc	2015-11-28 07:30:57.000000000 -0800
@@ -290,7 +290,7 @@
 void
 Adaptation::Ecap::StatusLineRep::statusCode(int code)
 {
-    theMessage.sline.set(theMessage.sline.version, static_cast<Http::StatusCode>(code), theMessage.sline.reason());
+    theMessage.sline.set(theMessage.sline.version, static_cast<Http::StatusCode>(code), nullptr);
 }
 
 int
@@ -301,9 +301,11 @@
 }
 
 void
-Adaptation::Ecap::StatusLineRep::reasonPhrase(const Area &str)
+Adaptation::Ecap::StatusLineRep::reasonPhrase(const Area &)
 {
-    theMessage.sline.set(theMessage.sline.version, theMessage.sline.status(), str.toString().c_str());
+    // Squid does not support external custom reason phrases so we have
+    // to just reset it (in case there was a custom internal reason set)
+    theMessage.sline.resetReason();
 }
 
 Adaptation::Ecap::StatusLineRep::Area
diff -u -r -N squid-4.0.2/src/adaptation/icap/Makefile.in squid-4.0.3/src/adaptation/icap/Makefile.in
--- squid-4.0.2/src/adaptation/icap/Makefile.in	2015-11-01 04:19:17.000000000 -0800
+++ squid-4.0.3/src/adaptation/icap/Makefile.in	2015-11-28 07:32:38.000000000 -0800
@@ -462,6 +462,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -495,7 +496,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/adaptation/icap/ServiceRep.h squid-4.0.3/src/adaptation/icap/ServiceRep.h
--- squid-4.0.2/src/adaptation/icap/ServiceRep.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/adaptation/icap/ServiceRep.h	2015-11-28 07:30:57.000000000 -0800
@@ -110,7 +110,7 @@
     // receive either an ICAP OPTIONS response header or an abort message
     virtual void noteAdaptationAnswer(const Answer &answer);
 
-    Security::ContextPointer sslContext;
+    Security::ContextPtr sslContext;
 #if USE_OPENSSL
     SSL_SESSION *sslSession;
 #endif
diff -u -r -N squid-4.0.2/src/adaptation/icap/Xaction.cc squid-4.0.3/src/adaptation/icap/Xaction.cc
--- squid-4.0.2/src/adaptation/icap/Xaction.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/adaptation/icap/Xaction.cc	2015-11-28 07:30:57.000000000 -0800
@@ -62,7 +62,7 @@
     /* PeerConnector API */
     virtual Security::SessionPointer initializeSsl();
     virtual void noteNegotiationDone(ErrorState *error);
-    virtual Security::ContextPointer getSslContext() {return icapService->sslContext;}
+    virtual Security::ContextPtr getSslContext() {return icapService->sslContext;}
 
 private:
     Adaptation::Icap::ServiceRep::Pointer icapService;
diff -u -r -N squid-4.0.2/src/adaptation/Makefile.in squid-4.0.3/src/adaptation/Makefile.in
--- squid-4.0.2/src/adaptation/Makefile.in	2015-11-01 04:19:16.000000000 -0800
+++ squid-4.0.3/src/adaptation/Makefile.in	2015-11-28 07:32:37.000000000 -0800
@@ -506,6 +506,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -539,7 +540,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/anyp/Makefile.in squid-4.0.3/src/anyp/Makefile.in
--- squid-4.0.2/src/anyp/Makefile.in	2015-11-01 04:19:17.000000000 -0800
+++ squid-4.0.3/src/anyp/Makefile.in	2015-11-28 07:32:38.000000000 -0800
@@ -460,6 +460,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -493,7 +494,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/anyp/PortCfg.cc squid-4.0.3/src/anyp/PortCfg.cc
--- squid-4.0.2/src/anyp/PortCfg.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/anyp/PortCfg.cc	2015-11-28 07:30:57.000000000 -0800
@@ -19,9 +19,6 @@
 #include <limits>
 
 AnyP::PortCfgPointer HttpPortList;
-#if USE_OPENSSL
-AnyP::PortCfgPointer HttpsPortList;
-#endif
 AnyP::PortCfgPointer FtpPortList;
 
 int NHttpSockets = 0;
@@ -107,7 +104,7 @@
 #if 0
     // TODO: AYJ: 2015-01-15: for now SSL does not clone the context object.
     // cloning should only be done before the PortCfg is post-configure initialized and opened
-    Security::ContextPointer sslContext;
+    Security::ContextPtr sslContext;
 #endif
 
 #endif /*0*/
diff -u -r -N squid-4.0.2/src/anyp/PortCfg.h squid-4.0.3/src/anyp/PortCfg.h
--- squid-4.0.2/src/anyp/PortCfg.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/anyp/PortCfg.h	2015-11-28 07:30:57.000000000 -0800
@@ -91,14 +91,9 @@
 
 } // namespace AnyP
 
-/// list of Squid http_port configured
+/// list of Squid http(s)_port configured
 extern AnyP::PortCfgPointer HttpPortList;
 
-#if USE_OPENSSL
-/// list of Squid https_port configured
-extern AnyP::PortCfgPointer HttpsPortList;
-#endif
-
 /// list of Squid ftp_port configured
 extern AnyP::PortCfgPointer FtpPortList;
 
diff -u -r -N squid-4.0.2/src/auth/basic/Makefile.in squid-4.0.3/src/auth/basic/Makefile.in
--- squid-4.0.2/src/auth/basic/Makefile.in	2015-11-01 04:19:18.000000000 -0800
+++ squid-4.0.3/src/auth/basic/Makefile.in	2015-11-28 07:32:39.000000000 -0800
@@ -460,6 +460,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -493,7 +494,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/auth/digest/Makefile.in squid-4.0.3/src/auth/digest/Makefile.in
--- squid-4.0.2/src/auth/digest/Makefile.in	2015-11-01 04:19:19.000000000 -0800
+++ squid-4.0.3/src/auth/digest/Makefile.in	2015-11-28 07:32:40.000000000 -0800
@@ -460,6 +460,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -493,7 +494,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/auth/Makefile.in squid-4.0.3/src/auth/Makefile.in
--- squid-4.0.2/src/auth/Makefile.in	2015-11-01 04:19:18.000000000 -0800
+++ squid-4.0.3/src/auth/Makefile.in	2015-11-28 07:32:39.000000000 -0800
@@ -505,6 +505,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -538,7 +539,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/auth/negotiate/Makefile.in squid-4.0.3/src/auth/negotiate/Makefile.in
--- squid-4.0.2/src/auth/negotiate/Makefile.in	2015-11-01 04:19:19.000000000 -0800
+++ squid-4.0.3/src/auth/negotiate/Makefile.in	2015-11-28 07:32:40.000000000 -0800
@@ -461,6 +461,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -494,7 +495,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/auth/ntlm/Makefile.in squid-4.0.3/src/auth/ntlm/Makefile.in
--- squid-4.0.2/src/auth/ntlm/Makefile.in	2015-11-01 04:19:20.000000000 -0800
+++ squid-4.0.3/src/auth/ntlm/Makefile.in	2015-11-28 07:32:41.000000000 -0800
@@ -460,6 +460,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -493,7 +494,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/base/Makefile.in squid-4.0.3/src/base/Makefile.in
--- squid-4.0.2/src/base/Makefile.in	2015-11-01 04:19:20.000000000 -0800
+++ squid-4.0.3/src/base/Makefile.in	2015-11-28 07:32:41.000000000 -0800
@@ -462,6 +462,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -495,7 +496,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/base/RefCount.h squid-4.0.3/src/base/RefCount.h
--- squid-4.0.2/src/base/RefCount.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/base/RefCount.h	2015-11-28 07:30:57.000000000 -0800
@@ -64,6 +64,8 @@
     }
 #endif
 
+    explicit operator bool() const { return p_; }
+
     bool operator !() const { return !p_; }
 
     C * operator-> () const {return const_cast<C *>(p_); }
diff -u -r -N squid-4.0.2/src/cache_cf.cc squid-4.0.3/src/cache_cf.cc
--- squid-4.0.2/src/cache_cf.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/cache_cf.cc	2015-11-28 07:30:57.000000000 -0800
@@ -57,8 +57,9 @@
 #include "SquidString.h"
 #include "ssl/ProxyCerts.h"
 #include "Store.h"
+#include "store/Disk.h"
+#include "store/Disks.h"
 #include "StoreFileSystem.h"
-#include "SwapDir.h"
 #include "tools.h"
 #include "util.h"
 #include "wordlist.h"
@@ -895,18 +896,11 @@
 
 #if USE_OPENSSL
     for (AnyP::PortCfgPointer s = HttpPortList; s != NULL; s = s->next) {
-        if (!s->flags.tunnelSslBumping)
+        if (!s->secure.encryptTransport)
             continue;
-
-        debugs(3, DBG_IMPORTANT, "Initializing http_port " << s->s << " SSL context");
-        s->configureSslServerContext();
-    }
-
-    for (AnyP::PortCfgPointer s = HttpsPortList; s != NULL; s = s->next) {
-        debugs(3, DBG_IMPORTANT, "Initializing https_port " << s->s << " SSL context");
+        debugs(3, DBG_IMPORTANT, "Initializing " << AnyP::UriScheme(s->transport.protocol) << "_port " << s->s << " TLS context");
         s->configureSslServerContext();
     }
-
 #endif
 
     // prevent infinite fetch loops in the request parser
@@ -1734,7 +1728,7 @@
 #endif
 
 static void
-dump_cachedir(StoreEntry * entry, const char *name, SquidConfig::_cacheSwap swap)
+dump_cachedir(StoreEntry * entry, const char *name, const Store::DiskConfig &swap)
 {
     SwapDir *s;
     int i;
@@ -1823,7 +1817,7 @@
 }
 
 static void
-parse_cachedir(SquidConfig::_cacheSwap * swap)
+parse_cachedir(Store::DiskConfig *swap)
 {
     char *type_str;
     char *path_str;
@@ -2662,9 +2656,7 @@
 
     min = (time_t) (i * 60);    /* convert minutes to seconds */
 
-    i = GetPercentage();    /* token: pct */
-
-    pct = (double) i / 100.0;
+    pct = GetPercentage(false);    /* token: pct . with no limit on size */
 
     i = GetInteger();       /* token: max */
 
@@ -3842,7 +3834,7 @@
     }
 
     if (stat(path, &sb) < 0) {
-        debugs(0, DBG_CRITICAL, (opt_parse_cfg_only?"FATAL ":"") << "ERROR: " << name << " " << path << ": " << xstrerror());
+        debugs(0, DBG_CRITICAL, (opt_parse_cfg_only?"FATAL: ":"ERROR: ") << name << " " << path << ": " << xstrerror());
         // keep going to find more issues if we are only checking the config file with "-k parse"
         if (opt_parse_cfg_only)
             return;
diff -u -r -N squid-4.0.2/src/CacheDigest.cc squid-4.0.3/src/CacheDigest.cc
--- squid-4.0.2/src/CacheDigest.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/CacheDigest.cc	2015-11-28 07:30:57.000000000 -0800
@@ -34,140 +34,124 @@
 /* static array used by cacheDigestHashKey for optimization purposes */
 static uint32_t hashed_keys[4];
 
-static void
-cacheDigestInit(CacheDigest * cd, int capacity, int bpe)
+void
+CacheDigest::init(int newCapacity)
 {
-    const size_t mask_size = cacheDigestCalcMaskSize(capacity, bpe);
-    assert(cd);
-    assert(capacity > 0 && bpe > 0);
-    assert(mask_size > 0);
-    cd->capacity = capacity;
-    cd->bits_per_entry = bpe;
-    cd->mask_size = mask_size;
-    cd->mask = (char *)xcalloc(cd->mask_size, 1);
-    debugs(70, 2, "cacheDigestInit: capacity: " << cd->capacity << " entries, bpe: " << cd->bits_per_entry << "; size: "
-           << cd->mask_size << " bytes");
-}
-
-CacheDigest *
-cacheDigestCreate(int capacity, int bpe)
+    const auto newMaskSz = CacheDigest::CalcMaskSize(newCapacity, bits_per_entry);
+    assert(newCapacity > 0 && bits_per_entry > 0);
+    assert(newMaskSz > 0);
+    capacity = newCapacity;
+    mask_size = newMaskSz;
+    mask = static_cast<char *>(xcalloc(mask_size,1));
+    debugs(70, 2, "capacity: " << capacity << " entries, bpe: " << bits_per_entry << "; size: "
+           << mask_size << " bytes");
+}
+
+CacheDigest::CacheDigest(int aCapacity, int bpe) :
+    mask(nullptr),
+    mask_size(0),
+    capacity(0),
+    bits_per_entry(bpe),
+    count(0),
+    del_count(0)
 {
-    CacheDigest *cd = (CacheDigest *)memAllocate(MEM_CACHE_DIGEST);
     assert(SQUID_MD5_DIGEST_LENGTH == 16);  /* our hash functions rely on 16 byte keys */
-    cacheDigestInit(cd, capacity, bpe);
-    return cd;
+    updateCapacity(aCapacity);
 }
 
-static void
-cacheDigestClean(CacheDigest * cd)
+CacheDigest::~CacheDigest()
 {
-    assert(cd);
-    xfree(cd->mask);
-    cd->mask = NULL;
-}
-
-void
-cacheDigestDestroy(CacheDigest * cd)
-{
-    assert(cd);
-    cacheDigestClean(cd);
-    memFree(cd, MEM_CACHE_DIGEST);
+    xfree(mask);
 }
 
 CacheDigest *
-cacheDigestClone(const CacheDigest * cd)
+CacheDigest::clone() const
 {
-    CacheDigest *clone;
-    assert(cd);
-    clone = cacheDigestCreate(cd->capacity, cd->bits_per_entry);
-    clone->count = cd->count;
-    clone->del_count = cd->del_count;
-    assert(cd->mask_size == clone->mask_size);
-    memcpy(clone->mask, cd->mask, cd->mask_size);
-    return clone;
+    CacheDigest *cl = new CacheDigest(capacity, bits_per_entry);
+    cl->count = count;
+    cl->del_count = del_count;
+    assert(mask_size == cl->mask_size);
+    memcpy(cl->mask, mask, mask_size);
+    return cl;
 }
 
 void
-cacheDigestClear(CacheDigest * cd)
+CacheDigest::clear()
 {
-    assert(cd);
-    cd->count = cd->del_count = 0;
-    memset(cd->mask, 0, cd->mask_size);
+    count = del_count = 0;
+    memset(mask, 0, mask_size);
 }
 
-/* changes mask size, resets bits to 0, preserves "cd" pointer */
 void
-cacheDigestChangeCap(CacheDigest * cd, int new_cap)
+CacheDigest::updateCapacity(int newCapacity)
 {
-    assert(cd);
-    cacheDigestClean(cd);
-    cacheDigestInit(cd, new_cap, cd->bits_per_entry);
+    safe_free(mask);
+    init(newCapacity); // will re-init mask and mask_size
 }
 
-/* returns true if the key belongs to the digest */
-int
-cacheDigestTest(const CacheDigest * cd, const cache_key * key)
+bool
+CacheDigest::contains(const cache_key * key) const
 {
-    assert(cd && key);
+    assert(key);
     /* hash */
-    cacheDigestHashKey(cd, key);
+    cacheDigestHashKey(this, key);
     /* test corresponding bits */
     return
-        CBIT_TEST(cd->mask, hashed_keys[0]) &&
-        CBIT_TEST(cd->mask, hashed_keys[1]) &&
-        CBIT_TEST(cd->mask, hashed_keys[2]) &&
-        CBIT_TEST(cd->mask, hashed_keys[3]);
+        CBIT_TEST(mask, hashed_keys[0]) &&
+        CBIT_TEST(mask, hashed_keys[1]) &&
+        CBIT_TEST(mask, hashed_keys[2]) &&
+        CBIT_TEST(mask, hashed_keys[3]);
 }
 
 void
-cacheDigestAdd(CacheDigest * cd, const cache_key * key)
+CacheDigest::add(const cache_key * key)
 {
-    assert(cd && key);
+    assert(key);
     /* hash */
-    cacheDigestHashKey(cd, key);
+    cacheDigestHashKey(this, key);
     /* turn on corresponding bits */
 #if CD_FAST_ADD
 
-    CBIT_SET(cd->mask, hashed_keys[0]);
-    CBIT_SET(cd->mask, hashed_keys[1]);
-    CBIT_SET(cd->mask, hashed_keys[2]);
-    CBIT_SET(cd->mask, hashed_keys[3]);
+    CBIT_SET(mask, hashed_keys[0]);
+    CBIT_SET(mask, hashed_keys[1]);
+    CBIT_SET(mask, hashed_keys[2]);
+    CBIT_SET(mask, hashed_keys[3]);
 #else
 
     {
         int on_xition_cnt = 0;
 
-        if (!CBIT_TEST(cd->mask, hashed_keys[0])) {
-            CBIT_SET(cd->mask, hashed_keys[0]);
+        if (!CBIT_TEST(mask, hashed_keys[0])) {
+            CBIT_SET(mask, hashed_keys[0]);
             ++on_xition_cnt;
         }
 
-        if (!CBIT_TEST(cd->mask, hashed_keys[1])) {
-            CBIT_SET(cd->mask, hashed_keys[1]);
+        if (!CBIT_TEST(mask, hashed_keys[1])) {
+            CBIT_SET(mask, hashed_keys[1]);
             ++on_xition_cnt;
         }
 
-        if (!CBIT_TEST(cd->mask, hashed_keys[2])) {
-            CBIT_SET(cd->mask, hashed_keys[2]);
+        if (!CBIT_TEST(mask, hashed_keys[2])) {
+            CBIT_SET(mask, hashed_keys[2]);
             ++on_xition_cnt;
         }
 
-        if (!CBIT_TEST(cd->mask, hashed_keys[3])) {
-            CBIT_SET(cd->mask, hashed_keys[3]);
+        if (!CBIT_TEST(mask, hashed_keys[3])) {
+            CBIT_SET(mask, hashed_keys[3]);
             ++on_xition_cnt;
         }
 
         statCounter.cd.on_xition_count.count(on_xition_cnt);
     }
 #endif
-    ++ cd->count;
+    ++count;
 }
 
 void
-cacheDigestDel(CacheDigest * cd, const cache_key * key)
+CacheDigest::remove(const cache_key * key)
 {
-    assert(cd && key);
-    ++ cd->del_count;
+    assert(key);
+    ++del_count;
     /* we do not support deletions from the digest */
 }
 
@@ -206,13 +190,12 @@
     stats->bseq_count = seq_count;
 }
 
-int
-cacheDigestBitUtil(const CacheDigest * cd)
+double
+CacheDigest::usedMaskPercent() const
 {
     CacheDigestStats stats;
-    assert(cd);
-    cacheDigestStats(cd, &stats);
-    return xpercentInt(stats.bit_on_count, stats.bit_count);
+    cacheDigestStats(this, &stats);
+    return xpercent(stats.bit_on_count, stats.bit_count);
 }
 
 void
@@ -298,8 +281,9 @@
 }
 
 size_t
-cacheDigestCalcMaskSize(int cap, int bpe)
+CacheDigest::CalcMaskSize(int cap, int bpe)
 {
+    // XXX: might 32-bit overflow during multiply
     return (size_t) (cap * bpe + 7) / 8;
 }
 
diff -u -r -N squid-4.0.2/src/CacheDigest.h squid-4.0.3/src/CacheDigest.h
--- squid-4.0.2/src/CacheDigest.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/CacheDigest.h	2015-11-28 07:30:57.000000000 -0800
@@ -11,14 +11,45 @@
 #ifndef SQUID_CACHEDIGEST_H_
 #define SQUID_CACHEDIGEST_H_
 
+#include "mem/forward.h"
 #include "store_key_md5.h"
 
 class CacheDigestGuessStats;
 class StoreEntry;
 
-// currently a POD
 class CacheDigest
 {
+    MEMPROXY_CLASS(CacheDigest);
+public:
+    CacheDigest(int capacity, int bpe);
+    ~CacheDigest();
+
+    // NP: only used by broken unit-test
+    /// produce a new identical copy of the digest object
+    CacheDigest *clone() const;
+
+    /// reset the digest mask and counters
+    void clear();
+
+    /// changes mask size to fit newCapacity, resets bits to 0
+    void updateCapacity(int newCapacity);
+
+    void add(const cache_key * key);
+    void remove(const cache_key * key);
+
+    /// \returns true if the key belongs to the digest
+    bool contains(const cache_key * key) const;
+
+    /// percentage of mask bits which are used
+    double usedMaskPercent() const;
+
+    /// calculate the size of mask required to digest up to
+    /// a specified capacity and bitsize.
+    static size_t CalcMaskSize(int cap, int bpe);
+
+private:
+    void init(int newCapacity);
+
 public:
     /* public, read-only */
     char *mask;         /* bit mask */
@@ -29,16 +60,6 @@
     int del_count;      /* number of deletions performed so far */
 };
 
-CacheDigest *cacheDigestCreate(int capacity, int bpe);
-void cacheDigestDestroy(CacheDigest * cd);
-CacheDigest *cacheDigestClone(const CacheDigest * cd);
-void cacheDigestClear(CacheDigest * cd);
-void cacheDigestChangeCap(CacheDigest * cd, int new_cap);
-int cacheDigestTest(const CacheDigest * cd, const cache_key * key);
-void cacheDigestAdd(CacheDigest * cd, const cache_key * key);
-void cacheDigestDel(CacheDigest * cd, const cache_key * key);
-size_t cacheDigestCalcMaskSize(int cap, int bpe);
-int cacheDigestBitUtil(const CacheDigest * cd);
 void cacheDigestGuessStatsUpdate(CacheDigestGuessStats * stats, int real_hit, int guess_hit);
 void cacheDigestGuessStatsReport(const CacheDigestGuessStats * stats, StoreEntry * sentry, const char *label);
 void cacheDigestReport(CacheDigest * cd, const char *label, StoreEntry * e);
diff -u -r -N squid-4.0.2/src/CachePeer.h squid-4.0.3/src/CachePeer.h
--- squid-4.0.2/src/CachePeer.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/CachePeer.h	2015-11-28 07:30:57.000000000 -0800
@@ -182,7 +182,7 @@
 
     /// security settings for peer connection
     Security::PeerOptions secure;
-    Security::ContextPointer sslContext;
+    Security::ContextPtr sslContext;
 #if USE_OPENSSL
     SSL_SESSION *sslSession;
 #endif
diff -u -r -N squid-4.0.2/src/cf.data.pre squid-4.0.3/src/cf.data.pre
--- squid-4.0.2/src/cf.data.pre	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/cf.data.pre	2015-11-28 07:30:57.000000000 -0800
@@ -2027,10 +2027,10 @@
 DOC_END
 
 NAME: https_port
-IFDEF: USE_OPENSSL
+IFDEF: USE_GNUTLS||USE_OPENSSL
 TYPE: PortCfg
 DEFAULT: none
-LOC: HttpsPortList
+LOC: HttpPortList
 DOC_START
 	Usage:  [ip:]port [mode] cert=certificate.pem [options]
 
@@ -3274,11 +3274,12 @@
 	
 	allow-miss	Disable Squid's use of only-if-cached when forwarding
 			requests to siblings. This is primarily useful when
-			icp_hit_stale is used by the sibling. To extensive use
-			of this option may result in forwarding loops, and you
-			should avoid having two-way peerings with this option.
-			For example to deny peer usage on requests from peer
-			by denying cache_peer_access if the source is a peer.
+			icp_hit_stale is used by the sibling. Excessive use
+			of this option may result in forwarding loops. One way
+			to prevent peering loops when using this option, is to
+			deny cache peer usage on requests from a peer:
+			acl fromPeer ...
+			cache_peer_access peerName deny fromPeer
 	
 	max-conn=N 	Limit the number of concurrent connections the Squid
 			may open to this peer, including already opened idle
@@ -3329,7 +3330,7 @@
 			Required if you have multiple peers on the same host
 			but different ports.
 			This name can be used in cache_peer_access and similar
-			directives to dentify the peer.
+			directives to identify the peer.
 			Can be used by outgoing access controls through the
 			peername ACL type.
 	
@@ -3344,17 +3345,43 @@
 NAME: cache_peer_access
 TYPE: peer_access
 DEFAULT: none
+DEFAULT_DOC: No peer usage restrictions.
 LOC: none
 DOC_START
-	Use to limit the requests for which a neighbor proxy will be
-	queried. Peers with no restrictions are queried for all requests.
+	Restricts usage of cache_peer proxies.
 
 	Usage:
-		cache_peer_access cache-host allow|deny [!]aclname ...
+		cache_peer_access peer-name allow|deny [!]aclname ...
+
+	For the required peer-name parameter, use either the value of the
+	cache_peer name=value parameter or, if name=value is missing, the
+	cache_peer hostname parameter.
+
+	This directive narrows down the selection of peering candidates, but
+	does not determine the order in which the selected candidates are
+	contacted. That order is determined by the peer selection algorithms
+	(see PEER SELECTION sections in the cache_peer documentation).
+
+	If a deny rule matches, the corresponding peer will not be contacted
+	for the current transaction -- Squid will not send ICP queries and
+	will not forward HTTP requests to that peer. An allow match leaves
+	the corresponding peer in the selection. The first match for a given
+	peer wins for that peer.
+
+	The relative order of cache_peer_access directives for the same peer
+	matters. The relative order of any two cache_peer_access directives
+	for different peers does not matter. To ease interpretation, it is a
+	good idea to group cache_peer_access directives for the same peer
+	together.
+
+	A single cache_peer_access directive may be evaluated multiple times
+	for a given transaction because individual peer selection algorithms
+	may check it independently from each other. These redundant checks
+	may be optimized away in future Squid versions.
+
+	This clause only supports fast acl types.
+	See http://wiki.squid-cache.org/SquidFaq/SquidAcl for details.
 
-	The syntax is identical to 'http_access' and the other lists of
-	ACL elements.  See the comments for 'http_access', or the
-	Squid FAQ (http://wiki.squid-cache.org/SquidFaq/SquidAcl).
 DOC_END
 
 NAME: neighbor_type_domain
@@ -6639,7 +6666,7 @@
 
 		delay_parameters 1 none 8000/8000
 
-	Note that 8 x 8000 KByte/sec -> 64Kbit/sec.
+	Note that 8 x 8K Byte/sec -> 64K bit/sec.
 
 	Note that the word 'none' is used to represent no limit.
 
@@ -6654,9 +6681,9 @@
 
 		delay_parameters 2 32000/32000 8000/8000 600/8000
 
-	Note that 8 x 32000 KByte/sec -> 256Kbit/sec.
-		  8 x  8000 KByte/sec ->  64Kbit/sec.
-		  8 x   600 Byte/sec  -> 4800bit/sec.
+	Note that 8 x  32K Byte/sec ->  256K bit/sec.
+		  8 x   8K Byte/sec ->   64K bit/sec.
+		  8 x 600  Byte/sec -> 4800  bit/sec.
 
 
 	Finally, for a class 4 delay pool as in the example - each user will
diff -u -r -N squid-4.0.2/src/clients/Makefile.in squid-4.0.3/src/clients/Makefile.in
--- squid-4.0.2/src/clients/Makefile.in	2015-11-01 04:19:21.000000000 -0800
+++ squid-4.0.3/src/clients/Makefile.in	2015-11-28 07:32:42.000000000 -0800
@@ -461,6 +461,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -494,7 +495,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/client_side.cc squid-4.0.3/src/client_side.cc
--- squid-4.0.2/src/client_side.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/client_side.cc	2015-11-28 07:30:57.000000000 -0800
@@ -52,7 +52,7 @@
  * data, or sending it.
  *
  \par
- * ClientKeepAliveNextRequest will then detect the presence of data in
+ * ConnStateData::kick() will then detect the presence of data in
  * the next ClientHttpRequest, and will send it, restablishing the
  * data flow.
  */
@@ -220,48 +220,6 @@
     return http->getConn();
 }
 
-/**
- * This routine should be called to grow the in.buf and then
- * call Comm::Read().
- */
-void
-ConnStateData::readSomeData()
-{
-    if (reading())
-        return;
-
-    debugs(33, 4, HERE << clientConnection << ": reading request...");
-
-    // we can only read if there is more than 1 byte of space free
-    if (Config.maxRequestBufferSize - in.buf.length() < 2)
-        return;
-
-    typedef CommCbMemFunT<ConnStateData, CommIoCbParams> Dialer;
-    reader = JobCallback(33, 5, Dialer, this, ConnStateData::clientReadRequest);
-    Comm::Read(clientConnection, reader);
-}
-
-void
-ClientSocketContext::removeFromConnectionList(ConnStateData * conn)
-{
-    ClientSocketContext::Pointer *tempContextPointer;
-    assert(conn != NULL && cbdataReferenceValid(conn));
-    assert(conn->getCurrentContext() != NULL);
-    /* Unlink us from the connection request list */
-    tempContextPointer = & conn->currentobject;
-
-    while (tempContextPointer->getRaw()) {
-        if (*tempContextPointer == this)
-            break;
-
-        tempContextPointer = &(*tempContextPointer)->next;
-    }
-
-    assert(tempContextPointer->getRaw() != NULL);
-    *tempContextPointer = next;
-    next = NULL;
-}
-
 ClientSocketContext::~ClientSocketContext()
 {
     clientStreamNode *node = getTail();
@@ -276,13 +234,7 @@
         }
     }
 
-    if (connRegistered_)
-        deRegisterWithConn();
-
     httpRequestFree(http);
-
-    /* clean up connection links to us */
-    assert(this != next.getRaw());
 }
 
 void
@@ -292,32 +244,29 @@
     assert (http);
     assert (http->getConn() != NULL);
     connRegistered_ = true;
-    http->getConn()->addContextToQueue(this);
-}
-
-void
-ClientSocketContext::deRegisterWithConn()
-{
-    assert (connRegistered_);
-    removeFromConnectionList(http->getConn());
-    connRegistered_ = false;
+    http->getConn()->pipeline.add(ClientSocketContext::Pointer(this));
 }
 
 void
-ClientSocketContext::connIsFinished()
+ClientSocketContext::finished()
 {
     assert (http);
     assert (http->getConn() != NULL);
-    deRegisterWithConn();
+    ConnStateData *conn = http->getConn();
+
     /* we can't handle any more stream data - detach */
     clientStreamDetach(getTail(), http);
+
+    assert(connRegistered_);
+    connRegistered_ = false;
+    assert(conn->pipeline.front() == this); // XXX: still assumes HTTP/1 semantics
+    conn->pipeline.popMe(ClientSocketContext::Pointer(this));
 }
 
 ClientSocketContext::ClientSocketContext(const Comm::ConnectionPointer &aConn, ClientHttpRequest *aReq) :
     clientConnection(aConn),
     http(aReq),
     reply(NULL),
-    next(NULL),
     writtenToSocket(0),
     mayUseConnection_ (false),
     connRegistered_ (false)
@@ -679,43 +628,6 @@
     delete http;
 }
 
-bool
-ConnStateData::areAllContextsForThisConnection() const
-{
-    ClientSocketContext::Pointer context = getCurrentContext();
-
-    while (context.getRaw()) {
-        if (context->http->getConn() != this)
-            return false;
-
-        context = context->next;
-    }
-
-    return true;
-}
-
-void
-ConnStateData::freeAllContexts()
-{
-    ClientSocketContext::Pointer context;
-
-    while ((context = getCurrentContext()).getRaw() != NULL) {
-        assert(getCurrentContext() !=
-               getCurrentContext()->next);
-        context->connIsFinished();
-        assert (context != currentobject);
-    }
-}
-
-/// propagates abort event to all contexts
-void
-ConnStateData::notifyAllContexts(int xerrno)
-{
-    typedef ClientSocketContext::Pointer CSCP;
-    for (CSCP c = getCurrentContext(); c.getRaw(); c = c->next)
-        c->noteIoError(xerrno);
-}
-
 /* This is a handler normally called by comm_close() */
 void ConnStateData::connStateClosed(const CommCloseCbParams &)
 {
@@ -811,20 +723,17 @@
     flags.readMore = false;
     DeregisterRunner(this);
     clientdbEstablished(clientConnection->remote, -1);  /* decrement */
-    assert(areAllContextsForThisConnection());
-    freeAllContexts();
+    pipeline.terminateAll(0);
 
     unpinConnection(true);
 
-    if (Comm::IsConnOpen(clientConnection))
-        clientConnection->close();
+    Server::swanSong(); // closes the client connection
 
 #if USE_AUTH
     // NP: do this bit after closing the connections to avoid side effects from unwanted TCP RST
     setAuth(NULL, "ConnStateData::SwanSong cleanup");
 #endif
 
-    BodyProducer::swanSong();
     flags.swanSang = true;
 }
 
@@ -849,6 +758,8 @@
     if (bodyPipe != NULL)
         stopProducingFor(bodyPipe, false);
 
+    delete bodyParser; // TODO: pool
+
 #if USE_OPENSSL
     delete sslServerBump;
 #endif
@@ -907,13 +818,6 @@
     return 0;
 }
 
-// careful: the "current" context may be gone if we wrote an early response
-ClientSocketContext::Pointer
-ConnStateData::getCurrentContext() const
-{
-    return currentobject;
-}
-
 void
 ClientSocketContext::deferRecipientForLater(clientStreamNode * node, HttpReply * rep, StoreIOBuffer receivedData)
 {
@@ -1440,7 +1344,8 @@
 
     /* TODO: check offset is what we asked for */
 
-    if (context != http->getConn()->getCurrentContext())
+    // TODO: enforces HTTP/1 MUST on pipeline order, but is irrelevant to HTTP/2
+    if (context != http->getConn()->pipeline.front())
         context->deferRecipientForLater(node, rep, receivedData);
     else
         http->getConn()->handleReply(rep, receivedData);
@@ -1521,18 +1426,17 @@
      */
 }
 
-/// called when we have successfully finished writing the response
 void
-ClientSocketContext::keepaliveNextRequest()
+ConnStateData::kick()
 {
-    ConnStateData * conn = http->getConn();
-
-    debugs(33, 3, HERE << "ConnnStateData(" << conn->clientConnection << "), Context(" << clientConnection << ")");
-    connIsFinished();
+    if (!Comm::IsConnOpen(clientConnection)) {
+        debugs(33, 2, clientConnection << " Connection was closed");
+        return;
+    }
 
-    if (conn->pinning.pinned && !Comm::IsConnOpen(conn->pinning.serverConnection)) {
-        debugs(33, 2, HERE << conn->clientConnection << " Connection was pinned but server side gone. Terminating client connection");
-        conn->clientConnection->close();
+    if (pinning.pinned && !Comm::IsConnOpen(pinning.serverConnection)) {
+        debugs(33, 2, clientConnection << " Connection was pinned but server side gone. Terminating client connection");
+        clientConnection->close();
         return;
     }
 
@@ -1550,9 +1454,9 @@
      * getting stuck and to prevent accidental request smuggling.
      */
 
-    if (const char *reason = conn->stoppedReceiving()) {
-        debugs(33, 3, HERE << "closing for earlier request error: " << reason);
-        conn->clientConnection->close();
+    if (const char *reason = stoppedReceiving()) {
+        debugs(33, 3, "closing for earlier request error: " << reason);
+        clientConnection->close();
         return;
     }
 
@@ -1566,8 +1470,8 @@
      * from our read buffer we may never re-register for another client read.
      */
 
-    if (conn->clientParseRequests()) {
-        debugs(33, 3, HERE << conn->clientConnection << ": parsed next request from buffer");
+    if (clientParseRequests()) {
+        debugs(33, 3, clientConnection << ": parsed next request from buffer");
     }
 
     /** \par
@@ -1577,14 +1481,12 @@
      * half-closed _AND_ then, sometimes, spending "Timeout" time in
      * the keepalive "Waiting for next request" state.
      */
-    if (commIsHalfClosed(conn->clientConnection->fd) && (conn->getConcurrentRequestCount() == 0)) {
-        debugs(33, 3, "ClientSocketContext::keepaliveNextRequest: half-closed client with no pending requests, closing");
-        conn->clientConnection->close();
+    if (commIsHalfClosed(clientConnection->fd) && pipeline.empty()) {
+        debugs(33, 3, "half-closed client with no pending requests, closing");
+        clientConnection->close();
         return;
     }
 
-    ClientSocketContext::Pointer deferredRequest;
-
     /** \par
      * At this point we either have a parsed request (which we've
      * kicked off the processing for) or not. If we have a deferred
@@ -1592,16 +1494,16 @@
      * then look at processing it. If not, simply kickstart
      * another read.
      */
-
-    if ((deferredRequest = conn->getCurrentContext()).getRaw()) {
-        debugs(33, 3, HERE << conn->clientConnection << ": calling PushDeferredIfNeeded");
-        ClientSocketContextPushDeferredIfNeeded(deferredRequest, conn);
-    } else if (conn->flags.readMore) {
-        debugs(33, 3, HERE << conn->clientConnection << ": calling conn->readNextRequest()");
-        conn->readNextRequest();
+    ClientSocketContext::Pointer deferredRequest = pipeline.front();
+    if (deferredRequest != nullptr) {
+        debugs(33, 3, clientConnection << ": calling PushDeferredIfNeeded");
+        ClientSocketContextPushDeferredIfNeeded(deferredRequest, this);
+    } else if (flags.readMore) {
+        debugs(33, 3, clientConnection << ": calling readNextRequest()");
+        readNextRequest();
     } else {
         // XXX: Can this happen? CONNECT tunnels have deferredRequest set.
-        debugs(33, DBG_IMPORTANT, HERE << "abandoning " << conn->clientConnection);
+        debugs(33, DBG_IMPORTANT, MYNAME << "abandoning " << clientConnection);
     }
 }
 
@@ -1796,6 +1698,7 @@
 void
 ClientSocketContext::initiateClose(const char *reason)
 {
+    debugs(33, 4, clientConnection << " because " << reason);
     http->getConn()->stopSending(reason); // closes ASAP
 }
 
@@ -1815,7 +1718,7 @@
     if (!stoppedReceiving()) {
         if (const int64_t expecting = mayNeedToReadMoreBody()) {
             debugs(33, 5, HERE << "must still read " << expecting <<
-                   " request body bytes with " << in.buf.length() << " unused");
+                   " request body bytes with " << inBuf.length() << " unused");
             return; // wait for the request receiver to finish reading
         }
     }
@@ -1850,13 +1753,15 @@
         pullData();
         break;
 
-    case STREAM_COMPLETE:
+    case STREAM_COMPLETE: {
         debugs(33, 5, conn << " Stream complete, keepalive is " << http->request->flags.proxyKeepalive);
-        if (http->request->flags.proxyKeepalive)
-            keepaliveNextRequest();
-        else
-            initiateClose("STREAM_COMPLETE NOKEEPALIVE");
-        return;
+        ConnStateData *c = http->getConn();
+        if (!http->request->flags.proxyKeepalive)
+            clientConnection->close();
+        finished();
+        c->kick();
+    }
+    return;
 
     case STREAM_UNPLANNED_COMPLETE:
         initiateClose("STREAM_UNPLANNED_COMPLETE");
@@ -1875,7 +1780,7 @@
 ConnStateData::abortRequestParsing(const char *const uri)
 {
     ClientHttpRequest *http = new ClientHttpRequest(this);
-    http->req_sz = in.buf.length();
+    http->req_sz = inBuf.length();
     http->uri = xstrdup(uri);
     setLogUri (http, uri);
     ClientSocketContext *context = new ClientSocketContext(clientConnection, http);
@@ -1895,7 +1800,7 @@
 
     // if connection is idle terminate it now,
     // otherwise wait for grace period to end
-    if (getConcurrentRequestCount() == 0)
+    if (pipeline.empty())
         endingShutdown();
 }
 
@@ -2161,12 +2066,12 @@
 {
     /* Attempt to parse the first line; this will define where the method, url, version and header begin */
     {
-        const bool parsedOk = hp->parse(csd->in.buf);
+        const bool parsedOk = hp->parse(csd->inBuf);
 
         if (csd->port->flags.isIntercepted() && Config.accessList.on_unsupported_protocol)
-            csd->preservedClientData = csd->in.buf;
+            csd->preservedClientData = csd->inBuf;
         // sync the buffers after parsing.
-        csd->in.buf = hp->remaining();
+        csd->inBuf = hp->remaining();
 
         if (hp->needsMoreData()) {
             debugs(33, 5, "Incomplete request, waiting for end of request line");
@@ -2282,75 +2187,30 @@
 }
 
 bool
-ConnStateData::In::maybeMakeSpaceAvailable()
-{
-    if (buf.spaceSize() < 2) {
-        const SBuf::size_type haveCapacity = buf.length() + buf.spaceSize();
-        if (haveCapacity >= Config.maxRequestBufferSize) {
-            debugs(33, 4, "request buffer full: client_request_buffer_max_size=" << Config.maxRequestBufferSize);
-            return false;
-        }
-        if (haveCapacity == 0) {
-            // haveCapacity is based on the SBuf visible window of the MemBlob buffer, which may fill up.
-            // at which point bump the buffer back to default. This allocates a new MemBlob with any un-parsed bytes.
-            buf.reserveCapacity(CLIENT_REQ_BUF_SZ);
-        } else {
-            const SBuf::size_type wantCapacity = min(static_cast<SBuf::size_type>(Config.maxRequestBufferSize), haveCapacity*2);
-            buf.reserveCapacity(wantCapacity);
-        }
-        debugs(33, 2, "growing request buffer: available=" << buf.spaceSize() << " used=" << buf.length());
-    }
-    return (buf.spaceSize() >= 2);
-}
-
-void
-ConnStateData::addContextToQueue(ClientSocketContext * context)
-{
-    ClientSocketContext::Pointer *S;
-
-    for (S = (ClientSocketContext::Pointer *) & currentobject; S->getRaw();
-            S = &(*S)->next);
-    *S = context;
-
-    ++nrequests;
-}
-
-int
-ConnStateData::getConcurrentRequestCount() const
-{
-    int result = 0;
-    ClientSocketContext::Pointer *T;
-
-    for (T = (ClientSocketContext::Pointer *) &currentobject;
-            T->getRaw(); T = &(*T)->next, ++result);
-    return result;
-}
-
-int
 ConnStateData::connFinishedWithConn(int size)
 {
     if (size == 0) {
-        if (getConcurrentRequestCount() == 0 && in.buf.isEmpty()) {
+        if (pipeline.empty() && inBuf.isEmpty()) {
             /* no current or pending requests */
             debugs(33, 4, HERE << clientConnection << " closed");
-            return 1;
+            return true;
         } else if (!Config.onoff.half_closed_clients) {
             /* admin doesn't want to support half-closed client sockets */
             debugs(33, 3, HERE << clientConnection << " aborted (half_closed_clients disabled)");
-            notifyAllContexts(0); // no specific error implies abort
-            return 1;
+            pipeline.terminateAll(0);
+            return true;
         }
     }
 
-    return 0;
+    return false;
 }
 
 void
 ConnStateData::consumeInput(const size_t byteCount)
 {
-    assert(byteCount > 0 && byteCount <= in.buf.length());
-    in.buf.consume(byteCount);
-    debugs(33, 5, "in.buf has " << in.buf.length() << " unused bytes");
+    assert(byteCount > 0 && byteCount <= inBuf.length());
+    inBuf.consume(byteCount);
+    debugs(33, 5, "inBuf has " << inBuf.length() << " unused bytes");
 }
 
 void
@@ -2473,7 +2333,7 @@
 clientTunnelOnError(ConnStateData *conn, ClientSocketContext *context, HttpRequest *request, const HttpRequestMethod& method, err_type requestError, Http::StatusCode errStatusCode, const char *requestErrorBytes)
 {
     if (conn->port->flags.isIntercepted() &&
-            Config.accessList.on_unsupported_protocol && conn->nrequests <= 1) {
+            Config.accessList.on_unsupported_protocol && conn->pipeline.nrequests <= 1) {
         ACLFilledChecklist checklist(Config.accessList.on_unsupported_protocol, request, NULL);
         checklist.requestErrorType = requestError;
         checklist.src_addr = conn->clientConnection->remote;
@@ -2482,8 +2342,13 @@
         allow_t answer = checklist.fastCheck();
         if (answer == ACCESS_ALLOWED && answer.kind == 1) {
             debugs(33, 3, "Request will be tunneled to server");
-            if (context)
-                context->removeFromConnectionList(conn);
+            if (context) {
+                // XXX: Either the context is finished() or it should stay queued.
+                // The below may leak client streams BodyPipe objects. BUT, we need
+                // to check if client-streams detatch is safe to do here (finished() will detatch).
+                assert(conn->pipeline.front() == context); // XXX: still assumes HTTP/1 semantics
+                conn->pipeline.popMe(ClientSocketContextPointer(context));
+            }
             Comm::SetSelect(conn->clientConnection->fd, COMM_SELECT_READ, NULL, NULL, 0);
             conn->fakeAConnectRequest("unknown-protocol", conn->preservedClientData);
             return true;
@@ -2728,7 +2593,7 @@
 bool
 ConnStateData::concurrentRequestQueueFilled() const
 {
-    const int existingRequestCount = getConcurrentRequestCount();
+    const int existingRequestCount = pipeline.count();
 
     // default to the configured pipeline size.
     // add 1 because the head of pipeline is counted in concurrent requests and not prefetch queue
@@ -2809,15 +2674,15 @@
     // http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt
 
     // detect and parse PROXY/2.0 protocol header
-    if (in.buf.startsWith(Proxy2p0magic))
+    if (inBuf.startsWith(Proxy2p0magic))
         return parseProxy2p0();
 
     // detect and parse PROXY/1.0 protocol header
-    if (in.buf.startsWith(Proxy1p0magic))
+    if (inBuf.startsWith(Proxy1p0magic))
         return parseProxy1p0();
 
     // detect and terminate other protocols
-    if (in.buf.length() >= Proxy2p0magic.length()) {
+    if (inBuf.length() >= Proxy2p0magic.length()) {
         // PROXY/1.0 magic is shorter, so we know that
         // the input does not start with any PROXY magic
         return proxyProtocolError("PROXY protocol error: invalid header");
@@ -2834,7 +2699,7 @@
 bool
 ConnStateData::parseProxy1p0()
 {
-    ::Parser::Tokenizer tok(in.buf);
+    ::Parser::Tokenizer tok(inBuf);
     tok.skip(Proxy1p0magic);
 
     // skip to first LF (assumes it is part of CRLF)
@@ -2843,7 +2708,7 @@
     if (tok.prefix(line, lineContent, 107-Proxy1p0magic.length())) {
         if (tok.skip('\n')) {
             // found valid header
-            in.buf = tok.remaining();
+            inBuf = tok.remaining();
             needProxyProtocolHeader_ = false;
             // reset the tokenizer to work on found line only.
             tok.reset(line);
@@ -2851,7 +2716,7 @@
             return false; // no LF yet
 
     } else // protocol error only if there are more than 107 bytes prefix header
-        return proxyProtocolError(in.buf.length() > 107? "PROXY/1.0 error: missing CRLF" : NULL);
+        return proxyProtocolError(inBuf.length() > 107? "PROXY/1.0 error: missing CRLF" : NULL);
 
     static const SBuf unknown("UNKNOWN"), tcpName("TCP");
     if (tok.skip(tcpName)) {
@@ -2928,34 +2793,34 @@
 ConnStateData::parseProxy2p0()
 {
     static const SBuf::size_type prefixLen = Proxy2p0magic.length();
-    if (in.buf.length() < prefixLen + 4)
+    if (inBuf.length() < prefixLen + 4)
         return false; // need more bytes
 
-    if ((in.buf[prefixLen] & 0xF0) != 0x20) // version == 2 is mandatory
+    if ((inBuf[prefixLen] & 0xF0) != 0x20) // version == 2 is mandatory
         return proxyProtocolError("PROXY/2.0 error: invalid version");
 
-    const char command = (in.buf[prefixLen] & 0x0F);
+    const char command = (inBuf[prefixLen] & 0x0F);
     if ((command & 0xFE) != 0x00) // values other than 0x0-0x1 are invalid
         return proxyProtocolError("PROXY/2.0 error: invalid command");
 
-    const char family = (in.buf[prefixLen+1] & 0xF0) >>4;
+    const char family = (inBuf[prefixLen+1] & 0xF0) >>4;
     if (family > 0x3) // values other than 0x0-0x3 are invalid
         return proxyProtocolError("PROXY/2.0 error: invalid family");
 
-    const char proto = (in.buf[prefixLen+1] & 0x0F);
+    const char proto = (inBuf[prefixLen+1] & 0x0F);
     if (proto > 0x2) // values other than 0x0-0x2 are invalid
         return proxyProtocolError("PROXY/2.0 error: invalid protocol type");
 
-    const char *clen = in.buf.rawContent() + prefixLen + 2;
+    const char *clen = inBuf.rawContent() + prefixLen + 2;
     uint16_t len;
     memcpy(&len, clen, sizeof(len));
     len = ntohs(len);
 
-    if (in.buf.length() < prefixLen + 4 + len)
+    if (inBuf.length() < prefixLen + 4 + len)
         return false; // need more bytes
 
-    in.buf.consume(prefixLen + 4); // 4 being the extra bytes
-    const SBuf extra = in.buf.consume(len);
+    inBuf.consume(prefixLen + 4); // 4 being the extra bytes
+    const SBuf extra = inBuf.consume(len);
     needProxyProtocolHeader_ = false; // found successfully
 
     // LOCAL connections do nothing with the extras
@@ -3045,10 +2910,10 @@
 
     // Loop while we have read bytes that are not needed for producing the body
     // On errors, bodyPipe may become nil, but readMore will be cleared
-    while (!in.buf.isEmpty() && !bodyPipe && flags.readMore) {
+    while (!inBuf.isEmpty() && !bodyPipe && flags.readMore) {
 
         /* Don't try to parse if the buffer is empty */
-        if (in.buf.isEmpty())
+        if (inBuf.isEmpty())
             break;
 
         /* Limit the number of concurrent requests */
@@ -3078,8 +2943,8 @@
             }
         } else {
             debugs(33, 5, clientConnection << ": not enough request data: " <<
-                   in.buf.length() << " < " << Config.maxRequestHeaderSize);
-            Must(in.buf.length() < Config.maxRequestHeaderSize);
+                   inBuf.length() << " < " << Config.maxRequestHeaderSize);
+            Must(inBuf.length() < Config.maxRequestHeaderSize);
             break;
         }
     }
@@ -3089,81 +2954,11 @@
 }
 
 void
-ConnStateData::clientReadRequest(const CommIoCbParams &io)
+ConnStateData::afterClientRead()
 {
-    debugs(33,5, io.conn);
-    Must(reading());
-    reader = NULL;
-
-    /* Bail out quickly on Comm::ERR_CLOSING - close handlers will tidy up */
-    if (io.flag == Comm::ERR_CLOSING) {
-        debugs(33,5, io.conn << " closing Bailout.");
-        return;
-    }
-
-    assert(Comm::IsConnOpen(clientConnection));
-    assert(io.conn->fd == clientConnection->fd);
-
-    /*
-     * Don't reset the timeout value here. The value should be
-     * counting Config.Timeout.request and applies to the request
-     * as a whole, not individual read() calls.
-     * Plus, it breaks our lame *HalfClosed() detection
-     */
-
-    in.maybeMakeSpaceAvailable();
-    CommIoCbParams rd(this); // will be expanded with ReadNow results
-    rd.conn = io.conn;
-    switch (Comm::ReadNow(rd, in.buf)) {
-    case Comm::INPROGRESS:
-        if (in.buf.isEmpty())
-            debugs(33, 2, io.conn << ": no data to process, " << xstrerr(rd.xerrno));
-        readSomeData();
-        return;
-
-    case Comm::OK:
-        statCounter.client_http.kbytes_in += rd.size;
-        if (!receivedFirstByte_)
-            receivedFirstByte();
-        // may comm_close or setReplyToError
-        if (!handleReadData())
-            return;
-
-        /* Continue to process previously read data */
-        break;
-
-    case Comm::ENDFILE: // close detected by 0-byte read
-        debugs(33, 5, io.conn << " closed?");
-
-        if (connFinishedWithConn(rd.size)) {
-            clientConnection->close();
-            return;
-        }
-
-        /* It might be half-closed, we can't tell */
-        fd_table[io.conn->fd].flags.socket_eof = true;
-        commMarkHalfClosed(io.conn->fd);
-        fd_note(io.conn->fd, "half-closed");
-
-        /* There is one more close check at the end, to detect aborted
-         * (partial) requests. At this point we can't tell if the request
-         * is partial.
-         */
-
-        /* Continue to process previously read data */
-        break;
-
-    // case Comm::COMM_ERROR:
-    default: // no other flags should ever occur
-        debugs(33, 2, io.conn << ": got flag " << rd.flag << "; " << xstrerr(rd.xerrno));
-        notifyAllContexts(rd.xerrno);
-        io.conn->close();
-        return;
-    }
-
     /* Process next request */
-    if (getConcurrentRequestCount() == 0)
-        fd_note(io.fd, "Reading next request");
+    if (pipeline.empty())
+        fd_note(clientConnection->fd, "Reading next request");
 
     if (!clientParseRequests()) {
         if (!isOpen())
@@ -3174,10 +2969,10 @@
          * The above check with connFinishedWithConn() only
          * succeeds _if_ the buffer is empty which it won't
          * be if we have an incomplete request.
-         * XXX: This duplicates ClientSocketContext::keepaliveNextRequest
+         * XXX: This duplicates ConnStateData::kick
          */
-        if (getConcurrentRequestCount() == 0 && commIsHalfClosed(io.fd)) {
-            debugs(33, 5, HERE << io.conn << ": half-closed connection, no completed request parsed, connection closing.");
+        if (pipeline.empty() && commIsHalfClosed(clientConnection->fd)) {
+            debugs(33, 5, clientConnection << ": half-closed connection, no completed request parsed, connection closing.");
             clientConnection->close();
             return;
         }
@@ -3205,7 +3000,7 @@
 }
 
 /**
- * called when new request body data has been buffered in in.buf
+ * called when new request body data has been buffered in inBuf
  * may close the connection if we were closing and piped everything out
  *
  * \retval false called comm_close or setReplyToError (the caller should bail)
@@ -3216,14 +3011,14 @@
 {
     assert(bodyPipe != NULL);
 
-    if (in.bodyParser) { // chunked encoding
+    if (bodyParser) { // chunked encoding
         if (const err_type error = handleChunkedRequestBody()) {
             abortChunkedRequestBody(error);
             return false;
         }
     } else { // identity encoding
         debugs(33,5, HERE << "handling plain request body for " << clientConnection);
-        const size_t putSize = bodyPipe->putMoreData(in.buf.c_str(), in.buf.length());
+        const size_t putSize = bodyPipe->putMoreData(inBuf.c_str(), inBuf.length());
         if (putSize > 0)
             consumeInput(putSize);
 
@@ -3253,17 +3048,17 @@
 err_type
 ConnStateData::handleChunkedRequestBody()
 {
-    debugs(33, 7, "chunked from " << clientConnection << ": " << in.buf.length());
+    debugs(33, 7, "chunked from " << clientConnection << ": " << inBuf.length());
 
     try { // the parser will throw on errors
 
-        if (in.buf.isEmpty()) // nothing to do
+        if (inBuf.isEmpty()) // nothing to do
             return ERR_NONE;
 
         BodyPipeCheckout bpc(*bodyPipe);
-        in.bodyParser->setPayloadBuffer(&bpc.buf);
-        const bool parsed = in.bodyParser->parse(in.buf);
-        in.buf = in.bodyParser->remaining(); // sync buffers
+        bodyParser->setPayloadBuffer(&bpc.buf);
+        const bool parsed = bodyParser->parse(inBuf);
+        inBuf = bodyParser->remaining(); // sync buffers
         bpc.checkIn();
 
         // dechunk then check: the size limit applies to _dechunked_ content
@@ -3277,10 +3072,10 @@
         }
 
         // if chunk parser needs data, then the body pipe must need it too
-        Must(!in.bodyParser->needsMoreData() || bodyPipe->mayNeedMoreData());
+        Must(!bodyParser->needsMoreData() || bodyPipe->mayNeedMoreData());
 
         // if parser needs more space and we can consume nothing, we will stall
-        Must(!in.bodyParser->needsMoreSpace() || bodyPipe->buf().hasContent());
+        Must(!bodyParser->needsMoreSpace() || bodyPipe->buf().hasContent());
     } catch (...) { // TODO: be more specific
         debugs(33, 3, HERE << "malformed chunks" << bodyPipe->status());
         return ERR_INVALID_REQ;
@@ -3300,7 +3095,7 @@
     // but if we fail when the server connection is used already, the server may send
     // us its response too, causing various assertions. How to prevent that?
 #if WE_KNOW_HOW_TO_SEND_ERRORS
-    ClientSocketContext::Pointer context = getCurrentContext();
+    ClientSocketContext::Pointer context = pipeline.front();
     if (context != NULL && !context->http->out.offset) { // output nothing yet
         clientStreamNode *node = context->getClientReplyContext();
         clientReplyContext *repContext = dynamic_cast<clientReplyContext*>(node->data.getRaw());
@@ -3312,7 +3107,7 @@
                                     repContext->http->uri,
                                     CachePeer,
                                     repContext->http->request,
-                                    in.buf, NULL);
+                                    inBuf, NULL);
         context->pullData();
     } else {
         // close or otherwise we may get stuck as nobody will notice the error?
@@ -3385,7 +3180,8 @@
 
 ConnStateData::ConnStateData(const MasterXaction::Pointer &xact) :
     AsyncJob("ConnStateData"), // kids overwrite
-    nrequests(0),
+    Server(xact),
+    bodyParser(nullptr),
 #if USE_OPENSSL
     sslBumpMode(Ssl::bumpEnd),
 #endif
@@ -3396,8 +3192,7 @@
     signAlgorithm(Ssl::algSignTrusted),
 #endif
     stoppedSending_(NULL),
-    stoppedReceiving_(NULL),
-    receivedFirstByte_(false)
+    stoppedReceiving_(NULL)
 {
     flags.readMore = true; // kids may overwrite
     flags.swanSang = false;
@@ -3410,9 +3205,6 @@
     pinning.peer = NULL;
 
     // store the details required for creating more MasterXaction objects as new requests come in
-    clientConnection = xact->tcpClient;
-    port = xact->squidPort;
-    transferProtocol = port->transport; // default to the *_port protocol= setting. may change later.
     log_addr = xact->tcpClient->remote;
     log_addr.applyMask(Config.Addrs.client_netmask);
 
@@ -3547,7 +3339,7 @@
 
 /** Create SSL connection structure and update fd_table */
 static Security::SessionPointer
-httpsCreate(const Comm::ConnectionPointer &conn, Security::ContextPointer sslContext)
+httpsCreate(const Comm::ConnectionPointer &conn, Security::ContextPtr sslContext)
 {
     if (auto ssl = Ssl::CreateServer(sslContext, conn->fd, "client https start")) {
         debugs(33, 5, "will negotate SSL on " << conn);
@@ -3695,11 +3487,11 @@
 }
 
 /**
- * If Security::ContextPointer is given, starts reading the TLS handshake.
- * Otherwise, calls switchToHttps to generate a dynamic Security::ContextPointer.
+ * If Security::ContextPtr is given, starts reading the TLS handshake.
+ * Otherwise, calls switchToHttps to generate a dynamic Security::ContextPtr.
  */
 static void
-httpsEstablish(ConnStateData *connState, Security::ContextPointer sslContext)
+httpsEstablish(ConnStateData *connState, Security::ContextPtr sslContext)
 {
     Security::SessionPointer ssl = nullptr;
     assert(connState);
@@ -3739,7 +3531,7 @@
         debugs(33, 2, HERE << "sslBump not needed for " << connState->clientConnection);
         connState->sslBumpMode = Ssl::bumpNone;
     }
-    connState->fakeAConnectRequest("ssl-bump", connState->in.buf);
+    connState->fakeAConnectRequest("ssl-bump", connState->inBuf);
 }
 
 /** handle a new HTTPS connection */
@@ -3797,7 +3589,7 @@
         acl_checklist->nonBlockingCheck(httpsSslBumpAccessCheckDone, this);
         return;
     } else {
-        Security::ContextPointer sslContext = port->staticSslContext.get();
+        Security::ContextPtr sslContext = port->staticSslContext.get();
         httpsEstablish(this, sslContext);
     }
 }
@@ -3938,9 +3730,10 @@
 void
 ConnStateData::getSslContextStart()
 {
-    assert(areAllContextsForThisConnection());
-    freeAllContexts();
-    /* careful: freeAllContexts() above frees request, host, etc. */
+    // XXX starting SSL with a pipeline of requests still waiting for non-SSL replies?
+    assert(pipeline.count() < 2); // the CONNECT is okay for now. Anything else is a bug.
+    pipeline.terminateAll(0);
+    /* careful: terminateAll(0) above frees request, host, etc. */
 
     if (port->generateHostCertificates) {
         Ssl::CertificateProperties certProperties;
@@ -3952,7 +3745,7 @@
         if (!(sslServerBump && (sslServerBump->act.step1 == Ssl::bumpPeek || sslServerBump->act.step1 == Ssl::bumpStare))) {
             debugs(33, 5, "Finding SSL certificate for " << sslBumpCertKey << " in cache");
             Ssl::LocalContextStorage * ssl_ctx_cache = Ssl::TheGlobalContextStorage.getLocalStorage(port->s);
-            Security::ContextPointer dynCtx = nullptr;
+            Security::ContextPtr dynCtx = nullptr;
             Ssl::SSL_CTX_Pointer *cachedCtx = ssl_ctx_cache ? ssl_ctx_cache->get(sslBumpCertKey.termedBuf()) : NULL;
             if (cachedCtx && (dynCtx = cachedCtx->get())) {
                 debugs(33, 5, "SSL certificate for " << sslBumpCertKey << " found in cache");
@@ -4004,7 +3797,7 @@
 }
 
 void
-ConnStateData::getSslContextDone(Security::ContextPointer sslContext, bool isNew)
+ConnStateData::getSslContextDone(Security::ContextPtr sslContext, bool isNew)
 {
     // Try to add generated ssl context to storage.
     if (port->generateHostCertificates && isNew) {
@@ -4244,9 +4037,9 @@
 
         // reset the current protocol to HTTP/1.1 (was "HTTPS" for the bumping process)
         transferProtocol = Http::ProtocolVersion();
-        // in.buf still has the "CONNECT ..." request data, reset it to SSL hello message
-        in.buf.append(rbuf.content(), rbuf.contentSize());
-        ClientSocketContext::Pointer context = getCurrentContext();
+        // inBuf still has the "CONNECT ..." request data, reset it to SSL hello message
+        inBuf.append(rbuf.content(), rbuf.contentSize());
+        ClientSocketContext::Pointer context = pipeline.front();
         ClientHttpRequest *http = context->http;
         tunnelStart(http);
     }
@@ -4302,8 +4095,8 @@
         debugs(33, 5, HERE << "Error while bumping: " << sslConnectHostOrIp);
 
         //  copy error detail from bump-server-first request to CONNECT request
-        if (currentobject != NULL && currentobject->http != NULL && currentobject->http->request)
-            currentobject->http->request->detailError(sslServerBump->request->errType, sslServerBump->request->errDetail);
+        if (!pipeline.empty() && pipeline.front()->http != nullptr && pipeline.front()->http->request)
+            pipeline.front()->http->request->detailError(sslServerBump->request->errType, sslServerBump->request->errDetail);
     }
 
     getSslContextStart();
@@ -4335,7 +4128,7 @@
     retStr.append(connectHost);
     retStr.append("\r\n\r\n");
     retStr.append(payload);
-    in.buf = retStr;
+    inBuf = retStr;
     bool ret = handleReadData();
     if (ret)
         ret = clientParseRequests();
@@ -4379,27 +4172,36 @@
 clientHttpConnectionsOpen(void)
 {
     for (AnyP::PortCfgPointer s = HttpPortList; s != NULL; s = s->next) {
+        const char *scheme = AnyP::UriScheme(s->transport.protocol).c_str();
+
         if (MAXTCPLISTENPORTS == NHttpSockets) {
-            debugs(1, DBG_IMPORTANT, "WARNING: You have too many 'http_port' lines.");
+            debugs(1, DBG_IMPORTANT, "WARNING: You have too many '" << scheme << "_port' lines.");
             debugs(1, DBG_IMPORTANT, "         The limit is " << MAXTCPLISTENPORTS << " HTTP ports.");
             continue;
         }
 
 #if USE_OPENSSL
-        if (s->flags.tunnelSslBumping && !Config.accessList.ssl_bump) {
-            debugs(33, DBG_IMPORTANT, "WARNING: No ssl_bump configured. Disabling ssl-bump on " << AnyP::UriScheme(s->transport.protocol) << "_port " << s->s);
-            s->flags.tunnelSslBumping = false;
+        if (s->flags.tunnelSslBumping) {
+            if (!Config.accessList.ssl_bump) {
+                debugs(33, DBG_IMPORTANT, "WARNING: No ssl_bump configured. Disabling ssl-bump on " << scheme << "_port " << s->s);
+                s->flags.tunnelSslBumping = false;
+            }
+            if (!s->staticSslContext && !s->generateHostCertificates) {
+                debugs(1, DBG_IMPORTANT, "Will not bump SSL at " << scheme << "_port " << s->s << " due to TLS initialization failure.");
+                s->flags.tunnelSslBumping = false;
+                if (s->transport.protocol == AnyP::PROTO_HTTP)
+                    s->secure.encryptTransport = false;
+            }
+            if (s->flags.tunnelSslBumping) {
+                // Create ssl_ctx cache for this port.
+                auto sz = s->dynamicCertMemCacheSize == std::numeric_limits<size_t>::max() ? 4194304 : s->dynamicCertMemCacheSize;
+                Ssl::TheGlobalContextStorage.addLocalStorage(s->s, sz);
+            }
         }
 
-        if (s->flags.tunnelSslBumping &&
-                !s->staticSslContext &&
-                !s->generateHostCertificates) {
-            debugs(1, DBG_IMPORTANT, "Will not bump SSL at http_port " << s->s << " due to SSL initialization failure.");
-            s->flags.tunnelSslBumping = false;
-        }
-        if (s->flags.tunnelSslBumping) {
-            // Create ssl_ctx cache for this port.
-            Ssl::TheGlobalContextStorage.addLocalStorage(s->s, s->dynamicCertMemCacheSize == std::numeric_limits<size_t>::max() ? 4194304 : s->dynamicCertMemCacheSize);
+        if (s->secure.encryptTransport && !s->staticSslContext) {
+            debugs(1, DBG_CRITICAL, "ERROR: Ignoring " << scheme << "_port " << s->s << " due to TLS context initialization failure.");
+            continue;
         }
 #endif
 
@@ -4407,75 +4209,37 @@
         //  then pass back when active so we can start a TcpAcceptor subscription.
         s->listenConn = new Comm::Connection;
         s->listenConn->local = s->s;
-        s->listenConn->flags = COMM_NONBLOCKING | (s->flags.tproxyIntercept ? COMM_TRANSPARENT : 0) | (s->flags.natIntercept ? COMM_INTERCEPTION : 0);
-
-        // setup the subscriptions such that new connections accepted by listenConn are handled by HTTP
-        typedef CommCbFunPtrCallT<CommAcceptCbPtrFun> AcceptCall;
-        RefCount<AcceptCall> subCall = commCbCall(5, 5, "httpAccept", CommAcceptCbPtrFun(httpAccept, CommAcceptCbParams(NULL)));
-        Subscription::Pointer sub = new CallSubscription<AcceptCall>(subCall);
 
-        AsyncCall::Pointer listenCall = asyncCall(33,2, "clientListenerConnectionOpened",
-                                        ListeningStartedDialer(&clientListenerConnectionOpened, s, Ipc::fdnHttpSocket, sub));
-        Ipc::StartListening(SOCK_STREAM, IPPROTO_TCP, s->listenConn, Ipc::fdnHttpSocket, listenCall);
-
-        HttpSockets[NHttpSockets] = -1; // set in clientListenerConnectionOpened
-        ++NHttpSockets;
-    }
-}
-
-#if USE_OPENSSL
-static void
-clientHttpsConnectionsOpen(void)
-{
-    for (AnyP::PortCfgPointer s = HttpsPortList; s != NULL; s = s->next) {
-        if (MAXTCPLISTENPORTS == NHttpSockets) {
-            debugs(1, DBG_IMPORTANT, "Ignoring 'https_port' lines exceeding the limit.");
-            debugs(1, DBG_IMPORTANT, "The limit is " << MAXTCPLISTENPORTS << " HTTPS ports.");
-            continue;
-        }
-
-        if (!s->staticSslContext) {
-            debugs(1, DBG_IMPORTANT, "Ignoring https_port " << s->s <<
-                   " due to SSL initialization failure.");
-            continue;
-        }
-
-        // TODO: merge with similar code in clientHttpConnectionsOpen()
-        if (s->flags.tunnelSslBumping && !Config.accessList.ssl_bump) {
-            debugs(33, DBG_IMPORTANT, "WARNING: No ssl_bump configured. Disabling ssl-bump on " << AnyP::UriScheme(s->transport.protocol) << "_port " << s->s);
-            s->flags.tunnelSslBumping = false;
-        }
-
-        if (s->flags.tunnelSslBumping && !s->staticSslContext && !s->generateHostCertificates) {
-            debugs(1, DBG_IMPORTANT, "Will not bump SSL at https_port " << s->s << " due to SSL initialization failure.");
-            s->flags.tunnelSslBumping = false;
-        }
-
-        if (s->flags.tunnelSslBumping) {
-            // Create ssl_ctx cache for this port.
-            Ssl::TheGlobalContextStorage.addLocalStorage(s->s, s->dynamicCertMemCacheSize == std::numeric_limits<size_t>::max() ? 4194304 : s->dynamicCertMemCacheSize);
-        }
-
-        // Fill out a Comm::Connection which IPC will open as a listener for us
-        s->listenConn = new Comm::Connection;
-        s->listenConn->local = s->s;
         s->listenConn->flags = COMM_NONBLOCKING | (s->flags.tproxyIntercept ? COMM_TRANSPARENT : 0) |
                                (s->flags.natIntercept ? COMM_INTERCEPTION : 0);
 
-        // setup the subscriptions such that new connections accepted by listenConn are handled by HTTPS
         typedef CommCbFunPtrCallT<CommAcceptCbPtrFun> AcceptCall;
-        RefCount<AcceptCall> subCall = commCbCall(5, 5, "httpsAccept", CommAcceptCbPtrFun(httpsAccept, CommAcceptCbParams(NULL)));
-        Subscription::Pointer sub = new CallSubscription<AcceptCall>(subCall);
+        if (s->transport.protocol == AnyP::PROTO_HTTP) {
+            // setup the subscriptions such that new connections accepted by listenConn are handled by HTTP
+            RefCount<AcceptCall> subCall = commCbCall(5, 5, "httpAccept", CommAcceptCbPtrFun(httpAccept, CommAcceptCbParams(NULL)));
+            Subscription::Pointer sub = new CallSubscription<AcceptCall>(subCall);
+
+            AsyncCall::Pointer listenCall = asyncCall(33,2, "clientListenerConnectionOpened",
+                                            ListeningStartedDialer(&clientListenerConnectionOpened, s, Ipc::fdnHttpSocket, sub));
+            Ipc::StartListening(SOCK_STREAM, IPPROTO_TCP, s->listenConn, Ipc::fdnHttpSocket, listenCall);
+
+#if USE_OPENSSL
+        } else if (s->transport.protocol == AnyP::PROTO_HTTPS) {
+            // setup the subscriptions such that new connections accepted by listenConn are handled by HTTPS
+            RefCount<AcceptCall> subCall = commCbCall(5, 5, "httpsAccept", CommAcceptCbPtrFun(httpsAccept, CommAcceptCbParams(NULL)));
+            Subscription::Pointer sub = new CallSubscription<AcceptCall>(subCall);
+
+            AsyncCall::Pointer listenCall = asyncCall(33, 2, "clientListenerConnectionOpened",
+                                            ListeningStartedDialer(&clientListenerConnectionOpened,
+                                                    s, Ipc::fdnHttpsSocket, sub));
+            Ipc::StartListening(SOCK_STREAM, IPPROTO_TCP, s->listenConn, Ipc::fdnHttpsSocket, listenCall);
+#endif
+        }
 
-        AsyncCall::Pointer listenCall = asyncCall(33, 2, "clientListenerConnectionOpened",
-                                        ListeningStartedDialer(&clientListenerConnectionOpened,
-                                                s, Ipc::fdnHttpsSocket, sub));
-        Ipc::StartListening(SOCK_STREAM, IPPROTO_TCP, s->listenConn, Ipc::fdnHttpsSocket, listenCall);
-        HttpSockets[NHttpSockets] = -1;
+        HttpSockets[NHttpSockets] = -1; // set in clientListenerConnectionOpened
         ++NHttpSockets;
     }
 }
-#endif
 
 void
 clientStartListeningOn(AnyP::PortCfgPointer &port, const RefCount< CommCbFunPtrCallT<CommAcceptCbPtrFun> > &subCall, const Ipc::FdNoteId fdNote)
@@ -4531,9 +4295,6 @@
 clientOpenListenSockets(void)
 {
     clientHttpConnectionsOpen();
-#if USE_OPENSSL
-    clientHttpsConnectionsOpen();
-#endif
     Ftp::StartListening();
 
     if (NHttpSockets < 1)
@@ -4545,21 +4306,11 @@
 {
     for (AnyP::PortCfgPointer s = HttpPortList; s != NULL; s = s->next) {
         if (s->listenConn != NULL) {
-            debugs(1, DBG_IMPORTANT, "Closing HTTP port " << s->listenConn->local);
-            s->listenConn->close();
-            s->listenConn = NULL;
-        }
-    }
-
-#if USE_OPENSSL
-    for (AnyP::PortCfgPointer s = HttpsPortList; s != NULL; s = s->next) {
-        if (s->listenConn != NULL) {
-            debugs(1, DBG_IMPORTANT, "Closing HTTPS port " << s->listenConn->local);
+            debugs(1, DBG_IMPORTANT, "Closing HTTP(S) port " << s->listenConn->local);
             s->listenConn->close();
             s->listenConn = NULL;
         }
     }
-#endif
 
     Ftp::StopListening();
 
@@ -4655,21 +4406,6 @@
     return clientConnection != NULL && (clientConnection->flags & (COMM_TRANSPARENT|COMM_INTERCEPTION));
 }
 
-bool
-ConnStateData::reading() const
-{
-    return reader != NULL;
-}
-
-void
-ConnStateData::stopReading()
-{
-    if (reading()) {
-        Comm::ReadCancel(clientConnection->fd, reader);
-        reader = NULL;
-    }
-}
-
 BodyPipe::Pointer
 ConnStateData::expectRequestBody(int64_t size)
 {
@@ -4691,7 +4427,7 @@
         return -1; // probably need to read more, but we cannot be sure
 
     const int64_t needToProduce = bodyPipe->unproducedSize();
-    const int64_t haveAvailable = static_cast<int64_t>(in.buf.length());
+    const int64_t haveAvailable = static_cast<int64_t>(inBuf.length());
 
     if (needToProduce <= haveAvailable)
         return 0; // we have read what we need (but are waiting for pipe space)
@@ -4734,8 +4470,8 @@
 {
     Must(bodyPipe != NULL);
     debugs(33, 5, HERE << "start dechunking" << bodyPipe->status());
-    assert(!in.bodyParser);
-    in.bodyParser = new Http1::TeChunkedParser;
+    assert(!bodyParser);
+    bodyParser = new Http1::TeChunkedParser;
 }
 
 /// put parsed content into input buffer and clean up
@@ -4751,26 +4487,17 @@
         Must(!bodyPipe); // we rely on it being nil after we are done with body
         if (withSuccess) {
             Must(myPipe->bodySizeKnown());
-            ClientSocketContext::Pointer context = getCurrentContext();
+            ClientSocketContext::Pointer context = pipeline.front();
             if (context != NULL && context->http && context->http->request)
                 context->http->request->setContentLength(myPipe->bodySize());
         }
     }
 
-    delete in.bodyParser;
-    in.bodyParser = NULL;
-}
-
-ConnStateData::In::In() :
-    bodyParser(NULL),
-    buf()
-{}
-
-ConnStateData::In::~In()
-{
-    delete bodyParser; // TODO: pool
+    delete bodyParser;
+    bodyParser = NULL;
 }
 
+// XXX: this is an HTTP/1-only operation
 void
 ConnStateData::sendControlMsg(HttpControlMsg msg)
 {
@@ -4779,9 +4506,8 @@
         return;
     }
 
-    ClientSocketContext::Pointer context = getCurrentContext();
-    if (context != NULL) {
-        context->writeControlMsg(msg); // will call msg.cbSuccess
+    if (!pipeline.empty()) {
+        pipeline.front()->writeControlMsg(msg); // will call msg.cbSuccess
         return;
     }
 
@@ -4884,6 +4610,46 @@
     }
 }
 
+#if USE_OPENSSL
+bool
+ConnStateData::handleIdleClientPinnedTlsRead()
+{
+    // A ready-for-reading connection means that the TLS server either closed
+    // the connection, sent us some unexpected HTTP data, or started TLS
+    // renegotiations. We should close the connection except for the last case.
+
+    Must(pinning.serverConnection != nullptr);
+    SSL *ssl = fd_table[pinning.serverConnection->fd].ssl;
+    if (!ssl)
+        return false;
+
+    char buf[1];
+    const int readResult = SSL_read(ssl, buf, sizeof(buf));
+
+    if (readResult > 0 || SSL_pending(ssl) > 0) {
+        debugs(83, 2, pinning.serverConnection << " TLS application data read");
+        return false;
+    }
+
+    switch(const int error = SSL_get_error(ssl, readResult)) {
+    case SSL_ERROR_WANT_WRITE:
+        debugs(83, DBG_IMPORTANT, pinning.serverConnection << " TLS SSL_ERROR_WANT_WRITE request for idle pinned connection");
+    // fall through to restart monitoring, for now
+    case SSL_ERROR_NONE:
+    case SSL_ERROR_WANT_READ:
+        startPinnedConnectionMonitoring();
+        return true;
+
+    default:
+        debugs(83, 2, pinning.serverConnection << " TLS error: " << error);
+        return false;
+    }
+
+    // not reached
+    return true;
+}
+#endif
+
 /// Our read handler called by Comm when the server either closes an idle pinned connection or
 /// perhaps unexpectedly sends something on that idle (from Squid p.o.v.) connection.
 void
@@ -4894,17 +4660,22 @@
     if (io.flag == Comm::ERR_CLOSING)
         return; // close handler will clean up
 
-    // We could use getConcurrentRequestCount(), but this may be faster.
-    const bool clientIsIdle = !getCurrentContext();
+    Must(pinning.serverConnection == io.conn);
+
+#if USE_OPENSSL
+    if (handleIdleClientPinnedTlsRead())
+        return;
+#endif
+
+    const bool clientIsIdle = pipeline.empty();
 
     debugs(33, 3, "idle pinned " << pinning.serverConnection << " read " <<
            io.size << (clientIsIdle ? " with idle client" : ""));
 
-    assert(pinning.serverConnection == io.conn);
     pinning.serverConnection->close();
 
     // If we are still sending data to the client, do not close now. When we are done sending,
-    // ClientSocketContext::keepaliveNextRequest() checks pinning.serverConnection and will close.
+    // ConnStateData::kick() checks pinning.serverConnection and will close.
     // However, if we are idle, then we must close to inform the idle client and minimize races.
     if (clientIsIdle && clientConnection != NULL)
         clientConnection->close();
diff -u -r -N squid-4.0.2/src/client_side.h squid-4.0.3/src/client_side.h
--- squid-4.0.2/src/client_side.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/client_side.h	2015-11-28 07:30:57.000000000 -0800
@@ -19,6 +19,7 @@
 #include "HttpControlMsg.h"
 #include "ipc/FdNotes.h"
 #include "SBuf.h"
+#include "servers/Server.h"
 #if USE_AUTH
 #include "auth/UserRequest.h"
 #endif
@@ -36,24 +37,39 @@
 
 /**
  * Badly named.
- * This is in fact the processing context for a single HTTP request.
+ * This is in fact the processing context for a single HTTP transaction.
  *
- * Managing what has been done, and what happens next to the data buffer
- * holding what we hope is an HTTP request.
+ * A context lifetime extends from directly after a request has been parsed
+ * off the client connection buffer, until the last byte of both request
+ * and reply payload (if any) have been written.
  *
- * Parsing is still a mess of global functions done in conjunction with the
- * real socket controller which generated ClientHttpRequest.
- * It also generates one of us and passes us control from there based on
- * the results of the parse.
+ * (NOTE: it is not certain yet if an early reply to a POST/PUT is sent by
+ * the server whether the context will remain in the pipeline until its
+ * request payload has finished being read. It is supposed to, but may not)
  *
- * After that all the request interpretation and adaptation is in our scope.
- * Then finally the reply fetcher is created by this and we get the result
- * back. Which we then have to manage writing of it to the ConnStateData.
+ * Contexts self-register with the Pipeline being managed by the Server
+ * for the connection on which the request was received.
  *
- * The socket level management is done by a ConnStateData which owns us.
+ * When HTTP/1 pipeline is operating there may be multiple transactions using
+ * the clientConnection. Only the back() context may read from the connection,
+ * and only the front() context may write to it. A context which needs to read
+ * or write to the connection but does not meet those criteria must be shifted
+ * to the deferred state.
+ *
+ * When a context is completed the finished() method needs to be called which
+ * will perform all cleanup and deregistration operations. If the reason for
+ * finishing is an error, then notifyIoError() needs to be called prior to
+ * the finished() method.
+ * The caller should follow finished() with a call to ConnStateData::kick()
+ * to resume processing of other transactions or I/O on the connection.
+ *
+ * Alternatively the initiateClose() method can be called to terminate the
+ * whole client connection and all other pending contexts.
+ *
+ * The socket level management is done by a Server which owns us.
  * The scope of this objects control over a socket consists of the data
- * buffer received from ConnStateData with an initially unknown length.
- * When that length is known it sets the end bounary of our acces to the
+ * buffer received from the Server with an initially unknown length.
+ * When that length is known it sets the end boundary of our access to the
  * buffer.
  *
  * The individual processing actions are done by other Jobs which we
@@ -61,7 +77,7 @@
  *
  * XXX: If an async call ends the ClientHttpRequest job, ClientSocketContext
  * (and ConnStateData) may not know about it, leading to segfaults and
- * assertions like areAllContextsForThisConnection(). This is difficult to fix
+ * assertions. This is difficult to fix
  * because ClientHttpRequest lacks a good way to communicate its ongoing
  * destruction back to the ClientSocketContext which pretends to "own" *http.
  */
@@ -75,13 +91,11 @@
     ~ClientSocketContext();
     bool startOfOutput() const;
     void writeComplete(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, Comm::Flag errflag);
-    void keepaliveNextRequest();
 
     Comm::ConnectionPointer clientConnection; /// details about the client connection socket.
     ClientHttpRequest *http;    /* we pretend to own that job */
     HttpReply *reply;
     char reqbuf[HTTP_REQBUF_SZ];
-    Pointer next;
 
     struct {
 
@@ -119,8 +133,7 @@
     clientStreamNode * getTail() const;
     clientStreamNode * getClientReplyContext() const;
     ConnStateData *getConn() const;
-    void connIsFinished();
-    void removeFromConnectionList(ConnStateData * conn);
+    void finished(); ///< cleanup when the transaction has finished. may destroy 'this'
     void deferRecipientForLater(clientStreamNode * node, HttpReply * rep, StoreIOBuffer receivedData);
     bool multipartRangeRequest() const;
     void registerWithConn();
@@ -137,7 +150,6 @@
     void prepareReply(HttpReply * rep);
     void packChunk(const StoreIOBuffer &bodyData, MemBuf &mb);
     void packRange(StoreIOBuffer const &, MemBuf * mb);
-    void deRegisterWithConn();
     void doClose();
     void initiateClose(const char *reason);
 
@@ -154,63 +166,56 @@
 class ServerBump;
 }
 #endif
+
 /**
- * Manages a connection to a client.
+ * Legacy Server code managing a connection to a client.
+ *
+ * NP: presents AsyncJob API but does not operate autonomously as a Job.
+ *     So Must() is not safe to use.
+ *
+ * Multiple requests (up to pipeline_prefetch) can be pipelined.
+ * This object is responsible for managing which one is currently being
+ * fulfilled and what happens to the queue if the current one causes the client
+ * connection to be closed early.
  *
- * Multiple requests (up to pipeline_prefetch) can be pipelined. This object is responsible for managing
- * which one is currently being fulfilled and what happens to the queue if the current one
- * causes the client connection to be closed early.
- *
- * Act as a manager for the connection and passes data in buffer to the current parser.
- * the parser has ambiguous scope at present due to being made from global functions
- * I believe this object uses the parser to identify boundaries and kick off the
- * actual HTTP request handling objects (ClientSocketContext, ClientHttpRequest, HttpRequest)
+ * Act as a manager for the client connection and passes data in buffer to a
+ * Parser relevant to the state (message headers vs body) that is being
+ * processed.
  *
- * If the above can be confirmed accurate we can call this object PipelineManager or similar
+ * Performs HTTP message processing to kick off the actual HTTP request
+ * handling objects (ClientSocketContext, ClientHttpRequest, HttpRequest).
+ *
+ * Performs SSL-Bump processing for switching between HTTP and HTTPS protocols.
+ *
+ * To terminate a ConnStateData close() the client Comm::Connection it is
+ * managing, or for graceful half-close use the stopReceiving() or
+ * stopSending() methods.
  */
-class ConnStateData : public BodyProducer, public HttpControlMsgSink, public RegisteredRunner
+class ConnStateData : public Server, public HttpControlMsgSink, public RegisteredRunner
 {
 
 public:
     explicit ConnStateData(const MasterXaction::Pointer &xact);
     virtual ~ConnStateData();
 
-    void readSomeData();
-    bool areAllContextsForThisConnection() const;
-    void freeAllContexts();
-    void notifyAllContexts(const int xerrno); ///< tell everybody about the err
+    /* ::Server API */
+    virtual void receivedFirstByte();
+    virtual bool handleReadData();
+    virtual void afterClientRead();
+
     /// Traffic parsing
     bool clientParseRequests();
     void readNextRequest();
-    ClientSocketContext::Pointer getCurrentContext() const;
-    void addContextToQueue(ClientSocketContext * context);
-    int getConcurrentRequestCount() const;
-    bool isOpen() const;
 
-    /// Update flags and timeout after the first byte received
-    void receivedFirstByte();
+    /// try to make progress on a transaction or read more I/O
+    void kick();
+
+    bool isOpen() const;
 
     // HttpControlMsgSink API
     virtual void sendControlMsg(HttpControlMsg msg);
 
-    // Client TCP connection details from comm layer.
-    Comm::ConnectionPointer clientConnection;
-
-    /**
-     * The transfer protocol currently being spoken on this connection.
-     * HTTP/1 CONNECT and HTTP/2 SETTINGS offers the ability to change
-     * protocols on the fly.
-     */
-    AnyP::ProtocolVersion transferProtocol;
-
-    struct In {
-        In();
-        ~In();
-        bool maybeMakeSpaceAvailable();
-
-        Http1::TeChunkedParser *bodyParser; ///< parses chunked request body
-        SBuf buf;
-    } in;
+    Http1::TeChunkedParser *bodyParser; ///< parses HTTP/1.1 chunked request body
 
     /** number of body bytes we need to comm_read for the "current" request
      *
@@ -238,14 +243,7 @@
     void setAuth(const Auth::UserRequest::Pointer &aur, const char *cause);
 #endif
 
-    /**
-     * used by the owner of the connection, opaque otherwise
-     * TODO: generalise the connection owner concept.
-     */
-    ClientSocketContext::Pointer currentobject;
-
     Ip::Address log_addr;
-    int nrequests;
 
     struct {
         bool readMore; ///< needs comm_read (for this request or new requests)
@@ -264,12 +262,7 @@
         AsyncCall::Pointer closeHandler; /*The close handler for pinned server side connection*/
     } pinning;
 
-    /// Squid listening port details where this connection arrived.
-    AnyP::PortCfgPointer port;
-
     bool transparent() const;
-    bool reading() const;
-    void stopReading(); ///< cancels comm_read if it is scheduled
 
     /// true if we stopped receiving the request
     const char *stoppedReceiving() const { return stoppedReceiving_; }
@@ -287,7 +280,6 @@
     virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer) = 0;
     virtual void noteBodyConsumerAborted(BodyPipe::Pointer) = 0;
 
-    bool handleReadData();
     bool handleRequestBodyData();
 
     /// Forward future client requests using the given server connection.
@@ -318,7 +310,6 @@
     virtual void clientPinnedConnectionClosed(const CommCloseCbParams &io);
 
     // comm callbacks
-    void clientReadRequest(const CommIoCbParams &io);
     void clientReadFtpData(const CommIoCbParams &io);
     void connStateClosed(const CommCloseCbParams &io);
     void requestTimeout(const CommTimeoutCbParams &params);
@@ -358,14 +349,14 @@
     /// \retval false otherwise
     bool spliceOnError(const err_type err);
 
-    /// Start to create dynamic SSL_CTX for host or uses static port SSL context.
+    /// Start to create dynamic Security::ContextPtr for host or uses static port SSL context.
     void getSslContextStart();
     /**
      * Done create dynamic ssl certificate.
      *
      * \param[in] isNew if generated certificate is new, so we need to add this certificate to storage.
      */
-    void getSslContextDone(Security::ContextPointer sslContext, bool isNew = false);
+    void getSslContextDone(Security::ContextPtr sslContext, bool isNew = false);
     /// Callback function. It is called when squid receive message from ssl_crtd.
     static void sslCrtdHandleReplyWrapper(void *data, const Helper::Reply &reply);
     /// Proccess response from ssl_crtd.
@@ -436,6 +427,12 @@
 
     void startPinnedConnectionMonitoring();
     void clientPinnedConnectionRead(const CommIoCbParams &io);
+#if USE_OPENSSL
+    /// Handles a ready-for-reading TLS squid-to-server connection that
+    /// we thought was idle.
+    /// \return false if and only if the connection should be closed.
+    bool handleIdleClientPinnedTlsRead();
+#endif
 
     /// parse input buffer prefix into a single transfer protocol request
     /// return NULL to request more header bytes (after checking any limits)
@@ -454,7 +451,9 @@
     BodyPipe::Pointer bodyPipe; ///< set when we are reading request body
 
 private:
-    int connFinishedWithConn(int size);
+    /* ::Server API */
+    virtual bool connFinishedWithConn(int size);
+
     void clientAfterReadingRequests();
     bool concurrentRequestQueueFilled() const;
 
@@ -495,9 +494,6 @@
     /// the reason why we no longer read the request or nil
     const char *stoppedReceiving_;
 
-    AsyncCall::Pointer reader; ///< set when we are reading
-
-    bool receivedFirstByte_; ///< true if at least one byte received on this connection
     SBuf connectionTag_; ///< clt_conn_tag=Tag annotation for client connection
 };
 
diff -u -r -N squid-4.0.2/src/client_side_request.cc squid-4.0.3/src/client_side_request.cc
--- squid-4.0.2/src/client_side_request.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/client_side_request.cc	2015-11-28 07:30:57.000000000 -0800
@@ -1722,7 +1722,6 @@
 
         if (!calloutContext->redirect_done) {
             calloutContext->redirect_done = true;
-            assert(calloutContext->redirect_state == REDIRECT_NONE);
 
             if (Config.Program.redirect) {
                 debugs(83, 3, HERE << "Doing calloutContext->clientRedirectStart()");
@@ -1741,7 +1740,6 @@
 
         if (!calloutContext->store_id_done) {
             calloutContext->store_id_done = true;
-            assert(calloutContext->store_id_state == REDIRECT_NONE);
 
             if (Config.Program.store_id) {
                 debugs(83, 3,"Doing calloutContext->clientStoreIdStart()");
diff -u -r -N squid-4.0.2/src/comm/Makefile.in squid-4.0.3/src/comm/Makefile.in
--- squid-4.0.2/src/comm/Makefile.in	2015-11-01 04:19:21.000000000 -0800
+++ squid-4.0.3/src/comm/Makefile.in	2015-11-28 07:32:42.000000000 -0800
@@ -463,6 +463,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -496,7 +497,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/disk.cc squid-4.0.3/src/disk.cc
--- squid-4.0.2/src/disk.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/disk.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,524 +0,0 @@
-/*
- * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-/* DEBUG: section 06    Disk I/O Routines */
-
-#include "squid.h"
-#include "comm/Loops.h"
-#include "disk.h"
-#include "fd.h"
-#include "fde.h"
-#include "globals.h"
-#include "MemBuf.h"
-#include "profiler/Profiler.h"
-#include "StatCounters.h"
-
-#include <cerrno>
-
-static PF diskHandleRead;
-static PF diskHandleWrite;
-
-#if _SQUID_WINDOWS_ || _SQUID_OS2_
-static int
-diskWriteIsComplete(int fd)
-{
-    return fd_table[fd].disk.write_q ? 0 : 1;
-}
-
-#endif
-
-void
-disk_init(void)
-{
-    (void) 0;
-}
-
-/* hack needed on SunStudio to avoid linkage convention mismatch */
-static void cxx_xfree(void *ptr)
-{
-    xfree(ptr);
-}
-
-/*
- * opens a disk file specified by 'path'.  This function always
- * blocks!  There is no callback.
- */
-int
-file_open(const char *path, int mode)
-{
-    int fd;
-    PROF_start(file_open);
-
-    if (FILE_MODE(mode) == O_WRONLY)
-        mode |= O_APPEND;
-
-    errno = 0;
-
-    fd = open(path, mode, 0644);
-
-    ++ statCounter.syscalls.disk.opens;
-
-    if (fd < 0) {
-        debugs(50, 3, "file_open: error opening file " << path << ": " << xstrerror());
-        fd = DISK_ERROR;
-    } else {
-        debugs(6, 5, "file_open: FD " << fd);
-        commSetCloseOnExec(fd);
-        fd_open(fd, FD_FILE, path);
-    }
-
-    PROF_stop(file_open);
-    return fd;
-}
-
-/* close a disk file. */
-void
-file_close(int fd)
-{
-    fde *F = &fd_table[fd];
-    PF *read_callback;
-    PROF_start(file_close);
-    assert(fd >= 0);
-    assert(F->flags.open);
-
-    if ((read_callback = F->read_handler)) {
-        F->read_handler = NULL;
-        read_callback(-1, F->read_data);
-    }
-
-    if (F->flags.write_daemon) {
-#if _SQUID_WINDOWS_ || _SQUID_OS2_
-        /*
-         * on some operating systems, you can not delete or rename
-         * open files, so we won't allow delayed close.
-         */
-        while (!diskWriteIsComplete(fd))
-            diskHandleWrite(fd, NULL);
-#else
-        F->flags.close_request = true;
-        debugs(6, 2, "file_close: FD " << fd << ", delaying close");
-        PROF_stop(file_close);
-        return;
-#endif
-
-    }
-
-    /*
-     * Assert there is no write callback.  Otherwise we might be
-     * leaking write state data by closing the descriptor
-     */
-    assert(F->write_handler == NULL);
-
-#if CALL_FSYNC_BEFORE_CLOSE
-
-    fsync(fd);
-
-#endif
-
-    close(fd);
-
-    debugs(6, F->flags.close_request ? 2 : 5, "file_close: FD " << fd << " really closing\n");
-
-    fd_close(fd);
-
-    ++ statCounter.syscalls.disk.closes;
-
-    PROF_stop(file_close);
-}
-
-/*
- * This function has the purpose of combining multiple writes.  This is
- * to facilitate the ASYNC_IO option since it can only guarantee 1
- * write to a file per trip around the comm.c select() loop. That's bad
- * because more than 1 write can be made to the access.log file per
- * trip, and so this code is purely designed to help batch multiple
- * sequential writes to the access.log file.  Squid will never issue
- * multiple writes for any other file type during 1 trip around the
- * select() loop.       --SLF
- */
-static void
-diskCombineWrites(_fde_disk *fdd)
-{
-    /*
-     * We need to combine multiple write requests on an FD's write
-     * queue But only if we don't need to seek() in between them, ugh!
-     * XXX This currently ignores any seeks (file_offset)
-     */
-
-    if (fdd->write_q != NULL && fdd->write_q->next != NULL) {
-        int len = 0;
-
-        for (dwrite_q *q = fdd->write_q; q != NULL; q = q->next)
-            len += q->len - q->buf_offset;
-
-        dwrite_q *wq = (dwrite_q *)memAllocate(MEM_DWRITE_Q);
-
-        wq->buf = (char *)xmalloc(len);
-
-        wq->len = 0;
-
-        wq->buf_offset = 0;
-
-        wq->next = NULL;
-
-        wq->free_func = cxx_xfree;
-
-        while (fdd->write_q != NULL) {
-            dwrite_q *q = fdd->write_q;
-
-            len = q->len - q->buf_offset;
-            memcpy(wq->buf + wq->len, q->buf + q->buf_offset, len);
-            wq->len += len;
-            fdd->write_q = q->next;
-
-            if (q->free_func)
-                q->free_func(q->buf);
-
-            memFree(q, MEM_DWRITE_Q);
-        };
-
-        fdd->write_q_tail = wq;
-
-        fdd->write_q = wq;
-    }
-}
-
-/* write handler */
-static void
-diskHandleWrite(int fd, void *)
-{
-    int len = 0;
-    fde *F = &fd_table[fd];
-
-    _fde_disk *fdd = &F->disk;
-    dwrite_q *q = fdd->write_q;
-    int status = DISK_OK;
-    bool do_close;
-
-    if (NULL == q)
-        return;
-
-    PROF_start(diskHandleWrite);
-
-    debugs(6, 3, "diskHandleWrite: FD " << fd);
-
-    F->flags.write_daemon = false;
-
-    assert(fdd->write_q != NULL);
-
-    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 at " <<
-           fdd->write_q->file_offset);
-
-    errno = 0;
-
-    if (fdd->write_q->file_offset != -1) {
-        errno = 0;
-        if (lseek(fd, fdd->write_q->file_offset, SEEK_SET) == -1) {
-            debugs(50, DBG_IMPORTANT, "error in seek for fd " << fd << ": " << xstrerror());
-            // XXX: handle error?
-        }
-    }
-
-    len = FD_WRITE_METHOD(fd,
-                          fdd->write_q->buf + fdd->write_q->buf_offset,
-                          fdd->write_q->len - fdd->write_q->buf_offset);
-
-    debugs(6, 3, "diskHandleWrite: FD " << fd << " len = " << len);
-
-    ++ statCounter.syscalls.disk.writes;
-
-    fd_bytes(fd, len, FD_WRITE);
-
-    if (len < 0) {
-        if (!ignoreErrno(errno)) {
-            status = errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR;
-            debugs(50, DBG_IMPORTANT, "diskHandleWrite: FD " << fd << ": disk write error: " << xstrerror());
-
-            /*
-             * If there is no write callback, then this file is
-             * most likely something important like a log file, or
-             * an interprocess pipe.  Its not a swapfile.  We feel
-             * that a write failure on a log file is rather important,
-             * and Squid doesn't otherwise deal with this condition.
-             * So to get the administrators attention, we exit with
-             * a fatal message.
-             */
-
-            if (fdd->wrt_handle == NULL)
-                fatal("Write failure -- check your disk space and cache.log");
-
-            /*
-             * If there is a write failure, then we notify the
-             * upper layer via the callback, at the end of this
-             * function.  Meanwhile, flush all pending buffers
-             * here.  Let the upper layer decide how to handle the
-             * failure.  This will prevent experiencing multiple,
-             * repeated write failures for the same FD because of
-             * the queued data.
-             */
-            do {
-                fdd->write_q = q->next;
-
-                if (q->free_func)
-                    q->free_func(q->buf);
-
-                if (q) {
-                    memFree(q, MEM_DWRITE_Q);
-                    q = NULL;
-                }
-            } while ((q = fdd->write_q));
-        }
-
-        len = 0;
-    }
-
-    if (q != NULL) {
-        /* q might become NULL from write failure above */
-        q->buf_offset += len;
-
-        if (q->buf_offset > q->len)
-            debugs(50, DBG_IMPORTANT, "diskHandleWriteComplete: q->buf_offset > q->len (" <<
-                   q << "," << (int) q->buf_offset << ", " << q->len << ", " <<
-                   len << " FD " << fd << ")");
-
-        assert(q->buf_offset <= q->len);
-
-        if (q->buf_offset == q->len) {
-            /* complete write */
-            fdd->write_q = q->next;
-
-            if (q->free_func)
-                q->free_func(q->buf);
-
-            if (q) {
-                memFree(q, MEM_DWRITE_Q);
-                q = NULL;
-            }
-        }
-    }
-
-    if (fdd->write_q == NULL) {
-        /* no more data */
-        fdd->write_q_tail = NULL;
-    } else {
-        /* another block is queued */
-        diskCombineWrites(fdd);
-        Comm::SetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0);
-        F->flags.write_daemon = true;
-    }
-
-    do_close = F->flags.close_request;
-
-    if (fdd->wrt_handle) {
-        DWCB *callback = fdd->wrt_handle;
-        void *cbdata;
-        fdd->wrt_handle = NULL;
-
-        if (cbdataReferenceValidDone(fdd->wrt_handle_data, &cbdata)) {
-            callback(fd, status, len, cbdata);
-            /*
-             * NOTE, this callback can close the FD, so we must
-             * not touch 'F', 'fdd', etc. after this.
-             */
-            PROF_stop(diskHandleWrite);
-            return;
-            /* XXX But what about close_request??? */
-        }
-    }
-
-    if (do_close)
-        file_close(fd);
-
-    PROF_stop(diskHandleWrite);
-}
-
-/* write block to a file */
-/* write back queue. Only one writer at a time. */
-/* call a handle when writing is complete. */
-void
-file_write(int fd,
-           off_t file_offset,
-           void const *ptr_to_buf,
-           int len,
-           DWCB * handle,
-           void *handle_data,
-           FREE * free_func)
-{
-    dwrite_q *wq = NULL;
-    fde *F = &fd_table[fd];
-    PROF_start(file_write);
-    assert(fd >= 0);
-    assert(F->flags.open);
-    /* if we got here. Caller is eligible to write. */
-    wq = (dwrite_q *)memAllocate(MEM_DWRITE_Q);
-    wq->file_offset = file_offset;
-    wq->buf = (char *)ptr_to_buf;
-    wq->len = len;
-    wq->buf_offset = 0;
-    wq->next = NULL;
-    wq->free_func = free_func;
-
-    if (!F->disk.wrt_handle_data) {
-        F->disk.wrt_handle = handle;
-        F->disk.wrt_handle_data = cbdataReference(handle_data);
-    } else {
-        /* Detect if there is multiple concurrent users of this fd.. we only support one callback */
-        assert(F->disk.wrt_handle_data == handle_data && F->disk.wrt_handle == handle);
-    }
-
-    /* add to queue */
-    if (F->disk.write_q == NULL) {
-        /* empty queue */
-        F->disk.write_q = F->disk.write_q_tail = wq;
-    } else {
-        F->disk.write_q_tail->next = wq;
-        F->disk.write_q_tail = wq;
-    }
-
-    if (!F->flags.write_daemon) {
-        diskHandleWrite(fd, NULL);
-    }
-
-    PROF_stop(file_write);
-}
-
-/*
- * a wrapper around file_write to allow for MemBuf to be file_written
- * in a snap
- */
-void
-file_write_mbuf(int fd, off_t off, MemBuf mb, DWCB * handler, void *handler_data)
-{
-    file_write(fd, off, mb.buf, mb.size, handler, handler_data, mb.freeFunc());
-}
-
-/* Read from FD */
-static void
-diskHandleRead(int fd, void *data)
-{
-    dread_ctrl *ctrl_dat = (dread_ctrl *)data;
-    fde *F = &fd_table[fd];
-    int len;
-    int rc = DISK_OK;
-    /*
-     * FD < 0 indicates premature close; we just have to free
-     * the state data.
-     */
-
-    if (fd < 0) {
-        memFree(ctrl_dat, MEM_DREAD_CTRL);
-        return;
-    }
-
-    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);
-        errno = 0;
-        if (lseek(fd, ctrl_dat->offset, SEEK_SET) == -1) {
-            // shouldn't happen, let's detect that
-            debugs(50, DBG_IMPORTANT, "error in seek for fd " << fd << ": " << xstrerror());
-            // XXX handle failures?
-        }
-        ++ statCounter.syscalls.disk.seeks;
-        F->disk.offset = ctrl_dat->offset;
-    }
-
-    errno = 0;
-    len = FD_READ_METHOD(fd, ctrl_dat->buf, ctrl_dat->req_len);
-
-    if (len > 0)
-        F->disk.offset += len;
-
-    ++ statCounter.syscalls.disk.reads;
-
-    fd_bytes(fd, len, FD_READ);
-
-    if (len < 0) {
-        if (ignoreErrno(errno)) {
-            Comm::SetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0);
-            PROF_stop(diskHandleRead);
-            return;
-        }
-
-        debugs(50, DBG_IMPORTANT, "diskHandleRead: FD " << fd << ": " << xstrerror());
-        len = 0;
-        rc = DISK_ERROR;
-    } else if (len == 0) {
-        rc = DISK_EOF;
-    }
-
-    if (cbdataReferenceValid(ctrl_dat->client_data))
-        ctrl_dat->handler(fd, ctrl_dat->buf, len, rc, ctrl_dat->client_data);
-
-    cbdataReferenceDone(ctrl_dat->client_data);
-
-    memFree(ctrl_dat, MEM_DREAD_CTRL);
-
-    PROF_stop(diskHandleRead);
-}
-
-/* start read operation */
-/* buffer must be allocated from the caller.
- * It must have at least req_len space in there.
- * call handler when a reading is complete. */
-void
-file_read(int fd, char *buf, int req_len, off_t offset, DRCB * handler, void *client_data)
-{
-    dread_ctrl *ctrl_dat;
-    PROF_start(file_read);
-    assert(fd >= 0);
-    ctrl_dat = (dread_ctrl *)memAllocate(MEM_DREAD_CTRL);
-    ctrl_dat->fd = fd;
-    ctrl_dat->offset = offset;
-    ctrl_dat->req_len = req_len;
-    ctrl_dat->buf = buf;
-    ctrl_dat->end_of_file = 0;
-    ctrl_dat->handler = handler;
-    ctrl_dat->client_data = cbdataReference(client_data);
-    diskHandleRead(fd, ctrl_dat);
-    PROF_stop(file_read);
-}
-
-void
-safeunlink(const char *s, int quiet)
-{
-    ++ statCounter.syscalls.disk.unlinks;
-
-    if (unlink(s) < 0 && !quiet)
-        debugs(50, DBG_IMPORTANT, "safeunlink: Couldn't delete " << s << ": " << xstrerror());
-}
-
-/*
- * Same as rename(2) but complains if something goes wrong;
- * the caller is responsible for handing and explaining the
- * consequences of errors.
- */
-int
-xrename(const char *from, const char *to)
-{
-    debugs(21, 2, "xrename: renaming " << from << " to " << to);
-#if _SQUID_OS2_ || _SQUID_WINDOWS_
-    remove(to);
-#endif
-
-    if (0 == rename(from, to))
-        return 0;
-
-    debugs(21, errno == ENOENT ? 2 : 1, "xrename: Cannot rename " << from << " to " << to << ": " << xstrerror());
-
-    return -1;
-}
-
diff -u -r -N squid-4.0.2/src/disk.h squid-4.0.3/src/disk.h
--- squid-4.0.2/src/disk.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/disk.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-/* DEBUG: section 06    Disk I/O Routines */
-
-#ifndef SQUID_DISK_H_
-#define SQUID_DISK_H_
-
-#include "mem/forward.h"
-#include "typedefs.h" //DRCB, DWCB
-
-class MemBuf;
-
-// POD
-class dread_ctrl
-{
-public:
-    int fd;
-    off_t offset;
-    int req_len;
-    char *buf;
-    int end_of_file;
-    DRCB *handler;
-    void *client_data;
-};
-
-// POD
-class dwrite_q
-{
-public:
-    off_t file_offset;
-    char *buf;
-    size_t len;
-    size_t buf_offset;
-    dwrite_q *next;
-    FREE *free_func;
-};
-
-int file_open(const char *path, int mode);
-void file_close(int fd);
-
-/* Adapter file_write for object callbacks */
-template <class O>
-void
-FreeObject(void *address)
-{
-    O *anObject = static_cast <O *>(address);
-    delete anObject;
-}
-
-void file_write(int, off_t, void const *, int len, DWCB *, void *, FREE *);
-void file_write_mbuf(int fd, off_t, MemBuf mb, DWCB * handler, void *handler_data);
-void file_read(int, char *, int, off_t, DRCB *, void *);
-void disk_init(void);
-void safeunlink(const char *path, int quiet);
-int xrename(const char *from, const char *to); //disk.cc
-
-#endif /* SQUID_DISK_H_ */
-
diff -u -r -N squid-4.0.2/src/DiskIO/AIO/AIODiskFile.cc squid-4.0.3/src/DiskIO/AIO/AIODiskFile.cc
--- squid-4.0.2/src/DiskIO/AIO/AIODiskFile.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/DiskIO/AIO/AIODiskFile.cc	2015-11-28 07:30:57.000000000 -0800
@@ -22,12 +22,12 @@
 
 #include "squid.h"
 #include "Debug.h"
-#include "disk.h"
 #include "DiskIO/AIO/AIODiskFile.h"
 #include "DiskIO/AIO/AIODiskIOStrategy.h"
 #include "DiskIO/IORequestor.h"
 #include "DiskIO/ReadRequest.h"
 #include "DiskIO/WriteRequest.h"
+#include "fs_io.h"
 #include "globals.h"
 
 #include <cerrno>
diff -u -r -N squid-4.0.2/src/DiskIO/AIO/Makefile.in squid-4.0.3/src/DiskIO/AIO/Makefile.in
--- squid-4.0.2/src/DiskIO/AIO/Makefile.in	2015-11-01 04:19:10.000000000 -0800
+++ squid-4.0.3/src/DiskIO/AIO/Makefile.in	2015-11-28 07:32:30.000000000 -0800
@@ -469,6 +469,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -502,7 +503,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/DiskIO/Blocking/BlockingFile.cc squid-4.0.3/src/DiskIO/Blocking/BlockingFile.cc
--- squid-4.0.2/src/DiskIO/Blocking/BlockingFile.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/DiskIO/Blocking/BlockingFile.cc	2015-11-28 07:30:57.000000000 -0800
@@ -12,10 +12,10 @@
 #include "BlockingFile.h"
 #include "Debug.h"
 #include "defines.h"
-#include "disk.h"
 #include "DiskIO/IORequestor.h"
 #include "DiskIO/ReadRequest.h"
 #include "DiskIO/WriteRequest.h"
+#include "fs_io.h"
 #include "globals.h"
 
 #include <cerrno>
diff -u -r -N squid-4.0.2/src/DiskIO/Blocking/Makefile.in squid-4.0.3/src/DiskIO/Blocking/Makefile.in
--- squid-4.0.2/src/DiskIO/Blocking/Makefile.in	2015-11-01 04:19:11.000000000 -0800
+++ squid-4.0.3/src/DiskIO/Blocking/Makefile.in	2015-11-28 07:32:30.000000000 -0800
@@ -461,6 +461,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -494,7 +495,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/DiskIO/DiskDaemon/Makefile.in squid-4.0.3/src/DiskIO/DiskDaemon/Makefile.in
--- squid-4.0.2/src/DiskIO/DiskDaemon/Makefile.in	2015-11-01 04:19:11.000000000 -0800
+++ squid-4.0.3/src/DiskIO/DiskDaemon/Makefile.in	2015-11-28 07:32:31.000000000 -0800
@@ -477,6 +477,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -510,7 +511,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/DiskIO/DiskIOModule.cc squid-4.0.3/src/DiskIO/DiskIOModule.cc
--- squid-4.0.2/src/DiskIO/DiskIOModule.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/DiskIO/DiskIOModule.cc	2015-11-28 07:30:57.000000000 -0800
@@ -25,7 +25,7 @@
 #if HAVE_DISKIO_MODULE_IPCIO
 #include "DiskIO/IpcIo/IpcIoDiskIOModule.h"
 #endif
-#if HAVE_DISKIO_MODULE_DISKTHREADS
+#if HAVE_DISKIO_MODULE_MMAPPED
 #include "DiskIO/Mmapped/MmappedDiskIOModule.h"
 #endif
 
diff -u -r -N squid-4.0.2/src/DiskIO/DiskThreads/DiskThreadsDiskFile.cc squid-4.0.3/src/DiskIO/DiskThreads/DiskThreadsDiskFile.cc
--- squid-4.0.2/src/DiskIO/DiskThreads/DiskThreadsDiskFile.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/DiskIO/DiskThreads/DiskThreadsDiskFile.cc	2015-11-28 07:30:57.000000000 -0800
@@ -9,12 +9,12 @@
 /* DEBUG: section 79    Disk IO Routines */
 
 #include "squid.h"
-#include "disk.h"
 #include "DiskIO/IORequestor.h"
 #include "DiskIO/ReadRequest.h"
 #include "DiskIO/WriteRequest.h"
 #include "DiskThreadsDiskFile.h"
 #include "fd.h"
+#include "fs_io.h"
 #include "Generic.h"
 #include "globals.h"
 #include "StatCounters.h"
diff -u -r -N squid-4.0.2/src/DiskIO/DiskThreads/Makefile.in squid-4.0.3/src/DiskIO/DiskThreads/Makefile.in
--- squid-4.0.2/src/DiskIO/DiskThreads/Makefile.in	2015-11-01 04:19:11.000000000 -0800
+++ squid-4.0.3/src/DiskIO/DiskThreads/Makefile.in	2015-11-28 07:32:31.000000000 -0800
@@ -471,6 +471,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -504,7 +505,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/DiskIO/IpcIo/IpcIoFile.cc squid-4.0.3/src/DiskIO/IpcIo/IpcIoFile.cc
--- squid-4.0.2/src/DiskIO/IpcIo/IpcIoFile.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/DiskIO/IpcIo/IpcIoFile.cc	2015-11-28 07:30:57.000000000 -0800
@@ -11,12 +11,12 @@
 #include "squid.h"
 #include "base/RunnersRegistry.h"
 #include "base/TextException.h"
-#include "disk.h"
 #include "DiskIO/IORequestor.h"
 #include "DiskIO/IpcIo/IpcIoFile.h"
 #include "DiskIO/ReadRequest.h"
 #include "DiskIO/WriteRequest.h"
 #include "fd.h"
+#include "fs_io.h"
 #include "globals.h"
 #include "ipc/mem/Pages.h"
 #include "ipc/Messages.h"
diff -u -r -N squid-4.0.2/src/DiskIO/IpcIo/Makefile.in squid-4.0.3/src/DiskIO/IpcIo/Makefile.in
--- squid-4.0.2/src/DiskIO/IpcIo/Makefile.in	2015-11-01 04:19:12.000000000 -0800
+++ squid-4.0.3/src/DiskIO/IpcIo/Makefile.in	2015-11-28 07:32:32.000000000 -0800
@@ -461,6 +461,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -494,7 +495,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/DiskIO/Makefile.in squid-4.0.3/src/DiskIO/Makefile.in
--- squid-4.0.2/src/DiskIO/Makefile.in	2015-11-01 04:19:12.000000000 -0800
+++ squid-4.0.3/src/DiskIO/Makefile.in	2015-11-28 07:32:32.000000000 -0800
@@ -523,6 +523,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -556,7 +557,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/DiskIO/Mmapped/Makefile.in squid-4.0.3/src/DiskIO/Mmapped/Makefile.in
--- squid-4.0.2/src/DiskIO/Mmapped/Makefile.in	2015-11-01 04:19:13.000000000 -0800
+++ squid-4.0.3/src/DiskIO/Mmapped/Makefile.in	2015-11-28 07:32:33.000000000 -0800
@@ -461,6 +461,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -494,7 +495,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/DiskIO/Mmapped/MmappedFile.cc squid-4.0.3/src/DiskIO/Mmapped/MmappedFile.cc
--- squid-4.0.2/src/DiskIO/Mmapped/MmappedFile.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/DiskIO/Mmapped/MmappedFile.cc	2015-11-28 07:30:57.000000000 -0800
@@ -10,11 +10,11 @@
 
 #include "squid.h"
 #include "Debug.h"
-#include "disk.h"
 #include "DiskIO/IORequestor.h"
 #include "DiskIO/Mmapped/MmappedFile.h"
 #include "DiskIO/ReadRequest.h"
 #include "DiskIO/WriteRequest.h"
+#include "fs_io.h"
 #include "globals.h"
 
 #include <cerrno>
diff -u -r -N squid-4.0.2/src/dns/Makefile.in squid-4.0.3/src/dns/Makefile.in
--- squid-4.0.2/src/dns/Makefile.in	2015-11-01 04:19:22.000000000 -0800
+++ squid-4.0.3/src/dns/Makefile.in	2015-11-28 07:32:43.000000000 -0800
@@ -461,6 +461,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -494,7 +495,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/errorpage.cc squid-4.0.3/src/errorpage.cc
--- squid-4.0.2/src/errorpage.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/errorpage.cc	2015-11-28 07:30:57.000000000 -0800
@@ -13,10 +13,10 @@
 #include "clients/forward.h"
 #include "comm/Connection.h"
 #include "comm/Write.h"
-#include "disk.h"
 #include "err_detail_type.h"
 #include "errorpage.h"
 #include "fde.h"
+#include "fs_io.h"
 #include "html_quote.h"
 #include "HttpHeaderTools.h"
 #include "HttpReply.h"
diff -u -r -N squid-4.0.2/src/err_type.h squid-4.0.3/src/err_type.h
--- squid-4.0.2/src/err_type.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/err_type.h	2015-11-28 07:30:57.000000000 -0800
@@ -27,7 +27,6 @@
     ERR_WRITE_ERROR,
     ERR_CONNECT_FAIL,
     ERR_SECURE_CONNECT_FAIL,
-    ERR_SECURE_ACCEPT_FAIL,
     ERR_SOCKET_FAILURE,
 
     /* DNS Errors */
@@ -70,12 +69,14 @@
     ERR_SQUID_SIGNATURE,        /* not really an error */
     ERR_SHUTTING_DOWN,
     ERR_PROTOCOL_UNKNOWN,
-    ERR_REQUEST_START_TIMEOUT,
 
     // NOTE: error types defined below TCP_RESET are optional and do not generate
     //       a log warning if the files are missing
     TCP_RESET,                  // Send TCP RST packet instead of error page
 
+    ERR_SECURE_ACCEPT_FAIL, // Rejects the SSL connection intead of error page
+    ERR_REQUEST_START_TIMEOUT, // Aborts the connection instead of error page
+
     /* Cache Manager GUI can install a manager index/home page */
     MGR_INDEX,
 
diff -u -r -N squid-4.0.2/src/esi/Makefile.in squid-4.0.3/src/esi/Makefile.in
--- squid-4.0.2/src/esi/Makefile.in	2015-11-01 04:19:22.000000000 -0800
+++ squid-4.0.3/src/esi/Makefile.in	2015-11-28 07:32:43.000000000 -0800
@@ -480,6 +480,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -513,7 +514,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/eui/Makefile.in squid-4.0.3/src/eui/Makefile.in
--- squid-4.0.2/src/eui/Makefile.in	2015-11-01 04:19:23.000000000 -0800
+++ squid-4.0.3/src/eui/Makefile.in	2015-11-28 07:32:44.000000000 -0800
@@ -461,6 +461,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -494,7 +495,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/fatal.cc squid-4.0.3/src/fatal.cc
--- squid-4.0.2/src/fatal.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/fatal.cc	2015-11-28 07:30:57.000000000 -0800
@@ -10,7 +10,7 @@
 #include "Debug.h"
 #include "fatal.h"
 #include "globals.h"
-#include "SwapDir.h"
+#include "store/Disks.h"
 #include "tools.h"
 
 static void
@@ -42,9 +42,6 @@
     shutting_down = 1;
 
     releaseServerSockets();
-    /* check for store_dirs_rebuilding because fatal() is often
-     * used in early initialization phases, long before we ever
-     * get to the store log. */
 
     /* XXX: this should be turned into a callback-on-fatal, or
      * a mandatory-shutdown-event or something like that.
@@ -61,8 +58,7 @@
      */
     leave_suid();
 
-    if (0 == StoreController::store_dirs_rebuilding)
-        storeDirWriteCleanLogs(0);
+    storeDirWriteCleanLogs(0);
 
     fatal_common(message);
 
diff -u -r -N squid-4.0.2/src/fde.h squid-4.0.3/src/fde.h
--- squid-4.0.2/src/fde.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/fde.h	2015-11-28 07:30:57.000000000 -0800
@@ -120,7 +120,7 @@
     READ_HANDLER *read_method;
     WRITE_HANDLER *write_method;
     Security::SessionPointer ssl;
-    Security::ContextPointer dynamicSslContext; ///< cached and then freed when fd is closed
+    Security::ContextPtr dynamicSslContext; ///< cached and then freed when fd is closed
 #if _SQUID_WINDOWS_
     struct {
         long handle;
diff -u -r -N squid-4.0.2/src/FileMap.h squid-4.0.3/src/FileMap.h
--- squid-4.0.2/src/FileMap.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/FileMap.h	2015-11-28 07:30:57.000000000 -0800
@@ -11,7 +11,7 @@
 #ifndef FILEMAP_H_
 #define FILEMAP_H_
 
-#include "fs/forward.h"
+#include "store/forward.h"
 
 /** A bitmap used for managing UFS StoreEntry "file numbers".
  *
diff -u -r -N squid-4.0.2/src/format/Makefile.in squid-4.0.3/src/format/Makefile.in
--- squid-4.0.2/src/format/Makefile.in	2015-11-01 04:19:23.000000000 -0800
+++ squid-4.0.3/src/format/Makefile.in	2015-11-28 07:32:44.000000000 -0800
@@ -460,6 +460,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -493,7 +494,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/fs/forward.h squid-4.0.3/src/fs/forward.h
--- squid-4.0.2/src/fs/forward.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/fs/forward.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#ifndef SQUID_FORWARD_H_
-#define SQUID_FORWARD_H_
-
-typedef int32_t sfileno;
-typedef signed int sdirno;
-
-#endif /* SQUID_FORWARD_H_ */
-
diff -u -r -N squid-4.0.2/src/fs/Makefile.in squid-4.0.3/src/fs/Makefile.in
--- squid-4.0.2/src/fs/Makefile.in	2015-11-01 04:19:24.000000000 -0800
+++ squid-4.0.3/src/fs/Makefile.in	2015-11-28 07:32:45.000000000 -0800
@@ -478,6 +478,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -511,7 +512,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/fs/rock/forward.h squid-4.0.3/src/fs/rock/forward.h
--- squid-4.0.2/src/fs/rock/forward.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/fs/rock/forward.h	2015-11-28 07:30:57.000000000 -0800
@@ -9,7 +9,7 @@
 #ifndef SQUID_FS_ROCK_FORWARD_H
 #define SQUID_FS_ROCK_FORWARD_H
 
-#include "fs/forward.h"
+#include "store/forward.h"
 
 namespace Ipc
 {
diff -u -r -N squid-4.0.2/src/fs/rock/RockDbCell.h squid-4.0.3/src/fs/rock/RockDbCell.h
--- squid-4.0.2/src/fs/rock/RockDbCell.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/fs/rock/RockDbCell.h	2015-11-28 07:30:57.000000000 -0800
@@ -9,7 +9,7 @@
 #ifndef SQUID_FS_ROCK_DB_CELL_H
 #define SQUID_FS_ROCK_DB_CELL_H
 
-#include "fs/forward.h"
+#include "store/forward.h"
 
 namespace Rock
 {
diff -u -r -N squid-4.0.2/src/fs/rock/RockRebuild.cc squid-4.0.3/src/fs/rock/RockRebuild.cc
--- squid-4.0.2/src/fs/rock/RockRebuild.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/fs/rock/RockRebuild.cc	2015-11-28 07:30:57.000000000 -0800
@@ -9,14 +9,16 @@
 /* DEBUG: section 79    Disk IO Routines */
 
 #include "squid.h"
-#include "disk.h"
+#include "base/AsyncJobCalls.h"
 #include "fs/rock/RockDbCell.h"
 #include "fs/rock/RockRebuild.h"
 #include "fs/rock/RockSwapDir.h"
+#include "fs_io.h"
 #include "globals.h"
 #include "ipc/StoreMap.h"
 #include "md5.h"
 #include "SquidTime.h"
+#include "Store.h"
 #include "store_rebuild.h"
 #include "tools.h"
 
diff -u -r -N squid-4.0.2/src/fs/rock/RockSwapDir.cc squid-4.0.3/src/fs/rock/RockSwapDir.cc
--- squid-4.0.2/src/fs/rock/RockSwapDir.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/fs/rock/RockSwapDir.cc	2015-11-28 07:30:57.000000000 -0800
@@ -51,19 +51,6 @@
     safe_free(filePath);
 }
 
-StoreSearch *
-Rock::SwapDir::search(String const, 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)
@@ -924,7 +911,7 @@
 }
 
 bool
-Rock::SwapDir::dereference(StoreEntry &e, bool)
+Rock::SwapDir::dereference(StoreEntry &e)
 {
     debugs(47, 5, HERE << &e << ' ' << e.swap_dirn << ' ' << e.swap_filen);
     if (repl && repl->Dereferenced)
diff -u -r -N squid-4.0.2/src/fs/rock/RockSwapDir.h squid-4.0.3/src/fs/rock/RockSwapDir.h
--- squid-4.0.2/src/fs/rock/RockSwapDir.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/fs/rock/RockSwapDir.h	2015-11-28 07:30:57.000000000 -0800
@@ -16,7 +16,8 @@
 #include "ipc/mem/Page.h"
 #include "ipc/mem/PageStack.h"
 #include "ipc/StoreMap.h"
-#include "SwapDir.h"
+#include "store/Disk.h"
+#include <vector>
 
 class DiskIOStrategy;
 class ReadRequest;
@@ -37,9 +38,7 @@
 
     /* 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 markForUnlink(StoreEntry &e);
     virtual void disconnect(StoreEntry &e);
     virtual uint64_t currentSize() const;
@@ -91,7 +90,7 @@
     virtual void maintain();
     virtual void diskFull();
     virtual void reference(StoreEntry &e);
-    virtual bool dereference(StoreEntry &e, bool);
+    virtual bool dereference(StoreEntry &e);
     virtual bool unlinkdUseful() const;
     virtual void unlink(StoreEntry &e);
     virtual void statfs(StoreEntry &e) const;
diff -u -r -N squid-4.0.2/src/fs/ufs/RebuildState.cc squid-4.0.3/src/fs/ufs/RebuildState.cc
--- squid-4.0.2/src/fs/ufs/RebuildState.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/fs/ufs/RebuildState.cc	2015-11-28 07:30:57.000000000 -0800
@@ -9,11 +9,12 @@
 /* DEBUG: section 47    Store Directory Routines */
 
 #include "squid.h"
-#include "disk.h"
+#include "fs_io.h"
 #include "globals.h"
 #include "RebuildState.h"
 #include "SquidConfig.h"
 #include "SquidTime.h"
+#include "store/Disks.h"
 #include "store_key_md5.h"
 #include "store_rebuild.h"
 #include "StoreSwapLogData.h"
@@ -345,7 +346,7 @@
             currentEntry()->lastmod = swapData.lastmod;
             currentEntry()->flags = swapData.flags;
             currentEntry()->refcount += swapData.refcount;
-            sd->dereference(*currentEntry(), false);
+            sd->dereference(*currentEntry());
         } else {
             debug_trap("commonUfsDirRebuildFromSwapLog: bad condition");
             debugs(47, DBG_IMPORTANT, HERE << "bad condition");
diff -u -r -N squid-4.0.2/src/fs/ufs/UFSStoreState.cc squid-4.0.3/src/fs/ufs/UFSStoreState.cc
--- squid-4.0.2/src/fs/ufs/UFSStoreState.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/fs/ufs/UFSStoreState.cc	2015-11-28 07:30:57.000000000 -0800
@@ -16,7 +16,7 @@
 #include "Generic.h"
 #include "SquidList.h"
 #include "Store.h"
-#include "SwapDir.h"
+#include "store/Disk.h"
 #include "UFSStoreState.h"
 #include "UFSStrategy.h"
 
diff -u -r -N squid-4.0.2/src/fs/ufs/UFSSwapDir.cc squid-4.0.3/src/fs/ufs/UFSSwapDir.cc
--- squid-4.0.2/src/fs/ufs/UFSSwapDir.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/fs/ufs/UFSSwapDir.cc	2015-11-28 07:30:57.000000000 -0800
@@ -13,11 +13,11 @@
 #include "squid.h"
 #include "cache_cf.h"
 #include "ConfigOption.h"
-#include "disk.h"
 #include "DiskIO/DiskIOModule.h"
 #include "DiskIO/DiskIOStrategy.h"
 #include "fde.h"
 #include "FileMap.h"
+#include "fs_io.h"
 #include "globals.h"
 #include "Parsing.h"
 #include "RebuildState.h"
@@ -293,7 +293,7 @@
         started_clean_event = 1;
     }
 
-    (void) storeDirGetBlkSize(path, &fs.blksize);
+    (void) fsBlockSize(path, &fs.blksize);
 }
 
 void
@@ -383,7 +383,7 @@
     storeAppendPrintf(&sentry, "Filemap bits in use: %d of %d (%d%%)\n",
                       map->numFilesInMap(), map->capacity(),
                       Math::intPercent(map->numFilesInMap(), map->capacity()));
-    x = storeDirGetUFSStats(path, &totl_kb, &free_kb, &totl_in, &free_in);
+    x = fsStats(path, &totl_kb, &free_kb, &totl_in, &free_in);
 
     if (0 == x) {
         storeAppendPrintf(&sentry, "Filesystem Space in use: %d/%d KB (%d%%)\n",
@@ -530,7 +530,7 @@
 }
 
 bool
-Fs::Ufs::UFSSwapDir::dereference(StoreEntry & e, bool)
+Fs::Ufs::UFSSwapDir::dereference(StoreEntry & e)
 {
     debugs(47, 3, HERE << "dereferencing " << &e << " " <<
            e.swap_dirn << "/" << e.swap_filen);
@@ -1200,6 +1200,9 @@
     replacementRemove(&e);
     mapBitReset(e.swap_filen);
     UFSSwapDir::unlinkFile(e.swap_filen);
+    e.swap_filen = -1;
+    e.swap_dirn = -1;
+    e.swap_status = SWAPOUT_NONE;
 }
 
 void
@@ -1212,12 +1215,10 @@
 void
 Fs::Ufs::UFSSwapDir::replacementRemove(StoreEntry * e)
 {
-    StorePointer SD;
-
     if (e->swap_dirn < 0)
         return;
 
-    SD = INDEXSD(e->swap_dirn);
+    SwapDirPointer SD = INDEXSD(e->swap_dirn);
 
     assert (dynamic_cast<UFSSwapDir *>(SD.getRaw()) == this);
 
@@ -1273,15 +1274,6 @@
     ++n_disk_objects;
 }
 
-StoreSearch *
-Fs::Ufs::UFSSwapDir::search(String const url, HttpRequest *)
-{
-    if (url.size())
-        fatal ("Cannot search by url yet\n");
-
-    return new Fs::Ufs::StoreSearchUFS (this);
-}
-
 void
 Fs::Ufs::UFSSwapDir::logEntry(const StoreEntry & e, int op) const
 {
diff -u -r -N squid-4.0.2/src/fs/ufs/UFSSwapDir.h squid-4.0.3/src/fs/ufs/UFSSwapDir.h
--- squid-4.0.2/src/fs/ufs/UFSSwapDir.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/fs/ufs/UFSSwapDir.h	2015-11-28 07:30:57.000000000 -0800
@@ -11,10 +11,10 @@
 
 #include "SquidString.h"
 #include "Store.h"
+#include "store/Disk.h"
 #include "StoreIOState.h"
 #include "StoreSearch.h"
 #include "swap_log_op.h"
-#include "SwapDir.h"
 #include "UFSStrategy.h"
 
 class HttpRequest;
@@ -41,55 +41,36 @@
     static bool FilenoBelongsHere(int fn, int cachedir, int level1dir, int level2dir);
 
     UFSSwapDir(char const *aType, const char *aModuleType);
-    /** Initial setup / end destruction */
-    virtual void init();
-    /** Create a new SwapDir (-z command-line option) */
-    virtual void create();
-    virtual void dump(StoreEntry &) const;
-    ~UFSSwapDir();
-    virtual StoreSearch *search(String const url, HttpRequest *);
-    /** double-check swap during rebuild (-S command-line option)
-     *
-     * called by storeCleanup if needed
-     */
-    virtual bool doubleCheck(StoreEntry &);
-    virtual bool unlinkdUseful() const;
-    /** unlink a file, and remove its entry from the filemap */
-    virtual void unlink(StoreEntry &);
-    virtual void statfs(StoreEntry &)const;
-    virtual void maintain();
-    /** check whether this filesystem can store the given object
-     *
-     * UFS filesystems will happily store anything as long as
-     * the LRU time isn't too small
-     */
-    virtual bool canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const;
-    /** reference an object
-     *
-     * This routine is called whenever an object is referenced, so we can
-     * maintain replacement information within the storage fs.
-     */
-    virtual void reference(StoreEntry &);
-    /** de-reference an object
-     *
-     * This routine is called whenever the last reference to an object is
-     * removed, to maintain replacement information within the storage fs.
-     */
-    virtual bool dereference(StoreEntry &, bool);
-    virtual StoreIOState::Pointer createStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *);
-    virtual StoreIOState::Pointer openStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *);
-    virtual void openLog();
-    virtual void closeLog();
-    virtual int writeCleanStart();
-    virtual void writeCleanDone();
-    virtual void logEntry(const StoreEntry & e, int op) const;
-    virtual void parse(int index, char *path); ///parse configuration and setup new SwapDir
-    virtual void reconfigure(); ///reconfigure the SwapDir
-    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; }
+    virtual ~UFSSwapDir();
+
+    /* Store::Disk API */
+    virtual void create() override;
+    virtual void init() override;
+    virtual void dump(StoreEntry &) const override;
+    virtual bool doubleCheck(StoreEntry &) override;
+    virtual bool unlinkdUseful() const override;
+    virtual void unlink(StoreEntry &) override;
+    virtual void statfs(StoreEntry &) const override;
+    virtual void maintain() override;
+    virtual void markForUnlink(StoreEntry &) override {}
+    virtual bool canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const override;
+    virtual void reference(StoreEntry &) override;
+    virtual bool dereference(StoreEntry &) override;
+    virtual StoreIOState::Pointer createStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *) override;
+    virtual StoreIOState::Pointer openStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *) override;
+    virtual void openLog() override;
+    virtual void closeLog() override;
+    virtual int writeCleanStart() override;
+    virtual void writeCleanDone() override;
+    virtual void logEntry(const StoreEntry & e, int op) const override;
+    virtual void parse(int index, char *path) override;
+    virtual void reconfigure() override;
+    virtual int callback() override;
+    virtual void sync() override;
+    virtual void swappedOut(const StoreEntry &e) override;
+    virtual uint64_t currentSize() const override { return cur_size; }
+    virtual uint64_t currentCount() const override { return n_disk_objects; }
+    virtual ConfigOption *getOptionTree() const override;
 
     void unlinkFile(sfileno f);
     // move down when unlink is a virtual method
@@ -121,7 +102,6 @@
     void undoAddDiskRestore(StoreEntry *e);
     int validFileno(sfileno filn, int flag) const;
     int mapBitAllocate();
-    virtual ConfigOption *getOptionTree() const;
 
     void *fsdata;
 
diff -u -r -N squid-4.0.2/src/fs_io.cc squid-4.0.3/src/fs_io.cc
--- squid-4.0.2/src/fs_io.cc	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/fs_io.cc	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,558 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/* DEBUG: section 06    Disk I/O Routines */
+
+#include "squid.h"
+#include "comm/Loops.h"
+#include "fd.h"
+#include "fde.h"
+#include "fs_io.h"
+#include "globals.h"
+#include "MemBuf.h"
+#include "profiler/Profiler.h"
+#include "StatCounters.h"
+
+#include <cerrno>
+
+static PF diskHandleRead;
+static PF diskHandleWrite;
+
+#if _SQUID_WINDOWS_ || _SQUID_OS2_
+static int
+diskWriteIsComplete(int fd)
+{
+    return fd_table[fd].disk.write_q ? 0 : 1;
+}
+
+#endif
+
+/* hack needed on SunStudio to avoid linkage convention mismatch */
+static void cxx_xfree(void *ptr)
+{
+    xfree(ptr);
+}
+
+/*
+ * opens a disk file specified by 'path'.  This function always
+ * blocks!  There is no callback.
+ */
+int
+file_open(const char *path, int mode)
+{
+    int fd;
+    PROF_start(file_open);
+
+    if (FILE_MODE(mode) == O_WRONLY)
+        mode |= O_APPEND;
+
+    errno = 0;
+
+    fd = open(path, mode, 0644);
+
+    ++ statCounter.syscalls.disk.opens;
+
+    if (fd < 0) {
+        debugs(50, 3, "file_open: error opening file " << path << ": " << xstrerror());
+        fd = DISK_ERROR;
+    } else {
+        debugs(6, 5, "file_open: FD " << fd);
+        commSetCloseOnExec(fd);
+        fd_open(fd, FD_FILE, path);
+    }
+
+    PROF_stop(file_open);
+    return fd;
+}
+
+/* close a disk file. */
+void
+file_close(int fd)
+{
+    fde *F = &fd_table[fd];
+    PF *read_callback;
+    PROF_start(file_close);
+    assert(fd >= 0);
+    assert(F->flags.open);
+
+    if ((read_callback = F->read_handler)) {
+        F->read_handler = NULL;
+        read_callback(-1, F->read_data);
+    }
+
+    if (F->flags.write_daemon) {
+#if _SQUID_WINDOWS_ || _SQUID_OS2_
+        /*
+         * on some operating systems, you can not delete or rename
+         * open files, so we won't allow delayed close.
+         */
+        while (!diskWriteIsComplete(fd))
+            diskHandleWrite(fd, NULL);
+#else
+        F->flags.close_request = true;
+        debugs(6, 2, "file_close: FD " << fd << ", delaying close");
+        PROF_stop(file_close);
+        return;
+#endif
+
+    }
+
+    /*
+     * Assert there is no write callback.  Otherwise we might be
+     * leaking write state data by closing the descriptor
+     */
+    assert(F->write_handler == NULL);
+
+#if CALL_FSYNC_BEFORE_CLOSE
+
+    fsync(fd);
+
+#endif
+
+    close(fd);
+
+    debugs(6, F->flags.close_request ? 2 : 5, "file_close: FD " << fd << " really closing\n");
+
+    fd_close(fd);
+
+    ++ statCounter.syscalls.disk.closes;
+
+    PROF_stop(file_close);
+}
+
+/*
+ * This function has the purpose of combining multiple writes.  This is
+ * to facilitate the ASYNC_IO option since it can only guarantee 1
+ * write to a file per trip around the comm.c select() loop. That's bad
+ * because more than 1 write can be made to the access.log file per
+ * trip, and so this code is purely designed to help batch multiple
+ * sequential writes to the access.log file.  Squid will never issue
+ * multiple writes for any other file type during 1 trip around the
+ * select() loop.       --SLF
+ */
+static void
+diskCombineWrites(_fde_disk *fdd)
+{
+    /*
+     * We need to combine multiple write requests on an FD's write
+     * queue But only if we don't need to seek() in between them, ugh!
+     * XXX This currently ignores any seeks (file_offset)
+     */
+
+    if (fdd->write_q != NULL && fdd->write_q->next != NULL) {
+        int len = 0;
+
+        for (dwrite_q *q = fdd->write_q; q != NULL; q = q->next)
+            len += q->len - q->buf_offset;
+
+        dwrite_q *wq = (dwrite_q *)memAllocate(MEM_DWRITE_Q);
+
+        wq->buf = (char *)xmalloc(len);
+
+        wq->len = 0;
+
+        wq->buf_offset = 0;
+
+        wq->next = NULL;
+
+        wq->free_func = cxx_xfree;
+
+        while (fdd->write_q != NULL) {
+            dwrite_q *q = fdd->write_q;
+
+            len = q->len - q->buf_offset;
+            memcpy(wq->buf + wq->len, q->buf + q->buf_offset, len);
+            wq->len += len;
+            fdd->write_q = q->next;
+
+            if (q->free_func)
+                q->free_func(q->buf);
+
+            memFree(q, MEM_DWRITE_Q);
+        };
+
+        fdd->write_q_tail = wq;
+
+        fdd->write_q = wq;
+    }
+}
+
+/* write handler */
+static void
+diskHandleWrite(int fd, void *)
+{
+    int len = 0;
+    fde *F = &fd_table[fd];
+
+    _fde_disk *fdd = &F->disk;
+    dwrite_q *q = fdd->write_q;
+    int status = DISK_OK;
+    bool do_close;
+
+    if (NULL == q)
+        return;
+
+    PROF_start(diskHandleWrite);
+
+    debugs(6, 3, "diskHandleWrite: FD " << fd);
+
+    F->flags.write_daemon = false;
+
+    assert(fdd->write_q != NULL);
+
+    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 at " <<
+           fdd->write_q->file_offset);
+
+    errno = 0;
+
+    if (fdd->write_q->file_offset != -1) {
+        errno = 0;
+        if (lseek(fd, fdd->write_q->file_offset, SEEK_SET) == -1) {
+            debugs(50, DBG_IMPORTANT, "error in seek for fd " << fd << ": " << xstrerror());
+            // XXX: handle error?
+        }
+    }
+
+    len = FD_WRITE_METHOD(fd,
+                          fdd->write_q->buf + fdd->write_q->buf_offset,
+                          fdd->write_q->len - fdd->write_q->buf_offset);
+
+    debugs(6, 3, "diskHandleWrite: FD " << fd << " len = " << len);
+
+    ++ statCounter.syscalls.disk.writes;
+
+    fd_bytes(fd, len, FD_WRITE);
+
+    if (len < 0) {
+        if (!ignoreErrno(errno)) {
+            status = errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR;
+            debugs(50, DBG_IMPORTANT, "diskHandleWrite: FD " << fd << ": disk write error: " << xstrerror());
+
+            /*
+             * If there is no write callback, then this file is
+             * most likely something important like a log file, or
+             * an interprocess pipe.  Its not a swapfile.  We feel
+             * that a write failure on a log file is rather important,
+             * and Squid doesn't otherwise deal with this condition.
+             * So to get the administrators attention, we exit with
+             * a fatal message.
+             */
+
+            if (fdd->wrt_handle == NULL)
+                fatal("Write failure -- check your disk space and cache.log");
+
+            /*
+             * If there is a write failure, then we notify the
+             * upper layer via the callback, at the end of this
+             * function.  Meanwhile, flush all pending buffers
+             * here.  Let the upper layer decide how to handle the
+             * failure.  This will prevent experiencing multiple,
+             * repeated write failures for the same FD because of
+             * the queued data.
+             */
+            do {
+                fdd->write_q = q->next;
+
+                if (q->free_func)
+                    q->free_func(q->buf);
+
+                if (q) {
+                    memFree(q, MEM_DWRITE_Q);
+                    q = NULL;
+                }
+            } while ((q = fdd->write_q));
+        }
+
+        len = 0;
+    }
+
+    if (q != NULL) {
+        /* q might become NULL from write failure above */
+        q->buf_offset += len;
+
+        if (q->buf_offset > q->len)
+            debugs(50, DBG_IMPORTANT, "diskHandleWriteComplete: q->buf_offset > q->len (" <<
+                   q << "," << (int) q->buf_offset << ", " << q->len << ", " <<
+                   len << " FD " << fd << ")");
+
+        assert(q->buf_offset <= q->len);
+
+        if (q->buf_offset == q->len) {
+            /* complete write */
+            fdd->write_q = q->next;
+
+            if (q->free_func)
+                q->free_func(q->buf);
+
+            if (q) {
+                memFree(q, MEM_DWRITE_Q);
+                q = NULL;
+            }
+        }
+    }
+
+    if (fdd->write_q == NULL) {
+        /* no more data */
+        fdd->write_q_tail = NULL;
+    } else {
+        /* another block is queued */
+        diskCombineWrites(fdd);
+        Comm::SetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0);
+        F->flags.write_daemon = true;
+    }
+
+    do_close = F->flags.close_request;
+
+    if (fdd->wrt_handle) {
+        DWCB *callback = fdd->wrt_handle;
+        void *cbdata;
+        fdd->wrt_handle = NULL;
+
+        if (cbdataReferenceValidDone(fdd->wrt_handle_data, &cbdata)) {
+            callback(fd, status, len, cbdata);
+            /*
+             * NOTE, this callback can close the FD, so we must
+             * not touch 'F', 'fdd', etc. after this.
+             */
+            PROF_stop(diskHandleWrite);
+            return;
+            /* XXX But what about close_request??? */
+        }
+    }
+
+    if (do_close)
+        file_close(fd);
+
+    PROF_stop(diskHandleWrite);
+}
+
+/* write block to a file */
+/* write back queue. Only one writer at a time. */
+/* call a handle when writing is complete. */
+void
+file_write(int fd,
+           off_t file_offset,
+           void const *ptr_to_buf,
+           int len,
+           DWCB * handle,
+           void *handle_data,
+           FREE * free_func)
+{
+    dwrite_q *wq = NULL;
+    fde *F = &fd_table[fd];
+    PROF_start(file_write);
+    assert(fd >= 0);
+    assert(F->flags.open);
+    /* if we got here. Caller is eligible to write. */
+    wq = (dwrite_q *)memAllocate(MEM_DWRITE_Q);
+    wq->file_offset = file_offset;
+    wq->buf = (char *)ptr_to_buf;
+    wq->len = len;
+    wq->buf_offset = 0;
+    wq->next = NULL;
+    wq->free_func = free_func;
+
+    if (!F->disk.wrt_handle_data) {
+        F->disk.wrt_handle = handle;
+        F->disk.wrt_handle_data = cbdataReference(handle_data);
+    } else {
+        /* Detect if there is multiple concurrent users of this fd.. we only support one callback */
+        assert(F->disk.wrt_handle_data == handle_data && F->disk.wrt_handle == handle);
+    }
+
+    /* add to queue */
+    if (F->disk.write_q == NULL) {
+        /* empty queue */
+        F->disk.write_q = F->disk.write_q_tail = wq;
+    } else {
+        F->disk.write_q_tail->next = wq;
+        F->disk.write_q_tail = wq;
+    }
+
+    if (!F->flags.write_daemon) {
+        diskHandleWrite(fd, NULL);
+    }
+
+    PROF_stop(file_write);
+}
+
+/*
+ * a wrapper around file_write to allow for MemBuf to be file_written
+ * in a snap
+ */
+void
+file_write_mbuf(int fd, off_t off, MemBuf mb, DWCB * handler, void *handler_data)
+{
+    file_write(fd, off, mb.buf, mb.size, handler, handler_data, mb.freeFunc());
+}
+
+/* Read from FD */
+static void
+diskHandleRead(int fd, void *data)
+{
+    dread_ctrl *ctrl_dat = (dread_ctrl *)data;
+    fde *F = &fd_table[fd];
+    int len;
+    int rc = DISK_OK;
+    /*
+     * FD < 0 indicates premature close; we just have to free
+     * the state data.
+     */
+
+    if (fd < 0) {
+        memFree(ctrl_dat, MEM_DREAD_CTRL);
+        return;
+    }
+
+    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);
+        errno = 0;
+        if (lseek(fd, ctrl_dat->offset, SEEK_SET) == -1) {
+            // shouldn't happen, let's detect that
+            debugs(50, DBG_IMPORTANT, "error in seek for fd " << fd << ": " << xstrerror());
+            // XXX handle failures?
+        }
+        ++ statCounter.syscalls.disk.seeks;
+        F->disk.offset = ctrl_dat->offset;
+    }
+
+    errno = 0;
+    len = FD_READ_METHOD(fd, ctrl_dat->buf, ctrl_dat->req_len);
+
+    if (len > 0)
+        F->disk.offset += len;
+
+    ++ statCounter.syscalls.disk.reads;
+
+    fd_bytes(fd, len, FD_READ);
+
+    if (len < 0) {
+        if (ignoreErrno(errno)) {
+            Comm::SetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0);
+            PROF_stop(diskHandleRead);
+            return;
+        }
+
+        debugs(50, DBG_IMPORTANT, "diskHandleRead: FD " << fd << ": " << xstrerror());
+        len = 0;
+        rc = DISK_ERROR;
+    } else if (len == 0) {
+        rc = DISK_EOF;
+    }
+
+    if (cbdataReferenceValid(ctrl_dat->client_data))
+        ctrl_dat->handler(fd, ctrl_dat->buf, len, rc, ctrl_dat->client_data);
+
+    cbdataReferenceDone(ctrl_dat->client_data);
+
+    memFree(ctrl_dat, MEM_DREAD_CTRL);
+
+    PROF_stop(diskHandleRead);
+}
+
+/* start read operation */
+/* buffer must be allocated from the caller.
+ * It must have at least req_len space in there.
+ * call handler when a reading is complete. */
+void
+file_read(int fd, char *buf, int req_len, off_t offset, DRCB * handler, void *client_data)
+{
+    dread_ctrl *ctrl_dat;
+    PROF_start(file_read);
+    assert(fd >= 0);
+    ctrl_dat = (dread_ctrl *)memAllocate(MEM_DREAD_CTRL);
+    ctrl_dat->fd = fd;
+    ctrl_dat->offset = offset;
+    ctrl_dat->req_len = req_len;
+    ctrl_dat->buf = buf;
+    ctrl_dat->end_of_file = 0;
+    ctrl_dat->handler = handler;
+    ctrl_dat->client_data = cbdataReference(client_data);
+    diskHandleRead(fd, ctrl_dat);
+    PROF_stop(file_read);
+}
+
+void
+safeunlink(const char *s, int quiet)
+{
+    ++ statCounter.syscalls.disk.unlinks;
+
+    if (unlink(s) < 0 && !quiet)
+        debugs(50, DBG_IMPORTANT, "safeunlink: Couldn't delete " << s << ": " << xstrerror());
+}
+
+/*
+ * Same as rename(2) but complains if something goes wrong;
+ * the caller is responsible for handing and explaining the
+ * consequences of errors.
+ */
+int
+xrename(const char *from, const char *to)
+{
+    debugs(21, 2, "xrename: renaming " << from << " to " << to);
+#if _SQUID_OS2_ || _SQUID_WINDOWS_
+    remove(to);
+#endif
+
+    if (0 == rename(from, to))
+        return 0;
+
+    debugs(21, errno == ENOENT ? 2 : 1, "xrename: Cannot rename " << from << " to " << to << ": " << xstrerror());
+
+    return -1;
+}
+
+int
+fsBlockSize(const char *path, int *blksize)
+{
+    struct statvfs sfs;
+
+    if (xstatvfs(path, &sfs)) {
+        debugs(50, DBG_IMPORTANT, "" << path << ": " << xstrerror());
+        *blksize = 2048;
+        return 1;
+    }
+
+    *blksize = (int) sfs.f_frsize;
+
+    // Sanity check; make sure we have a meaningful value.
+    if (*blksize < 512)
+        *blksize = 2048;
+
+    return 0;
+}
+
+#define fsbtoblk(num, fsbs, bs) \
+    (((fsbs) != 0 && (fsbs) < (bs)) ? \
+            (num) / ((bs) / (fsbs)) : (num) * ((fsbs) / (bs)))
+int
+fsStats(const char *path, int *totl_kb, int *free_kb, int *totl_in, int *free_in)
+{
+    struct statvfs sfs;
+
+    if (xstatvfs(path, &sfs)) {
+        debugs(50, DBG_IMPORTANT, "" << path << ": " << xstrerror());
+        return 1;
+    }
+
+    *totl_kb = (int) fsbtoblk(sfs.f_blocks, sfs.f_frsize, 1024);
+    *free_kb = (int) fsbtoblk(sfs.f_bfree, sfs.f_frsize, 1024);
+    *totl_in = (int) sfs.f_files;
+    *free_in = (int) sfs.f_ffree;
+    return 0;
+}
+
diff -u -r -N squid-4.0.2/src/fs_io.h squid-4.0.3/src/fs_io.h
--- squid-4.0.2/src/fs_io.h	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/fs_io.h	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/* DEBUG: section 06    Disk I/O Routines */
+
+#ifndef SQUID_FS_IO_H_
+#define SQUID_FS_IO_H_
+
+#include "mem/forward.h"
+#include "typedefs.h" //DRCB, DWCB
+
+class MemBuf;
+
+// POD
+class dread_ctrl
+{
+public:
+    int fd;
+    off_t offset;
+    int req_len;
+    char *buf;
+    int end_of_file;
+    DRCB *handler;
+    void *client_data;
+};
+
+// POD
+class dwrite_q
+{
+public:
+    off_t file_offset;
+    char *buf;
+    size_t len;
+    size_t buf_offset;
+    dwrite_q *next;
+    FREE *free_func;
+};
+
+int file_open(const char *path, int mode);
+void file_close(int fd);
+void file_write(int, off_t, void const *, int len, DWCB *, void *, FREE *);
+void file_write_mbuf(int fd, off_t, MemBuf mb, DWCB * handler, void *handler_data);
+void file_read(int, char *, int, off_t, DRCB *, void *);
+void safeunlink(const char *path, int quiet);
+int xrename(const char *from, const char *to);
+
+int fsBlockSize(const char *path, int *blksize);
+int fsStats(const char *, int *, int *, int *, int *);
+
+#endif /* SQUID_FS_IO_H_ */
+
diff -u -r -N squid-4.0.2/src/ftp/Makefile.in squid-4.0.3/src/ftp/Makefile.in
--- squid-4.0.2/src/ftp/Makefile.in	2015-11-01 04:19:24.000000000 -0800
+++ squid-4.0.3/src/ftp/Makefile.in	2015-11-28 07:32:45.000000000 -0800
@@ -460,6 +460,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -493,7 +494,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/FwdState.cc squid-4.0.3/src/FwdState.cc
--- squid-4.0.2/src/FwdState.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/FwdState.cc	2015-11-28 07:30:57.000000000 -0800
@@ -693,7 +693,7 @@
     if (!request->flags.pinned) {
         const CachePeer *p = serverConnection()->getPeer();
         const bool peerWantsTls = p && p->secure.encryptTransport;
-        // userWillSslToPeerForUs assumes CONNECT == HTTPS
+        // userWillTlsToPeerForUs assumes CONNECT == HTTPS
         const bool userWillTlsToPeerForUs = p && p->options.originserver &&
                                             request->method == Http::METHOD_CONNECT;
         const bool needTlsToPeer = peerWantsTls && !userWillTlsToPeerForUs;
diff -u -r -N squid-4.0.2/src/helper/Makefile.in squid-4.0.3/src/helper/Makefile.in
--- squid-4.0.2/src/helper/Makefile.in	2015-11-01 04:19:25.000000000 -0800
+++ squid-4.0.3/src/helper/Makefile.in	2015-11-28 07:32:46.000000000 -0800
@@ -460,6 +460,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -493,7 +494,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/http/Makefile.in squid-4.0.3/src/http/Makefile.in
--- squid-4.0.2/src/http/Makefile.in	2015-11-01 04:19:25.000000000 -0800
+++ squid-4.0.3/src/http/Makefile.in	2015-11-28 07:32:46.000000000 -0800
@@ -501,6 +501,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -534,7 +535,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/http/one/Makefile.in squid-4.0.3/src/http/one/Makefile.in
--- squid-4.0.2/src/http/one/Makefile.in	2015-11-01 04:19:26.000000000 -0800
+++ squid-4.0.3/src/http/one/Makefile.in	2015-11-28 07:32:47.000000000 -0800
@@ -461,6 +461,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -494,7 +495,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/http/one/RequestParser.cc squid-4.0.3/src/http/one/RequestParser.cc
--- squid-4.0.2/src/http/one/RequestParser.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/http/one/RequestParser.cc	2015-11-28 07:30:57.000000000 -0800
@@ -14,9 +14,14 @@
 #include "profiler/Profiler.h"
 #include "SquidConfig.h"
 
+// the right debugs() level for parsing errors
+inline static int
+ErrorLevel() {
+    return Config.onoff.relaxed_header_parser < 0 ? DBG_IMPORTANT : 5;
+}
+
 Http::One::RequestParser::RequestParser() :
-    Parser(),
-    firstLineGarbage_(0)
+    Parser()
 {}
 
 Http1::Parser::size_type
@@ -62,82 +67,111 @@
  * Governed by:
  *  RFC 1945 section 5.1
  *  RFC 7230 section 2.6, 3.1 and 3.5
- *
- * Parsing state is stored between calls. The current implementation uses
- * checkpoints after each successful request-line field.
- * The return value tells you whether the parsing is completed or not.
- *
- * \retval -1  an error occurred. parseStatusCode indicates HTTP status result.
- * \retval  1  successful parse. method_ is filled and buffer consumed including first delimiter.
- * \retval  0  more data is needed to complete the parse
  */
-int
-Http::One::RequestParser::parseMethodField(Http1::Tokenizer &tok, const CharacterSet &WspDelim)
+bool
+Http::One::RequestParser::parseMethodField(Http1::Tokenizer &tok)
 {
-    // scan for up to 16 valid method characters.
-    static const size_t maxMethodLength = 16; // TODO: make this configurable?
-
     // method field is a sequence of TCHAR.
-    SBuf methodFound;
-    if (tok.prefix(methodFound, CharacterSet::TCHAR, maxMethodLength) && tok.skipOne(WspDelim)) {
-
-        method_ = HttpRequestMethod(methodFound);
-        buf_ = tok.remaining(); // incremental parse checkpoint
-        return 1;
-
-    } else if (tok.atEnd()) {
-        debugs(74, 5, "Parser needs more data to find method");
-        return 0;
-
-    } // else error(s)
+    // Limit to 32 characters to prevent overly long sequences of non-HTTP
+    // being sucked in before mismatch is detected. 32 is itself annoyingly
+    // big but there are methods registered by IANA that reach 17 bytes:
+    //  http://www.iana.org/assignments/http-methods
+    static const size_t maxMethodLength = 32; // TODO: make this configurable?
 
-    // non-delimiter found after accepted method bytes means ...
-    if (methodFound.length() == maxMethodLength) {
-        // method longer than acceptible.
-        // RFC 7230 section 3.1.1 mandatory (SHOULD) 501 response
-        parseStatusCode = Http::scNotImplemented;
-        debugs(33, 5, "invalid request-line. method too long");
-    } else {
-        // invalid character in the URL
-        // RFC 7230 section 3.1.1 required (SHOULD) 400 response
+    SBuf methodFound;
+    if (!tok.prefix(methodFound, CharacterSet::TCHAR, maxMethodLength)) {
+        debugs(33, ErrorLevel(), "invalid request-line: missing or malformed method");
         parseStatusCode = Http::scBadRequest;
-        debugs(33, 5, "invalid request-line. missing method delimiter");
+        return false;
     }
-    return -1;
+    method_ = HttpRequestMethod(methodFound);
+    return true;
 }
 
-static CharacterSet
-uriValidCharacters()
+/// the characters which truly are valid within URI
+static const CharacterSet &
+UriValidCharacters()
 {
-    CharacterSet UriChars("URI-Chars","");
-
     /* RFC 3986 section 2:
      * "
      *   A URI is composed from a limited set of characters consisting of
      *   digits, letters, and a few graphic symbols.
      * "
      */
-    // RFC 3986 section 2.1 - percent encoding "%" HEXDIG
-    UriChars.add('%');
-    UriChars += CharacterSet::HEXDIG;
-    // RFC 3986 section 2.2 - reserved characters
-    UriChars += CharacterSet("gen-delims", ":/?#[]@");
-    UriChars += CharacterSet("sub-delims", "!$&'()*+,;=");
-    // RFC 3986 section 2.3 - unreserved characters
-    UriChars += CharacterSet::ALPHA;
-    UriChars += CharacterSet::DIGIT;
-    UriChars += CharacterSet("unreserved", "-._~");
+    static const CharacterSet UriChars =
+        CharacterSet("URI-Chars","") +
+        // RFC 3986 section 2.2 - reserved characters
+        CharacterSet("gen-delims", ":/?#[]@") +
+        CharacterSet("sub-delims", "!$&'()*+,;=") +
+        // RFC 3986 section 2.3 - unreserved characters
+        CharacterSet::ALPHA +
+        CharacterSet::DIGIT +
+        CharacterSet("unreserved", "-._~") +
+        // RFC 3986 section 2.1 - percent encoding "%" HEXDIG
+        CharacterSet("pct-encoded", "%") +
+        CharacterSet::HEXDIG;
 
     return UriChars;
 }
 
-int
-Http::One::RequestParser::parseUriField(Http1::Tokenizer &tok)
+/// characters HTTP permits tolerant parsers to accept as delimiters
+static const CharacterSet &
+RelaxedDelimiterCharacters()
 {
-    // URI field is a sequence of ... what? segments all have different valid charset
-    // go with non-whitespace non-binary characters for now
-    static CharacterSet UriChars = uriValidCharacters();
+    // RFC 7230 section 3.5
+    // tolerant parser MAY accept any of SP, HTAB, VT (%x0B), FF (%x0C),
+    // or bare CR as whitespace between request-line fields
+    static const CharacterSet RelaxedDels =
+        CharacterSet::SP +
+        CharacterSet::HTAB +
+        CharacterSet("VT,FF","\x0B\x0C") +
+        CharacterSet::CR;
+
+    return RelaxedDels;
+}
+
+/// characters used to separate HTTP fields
+const CharacterSet &
+Http::One::RequestParser::DelimiterCharacters()
+{
+    return Config.onoff.relaxed_header_parser ?
+           RelaxedDelimiterCharacters() : CharacterSet::SP;
+}
+
+/// characters which Squid will accept in the HTTP request-target (URI)
+const CharacterSet &
+Http::One::RequestParser::RequestTargetCharacters()
+{
+    if (Config.onoff.relaxed_header_parser) {
+#if USE_HTTP_VIOLATIONS
+        static const CharacterSet RelaxedExtended =
+            UriValidCharacters() +
+            // accept whitespace (extended), it will be dealt with later
+            DelimiterCharacters() +
+            // RFC 2396 unwise character set which must never be transmitted
+            // in un-escaped form. But many web services do anyway.
+            CharacterSet("RFC2396-unwise","\"\\|^<>`{}") +
+            // UTF-8 because we want to be future-proof
+            CharacterSet("UTF-8", 128, 255);
+
+        return RelaxedExtended;
+#else
+        static const CharacterSet RelaxedCompliant =
+            UriValidCharacters() +
+            // accept whitespace (extended), it will be dealt with later.
+            DelimiterCharacters();
+
+        return RelaxedCompliant;
+#endif
+    }
 
+    // strict parse only accepts what the RFC say we can
+    return UriValidCharacters();
+}
+
+bool
+Http::One::RequestParser::parseUriField(Http1::Tokenizer &tok)
+{
     /* Arbitrary 64KB URI upper length limit.
      *
      * Not quite as arbitrary as it seems though. Old SquidString objects
@@ -147,85 +181,93 @@
      * Not that it matters but RFC 7230 section 3.1.1 requires (RECOMMENDED)
      * at least 8000 octets for the whole line, including method and version.
      */
-    const size_t maxUriLength = min(static_cast<size_t>(Config.maxRequestHeaderSize) - firstLineSize(),
-                                    static_cast<size_t>((64*1024)-1));
+    const size_t maxUriLength = static_cast<size_t>((64*1024)-1);
 
     SBuf uriFound;
-
-    // RFC 7230 HTTP/1.x URI are followed by at least one whitespace delimiter
-    if (tok.prefix(uriFound, UriChars, maxUriLength) && tok.skipOne(CharacterSet::SP)) {
-        uri_ = uriFound;
-        buf_ = tok.remaining(); // incremental parse checkpoint
-        return 1;
-
-        // RFC 1945 for GET the line terminator may follow URL instead of a delimiter
-    } else if (method_ == Http::METHOD_GET && skipLineTerminator(tok)) {
-        debugs(33, 5, "HTTP/0.9 syntax request-line detected");
-        msgProtocol_ = Http::ProtocolVersion(0,9);
-        uri_ = uriFound; // found by successful prefix() call earlier.
-        parseStatusCode = Http::scOkay;
-        buf_ = tok.remaining(); // incremental parse checkpoint
-        return 1;
-
-    } else if (tok.atEnd()) {
-        debugs(74, 5, "Parser needs more data to find URI");
-        return 0;
+    if (!tok.prefix(uriFound, RequestTargetCharacters())) {
+        parseStatusCode = Http::scBadRequest;
+        debugs(33, ErrorLevel(), "invalid request-line: missing or malformed URI");
+        return false;
     }
 
-    // else errors...
-
-    if (uriFound.length() == maxUriLength) {
+    if (uriFound.length() > maxUriLength) {
         // RFC 7230 section 3.1.1 mandatory (MUST) 414 response
         parseStatusCode = Http::scUriTooLong;
-        debugs(33, 5, "invalid request-line. URI longer than " << maxUriLength << " bytes");
-    } else {
-        // RFC 7230 section 3.1.1 required (SHOULD) 400 response
-        parseStatusCode = Http::scBadRequest;
-        debugs(33, 5, "invalid request-line. missing URI delimiter");
+        debugs(33, ErrorLevel(), "invalid request-line: " << uriFound.length() <<
+               "-byte URI exceeds " << maxUriLength << "-byte limit");
+        return false;
     }
-    return -1;
+
+    uri_ = uriFound;
+    return true;
 }
 
-int
+bool
 Http::One::RequestParser::parseHttpVersionField(Http1::Tokenizer &tok)
 {
-    // partial match of HTTP/1 magic prefix
-    if (tok.remaining().length() < Http1magic.length() && Http1magic.startsWith(tok.remaining())) {
-        debugs(74, 5, "Parser needs more data to find version");
-        return 0;
-    }
+    const auto savedTok = tok;
 
-    if (!tok.skip(Http1magic)) {
-        debugs(74, 5, "invalid request-line. not HTTP/1 protocol");
-        parseStatusCode = Http::scHttpVersionNotSupported;
-        return -1;
+    SBuf digit;
+    // Searching for Http1magic precludes detecting HTTP/2+ versions.
+    // Rewrite if we ever _need_ to return 505 (Version Not Supported) errors.
+    if (tok.suffix(digit, CharacterSet::DIGIT) && tok.skipSuffix(Http1magic)) {
+        msgProtocol_ = Http::ProtocolVersion(1, (*digit.rawContent() - '0'));
+        return true;
     }
 
-    if (tok.atEnd()) {
-        debugs(74, 5, "Parser needs more data to find version");
-        return 0;
+    // A GET request might use HTTP/0.9 syntax
+    if (method_ == Http::METHOD_GET) {
+        // RFC 1945 - no HTTP version field at all
+        tok = savedTok; // in case the URI ends with a digit
+        // report this assumption as an error if configured to triage parsing
+        debugs(33, ErrorLevel(), "assuming HTTP/0.9 request-line");
+        msgProtocol_ = Http::ProtocolVersion(0,9);
+        return true;
     }
 
-    // get the version minor DIGIT
-    SBuf digit;
-    if (tok.prefix(digit, CharacterSet::DIGIT, 1) && skipLineTerminator(tok)) {
+    debugs(33, ErrorLevel(), "invalid request-line: not HTTP");
+    parseStatusCode = Http::scBadRequest;
+    return false;
+}
 
-        // found version fully AND terminator
-        msgProtocol_ = Http::ProtocolVersion(1, (*digit.rawContent() - '0'));
-        parseStatusCode = Http::scOkay;
-        buf_ = tok.remaining(); // incremental parse checkpoint
-        return 1;
+/**
+ * Skip characters separating request-line fields.
+ * To handle bidirectional parsing, the caller does the actual skipping and
+ * we just check how many character the caller has skipped.
+ */
+bool
+Http::One::RequestParser::skipDelimiter(const size_t count)
+{
+    if (count <= 0) {
+        debugs(33, ErrorLevel(), "invalid request-line: missing delimiter");
+        parseStatusCode = Http::scBadRequest;
+        return false;
+    }
 
-    } else if (tok.atEnd() || (tok.skip('\r') && tok.atEnd())) {
-        debugs(74, 5, "Parser needs more data to find version");
-        return 0;
+    // tolerant parser allows multiple whitespace characters between request-line fields
+    if (count > 1 && !Config.onoff.relaxed_header_parser) {
+        debugs(33, ErrorLevel(), "invalid request-line: too many delimiters");
+        parseStatusCode = Http::scBadRequest;
+        return false;
+    }
 
-    } // else error ...
+    return true;
+}
 
-    // non-DIGIT. invalid version number.
-    parseStatusCode = Http::scHttpVersionNotSupported;
-    debugs(33, 5, "invalid request-line. garbage before line terminator");
-    return -1;
+/// Parse CRs at the end of request-line, just before the terminating LF.
+bool
+Http::One::RequestParser::skipTrailingCrs(Http1::Tokenizer &tok)
+{
+    if (Config.onoff.relaxed_header_parser) {
+        (void)tok.skipAllTrailing(CharacterSet::CR); // optional; multiple OK
+    } else {
+        if (!tok.skipOneTrailing(CharacterSet::CR)) {
+            debugs(33, ErrorLevel(), "invalid request-line: missing CR before LF");
+            parseStatusCode = Http::scBadRequest;
+            return false;
+        }
+    }
+    return true;
 }
 
 /**
@@ -235,10 +277,6 @@
  *  RFC 1945 section 5.1
  *  RFC 7230 section 2.6, 3.1 and 3.5
  *
- * Parsing state is stored between calls. The current implementation uses
- * checkpoints after each successful request-line field.
- * The return value tells you whether the parsing is completed or not.
- *
  * \retval -1  an error occurred. parseStatusCode indicates HTTP status result.
  * \retval  1  successful parse. member fields contain the request-line items
  * \retval  0  more data is needed to complete the parse
@@ -246,186 +284,53 @@
 int
 Http::One::RequestParser::parseRequestFirstLine()
 {
-    Http1::Tokenizer tok(buf_);
-
     debugs(74, 5, "parsing possible request: buf.length=" << buf_.length());
     debugs(74, DBG_DATA, buf_);
 
-    // NP: would be static, except it need to change with reconfigure
-    CharacterSet WspDelim = CharacterSet::SP; // strict parse only accepts SP
-
-    if (Config.onoff.relaxed_header_parser) {
-        // RFC 7230 section 3.5
-        // tolerant parser MAY accept any of SP, HTAB, VT (%x0B), FF (%x0C), or bare CR
-        // as whitespace between request-line fields
-        WspDelim += CharacterSet::HTAB
-                    + CharacterSet("VT,FF","\x0B\x0C")
-                    + CharacterSet::CR;
-        debugs(74, 5, "using Parser relaxed WSP characters");
-    }
-
-    // only search for method if we have not yet found one
-    if (method_ == Http::METHOD_NONE) {
-        const int res = parseMethodField(tok, WspDelim);
-        if (res < 1)
-            return res;
-        // else keep going...
-    }
+    SBuf line;
 
-    // tolerant parser allows multiple whitespace characters between request-line fields
-    if (Config.onoff.relaxed_header_parser) {
-        const size_t garbage = tok.skipAll(WspDelim);
-        if (garbage > 0) {
-            firstLineGarbage_ += garbage;
-            buf_ = tok.remaining(); // re-checkpoint after garbage
-        }
-    }
-    if (tok.atEnd()) {
+    // Earlier, skipGarbageLines() took care of any leading LFs (if allowed).
+    // Now, the request line has to end at the first LF.
+    static const CharacterSet lineChars = CharacterSet::LF.complement("notLF");
+    ::Parser::Tokenizer lineTok(buf_);
+    if (!lineTok.prefix(line, lineChars) || !lineTok.skip('\n')) {
         debugs(74, 5, "Parser needs more data");
         return 0;
     }
 
-    // from here on, we have two possible parse paths: whitespace tolerant, and strict
-    if (Config.onoff.relaxed_header_parser) {
-        // whitespace tolerant
+    Http1::Tokenizer tok(line);
+    const CharacterSet &delimiters = DelimiterCharacters();
 
-        int warnOnError = (Config.onoff.relaxed_header_parser <= 0 ? DBG_IMPORTANT : 2);
+    if (!parseMethodField(tok))
+        return -1;
 
-        // NOTES:
-        // * this would be static, except WspDelim changes with reconfigure
-        // * HTTP-version charset is included by uriValidCharacters()
-        // * terminal CR is included by WspDelim here in relaxed parsing
-        CharacterSet LfDelim = uriValidCharacters() + WspDelim;
-
-        // seek the LF character, then tokenize the line in reverse
-        SBuf line;
-        if (tok.prefix(line, LfDelim) && tok.skip('\n')) {
-            Http1::Tokenizer rTok(line);
-            SBuf nil;
-            (void)rTok.suffix(nil,CharacterSet::CR); // optional CR in terminator
-            SBuf digit;
-            if (rTok.suffix(digit,CharacterSet::DIGIT) && rTok.skipSuffix(Http1magic) && rTok.suffix(nil,WspDelim)) {
-                uri_ = rTok.remaining();
-                msgProtocol_ = Http::ProtocolVersion(1, (*digit.rawContent() - '0'));
-                if (uri_.isEmpty()) {
-                    debugs(33, warnOnError, "invalid request-line. missing URL");
-                    parseStatusCode = Http::scBadRequest;
-                    return -1;
-                }
-
-                parseStatusCode = Http::scOkay;
-                buf_ = tok.remaining(); // incremental parse checkpoint
-                return 1;
-
-            } else if (method_ == Http::METHOD_GET) {
-                // RFC 1945 - for GET the line terminator may follow URL instead of a delimiter
-                debugs(33, 5, "HTTP/0.9 syntax request-line detected");
-                msgProtocol_ = Http::ProtocolVersion(0,9);
-                static const SBuf cr("\r",1);
-                uri_ = line.trim(cr,false,true);
-                parseStatusCode = Http::scOkay;
-                buf_ = tok.remaining(); // incremental parse checkpoint
-                return 1;
-            }
+    if (!skipDelimiter(tok.skipAll(delimiters)))
+        return -1;
 
-            debugs(33, warnOnError, "invalid request-line. not HTTP");
-            parseStatusCode = Http::scBadRequest;
-            return -1;
-        }
+    /* now parse backwards, to leave just the URI */
+    if (!skipTrailingCrs(tok))
+        return -1;
 
-        if (!tok.atEnd()) {
+    if (!parseHttpVersionField(tok))
+        return -1;
 
-#if USE_HTTP_VIOLATIONS
-            /*
-             * RFC 3986 explicitly lists the characters permitted in URI.
-             * A non-permitted character was found somewhere in the request-line.
-             * However, as long as we can find the LF, accept the characters
-             * which we know are invalid in any URI but actively used.
-             */
-            LfDelim.add('\0'); // Java
-            LfDelim.add(' ');  // IIS
-            LfDelim.add('\"'); // Bing
-            LfDelim.add('\\'); // MSIE, Firefox
-            LfDelim.add('|');  // Amazon
-            LfDelim.add('^');  // Microsoft News
-
-            // other ASCII characters for which RFC 2396 has explicitly disallowed use
-            // since 1998 and which were not later permitted by RFC 3986 in 2005.
-            LfDelim.add('<');  // HTML embedded in URL
-            LfDelim.add('>');  // HTML embedded in URL
-            LfDelim.add('`');  // Shell Script embedded in URL
-            LfDelim.add('{');  // JSON or Javascript embedded in URL
-            LfDelim.add('}');  // JSON or Javascript embedded in URL
-
-            // reset the tokenizer from anything the above did, then seek the LF character.
-            tok.reset(buf_);
-
-            if (tok.prefix(line, LfDelim) && tok.skip('\n')) {
-
-                Http1::Tokenizer rTok(line);
-
-                // strip terminating CR (if any)
-                SBuf nil;
-                (void)rTok.suffix(nil,CharacterSet::CR); // optional CR in terminator
-                line = rTok.remaining();
-
-                // strip terminating 'WSP HTTP-version' (if any)
-                if (rTok.suffix(nil,CharacterSet::DIGIT) && rTok.skipSuffix(Http1magic) && rTok.suffix(nil,WspDelim)) {
-                    hackExpectsMime_ = true; // client thinks its speaking HTTP, probably sent a mime block.
-                    uri_ = rTok.remaining();
-                } else
-                    uri_ = line; // no HTTP/1.x label found. Use the whole line.
-
-                if (uri_.isEmpty()) {
-                    debugs(33, warnOnError, "invalid request-line. missing URL");
-                    parseStatusCode = Http::scBadRequest;
-                    return -1;
-                }
-
-                debugs(33, warnOnError, "invalid request-line. treating as HTTP/0.9" << (hackExpectsMime_?" (with mime)":""));
-                msgProtocol_ = Http::ProtocolVersion(0,9);
-                parseStatusCode = Http::scOkay;
-                buf_ = tok.remaining(); // incremental parse checkpoint
-                return 1;
-
-            } else if (tok.atEnd()) {
-                debugs(74, 5, "Parser needs more data");
-                return 0;
-            }
-            // else, drop back to invalid request-line handling
-#endif
-            const SBuf t = tok.remaining();
-            debugs(33, warnOnError, "invalid request-line characters." << Raw("data", t.rawContent(), t.length()));
-            parseStatusCode = Http::scBadRequest;
-            return -1;
-        }
-        debugs(74, 5, "Parser needs more data");
-        return 0;
-    }
-    // else strict non-whitespace tolerant parse
+    if (!http0() && !skipDelimiter(tok.skipAllTrailing(delimiters)))
+        return -1;
 
-    // only search for request-target (URL) if we have not yet found one
-    if (uri_.isEmpty()) {
-        const int res = parseUriField(tok);
-        if (res < 1 || msgProtocol_.protocol == AnyP::PROTO_HTTP)
-            return res;
-        // else keep going...
-    }
+    /* parsed everything before and after the URI */
 
-    if (tok.atEnd()) {
-        debugs(74, 5, "Parser needs more data");
-        return 0;
-    }
+    if (!parseUriField(tok))
+        return -1;
 
-    // HTTP/1 version suffix (protocol magic) followed by CR*LF
-    if (msgProtocol_.protocol == AnyP::PROTO_NONE) {
-        return parseHttpVersionField(tok);
+    if (!tok.atEnd()) {
+        debugs(33, ErrorLevel(), "invalid request-line: garbage after URI");
+        parseStatusCode = Http::scBadRequest;
+        return -1;
     }
 
-    // If we got here this method has been called too many times
-    parseStatusCode = Http::scInternalServerError;
-    debugs(33, 5, "ERROR: Parser already processed request-line");
-    return -1;
+    parseStatusCode = Http::scOkay;
+    buf_ = lineTok.remaining(); // incremental parse checkpoint
+    return 1;
 }
 
 bool
diff -u -r -N squid-4.0.2/src/http/one/RequestParser.h squid-4.0.3/src/http/one/RequestParser.h
--- squid-4.0.2/src/http/one/RequestParser.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/http/one/RequestParser.h	2015-11-28 07:30:57.000000000 -0800
@@ -47,19 +47,23 @@
 private:
     void skipGarbageLines();
     int parseRequestFirstLine();
-    int parseMethodField(Http1::Tokenizer &, const CharacterSet &);
-    int parseUriField(Http1::Tokenizer &);
-    int parseHttpVersionField(Http1::Tokenizer &);
+
+    /* all these return false and set parseStatusCode on parsing failures */
+    bool parseMethodField(Http1::Tokenizer &);
+    bool parseUriField(Http1::Tokenizer &);
+    bool parseHttpVersionField(Http1::Tokenizer &);
+    bool skipDelimiter(const size_t count);
+    bool skipTrailingCrs(Http1::Tokenizer &tok);
+
+    bool http0() const {return !msgProtocol_.major;}
+    static const CharacterSet &DelimiterCharacters();
+    static const CharacterSet &RequestTargetCharacters();
 
     /// what request method has been found on the first line
     HttpRequestMethod method_;
 
     /// raw copy of the original client request-line URI field
     SBuf uri_;
-
-    /// amount of garbage bytes tolerantly skipped inside the request-line
-    /// may be -1 if sender only omitted CR on terminator
-    int64_t firstLineGarbage_;
 };
 
 } // namespace One
diff -u -r -N squid-4.0.2/src/http/StatusLine.h squid-4.0.3/src/http/StatusLine.h
--- squid-4.0.2/src/http/StatusLine.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/http/StatusLine.h	2015-11-28 07:30:57.000000000 -0800
@@ -35,8 +35,12 @@
 
     /// set this status-line to the given values
     /// when reason is NULL the default message text for this StatusCode will be used
+    /// when reason is not NULL, it must not point to a dynamically allocated value
     void set(const AnyP::ProtocolVersion &newVersion, Http::StatusCode newStatus, const char *newReason = NULL);
 
+    /// reset the reason phrase to its default status code-derived value
+    void resetReason() { reason_ = nullptr; }
+
     /// retrieve the status code for this status line
     Http::StatusCode status() const { return status_; }
 
diff -u -r -N squid-4.0.2/src/icmp/Makefile.in squid-4.0.3/src/icmp/Makefile.in
--- squid-4.0.2/src/icmp/Makefile.in	2015-11-01 04:19:26.000000000 -0800
+++ squid-4.0.3/src/icmp/Makefile.in	2015-11-28 07:32:47.000000000 -0800
@@ -488,6 +488,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -524,7 +525,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/icmp/net_db.cc squid-4.0.3/src/icmp/net_db.cc
--- squid-4.0.2/src/icmp/net_db.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/icmp/net_db.cc	2015-11-28 07:30:57.000000000 -0800
@@ -19,9 +19,9 @@
 #include "squid.h"
 #include "CachePeer.h"
 #include "cbdata.h"
-#include "disk.h"
 #include "event.h"
 #include "fde.h"
+#include "fs_io.h"
 #include "FwdState.h"
 #include "HttpReply.h"
 #include "HttpRequest.h"
@@ -33,10 +33,10 @@
 #include "mgr/Registration.h"
 #include "mime_header.h"
 #include "neighbors.h"
+#include "SquidConfig.h"
 #include "SquidTime.h"
 #include "Store.h"
 #include "StoreClient.h"
-#include "SwapDir.h"
 #include "tools.h"
 #include "URL.h"
 #include "wordlist.h"
diff -u -r -N squid-4.0.2/src/icp_v2.cc squid-4.0.3/src/icp_v2.cc
--- squid-4.0.2/src/icp_v2.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/icp_v2.cc	2015-11-28 07:30:57.000000000 -0800
@@ -39,7 +39,6 @@
 #include "StatCounters.h"
 #include "Store.h"
 #include "store_key_md5.h"
-#include "SwapDir.h"
 #include "tools.h"
 #include "wordlist.h"
 
diff -u -r -N squid-4.0.2/src/ident/Makefile.in squid-4.0.3/src/ident/Makefile.in
--- squid-4.0.2/src/ident/Makefile.in	2015-11-01 04:19:27.000000000 -0800
+++ squid-4.0.3/src/ident/Makefile.in	2015-11-28 07:32:48.000000000 -0800
@@ -460,6 +460,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -493,7 +494,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/ip/Makefile.in squid-4.0.3/src/ip/Makefile.in
--- squid-4.0.2/src/ip/Makefile.in	2015-11-01 04:19:27.000000000 -0800
+++ squid-4.0.3/src/ip/Makefile.in	2015-11-28 07:32:48.000000000 -0800
@@ -460,6 +460,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -493,7 +494,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/ipc/Makefile.in squid-4.0.3/src/ipc/Makefile.in
--- squid-4.0.2/src/ipc/Makefile.in	2015-11-01 04:19:27.000000000 -0800
+++ squid-4.0.3/src/ipc/Makefile.in	2015-11-28 07:32:49.000000000 -0800
@@ -466,6 +466,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -499,7 +500,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/ipc/mem/Pages.cc squid-4.0.3/src/ipc/mem/Pages.cc
--- squid-4.0.2/src/ipc/mem/Pages.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/ipc/mem/Pages.cc	2015-11-28 07:30:57.000000000 -0800
@@ -13,7 +13,6 @@
 #include "base/TextException.h"
 #include "ipc/mem/PagePool.h"
 #include "ipc/mem/Pages.h"
-#include "SwapDir.h"
 #include "tools.h"
 
 // Uses a single PagePool instance, for now.
diff -u -r -N squid-4.0.2/src/ipc/MemMap.h squid-4.0.3/src/ipc/MemMap.h
--- squid-4.0.2/src/ipc/MemMap.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/ipc/MemMap.h	2015-11-28 07:30:57.000000000 -0800
@@ -10,11 +10,11 @@
 #define SQUID_IPC_STORE_MAP_H
 
 #include "Debug.h"
-#include "fs/forward.h"
 #include "ipc/mem/FlexibleArray.h"
 #include "ipc/mem/Pointer.h"
 #include "ipc/ReadWriteLock.h"
 #include "SBuf.h"
+#include "store/forward.h"
 #include "store_key_md5.h"
 #include "tools.h"
 
diff -u -r -N squid-4.0.2/src/ipc/StoreMap.h squid-4.0.3/src/ipc/StoreMap.h
--- squid-4.0.2/src/ipc/StoreMap.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/ipc/StoreMap.h	2015-11-28 07:30:57.000000000 -0800
@@ -9,11 +9,11 @@
 #ifndef SQUID_IPC_STORE_MAP_H
 #define SQUID_IPC_STORE_MAP_H
 
-#include "fs/forward.h"
 #include "ipc/mem/FlexibleArray.h"
 #include "ipc/mem/Pointer.h"
 #include "ipc/ReadWriteLock.h"
 #include "SBuf.h"
+#include "store/forward.h"
 #include "store_key_md5.h"
 
 namespace Ipc
diff -u -r -N squid-4.0.2/src/ipc/Strand.cc squid-4.0.3/src/ipc/Strand.cc
--- squid-4.0.2/src/ipc/Strand.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/ipc/Strand.cc	2015-11-28 07:30:57.000000000 -0800
@@ -14,6 +14,7 @@
 #include "CacheManager.h"
 #include "CollapsedForwarding.h"
 #include "comm/Connection.h"
+#include "fatal.h"
 #include "globals.h"
 #include "ipc/Kids.h"
 #include "ipc/Messages.h"
@@ -24,7 +25,6 @@
 #include "mgr/Forwarder.h"
 #include "mgr/Request.h"
 #include "mgr/Response.h"
-#include "SwapDir.h" /* XXX: scope boundary violation */
 #if HAVE_DISKIO_MODULE_IPCIO
 #include "DiskIO/IpcIo/IpcIoFile.h" /* XXX: scope boundary violation */
 #endif
diff -u -r -N squid-4.0.2/src/log/Makefile.in squid-4.0.3/src/log/Makefile.in
--- squid-4.0.2/src/log/Makefile.in	2015-11-01 04:19:28.000000000 -0800
+++ squid-4.0.3/src/log/Makefile.in	2015-11-28 07:32:49.000000000 -0800
@@ -464,6 +464,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -497,7 +498,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/log/ModStdio.cc squid-4.0.3/src/log/ModStdio.cc
--- squid-4.0.2/src/log/ModStdio.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/log/ModStdio.cc	2015-11-28 07:30:57.000000000 -0800
@@ -9,10 +9,10 @@
 /* DEBUG: section 50    Log file handling */
 
 #include "squid.h"
-#include "disk.h"
 #include "fatal.h"
 #include "fd.h"
 #include "fde.h"
+#include "fs_io.h"
 #include "globals.h"
 #include "log/File.h"
 #include "log/ModStdio.h"
diff -u -r -N squid-4.0.2/src/log/ModUdp.cc squid-4.0.3/src/log/ModUdp.cc
--- squid-4.0.2/src/log/ModUdp.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/log/ModUdp.cc	2015-11-28 07:30:57.000000000 -0800
@@ -11,9 +11,9 @@
 #include "squid.h"
 #include "comm.h"
 #include "comm/Connection.h"
-#include "disk.h"
 #include "fatal.h"
 #include "fd.h"
+#include "fs_io.h"
 #include "log/File.h"
 #include "log/ModUdp.h"
 #include "Parsing.h"
diff -u -r -N squid-4.0.2/src/main.cc squid-4.0.3/src/main.cc
--- squid-4.0.2/src/main.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/main.cc	2015-11-28 07:30:57.000000000 -0800
@@ -23,7 +23,6 @@
 #include "comm.h"
 #include "ConfigParser.h"
 #include "CpuAffinity.h"
-#include "disk.h"
 #include "DiskIO/DiskIOModule.h"
 #include "dns/forward.h"
 #include "errorpage.h"
@@ -34,6 +33,7 @@
 #include "format/Token.h"
 #include "fqdncache.h"
 #include "fs/Module.h"
+#include "fs_io.h"
 #include "FwdState.h"
 #include "globals.h"
 #include "htcp.h"
@@ -65,9 +65,9 @@
 #include "stat.h"
 #include "StatCounters.h"
 #include "Store.h"
+#include "store/Disks.h"
 #include "store_log.h"
 #include "StoreFileSystem.h"
-#include "SwapDir.h"
 #include "tools.h"
 #include "unlinkd.h"
 #include "URL.h"
@@ -1141,9 +1141,6 @@
 
 #endif
 
-    if (!configured_once)
-        disk_init();        /* disk_init must go before ipcache_init() */
-
     ipcache_init();
 
     fqdncache_init();
@@ -1501,7 +1498,7 @@
         StoreFileSystem::SetupAllFs();
 
         /* we may want the parsing process to set this up in the future */
-        Store::Root(new StoreController);
+        Store::Init();
         Auth::Init();      /* required for config parsing. NOP if !USE_AUTH */
         Ip::ProbeTransport(); // determine IPv4 or IPv6 capabilities before parsing.
 
@@ -2052,8 +2049,7 @@
     mimeFreeMemory();
     errorClean();
 #endif
-    // clear StoreController
-    Store::Root(NULL);
+    Store::FreeMemory();
 
     fdDumpOpen();
 
diff -u -r -N squid-4.0.2/src/Makefile.am squid-4.0.3/src/Makefile.am
--- squid-4.0.2/src/Makefile.am	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/Makefile.am	2015-11-28 07:30:57.000000000 -0800
@@ -42,8 +42,8 @@
 	LoadableModules.h \
 	LoadableModules.cc
 
-SUBDIRS	= mem base anyp helper dns ftp parser comm eui acl format clients servers fs repl DiskIO
-DIST_SUBDIRS = mem base anyp helper dns ftp parser comm eui acl format clients servers fs repl DiskIO
+SUBDIRS	= mem base anyp helper dns ftp parser comm eui acl format clients servers fs repl store DiskIO
+DIST_SUBDIRS = mem base anyp helper dns ftp parser comm eui acl format clients servers fs repl store DiskIO
 
 if ENABLE_AUTH
 SUBDIRS += auth
@@ -280,8 +280,8 @@
 	Debug.h \
 	defines.h \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	dlink.h \
 	dlink.cc \
 	$(DNSSOURCE) \
@@ -312,7 +312,6 @@
 	filemap.cc \
 	fqdncache.h \
 	fqdncache.cc \
-	fs/forward.h \
 	FwdState.cc \
 	FwdState.h \
 	Generic.h \
@@ -411,6 +410,8 @@
 	PeerPoolMgr.cc \
 	PeerSelectState.h \
 	PingData.h \
+	Pipeline.cc \
+	Pipeline.h \
 	protos.h \
 	redirect.h \
 	redirect.cc \
@@ -448,7 +449,6 @@
 	Store.h \
 	StoreFileSystem.cc \
 	StoreFileSystem.h \
-	StoreHashIndex.h \
 	store_io.cc \
 	StoreIOBuffer.h \
 	StoreIOState.cc \
@@ -457,7 +457,6 @@
 	StoreClient.h \
 	store_digest.h \
 	store_digest.cc \
-	store_dir.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
 	store_log.h \
@@ -477,8 +476,6 @@
 	StoreSwapLogData.cc \
 	StoreSwapLogData.h \
 	swap_log_op.h \
-	SwapDir.cc \
-	SwapDir.h \
 	Transients.cc \
 	Transients.h \
 	MemStore.cc \
@@ -575,7 +572,6 @@
 	log/liblog.la \
 	format/libformat.la \
 	$(XTRA_OBJS) \
-	$(DISK_LINKOBJS) \
 	$(REPL_OBJS) \
 	$(NETTLELIB) \
 	$(CRYPTLIB) \
@@ -584,9 +580,11 @@
 	$(ESI_LIBS) \
 	$(SNMP_LIBS) \
 	mem/libmem.la \
+	store/libstore.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
 	$(top_builddir)/lib/libmiscutil.la \
+	$(ATOMICLIB) \
 	$(SSLLIB) \
 	$(EPOLL_LIBS) \
 	$(MINGW_LIBS) \
@@ -624,12 +622,11 @@
 ## ACLProxyAuth.cc wants ACLUserData
 ## ACLProxyAuth.cc wants ACLRegexData
 ## cache_cf.cc wants $(AUTH_LIBS)
-## cache_cf.cc wants Swapdir
+## cache_cf.cc wants store/libstore.la
 ## cache_cf.cc wants AnyP::PortCfg
 ## client_side wants client_db
 ## client_db wants SNMP_SOURCE
 ## snmp_core wants ACLStringData
-## SwapDir wants ConfigOption
 ## tools.cc wants ip/libip.la
 ## client_side.cc wants ip/libip.la
 ## libbase.la wants cbdata.*
@@ -696,7 +693,6 @@
 	ipc/libipc.la \
 	mgr/libmgr.la \
 	DiskIO/libdiskio.la \
-	$(DISK_LINKOBJS) \
 	$(REPL_OBJS)
 
 nodist_ufsdump_SOURCES = \
@@ -1120,7 +1116,6 @@
 	SBufDetailedStats.h \
 	tests/stub_SBufDetailedStats.cc \
 	String.cc \
-	store_dir.cc \
 	StoreIOState.cc \
 	tests/stub_StoreMeta.cc \
 	StoreMetaUnpacker.cc \
@@ -1130,7 +1125,6 @@
 	swap_log_op.cc \
 	swap_log_op.h \
 	tests/stub_SwapDir.cc \
-	SwapDir.h \
 	Transients.cc \
 	log/access_log.h \
 	tests/stub_access_log.cc \
@@ -1295,8 +1289,8 @@
 	CpuAffinitySet.cc \
 	CpuAffinitySet.h \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	dlink.h \
 	dlink.cc \
 	$(DNSSOURCE) \
@@ -1314,7 +1308,6 @@
 	filemap.cc \
 	fqdncache.h \
 	fqdncache.cc \
-	fs/forward.h \
 	FwdState.cc \
 	FwdState.h \
 	gopher.h \
@@ -1380,6 +1373,8 @@
 	peer_userhash.cc \
 	PeerPoolMgr.h \
 	PeerPoolMgr.cc \
+	Pipeline.cc \
+	Pipeline.h \
 	redirect.h \
 	tests/stub_redirect.cc \
 	refresh.h \
@@ -1411,7 +1406,6 @@
 	store_client.cc \
 	store_digest.h \
 	tests/stub_store_digest.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
@@ -1479,6 +1473,7 @@
 	mgr/libmgr.la \
 	$(SNMP_LIBS) \
 	mem/libmem.la \
+	store/libstore.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
 	$(top_builddir)/lib/libmiscutil.la \
@@ -1505,8 +1500,8 @@
 	ConfigOption.cc \
 	ConfigParser.cc \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	tests/stub_ETag.cc \
 	EventLoop.cc \
 	event.cc \
@@ -1518,7 +1513,6 @@
 	fde.cc \
 	FileMap.h \
 	filemap.cc \
-	fs/forward.h \
 	HttpBody.h \
 	HttpBody.cc \
 	HttpHeaderFieldStat.h \
@@ -1569,7 +1563,6 @@
 	tests/stub_StoreMeta.cc \
 	StoreMetaUnpacker.cc \
 	StoreSwapLogData.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
@@ -1660,6 +1653,7 @@
 	dns/libdns.la \
 	base/libbase.la \
 	mem/libmem.la \
+	store/libstore.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
 	$(top_builddir)/lib/libmiscutil.la \
@@ -1728,8 +1722,8 @@
 	CpuAffinitySet.h \
 	debug.cc \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	dlink.h \
 	dlink.cc \
 	$(DNSSOURCE) \
@@ -1750,7 +1744,6 @@
 	filemap.cc \
 	fqdncache.h \
 	fqdncache.cc \
-	fs/forward.h \
 	FwdState.cc \
 	FwdState.h \
 	gopher.h \
@@ -1819,6 +1812,8 @@
 	peer_sourcehash.cc \
 	peer_userhash.h \
 	peer_userhash.cc \
+	Pipeline.cc \
+	Pipeline.h \
 	redirect.h \
 	tests/stub_redirect.cc \
 	refresh.h \
@@ -1847,7 +1842,6 @@
 	store_client.cc \
 	store_digest.h \
 	tests/stub_store_digest.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
@@ -1925,6 +1919,7 @@
 	$(top_builddir)/lib/libmiscutil.la \
 	ipc/libipc.la \
 	mgr/libmgr.la \
+	store/libstore.la \
 	$(SNMP_LIBS) \
 	$(NETTLELIB) \
 	$(REGEXLIB) \
@@ -1974,8 +1969,8 @@
 	CpuAffinitySet.h \
 	debug.cc \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	dlink.h \
 	dlink.cc \
 	$(DNSSOURCE) \
@@ -1996,7 +1991,6 @@
 	filemap.cc \
 	fqdncache.h \
 	fqdncache.cc \
-	fs/forward.h \
 	FwdState.cc \
 	FwdState.h \
 	gopher.h \
@@ -2064,6 +2058,8 @@
 	peer_sourcehash.cc \
 	peer_userhash.h \
 	peer_userhash.cc \
+	Pipeline.cc \
+	Pipeline.h \
 	RemovalPolicy.cc \
 	redirect.h \
 	tests/stub_redirect.cc \
@@ -2090,7 +2086,6 @@
 	store_client.cc \
 	store_digest.h \
 	tests/stub_store_digest.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
@@ -2170,6 +2165,7 @@
 	$(top_builddir)/lib/libmiscutil.la \
 	ipc/libipc.la \
 	mgr/libmgr.la \
+	store/libstore.la \
 	$(SNMP_LIBS) \
 	$(NETTLELIB) \
 	$(REGEXLIB) \
@@ -2218,8 +2214,8 @@
 	CpuAffinitySet.h \
 	debug.cc \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	dlink.h \
 	dlink.cc \
 	$(DNSSOURCE) \
@@ -2237,7 +2233,6 @@
 	filemap.cc \
 	fqdncache.h \
 	fqdncache.cc \
-	fs/forward.h \
 	FwdState.cc \
 	FwdState.h \
 	gopher.h \
@@ -2304,6 +2299,8 @@
 	peer_sourcehash.cc \
 	peer_userhash.h \
 	peer_userhash.cc \
+	Pipeline.cc \
+	Pipeline.h \
 	pconn.cc \
 	redirect.h \
 	tests/stub_redirect.cc \
@@ -2331,7 +2328,6 @@
 	store_client.cc \
 	store_digest.h \
 	tests/stub_store_digest.cc \
-	store_dir.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
 	store_io.cc \
@@ -2408,6 +2404,7 @@
 	dns/libdns.la \
 	base/libbase.la \
 	mgr/libmgr.la \
+	store/libstore.la \
 	$(SNMP_LIBS) \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
@@ -2551,8 +2548,8 @@
 	CpuAffinitySet.cc \
 	CpuAffinitySet.h \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	dlink.h \
 	dlink.cc \
 	$(DNSSOURCE) \
@@ -2567,7 +2564,6 @@
 	fde.cc \
 	fqdncache.h \
 	fqdncache.cc \
-	fs/forward.h \
 	FwdState.cc \
 	FwdState.h \
 	gopher.h \
@@ -2632,6 +2628,8 @@
 	peer_userhash.cc \
 	PeerPoolMgr.h \
 	PeerPoolMgr.cc \
+	Pipeline.cc \
+	Pipeline.h \
 	redirect.h \
 	tests/stub_libauth_acls.cc \
 	tests/stub_redirect.cc \
@@ -2659,7 +2657,6 @@
 	store_client.cc \
 	store_digest.h \
 	tests/stub_store_digest.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
@@ -2724,6 +2721,7 @@
 	comm/libcomm.la \
 	log/liblog.la \
 	format/libformat.la \
+	store/libstore.la \
 	$(REPL_OBJS) \
 	$(ADAPTATION_LIBS) \
 	$(ESI_LIBS) \
@@ -2794,8 +2792,8 @@
 	ConfigOption.cc \
 	ConfigParser.cc \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	ETag.cc \
 	event.cc \
 	EventLoop.cc \
@@ -2803,7 +2801,6 @@
 	tests/stub_fatal.cc \
 	FileMap.h \
 	filemap.cc \
-	fs/forward.h \
 	HttpHeaderFieldStat.h \
 	HttpHdrCc.h \
 	HttpHdrCc.cc \
@@ -2842,7 +2839,6 @@
 	stmem.cc \
 	repl_modules.h \
 	store.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_swapout.cc \
 	StoreIOState.cc \
@@ -2859,7 +2855,6 @@
 	String.cc \
 	StrList.h \
 	StrList.cc \
-	SwapDir.cc \
 	tests/CapturingStoreEntry.h \
 	log/access_log.h \
 	tests/stub_access_log.cc \
@@ -2942,6 +2937,7 @@
 	ipc/libipc.la \
 	anyp/libanyp.la \
 	mem/libmem.la \
+	store/libstore.la \
 	DiskIO/libdiskio.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
@@ -3046,11 +3042,10 @@
 	fde.h \
 	fde.cc \
 	client_db.h \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	FileMap.h \
 	filemap.cc \
-	fs/forward.h \
 	HttpBody.h \
 	HttpBody.cc \
 	HttpReply.cc \
@@ -3084,14 +3079,12 @@
 	EventLoop.cc \
 	HttpMsg.cc \
 	RemovalPolicy.cc \
-	store_dir.cc \
 	repl_modules.h \
 	store.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
 	Parsing.cc \
 	ConfigOption.cc \
-	SwapDir.cc \
 	tests/stub_acl.cc \
 	cache_cf.h \
 	YesNoNone.h \
@@ -3179,6 +3172,7 @@
 	base/libbase.la \
 	ip/libip.la \
 	mem/libmem.la \
+	store/libstore.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
 	$(top_builddir)/lib/libmiscutil.la \
@@ -3215,8 +3209,8 @@
 	tests/stub_CacheDigest.cc \
 	ConfigOption.cc \
 	ConfigParser.cc \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	ETag.cc \
 	EventLoop.cc \
 	event.cc \
@@ -3228,7 +3222,6 @@
 	fde.cc \
 	FileMap.h \
 	filemap.cc \
-	fs/forward.h \
 	HttpHeaderFieldStat.h \
 	HttpBody.h \
 	HttpBody.cc \
@@ -3272,7 +3265,6 @@
 	StoreMetaUnpacker.cc \
 	$(STOREMETA_SOURCE) \
 	StoreSwapLogData.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
@@ -3286,7 +3278,6 @@
 	String.cc \
 	StrList.h \
 	StrList.cc \
-	SwapDir.cc \
 	Transients.h \
 	Transients.cc \
 	tests/testRock.cc \
@@ -3358,6 +3349,7 @@
 	ipc/libipc.la \
 	base/libbase.la \
 	mem/libmem.la \
+	store/libstore.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
 	$(top_builddir)/lib/libmiscutil.la \
@@ -3406,8 +3398,8 @@
 	CpuAffinitySet.cc \
 	CpuAffinitySet.h \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	dlink.h \
 	dlink.cc \
 	$(DNSSOURCE) \
@@ -3425,7 +3417,6 @@
 	filemap.cc \
 	fqdncache.h \
 	fqdncache.cc \
-	fs/forward.h \
 	FwdState.cc \
 	FwdState.h \
 	gopher.h \
@@ -3493,6 +3484,8 @@
 	peer_sourcehash.cc \
 	peer_userhash.h \
 	peer_userhash.cc \
+	Pipeline.cc \
+	Pipeline.h \
 	redirect.h \
 	tests/stub_redirect.cc \
 	refresh.h \
@@ -3519,7 +3512,6 @@
 	store_client.cc \
 	store_digest.h \
 	tests/stub_store_digest.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
@@ -3599,6 +3591,7 @@
 	comm/libcomm.la \
 	log/liblog.la \
 	format/libformat.la \
+	store/libstore.la \
 	$(REGEXLIB) \
 	$(REPL_OBJS) \
 	$(ADAPTATION_LIBS) \
diff -u -r -N squid-4.0.2/src/Makefile.in squid-4.0.3/src/Makefile.in
--- squid-4.0.2/src/Makefile.in	2015-11-01 04:19:15.000000000 -0800
+++ squid-4.0.3/src/Makefile.in	2015-11-28 07:32:35.000000000 -0800
@@ -252,16 +252,16 @@
 	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.h disk.cc dlink.h dlink.cc \
+	ClientDelayConfig.h fs_io.h fs_io.cc dlink.h dlink.cc \
 	dns_internal.cc enums.h err_type.h err_detail_type.h \
 	errorpage.cc errorpage.h ETag.cc ETag.h event.cc event.h \
 	EventLoop.h EventLoop.cc external_acl.cc ExternalACL.h \
 	ExternalACLEntry.cc ExternalACLEntry.h FadingCounter.h \
 	FadingCounter.cc fatal.h fatal.cc fd.h fd.cc fde.cc fde.h \
-	FileMap.h filemap.cc fqdncache.h fqdncache.cc fs/forward.h \
-	FwdState.cc FwdState.h Generic.h globals.h gopher.h gopher.cc \
-	helper.cc helper.h hier_code.h HierarchyLogEntry.h htcp.cc \
-	htcp.h HttpStateFlags.h http.cc http.h HttpHeaderFieldStat.h \
+	FileMap.h filemap.cc fqdncache.h fqdncache.cc FwdState.cc \
+	FwdState.h Generic.h globals.h gopher.h gopher.cc helper.cc \
+	helper.h hier_code.h HierarchyLogEntry.h htcp.cc htcp.h \
+	HttpStateFlags.h http.cc http.h HttpHeaderFieldStat.h \
 	HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci HttpHdrRange.cc \
 	HttpHdrSc.cc HttpHdrSc.h HttpHdrScTarget.cc HttpHdrScTarget.h \
 	HttpHdrContRange.cc HttpHdrContRange.h HttpHeaderStat.h \
@@ -282,22 +282,22 @@
 	peer_proxy_negotiate_auth.cc peer_select.cc peer_sourcehash.h \
 	peer_sourcehash.cc peer_userhash.h peer_userhash.cc \
 	PeerPoolMgr.h PeerPoolMgr.cc PeerSelectState.h PingData.h \
-	protos.h redirect.h redirect.cc refresh.h refresh.cc \
-	RemovalPolicy.cc RemovalPolicy.h send-announce.h \
-	send-announce.cc base/CharacterSet.h base/InstanceId.h \
-	MemBlob.h MemBlob.cc OutOfBoundsException.h SBuf.h SBuf.cc \
-	SBufExceptions.h SBufExceptions.cc SBufAlgos.h SBufAlgos.cc \
-	SBufDetailedStats.h SBufDetailedStats.cc SBufStatsAction.h \
-	SBufStatsAction.cc SnmpRequest.h snmp_core.h snmp_core.cc \
-	snmp_agent.h snmp_agent.cc SquidMath.h SquidMath.cc \
-	SquidNew.cc IoStats.h stat.h stat.cc StatCounters.h \
-	StatCounters.cc StatHist.h StatHist.cc String.cc StrList.h \
-	StrList.cc stmem.cc stmem.h repl_modules.h store.cc Store.h \
-	StoreFileSystem.cc StoreFileSystem.h StoreHashIndex.h \
+	Pipeline.cc Pipeline.h protos.h redirect.h redirect.cc \
+	refresh.h refresh.cc RemovalPolicy.cc RemovalPolicy.h \
+	send-announce.h send-announce.cc base/CharacterSet.h \
+	base/InstanceId.h MemBlob.h MemBlob.cc OutOfBoundsException.h \
+	SBuf.h SBuf.cc SBufExceptions.h SBufExceptions.cc SBufAlgos.h \
+	SBufAlgos.cc SBufDetailedStats.h SBufDetailedStats.cc \
+	SBufStatsAction.h SBufStatsAction.cc SnmpRequest.h snmp_core.h \
+	snmp_core.cc snmp_agent.h snmp_agent.cc SquidMath.h \
+	SquidMath.cc SquidNew.cc IoStats.h stat.h stat.cc \
+	StatCounters.h StatCounters.cc StatHist.h StatHist.cc \
+	String.cc StrList.h StrList.cc stmem.cc stmem.h repl_modules.h \
+	store.cc Store.h StoreFileSystem.cc StoreFileSystem.h \
 	store_io.cc StoreIOBuffer.h StoreIOState.cc StoreIOState.h \
 	store_client.cc StoreClient.h store_digest.h store_digest.cc \
-	store_dir.cc store_key_md5.h store_key_md5.cc store_log.h \
-	store_log.cc store_rebuild.h store_rebuild.cc store_swapin.h \
+	store_key_md5.h store_key_md5.cc store_log.h store_log.cc \
+	store_rebuild.h store_rebuild.cc store_swapin.h \
 	store_swapin.cc store_swapmeta.cc store_swapout.cc \
 	StoreMetaUnpacker.cc StoreMetaUnpacker.h StoreMeta.cc \
 	StoreMeta.h StoreMetaMD5.cc StoreMetaMD5.h StoreMetaSTD.cc \
@@ -305,11 +305,11 @@
 	StoreMetaObjSize.h StoreMetaURL.cc StoreMetaURL.h \
 	StoreMetaVary.cc StoreMetaVary.h StoreSearch.h StoreStats.cc \
 	StoreStats.h StoreSwapLogData.cc StoreSwapLogData.h \
-	swap_log_op.h SwapDir.cc SwapDir.h Transients.cc Transients.h \
-	MemStore.cc MemStore.h time.cc TimeOrTag.h tools.h tools.cc \
-	tunnel.cc typedefs.h unlinkd.h unlinkd.cc url.cc URL.h urn.h \
-	urn.cc wccp.h wccp.cc wccp2.h wccp2.cc whois.h whois.cc \
-	wordlist.h wordlist.cc win32.cc WinSvc.cc LoadableModule.h \
+	swap_log_op.h Transients.cc Transients.h MemStore.cc \
+	MemStore.h time.cc TimeOrTag.h tools.h tools.cc tunnel.cc \
+	typedefs.h unlinkd.h unlinkd.cc url.cc URL.h urn.h urn.cc \
+	wccp.h wccp.cc wccp2.h wccp2.cc whois.h whois.cc wordlist.h \
+	wordlist.cc win32.cc WinSvc.cc LoadableModule.h \
 	LoadableModule.cc LoadableModules.h LoadableModules.cc
 am__objects_1 = AclRegs.$(OBJEXT) AuthReg.$(OBJEXT)
 am__objects_2 = delay_pools.$(OBJEXT) DelayId.$(OBJEXT) \
@@ -347,7 +347,7 @@
 	ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) \
 	CpuAffinity.$(OBJEXT) CpuAffinityMap.$(OBJEXT) \
 	CpuAffinitySet.$(OBJEXT) debug.$(OBJEXT) $(am__objects_3) \
-	disk.$(OBJEXT) dlink.$(OBJEXT) $(am__objects_4) \
+	fs_io.$(OBJEXT) dlink.$(OBJEXT) $(am__objects_4) \
 	errorpage.$(OBJEXT) ETag.$(OBJEXT) event.$(OBJEXT) \
 	EventLoop.$(OBJEXT) external_acl.$(OBJEXT) \
 	ExternalACLEntry.$(OBJEXT) FadingCounter.$(OBJEXT) \
@@ -369,25 +369,26 @@
 	peer_digest.$(OBJEXT) peer_proxy_negotiate_auth.$(OBJEXT) \
 	peer_select.$(OBJEXT) peer_sourcehash.$(OBJEXT) \
 	peer_userhash.$(OBJEXT) PeerPoolMgr.$(OBJEXT) \
-	redirect.$(OBJEXT) refresh.$(OBJEXT) RemovalPolicy.$(OBJEXT) \
-	send-announce.$(OBJEXT) $(am__objects_9) SBufAlgos.$(OBJEXT) \
+	Pipeline.$(OBJEXT) redirect.$(OBJEXT) refresh.$(OBJEXT) \
+	RemovalPolicy.$(OBJEXT) send-announce.$(OBJEXT) \
+	$(am__objects_9) SBufAlgos.$(OBJEXT) \
 	SBufDetailedStats.$(OBJEXT) SBufStatsAction.$(OBJEXT) \
 	$(am__objects_11) SquidMath.$(OBJEXT) SquidNew.$(OBJEXT) \
 	stat.$(OBJEXT) StatCounters.$(OBJEXT) StatHist.$(OBJEXT) \
 	String.$(OBJEXT) StrList.$(OBJEXT) stmem.$(OBJEXT) \
 	store.$(OBJEXT) StoreFileSystem.$(OBJEXT) store_io.$(OBJEXT) \
 	StoreIOState.$(OBJEXT) store_client.$(OBJEXT) \
-	store_digest.$(OBJEXT) store_dir.$(OBJEXT) \
-	store_key_md5.$(OBJEXT) store_log.$(OBJEXT) \
-	store_rebuild.$(OBJEXT) store_swapin.$(OBJEXT) \
-	store_swapmeta.$(OBJEXT) store_swapout.$(OBJEXT) \
-	StoreMetaUnpacker.$(OBJEXT) $(am__objects_12) \
-	StoreStats.$(OBJEXT) StoreSwapLogData.$(OBJEXT) \
-	SwapDir.$(OBJEXT) Transients.$(OBJEXT) MemStore.$(OBJEXT) \
-	time.$(OBJEXT) tools.$(OBJEXT) tunnel.$(OBJEXT) \
-	$(am__objects_13) url.$(OBJEXT) urn.$(OBJEXT) wccp.$(OBJEXT) \
-	wccp2.$(OBJEXT) whois.$(OBJEXT) wordlist.$(OBJEXT) \
-	$(am__objects_14) $(am__objects_15) $(am__objects_17)
+	store_digest.$(OBJEXT) store_key_md5.$(OBJEXT) \
+	store_log.$(OBJEXT) store_rebuild.$(OBJEXT) \
+	store_swapin.$(OBJEXT) store_swapmeta.$(OBJEXT) \
+	store_swapout.$(OBJEXT) StoreMetaUnpacker.$(OBJEXT) \
+	$(am__objects_12) StoreStats.$(OBJEXT) \
+	StoreSwapLogData.$(OBJEXT) Transients.$(OBJEXT) \
+	MemStore.$(OBJEXT) time.$(OBJEXT) tools.$(OBJEXT) \
+	tunnel.$(OBJEXT) $(am__objects_13) url.$(OBJEXT) urn.$(OBJEXT) \
+	wccp.$(OBJEXT) wccp2.$(OBJEXT) whois.$(OBJEXT) \
+	wordlist.$(OBJEXT) $(am__objects_14) $(am__objects_15) \
+	$(am__objects_17)
 am__EXTRA_squid_SOURCES_DIST = ConfigOption.h CommonPool.h \
 	CompositePoolNode.h delay_pools.cc DelayId.cc DelayId.h \
 	DelayIdComposite.h DelayBucket.cc DelayBucket.h DelayConfig.cc \
@@ -426,14 +427,15 @@
 	format/libformat.la $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_4) $(am__DEPENDENCIES_5) mem/libmem.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_4) \
+	$(am__DEPENDENCIES_5) mem/libmem.la store/libstore.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
 	$(top_builddir)/lib/libmiscutil.la $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_3) \
-	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_6)
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_3) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_6)
 squid_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
 	$(CXXFLAGS) $(squid_LDFLAGS) $(LDFLAGS) -o $@
@@ -460,7 +462,7 @@
 	StatCounters.$(OBJEXT) StrList.$(OBJEXT) \
 	tests/stub_StatHist.$(OBJEXT) stmem.$(OBJEXT) $(am__objects_9) \
 	SBufAlgos.$(OBJEXT) tests/stub_SBufDetailedStats.$(OBJEXT) \
-	String.$(OBJEXT) store_dir.$(OBJEXT) StoreIOState.$(OBJEXT) \
+	String.$(OBJEXT) StoreIOState.$(OBJEXT) \
 	tests/stub_StoreMeta.$(OBJEXT) StoreMetaUnpacker.$(OBJEXT) \
 	StoreSwapLogData.$(OBJEXT) store_key_md5.$(OBJEXT) \
 	swap_log_op.$(OBJEXT) tests/stub_SwapDir.$(OBJEXT) \
@@ -534,12 +536,12 @@
 	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.h disk.cc dlink.h dlink.cc \
+	ClientDelayConfig.h fs_io.h fs_io.cc dlink.h dlink.cc \
 	dns_internal.cc errorpage.cc tests/stub_ETag.cc event.cc \
 	external_acl.cc ExternalACLEntry.cc fatal.h \
 	tests/stub_fatal.cc fd.h fd.cc fde.cc FileMap.h filemap.cc \
-	fqdncache.h fqdncache.cc fs/forward.h FwdState.cc FwdState.h \
-	gopher.h gopher.cc hier_code.h helper.cc htcp.cc htcp.h \
+	fqdncache.h fqdncache.cc FwdState.cc FwdState.h gopher.h \
+	gopher.cc hier_code.h helper.cc htcp.cc htcp.h \
 	HttpStateFlags.h http.cc HttpBody.h HttpBody.cc HttpHeader.h \
 	HttpHeader.cc HttpHeaderFieldInfo.h HttpHeaderTools.h \
 	HttpHeaderTools.cc HttpHeaderFieldStat.h HttpHdrCc.h \
@@ -555,25 +557,26 @@
 	peer_proxy_negotiate_auth.h peer_proxy_negotiate_auth.cc \
 	peer_select.cc peer_sourcehash.h peer_sourcehash.cc \
 	peer_userhash.h peer_userhash.cc PeerPoolMgr.h PeerPoolMgr.cc \
-	redirect.h tests/stub_redirect.cc refresh.h refresh.cc \
-	RemovalPolicy.cc base/CharacterSet.h base/InstanceId.h \
-	MemBlob.h MemBlob.cc OutOfBoundsException.h SBuf.h SBuf.cc \
-	SBufExceptions.h SBufExceptions.cc SBufAlgos.h SBufAlgos.cc \
-	SBufDetailedStats.h tests/stub_SBufDetailedStats.cc \
-	SnmpRequest.h snmp_core.h snmp_core.cc snmp_agent.h \
-	snmp_agent.cc SquidMath.h SquidMath.cc IoStats.h stat.h \
-	stat.cc StatCounters.h StatCounters.cc StatHist.h StrList.h \
-	StrList.cc tests/stub_libauth_acls.cc tests/stub_libauth.cc \
+	Pipeline.cc Pipeline.h redirect.h tests/stub_redirect.cc \
+	refresh.h refresh.cc RemovalPolicy.cc base/CharacterSet.h \
+	base/InstanceId.h MemBlob.h MemBlob.cc OutOfBoundsException.h \
+	SBuf.h SBuf.cc SBufExceptions.h SBufExceptions.cc SBufAlgos.h \
+	SBufAlgos.cc SBufDetailedStats.h \
+	tests/stub_SBufDetailedStats.cc SnmpRequest.h snmp_core.h \
+	snmp_core.cc snmp_agent.h snmp_agent.cc SquidMath.h \
+	SquidMath.cc IoStats.h stat.h stat.cc StatCounters.h \
+	StatCounters.cc StatHist.h StrList.h StrList.cc \
+	tests/stub_libauth_acls.cc tests/stub_libauth.cc \
 	tests/stub_libdiskio.cc tests/stub_StatHist.cc stmem.cc \
 	repl_modules.h store.cc store_client.cc store_digest.h \
-	tests/stub_store_digest.cc store_dir.cc store_io.cc \
-	store_key_md5.h store_key_md5.cc store_log.h store_log.cc \
-	store_rebuild.h store_rebuild.cc store_swapin.h \
-	store_swapin.cc store_swapmeta.cc store_swapout.cc \
-	StoreFileSystem.cc StoreIOState.cc tests/stub_StoreMeta.cc \
-	StoreMetaUnpacker.cc StoreSwapLogData.cc tools.h tools.cc \
-	Transients.cc tests/stub_tunnel.cc tests/stub_SwapDir.cc \
-	MemStore.cc unlinkd.h unlinkd.cc url.cc urn.h urn.cc wccp2.h \
+	tests/stub_store_digest.cc store_io.cc store_key_md5.h \
+	store_key_md5.cc store_log.h store_log.cc store_rebuild.h \
+	store_rebuild.cc store_swapin.h store_swapin.cc \
+	store_swapmeta.cc store_swapout.cc StoreFileSystem.cc \
+	StoreIOState.cc tests/stub_StoreMeta.cc StoreMetaUnpacker.cc \
+	StoreSwapLogData.cc tools.h tools.cc Transients.cc \
+	tests/stub_tunnel.cc tests/stub_SwapDir.cc MemStore.cc \
+	unlinkd.h unlinkd.cc url.cc urn.h urn.cc wccp2.h \
 	tests/stub_wccp2.cc whois.h tests/stub_whois.cc \
 	FadingCounter.cc win32.cc wordlist.h wordlist.cc
 am_tests_testCacheManager_OBJECTS = AccessLogEntry.$(OBJEXT) \
@@ -592,7 +595,7 @@
 	tests/stub_CollapsedForwarding.$(OBJEXT) \
 	ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) \
 	CpuAffinityMap.$(OBJEXT) CpuAffinitySet.$(OBJEXT) \
-	$(am__objects_3) disk.$(OBJEXT) dlink.$(OBJEXT) \
+	$(am__objects_3) fs_io.$(OBJEXT) dlink.$(OBJEXT) \
 	$(am__objects_4) errorpage.$(OBJEXT) tests/stub_ETag.$(OBJEXT) \
 	event.$(OBJEXT) external_acl.$(OBJEXT) \
 	ExternalACLEntry.$(OBJEXT) tests/stub_fatal.$(OBJEXT) \
@@ -613,15 +616,15 @@
 	Parsing.$(OBJEXT) pconn.$(OBJEXT) peer_digest.$(OBJEXT) \
 	peer_proxy_negotiate_auth.$(OBJEXT) peer_select.$(OBJEXT) \
 	peer_sourcehash.$(OBJEXT) peer_userhash.$(OBJEXT) \
-	PeerPoolMgr.$(OBJEXT) tests/stub_redirect.$(OBJEXT) \
-	refresh.$(OBJEXT) RemovalPolicy.$(OBJEXT) $(am__objects_9) \
-	SBufAlgos.$(OBJEXT) tests/stub_SBufDetailedStats.$(OBJEXT) \
-	$(am__objects_11) SquidMath.$(OBJEXT) stat.$(OBJEXT) \
-	StatCounters.$(OBJEXT) StrList.$(OBJEXT) \
-	tests/stub_libauth_acls.$(OBJEXT) tests/stub_libauth.$(OBJEXT) \
-	tests/stub_libdiskio.$(OBJEXT) tests/stub_StatHist.$(OBJEXT) \
-	stmem.$(OBJEXT) store.$(OBJEXT) store_client.$(OBJEXT) \
-	tests/stub_store_digest.$(OBJEXT) store_dir.$(OBJEXT) \
+	PeerPoolMgr.$(OBJEXT) Pipeline.$(OBJEXT) \
+	tests/stub_redirect.$(OBJEXT) refresh.$(OBJEXT) \
+	RemovalPolicy.$(OBJEXT) $(am__objects_9) SBufAlgos.$(OBJEXT) \
+	tests/stub_SBufDetailedStats.$(OBJEXT) $(am__objects_11) \
+	SquidMath.$(OBJEXT) stat.$(OBJEXT) StatCounters.$(OBJEXT) \
+	StrList.$(OBJEXT) tests/stub_libauth_acls.$(OBJEXT) \
+	tests/stub_libauth.$(OBJEXT) tests/stub_libdiskio.$(OBJEXT) \
+	tests/stub_StatHist.$(OBJEXT) stmem.$(OBJEXT) store.$(OBJEXT) \
+	store_client.$(OBJEXT) tests/stub_store_digest.$(OBJEXT) \
 	store_io.$(OBJEXT) store_key_md5.$(OBJEXT) store_log.$(OBJEXT) \
 	store_rebuild.$(OBJEXT) store_swapin.$(OBJEXT) \
 	store_swapmeta.$(OBJEXT) store_swapout.$(OBJEXT) \
@@ -678,26 +681,26 @@
 	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.h disk.cc \
+	ClientDelayConfig.cc ClientDelayConfig.h fs_io.h fs_io.cc \
 	tests/stub_ETag.cc EventLoop.cc event.cc fatal.h \
 	tests/stub_fatal.cc fd.h fd.cc fde.h fde.cc FileMap.h \
-	filemap.cc fs/forward.h HttpBody.h HttpBody.cc \
-	HttpHeaderFieldStat.h HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci \
-	HttpHdrContRange.cc HttpHdrSc.cc HttpHdrScTarget.cc \
-	HttpHdrRange.cc HttpHeaderFieldInfo.h HttpHeaderTools.h \
-	HttpHeaderTools.cc HttpHeader.h HttpHeader.cc HttpMsg.cc \
-	HttpReply.cc int.h int.cc SquidList.h SquidList.cc \
-	MasterXaction.cc MasterXaction.h MemBuf.cc MemObject.cc \
-	mem_node.cc Notes.h Notes.cc Parsing.cc refresh.h refresh.cc \
-	RemovalPolicy.cc RequestFlags.h RequestFlags.cc \
-	tests/stub_libsecurity.cc StatCounters.h StatCounters.cc \
-	StatHist.h tests/stub_StatHist.cc stmem.cc base/CharacterSet.h \
+	filemap.cc HttpBody.h HttpBody.cc HttpHeaderFieldStat.h \
+	HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci HttpHdrContRange.cc \
+	HttpHdrSc.cc HttpHdrScTarget.cc HttpHdrRange.cc \
+	HttpHeaderFieldInfo.h HttpHeaderTools.h HttpHeaderTools.cc \
+	HttpHeader.h HttpHeader.cc HttpMsg.cc HttpReply.cc int.h \
+	int.cc SquidList.h SquidList.cc MasterXaction.cc \
+	MasterXaction.h MemBuf.cc MemObject.cc mem_node.cc Notes.h \
+	Notes.cc Parsing.cc refresh.h refresh.cc RemovalPolicy.cc \
+	RequestFlags.h RequestFlags.cc tests/stub_libsecurity.cc \
+	StatCounters.h StatCounters.cc StatHist.h \
+	tests/stub_StatHist.cc stmem.cc base/CharacterSet.h \
 	base/InstanceId.h MemBlob.h MemBlob.cc OutOfBoundsException.h \
 	SBuf.h SBuf.cc SBufExceptions.h SBufExceptions.cc SBufAlgos.h \
 	SBufAlgos.cc SBufDetailedStats.h \
 	tests/stub_SBufDetailedStats.cc StoreFileSystem.cc \
 	StoreIOState.cc tests/stub_StoreMeta.cc StoreMetaUnpacker.cc \
-	StoreSwapLogData.cc store_dir.cc store_io.cc store_key_md5.h \
+	StoreSwapLogData.cc store_io.cc store_key_md5.h \
 	store_key_md5.cc store_swapout.cc store_swapmeta.cc \
 	repl_modules.h store.cc String.cc StrList.h StrList.cc \
 	tests/stub_SwapDir.cc Transients.cc log/access_log.h \
@@ -723,7 +726,7 @@
 am_tests_testDiskIO_OBJECTS = tests/stub_CacheDigest.$(OBJEXT) \
 	cbdata.$(OBJEXT) tests/stub_CollapsedForwarding.$(OBJEXT) \
 	ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) $(am__objects_3) \
-	disk.$(OBJEXT) tests/stub_ETag.$(OBJEXT) EventLoop.$(OBJEXT) \
+	fs_io.$(OBJEXT) tests/stub_ETag.$(OBJEXT) EventLoop.$(OBJEXT) \
 	event.$(OBJEXT) tests/stub_fatal.$(OBJEXT) fd.$(OBJEXT) \
 	fde.$(OBJEXT) filemap.$(OBJEXT) HttpBody.$(OBJEXT) \
 	HttpHdrCc.$(OBJEXT) HttpHdrContRange.$(OBJEXT) \
@@ -739,13 +742,12 @@
 	SBufAlgos.$(OBJEXT) tests/stub_SBufDetailedStats.$(OBJEXT) \
 	StoreFileSystem.$(OBJEXT) StoreIOState.$(OBJEXT) \
 	tests/stub_StoreMeta.$(OBJEXT) StoreMetaUnpacker.$(OBJEXT) \
-	StoreSwapLogData.$(OBJEXT) store_dir.$(OBJEXT) \
-	store_io.$(OBJEXT) store_key_md5.$(OBJEXT) \
-	store_swapout.$(OBJEXT) store_swapmeta.$(OBJEXT) \
-	store.$(OBJEXT) String.$(OBJEXT) StrList.$(OBJEXT) \
-	tests/stub_SwapDir.$(OBJEXT) Transients.$(OBJEXT) \
-	tests/stub_access_log.$(OBJEXT) tests/stub_acl.$(OBJEXT) \
-	tests/stub_cache_cf.$(OBJEXT) \
+	StoreSwapLogData.$(OBJEXT) store_io.$(OBJEXT) \
+	store_key_md5.$(OBJEXT) store_swapout.$(OBJEXT) \
+	store_swapmeta.$(OBJEXT) store.$(OBJEXT) String.$(OBJEXT) \
+	StrList.$(OBJEXT) tests/stub_SwapDir.$(OBJEXT) \
+	Transients.$(OBJEXT) tests/stub_access_log.$(OBJEXT) \
+	tests/stub_acl.$(OBJEXT) tests/stub_cache_cf.$(OBJEXT) \
 	tests/stub_cache_manager.$(OBJEXT) \
 	tests/stub_client_db.$(OBJEXT) \
 	tests/stub_client_side_request.$(OBJEXT) \
@@ -814,45 +816,46 @@
 	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.h disk.cc dlink.h dlink.cc \
+	ClientDelayConfig.h fs_io.h fs_io.cc dlink.h dlink.cc \
 	dns_internal.cc errorpage.cc tests/stub_ETag.cc event.cc \
 	EventLoop.h EventLoop.cc external_acl.cc ExternalACLEntry.cc \
 	FadingCounter.cc fatal.h tests/stub_fatal.cc fd.h fd.cc fde.cc \
-	FileMap.h filemap.cc fqdncache.h fqdncache.cc fs/forward.h \
-	FwdState.cc FwdState.h gopher.h gopher.cc helper.cc \
-	hier_code.h htcp.cc htcp.h http.cc HttpBody.h HttpBody.cc \
-	HttpHeader.h HttpHeader.cc HttpHeaderFieldInfo.h \
-	HttpHeaderTools.h HttpHeaderTools.cc HttpHeaderFieldStat.h \
-	HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci HttpHdrContRange.cc \
-	HttpHdrRange.cc HttpHdrSc.cc HttpHdrScTarget.cc HttpMsg.cc \
-	HttpReply.cc PeerPoolMgr.h PeerPoolMgr.cc RequestFlags.h \
-	RequestFlags.cc HttpRequest.cc icp_v2.cc icp_v3.cc SquidIpc.h \
-	ipc.cc ipc_win32.cc ipcache.cc int.h int.cc internal.h \
-	internal.cc LogTags.cc tests/stub_libsecurity.cc SquidList.h \
-	SquidList.cc MasterXaction.cc MasterXaction.h \
-	tests/stub_libmem.cc mem_node.cc MemBuf.cc MemObject.cc mime.h \
-	mime.cc mime_header.h mime_header.cc multicast.h multicast.cc \
+	FileMap.h filemap.cc fqdncache.h fqdncache.cc FwdState.cc \
+	FwdState.h gopher.h gopher.cc helper.cc hier_code.h htcp.cc \
+	htcp.h http.cc HttpBody.h HttpBody.cc HttpHeader.h \
+	HttpHeader.cc HttpHeaderFieldInfo.h HttpHeaderTools.h \
+	HttpHeaderTools.cc HttpHeaderFieldStat.h HttpHdrCc.h \
+	HttpHdrCc.cc HttpHdrCc.cci HttpHdrContRange.cc HttpHdrRange.cc \
+	HttpHdrSc.cc HttpHdrScTarget.cc HttpMsg.cc HttpReply.cc \
+	PeerPoolMgr.h PeerPoolMgr.cc RequestFlags.h RequestFlags.cc \
+	HttpRequest.cc icp_v2.cc icp_v3.cc SquidIpc.h ipc.cc \
+	ipc_win32.cc ipcache.cc int.h int.cc internal.h internal.cc \
+	LogTags.cc tests/stub_libsecurity.cc SquidList.h SquidList.cc \
+	MasterXaction.cc MasterXaction.h tests/stub_libmem.cc \
+	mem_node.cc MemBuf.cc MemObject.cc mime.h mime.cc \
+	mime_header.h mime_header.cc multicast.h multicast.cc \
 	neighbors.h neighbors.cc Notes.cc Notes.h Parsing.cc pconn.cc \
 	peer_digest.cc peer_proxy_negotiate_auth.h \
 	peer_proxy_negotiate_auth.cc peer_select.cc peer_sourcehash.h \
-	peer_sourcehash.cc peer_userhash.h peer_userhash.cc redirect.h \
-	tests/stub_redirect.cc refresh.h refresh.cc RemovalPolicy.cc \
-	StrList.h StrList.cc base/CharacterSet.h base/InstanceId.h \
-	MemBlob.h MemBlob.cc OutOfBoundsException.h SBuf.h SBuf.cc \
-	SBufExceptions.h SBufExceptions.cc SBufAlgos.h SBufAlgos.cc \
-	SBufDetailedStats.h tests/stub_SBufDetailedStats.cc \
-	SnmpRequest.h snmp_core.h snmp_core.cc snmp_agent.h \
-	snmp_agent.cc SquidMath.cc SquidMath.h IoStats.h stat.h \
-	stat.cc StatCounters.h StatCounters.cc StatHist.h StatHist.cc \
-	stmem.cc repl_modules.h store.cc store_client.cc \
-	store_digest.h tests/stub_store_digest.cc store_dir.cc \
-	store_io.cc store_key_md5.h store_key_md5.cc store_log.h \
-	store_log.cc store_rebuild.h store_rebuild.cc store_swapin.h \
-	store_swapin.cc store_swapmeta.cc store_swapout.cc \
-	StoreFileSystem.cc StoreIOState.cc tests/stub_StoreMeta.cc \
-	StoreMetaUnpacker.cc StoreSwapLogData.cc String.cc \
-	tests/stub_SwapDir.cc tests/CapturingStoreEntry.h \
-	tests/testEvent.cc tests/testEvent.h tests/stub_main_cc.cc \
+	peer_sourcehash.cc peer_userhash.h peer_userhash.cc \
+	Pipeline.cc Pipeline.h redirect.h tests/stub_redirect.cc \
+	refresh.h refresh.cc RemovalPolicy.cc StrList.h StrList.cc \
+	base/CharacterSet.h base/InstanceId.h MemBlob.h MemBlob.cc \
+	OutOfBoundsException.h SBuf.h SBuf.cc SBufExceptions.h \
+	SBufExceptions.cc SBufAlgos.h SBufAlgos.cc SBufDetailedStats.h \
+	tests/stub_SBufDetailedStats.cc SnmpRequest.h snmp_core.h \
+	snmp_core.cc snmp_agent.h snmp_agent.cc SquidMath.cc \
+	SquidMath.h IoStats.h stat.h stat.cc StatCounters.h \
+	StatCounters.cc StatHist.h StatHist.cc stmem.cc repl_modules.h \
+	store.cc store_client.cc store_digest.h \
+	tests/stub_store_digest.cc store_io.cc store_key_md5.h \
+	store_key_md5.cc store_log.h store_log.cc store_rebuild.h \
+	store_rebuild.cc store_swapin.h store_swapin.cc \
+	store_swapmeta.cc store_swapout.cc StoreFileSystem.cc \
+	StoreIOState.cc tests/stub_StoreMeta.cc StoreMetaUnpacker.cc \
+	StoreSwapLogData.cc String.cc tests/stub_SwapDir.cc \
+	tests/CapturingStoreEntry.h tests/testEvent.cc \
+	tests/testEvent.h tests/stub_main_cc.cc \
 	tests/stub_ipc_Forwarder.cc tests/stub_libauth_acls.cc \
 	tests/stub_libauth.cc tests/stub_libdiskio.cc \
 	tests/stub_libeui.cc tests/stub_store_stats.cc time.cc tools.h \
@@ -870,7 +873,7 @@
 	tests/stub_CollapsedForwarding.$(OBJEXT) \
 	ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) \
 	CpuAffinityMap.$(OBJEXT) CpuAffinitySet.$(OBJEXT) \
-	debug.$(OBJEXT) $(am__objects_3) disk.$(OBJEXT) \
+	debug.$(OBJEXT) $(am__objects_3) fs_io.$(OBJEXT) \
 	dlink.$(OBJEXT) $(am__objects_4) errorpage.$(OBJEXT) \
 	tests/stub_ETag.$(OBJEXT) event.$(OBJEXT) EventLoop.$(OBJEXT) \
 	external_acl.$(OBJEXT) ExternalACLEntry.$(OBJEXT) \
@@ -894,13 +897,13 @@
 	pconn.$(OBJEXT) peer_digest.$(OBJEXT) \
 	peer_proxy_negotiate_auth.$(OBJEXT) peer_select.$(OBJEXT) \
 	peer_sourcehash.$(OBJEXT) peer_userhash.$(OBJEXT) \
-	tests/stub_redirect.$(OBJEXT) refresh.$(OBJEXT) \
-	RemovalPolicy.$(OBJEXT) StrList.$(OBJEXT) $(am__objects_9) \
-	SBufAlgos.$(OBJEXT) tests/stub_SBufDetailedStats.$(OBJEXT) \
-	$(am__objects_11) SquidMath.$(OBJEXT) stat.$(OBJEXT) \
-	StatCounters.$(OBJEXT) StatHist.$(OBJEXT) stmem.$(OBJEXT) \
-	store.$(OBJEXT) store_client.$(OBJEXT) \
-	tests/stub_store_digest.$(OBJEXT) store_dir.$(OBJEXT) \
+	Pipeline.$(OBJEXT) tests/stub_redirect.$(OBJEXT) \
+	refresh.$(OBJEXT) RemovalPolicy.$(OBJEXT) StrList.$(OBJEXT) \
+	$(am__objects_9) SBufAlgos.$(OBJEXT) \
+	tests/stub_SBufDetailedStats.$(OBJEXT) $(am__objects_11) \
+	SquidMath.$(OBJEXT) stat.$(OBJEXT) StatCounters.$(OBJEXT) \
+	StatHist.$(OBJEXT) stmem.$(OBJEXT) store.$(OBJEXT) \
+	store_client.$(OBJEXT) tests/stub_store_digest.$(OBJEXT) \
 	store_io.$(OBJEXT) store_key_md5.$(OBJEXT) store_log.$(OBJEXT) \
 	store_rebuild.$(OBJEXT) store_swapin.$(OBJEXT) \
 	store_swapmeta.$(OBJEXT) store_swapout.$(OBJEXT) \
@@ -940,14 +943,14 @@
 	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.h disk.cc \
+	ClientDelayConfig.cc ClientDelayConfig.h fs_io.h fs_io.cc \
 	dlink.h dlink.cc dns_internal.cc errorpage.cc \
 	tests/stub_ETag.cc EventLoop.h EventLoop.cc event.cc \
 	external_acl.cc ExternalACLEntry.cc FadingCounter.cc fatal.h \
 	tests/stub_fatal.cc fd.h fd.cc fde.cc FileMap.h filemap.cc \
-	fqdncache.h fqdncache.cc fs/forward.h FwdState.cc FwdState.h \
-	gopher.h gopher.cc helper.cc hier_code.h htcp.cc htcp.h \
-	http.cc HttpBody.h HttpBody.cc HttpHeader.h HttpHeader.cc \
+	fqdncache.h fqdncache.cc FwdState.cc FwdState.h gopher.h \
+	gopher.cc helper.cc hier_code.h htcp.cc htcp.h http.cc \
+	HttpBody.h HttpBody.cc HttpHeader.h HttpHeader.cc \
 	HttpHeaderFieldInfo.h HttpHeaderTools.h HttpHeaderTools.cc \
 	HttpHeaderFieldStat.h HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci \
 	HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \
@@ -962,22 +965,23 @@
 	peer_digest.cc peer_proxy_negotiate_auth.h \
 	peer_proxy_negotiate_auth.cc peer_select.cc peer_sourcehash.h \
 	peer_sourcehash.cc peer_userhash.h peer_userhash.cc \
-	RemovalPolicy.cc redirect.h tests/stub_redirect.cc refresh.h \
-	refresh.cc base/CharacterSet.h base/InstanceId.h MemBlob.h \
-	MemBlob.cc OutOfBoundsException.h SBuf.h SBuf.cc \
-	SBufExceptions.h SBufExceptions.cc SBufAlgos.h SBufAlgos.cc \
-	SBufDetailedStats.h tests/stub_SBufDetailedStats.cc \
-	SnmpRequest.h snmp_core.h snmp_core.cc snmp_agent.h \
-	snmp_agent.cc SquidMath.h SquidMath.cc IoStats.h stat.h \
-	stat.cc StatCounters.h StatCounters.cc StatHist.h StatHist.cc \
-	stmem.cc repl_modules.h store.cc store_client.cc \
-	store_digest.h tests/stub_store_digest.cc store_dir.cc \
-	store_io.cc store_key_md5.h store_key_md5.cc store_log.h \
-	store_log.cc store_rebuild.h store_rebuild.cc store_swapin.h \
-	store_swapin.cc store_swapmeta.cc store_swapout.cc \
-	StoreFileSystem.cc StoreIOState.cc tests/stub_StoreMeta.cc \
-	StoreMetaUnpacker.cc StoreSwapLogData.cc String.cc StrList.h \
-	StrList.cc tests/stub_SwapDir.cc tests/testEventLoop.cc \
+	Pipeline.cc Pipeline.h RemovalPolicy.cc redirect.h \
+	tests/stub_redirect.cc refresh.h refresh.cc \
+	base/CharacterSet.h base/InstanceId.h MemBlob.h MemBlob.cc \
+	OutOfBoundsException.h SBuf.h SBuf.cc SBufExceptions.h \
+	SBufExceptions.cc SBufAlgos.h SBufAlgos.cc SBufDetailedStats.h \
+	tests/stub_SBufDetailedStats.cc SnmpRequest.h snmp_core.h \
+	snmp_core.cc snmp_agent.h snmp_agent.cc SquidMath.h \
+	SquidMath.cc IoStats.h stat.h stat.cc StatCounters.h \
+	StatCounters.cc StatHist.h StatHist.cc stmem.cc repl_modules.h \
+	store.cc store_client.cc store_digest.h \
+	tests/stub_store_digest.cc store_io.cc store_key_md5.h \
+	store_key_md5.cc store_log.h store_log.cc store_rebuild.h \
+	store_rebuild.cc store_swapin.h store_swapin.cc \
+	store_swapmeta.cc store_swapout.cc StoreFileSystem.cc \
+	StoreIOState.cc tests/stub_StoreMeta.cc StoreMetaUnpacker.cc \
+	StoreSwapLogData.cc String.cc StrList.h StrList.cc \
+	tests/stub_SwapDir.cc tests/testEventLoop.cc \
 	tests/testEventLoop.h tests/stub_main_cc.cc \
 	tests/stub_ipc_Forwarder.cc tests/stub_libauth_acls.cc \
 	tests/stub_libauth.cc tests/stub_libdiskio.cc \
@@ -996,7 +1000,7 @@
 	tests/stub_CollapsedForwarding.$(OBJEXT) \
 	ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) \
 	CpuAffinityMap.$(OBJEXT) CpuAffinitySet.$(OBJEXT) \
-	debug.$(OBJEXT) $(am__objects_3) disk.$(OBJEXT) \
+	debug.$(OBJEXT) $(am__objects_3) fs_io.$(OBJEXT) \
 	dlink.$(OBJEXT) $(am__objects_4) errorpage.$(OBJEXT) \
 	tests/stub_ETag.$(OBJEXT) EventLoop.$(OBJEXT) event.$(OBJEXT) \
 	external_acl.$(OBJEXT) ExternalACLEntry.$(OBJEXT) \
@@ -1019,19 +1023,19 @@
 	Parsing.$(OBJEXT) pconn.$(OBJEXT) peer_digest.$(OBJEXT) \
 	peer_proxy_negotiate_auth.$(OBJEXT) peer_select.$(OBJEXT) \
 	peer_sourcehash.$(OBJEXT) peer_userhash.$(OBJEXT) \
-	RemovalPolicy.$(OBJEXT) tests/stub_redirect.$(OBJEXT) \
-	refresh.$(OBJEXT) $(am__objects_9) SBufAlgos.$(OBJEXT) \
+	Pipeline.$(OBJEXT) RemovalPolicy.$(OBJEXT) \
+	tests/stub_redirect.$(OBJEXT) refresh.$(OBJEXT) \
+	$(am__objects_9) SBufAlgos.$(OBJEXT) \
 	tests/stub_SBufDetailedStats.$(OBJEXT) $(am__objects_11) \
 	SquidMath.$(OBJEXT) stat.$(OBJEXT) StatCounters.$(OBJEXT) \
 	StatHist.$(OBJEXT) stmem.$(OBJEXT) store.$(OBJEXT) \
 	store_client.$(OBJEXT) tests/stub_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) tests/stub_StoreMeta.$(OBJEXT) \
-	StoreMetaUnpacker.$(OBJEXT) StoreSwapLogData.$(OBJEXT) \
-	String.$(OBJEXT) StrList.$(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) \
+	tests/stub_StoreMeta.$(OBJEXT) StoreMetaUnpacker.$(OBJEXT) \
+	StoreSwapLogData.$(OBJEXT) String.$(OBJEXT) StrList.$(OBJEXT) \
 	tests/stub_SwapDir.$(OBJEXT) tests/testEventLoop.$(OBJEXT) \
 	tests/stub_main_cc.$(OBJEXT) \
 	tests/stub_ipc_Forwarder.$(OBJEXT) \
@@ -1126,13 +1130,13 @@
 	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.h disk.cc dlink.h dlink.cc \
+	ClientDelayConfig.h fs_io.h fs_io.cc dlink.h dlink.cc \
 	dns_internal.cc errorpage.cc tests/stub_ETag.cc \
 	external_acl.cc ExternalACLEntry.cc fatal.h \
 	tests/stub_fatal.cc fd.h fd.cc fde.cc fqdncache.h fqdncache.cc \
-	fs/forward.h FwdState.cc FwdState.h gopher.h gopher.cc \
-	helper.cc hier_code.h htcp.cc htcp.h http.cc HttpBody.h \
-	HttpBody.cc HttpHeader.h HttpHeader.cc HttpHeaderFieldInfo.h \
+	FwdState.cc FwdState.h gopher.h gopher.cc helper.cc \
+	hier_code.h htcp.cc htcp.h http.cc HttpBody.h HttpBody.cc \
+	HttpHeader.h HttpHeader.cc HttpHeaderFieldInfo.h \
 	HttpHeaderTools.h HttpHeaderTools.cc HttpHeaderFieldStat.h \
 	HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci HttpHdrContRange.cc \
 	HttpHdrRange.cc HttpHdrSc.cc HttpHdrScTarget.cc HttpMsg.cc \
@@ -1146,23 +1150,23 @@
 	peer_proxy_negotiate_auth.h peer_proxy_negotiate_auth.cc \
 	peer_select.cc peer_sourcehash.h peer_sourcehash.cc \
 	peer_userhash.h peer_userhash.cc PeerPoolMgr.h PeerPoolMgr.cc \
-	redirect.h tests/stub_libauth_acls.cc tests/stub_redirect.cc \
-	refresh.h refresh.cc RemovalPolicy.cc base/CharacterSet.h \
-	base/InstanceId.h MemBlob.h MemBlob.cc OutOfBoundsException.h \
-	SBuf.h SBuf.cc SBufExceptions.h SBufExceptions.cc SBufAlgos.h \
-	SBufAlgos.cc SBufDetailedStats.h \
+	Pipeline.cc Pipeline.h redirect.h tests/stub_libauth_acls.cc \
+	tests/stub_redirect.cc refresh.h refresh.cc RemovalPolicy.cc \
+	base/CharacterSet.h base/InstanceId.h MemBlob.h MemBlob.cc \
+	OutOfBoundsException.h SBuf.h SBuf.cc SBufExceptions.h \
+	SBufExceptions.cc SBufAlgos.h SBufAlgos.cc SBufDetailedStats.h \
 	tests/stub_SBufDetailedStats.cc SnmpRequest.h snmp_core.h \
 	snmp_core.cc snmp_agent.h snmp_agent.cc SquidMath.h \
 	SquidMath.cc IoStats.h stat.h stat.cc StatCounters.h \
 	StatCounters.cc StatHist.h StatHist.cc stmem.cc repl_modules.h \
 	store.cc store_client.cc store_digest.h \
-	tests/stub_store_digest.cc store_dir.cc store_io.cc \
-	store_key_md5.h store_key_md5.cc store_log.h store_log.cc \
-	store_rebuild.h store_rebuild.cc store_swapin.h \
-	store_swapin.cc store_swapmeta.cc store_swapout.cc \
-	StoreFileSystem.cc StoreIOState.cc tests/stub_StoreMeta.cc \
-	StoreMetaUnpacker.cc StoreSwapLogData.cc StrList.h StrList.cc \
-	event.cc tools.h tools.cc Transients.cc tests/stub_tunnel.cc \
+	tests/stub_store_digest.cc store_io.cc store_key_md5.h \
+	store_key_md5.cc store_log.h store_log.cc store_rebuild.h \
+	store_rebuild.cc store_swapin.h store_swapin.cc \
+	store_swapmeta.cc store_swapout.cc StoreFileSystem.cc \
+	StoreIOState.cc tests/stub_StoreMeta.cc StoreMetaUnpacker.cc \
+	StoreSwapLogData.cc StrList.h StrList.cc event.cc tools.h \
+	tools.cc Transients.cc tests/stub_tunnel.cc \
 	tests/stub_SwapDir.cc MemStore.cc url.cc urn.h urn.cc wccp2.h \
 	tests/stub_wccp2.cc whois.h tests/stub_whois.cc \
 	FadingCounter.cc win32.cc wordlist.h wordlist.cc
@@ -1185,7 +1189,7 @@
 	tests/stub_CollapsedForwarding.$(OBJEXT) \
 	ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) \
 	CpuAffinityMap.$(OBJEXT) CpuAffinitySet.$(OBJEXT) \
-	$(am__objects_3) disk.$(OBJEXT) dlink.$(OBJEXT) \
+	$(am__objects_3) fs_io.$(OBJEXT) dlink.$(OBJEXT) \
 	$(am__objects_4) errorpage.$(OBJEXT) tests/stub_ETag.$(OBJEXT) \
 	external_acl.$(OBJEXT) ExternalACLEntry.$(OBJEXT) \
 	tests/stub_fatal.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) \
@@ -1205,25 +1209,25 @@
 	Parsing.$(OBJEXT) pconn.$(OBJEXT) peer_digest.$(OBJEXT) \
 	peer_proxy_negotiate_auth.$(OBJEXT) peer_select.$(OBJEXT) \
 	peer_sourcehash.$(OBJEXT) peer_userhash.$(OBJEXT) \
-	PeerPoolMgr.$(OBJEXT) tests/stub_libauth_acls.$(OBJEXT) \
+	PeerPoolMgr.$(OBJEXT) Pipeline.$(OBJEXT) \
+	tests/stub_libauth_acls.$(OBJEXT) \
 	tests/stub_redirect.$(OBJEXT) refresh.$(OBJEXT) \
 	RemovalPolicy.$(OBJEXT) $(am__objects_9) SBufAlgos.$(OBJEXT) \
 	tests/stub_SBufDetailedStats.$(OBJEXT) $(am__objects_11) \
 	SquidMath.$(OBJEXT) stat.$(OBJEXT) StatCounters.$(OBJEXT) \
 	StatHist.$(OBJEXT) stmem.$(OBJEXT) store.$(OBJEXT) \
 	store_client.$(OBJEXT) tests/stub_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) tests/stub_StoreMeta.$(OBJEXT) \
-	StoreMetaUnpacker.$(OBJEXT) StoreSwapLogData.$(OBJEXT) \
-	StrList.$(OBJEXT) event.$(OBJEXT) tools.$(OBJEXT) \
-	Transients.$(OBJEXT) tests/stub_tunnel.$(OBJEXT) \
-	tests/stub_SwapDir.$(OBJEXT) MemStore.$(OBJEXT) url.$(OBJEXT) \
-	urn.$(OBJEXT) tests/stub_wccp2.$(OBJEXT) \
-	tests/stub_whois.$(OBJEXT) FadingCounter.$(OBJEXT) \
-	$(am__objects_14) wordlist.$(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) \
+	tests/stub_StoreMeta.$(OBJEXT) StoreMetaUnpacker.$(OBJEXT) \
+	StoreSwapLogData.$(OBJEXT) StrList.$(OBJEXT) event.$(OBJEXT) \
+	tools.$(OBJEXT) Transients.$(OBJEXT) \
+	tests/stub_tunnel.$(OBJEXT) tests/stub_SwapDir.$(OBJEXT) \
+	MemStore.$(OBJEXT) url.$(OBJEXT) urn.$(OBJEXT) \
+	tests/stub_wccp2.$(OBJEXT) tests/stub_whois.$(OBJEXT) \
+	FadingCounter.$(OBJEXT) $(am__objects_14) wordlist.$(OBJEXT)
 nodist_tests_testHttpRequest_OBJECTS = $(am__objects_18)
 tests_testHttpRequest_OBJECTS = $(am_tests_testHttpRequest_OBJECTS) \
 	$(nodist_tests_testHttpRequest_OBJECTS)
@@ -1269,8 +1273,8 @@
 am__tests_testRock_SOURCES_DIST = cbdata.cc CacheDigest.h \
 	CollapsedForwarding.h CollapsedForwarding.cc \
 	tests/stub_CacheDigest.cc ConfigOption.cc ConfigParser.cc \
-	disk.h disk.cc ETag.cc EventLoop.cc event.cc fatal.h fatal.cc \
-	fd.h fd.cc fde.h fde.cc FileMap.h filemap.cc fs/forward.h \
+	fs_io.h fs_io.cc ETag.cc EventLoop.cc event.cc fatal.h \
+	fatal.cc fd.h fd.cc fde.h fde.cc FileMap.h filemap.cc \
 	HttpHeaderFieldStat.h HttpBody.h HttpBody.cc HttpHdrCc.cc \
 	HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \
 	HttpHdrScTarget.cc HttpHeader.h HttpHeader.cc \
@@ -1285,13 +1289,13 @@
 	StoreMetaMD5.h StoreMetaSTD.cc StoreMetaSTD.h \
 	StoreMetaSTDLFS.cc StoreMetaSTDLFS.h StoreMetaObjSize.h \
 	StoreMetaURL.cc StoreMetaURL.h StoreMetaVary.cc \
-	StoreMetaVary.h StoreSwapLogData.cc store_dir.cc store_io.cc \
+	StoreMetaVary.h StoreSwapLogData.cc store_io.cc \
 	store_key_md5.h store_key_md5.cc store_swapmeta.cc \
 	store_swapout.cc base/CharacterSet.h base/InstanceId.h \
 	MemBlob.h MemBlob.cc OutOfBoundsException.h SBuf.h SBuf.cc \
 	SBufExceptions.h SBufExceptions.cc SBufAlgos.h SBufAlgos.cc \
 	SBufDetailedStats.h tests/stub_SBufDetailedStats.cc String.cc \
-	StrList.h StrList.cc SwapDir.cc Transients.h Transients.cc \
+	StrList.h StrList.cc Transients.h Transients.cc \
 	tests/testRock.cc tests/testRock.h tests/testStoreSupport.cc \
 	tests/testStoreSupport.h log/access_log.h \
 	tests/stub_access_log.cc cache_cf.h YesNoNone.h \
@@ -1317,7 +1321,7 @@
 	ClientDelayConfig.cc ClientDelayConfig.h unlinkd.h unlinkd.cc
 am_tests_testRock_OBJECTS = cbdata.$(OBJEXT) \
 	CollapsedForwarding.$(OBJEXT) tests/stub_CacheDigest.$(OBJEXT) \
-	ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) disk.$(OBJEXT) \
+	ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) fs_io.$(OBJEXT) \
 	ETag.$(OBJEXT) EventLoop.$(OBJEXT) event.$(OBJEXT) \
 	fatal.$(OBJEXT) fd.$(OBJEXT) fde.$(OBJEXT) filemap.$(OBJEXT) \
 	HttpBody.$(OBJEXT) HttpHdrCc.$(OBJEXT) \
@@ -1333,12 +1337,11 @@
 	tests/stub_stat.$(OBJEXT) store.$(OBJEXT) \
 	StoreFileSystem.$(OBJEXT) StoreIOState.$(OBJEXT) \
 	StoreMetaUnpacker.$(OBJEXT) $(am__objects_12) \
-	StoreSwapLogData.$(OBJEXT) store_dir.$(OBJEXT) \
-	store_io.$(OBJEXT) store_key_md5.$(OBJEXT) \
-	store_swapmeta.$(OBJEXT) store_swapout.$(OBJEXT) \
-	$(am__objects_9) SBufAlgos.$(OBJEXT) \
+	StoreSwapLogData.$(OBJEXT) store_io.$(OBJEXT) \
+	store_key_md5.$(OBJEXT) store_swapmeta.$(OBJEXT) \
+	store_swapout.$(OBJEXT) $(am__objects_9) SBufAlgos.$(OBJEXT) \
 	tests/stub_SBufDetailedStats.$(OBJEXT) String.$(OBJEXT) \
-	StrList.$(OBJEXT) SwapDir.$(OBJEXT) Transients.$(OBJEXT) \
+	StrList.$(OBJEXT) Transients.$(OBJEXT) \
 	tests/testRock.$(OBJEXT) tests/testStoreSupport.$(OBJEXT) \
 	tests/stub_access_log.$(OBJEXT) tests/stub_cache_cf.$(OBJEXT) \
 	tests/stub_cache_manager.$(OBJEXT) \
@@ -1434,26 +1437,25 @@
 	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.h disk.cc \
+	ClientDelayConfig.cc ClientDelayConfig.h fs_io.h fs_io.cc \
 	ETag.cc event.cc EventLoop.cc fatal.h tests/stub_fatal.cc \
-	FileMap.h filemap.cc fs/forward.h HttpHeaderFieldStat.h \
-	HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci HttpHdrContRange.cc \
-	HttpHdrRange.cc HttpHdrSc.cc HttpHdrScTarget.cc \
-	HttpHeaderFieldInfo.h HttpHeaderTools.h HttpHeaderTools.cc \
-	HttpHeader.h HttpHeader.cc HttpMsg.cc RequestFlags.cc \
-	RequestFlags.h int.h int.cc SquidList.h SquidList.cc \
-	MasterXaction.cc MasterXaction.h mem_node.cc MemBuf.cc \
-	MemObject.cc Notes.h Notes.cc Parsing.cc RemovalPolicy.cc \
-	refresh.h refresh.cc StatCounters.h StatCounters.cc StatHist.h \
-	StatHist.cc stmem.cc repl_modules.h store.cc store_dir.cc \
-	store_io.cc store_swapout.cc StoreIOState.cc \
-	tests/stub_StoreMeta.cc StoreMetaUnpacker.cc \
+	FileMap.h filemap.cc HttpHeaderFieldStat.h HttpHdrCc.h \
+	HttpHdrCc.cc HttpHdrCc.cci HttpHdrContRange.cc HttpHdrRange.cc \
+	HttpHdrSc.cc HttpHdrScTarget.cc HttpHeaderFieldInfo.h \
+	HttpHeaderTools.h HttpHeaderTools.cc HttpHeader.h \
+	HttpHeader.cc HttpMsg.cc RequestFlags.cc RequestFlags.h int.h \
+	int.cc SquidList.h SquidList.cc MasterXaction.cc \
+	MasterXaction.h mem_node.cc MemBuf.cc MemObject.cc Notes.h \
+	Notes.cc Parsing.cc RemovalPolicy.cc refresh.h refresh.cc \
+	StatCounters.h StatCounters.cc StatHist.h StatHist.cc stmem.cc \
+	repl_modules.h store.cc store_io.cc store_swapout.cc \
+	StoreIOState.cc tests/stub_StoreMeta.cc StoreMetaUnpacker.cc \
 	StoreSwapLogData.cc store_key_md5.h store_key_md5.cc \
 	base/CharacterSet.h base/InstanceId.h MemBlob.h MemBlob.cc \
 	OutOfBoundsException.h SBuf.h SBuf.cc SBufExceptions.h \
 	SBufExceptions.cc SBufAlgos.h SBufAlgos.cc SBufDetailedStats.h \
 	tests/stub_SBufDetailedStats.cc String.cc StrList.h StrList.cc \
-	SwapDir.cc tests/CapturingStoreEntry.h log/access_log.h \
+	tests/CapturingStoreEntry.h log/access_log.h \
 	tests/stub_access_log.cc tests/stub_acl.cc cache_cf.h \
 	YesNoNone.h tests/stub_cache_cf.cc tests/stub_cache_manager.cc \
 	tests/stub_client_side_request.cc tests/stub_comm.cc \
@@ -1480,7 +1482,7 @@
 am_tests_testStore_OBJECTS = tests/stub_CacheDigest.$(OBJEXT) \
 	cbdata.$(OBJEXT) tests/stub_CollapsedForwarding.$(OBJEXT) \
 	ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) $(am__objects_3) \
-	disk.$(OBJEXT) ETag.$(OBJEXT) event.$(OBJEXT) \
+	fs_io.$(OBJEXT) ETag.$(OBJEXT) event.$(OBJEXT) \
 	EventLoop.$(OBJEXT) tests/stub_fatal.$(OBJEXT) \
 	filemap.$(OBJEXT) HttpHdrCc.$(OBJEXT) \
 	HttpHdrContRange.$(OBJEXT) HttpHdrRange.$(OBJEXT) \
@@ -1491,15 +1493,13 @@
 	MemBuf.$(OBJEXT) MemObject.$(OBJEXT) Notes.$(OBJEXT) \
 	Parsing.$(OBJEXT) RemovalPolicy.$(OBJEXT) refresh.$(OBJEXT) \
 	StatCounters.$(OBJEXT) StatHist.$(OBJEXT) stmem.$(OBJEXT) \
-	store.$(OBJEXT) store_dir.$(OBJEXT) store_io.$(OBJEXT) \
-	store_swapout.$(OBJEXT) StoreIOState.$(OBJEXT) \
-	tests/stub_StoreMeta.$(OBJEXT) StoreMetaUnpacker.$(OBJEXT) \
-	StoreSwapLogData.$(OBJEXT) store_key_md5.$(OBJEXT) \
-	$(am__objects_9) SBufAlgos.$(OBJEXT) \
+	store.$(OBJEXT) store_io.$(OBJEXT) store_swapout.$(OBJEXT) \
+	StoreIOState.$(OBJEXT) tests/stub_StoreMeta.$(OBJEXT) \
+	StoreMetaUnpacker.$(OBJEXT) StoreSwapLogData.$(OBJEXT) \
+	store_key_md5.$(OBJEXT) $(am__objects_9) SBufAlgos.$(OBJEXT) \
 	tests/stub_SBufDetailedStats.$(OBJEXT) String.$(OBJEXT) \
-	StrList.$(OBJEXT) SwapDir.$(OBJEXT) \
-	tests/stub_access_log.$(OBJEXT) tests/stub_acl.$(OBJEXT) \
-	tests/stub_cache_cf.$(OBJEXT) \
+	StrList.$(OBJEXT) tests/stub_access_log.$(OBJEXT) \
+	tests/stub_acl.$(OBJEXT) tests/stub_cache_cf.$(OBJEXT) \
 	tests/stub_cache_manager.$(OBJEXT) \
 	tests/stub_client_side_request.$(OBJEXT) \
 	tests/stub_comm.$(OBJEXT) tests/stub_debug.$(OBJEXT) \
@@ -1579,14 +1579,14 @@
 	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.h disk.cc dlink.h dlink.cc \
+	ClientDelayConfig.h fs_io.h fs_io.cc dlink.h dlink.cc \
 	dns_internal.cc errorpage.cc ETag.cc event.cc external_acl.cc \
 	ExternalACLEntry.cc fatal.h tests/stub_fatal.cc fd.h fd.cc \
 	fde.cc FileMap.h filemap.cc fqdncache.h fqdncache.cc \
-	fs/forward.h FwdState.cc FwdState.h gopher.h gopher.cc \
-	helper.cc hier_code.h htcp.cc htcp.h http.cc HttpBody.h \
-	HttpBody.cc HttpHeaderFieldStat.h HttpHdrCc.h HttpHdrCc.cc \
-	HttpHdrCc.cci HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \
+	FwdState.cc FwdState.h gopher.h gopher.cc helper.cc \
+	hier_code.h htcp.cc htcp.h http.cc HttpBody.h HttpBody.cc \
+	HttpHeaderFieldStat.h HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci \
+	HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \
 	HttpHdrScTarget.cc HttpHeader.h HttpHeader.cc \
 	HttpHeaderFieldInfo.h HttpHeaderTools.h HttpHeaderTools.cc \
 	HttpMsg.cc HttpReply.cc PeerPoolMgr.h PeerPoolMgr.cc \
@@ -1599,23 +1599,24 @@
 	neighbors.cc Notes.h Notes.cc Parsing.cc pconn.cc \
 	peer_digest.cc peer_proxy_negotiate_auth.h \
 	peer_proxy_negotiate_auth.cc peer_select.cc peer_sourcehash.h \
-	peer_sourcehash.cc peer_userhash.h peer_userhash.cc redirect.h \
-	tests/stub_redirect.cc refresh.h refresh.cc RemovalPolicy.cc \
-	base/CharacterSet.h base/InstanceId.h MemBlob.h MemBlob.cc \
-	OutOfBoundsException.h SBuf.h SBuf.cc SBufExceptions.h \
-	SBufExceptions.cc SBufAlgos.h SBufAlgos.cc SBufDetailedStats.h \
+	peer_sourcehash.cc peer_userhash.h peer_userhash.cc \
+	Pipeline.cc Pipeline.h redirect.h tests/stub_redirect.cc \
+	refresh.h refresh.cc RemovalPolicy.cc base/CharacterSet.h \
+	base/InstanceId.h MemBlob.h MemBlob.cc OutOfBoundsException.h \
+	SBuf.h SBuf.cc SBufExceptions.h SBufExceptions.cc SBufAlgos.h \
+	SBufAlgos.cc SBufDetailedStats.h \
 	tests/stub_SBufDetailedStats.cc SnmpRequest.h snmp_core.h \
 	snmp_core.cc snmp_agent.h snmp_agent.cc SquidMath.h \
 	SquidMath.cc IoStats.h stat.h stat.cc StatCounters.h \
 	StatCounters.cc StatHist.h tests/stub_StatHist.cc stmem.cc \
 	repl_modules.h store.cc store_client.cc store_digest.h \
-	tests/stub_store_digest.cc store_dir.cc store_io.cc \
-	store_key_md5.h store_key_md5.cc store_log.h store_log.cc \
-	store_rebuild.h store_rebuild.cc store_swapin.h \
-	store_swapin.cc store_swapmeta.cc store_swapout.cc \
-	StoreFileSystem.cc StoreIOState.cc tests/stub_StoreMeta.cc \
-	StoreMetaUnpacker.cc StoreSwapLogData.cc String.cc StrList.h \
-	StrList.cc Transients.cc tests/stub_SwapDir.cc MemStore.cc \
+	tests/stub_store_digest.cc store_io.cc store_key_md5.h \
+	store_key_md5.cc store_log.h store_log.cc store_rebuild.h \
+	store_rebuild.cc store_swapin.h store_swapin.cc \
+	store_swapmeta.cc store_swapout.cc StoreFileSystem.cc \
+	StoreIOState.cc tests/stub_StoreMeta.cc StoreMetaUnpacker.cc \
+	StoreSwapLogData.cc String.cc StrList.h StrList.cc \
+	Transients.cc tests/stub_SwapDir.cc MemStore.cc \
 	tests/stub_debug.cc tests/stub_libauth_acls.cc \
 	tests/stub_libauth.cc tests/stub_libdiskio.cc \
 	tests/stub_libmem.cc tests/stub_libsecurity.cc \
@@ -1636,7 +1637,7 @@
 	tests/stub_CollapsedForwarding.$(OBJEXT) \
 	ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) \
 	CpuAffinityMap.$(OBJEXT) CpuAffinitySet.$(OBJEXT) \
-	$(am__objects_3) disk.$(OBJEXT) dlink.$(OBJEXT) \
+	$(am__objects_3) fs_io.$(OBJEXT) dlink.$(OBJEXT) \
 	$(am__objects_4) errorpage.$(OBJEXT) ETag.$(OBJEXT) \
 	event.$(OBJEXT) external_acl.$(OBJEXT) \
 	ExternalACLEntry.$(OBJEXT) tests/stub_fatal.$(OBJEXT) \
@@ -1658,24 +1659,24 @@
 	pconn.$(OBJEXT) peer_digest.$(OBJEXT) \
 	peer_proxy_negotiate_auth.$(OBJEXT) peer_select.$(OBJEXT) \
 	peer_sourcehash.$(OBJEXT) peer_userhash.$(OBJEXT) \
-	tests/stub_redirect.$(OBJEXT) refresh.$(OBJEXT) \
-	RemovalPolicy.$(OBJEXT) $(am__objects_9) SBufAlgos.$(OBJEXT) \
-	tests/stub_SBufDetailedStats.$(OBJEXT) $(am__objects_11) \
-	SquidMath.$(OBJEXT) stat.$(OBJEXT) StatCounters.$(OBJEXT) \
-	tests/stub_StatHist.$(OBJEXT) stmem.$(OBJEXT) store.$(OBJEXT) \
-	store_client.$(OBJEXT) tests/stub_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) tests/stub_StoreMeta.$(OBJEXT) \
-	StoreMetaUnpacker.$(OBJEXT) StoreSwapLogData.$(OBJEXT) \
-	String.$(OBJEXT) StrList.$(OBJEXT) Transients.$(OBJEXT) \
-	tests/stub_SwapDir.$(OBJEXT) MemStore.$(OBJEXT) \
-	tests/stub_debug.$(OBJEXT) tests/stub_libauth_acls.$(OBJEXT) \
-	tests/stub_libauth.$(OBJEXT) tests/stub_libdiskio.$(OBJEXT) \
-	tests/stub_libmem.$(OBJEXT) tests/stub_libsecurity.$(OBJEXT) \
-	tests/stub_main_cc.$(OBJEXT) \
+	Pipeline.$(OBJEXT) tests/stub_redirect.$(OBJEXT) \
+	refresh.$(OBJEXT) RemovalPolicy.$(OBJEXT) $(am__objects_9) \
+	SBufAlgos.$(OBJEXT) tests/stub_SBufDetailedStats.$(OBJEXT) \
+	$(am__objects_11) SquidMath.$(OBJEXT) stat.$(OBJEXT) \
+	StatCounters.$(OBJEXT) tests/stub_StatHist.$(OBJEXT) \
+	stmem.$(OBJEXT) store.$(OBJEXT) store_client.$(OBJEXT) \
+	tests/stub_store_digest.$(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) \
+	tests/stub_StoreMeta.$(OBJEXT) StoreMetaUnpacker.$(OBJEXT) \
+	StoreSwapLogData.$(OBJEXT) String.$(OBJEXT) StrList.$(OBJEXT) \
+	Transients.$(OBJEXT) tests/stub_SwapDir.$(OBJEXT) \
+	MemStore.$(OBJEXT) tests/stub_debug.$(OBJEXT) \
+	tests/stub_libauth_acls.$(OBJEXT) tests/stub_libauth.$(OBJEXT) \
+	tests/stub_libdiskio.$(OBJEXT) tests/stub_libmem.$(OBJEXT) \
+	tests/stub_libsecurity.$(OBJEXT) tests/stub_main_cc.$(OBJEXT) \
 	tests/stub_ipc_Forwarder.$(OBJEXT) \
 	tests/stub_store_stats.$(OBJEXT) tests/testURL.$(OBJEXT) \
 	tests/testUriScheme.$(OBJEXT) tests/stub_time.$(OBJEXT) \
@@ -1701,13 +1702,13 @@
 	tests/stub_libformat.cc tests/stub_libsecurity.cc \
 	tests/stub_stat.cc store_rebuild.h tests/stub_store_rebuild.cc \
 	tests/stub_store_stats.cc fatal.h tests/stub_fatal.cc fd.h \
-	fd.cc fde.h fde.cc client_db.h disk.h disk.cc FileMap.h \
-	filemap.cc fs/forward.h HttpBody.h HttpBody.cc HttpReply.cc \
-	int.h int.cc RequestFlags.h RequestFlags.cc SquidList.h \
-	SquidList.cc Transients.cc MasterXaction.cc MasterXaction.h \
-	MemObject.cc Notes.h Notes.cc StoreSwapLogData.cc \
-	StoreIOState.cc StoreMetaUnpacker.cc StoreMeta.cc StoreMeta.h \
-	StoreMetaMD5.cc StoreMetaMD5.h StoreMetaSTD.cc StoreMetaSTD.h \
+	fd.cc fde.h fde.cc client_db.h fs_io.h fs_io.cc FileMap.h \
+	filemap.cc HttpBody.h HttpBody.cc HttpReply.cc int.h int.cc \
+	RequestFlags.h RequestFlags.cc SquidList.h SquidList.cc \
+	Transients.cc MasterXaction.cc MasterXaction.h MemObject.cc \
+	Notes.h Notes.cc StoreSwapLogData.cc StoreIOState.cc \
+	StoreMetaUnpacker.cc StoreMeta.cc StoreMeta.h StoreMetaMD5.cc \
+	StoreMetaMD5.h StoreMetaSTD.cc StoreMetaSTD.h \
 	StoreMetaSTDLFS.cc StoreMetaSTDLFS.h StoreMetaObjSize.h \
 	StoreMetaURL.cc StoreMetaURL.h StoreMetaVary.cc \
 	StoreMetaVary.h StoreFileSystem.cc store_io.cc \
@@ -1720,25 +1721,24 @@
 	DelayVector.cc DelayVector.h NullDelayId.cc NullDelayId.h \
 	ClientDelayConfig.cc ClientDelayConfig.h CacheDigest.h \
 	tests/stub_CacheDigest.cc ConfigParser.cc EventLoop.cc \
-	HttpMsg.cc RemovalPolicy.cc store_dir.cc repl_modules.h \
-	store.cc store_key_md5.h store_key_md5.cc Parsing.cc \
-	ConfigOption.cc SwapDir.cc tests/stub_acl.cc cache_cf.h \
-	YesNoNone.h tests/stub_cache_cf.cc tests/stub_helper.cc \
-	cbdata.cc base/CharacterSet.h base/InstanceId.h MemBlob.h \
-	MemBlob.cc OutOfBoundsException.h SBuf.h SBuf.cc \
-	SBufExceptions.h SBufExceptions.cc SBufAlgos.h SBufAlgos.cc \
-	SBufDetailedStats.h tests/stub_SBufDetailedStats.cc String.cc \
-	tests/stub_debug.cc tests/stub_client_side_request.cc \
-	tests/stub_http.cc tests/stub_libauth.cc mem_node.cc stmem.cc \
-	mime.h tests/stub_mime.cc HttpHeaderFieldInfo.h \
-	HttpHeaderTools.h HttpHeaderTools.cc HttpHeader.h \
-	HttpHeader.cc ClientInfo.h MemBuf.cc HttpHdrContRange.cc \
-	HttpHeaderFieldStat.h HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci \
-	HttpHdrSc.cc HttpHdrScTarget.cc url.cc StatCounters.h \
-	StatCounters.cc StatHist.h StatHist.cc StrList.h StrList.cc \
-	HttpHdrRange.cc ETag.cc tests/stub_errorpage.cc \
-	tests/stub_HttpRequest.cc log/access_log.h \
-	tests/stub_access_log.cc refresh.h refresh.cc \
+	HttpMsg.cc RemovalPolicy.cc repl_modules.h store.cc \
+	store_key_md5.h store_key_md5.cc Parsing.cc ConfigOption.cc \
+	tests/stub_acl.cc cache_cf.h YesNoNone.h \
+	tests/stub_cache_cf.cc tests/stub_helper.cc cbdata.cc \
+	base/CharacterSet.h base/InstanceId.h MemBlob.h MemBlob.cc \
+	OutOfBoundsException.h SBuf.h SBuf.cc SBufExceptions.h \
+	SBufExceptions.cc SBufAlgos.h SBufAlgos.cc SBufDetailedStats.h \
+	tests/stub_SBufDetailedStats.cc String.cc tests/stub_debug.cc \
+	tests/stub_client_side_request.cc tests/stub_http.cc \
+	tests/stub_libauth.cc mem_node.cc stmem.cc mime.h \
+	tests/stub_mime.cc HttpHeaderFieldInfo.h HttpHeaderTools.h \
+	HttpHeaderTools.cc HttpHeader.h HttpHeader.cc ClientInfo.h \
+	MemBuf.cc HttpHdrContRange.cc HttpHeaderFieldStat.h \
+	HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci HttpHdrSc.cc \
+	HttpHdrScTarget.cc url.cc StatCounters.h StatCounters.cc \
+	StatHist.h StatHist.cc StrList.h StrList.cc HttpHdrRange.cc \
+	ETag.cc tests/stub_errorpage.cc tests/stub_HttpRequest.cc \
+	log/access_log.h tests/stub_access_log.cc refresh.h refresh.cc \
 	tests/stub_store_client.cc tools.h tests/stub_tools.cc \
 	tests/testStoreSupport.cc tests/testStoreSupport.h time.cc \
 	wordlist.h wordlist.cc
@@ -1756,7 +1756,7 @@
 	tests/stub_libsecurity.$(OBJEXT) tests/stub_stat.$(OBJEXT) \
 	tests/stub_store_rebuild.$(OBJEXT) \
 	tests/stub_store_stats.$(OBJEXT) tests/stub_fatal.$(OBJEXT) \
-	fd.$(OBJEXT) fde.$(OBJEXT) disk.$(OBJEXT) filemap.$(OBJEXT) \
+	fd.$(OBJEXT) fde.$(OBJEXT) fs_io.$(OBJEXT) filemap.$(OBJEXT) \
 	HttpBody.$(OBJEXT) HttpReply.$(OBJEXT) int.$(OBJEXT) \
 	RequestFlags.$(OBJEXT) SquidList.$(OBJEXT) \
 	Transients.$(OBJEXT) MasterXaction.$(OBJEXT) \
@@ -1767,13 +1767,13 @@
 	$(am__objects_13) $(am__objects_14) event.$(OBJEXT) \
 	$(am__objects_3) tests/stub_CacheDigest.$(OBJEXT) \
 	ConfigParser.$(OBJEXT) EventLoop.$(OBJEXT) HttpMsg.$(OBJEXT) \
-	RemovalPolicy.$(OBJEXT) store_dir.$(OBJEXT) store.$(OBJEXT) \
+	RemovalPolicy.$(OBJEXT) store.$(OBJEXT) \
 	store_key_md5.$(OBJEXT) Parsing.$(OBJEXT) \
-	ConfigOption.$(OBJEXT) SwapDir.$(OBJEXT) \
-	tests/stub_acl.$(OBJEXT) tests/stub_cache_cf.$(OBJEXT) \
-	tests/stub_helper.$(OBJEXT) cbdata.$(OBJEXT) $(am__objects_9) \
-	SBufAlgos.$(OBJEXT) tests/stub_SBufDetailedStats.$(OBJEXT) \
-	String.$(OBJEXT) tests/stub_debug.$(OBJEXT) \
+	ConfigOption.$(OBJEXT) tests/stub_acl.$(OBJEXT) \
+	tests/stub_cache_cf.$(OBJEXT) tests/stub_helper.$(OBJEXT) \
+	cbdata.$(OBJEXT) $(am__objects_9) SBufAlgos.$(OBJEXT) \
+	tests/stub_SBufDetailedStats.$(OBJEXT) String.$(OBJEXT) \
+	tests/stub_debug.$(OBJEXT) \
 	tests/stub_client_side_request.$(OBJEXT) \
 	tests/stub_http.$(OBJEXT) tests/stub_libauth.$(OBJEXT) \
 	mem_node.$(OBJEXT) stmem.$(OBJEXT) tests/stub_mime.$(OBJEXT) \
@@ -1812,51 +1812,52 @@
 	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.h disk.cc dlink.h dlink.cc \
+	ClientDelayConfig.h fs_io.h fs_io.cc dlink.h dlink.cc \
 	dns_internal.cc errorpage.cc tests/stub_ETag.cc event.cc \
 	FadingCounter.cc fatal.h tests/stub_libauth.cc \
 	tests/stub_fatal.cc fd.h fd.cc fde.cc FileMap.h filemap.cc \
-	fqdncache.h fqdncache.cc fs/forward.h FwdState.cc FwdState.h \
-	gopher.h gopher.cc helper.cc hier_code.h htcp.cc htcp.h \
-	http.cc HttpBody.h HttpBody.cc HttpHeaderFieldStat.h \
-	HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci HttpHdrContRange.cc \
-	HttpHdrRange.cc HttpHdrSc.cc HttpHdrScTarget.cc HttpHeader.h \
-	HttpHeader.cc HttpHeaderFieldInfo.h HttpHeaderTools.h \
-	HttpHeaderTools.cc HttpMsg.cc HttpReply.cc PeerPoolMgr.h \
-	PeerPoolMgr.cc RequestFlags.h RequestFlags.cc HttpRequest.cc \
-	icp_v2.cc icp_v3.cc int.h int.cc internal.h internal.cc \
-	SquidIpc.h ipc.cc ipc_win32.cc ipcache.cc LogTags.cc \
-	SquidList.h SquidList.cc MasterXaction.cc MasterXaction.h \
-	MemBuf.cc MemObject.cc tests/stub_libmem.cc mem_node.cc mime.h \
-	mime.cc mime_header.h mime_header.cc multicast.h multicast.cc \
+	fqdncache.h fqdncache.cc FwdState.cc FwdState.h gopher.h \
+	gopher.cc helper.cc hier_code.h htcp.cc htcp.h http.cc \
+	HttpBody.h HttpBody.cc HttpHeaderFieldStat.h HttpHdrCc.h \
+	HttpHdrCc.cc HttpHdrCc.cci HttpHdrContRange.cc HttpHdrRange.cc \
+	HttpHdrSc.cc HttpHdrScTarget.cc HttpHeader.h HttpHeader.cc \
+	HttpHeaderFieldInfo.h HttpHeaderTools.h HttpHeaderTools.cc \
+	HttpMsg.cc HttpReply.cc PeerPoolMgr.h PeerPoolMgr.cc \
+	RequestFlags.h RequestFlags.cc HttpRequest.cc icp_v2.cc \
+	icp_v3.cc int.h int.cc internal.h internal.cc SquidIpc.h \
+	ipc.cc ipc_win32.cc ipcache.cc LogTags.cc SquidList.h \
+	SquidList.cc MasterXaction.cc MasterXaction.h MemBuf.cc \
+	MemObject.cc tests/stub_libmem.cc mem_node.cc mime.h mime.cc \
+	mime_header.h mime_header.cc multicast.h multicast.cc \
 	neighbors.h neighbors.cc Notes.cc Notes.h Parsing.cc \
 	peer_digest.cc peer_proxy_negotiate_auth.h \
 	peer_proxy_negotiate_auth.cc peer_select.cc peer_sourcehash.h \
-	peer_sourcehash.cc peer_userhash.h peer_userhash.cc pconn.cc \
-	redirect.h tests/stub_redirect.cc refresh.h refresh.cc \
-	RemovalPolicy.cc base/CharacterSet.h base/InstanceId.h \
-	MemBlob.h MemBlob.cc OutOfBoundsException.h SBuf.h SBuf.cc \
-	SBufExceptions.h SBufExceptions.cc SBufAlgos.h SBufAlgos.cc \
-	SBufDetailedStats.h tests/stub_SBufDetailedStats.cc \
-	SnmpRequest.h snmp_core.h snmp_core.cc snmp_agent.h \
-	snmp_agent.cc SquidMath.h SquidMath.cc IoStats.h stat.h \
-	stat.cc StatCounters.h StatCounters.cc StatHist.h StatHist.cc \
-	stmem.cc repl_modules.h store.cc store_client.cc \
-	store_digest.h tests/stub_store_digest.cc store_dir.cc \
-	store_key_md5.h store_key_md5.cc store_io.cc store_log.h \
-	store_log.cc store_rebuild.h store_rebuild.cc store_swapin.h \
-	store_swapin.cc store_swapmeta.cc store_swapout.cc \
-	StoreFileSystem.cc StoreIOState.cc tests/stub_StoreMeta.cc \
-	StoreMetaUnpacker.cc StoreSwapLogData.cc String.cc StrList.h \
-	StrList.cc tests/stub_SwapDir.cc Transients.cc \
-	tests/test_http_range.cc tests/stub_external_acl.cc \
-	tests/stub_ipc_Forwarder.cc tests/stub_libdiskio.cc \
-	tests/stub_libeui.cc tests/stub_libsecurity.cc \
-	tests/stub_main_cc.cc tests/stub_MemStore.cc \
-	tests/stub_store_stats.cc tests/stub_EventLoop.cc time.cc \
-	tools.h tools.cc tests/stub_tunnel.cc unlinkd.h unlinkd.cc \
-	url.cc urn.h urn.cc wccp2.h tests/stub_wccp2.cc whois.h \
-	tests/stub_whois.cc win32.cc wordlist.h wordlist.cc
+	peer_sourcehash.cc peer_userhash.h peer_userhash.cc \
+	Pipeline.cc Pipeline.h pconn.cc redirect.h \
+	tests/stub_redirect.cc refresh.h refresh.cc RemovalPolicy.cc \
+	base/CharacterSet.h base/InstanceId.h MemBlob.h MemBlob.cc \
+	OutOfBoundsException.h SBuf.h SBuf.cc SBufExceptions.h \
+	SBufExceptions.cc SBufAlgos.h SBufAlgos.cc SBufDetailedStats.h \
+	tests/stub_SBufDetailedStats.cc SnmpRequest.h snmp_core.h \
+	snmp_core.cc snmp_agent.h snmp_agent.cc SquidMath.h \
+	SquidMath.cc IoStats.h stat.h stat.cc StatCounters.h \
+	StatCounters.cc StatHist.h StatHist.cc stmem.cc repl_modules.h \
+	store.cc store_client.cc store_digest.h \
+	tests/stub_store_digest.cc store_key_md5.h store_key_md5.cc \
+	store_io.cc store_log.h store_log.cc store_rebuild.h \
+	store_rebuild.cc store_swapin.h store_swapin.cc \
+	store_swapmeta.cc store_swapout.cc StoreFileSystem.cc \
+	StoreIOState.cc tests/stub_StoreMeta.cc StoreMetaUnpacker.cc \
+	StoreSwapLogData.cc String.cc StrList.h StrList.cc \
+	tests/stub_SwapDir.cc Transients.cc tests/test_http_range.cc \
+	tests/stub_external_acl.cc tests/stub_ipc_Forwarder.cc \
+	tests/stub_libdiskio.cc tests/stub_libeui.cc \
+	tests/stub_libsecurity.cc tests/stub_main_cc.cc \
+	tests/stub_MemStore.cc tests/stub_store_stats.cc \
+	tests/stub_EventLoop.cc time.cc tools.h tools.cc \
+	tests/stub_tunnel.cc unlinkd.h unlinkd.cc url.cc urn.h urn.cc \
+	wccp2.h tests/stub_wccp2.cc whois.h tests/stub_whois.cc \
+	win32.cc wordlist.h wordlist.cc
 am_tests_test_http_range_OBJECTS = AccessLogEntry.$(OBJEXT) \
 	BodyPipe.$(OBJEXT) YesNoNone.$(OBJEXT) cache_cf.$(OBJEXT) \
 	CachePeer.$(OBJEXT) cache_manager.$(OBJEXT) \
@@ -1867,7 +1868,7 @@
 	tests/stub_CollapsedForwarding.$(OBJEXT) \
 	ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) \
 	CpuAffinityMap.$(OBJEXT) CpuAffinitySet.$(OBJEXT) \
-	debug.$(OBJEXT) $(am__objects_3) disk.$(OBJEXT) \
+	debug.$(OBJEXT) $(am__objects_3) fs_io.$(OBJEXT) \
 	dlink.$(OBJEXT) $(am__objects_4) errorpage.$(OBJEXT) \
 	tests/stub_ETag.$(OBJEXT) event.$(OBJEXT) \
 	FadingCounter.$(OBJEXT) tests/stub_libauth.$(OBJEXT) \
@@ -1889,13 +1890,13 @@
 	Parsing.$(OBJEXT) peer_digest.$(OBJEXT) \
 	peer_proxy_negotiate_auth.$(OBJEXT) peer_select.$(OBJEXT) \
 	peer_sourcehash.$(OBJEXT) peer_userhash.$(OBJEXT) \
-	pconn.$(OBJEXT) tests/stub_redirect.$(OBJEXT) \
-	refresh.$(OBJEXT) RemovalPolicy.$(OBJEXT) $(am__objects_9) \
-	SBufAlgos.$(OBJEXT) tests/stub_SBufDetailedStats.$(OBJEXT) \
-	$(am__objects_11) SquidMath.$(OBJEXT) stat.$(OBJEXT) \
-	StatCounters.$(OBJEXT) StatHist.$(OBJEXT) stmem.$(OBJEXT) \
-	store.$(OBJEXT) store_client.$(OBJEXT) \
-	tests/stub_store_digest.$(OBJEXT) store_dir.$(OBJEXT) \
+	Pipeline.$(OBJEXT) pconn.$(OBJEXT) \
+	tests/stub_redirect.$(OBJEXT) refresh.$(OBJEXT) \
+	RemovalPolicy.$(OBJEXT) $(am__objects_9) SBufAlgos.$(OBJEXT) \
+	tests/stub_SBufDetailedStats.$(OBJEXT) $(am__objects_11) \
+	SquidMath.$(OBJEXT) stat.$(OBJEXT) StatCounters.$(OBJEXT) \
+	StatHist.$(OBJEXT) stmem.$(OBJEXT) store.$(OBJEXT) \
+	store_client.$(OBJEXT) tests/stub_store_digest.$(OBJEXT) \
 	store_key_md5.$(OBJEXT) store_io.$(OBJEXT) store_log.$(OBJEXT) \
 	store_rebuild.$(OBJEXT) store_swapin.$(OBJEXT) \
 	store_swapmeta.$(OBJEXT) store_swapout.$(OBJEXT) \
@@ -2350,6 +2351,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -2387,7 +2389,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
@@ -2622,12 +2623,12 @@
 	LoadableModules.cc
 
 SUBDIRS = mem base anyp helper dns ftp parser comm eui acl format \
-	clients servers fs repl DiskIO $(am__append_2) http ip icmp \
-	ident log ipc mgr security $(am__append_4) $(am__append_6) \
-	$(am__append_7) $(am__append_8)
+	clients servers fs repl store DiskIO $(am__append_2) http ip \
+	icmp ident log ipc mgr security $(am__append_4) \
+	$(am__append_6) $(am__append_7) $(am__append_8)
 DIST_SUBDIRS = mem base anyp helper dns ftp parser comm eui acl format \
-	clients servers fs repl DiskIO auth http ip icmp ident log ipc \
-	mgr security ssl snmp adaptation esi
+	clients servers fs repl store DiskIO auth http ip icmp ident \
+	log ipc mgr security ssl snmp adaptation esi
 @ENABLE_AUTH_TRUE@AUTH_LIBS = auth/libauth.la
 @ENABLE_AUTH_TRUE@AUTH_ACL_LIBS = auth/libacls.la
 SSL_LIBS = $(am__append_5)
@@ -2733,16 +2734,16 @@
 	ConfigOption.cc ConfigParser.cc ConfigParser.h CpuAffinity.cc \
 	CpuAffinity.h CpuAffinityMap.cc CpuAffinityMap.h \
 	CpuAffinitySet.cc CpuAffinitySet.h debug.cc Debug.h defines.h \
-	$(DELAY_POOL_SOURCE) disk.h disk.cc dlink.h dlink.cc \
+	$(DELAY_POOL_SOURCE) fs_io.h fs_io.cc dlink.h dlink.cc \
 	$(DNSSOURCE) enums.h err_type.h err_detail_type.h errorpage.cc \
 	errorpage.h ETag.cc ETag.h event.cc event.h EventLoop.h \
 	EventLoop.cc external_acl.cc ExternalACL.h ExternalACLEntry.cc \
 	ExternalACLEntry.h FadingCounter.h FadingCounter.cc fatal.h \
 	fatal.cc fd.h fd.cc fde.cc fde.h FileMap.h filemap.cc \
-	fqdncache.h fqdncache.cc fs/forward.h FwdState.cc FwdState.h \
-	Generic.h globals.h gopher.h gopher.cc helper.cc helper.h \
-	hier_code.h HierarchyLogEntry.h $(HTCPSOURCE) HttpStateFlags.h \
-	http.cc http.h HttpHeaderFieldStat.h HttpHdrCc.h HttpHdrCc.cc \
+	fqdncache.h fqdncache.cc FwdState.cc FwdState.h Generic.h \
+	globals.h gopher.h gopher.cc helper.cc helper.h hier_code.h \
+	HierarchyLogEntry.h $(HTCPSOURCE) HttpStateFlags.h http.cc \
+	http.h HttpHeaderFieldStat.h HttpHdrCc.h HttpHdrCc.cc \
 	HttpHdrCc.cci HttpHdrRange.cc HttpHdrSc.cc HttpHdrSc.h \
 	HttpHdrScTarget.cc HttpHdrScTarget.h HttpHdrContRange.cc \
 	HttpHdrContRange.h HttpHeaderStat.h HttpHeader.h HttpHeader.cc \
@@ -2762,28 +2763,28 @@
 	peer_proxy_negotiate_auth.h peer_proxy_negotiate_auth.cc \
 	peer_select.cc peer_sourcehash.h peer_sourcehash.cc \
 	peer_userhash.h peer_userhash.cc PeerPoolMgr.h PeerPoolMgr.cc \
-	PeerSelectState.h PingData.h protos.h redirect.h redirect.cc \
-	refresh.h refresh.cc RemovalPolicy.cc RemovalPolicy.h \
-	send-announce.h send-announce.cc $(SBUF_SOURCE) SBufAlgos.h \
-	SBufAlgos.cc SBufDetailedStats.h SBufDetailedStats.cc \
-	SBufStatsAction.h SBufStatsAction.cc $(SNMP_SOURCE) \
-	SquidMath.h SquidMath.cc SquidNew.cc IoStats.h stat.h stat.cc \
-	StatCounters.h StatCounters.cc StatHist.h StatHist.cc \
-	String.cc StrList.h StrList.cc stmem.cc stmem.h repl_modules.h \
-	store.cc Store.h StoreFileSystem.cc StoreFileSystem.h \
-	StoreHashIndex.h store_io.cc StoreIOBuffer.h StoreIOState.cc \
+	PeerSelectState.h PingData.h Pipeline.cc Pipeline.h protos.h \
+	redirect.h redirect.cc refresh.h refresh.cc RemovalPolicy.cc \
+	RemovalPolicy.h send-announce.h send-announce.cc \
+	$(SBUF_SOURCE) SBufAlgos.h SBufAlgos.cc SBufDetailedStats.h \
+	SBufDetailedStats.cc SBufStatsAction.h SBufStatsAction.cc \
+	$(SNMP_SOURCE) SquidMath.h SquidMath.cc SquidNew.cc IoStats.h \
+	stat.h stat.cc StatCounters.h StatCounters.cc StatHist.h \
+	StatHist.cc String.cc StrList.h StrList.cc stmem.cc stmem.h \
+	repl_modules.h store.cc Store.h StoreFileSystem.cc \
+	StoreFileSystem.h store_io.cc StoreIOBuffer.h StoreIOState.cc \
 	StoreIOState.h store_client.cc StoreClient.h store_digest.h \
-	store_digest.cc store_dir.cc store_key_md5.h store_key_md5.cc \
-	store_log.h store_log.cc store_rebuild.h store_rebuild.cc \
-	store_swapin.h store_swapin.cc store_swapmeta.cc \
-	store_swapout.cc StoreMetaUnpacker.cc StoreMetaUnpacker.h \
-	$(STOREMETA_SOURCE) StoreSearch.h StoreStats.cc StoreStats.h \
-	StoreSwapLogData.cc StoreSwapLogData.h swap_log_op.h \
-	SwapDir.cc SwapDir.h Transients.cc Transients.h MemStore.cc \
-	MemStore.h time.cc TimeOrTag.h tools.h tools.cc tunnel.cc \
-	typedefs.h $(UNLINKDSOURCE) url.cc URL.h urn.h urn.cc wccp.h \
-	wccp.cc wccp2.h wccp2.cc whois.h whois.cc wordlist.h \
-	wordlist.cc $(WIN32_SOURCE) $(WINSVC_SOURCE) $(am__append_9)
+	store_digest.cc store_key_md5.h store_key_md5.cc store_log.h \
+	store_log.cc store_rebuild.h store_rebuild.cc store_swapin.h \
+	store_swapin.cc store_swapmeta.cc store_swapout.cc \
+	StoreMetaUnpacker.cc StoreMetaUnpacker.h $(STOREMETA_SOURCE) \
+	StoreSearch.h StoreStats.cc StoreStats.h StoreSwapLogData.cc \
+	StoreSwapLogData.h swap_log_op.h Transients.cc Transients.h \
+	MemStore.cc MemStore.h time.cc TimeOrTag.h tools.h tools.cc \
+	tunnel.cc typedefs.h $(UNLINKDSOURCE) url.cc URL.h urn.h \
+	urn.cc wccp.h wccp.cc wccp2.h wccp2.cc whois.h whois.cc \
+	wordlist.h wordlist.cc $(WIN32_SOURCE) $(WINSVC_SOURCE) \
+	$(am__append_9)
 EXTRA_squid_SOURCES = \
 	$(all_AUTHMODULES) \
 	ConfigOption.h \
@@ -2831,14 +2832,14 @@
 	$(SSL_LIBS) ipc/libipc.la mgr/libmgr.la anyp/libanyp.la \
 	security/libsecurity.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) \
-	$(NETTLELIB) $(CRYPTLIB) $(REGEXLIB) $(ADAPTATION_LIBS) \
-	$(ESI_LIBS) $(SNMP_LIBS) mem/libmem.la \
+	format/libformat.la $(XTRA_OBJS) $(REPL_OBJS) $(NETTLELIB) \
+	$(CRYPTLIB) $(REGEXLIB) $(ADAPTATION_LIBS) $(ESI_LIBS) \
+	$(SNMP_LIBS) mem/libmem.la store/libstore.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
-	$(top_builddir)/lib/libmiscutil.la $(SSLLIB) $(EPOLL_LIBS) \
-	$(MINGW_LIBS) $(KRB5LIBS) $(COMPAT_LIB) $(XTRA_LIBS) \
-	$(am__append_10)
+	$(top_builddir)/lib/libmiscutil.la $(ATOMICLIB) $(SSLLIB) \
+	$(EPOLL_LIBS) $(MINGW_LIBS) $(KRB5LIBS) $(COMPAT_LIB) \
+	$(XTRA_LIBS) $(am__append_10)
 @ENABLE_LOADABLE_MODULES_TRUE@squid_LDFLAGS = -export-dynamic -dlopen force
 unlinkd_SOURCES = unlinkd_daemon.cc
 unlinkd_LDADD = \
@@ -2910,7 +2911,6 @@
 	ipc/libipc.la \
 	mgr/libmgr.la \
 	DiskIO/libdiskio.la \
-	$(DISK_LINKOBJS) \
 	$(REPL_OBJS)
 
 nodist_ufsdump_SOURCES = \
@@ -3240,7 +3240,6 @@
 	SBufDetailedStats.h \
 	tests/stub_SBufDetailedStats.cc \
 	String.cc \
-	store_dir.cc \
 	StoreIOState.cc \
 	tests/stub_StoreMeta.cc \
 	StoreMetaUnpacker.cc \
@@ -3250,7 +3249,6 @@
 	swap_log_op.cc \
 	swap_log_op.h \
 	tests/stub_SwapDir.cc \
-	SwapDir.h \
 	Transients.cc \
 	log/access_log.h \
 	tests/stub_access_log.cc \
@@ -3416,8 +3414,8 @@
 	CpuAffinitySet.cc \
 	CpuAffinitySet.h \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	dlink.h \
 	dlink.cc \
 	$(DNSSOURCE) \
@@ -3435,7 +3433,6 @@
 	filemap.cc \
 	fqdncache.h \
 	fqdncache.cc \
-	fs/forward.h \
 	FwdState.cc \
 	FwdState.h \
 	gopher.h \
@@ -3501,6 +3498,8 @@
 	peer_userhash.cc \
 	PeerPoolMgr.h \
 	PeerPoolMgr.cc \
+	Pipeline.cc \
+	Pipeline.h \
 	redirect.h \
 	tests/stub_redirect.cc \
 	refresh.h \
@@ -3532,7 +3531,6 @@
 	store_client.cc \
 	store_digest.h \
 	tests/stub_store_digest.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
@@ -3602,6 +3600,7 @@
 	mgr/libmgr.la \
 	$(SNMP_LIBS) \
 	mem/libmem.la \
+	store/libstore.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
 	$(top_builddir)/lib/libmiscutil.la \
@@ -3629,8 +3628,8 @@
 	ConfigOption.cc \
 	ConfigParser.cc \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	tests/stub_ETag.cc \
 	EventLoop.cc \
 	event.cc \
@@ -3642,7 +3641,6 @@
 	fde.cc \
 	FileMap.h \
 	filemap.cc \
-	fs/forward.h \
 	HttpBody.h \
 	HttpBody.cc \
 	HttpHeaderFieldStat.h \
@@ -3693,7 +3691,6 @@
 	tests/stub_StoreMeta.cc \
 	StoreMetaUnpacker.cc \
 	StoreSwapLogData.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
@@ -3786,6 +3783,7 @@
 	dns/libdns.la \
 	base/libbase.la \
 	mem/libmem.la \
+	store/libstore.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
 	$(top_builddir)/lib/libmiscutil.la \
@@ -3856,8 +3854,8 @@
 	CpuAffinitySet.h \
 	debug.cc \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	dlink.h \
 	dlink.cc \
 	$(DNSSOURCE) \
@@ -3878,7 +3876,6 @@
 	filemap.cc \
 	fqdncache.h \
 	fqdncache.cc \
-	fs/forward.h \
 	FwdState.cc \
 	FwdState.h \
 	gopher.h \
@@ -3947,6 +3944,8 @@
 	peer_sourcehash.cc \
 	peer_userhash.h \
 	peer_userhash.cc \
+	Pipeline.cc \
+	Pipeline.h \
 	redirect.h \
 	tests/stub_redirect.cc \
 	refresh.h \
@@ -3975,7 +3974,6 @@
 	store_client.cc \
 	store_digest.h \
 	tests/stub_store_digest.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
@@ -4055,6 +4053,7 @@
 	$(top_builddir)/lib/libmiscutil.la \
 	ipc/libipc.la \
 	mgr/libmgr.la \
+	store/libstore.la \
 	$(SNMP_LIBS) \
 	$(NETTLELIB) \
 	$(REGEXLIB) \
@@ -4104,8 +4103,8 @@
 	CpuAffinitySet.h \
 	debug.cc \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	dlink.h \
 	dlink.cc \
 	$(DNSSOURCE) \
@@ -4126,7 +4125,6 @@
 	filemap.cc \
 	fqdncache.h \
 	fqdncache.cc \
-	fs/forward.h \
 	FwdState.cc \
 	FwdState.h \
 	gopher.h \
@@ -4194,6 +4192,8 @@
 	peer_sourcehash.cc \
 	peer_userhash.h \
 	peer_userhash.cc \
+	Pipeline.cc \
+	Pipeline.h \
 	RemovalPolicy.cc \
 	redirect.h \
 	tests/stub_redirect.cc \
@@ -4220,7 +4220,6 @@
 	store_client.cc \
 	store_digest.h \
 	tests/stub_store_digest.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
@@ -4302,6 +4301,7 @@
 	$(top_builddir)/lib/libmiscutil.la \
 	ipc/libipc.la \
 	mgr/libmgr.la \
+	store/libstore.la \
 	$(SNMP_LIBS) \
 	$(NETTLELIB) \
 	$(REGEXLIB) \
@@ -4351,8 +4351,8 @@
 	CpuAffinitySet.h \
 	debug.cc \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	dlink.h \
 	dlink.cc \
 	$(DNSSOURCE) \
@@ -4370,7 +4370,6 @@
 	filemap.cc \
 	fqdncache.h \
 	fqdncache.cc \
-	fs/forward.h \
 	FwdState.cc \
 	FwdState.h \
 	gopher.h \
@@ -4437,6 +4436,8 @@
 	peer_sourcehash.cc \
 	peer_userhash.h \
 	peer_userhash.cc \
+	Pipeline.cc \
+	Pipeline.h \
 	pconn.cc \
 	redirect.h \
 	tests/stub_redirect.cc \
@@ -4464,7 +4465,6 @@
 	store_client.cc \
 	store_digest.h \
 	tests/stub_store_digest.cc \
-	store_dir.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
 	store_io.cc \
@@ -4543,6 +4543,7 @@
 	dns/libdns.la \
 	base/libbase.la \
 	mgr/libmgr.la \
+	store/libstore.la \
 	$(SNMP_LIBS) \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
@@ -4690,8 +4691,8 @@
 	CpuAffinitySet.cc \
 	CpuAffinitySet.h \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	dlink.h \
 	dlink.cc \
 	$(DNSSOURCE) \
@@ -4706,7 +4707,6 @@
 	fde.cc \
 	fqdncache.h \
 	fqdncache.cc \
-	fs/forward.h \
 	FwdState.cc \
 	FwdState.h \
 	gopher.h \
@@ -4771,6 +4771,8 @@
 	peer_userhash.cc \
 	PeerPoolMgr.h \
 	PeerPoolMgr.cc \
+	Pipeline.cc \
+	Pipeline.h \
 	redirect.h \
 	tests/stub_libauth_acls.cc \
 	tests/stub_redirect.cc \
@@ -4798,7 +4800,6 @@
 	store_client.cc \
 	store_digest.h \
 	tests/stub_store_digest.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
@@ -4865,6 +4866,7 @@
 	comm/libcomm.la \
 	log/liblog.la \
 	format/libformat.la \
+	store/libstore.la \
 	$(REPL_OBJS) \
 	$(ADAPTATION_LIBS) \
 	$(ESI_LIBS) \
@@ -4937,8 +4939,8 @@
 	ConfigOption.cc \
 	ConfigParser.cc \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	ETag.cc \
 	event.cc \
 	EventLoop.cc \
@@ -4946,7 +4948,6 @@
 	tests/stub_fatal.cc \
 	FileMap.h \
 	filemap.cc \
-	fs/forward.h \
 	HttpHeaderFieldStat.h \
 	HttpHdrCc.h \
 	HttpHdrCc.cc \
@@ -4985,7 +4986,6 @@
 	stmem.cc \
 	repl_modules.h \
 	store.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_swapout.cc \
 	StoreIOState.cc \
@@ -5002,7 +5002,6 @@
 	String.cc \
 	StrList.h \
 	StrList.cc \
-	SwapDir.cc \
 	tests/CapturingStoreEntry.h \
 	log/access_log.h \
 	tests/stub_access_log.cc \
@@ -5085,6 +5084,7 @@
 	ipc/libipc.la \
 	anyp/libanyp.la \
 	mem/libmem.la \
+	store/libstore.la \
 	DiskIO/libdiskio.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
@@ -5190,11 +5190,10 @@
 	fde.h \
 	fde.cc \
 	client_db.h \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	FileMap.h \
 	filemap.cc \
-	fs/forward.h \
 	HttpBody.h \
 	HttpBody.cc \
 	HttpReply.cc \
@@ -5228,14 +5227,12 @@
 	EventLoop.cc \
 	HttpMsg.cc \
 	RemovalPolicy.cc \
-	store_dir.cc \
 	repl_modules.h \
 	store.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
 	Parsing.cc \
 	ConfigOption.cc \
-	SwapDir.cc \
 	tests/stub_acl.cc \
 	cache_cf.h \
 	YesNoNone.h \
@@ -5324,6 +5321,7 @@
 	base/libbase.la \
 	ip/libip.la \
 	mem/libmem.la \
+	store/libstore.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
 	$(top_builddir)/lib/libmiscutil.la \
@@ -5361,8 +5359,8 @@
 	tests/stub_CacheDigest.cc \
 	ConfigOption.cc \
 	ConfigParser.cc \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	ETag.cc \
 	EventLoop.cc \
 	event.cc \
@@ -5374,7 +5372,6 @@
 	fde.cc \
 	FileMap.h \
 	filemap.cc \
-	fs/forward.h \
 	HttpHeaderFieldStat.h \
 	HttpBody.h \
 	HttpBody.cc \
@@ -5418,7 +5415,6 @@
 	StoreMetaUnpacker.cc \
 	$(STOREMETA_SOURCE) \
 	StoreSwapLogData.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
@@ -5432,7 +5428,6 @@
 	String.cc \
 	StrList.h \
 	StrList.cc \
-	SwapDir.cc \
 	Transients.h \
 	Transients.cc \
 	tests/testRock.cc \
@@ -5506,6 +5501,7 @@
 	ipc/libipc.la \
 	base/libbase.la \
 	mem/libmem.la \
+	store/libstore.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
 	$(top_builddir)/lib/libmiscutil.la \
@@ -5553,8 +5549,8 @@
 	CpuAffinitySet.cc \
 	CpuAffinitySet.h \
 	$(DELAY_POOL_SOURCE) \
-	disk.h \
-	disk.cc \
+	fs_io.h \
+	fs_io.cc \
 	dlink.h \
 	dlink.cc \
 	$(DNSSOURCE) \
@@ -5572,7 +5568,6 @@
 	filemap.cc \
 	fqdncache.h \
 	fqdncache.cc \
-	fs/forward.h \
 	FwdState.cc \
 	FwdState.h \
 	gopher.h \
@@ -5640,6 +5635,8 @@
 	peer_sourcehash.cc \
 	peer_userhash.h \
 	peer_userhash.cc \
+	Pipeline.cc \
+	Pipeline.h \
 	redirect.h \
 	tests/stub_redirect.cc \
 	refresh.h \
@@ -5666,7 +5663,6 @@
 	store_client.cc \
 	store_digest.h \
 	tests/stub_store_digest.cc \
-	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
@@ -5748,6 +5744,7 @@
 	comm/libcomm.la \
 	log/liblog.la \
 	format/libformat.la \
+	store/libstore.la \
 	$(REGEXLIB) \
 	$(REPL_OBJS) \
 	$(ADAPTATION_LIBS) \
@@ -6604,6 +6601,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NullDelayId.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Parsing.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerPoolMgr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Pipeline.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ProfStats.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RemovalPolicy.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestFlags.Po@am__quote@
@@ -6632,7 +6630,6 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StoreSwapLogData.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StrList.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/String.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SwapDir.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Transients.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/WinSvc.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YesNoNone.Po@am__quote@
@@ -6649,7 +6646,6 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/comm.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delay_pools.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disk.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlink.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dns_internal.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/err_detail_type.Po@am__quote@
@@ -6662,6 +6658,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fde.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filemap.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fqdncache.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_io.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globals.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gopher.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper.Po@am__quote@
@@ -6701,7 +6698,6 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/store.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/store_client.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/store_digest.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/store_dir.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/store_io.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/store_key_md5.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/store_log.Po@am__quote@
diff -u -r -N squid-4.0.2/src/mem/forward.h squid-4.0.3/src/mem/forward.h
--- squid-4.0.2/src/mem/forward.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/mem/forward.h	2015-11-28 07:30:57.000000000 -0800
@@ -46,9 +46,6 @@
     MEM_64K_BUF,
     MEM_ACL_DENY_INFO_LIST,
     MEM_ACL_NAME_LIST,
-#if USE_CACHE_DIGESTS
-    MEM_CACHE_DIGEST,
-#endif
     MEM_CLIENT_INFO,
     MEM_LINK_LIST,
     MEM_DLINK_NODE,
diff -u -r -N squid-4.0.2/src/mem/Makefile.in squid-4.0.3/src/mem/Makefile.in
--- squid-4.0.2/src/mem/Makefile.in	2015-11-01 04:19:28.000000000 -0800
+++ squid-4.0.3/src/mem/Makefile.in	2015-11-28 07:32:50.000000000 -0800
@@ -461,6 +461,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -494,7 +495,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/mem/old_api.cc squid-4.0.3/src/mem/old_api.cc
--- squid-4.0.2/src/mem/old_api.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/mem/old_api.cc	2015-11-28 07:30:57.000000000 -0800
@@ -12,11 +12,10 @@
 #include "acl/AclDenyInfoList.h"
 #include "acl/AclNameList.h"
 #include "base/PackableStream.h"
-#include "CacheDigest.h"
 #include "ClientInfo.h"
-#include "disk.h"
 #include "dlink.h"
 #include "event.h"
+#include "fs_io.h"
 #include "icmp/net_db.h"
 #include "md5.h"
 #include "mem/forward.h"
@@ -428,11 +427,6 @@
     memDataInit(MEM_ACL_DENY_INFO_LIST, "AclDenyInfoList",
                 sizeof(AclDenyInfoList), 0);
     memDataInit(MEM_ACL_NAME_LIST, "acl_name_list", sizeof(AclNameList), 0);
-#if USE_CACHE_DIGESTS
-
-    memDataInit(MEM_CACHE_DIGEST, "CacheDigest", sizeof(CacheDigest), 0);
-#endif
-
     memDataInit(MEM_LINK_LIST, "link_list", sizeof(link_list), 10);
     memDataInit(MEM_DLINK_NODE, "dlink_node", sizeof(dlink_node), 10);
     memDataInit(MEM_DREAD_CTRL, "dread_ctrl", sizeof(dread_ctrl), 0);
diff -u -r -N squid-4.0.2/src/MemStore.cc squid-4.0.3/src/MemStore.cc
--- squid-4.0.2/src/MemStore.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/MemStore.cc	2015-11-28 07:30:57.000000000 -0800
@@ -168,25 +168,12 @@
 }
 
 bool
-MemStore::dereference(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)
 {
@@ -220,13 +207,6 @@
     return NULL;
 }
 
-void
-MemStore::get(String const, STOREGETCLIENT, void *)
-{
-    // XXX: not needed but Store parent forces us to implement this
-    fatal("MemStore::get(key,callback,data) should not be called");
-}
-
 bool
 MemStore::anchorCollapsed(StoreEntry &collapsed, bool &inSync)
 {
diff -u -r -N squid-4.0.2/src/MemStore.h squid-4.0.3/src/MemStore.h
--- squid-4.0.2/src/MemStore.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/MemStore.h	2015-11-28 07:30:57.000000000 -0800
@@ -13,6 +13,7 @@
 #include "ipc/mem/PageStack.h"
 #include "ipc/StoreMap.h"
 #include "Store.h"
+#include "store/Controlled.h"
 
 // StoreEntry restoration info not already stored by Ipc::StoreMap
 struct MemStoreMapExtraItem {
@@ -23,7 +24,7 @@
 
 /// 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
+class MemStore: public Store::Controlled, public Ipc::StoreMapCleaner
 {
 public:
     MemStore();
@@ -38,31 +39,27 @@
     /// all data has been received; there will be no more write() calls
     void completeWriting(StoreEntry &e);
 
-    /// remove from the cache
-    void unlink(StoreEntry &e);
-
     /// called when the entry is about to forget its association with mem cache
     void disconnect(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 getStats(StoreInfoStats &stats) const;
-    virtual void stat(StoreEntry &) const;
-    virtual StoreSearch *search(String const url, HttpRequest *);
-    virtual void markForUnlink(StoreEntry &e);
-    virtual void reference(StoreEntry &);
-    virtual bool dereference(StoreEntry &, bool);
-    virtual void maintain();
-    virtual bool anchorCollapsed(StoreEntry &collapsed, bool &inSync);
-    virtual bool updateCollapsed(StoreEntry &collapsed);
+    /* Storage API */
+    virtual void create() override {}
+    virtual void init() override;
+    virtual StoreEntry *get(const cache_key *) override;
+    virtual uint64_t maxSize() const override;
+    virtual uint64_t minSize() const override;
+    virtual uint64_t currentSize() const override;
+    virtual uint64_t currentCount() const override;
+    virtual int64_t maxObjectSize() const override;
+    virtual void getStats(StoreInfoStats &stats) const override;
+    virtual void stat(StoreEntry &e) const override;
+    virtual void reference(StoreEntry &e) override;
+    virtual bool dereference(StoreEntry &e) override;
+    virtual void maintain() override;
+    virtual bool anchorCollapsed(StoreEntry &e, bool &inSync) override;
+    virtual bool updateCollapsed(StoreEntry &e) override;
+    virtual void markForUnlink(StoreEntry &) override;
+    virtual void unlink(StoreEntry &e) override;
 
     static int64_t EntryLimit();
 
@@ -81,7 +78,7 @@
     sfileno reserveSapForWriting(Ipc::Mem::PageId &page);
 
     // Ipc::StoreMapCleaner API
-    virtual void noteFreeMapSlice(const Ipc::StoreMapSliceId sliceId);
+    virtual void noteFreeMapSlice(const Ipc::StoreMapSliceId sliceId) override;
 
 private:
     // TODO: move freeSlots into map
diff -u -r -N squid-4.0.2/src/mgr/Makefile.in squid-4.0.3/src/mgr/Makefile.in
--- squid-4.0.2/src/mgr/Makefile.in	2015-11-01 04:19:29.000000000 -0800
+++ squid-4.0.3/src/mgr/Makefile.in	2015-11-28 07:32:50.000000000 -0800
@@ -465,6 +465,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -498,7 +499,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/mime.cc squid-4.0.3/src/mime.cc
--- squid-4.0.2/src/mime.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/mime.cc	2015-11-28 07:30:57.000000000 -0800
@@ -9,8 +9,8 @@
 /* DEBUG: section 25    MIME Parsing and Internal Icons */
 
 #include "squid.h"
-#include "disk.h"
 #include "fde.h"
+#include "fs_io.h"
 #include "globals.h"
 #include "HttpHdrCc.h"
 #include "HttpReply.h"
diff -u -r -N squid-4.0.2/src/neighbors.cc squid-4.0.3/src/neighbors.cc
--- squid-4.0.2/src/neighbors.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/neighbors.cc	2015-11-28 07:30:57.000000000 -0800
@@ -762,7 +762,7 @@
     assert(p->digest->cd);
     /* does digest predict a hit? */
 
-    if (!cacheDigestTest(p->digest->cd, key))
+    if (!p->digest->cd->contains(key))
         return LOOKUP_MISS;
 
     debugs(15, 5, "peerDigestLookup: peer " << p->host << " says HIT!");
diff -u -r -N squid-4.0.2/src/parser/Makefile.in squid-4.0.3/src/parser/Makefile.in
--- squid-4.0.2/src/parser/Makefile.in	2015-11-01 04:19:29.000000000 -0800
+++ squid-4.0.3/src/parser/Makefile.in	2015-11-28 07:32:51.000000000 -0800
@@ -460,6 +460,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -493,7 +494,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/Parsing.cc squid-4.0.3/src/Parsing.cc
--- squid-4.0.2/src/Parsing.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/Parsing.cc	2015-11-28 07:30:57.000000000 -0800
@@ -163,14 +163,15 @@
  * the percentage symbol (%) and we check whether the value is in the range
  * of [0, 100]
  * So, we accept two types of input: 1. XX% or 2. XX , 0<=XX<=100
+ * unless the limit parameter is set to false.
  */
-int
-GetPercentage(void)
+double
+GetPercentage(bool limit)
 {
     char *token = ConfigParser::NextToken();
 
     if (!token) {
-        debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: A percentage value is missing.");
+        debugs(3, DBG_CRITICAL, "FATAL: A percentage value is missing.");
         self_destruct();
     }
 
@@ -182,12 +183,12 @@
 
     int p = xatoi(token);
 
-    if (p < 0 || p > 100) {
-        debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is out of range. A percentage should be within [0, 100].");
+    if (p < 0 || (limit && p > 100)) {
+        debugs(3, DBG_CRITICAL, "FATAL: The value '" << token << "' is out of range. A percentage should be within [0, 100].");
         self_destruct();
     }
 
-    return p;
+    return static_cast<double>(p) / 100.0;
 }
 
 unsigned short
diff -u -r -N squid-4.0.2/src/Parsing.h squid-4.0.3/src/Parsing.h
--- squid-4.0.2/src/Parsing.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/Parsing.h	2015-11-28 07:30:57.000000000 -0800
@@ -36,10 +36,14 @@
  * Parse a percentage value, e.g., 20%.
  * The behavior of this function is similar as GetInteger().
  * The difference is that the token might contain '%' as percentage symbol (%),
- * and we further check whether the value is in the range of [0, 100]
+ * and we may further check whether the value is in the range of [0, 100].
  * For example, 20% and 20 are both valid tokens, while 101%, 101, -1 are invalid.
+ *
+ * \param limit whether to check the value is within 0-100% limit
+ *
+ * \return the percentage as a decimal number. ie 100% = 1.00, 50% = 0.5
  */
-int GetPercentage(void);
+double GetPercentage(bool limit = true);
 
 unsigned short GetShort(void);
 
diff -u -r -N squid-4.0.2/src/peer_digest.cc squid-4.0.3/src/peer_digest.cc
--- squid-4.0.2/src/peer_digest.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/peer_digest.cc	2015-11-28 07:30:57.000000000 -0800
@@ -35,7 +35,6 @@
 static time_t peerDigestIncDelay(const PeerDigest * pd);
 static time_t peerDigestNewDelay(const StoreEntry * e);
 static void peerDigestSetCheck(PeerDigest * pd, time_t delay);
-static void peerDigestClean(PeerDigest *);
 static EVH peerDigestCheck;
 static void peerDigestRequest(PeerDigest * pd);
 static STCB peerDigestHandleReply;
@@ -86,17 +85,6 @@
     pd->times.initialized = squid_curtime;
 }
 
-static void
-peerDigestClean(PeerDigest * pd)
-{
-    assert(pd);
-
-    if (pd->cd)
-        cacheDigestDestroy(pd->cd);
-
-    pd->host.clean();
-}
-
 CBDATA_CLASS_INIT(PeerDigest);
 
 CBDATA_CLASS_INIT(DigestFetchState);
@@ -171,7 +159,8 @@
     if (cbdataReferenceValidDone(peerTmp, &p))
         peerNoteDigestGone((CachePeer *)p);
 
-    peerDigestClean(pd);
+    delete pd->cd;
+    pd->host.clean();
 
     delete pd;
 }
@@ -200,10 +189,8 @@
     pd->times.next_check = -1;  /* never */
     pd->flags.usable = 0;
 
-    if (pd->cd) {
-        cacheDigestDestroy(pd->cd);
-        pd->cd = NULL;
-    }
+    delete pd->cd
+    pd->cd = nullptr;
 
     /* we do not destroy the pd itself to preserve its "history" and stats */
 }
@@ -861,10 +848,8 @@
     if (err) {
         debugs(72, DBG_IMPORTANT, "" << (pcb_valid ? "temporary " : "" ) << "disabling (" << pd->req_result << ") digest from " << host);
 
-        if (pd->cd) {
-            cacheDigestDestroy(pd->cd);
-            pd->cd = NULL;
-        }
+        delete pd->cd;
+        pd->cd = nullptr;
 
         pd->flags.usable = false;
 
@@ -992,10 +977,10 @@
     }
 
     /* check consistency further */
-    if ((size_t)cblock.mask_size != cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry)) {
+    if ((size_t)cblock.mask_size != CacheDigest::CalcMaskSize(cblock.capacity, cblock.bits_per_entry)) {
         debugs(72, DBG_CRITICAL, host << " digest cblock is corrupted " <<
                "(mask size mismatch: " << cblock.mask_size << " ? " <<
-               cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry)
+               CacheDigest::CalcMaskSize(cblock.capacity, cblock.bits_per_entry)
                << ").");
         return 0;
     }
@@ -1015,14 +1000,14 @@
         debugs(72, 2, host << " digest changed size: " << cblock.mask_size <<
                " -> " << pd->cd->mask_size);
         freed_size = pd->cd->mask_size;
-        cacheDigestDestroy(pd->cd);
-        pd->cd = NULL;
+        delete pd->cd;
+        pd->cd = nullptr;
     }
 
     if (!pd->cd) {
         debugs(72, 2, "creating " << host << " digest; size: " << cblock.mask_size << " (" <<
                std::showpos <<  (int) (cblock.mask_size - freed_size) << ") bytes");
-        pd->cd = cacheDigestCreate(cblock.capacity, cblock.bits_per_entry);
+        pd->cd = new CacheDigest(cblock.capacity, cblock.bits_per_entry);
 
         if (cblock.mask_size >= freed_size)
             statCounter.cd.memory += (cblock.mask_size - freed_size);
@@ -1039,12 +1024,11 @@
 peerDigestUseful(const PeerDigest * pd)
 {
     /* TODO: we should calculate the prob of a false hit instead of bit util */
-    const int bit_util = cacheDigestBitUtil(pd->cd);
+    const auto bit_util = pd->cd->usedMaskPercent();
 
-    if (bit_util > 65) {
+    if (bit_util > 65.0) {
         debugs(72, DBG_CRITICAL, "Warning: " << pd->host <<
-               " peer digest has too many bits on (" << bit_util << "%%).");
-
+               " peer digest has too many bits on (" << bit_util << "%).");
         return 0;
     }
 
diff -u -r -N squid-4.0.2/src/Pipeline.cc squid-4.0.3/src/Pipeline.cc
--- squid-4.0.2/src/Pipeline.cc	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/Pipeline.cc	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/*
+ * DEBUG: section 33    Client Request Pipeline
+ */
+#include "squid.h"
+#include "anyp/PortCfg.h"
+#include "client_side.h"
+#include "Debug.h"
+#include "Pipeline.h"
+
+void
+Pipeline::add(const ClientSocketContextPointer &c)
+{
+    requests.push_back(c);
+    ++nrequests;
+    debugs(33, 3, "Pipeline " << (void*)this << " add request " << nrequests << ' ' << c);
+}
+
+ClientSocketContextPointer
+Pipeline::front() const
+{
+    if (requests.empty()) {
+        debugs(33, 3, "Pipeline " << (void*)this << " empty");
+        return ClientSocketContextPointer();
+    }
+
+    debugs(33, 3, "Pipeline " << (void*)this << " front " << requests.front());
+    return requests.front();
+}
+
+void
+Pipeline::terminateAll(int xerrno)
+{
+    while (!requests.empty()) {
+        ClientSocketContextPointer context = requests.front();
+        debugs(33, 3, "Pipeline " << (void*)this << " notify(" << xerrno << ") " << context);
+        context->noteIoError(xerrno);
+        context->finished();  // cleanup and self-deregister
+        assert(context != requests.front());
+    }
+}
+
+void
+Pipeline::popMe(const ClientSocketContextPointer &which)
+{
+    if (requests.empty())
+        return;
+
+    debugs(33, 3, "Pipeline " << (void*)this << " drop " << requests.front());
+    // in reality there may be multiple contexts doing processing in parallel.
+    // XXX: pipeline still assumes HTTP/1 FIFO semantics are obeyed.
+    assert(which == requests.front());
+    requests.pop_front();
+}
+
diff -u -r -N squid-4.0.2/src/Pipeline.h squid-4.0.3/src/Pipeline.h
--- squid-4.0.2/src/Pipeline.h	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/Pipeline.h	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_SRC_PIPELINE_H
+#define SQUID_SRC_PIPELINE_H
+
+#include "base/RefCount.h"
+
+#include <list>
+
+class ClientSocketContext;
+typedef RefCount<ClientSocketContext> ClientSocketContextPointer;
+
+/**
+ * A queue of transactions awaiting completion.
+ *
+ * Transactions in the queue may be fully processed, but not yet delivered,
+ * or only partially processed.
+ *
+ * - HTTP/1 pipelined requests can be processed out of order but
+ *   responses MUST be written to the client in-order.
+ *   The front() context is for the response writing transaction.
+ *   The back context may still be reading a request payload/body.
+ *   Other contexts are in deferred I/O state, but may be accumulating
+ *   payload/body data to be written later.
+ *
+ * - HTTP/2 multiplexed streams can be processed and delivered in any order.
+ *
+ * For consistency we treat the pipeline as a FIFO queue in both cases.
+ */
+class Pipeline
+{
+    Pipeline(const Pipeline &) = delete;
+    Pipeline & operator =(const Pipeline &) = delete;
+
+public:
+    Pipeline() : nrequests(0) {}
+    ~Pipeline() = default;
+
+    /// register a new request context to the pipeline
+    void add(const ClientSocketContextPointer &);
+
+    /// get the first request context in the pipeline
+    ClientSocketContextPointer front() const;
+
+    /// how many requests are currently pipelined
+    size_t count() const {return requests.size();}
+
+    /// whether there are none or any requests currently pipelined
+    bool empty() const {return requests.empty();}
+
+    /// tell everybody about the err, and abort all waiting requests
+    void terminateAll(const int xerrno);
+
+    /// deregister the front request from the pipeline
+    void popMe(const ClientSocketContextPointer &);
+
+    /// Number of requests seen in this pipeline (so far).
+    /// Includes incomplete transactions.
+    uint32_t nrequests;
+
+private:
+    /// requests parsed from the connection but not yet completed.
+    std::list<ClientSocketContextPointer> requests;
+};
+
+#endif /* SQUID_SRC_PIPELINE_H */
+
diff -u -r -N squid-4.0.2/src/repl/Makefile.in squid-4.0.3/src/repl/Makefile.in
--- squid-4.0.2/src/repl/Makefile.in	2015-11-01 04:19:30.000000000 -0800
+++ squid-4.0.3/src/repl/Makefile.in	2015-11-28 07:32:51.000000000 -0800
@@ -471,6 +471,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -504,7 +505,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/SBuf.h squid-4.0.3/src/SBuf.h
--- squid-4.0.2/src/SBuf.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/SBuf.h	2015-11-28 07:30:57.000000000 -0800
@@ -13,6 +13,7 @@
 
 #include "base/InstanceId.h"
 #include "Debug.h"
+#include "globals.h"
 #include "MemBlob.h"
 #include "SBufExceptions.h"
 #include "SquidString.h"
diff -u -r -N squid-4.0.2/src/security/Context.h squid-4.0.3/src/security/Context.h
--- squid-4.0.2/src/security/Context.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/security/Context.h	2015-11-28 07:30:57.000000000 -0800
@@ -24,14 +24,14 @@
 namespace Security {
 
 #if USE_OPENSSL
-typedef SSL_CTX* ContextPointer;
+typedef SSL_CTX* ContextPtr;
 
 #elif USE_GNUTLS
-typedef gnutls_certificate_credentials_t ContextPointer;
+typedef gnutls_certificate_credentials_t ContextPtr;
 
 #else
-// use void* so we can check against NULL
-typedef void* ContextPointer;
+// use void* so we can check against nullptr
+typedef void* ContextPtr;
 #endif
 
 } // namespace Security
diff -u -r -N squid-4.0.2/src/security/Makefile.in squid-4.0.3/src/security/Makefile.in
--- squid-4.0.2/src/security/Makefile.in	2015-11-01 04:19:30.000000000 -0800
+++ squid-4.0.3/src/security/Makefile.in	2015-11-28 07:32:52.000000000 -0800
@@ -461,6 +461,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -494,7 +495,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/security/PeerOptions.cc squid-4.0.3/src/security/PeerOptions.cc
--- squid-4.0.2/src/security/PeerOptions.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/security/PeerOptions.cc	2015-11-28 07:30:57.000000000 -0800
@@ -193,10 +193,10 @@
 }
 
 // XXX: make a GnuTLS variant
-Security::ContextPointer
+Security::ContextPtr
 Security::PeerOptions::createClientContext(bool setOptions)
 {
-    Security::ContextPointer t = nullptr;
+    Security::ContextPtr t = nullptr;
 
     updateTlsVersionLimits();
 
@@ -488,7 +488,7 @@
 }
 
 void
-Security::PeerOptions::updateContextCa(Security::ContextPointer &ctx)
+Security::PeerOptions::updateContextCa(Security::ContextPtr &ctx)
 {
     debugs(83, 8, "Setting CA certificate locations.");
 
@@ -522,7 +522,7 @@
 }
 
 void
-Security::PeerOptions::updateContextCrl(Security::ContextPointer &ctx)
+Security::PeerOptions::updateContextCrl(Security::ContextPtr &ctx)
 {
 #if USE_OPENSSL
     bool verifyCrl = false;
diff -u -r -N squid-4.0.2/src/security/PeerOptions.h squid-4.0.3/src/security/PeerOptions.h
--- squid-4.0.2/src/security/PeerOptions.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/security/PeerOptions.h	2015-11-28 07:30:57.000000000 -0800
@@ -33,16 +33,16 @@
     virtual void clear() {*this = PeerOptions();}
 
     /// generate a security client-context from these configured options
-    Security::ContextPointer createClientContext(bool setOptions);
+    Security::ContextPtr createClientContext(bool setOptions);
 
     /// sync the context options with tls-min-version=N configuration
     void updateTlsVersionLimits();
 
     /// setup the CA details for the given context
-    void updateContextCa(Security::ContextPointer &);
+    void updateContextCa(Security::ContextPtr &);
 
     /// setup the CRL details for the given context
-    void updateContextCrl(Security::ContextPointer &);
+    void updateContextCrl(Security::ContextPtr &);
 
     /// output squid.conf syntax with 'pfx' prefix on parameters for the stored settings
     virtual void dumpCfg(Packable *, const char *pfx) const;
diff -u -r -N squid-4.0.2/src/security/ServerOptions.cc squid-4.0.3/src/security/ServerOptions.cc
--- squid-4.0.2/src/security/ServerOptions.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/security/ServerOptions.cc	2015-11-28 07:30:57.000000000 -0800
@@ -122,7 +122,7 @@
 }
 
 void
-Security::ServerOptions::updateContextEecdh(Security::ContextPointer &ctx)
+Security::ServerOptions::updateContextEecdh(Security::ContextPtr &ctx)
 {
     // set Elliptic Curve details into the server context
     if (!eecdhCurve.isEmpty()) {
diff -u -r -N squid-4.0.2/src/security/ServerOptions.h squid-4.0.3/src/security/ServerOptions.h
--- squid-4.0.2/src/security/ServerOptions.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/security/ServerOptions.h	2015-11-28 07:30:57.000000000 -0800
@@ -28,7 +28,7 @@
     virtual void dumpCfg(Packable *, const char *pfx) const;
 
     /// update the context with DH, EDH, EECDH settings
-    void updateContextEecdh(Security::ContextPointer &);
+    void updateContextEecdh(Security::ContextPtr &);
 
 private:
     void loadDhParams();
diff -u -r -N squid-4.0.2/src/send-announce.cc squid-4.0.3/src/send-announce.cc
--- squid-4.0.2/src/send-announce.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/send-announce.cc	2015-11-28 07:30:57.000000000 -0800
@@ -11,10 +11,10 @@
 #include "squid.h"
 #include "anyp/PortCfg.h"
 #include "comm/Connection.h"
-#include "disk.h"
 #include "event.h"
 #include "fd.h"
 #include "fde.h"
+#include "fs_io.h"
 #include "globals.h"
 #include "ICP.h"
 #include "ipcache.h"
diff -u -r -N squid-4.0.2/src/servers/FtpServer.cc squid-4.0.3/src/servers/FtpServer.cc
--- squid-4.0.2/src/servers/FtpServer.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/servers/FtpServer.cc	2015-11-28 07:30:57.000000000 -0800
@@ -124,9 +124,9 @@
 Ftp::Server::doProcessRequest()
 {
     // zero pipelinePrefetchMax() ensures that there is only parsed request
-    ClientSocketContext::Pointer context = getCurrentContext();
-    Must(context != NULL);
-    Must(getConcurrentRequestCount() == 1);
+    Must(pipeline.count() == 1);
+    ClientSocketContext::Pointer context = pipeline.front();
+    Must(context != nullptr);
 
     ClientHttpRequest *const http = context->http;
     assert(http != NULL);
@@ -151,7 +151,7 @@
 void
 Ftp::Server::processParsedRequest(ClientSocketContext *)
 {
-    Must(getConcurrentRequestCount() == 1);
+    Must(pipeline.count() == 1);
 
     // Process FTP request asynchronously to make sure FTP
     // data connection accept callback is fired first.
@@ -288,8 +288,8 @@
 Ftp::Server::notePeerConnection(Comm::ConnectionPointer conn)
 {
     // find request
-    ClientSocketContext::Pointer context = getCurrentContext();
-    Must(context != NULL);
+    ClientSocketContext::Pointer context = pipeline.front();
+    Must(context != nullptr);
     ClientHttpRequest *const http = context->http;
     Must(http != NULL);
     HttpRequest *const request = http->request;
@@ -640,7 +640,7 @@
     SBuf cmd;
     SBuf params;
 
-    Parser::Tokenizer tok(in.buf);
+    Parser::Tokenizer tok(inBuf);
 
     (void)tok.skipAll(LeadingSpace); // leading OWS and empty commands
     const bool parsed = tok.prefix(cmd, CommandChars); // required command
@@ -667,14 +667,14 @@
     // technically, we may skip multiple NLs below, but that is OK
     if (!parsed || !tok.skipAll(CharacterSet::LF)) { // did not find terminating LF yet
         // we need more data, but can we buffer more?
-        if (in.buf.length() >= Config.maxRequestHeaderSize) {
+        if (inBuf.length() >= Config.maxRequestHeaderSize) {
             changeState(fssError, "huge req");
             quitAfterError(NULL);
             return earlyError(EarlyErrorKind::HugeRequest);
         } else {
             flags.readMore = true;
             debugs(33, 5, "Waiting for more, up to " <<
-                   (Config.maxRequestHeaderSize - in.buf.length()));
+                   (Config.maxRequestHeaderSize - inBuf.length()));
             return NULL;
         }
     }
@@ -761,8 +761,8 @@
 Ftp::Server::handleReply(HttpReply *reply, StoreIOBuffer data)
 {
     // the caller guarantees that we are dealing with the current context only
-    ClientSocketContext::Pointer context = getCurrentContext();
-    assert(context != NULL);
+    ClientSocketContext::Pointer context = pipeline.front();
+    assert(context != nullptr);
 
     if (context->http && context->http->al != NULL &&
             !context->http->al->reply && reply) {
@@ -800,7 +800,7 @@
 void
 Ftp::Server::handleFeatReply(const HttpReply *reply, StoreIOBuffer)
 {
-    if (getCurrentContext()->http->request->errType != ERR_NONE) {
+    if (pipeline.front()->http->request->errType != ERR_NONE) {
         writeCustomReply(502, "Server does not support FEAT", reply);
         return;
     }
@@ -869,8 +869,8 @@
 void
 Ftp::Server::handlePasvReply(const HttpReply *reply, StoreIOBuffer)
 {
-    ClientSocketContext::Pointer context = getCurrentContext();
-    assert(context != NULL);
+    const ClientSocketContext::Pointer context(pipeline.front());
+    assert(context != nullptr);
 
     if (context->http->request->errType != ERR_NONE) {
         writeCustomReply(502, "Server does not support PASV", reply);
@@ -909,7 +909,7 @@
 void
 Ftp::Server::handlePortReply(const HttpReply *reply, StoreIOBuffer)
 {
-    if (getCurrentContext()->http->request->errType != ERR_NONE) {
+    if (pipeline.front()->http->request->errType != ERR_NONE) {
         writeCustomReply(502, "Server does not support PASV (converted from PORT)", reply);
         return;
     }
@@ -967,7 +967,7 @@
     AsyncCall::Pointer call = JobCallback(33, 5, Dialer, this, Ftp::Server::wroteReplyData);
     Comm::Write(dataConn, &mb, call);
 
-    getCurrentContext()->noteSentBodyBytes(data.length);
+    pipeline.front()->noteSentBodyBytes(data.length);
 }
 
 /// called when we are done writing a chunk of the response data
@@ -984,8 +984,8 @@
         return;
     }
 
-    assert(getCurrentContext()->http);
-    getCurrentContext()->http->out.size += io.size;
+    assert(pipeline.front()->http);
+    pipeline.front()->http->out.size += io.size;
     replyDataWritingCheckpoint();
 }
 
@@ -993,10 +993,10 @@
 void
 Ftp::Server::replyDataWritingCheckpoint()
 {
-    switch (getCurrentContext()->socketState()) {
+    switch (pipeline.front()->socketState()) {
     case STREAM_NONE:
         debugs(33, 3, "Keep going");
-        getCurrentContext()->pullData();
+        pipeline.front()->pullData();
         return;
     case STREAM_COMPLETE:
         debugs(33, 3, "FTP reply data transfer successfully complete");
@@ -1044,7 +1044,7 @@
 void
 Ftp::Server::handleEprtReply(const HttpReply *reply, StoreIOBuffer)
 {
-    if (getCurrentContext()->http->request->errType != ERR_NONE) {
+    if (pipeline.front()->http->request->errType != ERR_NONE) {
         writeCustomReply(502, "Server does not support PASV (converted from EPRT)", reply);
         return;
     }
@@ -1057,7 +1057,7 @@
 void
 Ftp::Server::handleEpsvReply(const HttpReply *reply, StoreIOBuffer)
 {
-    if (getCurrentContext()->http->request->errType != ERR_NONE) {
+    if (pipeline.front()->http->request->errType != ERR_NONE) {
         writeCustomReply(502, "Cannot connect to server", reply);
         return;
     }
@@ -1080,7 +1080,7 @@
 void
 Ftp::Server::writeErrorReply(const HttpReply *reply, const int scode)
 {
-    const HttpRequest *request = getCurrentContext()->http->request;
+    const HttpRequest *request = pipeline.front()->http->request;
     assert(request);
 
     MemBuf mb;
@@ -1227,8 +1227,8 @@
         return;
     }
 
-    ClientSocketContext::Pointer context = getCurrentContext();
-    if (context != NULL && context->http) {
+    ClientSocketContext::Pointer context = pipeline.front();
+    if (context != nullptr && context->http) {
         context->http->out.size += io.size;
         context->http->out.headers_sz += io.size;
     }
@@ -1249,7 +1249,7 @@
         return;
     }
 
-    ClientSocketContext::Pointer context = getCurrentContext();
+    ClientSocketContext::Pointer context = pipeline.front();
     assert(context->http);
     context->http->out.size += io.size;
     context->http->out.headers_sz += io.size;
@@ -1272,9 +1272,10 @@
     case STREAM_COMPLETE:
         flags.readMore = true;
         changeState(fssConnected, "Ftp::Server::wroteReply");
-        if (in.bodyParser)
+        if (bodyParser)
             finishDechunkingRequest(false);
-        context->keepaliveNextRequest();
+        context->finished();
+        kick();
         return;
     }
 }
@@ -1494,7 +1495,7 @@
         return false;
 
     if (Config.accessList.forceRequestBodyContinuation) {
-        ClientHttpRequest *http = getCurrentContext()->http;
+        ClientHttpRequest *http = pipeline.front()->http;
         HttpRequest *request = http->request;
         ACLFilledChecklist bodyContinuationCheck(Config.accessList.forceRequestBodyContinuation, request, NULL);
         if (bodyContinuationCheck.fastCheck() == ACCESS_ALLOWED) {
@@ -1598,7 +1599,7 @@
 void
 Ftp::Server::setDataCommand()
 {
-    ClientHttpRequest *const http = getCurrentContext()->http;
+    ClientHttpRequest *const http = pipeline.front()->http;
     assert(http != NULL);
     HttpRequest *const request = http->request;
     assert(request != NULL);
@@ -1664,7 +1665,7 @@
         if (params.conn != NULL)
             params.conn->close();
         setReply(425, "Cannot open data connection.");
-        ClientSocketContext::Pointer context = getCurrentContext();
+        ClientSocketContext::Pointer context = pipeline.front();
         Must(context->http);
         Must(context->http->storeEntry() != NULL);
     } else {
@@ -1679,7 +1680,7 @@
 void
 Ftp::Server::setReply(const int code, const char *msg)
 {
-    ClientSocketContext::Pointer context = getCurrentContext();
+    ClientSocketContext::Pointer context = pipeline.front();
     ClientHttpRequest *const http = context->http;
     assert(http != NULL);
     assert(http->storeEntry() == NULL);
diff -u -r -N squid-4.0.2/src/servers/Http1Server.cc squid-4.0.3/src/servers/Http1Server.cc
--- squid-4.0.2/src/servers/Http1Server.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/servers/Http1Server.cc	2015-11-28 07:30:57.000000000 -0800
@@ -121,7 +121,7 @@
         }
         // setLogUri should called before repContext->setReplyToError
         setLogUri(http, http->uri, true);
-        const char * requestErrorBytes = in.buf.c_str();
+        const char * requestErrorBytes = inBuf.c_str();
         if (!clientTunnelOnError(this, context, request.getRaw(), parser_->method(), errPage, parser_->parseStatusCode, requestErrorBytes)) {
             // HttpRequest object not build yet, there is no reason to call
             // clientProcessRequestFinished method
@@ -135,7 +135,7 @@
         // setLogUri should called before repContext->setReplyToError
         setLogUri(http, http->uri, true);
 
-        const char * requestErrorBytes = in.buf.c_str();
+        const char * requestErrorBytes = inBuf.c_str();
         if (!clientTunnelOnError(this, context, request.getRaw(), parser_->method(), ERR_INVALID_URL, Http::scBadRequest, requestErrorBytes)) {
             // HttpRequest object not build yet, there is no reason to call
             // clientProcessRequestFinished method
@@ -242,8 +242,8 @@
 Http::One::Server::handleReply(HttpReply *rep, StoreIOBuffer receivedData)
 {
     // the caller guarantees that we are dealing with the current context only
-    ClientSocketContext::Pointer context = getCurrentContext();
-    Must(context != NULL);
+    ClientSocketContext::Pointer context = pipeline.front();
+    Must(context != nullptr);
     const ClientHttpRequest *http = context->http;
     Must(http != NULL);
 
@@ -279,7 +279,7 @@
     // it is not clear what headers are required for control messages
     rep->header.removeHopByHopEntries();
     rep->header.putStr(Http::HdrType::CONNECTION, "keep-alive");
-    httpHdrMangleList(&rep->header, getCurrentContext()->http->request, ROR_REPLY);
+    httpHdrMangleList(&rep->header, pipeline.front()->http->request, ROR_REPLY);
 
     MemBuf *mb = rep->pack();
 
diff -u -r -N squid-4.0.2/src/servers/Makefile.am squid-4.0.3/src/servers/Makefile.am
--- squid-4.0.2/src/servers/Makefile.am	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/servers/Makefile.am	2015-11-28 07:30:57.000000000 -0800
@@ -11,8 +11,10 @@
 noinst_LTLIBRARIES = libservers.la
 
 libservers_la_SOURCES = \
+	forward.h \
 	FtpServer.cc \
 	FtpServer.h \
 	Http1Server.cc \
 	Http1Server.h \
-	forward.h
+	Server.cc \
+	Server.h
diff -u -r -N squid-4.0.2/src/servers/Makefile.in squid-4.0.3/src/servers/Makefile.in
--- squid-4.0.2/src/servers/Makefile.in	2015-11-01 04:19:31.000000000 -0800
+++ squid-4.0.3/src/servers/Makefile.in	2015-11-28 07:32:52.000000000 -0800
@@ -159,7 +159,7 @@
 CONFIG_CLEAN_VPATH_FILES =
 LTLIBRARIES = $(noinst_LTLIBRARIES)
 libservers_la_LIBADD =
-am_libservers_la_OBJECTS = FtpServer.lo Http1Server.lo
+am_libservers_la_OBJECTS = FtpServer.lo Http1Server.lo Server.lo
 libservers_la_OBJECTS = $(am_libservers_la_OBJECTS)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -460,6 +460,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -493,7 +494,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
@@ -692,11 +692,13 @@
 subst_perlshell = sed -e 's,[@]PERL[@],$(PERL),g' <$(srcdir)/$@.pl.in >$@ || ($(RM) -f $@ ; exit 1)
 noinst_LTLIBRARIES = libservers.la
 libservers_la_SOURCES = \
+	forward.h \
 	FtpServer.cc \
 	FtpServer.h \
 	Http1Server.cc \
 	Http1Server.h \
-	forward.h
+	Server.cc \
+	Server.h
 
 all: all-am
 
@@ -764,6 +766,7 @@
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpServer.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Http1Server.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Server.Plo@am__quote@
 
 .cc.o:
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
diff -u -r -N squid-4.0.2/src/servers/Server.cc squid-4.0.3/src/servers/Server.cc
--- squid-4.0.2/src/servers/Server.cc	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/servers/Server.cc	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#include "squid.h"
+#include "anyp/PortCfg.h"
+#include "client_side.h"
+#include "comm.h"
+#include "comm/Read.h"
+#include "Debug.h"
+#include "fd.h"
+#include "fde.h"
+#include "MasterXaction.h"
+#include "servers/Server.h"
+#include "SquidConfig.h"
+#include "StatCounters.h"
+#include "tools.h"
+
+Server::Server(const MasterXaction::Pointer &xact) :
+    AsyncJob("::Server"), // kids overwrite
+    clientConnection(xact->tcpClient),
+    transferProtocol(xact->squidPort->transport),
+    port(xact->squidPort),
+    receivedFirstByte_(false)
+{}
+
+bool
+Server::doneAll() const
+{
+    // servers are not done while the connection is open
+    return !Comm::IsConnOpen(clientConnection) &&
+           BodyProducer::doneAll();
+}
+
+void
+Server::start()
+{
+    // TODO: shuffle activity from ConnStateData
+}
+
+void
+Server::swanSong()
+{
+    if (Comm::IsConnOpen(clientConnection))
+        clientConnection->close();
+
+    BodyProducer::swanSong();
+}
+
+void
+Server::stopReading()
+{
+    if (reading()) {
+        Comm::ReadCancel(clientConnection->fd, reader);
+        reader = NULL;
+    }
+}
+
+bool
+Server::maybeMakeSpaceAvailable()
+{
+    if (inBuf.spaceSize() < 2) {
+        const SBuf::size_type haveCapacity = inBuf.length() + inBuf.spaceSize();
+        if (haveCapacity >= Config.maxRequestBufferSize) {
+            debugs(33, 4, "request buffer full: client_request_buffer_max_size=" << Config.maxRequestBufferSize);
+            return false;
+        }
+        if (haveCapacity == 0) {
+            // haveCapacity is based on the SBuf visible window of the MemBlob buffer, which may fill up.
+            // at which point bump the buffer back to default. This allocates a new MemBlob with any un-parsed bytes.
+            inBuf.reserveCapacity(CLIENT_REQ_BUF_SZ);
+        } else {
+            const SBuf::size_type wantCapacity = min(static_cast<SBuf::size_type>(Config.maxRequestBufferSize), haveCapacity*2);
+            inBuf.reserveCapacity(wantCapacity);
+        }
+        debugs(33, 2, "growing request buffer: available=" << inBuf.spaceSize() << " used=" << inBuf.length());
+    }
+    return (inBuf.spaceSize() >= 2);
+}
+
+void
+Server::readSomeData()
+{
+    if (reading())
+        return;
+
+    debugs(33, 4, clientConnection << ": reading request...");
+
+    // we can only read if there is more than 1 byte of space free
+    if (Config.maxRequestBufferSize - inBuf.length() < 2)
+        return;
+
+    typedef CommCbMemFunT<Server, CommIoCbParams> Dialer;
+    reader = JobCallback(33, 5, Dialer, this, Server::doClientRead);
+    Comm::Read(clientConnection, reader);
+}
+
+void
+Server::doClientRead(const CommIoCbParams &io)
+{
+    debugs(33,5, io.conn);
+    Must(reading());
+    reader = NULL;
+
+    /* Bail out quickly on Comm::ERR_CLOSING - close handlers will tidy up */
+    if (io.flag == Comm::ERR_CLOSING) {
+        debugs(33,5, io.conn << " closing Bailout.");
+        return;
+    }
+
+    assert(Comm::IsConnOpen(clientConnection));
+    assert(io.conn->fd == clientConnection->fd);
+
+    /*
+     * Don't reset the timeout value here. The value should be
+     * counting Config.Timeout.request and applies to the request
+     * as a whole, not individual read() calls.
+     * Plus, it breaks our lame *HalfClosed() detection
+     */
+
+    maybeMakeSpaceAvailable();
+    CommIoCbParams rd(this); // will be expanded with ReadNow results
+    rd.conn = io.conn;
+    switch (Comm::ReadNow(rd, inBuf)) {
+    case Comm::INPROGRESS:
+
+        if (inBuf.isEmpty())
+            debugs(33, 2, io.conn << ": no data to process, " << xstrerr(rd.xerrno));
+        readSomeData();
+        return;
+
+    case Comm::OK:
+        statCounter.client_http.kbytes_in += rd.size;
+        if (!receivedFirstByte_)
+            receivedFirstByte();
+        // may comm_close or setReplyToError
+        if (!handleReadData())
+            return;
+
+        /* Continue to process previously read data */
+        break;
+
+    case Comm::ENDFILE: // close detected by 0-byte read
+        debugs(33, 5, io.conn << " closed?");
+
+        if (connFinishedWithConn(rd.size)) {
+            clientConnection->close();
+            return;
+        }
+
+        /* It might be half-closed, we can't tell */
+        fd_table[io.conn->fd].flags.socket_eof = true;
+        commMarkHalfClosed(io.conn->fd);
+        fd_note(io.conn->fd, "half-closed");
+
+        /* There is one more close check at the end, to detect aborted
+         * (partial) requests. At this point we can't tell if the request
+         * is partial.
+         */
+
+        /* Continue to process previously read data */
+        break;
+
+    // case Comm::COMM_ERROR:
+    default: // no other flags should ever occur
+        debugs(33, 2, io.conn << ": got flag " << rd.flag << "; " << xstrerr(rd.xerrno));
+        pipeline.terminateAll(rd.xerrno);
+        io.conn->close();
+        return;
+    }
+
+    afterClientRead();
+}
+
+void
+Server::clientWriteDone(const CommIoCbParams &io)
+{
+    debugs(33,5, io.conn);
+    Must(writer != NULL);
+    writer = NULL;
+
+    /* Bail out quickly on Comm::ERR_CLOSING - close handlers will tidy up */
+    if (io.flag == Comm::ERR_CLOSING) {
+        debugs(33,5, io.conn << " closing Bailout.");
+        return;
+    }
+
+    assert(Comm::IsConnOpen(clientConnection));
+    assert(io.conn->fd == clientConnection->fd);
+
+    writeSomeData(); // maybe schedules another write
+}
+
diff -u -r -N squid-4.0.2/src/servers/Server.h squid-4.0.3/src/servers/Server.h
--- squid-4.0.2/src/servers/Server.h	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/servers/Server.h	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/* DEBUG: section 33    Client-side Routines */
+
+#ifndef SQUID_SERVERS_SERVER_H
+#define SQUID_SERVERS_SERVER_H
+
+#include "anyp/forward.h"
+#include "anyp/ProtocolVersion.h"
+#include "base/AsyncJob.h"
+#include "BodyPipe.h"
+#include "comm/forward.h"
+#include "CommCalls.h"
+#include "Pipeline.h"
+#include "SBuf.h"
+
+/**
+ * Common base for all Server classes used
+ * to manage connections from clients.
+ */
+class Server : virtual public AsyncJob, public BodyProducer
+{
+public:
+    Server(const MasterXaction::Pointer &xact);
+    virtual ~Server() {}
+
+    /* AsyncJob API */
+    virtual void start();
+    virtual bool doneAll() const;
+    virtual void swanSong();
+
+    /// ??
+    virtual bool connFinishedWithConn(int size) = 0;
+
+    /// processing to be done after a Comm::Read()
+    virtual void afterClientRead() = 0;
+
+    /// maybe grow the inBuf and schedule Comm::Read()
+    void readSomeData();
+
+    /**
+     * called when new request data has been read from the socket
+     *
+     * \retval false called comm_close or setReplyToError (the caller should bail)
+     * \retval true  we did not call comm_close or setReplyToError
+     */
+    virtual bool handleReadData() = 0;
+
+    /// whether Comm::Read() is scheduled
+    bool reading() const {return reader != NULL;}
+
+    /// cancels Comm::Read() if it is scheduled
+    void stopReading();
+
+    /// Update flags and timeout after the first byte received
+    virtual void receivedFirstByte() = 0;
+
+    /// maybe schedule another Comm::Write() and perform any
+    /// processing to be done after previous Comm::Write() completes
+    virtual void writeSomeData() {}
+
+    /// whether Comm::Write() is scheduled
+    bool writing() const {return writer != NULL;}
+
+// XXX: should be 'protected:' for child access only,
+//      but all sorts of code likes to play directly
+//      with the I/O buffers and socket.
+public:
+
+    /// grows the available read buffer space (if possible)
+    bool maybeMakeSpaceAvailable();
+
+    // Client TCP connection details from comm layer.
+    Comm::ConnectionPointer clientConnection;
+
+    /**
+     * The transfer protocol currently being spoken on this connection.
+     * HTTP/1.x CONNECT, HTTP/1.1 Upgrade and HTTP/2 SETTINGS offer the
+     * ability to change protocols on the fly.
+     */
+    AnyP::ProtocolVersion transferProtocol;
+
+    /// Squid listening port details where this connection arrived.
+    AnyP::PortCfgPointer port;
+
+    /// read I/O buffer for the client connection
+    SBuf inBuf;
+
+    bool receivedFirstByte_; ///< true if at least one byte received on this connection
+
+    /// set of requests waiting to be serviced
+    Pipeline pipeline;
+
+protected:
+    void doClientRead(const CommIoCbParams &io);
+    void clientWriteDone(const CommIoCbParams &io);
+
+    AsyncCall::Pointer reader; ///< set when we are reading
+    AsyncCall::Pointer writer; ///< set when we are writing
+};
+
+#endif /* SQUID_SERVERS_SERVER_H */
+
diff -u -r -N squid-4.0.2/src/snmp/Makefile.in squid-4.0.3/src/snmp/Makefile.in
--- squid-4.0.2/src/snmp/Makefile.in	2015-11-01 04:19:31.000000000 -0800
+++ squid-4.0.3/src/snmp/Makefile.in	2015-11-28 07:32:53.000000000 -0800
@@ -461,6 +461,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -494,7 +495,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/SquidConfig.h squid-4.0.3/src/SquidConfig.h
--- squid-4.0.2/src/SquidConfig.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/SquidConfig.h	2015-11-28 07:30:57.000000000 -0800
@@ -19,6 +19,7 @@
 #include "Notes.h"
 #include "security/forward.h"
 #include "SquidTime.h"
+#include "store/forward.h"
 #include "YesNoNone.h"
 
 #if USE_OPENSSL
@@ -37,13 +38,24 @@
 class HeaderManglers;
 class RefreshPattern;
 class RemovalPolicySettings;
-class SwapDir;
 
 namespace AnyP
 {
 class PortCfg;
 }
 
+namespace Store {
+class DiskConfig {
+public:
+    RefCount<SwapDir> *swapDirs;
+    int n_allocated;
+    int n_configured;
+    /// number of disk processes required to support all cache_dirs
+    int n_strands;
+};
+#define INDEXSD(i) (Config.cacheSwap.swapDirs[i].getRaw())
+}
+
 /// the representation of the configuration. POD.
 class SquidConfig
 {
@@ -392,17 +404,7 @@
     } Ftp;
     RefreshPattern *Refresh;
 
-    struct _cacheSwap {
-        RefCount<SwapDir> *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 ..
-     */
-#define INDEXSD(i)   (Config.cacheSwap.swapDirs[(i)].getRaw())
+    Store::DiskConfig cacheSwap;
 
     struct {
         char *directory;
@@ -492,7 +494,7 @@
     external_acl *externalAclHelperList;
 
     struct {
-        Security::ContextPointer sslContext;
+        Security::ContextPtr sslContext;
 #if USE_OPENSSL
         acl_access *cert_error;
         sslproxy_cert_sign *cert_sign;
diff -u -r -N squid-4.0.2/src/ssl/helper.cc squid-4.0.3/src/ssl/helper.cc
--- squid-4.0.2/src/ssl/helper.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/ssl/helper.cc	2015-11-28 07:30:57.000000000 -0800
@@ -9,6 +9,7 @@
 #include "squid.h"
 #include "../helper.h"
 #include "anyp/PortCfg.h"
+#include "fs_io.h"
 #include "helper/Reply.h"
 #include "SquidConfig.h"
 #include "SquidString.h"
@@ -16,7 +17,6 @@
 #include "ssl/cert_validate_message.h"
 #include "ssl/Config.h"
 #include "ssl/helper.h"
-#include "SwapDir.h"
 #include "wordlist.h"
 
 LruMap<Ssl::CertValidationResponse> *Ssl::CertValidationHelper::HelperCache = NULL;
@@ -46,8 +46,6 @@
     bool found = false;
     for (AnyP::PortCfgPointer s = HttpPortList; !found && s != NULL; s = s->next)
         found = s->flags.tunnelSslBumping && s->generateHostCertificates;
-    for (AnyP::PortCfgPointer s = HttpsPortList; !found && s != NULL; s = s->next)
-        found = s->flags.tunnelSslBumping && s->generateHostCertificates;
     if (!found)
         return;
 
@@ -74,7 +72,7 @@
             } else if (db_path_was_found) {
                 db_path_was_found = false;
                 int fs_block_size = 0;
-                storeDirGetBlkSize(token, &fs_block_size);
+                fsBlockSize(token, &fs_block_size);
                 snprintf(buffer, sizeof(buffer), "%i", fs_block_size);
             }
         }
@@ -138,8 +136,6 @@
     bool found = false;
     for (AnyP::PortCfgPointer s = HttpPortList; !found && s != NULL; s = s->next)
         found = s->flags.tunnelSslBumping;
-    for (AnyP::PortCfgPointer s = HttpsPortList; !found && s != NULL; s = s->next)
-        found = s->flags.tunnelSslBumping;
     if (!found)
         return;
 
diff -u -r -N squid-4.0.2/src/ssl/Makefile.in squid-4.0.3/src/ssl/Makefile.in
--- squid-4.0.2/src/ssl/Makefile.in	2015-11-01 04:19:32.000000000 -0800
+++ squid-4.0.3/src/ssl/Makefile.in	2015-11-28 07:32:53.000000000 -0800
@@ -488,6 +488,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -521,7 +522,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/src/ssl/PeerConnector.cc squid-4.0.3/src/ssl/PeerConnector.cc
--- squid-4.0.2/src/ssl/PeerConnector.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/ssl/PeerConnector.cc	2015-11-28 07:30:57.000000000 -0800
@@ -101,7 +101,7 @@
 SSL *
 Ssl::PeerConnector::initializeSsl()
 {
-    SSL_CTX *sslContext = getSslContext();
+    Security::ContextPtr sslContext(getSslContext());
     assert(sslContext);
 
     const int fd = serverConnection()->fd;
@@ -589,15 +589,15 @@
     return buf.content();
 }
 
-SSL_CTX *
+Security::ContextPtr
 Ssl::BlindPeerConnector::getSslContext()
 {
     if (const CachePeer *peer = serverConnection()->getPeer()) {
         assert(peer->secure.encryptTransport);
-        SSL_CTX *sslContext = peer->sslContext;
+        Security::ContextPtr sslContext(peer->sslContext);
         return sslContext;
     }
-    return NULL;
+    return nullptr;
 }
 
 SSL *
@@ -647,7 +647,7 @@
     }
 }
 
-SSL_CTX *
+Security::ContextPtr
 Ssl::PeekingPeerConnector::getSslContext()
 {
     // XXX: locate a per-server context in Security:: instead
diff -u -r -N squid-4.0.2/src/ssl/PeerConnector.h squid-4.0.3/src/ssl/PeerConnector.h
--- squid-4.0.2/src/ssl/PeerConnector.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/ssl/PeerConnector.h	2015-11-28 07:30:57.000000000 -0800
@@ -134,9 +134,9 @@
     /// \param error if not NULL the SSL negotiation was aborted with an error
     virtual void noteNegotiationDone(ErrorState *error) {}
 
-    /// Must implemented by the kid classes to return the SSL_CTX object to use
+    /// Must implemented by the kid classes to return the Security::ContextPtr object to use
     /// for building the SSL objects.
-    virtual SSL_CTX *getSslContext() = 0;
+    virtual Security::ContextPtr getSslContext() = 0;
 
     /// mimics FwdState to minimize changes to FwdState::initiate/negotiateSsl
     Comm::ConnectionPointer const &serverConnection() const { return serverConn; }
@@ -196,8 +196,8 @@
     /// and sets the hostname to use for certificates validation
     virtual SSL *initializeSsl();
 
-    /// Return the configured SSL_CTX object
-    virtual SSL_CTX *getSslContext();
+    /// Return the configured Security::ContextPtr object
+    virtual Security::ContextPtr getSslContext();
 
     /// On error calls peerConnectFailed function, on success store the used SSL session
     /// for later use
@@ -224,7 +224,7 @@
 
     /* PeerConnector API */
     virtual SSL *initializeSsl();
-    virtual SSL_CTX *getSslContext();
+    virtual Security::ContextPtr getSslContext();
     virtual void noteWantWrite();
     virtual void noteSslNegotiationError(const int result, const int ssl_error, const int ssl_lib_error);
     virtual void noteNegotiationDone(ErrorState *error);
diff -u -r -N squid-4.0.2/src/ssl/support.cc squid-4.0.3/src/ssl/support.cc
--- squid-4.0.2/src/ssl/support.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/ssl/support.cc	2015-11-28 07:30:57.000000000 -0800
@@ -33,7 +33,7 @@
 
 #include <cerrno>
 
-static void setSessionCallbacks(SSL_CTX *ctx);
+static void setSessionCallbacks(Security::ContextPtr ctx);
 Ipc::MemMap *SslSessionCache = NULL;
 const char *SslSessionCacheName = "ssl_session_cache";
 
@@ -227,7 +227,7 @@
 
     char buffer[256] = "";
     SSL *ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
-    SSL_CTX *sslctx = SSL_get_SSL_CTX(ssl);
+    Security::ContextPtr sslctx = SSL_get_SSL_CTX(ssl);
     SBuf *server = (SBuf *)SSL_get_ex_data(ssl, ssl_ex_index_server);
     void *dont_verify_domain = SSL_CTX_get_ex_data(sslctx, ssl_ctx_ex_index_dont_verify_domain);
     ACLChecklist *check = (ACLChecklist*)SSL_get_ex_data(ssl, ssl_ex_index_cert_error_check);
@@ -484,7 +484,7 @@
 #endif
 
 static bool
-configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port)
+configureSslContext(Security::ContextPtr sslContext, AnyP::PortCfg &port)
 {
     int ssl_error;
     SSL_CTX_set_options(sslContext, port.secure.parsedOptions);
@@ -555,15 +555,15 @@
     return true;
 }
 
-SSL_CTX *
+Security::ContextPtr
 sslCreateServerContext(AnyP::PortCfg &port)
 {
     ssl_initialize();
 
 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
-    SSL_CTX *sslContext = SSL_CTX_new(TLS_server_method());
+    Security::ContextPtr sslContext(SSL_CTX_new(TLS_server_method()));
 #else
-    SSL_CTX *sslContext = SSL_CTX_new(SSLv23_server_method());
+    Security::ContextPtr sslContext(SSL_CTX_new(SSLv23_server_method()));
 #endif
 
     if (sslContext == NULL) {
@@ -639,15 +639,15 @@
 }
 #endif
 
-SSL_CTX *
+Security::ContextPtr
 sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, long fl)
 {
     ssl_initialize();
 
 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
-    SSL_CTX *sslContext = SSL_CTX_new(TLS_client_method());
+    Security::ContextPtr sslContext(SSL_CTX_new(TLS_client_method()));
 #else
-    SSL_CTX *sslContext = SSL_CTX_new(SSLv23_client_method());
+    Security::ContextPtr sslContext(SSL_CTX_new(SSLv23_client_method()));
 #endif
 
     if (sslContext == NULL) {
@@ -959,9 +959,8 @@
     return str;
 }
 
-/// \ingroup ServerProtocolSSLInternal
 /// Create SSL context and apply ssl certificate and private key to it.
-SSL_CTX *
+Security::ContextPtr
 Ssl::createSSLContext(Security::CertPointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port)
 {
 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
@@ -982,33 +981,24 @@
     return sslContext.release();
 }
 
-SSL_CTX *
+Security::ContextPtr
 Ssl::generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port)
 {
     Security::CertPointer cert;
     Ssl::EVP_PKEY_Pointer pkey;
-    if (!readCertAndPrivateKeyFromMemory(cert, pkey, data))
-        return NULL;
-
-    if (!cert || !pkey)
-        return NULL;
+    if (!readCertAndPrivateKeyFromMemory(cert, pkey, data) || !cert || !pkey)
+        return nullptr;
 
     return createSSLContext(cert, pkey, port);
 }
 
-SSL_CTX *
+Security::ContextPtr
 Ssl::generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port)
 {
     Security::CertPointer cert;
     Ssl::EVP_PKEY_Pointer pkey;
-    if (!generateSslCertificate(cert, pkey, properties))
-        return NULL;
-
-    if (!cert)
-        return NULL;
-
-    if (!pkey)
-        return NULL;
+    if (!generateSslCertificate(cert, pkey, properties) || !cert || !pkey)
+        return nullptr;
 
     return createSSLContext(cert, pkey, port);
 }
@@ -1056,10 +1046,10 @@
     return true;
 }
 
-bool Ssl::verifySslCertificate(SSL_CTX * sslContext, CertificateProperties const &properties)
+bool Ssl::verifySslCertificate(Security::ContextPtr sslContext, CertificateProperties const &properties)
 {
     // SSL_get_certificate is buggy in openssl versions 1.0.1d and 1.0.1e
-    // Try to retrieve certificate directly from SSL_CTX object
+    // Try to retrieve certificate directly from Security::ContextPtr object
 #if SQUID_USE_SSLGETCERTIFICATE_HACK
     X509 ***pCert = (X509 ***)sslContext->cert;
     X509 * cert = pCert && *pCert ? **pCert : NULL;
@@ -1101,7 +1091,7 @@
 #endif
 }
 
-void Ssl::addChainToSslContext(SSL_CTX *sslContext, STACK_OF(X509) *chain)
+void Ssl::addChainToSslContext(Security::ContextPtr sslContext, STACK_OF(X509) *chain)
 {
     if (!chain)
         return;
@@ -1199,7 +1189,7 @@
 }
 
 SSL *
-SslCreate(SSL_CTX *sslContext, const int fd, Ssl::Bio::Type type, const char *squidCtx)
+SslCreate(Security::ContextPtr sslContext, const int fd, Ssl::Bio::Type type, const char *squidCtx)
 {
     if (fd < 0) {
         debugs(83, DBG_IMPORTANT, "Gone connection");
@@ -1234,13 +1224,13 @@
 }
 
 SSL *
-Ssl::CreateClient(SSL_CTX *sslContext, const int fd, const char *squidCtx)
+Ssl::CreateClient(Security::ContextPtr sslContext, const int fd, const char *squidCtx)
 {
     return SslCreate(sslContext, fd, Ssl::Bio::BIO_TO_SERVER, squidCtx);
 }
 
 SSL *
-Ssl::CreateServer(SSL_CTX *sslContext, const int fd, const char *squidCtx)
+Ssl::CreateServer(Security::ContextPtr sslContext, const int fd, const char *squidCtx)
 {
     return SslCreate(sslContext, fd, Ssl::Bio::BIO_TO_CLIENT, squidCtx);
 }
@@ -1364,7 +1354,7 @@
 }
 
 static void
-setSessionCallbacks(SSL_CTX *ctx)
+setSessionCallbacks(Security::ContextPtr ctx)
 {
     if (SslSessionCache) {
         SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL);
@@ -1377,10 +1367,9 @@
 static bool
 isSslServer()
 {
-    if (HttpsPortList != NULL)
-        return true;
-
     for (AnyP::PortCfgPointer s = HttpPortList; s != NULL; s = s->next) {
+        if (s->secure.encryptTransport)
+            return true;
         if (s->flags.tunnelSslBumping)
             return true;
     }
@@ -1411,11 +1400,6 @@
         return;
     }
 
-    for (AnyP::PortCfgPointer s = HttpsPortList; s != NULL; s = s->next) {
-        if (s->staticSslContext.get() != NULL)
-            setSessionCallbacks(s->staticSslContext.get());
-    }
-
     for (AnyP::PortCfgPointer s = HttpPortList; s != NULL; s = s->next) {
         if (s->staticSslContext.get() != NULL)
             setSessionCallbacks(s->staticSslContext.get());
diff -u -r -N squid-4.0.2/src/ssl/support.h squid-4.0.3/src/ssl/support.h
--- squid-4.0.2/src/ssl/support.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/ssl/support.h	2015-11-28 07:30:57.000000000 -0800
@@ -61,11 +61,11 @@
 
 /// Creates SSL Client connection structure and initializes SSL I/O (Comm and BIO).
 /// On errors, emits DBG_IMPORTANT with details and returns NULL.
-SSL *CreateClient(SSL_CTX *sslContext, const int fd, const char *squidCtx);
+SSL *CreateClient(Security::ContextPtr sslContext, const int fd, const char *squidCtx);
 
 /// Creates SSL Server connection structure and initializes SSL I/O (Comm and BIO).
 /// On errors, emits DBG_IMPORTANT with details and returns NULL.
-SSL *CreateServer(SSL_CTX *sslContext, const int fd, const char *squidCtx);
+SSL *CreateServer(Security::ContextPtr sslContext, const int fd, const char *squidCtx);
 
 /// An SSL certificate-related error.
 /// Pairs an error code with the certificate experiencing the error.
@@ -87,10 +87,10 @@
 } //namespace Ssl
 
 /// \ingroup ServerProtocolSSLAPI
-SSL_CTX *sslCreateServerContext(AnyP::PortCfg &port);
+Security::ContextPtr sslCreateServerContext(AnyP::PortCfg &port);
 
 /// \ingroup ServerProtocolSSLAPI
-SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, long flags);
+Security::ContextPtr sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, long flags);
 
 /// \ingroup ServerProtocolSSLAPI
 int ssl_read_method(int, char *, int);
@@ -165,7 +165,7 @@
   \ingroup ServerProtocolSSLAPI
   * Decide on the kind of certificate and generate a CA- or self-signed one
 */
-SSL_CTX * generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port);
+Security::ContextPtr generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port);
 
 /**
   \ingroup ServerProtocolSSLAPI
@@ -174,20 +174,20 @@
   \param properties Check if the context certificate matches the given properties
   \return true if the contexts certificate is valid, false otherwise
  */
-bool verifySslCertificate(SSL_CTX * sslContext,  CertificateProperties const &properties);
+bool verifySslCertificate(Security::ContextPtr sslContext,  CertificateProperties const &properties);
 
 /**
   \ingroup ServerProtocolSSLAPI
   * Read private key and certificate from memory and generate SSL context
   * using their.
  */
-SSL_CTX * generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port);
+Security::ContextPtr generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port);
 
 /**
   \ingroup ServerProtocolSSLAPI
   * Create an SSL context using the provided certificate and key
  */
-SSL_CTX * createSSLContext(Security::CertPointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port);
+Security::ContextPtr createSSLContext(Security::CertPointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port);
 
 /**
   \ingroup ServerProtocolSSLAPI
@@ -207,7 +207,7 @@
   \ingroup ServerProtocolSSLAPI
   * Adds the certificates in certList to the certificate chain of the SSL context
  */
-void addChainToSslContext(SSL_CTX *sslContext, STACK_OF(X509) *certList);
+void addChainToSslContext(Security::ContextPtr sslContext, STACK_OF(X509) *certList);
 
 /**
  \ingroup ServerProtocolSSLAPI
diff -u -r -N squid-4.0.2/src/stat.cc squid-4.0.3/src/stat.cc
--- squid-4.0.2/src/stat.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/stat.cc	2015-11-28 07:30:57.000000000 -0800
@@ -409,7 +409,7 @@
     state->filter = filter;
 
     sentry->lock("statObjects");
-    state->theSearch = Store::Root().search(NULL, NULL);
+    state->theSearch = Store::Root().search();
 
     eventAdd("statObjects", statObjects, state, 0.0, 1);
 }
@@ -1857,13 +1857,12 @@
                               fd_table[fd].bytes_read, fd_table[fd].bytes_written);
             storeAppendPrintf(s, "\tFD desc: %s\n", fd_table[fd].desc);
             storeAppendPrintf(s, "\tin: buf %p, used %ld, free %ld\n",
-                              conn->in.buf.c_str(), (long int) conn->in.buf.length(), (long int) conn->in.buf.spaceSize());
+                              conn->inBuf.rawContent(), (long int) conn->inBuf.length(), (long int) conn->inBuf.spaceSize());
             storeAppendPrintf(s, "\tremote: %s\n",
                               conn->clientConnection->remote.toUrl(buf,MAX_IPSTRLEN));
             storeAppendPrintf(s, "\tlocal: %s\n",
                               conn->clientConnection->local.toUrl(buf,MAX_IPSTRLEN));
-            storeAppendPrintf(s, "\tnrequests: %d\n",
-                              conn->nrequests);
+            storeAppendPrintf(s, "\tnrequests: %u\n", conn->pipeline.nrequests);
         }
 
         storeAppendPrintf(s, "uri %s\n", http->uri);
diff -u -r -N squid-4.0.2/src/store/Controlled.h squid-4.0.3/src/store/Controlled.h
--- squid-4.0.2/src/store/Controlled.h	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/store/Controlled.h	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_STORE_CONTROLLED_H
+#define SQUID_STORE_CONTROLLED_H
+
+#include "store/Storage.h"
+
+namespace Store {
+
+/// Storage controlled by a Controller.
+/// This API is shared among Disks, Disk, Memory caches and Transients.
+class Controlled: public Storage
+{
+public:
+    /// somebody needs this entry (many cache replacement policies need to know)
+    virtual void reference(StoreEntry &e) = 0;
+
+    /// somebody no longer needs this entry (usually after calling reference())
+    /// return false iff the idle entry should be destroyed
+    virtual bool dereference(StoreEntry &e) = 0;
+
+    /// If this storage cannot cache collapsed entries, return false.
+    /// If the entry is not found, return false. Otherwise, return true after
+    /// tying the entry to this cache and setting inSync to updateCollapsed().
+    virtual bool anchorCollapsed(StoreEntry &, bool &/*inSync*/) { return false; }
+
+    /// Update a local collapsed entry with fresh info from this cache (if any).
+    /// Return true iff the cache supports collapsed entries and
+    /// the given local collapsed entry is now in sync with this storage.
+    virtual bool updateCollapsed(StoreEntry &) { return false; }
+};
+
+} // namespace Store
+
+#endif /* SQUID_STORE_CONTROLLED_H */
+
diff -u -r -N squid-4.0.2/src/store/Controller.cc squid-4.0.3/src/store/Controller.cc
--- squid-4.0.2/src/store/Controller.cc	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/store/Controller.cc	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,593 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/* DEBUG: section 20    Store Controller */
+
+#include "squid.h"
+#include "mem_node.h"
+#include "MemStore.h"
+#include "profiler/Profiler.h"
+#include "SquidConfig.h"
+#include "SquidMath.h"
+#include "store/Controller.h"
+#include "store/Disks.h"
+#include "store/LocalSearch.h"
+#include "tools.h"
+#include "Transients.h"
+
+#if HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+/*
+ * store_dirs_rebuilding is initialized to _1_ as a hack so that
+ * storeDirWriteCleanLogs() doesn't try to do anything unless _all_
+ * cache_dirs have been read.  For example, without this hack, Squid
+ * will try to write clean log files if -kparse fails (becasue it
+ * calls fatal()).
+ */
+int Store::Controller::store_dirs_rebuilding = 1;
+
+Store::Controller::Controller() :
+    swapDir(new Disks),
+    memStore(NULL),
+    transients(NULL)
+{
+    assert(!store_table);
+}
+
+Store::Controller::~Controller()
+{
+    delete memStore;
+    delete transients;
+    delete swapDir;
+
+    if (store_table) {
+        hashFreeItems(store_table, destroyStoreEntry);
+        hashFreeMemory(store_table);
+        store_table = nullptr;
+    }
+}
+
+void
+Store::Controller::init()
+{
+    if (Config.memShared && IamWorkerProcess()) {
+        memStore = new MemStore;
+        memStore->init();
+    }
+
+    swapDir->init();
+
+    if (UsingSmp() && IamWorkerProcess() && Config.onoff.collapsed_forwarding) {
+        transients = new Transients;
+        transients->init();
+    }
+}
+
+void
+Store::Controller::create()
+{
+    swapDir->create();
+
+#if !_SQUID_WINDOWS_
+
+    pid_t pid;
+
+    do {
+        int status;
+#if _SQUID_NEXT_
+
+        pid = wait3(&status, WNOHANG, NULL);
+#else
+
+        pid = waitpid(-1, &status, 0);
+#endif
+
+    } while (pid > 0 || (pid < 0 && errno == EINTR));
+
+#endif
+}
+
+void
+Store::Controller::maintain()
+{
+    static time_t last_warn_time = 0;
+
+    PROF_start(storeMaintainSwapSpace);
+    swapDir->maintain();
+
+    /* this should be emitted by the oversize dir, not globally */
+
+    if (Root().currentSize() > Store::Root().maxSize()) {
+        if (squid_curtime - last_warn_time > 10) {
+            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;
+        }
+    }
+
+    PROF_stop(storeMaintainSwapSpace);
+}
+
+void
+Store::Controller::getStats(StoreInfoStats &stats) const
+{
+    if (memStore)
+        memStore->getStats(stats);
+    else {
+        // move this code to a non-shared memory cache class when we have it
+        stats.mem.shared = false;
+        stats.mem.capacity = Config.memMaxSize;
+        stats.mem.size = mem_node::StoreMemSize();
+        stats.mem.count = hot_obj_count;
+    }
+
+    swapDir->getStats(stats);
+
+    // low-level info not specific to memory or disk cache
+    stats.store_entry_count = StoreEntry::inUseCount();
+    stats.mem_object_count = MemObject::inUseCount();
+}
+
+void
+Store::Controller::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() >> 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);
+}
+
+/* if needed, this could be taught to cache the result */
+uint64_t
+Store::Controller::maxSize() const
+{
+    /* TODO: include memory cache ? */
+    return swapDir->maxSize();
+}
+
+uint64_t
+Store::Controller::minSize() const
+{
+    /* TODO: include memory cache ? */
+    return swapDir->minSize();
+}
+
+uint64_t
+Store::Controller::currentSize() const
+{
+    /* TODO: include memory cache ? */
+    return swapDir->currentSize();
+}
+
+uint64_t
+Store::Controller::currentCount() const
+{
+    /* TODO: include memory cache ? */
+    return swapDir->currentCount();
+}
+
+int64_t
+Store::Controller::maxObjectSize() const
+{
+    /* TODO: include memory cache ? */
+    return swapDir->maxObjectSize();
+}
+
+StoreSearch *
+Store::Controller::search()
+{
+    // this is the only kind of search we currently support
+    return NewLocalSearch();
+}
+
+void
+Store::Controller::sync(void)
+{
+    if (memStore)
+        memStore->sync();
+    swapDir->sync();
+}
+
+/*
+ * handle callbacks all avaliable fs'es
+ */
+int
+Store::Controller::callback()
+{
+    /* This will likely double count. Thats ok. */
+    PROF_start(storeDirCallback);
+
+    /* mem cache callbacks ? */
+    int result = swapDir->callback();
+
+    PROF_stop(storeDirCallback);
+
+    return result;
+}
+
+void
+Store::Controller::referenceBusy(StoreEntry &e)
+{
+    // special entries do not belong to any specific Store, but are IN_MEMORY
+    if (EBIT_TEST(e.flags, ENTRY_SPECIAL))
+        return;
+
+    /* Notify the fs that we're referencing this object again */
+
+    if (e.swap_dirn > -1)
+        swapDir->reference(e);
+
+    // Notify the memory cache that we're referencing this object again
+    if (memStore && e.mem_status == IN_MEMORY)
+        memStore->reference(e);
+
+    // 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);
+    }
+}
+
+bool
+Store::Controller::dereferenceIdle(StoreEntry &e, bool wantsLocalMemory)
+{
+    // special entries do not belong to any specific Store, but are IN_MEMORY
+    if (EBIT_TEST(e.flags, ENTRY_SPECIAL))
+        return true;
+
+    bool keepInStoreTable = false; // keep only if somebody needs it there
+
+    /* Notify the fs that we're not referencing this object any more */
+
+    if (e.swap_filen > -1)
+        keepInStoreTable = swapDir->dereference(e) || keepInStoreTable;
+
+    // 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);
+        // non-shared memory cache relies on store_table
+        if (!memStore)
+            keepInStoreTable = wantsLocalMemory || keepInStoreTable;
+    }
+
+    return keepInStoreTable;
+}
+
+StoreEntry *
+Store::Controller::get(const cache_key *key)
+{
+    if (StoreEntry *e = find(key)) {
+        // this is not very precise: some get()s are not initiated by clients
+        e->touch();
+        referenceBusy(*e);
+        return e;
+    }
+    return NULL;
+}
+
+/// Internal method to implements the guts of the Store::get() API:
+/// returns an in-transit or cached object with a given key, if any.
+StoreEntry *
+Store::Controller::find(const cache_key *key)
+{
+    debugs(20, 3, storeKeyText(key));
+
+    if (StoreEntry *e = static_cast<StoreEntry*>(hash_lookup(store_table, 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;
+    }
+
+    // Must search transients before caches because we must sync those we find.
+    if (transients) {
+        if (StoreEntry *e = transients->get(key)) {
+            debugs(20, 3, "got shared in-transit entry: " << *e);
+            bool inSync = false;
+            const bool found = anchorCollapsed(*e, inSync);
+            if (!found || inSync)
+                return e;
+            assert(!e->locked()); // ensure release will destroyStoreEntry()
+            e->release(); // do not let others into the same trap
+            return NULL;
+        }
+    }
+
+    if (memStore) {
+        if (StoreEntry *e = memStore->get(key)) {
+            debugs(20, 3, HERE << "got mem-cached entry: " << *e);
+            return e;
+        }
+    }
+
+    if (swapDir) {
+        if (StoreEntry *e = swapDir->get(key)) {
+            debugs(20, 3, "got disk-cached entry: " << *e);
+            return e;
+        }
+    }
+
+    debugs(20, 4, "cannot locate " << storeKeyText(key));
+    return nullptr;
+}
+
+void
+Store::Controller::markForUnlink(StoreEntry &e)
+{
+    if (transients && e.mem_obj && e.mem_obj->xitTable.index >= 0)
+        transients->markForUnlink(e);
+    if (memStore && e.mem_obj && e.mem_obj->memCache.index >= 0)
+        memStore->markForUnlink(e);
+    if (swapDir && e.swap_filen >= 0)
+        swapDir->markForUnlink(e);
+}
+
+void
+Store::Controller::unlink(StoreEntry &e)
+{
+    memoryUnlink(e);
+    if (swapDir && e.swap_filen >= 0)
+        swapDir->unlink(e);
+}
+
+// move this into [non-shared] memory cache class when we have one
+/// whether e should be kept in local RAM for possible future caching
+bool
+Store::Controller::keepForLocalMemoryCache(StoreEntry &e) const
+{
+    if (!e.memoryCachable())
+        return false;
+
+    // does the current and expected size obey memory caching limits?
+    assert(e.mem_obj);
+    const int64_t loadedSize = e.mem_obj->endOffset();
+    const int64_t expectedSize = e.mem_obj->expectedReplySize(); // may be < 0
+    const int64_t ramSize = max(loadedSize, expectedSize);
+    const int64_t ramLimit = min(
+                                 static_cast<int64_t>(Config.memMaxSize),
+                                 static_cast<int64_t>(Config.Store.maxInMemObjSize));
+    return ramSize <= ramLimit;
+}
+
+void
+Store::Controller::memoryOut(StoreEntry &e, const bool preserveSwappable)
+{
+    bool keepInLocalMemory = false;
+    if (memStore)
+        memStore->write(e); // leave keepInLocalMemory false
+    else
+        keepInLocalMemory = keepForLocalMemoryCache(e);
+
+    debugs(20, 7, HERE << "keepInLocalMemory: " << keepInLocalMemory);
+
+    if (!keepInLocalMemory)
+        e.trimMemory(preserveSwappable);
+}
+
+void
+Store::Controller::memoryUnlink(StoreEntry &e)
+{
+    if (memStore)
+        memStore->unlink(e);
+    else // TODO: move into [non-shared] memory cache class when we have one
+        e.destroyMemObject();
+}
+
+void
+Store::Controller::memoryDisconnect(StoreEntry &e)
+{
+    if (memStore)
+        memStore->disconnect(e);
+    // else nothing to do for non-shared memory cache
+}
+
+void
+Store::Controller::transientsAbandon(StoreEntry &e)
+{
+    if (transients) {
+        assert(e.mem_obj);
+        if (e.mem_obj->xitTable.index >= 0)
+            transients->abandon(e);
+    }
+}
+
+void
+Store::Controller::transientsCompleteWriting(StoreEntry &e)
+{
+    if (transients) {
+        assert(e.mem_obj);
+        if (e.mem_obj->xitTable.index >= 0)
+            transients->completeWriting(e);
+    }
+}
+
+int
+Store::Controller::transientReaders(const StoreEntry &e) const
+{
+    return (transients && e.mem_obj && e.mem_obj->xitTable.index >= 0) ?
+           transients->readers(e) : 0;
+}
+
+void
+Store::Controller::transientsDisconnect(MemObject &mem_obj)
+{
+    if (transients)
+        transients->disconnect(mem_obj);
+}
+
+void
+Store::Controller::handleIdleEntry(StoreEntry &e)
+{
+    bool keepInLocalMemory = false;
+
+    if (EBIT_TEST(e.flags, ENTRY_SPECIAL)) {
+        // Icons (and cache digests?) should stay in store_table until we
+        // have a dedicated storage for them (that would not purge them).
+        // They are not managed [well] by any specific Store handled below.
+        keepInLocalMemory = true;
+    } else if (memStore) {
+        // leave keepInLocalMemory false; memStore maintains its own cache
+    } else {
+        keepInLocalMemory = keepForLocalMemoryCache(e) && // in good shape and
+                            // the local memory cache is not overflowing
+                            (mem_node::InUseCount() <= store_pages_max);
+    }
+
+    // An idle, unlocked entry that only belongs to a SwapDir which controls
+    // its own index, should not stay in the global store_table.
+    if (!dereferenceIdle(e, keepInLocalMemory)) {
+        debugs(20, 5, HERE << "destroying unlocked entry: " << &e << ' ' << e);
+        destroyStoreEntry(static_cast<hash_link*>(&e));
+        return;
+    }
+
+    debugs(20, 5, HERE << "keepInLocalMemory: " << keepInLocalMemory);
+
+    // 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
+    }
+}
+
+void
+Store::Controller::allowCollapsing(StoreEntry *e, const RequestFlags &reqFlags,
+                                   const HttpRequestMethod &reqMethod)
+{
+    e->makePublic(); // this is needed for both local and SMP collapsing
+    if (transients)
+        transients->startWriting(e, reqFlags, reqMethod);
+    debugs(20, 3, "may " << (transients && e->mem_obj->xitTable.index >= 0 ?
+                             "SMP-" : "locally-") << "collapse " << *e);
+}
+
+void
+Store::Controller::syncCollapsed(const sfileno xitIndex)
+{
+    assert(transients);
+
+    StoreEntry *collapsed = transients->findCollapsed(xitIndex);
+    if (!collapsed) { // the entry is no longer locally active, ignore update
+        debugs(20, 7, "not SMP-syncing not-transient " << xitIndex);
+        return;
+    }
+    assert(collapsed->mem_obj);
+    assert(collapsed->mem_obj->smpCollapsed);
+
+    debugs(20, 7, "syncing " << *collapsed);
+
+    bool abandoned = transients->abandoned(*collapsed);
+    bool found = false;
+    bool inSync = false;
+    if (memStore && collapsed->mem_obj->memCache.io == MemObject::ioDone) {
+        found = true;
+        inSync = true;
+        debugs(20, 7, "fully mem-loaded " << *collapsed);
+    } else if (memStore && collapsed->mem_obj->memCache.index >= 0) {
+        found = true;
+        inSync = memStore->updateCollapsed(*collapsed);
+    } else if (swapDir && collapsed->swap_filen >= 0) {
+        found = true;
+        inSync = swapDir->updateCollapsed(*collapsed);
+    } else {
+        found = anchorCollapsed(*collapsed, inSync);
+    }
+
+    if (abandoned && collapsed->store_status == STORE_PENDING) {
+        debugs(20, 3, "aborting abandoned but STORE_PENDING " << *collapsed);
+        collapsed->abort();
+        return;
+    }
+
+    if (inSync) {
+        debugs(20, 5, "synced " << *collapsed);
+        collapsed->invokeHandlers();
+    } else if (found) { // unrecoverable problem syncing this entry
+        debugs(20, 3, "aborting unsyncable " << *collapsed);
+        collapsed->abort();
+    } else { // the entry is still not in one of the caches
+        debugs(20, 7, "waiting " << *collapsed);
+    }
+}
+
+/// Called for in-transit entries that are not yet anchored to a cache.
+/// For cached entries, return true after synchronizing them with their cache
+/// (making inSync true on success). For not-yet-cached entries, return false.
+bool
+Store::Controller::anchorCollapsed(StoreEntry &collapsed, bool &inSync)
+{
+    // this method is designed to work with collapsed transients only
+    assert(collapsed.mem_obj);
+    assert(collapsed.mem_obj->xitTable.index >= 0);
+    assert(collapsed.mem_obj->smpCollapsed);
+
+    debugs(20, 7, "anchoring " << collapsed);
+
+    bool found = false;
+    if (memStore)
+        found = memStore->anchorCollapsed(collapsed, inSync);
+    if (!found && swapDir)
+        found = swapDir->anchorCollapsed(collapsed, inSync);
+
+    if (found) {
+        if (inSync)
+            debugs(20, 7, "anchored " << collapsed);
+        else
+            debugs(20, 5, "failed to anchor " << collapsed);
+    } else {
+        debugs(20, 7, "skipping not yet cached " << collapsed);
+    }
+
+    return found;
+}
+
+namespace Store {
+static RefCount<Controller> TheRoot;
+}
+
+Store::Controller&
+Store::Root()
+{
+    assert(TheRoot);
+    return *TheRoot;
+}
+
+void
+Store::Init(Controller *root)
+{
+    TheRoot = root ? root : new Controller;
+}
+
+void
+Store::FreeMemory()
+{
+    TheRoot = nullptr;
+}
+
diff -u -r -N squid-4.0.2/src/store/Controller.h squid-4.0.3/src/store/Controller.h
--- squid-4.0.2/src/store/Controller.h	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/store/Controller.h	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_STORE_CONTROLLER_H
+#define SQUID_STORE_CONTROLLER_H
+
+#include "store/Storage.h"
+
+class MemObject;
+class RequestFlags;
+class HttpRequestMethod;
+
+namespace Store {
+
+/// Public Store interface. Coordinates the work of memory/disk/transient stores
+/// and hides their individual existence/differences from the callers.
+class Controller: public Storage
+{
+public:
+    Controller();
+    virtual ~Controller() override;
+
+    /* Storage API */
+    virtual void create() override;
+    virtual void init() override;
+    virtual StoreEntry *get(const cache_key *) override;
+    virtual uint64_t maxSize() const override;
+    virtual uint64_t minSize() const override;
+    virtual uint64_t currentSize() const override;
+    virtual uint64_t currentCount() const override;
+    virtual int64_t maxObjectSize() const override;
+    virtual void getStats(StoreInfoStats &stats) const override;
+    virtual void stat(StoreEntry &) const override;
+    virtual void sync() override;
+    virtual void maintain() override;
+    virtual void markForUnlink(StoreEntry &) override;
+    virtual void unlink(StoreEntry &) override;
+    virtual int callback() override;
+
+    /// called when the entry is no longer needed by any transaction
+    void handleIdleEntry(StoreEntry &);
+
+    /// called to get rid of no longer needed entry data in RAM, if any
+    void memoryOut(StoreEntry &, const bool preserveSwappable);
+
+    /// makes the entry available for collapsing future requests
+    void allowCollapsing(StoreEntry *, const RequestFlags &, const HttpRequestMethod &);
+
+    /// marks the entry completed for collapsed requests
+    void transientsCompleteWriting(StoreEntry &);
+
+    /// Update local intransit entry after changes made by appending worker.
+    void syncCollapsed(const sfileno);
+
+    /// calls Root().transients->abandon() if transients are tracked
+    void transientsAbandon(StoreEntry &);
+
+    /// number of the transient entry readers some time ago
+    int transientReaders(const StoreEntry &) const;
+
+    /// disassociates the entry from the intransit table
+    void transientsDisconnect(MemObject &);
+
+    /// removes the entry from the memory cache
+    void memoryUnlink(StoreEntry &);
+
+    /// disassociates the entry from the memory cache, preserving cached data
+    void memoryDisconnect(StoreEntry &);
+
+    /// \returns an iterator for all Store entries
+    StoreSearch *search();
+
+    /// the number of cache_dirs being rebuilt; TODO: move to Disks::Rebuilding
+    static int store_dirs_rebuilding;
+
+private:
+    /// update reference counters of the recently touched entry
+    void referenceBusy(StoreEntry &e);
+    /// dereference() an idle entry and return true if the entry should be deleted
+    bool dereferenceIdle(StoreEntry &, bool wantsLocalMemory);
+
+    StoreEntry *find(const cache_key *key);
+    bool keepForLocalMemoryCache(StoreEntry &e) const;
+    bool anchorCollapsed(StoreEntry &, bool &inSync);
+
+    Disks *swapDir; ///< summary view of all disk caches
+    Memory *memStore; ///< memory cache
+
+    /// A shared table of public store entries that do not know whether they
+    /// will belong to a memory cache, a disk cache, or will be uncachable
+    /// when the response header comes. Used for SMP collapsed forwarding.
+    Transients *transients;
+};
+
+/// safely access controller singleton
+extern Controller &Root();
+
+/// initialize the storage module; a custom root is used by unit tests only
+extern void Init(Controller *root = nullptr);
+
+/// undo Init()
+extern void FreeMemory();
+
+} // namespace Store
+
+#endif /* SQUID_STORE_CONTROLLER_H */
+
diff -u -r -N squid-4.0.2/src/store/Disk.cc squid-4.0.3/src/store/Disk.cc
--- squid-4.0.2/src/store/Disk.cc	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/store/Disk.cc	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/* DEBUG: section 20    Swap Dir base object */
+
+#include "squid.h"
+#include "cache_cf.h"
+#include "compat/strtoll.h"
+#include "ConfigOption.h"
+#include "ConfigParser.h"
+#include "globals.h"
+#include "Parsing.h"
+#include "SquidConfig.h"
+#include "Store.h"
+#include "store/Disk.h"
+#include "StoreFileSystem.h"
+#include "tools.h"
+
+Store::Disk::Disk(char const *aType): theType(aType),
+    max_size(0), min_objsize(0), max_objsize (-1),
+    path(NULL), index(-1), disker(-1),
+    repl(NULL), removals(0), scanned(0),
+    cleanLog(NULL)
+{
+    fs.blksize = 1024;
+}
+
+Store::Disk::~Disk()
+{
+    // TODO: should we delete repl?
+    xfree(path);
+}
+
+void
+Store::Disk::create() {}
+
+void
+Store::Disk::dump(StoreEntry &)const {}
+
+bool
+Store::Disk::doubleCheck(StoreEntry &)
+{
+    return false;
+}
+
+void
+Store::Disk::getStats(StoreInfoStats &stats) const
+{
+    if (!doReportStat())
+        return;
+
+    stats.swap.size = currentSize();
+    stats.swap.capacity = maxSize();
+    stats.swap.count = currentCount();
+}
+
+void
+Store::Disk::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",
+                      fs.blksize);
+    statfs(output);
+
+    if (repl) {
+        storeAppendPrintf(&output, "Removal policy: %s\n", repl->_type);
+
+        if (repl->Stats)
+            repl->Stats(repl, &output);
+    }
+}
+
+void
+Store::Disk::statfs(StoreEntry &)const {}
+
+void
+Store::Disk::maintain() {}
+
+uint64_t
+Store::Disk::minSize() const
+{
+    // XXX: Not all disk stores use Config.Swap.lowWaterMark
+    return ((maxSize() * Config.Swap.lowWaterMark) / 100);
+}
+
+int64_t
+Store::Disk::maxObjectSize() const
+{
+    // per-store max-size=N value is authoritative
+    if (max_objsize > -1)
+        return max_objsize;
+
+    // store with no individual max limit is limited by configured maximum_object_size
+    // or the total store size, whichever is smaller
+    return min(static_cast<int64_t>(maxSize()), Config.Store.maxObjectSize);
+}
+
+void
+Store::Disk::maxObjectSize(int64_t newMax)
+{
+    // negative values mean no limit (-1)
+    if (newMax < 0) {
+        max_objsize = -1; // set explicitly in case it had a non-default value previously
+        return;
+    }
+
+    // prohibit values greater than total storage area size
+    // but set max_objsize to the maximum allowed to override maximum_object_size global config
+    if (static_cast<uint64_t>(newMax) > maxSize()) {
+        debugs(47, DBG_PARSE_NOTE(2), "WARNING: Ignoring 'max-size' option for " << path <<
+               " which is larger than total cache_dir size of " << maxSize() << " bytes.");
+        max_objsize = maxSize();
+        return;
+    }
+
+    max_objsize = newMax;
+}
+
+void
+Store::Disk::reference(StoreEntry &) {}
+
+bool
+Store::Disk::dereference(StoreEntry &)
+{
+    return true; // keep in global store_table
+}
+
+void
+Store::Disk::diskFull()
+{
+    if (currentSize() >= maxSize())
+        return;
+
+    max_size = currentSize();
+
+    debugs(20, DBG_IMPORTANT, "WARNING: Shrinking cache_dir #" << index << " to " << currentSize() / 1024.0 << " KB");
+}
+
+bool
+Store::Disk::objectSizeIsAcceptable(int64_t objsize) const
+{
+    // without limits, all object sizes are acceptable, including unknown ones
+    if (min_objsize <= 0 && max_objsize == -1)
+        return true;
+
+    // with limits, objects with unknown sizes are not acceptable
+    if (objsize == -1)
+        return false;
+
+    // without the upper limit, just check the lower limit
+    if (max_objsize == -1)
+        return  min_objsize <= objsize;
+
+    return min_objsize <= objsize && objsize < max_objsize;
+}
+
+bool
+Store::Disk::canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const
+{
+    debugs(47,8, HERE << "cache_dir[" << index << "]: needs " <<
+           diskSpaceNeeded << " <? " << max_objsize);
+
+    if (EBIT_TEST(e.flags, ENTRY_SPECIAL))
+        return false; // we do not store Squid-generated entries
+
+    if (!objectSizeIsAcceptable(diskSpaceNeeded))
+        return false; // does not satisfy size limits
+
+    if (flags.read_only)
+        return false; // cannot write at all
+
+    if (currentSize() > 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
+}
+
+/* Move to StoreEntry ? */
+bool
+Store::Disk::canLog(StoreEntry const &e)const
+{
+    if (e.swap_filen < 0)
+        return false;
+
+    if (e.swap_status != SWAPOUT_DONE)
+        return false;
+
+    if (e.swap_file_sz <= 0)
+        return false;
+
+    if (EBIT_TEST(e.flags, RELEASE_REQUEST))
+        return false;
+
+    if (EBIT_TEST(e.flags, KEY_PRIVATE))
+        return false;
+
+    if (EBIT_TEST(e.flags, ENTRY_SPECIAL))
+        return false;
+
+    return true;
+}
+
+void
+Store::Disk::openLog() {}
+
+void
+Store::Disk::closeLog() {}
+
+int
+Store::Disk::writeCleanStart()
+{
+    return 0;
+}
+
+void
+Store::Disk::writeCleanDone() {}
+
+void
+Store::Disk::logEntry(const StoreEntry &, int) const {}
+
+char const *
+Store::Disk::type() const
+{
+    return theType;
+}
+
+bool
+Store::Disk::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
+Store::Disk::needsDiskStrand() const
+{
+    return false;
+}
+
+/* NOT performance critical. Really. Don't bother optimising for speed
+ * - RBC 20030718
+ */
+ConfigOption *
+Store::Disk::getOptionTree() const
+{
+    ConfigOptionVector *result = new ConfigOptionVector;
+    result->options.push_back(new ConfigOptionAdapter<Disk>(*const_cast<Disk*>(this), &Store::Disk::optionReadOnlyParse, &Store::Disk::optionReadOnlyDump));
+    result->options.push_back(new ConfigOptionAdapter<Disk>(*const_cast<Disk*>(this), &Store::Disk::optionObjectSizeParse, &Store::Disk::optionObjectSizeDump));
+    return result;
+}
+
+void
+Store::Disk::parseOptions(int isaReconfig)
+{
+    const bool old_read_only = flags.read_only;
+    char *name, *value;
+
+    ConfigOption *newOption = getOptionTree();
+
+    while ((name = ConfigParser::NextToken()) != NULL) {
+        value = strchr(name, '=');
+
+        if (value) {
+            *value = '\0';  /* cut on = */
+            ++value;
+        }
+
+        debugs(3,2, "cache_dir " << name << '=' << (value ? value : ""));
+
+        if (newOption)
+            if (!newOption->parse(name, value, isaReconfig))
+                self_destruct();
+    }
+
+    delete newOption;
+
+    /*
+     * Handle notifications about reconfigured single-options with no value
+     * where the removal of the option cannot be easily detected in the
+     * parsing...
+     */
+
+    if (isaReconfig) {
+        if (old_read_only != flags.read_only) {
+            debugs(3, DBG_IMPORTANT, "Cache dir '" << path << "' now " << (flags.read_only ? "No-Store" : "Read-Write"));
+        }
+    }
+}
+
+void
+Store::Disk::dumpOptions(StoreEntry * entry) const
+{
+    ConfigOption *newOption = getOptionTree();
+
+    if (newOption)
+        newOption->dump(entry);
+
+    delete newOption;
+}
+
+bool
+Store::Disk::optionReadOnlyParse(char const *option, const char *value, int)
+{
+    if (strcmp(option, "no-store") != 0 && strcmp(option, "read-only") != 0)
+        return false;
+
+    if (strcmp(option, "read-only") == 0) {
+        debugs(3, DBG_PARSE_NOTE(3), "UPGRADE WARNING: Replace cache_dir option 'read-only' with 'no-store'.");
+    }
+
+    bool read_only = 0;
+
+    if (value)
+        read_only = (xatoi(value) != 0);
+    else
+        read_only = true;
+
+    flags.read_only = read_only;
+
+    return true;
+}
+
+void
+Store::Disk::optionReadOnlyDump(StoreEntry * e) const
+{
+    if (flags.read_only)
+        storeAppendPrintf(e, " no-store");
+}
+
+bool
+Store::Disk::optionObjectSizeParse(char const *option, const char *value, int isaReconfig)
+{
+    int64_t *val;
+    if (strcmp(option, "max-size") == 0) {
+        val = &max_objsize;
+    } else if (strcmp(option, "min-size") == 0) {
+        val = &min_objsize;
+    } else
+        return false;
+
+    if (!value)
+        self_destruct();
+
+    int64_t size = strtoll(value, NULL, 10);
+
+    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;
+
+    return true;
+}
+
+void
+Store::Disk::optionObjectSizeDump(StoreEntry * e) const
+{
+    if (min_objsize != 0)
+        storeAppendPrintf(e, " min-size=%" PRId64, min_objsize);
+
+    if (max_objsize != -1)
+        storeAppendPrintf(e, " max-size=%" PRId64, max_objsize);
+}
+
+// some SwapDirs may maintain their indexes and be able to lookup an entry key
+StoreEntry *
+Store::Disk::get(const cache_key *)
+{
+    return NULL;
+}
+
diff -u -r -N squid-4.0.2/src/store/Disk.h squid-4.0.3/src/store/Disk.h
--- squid-4.0.2/src/store/Disk.h	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/store/Disk.h	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_STORE_DISK_H
+#define SQUID_STORE_DISK_H
+
+#include "store/Controlled.h"
+#include "StoreIOState.h"
+
+class ConfigOption;
+class RemovalPolicy;
+
+namespace Store {
+
+/// manages a single cache_dir
+class Disk: public Controlled
+{
+
+public:
+    typedef RefCount<Disk> Pointer;
+
+    explicit Disk(char const *aType);
+    virtual ~Disk();
+    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(); }
+    /// whether SwapDir may benefit from unlinkd
+    virtual bool unlinkdUseful() const = 0;
+
+    /**
+     * Notify this disk that it is full.
+     \todo XXX move into a protected api call between store files and their stores, rather than a top level api call
+     */
+    virtual void diskFull();
+
+    /* Controlled API */
+    virtual void create() override;
+    virtual StoreEntry *get(const cache_key *) override;
+    virtual uint64_t maxSize() const override { return max_size; }
+    virtual uint64_t minSize() const override;
+    virtual int64_t maxObjectSize() const override;
+    virtual void getStats(StoreInfoStats &stats) const override;
+    virtual void stat(StoreEntry &) const override;
+    virtual void reference(StoreEntry &e) override;
+    virtual bool dereference(StoreEntry &e) override;
+    virtual void maintain() override;
+
+    /// configure the maximum object size for this storage area.
+    /// May be any size up to the total storage area.
+    void maxObjectSize(int64_t newMax);
+
+    /// whether we can store an object of the given size
+    /// negative objSize means the object size is currently unknown
+    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);
+    void optionReadOnlyDump(StoreEntry * e) const;
+    bool optionObjectSizeParse(char const *option, const char *value, int reconfiguring);
+    void optionObjectSizeDump(StoreEntry * e) const;
+    char const *theType;
+
+protected:
+    uint64_t max_size;        ///< maximum allocatable size of the storage area
+    int64_t min_objsize;      ///< minimum size of any object stored here (-1 for no limit)
+    int64_t max_objsize;      ///< maximum size of any object stored here (-1 for no limit)
+
+public:
+    char *path;
+    int index;          /* This entry's index into the swapDirs array */
+    int disker; ///< disker kid id dedicated to this SwapDir or -1
+    RemovalPolicy *repl;
+    int removals;
+    int scanned;
+
+    struct Flags {
+        Flags() : selected(false), read_only(false) {}
+        bool selected;
+        bool read_only;
+    } flags;
+
+    virtual void dump(StoreEntry &)const;   /* Dump fs config snippet */
+    virtual bool doubleCheck(StoreEntry &); /* Double check the obj integrity */
+    virtual void statfs(StoreEntry &) const;    /* Dump fs statistics */
+
+    /// 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;
+
+    virtual StoreIOState::Pointer createStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *) = 0;
+    virtual StoreIOState::Pointer openStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *) = 0;
+
+    bool canLog(StoreEntry const &e)const;
+    virtual void openLog();
+    virtual void closeLog();
+    virtual void logEntry(const StoreEntry & e, int op) const;
+
+    class CleanLog
+    {
+
+    public:
+        virtual ~CleanLog() {}
+
+        virtual const StoreEntry *nextEntry() = 0;
+        virtual void write(StoreEntry const &) = 0;
+    };
+
+    CleanLog *cleanLog;
+    virtual int writeCleanStart();
+    virtual void writeCleanDone();
+    virtual void parse(int index, char *path) = 0;
+
+    struct {
+        int blksize;
+    } fs;
+};
+
+} // namespace Store
+
+#endif /* SQUID_STORE_DISK_H */
+
diff -u -r -N squid-4.0.2/src/store/Disks.cc squid-4.0.3/src/store/Disks.cc
--- squid-4.0.2/src/store/Disks.cc	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/store/Disks.cc	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,639 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/* DEBUG: section 47    Store Directory Routines */
+
+#include "squid.h"
+#include "Debug.h"
+#include "globals.h"
+#include "profiler/Profiler.h"
+#include "SquidConfig.h"
+#include "Store.h"
+#include "store/Disk.h"
+#include "store/Disks.h"
+#include "swap_log_op.h"
+#include "util.h" // for tvSubDsec() which should be in SquidTime.h
+
+static STDIRSELECT storeDirSelectSwapDirRoundRobin;
+static STDIRSELECT storeDirSelectSwapDirLeastLoad;
+/**
+ * This function pointer is set according to 'store_dir_select_algorithm'
+ * in squid.conf.
+ */
+STDIRSELECT *storeDirSelectSwapDir = storeDirSelectSwapDirLeastLoad;
+
+/**
+ * This new selection scheme simply does round-robin on all SwapDirs.
+ * A SwapDir is skipped if it is over the max_size (100%) limit, or
+ * overloaded.
+ */
+static int
+storeDirSelectSwapDirRoundRobin(const StoreEntry * e)
+{
+    // 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;
+
+    // Increment the first candidate once per selection (not once per
+    // iteration) to reduce bias when some disk(s) attract more entries.
+    static int firstCandidate = 0;
+    if (++firstCandidate >= Config.cacheSwap.n_configured)
+        firstCandidate = 0;
+
+    for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
+        const int dirn = (firstCandidate + i) % Config.cacheSwap.n_configured;
+        const SwapDir *sd = dynamic_cast<SwapDir*>(INDEXSD(dirn));
+
+        int load = 0;
+        if (!sd->canStore(*e, objsize, load))
+            continue;
+
+        if (load < 0 || load > 1000) {
+            continue;
+        }
+
+        return dirn;
+    }
+
+    return -1;
+}
+
+/**
+ * Spread load across all of the store directories
+ *
+ * Note: We should modify this later on to prefer sticking objects
+ * in the *tightest fit* swapdir to conserve space, along with the
+ * actual swapdir usage. But for now, this hack will do while
+ * testing, so you should order your swapdirs in the config file
+ * from smallest max-size= to largest max-size=.
+ *
+ * We also have to choose nleast == nconf since we need to consider
+ * ALL swapdirs, regardless of state. Again, this is a hack while
+ * we sort out the real usefulness of this algorithm.
+ */
+static int
+storeDirSelectSwapDirLeastLoad(const StoreEntry * e)
+{
+    int64_t most_free = 0;
+    ssize_t least_objsize = -1;
+    int least_load = INT_MAX;
+    int load;
+    int dirn = -1;
+    int i;
+    RefCount<SwapDir> SD;
+
+    // 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) {
+        SD = dynamic_cast<SwapDir *>(INDEXSD(i));
+        SD->flags.selected = false;
+
+        if (!SD->canStore(*e, objsize, load))
+            continue;
+
+        if (load < 0 || load > 1000)
+            continue;
+
+        if (load > least_load)
+            continue;
+
+        const int64_t cur_free = SD->maxSize() - SD->currentSize();
+
+        /* If the load is equal, then look in more details */
+        if (load == least_load) {
+            /* closest max-size fit */
+
+            if (least_objsize != -1)
+                if (SD->maxObjectSize() > least_objsize)
+                    continue;
+
+            /* most free */
+            if (cur_free < most_free)
+                continue;
+        }
+
+        least_load = load;
+        least_objsize = SD->maxObjectSize();
+        most_free = cur_free;
+        dirn = i;
+    }
+
+    if (dirn >= 0)
+        dynamic_cast<SwapDir *>(INDEXSD(dirn))->flags.selected = true;
+
+    return dirn;
+}
+
+SwapDir *
+Store::Disks::store(int const x) const
+{
+    return INDEXSD(x);
+}
+
+SwapDir &
+Store::Disks::dir(const int i) const
+{
+    SwapDir *sd = INDEXSD(i);
+    assert(sd);
+    return *sd;
+}
+
+int
+Store::Disks::callback()
+{
+    int result = 0;
+    int j;
+    static int ndir = 0;
+
+    do {
+        j = 0;
+
+        for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
+            if (ndir >= Config.cacheSwap.n_configured)
+                ndir = ndir % Config.cacheSwap.n_configured;
+
+            int temp_result = store(ndir)->callback();
+
+            ++ndir;
+
+            j += temp_result;
+
+            result += temp_result;
+
+            if (j > 100)
+                fatal ("too much io\n");
+        }
+    } while (j > 0);
+
+    ++ndir;
+
+    return result;
+}
+
+void
+Store::Disks::create()
+{
+    if (Config.cacheSwap.n_configured == 0) {
+        debugs(0, DBG_PARSE_NOTE(DBG_CRITICAL), "No cache_dir stores are configured.");
+    }
+
+    for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
+        if (dir(i).active())
+            store(i)->create();
+    }
+}
+
+StoreEntry *
+Store::Disks::get(const cache_key *key)
+{
+    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<SwapDir*>(INDEXSD(idx));
+            if (!sd->active())
+                continue;
+
+            if (StoreEntry *e = sd->get(key)) {
+                debugs(20, 7, "cache_dir " << idx << " has: " << *e);
+                return e;
+            }
+        }
+    }
+
+    debugs(20, 6, "none of " << Config.cacheSwap.n_configured <<
+           " cache_dirs have " << storeKeyText(key));
+    return nullptr;
+}
+
+void
+Store::Disks::init()
+{
+    if (Config.Store.objectsPerBucket <= 0)
+        fatal("'store_objects_per_bucket' should be larger than 0.");
+
+    if (Config.Store.avgObjectSize <= 0)
+        fatal("'store_avg_object_size' should be larger than 0.");
+
+    /* 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) / Config.Store.avgObjectSize;
+    debugs(20, DBG_IMPORTANT, "Swap maxSize " << (Store::Root().maxSize() >> 10) <<
+           " + " << ( Config.memMaxSize >> 10) << " KB, estimated " << buckets << " objects");
+    buckets /= Config.Store.objectsPerBucket;
+    debugs(20, DBG_IMPORTANT, "Target number of buckets: " << buckets);
+    /* ideally the full scan period should be configurable, for the
+     * moment it remains at approximately 24 hours.  */
+    store_hash_buckets = storeKeyHashBuckets(buckets);
+    debugs(20, DBG_IMPORTANT, "Using " << store_hash_buckets << " Store buckets");
+    debugs(20, DBG_IMPORTANT, "Max Mem  size: " << ( Config.memMaxSize >> 10) << " KB" <<
+           (Config.memShared ? " [shared]" : ""));
+    debugs(20, DBG_IMPORTANT, "Max Swap size: " << (Store::Root().maxSize() >> 10) << " KB");
+
+    store_table = hash_create(storeKeyHashCmp,
+                              store_hash_buckets, storeKeyHashHash);
+
+    for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
+        /* this starts a search of the store dirs, loading their
+         * index. under the new Store api this should be
+         * driven by the StoreHashIndex, not by each store.
+        *
+        * That is, the HashIndex should perform a search of each dir it is
+        * indexing to do the hash insertions. The search is then able to
+        * decide 'from-memory', or 'from-clean-log' or 'from-dirty-log' or
+        * 'from-no-log'.
+        *
+         * Step 1: make the store rebuilds use a search internally
+        * Step 2: change the search logic to use the four modes described
+        *         above
+        * Step 3: have the hash index walk the searches itself.
+         */
+        if (dir(i).active())
+            store(i)->init();
+    }
+
+    if (strcasecmp(Config.store_dir_select_algorithm, "round-robin") == 0) {
+        storeDirSelectSwapDir = storeDirSelectSwapDirRoundRobin;
+        debugs(47, DBG_IMPORTANT, "Using Round Robin store dir selection");
+    } else {
+        storeDirSelectSwapDir = storeDirSelectSwapDirLeastLoad;
+        debugs(47, DBG_IMPORTANT, "Using Least Load store dir selection");
+    }
+}
+
+uint64_t
+Store::Disks::maxSize() const
+{
+    uint64_t result = 0;
+
+    for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
+        if (dir(i).doReportStat())
+            result += store(i)->maxSize();
+    }
+
+    return result;
+}
+
+uint64_t
+Store::Disks::minSize() const
+{
+    uint64_t result = 0;
+
+    for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
+        if (dir(i).doReportStat())
+            result += store(i)->minSize();
+    }
+
+    return result;
+}
+
+uint64_t
+Store::Disks::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
+Store::Disks::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
+Store::Disks::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;
+}
+
+void
+Store::Disks::getStats(StoreInfoStats &stats) const
+{
+    // accumulate per-disk cache stats
+    for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
+        StoreInfoStats dirStats;
+        store(i)->getStats(dirStats);
+        stats += dirStats;
+    }
+
+    // common to all disks
+    stats.swap.open_disk_fd = store_open_disk_fd;
+
+    // memory cache stats are collected in StoreController::getStats(), for now
+}
+
+void
+Store::Disks::stat(StoreEntry & output) const
+{
+    int i;
+
+    /* Now go through each store, calling its stat routine */
+
+    for (i = 0; i < Config.cacheSwap.n_configured; ++i) {
+        storeAppendPrintf(&output, "\n");
+        store(i)->stat(output);
+    }
+}
+
+void
+Store::Disks::reference(StoreEntry &e)
+{
+    e.disk().reference(e);
+}
+
+bool
+Store::Disks::dereference(StoreEntry &e)
+{
+    return e.disk().dereference(e);
+}
+
+void
+Store::Disks::maintain()
+{
+    int i;
+    /* walk each fs */
+
+    for (i = 0; i < Config.cacheSwap.n_configured; ++i) {
+        /* XXX FixMe: This should be done "in parallell" on the different
+         * cache_dirs, not one at a time.
+         */
+        /* call the maintain function .. */
+        store(i)->maintain();
+    }
+}
+
+void
+Store::Disks::sync()
+{
+    for (int i = 0; i < Config.cacheSwap.n_configured; ++i)
+        store(i)->sync();
+}
+
+void
+Store::Disks::markForUnlink(StoreEntry &e) {
+    if (e.swap_filen >= 0)
+        store(e.swap_dirn)->markForUnlink(e);
+}
+
+void
+Store::Disks::unlink(StoreEntry &e) {
+    if (e.swap_filen >= 0)
+        store(e.swap_dirn)->unlink(e);
+}
+
+bool
+Store::Disks::anchorCollapsed(StoreEntry &collapsed, bool &inSync)
+{
+    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 = dir(idx);
+            if (!sd.active())
+                continue;
+
+            if (sd.anchorCollapsed(collapsed, inSync)) {
+                debugs(20, 3, "cache_dir " << idx << " anchors " << collapsed);
+                return true;
+            }
+        }
+    }
+
+    debugs(20, 4, "none of " << Config.cacheSwap.n_configured <<
+           " cache_dirs have " << collapsed);
+    return false;
+}
+
+bool
+Store::Disks::updateCollapsed(StoreEntry &collapsed)
+{
+    return collapsed.swap_filen >= 0 &&
+           dir(collapsed.swap_dirn).updateCollapsed(collapsed);
+}
+
+/* Store::Disks globals that should be converted to use RegisteredRunner */
+
+void
+storeDirOpenSwapLogs()
+{
+    for (int dirn = 0; dirn < Config.cacheSwap.n_configured; ++dirn)
+        INDEXSD(dirn)->openLog();
+}
+
+void
+storeDirCloseSwapLogs()
+{
+    for (int dirn = 0; dirn < Config.cacheSwap.n_configured; ++dirn)
+        INDEXSD(dirn)->closeLog();
+}
+
+/**
+ *  storeDirWriteCleanLogs
+ *
+ *  Writes a "clean" swap log file from in-memory metadata.
+ *  This is a rewrite of the original function to troll each
+ *  StoreDir and write the logs, and flush at the end of
+ *  the run. Thanks goes to Eric Stern, since this solution
+ *  came out of his COSS code.
+ */
+int
+storeDirWriteCleanLogs(int reopen)
+{
+    const StoreEntry *e = NULL;
+    int n = 0;
+
+    struct timeval start;
+    double dt;
+    RefCount<SwapDir> sd;
+    int dirn;
+    int notdone = 1;
+
+    // Check for store_dirs_rebuilding because fatal() often calls us in early
+    // initialization phases, before store log is initialized and ready. Also,
+    // some stores probably do not support log cleanup during Store rebuilding.
+    if (StoreController::store_dirs_rebuilding) {
+        debugs(20, DBG_IMPORTANT, "Not currently OK to rewrite swap log.");
+        debugs(20, DBG_IMPORTANT, "storeDirWriteCleanLogs: Operation aborted.");
+        return 0;
+    }
+
+    debugs(20, DBG_IMPORTANT, "storeDirWriteCleanLogs: Starting...");
+    getCurrentTime();
+    start = current_time;
+
+    for (dirn = 0; dirn < Config.cacheSwap.n_configured; ++dirn) {
+        sd = dynamic_cast<SwapDir *>(INDEXSD(dirn));
+
+        if (sd->writeCleanStart() < 0) {
+            debugs(20, DBG_IMPORTANT, "log.clean.start() failed for dir #" << sd->index);
+            continue;
+        }
+    }
+
+    /*
+     * This may look inefficient as CPU wise it is more efficient to do this
+     * sequentially, but I/O wise the parallellism helps as it allows more
+     * hdd spindles to be active.
+     */
+    while (notdone) {
+        notdone = 0;
+
+        for (dirn = 0; dirn < Config.cacheSwap.n_configured; ++dirn) {
+            sd = dynamic_cast<SwapDir *>(INDEXSD(dirn));
+
+            if (NULL == sd->cleanLog)
+                continue;
+
+            e = sd->cleanLog->nextEntry();
+
+            if (!e)
+                continue;
+
+            notdone = 1;
+
+            if (!sd->canLog(*e))
+                continue;
+
+            sd->cleanLog->write(*e);
+
+            if ((++n & 0xFFFF) == 0) {
+                getCurrentTime();
+                debugs(20, DBG_IMPORTANT, "  " << std::setw(7) << n  <<
+                       " entries written so far.");
+            }
+        }
+    }
+
+    /* Flush */
+    for (dirn = 0; dirn < Config.cacheSwap.n_configured; ++dirn)
+        dynamic_cast<SwapDir *>(INDEXSD(dirn))->writeCleanDone();
+
+    if (reopen)
+        storeDirOpenSwapLogs();
+
+    getCurrentTime();
+
+    dt = tvSubDsec(start, current_time);
+
+    debugs(20, DBG_IMPORTANT, "  Finished.  Wrote " << n << " entries.");
+    debugs(20, DBG_IMPORTANT, "  Took "<< std::setw(3)<< std::setprecision(2) << dt <<
+           " seconds ("<< std::setw(6) << ((double) n / (dt > 0.0 ? dt : 1.0)) << " entries/sec).");
+
+    return n;
+}
+
+/* Globals that should be converted to static Store::Disks methods */
+
+void
+allocate_new_swapdir(Store::DiskConfig *swap)
+{
+    if (swap->swapDirs == NULL) {
+        swap->n_allocated = 4;
+        swap->swapDirs = static_cast<SwapDir::Pointer *>(xcalloc(swap->n_allocated, sizeof(SwapDir::Pointer)));
+    }
+
+    if (swap->n_allocated == swap->n_configured) {
+        swap->n_allocated <<= 1;
+        SwapDir::Pointer *const tmp = static_cast<SwapDir::Pointer *>(xcalloc(swap->n_allocated, sizeof(SwapDir::Pointer)));
+        memcpy(tmp, swap->swapDirs, swap->n_configured * sizeof(SwapDir *));
+        xfree(swap->swapDirs);
+        swap->swapDirs = tmp;
+    }
+}
+
+void
+free_cachedir(Store::DiskConfig *swap)
+{
+    int i;
+    /* DON'T FREE THESE FOR RECONFIGURE */
+
+    if (reconfiguring)
+        return;
+
+    for (i = 0; i < swap->n_configured; ++i) {
+        /* TODO XXX this lets the swapdir free resources asynchronously
+        * swap->swapDirs[i]->deactivate();
+        * but there may be such a means already.
+        * RBC 20041225
+        */
+        swap->swapDirs[i] = NULL;
+    }
+
+    safe_free(swap->swapDirs);
+    swap->swapDirs = NULL;
+    swap->n_allocated = 0;
+    swap->n_configured = 0;
+}
+
+/* Globals that should be moved to some Store::UFS-specific logging module */
+
+/**
+ * An entry written to the swap log MUST have the following
+ * properties.
+ *   1.  It MUST be a public key.  It does no good to log
+ *       a public ADD, change the key, then log a private
+ *       DEL.  So we need to log a DEL before we change a
+ *       key from public to private.
+ *   2.  It MUST have a valid (> -1) swap_filen.
+ */
+void
+storeDirSwapLog(const StoreEntry * e, int op)
+{
+    assert (e);
+    assert(!EBIT_TEST(e->flags, KEY_PRIVATE));
+    assert(e->swap_filen >= 0);
+    /*
+     * icons and such; don't write them to the swap log
+     */
+
+    if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
+        return;
+
+    assert(op > SWAP_LOG_NOP && op < SWAP_LOG_MAX);
+
+    debugs(20, 3, "storeDirSwapLog: " <<
+           swap_log_op_str[op] << " " <<
+           e->getMD5Text() << " " <<
+           e->swap_dirn << " " <<
+           std::hex << std::uppercase << std::setfill('0') << std::setw(8) << e->swap_filen);
+
+    dynamic_cast<SwapDir *>(INDEXSD(e->swap_dirn))->logEntry(*e, op);
+}
+
diff -u -r -N squid-4.0.2/src/store/Disks.h squid-4.0.3/src/store/Disks.h
--- squid-4.0.2/src/store/Disks.h	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/store/Disks.h	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_STORE_DISKS_H
+#define SQUID_STORE_DISKS_H
+
+#include "store/Controlled.h"
+#include "store/forward.h"
+
+namespace Store {
+
+/// summary view of all disk caches (cache_dirs) combined
+class Disks: public Controlled
+{
+public:
+    /* Storage API */
+    virtual void create() override;
+    virtual void init() override;
+    virtual StoreEntry *get(const cache_key *) override;
+    virtual uint64_t maxSize() const override;
+    virtual uint64_t minSize() const override;
+    virtual uint64_t currentSize() const override;
+    virtual uint64_t currentCount() const override;
+    virtual int64_t maxObjectSize() const override;
+    virtual void getStats(StoreInfoStats &stats) const override;
+    virtual void stat(StoreEntry &) const override;
+    virtual void sync() override;
+    virtual void reference(StoreEntry &) override;
+    virtual bool dereference(StoreEntry &e) override;
+    virtual void maintain() override;
+    virtual bool anchorCollapsed(StoreEntry &e, bool &inSync) override;
+    virtual bool updateCollapsed(StoreEntry &e) override;
+    virtual void markForUnlink(StoreEntry &) override;
+    virtual void unlink(StoreEntry &) override;
+    virtual int callback() override;
+
+private:
+    /* migration logic */
+    SwapDir *store(int const x) const;
+    SwapDir &dir(int const idx) const;
+};
+
+} // namespace Store
+
+/* Store::Disks globals that should be converted to use RegisteredRunner */
+void storeDirOpenSwapLogs(void);
+int storeDirWriteCleanLogs(int reopen);
+void storeDirCloseSwapLogs(void);
+
+/* Globals that should be converted to static Store::Disks methods */
+void allocate_new_swapdir(Store::DiskConfig *swap);
+void free_cachedir(Store::DiskConfig *swap);
+
+/* Globals that should be converted to Store::Disks private data members */
+typedef int STDIRSELECT(const StoreEntry *e);
+extern STDIRSELECT *storeDirSelectSwapDir;
+
+/* Globals that should be moved to some Store::UFS-specific logging module */
+void storeDirSwapLog(const StoreEntry *e, int op);
+
+#endif /* SQUID_STORE_DISKS_H */
+
diff -u -r -N squid-4.0.2/src/store/forward.h squid-4.0.3/src/store/forward.h
--- squid-4.0.2/src/store/forward.h	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/store/forward.h	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_STORE_FORWARD_H
+#define SQUID_STORE_FORWARD_H
+
+typedef int32_t sfileno;
+typedef signed int sdirno;
+
+/// maximum number of entries per cache_dir
+enum { SwapFilenMax = 0xFFFFFF }; // keep in sync with StoreEntry::swap_filen
+
+/// Store key.
+typedef unsigned char cache_key;
+
+class StoreSearch;
+class StoreClient;
+class StoreEntry;
+class MemStore;
+class Transients;
+
+namespace Store
+{
+class Storage;
+class Controller;
+class Controlled;
+class Disks;
+class Disk;
+class DiskConfig;
+
+typedef ::StoreEntry Entry;
+typedef ::MemStore Memory;
+typedef ::Transients Transients;
+} // namespace Store
+
+// TODO: Remove these once all code has been transitioned to Store namespace.
+typedef Store::Controller StoreController;
+typedef Store::Disks StoreHashIndex;
+typedef Store::Disk SwapDir;
+template <class C> class RefCount;
+typedef RefCount<Store::Disk> SwapDirPointer;
+
+#endif /* SQUID_STORE_FORWARD_H */
+
diff -u -r -N squid-4.0.2/src/store/LocalSearch.cc squid-4.0.3/src/store/LocalSearch.cc
--- squid-4.0.2/src/store/LocalSearch.cc	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/store/LocalSearch.cc	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/* DEBUG: section 47    Store Search */
+
+#include "squid.h"
+#include "Debug.h"
+#include "globals.h"
+#include "store/LocalSearch.h"
+#include "StoreSearch.h"
+
+namespace Store {
+
+/// iterates local store_table
+class LocalSearch : public StoreSearch
+{
+    CBDATA_CLASS(LocalSearch);
+
+public:
+    LocalSearch();
+
+    /* StoreSearch API */
+    virtual void next(void (callback)(void *cbdata), void *cbdata) override;
+    virtual bool next() override;
+    virtual bool error() const override;
+    virtual bool isDone() const override;
+    virtual StoreEntry *currentItem() override;
+
+private:
+    void copyBucket();
+    void (*callback)(void *cbdata);
+    void *cbdata;
+    bool _done;
+    int bucket;
+    std::vector<StoreEntry *> entries;
+};
+
+} // namespace Store
+
+CBDATA_NAMESPACED_CLASS_INIT(Store, LocalSearch);
+
+StoreSearch *
+Store::NewLocalSearch()
+{
+    return new LocalSearch;
+}
+
+Store::LocalSearch::LocalSearch() :
+    callback(NULL),
+    cbdata(NULL),
+    _done(false),
+    bucket(0)
+{}
+
+void
+Store::LocalSearch::next(void (aCallback)(void *), void *aCallbackData)
+{
+    next();
+    aCallback (aCallbackData);
+}
+
+bool
+Store::LocalSearch::next()
+{
+    if (!entries.empty())
+        entries.pop_back();
+
+    while (!isDone() && !entries.size())
+        copyBucket();
+
+    return currentItem() != NULL;
+}
+
+bool
+Store::LocalSearch::error() const
+{
+    return false;
+}
+
+bool
+Store::LocalSearch::isDone() const
+{
+    return bucket >= store_hash_buckets || _done;
+}
+
+StoreEntry *
+Store::LocalSearch::currentItem()
+{
+    if (!entries.size())
+        return NULL;
+
+    return entries.back();
+}
+
+void
+Store::LocalSearch::copyBucket()
+{
+    /* probably need to lock the store entries...
+     * we copy them all to prevent races on the links. */
+    debugs(47, 3, "Store::LocalSearch::copyBucket #" << bucket);
+    assert (!entries.size());
+    hash_link *link_ptr = NULL;
+    hash_link *link_next = NULL;
+    link_next = hash_get_bucket(store_table, bucket);
+
+    while (NULL != (link_ptr = link_next)) {
+        link_next = link_ptr->next;
+        StoreEntry *e = (StoreEntry *) link_ptr;
+
+        entries.push_back(e);
+    }
+
+    ++bucket;
+    debugs(47,3, "got entries: " << entries.size());
+}
+
diff -u -r -N squid-4.0.2/src/store/LocalSearch.h squid-4.0.3/src/store/LocalSearch.h
--- squid-4.0.2/src/store/LocalSearch.h	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/store/LocalSearch.h	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_STORE_LOCAL_SEARCH_H
+#define SQUID_STORE_LOCAL_SEARCH_H
+
+#include "store/forward.h"
+
+namespace Store {
+StoreSearch *NewLocalSearch();
+} // namespace Store
+
+#endif /* SQUID_STORE_LOCAL_SEARCH_H */
+
diff -u -r -N squid-4.0.2/src/store/Makefile.am squid-4.0.3/src/store/Makefile.am
--- squid-4.0.2/src/store/Makefile.am	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/store/Makefile.am	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,24 @@
+## Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+##
+## Squid software is distributed under GPLv2+ license and includes
+## contributions from numerous individuals and organizations.
+## Please see the COPYING and CONTRIBUTORS files for details.
+##
+
+include $(top_srcdir)/src/Common.am
+include $(top_srcdir)/src/TestHeaders.am
+
+noinst_LTLIBRARIES = libstore.la
+
+libstore_la_SOURCES= \
+	Controlled.h \
+	Controller.cc \
+	Controller.h \
+	Disk.cc \
+	Disk.h \
+	Disks.cc \
+	Disks.h \
+	forward.h \
+	LocalSearch.cc \
+	LocalSearch.h \
+	Storage.h
diff -u -r -N squid-4.0.2/src/store/Makefile.in squid-4.0.3/src/store/Makefile.in
--- squid-4.0.2/src/store/Makefile.in	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/store/Makefile.in	2015-11-28 07:32:54.000000000 -0800
@@ -0,0 +1,1191 @@
+# Makefile.in generated by automake 1.15 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2014 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+check_PROGRAMS =
+@ENABLE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL)
+subdir = src/store
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude/ax_with_prog.m4 \
+	$(top_srcdir)/acinclude/init.m4 \
+	$(top_srcdir)/acinclude/squid-util.m4 \
+	$(top_srcdir)/acinclude/compiler-flags.m4 \
+	$(top_srcdir)/acinclude/os-deps.m4 \
+	$(top_srcdir)/acinclude/krb5.m4 $(top_srcdir)/acinclude/pam.m4 \
+	$(top_srcdir)/acinclude/pkg.m4 \
+	$(top_srcdir)/acinclude/lib-checks.m4 \
+	$(top_srcdir)/acinclude/ax_cxx_compile_stdcxx_11.m4 \
+	$(top_srcdir)/acinclude/ax_cxx_0x_types.m4 \
+	$(top_srcdir)/helpers/basic_auth/modules.m4 \
+	$(top_srcdir)/helpers/basic_auth/DB/required.m4 \
+	$(top_srcdir)/helpers/basic_auth/LDAP/required.m4 \
+	$(top_srcdir)/helpers/basic_auth/NCSA/required.m4 \
+	$(top_srcdir)/helpers/basic_auth/NIS/required.m4 \
+	$(top_srcdir)/helpers/basic_auth/PAM/required.m4 \
+	$(top_srcdir)/helpers/basic_auth/POP3/required.m4 \
+	$(top_srcdir)/helpers/basic_auth/RADIUS/required.m4 \
+	$(top_srcdir)/helpers/basic_auth/SASL/required.m4 \
+	$(top_srcdir)/helpers/basic_auth/SMB/required.m4 \
+	$(top_srcdir)/helpers/basic_auth/SMB_LM/required.m4 \
+	$(top_srcdir)/helpers/basic_auth/SSPI/required.m4 \
+	$(top_srcdir)/helpers/basic_auth/fake/required.m4 \
+	$(top_srcdir)/helpers/basic_auth/getpwnam/required.m4 \
+	$(top_srcdir)/helpers/digest_auth/modules.m4 \
+	$(top_srcdir)/helpers/digest_auth/LDAP/required.m4 \
+	$(top_srcdir)/helpers/digest_auth/eDirectory/required.m4 \
+	$(top_srcdir)/helpers/digest_auth/file/required.m4 \
+	$(top_srcdir)/helpers/negotiate_auth/modules.m4 \
+	$(top_srcdir)/helpers/negotiate_auth/SSPI/required.m4 \
+	$(top_srcdir)/helpers/negotiate_auth/kerberos/required.m4 \
+	$(top_srcdir)/helpers/negotiate_auth/wrapper/required.m4 \
+	$(top_srcdir)/helpers/ntlm_auth/modules.m4 \
+	$(top_srcdir)/helpers/ntlm_auth/fake/required.m4 \
+	$(top_srcdir)/helpers/ntlm_auth/SSPI/required.m4 \
+	$(top_srcdir)/helpers/ntlm_auth/smb_lm/required.m4 \
+	$(top_srcdir)/helpers/log_daemon/modules.m4 \
+	$(top_srcdir)/helpers/log_daemon/DB/required.m4 \
+	$(top_srcdir)/helpers/log_daemon/file/required.m4 \
+	$(top_srcdir)/helpers/external_acl/modules.m4 \
+	$(top_srcdir)/helpers/external_acl/AD_group/required.m4 \
+	$(top_srcdir)/helpers/external_acl/LDAP_group/required.m4 \
+	$(top_srcdir)/helpers/external_acl/LM_group/required.m4 \
+	$(top_srcdir)/helpers/external_acl/delayer/required.m4 \
+	$(top_srcdir)/helpers/external_acl/SQL_session/required.m4 \
+	$(top_srcdir)/helpers/external_acl/eDirectory_userip/required.m4 \
+	$(top_srcdir)/helpers/external_acl/file_userip/required.m4 \
+	$(top_srcdir)/helpers/external_acl/kerberos_ldap_group/required.m4 \
+	$(top_srcdir)/helpers/external_acl/session/required.m4 \
+	$(top_srcdir)/helpers/external_acl/time_quota/required.m4 \
+	$(top_srcdir)/helpers/external_acl/unix_group/required.m4 \
+	$(top_srcdir)/helpers/external_acl/wbinfo_group/required.m4 \
+	$(top_srcdir)/helpers/url_rewrite/modules.m4 \
+	$(top_srcdir)/helpers/url_rewrite/fake/required.m4 \
+	$(top_srcdir)/helpers/url_rewrite/LFS/required.m4 \
+	$(top_srcdir)/helpers/storeid_rewrite/modules.m4 \
+	$(top_srcdir)/helpers/storeid_rewrite/file/required.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/autoconf.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libstore_la_LIBADD =
+am_libstore_la_OBJECTS = Controller.lo Disk.lo Disks.lo LocalSearch.lo
+libstore_la_OBJECTS = $(am_libstore_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = 
+depcomp = $(SHELL) $(top_srcdir)/cfgaux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_@AM_V@)
+am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
+am__v_CXX_0 = @echo "  CXX     " $@;
+am__v_CXX_1 = 
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo "  CXXLD   " $@;
+am__v_CXXLD_1 = 
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(libstore_la_SOURCES)
+DIST_SOURCES = $(libstore_la_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+  mgn= red= grn= lgn= blu= brg= std=; \
+  am__color_tests=no
+am__tty_colors = { \
+  $(am__tty_colors_dummy); \
+  if test "X$(AM_COLOR_TESTS)" = Xno; then \
+    am__color_tests=no; \
+  elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+    am__color_tests=yes; \
+  elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+    am__color_tests=yes; \
+  fi; \
+  if test $$am__color_tests = yes; then \
+    red='[0;31m'; \
+    grn='[0;32m'; \
+    lgn='[1;32m'; \
+    blu='[1;34m'; \
+    mgn='[0;35m'; \
+    brg='[1m'; \
+    std='[m'; \
+  fi; \
+}
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__recheck_rx = ^[ 	]*:recheck:[ 	]*
+am__global_test_result_rx = ^[ 	]*:global-test-result:[ 	]*
+am__copy_in_global_log_rx = ^[ 	]*:copy-in-global-log:[ 	]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+  recheck = 1; \
+  while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+    { \
+      if (rc < 0) \
+        { \
+          if ((getline line2 < ($$0 ".log")) < 0) \
+	    recheck = 0; \
+          break; \
+        } \
+      else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+        { \
+          recheck = 0; \
+          break; \
+        } \
+      else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+        { \
+          break; \
+        } \
+    }; \
+  if (recheck) \
+    print $$0; \
+  close ($$0 ".trs"); \
+  close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+  print "fatal: making $@: " msg | "cat >&2"; \
+  exit 1; \
+} \
+function rst_section(header) \
+{ \
+  print header; \
+  len = length(header); \
+  for (i = 1; i <= len; i = i + 1) \
+    printf "="; \
+  printf "\n\n"; \
+} \
+{ \
+  copy_in_global_log = 1; \
+  global_test_result = "RUN"; \
+  while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+    { \
+      if (rc < 0) \
+         fatal("failed to read from " $$0 ".trs"); \
+      if (line ~ /$(am__global_test_result_rx)/) \
+        { \
+          sub("$(am__global_test_result_rx)", "", line); \
+          sub("[ 	]*$$", "", line); \
+          global_test_result = line; \
+        } \
+      else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+        copy_in_global_log = 0; \
+    }; \
+  if (copy_in_global_log) \
+    { \
+      rst_section(global_test_result ": " $$0); \
+      while ((rc = (getline line < ($$0 ".log"))) != 0) \
+      { \
+        if (rc < 0) \
+          fatal("failed to read from " $$0 ".log"); \
+        print line; \
+      }; \
+      printf "\n"; \
+    }; \
+  close ($$0 ".trs"); \
+  close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/   &   /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this.  Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+  --color-tests "$$am__color_tests" \
+  --enable-hard-errors "$$am__enable_hard_errors" \
+  --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test.  Creates the
+# directory for the log if needed.  Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log.  Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT.  Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup);					\
+$(am__vpath_adj_setup) $(am__vpath_adj)			\
+$(am__tty_colors);					\
+srcdir=$(srcdir); export srcdir;			\
+case "$@" in						\
+  */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;;	\
+    *) am__odir=.;; 					\
+esac;							\
+test "x$$am__odir" = x"." || test -d "$$am__odir" 	\
+  || $(MKDIR_P) "$$am__odir" || exit $$?;		\
+if test -f "./$$f"; then dir=./;			\
+elif test -f "$$f"; then dir=;				\
+else dir="$(srcdir)/"; fi;				\
+tst=$$dir$$f; log='$@'; 				\
+if test -n '$(DISABLE_HARD_ERRORS)'; then		\
+  am__enable_hard_errors=no; 				\
+else							\
+  am__enable_hard_errors=yes; 				\
+fi; 							\
+case " $(XFAIL_TESTS) " in				\
+  *[\ \	]$$f[\ \	]* | *[\ \	]$$dir$$f[\ \	]*) \
+    am__expect_failure=yes;;				\
+  *)							\
+    am__expect_failure=no;;				\
+esac; 							\
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed).  The result is saved in the shell variable
+# '$bases'.  This honors runtime overriding of TESTS and TEST_LOGS.  Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+  bases='$(TEST_LOGS)'; \
+  bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+  bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_DRIVER = $(SHELL) $(top_srcdir)/cfgaux/test-driver
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+  case '$@' in \
+    */*) \
+      case '$*' in \
+        */*) b='$*';; \
+          *) b=`echo '$@' | sed 's/\.log$$//'`; \
+       esac;; \
+    *) \
+      b='$*';; \
+  esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/cfgaux/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+	$(TEST_LOG_FLAGS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/cfgaux/depcomp \
+	$(top_srcdir)/cfgaux/test-driver $(top_srcdir)/src/Common.am \
+	$(top_srcdir)/src/TestHeaders.am
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ADAPTATION_LIBS = @ADAPTATION_LIBS@
+AIOLIB = @AIOLIB@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ARGZ_H = @ARGZ_H@
+AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
+AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
+AUTH_MODULES = @AUTH_MODULES@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASIC_AUTH_HELPERS = @BASIC_AUTH_HELPERS@
+BUILDCXX = @BUILDCXX@
+BUILDCXXFLAGS = @BUILDCXXFLAGS@
+BZR = @BZR@
+CACHE_EFFECTIVE_USER = @CACHE_EFFECTIVE_USER@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CGIEXT = @CGIEXT@
+CHMOD = @CHMOD@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPUNITCONFIG = @CPPUNITCONFIG@
+CRYPTLIB = @CRYPTLIB@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_HOSTS = @DEFAULT_HOSTS@
+DEFAULT_LOG_DIR = @DEFAULT_LOG_DIR@
+DEFAULT_PID_FILE = @DEFAULT_PID_FILE@
+DEFAULT_SWAP_DIR = @DEFAULT_SWAP_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
+DISK_LIBS = @DISK_LIBS@
+DISK_MODULES = @DISK_MODULES@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECAP_LIBS = @ECAP_LIBS@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EPOLL_LIBS = @EPOLL_LIBS@
+EUILIB = @EUILIB@
+EXEEXT = @EXEEXT@
+EXPATLIB = @EXPATLIB@
+EXTERNAL_ACL_HELPERS = @EXTERNAL_ACL_HELPERS@
+EXT_LIBECAP_CFLAGS = @EXT_LIBECAP_CFLAGS@
+EXT_LIBECAP_LIBS = @EXT_LIBECAP_LIBS@
+FALSE = @FALSE@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+ICAP_LIBS = @ICAP_LIBS@
+INCLTDL = @INCLTDL@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KRB5INCS = @KRB5INCS@
+KRB5LIBS = @KRB5LIBS@
+LBERLIB = @LBERLIB@
+LD = @LD@
+LDAPLIB = @LDAPLIB@
+LDFLAGS = @LDFLAGS@
+LIBADD_DL = @LIBADD_DL@
+LIBADD_DLD_LINK = @LIBADD_DLD_LINK@
+LIBADD_DLOPEN = @LIBADD_DLOPEN@
+LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@
+LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
+LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
+LIBLTDL = @LIBLTDL@
+LIBOBJS = @LIBOBJS@
+LIBOPENSSL_CFLAGS = @LIBOPENSSL_CFLAGS@
+LIBOPENSSL_LIBS = @LIBOPENSSL_LIBS@
+LIBPTHREADS = @LIBPTHREADS@
+LIBS = @LIBS@
+LIBSASL = @LIBSASL@
+LIBTOOL = @LIBTOOL@
+LIB_DB = @LIB_DB@
+LIB_KRB5_CFLAGS = @LIB_KRB5_CFLAGS@
+LIB_KRB5_LIBS = @LIB_KRB5_LIBS@
+LINUXDOC = @LINUXDOC@
+LIPO = @LIPO@
+LN = @LN@
+LN_S = @LN_S@
+LOG_DAEMON_HELPERS = @LOG_DAEMON_HELPERS@
+LTDLDEPS = @LTDLDEPS@
+LTDLINCL = @LTDLINCL@
+LTDLOPEN = @LTDLOPEN@
+LTLIBOBJS = @LTLIBOBJS@
+LT_CONFIG_H = @LT_CONFIG_H@
+LT_DLLOADERS = @LT_DLLOADERS@
+LT_DLPREOPEN = @LT_DLPREOPEN@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MINGW_LIBS = @MINGW_LIBS@
+MKDIR = @MKDIR@
+MKDIR_P = @MKDIR_P@
+MV = @MV@
+NEGOTIATE_AUTH_HELPERS = @NEGOTIATE_AUTH_HELPERS@
+NETTLELIB = @NETTLELIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NTLM_AUTH_HELPERS = @NTLM_AUTH_HELPERS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PO2HTML = @PO2HTML@
+PO2TEXT = @PO2TEXT@
+POD2MAN = @POD2MAN@
+RANLIB = @RANLIB@
+REGEXLIB = @REGEXLIB@
+REPL_LIBS = @REPL_LIBS@
+REPL_OBJS = @REPL_OBJS@
+REPL_POLICIES = @REPL_POLICIES@
+RM = @RM@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SH = @SH@
+SHELL = @SHELL@
+SMBCLIENT = @SMBCLIENT@
+SNMPLIB = @SNMPLIB@
+SQUID_CFLAGS = @SQUID_CFLAGS@
+SQUID_CPPUNIT_INC = @SQUID_CPPUNIT_INC@
+SQUID_CPPUNIT_LA = @SQUID_CPPUNIT_LA@
+SQUID_CPPUNIT_LIBS = @SQUID_CPPUNIT_LIBS@
+SQUID_CXXFLAGS = @SQUID_CXXFLAGS@
+SSLLIB = @SSLLIB@
+STOREID_REWRITE_HELPERS = @STOREID_REWRITE_HELPERS@
+STORE_LIBS_TO_ADD = @STORE_LIBS_TO_ADD@
+STORE_LIBS_TO_BUILD = @STORE_LIBS_TO_BUILD@
+STORE_TESTS = @STORE_TESTS@
+STRIP = @STRIP@
+TR = @TR@
+TRUE = @TRUE@
+URL_REWRITE_HELPERS = @URL_REWRITE_HELPERS@
+VERSION = @VERSION@
+WBINFO = @WBINFO@
+WIN32_PSAPI = @WIN32_PSAPI@
+XMLLIB = @XMLLIB@
+XTRA_LIBS = @XTRA_LIBS@
+XTRA_OBJS = @XTRA_OBJS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+krb5_config = @krb5_config@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+ltdl_LIBOBJS = @ltdl_LIBOBJS@
+ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sys_symbol_underscore = @sys_symbol_underscore@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CFLAGS = $(SQUID_CFLAGS)
+AM_CXXFLAGS = $(SQUID_CXXFLAGS)
+CLEANFILES = testHeaders
+TESTS = testHeaders
+AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
+	-I$(top_srcdir)/lib -I$(top_srcdir)/src \
+	-I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(KRB5INCS) \
+	$(am__append_1)
+@ENABLE_XPROF_STATS_FALSE@LIBPROFILER = 
+@ENABLE_XPROF_STATS_TRUE@LIBPROFILER = $(top_builddir)/lib/profiler/libprofiler.la
+COMPAT_LIB = $(top_builddir)/compat/libcompat-squid.la $(LIBPROFILER)
+subst_perlshell = sed -e 's,[@]PERL[@],$(PERL),g' <$(srcdir)/$@.pl.in >$@ || ($(RM) -f $@ ; exit 1)
+noinst_LTLIBRARIES = libstore.la
+libstore_la_SOURCES = \
+	Controlled.h \
+	Controller.cc \
+	Controller.h \
+	Disk.cc \
+	Disk.h \
+	Disks.cc \
+	Disks.h \
+	forward.h \
+	LocalSearch.cc \
+	LocalSearch.h \
+	Storage.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cc .lo .log .o .obj .test .test$(EXEEXT) .trs
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/src/Common.am $(top_srcdir)/src/TestHeaders.am $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/store/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign src/store/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+$(top_srcdir)/src/Common.am $(top_srcdir)/src/TestHeaders.am $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+libstore.la: $(libstore_la_OBJECTS) $(libstore_la_DEPENDENCIES) $(EXTRA_libstore_la_DEPENDENCIES) 
+	$(AM_V_CXXLD)$(CXXLINK)  $(libstore_la_OBJECTS) $(libstore_la_LIBADD) $(LIBS)
+
+clean-checkPROGRAMS:
+	@list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Controller.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Disk.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Disks.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LocalSearch.Plo@am__quote@
+
+.cc.o:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCXX_TRUE@	$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'.  Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+	rm -f $< $@
+	$(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+	@:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+	@$(am__set_TESTS_bases); \
+	am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+	redo_bases=`for i in $$bases; do \
+	              am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+	            done`; \
+	if test -n "$$redo_bases"; then \
+	  redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+	  redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+	  if $(am__make_dryrun); then :; else \
+	    rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+	  fi; \
+	fi; \
+	if test -n "$$am__remaking_logs"; then \
+	  echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+	       "recursion detected" >&2; \
+	elif test -n "$$redo_logs"; then \
+	  am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+	fi; \
+	if $(am__make_dryrun); then :; else \
+	  st=0;  \
+	  errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+	  for i in $$redo_bases; do \
+	    test -f $$i.trs && test -r $$i.trs \
+	      || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+	    test -f $$i.log && test -r $$i.log \
+	      || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+	  done; \
+	  test $$st -eq 0 || exit 1; \
+	fi
+	@$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+	ws='[ 	]'; \
+	results=`for b in $$bases; do echo $$b.trs; done`; \
+	test -n "$$results" || results=/dev/null; \
+	all=`  grep "^$$ws*:test-result:"           $$results | wc -l`; \
+	pass=` grep "^$$ws*:test-result:$$ws*PASS"  $$results | wc -l`; \
+	fail=` grep "^$$ws*:test-result:$$ws*FAIL"  $$results | wc -l`; \
+	skip=` grep "^$$ws*:test-result:$$ws*SKIP"  $$results | wc -l`; \
+	xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+	xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+	error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+	if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+	  success=true; \
+	else \
+	  success=false; \
+	fi; \
+	br='==================='; br=$$br$$br$$br$$br; \
+	result_count () \
+	{ \
+	    if test x"$$1" = x"--maybe-color"; then \
+	      maybe_colorize=yes; \
+	    elif test x"$$1" = x"--no-color"; then \
+	      maybe_colorize=no; \
+	    else \
+	      echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+	    fi; \
+	    shift; \
+	    desc=$$1 count=$$2; \
+	    if test $$maybe_colorize = yes && test $$count -gt 0; then \
+	      color_start=$$3 color_end=$$std; \
+	    else \
+	      color_start= color_end=; \
+	    fi; \
+	    echo "$${color_start}# $$desc $$count$${color_end}"; \
+	}; \
+	create_testsuite_report () \
+	{ \
+	  result_count $$1 "TOTAL:" $$all   "$$brg"; \
+	  result_count $$1 "PASS: " $$pass  "$$grn"; \
+	  result_count $$1 "SKIP: " $$skip  "$$blu"; \
+	  result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+	  result_count $$1 "FAIL: " $$fail  "$$red"; \
+	  result_count $$1 "XPASS:" $$xpass "$$red"; \
+	  result_count $$1 "ERROR:" $$error "$$mgn"; \
+	}; \
+	{								\
+	  echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" |	\
+	    $(am__rst_title);						\
+	  create_testsuite_report --no-color;				\
+	  echo;								\
+	  echo ".. contents:: :depth: 2";				\
+	  echo;								\
+	  for b in $$bases; do echo $$b; done				\
+	    | $(am__create_global_log);					\
+	} >$(TEST_SUITE_LOG).tmp || exit 1;				\
+	mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG);			\
+	if $$success; then						\
+	  col="$$grn";							\
+	 else								\
+	  col="$$red";							\
+	  test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG);		\
+	fi;								\
+	echo "$${col}$$br$${std}"; 					\
+	echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}";	\
+	echo "$${col}$$br$${std}"; 					\
+	create_testsuite_report --maybe-color;				\
+	echo "$$col$$br$$std";						\
+	if $$success; then :; else					\
+	  echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}";		\
+	  if test -n "$(PACKAGE_BUGREPORT)"; then			\
+	    echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}";	\
+	  fi;								\
+	  echo "$$col$$br$$std";					\
+	fi;								\
+	$$success || exit 1
+
+check-TESTS:
+	@list='$(RECHECK_LOGS)';           test -z "$$list" || rm -f $$list
+	@list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+	@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+	@set +e; $(am__set_TESTS_bases); \
+	log_list=`for i in $$bases; do echo $$i.log; done`; \
+	trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+	log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+	$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+	exit $$?;
+recheck: all $(check_PROGRAMS)
+	@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+	@set +e; $(am__set_TESTS_bases); \
+	bases=`for i in $$bases; do echo $$i; done \
+	         | $(am__list_recheck_tests)` || exit 1; \
+	log_list=`for i in $$bases; do echo $$i.log; done`; \
+	log_list=`echo $$log_list`; \
+	$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+	        am__force_recheck=am--force-recheck \
+	        TEST_LOGS="$$log_list"; \
+	exit $$?
+testHeaders.log: testHeaders
+	@p='testHeaders'; \
+	b='testHeaders'; \
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+	@p='$<'; \
+	$(am__set_b); \
+	$(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+	--log-file $$b.log --trs-file $$b.trs \
+	$(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@	@p='$<'; \
+@am__EXEEXT_TRUE@	$(am__set_b); \
+@am__EXEEXT_TRUE@	$(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@	--log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@	$(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@	"$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+	-test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+	-test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+	-test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+	clean-noinstLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
+	clean-checkPROGRAMS clean-generic clean-libtool \
+	clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am recheck tags tags-am uninstall \
+	uninstall-am
+
+.PRECIOUS: Makefile
+
+
+$(OBJS): $(top_srcdir)/include/version.h $(top_builddir)/include/autoconf.h
+
+testHeaders: $(srcdir)/*.h
+	$(SHELL) $(top_srcdir)/test-suite/testheaders.sh "$(CXXCOMPILE)" $^ || exit 1
+
+.PHONY: testHeaders
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff -u -r -N squid-4.0.2/src/store/Storage.h squid-4.0.3/src/store/Storage.h
--- squid-4.0.2/src/store/Storage.h	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/src/store/Storage.h	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_STORE_STORAGE_H
+#define SQUID_STORE_STORAGE_H
+
+#include "base/RefCount.h"
+#include "store/forward.h"
+
+class StoreInfoStats;
+
+namespace Store {
+
+/// A "response storage" abstraction.
+/// This API is shared among Controller and Controlled classes.
+class Storage: public RefCountable
+{
+public:
+    virtual ~Storage() {}
+
+    /// create system resources needed for this store to operate in the future
+    virtual void create() = 0;
+
+    /// Start preparing the store for use. To check readiness, callers should
+    /// use readable() and writable() methods.
+    virtual void init() = 0;
+
+    /// Retrieve a store entry from the store (blocking)
+    virtual StoreEntry *get(const cache_key *) = 0;
+
+    /**
+     * The maximum size the store will support in normal use. Inaccuracy is
+     * permitted, but may throw estimates for memory etc out of whack.
+     */
+    virtual uint64_t maxSize() const = 0;
+
+    /// the minimum size the store will shrink to via normal housekeeping
+    virtual uint64_t minSize() const = 0;
+
+    /// current size
+    virtual uint64_t currentSize() const = 0;
+
+    /// the total number of objects stored right now
+    virtual uint64_t currentCount() const = 0;
+
+    /// the maximum size of a storable object; -1 if unlimited
+    virtual int64_t maxObjectSize() const = 0;
+
+    /// collect statistics
+    virtual void getStats(StoreInfoStats &stats) const = 0;
+
+    /**
+     * Output stats to the provided store entry.
+     \todo make these calls asynchronous
+     */
+    virtual void stat(StoreEntry &e) const = 0;
+
+    /// expect an unlink() call after the entry becomes idle
+    virtual void markForUnlink(StoreEntry &e) = 0;
+
+    /// remove the entry from the store
+    virtual void unlink(StoreEntry &e) = 0;
+
+    /// called once every main loop iteration; TODO: Move to UFS code.
+    virtual int callback() { return 0; }
+
+    /// perform regular periodic maintenance; TODO: move to UFSSwapDir::Maintain
+    virtual void maintain() = 0;
+
+    /// prepare for shutdown
+    virtual void sync() {}
+};
+
+} // namespace Store
+
+#endif /* SQUID_STORE_STORAGE_H */
+
diff -u -r -N squid-4.0.2/src/store.cc squid-4.0.3/src/store.cc
--- squid-4.0.2/src/store.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/store.cc	2015-11-28 07:30:57.000000000 -0800
@@ -32,6 +32,9 @@
 #include "StatCounters.h"
 #include "stmem.h"
 #include "Store.h"
+#include "store/Controller.h"
+#include "store/Disk.h"
+#include "store/Disks.h"
 #include "store_digest.h"
 #include "store_key_md5.h"
 #include "store_key_md5.h"
@@ -42,7 +45,6 @@
 #include "StoreMeta.h"
 #include "StrList.h"
 #include "swap_log_op.h"
-#include "SwapDir.h"
 #include "tools.h"
 #if USE_DELAY_POOLS
 #include "DelayPools.h"
@@ -110,20 +112,6 @@
 static std::stack<StoreEntry*> LateReleaseStack;
 MemAllocator *StoreEntry::pool = NULL;
 
-StorePointer Store::CurrentRoot = NULL;
-
-void
-Store::Root(Store * aRoot)
-{
-    CurrentRoot = aRoot;
-}
-
-void
-Store::Root(StorePointer aRoot)
-{
-    Root(aRoot.getRaw());
-}
-
 void
 Store::Stats(StoreEntry * output)
 {
@@ -132,24 +120,6 @@
 }
 
 void
-Store::create()
-{}
-
-void
-Store::diskFull()
-{}
-
-void
-Store::sync()
-{}
-
-void
-Store::unlink(StoreEntry &)
-{
-    fatal("Store::unlink on invalid Store\n");
-}
-
-void
 StoreEntry::makePublic()
 {
     /* This object can be cached for a long time */
@@ -413,10 +383,8 @@
         return;
 
     // Store::Root() is FATALly missing during shutdown
-    if (e->swap_filen >= 0 && !shutting_down) {
-        SwapDir &sd = dynamic_cast<SwapDir&>(*e->store());
-        sd.disconnect(*e);
-    }
+    if (e->swap_filen >= 0 && !shutting_down)
+        e->disk().disconnect(*e);
 
     e->destroyMemObject();
 
@@ -475,7 +443,6 @@
 StoreEntry::touch()
 {
     lastref = squid_curtime;
-    Store::Root().reference(*this);
 }
 
 void
@@ -1233,34 +1200,6 @@
 #define MAINTAIN_MAX_SCAN       1024
 #define MAINTAIN_MAX_REMOVE     64
 
-/*
- * This routine is to be called by main loop in main.c.
- * It removes expired objects on only one bucket for each time called.
- *
- * This should get called 1/s from main().
- */
-void
-StoreController::maintain()
-{
-    static time_t last_warn_time = 0;
-
-    PROF_start(storeMaintainSwapSpace);
-    swapDir->maintain();
-
-    /* this should be emitted by the oversize dir, not globally */
-
-    if (Store::Root().currentSize() > Store::Root().maxSize()) {
-        if (squid_curtime - last_warn_time > 10) {
-            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;
-        }
-    }
-
-    PROF_stop(storeMaintainSwapSpace);
-}
-
 /* release an object from a cache */
 void
 StoreEntry::release()
@@ -1278,35 +1217,27 @@
         return;
     }
 
-    Store::Root().memoryUnlink(*this);
+    if (Store::Controller::store_dirs_rebuilding && swap_filen > -1) {
+        /* TODO: Teach disk stores to handle releases during rebuild instead. */
 
-    if (StoreController::store_dirs_rebuilding && swap_filen > -1) {
-        setPrivateKey();
+        Store::Root().memoryUnlink(*this);
 
-        if (swap_filen > -1) {
-            // lock the entry until rebuilding is done
-            lock("storeLateRelease");
-            setReleaseFlag();
-            LateReleaseStack.push(this);
-        } else {
-            destroyStoreEntry(static_cast<hash_link *>(this));
-            // "this" is no longer valid
-        }
+        setPrivateKey();
 
-        PROF_stop(storeRelease);
+        // lock the entry until rebuilding is done
+        lock("storeLateRelease");
+        setReleaseFlag();
+        LateReleaseStack.push(this);
         return;
     }
 
     storeLog(STORE_LOG_RELEASE, this);
-
-    if (swap_filen > -1) {
+    if (swap_filen > -1 && !EBIT_TEST(flags, KEY_PRIVATE)) {
         // log before unlink() below clears swap_filen
-        if (!EBIT_TEST(flags, KEY_PRIVATE))
-            storeDirSwapLog(this, SWAP_LOG_DEL);
-
-        unlink();
+        storeDirSwapLog(this, SWAP_LOG_DEL);
     }
 
+    Store::Root().unlink(*this);
     destroyStoreEntry(static_cast<hash_link *>(this));
     PROF_stop(storeRelease);
 }
@@ -1317,7 +1248,7 @@
     StoreEntry *e;
     static int n = 0;
 
-    if (StoreController::store_dirs_rebuilding) {
+    if (Store::Controller::store_dirs_rebuilding) {
         eventAdd("storeLateRelease", storeLateRelease, NULL, 1.0, 1);
         return;
     }
@@ -1519,14 +1450,10 @@
 void
 storeFreeMemory(void)
 {
-    Store::Root(NULL);
+    Store::FreeMemory();
 #if USE_CACHE_DIGESTS
-
-    if (store_digest)
-        cacheDigestDestroy(store_digest);
-
+    delete store_digest;
 #endif
-
     store_digest = NULL;
 }
 
@@ -2095,20 +2022,13 @@
     return matched;
 }
 
-SwapDir::Pointer
-StoreEntry::store() const
+Store::Disk &
+StoreEntry::disk() const
 {
     assert(0 <= swap_dirn && swap_dirn < Config.cacheSwap.n_configured);
-    return INDEXSD(swap_dirn);
-}
-
-void
-StoreEntry::unlink()
-{
-    store()->unlink(*this); // implies disconnect()
-    swap_filen = -1;
-    swap_dirn = -1;
-    swap_status = SWAPOUT_NONE;
+    const RefCount<Store::Disk> &sd = INDEXSD(swap_dirn);
+    assert(sd);
+    return *sd;
 }
 
 /*
diff -u -r -N squid-4.0.2/src/store_digest.cc squid-4.0.3/src/store_digest.cc
--- squid-4.0.2/src/store_digest.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/store_digest.cc	2015-11-28 07:30:57.000000000 -0800
@@ -107,7 +107,7 @@
         return;
     }
 
-    store_digest = cacheDigestCreate(cap, Config.digest.bits_per_entry);
+    store_digest = new CacheDigest(cap, Config.digest.bits_per_entry);
     debugs(71, DBG_IMPORTANT, "Local cache digest enabled; rebuild/rewrite every " <<
            (int) Config.digest.rebuild_period << "/" <<
            (int) Config.digest.rewrite_period << " sec");
@@ -147,12 +147,12 @@
     debugs(71, 6, "storeDigestDel: checking entry, key: " << entry->getMD5Text());
 
     if (!EBIT_TEST(entry->flags, KEY_PRIVATE)) {
-        if (!cacheDigestTest(store_digest,  (const cache_key *)entry->key)) {
+        if (!store_digest->contains(static_cast<const cache_key *>(entry->key))) {
             ++sd_stats.del_lost_count;
             debugs(71, 6, "storeDigestDel: lost entry, key: " << entry->getMD5Text() << " url: " << entry->url()  );
         } else {
             ++sd_stats.del_count;
-            cacheDigestDel(store_digest,  (const cache_key *)entry->key);
+            store_digest->remove(static_cast<const cache_key *>(entry->key));
             debugs(71, 6, "storeDigestDel: deled entry, key: " << entry->getMD5Text());
         }
     }
@@ -254,16 +254,16 @@
     if (storeDigestAddable(entry)) {
         ++sd_stats.add_count;
 
-        if (cacheDigestTest(store_digest, (const cache_key *)entry->key))
+        if (store_digest->contains(static_cast<const cache_key *>(entry->key)))
             ++sd_stats.add_coll_count;
 
-        cacheDigestAdd(store_digest,  (const cache_key *)entry->key);
+        store_digest->add(static_cast<const cache_key *>(entry->key));
 
         debugs(71, 6, "storeDigestAdd: added entry, key: " << entry->getMD5Text());
     } else {
         ++sd_stats.rej_count;
 
-        if (cacheDigestTest(store_digest,  (const cache_key *)entry->key))
+        if (store_digest->contains(static_cast<const cache_key *>(entry->key)))
             ++sd_stats.rej_coll_count;
     }
 }
@@ -297,11 +297,11 @@
 {
     assert(sd_state.rebuild_lock);
     assert(!sd_state.rewrite_lock);
-    sd_state.theSearch = Store::Root().search(NULL, NULL);
+    sd_state.theSearch = Store::Root().search();
     /* resize or clear */
 
     if (!storeDigestResize())
-        cacheDigestClear(store_digest);     /* not clean()! */
+        store_digest->clear();     /* not clean()! */
 
     memset(&sd_stats, 0, sizeof(sd_stats));
 
@@ -518,7 +518,7 @@
         return 0;
     } else {
         debugs(71, 2, "storeDigestResize: big change, resizing.");
-        cacheDigestChangeCap(store_digest, cap);
+        store_digest->updateCapacity(cap);
         return 1;
     }
 }
diff -u -r -N squid-4.0.2/src/store_dir.cc squid-4.0.3/src/store_dir.cc
--- squid-4.0.2/src/store_dir.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/store_dir.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,1350 +0,0 @@
-/*
- * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-/* DEBUG: section 47    Store Directory Routines */
-
-#include "squid.h"
-#include "globals.h"
-#include "mem_node.h"
-#include "MemObject.h"
-#include "MemStore.h"
-#include "profiler/Profiler.h"
-#include "SquidConfig.h"
-#include "SquidMath.h"
-#include "SquidTime.h"
-#include "Store.h"
-#include "store_key_md5.h"
-#include "StoreHashIndex.h"
-#include "swap_log_op.h"
-#include "SwapDir.h"
-#include "tools.h"
-#include "Transients.h"
-// for tvSubDsec() which should be in SquidTime.h
-#include "util.h"
-
-#include <cerrno>
-#include <climits>
-#if HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-static STDIRSELECT storeDirSelectSwapDirRoundRobin;
-static STDIRSELECT storeDirSelectSwapDirLeastLoad;
-
-/*
- * store_dirs_rebuilding is initialized to _1_ as a hack so that
- * storeDirWriteCleanLogs() doesn't try to do anything unless _all_
- * cache_dirs have been read.  For example, without this hack, Squid
- * will try to write clean log files if -kparse fails (becasue it
- * calls fatal()).
- */
-int StoreController::store_dirs_rebuilding = 1;
-
-StoreController::StoreController() : swapDir (new StoreHashIndex())
-    , memStore(NULL), transients(NULL)
-{}
-
-StoreController::~StoreController()
-{
-    delete memStore;
-    delete transients;
-}
-
-/*
- * This function pointer is set according to 'store_dir_select_algorithm'
- * in squid.conf.
- */
-STDIRSELECT *storeDirSelectSwapDir = storeDirSelectSwapDirLeastLoad;
-
-void
-StoreController::init()
-{
-    if (Config.memShared && IamWorkerProcess()) {
-        memStore = new MemStore;
-        memStore->init();
-    }
-
-    swapDir->init();
-
-    if (0 == strcasecmp(Config.store_dir_select_algorithm, "round-robin")) {
-        storeDirSelectSwapDir = storeDirSelectSwapDirRoundRobin;
-        debugs(47, DBG_IMPORTANT, "Using Round Robin store dir selection");
-    } else {
-        storeDirSelectSwapDir = storeDirSelectSwapDirLeastLoad;
-        debugs(47, DBG_IMPORTANT, "Using Least Load store dir selection");
-    }
-
-    if (UsingSmp() && IamWorkerProcess() && Config.onoff.collapsed_forwarding) {
-        transients = new Transients;
-        transients->init();
-    }
-}
-
-void
-StoreController::createOneStore(Store &aStore)
-{
-    /*
-     * On Windows, fork() is not available.
-     * The following is a workaround for create store directories sequentially
-     * when running on native Windows port.
-     */
-#if !_SQUID_WINDOWS_
-
-    if (fork())
-        return;
-
-#endif
-
-    aStore.create();
-
-#if !_SQUID_WINDOWS_
-
-    exit(0);
-
-#endif
-}
-
-void
-StoreController::create()
-{
-    swapDir->create();
-
-#if !_SQUID_WINDOWS_
-
-    pid_t pid;
-
-    do {
-        int status;
-#if _SQUID_NEXT_
-
-        pid = wait3(&status, WNOHANG, NULL);
-#else
-
-        pid = waitpid(-1, &status, 0);
-#endif
-
-    } while (pid > 0 || (pid < 0 && errno == EINTR));
-
-#endif
-}
-
-/**
- * Determine whether the given directory can handle this object
- * size
- *
- * Note: if the object size is -1, then the only swapdirs that
- * will return true here are ones that have min and max unset,
- * ie any-sized-object swapdirs. This is a good thing.
- */
-bool
-SwapDir::objectSizeIsAcceptable(int64_t objsize) const
-{
-    // If the swapdir has no range limits, then it definitely can
-    if (min_objsize <= 0 && max_objsize == -1)
-        return true;
-
-    /*
-     * If the object size is -1 and the storedir has limits we
-     * can't store it there.
-     */
-    if (objsize == -1)
-        return false;
-
-    // Else, make sure that the object size will fit.
-    if (max_objsize == -1 && min_objsize <= objsize)
-        return true;
-    else
-        return min_objsize <= objsize && max_objsize > objsize;
-}
-
-/*
- * This new selection scheme simply does round-robin on all SwapDirs.
- * A SwapDir is skipped if it is over the max_size (100%) limit, or
- * overloaded.
- */
-static int
-storeDirSelectSwapDirRoundRobin(const StoreEntry * e)
-{
-    // 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;
-
-    // Increment the first candidate once per selection (not once per
-    // iteration) to reduce bias when some disk(s) attract more entries.
-    static int firstCandidate = 0;
-    if (++firstCandidate >= Config.cacheSwap.n_configured)
-        firstCandidate = 0;
-
-    for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
-        const int dirn = (firstCandidate + i) % Config.cacheSwap.n_configured;
-        const SwapDir *sd = dynamic_cast<SwapDir*>(INDEXSD(dirn));
-
-        int load = 0;
-        if (!sd->canStore(*e, objsize, load))
-            continue;
-
-        if (load < 0 || load > 1000) {
-            continue;
-        }
-
-        return dirn;
-    }
-
-    return -1;
-}
-
-/*
- * Spread load across all of the store directories
- *
- * Note: We should modify this later on to prefer sticking objects
- * in the *tightest fit* swapdir to conserve space, along with the
- * actual swapdir usage. But for now, this hack will do while
- * testing, so you should order your swapdirs in the config file
- * from smallest max-size= to largest max-size=.
- *
- * We also have to choose nleast == nconf since we need to consider
- * ALL swapdirs, regardless of state. Again, this is a hack while
- * we sort out the real usefulness of this algorithm.
- */
-static int
-storeDirSelectSwapDirLeastLoad(const StoreEntry * e)
-{
-    int64_t most_free = 0;
-    ssize_t least_objsize = -1;
-    int least_load = INT_MAX;
-    int load;
-    int dirn = -1;
-    int i;
-    RefCount<SwapDir> SD;
-
-    // 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) {
-        SD = dynamic_cast<SwapDir *>(INDEXSD(i));
-        SD->flags.selected = false;
-
-        if (!SD->canStore(*e, objsize, load))
-            continue;
-
-        if (load < 0 || load > 1000)
-            continue;
-
-        if (load > least_load)
-            continue;
-
-        const int64_t cur_free = SD->maxSize() - SD->currentSize();
-
-        /* If the load is equal, then look in more details */
-        if (load == least_load) {
-            /* closest max-size fit */
-
-            if (least_objsize != -1)
-                if (SD->maxObjectSize() > least_objsize)
-                    continue;
-
-            /* most free */
-            if (cur_free < most_free)
-                continue;
-        }
-
-        least_load = load;
-        least_objsize = SD->maxObjectSize();
-        most_free = cur_free;
-        dirn = i;
-    }
-
-    if (dirn >= 0)
-        dynamic_cast<SwapDir *>(INDEXSD(dirn))->flags.selected = true;
-
-    return dirn;
-}
-
-/*
- * An entry written to the swap log MUST have the following
- * properties.
- *   1.  It MUST be a public key.  It does no good to log
- *       a public ADD, change the key, then log a private
- *       DEL.  So we need to log a DEL before we change a
- *       key from public to private.
- *   2.  It MUST have a valid (> -1) swap_filen.
- */
-void
-storeDirSwapLog(const StoreEntry * e, int op)
-{
-    assert (e);
-    assert(!EBIT_TEST(e->flags, KEY_PRIVATE));
-    assert(e->swap_filen >= 0);
-    /*
-     * icons and such; don't write them to the swap log
-     */
-
-    if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
-        return;
-
-    assert(op > SWAP_LOG_NOP && op < SWAP_LOG_MAX);
-
-    debugs(20, 3, "storeDirSwapLog: " <<
-           swap_log_op_str[op] << " " <<
-           e->getMD5Text() << " " <<
-           e->swap_dirn << " " <<
-           std::hex << std::uppercase << std::setfill('0') << std::setw(8) << e->swap_filen);
-
-    dynamic_cast<SwapDir *>(INDEXSD(e->swap_dirn))->logEntry(*e, op);
-}
-
-void
-StoreController::getStats(StoreInfoStats &stats) const
-{
-    if (memStore)
-        memStore->getStats(stats);
-    else {
-        // move this code to a non-shared memory cache class when we have it
-        stats.mem.shared = false;
-        stats.mem.capacity = Config.memMaxSize;
-        stats.mem.size = mem_node::StoreMemSize();
-        stats.mem.count = hot_obj_count;
-    }
-
-    swapDir->getStats(stats);
-
-    // low-level info not specific to memory or disk cache
-    stats.store_entry_count = StoreEntry::inUseCount();
-    stats.mem_object_count = MemObject::inUseCount();
-}
-
-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() >> 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);
-}
-
-/* if needed, this could be taught to cache the result */
-uint64_t
-StoreController::maxSize() const
-{
-    /* TODO: include memory cache ? */
-    return swapDir->maxSize();
-}
-
-uint64_t
-StoreController::minSize() const
-{
-    /* TODO: include memory cache ? */
-    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 (currentSize() >= maxSize())
-        return;
-
-    max_size = currentSize();
-
-    debugs(20, DBG_IMPORTANT, "WARNING: Shrinking cache_dir #" << index << " to " << currentSize() / 1024.0 << " KB");
-}
-
-void
-storeDirOpenSwapLogs(void)
-{
-    for (int dirn = 0; dirn < Config.cacheSwap.n_configured; ++dirn)
-        dynamic_cast<SwapDir *>(INDEXSD(dirn))->openLog();
-}
-
-void
-storeDirCloseSwapLogs(void)
-{
-    for (int dirn = 0; dirn < Config.cacheSwap.n_configured; ++dirn)
-        dynamic_cast<SwapDir *>(INDEXSD(dirn))->closeLog();
-}
-
-/*
- *  storeDirWriteCleanLogs
- *
- *  Writes a "clean" swap log file from in-memory metadata.
- *  This is a rewrite of the original function to troll each
- *  StoreDir and write the logs, and flush at the end of
- *  the run. Thanks goes to Eric Stern, since this solution
- *  came out of his COSS code.
- */
-int
-storeDirWriteCleanLogs(int reopen)
-{
-    const StoreEntry *e = NULL;
-    int n = 0;
-
-    struct timeval start;
-    double dt;
-    RefCount<SwapDir> sd;
-    int dirn;
-    int notdone = 1;
-
-    if (StoreController::store_dirs_rebuilding) {
-        debugs(20, DBG_IMPORTANT, "Not currently OK to rewrite swap log.");
-        debugs(20, DBG_IMPORTANT, "storeDirWriteCleanLogs: Operation aborted.");
-        return 0;
-    }
-
-    debugs(20, DBG_IMPORTANT, "storeDirWriteCleanLogs: Starting...");
-    getCurrentTime();
-    start = current_time;
-
-    for (dirn = 0; dirn < Config.cacheSwap.n_configured; ++dirn) {
-        sd = dynamic_cast<SwapDir *>(INDEXSD(dirn));
-
-        if (sd->writeCleanStart() < 0) {
-            debugs(20, DBG_IMPORTANT, "log.clean.start() failed for dir #" << sd->index);
-            continue;
-        }
-    }
-
-    /*
-     * This may look inefficient as CPU wise it is more efficient to do this
-     * sequentially, but I/O wise the parallellism helps as it allows more
-     * hdd spindles to be active.
-     */
-    while (notdone) {
-        notdone = 0;
-
-        for (dirn = 0; dirn < Config.cacheSwap.n_configured; ++dirn) {
-            sd = dynamic_cast<SwapDir *>(INDEXSD(dirn));
-
-            if (NULL == sd->cleanLog)
-                continue;
-
-            e = sd->cleanLog->nextEntry();
-
-            if (!e)
-                continue;
-
-            notdone = 1;
-
-            if (!sd->canLog(*e))
-                continue;
-
-            sd->cleanLog->write(*e);
-
-            if ((++n & 0xFFFF) == 0) {
-                getCurrentTime();
-                debugs(20, DBG_IMPORTANT, "  " << std::setw(7) << n  <<
-                       " entries written so far.");
-            }
-        }
-    }
-
-    /* Flush */
-    for (dirn = 0; dirn < Config.cacheSwap.n_configured; ++dirn)
-        dynamic_cast<SwapDir *>(INDEXSD(dirn))->writeCleanDone();
-
-    if (reopen)
-        storeDirOpenSwapLogs();
-
-    getCurrentTime();
-
-    dt = tvSubDsec(start, current_time);
-
-    debugs(20, DBG_IMPORTANT, "  Finished.  Wrote " << n << " entries.");
-    debugs(20, DBG_IMPORTANT, "  Took "<< std::setw(3)<< std::setprecision(2) << dt <<
-           " seconds ("<< std::setw(6) << ((double) n / (dt > 0.0 ? dt : 1.0)) << " entries/sec).");
-
-    return n;
-}
-
-StoreSearch *
-StoreController::search(String const url, HttpRequest *request)
-{
-    /* cheat, for now you can't search the memory hot cache */
-    return swapDir->search(url, request);
-}
-
-StorePointer
-StoreHashIndex::store(int const x) const
-{
-    return INDEXSD(x);
-}
-
-SwapDir &
-StoreHashIndex::dir(const int i) const
-{
-    SwapDir *sd = dynamic_cast<SwapDir*>(INDEXSD(i));
-    assert(sd);
-    return *sd;
-}
-
-void
-StoreController::sync(void)
-{
-    if (memStore)
-        memStore->sync();
-    swapDir->sync();
-}
-
-/*
- * handle callbacks all avaliable fs'es
- */
-int
-StoreController::callback()
-{
-    /* This will likely double count. Thats ok. */
-    PROF_start(storeDirCallback);
-
-    /* mem cache callbacks ? */
-    int result = swapDir->callback();
-
-    PROF_stop(storeDirCallback);
-
-    return result;
-}
-
-int
-storeDirGetBlkSize(const char *path, int *blksize)
-{
-    struct statvfs sfs;
-
-    if (xstatvfs(path, &sfs)) {
-        debugs(50, DBG_IMPORTANT, "" << path << ": " << xstrerror());
-        *blksize = 2048;
-        return 1;
-    }
-
-    *blksize = (int) sfs.f_frsize;
-
-    // Sanity check; make sure we have a meaningful value.
-    if (*blksize < 512)
-        *blksize = 2048;
-
-    return 0;
-}
-
-#define fsbtoblk(num, fsbs, bs) \
-    (((fsbs) != 0 && (fsbs) < (bs)) ? \
-            (num) / ((bs) / (fsbs)) : (num) * ((fsbs) / (bs)))
-int
-storeDirGetUFSStats(const char *path, int *totl_kb, int *free_kb, int *totl_in, int *free_in)
-{
-    struct statvfs sfs;
-
-    if (xstatvfs(path, &sfs)) {
-        debugs(50, DBG_IMPORTANT, "" << path << ": " << xstrerror());
-        return 1;
-    }
-
-    *totl_kb = (int) fsbtoblk(sfs.f_blocks, sfs.f_frsize, 1024);
-    *free_kb = (int) fsbtoblk(sfs.f_bfree, sfs.f_frsize, 1024);
-    *totl_in = (int) sfs.f_files;
-    *free_in = (int) sfs.f_ffree;
-    return 0;
-}
-
-void
-allocate_new_swapdir(SquidConfig::_cacheSwap * swap)
-{
-    if (swap->swapDirs == NULL) {
-        swap->n_allocated = 4;
-        swap->swapDirs = static_cast<SwapDir::Pointer *>(xcalloc(swap->n_allocated, sizeof(SwapDir::Pointer)));
-    }
-
-    if (swap->n_allocated == swap->n_configured) {
-        swap->n_allocated <<= 1;
-        SwapDir::Pointer *const tmp = static_cast<SwapDir::Pointer *>(xcalloc(swap->n_allocated, sizeof(SwapDir::Pointer)));
-        memcpy(tmp, swap->swapDirs, swap->n_configured * sizeof(SwapDir *));
-        xfree(swap->swapDirs);
-        swap->swapDirs = tmp;
-    }
-}
-
-void
-free_cachedir(SquidConfig::_cacheSwap * swap)
-{
-    int i;
-    /* DON'T FREE THESE FOR RECONFIGURE */
-
-    if (reconfiguring)
-        return;
-
-    for (i = 0; i < swap->n_configured; ++i) {
-        /* TODO XXX this lets the swapdir free resources asynchronously
-        * swap->swapDirs[i]->deactivate();
-        * but there may be such a means already.
-        * RBC 20041225
-        */
-        swap->swapDirs[i] = NULL;
-    }
-
-    safe_free(swap->swapDirs);
-    swap->swapDirs = NULL;
-    swap->n_allocated = 0;
-    swap->n_configured = 0;
-}
-
-/* this should be a virtual method on StoreEntry,
- * i.e. e->referenced()
- * so that the entry can notify the creating Store
- */
-void
-StoreController::reference(StoreEntry &e)
-{
-    // special entries do not belong to any specific Store, but are IN_MEMORY
-    if (EBIT_TEST(e.flags, ENTRY_SPECIAL))
-        return;
-
-    /* Notify the fs that we're referencing this object again */
-
-    if (e.swap_dirn > -1)
-        swapDir->reference(e);
-
-    // Notify the memory cache that we're referencing this object again
-    if (memStore && e.mem_status == IN_MEMORY)
-        memStore->reference(e);
-
-    // 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);
-    }
-}
-
-bool
-StoreController::dereference(StoreEntry &e, bool wantsLocalMemory)
-{
-    // special entries do not belong to any specific Store, but are IN_MEMORY
-    if (EBIT_TEST(e.flags, ENTRY_SPECIAL))
-        return true;
-
-    bool keepInStoreTable = false; // keep only if somebody needs it there
-
-    /* Notify the fs that we're not referencing this object any more */
-
-    if (e.swap_filen > -1)
-        keepInStoreTable = swapDir->dereference(e, wantsLocalMemory) || keepInStoreTable;
-
-    // Notify the memory cache that we're not referencing this object any more
-    if (memStore && e.mem_status == IN_MEMORY)
-        keepInStoreTable = memStore->dereference(e, wantsLocalMemory) || 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);
-        // non-shared memory cache relies on store_table
-        if (!memStore)
-            keepInStoreTable = wantsLocalMemory || keepInStoreTable;
-    }
-
-    return keepInStoreTable;
-}
-
-StoreEntry *
-StoreController::get(const cache_key *key)
-{
-    if (StoreEntry *e = find(key)) {
-        // this is not very precise: some get()s are not initiated by clients
-        e->touch();
-        return e;
-    }
-    return NULL;
-}
-
-/// Internal method to implements the guts of the Store::get() API:
-/// returns an in-transit or cached object with a given key, if any.
-StoreEntry *
-StoreController::find(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;
-    }
-
-    // Must search transients before caches because we must sync those we find.
-    if (transients) {
-        if (StoreEntry *e = transients->get(key)) {
-            debugs(20, 3, "got shared in-transit entry: " << *e);
-            bool inSync = false;
-            const bool found = anchorCollapsed(*e, inSync);
-            if (!found || inSync)
-                return e;
-            assert(!e->locked()); // ensure release will destroyStoreEntry()
-            e->release(); // do not let others into the same trap
-            return NULL;
-        }
-    }
-
-    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<SwapDir*>(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;
-            }
-        }
-    }
-
-    debugs(20, 4, HERE << "none of " << Config.cacheSwap.n_configured <<
-           " cache_dirs have " << storeKeyText(key));
-    return NULL;
-}
-
-void
-StoreController::get(String const, STOREGETCLIENT, void *)
-{
-    fatal("not implemented");
-}
-
-/// updates the collapsed entry with the corresponding on-disk entry, if any
-/// In other words, the SwapDir::anchorCollapsed() API applied to all disks.
-bool
-StoreController::anchorCollapsedOnDisk(StoreEntry &collapsed, bool &inSync)
-{
-    // TODO: move this loop to StoreHashIndex, just like the one in get().
-    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<SwapDir*>(INDEXSD(idx));
-            if (!sd->active())
-                continue;
-
-            if (sd->anchorCollapsed(collapsed, inSync)) {
-                debugs(20, 3, "cache_dir " << idx << " anchors " << collapsed);
-                return true;
-            }
-        }
-    }
-
-    debugs(20, 4, "none of " << Config.cacheSwap.n_configured <<
-           " cache_dirs have " << collapsed);
-    return false;
-}
-
-void StoreController::markForUnlink(StoreEntry &e)
-{
-    if (transients && e.mem_obj && e.mem_obj->xitTable.index >= 0)
-        transients->markForUnlink(e);
-    if (memStore && e.mem_obj && e.mem_obj->memCache.index >= 0)
-        memStore->markForUnlink(e);
-    if (e.swap_filen >= 0)
-        e.store()->markForUnlink(e);
-}
-
-// move this into [non-shared] memory cache class when we have one
-/// whether e should be kept in local RAM for possible future caching
-bool
-StoreController::keepForLocalMemoryCache(StoreEntry &e) const
-{
-    if (!e.memoryCachable())
-        return false;
-
-    // does the current and expected size obey memory caching limits?
-    assert(e.mem_obj);
-    const int64_t loadedSize = e.mem_obj->endOffset();
-    const int64_t expectedSize = e.mem_obj->expectedReplySize(); // may be < 0
-    const int64_t ramSize = max(loadedSize, expectedSize);
-    const int64_t ramLimit = min(
-                                 static_cast<int64_t>(Config.memMaxSize),
-                                 static_cast<int64_t>(Config.Store.maxInMemObjSize));
-    return ramSize <= ramLimit;
-}
-
-void
-StoreController::memoryOut(StoreEntry &e, const bool preserveSwappable)
-{
-    bool keepInLocalMemory = false;
-    if (memStore)
-        memStore->write(e); // leave keepInLocalMemory false
-    else
-        keepInLocalMemory = keepForLocalMemoryCache(e);
-
-    debugs(20, 7, HERE << "keepInLocalMemory: " << keepInLocalMemory);
-
-    if (!keepInLocalMemory)
-        e.trimMemory(preserveSwappable);
-}
-
-void
-StoreController::memoryUnlink(StoreEntry &e)
-{
-    if (memStore)
-        memStore->unlink(e);
-    else // TODO: move into [non-shared] memory cache class when we have one
-        e.destroyMemObject();
-}
-
-void
-StoreController::memoryDisconnect(StoreEntry &e)
-{
-    if (memStore)
-        memStore->disconnect(e);
-    // else nothing to do for non-shared memory cache
-}
-
-void
-StoreController::transientsAbandon(StoreEntry &e)
-{
-    if (transients) {
-        assert(e.mem_obj);
-        if (e.mem_obj->xitTable.index >= 0)
-            transients->abandon(e);
-    }
-}
-
-void
-StoreController::transientsCompleteWriting(StoreEntry &e)
-{
-    if (transients) {
-        assert(e.mem_obj);
-        if (e.mem_obj->xitTable.index >= 0)
-            transients->completeWriting(e);
-    }
-}
-
-int
-StoreController::transientReaders(const StoreEntry &e) const
-{
-    return (transients && e.mem_obj && e.mem_obj->xitTable.index >= 0) ?
-           transients->readers(e) : 0;
-}
-
-void
-StoreController::transientsDisconnect(MemObject &mem_obj)
-{
-    if (transients)
-        transients->disconnect(mem_obj);
-}
-
-void
-StoreController::handleIdleEntry(StoreEntry &e)
-{
-    bool keepInLocalMemory = false;
-
-    if (EBIT_TEST(e.flags, ENTRY_SPECIAL)) {
-        // Icons (and cache digests?) should stay in store_table until we
-        // have a dedicated storage for them (that would not purge them).
-        // They are not managed [well] by any specific Store handled below.
-        keepInLocalMemory = true;
-    } else if (memStore) {
-        // leave keepInLocalMemory false; memStore maintains its own cache
-    } else {
-        keepInLocalMemory = keepForLocalMemoryCache(e) && // in good shape and
-                            // the local memory cache is not overflowing
-                            (mem_node::InUseCount() <= store_pages_max);
-    }
-
-    // An idle, unlocked entry that only belongs to a SwapDir which controls
-    // its own index, should not stay in the global store_table.
-    if (!dereference(e, keepInLocalMemory)) {
-        debugs(20, 5, HERE << "destroying unlocked entry: " << &e << ' ' << e);
-        destroyStoreEntry(static_cast<hash_link*>(&e));
-        return;
-    }
-
-    debugs(20, 5, HERE << "keepInLocalMemory: " << keepInLocalMemory);
-
-    // 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
-    }
-}
-
-void
-StoreController::allowCollapsing(StoreEntry *e, const RequestFlags &reqFlags,
-                                 const HttpRequestMethod &reqMethod)
-{
-    e->makePublic(); // this is needed for both local and SMP collapsing
-    if (transients)
-        transients->startWriting(e, reqFlags, reqMethod);
-    debugs(20, 3, "may " << (transients && e->mem_obj->xitTable.index >= 0 ?
-                             "SMP-" : "locally-") << "collapse " << *e);
-}
-
-void
-StoreController::syncCollapsed(const sfileno xitIndex)
-{
-    assert(transients);
-
-    StoreEntry *collapsed = transients->findCollapsed(xitIndex);
-    if (!collapsed) { // the entry is no longer locally active, ignore update
-        debugs(20, 7, "not SMP-syncing not-transient " << xitIndex);
-        return;
-    }
-    assert(collapsed->mem_obj);
-    assert(collapsed->mem_obj->smpCollapsed);
-
-    debugs(20, 7, "syncing " << *collapsed);
-
-    bool abandoned = transients->abandoned(*collapsed);
-    bool found = false;
-    bool inSync = false;
-    if (memStore && collapsed->mem_obj->memCache.io == MemObject::ioDone) {
-        found = true;
-        inSync = true;
-        debugs(20, 7, "fully mem-loaded " << *collapsed);
-    } else if (memStore && collapsed->mem_obj->memCache.index >= 0) {
-        found = true;
-        inSync = memStore->updateCollapsed(*collapsed);
-    } else if (collapsed->swap_filen >= 0) {
-        found = true;
-        inSync = collapsed->store()->updateCollapsed(*collapsed);
-    } else {
-        found = anchorCollapsed(*collapsed, inSync);
-    }
-
-    if (abandoned && collapsed->store_status == STORE_PENDING) {
-        debugs(20, 3, "aborting abandoned but STORE_PENDING " << *collapsed);
-        collapsed->abort();
-        return;
-    }
-
-    if (inSync) {
-        debugs(20, 5, "synced " << *collapsed);
-        collapsed->invokeHandlers();
-    } else if (found) { // unrecoverable problem syncing this entry
-        debugs(20, 3, "aborting unsyncable " << *collapsed);
-        collapsed->abort();
-    } else { // the entry is still not in one of the caches
-        debugs(20, 7, "waiting " << *collapsed);
-    }
-}
-
-/// Called for in-transit entries that are not yet anchored to a cache.
-/// For cached entries, return true after synchronizing them with their cache
-/// (making inSync true on success). For not-yet-cached entries, return false.
-bool
-StoreController::anchorCollapsed(StoreEntry &collapsed, bool &inSync)
-{
-    // this method is designed to work with collapsed transients only
-    assert(collapsed.mem_obj);
-    assert(collapsed.mem_obj->xitTable.index >= 0);
-    assert(collapsed.mem_obj->smpCollapsed);
-
-    debugs(20, 7, "anchoring " << collapsed);
-
-    bool found = false;
-    if (memStore)
-        found = memStore->anchorCollapsed(collapsed, inSync);
-    if (!found && Config.cacheSwap.n_configured)
-        found = anchorCollapsedOnDisk(collapsed, inSync);
-
-    if (found) {
-        if (inSync)
-            debugs(20, 7, "anchored " << collapsed);
-        else
-            debugs(20, 5, "failed to anchor " << collapsed);
-    } else {
-        debugs(20, 7, "skipping not yet cached " << collapsed);
-    }
-
-    return found;
-}
-
-StoreHashIndex::StoreHashIndex()
-{
-    if (store_table)
-        abort();
-    assert (store_table == NULL);
-}
-
-StoreHashIndex::~StoreHashIndex()
-{
-    if (store_table) {
-        hashFreeItems(store_table, destroyStoreEntry);
-        hashFreeMemory(store_table);
-        store_table = NULL;
-    }
-}
-
-int
-StoreHashIndex::callback()
-{
-    int result = 0;
-    int j;
-    static int ndir = 0;
-
-    do {
-        j = 0;
-
-        for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
-            if (ndir >= Config.cacheSwap.n_configured)
-                ndir = ndir % Config.cacheSwap.n_configured;
-
-            int temp_result = store(ndir)->callback();
-
-            ++ndir;
-
-            j += temp_result;
-
-            result += temp_result;
-
-            if (j > 100)
-                fatal ("too much io\n");
-        }
-    } while (j > 0);
-
-    ++ndir;
-
-    return result;
-}
-
-void
-StoreHashIndex::create()
-{
-    if (Config.cacheSwap.n_configured == 0) {
-        debugs(0, DBG_PARSE_NOTE(DBG_CRITICAL), "No cache_dir stores are configured.");
-    }
-
-    for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
-        if (dir(i).active())
-            store(i)->create();
-    }
-}
-
-/* Lookup an object in the cache.
- * return just a reference to object, don't start swapping in yet. */
-StoreEntry *
-StoreHashIndex::get(const cache_key *key)
-{
-    PROF_start(storeGet);
-    debugs(20, 3, "storeGet: looking up " << storeKeyText(key));
-    StoreEntry *p = static_cast<StoreEntry *>(hash_lookup(store_table, key));
-    PROF_stop(storeGet);
-    return p;
-}
-
-void
-StoreHashIndex::get(String const, STOREGETCLIENT, void *)
-{
-    fatal("not implemented");
-}
-
-void
-StoreHashIndex::init()
-{
-    if (Config.Store.objectsPerBucket <= 0)
-        fatal("'store_objects_per_bucket' should be larger than 0.");
-
-    if (Config.Store.avgObjectSize <= 0)
-        fatal("'store_avg_object_size' should be larger than 0.");
-
-    /* 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) / Config.Store.avgObjectSize;
-    debugs(20, DBG_IMPORTANT, "Swap maxSize " << (Store::Root().maxSize() >> 10) <<
-           " + " << ( Config.memMaxSize >> 10) << " KB, estimated " << buckets << " objects");
-    buckets /= Config.Store.objectsPerBucket;
-    debugs(20, DBG_IMPORTANT, "Target number of buckets: " << buckets);
-    /* ideally the full scan period should be configurable, for the
-     * moment it remains at approximately 24 hours.  */
-    store_hash_buckets = storeKeyHashBuckets(buckets);
-    debugs(20, DBG_IMPORTANT, "Using " << store_hash_buckets << " Store buckets");
-    debugs(20, DBG_IMPORTANT, "Max Mem  size: " << ( Config.memMaxSize >> 10) << " KB" <<
-           (Config.memShared ? " [shared]" : ""));
-    debugs(20, DBG_IMPORTANT, "Max Swap size: " << (Store::Root().maxSize() >> 10) << " KB");
-
-    store_table = hash_create(storeKeyHashCmp,
-                              store_hash_buckets, storeKeyHashHash);
-
-    for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
-        /* this starts a search of the store dirs, loading their
-         * index. under the new Store api this should be
-         * driven by the StoreHashIndex, not by each store.
-        *
-        * That is, the HashIndex should perform a search of each dir it is
-        * indexing to do the hash insertions. The search is then able to
-        * decide 'from-memory', or 'from-clean-log' or 'from-dirty-log' or
-        * 'from-no-log'.
-        *
-         * Step 1: make the store rebuilds use a search internally
-        * Step 2: change the search logic to use the four modes described
-        *         above
-        * Step 3: have the hash index walk the searches itself.
-         */
-        if (dir(i).active())
-            store(i)->init();
-    }
-}
-
-uint64_t
-StoreHashIndex::maxSize() const
-{
-    uint64_t result = 0;
-
-    for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
-        if (dir(i).doReportStat())
-            result += store(i)->maxSize();
-    }
-
-    return result;
-}
-
-uint64_t
-StoreHashIndex::minSize() const
-{
-    uint64_t result = 0;
-
-    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;
-}
-
-void
-StoreHashIndex::getStats(StoreInfoStats &stats) const
-{
-    // accumulate per-disk cache stats
-    for (int i = 0; i < Config.cacheSwap.n_configured; ++i) {
-        StoreInfoStats dirStats;
-        store(i)->getStats(dirStats);
-        stats += dirStats;
-    }
-
-    // common to all disks
-    stats.swap.open_disk_fd = store_open_disk_fd;
-
-    // memory cache stats are collected in StoreController::getStats(), for now
-}
-
-void
-StoreHashIndex::stat(StoreEntry & output) const
-{
-    int i;
-
-    /* Now go through each store, calling its stat routine */
-
-    for (i = 0; i < Config.cacheSwap.n_configured; ++i) {
-        storeAppendPrintf(&output, "\n");
-        store(i)->stat(output);
-    }
-}
-
-void
-StoreHashIndex::reference(StoreEntry &e)
-{
-    e.store()->reference(e);
-}
-
-bool
-StoreHashIndex::dereference(StoreEntry &e, bool wantsLocalMemory)
-{
-    return e.store()->dereference(e, wantsLocalMemory);
-}
-
-void
-StoreHashIndex::maintain()
-{
-    int i;
-    /* walk each fs */
-
-    for (i = 0; i < Config.cacheSwap.n_configured; ++i) {
-        /* XXX FixMe: This should be done "in parallell" on the different
-         * cache_dirs, not one at a time.
-         */
-        /* call the maintain function .. */
-        store(i)->maintain();
-    }
-}
-
-void
-StoreHashIndex::sync()
-{
-    for (int i = 0; i < Config.cacheSwap.n_configured; ++i)
-        store(i)->sync();
-}
-
-StoreSearch *
-StoreHashIndex::search(String const url, HttpRequest *)
-{
-    if (url.size())
-        fatal ("Cannot search by url yet\n");
-
-    return new StoreSearchHashIndex (this);
-}
-
-CBDATA_CLASS_INIT(StoreSearchHashIndex);
-
-StoreSearchHashIndex::StoreSearchHashIndex(RefCount<StoreHashIndex> aSwapDir) :
-    sd(aSwapDir),
-    callback(NULL),
-    cbdata(NULL),
-    _done(false),
-    bucket(0)
-{}
-
-/* do not link
-StoreSearchHashIndex::StoreSearchHashIndex(StoreSearchHashIndex const &);
-*/
-
-StoreSearchHashIndex::~StoreSearchHashIndex()
-{}
-
-void
-StoreSearchHashIndex::next(void (aCallback)(void *), void *aCallbackData)
-{
-    next();
-    aCallback (aCallbackData);
-}
-
-bool
-StoreSearchHashIndex::next()
-{
-    if (!entries.empty())
-        entries.pop_back();
-
-    while (!isDone() && !entries.size())
-        copyBucket();
-
-    return currentItem() != NULL;
-}
-
-bool
-StoreSearchHashIndex::error() const
-{
-    return false;
-}
-
-bool
-StoreSearchHashIndex::isDone() const
-{
-    return bucket >= store_hash_buckets || _done;
-}
-
-StoreEntry *
-StoreSearchHashIndex::currentItem()
-{
-    if (!entries.size())
-        return NULL;
-
-    return entries.back();
-}
-
-void
-StoreSearchHashIndex::copyBucket()
-{
-    /* probably need to lock the store entries...
-     * we copy them all to prevent races on the links. */
-    debugs(47, 3, "StoreSearchHashIndex::copyBucket #" << bucket);
-    assert (!entries.size());
-    hash_link *link_ptr = NULL;
-    hash_link *link_next = NULL;
-    link_next = hash_get_bucket(store_table, bucket);
-
-    while (NULL != (link_ptr = link_next)) {
-        link_next = link_ptr->next;
-        StoreEntry *e = (StoreEntry *) link_ptr;
-
-        entries.push_back(e);
-    }
-
-    ++bucket;
-    debugs(47,3, "got entries: " << entries.size());
-}
-
diff -u -r -N squid-4.0.2/src/StoreFileSystem.h squid-4.0.3/src/StoreFileSystem.h
--- squid-4.0.2/src/StoreFileSystem.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/StoreFileSystem.h	2015-11-28 07:30:57.000000000 -0800
@@ -9,6 +9,7 @@
 #ifndef SQUID_STOREFILESYSTEM_H
 #define SQUID_STOREFILESYSTEM_H
 
+#include "store/forward.h"
 #include <vector>
 
 /* ****** DOCUMENTATION ***** */
@@ -79,8 +80,6 @@
  *    given StoreEntry. A maxobjsize of -1 means 'any size'.
  */
 
-class SwapDir;
-
 /**
  \ingroup FileSystems
  *
diff -u -r -N squid-4.0.2/src/Store.h squid-4.0.3/src/Store.h
--- squid-4.0.2/src/Store.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/Store.h	2015-11-28 07:30:57.000000000 -0800
@@ -20,6 +20,8 @@
 #include "MemObject.h"
 #include "Range.h"
 #include "RemovalPolicy.h"
+#include "store/Controller.h"
+#include "store/forward.h"
 #include "store_key_md5.h"
 #include "StoreIOBuffer.h"
 #include "StoreStats.h"
@@ -33,15 +35,9 @@
 class AsyncCall;
 class HttpRequest;
 class RequestFlags;
-class StoreClient;
-class StoreSearch;
-class SwapDir;
 
 extern StoreIoStats store_io_stats;
 
-/// maximum number of entries per cache_dir
-enum { SwapFilenMax = 0xFFFFFF }; // keep in sync with StoreEntry::swap_filen
-
 class StoreEntry : public hash_link, public Packable
 {
     MEMPROXY_CLASS(StoreEntry);
@@ -87,7 +83,6 @@
     void swapOutDecision(const MemObject::SwapOut::Decision &decision);
 
     void abort();
-    void unlink();
     void makePublic();
     void makePrivate();
     void setPublicKey();
@@ -141,8 +136,8 @@
     /// whether this entry has an ETag; if yes, puts ETag value into parameter
     bool hasEtag(ETag &etag) const;
 
-    /** What store does this entry belong too ? */
-    virtual RefCount<SwapDir> store() const;
+    /// the disk this entry is [being] cached on; asserts for entries w/o a disk
+    Store::Disk &disk() const;
 
     MemObject *mem_obj;
     RemovalPolicyNode repl;
@@ -272,165 +267,12 @@
 /// \ingroup StoreAPI
 typedef void (*STOREGETCLIENT) (StoreEntry *, void *cbdata);
 
-/**
- \ingroup StoreAPI
- * Abstract base class that will replace the whole store and swapdir interface.
- */
-class Store : public RefCountable
-{
-
-public:
-    /** The root store */
-    static Store &Root() {
-        if (CurrentRoot == NULL)
-            fatal("No Store Root has been set");
-        return *CurrentRoot;
-    }
-    static void Root(Store *);
-    static void Root(RefCount<Store>);
-    static void Stats(StoreEntry * output);
-    static void Maintain(void *unused);
-
-    virtual ~Store() {}
-
-    /** Handle pending callbacks - called by the event loop. */
-    virtual int callback() = 0;
-
-    /** create the resources needed for this store to operate */
-    virtual void create();
-
-    /**
-     * Notify this store that its disk is full.
-     \todo XXX move into a protected api call between store files and their stores, rather than a top level api call
-     */
-    virtual void diskFull();
-
-    /** Retrieve a store entry from the store */
-    virtual StoreEntry * get(const cache_key *) = 0;
-
-    /** \todo imeplement the async version */
-    virtual void get(String const key , STOREGETCLIENT callback, void *cbdata) = 0;
-
-    /* prepare the store for use. The store need not be usable immediately,
-     * it should respond to readable() and writable() with true as soon
-     * as it can provide those services
-     */
-    virtual void init() = 0;
-
-    /**
-     * The maximum size the store will support in normal use. Inaccuracy is permitted,
-     * but may throw estimates for memory etc out of whack.
-     */
-    virtual uint64_t maxSize() const = 0;
-
-    /** 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;
-
-    /// collect cache storage-related statistics
-    virtual void getStats(StoreInfoStats &stats) const = 0;
-
-    /**
-     * Output stats to the provided store entry.
-     \todo make these calls asynchronous
-     */
-    virtual void stat(StoreEntry &) const = 0;
-
-    /** Sync the store prior to shutdown */
-    virtual void sync();
-
-    /** remove a Store entry from the store */
-    virtual void unlink (StoreEntry &);
-
-    /* search in the store */
-    virtual StoreSearch *search(String const url, HttpRequest *) = 0;
-
-    /* pulled up from SwapDir for migration.... probably do not belong here */
-    virtual void reference(StoreEntry &) = 0;   /* Reference this object */
-
-    /// Undo reference(), returning false iff idle e should be destroyed
-    virtual bool dereference(StoreEntry &, bool wantsLocalMemory) = 0;
-
-    virtual void maintain() = 0; /* perform regular maintenance should be private and self registered ... */
-
-    // XXX: This method belongs to Store::Root/StoreController, but it is here
-    // to avoid casting Root() to StoreController until Root() API is fixed.
-    /// informs stores that this entry will be eventually unlinked
-    virtual void markForUnlink(StoreEntry &) {}
-
-    // 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 &) {}
-
-    // XXX: This method belongs to Store::Root/StoreController, but it is here
-    // because test cases use non-StoreController derivatives as Root
-    /// called to get rid of no longer needed entry data in RAM, if any
-    virtual void memoryOut(StoreEntry &, const bool /*preserveSwappable*/) {}
-
-    // XXX: This method belongs to Store::Root/StoreController, but it is here
-    // to avoid casting Root() to StoreController until Root() API is fixed.
-    /// makes the entry available for collapsing future requests
-    virtual void allowCollapsing(StoreEntry *, const RequestFlags &, const HttpRequestMethod &) {}
-
-    // XXX: This method belongs to Store::Root/StoreController, but it is here
-    // to avoid casting Root() to StoreController until Root() API is fixed.
-    /// marks the entry completed for collapsed requests
-    virtual void transientsCompleteWriting(StoreEntry &) {}
-
-    // XXX: This method belongs to Store::Root/StoreController, but it is here
-    // to avoid casting Root() to StoreController until Root() API is fixed.
-    /// Update local intransit entry after changes made by appending worker.
-    virtual void syncCollapsed(const sfileno) {}
-
-    // XXX: This method belongs to Store::Root/StoreController, but it is here
-    // to avoid casting Root() to StoreController until Root() API is fixed.
-    /// calls Root().transients->abandon() if transients are tracked
-    virtual void transientsAbandon(StoreEntry &) {}
-
-    // XXX: This method belongs to Store::Root/StoreController, but it is here
-    // to avoid casting Root() to StoreController until Root() API is fixed.
-    /// number of the transient entry readers some time ago
-    virtual int transientReaders(const StoreEntry &) const { return 0; }
-
-    // XXX: This method belongs to Store::Root/StoreController, but it is here
-    // to avoid casting Root() to StoreController until Root() API is fixed.
-    /// disassociates the entry from the intransit table
-    virtual void transientsDisconnect(MemObject &) {}
-
-    // XXX: This method belongs to Store::Root/StoreController, but it is here
-    // to avoid casting Root() to StoreController until Root() API is fixed.
-    /// removes the entry from the memory cache
-    virtual void memoryUnlink(StoreEntry &) {}
-
-    // XXX: This method belongs to Store::Root/StoreController, but it is here
-    // to avoid casting Root() to StoreController until Root() API is fixed.
-    /// disassociates the entry from the memory cache, preserving cached data
-    virtual void memoryDisconnect(StoreEntry &) {}
-
-    /// If the entry is not found, return false. Otherwise, return true after
-    /// tying the entry to this cache and setting inSync to updateCollapsed().
-    virtual bool anchorCollapsed(StoreEntry &, bool &/*inSync*/) { return false; }
-
-    /// update a local collapsed entry with fresh info from this cache (if any)
-    virtual bool updateCollapsed(StoreEntry &) { return false; }
-
-private:
-    static RefCount<Store> CurrentRoot;
+namespace Store {
+void Stats(StoreEntry *output);
+void Maintain(void *unused);
 };
 
 /// \ingroup StoreAPI
-typedef RefCount<Store> StorePointer;
-
-/// \ingroup StoreAPI
 size_t storeEntryInUse();
 
 /// \ingroup StoreAPI
@@ -477,7 +319,6 @@
 /// \ingroup StoreAPI
 int storeTooManyDiskFilesOpen(void);
 
-class SwapDir;
 /// \ingroup StoreAPI
 void storeHeapPositionUpdate(StoreEntry *, SwapDir *);
 
diff -u -r -N squid-4.0.2/src/StoreHashIndex.h squid-4.0.3/src/StoreHashIndex.h
--- squid-4.0.2/src/StoreHashIndex.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/StoreHashIndex.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#ifndef SQUID_STOREHASHINDEX_H
-#define SQUID_STOREHASHINDEX_H
-
-#include "Store.h"
-#include "StoreSearch.h"
-
-/* A summary store that indexs all its children
- * into a memory hash
- */
-
-class StoreSearch;
-
-class StoreHashIndex : public Store
-{
-
-public:
-    StoreHashIndex();
-    StoreHashIndex(StoreHashIndex const &); /* to cause link failures */
-    virtual ~StoreHashIndex();
-    virtual int callback();
-    virtual void create();
-
-    virtual StoreEntry * get
-    (const cache_key *);
-
-    virtual void get
-    (String const, STOREGETCLIENT, void * cbdata);
-
-    virtual void init();
-
-    virtual void sync();
-
-    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 getStats(StoreInfoStats &stats) const;
-    virtual void stat(StoreEntry&) const;
-
-    virtual void reference(StoreEntry&);
-
-    virtual bool dereference(StoreEntry&, bool);
-
-    virtual void maintain();
-
-    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
-{};
-
-class StoreSearchHashIndex : public StoreSearch
-{
-    CBDATA_CLASS(StoreSearchHashIndex);
-
-public:
-    StoreSearchHashIndex(RefCount<StoreHashIndex> sd);
-    StoreSearchHashIndex(StoreSearchHashIndex const &);
-    virtual ~StoreSearchHashIndex();
-    /* Iterator API - garh, wrong place */
-    /* callback the client when a new StoreEntry is available
-     * or an error occurs
-     */
-    virtual void next(void (callback)(void *cbdata), void *cbdata);
-    /* return true if a new StoreEntry is immediately available */
-    virtual bool next();
-    virtual bool error() const;
-    virtual bool isDone() const;
-    virtual StoreEntry *currentItem();
-
-    RefCount<StoreHashIndex> sd;
-
-private:
-    void copyBucket();
-    void (*callback)(void *cbdata);
-    void *cbdata;
-    bool _done;
-    int bucket;
-    std::vector<StoreEntry *> entries;
-};
-
-#endif /* SQUID_STOREHASHINDEX_H */
-
diff -u -r -N squid-4.0.2/src/store_io.cc squid-4.0.3/src/store_io.cc
--- squid-4.0.2/src/store_io.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/store_io.cc	2015-11-28 07:30:57.000000000 -0800
@@ -10,7 +10,8 @@
 #include "MemObject.h"
 #include "SquidConfig.h"
 #include "Store.h"
-#include "SwapDir.h"
+#include "store/Disk.h"
+#include "store/Disks.h"
 
 StoreIoStats store_io_stats;
 
@@ -60,7 +61,7 @@
 storeOpen(StoreEntry * e, StoreIOState::STFNCB * file_callback, StoreIOState::STIOCB * callback,
           void *callback_data)
 {
-    return dynamic_cast<SwapDir *>(e->store().getRaw())->openStoreIO(*e, file_callback, callback, callback_data);
+    return e->disk().openStoreIO(*e, file_callback, callback, callback_data);
 }
 
 void
diff -u -r -N squid-4.0.2/src/StoreIOState.h squid-4.0.3/src/StoreIOState.h
--- squid-4.0.2/src/StoreIOState.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/StoreIOState.h	2015-11-28 07:30:57.000000000 -0800
@@ -11,8 +11,8 @@
 
 #include "base/RefCount.h"
 #include "cbdata.h"
-#include "fs/forward.h"
 #include "mem/forward.h"
+#include "store/forward.h"
 
 class StoreIOState : public RefCountable
 {
diff -u -r -N squid-4.0.2/src/store_key_md5.h squid-4.0.3/src/store_key_md5.h
--- squid-4.0.2/src/store_key_md5.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/store_key_md5.h	2015-11-28 07:30:57.000000000 -0800
@@ -12,13 +12,11 @@
 #define SQUID_STORE_KEY_MD5_H_
 
 #include "hash.h"
+#include "store/forward.h"
 
 class HttpRequestMethod;
 class HttpRequest;
 
-/* MD5 cache keys */
-typedef unsigned char cache_key;
-
 cache_key *storeKeyDup(const cache_key *);
 cache_key *storeKeyCopy(cache_key *, const cache_key *);
 void storeKeyFree(const cache_key *);
diff -u -r -N squid-4.0.2/src/store_rebuild.cc squid-4.0.3/src/store_rebuild.cc
--- squid-4.0.2/src/store_rebuild.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/store_rebuild.cc	2015-11-28 07:30:57.000000000 -0800
@@ -16,11 +16,11 @@
 #include "SquidTime.h"
 #include "StatCounters.h"
 #include "Store.h"
+#include "store/Disk.h"
 #include "store_digest.h"
 #include "store_key_md5.h"
 #include "store_rebuild.h"
 #include "StoreSearch.h"
-#include "SwapDir.h"
 // for tvSubDsec() which should be in SquidTime.h
 #include "util.h"
 
@@ -56,7 +56,7 @@
     static int seen = 0;
 
     if (currentSearch == NULL || currentSearch->isDone())
-        currentSearch = Store::Root().search(NULL, NULL);
+        currentSearch = Store::Root().search();
 
     size_t statCount = 500;
 
diff -u -r -N squid-4.0.2/src/StoreSwapLogData.h squid-4.0.3/src/StoreSwapLogData.h
--- squid-4.0.2/src/StoreSwapLogData.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/StoreSwapLogData.h	2015-11-28 07:30:57.000000000 -0800
@@ -35,9 +35,9 @@
  *      the value for MemObject->swap_hdr_sz.
  */
 
-#include "fs/forward.h"
 #include "md5.h"
 #include "mem/forward.h"
+#include "store/forward.h"
 
 /// maintains a 24-bit checksum over integer fields
 class SwapChecksum24
diff -u -r -N squid-4.0.2/src/store_swapout.cc squid-4.0.3/src/store_swapout.cc
--- squid-4.0.2/src/store_swapout.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/store_swapout.cc	2015-11-28 07:30:57.000000000 -0800
@@ -18,9 +18,10 @@
 #include "MemObject.h"
 #include "SquidConfig.h"
 #include "StatCounters.h"
+#include "store/Disk.h"
+#include "store/Disks.h"
 #include "store_log.h"
 #include "swap_log_op.h"
-#include "SwapDir.h"
 
 static void storeSwapOutStart(StoreEntry * e);
 static StoreIOState::STIOCB storeSwapOutFileClosed;
@@ -299,12 +300,12 @@
             /* FIXME: this should be handle by the link from store IO to
              * Store, rather than being a top level API call.
              */
-            e->store()->diskFull();
+            e->disk().diskFull();
             storeConfigure();
         }
 
         if (e->swap_filen >= 0)
-            e->unlink();
+            e->disk().unlink(*e);
 
         assert(e->swap_status == SWAPOUT_NONE);
 
@@ -319,7 +320,7 @@
 
         e->swap_file_sz = e->objectLen() + mem->swap_hdr_sz;
         e->swap_status = SWAPOUT_DONE;
-        e->store()->swappedOut(*e);
+        e->disk().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
diff -u -r -N squid-4.0.2/src/SwapDir.cc squid-4.0.3/src/SwapDir.cc
--- squid-4.0.2/src/SwapDir.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/SwapDir.cc	1969-12-31 16:00:00.000000000 -0800
@@ -1,383 +0,0 @@
-/*
- * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-/* DEBUG: section 20    Swap Dir base object */
-
-#include "squid.h"
-#include "cache_cf.h"
-#include "compat/strtoll.h"
-#include "ConfigOption.h"
-#include "ConfigParser.h"
-#include "globals.h"
-#include "Parsing.h"
-#include "SquidConfig.h"
-#include "StoreFileSystem.h"
-#include "SwapDir.h"
-#include "tools.h"
-
-SwapDir::SwapDir(char const *aType): theType(aType),
-    max_size(0), min_objsize(0), max_objsize (-1),
-    path(NULL), index(-1), disker(-1),
-    repl(NULL), removals(0), scanned(0),
-    cleanLog(NULL)
-{
-    fs.blksize = 1024;
-}
-
-SwapDir::~SwapDir()
-{
-    // TODO: should we delete repl?
-    xfree(path);
-}
-
-void
-SwapDir::create() {}
-
-void
-SwapDir::dump(StoreEntry &)const {}
-
-bool
-SwapDir::doubleCheck(StoreEntry &)
-{
-    return false;
-}
-
-void
-SwapDir::unlink(StoreEntry &) {}
-
-void
-SwapDir::getStats(StoreInfoStats &stats) const
-{
-    if (!doReportStat())
-        return;
-
-    stats.swap.size = currentSize();
-    stats.swap.capacity = maxSize();
-    stats.swap.count = currentCount();
-}
-
-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",
-                      fs.blksize);
-    statfs(output);
-
-    if (repl) {
-        storeAppendPrintf(&output, "Removal policy: %s\n", repl->_type);
-
-        if (repl->Stats)
-            repl->Stats(repl, &output);
-    }
-}
-
-void
-SwapDir::statfs(StoreEntry &)const {}
-
-void
-SwapDir::maintain() {}
-
-uint64_t
-SwapDir::minSize() const
-{
-    return ((maxSize() * Config.Swap.lowWaterMark) / 100);
-}
-
-int64_t
-SwapDir::maxObjectSize() const
-{
-    // per-store max-size=N value is authoritative
-    if (max_objsize > -1)
-        return max_objsize;
-
-    // store with no individual max limit is limited by configured maximum_object_size
-    // or the total store size, whichever is smaller
-    return min(static_cast<int64_t>(maxSize()), Config.Store.maxObjectSize);
-}
-
-void
-SwapDir::maxObjectSize(int64_t newMax)
-{
-    // negative values mean no limit (-1)
-    if (newMax < 0) {
-        max_objsize = -1; // set explicitly in case it had a non-default value previously
-        return;
-    }
-
-    // prohibit values greater than total storage area size
-    // but set max_objsize to the maximum allowed to override maximum_object_size global config
-    if (static_cast<uint64_t>(newMax) > maxSize()) {
-        debugs(47, DBG_PARSE_NOTE(2), "WARNING: Ignoring 'max-size' option for " << path <<
-               " which is larger than total cache_dir size of " << maxSize() << " bytes.");
-        max_objsize = maxSize();
-        return;
-    }
-
-    max_objsize = newMax;
-}
-
-void
-SwapDir::reference(StoreEntry &) {}
-
-bool
-SwapDir::dereference(StoreEntry &, bool)
-{
-    return true; // keep in global store_table
-}
-
-int
-SwapDir::callback()
-{
-    return 0;
-}
-
-bool
-SwapDir::canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const
-{
-    debugs(47,8, HERE << "cache_dir[" << index << "]: needs " <<
-           diskSpaceNeeded << " <? " << max_objsize);
-
-    if (EBIT_TEST(e.flags, ENTRY_SPECIAL))
-        return false; // we do not store Squid-generated entries
-
-    if (!objectSizeIsAcceptable(diskSpaceNeeded))
-        return false; // does not satisfy size limits
-
-    if (flags.read_only)
-        return false; // cannot write at all
-
-    if (currentSize() > 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() {}
-
-/* Move to StoreEntry ? */
-bool
-SwapDir::canLog(StoreEntry const &e)const
-{
-    if (e.swap_filen < 0)
-        return false;
-
-    if (e.swap_status != SWAPOUT_DONE)
-        return false;
-
-    if (e.swap_file_sz <= 0)
-        return false;
-
-    if (EBIT_TEST(e.flags, RELEASE_REQUEST))
-        return false;
-
-    if (EBIT_TEST(e.flags, KEY_PRIVATE))
-        return false;
-
-    if (EBIT_TEST(e.flags, ENTRY_SPECIAL))
-        return false;
-
-    return true;
-}
-
-void
-SwapDir::openLog() {}
-
-void
-SwapDir::closeLog() {}
-
-int
-SwapDir::writeCleanStart()
-{
-    return 0;
-}
-
-void
-SwapDir::writeCleanDone() {}
-
-void
-SwapDir::logEntry(const StoreEntry &, int) const {}
-
-char const *
-SwapDir::type() const
-{
-    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
- */
-ConfigOption *
-SwapDir::getOptionTree() const
-{
-    ConfigOptionVector *result = new ConfigOptionVector;
-    result->options.push_back(new ConfigOptionAdapter<SwapDir>(*const_cast<SwapDir *>(this), &SwapDir::optionReadOnlyParse, &SwapDir::optionReadOnlyDump));
-    result->options.push_back(new ConfigOptionAdapter<SwapDir>(*const_cast<SwapDir *>(this), &SwapDir::optionObjectSizeParse, &SwapDir::optionObjectSizeDump));
-    return result;
-}
-
-void
-SwapDir::parseOptions(int isaReconfig)
-{
-    const bool old_read_only = flags.read_only;
-    char *name, *value;
-
-    ConfigOption *newOption = getOptionTree();
-
-    while ((name = ConfigParser::NextToken()) != NULL) {
-        value = strchr(name, '=');
-
-        if (value) {
-            *value = '\0';  /* cut on = */
-            ++value;
-        }
-
-        debugs(3,2, "SwapDir::parseOptions: parsing store option '" << name << "'='" << (value ? value : "") << "'");
-
-        if (newOption)
-            if (!newOption->parse(name, value, isaReconfig))
-                self_destruct();
-    }
-
-    delete newOption;
-
-    /*
-     * Handle notifications about reconfigured single-options with no value
-     * where the removal of the option cannot be easily detected in the
-     * parsing...
-     */
-
-    if (isaReconfig) {
-        if (old_read_only != flags.read_only) {
-            debugs(3, DBG_IMPORTANT, "Cache dir '" << path << "' now " << (flags.read_only ? "No-Store" : "Read-Write"));
-        }
-    }
-}
-
-void
-SwapDir::dumpOptions(StoreEntry * entry) const
-{
-    ConfigOption *newOption = getOptionTree();
-
-    if (newOption)
-        newOption->dump(entry);
-
-    delete newOption;
-}
-
-bool
-SwapDir::optionReadOnlyParse(char const *option, const char *value, int)
-{
-    if (strcmp(option, "no-store") != 0 && strcmp(option, "read-only") != 0)
-        return false;
-
-    if (strcmp(option, "read-only") == 0) {
-        debugs(3, DBG_PARSE_NOTE(3), "UPGRADE WARNING: Replace cache_dir option 'read-only' with 'no-store'.");
-    }
-
-    bool read_only = 0;
-
-    if (value)
-        read_only = (xatoi(value) != 0);
-    else
-        read_only = true;
-
-    flags.read_only = read_only;
-
-    return true;
-}
-
-void
-SwapDir::optionReadOnlyDump(StoreEntry * e) const
-{
-    if (flags.read_only)
-        storeAppendPrintf(e, " no-store");
-}
-
-bool
-SwapDir::optionObjectSizeParse(char const *option, const char *value, int isaReconfig)
-{
-    int64_t *val;
-    if (strcmp(option, "max-size") == 0) {
-        val = &max_objsize;
-    } else if (strcmp(option, "min-size") == 0) {
-        val = &min_objsize;
-    } else
-        return false;
-
-    if (!value)
-        self_destruct();
-
-    int64_t size = strtoll(value, NULL, 10);
-
-    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;
-
-    return true;
-}
-
-void
-SwapDir::optionObjectSizeDump(StoreEntry * e) const
-{
-    if (min_objsize != 0)
-        storeAppendPrintf(e, " min-size=%" PRId64, min_objsize);
-
-    if (max_objsize != -1)
-        storeAppendPrintf(e, " max-size=%" PRId64, max_objsize);
-}
-
-// some SwapDirs may maintain their indexes and be able to lookup an entry key
-StoreEntry *
-SwapDir::get(const cache_key *)
-{
-    return NULL;
-}
-
-void
-SwapDir::get(String const, STOREGETCLIENT, void *)
-{
-    fatal("not implemented");
-}
-
diff -u -r -N squid-4.0.2/src/SwapDir.h squid-4.0.3/src/SwapDir.h
--- squid-4.0.2/src/SwapDir.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/SwapDir.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#ifndef SQUID_SWAPDIR_H
-#define SQUID_SWAPDIR_H
-
-#include "mgr/forward.h"
-#include "SquidConfig.h"
-#include "Store.h"
-#include "StoreIOState.h"
-
-/* forward decls */
-class RemovalPolicy;
-class MemStore;
-class Transients;
-class RequestFlags;
-class HttpRequestMethod;
-
-/* Store dir configuration routines */
-/* SwapDir *sd, char *path ( + char *opt later when the strtok mess is gone) */
-
-typedef int STDIRSELECT(const StoreEntry *);
-
-class ConfigOption;
-
-/// hides memory/disk cache distinction from callers
-class StoreController : public Store
-{
-
-public:
-    StoreController();
-    virtual ~StoreController();
-    virtual int callback();
-    virtual void create();
-
-    virtual StoreEntry * get(const cache_key *);
-
-    virtual void get(String const, STOREGETCLIENT, void * cbdata);
-
-    /* Store parent API */
-    virtual void markForUnlink(StoreEntry &e);
-    virtual void handleIdleEntry(StoreEntry &e);
-    virtual void transientsCompleteWriting(StoreEntry &e);
-    virtual void transientsAbandon(StoreEntry &e);
-    virtual int transientReaders(const StoreEntry &e) const;
-    virtual void transientsDisconnect(MemObject &mem_obj);
-    virtual void memoryOut(StoreEntry &e, const bool preserveSwappable);
-    virtual void memoryUnlink(StoreEntry &e);
-    virtual void memoryDisconnect(StoreEntry &e);
-    virtual void allowCollapsing(StoreEntry *e, const RequestFlags &reqFlags, const HttpRequestMethod &reqMethod);
-    virtual void syncCollapsed(const sfileno xitIndex);
-
-    virtual void init();
-
-    virtual void maintain(); /* perform regular maintenance should be private and self registered ... */
-
-    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 getStats(StoreInfoStats &stats) const;
-    virtual void stat(StoreEntry &) const;
-
-    virtual void sync();    /* Sync the store prior to shutdown */
-
-    virtual StoreSearch *search(String const url, HttpRequest *);
-
-    virtual void reference(StoreEntry &);   /* Reference this object */
-
-    virtual bool dereference(StoreEntry &, bool);   /* Unreference this object */
-
-    /* the number of store dirs being rebuilt. */
-    static int store_dirs_rebuilding;
-
-private:
-    void createOneStore(Store &aStore);
-    StoreEntry *find(const cache_key *key);
-    bool keepForLocalMemoryCache(StoreEntry &e) const;
-    bool anchorCollapsed(StoreEntry &collapsed, bool &inSync);
-    bool anchorCollapsedOnDisk(StoreEntry &collapsed, bool &inSync);
-
-    StorePointer swapDir; ///< summary view of all disk caches
-    MemStore *memStore; ///< memory cache
-
-    /// A shared table of public store entries that do not know whether they
-    /// will belong to a memory cache, a disk cache, or will be uncachable
-    /// when the response header comes. Used for SMP collapsed forwarding.
-    Transients *transients;
-};
-
-/* migrating from the Config based list of swapdirs */
-void allocate_new_swapdir(SquidConfig::_cacheSwap *);
-void free_cachedir(SquidConfig::_cacheSwap * swap);
-extern OBJH storeDirStats;
-char *storeDirSwapLogFile(int, const char *);
-char *storeSwapFullPath(int, char *);
-char *storeSwapSubSubDir(int, char *);
-const char *storeSwapPath(int);
-int storeDirWriteCleanLogs(int reopen);
-extern STDIRSELECT *storeDirSelectSwapDir;
-int storeVerifySwapDirs(void);
-void storeDirCloseSwapLogs(void);
-void storeDirCloseTmpSwapLog(int dirn);
-void storeDirDiskFull(sdirno);
-void storeDirOpenSwapLogs(void);
-void storeDirSwapLog(const StoreEntry *, int op);
-void storeDirLRUDelete(StoreEntry *);
-void storeDirLRUAdd(StoreEntry *);
-int storeDirGetBlkSize(const char *path, int *blksize);
-int storeDirGetUFSStats(const char *, int *, int *, int *, int *);
-
-/// manages a single cache_dir
-class SwapDir : public Store
-{
-
-public:
-    typedef RefCount<SwapDir> Pointer;
-
-    SwapDir(char const *aType);
-    virtual ~SwapDir();
-    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(); }
-    /// whether SwapDir may benefit from unlinkd
-    virtual bool unlinkdUseful() const = 0;
-
-    /* official Store interface functions */
-    virtual void diskFull();
-
-    virtual StoreEntry * get(const cache_key *);
-
-    virtual void get(String const, STOREGETCLIENT, void * cbdata);
-
-    virtual uint64_t maxSize() const { return max_size;}
-
-    virtual uint64_t minSize() const;
-
-    /// The maximum size of object which may be stored here.
-    /// Larger objects will not be added and may be purged.
-    virtual int64_t maxObjectSize() const;
-
-    /// configure the maximum object size for this storage area.
-    /// May be any size up to the total storage area.
-    void maxObjectSize(int64_t newMax);
-
-    virtual void getStats(StoreInfoStats &stats) const;
-    virtual void stat (StoreEntry &anEntry) const;
-    virtual StoreSearch *search(String const url, HttpRequest *) = 0;
-
-    /* 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);
-    void optionReadOnlyDump(StoreEntry * e) const;
-    bool optionObjectSizeParse(char const *option, const char *value, int reconfiguring);
-    void optionObjectSizeDump(StoreEntry * e) const;
-    char const *theType;
-
-protected:
-    uint64_t max_size;        ///< maximum allocatable size of the storage area
-    int64_t min_objsize;      ///< minimum size of any object stored here (-1 for no limit)
-    int64_t max_objsize;      ///< maximum size of any object stored here (-1 for no limit)
-
-public:
-    char *path;
-    int index;          /* This entry's index into the swapDirs array */
-    int disker; ///< disker kid id dedicated to this SwapDir or -1
-    RemovalPolicy *repl;
-    int removals;
-    int scanned;
-
-    struct Flags {
-        Flags() : selected(false), read_only(false) {}
-        bool selected;
-        bool read_only;
-    } flags;
-    virtual void init() = 0;    /* Initialise the fs */
-    virtual void create();  /* Create a new fs */
-    virtual void dump(StoreEntry &)const;   /* Dump fs config snippet */
-    virtual bool doubleCheck(StoreEntry &); /* Double check the obj integrity */
-    virtual void statfs(StoreEntry &) const;    /* Dump fs statistics */
-    virtual void maintain();    /* Replacement maintainence */
-    /// 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 bool dereference(StoreEntry &, bool);   /* 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;
-    virtual StoreIOState::Pointer openStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *) = 0;
-    virtual void unlink (StoreEntry &);
-    bool canLog(StoreEntry const &e)const;
-    virtual void openLog();
-    virtual void closeLog();
-    virtual void logEntry(const StoreEntry & e, int op) const;
-
-    class CleanLog
-    {
-
-    public:
-        virtual ~CleanLog() {}
-
-        virtual const StoreEntry *nextEntry() = 0;
-        virtual void write(StoreEntry const &) = 0;
-    };
-
-    CleanLog *cleanLog;
-    virtual int writeCleanStart();
-    virtual void writeCleanDone();
-    virtual void parse(int index, char *path) = 0;
-
-    struct {
-        int blksize;
-    } fs;
-};
-
-#endif /* SQUID_SWAPDIR_H */
-
diff -u -r -N squid-4.0.2/src/tests/stub_CacheDigest.cc squid-4.0.3/src/tests/stub_CacheDigest.cc
--- squid-4.0.2/src/tests/stub_CacheDigest.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/stub_CacheDigest.cc	2015-11-28 07:30:57.000000000 -0800
@@ -16,17 +16,18 @@
 class CacheDigestGuessStats;
 class StoreEntry;
 
-CacheDigest * cacheDigestCreate(int, int) STUB_RETVAL(NULL)
-void cacheDigestDestroy(CacheDigest *) STUB
-CacheDigest * cacheDigestClone(const CacheDigest *) STUB_RETVAL(NULL)
-void cacheDigestClear(CacheDigest * ) STUB
-void cacheDigestChangeCap(CacheDigest *,int) STUB
-int cacheDigestTest(const CacheDigest *, const cache_key *) STUB_RETVAL(1)
-void cacheDigestAdd(CacheDigest *, const cache_key *) STUB
-void cacheDigestDel(CacheDigest *, const cache_key *) STUB
-int cacheDigestBitUtil(const CacheDigest *) STUB_RETVAL(0)
+#include "CacheDigest.h"
+CacheDigest::CacheDigest(int, int) {STUB}
+CacheDigest::~CacheDigest() {STUB}
+CacheDigest *CacheDigest::clone() const STUB_RETVAL(nullptr)
+void CacheDigest::clear() STUB
+void CacheDigest::updateCapacity(int) STUB
+bool CacheDigest::contains(const cache_key *) const STUB_RETVAL(false)
+void CacheDigest::add(const cache_key *) STUB
+void CacheDigest::remove(const cache_key *) STUB
+double CacheDigest::usedMaskPercent() const STUB_RETVAL(0.0)
 void cacheDigestGuessStatsUpdate(CacheDigestGuessStats *, int, int) STUB
 void cacheDigestGuessStatsReport(const CacheDigestGuessStats *, StoreEntry *, const char *) STUB
 void cacheDigestReport(CacheDigest *, const char *, StoreEntry *) STUB
-size_t cacheDigestCalcMaskSize(int, int) STUB_RETVAL(1)
+size_t CacheDigest::CalcMaskSize(int, int) STUB_RETVAL(1)
 
diff -u -r -N squid-4.0.2/src/tests/stub_client_side.cc squid-4.0.3/src/tests/stub_client_side.cc
--- squid-4.0.2/src/tests/stub_client_side.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/stub_client_side.cc	2015-11-28 07:30:57.000000000 -0800
@@ -16,7 +16,6 @@
 //ClientSocketContext::~ClientSocketContext() STUB
 bool ClientSocketContext::startOfOutput() const STUB_RETVAL(false)
 void ClientSocketContext::writeComplete(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, Comm::Flag errflag) STUB
-void ClientSocketContext::keepaliveNextRequest() STUB
 void ClientSocketContext::pullData() STUB
 int64_t ClientSocketContext::getNextRangeOffset() const STUB_RETVAL(0)
 bool ClientSocketContext::canPackMoreRanges() const STUB_RETVAL(false)
@@ -28,31 +27,23 @@
 void ClientSocketContext::buildRangeHeader(HttpReply * rep) STUB
 clientStreamNode * ClientSocketContext::getTail() const STUB_RETVAL(NULL)
 clientStreamNode * ClientSocketContext::getClientReplyContext() const STUB_RETVAL(NULL)
-void ClientSocketContext::connIsFinished() STUB
-void ClientSocketContext::removeFromConnectionList(ConnStateData * conn) STUB
+void ClientSocketContext::finished() STUB
 void ClientSocketContext::deferRecipientForLater(clientStreamNode * node, HttpReply * rep, StoreIOBuffer receivedData) STUB
 bool ClientSocketContext::multipartRangeRequest() const STUB_RETVAL(false)
 void ClientSocketContext::registerWithConn() STUB
 void ClientSocketContext::noteIoError(const int xerrno) STUB
 void ClientSocketContext::writeControlMsg(HttpControlMsg &msg) STUB
 
-void ConnStateData::readSomeData() STUB
-bool ConnStateData::areAllContextsForThisConnection() const STUB_RETVAL(false)
-void ConnStateData::freeAllContexts() STUB
-void ConnStateData::notifyAllContexts(const int xerrno) STUB
 bool ConnStateData::clientParseRequests() STUB_RETVAL(false)
 void ConnStateData::readNextRequest() STUB
-void ConnStateData::addContextToQueue(ClientSocketContext * context) STUB
-int ConnStateData::getConcurrentRequestCount() const STUB_RETVAL(0)
 bool ConnStateData::isOpen() const STUB_RETVAL(false)
+void ConnStateData::kick() STUB
 void ConnStateData::sendControlMsg(HttpControlMsg msg) STUB
 int64_t ConnStateData::mayNeedToReadMoreBody() const STUB_RETVAL(0)
 #if USE_AUTH
 void ConnStateData::setAuth(const Auth::UserRequest::Pointer &aur, const char *cause) STUB
 #endif
 bool ConnStateData::transparent() const STUB_RETVAL(false)
-bool ConnStateData::reading() const STUB_RETVAL(false)
-void ConnStateData::stopReading() STUB
 void ConnStateData::stopReceiving(const char *error) STUB
 void ConnStateData::stopSending(const char *error) STUB
 void ConnStateData::expectNoForwarding() STUB
@@ -64,7 +55,6 @@
 void ConnStateData::unpinConnection(const bool andClose) STUB
 const Comm::ConnectionPointer ConnStateData::validatePinnedConnection(HttpRequest *request, const CachePeer *peer) STUB_RETVAL(NULL)
 void ConnStateData::clientPinnedConnectionClosed(const CommCloseCbParams &io) STUB
-void ConnStateData::clientReadRequest(const CommIoCbParams &io) STUB
 void ConnStateData::connStateClosed(const CommCloseCbParams &io) STUB
 void ConnStateData::requestTimeout(const CommTimeoutCbParams &params) STUB
 void ConnStateData::swanSong() STUB
@@ -72,7 +62,7 @@
 #if USE_OPENSSL
 void ConnStateData::httpsPeeked(Comm::ConnectionPointer serverConnection) STUB
 void ConnStateData::getSslContextStart() STUB
-void ConnStateData::getSslContextDone(Security::ContextPointer, bool) STUB
+void ConnStateData::getSslContextDone(Security::ContextPtr, bool) STUB
 void ConnStateData::sslCrtdHandleReplyWrapper(void *data, const Helper::Reply &reply) STUB
 void ConnStateData::sslCrtdHandleReply(const Helper::Reply &reply) STUB
 void ConnStateData::switchToHttps(HttpRequest *request, Ssl::BumpMode bumpServerMode) STUB
@@ -80,8 +70,6 @@
 bool ConnStateData::serveDelayedError(ClientSocketContext *context) STUB_RETVAL(false)
 #endif
 
-bool ConnStateData::In::maybeMakeSpaceAvailable() STUB_RETVAL(false)
-
 void setLogUri(ClientHttpRequest * http, char const *uri, bool cleanUrl) STUB
 const char *findTrailingHTTPVersion(const char *uriAndHTTPVersion, const char *end) STUB_RETVAL(NULL)
 int varyEvaluateMatch(StoreEntry * entry, HttpRequest * req) STUB_RETVAL(0)
diff -u -r -N squid-4.0.2/src/tests/STUB.h squid-4.0.3/src/tests/STUB.h
--- squid-4.0.2/src/tests/STUB.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/STUB.h	2015-11-28 07:30:57.000000000 -0800
@@ -46,17 +46,12 @@
 
 /** macro to stub a function which returns a reference to dynamic
  *  Aborts unit tests requiring its definition with a message about the missing linkage
- *  This macro uses 'new x' to construct a stack vailable for the reference, may leak.
- *  \param x may be the type to define or a constructor call with parameter values
+ *  \param x underlying or "referred to" type
  */
-#define STUB_RETREF(x) { stub_fatal(STUB_API " required"); return new x; }
+#define STUB_RETREF(x) { stub_fatal(STUB_API " required"); return *(x *)nullptr; }
 
-/** macro to stub a function which returns a reference to static
- *  Aborts unit tests requiring its definition with a message about the missing linkage
- *  This macro uses static variable definition to avoid leaks.
- *  \param x  the type name to define
- */
-#define STUB_RETSTATREF(x) { stub_fatal(STUB_API " required"); static x v; return v; }
+/** Same as STUB_RETREF(). TODO: Remove */
+#define STUB_RETSTATREF(x) STUB_RETREF(x)
 
 #endif /* STUB */
 
diff -u -r -N squid-4.0.2/src/tests/stub_libsecurity.cc squid-4.0.3/src/tests/stub_libsecurity.cc
--- squid-4.0.2/src/tests/stub_libsecurity.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/stub_libsecurity.cc	2015-11-28 07:30:57.000000000 -0800
@@ -19,10 +19,10 @@
 #include "security/PeerOptions.h"
 Security::PeerOptions Security::ProxyOutgoingConfig;
 void Security::PeerOptions::parse(char const*) STUB
-Security::ContextPointer Security::PeerOptions::createClientContext(bool) STUB_RETVAL(NULL)
+Security::ContextPtr Security::PeerOptions::createClientContext(bool) STUB_RETVAL(NULL)
 void Security::PeerOptions::updateTlsVersionLimits() STUB
-void Security::PeerOptions::updateContextCa(Security::ContextPointer &) STUB
-void Security::PeerOptions::updateContextCrl(Security::ContextPointer &) STUB
+void Security::PeerOptions::updateContextCa(Security::ContextPtr &) STUB
+void Security::PeerOptions::updateContextCrl(Security::ContextPtr &) STUB
 void Security::PeerOptions::dumpCfg(Packable*, char const*) const STUB
 long Security::PeerOptions::parseOptions() STUB_RETVAL(0)
 long Security::PeerOptions::parseFlags() STUB_RETVAL(0)
@@ -32,5 +32,5 @@
 //Security::ServerOptions::ServerOptions(const Security::ServerOptions &) STUB
 void Security::ServerOptions::parse(const char *) STUB
 void Security::ServerOptions::dumpCfg(Packable *, const char *) const STUB
-void Security::ServerOptions::updateContextEecdh(Security::ContextPointer &) STUB
+void Security::ServerOptions::updateContextEecdh(Security::ContextPtr &) STUB
 
diff -u -r -N squid-4.0.2/src/tests/stub_libsslsquid.cc squid-4.0.3/src/tests/stub_libsslsquid.cc
--- squid-4.0.2/src/tests/stub_libsslsquid.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/stub_libsslsquid.cc	2015-11-28 07:30:57.000000000 -0800
@@ -56,8 +56,8 @@
 bool CertError::operator == (const CertError &ce) const STUB_RETVAL(false)
 bool CertError::operator != (const CertError &ce) const STUB_RETVAL(false)
 } // namespace Ssl
-SSL_CTX *sslCreateServerContext(AnyP::PortCfg &port) STUB_RETVAL(NULL)
-SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, const char *flags) STUB_RETVAL(NULL)
+Security::ContextPtr sslCreateServerContext(AnyP::PortCfg &port) STUB_RETVAL(NULL)
+Security::ContextPtr sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, const char *flags) STUB_RETVAL(NULL)
 int ssl_read_method(int, char *, int) STUB_RETVAL(0)
 int ssl_write_method(int, const char *, int) STUB_RETVAL(0)
 void ssl_shutdown_method(SSL *ssl) STUB
@@ -73,10 +73,10 @@
 //GETX509ATTRIBUTE GetX509Fingerprint;
 const char *BumpModeStr[] = {""};
 bool generateUntrustedCert(Security::CertPointer & untrustedCert, EVP_PKEY_Pointer & untrustedPkey, Security::CertPointer const & cert, EVP_PKEY_Pointer const & pkey) STUB_RETVAL(false)
-SSL_CTX * generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port) STUB_RETVAL(NULL)
-bool verifySslCertificate(SSL_CTX * sslContext,  CertificateProperties const &properties) STUB_RETVAL(false)
-SSL_CTX * generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port) STUB_RETVAL(NULL)
-void addChainToSslContext(SSL_CTX *sslContext, STACK_OF(X509) *certList) STUB
+Security::ContextPtr generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port) STUB_RETVAL(NULL)
+bool verifySslCertificate(Security::ContextPtr sslContext,  CertificateProperties const &properties) STUB_RETVAL(false)
+Security::ContextPtr generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port) STUB_RETVAL(NULL)
+void addChainToSslContext(Security::ContextPtr sslContext, STACK_OF(X509) *certList) STUB
 void readCertChainAndPrivateKeyFromFiles(Security::CertPointer & cert, EVP_PKEY_Pointer & pkey, X509_STACK_Pointer & chain, char const * certFilename, char const * keyFilename) STUB
 int matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data,  ASN1_STRING *cn_data)) STUB_RETVAL(0)
 bool checkX509ServerValidity(X509 *cert, const char *server) STUB_RETVAL(false)
diff -u -r -N squid-4.0.2/src/tests/stub_MemStore.cc squid-4.0.3/src/tests/stub_MemStore.cc
--- squid-4.0.2/src/tests/stub_MemStore.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/stub_MemStore.cc	2015-11-28 07:30:57.000000000 -0800
@@ -24,19 +24,16 @@
 void MemStore::reference(StoreEntry &) STUB
 void MemStore::maintain() STUB
 void MemStore::noteFreeMapSlice(const Ipc::StoreMapSliceId) STUB
-void MemStore::get(String const, STOREGETCLIENT, void *) STUB
 void MemStore::init() STUB
 void MemStore::getStats(StoreInfoStats&) const 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 &, bool) STUB_RETVAL(false)
+bool MemStore::dereference(StoreEntry &) STUB_RETVAL(false)
 void MemStore::markForUnlink(StoreEntry&) STUB
 bool MemStore::anchorCollapsed(StoreEntry&, bool&) STUB_RETVAL(false)
 bool MemStore::updateCollapsed(StoreEntry&) STUB_RETVAL(false)
diff -u -r -N squid-4.0.2/src/tests/stub_store.cc squid-4.0.3/src/tests/stub_store.cc
--- squid-4.0.2/src/tests/stub_store.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/stub_store.cc	2015-11-28 07:30:57.000000000 -0800
@@ -17,14 +17,10 @@
 const char *memStatusStr[] = { };
 const char *swapStatusStr[] = { };
 
-/* and code defined in the wrong .cc file */
-#include "SwapDir.h"
-void StoreController::maintain() STUB
 #include "RemovalPolicy.h"
 RemovalPolicy * createRemovalPolicy(RemovalPolicySettings * settings) STUB_RETVAL(NULL)
 
 #include "Store.h"
-StorePointer Store::CurrentRoot = NULL;
 StoreIoStats store_io_stats;
 bool StoreEntry::checkDeferRead(int fd) const STUB_RETVAL(false)
 const char *StoreEntry::getMD5Text() const STUB_RETVAL(NULL)
@@ -41,7 +37,6 @@
 bool StoreEntry::mayStartSwapOut() STUB_RETVAL(false)
 void StoreEntry::trimMemory(const bool preserveSwappable) STUB
 void StoreEntry::abort() STUB
-void StoreEntry::unlink() STUB
 void StoreEntry::makePublic() STUB
 void StoreEntry::makePrivate() STUB
 void StoreEntry::setPublicKey() STUB
@@ -76,7 +71,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<SwapDir> StoreEntry::store() const STUB_RETVAL(NULL)
+Store::Disk &StoreEntry::disk() const STUB_RETREF(Store::Disk)
 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
@@ -102,14 +97,14 @@
 // private virtual. Why is this linked from outside?
 const char *NullStoreEntry::getSerialisedMetaData() STUB_RETVAL(NULL)
 
-void Store::Root(Store *) STUB
-void Store::Root(RefCount<Store>) STUB
+Store::Controller &Store::Root() STUB_RETREF(Store::Controller)
+void Store::Init(Store::Controller *root) STUB
+void Store::FreeMemory() STUB
 void Store::Stats(StoreEntry * output) STUB
 void Store::Maintain(void *unused) STUB
-void Store::create() STUB
-void Store::diskFull() STUB
-void Store::sync() STUB
-void Store::unlink(StoreEntry &) STUB
+int Store::Controller::store_dirs_rebuilding = 0;
+StoreSearch *Store::Controller::search() STUB_RETVAL(NULL)
+void Store::Controller::maintain() STUB
 
 std::ostream &operator <<(std::ostream &os, const StoreEntry &)
 {
@@ -124,9 +119,7 @@
 StoreEntry *storeGetPublicByRequestMethod(HttpRequest * request, const HttpRequestMethod& method) STUB_RETVAL(NULL)
 StoreEntry *storeCreateEntry(const char *, const char *, const RequestFlags &, const HttpRequestMethod&) STUB_RETVAL(NULL)
 StoreEntry *storeCreatePureEntry(const char *storeId, const char *logUrl, const RequestFlags &, const HttpRequestMethod&) STUB_RETVAL(NULL)
-void storeInit(void) STUB
 void storeConfigure(void) STUB
-void storeFreeMemory(void) STUB
 int expiresMoreThan(time_t, time_t) STUB_RETVAL(0)
 void storeAppendPrintf(StoreEntry *, const char *,...) STUB
 void storeAppendVPrintf(StoreEntry *, const char *, va_list ap) STUB
diff -u -r -N squid-4.0.2/src/tests/stub_store_rebuild.cc squid-4.0.3/src/tests/stub_store_rebuild.cc
--- squid-4.0.2/src/tests/stub_store_rebuild.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/stub_store_rebuild.cc	2015-11-28 07:30:57.000000000 -0800
@@ -10,8 +10,8 @@
 
 #include "squid.h"
 #include "MemBuf.h"
+#include "store/Controller.h"
 #include "store_rebuild.h"
-#include "SwapDir.h"
 
 #include <cstring>
 
diff -u -r -N squid-4.0.2/src/tests/stub_SwapDir.cc squid-4.0.3/src/tests/stub_SwapDir.cc
--- squid-4.0.2/src/tests/stub_SwapDir.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/stub_SwapDir.cc	2015-11-28 07:30:57.000000000 -0800
@@ -7,9 +7,9 @@
  */
 
 #include "squid.h"
-#include "SwapDir.h"
+#include "store/Disk.h"
 
-#define STUB_API "SwapDir.cc"
+#define STUB_API "store/Disk.cc"
 #include "tests/STUB.h"
 
 // SwapDir::SwapDir(char const *) STUB
@@ -17,7 +17,6 @@
 void SwapDir::create() STUB
 void SwapDir::dump(StoreEntry &) const STUB
 bool SwapDir::doubleCheck(StoreEntry &) STUB_RETVAL(false)
-void SwapDir::unlink(StoreEntry &) STUB
 void SwapDir::getStats(StoreInfoStats &) const STUB
 void SwapDir::stat(StoreEntry &) const STUB
 void SwapDir::statfs(StoreEntry &)const STUB
@@ -26,11 +25,9 @@
 int64_t SwapDir::maxObjectSize() const STUB_RETVAL(0)
 void SwapDir::maxObjectSize(int64_t) STUB
 void SwapDir::reference(StoreEntry &) STUB
-bool SwapDir::dereference(StoreEntry &, bool) STUB_RETVAL(false)
-int SwapDir::callback() STUB_RETVAL(0)
+bool SwapDir::dereference(StoreEntry &) STUB_RETVAL(false)
 bool SwapDir::canStore(const StoreEntry &, int64_t, int &) const STUB_RETVAL(false)
 bool SwapDir::canLog(StoreEntry const &)const STUB_RETVAL(false)
-void SwapDir::sync() STUB
 void SwapDir::openLog() STUB
 void SwapDir::closeLog() STUB
 int SwapDir::writeCleanStart() STUB_RETVAL(0)
@@ -47,5 +44,4 @@
 bool SwapDir::optionObjectSizeParse(char const *, const char *, int) STUB_RETVAL(false)
 void SwapDir::optionObjectSizeDump(StoreEntry *) const STUB
 StoreEntry * SwapDir::get(const cache_key *) STUB_RETVAL(NULL)
-void SwapDir::get(String const, STOREGETCLIENT , void *) STUB
 
diff -u -r -N squid-4.0.2/src/tests/testDiskIO.cc squid-4.0.3/src/tests/testDiskIO.cc
--- squid-4.0.2/src/tests/testDiskIO.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/testDiskIO.cc	2015-11-28 07:30:57.000000000 -0800
@@ -13,7 +13,6 @@
 #include "MemObject.h"
 #include "Store.h"
 #include "StoreFileSystem.h"
-#include "SwapDir.h"
 #include "testDiskIO.h"
 #include "testStoreSupport.h"
 #include "unitTestMain.h"
diff -u -r -N squid-4.0.2/src/tests/testHttp1Parser.cc squid-4.0.3/src/tests/testHttp1Parser.cc
--- squid-4.0.2/src/tests/testHttp1Parser.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/testHttp1Parser.cc	2015-11-28 07:30:57.000000000 -0800
@@ -53,21 +53,65 @@
     AnyP::ProtocolVersion version;
 };
 
+// define SQUID_DEBUG_TESTS to see exactly which test sub-cases fail and where
+#ifdef SQUID_DEBUG_TESTS
+// not optimized for runtime use
+static void
+Replace(SBuf &where, const SBuf &what, const SBuf &with)
+{
+    // prevent infinite loops
+    if (!what.length() || with.find(what) != SBuf::npos)
+        return;
+
+    SBuf::size_type pos = 0;
+    while ((pos = where.find(what, pos)) != SBuf::npos) {
+        SBuf buf = where.substr(0, pos);
+        buf.append(with);
+        buf.append(where.substr(pos+what.length()));
+        where = buf;
+        pos += with.length();
+    }
+}
+
+static SBuf Pretty(SBuf raw)
+{
+    Replace(raw, SBuf("\r"), SBuf("\\r"));
+    Replace(raw, SBuf("\n"), SBuf("\\n"));
+    return raw;
+}
+#endif
+
 static void
 testResults(int line, const SBuf &input, Http1::RequestParser &output, struct resultSet &expect)
 {
-#if WHEN_TEST_DEBUG_IS_NEEDED
-    printf("TEST @%d, in=%u: " SQUIDSBUFPH "\n", line, input.length(), SQUIDSBUFPRINT(input));
+#ifdef SQUID_DEBUG_TESTS
+    std::cerr << "TEST @" << line << ", in=" << Pretty(input) << "\n";
+#endif
+
+    const bool parsed = output.parse(input);
+
+#ifdef SQUID_DEBUG_TESTS
+    if (expect.parsed != parsed)
+        std::cerr << "\tparse-FAILED: " << expect.parsed << "!=" << parsed << "\n";
+    else if (parsed && expect.method != output.method_)
+        std::cerr << "\tmethod-FAILED: " << expect.method << "!=" << output.method_ << "\n";
+    if (expect.status != output.parseStatusCode)
+        std::cerr << "\tscode-FAILED: " << expect.status << "!=" << output.parseStatusCode << "\n";
+    if (expect.suffixSz != output.buf_.length())
+        std::cerr << "\tsuffixSz-FAILED: " << expect.suffixSz << "!=" << output.buf_.length() << "\n";
 #endif
 
     // runs the parse
-    CPPUNIT_ASSERT_EQUAL(expect.parsed, output.parse(input));
+    CPPUNIT_ASSERT_EQUAL(expect.parsed, parsed);
+
+    // if parsing was successful, check easily visible field outputs
+    if (parsed) {
+        CPPUNIT_ASSERT_EQUAL(expect.method, output.method_);
+        if (expect.uri != NULL)
+            CPPUNIT_ASSERT_EQUAL(0, output.uri_.cmp(expect.uri));
+        CPPUNIT_ASSERT_EQUAL(expect.version, output.msgProtocol_);
+    }
 
-    // check easily visible field outputs
-    CPPUNIT_ASSERT_EQUAL(expect.method, output.method_);
-    if (expect.uri != NULL)
-        CPPUNIT_ASSERT_EQUAL(0, output.uri_.cmp(expect.uri));
-    CPPUNIT_ASSERT_EQUAL(expect.version, output.msgProtocol_);
     CPPUNIT_ASSERT_EQUAL(expect.status, output.parseStatusCode);
 
     // check more obscure states
@@ -146,7 +190,7 @@
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
             .status = Http::scBadRequest,
-            .suffixSz = 3,
+            .suffixSz = input.length(),
             .method = HttpRequestMethod(Http::METHOD_POST),
             .uri = NULL,
             .version = AnyP::ProtocolVersion()
@@ -217,9 +261,9 @@
             .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_MIME,
-            .status = Http::scHttpVersionNotSupported,
-            .suffixSz = input.length()-6,
-            .method = HttpRequestMethod(Http::METHOD_GET),
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
+            .method = HttpRequestMethod(),
             .uri = "/",
             .version = AnyP::ProtocolVersion()
         };
@@ -232,8 +276,8 @@
             .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_MIME,
-            .status = Http::scHttpVersionNotSupported,
-            .suffixSz = input.length()-6,
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
             .method = HttpRequestMethod(Http::METHOD_GET),
             .uri = "/",
             .version = AnyP::ProtocolVersion()
@@ -250,8 +294,8 @@
             .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
-            .status = Http::scHttpVersionNotSupported,
-            .suffixSz = input.length()-6,
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
             .method = HttpRequestMethod(Http::METHOD_GET),
             .uri = "/",
             .version = AnyP::ProtocolVersion()
@@ -268,8 +312,8 @@
             .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
-            .status = Http::scHttpVersionNotSupported,
-            .suffixSz = input.length()-6,
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
             .method = HttpRequestMethod(Http::METHOD_GET),
             .uri = "/",
             .version = AnyP::ProtocolVersion()
@@ -286,8 +330,8 @@
             .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
-            .status = Http::scHttpVersionNotSupported,
-            .suffixSz = input.length()-6,
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
             .method = HttpRequestMethod(Http::METHOD_GET),
             .uri = "/",
             .version = AnyP::ProtocolVersion()
@@ -304,8 +348,8 @@
             .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
-            .status = Http::scHttpVersionNotSupported,
-            .suffixSz = input.length()-6,
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
             .method = HttpRequestMethod(Http::METHOD_GET),
             .uri = "/",
             .version = AnyP::ProtocolVersion()
@@ -322,8 +366,8 @@
             .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
-            .status = Http::scHttpVersionNotSupported,
-            .suffixSz = input.length()-6,
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
             .method = HttpRequestMethod(Http::METHOD_GET),
             .uri = "/",
             .version = AnyP::ProtocolVersion()
@@ -340,8 +384,8 @@
             .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
-            .status = Http::scHttpVersionNotSupported,
-            .suffixSz = input.length()-6,
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
             .method = HttpRequestMethod(Http::METHOD_GET),
             .uri = "/",
             .version = AnyP::ProtocolVersion()
@@ -358,8 +402,8 @@
             .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
-            .status = Http::scHttpVersionNotSupported,
-            .suffixSz = input.length()-6,
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
             .method = HttpRequestMethod(Http::METHOD_GET),
             .uri = "/",
             .version = AnyP::ProtocolVersion()
@@ -403,8 +447,8 @@
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
             .status = Http::scBadRequest,
-            .suffixSz = input.length()-4,
-            .method = HttpRequestMethod(Http::METHOD_GET),
+            .suffixSz = input.length(),
+            .method = HttpRequestMethod(),
             .uri = NULL,
             .version = AnyP::ProtocolVersion()
         };
@@ -435,9 +479,9 @@
             .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
-            .status = Http::scHttpVersionNotSupported, // version being "o/ HTTP/1.1"
-            .suffixSz = 13,
-            .method = HttpRequestMethod(Http::METHOD_GET),
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
+            .method = HttpRequestMethod(),
             .uri = NULL,
             .version = AnyP::ProtocolVersion()
         };
@@ -498,10 +542,10 @@
             .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
-            .status = Http::scHttpVersionNotSupported,
-            .suffixSz = 9,
-            .method = HttpRequestMethod(Http::METHOD_GET),
-            .uri = "/",
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
+            .method = HttpRequestMethod(),
+            .uri = NULL,
             .version = AnyP::ProtocolVersion()
         };
         output.clear();
@@ -533,10 +577,10 @@
             .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
-            .status = Http::scHttpVersionNotSupported,
-            .suffixSz = 10,
-            .method = HttpRequestMethod(Http::METHOD_GET),
-            .uri = "/",
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
+            .method = HttpRequestMethod(),
+            .uri = NULL,
             .version = AnyP::ProtocolVersion()
         };
         output.clear();
@@ -552,10 +596,10 @@
             .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
-            .status = Http::scHttpVersionNotSupported,
-            .suffixSz = input.length()-6,
-            .method = HttpRequestMethod(Http::METHOD_GET),
-            .uri = "/",
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
+            .method = HttpRequestMethod(),
+            .uri = NULL,
             .version = AnyP::ProtocolVersion()
         };
         output.clear();
@@ -645,6 +689,7 @@
         input.clear();
     }
 
+#if 0
     // too-long method (over 16 bytes)
     {
         input.append("HELLOSTRANGEWORLD / HTTP/1.1\r\n", 31);
@@ -662,6 +707,7 @@
         testResults(__LINE__, input, output, expect);
         input.clear();
     }
+#endif
 
     // method-only
     {
@@ -882,9 +928,9 @@
         input.clear();
     }
 
-    // binary code in method (invalid)
+    // binary code after method (invalid)
     {
-        input.append("GET\x0A / HTTP/1.1\r\n", 17);
+        input.append("GET\x16 / HTTP/1.1\r\n", 17);
         struct resultSet expect = {
             .parsed = false,
             .needsMore = false,
@@ -900,7 +946,7 @@
         input.clear();
     }
 
-    // binary code NUL! in method (always invalid)
+    // binary code NUL! after method (always invalid)
     {
         input.append("GET\0 / HTTP/1.1\r\n", 17);
         struct resultSet expect = {
@@ -918,20 +964,20 @@
         input.clear();
     }
 
-    // no URL (grammer invalid, ambiguous with RFC 1945 HTTP/0.9 simple-request)
+    // Either an RFC 1945 HTTP/0.9 simple-request for an "HTTP/1.1" URI or
+    // an invalid (no URI) HTTP/1.1 request. We treat this as latter, naturally.
     {
         input.append("GET  HTTP/1.1\r\n", 15);
-        // RFC 7230 tolerance allows sequence of SP to make this ambiguous
         Config.onoff.relaxed_header_parser = 1;
         struct resultSet expect = {
-            .parsed = true,
+            .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
-            .status = Http::scOkay,
-            .suffixSz = 0,
-            .method = HttpRequestMethod(Http::METHOD_GET),
-            .uri = "HTTP/1.1",
-            .version = AnyP::ProtocolVersion(AnyP::PROTO_HTTP,0,9)
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
+            .method = HttpRequestMethod(),
+            .uri = NULL,
+            .version = AnyP::ProtocolVersion()
         };
         output.clear();
         testResults(__LINE__, input, output, expect);
@@ -942,8 +988,8 @@
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
             .status = Http::scBadRequest,
-            .suffixSz = 11,
-            .method = HttpRequestMethod(Http::METHOD_GET),
+            .suffixSz = input.length(),
+            .method = HttpRequestMethod(),
             .uri = NULL,
             .version = AnyP::ProtocolVersion()
         };
@@ -952,18 +998,19 @@
         input.clear();
     }
 
-    // no URL (grammer invalid, ambiguous with RFC 1945 HTTP/0.9 simple-request)
+    // Either an RFC 1945 HTTP/0.9 simple-request for an "HTTP/1.1" URI or
+    // an invalid (no URI) HTTP/1.1 request. We treat this as latter, naturally.
     {
         input.append("GET HTTP/1.1\r\n", 14);
         struct resultSet expect = {
-            .parsed = true,
+            .parsed = false,
             .needsMore = false,
             .parserState = Http1::HTTP_PARSE_DONE,
-            .status = Http::scOkay,
-            .suffixSz = 0,
-            .method = HttpRequestMethod(Http::METHOD_GET),
-            .uri = "HTTP/1.1",
-            .version = AnyP::ProtocolVersion(AnyP::PROTO_HTTP,0,9)
+            .status = Http::scBadRequest,
+            .suffixSz = input.length(),
+            .method = HttpRequestMethod(),
+            .uri = NULL,
+            .version = AnyP::ProtocolVersion()
         };
         output.clear();
         testResults(__LINE__, input, output, expect);
@@ -1036,9 +1083,7 @@
     data.append("\n\n\n\n\n\n\n\n\n\n\n\n", 12);
     SBuf::size_type garbageEnd = data.length();
     data.append("GET ", 4);
-    SBuf::size_type methodEnd = data.length()-1;
     data.append("http://example.com/ ", 20);
-    SBuf::size_type uriEnd = data.length()-1;
     data.append("HTTP/1.1\r\n", 10);
     SBuf::size_type reqLineEnd = data.length() - 1;
     data.append("Host: example.com\r\n\r\n", 21);
@@ -1091,19 +1136,6 @@
             if (pos >= garbageEnd)
                 expect.suffixSz = ioBuf.length();
 
-            // at end of request line expect to see method details
-            if (pos == methodEnd) {
-                expect.suffixSz = 0; // and a checkpoint buffer reset
-                expect.method = HttpRequestMethod(Http::METHOD_GET);
-            }
-
-            // at end of URI strict expects to see method, URI details
-            // relaxed must wait to end of line for whitespace tolerance
-            if (pos == uriEnd && !Config.onoff.relaxed_header_parser) {
-                expect.suffixSz = 0; // and a checkpoint buffer reset
-                expect.uri = "http://example.com/";
-            }
-
             // at end of request line expect to see method, URI, version details
             // and switch to seeking Mime header section
             if (pos == reqLineEnd) {
diff -u -r -N squid-4.0.2/src/tests/testPackableStream.cc squid-4.0.3/src/tests/testPackableStream.cc
--- squid-4.0.2/src/tests/testPackableStream.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/testPackableStream.cc	2015-11-28 07:30:57.000000000 -0800
@@ -31,8 +31,7 @@
 testPackableStream::testGetStream()
 {
     /* Setup a store root so we can create a StoreEntry */
-    StorePointer aStore (new TestStore);
-    Store::Root(aStore);
+    Store::Init();
 
     CapturingStoreEntry * anEntry = new CapturingStoreEntry();
     {
@@ -57,6 +56,6 @@
         CPPUNIT_ASSERT_EQUAL(String("12345677.7 some text   !."), anEntry->_appended_text);
     }
     delete anEntry; // does the unlock()
-    Store::Root(NULL);
+    Store::FreeMemory();
 }
 
diff -u -r -N squid-4.0.2/src/tests/testRock.cc squid-4.0.3/src/tests/testRock.cc
--- squid-4.0.2/src/tests/testRock.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/testRock.cc	2015-11-28 07:30:57.000000000 -0800
@@ -17,9 +17,10 @@
 #include "RequestFlags.h"
 #include "SquidConfig.h"
 #include "Store.h"
+#include "store/Disk.h"
+#include "store/Disks.h"
 #include "StoreFileSystem.h"
 #include "StoreSearch.h"
-#include "SwapDir.h"
 #include "testRock.h"
 #include "testStoreSupport.h"
 #include "unitTestMain.h"
@@ -61,7 +62,7 @@
     if (Ipc::Mem::Segment::BasePath == NULL)
         Ipc::Mem::Segment::BasePath = ".";
 
-    Store::Root(new StoreController);
+    Store::Init();
 
     store = new Rock::SwapDir();
 
@@ -94,7 +95,7 @@
 {
     CPPUNIT_NS::TestFixture::tearDown();
 
-    Store::Root(NULL);
+    Store::FreeMemory();
 
     store = NULL;
 
diff -u -r -N squid-4.0.2/src/tests/testStore.cc squid-4.0.3/src/tests/testStore.cc
--- squid-4.0.2/src/tests/testStore.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/testStore.cc	2015-11-28 07:30:57.000000000 -0800
@@ -75,7 +75,7 @@
 }
 
 StoreSearch *
-TestStore::search(String const url, HttpRequest *)
+TestStore::search()
 {
     return NULL;
 }
@@ -83,41 +83,42 @@
 void
 testStore::testSetRoot()
 {
-    StorePointer aStore(new TestStore);
-    Store::Root(aStore);
+    Store::Controller *aStore(new TestStore);
+    Store::Init(aStore);
 
-    CPPUNIT_ASSERT_EQUAL(&Store::Root(),aStore.getRaw());
-    Store::Root(NULL);
+    CPPUNIT_ASSERT_EQUAL(&Store::Root(), aStore);
+    Store::FreeMemory();
 }
 
 void
 testStore::testUnsetRoot()
 {
-    StorePointer aStore(new TestStore);
-    StorePointer aStore2(new TestStore);
-    Store::Root(aStore);
-    Store::Root(aStore2);
-    CPPUNIT_ASSERT_EQUAL(&Store::Root(),aStore2.getRaw());
-    Store::Root(NULL);
+    Store::Controller *aStore(new TestStore);
+    Store::Controller *aStore2(new TestStore);
+    Store::Init(aStore);
+    Store::FreeMemory();
+    Store::Init(aStore2);
+    CPPUNIT_ASSERT_EQUAL(&Store::Root(),aStore2);
+    Store::FreeMemory();
 }
 
 void
 testStore::testStats()
 {
-    TestStorePointer aStore(new TestStore);
-    Store::Root(aStore.getRaw());
+    TestStore *aStore(new TestStore);
+    Store::Init(aStore);
     CPPUNIT_ASSERT_EQUAL(false, aStore->statsCalled);
     Store::Stats(NullStoreEntry::getInstance());
     CPPUNIT_ASSERT_EQUAL(true, aStore->statsCalled);
-    Store::Root(NULL);
+    Store::FreeMemory();
 }
 
 void
 testStore::testMaxSize()
 {
-    StorePointer aStore(new TestStore);
-    Store::Root(aStore.getRaw());
+    Store::Controller *aStore(new TestStore);
+    Store::Init(aStore);
     CPPUNIT_ASSERT_EQUAL(static_cast<uint64_t>(3), aStore->maxSize());
-    Store::Root(NULL);
+    Store::FreeMemory();
 }
 
diff -u -r -N squid-4.0.2/src/tests/testStoreController.cc squid-4.0.3/src/tests/testStoreController.cc
--- squid-4.0.2/src/tests/testStoreController.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/testStoreController.cc	2015-11-28 07:30:57.000000000 -0800
@@ -11,8 +11,8 @@
 #include "SquidConfig.h"
 #include "SquidTime.h"
 #include "Store.h"
+#include "store/Disks.h"
 #include "StoreSearch.h"
-#include "SwapDir.h"
 #include "testStoreController.h"
 #include "TestSwapDir.h"
 
@@ -29,12 +29,11 @@
 void
 testStoreController::testStats()
 {
+    Store::Init();
     StoreEntry *logEntry = new StoreEntry;
     logEntry->makeMemObject();
     logEntry->mem_obj->setUris("dummy_storeId", NULL, HttpRequestMethod());
     logEntry->store_status = STORE_PENDING;
-    StorePointer aRoot (new StoreController);
-    Store::Root(aRoot);
     TestSwapDirPointer aStore (new TestSwapDir);
     TestSwapDirPointer aStore2 (new TestSwapDir);
     addSwapDir(aStore);
@@ -45,7 +44,7 @@
     free_cachedir(&Config.cacheSwap);
     CPPUNIT_ASSERT_EQUAL(true, aStore->statsCalled);
     CPPUNIT_ASSERT_EQUAL(true, aStore2->statsCalled);
-    Store::Root(NULL);
+    Store::FreeMemory();
 }
 
 static void
@@ -75,20 +74,18 @@
     logEntry->makeMemObject();
     logEntry->mem_obj->setUris("dummy_storeId", NULL, HttpRequestMethod());
     logEntry->store_status = STORE_PENDING;
-    StorePointer aRoot (new StoreController);
-    Store::Root(aRoot);
+    Store::Init();
     TestSwapDirPointer aStore (new TestSwapDir);
     TestSwapDirPointer aStore2 (new TestSwapDir);
     addSwapDir(aStore);
     addSwapDir(aStore2);
     CPPUNIT_ASSERT_EQUAL(static_cast<uint64_t>(6), Store::Root().maxSize());
     free_cachedir(&Config.cacheSwap);
-    Store::Root(NULL);
+    Store::FreeMemory();
 }
 
 static StoreEntry *
-addedEntry(StorePointer hashStore,
-           StorePointer aStore,
+addedEntry(Store::Disk *aStore,
            String name,
            String varySpec,
            String varyKey
@@ -103,7 +100,7 @@
     e->swap_dirn = -1;
 
     for (int i=0; i < Config.cacheSwap.n_configured; ++i) {
-        if (INDEXSD (i) == aStore.getRaw())
+        if (INDEXSD(i) == aStore)
             e->swap_dirn = i;
     }
 
@@ -136,16 +133,15 @@
 testStoreController::testSearch()
 {
     commonInit();
-    StorePointer aRoot (new StoreController());
-    Store::Root(aRoot);
+    Store::Init();
     TestSwapDirPointer aStore (new TestSwapDir);
     TestSwapDirPointer aStore2 (new TestSwapDir);
     addSwapDir(aStore);
     addSwapDir(aStore2);
     Store::Root().init();
-    StoreEntry * entry1 = addedEntry (&Store::Root(), aStore.getRaw(), "name", NULL, NULL);
-    StoreEntry * entry2 = addedEntry (&Store::Root(), aStore2.getRaw(), "name2", NULL, NULL);
-    StoreSearchPointer search = aRoot->search (NULL, NULL); /* search for everything in the store */
+    StoreEntry * entry1 = addedEntry(aStore.getRaw(), "name", NULL, NULL);
+    StoreEntry * entry2 = addedEntry(aStore2.getRaw(), "name2", NULL, NULL);
+    StoreSearchPointer search = Store::Root().search(); /* search for everything in the store */
 
     /* nothing should be immediately available */
     CPPUNIT_ASSERT_EQUAL(false, search->error());
@@ -190,6 +186,6 @@
     CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry *>(NULL), search->currentItem());
     //CPPUNIT_ASSERT_EQUAL(false, search->next());
 
-    Store::Root(NULL);
+    Store::FreeMemory();
 }
 
diff -u -r -N squid-4.0.2/src/tests/testStore.h squid-4.0.3/src/tests/testStore.h
--- squid-4.0.2/src/tests/testStore.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/testStore.h	2015-11-28 07:30:57.000000000 -0800
@@ -10,6 +10,7 @@
 #define SQUID_SRC_TEST_STORE_H
 
 #include "Store.h"
+#include "store/Controlled.h"
 
 #include <cppunit/extensions/HelperMacros.h>
 
@@ -35,11 +36,8 @@
     void testMaxSize();
 };
 
-/* subclass of Store to allow testing of methods without having all the
- * other components live
- */
-
-class TestStore : public Store
+/// allows testing of methods without having all the other components live
+class TestStore : public Store::Controller
 {
 
 public:
@@ -73,9 +71,9 @@
 
     virtual void reference(StoreEntry &) {} /* Reference this object */
 
-    virtual bool dereference(StoreEntry &, bool) { return true; }
+    virtual bool dereference(StoreEntry &) { return true; }
 
-    virtual StoreSearch *search(String const url, HttpRequest *);
+    virtual StoreSearch *search();
 };
 
 typedef RefCount<TestStore> TestStorePointer;
diff -u -r -N squid-4.0.2/src/tests/testStoreHashIndex.cc squid-4.0.3/src/tests/testStoreHashIndex.cc
--- squid-4.0.2/src/tests/testStoreHashIndex.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/testStoreHashIndex.cc	2015-11-28 07:30:57.000000000 -0800
@@ -11,9 +11,8 @@
 #include "SquidConfig.h"
 #include "SquidTime.h"
 #include "Store.h"
-#include "StoreHashIndex.h"
+#include "store/Disks.h"
 #include "StoreSearch.h"
-#include "SwapDir.h"
 #include "testStoreHashIndex.h"
 #include "TestSwapDir.h"
 
@@ -34,8 +33,7 @@
     logEntry->makeMemObject();
     logEntry->mem_obj->setUris("dummy_storeId", NULL, HttpRequestMethod());
     logEntry->store_status = STORE_PENDING;
-    StorePointer aRoot (new StoreHashIndex());
-    Store::Root(aRoot);
+    Store::Init();
     TestSwapDirPointer aStore (new TestSwapDir);
     TestSwapDirPointer aStore2 (new TestSwapDir);
     addSwapDir(aStore);
@@ -46,7 +44,7 @@
     free_cachedir(&Config.cacheSwap);
     CPPUNIT_ASSERT_EQUAL(true, aStore->statsCalled);
     CPPUNIT_ASSERT_EQUAL(true, aStore2->statsCalled);
-    Store::Root(NULL);
+    Store::FreeMemory();
 }
 
 void
@@ -56,20 +54,18 @@
     logEntry->makeMemObject();
     logEntry->mem_obj->setUris("dummy_storeId", NULL, HttpRequestMethod());
     logEntry->store_status = STORE_PENDING;
-    StorePointer aRoot (new StoreHashIndex());
-    Store::Root(aRoot);
+    Store::Init();
     TestSwapDirPointer aStore (new TestSwapDir);
     TestSwapDirPointer aStore2 (new TestSwapDir);
     addSwapDir(aStore);
     addSwapDir(aStore2);
     CPPUNIT_ASSERT_EQUAL(static_cast<uint64_t>(6), Store::Root().maxSize());
     free_cachedir(&Config.cacheSwap);
-    Store::Root(NULL);
+    Store::FreeMemory();
 }
 
 StoreEntry *
-addedEntry(StorePointer hashStore,
-           StorePointer aStore,
+addedEntry(Store::Disk *aStore,
            String name,
            String varySpec,
            String varyKey
@@ -84,7 +80,7 @@
     e->swap_dirn = -1;
 
     for (int i=0; i < Config.cacheSwap.n_configured; ++i) {
-        if (INDEXSD (i) == aStore.getRaw())
+        if (INDEXSD(i) == aStore)
             e->swap_dirn = i;
     }
 
@@ -133,16 +129,15 @@
 testStoreHashIndex::testSearch()
 {
     commonInit();
-    StorePointer aRoot (new StoreHashIndex());
-    Store::Root(aRoot);
+    Store::Init();
     TestSwapDirPointer aStore (new TestSwapDir);
     TestSwapDirPointer aStore2 (new TestSwapDir);
     addSwapDir(aStore);
     addSwapDir(aStore2);
     Store::Root().init();
-    StoreEntry * entry1 = addedEntry (&Store::Root(), aStore.getRaw(), "name", NULL, NULL);
-    StoreEntry * entry2 = addedEntry (&Store::Root(), aStore2.getRaw(), "name2", NULL, NULL);
-    StoreSearchPointer search = aRoot->search (NULL, NULL); /* search for everything in the store */
+    StoreEntry * entry1 = addedEntry(aStore.getRaw(), "name", NULL, NULL);
+    StoreEntry * entry2 = addedEntry(aStore2.getRaw(), "name2", NULL, NULL);
+    StoreSearchPointer search = Store::Root().search(); /* search for everything in the store */
 
     /* nothing should be immediately available */
     CPPUNIT_ASSERT_EQUAL(false, search->error());
@@ -187,6 +182,6 @@
     CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry *>(NULL), search->currentItem());
     //CPPUNIT_ASSERT_EQUAL(false, search->next());
 
-    Store::Root(NULL);
+    Store::FreeMemory();
 }
 
diff -u -r -N squid-4.0.2/src/tests/TestSwapDir.cc squid-4.0.3/src/tests/TestSwapDir.cc
--- squid-4.0.2/src/tests/TestSwapDir.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/TestSwapDir.cc	2015-11-28 07:30:57.000000000 -0800
@@ -70,9 +70,3 @@
 TestSwapDir::parse(int, char*)
 {}
 
-StoreSearch *
-TestSwapDir::search(String, HttpRequest *)
-{
-    return NULL;
-}
-
diff -u -r -N squid-4.0.2/src/tests/TestSwapDir.h squid-4.0.3/src/tests/TestSwapDir.h
--- squid-4.0.2/src/tests/TestSwapDir.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/TestSwapDir.h	2015-11-28 07:30:57.000000000 -0800
@@ -9,7 +9,7 @@
 #ifndef TEST_TESTSWAPDIR
 #define TEST_TESTSWAPDIR
 
-#include "SwapDir.h"
+#include "store/Disk.h"
 
 class TestSwapDir : public SwapDir
 {
@@ -19,20 +19,21 @@
 
     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();
-    virtual void init();
-    virtual bool unlinkdUseful() 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*);
-    virtual StoreSearch *search(String, HttpRequest *);
+    /* Store::Disk API */
+    virtual uint64_t maxSize() const override;
+    virtual uint64_t currentSize() const override;
+    virtual uint64_t currentCount() const override;
+    virtual void stat(StoreEntry &) const override;
+    virtual void swappedOut(const StoreEntry &e) override {}
+    virtual void reconfigure() override;
+    virtual void init() override;
+    virtual bool unlinkdUseful() const override;
+    virtual bool canStore(const StoreEntry &e, int64_t diskSpaceNeeded, int &load) const override;
+    virtual StoreIOState::Pointer createStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *) override;
+    virtual StoreIOState::Pointer openStoreIO(StoreEntry &, StoreIOState::STFNCB *, StoreIOState::STIOCB *, void *) override;
+    virtual void parse(int, char*) override;
+    virtual void markForUnlink(StoreEntry &) override {}
+    virtual void unlink(StoreEntry &) override {}
 };
 
 typedef RefCount<TestSwapDir> TestSwapDirPointer;
diff -u -r -N squid-4.0.2/src/tests/testUfs.cc squid-4.0.3/src/tests/testUfs.cc
--- squid-4.0.2/src/tests/testUfs.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tests/testUfs.cc	2015-11-28 07:30:57.000000000 -0800
@@ -16,7 +16,7 @@
 #include "RequestFlags.h"
 #include "SquidConfig.h"
 #include "Store.h"
-#include "SwapDir.h"
+#include "store/Disks.h"
 #include "testStoreSupport.h"
 #include "testUfs.h"
 #include "unitTestMain.h"
@@ -27,11 +27,11 @@
 
 CPPUNIT_TEST_SUITE_REGISTRATION( testUfs );
 
-typedef RefCount<Fs::Ufs::UFSSwapDir> SwapDirPointer;
+typedef RefCount<Fs::Ufs::UFSSwapDir> MySwapDirPointer;
 extern REMOVALPOLICYCREATE createRemovalPolicy_lru; /* XXX fails with --enable-removal-policies=heap */
 
 static void
-addSwapDir(SwapDirPointer aStore)
+addSwapDir(MySwapDirPointer aStore)
 {
     allocate_new_swapdir(&Config.cacheSwap);
     Config.cacheSwap.swapDirs[Config.cacheSwap.n_configured] = aStore.getRaw();
@@ -92,9 +92,9 @@
     if (0 > system ("rm -rf " TESTDIR))
         throw std::runtime_error("Failed to clean test work directory");
 
-    Store::Root(new StoreController);
+    Store::Init();
 
-    SwapDirPointer aStore (new Fs::Ufs::UFSSwapDir("ufs", "Blocking"));
+    MySwapDirPointer aStore (new Fs::Ufs::UFSSwapDir("ufs", "Blocking"));
 
     aStore->IO = new Fs::Ufs::UFSStrategy(DiskIOModule::Find("Blocking")->createStrategy());
 
@@ -167,7 +167,7 @@
     /* here we cheat: we know that UFSSwapDirs search off disk. If we did an init call to a new
      * swapdir instance, we'd not be testing a clean build.
      */
-    StoreSearchPointer search = aStore->search (NULL, NULL); /* search for everything in the store */
+    StoreSearchPointer search = Store::Root().search(); /* search for everything in the store */
 
     /* nothing should be immediately available */
 #if 0
@@ -201,7 +201,7 @@
     CPPUNIT_ASSERT_EQUAL(true, search->isDone());
     CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry *>(NULL), search->currentItem());
 
-    Store::Root(NULL);
+    Store::FreeMemory();
 
     free_cachedir(&Config.cacheSwap);
 
@@ -229,8 +229,8 @@
     // objects such as "StorePointer aRoot" from being called.
     CPPUNIT_ASSERT(!store_table); // or StoreHashIndex ctor will abort below
 
-    Store::Root(new StoreController);
-    SwapDirPointer aStore (new Fs::Ufs::UFSSwapDir("ufs", "Blocking"));
+    Store::Init();
+    MySwapDirPointer aStore (new Fs::Ufs::UFSSwapDir("ufs", "Blocking"));
     addSwapDir(aStore);
     commonInit();
     Config.replPolicy = new RemovalPolicySettings;
@@ -245,7 +245,7 @@
     safe_free(config_line);
     CPPUNIT_ASSERT(aStore->IO->io != NULL);
 
-    Store::Root(NULL);
+    Store::FreeMemory();
     free_cachedir(&Config.cacheSwap);
     safe_free(Config.replPolicy->type);
     delete Config.replPolicy;
diff -u -r -N squid-4.0.2/src/tools.cc squid-4.0.3/src/tools.cc
--- squid-4.0.2/src/tools.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tools.cc	2015-11-28 07:30:57.000000000 -0800
@@ -12,9 +12,10 @@
 #include "anyp/PortCfg.h"
 #include "base/Subscription.h"
 #include "client_side.h"
-#include "disk.h"
+#include "fatal.h"
 #include "fde.h"
 #include "fqdncache.h"
+#include "fs_io.h"
 #include "htcp.h"
 #include "ICP.h"
 #include "ip/Intercept.h"
@@ -26,7 +27,7 @@
 #include "SquidConfig.h"
 #include "SquidMath.h"
 #include "SquidTime.h"
-#include "SwapDir.h"
+#include "store/Disks.h"
 #include "tools.h"
 #include "wordlist.h"
 
@@ -421,13 +422,6 @@
     if (HttpPortList != NULL && sa.isAnyAddr())
         sa = HttpPortList->s;
 
-#if USE_OPENSSL
-
-    if (HttpsPortList != NULL && sa.isAnyAddr())
-        sa = HttpsPortList->s;
-
-#endif
-
     /*
      * If the first http_port address has a specific address, try a
      * reverse DNS lookup on it.
@@ -1078,16 +1072,6 @@
             return p->s.port();
     }
 
-#if USE_OPENSSL
-    if ((p = HttpsPortList) != NULL) {
-        // skip any special interception ports
-        while (p != NULL && p->flags.isIntercepted())
-            p = p->next;
-        if (p != NULL)
-            return p->s.port();
-    }
-#endif
-
     if ((p = FtpPortList) != NULL) {
         // skip any special interception ports
         while (p != NULL && p->flags.isIntercepted())
diff -u -r -N squid-4.0.2/src/Transients.cc squid-4.0.3/src/Transients.cc
--- squid-4.0.2/src/Transients.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/Transients.cc	2015-11-28 07:30:57.000000000 -0800
@@ -137,25 +137,12 @@
 }
 
 bool
-Transients::dereference(StoreEntry &, bool)
+Transients::dereference(StoreEntry &)
 {
     // no need to keep e in the global store_table for us; we have our own map
     return false;
 }
 
-int
-Transients::callback()
-{
-    return 0;
-}
-
-StoreSearch *
-Transients::search(String const, HttpRequest *)
-{
-    fatal("not implemented");
-    return NULL;
-}
-
 StoreEntry *
 Transients::get(const cache_key *key)
 {
@@ -212,13 +199,6 @@
     return e;
 }
 
-void
-Transients::get(String const, STOREGETCLIENT, void *)
-{
-    // XXX: not needed but Store parent forces us to implement this
-    fatal("Transients::get(key,callback,data) should not be called");
-}
-
 StoreEntry *
 Transients::findCollapsed(const sfileno index)
 {
@@ -355,6 +335,12 @@
 void
 Transients::markForUnlink(StoreEntry &e)
 {
+    unlink(e);
+}
+
+void
+Transients::unlink(StoreEntry &e)
+{
     if (e.mem_obj && e.mem_obj->xitTable.io == MemObject::ioWriting)
         abandon(e);
 }
diff -u -r -N squid-4.0.2/src/Transients.h squid-4.0.3/src/Transients.h
--- squid-4.0.2/src/Transients.h	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/Transients.h	2015-11-28 07:30:57.000000000 -0800
@@ -14,6 +14,7 @@
 #include "ipc/mem/PageStack.h"
 #include "ipc/StoreMap.h"
 #include "Store.h"
+#include "store/Controlled.h"
 #include <vector>
 
 // StoreEntry restoration info not already stored by Ipc::StoreMap
@@ -28,7 +29,7 @@
 /// Keeps track of store entries being delivered to clients that arrived before
 /// those entries were [fully] cached. This shared table is necessary to sync
 /// the entry-writing worker with entry-reading worker(s).
-class Transients: public Store, public Ipc::StoreMapCleaner
+class Transients: public Store::Controlled, public Ipc::StoreMapCleaner
 {
 public:
     Transients();
@@ -56,22 +57,21 @@
     void disconnect(MemObject &mem_obj);
 
     /* 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 getStats(StoreInfoStats &stats) const;
-    virtual void stat(StoreEntry &) const;
-    virtual StoreSearch *search(String const url, HttpRequest *);
-    virtual void reference(StoreEntry &);
-    virtual bool dereference(StoreEntry &, bool);
-    virtual void markForUnlink(StoreEntry &e);
-    virtual void maintain();
+    virtual StoreEntry *get(const cache_key *) override;
+    virtual void create() override {}
+    virtual void init() override;
+    virtual uint64_t maxSize() const override;
+    virtual uint64_t minSize() const override;
+    virtual uint64_t currentSize() const override;
+    virtual uint64_t currentCount() const override;
+    virtual int64_t maxObjectSize() const override;
+    virtual void getStats(StoreInfoStats &stats) const override;
+    virtual void stat(StoreEntry &e) const override;
+    virtual void reference(StoreEntry &e) override;
+    virtual bool dereference(StoreEntry &e) override;
+    virtual void markForUnlink(StoreEntry &e) override;
+    virtual void unlink(StoreEntry &e) override;
+    virtual void maintain() override;
 
     static int64_t EntryLimit();
 
@@ -82,7 +82,7 @@
     bool abandonedAt(const sfileno index) const;
 
     // Ipc::StoreMapCleaner API
-    virtual void noteFreeMapSlice(const Ipc::StoreMapSliceId sliceId);
+    virtual void noteFreeMapSlice(const Ipc::StoreMapSliceId sliceId) override;
 
 private:
     /// shared packed info indexed by Store keys, for creating new StoreEntries
diff -u -r -N squid-4.0.2/src/tunnel.cc squid-4.0.3/src/tunnel.cc
--- squid-4.0.2/src/tunnel.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/tunnel.cc	2015-11-28 07:30:57.000000000 -0800
@@ -242,6 +242,10 @@
         tunnelState->request->hier.stopPeerClock(false);
 
     if (tunnelState->noConnections()) {
+        // ConnStateData pipeline should contain the CONNECT we are performing
+        auto ctx = tunnelState->http->getConn()->pipeline.front();
+        if (ctx != nullptr)
+            ctx->finished();
         delete tunnelState;
         return;
     }
@@ -261,6 +265,10 @@
     tunnelState->client.writer = NULL;
 
     if (tunnelState->noConnections()) {
+        // ConnStateData pipeline should contain the CONNECT we are performing
+        auto ctx = tunnelState->http->getConn()->pipeline.front();
+        if (ctx != nullptr)
+            ctx->finished();
         delete tunnelState;
         return;
     }
@@ -837,11 +845,11 @@
             tunnelState->copy(tunnelState->server.len, tunnelState->server, tunnelState->client, TunnelStateData::WriteClientDone);
         }
 
-        if (tunnelState->http.valid() && tunnelState->http->getConn() && !tunnelState->http->getConn()->in.buf.isEmpty()) {
-            struct ConnStateData::In *in = &tunnelState->http->getConn()->in;
-            debugs(26, DBG_DATA, "Tunnel client PUSH Payload: \n" << in->buf << "\n----------");
-            tunnelState->preReadClientData.append(in->buf);
-            in->buf.consume(); // ConnStateData buffer accounting after the shuffle.
+        if (tunnelState->http.valid() && tunnelState->http->getConn() && !tunnelState->http->getConn()->inBuf.isEmpty()) {
+            SBuf * const in = &tunnelState->http->getConn()->inBuf;
+            debugs(26, DBG_DATA, "Tunnel client PUSH Payload: \n" << *in << "\n----------");
+            tunnelState->preReadClientData.append(*in);
+            in->consume(); // ConnStateData buffer accounting after the shuffle.
         }
         tunnelState->copyClientBytes();
     }
@@ -992,9 +1000,11 @@
     debugs(26, 4, HERE << "determine post-connect handling pathway.");
     if (conn->getPeer()) {
         tunnelState->request->peer_login = conn->getPeer()->login;
+        tunnelState->request->peer_domain = conn->getPeer()->domain;
         tunnelState->request->flags.proxying = !(conn->getPeer()->options.originserver);
     } else {
         tunnelState->request->peer_login = NULL;
+        tunnelState->request->peer_domain = NULL;
         tunnelState->request->flags.proxying = false;
     }
 
@@ -1231,8 +1241,8 @@
 
     ConnStateData *conn;
     if ((conn = request->clientConnectionManager.get())) {
-        ClientSocketContext::Pointer context = conn->getCurrentContext();
-        if (context != NULL && context->http != NULL) {
+        ClientSocketContext::Pointer context = conn->pipeline.front();
+        if (context != nullptr && context->http != nullptr) {
             tunnelState->logTag_ptr = &context->http->logType;
             tunnelState->server.size_ptr = &context->http->out.size;
 
@@ -1263,9 +1273,11 @@
     debugs(26, 4, "determine post-connect handling pathway.");
     if (srvConn->getPeer()) {
         tunnelState->request->peer_login = srvConn->getPeer()->login;
+        tunnelState->request->peer_domain = srvConn->getPeer()->domain;
         tunnelState->request->flags.proxying = !(srvConn->getPeer()->options.originserver);
     } else {
         tunnelState->request->peer_login = NULL;
+        tunnelState->request->peer_domain = NULL;
         tunnelState->request->flags.proxying = false;
     }
 
diff -u -r -N squid-4.0.2/src/unlinkd.cc squid-4.0.3/src/unlinkd.cc
--- squid-4.0.2/src/unlinkd.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/unlinkd.cc	2015-11-28 07:30:57.000000000 -0800
@@ -11,14 +11,15 @@
 #include "squid.h"
 
 #if USE_UNLINKD
-#include "disk.h"
 #include "fd.h"
 #include "fde.h"
+#include "fs_io.h"
 #include "globals.h"
+#include "SquidConfig.h"
 #include "SquidIpc.h"
 #include "SquidTime.h"
 #include "StatCounters.h"
-#include "SwapDir.h"
+#include "store/Disk.h"
 #include "tools.h"
 #include "xusleep.h"
 
diff -u -r -N squid-4.0.2/src/wccp2.cc squid-4.0.3/src/wccp2.cc
--- squid-4.0.2/src/wccp2.cc	2015-11-01 04:17:47.000000000 -0800
+++ squid-4.0.3/src/wccp2.cc	2015-11-28 07:30:57.000000000 -0800
@@ -21,8 +21,8 @@
 #include "ip/Address.h"
 #include "md5.h"
 #include "Parsing.h"
+#include "SquidConfig.h"
 #include "Store.h"
-#include "SwapDir.h"
 
 #if HAVE_NETDB_H
 #include <netdb.h>
diff -u -r -N squid-4.0.2/test-suite/Makefile.in squid-4.0.3/test-suite/Makefile.in
--- squid-4.0.2/test-suite/Makefile.in	2015-11-01 04:19:32.000000000 -0800
+++ squid-4.0.3/test-suite/Makefile.in	2015-11-28 07:32:54.000000000 -0800
@@ -543,6 +543,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -576,7 +577,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/test-suite/squidconf/regressions-3.3 squid-4.0.3/test-suite/squidconf/regressions-3.3
--- squid-4.0.2/test-suite/squidconf/regressions-3.3	1969-12-31 16:00:00.000000000 -0800
+++ squid-4.0.3/test-suite/squidconf/regressions-3.3	2015-11-28 07:30:57.000000000 -0800
@@ -0,0 +1,15 @@
+## Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+##
+## Squid software is distributed under GPLv2+ license and includes
+## contributions from numerous individuals and organizations.
+## Please see the COPYING and CONTRIBUTORS files for details.
+##
+
+#
+# This file contains the list of reported regression cases in 3.3.x config parser
+# it covers:
+#	refresh_pattern
+
+# pct field parser
+refresh_pattern . 1 1000% 60
+refresh_pattern . 1 0% 60
diff -u -r -N squid-4.0.2/test-suite/STUB.h squid-4.0.3/test-suite/STUB.h
--- squid-4.0.2/test-suite/STUB.h	2015-11-01 05:16:09.000000000 -0800
+++ squid-4.0.3/test-suite/STUB.h	2015-11-28 08:16:00.000000000 -0800
@@ -46,17 +46,12 @@
 
 /** macro to stub a function which returns a reference to dynamic
  *  Aborts unit tests requiring its definition with a message about the missing linkage
- *  This macro uses 'new x' to construct a stack vailable for the reference, may leak.
- *  \param x may be the type to define or a constructor call with parameter values
+ *  \param x underlying or "referred to" type
  */
-#define STUB_RETREF(x) { stub_fatal(STUB_API " required"); return new x; }
+#define STUB_RETREF(x) { stub_fatal(STUB_API " required"); return *(x *)nullptr; }
 
-/** macro to stub a function which returns a reference to static
- *  Aborts unit tests requiring its definition with a message about the missing linkage
- *  This macro uses static variable definition to avoid leaks.
- *  \param x  the type name to define
- */
-#define STUB_RETSTATREF(x) { stub_fatal(STUB_API " required"); static x v; return v; }
+/** Same as STUB_RETREF(). TODO: Remove */
+#define STUB_RETSTATREF(x) STUB_RETREF(x)
 
 #endif /* STUB */
 
diff -u -r -N squid-4.0.2/tools/helper-mux/helper-mux.8 squid-4.0.3/tools/helper-mux/helper-mux.8
--- squid-4.0.2/tools/helper-mux/helper-mux.8	2015-11-01 05:16:14.000000000 -0800
+++ squid-4.0.3/tools/helper-mux/helper-mux.8	2015-11-28 08:16:03.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "HELPER-MUX 8"
-.TH HELPER-MUX 8 "2015-11-01" "perl v5.20.2" "User Contributed Perl Documentation"
+.TH HELPER-MUX 8 "2015-11-28" "perl v5.20.2" "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-4.0.2/tools/helper-mux/Makefile.in squid-4.0.3/tools/helper-mux/Makefile.in
--- squid-4.0.2/tools/helper-mux/Makefile.in	2015-11-01 04:19:33.000000000 -0800
+++ squid-4.0.3/tools/helper-mux/Makefile.in	2015-11-28 07:32:55.000000000 -0800
@@ -399,6 +399,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -432,7 +433,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/tools/Makefile.in squid-4.0.3/tools/Makefile.in
--- squid-4.0.2/tools/Makefile.in	2015-11-01 04:19:33.000000000 -0800
+++ squid-4.0.3/tools/Makefile.in	2015-11-28 07:32:55.000000000 -0800
@@ -523,6 +523,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -556,7 +557,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/tools/purge/Makefile.in squid-4.0.3/tools/purge/Makefile.in
--- squid-4.0.2/tools/purge/Makefile.in	2015-11-01 04:19:34.000000000 -0800
+++ squid-4.0.3/tools/purge/Makefile.in	2015-11-28 07:32:56.000000000 -0800
@@ -469,6 +469,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -502,7 +503,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/tools/squidclient/Makefile.in squid-4.0.3/tools/squidclient/Makefile.in
--- squid-4.0.2/tools/squidclient/Makefile.in	2015-11-01 04:19:34.000000000 -0800
+++ squid-4.0.3/tools/squidclient/Makefile.in	2015-11-28 07:32:56.000000000 -0800
@@ -518,6 +518,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -551,7 +552,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/tools/squidclient/STUB.h squid-4.0.3/tools/squidclient/STUB.h
--- squid-4.0.2/tools/squidclient/STUB.h	2015-11-01 05:16:17.000000000 -0800
+++ squid-4.0.3/tools/squidclient/STUB.h	2015-11-28 08:16:05.000000000 -0800
@@ -46,17 +46,12 @@
 
 /** macro to stub a function which returns a reference to dynamic
  *  Aborts unit tests requiring its definition with a message about the missing linkage
- *  This macro uses 'new x' to construct a stack vailable for the reference, may leak.
- *  \param x may be the type to define or a constructor call with parameter values
+ *  \param x underlying or "referred to" type
  */
-#define STUB_RETREF(x) { stub_fatal(STUB_API " required"); return new x; }
+#define STUB_RETREF(x) { stub_fatal(STUB_API " required"); return *(x *)nullptr; }
 
-/** macro to stub a function which returns a reference to static
- *  Aborts unit tests requiring its definition with a message about the missing linkage
- *  This macro uses static variable definition to avoid leaks.
- *  \param x  the type name to define
- */
-#define STUB_RETSTATREF(x) { stub_fatal(STUB_API " required"); static x v; return v; }
+/** Same as STUB_RETREF(). TODO: Remove */
+#define STUB_RETSTATREF(x) STUB_RETREF(x)
 
 #endif /* STUB */
 
diff -u -r -N squid-4.0.2/tools/STUB.h squid-4.0.3/tools/STUB.h
--- squid-4.0.2/tools/STUB.h	2015-11-01 05:16:12.000000000 -0800
+++ squid-4.0.3/tools/STUB.h	2015-11-28 08:16:02.000000000 -0800
@@ -46,17 +46,12 @@
 
 /** macro to stub a function which returns a reference to dynamic
  *  Aborts unit tests requiring its definition with a message about the missing linkage
- *  This macro uses 'new x' to construct a stack vailable for the reference, may leak.
- *  \param x may be the type to define or a constructor call with parameter values
+ *  \param x underlying or "referred to" type
  */
-#define STUB_RETREF(x) { stub_fatal(STUB_API " required"); return new x; }
+#define STUB_RETREF(x) { stub_fatal(STUB_API " required"); return *(x *)nullptr; }
 
-/** macro to stub a function which returns a reference to static
- *  Aborts unit tests requiring its definition with a message about the missing linkage
- *  This macro uses static variable definition to avoid leaks.
- *  \param x  the type name to define
- */
-#define STUB_RETSTATREF(x) { stub_fatal(STUB_API " required"); static x v; return v; }
+/** Same as STUB_RETREF(). TODO: Remove */
+#define STUB_RETSTATREF(x) STUB_RETREF(x)
 
 #endif /* STUB */
 
diff -u -r -N squid-4.0.2/tools/systemd/Makefile.in squid-4.0.3/tools/systemd/Makefile.in
--- squid-4.0.2/tools/systemd/Makefile.in	2015-11-01 04:19:34.000000000 -0800
+++ squid-4.0.3/tools/systemd/Makefile.in	2015-11-28 07:32:56.000000000 -0800
@@ -185,6 +185,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -218,7 +219,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
diff -u -r -N squid-4.0.2/tools/sysvinit/Makefile.in squid-4.0.3/tools/sysvinit/Makefile.in
--- squid-4.0.2/tools/sysvinit/Makefile.in	2015-11-01 04:19:34.000000000 -0800
+++ squid-4.0.3/tools/sysvinit/Makefile.in	2015-11-28 07:32:57.000000000 -0800
@@ -185,6 +185,7 @@
 AR = @AR@
 ARGZ_H = @ARGZ_H@
 AR_R = @AR_R@
+ATOMICLIB = @ATOMICLIB@
 AUTH_LIBS_TO_BUILD = @AUTH_LIBS_TO_BUILD@
 AUTH_MODULES = @AUTH_MODULES@
 AUTOCONF = @AUTOCONF@
@@ -218,7 +219,6 @@
 DEPDIR = @DEPDIR@
 DIGEST_AUTH_HELPERS = @DIGEST_AUTH_HELPERS@
 DISK_LIBS = @DISK_LIBS@
-DISK_LINKOBJS = @DISK_LINKOBJS@
 DISK_MODULES = @DISK_MODULES@
 DLLTOOL = @DLLTOOL@
 DSYMUTIL = @DSYMUTIL@
