]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Merged from parent (trunk r11623, v3.2.0.10+).
authorAlex Rousskov <rousskov@measurement-factory.com>
Wed, 10 Aug 2011 15:54:51 +0000 (09:54 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Wed, 10 Aug 2011 15:54:51 +0000 (09:54 -0600)
46 files changed:
1  2 
configure.ac
src/Makefile.am
src/MemObject.cc
src/Server.cc
src/Store.h
src/adaptation/icap/ServiceRep.cc
src/adaptation/icap/ServiceRep.h
src/adaptation/icap/Xaction.cc
src/cache_cf.cc
src/cf.data.depend
src/cf.data.pre
src/client_side.cc
src/client_side_reply.cc
src/comm.cc
src/comm.h
src/format/Format.cc
src/format/Tokens.h
src/fs/coss/store_dir_coss.cc
src/fs/ufs/store_dir_ufs.cc
src/fs/ufs/store_io_ufs.cc
src/globals.h
src/http.cc
src/ipc/Coordinator.cc
src/ipc/Coordinator.h
src/ipc/Forwarder.cc
src/ipc/Kid.h
src/ipc/Makefile.am
src/ipc/Strand.cc
src/log/FormatSquidCustom.cc.THIS
src/log/FormatSquidIcap.cc
src/main.cc
src/mem.cc
src/mgr/FunAction.cc
src/mgr/InfoAction.cc
src/neighbors.cc
src/protos.h
src/stat.cc
src/store.cc
src/store_dir.cc
src/structs.h
src/tests/stub_MemObject.cc
src/tests/stub_store.cc
src/tests/stub_tools.cc
src/tests/testStore.cc
src/tools.cc
src/urn.cc

diff --cc configure.ac
Simple merge
diff --cc src/Makefile.am
index 0305c94022a62b29ad48454737bc6cd9515d906c,19110eba005b171b5fe08103cd8103bdf200ef87..8e10d9681d47fc3cb4dd8d91835c2e0fdfb42090
@@@ -466,9 -467,10 +469,10 @@@ squid_SOURCES = 
        Server.h \
        structs.h \
        swap_log_op.h \
 -      SwapDir.cc \
 -      SwapDir.h \
 +      SwapDir.cc MemStore.cc \
 +      SwapDir.h MemStore.h \
        time.cc \
+       TimeOrTag.h \
        tools.cc \
        tunnel.cc \
        typedefs.h \
@@@ -1367,8 -1360,8 +1383,9 @@@ tests_testCacheManager_LDADD = 
        comm/libcomm.la \
        icmp/libicmp.la icmp/libicmp-core.la \
        log/liblog.la \
+       format/libformat.la \
        $(REPL_OBJS) \
 +      $(DISK_OS_LIBS) \
        $(ADAPTATION_LIBS) \
        $(ESI_LIBS) \
        $(SSL_LIBS) \
@@@ -1457,9 -1451,13 +1475,14 @@@ tests_testDiskIO_SOURCES = 
        tests/stub_HelperChildConfig.cc \
        tests/stub_HttpRequest.cc \
        tests/stub_http.cc \
+       tests/stub_icp.cc \
        tests/stub_internal.cc \
+       tests/stub_ipc.cc \
+       tests/stub_ipcache.cc \
+       tests/stub_libicmp.cc \
 +      tests/stub_MemStore.cc \
        tests/stub_mime.cc \
+       tests/stub_pconn.cc \
        tests/stub_Port.cc \
        tests/stub_store_client.cc \
        tests/stub_store_rebuild.cc \
@@@ -1494,15 -1493,17 +1517,18 @@@ tests_testDiskIO_LDADD = 
        acl/libstate.la \
        $(AUTH_LIBS) \
        libsquid.la \
 -      base/libbase.la \
+       comm/libcomm.la \
        ip/libip.la \
        fs/libfs.la \
+       ipc/libipc.la \
        $(REPL_OBJS) \
        $(DISK_LIBS) \
        $(DISK_OS_LIBS) \
        acl/libapi.la \
        mgr/libmgr.la \
 +      ipc/libipc.la \
 +      base/libbase.la \
+       $(SSL_LIBS) \
        $(top_builddir)/lib/libmisccontainers.la \
        $(top_builddir)/lib/libmiscencoding.la \
        $(top_builddir)/lib/libmiscutil.la \
@@@ -2403,12 -2437,15 +2471,15 @@@ tests_testUfs_SOURCES = 
        tests/testMain.cc \
        tests/testUfs.h \
        tests/stub_cache_manager.cc \
+       tests/stub_client_db.cc \
        tests/stub_HelperChildConfig.cc \
+       tests/stub_icp.cc \
+       tests/stub_ipc.cc \
 +      tests/stub_MemStore.cc \
+       tests/stub_pconn.cc \
        tests/stub_Port.cc \
 -      tests/stub_TypedMsgHdr.cc \
        tests/stub_UdsOp.cc \
        tests/stub_internal.cc \
-       tests/stub_CommIO.cc \
        tests/stub_store_rebuild.cc \
        fd.cc \
        disk.cc \
@@@ -2507,13 -2542,18 +2576,18 @@@ tests_testUfs_LDADD = 
        libsquid.la \
        ip/libip.la \
        fs/libfs.la \
 -      ipc/libipc.la \
        mgr/libmgr.la \
        $(REPL_OBJS) \
+       acl/libacls.la \
+       anyp/libanyp.la \
        $(DISK_LIBS) \
        $(DISK_OS_LIBS) \
 +      acl/libapi.la \
 +      ipc/libipc.la \
+       $(SSL_LIBS) \
+       comm/libcomm.la \
        base/libbase.la \
+       ip/libip.la \
        $(top_builddir)/lib/libmisccontainers.la \
        $(top_builddir)/lib/libmiscencoding.la \
        $(top_builddir)/lib/libmiscutil.la \
@@@ -2740,9 -2678,9 +2814,11 @@@ tests_testCoss_LDADD = 
        $(REPL_OBJS) \
        $(DISK_LIBS) \
        $(DISK_OS_LIBS) \
+       $(COMMON_LIBS) \
+       libsquid.la \
        acl/libapi.la \
 +      ipc/libipc.la \
 +      base/libbase.la \
        $(top_builddir)/lib/libmisccontainers.la \
        $(top_builddir)/lib/libmiscencoding.la \
        $(top_builddir)/lib/libmiscutil.la \
@@@ -3031,7 -2972,7 +3110,8 @@@ tests_testURL_LDADD = 
        icmp/libicmp.la icmp/libicmp-core.la \
        comm/libcomm.la \
        log/liblog.la \
 +      $(DISK_OS_LIBS) \
+       format/libformat.la \
        $(REGEXLIB) \
        $(REPL_OBJS) \
        $(ADAPTATION_LIBS) \
Simple merge
diff --cc src/Server.cc
Simple merge
diff --cc src/Store.h
Simple merge
index 9c2edc38b564e3de50b903a3354caec41c0c5821,2cdbb594541faefb0497c694322bac0f07dc933c..d4028c18e516a43412534d4444200fa1973b8df0
@@@ -108,23 -115,18 +115,23 @@@ Adaptation::Icap::ServiceRep::getConnec
  }
  
  // pools connection if it is reusable or closes it
- void Adaptation::Icap::ServiceRep::putConnection(int fd, bool isReusable, bool sendReset, const char *comment)
 -void Adaptation::Icap::ServiceRep::putConnection(const Comm::ConnectionPointer &conn, bool isReusable, const char *comment)
