Author: Nathan Hoad <nathan@getoffmalawn.com>
Author: Alex Rousskov <measurement-factory.com>
Bug 3389:  Auto-reconnect for tcp access_log.

Major changes:

1. Squid reconnects to TCP logger as needed. Squid keeps trying to connect
forever, using a hard-coded 0.5 second delay between attempts.

2. Squid buffers log records while there is no connectivity. The buffering
limit is configurable.

3. On buffer overflows, Squid worker either dies or starts dropping log
records. The choice is configurable.

4. The tcp logging module honors buffered_logs setting. Old code was flushing
each record.

5. Squid reports changes in logging state to cache.log. Routine connection
retries are not reported at level 1, to reduce noise level.

6. A new access_log configuration format/style has been added. It allows us to
easily add named options such as buffer-size or on-error. The same format can
be used to add module-specific options in the future, but doing so would
require changes to the high-level logging code. All old configuration
formats/styles are still supported.

7. squid.conf buffered_log option documentation now reflects reality. It used
to talk about cache.log but I do not think Squid uses that option for
cache.log maintenance.


Known minor side-effects of these changes:

i) All access_log logs can now be configured to bypass errors because the old
"fatal" flag is now configurable via log-specific on-error option in
squid.conf. The default is still "die". I have not checked whether modules
other than TCP logger honor that flag.

ii) All access_log logs now use 8*MAX_URL (64KB) instead of a 4*MAX_URL (32KB)
or smaller buffer size by default. The ICAP logger was using 2*MAX_URL buffer
size. The TCP logger was using 64KB buffer size before so no change for TCP. I
decided that it is better to raise the default buffering level for some logs
rather than decrease it for other logs, but it is not clear what the best
default is. The buffer size is now configurable via buffer-size so admins can
control it on individual log basis.

iii) Some access_log configuration styles overlap. To resolve ambiguities,
Squid may need to assume that the first logging ACL name (if any) does not
contain '=' and is not equal to an existing logformat name. It is possible to
use 'all' as the first ACL name if these heuristics cause problems.


TODO: We have attempted to solve more TCP logging problems, but it turns out
that correct solutions would require fixing higher-level logging code, not
specific to TCP logger or Bug 3389 scope. Those unsolved problems include:

A. During reconfiguration, all logs are closed and reopened, even if there
have been no changes to their configuration that necessitate such a drastic
action (or no changes at all!). For TCP logger, this means that the old
connection is used to flush remaining buffered records (if any), and the new
connection is used to log new records, possibly at the same time. Nathan wrote
clever code that keeps logging going using the same job/connection. However,
we had to yank that code out because it clashed with higher-level logging
state in subtle ways.

B. During shutdown, all connections are put in the closing state before logs
are told to flush remaining records. For TCP logger, this means that the
remaining buffered records (if any) are lost. The correct fix would probably
require rearranging shutdown sequence AND letting EventLoop run during
shutdown (probably among other things).

C. When logger connectivity is lost, Squid does not notice the problem until
the second TCP socket write (or later). This results in lost records. This is
due to TCP-level buffering. I suspect the only cure for this is adding
logger-to-Squid "I got your records" feedback, which requires changes in the
logging protocol (currently there is no logger-to-Squid communication at all).

# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: rousskov@measurement-factory.com-20130429185049-\
#   65dujc1f0p0e4ikj
# target_branch: http://www.squid-cache.org/bzr/squid3/trunk
# testament_sha1: 6eae957142f725213d92d9cc703f15a6090d6636
# timestamp: 2013-04-29 13:00:37 -0600
# base_revision_id: rousskov@measurement-factory.com-20130326220843-\
#   e8yzu2sprsfmlfee
# 
# Begin patch
=== modified file 'CONTRIBUTORS'
--- CONTRIBUTORS	2013-03-11 00:30:26 +0000
+++ CONTRIBUTORS	2013-04-18 21:43:22 +0000
@@ -39,6 +39,7 @@
     Cord Beermann <cord@cc.fh-lippe.de>
     Daniel O'Callaghan <danny@miriworld.its.unimelb.EDU.AU>
     David Luyer <luyer@ucs.uwa.edu.au>
+    Dhaval Varia
     Diego Woitasen <diegows@xtech.com.ar>
     Dmitry Kurochkin
     Don Hopkins <dhopkins@DonHopkins.com>

=== modified file 'src/Makefile.am'
--- src/Makefile.am	2013-03-18 04:55:51 +0000
+++ src/Makefile.am	2013-04-12 15:45:24 +0000
@@ -1487,6 +1487,7 @@
 	multicast.h \
 	multicast.cc \
 	mem_node.cc \
+	MemBlob.cc \
 	MemBuf.cc \
 	MemObject.cc \
 	mime.h \
@@ -1901,6 +1902,7 @@
 	Mem.h \
 	mem.cc \
 	mem_node.cc \
+	MemBlob.cc \
 	MemBuf.cc \
 	MemObject.cc \
 	mime.h \
@@ -2144,6 +2146,7 @@
 	internal.cc \
 	SquidList.h \
 	SquidList.cc \
+	MemBlob.cc \
 	MemBuf.cc \
 	MemObject.cc \
 	Mem.h \
@@ -2387,6 +2390,7 @@
 	ipcache.cc \
 	SquidList.h \
 	SquidList.cc \
+	MemBlob.cc \
 	MemBuf.cc \
 	MemObject.cc \
 	Mem.h \
@@ -2677,6 +2681,7 @@
 	multicast.h \
 	multicast.cc \
 	mem_node.cc \
+	MemBlob.cc \
 	MemBuf.cc \
 	MemObject.cc \
 	mime.h \
@@ -3647,6 +3652,7 @@
 	Mem.h \
 	mem.cc \
 	mem_node.cc \
+	MemBlob.cc \
 	MemBuf.cc \
 	MemObject.cc \
 	mime.h \

=== modified file 'src/acl/Gadgets.cc'
--- src/acl/Gadgets.cc	2012-09-05 14:49:29 +0000
+++ src/acl/Gadgets.cc	2013-04-16 04:46:27 +0000
@@ -209,7 +209,7 @@
     /* next expect a list of ACL names, possibly preceeded
      * by '!' for negation */
 
