From: Alex Rousskov Date: Wed, 10 Aug 2011 15:54:51 +0000 (-0600) Subject: Merged from parent (trunk r11623, v3.2.0.10+). X-Git-Tag: take08~55 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=109cf61c2a9f1ece83ea8f453f5c9d9982dd3326;p=thirdparty%2Fsquid.git Merged from parent (trunk r11623, v3.2.0.10+). --- 109cf61c2a9f1ece83ea8f453f5c9d9982dd3326 diff --cc src/Makefile.am index 0305c94022,19110eba00..8e10d9681d --- a/src/Makefile.am +++ b/src/Makefile.am @@@ -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 \ + comm/libcomm.la \ - base/libbase.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) \ diff --cc src/adaptation/icap/ServiceRep.cc index 9c2edc38b5,2cdbb59454..d4028c18e5 --- a/src/adaptation/icap/ServiceRep.cc +++ b/src/adaptation/icap/ServiceRep.cc @@@ -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); diff --cc src/adaptation/icap/ServiceRep.h index 1985ced4fa,f7c342469f..8bf64db33b --- a/src/adaptation/icap/ServiceRep.h +++ b/src/adaptation/icap/ServiceRep.h @@@ -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 diff --cc src/client_side.cc index 72af0333b9,4f62f0a875..574c99d7ad --- a/src/client_side.cc +++ b/src/client_side.cc @@@ -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 */ diff --cc src/comm.cc index 8142109d95,a6ab545de7..47c12cb115 --- a/src/comm.cc +++ b/src/comm.cc @@@ -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 fb206c93de,322d22ec93..899ea0e8a8 --- a/src/comm.h +++ b/src/comm.h @@@ -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 diff --cc src/format/Format.cc index 0000000000,8e611520cb..1ac21dd742 mode 000000,100644..100644 --- a/src/format/Format.cc +++ b/src/format/Format.cc @@@ -1,0 -1,1067 +1,1074 @@@ + #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, "e); + + while (cur < eos) { + new_lt = new Token; + last_lt->next = new_lt; + last_lt = new_lt; + cur += new_lt->parse(cur, "e); + } + + 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(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::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::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(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; + } + } + - if (fmt->width) { ++ // enforce width limits if configured ++ const bool haveMaxWidth = fmt->precision && !doint && !dooff; ++ if (haveMaxWidth || fmt->width) { ++ const int minWidth = fmt->width ? ++ static_cast(fmt->width) : 0; ++ const int maxWidth = haveMaxWidth ? ++ static_cast(fmt->precision) : strlen(out); ++ + if (fmt->left) - mb.Printf("%-*s", (int) fmt->width, out); ++ mb.Printf("%-*.*s", minWidth, maxWidth, out); + else - mb.Printf("%*s", (int) fmt->width, out); ++ 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); + } + } diff --cc src/format/Tokens.h index aa42bbf057,b37ec9187a..2f0ed80db3 --- a/src/format/Tokens.h +++ b/src/format/Tokens.h @@@ -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; diff --cc src/ipc/Coordinator.h index 9bd74d3c9e,d81a04fe4b..4add0081a9 --- a/src/ipc/Coordinator.h +++ b/src/ipc/Coordinator.h @@@ -67,10 -58,7 +67,10 @@@ protected private: StrandCoords strands_; ///< registered processes and threads - typedef std::map Listeners; ///< params:fd map + typedef std::list Searchers; ///< search requests + Searchers searchers; ///< yet unanswered search requests in arrival order + - typedef std::map Listeners; ///< params:fd map ++ typedef std::map Listeners; ///< params:connection map Listeners listeners; ///< cached comm_open_listener() results static Coordinator* TheInstance; ///< the only class instance in existence diff --cc src/ipc/Makefile.am index 14d3d0af03,5524c12bd5..bf35d8a1c2 --- a/src/ipc/Makefile.am +++ b/src/ipc/Makefile.am @@@ -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; diff --cc src/log/FormatSquidCustom.cc.THIS index 0000000000,0000000000..df1d37e8ab new file mode 100644 --- /dev/null +++ b/src/log/FormatSquidCustom.cc.THIS @@@ -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(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::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::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(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(fmt->width) : 0; ++ const int maxWidth = haveMaxWidth ? ++ static_cast(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); ++} diff --cc src/main.cc index 4294b19635,53d09a5bf5..40012fc301 --- a/src/main.cc +++ b/src/main.cc @@@ -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/store.cc index c4ffa93b5c,039903cd30..ad8719ad98 --- a/src/store.cc +++ b/src/store.cc @@@ -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 diff --cc src/tests/stub_tools.cc index d9d20d61cb,875f634829..014b561ba6 --- a/src/tests/stub_tools.cc +++ b/src/tests/stub_tools.cc @@@ -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"); + }