++void Adaptation::Icap::ServiceRep::putConnection(const Comm::ConnectionPointer &conn, bool isReusable, bool sendReset, const char *comment)
  {
-     Must(fd >= 0);
+     Must(Comm::IsConnOpen(conn));
      // do not pool an idle connection if we owe connections
      if (isReusable && excessConnections() == 0) {
          debugs(93, 3, HERE << "pushing pconn" << comment);
-         commSetTimeout(fd, -1, NULL, NULL);
-         Ip::Address anyAddr;
-         theIdleConns.push(fd, cfg().host.termedBuf(), cfg().port, NULL, anyAddr);
+         commUnsetConnTimeout(conn);
+         theIdleConns->push(conn);
      } else {
 -        debugs(93, 3, HERE << "closing pconn" << comment);
 -        // comm_close will clear timeout
 -        conn->close();
 +        debugs(93, 3, HERE << (sendReset ? "RST" : "FIN") << "-closing " <<
 +               comment);
-         // comm_close will clear timeout
++        // comm_close called from Connection::close will clear timeout
++        // TODO: add "bool sendReset = false" to Connection::close()?
 +        if (sendReset)
-             comm_reset_close(fd);
++            comm_reset_close(conn);
 +        else
-             comm_close(fd);
++            conn->close();
      }
  
      Must(theBusyConns > 0);
index 1985ced4facc091f9001a4008ad35203e1afd011,f7c342469fa39ae1938da3f79f9a70c0f4f1a789..8bf64db33b7e1bf4258b3f8b6504fc64d1048749
@@@ -112,9 -110,10 +112,10 @@@ public
      bool wantsPreview(const String &urlPath, size_t &wantedSize) const;
      bool allows204() const;
      bool allows206() const;
-     int getConnection(bool isRetriable, bool &isReused);
-     void putConnection(int fd, bool isReusable, bool sendReset, const char *comment);
-     void noteConnectionUse(int fd);
+     Comm::ConnectionPointer getConnection(bool isRetriable, bool &isReused);
 -    void putConnection(const Comm::ConnectionPointer &conn, bool isReusable, const char *comment);
++    void putConnection(const Comm::ConnectionPointer &conn, bool isReusable, bool sendReset, const char *comment);
+     void noteConnectionUse(const Comm::ConnectionPointer &conn);
+     void noteConnectionFailed(const char *comment);
  
      void noteFailure(); // called by transactions to report service failure
  
Simple merge
diff --cc src/cache_cf.cc
Simple merge
Simple merge
diff --cc src/cf.data.pre
Simple merge
index 72af0333b9711f95587e0351ab7a359d03033761,4f62f0a8756006ddae5665a07cab7b514ae06d7d..574c99d7ad341476ec58430c825dd62d3edac9d6
@@@ -1811,16 -1816,14 +1816,14 @@@ ClientSocketContext::initiateClose(cons
  }
  
  void
- ClientSocketContext::writeComplete(int aFileDescriptor, char *bufnotused, size_t size, comm_err_t errflag)
+ ClientSocketContext::writeComplete(const Comm::ConnectionPointer &conn, char *bufnotused, size_t size, comm_err_t errflag)
  {
 -    StoreEntry *entry = http->storeEntry();
 +    const StoreEntry *entry = http->storeEntry();
      http->out.size += size;
-     assert(aFileDescriptor > -1);
-     debugs(33, 5, "clientWriteComplete: FD " << aFileDescriptor << ", sz " << size <<
+     debugs(33, 5, HERE << conn << ", sz " << size <<
             ", err " << errflag << ", off " << http->out.size << ", len " <<
 -           entry ? entry->objectLen() : 0);
 +           (entry ? entry->objectLen() : 0));
      clientUpdateSocketStats(http->logType, size);
-     assert (this->fd() == aFileDescriptor);
  
      /* Bail out quickly on COMM_ERR_CLOSING - close handlers will tidy up */
  
Simple merge
diff --cc src/comm.cc
index 8142109d9563223e8068cbc87067afb08759a040,a6ab545de771c507acf9ee3ffc0db90261f67d16..47c12cb115b7bd92f3ba048a41b2a73c23b78013
@@@ -1367,9 -1021,22 +1021,22 @@@ comm_lingering_close(int fd
   * closed, TCP generates a RESET
   */
  void
- comm_reset_close(int fd)
 -comm_reset_close(Comm::ConnectionPointer &conn)
++comm_reset_close(const Comm::ConnectionPointer &conn)
  {
+     struct linger L;
+     L.l_onoff = 1;
+     L.l_linger = 0;
+     if (setsockopt(conn->fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0)
+         debugs(50, DBG_CRITICAL, "ERROR: Closing " << conn << " with TCP RST: " << xstrerror());
+     conn->close();
+ }
  
+ // Legacy close function.
+ void
+ old_comm_reset_close(int fd)
+ {
      struct linger L;
      L.l_onoff = 1;
      L.l_linger = 0;
diff --cc src/comm.h
index fb206c93de3a944940feb47c0321b8c9d7818480,322d22ec93d10b291bce89c620799204b5d8d602..899ea0e8a85df70b0c9104d2216f348abbe3c22a
@@@ -24,8 -17,9 +17,9 @@@ SQUIDCEXTERN int commUnsetNonBlocking(i
  SQUIDCEXTERN void commSetCloseOnExec(int fd);
  SQUIDCEXTERN void commSetTcpKeepalive(int fd, int idle, int interval, int timeout);
  extern void _comm_close(int fd, char const *file, int line);
- #define comm_close(fd) (_comm_close((fd), __FILE__, __LINE__))
- SQUIDCEXTERN void comm_reset_close(int fd);
+ #define comm_close(x) (_comm_close((x), __FILE__, __LINE__))
+ SQUIDCEXTERN void old_comm_reset_close(int fd);
 -SQUIDCEXTERN void comm_reset_close(Comm::ConnectionPointer &conn);
++SQUIDCEXTERN void comm_reset_close(const Comm::ConnectionPointer &conn);
  #if LINGERING_CLOSE
  SQUIDCEXTERN void comm_lingering_close(int fd);
  #endif
index 0000000000000000000000000000000000000000,8e611520cbc04336815d00dcb2b12d3a52574c6b..1ac21dd742d659f2145d43c6a764afbabbf6ed30
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1067 +1,1074 @@@
 -            if (fmt->width) {
+ #include "config.h"
+ #include "AccessLogEntry.h"
+ #include "comm/Connection.h"
+ #include "err_detail_type.h"
+ #include "errorpage.h"
+ #include "format/Format.h"
+ #include "format/Quoting.h"
+ #include "format/Tokens.h"
+ #include "HttpRequest.h"
+ #include "MemBuf.h"
+ #include "rfc1738.h"
+ #include "SquidTime.h"
+ #include "Store.h"
+ Format::Format::Format(const char *n) :
+         format(NULL),
+         next(NULL)
+ {
+     name = xstrdup(n);
+ }
+ Format::Format::~Format()
+ {
+     // erase the list without consuming stack space
+     while (next) {
+         // unlink the next entry for deletion
+         Format *temp = next;
+         next = temp->next;
+         temp->next = NULL;
+         delete temp;
+     }
+     // remove locals
+     xfree(name);
+     delete format;
+ }
+ bool
+ Format::Format::parse(char *def)
+ {
+     char *cur, *eos;
+     Token *new_lt, *last_lt;
+     enum Quoting quote = LOG_QUOTE_NONE;
+     debugs(46, 2, HERE << "got definition '" << def << "'");
+     if (format) {
+         debugs(46, DBG_IMPORTANT, "WARNING: existing format for '" << name << " " << def << "'");
+         return false;
+     }
+     /* very inefficent parser, but who cares, this needs to be simple */
+     /* First off, let's tokenize, we'll optimize in a second pass.
+      * A token can either be a %-prefixed sequence (usually a dynamic
+      * token but it can be an escaped sequence), or a string. */
+     cur = def;
+     eos = def + strlen(def);
+     format = new_lt = last_lt = new Token;
+     cur += new_lt->parse(cur, &quote);
+     while (cur < eos) {
+         new_lt = new Token;
+         last_lt->next = new_lt;
+         last_lt = new_lt;
+         cur += new_lt->parse(cur, &quote);
+     }
+     return true;
+ }
+ void
+ Format::Format::dump(StoreEntry * entry, const char *name)
+ {
+     debugs(46, 4, HERE);
+     // loop rather than recursing to conserve stack space.
+     for (Format *format = this; format; format = format->next) {
+         debugs(46, 3, HERE << "Dumping format definition for " << format->name);
+         storeAppendPrintf(entry, "format %s ", format->name);
+         for (Token *t = format->format; t; t = t->next) {
+             if (t->type == LFT_STRING)
+                 storeAppendPrintf(entry, "%s", t->data.string);
+             else {
+                 char argbuf[256];
+                 char *arg = NULL;
+                 ByteCode_t type = t->type;
+                 switch (type) {
+                     /* special cases */
+                 case LFT_STRING:
+                     break;
+ #if USE_ADAPTATION
+                 case LFT_ADAPTATION_LAST_HEADER_ELEM:
+ #endif
+ #if ICAP_CLIENT
+                 case LFT_ICAP_REQ_HEADER_ELEM:
+                 case LFT_ICAP_REP_HEADER_ELEM:
+ #endif
+                 case LFT_REQUEST_HEADER_ELEM:
+                 case LFT_ADAPTED_REQUEST_HEADER_ELEM:
+                 case LFT_REPLY_HEADER_ELEM:
+                     if (t->data.header.separator != ',')
+                         snprintf(argbuf, sizeof(argbuf), "%s:%c%s", t->data.header.header, t->data.header.separator, t->data.header.element);
+                     else
+                         snprintf(argbuf, sizeof(argbuf), "%s:%s", t->data.header.header, t->data.header.element);
+                     arg = argbuf;
+                     switch (type) {
+                     case LFT_REQUEST_HEADER_ELEM:
+                         type = LFT_REQUEST_HEADER_ELEM; // XXX: remove _ELEM?
+                         break;
+                     case LFT_ADAPTED_REQUEST_HEADER_ELEM:
+                         type = LFT_ADAPTED_REQUEST_HEADER_ELEM; // XXX: remove _ELEM?
+                         break;
+                     case LFT_REPLY_HEADER_ELEM:
+                         type = LFT_REPLY_HEADER_ELEM; // XXX: remove _ELEM?
+                         break;
+ #if USE_ADAPTATION
+                     case LFT_ADAPTATION_LAST_HEADER_ELEM:
+                         type = LFT_ADAPTATION_LAST_HEADER;
+                         break;
+ #endif
+ #if ICAP_CLIENT
+                     case LFT_ICAP_REQ_HEADER_ELEM:
+                         type = LFT_ICAP_REQ_HEADER;
+                         break;
+                     case LFT_ICAP_REP_HEADER_ELEM:
+                         type = LFT_ICAP_REP_HEADER;
+                         break;
+ #endif
+                     default:
+                         break;
+                     }
+                     break;
+                 case LFT_REQUEST_ALL_HEADERS:
+                 case LFT_ADAPTED_REQUEST_ALL_HEADERS:
+                 case LFT_REPLY_ALL_HEADERS:
+ #if USE_ADAPTATION
+                 case LFT_ADAPTATION_LAST_ALL_HEADERS:
+ #endif
+ #if ICAP_CLIENT
+                 case LFT_ICAP_REQ_ALL_HEADERS:
+                 case LFT_ICAP_REP_ALL_HEADERS:
+ #endif
+                     switch (type) {
+                     case LFT_REQUEST_ALL_HEADERS:
+                         type = LFT_REQUEST_HEADER;
+                         break;
+                     case LFT_ADAPTED_REQUEST_ALL_HEADERS:
+                         type = LFT_ADAPTED_REQUEST_HEADER;
+                         break;
+                     case LFT_REPLY_ALL_HEADERS:
+                         type = LFT_REPLY_HEADER;
+                         break;
+ #if USE_ADAPTATION
+                     case LFT_ADAPTATION_LAST_ALL_HEADERS:
+                         type = LFT_ADAPTATION_LAST_HEADER;
+                         break;
+ #endif
+ #if ICAP_CLIENT
+                     case LFT_ICAP_REQ_ALL_HEADERS:
+                         type = LFT_ICAP_REQ_HEADER;
+                         break;
+                     case LFT_ICAP_REP_ALL_HEADERS:
+                         type = LFT_ICAP_REP_HEADER;
+                         break;
+ #endif
+                     default:
+                         break;
+                     }
+                     break;
+                 default:
+                     if (t->data.string)
+                         arg = t->data.string;
+                     break;
+                 }
+                 entry->append("%", 1);
+                 switch (t->quote) {
+                 case LOG_QUOTE_QUOTES:
+                     entry->append("\"", 1);
+                     break;
+                 case LOG_QUOTE_MIMEBLOB:
+                     entry->append("[", 1);
+                     break;
+                 case LOG_QUOTE_URL:
+                     entry->append("#", 1);
+                     break;
+                 case LOG_QUOTE_RAW:
+                     entry->append("'", 1);
+                     break;
+                 case LOG_QUOTE_NONE:
+                     break;
+                 }
+                 if (t->left)
+                     entry->append("-", 1);
+                 if (t->zero)
+                     entry->append("0", 1);
+                 if (t->width)
+                     storeAppendPrintf(entry, "%d", (int) t->width);
+                 if (t->precision)
+                     storeAppendPrintf(entry, ".%d", (int) t->precision);
+                 if (arg)
+                     storeAppendPrintf(entry, "{%s}", arg);
+                 for (struct TokenTableEntry *te = TokenTable; te->config != NULL; te++) {
+                     if (te->token_type == type) {
+                         storeAppendPrintf(entry, "%s", te->config);
+                         break;
+                     }
+                 }
+                 if (t->space)
+                     entry->append(" ", 1);
+             }
+         }
+         entry->append("\n", 1);
+     }
+ }
+ static void
+ log_quoted_string(const char *str, char *out)
+ {
+     char *p = out;
+     while (*str) {
+         int l = strcspn(str, "\"\\\r\n\t");
+         memcpy(p, str, l);
+         str += l;
+         p += l;
+         switch (*str) {
+         case '\0':
+             break;
+         case '\r':
+             *p++ = '\\';
+             *p++ = 'r';
+             str++;
+             break;
+         case '\n':
+             *p++ = '\\';
+             *p++ = 'n';
+             str++;
+             break;
+         case '\t':
+             *p++ = '\\';
+             *p++ = 't';
+             str++;
+             break;
+         default:
+             *p++ = '\\';
+             *p++ = *str;
+             str++;
+             break;
+         }
+     }
+     *p++ = '\0';
+ }
+ void
+ Format::Format::assemble(MemBuf &mb, AccessLogEntry *al, int logSequenceNumber) const
+ {
+     char tmp[1024];
+     String sb;
+     for (Token *fmt = format; fmt != NULL; fmt = fmt->next) { /* for each token */
+         const char *out = NULL;
+         int quote = 0;
+         long int outint = 0;
+         int doint = 0;
+         int dofree = 0;
+         int64_t outoff = 0;
+         int dooff = 0;
+         switch (fmt->type) {
+         case LFT_NONE:
+             out = "";
+             break;
+         case LFT_STRING:
+             out = fmt->data.string;
+             break;
+         case LFT_CLIENT_IP_ADDRESS:
+             if (al->cache.caddr.IsNoAddr()) // e.g., ICAP OPTIONS lack client
+                 out = "-";
+             else
+                 out = al->cache.caddr.NtoA(tmp,1024);
+             break;
+         case LFT_CLIENT_FQDN:
+             if (al->cache.caddr.IsAnyAddr()) // e.g., ICAP OPTIONS lack client
+                 out = "-";
+             else
+                 out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
+             if (!out) {
+                 out = al->cache.caddr.NtoA(tmp,1024);
+             }
+             break;
+         case LFT_CLIENT_PORT:
+             if (al->request) {
+                 outint = al->request->client_addr.GetPort();
+                 doint = 1;
+             }
+             break;
+ #if USE_SQUID_EUI
+         case LFT_CLIENT_EUI:
+             // TODO make the ACL checklist have a direct link to any TCP details.
+             if (al->request && al->request->clientConnectionManager.valid() && al->request->clientConnectionManager->clientConnection != NULL) {
+                 if (al->request->clientConnectionManager->clientConnection->remote.IsIPv4())
+                     al->request->clientConnectionManager->clientConnection->remoteEui48.encode(tmp, 1024);
+                 else
+                     al->request->clientConnectionManager->clientConnection->remoteEui64.encode(tmp, 1024);
+                 out = tmp;
+             }
+             break;
+ #endif
+             /* case LFT_SERVER_IP_ADDRESS: */
+         case LFT_SERVER_IP_OR_PEER_NAME:
+             out = al->hier.host;
+             break;
+             /* case LFT_SERVER_PORT: */
+         case LFT_LOCAL_IP:
+             if (al->request) {
+                 out = al->request->my_addr.NtoA(tmp,sizeof(tmp));
+             }
+             break;
+         case LFT_LOCAL_PORT:
+             if (al->request) {
+                 outint = al->request->my_addr.GetPort();
+                 doint = 1;
+             }
+             break;
+             // the fmt->type can not be LFT_PEER_LOCAL_IP_OLD_27
+             // but compiler complains if ommited
+         case LFT_PEER_LOCAL_IP_OLD_27:
+         case LFT_PEER_LOCAL_IP:
+             if (!al->hier.peer_local_addr.IsAnyAddr()) {
+                 out = al->hier.peer_local_addr.NtoA(tmp,sizeof(tmp));
+             }
+             break;
+         case LFT_PEER_LOCAL_PORT:
+             if ((outint = al->hier.peer_local_addr.GetPort())) {
+                 doint = 1;
+             }
+             break;
+         case LFT_TIME_SECONDS_SINCE_EPOCH:
+             // some platforms store time in 32-bit, some 64-bit...
+             outoff = static_cast<int64_t>(current_time.tv_sec);
+             dooff = 1;
+             break;
+         case LFT_TIME_SUBSECOND:
+             outint = current_time.tv_usec / fmt->divisor;
+             doint = 1;
+             break;
+         case LFT_TIME_LOCALTIME:
+         case LFT_TIME_GMT: {
+             const char *spec;
+             struct tm *t;
+             spec = fmt->data.timespec;
+             if (fmt->type == LFT_TIME_LOCALTIME) {
+                 if (!spec)
+                     spec = "%d/%b/%Y:%H:%M:%S %z";
+                 t = localtime(&squid_curtime);
+             } else {
+                 if (!spec)
+                     spec = "%d/%b/%Y:%H:%M:%S";
+                 t = gmtime(&squid_curtime);
+             }
+             strftime(tmp, sizeof(tmp), spec, t);
+             out = tmp;
+         }
+         break;
+         case LFT_TIME_TO_HANDLE_REQUEST:
+             outint = al->cache.msec;
+             doint = 1;
+             break;
+         case LFT_PEER_RESPONSE_TIME:
+             if (al->hier.peer_response_time < 0) {
+                 out = "-";
+             } else {
+                 outoff = al->hier.peer_response_time;
+                 dooff = 1;
+             }
+             break;
+         case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME:
+             if (al->hier.total_response_time < 0) {
+                 out = "-";
+             } else {
+                 outoff = al->hier.total_response_time;
+                 dooff = 1;
+             }
+             break;
+         case LFT_DNS_WAIT_TIME:
+             if (al->request && al->request->dnsWait >= 0) {
+                 outint = al->request->dnsWait;
+                 doint = 1;
+             }
+             break;
+         case LFT_REQUEST_HEADER:
+             if (al->request)
+                 sb = al->request->header.getByName(fmt->data.header.header);
+             out = sb.termedBuf();
+             quote = 1;
+             break;
+         case LFT_ADAPTED_REQUEST_HEADER:
+             if (al->request)
+                 sb = al->adapted_request->header.getByName(fmt->data.header.header);
+             out = sb.termedBuf();
+             quote = 1;
+             break;
+         case LFT_REPLY_HEADER:
+             if (al->reply)
+                 sb = al->reply->header.getByName(fmt->data.header.header);
+             out = sb.termedBuf();
+             quote = 1;
+             break;
+ #if USE_ADAPTATION
+         case LTF_ADAPTATION_SUM_XACT_TIMES:
+             if (al->request) {
+                 Adaptation::History::Pointer ah = al->request->adaptHistory();
+                 if (ah != NULL)
+                     ah->sumLogString(fmt->data.string, sb);
+                 out = sb.termedBuf();
+             }
+             break;
+         case LTF_ADAPTATION_ALL_XACT_TIMES:
+             if (al->request) {
+                 Adaptation::History::Pointer ah = al->request->adaptHistory();
+                 if (ah != NULL)
+                     ah->allLogString(fmt->data.string, sb);
+                 out = sb.termedBuf();
+             }
+             break;
+         case LFT_ADAPTATION_LAST_HEADER:
+             if (al->request) {
+                 const Adaptation::History::Pointer ah = al->request->adaptHistory();
+                 if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here
+                     sb = ah->allMeta.getByName(fmt->data.header.header);
+             }
+             // XXX: here and elsewhere: move such code inside the if guard
+             out = sb.termedBuf();
+             quote = 1;
+             break;
+         case LFT_ADAPTATION_LAST_HEADER_ELEM:
+             if (al->request) {
+                 const Adaptation::History::Pointer ah = al->request->adaptHistory();
+                 if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here
+                     sb = ah->allMeta.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+             }
+             out = sb.termedBuf();
+             quote = 1;
+             break;
+         case LFT_ADAPTATION_LAST_ALL_HEADERS:
+             out = al->adapt.last_meta;
+             quote = 1;
+             break;
+ #endif
+ #if ICAP_CLIENT
+         case LFT_ICAP_ADDR:
+             if (!out)
+                 out = al->icap.hostAddr.NtoA(tmp,1024);
+             break;
+         case LFT_ICAP_SERV_NAME:
+             out = al->icap.serviceName.termedBuf();
+             break;
+         case LFT_ICAP_REQUEST_URI:
+             out = al->icap.reqUri.termedBuf();
+             break;
+         case LFT_ICAP_REQUEST_METHOD:
+             out = Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod);
+             break;
+         case LFT_ICAP_BYTES_SENT:
+             outoff = al->icap.bytesSent;
+             dooff = 1;
+             break;
+         case LFT_ICAP_BYTES_READ:
+             outoff = al->icap.bytesRead;
+             dooff = 1;
+             break;
+         case LFT_ICAP_BODY_BYTES_READ:
+             if (al->icap.bodyBytesRead >= 0) {
+                 outoff = al->icap.bodyBytesRead;
+                 dooff = 1;
+             }
+             // else if icap.bodyBytesRead < 0, we do not have any http data,
+             // so just print a "-" (204 responses etc)
+             break;
+         case LFT_ICAP_REQ_HEADER:
+             if (NULL != al->icap.request) {
+                 sb = al->icap.request->header.getByName(fmt->data.header.header);
+                 out = sb.termedBuf();
+                 quote = 1;
+             }
+             break;
+         case LFT_ICAP_REQ_HEADER_ELEM:
+             if (al->request)
+                 sb = al->icap.request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+             out = sb.termedBuf();
+             quote = 1;
+             break;
+         case LFT_ICAP_REQ_ALL_HEADERS:
+             if (al->icap.request) {
+                 HttpHeaderPos pos = HttpHeaderInitPos;
+                 while (const HttpHeaderEntry *e = al->icap.request->header.getEntry(&pos)) {
+                     sb.append(e->name);
+                     sb.append(": ");
+                     sb.append(e->value);
+                     sb.append("\r\n");
+                 }
+                 out = sb.termedBuf();
+                 quote = 1;
+             }
+             break;
+         case LFT_ICAP_REP_HEADER:
+             if (NULL != al->icap.reply) {
+                 sb = al->icap.reply->header.getByName(fmt->data.header.header);
+                 out = sb.termedBuf();
+                 quote = 1;
+             }
+             break;
+         case LFT_ICAP_REP_HEADER_ELEM:
+             if (NULL != al->icap.reply)
+                 sb = al->icap.reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+             out = sb.termedBuf();
+             quote = 1;
+             break;
+         case LFT_ICAP_REP_ALL_HEADERS:
+             if (al->icap.reply) {
+                 HttpHeaderPos pos = HttpHeaderInitPos;
+                 while (const HttpHeaderEntry *e = al->icap.reply->header.getEntry(&pos)) {
+                     sb.append(e->name);
+                     sb.append(": ");
+                     sb.append(e->value);
+                     sb.append("\r\n");
+                 }
+                 out = sb.termedBuf();
+                 quote = 1;
+             }
+             break;
+         case LFT_ICAP_TR_RESPONSE_TIME:
+             outint = al->icap.trTime;
+             doint = 1;
+             break;
+         case LFT_ICAP_IO_TIME:
+             outint = al->icap.ioTime;
+             doint = 1;
+             break;
+         case LFT_ICAP_STATUS_CODE:
+             outint = al->icap.resStatus;
+             doint  = 1;
+             break;
+         case LFT_ICAP_OUTCOME:
+             out = al->icap.outcome;
+             break;
+         case LFT_ICAP_TOTAL_TIME:
+             outint = al->icap.processingTime;
+             doint = 1;
+             break;
+ #endif
+         case LFT_REQUEST_HEADER_ELEM:
+             if (al->request)
+                 sb = al->request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+             out = sb.termedBuf();
+             quote = 1;
+             break;
+         case LFT_ADAPTED_REQUEST_HEADER_ELEM:
+             if (al->adapted_request)
+                 sb = al->adapted_request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+             out = sb.termedBuf();
+             quote = 1;
+             break;
+         case LFT_REPLY_HEADER_ELEM:
+             if (al->reply)
+                 sb = al->reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+             out = sb.termedBuf();
+             quote = 1;
+             break;
+         case LFT_REQUEST_ALL_HEADERS:
+             out = al->headers.request;
+             quote = 1;
+             break;
+         case LFT_ADAPTED_REQUEST_ALL_HEADERS:
+             out = al->headers.adapted_request;
+             quote = 1;
+             break;
+         case LFT_REPLY_ALL_HEADERS:
+             out = al->headers.reply;
+             quote = 1;
+             break;
+         case LFT_USER_NAME:
+             out = QuoteUrlEncodeUsername(al->cache.authuser);
+             if (!out)
+                 out = QuoteUrlEncodeUsername(al->cache.extuser);
+ #if USE_SSL
+             if (!out)
+                 out = QuoteUrlEncodeUsername(al->cache.ssluser);
+ #endif
+             if (!out)
+                 out = QuoteUrlEncodeUsername(al->cache.rfc931);
+             dofree = 1;
+             break;
+         case LFT_USER_LOGIN:
+             out = QuoteUrlEncodeUsername(al->cache.authuser);
+             dofree = 1;
+             break;
+         case LFT_USER_IDENT:
+             out = QuoteUrlEncodeUsername(al->cache.rfc931);
+             dofree = 1;
+             break;
+         case LFT_USER_EXTERNAL:
+             out = QuoteUrlEncodeUsername(al->cache.extuser);
+             dofree = 1;
+             break;
+             /* case LFT_USER_REALM: */
+             /* case LFT_USER_SCHEME: */
+             // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30
+             // but compiler complains if ommited
+         case LFT_HTTP_SENT_STATUS_CODE_OLD_30:
+         case LFT_HTTP_SENT_STATUS_CODE:
+             outint = al->http.code;
+             doint = 1;
+             break;
+         case LFT_HTTP_RECEIVED_STATUS_CODE:
+             if (al->hier.peer_reply_status == HTTP_STATUS_NONE) {
+                 out = "-";
+             } else {
+                 outint = al->hier.peer_reply_status;
+                 doint = 1;
+             }
+             break;
+             /* case LFT_HTTP_STATUS:
+              *           out = statusline->text;
+              *     quote = 1;
+              *     break;
+              */
+         case LFT_HTTP_BODY_BYTES_READ:
+             if (al->hier.bodyBytesRead >= 0) {
+                 outoff = al->hier.bodyBytesRead;
+                 dooff = 1;
+             }
+             // else if hier.bodyBytesRead < 0 we did not have any data exchange with
+             // a peer server so just print a "-" (eg requests served from cache,
+             // or internal error messages).
+             break;
+         case LFT_SQUID_STATUS:
+             if (al->http.timedout || al->http.aborted) {
+                 snprintf(tmp, sizeof(tmp), "%s%s", log_tags[al->cache.code],
+                          al->http.statusSfx());
+                 out = tmp;
+             } else {
+                 out = log_tags[al->cache.code];
+             }
+             break;
+         case LFT_SQUID_ERROR:
+             if (al->request && al->request->errType != ERR_NONE)
+                 out = errorPageName(al->request->errType);
+             break;
+         case LFT_SQUID_ERROR_DETAIL:
+             if (al->request && al->request->errDetail != ERR_DETAIL_NONE) {
+                 if (al->request->errDetail > ERR_DETAIL_START  &&
+                         al->request->errDetail < ERR_DETAIL_MAX)
+                     out = errorDetailName(al->request->errDetail);
+                 else {
+                     if (al->request->errDetail >= ERR_DETAIL_EXCEPTION_START)
+                         snprintf(tmp, sizeof(tmp), "%s=0x%X",
+                                  errorDetailName(al->request->errDetail), (uint32_t) al->request->errDetail);
+                     else
+                         snprintf(tmp, sizeof(tmp), "%s=%d",
+                                  errorDetailName(al->request->errDetail), al->request->errDetail);
+                     out = tmp;
+                 }
+             }
+             break;
+         case LFT_SQUID_HIERARCHY:
+             if (al->hier.ping.timedout)
+                 mb.append("TIMEOUT_", 8);
+             out = hier_code_str[al->hier.code];
+             break;
+         case LFT_MIME_TYPE:
+             out = al->http.content_type;
+             break;
+         case LFT_CLIENT_REQ_METHOD:
+             if (al->request) {
+                 out = al->request->method.image();
+                 quote = 1;
+             }
+             break;
+         case LFT_CLIENT_REQ_URI:
+             // original client URI
+             if (al->request) {
+                 out = urlCanonical(al->request);
+                 quote = 1;
+             }
+             break;
+         case LFT_REQUEST_URLPATH_OLD_31:
+         case LFT_CLIENT_REQ_URLPATH:
+             if (al->request) {
+                 out = al->request->urlpath.termedBuf();
+                 quote = 1;
+             }
+             break;
+         case LFT_CLIENT_REQ_VERSION:
+             if (al->request) {
+                 snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->request->http_ver.major, (int) al->request->http_ver.minor);
+                 out = tmp;
+             }
+             break;
+         case LFT_REQUEST_METHOD:
+             out = al->_private.method_str;
+             break;
+         case LFT_REQUEST_URI:
+             out = al->url;
+             break;
+         case LFT_REQUEST_VERSION_OLD_2X:
+         case LFT_REQUEST_VERSION:
+             snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->http.version.major, (int) al->http.version.minor);
+             out = tmp;
+             break;
+         case LFT_SERVER_REQ_METHOD:
+             if (al->adapted_request) {
+                 out = al->adapted_request->method.image();
+                 quote = 1;
+             }
+             break;
+         case LFT_SERVER_REQ_URI:
+             // adapted request URI sent to server/peer
+             if (al->adapted_request) {
+                 out = urlCanonical(al->adapted_request);
+                 quote = 1;
+             }
+             break;
+         case LFT_SERVER_REQ_URLPATH:
+             if (al->adapted_request) {
+                 out = al->adapted_request->urlpath.termedBuf();
+                 quote = 1;
+             }
+             break;
+         case LFT_SERVER_REQ_VERSION:
+             if (al->adapted_request) {
+                 snprintf(tmp, sizeof(tmp), "%d.%d",
+                          (int) al->adapted_request->http_ver.major,
+                          (int) al->adapted_request->http_ver.minor);
+                 out = tmp;
+             }
+             break;
+         case LFT_REQUEST_SIZE_TOTAL:
+             outoff = al->cache.requestSize;
+             dooff = 1;
+             break;
+             /*case LFT_REQUEST_SIZE_LINE: */
+         case LFT_REQUEST_SIZE_HEADERS:
+             outoff = al->cache.requestHeadersSize;
+             dooff =1;
+             break;
+             /*case LFT_REQUEST_SIZE_BODY: */
+             /*case LFT_REQUEST_SIZE_BODY_NO_TE: */
+         case LFT_REPLY_SIZE_TOTAL:
+             outoff = al->cache.replySize;
+             dooff = 1;
+             break;
+         case LFT_REPLY_HIGHOFFSET:
+             outoff = al->cache.highOffset;
+             dooff = 1;
+             break;
+         case LFT_REPLY_OBJECTSIZE:
+             outoff = al->cache.objectSize;
+             dooff = 1;
+             break;
+             /*case LFT_REPLY_SIZE_LINE: */
+         case LFT_REPLY_SIZE_HEADERS:
+             outint = al->cache.replyHeadersSize;
+             doint = 1;
+             break;
+             /*case LFT_REPLY_SIZE_BODY: */
+             /*case LFT_REPLY_SIZE_BODY_NO_TE: */
+         case LFT_TAG:
+             if (al->request)
+                 out = al->request->tag.termedBuf();
+             quote = 1;
+             break;
+         case LFT_IO_SIZE_TOTAL:
+             outint = al->cache.requestSize + al->cache.replySize;
+             doint = 1;
+             break;
+         case LFT_EXT_LOG:
+             if (al->request)
+                 out = al->request->extacl_log.termedBuf();
+             quote = 1;
+             break;
+         case LFT_SEQUENCE_NUMBER:
+             outoff = logSequenceNumber;
+             dooff = 1;
+             break;
+         case LFT_PERCENT:
+             out = "%";
+             break;
+         }
+         if (dooff) {
+             snprintf(tmp, sizeof(tmp), "%0*" PRId64, fmt->zero ? (int) fmt->width : 0, outoff);
+             out = tmp;
+         } else if (doint) {
+             snprintf(tmp, sizeof(tmp), "%0*ld", fmt->zero ? (int) fmt->width : 0, outint);
+             out = tmp;
+         }
+         if (out && *out) {
+             if (quote || fmt->quote != LOG_QUOTE_NONE) {
+                 char *newout = NULL;
+                 int newfree = 0;
+                 switch (fmt->quote) {
+                 case LOG_QUOTE_NONE:
+                     newout = rfc1738_escape_unescaped(out);
+                     break;
+                 case LOG_QUOTE_QUOTES: {
+                     size_t out_len = static_cast<size_t>(strlen(out)) * 2 + 1;
+                     if (out_len >= sizeof(tmp)) {
+                         newout = (char *)xmalloc(out_len);
+                         newfree = 1;
+                     } else
+                         newout = tmp;
+                     log_quoted_string(out, newout);
+                 }
+                 break;
+                 case LOG_QUOTE_MIMEBLOB:
+                     newout = QuoteMimeBlob(out);
+                     newfree = 1;
+                     break;
+                 case LOG_QUOTE_URL:
+                     newout = rfc1738_escape(out);
+                     break;
+                 case LOG_QUOTE_RAW:
+                     break;
+                 }
+                 if (newout) {
+                     if (dofree)
+                         safe_free(out);
+                     out = newout;
+                     dofree = newfree;
+                 }
+             }
 -                    mb.Printf("%-*s", (int) fmt->width, out);
++            // enforce width limits if configured
++            const bool haveMaxWidth = fmt->precision && !doint && !dooff;
++            if (haveMaxWidth || fmt->width) {
++                const int minWidth = fmt->width ?
++                                     static_cast<int>(fmt->width) : 0;
++                const int maxWidth = haveMaxWidth ?
++                                     static_cast<int>(fmt->precision) : strlen(out);
++
+                 if (fmt->left)
 -                    mb.Printf("%*s", (int) fmt->width, out);
++                    mb.Printf("%-*.*s", minWidth, maxWidth, out);
+                 else
++                    mb.Printf("%*.*s", minWidth, maxWidth, out);
+             } else
+                 mb.append(out, strlen(out));
+         } else {
+             mb.append("-", 1);
+         }
+         if (fmt->space)
+             mb.append(" ", 1);
+         sb.clean();
+         if (dofree)
+             safe_free(out);
+     }
+ }
index aa42bbf057fa6c64dabd77853e84873faa907860,b37ec9187a519584dbcdd696012783598e03f75f..2f0ed80db30e4639c516050fef9fab709d3816d2
@@@ -191,9 -197,9 +197,9 @@@ public
          } header;
          char *timespec;
      } data;
 -    unsigned char width;
 -    unsigned char precision;
 +    unsigned int width;
 +    unsigned int precision;
-     enum log_quote quote;
+     enum Quoting quote;
      unsigned int left:1;
      unsigned int space:1;
      unsigned int zero:1;
Simple merge
Simple merge
Simple merge
diff --cc src/globals.h
Simple merge
diff --cc src/http.cc
Simple merge
Simple merge
index 9bd74d3c9e91e683a0f8bf4302d663e4f78f8d94,d81a04fe4bb6ba57c5d2472490c48f06a424793b..4add0081a96c35c8d796959908762916971fa6e4
@@@ -67,10 -58,7 +67,10 @@@ protected
  private:
      StrandCoords strands_; ///< registered processes and threads
  
 -    typedef std::map<OpenListenerParams, Comm::ConnectionPointer> Listeners; ///< params:fd map
 +    typedef std::list<StrandSearchRequest> Searchers; ///< search requests
 +    Searchers searchers; ///< yet unanswered search requests in arrival order
 +
-     typedef std::map<OpenListenerParams, int> Listeners; ///< params:fd map
++    typedef std::map<OpenListenerParams, Comm::ConnectionPointer> Listeners; ///< params:connection map
      Listeners listeners; ///< cached comm_open_listener() results
  
      static Coordinator* TheInstance; ///< the only class instance in existence
Simple merge
diff --cc src/ipc/Kid.h
Simple merge
index 14d3d0af03c3e3d81f9d01143448d8d5e705bc01,5524c12bd51fbebe1f51f0e451f3d83a82dfa0e7..bf35d8a1c29ab0fdfbd997b8004cbf972dd39d39
@@@ -43,18 -34,9 +43,21 @@@ libipc_la_SOURCES = 
        Inquirer.cc \
        Inquirer.h \
        Request.h \
 -      Response.h
 +      Response.h \
 +      \
 +      mem/Page.cc \
 +      mem/Page.h \
 +      mem/PagePool.cc \
 +      mem/PagePool.h \
 +      mem/Pages.cc \
 +      mem/Pages.h \
 +      mem/PageStack.cc \
 +      mem/PageStack.h \
 +      mem/Pointer.h \
 +      mem/Segment.cc \
 +      mem/Segment.h
  
- DEFS += -DDEFAULT_PREFIX=\"$(prefix)\"
+ DEFS += -DDEFAULT_STATEDIR=\"$(localstatedir)/run/squid\"
+ install-data-local:
+       $(mkinstalldirs) $(DESTDIR)$(localstatedir)/run/squid;
Simple merge
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..df1d37e8abc948f1b061e991b929dd23ac8c0fd1
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,834 @@@
++/*
++ * $Id$
++ *
++ * DEBUG: section 46    Access Log - Squid Custom format
++ * AUTHOR: Duane Wessels
++ *
++ * 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 "config.h"
++#include "AccessLogEntry.h"
++#include "log/File.h"
++#include "log/Formats.h"
++#include "log/Gadgets.h"
++#include "log/Tokens.h"
++#include "SquidTime.h"
++
++#include "MemBuf.h"
++#include "HttpRequest.h"
++#include "rfc1738.h"
++#include "err_detail_type.h"
++#include "errorpage.h"
++
++static void
++log_quoted_string(const char *str, char *out)
++{
++    char *p = out;
++
++    while (*str) {
++        int l = strcspn(str, "\"\\\r\n\t");
++        memcpy(p, str, l);
++        str += l;
++        p += l;
++
++        switch (*str) {
++
++        case '\0':
++            break;
++
++        case '\r':
++            *p++ = '\\';
++            *p++ = 'r';
++            str++;
++            break;
++
++        case '\n':
++            *p++ = '\\';
++            *p++ = 'n';
++            str++;
++            break;
++
++        case '\t':
++            *p++ = '\\';
++            *p++ = 't';
++            str++;
++            break;
++
++        default:
++            *p++ = '\\';
++            *p++ = *str;
++            str++;
++            break;
++        }
++    }
++
++    *p++ = '\0';
++}
++
++void
++Log::Format::SquidCustom(AccessLogEntry * al, customlog * log)
++{
++    logformat *lf;
++    Logfile *logfile;
++    logformat_token *fmt;
++    static MemBuf mb;
++    char tmp[1024];
++    String sb;
++
++    mb.reset();
++
++    lf = log->logFormat;
++    logfile = log->logfile;
++
++    for (fmt = lf->format; fmt != NULL; fmt = fmt->next) {    /* for each token */
++        const char *out = NULL;
++        int quote = 0;
++        long int outint = 0;
++        int doint = 0;
++        int dofree = 0;
++        int64_t outoff = 0;
++        int dooff = 0;
++
++        switch (fmt->type) {
++
++        case LFT_NONE:
++            out = "";
++            break;
++
++        case LFT_STRING:
++            out = fmt->data.string;
++            break;
++
++        case LFT_CLIENT_IP_ADDRESS:
++            if (al->cache.caddr.IsNoAddr()) // e.g., ICAP OPTIONS lack client
++                out = "-";
++            else
++                out = al->cache.caddr.NtoA(tmp,1024);
++            break;
++
++        case LFT_CLIENT_FQDN:
++            if (al->cache.caddr.IsAnyAddr()) // e.g., ICAP OPTIONS lack client
++                out = "-";
++            else
++                out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
++            if (!out) {
++                out = al->cache.caddr.NtoA(tmp,1024);
++            }
++
++            break;
++
++        case LFT_CLIENT_PORT:
++            if (al->request) {
++                outint = al->request->client_addr.GetPort();
++                doint = 1;
++            }
++            break;
++
++#if USE_SQUID_EUI
++        case LFT_CLIENT_EUI:
++            if (al->request) {
++                if (al->cache.caddr.IsIPv4())
++                    al->request->client_eui48.encode(tmp, 1024);
++                else
++                    al->request->client_eui64.encode(tmp, 1024);
++                out = tmp;
++            }
++            break;
++#endif
++
++            /* case LFT_SERVER_IP_ADDRESS: */
++
++        case LFT_SERVER_IP_OR_PEER_NAME:
++            out = al->hier.host;
++
++            break;
++
++            /* case LFT_SERVER_PORT: */
++
++        case LFT_LOCAL_IP:
++            if (al->request) {
++                out = al->request->my_addr.NtoA(tmp,sizeof(tmp));
++            }
++
++            break;
++
++        case LFT_LOCAL_PORT:
++            if (al->request) {
++                outint = al->request->my_addr.GetPort();
++                doint = 1;
++            }
++
++            break;
++
++            // the fmt->type can not be LFT_PEER_LOCAL_IP_OLD_27
++            // but compiler complains if ommited
++        case LFT_PEER_LOCAL_IP_OLD_27:
++        case LFT_PEER_LOCAL_IP:
++            if (!al->hier.peer_local_addr.IsAnyAddr()) {
++                out = al->hier.peer_local_addr.NtoA(tmp,sizeof(tmp));
++            }
++            break;
++
++        case LFT_PEER_LOCAL_PORT:
++            if ((outint = al->hier.peer_local_addr.GetPort())) {
++                doint = 1;
++            }
++
++            break;
++
++        case LFT_TIME_SECONDS_SINCE_EPOCH:
++            // some platforms store time in 32-bit, some 64-bit...
++            outoff = static_cast<int64_t>(current_time.tv_sec);
++            dooff = 1;
++            break;
++
++        case LFT_TIME_SUBSECOND:
++            outint = current_time.tv_usec / fmt->divisor;
++            doint = 1;
++            break;
++
++
++        case LFT_TIME_LOCALTIME:
++
++        case LFT_TIME_GMT: {
++            const char *spec;
++
++            struct tm *t;
++            spec = fmt->data.timespec;
++
++            if (fmt->type == LFT_TIME_LOCALTIME) {
++                if (!spec)
++                    spec = "%d/%b/%Y:%H:%M:%S %z";
++                t = localtime(&squid_curtime);
++            } else {
++                if (!spec)
++                    spec = "%d/%b/%Y:%H:%M:%S";
++
++                t = gmtime(&squid_curtime);
++            }
++
++            strftime(tmp, sizeof(tmp), spec, t);
++
++            out = tmp;
++        }
++
++        break;
++
++        case LFT_TIME_TO_HANDLE_REQUEST:
++            outint = al->cache.msec;
++            doint = 1;
++            break;
++
++        case LFT_PEER_RESPONSE_TIME:
++            if (al->hier.peer_response_time < 0) {
++                out = "-";
++            } else {
++                outoff = al->hier.peer_response_time;
++                dooff = 1;
++            }
++            break;
++
++        case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME:
++            if (al->hier.total_response_time < 0) {
++                out = "-";
++            } else {
++                outoff = al->hier.total_response_time;
++                dooff = 1;
++            }
++            break;
++
++        case LFT_DNS_WAIT_TIME:
++            if (al->request && al->request->dnsWait >= 0) {
++                outint = al->request->dnsWait;
++                doint = 1;
++            }
++            break;
++
++        case LFT_REQUEST_HEADER:
++
++            if (al->request)
++                sb = al->request->header.getByName(fmt->data.header.header);
++
++            out = sb.termedBuf();
++
++            quote = 1;
++
++            break;
++
++        case LFT_ADAPTED_REQUEST_HEADER:
++
++            if (al->request)
++                sb = al->adapted_request->header.getByName(fmt->data.header.header);
++
++            out = sb.termedBuf();
++
++            quote = 1;
++
++            break;
++
++        case LFT_REPLY_HEADER:
++            if (al->reply)
++                sb = al->reply->header.getByName(fmt->data.header.header);
++
++            out = sb.termedBuf();
++
++            quote = 1;
++
++            break;
++
++#if USE_ADAPTATION
++        case LTF_ADAPTATION_SUM_XACT_TIMES:
++            if (al->request) {
++                Adaptation::History::Pointer ah = al->request->adaptHistory();
++                if (ah != NULL)
++                    ah->sumLogString(fmt->data.string, sb);
++                out = sb.termedBuf();
++            }
++            break;
++
++        case LTF_ADAPTATION_ALL_XACT_TIMES:
++            if (al->request) {
++                Adaptation::History::Pointer ah = al->request->adaptHistory();
++                if (ah != NULL)
++                    ah->allLogString(fmt->data.string, sb);
++                out = sb.termedBuf();
++            }
++            break;
++
++        case LFT_ADAPTATION_LAST_HEADER:
++            if (al->request) {
++                const Adaptation::History::Pointer ah = al->request->adaptHistory();
++                if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here
++                    sb = ah->allMeta.getByName(fmt->data.header.header);
++            }
++
++            // XXX: here and elsewhere: move such code inside the if guard
++            out = sb.termedBuf();
++
++            quote = 1;
++
++            break;
++
++        case LFT_ADAPTATION_LAST_HEADER_ELEM:
++            if (al->request) {
++                const Adaptation::History::Pointer ah = al->request->adaptHistory();
++                if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here
++                    sb = ah->allMeta.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
++            }
++
++            out = sb.termedBuf();
++
++            quote = 1;
++
++            break;
++
++        case LFT_ADAPTATION_LAST_ALL_HEADERS:
++            out = al->adapt.last_meta;
++
++            quote = 1;
++
++            break;
++#endif
++
++#if ICAP_CLIENT
++        case LFT_ICAP_ADDR:
++            if (!out)
++                out = al->icap.hostAddr.NtoA(tmp,1024);
++            break;
++
++        case LFT_ICAP_SERV_NAME:
++            out = al->icap.serviceName.termedBuf();
++            break;
++
++        case LFT_ICAP_REQUEST_URI:
++            out = al->icap.reqUri.termedBuf();
++            break;
++
++        case LFT_ICAP_REQUEST_METHOD:
++            out = Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod);
++            break;
++
++        case LFT_ICAP_BYTES_SENT:
++            outoff = al->icap.bytesSent;
++            dooff = 1;
++            break;
++
++        case LFT_ICAP_BYTES_READ:
++            outoff = al->icap.bytesRead;
++            dooff = 1;
++            break;
++
++        case LFT_ICAP_BODY_BYTES_READ:
++            if (al->icap.bodyBytesRead >= 0) {
++                outoff = al->icap.bodyBytesRead;
++                dooff = 1;
++            }
++            // else if icap.bodyBytesRead < 0, we do not have any http data,
++            // so just print a "-" (204 responses etc)
++            break;
++
++        case LFT_ICAP_REQ_HEADER:
++            if (NULL != al->icap.request) {
++                sb = al->icap.request->header.getByName(fmt->data.header.header);
++                out = sb.termedBuf();
++                quote = 1;
++            }
++            break;
++
++        case LFT_ICAP_REQ_HEADER_ELEM:
++            if (al->request)
++                sb = al->icap.request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
++
++            out = sb.termedBuf();
++
++            quote = 1;
++
++            break;
++
++        case LFT_ICAP_REQ_ALL_HEADERS:
++            if (al->icap.request) {
++                HttpHeaderPos pos = HttpHeaderInitPos;
++                while (const HttpHeaderEntry *e = al->icap.request->header.getEntry(&pos)) {
++                    sb.append(e->name);
++                    sb.append(": ");
++                    sb.append(e->value);
++                    sb.append("\r\n");
++                }
++                out = sb.termedBuf();
++                quote = 1;
++            }
++            break;
++
++        case LFT_ICAP_REP_HEADER:
++            if (NULL != al->icap.reply) {
++                sb = al->icap.reply->header.getByName(fmt->data.header.header);
++                out = sb.termedBuf();
++                quote = 1;
++            }
++            break;
++
++        case LFT_ICAP_REP_HEADER_ELEM:
++            if (NULL != al->icap.reply)
++                sb = al->icap.reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
++
++            out = sb.termedBuf();
++
++            quote = 1;
++
++            break;
++
++        case LFT_ICAP_REP_ALL_HEADERS:
++            if (al->icap.reply) {
++                HttpHeaderPos pos = HttpHeaderInitPos;
++                while (const HttpHeaderEntry *e = al->icap.reply->header.getEntry(&pos)) {
++                    sb.append(e->name);
++                    sb.append(": ");
++                    sb.append(e->value);
++                    sb.append("\r\n");
++                }
++                out = sb.termedBuf();
++                quote = 1;
++            }
++            break;
++
++        case LFT_ICAP_TR_RESPONSE_TIME:
++            outint = al->icap.trTime;
++            doint = 1;
++            break;
++
++        case LFT_ICAP_IO_TIME:
++            outint = al->icap.ioTime;
++            doint = 1;
++            break;
++
++        case LFT_ICAP_STATUS_CODE:
++            outint = al->icap.resStatus;
++            doint  = 1;
++            break;
++
++        case LFT_ICAP_OUTCOME:
++            out = al->icap.outcome;
++            break;
++
++        case LFT_ICAP_TOTAL_TIME:
++            outint = al->icap.processingTime;
++            doint = 1;
++            break;
++#endif
++        case LFT_REQUEST_HEADER_ELEM:
++            if (al->request)
++                sb = al->request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
++
++            out = sb.termedBuf();
++
++            quote = 1;
++
++            break;
++
++        case LFT_ADAPTED_REQUEST_HEADER_ELEM:
++            if (al->adapted_request)
++                sb = al->adapted_request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
++
++            out = sb.termedBuf();
++
++            quote = 1;
++
++            break;
++
++        case LFT_REPLY_HEADER_ELEM:
++            if (al->reply)
++                sb = al->reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
++
++            out = sb.termedBuf();
++
++            quote = 1;
++
++            break;
++
++        case LFT_REQUEST_ALL_HEADERS:
++            out = al->headers.request;
++
++            quote = 1;
++
++            break;
++
++        case LFT_ADAPTED_REQUEST_ALL_HEADERS:
++            out = al->headers.adapted_request;
++
++            quote = 1;
++
++            break;
++
++        case LFT_REPLY_ALL_HEADERS:
++            out = al->headers.reply;
++
++            quote = 1;
++
++            break;
++
++        case LFT_USER_NAME:
++            out = Log::FormatName(al->cache.authuser);
++
++            if (!out)
++                out = Log::FormatName(al->cache.extuser);
++
++#if USE_SSL
++
++            if (!out)
++                out = Log::FormatName(al->cache.ssluser);
++
++#endif
++
++            if (!out)
++                out = Log::FormatName(al->cache.rfc931);
++
++            dofree = 1;
++
++            break;
++
++        case LFT_USER_LOGIN:
++            out = Log::FormatName(al->cache.authuser);
++
++            dofree = 1;
++
++            break;
++
++        case LFT_USER_IDENT:
++            out = Log::FormatName(al->cache.rfc931);
++
++            dofree = 1;
++
++            break;
++
++        case LFT_USER_EXTERNAL:
++            out = Log::FormatName(al->cache.extuser);
++
++            dofree = 1;
++
++            break;
++
++            /* case LFT_USER_REALM: */
++            /* case LFT_USER_SCHEME: */
++
++            // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30
++            // but compiler complains if ommited
++        case LFT_HTTP_SENT_STATUS_CODE_OLD_30:
++        case LFT_HTTP_SENT_STATUS_CODE:
++            outint = al->http.code;
++
++            doint = 1;
++
++            break;
++
++        case LFT_HTTP_RECEIVED_STATUS_CODE:
++            if (al->hier.peer_reply_status == HTTP_STATUS_NONE) {
++                out = "-";
++            } else {
++                outint = al->hier.peer_reply_status;
++                doint = 1;
++            }
++            break;
++            /* case LFT_HTTP_STATUS:
++             *           out = statusline->text;
++             *     quote = 1;
++             *     break;
++             */
++        case LFT_HTTP_BODY_BYTES_READ:
++            if (al->hier.bodyBytesRead >= 0) {
++                outoff = al->hier.bodyBytesRead;
++                dooff = 1;
++            }
++            // else if hier.bodyBytesRead < 0 we did not have any data exchange with
++            // a peer server so just print a "-" (eg requests served from cache,
++            // or internal error messages).
++            break;
++
++        case LFT_SQUID_STATUS:
++            if (al->http.timedout || al->http.aborted) {
++                snprintf(tmp, sizeof(tmp), "%s%s", log_tags[al->cache.code],
++                         al->http.statusSfx());
++                out = tmp;
++            } else {
++                out = log_tags[al->cache.code];
++            }
++
++            break;
++
++        case LFT_SQUID_ERROR:
++            if (al->request && al->request->errType != ERR_NONE)
++                out = errorPageName(al->request->errType);
++            break;
++
++        case LFT_SQUID_ERROR_DETAIL:
++            if (al->request && al->request->errDetail != ERR_DETAIL_NONE) {
++                if (al->request->errDetail > ERR_DETAIL_START  &&
++                        al->request->errDetail < ERR_DETAIL_MAX)
++                    out = errorDetailName(al->request->errDetail);
++                else {
++                    if (al->request->errDetail >= ERR_DETAIL_EXCEPTION_START)
++                        snprintf(tmp, sizeof(tmp), "%s=0x%X",
++                                 errorDetailName(al->request->errDetail), (uint32_t) al->request->errDetail);
++                    else
++                        snprintf(tmp, sizeof(tmp), "%s=%d",
++                                 errorDetailName(al->request->errDetail), al->request->errDetail);
++                    out = tmp;
++                }
++            }
++            break;
++
++        case LFT_SQUID_HIERARCHY:
++            if (al->hier.ping.timedout)
++                mb.append("TIMEOUT_", 8);
++
++            out = hier_code_str[al->hier.code];
++
++            break;
++
++        case LFT_MIME_TYPE:
++            out = al->http.content_type;
++
++            break;
++
++        case LFT_REQUEST_METHOD:
++            out = al->_private.method_str;
++
++            break;
++
++        case LFT_REQUEST_URI:
++            out = al->url;
++
++            break;
++
++        case LFT_REQUEST_URLPATH:
++            if (al->request) {
++                out = al->request->urlpath.termedBuf();
++                quote = 1;
++            }
++            break;
++
++        case LFT_REQUEST_VERSION:
++            snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->http.version.major, (int) al->http.version.minor);
++            out = tmp;
++            break;
++
++        case LFT_REQUEST_SIZE_TOTAL:
++            outoff = al->cache.requestSize;
++            dooff = 1;
++            break;
++
++            /*case LFT_REQUEST_SIZE_LINE: */
++        case LFT_REQUEST_SIZE_HEADERS:
++            outoff = al->cache.requestHeadersSize;
++            dooff =1;
++            break;
++            /*case LFT_REQUEST_SIZE_BODY: */
++            /*case LFT_REQUEST_SIZE_BODY_NO_TE: */
++
++        case LFT_REPLY_SIZE_TOTAL:
++            outoff = al->cache.replySize;
++            dooff = 1;
++            break;
++
++        case LFT_REPLY_HIGHOFFSET:
++            outoff = al->cache.highOffset;
++
++            dooff = 1;
++
++            break;
++
++        case LFT_REPLY_OBJECTSIZE:
++            outoff = al->cache.objectSize;
++
++            dooff = 1;
++
++            break;
++
++            /*case LFT_REPLY_SIZE_LINE: */
++        case LFT_REPLY_SIZE_HEADERS:
++            outint = al->cache.replyHeadersSize;
++            doint = 1;
++            break;
++            /*case LFT_REPLY_SIZE_BODY: */
++            /*case LFT_REPLY_SIZE_BODY_NO_TE: */
++
++        case LFT_TAG:
++            if (al->request)
++                out = al->request->tag.termedBuf();
++
++            quote = 1;
++
++            break;
++
++        case LFT_IO_SIZE_TOTAL:
++            outint = al->cache.requestSize + al->cache.replySize;
++            doint = 1;
++            break;
++
++        case LFT_EXT_LOG:
++            if (al->request)
++                out = al->request->extacl_log.termedBuf();
++
++            quote = 1;
++
++            break;
++
++        case LFT_SEQUENCE_NUMBER:
++            outoff = logfile->sequence_number;
++            dooff = 1;
++            break;
++
++        case LFT_PERCENT:
++            out = "%";
++
++            break;
++        }
++
++        if (dooff) {
++            snprintf(tmp, sizeof(tmp), "%0*" PRId64, fmt->zero ? (int) fmt->width : 0, outoff);
++            out = tmp;
++
++        } else if (doint) {
++            snprintf(tmp, sizeof(tmp), "%0*ld", fmt->zero ? (int) fmt->width : 0, outint);
++            out = tmp;
++        }
++
++        if (out && *out) {
++            if (quote || fmt->quote != LOG_QUOTE_NONE) {
++                char *newout = NULL;
++                int newfree = 0;
++
++                switch (fmt->quote) {
++
++                case LOG_QUOTE_NONE:
++                    newout = rfc1738_escape_unescaped(out);
++                    break;
++
++                case LOG_QUOTE_QUOTES: {
++                    size_t out_len = static_cast<size_t>(strlen(out)) * 2 + 1;
++                    if (out_len >= sizeof(tmp)) {
++                        newout = (char *)xmalloc(out_len);
++                        newfree = 1;
++                    } else
++                        newout = tmp;
++                    log_quoted_string(out, newout);
++                }
++                break;
++
++                case LOG_QUOTE_MIMEBLOB:
++                    newout = Log::QuoteMimeBlob(out);
++                    newfree = 1;
++                    break;
++
++                case LOG_QUOTE_URL:
++                    newout = rfc1738_escape(out);
++                    break;
++
++                case LOG_QUOTE_RAW:
++                    break;
++                }
++
++                if (newout) {
++                    if (dofree)
++                        safe_free(out);
++
++                    out = newout;
++
++                    dofree = newfree;
++                }
++            }
++
++            // enforce width limits if configured
++            const bool haveMaxWidth = fmt->precision && !doint && !dooff;
++            if (haveMaxWidth || fmt->width) {
++                const int minWidth = fmt->width ?
++                                     static_cast<int>(fmt->width) : 0;
++                const int maxWidth = haveMaxWidth ?
++                                     static_cast<int>(fmt->precision) : strlen(out);
++
++                if (fmt->left)
++                    mb.Printf("%-*.*s", minWidth, maxWidth, out);
++                else
++                    mb.Printf("%*.*s", minWidth, maxWidth, out);
++            } else
++                mb.append(out, strlen(out));
++        } else {
++            mb.append("-", 1);
++        }
++
++        if (fmt->space)
++            mb.append(" ", 1);
++
++        sb.clean();
++
++        if (dofree)
++            safe_free(out);
++    }
++
++    logfilePrintf(logfile, "%s\n", mb.buf);
++}
Simple merge
diff --cc src/main.cc
index 4294b1963545548c749733dade7f915f4434a6ae,53d09a5bf50a7b52cdc62a15d3d8b756745dccd6..40012fc3013eaa8479fcd70b1b1ba757efdad9f6
@@@ -40,7 -47,7 +47,8 @@@
  #if USE_AUTH
  #include "auth/Gadgets.h"
  #endif
 +#include "base/RunnersRegistry.h"