-    while ((t = strtok(NULL, w_space))) {
+    while ((t = parser.strtokFile())) {
         ACLList *L = new ACLList;
 
         if (*t == '!') {

=== modified file 'src/adaptation/icap/icap_log.cc'
--- src/adaptation/icap/icap_log.cc	2012-09-06 13:29:14 +0000
+++ src/adaptation/icap/icap_log.cc	2013-04-05 23:50:25 +0000
@@ -17,7 +17,7 @@
         if (log->type == Log::Format::CLF_NONE)
             continue;
 
-        log->logfile = logfileOpen(log->filename, MAX_URL << 1, 1);
+        log->logfile = logfileOpen(log->filename, log->bufferSize, log->fatal);
 
         IcapLogfileStatus = LOG_ENABLE;
     }

=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc	2013-03-26 22:08:43 +0000
+++ src/cache_cf.cc	2013-04-29 18:50:49 +0000
@@ -180,6 +180,7 @@
 static int check_null_access_log(CustomLog *customlog_definitions);
 static void dump_access_log(StoreEntry * entry, const char *name, CustomLog * definitions);
 static void free_access_log(CustomLog ** definitions);
+static bool setLogformat(CustomLog *cl, const char *name, const bool dieWhenMissing);
 
 static void update_maxobjsize(void);
 static void configDoConfigure(void);
@@ -1224,7 +1225,6 @@
 }
 #endif
 
-#if USE_SSL
 /**
  * Parse bytes from a string.
  * Similar to the parseBytesLine function but parses the string value instead of
@@ -1260,7 +1260,6 @@
     if (static_cast<double>(*bptr) * 2 != (m * d / u) * 2)
         self_destruct();
 }
-#endif
 
 static size_t
 parseBytesUnits(const char *unit)
@@ -4024,14 +4023,39 @@
 
 #include "AccessLogEntry.h"
 
+/**
+  We support several access_log configuration styles:
+
+  #1: Deprecated ancient style without an explicit logging module:
+  access_log /var/log/access.log
+
+  #2: The "none" logging module (i.e., no logging [of matching transactions]):
+  access_log none [acl ...]
+
+  #3: Configurable logging module without named options:
+  Logformat or the first ACL name, whichever comes first, may not contain '='.
+  If no explicit logformat name is given, the first ACL name, if any,
+  should not be an existing logformat name or it will be treated as such.
+  access_log module:place [[logformat_name] acl ...]
+
+  #4: Configurable logging module with name=value options such as logformat=x:
+  The first ACL name may not contain '='.
+  access_log module:place [option ...] [acl ...]
+
+*/
 static void
 parse_access_log(CustomLog ** logs)
 {
-    const char *filename, *logdef_name;
-
     CustomLog *cl = (CustomLog *)xcalloc(1, sizeof(*cl));
 
-    if ((filename = strtok(NULL, w_space)) == NULL) {
+    // default buffer size and fatal settings
+    cl->bufferSize = 8*MAX_URL;
+    cl->fatal = true;
+
+    /* determine configuration style */
+
+    const char *filename = strtok(NULL, w_space);
+    if (!filename) {
         self_destruct();
         return;
     }
@@ -4045,12 +4069,72 @@
         return;
     }
 
-    if ((logdef_name = strtok(NULL, w_space)) == NULL)
-        logdef_name = "squid";
-
-    debugs(3, 9, "Log definition name '" << logdef_name << "' file '" << filename << "'");
-
     cl->filename = xstrdup(filename);
+    cl->type = Log::Format::CLF_UNKNOWN;
+
+    const char *token = ConfigParser::strtokFile();
+    if (!token) { // style #1
+        // no options to deal with
+    } else if (!strchr(token, '=')) { // style #3
+        // if logformat name is not recognized,
+        // put back the token; it must be an ACL name
+        if (!setLogformat(cl, token, false))
+            ConfigParser::strtokFileUndo();
+    } else { // style #4
+        do {
+            if (strncasecmp(token, "on-error=", 9) == 0) {
+                if (strncasecmp(token+9, "die", 3) == 0) {
+                    cl->fatal = true;
+                } else if (strncasecmp(token+9, "drop", 4) == 0) {
+                    cl->fatal = false;
+                } else {
+                    debugs(3, DBG_CRITICAL, "Unknown value for on-error '" <<
+                           token << "' expected 'drop' or 'die'");
+                    self_destruct();
+                }
+            } else if (strncasecmp(token, "buffer-size=", 12) == 0) {
+                parseBytesOptionValue(&cl->bufferSize, B_BYTES_STR, token+12);
+            } else if (strncasecmp(token, "logformat=", 10) == 0) {
+                setLogformat(cl, token+10, true);
+            } else if (!strchr(token, '=')) {
+                // put back the token; it must be an ACL name
+                ConfigParser::strtokFileUndo();
+                break; // done with name=value options, now to ACLs
+            } else {
+                debugs(3, DBG_CRITICAL, "Unknown access_log option " << token);
+                self_destruct();
+            }
+        } while ((token = ConfigParser::strtokFile()) != NULL);
+    }
+
+    // set format if it has not been specified explicitly
+    if (cl->type == Log::Format::CLF_UNKNOWN)
+        setLogformat(cl, "squid", true);
+
+    aclParseAclList(LegacyParser, &cl->aclList);
+
+    while (*logs)
+        logs = &(*logs)->next;
+
+    *logs = cl;
+}
+
+/// sets CustomLog::type and, if needed, CustomLog::lf
+/// returns false iff there is no named log format
+static bool
+setLogformat(CustomLog *cl, const char *logdef_name, const bool dieWhenMissing)
+{
+    assert(cl);
+    assert(logdef_name);
+
+    debugs(3, 9, "possible " << cl->filename << " logformat: " << logdef_name);
+
+    if (cl->type != Log::Format::CLF_UNKNOWN) {
+        debugs(3, DBG_CRITICAL, "Second logformat name in one access_log: " <<
+               logdef_name << " " << cl->type << " ? " << Log::Format::CLF_NONE);
+        self_destruct();
+        return false;
+    }
 
     /* look for the definition pointer corresponding to this name */
     Format::Format *lf = Log::TheConfig.logformats;
@@ -4084,18 +4168,15 @@
         cl->type = Log::Format::CLF_USERAGENT;
     } else if (strcmp(logdef_name, "referrer") == 0) {
         cl->type = Log::Format::CLF_REFERER;
-    } else {
+    } else if (dieWhenMissing) {
         debugs(3, DBG_CRITICAL, "Log format '" << logdef_name << "' is not defined");
         self_destruct();
-        return;
+        return false;
+    } else {
+        return false;
     }
 
-    aclParseAclList(LegacyParser, &cl->aclList);
-
-    while (*logs)
-        logs = &(*logs)->next;
-
-    *logs = cl;
+    return true;
 }
 
 static int

