pconn.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:6k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: pconn.c,v 1.25 1999/01/14 23:15:43 wessels Exp $
  3.  *
  4.  * DEBUG: section 48    Persistent Connections
  5.  * AUTHOR: Duane Wessels
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or modify
  20.  *  it under the terms of the GNU General Public License as published by
  21.  *  the Free Software Foundation; either version 2 of the License, or
  22.  *  (at your option) any later version.
  23.  *  
  24.  *  This program is distributed in the hope that it will be useful,
  25.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *  GNU General Public License for more details.
  28.  *  
  29.  *  You should have received a copy of the GNU General Public License
  30.  *  along with this program; if not, write to the Free Software
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. #include "squid.h"
  35. struct _pconn {
  36.     char *key;
  37.     struct _pconn *next;
  38.     int *fds;
  39.     int nfds_alloc;
  40.     int nfds;
  41. };
  42. #define PCONN_HIST_SZ (1<<16)
  43. int client_pconn_hist[PCONN_HIST_SZ];
  44. int server_pconn_hist[PCONN_HIST_SZ];
  45. static PF pconnRead;
  46. static PF pconnTimeout;
  47. static const char *pconnKey(const char *host, u_short port);
  48. static hash_table *table = NULL;
  49. static struct _pconn *pconnNew(const char *key);
  50. static void pconnDelete(struct _pconn *p);
  51. static void pconnRemoveFD(struct _pconn *p, int fd);
  52. static OBJH pconnHistDump;
  53. static const char *
  54. pconnKey(const char *host, u_short port)
  55. {
  56.     LOCAL_ARRAY(char, buf, SQUIDHOSTNAMELEN + 10);
  57.     snprintf(buf, SQUIDHOSTNAMELEN + 10, "%s.%d", host, (int) port);
  58.     return buf;
  59. }
  60. static struct _pconn *
  61. pconnNew(const char *key)
  62. {
  63.     struct _pconn *p = xcalloc(1, sizeof(struct _pconn));
  64.     p->key = xstrdup(key);
  65.     p->nfds_alloc = 2;
  66.     p->fds = xcalloc(p->nfds_alloc, sizeof(int));
  67.     debug(48, 3) ("pconnNew: adding %sn", p->key);
  68.     hash_join(table, (hash_link *) p);
  69.     return p;
  70. }
  71. static void
  72. pconnDelete(struct _pconn *p)
  73. {
  74.     debug(48, 3) ("pconnDelete: deleting %sn", p->key);
  75.     hash_remove_link(table, (hash_link *) p);
  76.     xfree(p->fds);
  77.     xfree(p->key);
  78.     xfree(p);
  79. }
  80. static void
  81. pconnRemoveFD(struct _pconn *p, int fd)
  82. {
  83.     int i;
  84.     for (i = 0; i < p->nfds; i++) {
  85. if (p->fds[i] == fd)
  86.     break;
  87.     }
  88.     assert(i < p->nfds);
  89.     debug(48, 3) ("pconnRemoveFD: found FD %d at index %dn", fd, i);
  90.     for (; i < p->nfds - 1; i++)
  91. p->fds[i] = p->fds[i + 1];
  92.     if (--p->nfds == 0)
  93. pconnDelete(p);
  94. }
  95. static void
  96. pconnTimeout(int fd, void *data)
  97. {
  98.     struct _pconn *p = data;
  99.     assert(table != NULL);
  100.     debug(48, 3) ("pconnTimeout: FD %d %sn", fd, p->key);
  101.     pconnRemoveFD(p, fd);
  102.     comm_close(fd);
  103. }
  104. static void
  105. pconnRead(int fd, void *data)
  106. {
  107.     LOCAL_ARRAY(char, buf, 256);
  108.     struct _pconn *p = data;
  109.     int n;
  110.     assert(table != NULL);
  111.     Counter.syscalls.sock.reads++;
  112.     n = read(fd, buf, 256);
  113.     debug(48, 3) ("pconnRead: %d bytes from FD %d, %sn", n, fd, p->key);
  114.     pconnRemoveFD(p, fd);
  115.     comm_close(fd);
  116. }
  117. static void
  118. pconnHistDump(StoreEntry * e)
  119. {
  120.     int i;
  121.     storeAppendPrintf(e,
  122. "Client-side persistent connection counts:n"
  123. "n"
  124. "treq/n"
  125. "tconn      countn"
  126. "t----  ---------n");
  127.     for (i = 0; i < PCONN_HIST_SZ; i++) {
  128. if (client_pconn_hist[i] == 0)
  129.     continue;
  130. storeAppendPrintf(e, "t%4d  %9dn", i, client_pconn_hist[i]);
  131.     }
  132.     storeAppendPrintf(e,
  133. "n"
  134. "Server-side persistent connection counts:n"
  135. "n"
  136. "treq/n"
  137. "tconn      countn"
  138. "t----  ---------n");
  139.     for (i = 0; i < PCONN_HIST_SZ; i++) {
  140. if (server_pconn_hist[i] == 0)
  141.     continue;
  142. storeAppendPrintf(e, "t%4d  %9dn", i, server_pconn_hist[i]);
  143.     }
  144. }
  145. /* ========== PUBLIC FUNCTIONS ============================================ */
  146. void
  147. pconnInit(void)
  148. {
  149.     int i;
  150.     assert(table == NULL);
  151.     table = hash_create((HASHCMP *) strcmp, 229, hash_string);
  152.     for (i = 0; i < PCONN_HIST_SZ; i++) {
  153. client_pconn_hist[i] = 0;
  154. server_pconn_hist[i] = 0;
  155.     }
  156.     cachemgrRegister("pconn",
  157. "Persistent Connection Utilization Histograms",
  158. pconnHistDump, 0, 1);
  159.     debug(48, 3) ("persistent connection module initializedn");
  160. }
  161. void
  162. pconnPush(int fd, const char *host, u_short port)
  163. {
  164.     struct _pconn *p;
  165.     int *old;
  166.     LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10);
  167.     LOCAL_ARRAY(char, desc, FD_DESC_SZ);
  168.     if (fdNFree() < (RESERVED_FD << 1)) {
  169. debug(48, 3) ("pconnPush: Not many unused FDsn");
  170. comm_close(fd);
  171. return;
  172.     } else if (shutting_down) {
  173. comm_close(fd);
  174. return;
  175.     }
  176.     assert(table != NULL);
  177.     strcpy(key, pconnKey(host, port));
  178.     p = (struct _pconn *) hash_lookup(table, key);
  179.     if (p == NULL)
  180. p = pconnNew(key);
  181.     if (p->nfds == p->nfds_alloc) {
  182. debug(48, 3) ("pconnPush: growing FD arrayn");
  183. p->nfds_alloc <<= 1;
  184. old = p->fds;
  185. p->fds = xmalloc(p->nfds_alloc * sizeof(int));
  186. xmemcpy(p->fds, old, p->nfds * sizeof(int));
  187. xfree(old);
  188.     }
  189.     p->fds[p->nfds++] = fd;
  190.     commSetSelect(fd, COMM_SELECT_READ, pconnRead, p, 0);
  191.     commSetTimeout(fd, Config.Timeout.pconn, pconnTimeout, p);
  192.     snprintf(desc, FD_DESC_SZ, "%s idle connection", host);
  193.     fd_note(fd, desc);
  194.     debug(48, 3) ("pconnPush: pushed FD %d for %sn", fd, key);
  195. }
  196. int
  197. pconnPop(const char *host, u_short port)
  198. {
  199.     struct _pconn *p;
  200.     hash_link *hptr;
  201.     int fd = -1;
  202.     LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10);
  203.     assert(table != NULL);
  204.     strcpy(key, pconnKey(host, port));
  205.     hptr = hash_lookup(table, key);
  206.     if (hptr != NULL) {
  207. p = (struct _pconn *) hptr;
  208. assert(p->nfds > 0);
  209. fd = p->fds[0];
  210. pconnRemoveFD(p, fd);
  211. commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
  212. commSetTimeout(fd, -1, NULL, NULL);
  213.     }
  214.     return fd;
  215. }
  216. void
  217. pconnHistCount(int what, int i)
  218. {
  219.     if (i >= PCONN_HIST_SZ)
  220. i = PCONN_HIST_SZ - 1;
  221.     /* what == 0 for client, 1 for server */
  222.     if (what == 0)
  223. client_pconn_hist[i]++;
  224.     else if (what == 1)
  225. server_pconn_hist[i]++;
  226.     else
  227. assert(0);
  228. }