+ #include "base/Subscription.h"
  #include "base/TextException.h"
  #if USE_DELAY_POOLS
  #include "ClientDelayConfig.h"
diff --cc src/mem.cc
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc src/protos.h
Simple merge
diff --cc src/stat.cc
Simple merge
diff --cc src/store.cc
index c4ffa93b5c4daf94fc78e7451695df0bd0a63e63,039903cd30fd6ddb982170d88c720c9d84331211..ad8719ad98a0c19204ec7d5ae9d4e1865ddb0990
@@@ -255,17 -256,7 +257,17 @@@ StoreEntry::delayAwareRead(const Comm::
  
      }
  
-     if (fd_table[fd].closing()) {
++    if (fd_table[conn->fd].closing()) {
 +        // Readers must have closing callbacks if they want to be notified. No
 +        // readers appeared to care around 2009/12/14 as they skipped reading
 +        // for other reasons. Closing may already be true at the delyaAwareRead
 +        // call time or may happen while we wait after delayRead() above.
-         debugs(20, 3, HERE << "wont read from closing FD " << fd << " for " <<
++        debugs(20, 3, HERE << "wont read from closing " << conn << " for " <<
 +               callback);
 +        return; // the read callback will never be called
 +    }
 +
-     comm_read(fd, buf, amountToRead, callback);
+     comm_read(conn, buf, amountToRead, callback);
  }
  
  size_t
Simple merge
diff --cc src/structs.h
Simple merge
Simple merge
Simple merge
index d9d20d61cb24381ca2558f9ecab2832eeec64223,875f634829287b2ee63f8fa972e5e57147a54cca..014b561ba667d870662cf518f6ef107de7cdd8ca
@@@ -55,30 -54,14 +54,42 @@@ xmemset(void* dst, int val, size_t sz
      return memset(dst, val, sz);
  }
  
 +bool
 +IamWorkerProcess()
 +{
 +    fprintf(stderr, "Not implemented");
 +    return true;
 +}
 +
 +bool
 +IamDiskProcess()
 +{
 +    fprintf(stderr, "Not implemented");
 +    return false;
 +}
 +
 +bool
 +IamMasterProcess()
 +{
 +    fprintf(stderr, "Not implemented");
 +    return false;
 +}
 +
 +bool
 +UsingSmp()
 +{
 +    fprintf(stderr, "Not implemented");
 +    return false;
 +}
++
+ void
+ logsFlush(void)
+ {
+     fatal("tools.cc required");
+ }
+ void
+ no_suid(void)
+ {
+     fatal("tools.cc required");
+ }
Simple merge
diff --cc src/tools.cc
Simple merge
diff --cc src/urn.cc
Simple merge