=== modified file 'src/cf.data.pre'
--- src/cf.data.pre	2013-03-18 10:10:13 +0000
+++ src/cf.data.pre	2013-04-29 18:50:49 +0000
@@ -3692,16 +3692,47 @@
 LOC: Config.Log.accesslogs
 DEFAULT_IF_NONE: daemon:@DEFAULT_ACCESS_LOG@ squid
 DOC_START
-	These files log client request activities. Has a line every HTTP or
-	ICP request. The format is:
+	Configures whether and how Squid logs HTTP and ICP transactions.
+	If access logging is enabled, a single line is logged for every 
+	matching HTTP or ICP request. The recommended directive formats are:
+
+	access_log <module>:<place> [option ...] [acl acl ...]
+	access_log none [acl acl ...]]
+
+	The following directive format is accepted but may be deprecated:
 	access_log <module>:<place> [<logformat name> [acl acl ...]]
-	access_log none [acl acl ...]]
+
+        In most cases, the first ACL name must not contain the '=' character
+	and should not be equal to an existing logformat name. You can always
+	start with an 'all' ACL to work around those restrictions.
 	
 	Will log to the specified module:place using the specified format (which
 	must be defined in a logformat directive) those entries which match
 	ALL the acl's specified (which must be defined in acl clauses).
 	If no acl is specified, all requests will be logged to this destination.
 	
+	===== Available options for the recommended directive format =====
+
+	logformat=name		Names log line format (either built-in or
+				defined by a logformat directive). Defaults
+				to 'squid'.
+
+	buffer-size=64KB	Defines approximate buffering limit for log
+				records (see buffered_logs).  Squid should not
+				keep more than the specified size and, hence,
+				should flush records before the buffer becomes
+				full to avoid overflows under normal
+				conditions (the exact flushing algorithm is
+				module-dependent though).  The on-error option
+				controls overflow handling.
+
+	on-error=die|drop	Defines action on unrecoverable errors. The
+				'drop' action ignores (i.e., does not log)
+				affected log records. The default 'die' action
+				kills the affected worker. The drop action 
+				support has not been tested for modules other
+				than tcp.
+
 	===== Modules Currently available =====
 	
 	none	Do not log any requests matching these ACL.
@@ -3732,6 +3763,7 @@
 		Place Format:   //host:port
 
 	tcp	To send each log line as text data to a TCP receiver.
+		Lines may be accumulated before sending (see buffered_logs).
 		Place: The destination host name or IP and port.
 		Place Format:   //host:port
 
@@ -4041,11 +4073,18 @@
 DEFAULT: off
 LOC: Config.onoff.buffered_logs
 DOC_START
-	cache.log log file is written with stdio functions, and as such
-	it can be buffered or unbuffered. By default it will be unbuffered.
-	Buffering it can speed up the writing slightly (though you are
-	unlikely to need to worry unless you run with tons of debugging
-	enabled in which case performance will suffer badly anyway..).
+	Whether to write/send access_log records ASAP or accumulate them and
+	then write/send them in larger chunks. Buffering may improve
+	performance because it decreases the number of I/Os. However,
+	buffering increases the delay before log records become available to
+	the final recipient (e.g., a disk file or logging daemon) and,
+	hence, increases the risk of log records loss.
+
+	Note that even when buffered_logs are off, Squid may have to buffer
+	records if it cannot write/send them immediately due to pending I/Os
+	(e.g., the I/O writing the previous log record) or connectivity loss.
+
+	Currently honored by 'daemon' and 'tcp' access_log modules only.
 DOC_END
 
 NAME: netdb_filename

=== modified file 'src/log/CustomLog.h'
--- src/log/CustomLog.h	2012-10-04 00:23:44 +0000
+++ src/log/CustomLog.h	2013-04-12 00:15:02 +0000
@@ -48,6 +48,10 @@
     Logfile *logfile;
     CustomLog *next;
     Log::Format::log_type type;
+    /// how much to buffer before dropping or dying (access_log buffer-size)
+    size_t bufferSize;
+    /// whether unrecoverable errors (e.g., dropping a log record) kill worker
+    bool fatal;
 };
 
 #endif /* SQUID_CUSTOMLOG_H_ */

=== modified file 'src/log/File.cc'
--- src/log/File.cc	2012-09-01 14:38:36 +0000
+++ src/log/File.cc	2013-04-18 21:43:22 +0000
@@ -37,7 +37,7 @@
 #include "log/ModStdio.h"
 #include "log/ModSyslog.h"
 #include "log/ModUdp.h"
-#include "log/ModTcp.h"
+#include "log/TcpLogger.h"
 
 CBDATA_TYPE(Logfile);
 
@@ -62,7 +62,7 @@
         ret = logfile_mod_daemon_open(lf, patharg, bufsz, fatal_flag);
     } else if (strncmp(path, "tcp:", 4) == 0) {
         patharg = path + 4;
-        ret = logfile_mod_tcp_open(lf, patharg, bufsz, fatal_flag);
+        ret = Log::TcpLogger::Open(lf, patharg, bufsz, fatal_flag);
     } else if (strncmp(path, "udp:", 4) == 0) {
         patharg = path + 4;
         ret = logfile_mod_udp_open(lf, patharg, bufsz, fatal_flag);
@@ -72,7 +72,7 @@
         ret = logfile_mod_syslog_open(lf, patharg, bufsz, fatal_flag);
 #endif
     } else {
-        debugs(50, DBG_IMPORTANT, "WARNING: log parameters now start with a module name. Use 'stdio:" << patharg << "'");
+        debugs(50, DBG_IMPORTANT, "WARNING: log name now starts with a module name. Use 'stdio:" << patharg << "'");
         snprintf(lf->path, MAXPATHLEN, "stdio:%s", patharg);
         ret = logfile_mod_stdio_open(lf, patharg, bufsz, fatal_flag);
     }

