From: wessels <> Date: Wed, 7 Dec 2005 06:03:34 +0000 (+0000) Subject: Turned pconn.cc into C++ classes. There are now separate persistent X-Git-Tag: SQUID_3_0_PRE4~465 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=781ce8ff40f9cd5e6f5c4ec84ff2a978cff98ab0;p=thirdparty%2Fsquid.git Turned pconn.cc into C++ classes. There are now separate persistent connection pools for client-side, server-side, and now ICAP. Accounting for persistent connection use still sucks because HTTP (http.c) and ICAP state structures don't have any way to keep track of how many times a given TCP connection was used. So we'll keep abusing fd_entry[] for this purpose. --- diff --git a/src/ICAP/ICAPModXact.cc b/src/ICAP/ICAPModXact.cc index e4dd01a579..da763b9a76 100644 --- a/src/ICAP/ICAPModXact.cc +++ b/src/ICAP/ICAPModXact.cc @@ -707,7 +707,7 @@ bool ICAPModXact::parseHead(HttpMsg *head) } if (httpHeaderHasConnDir(&head->header, "close")) { - debug(0,0)("%s(%d) found connection close!\n", __FILE__,__LINE__); + debug(93,5)("%s(%d) found connection close\n", __FILE__,__LINE__); reuseConnection = false; } diff --git a/src/ICAP/ICAPXaction.cc b/src/ICAP/ICAPXaction.cc index b4bb330c84..2a6503ca9c 100644 --- a/src/ICAP/ICAPXaction.cc +++ b/src/ICAP/ICAPXaction.cc @@ -8,6 +8,10 @@ #include "ICAPXaction.h" #include "ICAPClient.h" #include "TextException.h" +#include "pconn.h" +#include "fde.h" + +static PconnPool *icapPconnPool = new PconnPool("ICAP Servers"); /* comm module handlers (wrappers around corresponding ICAPXaction methods */ @@ -81,7 +85,7 @@ void ICAPXaction::openConnection() { const ICAPServiceRep &s = service(); // TODO: check whether NULL domain is appropriate here - connection = pconnPop(s.host.buf(), s.port, NULL); + connection = icapPconnPool->pop(s.host.buf(), s.port, NULL); if (connection >= 0) { debug(93,3)("%s(%d) reused pconn FD %d\n", __FILE__, __LINE__, connection); @@ -144,7 +148,7 @@ void ICAPXaction::closeConnection() if (reuseConnection) { debug(93,3)("%s(%d) pushing pconn %d\n", __FILE__,__LINE__,connection); - pconnPush(connection, theService->host.buf(), theService->port, NULL); + icapPconnPool->push(connection, theService->host.buf(), theService->port, NULL); } else { debug(93,3)("%s(%d) closing pconn %d\n", __FILE__,__LINE__,connection); comm_close(connection); @@ -174,6 +178,7 @@ void ICAPXaction::scheduleWrite(MemBuf &buf) // comm module will free the buffer writer = &ICAPXaction_noteCommWrote; comm_old_write_mbuf(connection, &buf, writer, this); + fd_table[connection].noteUse(icapPconnPool); } void ICAPXaction::noteCommWrote(comm_err_t commStatus, size_t size) diff --git a/src/client_side.cc b/src/client_side.cc index c10cf436e5..2599fb746d 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side.cc,v 1.704 2005/11/29 20:18:20 serassio Exp $ + * $Id: client_side.cc,v 1.705 2005/12/06 23:03:34 wessels Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -624,8 +624,6 @@ ConnStateData::~ConnStateData() auth_user_request = NULL; - pconnHistCount(0, nrequests); - cbdataReferenceDone(port); } diff --git a/src/comm.cc b/src/comm.cc index 212b9cbebd..8ef527ac34 100644 --- a/src/comm.cc +++ b/src/comm.cc @@ -1,6 +1,6 @@ /* - * $Id: comm.cc,v 1.411 2005/09/17 05:50:08 wessels Exp $ + * $Id: comm.cc,v 1.412 2005/12/06 23:03:34 wessels Exp $ * * DEBUG: section 5 Socket Functions * AUTHOR: Harvest Derived @@ -42,6 +42,7 @@ #include "CommIO.h" #include "ConnectionDetail.h" #include "MemBuf.h" +#include "pconn.h" #if defined(_SQUID_CYGWIN_) #include @@ -1786,8 +1787,8 @@ _comm_close(int fd, char const *file, int line) commCallCloseHandlers(fd); - if (F->uses) /* assume persistent connect count */ - pconnHistCount(1, F->uses); + if (F->pconn.uses) + F->pconn.pool->count(F->pconn.uses); comm_empty_os_read_buffers(fd); diff --git a/src/fde.cc b/src/fde.cc index 5f025ef0eb..69534d24ac 100644 --- a/src/fde.cc +++ b/src/fde.cc @@ -1,6 +1,6 @@ /* - * $Id: fde.cc,v 1.2 2003/02/21 22:50:08 robertc Exp $ + * $Id: fde.cc,v 1.3 2005/12/06 23:03:34 wessels Exp $ * * DEBUG: section ?? FDE * AUTHOR: Robert Collins @@ -98,3 +98,9 @@ fde::remoteAddr() const return buf; } +void +fde::noteUse(PconnPool *pool) +{ + pconn.uses++; + pconn.pool = pool; +} diff --git a/src/fde.h b/src/fde.h index cac05c73bf..e6329e7921 100644 --- a/src/fde.h +++ b/src/fde.h @@ -1,6 +1,6 @@ /* - * $Id: fde.h,v 1.9 2005/08/27 18:40:20 serassio Exp $ + * $Id: fde.h,v 1.10 2005/12/06 23:03:34 wessels Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -35,6 +35,8 @@ #define SQUID_FDE_H #include "comm.h" +class PconnPool; + class fde { @@ -45,6 +47,7 @@ public: char const *remoteAddr() const; void dumpStats (StoreEntry &, int); bool readPending(int); + void noteUse(PconnPool *); unsigned int type; u_short local_port; @@ -101,7 +104,14 @@ unsigned int write_pending: flags; int bytes_read; int bytes_written; - int uses; /* ie # req's over persistent conn */ + + struct + { + int uses; /* ie # req's over persistent conn */ + PconnPool *pool; + } + + pconn; unsigned epoll_state; struct _fde_disk disk; diff --git a/src/forward.cc b/src/forward.cc index 1af4dd2afe..4549eaf10d 100644 --- a/src/forward.cc +++ b/src/forward.cc @@ -1,6 +1,6 @@ /* - * $Id: forward.cc,v 1.130 2005/11/06 11:14:27 serassio Exp $ + * $Id: forward.cc,v 1.131 2005/12/06 23:03:34 wessels Exp $ * * DEBUG: section 17 Request Forwarding * AUTHOR: Duane Wessels @@ -42,6 +42,7 @@ #include "ACLChecklist.h" #include "ACL.h" #include "HttpReply.h" +#include "pconn.h" static PSC fwdStartComplete; static void fwdDispatch(FwdState *); @@ -67,6 +68,8 @@ static void fwdLog(FwdState * fwdState); static Logfile *logfile = NULL; #endif +static PconnPool *fwdPconnPool = new PconnPool("server-side"); + static peer * fwdStateServerPeer(FwdState * fwdState) { @@ -581,7 +584,7 @@ fwdConnectStart(void *data) if (ftimeout < ctimeout) ctimeout = ftimeout; - if ((fd = pconnPop(host, port, domain)) >= 0) { + if ((fd = fwdPconnPool->pop(host, port, domain)) >= 0) { if (fwdCheckRetriable(fwdState)) { debug(17, 3) ("fwdConnectStart: reusing pconn FD %d\n", fd); fwdState->server_fd = fd; @@ -715,7 +718,7 @@ fwdDispatch(FwdState * fwdState) fd_note(server_fd, storeUrl(fwdState->entry)); - fd_table[server_fd].uses++; + fd_table[server_fd].noteUse(fwdPconnPool); /*assert(!EBIT_TEST(entry->flags, ENTRY_DISPATCHED)); */ assert(entry->ping_status != PING_WAITING); @@ -1040,6 +1043,12 @@ fwdComplete(FwdState * fwdState) } } +void +fwdPconnPush(int fd, const char *host, int port, const char *domain) +{ + fwdPconnPool->push(fd, host, port, domain); +} + void fwdInit(void) { diff --git a/src/http.cc b/src/http.cc index e1ca8e7192..86173e440d 100644 --- a/src/http.cc +++ b/src/http.cc @@ -1,6 +1,6 @@ /* - * $Id: http.cc,v 1.469 2005/12/03 18:00:28 wessels Exp $ + * $Id: http.cc,v 1.470 2005/12/06 23:03:34 wessels Exp $ * * DEBUG: section 11 Hypertext Transfer Protocol (HTTP) * AUTHOR: Harvest Derived @@ -1195,11 +1195,11 @@ HttpStateData::processReplyBody() if (_peer) { if (_peer->options.originserver) - pconnPush(fd, _peer->name, orig_request->port, orig_request->host); + fwdPconnPush(fd, _peer->name, orig_request->port, orig_request->host); else - pconnPush(fd, _peer->name, _peer->http_port, NULL); + fwdPconnPush(fd, _peer->name, _peer->http_port, NULL); } else { - pconnPush(fd, request->host, request->port, NULL); + fwdPconnPush(fd, request->host, request->port, NULL); } fd = -1; diff --git a/src/main.cc b/src/main.cc index 31c6dcd017..40c534bc5f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,6 +1,6 @@ /* - * $Id: main.cc,v 1.414 2005/11/21 22:41:45 wessels Exp $ + * $Id: main.cc,v 1.415 2005/12/06 23:03:34 wessels Exp $ * * DEBUG: section 1 Startup and Main Loop * AUTHOR: Harvest Derived @@ -787,7 +787,6 @@ mainInitialize(void) /* after this point we want to see the mallinfo() output */ do_mallinfo = 1; mimeInit(Config.mimeTablePathname); - pconnInit(); refreshInit(); #if DELAY_POOLS diff --git a/src/pconn.cc b/src/pconn.cc index 33b2335d01..a0b56ae748 100644 --- a/src/pconn.cc +++ b/src/pconn.cc @@ -1,6 +1,6 @@ /* - * $Id: pconn.cc,v 1.44 2004/08/30 05:12:31 robertc Exp $ + * $Id: pconn.cc,v 1.45 2005/12/06 23:03:34 wessels Exp $ * * DEBUG: section 48 Persistent Connections * AUTHOR: Duane Wessels @@ -36,224 +36,204 @@ #include "squid.h" #include "Store.h" #include "comm.h" - -struct _pconn -{ - hash_link hash; /* must be first */ - int *fds; - int nfds_alloc; - int nfds; - char buf[4096]; -}; - -typedef struct _pconn pconn; +#include "pconn.h" +#include "fde.h" #define PCONN_FDS_SZ 8 /* pconn set size, increase for better memcache hit rate */ -#define PCONN_HIST_SZ (1<<16) -int client_pconn_hist[PCONN_HIST_SZ]; -int server_pconn_hist[PCONN_HIST_SZ]; - -static IOCB pconnRead; -static PF pconnTimeout; -static const char *pconnKey(const char *host, u_short port, const char *domain); -static hash_table *table = NULL; - -static struct _pconn *pconnNew(const char *key); -static void pconnDelete(struct _pconn *p); - -static void pconnRemoveFD(struct _pconn *p, int fd); -static OBJH pconnHistDump; +static PconnModule *ThePconnModule = NULL; static MemAllocator *pconn_fds_pool = NULL; -CBDATA_TYPE(pconn); - +static OBJH PconnModuleDumpWrapper; +CBDATA_CLASS_INIT(IdleConnList); +/* ========== IdleConnList ============================================ */ -static const char * -pconnKey(const char *host, u_short port, const char *domain) +IdleConnList::IdleConnList(const char *key, PconnPool *thePool) : parent(thePool) { - LOCAL_ARRAY(char, buf, SQUIDHOSTNAMELEN * 2 + 10); - - if (domain) - snprintf(buf, SQUIDHOSTNAMELEN * 2 + 10, "%s:%d/%s", host, (int) port, domain); - else - snprintf(buf, SQUIDHOSTNAMELEN * 2 + 10, "%s:%d", host, (int) port); - - return buf; + hash.key = xstrdup(key); + nfds_alloc = PCONN_FDS_SZ; + nfds = 0; + fds = (int *)pconn_fds_pool->alloc(); } -static struct _pconn * - pconnNew(const char *key) +IdleConnList::~IdleConnList() { - pconn *p; - CBDATA_INIT_TYPE(pconn); - p = cbdataAlloc(pconn); - p->hash.key = xstrdup(key); - p->nfds_alloc = PCONN_FDS_SZ; - p->nfds = 0; - p->fds = (int *)pconn_fds_pool->alloc(); - debug(48, 3) ("pconnNew: adding %s\n", hashKeyStr(&p->hash)); - hash_join(table, &p->hash); - return p; -} -static void + parent->unlinkList(this); -pconnDelete(struct _pconn *p) -{ - debug(48, 3) ("pconnDelete: deleting %s\n", hashKeyStr(&p->hash)); - hash_remove_link(table, (hash_link *) p); - - if (p->nfds_alloc == PCONN_FDS_SZ) - pconn_fds_pool->free(p->fds); + if (nfds_alloc == PCONN_FDS_SZ) + pconn_fds_pool->free(fds); else - xfree(p->fds); - - xfree(p->hash.key); + xfree(fds); - cbdataFree(p); + xfree(hash.key); } -static int - -pconnFindFDIndex (struct _pconn *p, int fd) +int +IdleConnList::findFDIndex (int fd) { - int result; + int index; - for (result = p->nfds - 1; result >= 0; --result) - { - if (p->fds[result] == fd) - return result; + for (index = nfds - 1; index >= 0; --index) { + if (fds[index] == fd) + return index; } - return p->nfds; + return -1; } -static void - -pconnRemoveFDByIndex (struct _pconn *p, int index) +void +IdleConnList::removeFD(int fd) { - for (; index < p->nfds - 1; index++) - p->fds[index] = p->fds[index + 1]; -} + int index = findFDIndex(fd); + assert(index >= 0); + debug(48, 3) ("IdleConnList::removeFD: found FD %d at index %d\n", fd, index); -static void + for (; index < nfds - 1; index++) + fds[index] = fds[index + 1]; -pconnPreventHandingOutFD(struct _pconn *p, int fd) -{ - int i = pconnFindFDIndex (p, fd); - assert(i >= 0); - debug(48, 3) ("pconnRemoveFD: found FD %d at index %d\n", fd, i); - pconnRemoveFDByIndex(p, i); + if (--nfds == 0) { + debug(48, 3) ("IdleConnList::removeFD: deleting %s\n", hashKeyStr(&hash)); + delete this; + } } -static void +void +IdleConnList::clearHandlers(int fd) +{ + comm_read_cancel(fd, IdleConnList::read, this); + commSetTimeout(fd, -1, NULL, NULL); +} -pconnRemoveFD(struct _pconn *p, int fd) +void +IdleConnList::push(int fd) { - pconnPreventHandingOutFD(p, fd); + if (nfds == nfds_alloc) { + debug(48, 3) ("IdleConnList::push: growing FD array\n"); + nfds_alloc <<= 1; + int *old = fds; + fds = (int *)xmalloc(nfds_alloc * sizeof(int)); + xmemcpy(fds, old, nfds * sizeof(int)); + + if (nfds == PCONN_FDS_SZ) + pconn_fds_pool->free(old); + else + xfree(old); + } - if (--p->nfds == 0) - pconnDelete(p); + fds[nfds++] = fd; + comm_read(fd, fakeReadBuf, sizeof(fakeReadBuf), IdleConnList::read, this); + commSetTimeout(fd, Config.Timeout.pconn, IdleConnList::timeout, this); } -static void -pconnTimeout(int fd, void *data) +/* + * XXX this routine isn't terribly efficient - if there's a pending + * read event (which signifies the fd will close in the next IO loop!) + * we ignore the FD and move onto the next one. This means, as an example, + * if we have a lot of FDs open to a very popular server and we get a bunch + * of requests JUST as they timeout (say, it shuts down) we'll be wasting + * quite a bit of CPU. Just keep it in mind. + */ +int +IdleConnList::findUseableFD() { + assert(nfds); - struct _pconn *p = (_pconn *)data; - assert(table != NULL); - debug(48, 3) ("pconnTimeout: FD %d %s\n", fd, hashKeyStr(&p->hash)); - pconnRemoveFD(p, fd); - comm_close(fd); + for (int i = 0; i< nfds; i++) { + if (!comm_has_pending_read_callback(fds[i])) { + return fds[i]; + } + } + + return -1; } -static void -pconnRead(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data) +void +IdleConnList::read(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data) { - - struct _pconn *p = (_pconn *)data; - assert(table != NULL); - /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */ + debug(48, 3) ("IdleConnList::read: %d bytes from FD %d\n", (int) len, fd); if (flag == COMM_ERR_CLOSING) { + /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */ return; } - debug(48, 3) ("pconnRead: %d bytes from FD %d, %s\n", (int) len, fd, - hashKeyStr(&p->hash)); - pconnRemoveFD(p, fd); + IdleConnList *list = (IdleConnList *) data; + list->removeFD(fd); /* might delete list */ comm_close(fd); } -static void -pconnHistDump(StoreEntry * e) +void +IdleConnList::timeout(int fd, void *data) { - int i; - storeAppendPrintf(e, - "Client-side persistent connection counts:\n" - "\n" - "\treq/\n" - "\tconn count\n" - "\t---- ---------\n"); + debug(48, 3) ("IdleConnList::timeout: FD %d\n", fd); + IdleConnList *list = (IdleConnList *) data; + list->removeFD(fd); /* might delete list */ + comm_close(fd); +} - for (i = 0; i < PCONN_HIST_SZ; i++) { - if (client_pconn_hist[i] == 0) - continue; +/* ========== PconnPool PRIVATE FUNCTIONS ============================================ */ - storeAppendPrintf(e, "\t%4d %9d\n", i, client_pconn_hist[i]); - } +const char * +PconnPool::key(const char *host, u_short port, const char *domain) +{ + LOCAL_ARRAY(char, buf, SQUIDHOSTNAMELEN * 2 + 10); + + if (domain) + snprintf(buf, SQUIDHOSTNAMELEN * 2 + 10, "%s:%d/%s", host, (int) port, domain); + else + snprintf(buf, SQUIDHOSTNAMELEN * 2 + 10, "%s:%d", host, (int) port); + + return buf; +} +void +PconnPool::dumpHist(StoreEntry * e) +{ + int i; storeAppendPrintf(e, - "\n" - "Server-side persistent connection counts:\n" + "%s persistent connection counts:\n" "\n" "\treq/\n" "\tconn count\n" - "\t---- ---------\n"); + "\t---- ---------\n", + descr); for (i = 0; i < PCONN_HIST_SZ; i++) { - if (server_pconn_hist[i] == 0) + if (hist[i] == 0) continue; - storeAppendPrintf(e, "\t%4d %9d\n", i, server_pconn_hist[i]); + storeAppendPrintf(e, "\t%4d %9d\n", i, hist[i]); } } -/* ========== PUBLIC FUNCTIONS ============================================ */ +/* ========== PconnPool PUBLIC FUNCTIONS ============================================ */ - -void -pconnInit(void) +PconnPool::PconnPool(const char *aDescr) : table(NULL), descr(aDescr) { int i; - assert(table == NULL); table = hash_create((HASHCMP *) strcmp, 229, hash_string); - for (i = 0; i < PCONN_HIST_SZ; i++) { - client_pconn_hist[i] = 0; - server_pconn_hist[i] = 0; - } + for (i = 0; i < PCONN_HIST_SZ; i++) + hist[i] = 0; - pconn_fds_pool = MemPools::GetInstance().create("pconn_fds", PCONN_FDS_SZ * sizeof(int)); + if (ThePconnModule == NULL) + ThePconnModule = new PconnModule; - cachemgrRegister("pconn", - "Persistent Connection Utilization Histograms", - pconnHistDump, 0, 1); - debug(48, 3) ("persistent connection module initialized\n"); + ThePconnModule->add + (this); } void -pconnPush(int fd, const char *host, u_short port, const char *domain) +PconnPool::push(int fd, const char *host, u_short port, const char *domain) { - struct _pconn *p; - int *old; - LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10); + IdleConnList *list; + const char *aKey; LOCAL_ARRAY(char, desc, FD_DESC_SZ); if (fdUsageHigh()) { - debug(48, 3) ("pconnPush: Not many unused FDs\n"); + debug(48, 3) ("PconnPool::push: Not many unused FDs\n"); comm_close(fd); return; } else if (shutting_down) { @@ -261,91 +241,100 @@ pconnPush(int fd, const char *host, u_short port, const char *domain) return; } - assert(table != NULL); - strncpy(key, pconnKey(host, port, domain), SQUIDHOSTNAMELEN + 10); - - p = (struct _pconn *) hash_lookup(table, key); - - if (p == NULL) - p = pconnNew(key); + aKey = key(host, port, domain); - if (p->nfds == p->nfds_alloc) { - debug(48, 3) ("pconnPush: growing FD array\n"); - p->nfds_alloc <<= 1; - old = p->fds; - p->fds = (int *)xmalloc(p->nfds_alloc * sizeof(int)); - xmemcpy(p->fds, old, p->nfds * sizeof(int)); + list = (IdleConnList *) hash_lookup(table, aKey); - if (p->nfds == PCONN_FDS_SZ) - pconn_fds_pool->free(old); - else - xfree(old); + if (list == NULL) { + list = new IdleConnList(aKey, this); + debug(48, 3) ("pconnNew: adding %s\n", hashKeyStr(&list->hash)); + hash_join(table, &list->hash); } + list->push(fd); + assert(!comm_has_incomplete_write(fd)); - p->fds[p->nfds++] = fd; - comm_read(fd, p->buf, BUFSIZ, pconnRead, p); - commSetTimeout(fd, Config.Timeout.pconn, pconnTimeout, p); snprintf(desc, FD_DESC_SZ, "%s idle connection", host); fd_note(fd, desc); - debug(48, 3) ("pconnPush: pushed FD %d for %s\n", fd, key); + debug(48, 3) ("PconnPool::push: pushed FD %d for %s\n", fd, aKey); } /* * return a pconn fd for host:port, or -1 if none are available - * - * XXX this routine isn't terribly efficient - if there's a pending - * read event (which signifies the fd will close in the next IO loop!) - * we ignore the FD and move onto the next one. This means, as an example, - * if we have a lot of FDs open to a very popular server and we get a bunch - * of requests JUST as they timeout (say, it shuts down) we'll be wasting - * quite a bit of CPU. Just keep it in mind. */ int -pconnPop(const char *host, u_short port, const char *domain) +PconnPool::pop(const char *host, u_short port, const char *domain) { + IdleConnList *list; + const char * aKey = key(host, port, domain); + list = (IdleConnList *)hash_lookup(table, aKey); - struct _pconn *p; - hash_link *hptr; - int fd = -1; - LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10); - assert(table != NULL); - strncpy(key, pconnKey(host, port, domain), SQUIDHOSTNAMELEN + 10); - hptr = (hash_link *)hash_lookup(table, key); - - if (hptr != NULL) { - - p = (struct _pconn *) hptr; - assert(p->nfds > 0); - - for (int i = 0; i < p->nfds; i++) { - fd = p->fds[p->nfds - 1]; - /* If there are pending read callbacks - we're about to close it, so don't issue it! */ - - if (!comm_has_pending_read_callback(fd)) { - pconnRemoveFD(p, fd); - comm_read_cancel(fd, pconnRead, p); - commSetTimeout(fd, -1, NULL, NULL); - return fd; - } - } + if (list == NULL) + return -1; + + int fd = list->findUseableFD(); + + if (fd >= 0) { + list->clearHandlers(fd); + list->removeFD(fd); /* might delete list */ } - /* Nothing (valid!) found */ - return -1; + return fd; } void -pconnHistCount(int what, int i) +PconnPool::unlinkList(IdleConnList *list) const { - if (i >= PCONN_HIST_SZ) - i = PCONN_HIST_SZ - 1; - - /* what == 0 for client, 1 for server */ - if (what == 0) - client_pconn_hist[i]++; - else if (what == 1) - server_pconn_hist[i]++; - else - assert(0); + hash_remove_link(table, &list->hash); +} + +void +PconnPool::count(int uses) +{ + if (uses >= PCONN_HIST_SZ) + uses = PCONN_HIST_SZ - 1; + + hist[uses]++; +} + +/* ========== PconnModule ============================================ */ + +/* + * This simple class exists only for the cache manager + */ + +PconnModule::PconnModule() : pools(NULL), poolCount(0) +{ + pools = (PconnPool **) xcalloc(MAX_NUM_PCONN_POOLS, sizeof(*pools)); + cachemgrRegister("pconn", + "Persistent Connection Utilization Histograms", + PconnModuleDumpWrapper, 0, 1); + pconn_fds_pool = MemPools::GetInstance().create("pconn_fds", PCONN_FDS_SZ * sizeof(int)); + debug(48, 0) ("persistent connection module initialized\n"); +} + +void + +PconnModule::add + (PconnPool *aPool) +{ + assert(poolCount < MAX_NUM_PCONN_POOLS); + *(pools+poolCount) = aPool; + poolCount++; +} + +void +PconnModule::dump(StoreEntry *e) +{ + int i; + + for (i = 0; i < poolCount; i++) { + (*(pools+i))->dumpHist(e); + } +} + +static void +PconnModuleDumpWrapper(StoreEntry *e) +{ + ThePconnModule->dump(e); } diff --git a/src/pconn.h b/src/pconn.h new file mode 100644 index 0000000000..a8a08b556d --- /dev/null +++ b/src/pconn.h @@ -0,0 +1,80 @@ + +#ifndef SQUID_PCONN_H +#define SQUID_PCONN_H + +#define MAX_NUM_PCONN_POOLS 10 +#define PCONN_HIST_SZ (1<<16) + +class PconnPool; + +class IdleConnList +{ + +public: + IdleConnList(const char *key, PconnPool *parent); + ~IdleConnList(); + int numIdle() { return nfds; } + + int findFDIndex(int fd); + void removeFD(int fd); + void push(int fd); + int findUseableFD(); + void clearHandlers(int fd); + +private: + static IOCB read; + static PF timeout; + +public: + hash_link hash; /* must be first */ + +private: + int *fds; + int nfds_alloc; + int nfds; + PconnPool *parent; + char fakeReadBuf[4096]; + CBDATA_CLASS2(IdleConnList); +}; + +class PconnPool +{ + +public: + PconnPool(const char *); + + void moduleInit(); + void push(int fd, const char *host, u_short port, const char *domain); + int pop(const char *host, u_short port, const char *domain); + void count(int uses); + void dumpHist(StoreEntry *e); + void unlinkList(IdleConnList *list) const; + +private: + + static const char *key(const char *host, u_short port, const char *domain); + + int hist[PCONN_HIST_SZ]; + hash_table *table; + const char *descr; + +}; + +class PconnModule +{ + +public: + PconnModule(); + + void add + (PconnPool *); + + OBJH dump; + +private: + PconnPool **pools; + + int poolCount; +}; + +#endif /* SQUID_PCONN_H */ diff --git a/src/protos.h b/src/protos.h index 322ea12ae2..2e5e0c3c51 100644 --- a/src/protos.h +++ b/src/protos.h @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.514 2005/11/06 16:54:30 serassio Exp $ + * $Id: protos.h,v 1.515 2005/12/06 23:03:34 wessels Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -598,6 +598,7 @@ SQUIDCEXTERN void fwdComplete(FwdState * fwdState); SQUIDCEXTERN void fwdInit(void); SQUIDCEXTERN int fwdReforwardableStatus(http_status s); SQUIDCEXTERN void fwdServersFree(FwdServer ** FSVR); +SQUIDCEXTERN void fwdPconnPush(int, const char *, int, const char *); #if WIP_FWD_LOG SQUIDCEXTERN void fwdUninit(void); SQUIDCEXTERN void fwdLogRotate(void); @@ -852,10 +853,6 @@ SQUIDCEXTERN void errorStateFree(ErrorState * err); SQUIDCEXTERN err_type errorReservePageId(const char *page_name); SQUIDCEXTERN ErrorState *errorCon(err_type type, http_status); -SQUIDCEXTERN void pconnPush(int, const char *host, u_short port, const char *domain); -SQUIDCEXTERN int pconnPop(const char *host, u_short port, const char *domain); -SQUIDCEXTERN void pconnInit(void); - /* tools.c */ SQUIDCEXTERN void dlinkAdd(void *data, dlink_node *, dlink_list *); SQUIDCEXTERN void dlinkAddAfter(void *, dlink_node *, dlink_node *, dlink_list *);