=== modified file 'src/log/Makefile.am'
--- src/log/Makefile.am	2012-09-06 12:47:15 +0000
+++ src/log/Makefile.am	2013-04-18 21:43:22 +0000
@@ -24,10 +24,10 @@
 	ModStdio.h \
 	ModSyslog.cc \
 	ModSyslog.h \
-	ModTcp.cc \
-	ModTcp.h \
 	ModUdp.cc \
 	ModUdp.h \
 	CustomLog.h \
-	CustomLog.cc
+	CustomLog.cc \
+	TcpLogger.cc \
+	TcpLogger.h
 

=== removed file 'src/log/ModTcp.cc'
--- src/log/ModTcp.cc	2012-09-23 09:04:21 +0000
+++ src/log/ModTcp.cc	1970-01-01 00:00:00 +0000
@@ -1,237 +0,0 @@
-/*
- * DEBUG: section 50    Log file handling
- * AUTHOR: Dhaval Varia
- * Developed based on ModUdp.* by Adrian Chadd
- *
- * SQUID Web Proxy Cache          http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- *  Squid is the result of efforts by numerous individuals from
- *  the Internet community; see the CONTRIBUTORS file for full
- *  details.   Many organizations have provided support for Squid's
- *  development; see the SPONSORS file for full details.  Squid is
- *  Copyrighted (C) 2001 by the Regents of the University of
- *  California; see the COPYRIGHT file for full details.  Squid
- *  incorporates software developed and/or copyrighted by other
- *  sources; see the CREDITS file for full details.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
- *
- */
-
-#include "squid.h"
-#include "comm.h"
-#include "comm/Connection.h"
-#include "disk.h"
-#include "fd.h"
-#include "log/File.h"
-#include "log/ModTcp.h"
-#include "Parsing.h"
-#include "SquidConfig.h"
-
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-/*
- * This logfile TCP module is mostly inspired by a patch by Tim Starling
- * from Wikimedia.
- *
- * It doesn't do any TCP buffering - it'd be quite a bit of work for
- * something which the kernel could be doing for you!
- */
-
-typedef struct {
-    int fd;
-    char *buf;
-    size_t bufsz;
-    int offset;
-} l_tcp_t;
-
-static void
-logfile_mod_tcp_write(Logfile * lf, const char *buf, size_t len)
-{
-    l_tcp_t *ll = (l_tcp_t *) lf->data;
-    ssize_t s;
-    s = write(ll->fd, (char const *) buf, len);
-
-    fd_bytes(ll->fd, s, FD_WRITE);
-#if 0
-    if (s < 0) {
-        debugs(1, DBG_IMPORTANT, "logfile (tcp): got errno (" << errno << "):" << xstrerror());
-    }
-    if (s != len) {
-        debugs(1, DBG_IMPORTANT, "logfile (tcp): len=" << len << ", wrote=" << s);
-    }
-#endif
-
-    /* We don't worry about network errors for now */
-}
-
-static void
-logfile_mod_tcp_flush(Logfile * lf)
-{
-    l_tcp_t *ll = (l_tcp_t *) lf->data;
-    if (0 == ll->offset)
-        return;
-    logfile_mod_tcp_write(lf, ll->buf, (size_t) ll->offset);
-    ll->offset = 0;
-}
-
-static void
-logfile_mod_tcp_writeline(Logfile * lf, const char *buf, size_t len)
-{
-    l_tcp_t *ll = (l_tcp_t *) lf->data;
-
-    if (0 == ll->bufsz) {
-        /* buffering disabled */
-        logfile_mod_tcp_write(lf, buf, len);
-        return;
-    }
-    if (ll->offset > 0 && (ll->offset + len + 4) > ll->bufsz)
-        logfile_mod_tcp_flush(lf);
-
-    if (len > ll->bufsz) {
-        /* too big to fit in buffer */
-        logfile_mod_tcp_write(lf, buf, len);
-        return;
-    }
-    /* buffer it */
-    memcpy(ll->buf + ll->offset, buf, len);
-
-    ll->offset += len;
-
-    assert(ll->offset >= 0);
-
-    assert((size_t) ll->offset <= ll->bufsz);
-}
-
-static void
-logfile_mod_tcp_linestart(Logfile * lf)
-{
-}
-
-static void
-logfile_mod_tcp_lineend(Logfile * lf)
-{
-    logfile_mod_tcp_flush(lf);
-}
-
-static void
-logfile_mod_tcp_rotate(Logfile * lf)
-{
-    return;
-}
-
-static void
-logfile_mod_tcp_close(Logfile * lf)
-{
-    l_tcp_t *ll = (l_tcp_t *) lf->data;
-    lf->f_flush(lf);
-
-    if (ll->fd >= 0)
-        file_close(ll->fd);
-
-    if (ll->buf)
-        xfree(ll->buf);
-
-    xfree(lf->data);
-    lf->data = NULL;
-}
-
-/*
- * This code expects the path to be //host:port
- */
-int
-logfile_mod_tcp_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag)
-{
-    debugs(5, 3, "Tcp Open called");
-    Ip::Address addr;
-
-    char *strAddr;
-
-    lf->f_close = logfile_mod_tcp_close;
-    lf->f_linewrite = logfile_mod_tcp_writeline;
-    lf->f_linestart = logfile_mod_tcp_linestart;
-    lf->f_lineend = logfile_mod_tcp_lineend;
-    lf->f_flush = logfile_mod_tcp_flush;
-    lf->f_rotate = logfile_mod_tcp_rotate;
-
-    l_tcp_t *ll = static_cast<l_tcp_t*>(xcalloc(1, sizeof(*ll)));
-    lf->data = ll;
-
-    if (strncmp(path, "//", 2) == 0) {
-        path += 2;
-    }
-    strAddr = xstrdup(path);
-
-    if (!GetHostWithPort(strAddr, &addr)) {
-        if (lf->flags.fatal) {
-            fatalf("Invalid TCP logging address '%s'\n", lf->path);
-        } else {
-            debugs(50, DBG_IMPORTANT, "Invalid TCP logging address '" << lf->path << "'");
-            safe_free(strAddr);
-            return FALSE;
-        }
-    }
-
-    safe_free(strAddr);
-
-    Ip::Address any_addr;
-    any_addr.SetAnyAddr();
-
-    // require the sending TCP port to be of the right family for the destination address.
-    if (addr.IsIPv4())
-        any_addr.SetIPv4();
-
-    ll->fd = comm_open(SOCK_STREAM, IPPROTO_TCP, any_addr, COMM_NONBLOCKING, "TCP log socket");
-    if (ll->fd < 0) {
-        if (lf->flags.fatal) {
-            fatalf("Unable to open TCP socket for logging\n");
-        } else {
-            debugs(50, DBG_IMPORTANT, "Unable to open TCP socket for logging");
-            return FALSE;
-        }
-    } else if (!comm_connect_addr(ll->fd, &addr)) {
-        if (lf->flags.fatal) {
-            fatalf("Unable to connect to %s for TCP log: %s\n", lf->path, xstrerror());
-        } else {
-            debugs(50, DBG_IMPORTANT, "Unable to connect to " << lf->path << " for TCP log: " << xstrerror());
-            return FALSE;
-        }
-    }
-    if (ll->fd == -1) {
-        if (ENOENT == errno && fatal_flag) {
-            fatalf("Cannot open '%s' because\n"
-                   "\tthe parent directory does not exist.\n"
-                   "\tPlease create the directory.\n", path);
-        } else if (EACCES == errno && fatal_flag) {
-            fatalf("Cannot open '%s' for writing.\n"
-                   "\tThe parent directory must be writeable by the\n"
-                   "\tuser '%s', which is the cache_effective_user\n"
-                   "\tset in squid.conf.", path, Config.effectiveUser);
-        } else {
-            debugs(50, DBG_IMPORTANT, "logfileOpen (TCP): " << lf->path << ": " << xstrerror());
-            return 0;
-        }
-    }
-
-    bufsz = 65536;
-    if (bufsz > 0) {
-        ll->buf = static_cast<char*>(xmalloc(bufsz));
-        ll->bufsz = bufsz;
-    }
-
-    return 1;
-}

=== removed file 'src/log/ModTcp.h'
--- src/log/ModTcp.h	2012-10-04 09:14:06 +0000
+++ src/log/ModTcp.h	1970-01-01 00:00:00 +0000
@@ -1,40 +0,0 @@
-/*
- * DEBUG: section 50    Log file handling
- * AUTHOR: Dhaval Varia
- * Developed based on ModUdp.* by Adrian Chadd
- *
- * SQUID Web Proxy Cache          http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- *  Squid is the result of efforts by numerous individuals from
- *  the Internet community; see the CONTRIBUTORS file for full
- *  details.   Many organizations have provided support for Squid's
- *  development; see the SPONSORS file for full details.  Squid is
- *  Copyrighted (C) 2001 by the Regents of the University of
- *  California; see the COPYRIGHT file for full details.  Squid
- *  incorporates software developed and/or copyrighted by other
- *  sources; see the CREDITS file for full details.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
- *
- */
-#ifndef _SQUID_SRC_LOG_MODTCP_H
-#define _SQUID_SRC_LOG_MODTCP_H
-
-class Logfile;
-
-int logfile_mod_tcp_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag);
-
-#endif /* _SQUID_SRC_LOG_MODTCP_H */

=== added file 'src/log/TcpLogger.cc'
--- src/log/TcpLogger.cc	1970-01-01 00:00:00 +0000
+++ src/log/TcpLogger.cc	2013-04-18 21:43:22 +0000
@@ -0,0 +1,471 @@
+#include "squid.h"
+#include "comm.h"
+#include "comm/ConnOpener.h"
+#include "comm/Connection.h"
+#include "comm/Loops.h"
+#include "comm/Write.h"
+#include "fde.h"
+#include "globals.h" // for shutting_down
+#include "log/CustomLog.h"
+#include "log/File.h"
+#include "log/TcpLogger.h"
+#include "MemBlob.h"
+#include "Parsing.h"
+#include "SquidConfig.h"
+#include "SquidTime.h"
+
+// a single I/O buffer should be large enough to store any access.log record
+const size_t Log::TcpLogger::IoBufSize = 2*MAX_URL;
+// We need at least two buffers because when we write the first buffer,
+// we have to use the second buffer to accumulate new entries.
+const size_t Log::TcpLogger::BufferCapacityMin = 2*Log::TcpLogger::IoBufSize;
+
+#define MY_DEBUG_SECTION 50 /* Log file handling */
+
+
+CBDATA_NAMESPACED_CLASS_INIT(Log, TcpLogger);
+
+Log::TcpLogger::TcpLogger(size_t bufCap, bool dieOnErr, Ip::Address them):
+    AsyncJob("TcpLogger"),
+    dieOnError(dieOnErr),
+    bufferCapacity(bufCap),
+    bufferedSize(0),
+    flushDebt(0),
+    quitOnEmpty(false),
+    reconnectScheduled(false),
+    writeScheduled(false),
+    conn(NULL),
+    remote(them),
+    connectFailures(0),
+    drops(0)
+{
+    if (bufferCapacity < BufferCapacityMin) {
+        debugs(MY_DEBUG_SECTION, DBG_IMPORTANT,
+               "WARNING: tcp:" << remote << " logger configured buffer " <<
+               "size " << bufferCapacity << " is smaller than the " <<
+               BufferCapacityMin << "-byte" << " minimum. " <<
+               "Using the minimum instead.");
+        bufferCapacity = BufferCapacityMin;
+    }
+}
+
+Log::TcpLogger::~TcpLogger()
+{
+    // make sure Comm::Write does not have our buffer pointer
+    assert(!writeScheduled);
+}
+
+void
+Log::TcpLogger::start()
+{
+    connect();
+}
+
+bool
+Log::TcpLogger::doneAll() const
+{
+    debugs(MY_DEBUG_SECTION, 5, "quitOnEmpty: " << quitOnEmpty <<
+           " buffered: " << bufferedSize <<
+           " conn: " << conn << ' ' << connectFailures);
+
+    // we do not quit unless we are told that we may
+    if (!quitOnEmpty)
+        return false;
+
+    /* We were asked to quit after we are done writing buffers. Are we done? */
+
+    // If we have records but are failing to connect, quit. Otherwise, we may
+    // be trying to connect forever due to a [since fixed] misconfiguration!
+    const bool failingToConnect = !conn && connectFailures;
+    if (bufferedSize && !failingToConnect)
+        return false;
+
+    return AsyncJob::doneAll();
+}
+
+void
+Log::TcpLogger::swanSong()
+{
+    disconnect(); // optional: refcounting should close/delete conn eventually
+    AsyncJob::swanSong();
+}
+
+void
+Log::TcpLogger::endGracefully()
+{
+    // job call protection must end our job if we are done logging current bufs
+    assert(inCall != NULL);
+    quitOnEmpty = true;
+    flush();
+}
+
+void
+Log::TcpLogger::flush()
+{
+    flushDebt = bufferedSize;
+    writeIfNeeded();
+}
+
+void
+Log::TcpLogger::logRecord(const char *buf, const size_t len)
+{
+    appendRecord(buf, len);
+    writeIfNeeded();
+}
+
+/// starts writing if and only if it is time to write accumulated records
+void
+Log::TcpLogger::writeIfNeeded()
+{
+    // write if an earlier flush command forces us to write or
+    // if we have filled at least one I/O buffer
+    if (flushDebt > 0 || buffers.size() > 1)
+        writeIfPossible();
+}
+
+/// starts writing if possible
+void Log::TcpLogger::writeIfPossible()
+{
+    debugs(MY_DEBUG_SECTION, 7, "guards: " << (!writeScheduled) <<
+           (bufferedSize > 0) << (conn != NULL) <<
+           (conn != NULL && !fd_table[conn->fd].closing()) << " buffered: " <<
+           bufferedSize << '/' << buffers.size());
+
+    // XXX: Squid shutdown sequence starts closing our connection before
+    // calling LogfileClose, leading to loss of log records during shutdown.
+    if (!writeScheduled && bufferedSize > 0 && conn != NULL &&
+        !fd_table[conn->fd].closing()) {
+        debugs(MY_DEBUG_SECTION, 5, "writing first buffer");
+
+        typedef CommCbMemFunT<TcpLogger, CommIoCbParams> WriteDialer;
+        AsyncCall::Pointer callback = JobCallback(MY_DEBUG_SECTION, 5, WriteDialer, this, Log::TcpLogger::writeDone);
+        const MemBlob::Pointer &buffer = buffers.front();
+        Comm::Write(conn, buffer->mem, buffer->size, callback, NULL);
+        writeScheduled = true;
+    }
+}
+
+/// whether len more bytes can be buffered
+bool
+Log::TcpLogger::canFit(const size_t len) const
+{
+    // TODO: limit reporting frequency in addition to reporting only changes
+
+    if (bufferedSize+len <= bufferCapacity) {
+        if (drops) {
+            // We can get here if a shorter record accidentally fits after we
+            // started dropping records. When that happens, the following
+            // DBG_IMPORTANT message will mislead admin into thinking that
+            // the problem was resolved (for a brief period of time, until
+            // another record comes in and overflows the buffer). It is
+            // difficult to prevent this without also creating the opposite
+            // problem: A huge record that does not fit and is dropped blocks
+            // subsequent regular records from being buffered until we write.
+            debugs(MY_DEBUG_SECTION, DBG_IMPORTANT, "tcp:" << remote <<
+               " logger stops dropping records after " << drops << " drops" <<
+               "; current buffer use: " << (bufferedSize+len) <<
+               " out of " << bufferCapacity << " bytes");
+        }
+        return true;
+    }
+
+    if (!drops || dieOnError) {
+        debugs(MY_DEBUG_SECTION,
+               dieOnError ? DBG_CRITICAL : DBG_IMPORTANT,
+               "tcp:" << remote << " logger " << bufferCapacity << "-byte " <<
+               "buffer overflowed; cannot fit " <<
+               (bufferedSize+len-bufferCapacity) << " bytes");
+    }
+
+    if (dieOnError)
+        fatal("tcp logger buffer overflowed");
+
+    if (!drops) {
+        debugs(MY_DEBUG_SECTION, DBG_IMPORTANT, "tcp:" << remote <<
+               " logger starts dropping records.");
+    }
+
+    return false;
+}
+
+/// buffer a record that might exceed IoBufSize
+void
+Log::TcpLogger::appendRecord(const char *record, const size_t len)
+{
+    // they should not happen, but to be safe, let's protect drop start/stop
+    // monitoring algorithm from empty records (which can never be dropped)
+    if (!len)
+        return;
+
+    if (!canFit(len)) {
+        ++drops;
+        return;
+    }
+
+    drops = 0;
+    // append without spliting buf, unless it exceeds IoBufSize
+    for (size_t off = 0; off < len; off += IoBufSize)
+        appendChunk(record + off, min(len - off, IoBufSize));
+}
+
+/// buffer a record chunk without splitting it across buffers
+void
+Log::TcpLogger::appendChunk(const char *chunk, const size_t len)
+{
+    Must(len <= IoBufSize);
+    // add a buffer if there is not one that can accomodate len bytes
+    bool addBuffer = buffers.empty() ||
+                     (buffers.back()->size+len > IoBufSize);
+    // also add a buffer if there is only one and that one is being written
+    addBuffer = addBuffer || (writeScheduled && buffers.size() == 1);
+
+    if (addBuffer) {
+        buffers.push_back(new MemBlob(IoBufSize));
+        debugs(MY_DEBUG_SECTION, 7, "added buffer #" << buffers.size());
+    }
+
+    Must(!buffers.empty());
+    buffers.back()->append(chunk, len);
+    bufferedSize += len;
+}
+
+/// starts [re]connecting to the remote logger
+void
+Log::TcpLogger::connect()
+{
+    if (shutting_down)
+        return;
+
+    debugs(MY_DEBUG_SECTION, 3, "connecting");
+    Must(!conn);
+
+    Comm::ConnectionPointer futureConn = new Comm::Connection;
+    futureConn->remote = remote;
+    futureConn->local.SetAnyAddr();
+    if (futureConn->remote.IsIPv4())
+        futureConn->local.SetIPv4();
+
+    typedef CommCbMemFunT<TcpLogger, CommConnectCbParams> Dialer;
+    AsyncCall::Pointer call = JobCallback(MY_DEBUG_SECTION, 5, Dialer, this, Log::TcpLogger::connectDone);
+    AsyncJob::Start(new Comm::ConnOpener(futureConn, call, 2));
+}
+
+/// Comm::ConnOpener callback
+void
+Log::TcpLogger::connectDone(const CommConnectCbParams &params)
+{
+    if (params.flag != COMM_OK) {
+        const double delay = 0.5; // seconds
+        if (connectFailures++ % 100 == 0) {
+            debugs(MY_DEBUG_SECTION, DBG_IMPORTANT, "tcp:" << remote <<
+                   " logger connection attempt #" << connectFailures <<
+                   " failed. Will keep trying every " << delay << " seconds.");
+        }
+
+        if (!reconnectScheduled) {
+            reconnectScheduled = true;
+            eventAdd("Log::TcpLogger::DelayedReconnect",
+                     Log::TcpLogger::DelayedReconnect,
+                     new Pointer(this), 0.5, 0, false);
+        }
+    } else {
+        if (connectFailures > 0) {
+            debugs(MY_DEBUG_SECTION, DBG_IMPORTANT, "tcp:" << remote <<
+                   " logger connectivity restored after " <<
+                   (connectFailures+1) << " attempts.");
+            connectFailures = 0;
+        }
+
+        Must(!conn);
+        conn = params.conn;
+
+        Must(!closer);
+        typedef CommCbMemFunT<TcpLogger, CommCloseCbParams> Closer;
+        closer = JobCallback(MY_DEBUG_SECTION, 4, Closer, this, Log::TcpLogger::handleClosure);
+        comm_add_close_handler(conn->fd, closer);
+
+        writeIfNeeded();
+    }
+}
+
+// XXX: Needed until eventAdd() starts accepting Async calls directly.
+/// Log::TcpLogger::delayedReconnect() wrapper.
+void
+Log::TcpLogger::DelayedReconnect(void *data)
+{
+    Pointer *ptr = static_cast<Pointer*>(data);
+    assert(ptr);
+    if (TcpLogger *logger = ptr->valid()) {
+        // Get back inside AsyncJob protections by scheduling another call.
+        typedef NullaryMemFunT<TcpLogger> Dialer;
+        AsyncCall::Pointer call = JobCallback(MY_DEBUG_SECTION, 5, Dialer,
+                                              logger,
+                                              Log::TcpLogger::delayedReconnect);
+        ScheduleCallHere(call);
+    }
+    delete ptr;
+}
+
+/// "sleep a little before trying to connect again" event callback
+void
+Log::TcpLogger::delayedReconnect() {
+    Must(reconnectScheduled);
+    Must(!conn);
+    reconnectScheduled = false;
+    connect();
+}
+
+/// Comm::Write callback
+void
+Log::TcpLogger::writeDone(const CommIoCbParams &io)
+{
+    writeScheduled = false;
+    if (io.flag == COMM_ERR_CLOSING) {
+        debugs(MY_DEBUG_SECTION, 7, "closing");
+        // do nothing here -- our comm_close_handler will be called to clean up
+    } else
+    if (io.flag != COMM_OK) {
+        debugs(MY_DEBUG_SECTION, 2, "write failure: " << xstrerr(io.xerrno));
+        // keep the first buffer (the one we failed to write)
+        disconnect();
+        connect();
+    } else {
+        debugs(MY_DEBUG_SECTION, 5, "write successful");
+
+        Must(!buffers.empty()); // we had a buffer to write
+        const MemBlob::Pointer &written = buffers.front();
+        const size_t writtenSize = static_cast<size_t>(written->size);
+        // and we wrote the whole buffer
+        Must(io.size >= 0 && writtenSize >= 0 && io.size == writtenSize);
+        Must(bufferedSize >= writtenSize);
+        bufferedSize -= writtenSize;
+
+        buffers.pop_front();
+
+        if (flushDebt > io.size)
+            flushDebt -= io.size;
+        else
+            flushDebt = 0; // wrote everything we owed (or more)
+
+        writeIfNeeded();
+    }
+}
+
+/// This is our comm_close_handler. It is called when some external force 
+/// (e.g., reconfigure or shutdown) is closing the connection (rather than us).
+void
+Log::TcpLogger::handleClosure(const CommCloseCbParams &io)
+{
+    assert(inCall != NULL);
+    closer = NULL;
+    conn = NULL;
+    // in all current use cases, we should not try to reconnect
+    mustStop("Log::TcpLogger::handleClosure");
+}
+
+/// close our connection now, without flushing
+void
+Log::TcpLogger::disconnect()
+{
+    if (conn != NULL) {
+        if (closer != NULL) {
+            comm_remove_close_handler(conn->fd, closer);
+            closer = NULL;
+        }
+        conn->close();
+        conn = NULL;
+    }
+}
+
+/// Converts Logfile into a pointer to a valid TcpLogger job or, 
+/// if the logger job has quit, into a nill pointer
+Log::TcpLogger *
+Log::TcpLogger::StillLogging(Logfile *lf)
+{
+    if (Pointer *pptr = static_cast<Pointer*>(lf->data))
+        return pptr->get(); // may be nil
+    return NULL;
+}
+
+void
+Log::TcpLogger::Flush(Logfile * lf)
+{
+    if (TcpLogger *logger = StillLogging(lf))
+        logger->flush();
+}
+
+void
+Log::TcpLogger::WriteLine(Logfile * lf, const char *buf, size_t len)
+{
+    if (TcpLogger *logger = StillLogging(lf))
+        logger->logRecord(buf, len);
+}
+
+void
+Log::TcpLogger::StartLine(Logfile * lf)
+{
+}
+
+void
+Log::TcpLogger::EndLine(Logfile * lf)
+{
+    if (!Config.onoff.buffered_logs)
+        Flush(lf);
+}
+
+void
+Log::TcpLogger::Rotate(Logfile * lf)
+{
+}
+
+void
+Log::TcpLogger::Close(Logfile * lf)
+{
+    if (TcpLogger *logger = StillLogging(lf)) {
+        debugs(50, 3, "Closing " << logger);
+        typedef NullaryMemFunT<TcpLogger> Dialer;
+        Dialer dialer(logger, &Log::TcpLogger::endGracefully);
+        AsyncCall::Pointer call = asyncCall(50, 3, "Log::TcpLogger::endGracefully", dialer);
+        ScheduleCallHere(call);
+    }
+    delete static_cast<Pointer*>(lf->data);
+    lf->data = NULL;
+}
+
+/*
+ * This code expects the path to be //host:port
+ */
+int
+Log::TcpLogger::Open(Logfile * lf, const char *path, size_t bufsz, int fatalFlag)
+{
+    assert(!StillLogging(lf));
+    debugs(5, 3, "Tcp Open called");
+
+    Ip::Address addr;
+
+    if (strncmp(path, "//", 2) == 0)
+        path += 2;
+    char *strAddr = xstrdup(path);
+    if (!GetHostWithPort(strAddr, &addr)) {
+        if (lf->flags.fatal) {
+            fatalf("Invalid TCP logging address '%s'\n", lf->path);
+        } else {
+            debugs(50, DBG_IMPORTANT, "Invalid TCP logging address '" << lf->path << "'");
+            safe_free(strAddr);
+            return FALSE;
+        }
+    }
+    safe_free(strAddr);
+
+    TcpLogger *logger = new TcpLogger(bufsz, fatalFlag, addr);
+    lf->data = new Pointer(logger);
+    lf->f_close = &Close;
+    lf->f_linewrite = &WriteLine;
+    lf->f_linestart = &StartLine;
+    lf->f_lineend = &EndLine;
+    lf->f_flush = &Flush;
+    lf->f_rotate = &Rotate;
+    AsyncJob::Start(logger);
+
+    return 1;
+}

=== added file 'src/log/TcpLogger.h'
--- src/log/TcpLogger.h	1970-01-01 00:00:00 +0000
+++ src/log/TcpLogger.h	2013-04-18 21:43:22 +0000
@@ -0,0 +1,106 @@
+#ifndef _SQUID_SRC_LOG_TCPLOGGER_H
+#define _SQUID_SRC_LOG_TCPLOGGER_H
+
+#include "squid.h"
+#include "base/AsyncJob.h"
+#include "ip/Address.h"
+
+#ifdef HAVE_LIST
+#include <list>
+#endif
+
+class MemBlob;
+typedef RefCount<MemBlob> MemBlobPointer;
+
+namespace Log {
+
+/**
+ * Sends log records to a remote TCP logger at the configured IP:port address.
+ * Handles loss of connectivity, record buffering, and buffer overflows.
+ */
+class TcpLogger : public AsyncJob
+{
+public:
+    typedef CbcPointer<TcpLogger> Pointer;
+
+    // Logfile API. XXX: The only method general logging code needs to know.
+    static int Open(Logfile *lf, const char *path, size_t bufSz, int fatalFlag);
+
+protected:
+    TcpLogger(size_t, bool, Ip::Address);
+    virtual ~TcpLogger();
+
+    /// Called when Squid is reconfiguring (or exiting) to give us a chance to
+    /// flush remaining buffers and end this job w/o loss of data. No new log
+    /// records are expected. Must be used as (or inside) an async job call and
+    /// will result in [eventual] job termination.
+    void endGracefully();
+
+    /// buffers record and possibly writes it to the remote logger
+    void logRecord(const char *buf, size_t len);
+    /// write all currently buffered records ASAP
+    void flush();
+
+    /* AsyncJob API */
+    virtual void start();
+    virtual bool doneAll() const;
+    virtual void swanSong();
+
+private:
+    /* Logfile API. Map c-style Logfile calls to TcpLogger method calls. */
+    static void Flush(Logfile *lf);
+    static void WriteLine(Logfile *lf, const char *buf, size_t len);
+    static void StartLine(Logfile *lf);
+    static void EndLine(Logfile *lf);
+    static void Rotate(Logfile *lf);
+    static void Close(Logfile *lf);
+
+    static TcpLogger *StillLogging(Logfile *lf);
+
+    static void DelayedReconnect(void *data);
+    void delayedReconnect();
+
+    bool canFit(const size_t len) const;
+    void appendRecord(const char *buf, size_t len);
+    void appendChunk(const char *chunk, const size_t len);
+    void writeIfNeeded();
+    void writeIfPossible();
+    void connect();
+    void disconnect();
+
+    /* comm callbacks */
+    void connectDone(const CommConnectCbParams &conn);
+    void writeDone(const CommIoCbParams &io);
+    void handleClosure(const CommCloseCbParams &io);
+
+    static const size_t IoBufSize; ///< fixed I/O buffer size
+    static const size_t BufferCapacityMin; ///< minimum bufferCapacity value
+
+    /// Whether this job must kill Squid on the first unrecoverable error.
+    /// Note that we may be able to recover from a failure to connect, but we
+    /// cannot recover from forgetting (dropping) a record while connecting.
+    bool dieOnError;
+
+    std::list<MemBlobPointer> buffers; ///< I/O buffers
+    size_t bufferCapacity; ///< bufferedSize limit
+    size_t bufferedSize; ///< number of log record bytes stored in RAM now
+    size_t flushDebt; ///< how many record bytes we still need to write ASAP
+
+    bool quitOnEmpty; ///< whether this job should quit when buffers are empty
+    bool reconnectScheduled; ///< we are sleeping before the next connection attempt
+    bool writeScheduled; ///< we are waiting for the latest write() results
+
+    Comm::ConnectionPointer conn; ///< opened connection to the remote logger
+    Ip::Address remote; ///< where the remote logger expects our records
+    AsyncCall::Pointer closer; ///< handles unpexted/external conn closures
+
+    uint64_t connectFailures; ///< number of sequential connection failures
+    uint64_t drops; ///< number of records dropped during the current outage
+
+    CBDATA_CLASS2(TcpLogger);
+};
+
+} // namespace Log
+
+
+#endif /* _SQUID_SRC_LOG_TCPLOGGER_H */

=== modified file 'src/log/access_log.cc'
--- src/log/access_log.cc	2013-03-18 04:55:51 +0000
+++ src/log/access_log.cc	2013-04-05 23:50:25 +0000
@@ -320,7 +320,7 @@
         if (log->type == Log::Format::CLF_NONE)
             continue;
 
-        log->logfile = logfileOpen(log->filename, MAX_URL << 2, 1);
+        log->logfile = logfileOpen(log->filename, log->bufferSize, log->fatal);
 
         LogfileStatus = LOG_ENABLE;
 

# Begin bundle
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
qadWUUmYTAFoQxMsd8+6Of/i7kinChIGTsejQA==

