--------------------- PatchSet 5229 Date: 2002/10/05 06:39:11 Author: rbcollins Branch: rbcollins_cxxtest Tag: (none) Log: more updates Members: include/util.h:1.11.20.1->1.11.20.2 src/Makefile.am:1.29.2.5->1.29.2.6 src/String.c:1.5->1.5.28.1(DEAD) src/String.cc:1.1->1.1.2.1 src/client.c:1.12->1.12.6.1(DEAD) src/client.cc:1.1->1.1.2.1 src/http.cc:1.1.2.4->1.1.2.5 src/http.h:1.1.6.1->1.1.6.2 src/mem.c:1.21.6.3->1.21.6.4(DEAD) src/mem.cc:1.1->1.1.2.1 src/stmem.c:1.8->1.8.6.1(DEAD) src/stmem.cc:1.1->1.1.2.1 Index: squid/include/util.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/util.h,v retrieving revision 1.11.20.1 retrieving revision 1.11.20.2 diff -u -r1.11.20.1 -r1.11.20.2 --- squid/include/util.h 3 Oct 2002 01:04:32 -0000 1.11.20.1 +++ squid/include/util.h 5 Oct 2002 06:39:11 -0000 1.11.20.2 @@ -1,5 +1,5 @@ /* - * $Id: util.h,v 1.11.20.1 2002/10/03 01:04:32 rbcollins Exp $ + * $Id: util.h,v 1.11.20.2 2002/10/05 06:39:11 rbcollins Exp $ * * AUTHOR: Harvest Derived * @@ -69,7 +69,7 @@ SQUIDCEXTERN char *xstrndup(const char *, size_t); SQUIDCEXTERN const char *xstrerror(void); extern const char *xbstrerror(int); -extern int tvSubMsec(struct timeval, struct timeval); +SQUIDCEXTERN int tvSubMsec(struct timeval, struct timeval); extern int tvSubUsec(struct timeval, struct timeval); extern double tvSubDsec(struct timeval, struct timeval); SQUIDCEXTERN char *xstrncpy(char *, const char *, size_t); @@ -117,9 +117,9 @@ SQUIDCEXTERN const char *base64_encode(const char *decoded); SQUIDCEXTERN const char *base64_encode_bin(const char *data, int len); -extern double xpercent(double part, double whole); -extern int xpercentInt(double part, double whole); -extern double xdiv(double nom, double denom); +SQUIDCEXTERN double xpercent(double part, double whole); +SQUIDCEXTERN int xpercentInt(double part, double whole); +SQUIDCEXTERN double xdiv(double nom, double denom); extern const char *xitoa(int num); @@ -139,7 +139,7 @@ #define gb_incb(gb, delta) { if ((gb)->bytes > gb_flush_limit || delta > gb_flush_limit) gb_flush(gb); (gb)->bytes += delta; } #define gb_incc(gb, delta) { if ((gb)->bytes > gb_flush_limit || delta > gb_flush_limit) gb_flush(gb); (gb)->count+= delta; } extern double gb_to_double(const gb_t *); -extern const char *double_to_str(char *buf, int buf_size, double value); +SQUIDCEXTERN const char *double_to_str(char *buf, int buf_size, double value); extern const char *gb_to_str(const gb_t *); extern void gb_flush(gb_t *); /* internal, do not use this */ Index: squid/src/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Makefile.am,v retrieving revision 1.29.2.5 retrieving revision 1.29.2.6 diff -u -r1.29.2.5 -r1.29.2.6 --- squid/src/Makefile.am 4 Oct 2002 21:22:09 -0000 1.29.2.5 +++ squid/src/Makefile.am 5 Oct 2002 06:39:11 -0000 1.29.2.6 @@ -98,7 +98,7 @@ cf_gen_SOURCES = cf_gen.c defines.h nodist_cf_gen_HEADER = cf_gen_defines.h cf_gen.$(OBJEXT): cf_gen_defines.h -squidclient_SOURCES = client.c +squidclient_SOURCES = client.cc cachemgr__CGIEXT__SOURCES = cachemgr.c EXTRA_squid_SOURCES = \ @@ -178,7 +178,7 @@ $(LEAKFINDERSOURCE) \ logfile.cc \ main.cc \ - mem.c \ + mem.cc \ MemBuf.c \ mime.c \ multicast.c \ @@ -200,8 +200,8 @@ $(SSLSOURCE) \ stat.c \ StatHist.c \ - String.c \ - stmem.c \ + String.cc \ + stmem.cc \ store.cc \ store_io.c \ StoreIOBuffer.h \ --- squid/src/String.c Wed Feb 14 01:07:20 2007 +++ /dev/null Wed Feb 14 01:05:20 2007 @@ -1,111 +0,0 @@ - -/* - * $Id: String.c,v 1.5 2002/02/13 17:24:42 squidadm Exp $ - * - * DEBUG: section 67 String - * 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 "squid.h" - -static void -stringInitBuf(String * s, size_t sz) -{ - s->buf = memAllocString(sz, &sz); - assert(sz < 65536); - s->size = sz; -} - -void -stringInit(String * s, const char *str) -{ - assert(s); - if (str) - stringLimitInit(s, str, strlen(str)); - else - *s = StringNull; -} - -void -stringLimitInit(String * s, const char *str, int len) -{ - assert(s && str); - stringInitBuf(s, len + 1); - s->len = len; - xmemcpy(s->buf, str, len); - s->buf[len] = '\0'; -} - -String -stringDup(const String * s) -{ - String dup; - assert(s); - stringInit(&dup, s->buf); - return dup; -} - -void -stringClean(String * s) -{ - assert(s); - if (s->buf) - memFreeString(s->size, s->buf); - *s = StringNull; -} - -void -stringReset(String * s, const char *str) -{ - stringClean(s); - stringInit(s, str); -} - -void -stringAppend(String * s, const char *str, int len) -{ - assert(s); - assert(str && len >= 0); - if (s->len + len < s->size) { - strncat(s->buf, str, len); - s->len += len; - } else { - String snew = StringNull; - snew.len = s->len + len; - stringInitBuf(&snew, snew.len + 1); - if (s->buf) - xmemcpy(snew.buf, s->buf, s->len); - if (len) - xmemcpy(snew.buf + s->len, str, len); - snew.buf[snew.len] = '\0'; - stringClean(s); - *s = snew; - } -} --- /dev/null Wed Feb 14 01:05:20 2007 +++ squid/src/String.cc Wed Feb 14 01:07:20 2007 @@ -0,0 +1,111 @@ + +/* + * $Id: String.cc,v 1.1.2.1 2002/10/05 06:41:56 rbcollins Exp $ + * + * DEBUG: section 67 String + * 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 "squid.h" + +static void +stringInitBuf(String * s, size_t sz) +{ + s->buf = (char *)memAllocString(sz, &sz); + assert(sz < 65536); + s->size = sz; +} + +void +stringInit(String * s, const char *str) +{ + assert(s); + if (str) + stringLimitInit(s, str, strlen(str)); + else + *s = StringNull; +} + +void +stringLimitInit(String * s, const char *str, int len) +{ + assert(s && str); + stringInitBuf(s, len + 1); + s->len = len; + xmemcpy(s->buf, str, len); + s->buf[len] = '\0'; +} + +String +stringDup(const String * s) +{ + String dup; + assert(s); + stringInit(&dup, s->buf); + return dup; +} + +void +stringClean(String * s) +{ + assert(s); + if (s->buf) + memFreeString(s->size, s->buf); + *s = StringNull; +} + +void +stringReset(String * s, const char *str) +{ + stringClean(s); + stringInit(s, str); +} + +void +stringAppend(String * s, const char *str, int len) +{ + assert(s); + assert(str && len >= 0); + if (s->len + len < s->size) { + strncat(s->buf, str, len); + s->len += len; + } else { + String snew = StringNull; + snew.len = s->len + len; + stringInitBuf(&snew, snew.len + 1); + if (s->buf) + xmemcpy(snew.buf, s->buf, s->len); + if (len) + xmemcpy(snew.buf + s->len, str, len); + snew.buf[snew.len] = '\0'; + stringClean(s); + *s = snew; + } +} --- squid/src/client.c Wed Feb 14 01:07:20 2007 +++ /dev/null Wed Feb 14 01:05:20 2007 @@ -1,503 +0,0 @@ - -/* - * $Id: client.c,v 1.12 2002/09/01 16:30:42 squidadm Exp $ - * - * DEBUG: section 0 WWW Client - * AUTHOR: Harvest Derived - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" - -#ifndef BUFSIZ -#define BUFSIZ 8192 -#endif - -/* Local functions */ -static int client_comm_bind(int, const char *); -static int client_comm_connect(int, const char *, u_short, struct timeval *); -static void usage(const char *progname); -static int Now(struct timeval *); -static SIGHDLR catch; -static SIGHDLR pipe_handler; -static void set_our_signal(void); -static ssize_t myread(int fd, void *buf, size_t len); -static ssize_t mywrite(int fd, void *buf, size_t len); -static int put_fd; -static char *put_file = NULL; -static struct stat sb; -int total_bytes = 0; -int io_timeout = 120; - -static void -usage(const char *progname) -{ - fprintf(stderr, - "Usage: %s [-arsv] [-i IMS] [-h remote host] [-l local host] [-p port] [-m method] [-t count] [-I ping-interval] [-H 'strings'] [-T timeout] url\n" - "Options:\n" - " -P file PUT request.\n" - " -a Do NOT include Accept: header.\n" - " -r Force cache to reload URL.\n" - " -s Silent. Do not print data to stdout.\n" - " -v Verbose. Print outgoing message to stderr.\n" - " -i IMS If-Modified-Since time (in Epoch seconds).\n" - " -h host Retrieve URL from cache on hostname. Default is localhost.\n" - " -l host Specify a local IP address to bind to. Default is none.\n" - " -p port Port number of cache. Default is %d.\n" - " -m method Request method, default is GET.\n" - " -t count Trace count cache-hops\n" - " -g count Ping mode, \"count\" iterations (0 to loop until interrupted).\n" - " -I interval Ping interval in seconds (default 1 second).\n" - " -H 'string' Extra headers to send. Use '\\n' for new lines.\n" - " -T timeout Timeout value (seconds) for read/write operations.\n" - " -u user Proxy authentication username\n" - " -w password Proxy authentication password\n" - " -U user WWW authentication username\n" - " -W password WWW authentication password\n", - progname, CACHE_HTTP_PORT); - exit(1); -} - -static int interrupted = 0; -int -main(int argc, char *argv[]) -{ - int conn, c, len, bytesWritten; - int port, to_stdout, reload; - int ping, pcount; - int keep_alive = 0; - int opt_noaccept = 0; - int opt_verbose = 0; - const char *hostname, *localhost; - char url[BUFSIZ], msg[BUFSIZ], buf[BUFSIZ]; - char extra_hdrs[BUFSIZ]; - const char *method = "GET"; - extern char *optarg; - time_t ims = 0; - int max_forwards = -1; - struct timeval tv1, tv2; - int i = 0, loops; - long ping_int; - long ping_min = 0, ping_max = 0, ping_sum = 0, ping_mean = 0; - char *proxy_user = NULL; - char *proxy_password = NULL; - char *www_user = NULL; - char *www_password = NULL; - - /* set the defaults */ - hostname = "localhost"; - localhost = NULL; - extra_hdrs[0] = '\0'; - port = CACHE_HTTP_PORT; - to_stdout = 1; - reload = 0; - ping = 0; - pcount = 0; - ping_int = 1 * 1000; - - if (argc < 2) { - usage(argv[0]); /* need URL */ - } else if (argc >= 2) { - strcpy(url, argv[argc - 1]); - if (url[0] == '-') - usage(argv[0]); - while ((c = getopt(argc, argv, "ah:l:P:i:km:p:rsvt:g:p:I:H:T:u:U:w:W:?")) != -1) - switch (c) { - case 'a': - opt_noaccept = 1; - break; - case 'h': /* remote host */ - if (optarg != NULL) - hostname = optarg; - break; - case 'l': /* local host */ - if (optarg != NULL) - localhost = optarg; - break; - case 's': /* silent */ - to_stdout = 0; - break; - case 'k': /* backward compat */ - keep_alive = 1; - break; - case 'r': /* reload */ - reload = 1; - break; - case 'p': /* port number */ - sscanf(optarg, "%d", &port); - if (port < 1) - port = CACHE_HTTP_PORT; /* default */ - break; - case 'P': - put_file = xstrdup(optarg); - break; - case 'i': /* IMS */ - ims = (time_t) atoi(optarg); - break; - case 'm': - method = xstrdup(optarg); - break; - case 't': - method = xstrdup("TRACE"); - max_forwards = atoi(optarg); - break; - case 'g': - ping = 1; - pcount = atoi(optarg); - to_stdout = 0; - break; - case 'I': - if ((ping_int = atoi(optarg) * 1000) <= 0) - usage(argv[0]); - break; - case 'H': - if (strlen(optarg)) { - char *t; - strncpy(extra_hdrs, optarg, sizeof(extra_hdrs)); - while ((t = strstr(extra_hdrs, "\\n"))) - *t = '\r', *(t + 1) = '\n'; - } - break; - case 'T': - io_timeout = atoi(optarg); - break; - case 'u': - proxy_user = optarg; - break; - case 'w': - proxy_password = optarg; - break; - case 'U': - www_user = optarg; - break; - case 'W': - www_password = optarg; - break; - case 'v': - /* undocumented: may increase verb-level by giving more -v's */ - opt_verbose++; - break; - case '?': /* usage */ - default: - usage(argv[0]); - break; - } - } - /* Build the HTTP request */ - if (strncmp(url, "mgr:", 4) == 0) { - char *t = xstrdup(url + 4); - snprintf(url, BUFSIZ, "cache_object://%s/%s", hostname, t); - xfree(t); - } - if (put_file) { - put_fd = open(put_file, O_RDONLY); - set_our_signal(); - if (put_fd < 0) { - fprintf(stderr, "%s: can't open file (%s)\n", argv[0], - xstrerror()); - exit(-1); - } -#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) - setmode(put_fd, O_BINARY); -#endif - fstat(put_fd, &sb); - } - snprintf(msg, BUFSIZ, "%s %s HTTP/1.0\r\n", method, url); - if (reload) { - snprintf(buf, BUFSIZ, "Pragma: no-cache\r\n"); - strcat(msg, buf); - } - if (put_fd > 0) { - snprintf(buf, BUFSIZ, "Content-length: %d\r\n", (int) sb.st_size); - strcat(msg, buf); - } - if (opt_noaccept == 0) { - snprintf(buf, BUFSIZ, "Accept: */*\r\n"); - strcat(msg, buf); - } - if (ims) { - snprintf(buf, BUFSIZ, "If-Modified-Since: %s\r\n", mkrfc1123(ims)); - strcat(msg, buf); - } - if (max_forwards > -1) { - snprintf(buf, BUFSIZ, "Max-Forwards: %d\r\n", max_forwards); - strcat(msg, buf); - } - if (proxy_user) { - char *user = proxy_user; - char *password = proxy_password; -#if HAVE_GETPASS - if (!password) - password = getpass("Proxy password: "); -#endif - if (!password) { - fprintf(stderr, "ERROR: Proxy password missing\n"); - exit(1); - } - snprintf(buf, BUFSIZ, "%s:%s", user, password); - snprintf(buf, BUFSIZ, "Proxy-Authorization: Basic %s\n", base64_encode(buf)); - strcat(msg, buf); - } - if (www_user) { - char *user = www_user; - char *password = www_password; -#if HAVE_GETPASS - if (!password) - password = getpass("WWW password: "); -#endif - if (!password) { - fprintf(stderr, "ERROR: WWW password missing\n"); - exit(1); - } - snprintf(buf, BUFSIZ, "%s:%s", user, password); - snprintf(buf, BUFSIZ, "Authorization: Basic %s\n", base64_encode(buf)); - strcat(msg, buf); - } - if (keep_alive) { - if (port != 80) - snprintf(buf, BUFSIZ, "Proxy-Connection: keep-alive\r\n"); - else - snprintf(buf, BUFSIZ, "Connection: keep-alive\r\n"); - strcat(msg, buf); - } - strcat(msg, extra_hdrs); - snprintf(buf, BUFSIZ, "\r\n"); - strcat(msg, buf); - - if (opt_verbose) - fprintf(stderr, "headers: '%s'\n", msg); - - if (ping) { -#if HAVE_SIGACTION - struct sigaction sa, osa; - if (sigaction(SIGINT, NULL, &osa) == 0 && osa.sa_handler == SIG_DFL) { - sa.sa_handler = catch; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - (void) sigaction(SIGINT, &sa, NULL); - } -#else - void (*osig) (); - if ((osig = signal(SIGINT, catch)) != SIG_DFL) - (void) signal(SIGINT, osig); -#endif - } - loops = ping ? pcount : 1; - for (i = 0; loops == 0 || i < loops; i++) { - int fsize = 0; - /* Connect to the server */ - if ((conn = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - perror("client: socket"); - exit(1); - } - if (localhost && client_comm_bind(conn, localhost) < 0) { - perror("client: bind"); - exit(1); - } - if (client_comm_connect(conn, hostname, port, ping ? &tv1 : NULL) < 0) { - if (errno == 0) { - fprintf(stderr, "client: ERROR: Cannot connect to %s:%d: Host unknown.\n", hostname, port); - } else { - char tbuf[BUFSIZ]; - snprintf(tbuf, BUFSIZ, "client: ERROR: Cannot connect to %s:%d", - hostname, port); - perror(tbuf); - } - exit(1); - } - /* Send the HTTP request */ - bytesWritten = mywrite(conn, msg, strlen(msg)); - if (bytesWritten < 0) { - perror("client: ERROR: write"); - exit(1); - } else if (bytesWritten != strlen(msg)) { - fprintf(stderr, "client: ERROR: Cannot send request?: %s\n", msg); - exit(1); - } - if (put_file) { - int x; - lseek(put_fd, 0, SEEK_SET); - while ((x = myread(put_fd, buf, sizeof(buf))) > 0) { - x = mywrite(conn, buf, x); - total_bytes += x; - if (x <= 0) - break; - } - if (x != 0) - fprintf(stderr, "client: ERROR: Cannot send file.\n"); - } - /* Read the data */ - - while ((len = myread(conn, buf, sizeof(buf))) > 0) { - fsize += len; - if (to_stdout) - fwrite(buf, len, 1, stdout); - } - (void) close(conn); /* done with socket */ - - if (interrupted) - break; - - if (ping) { - struct tm *tmp; - time_t t2s; - long elapsed_msec; - - (void) Now(&tv2); - elapsed_msec = tvSubMsec(tv1, tv2); - t2s = tv2.tv_sec; - tmp = localtime(&t2s); - fprintf(stderr, "%d-%02d-%02d %02d:%02d:%02d [%d]: %ld.%03ld secs, %f KB/s\n", - tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec, i + 1, - elapsed_msec / 1000, elapsed_msec % 1000, - elapsed_msec ? (double) fsize / elapsed_msec : -1.0); - if (i == 0 || elapsed_msec < ping_min) - ping_min = elapsed_msec; - if (i == 0 || elapsed_msec > ping_max) - ping_max = elapsed_msec; - ping_sum += elapsed_msec; - /* Delay until next "ping_int" boundary */ - if ((loops == 0 || i + 1 < loops) && elapsed_msec < ping_int) { - struct timeval tvs; - long msec_left = ping_int - elapsed_msec; - - tvs.tv_sec = msec_left / 1000; - tvs.tv_usec = (msec_left % 1000) * 1000; - select(0, NULL, NULL, NULL, &tvs); - } - } - } - - if (ping && i) { - ping_mean = ping_sum / i; - fprintf(stderr, "%d requests, round-trip (secs) min/avg/max = " - "%ld.%03ld/%ld.%03ld/%ld.%03ld\n", i, - ping_min / 1000, ping_min % 1000, ping_mean / 1000, ping_mean % 1000, - ping_max / 1000, ping_max % 1000); - } - exit(0); - /*NOTREACHED */ - return 0; -} - -static int -client_comm_bind(int sock, const char *local_host) -{ - static const struct hostent *hp = NULL; - static struct sockaddr_in from_addr; - - /* Set up the source socket address from which to send. */ - if (hp == NULL) { - from_addr.sin_family = AF_INET; - - if ((hp = gethostbyname(local_host)) == 0) { - return (-1); - } - xmemcpy(&from_addr.sin_addr, hp->h_addr, hp->h_length); - from_addr.sin_port = 0; - } - return bind(sock, (struct sockaddr *) &from_addr, sizeof(struct sockaddr_in)); -} - -static int -client_comm_connect(int sock, const char *dest_host, u_short dest_port, struct timeval *tvp) -{ - static const struct hostent *hp = NULL; - static struct sockaddr_in to_addr; - - /* Set up the destination socket address for message to send to. */ - if (hp == NULL) { - to_addr.sin_family = AF_INET; - - if ((hp = gethostbyname(dest_host)) == 0) { - return (-1); - } - xmemcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length); - to_addr.sin_port = htons(dest_port); - } - if (tvp) - (void) Now(tvp); - return connect(sock, (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in)); -} - -static int -Now(struct timeval *tp) -{ -#if GETTIMEOFDAY_NO_TZP - return gettimeofday(tp); -#else - return gettimeofday(tp, NULL); -#endif -} /* ARGSUSED */ - -static void -catch(int sig) -{ - interrupted = 1; - fprintf(stderr, "Interrupted.\n"); -} - -static void -pipe_handler(int sig) -{ - fprintf(stderr, "SIGPIPE received.\n"); -} - -static void -set_our_signal(void) -{ -#if HAVE_SIGACTION - struct sigaction sa; - sa.sa_handler = pipe_handler; - sa.sa_flags = SA_RESTART; - sigemptyset(&sa.sa_mask); - if (sigaction(SIGPIPE, &sa, NULL) < 0) { - fprintf(stderr, "Cannot set PIPE signal.\n"); - exit(-1); - } -#else - signal(SIGPIPE, pipe_handler); -#endif - -} - -static ssize_t -myread(int fd, void *buf, size_t len) -{ - alarm(io_timeout); - return read(fd, buf, len); -} - -static ssize_t -mywrite(int fd, void *buf, size_t len) -{ - alarm(io_timeout); - return write(fd, buf, len); -} --- /dev/null Wed Feb 14 01:05:20 2007 +++ squid/src/client.cc Wed Feb 14 01:07:20 2007 @@ -0,0 +1,503 @@ + +/* + * $Id: client.cc,v 1.1.2.1 2002/10/05 06:41:57 rbcollins Exp $ + * + * DEBUG: section 0 WWW Client + * AUTHOR: Harvest Derived + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" + +#ifndef BUFSIZ +#define BUFSIZ 8192 +#endif + +/* Local functions */ +static int client_comm_bind(int, const char *); +static int client_comm_connect(int, const char *, u_short, struct timeval *); +static void usage(const char *progname); +static int Now(struct timeval *); +static SIGHDLR catchSignal; +static SIGHDLR pipe_handler; +static void set_our_signal(void); +static ssize_t myread(int fd, void *buf, size_t len); +static ssize_t mywrite(int fd, void *buf, size_t len); +static int put_fd; +static char *put_file = NULL; +static struct stat sb; +int total_bytes = 0; +int io_timeout = 120; + +static void +usage(const char *progname) +{ + fprintf(stderr, + "Usage: %s [-arsv] [-i IMS] [-h remote host] [-l local host] [-p port] [-m method] [-t count] [-I ping-interval] [-H 'strings'] [-T timeout] url\n" + "Options:\n" + " -P file PUT request.\n" + " -a Do NOT include Accept: header.\n" + " -r Force cache to reload URL.\n" + " -s Silent. Do not print data to stdout.\n" + " -v Verbose. Print outgoing message to stderr.\n" + " -i IMS If-Modified-Since time (in Epoch seconds).\n" + " -h host Retrieve URL from cache on hostname. Default is localhost.\n" + " -l host Specify a local IP address to bind to. Default is none.\n" + " -p port Port number of cache. Default is %d.\n" + " -m method Request method, default is GET.\n" + " -t count Trace count cache-hops\n" + " -g count Ping mode, \"count\" iterations (0 to loop until interrupted).\n" + " -I interval Ping interval in seconds (default 1 second).\n" + " -H 'string' Extra headers to send. Use '\\n' for new lines.\n" + " -T timeout Timeout value (seconds) for read/write operations.\n" + " -u user Proxy authentication username\n" + " -w password Proxy authentication password\n" + " -U user WWW authentication username\n" + " -W password WWW authentication password\n", + progname, CACHE_HTTP_PORT); + exit(1); +} + +static int interrupted = 0; +int +main(int argc, char *argv[]) +{ + int conn, c, len, bytesWritten; + int port, to_stdout, reload; + int ping, pcount; + int keep_alive = 0; + int opt_noaccept = 0; + int opt_verbose = 0; + const char *hostname, *localhost; + char url[BUFSIZ], msg[BUFSIZ], buf[BUFSIZ]; + char extra_hdrs[BUFSIZ]; + const char *method = "GET"; + extern char *optarg; + time_t ims = 0; + int max_forwards = -1; + struct timeval tv1, tv2; + int i = 0, loops; + long ping_int; + long ping_min = 0, ping_max = 0, ping_sum = 0, ping_mean = 0; + char *proxy_user = NULL; + char *proxy_password = NULL; + char *www_user = NULL; + char *www_password = NULL; + + /* set the defaults */ + hostname = "localhost"; + localhost = NULL; + extra_hdrs[0] = '\0'; + port = CACHE_HTTP_PORT; + to_stdout = 1; + reload = 0; + ping = 0; + pcount = 0; + ping_int = 1 * 1000; + + if (argc < 2) { + usage(argv[0]); /* need URL */ + } else if (argc >= 2) { + strcpy(url, argv[argc - 1]); + if (url[0] == '-') + usage(argv[0]); + while ((c = getopt(argc, argv, "ah:l:P:i:km:p:rsvt:g:p:I:H:T:u:U:w:W:?")) != -1) + switch (c) { + case 'a': + opt_noaccept = 1; + break; + case 'h': /* remote host */ + if (optarg != NULL) + hostname = optarg; + break; + case 'l': /* local host */ + if (optarg != NULL) + localhost = optarg; + break; + case 's': /* silent */ + to_stdout = 0; + break; + case 'k': /* backward compat */ + keep_alive = 1; + break; + case 'r': /* reload */ + reload = 1; + break; + case 'p': /* port number */ + sscanf(optarg, "%d", &port); + if (port < 1) + port = CACHE_HTTP_PORT; /* default */ + break; + case 'P': + put_file = xstrdup(optarg); + break; + case 'i': /* IMS */ + ims = (time_t) atoi(optarg); + break; + case 'm': + method = xstrdup(optarg); + break; + case 't': + method = xstrdup("TRACE"); + max_forwards = atoi(optarg); + break; + case 'g': + ping = 1; + pcount = atoi(optarg); + to_stdout = 0; + break; + case 'I': + if ((ping_int = atoi(optarg) * 1000) <= 0) + usage(argv[0]); + break; + case 'H': + if (strlen(optarg)) { + char *t; + strncpy(extra_hdrs, optarg, sizeof(extra_hdrs)); + while ((t = strstr(extra_hdrs, "\\n"))) + *t = '\r', *(t + 1) = '\n'; + } + break; + case 'T': + io_timeout = atoi(optarg); + break; + case 'u': + proxy_user = optarg; + break; + case 'w': + proxy_password = optarg; + break; + case 'U': + www_user = optarg; + break; + case 'W': + www_password = optarg; + break; + case 'v': + /* undocumented: may increase verb-level by giving more -v's */ + opt_verbose++; + break; + case '?': /* usage */ + default: + usage(argv[0]); + break; + } + } + /* Build the HTTP request */ + if (strncmp(url, "mgr:", 4) == 0) { + char *t = xstrdup(url + 4); + snprintf(url, BUFSIZ, "cache_object://%s/%s", hostname, t); + xfree(t); + } + if (put_file) { + put_fd = open(put_file, O_RDONLY); + set_our_signal(); + if (put_fd < 0) { + fprintf(stderr, "%s: can't open file (%s)\n", argv[0], + xstrerror()); + exit(-1); + } +#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) + setmode(put_fd, O_BINARY); +#endif + fstat(put_fd, &sb); + } + snprintf(msg, BUFSIZ, "%s %s HTTP/1.0\r\n", method, url); + if (reload) { + snprintf(buf, BUFSIZ, "Pragma: no-cache\r\n"); + strcat(msg, buf); + } + if (put_fd > 0) { + snprintf(buf, BUFSIZ, "Content-length: %d\r\n", (int) sb.st_size); + strcat(msg, buf); + } + if (opt_noaccept == 0) { + snprintf(buf, BUFSIZ, "Accept: */*\r\n"); + strcat(msg, buf); + } + if (ims) { + snprintf(buf, BUFSIZ, "If-Modified-Since: %s\r\n", mkrfc1123(ims)); + strcat(msg, buf); + } + if (max_forwards > -1) { + snprintf(buf, BUFSIZ, "Max-Forwards: %d\r\n", max_forwards); + strcat(msg, buf); + } + if (proxy_user) { + char *user = proxy_user; + char *password = proxy_password; +#if HAVE_GETPASS + if (!password) + password = getpass("Proxy password: "); +#endif + if (!password) { + fprintf(stderr, "ERROR: Proxy password missing\n"); + exit(1); + } + snprintf(buf, BUFSIZ, "%s:%s", user, password); + snprintf(buf, BUFSIZ, "Proxy-Authorization: Basic %s\n", base64_encode(buf)); + strcat(msg, buf); + } + if (www_user) { + char *user = www_user; + char *password = www_password; +#if HAVE_GETPASS + if (!password) + password = getpass("WWW password: "); +#endif + if (!password) { + fprintf(stderr, "ERROR: WWW password missing\n"); + exit(1); + } + snprintf(buf, BUFSIZ, "%s:%s", user, password); + snprintf(buf, BUFSIZ, "Authorization: Basic %s\n", base64_encode(buf)); + strcat(msg, buf); + } + if (keep_alive) { + if (port != 80) + snprintf(buf, BUFSIZ, "Proxy-Connection: keep-alive\r\n"); + else + snprintf(buf, BUFSIZ, "Connection: keep-alive\r\n"); + strcat(msg, buf); + } + strcat(msg, extra_hdrs); + snprintf(buf, BUFSIZ, "\r\n"); + strcat(msg, buf); + + if (opt_verbose) + fprintf(stderr, "headers: '%s'\n", msg); + + if (ping) { +#if HAVE_SIGACTION + struct sigaction sa, osa; + if (sigaction(SIGINT, NULL, &osa) == 0 && osa.sa_handler == SIG_DFL) { + sa.sa_handler = catchSignal; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + (void) sigaction(SIGINT, &sa, NULL); + } +#else + void (*osig) (); + if ((osig = signal(SIGINT, catchSignal)) != SIG_DFL) + (void) signal(SIGINT, osig); +#endif + } + loops = ping ? pcount : 1; + for (i = 0; loops == 0 || i < loops; i++) { + int fsize = 0; + /* Connect to the server */ + if ((conn = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + perror("client: socket"); + exit(1); + } + if (localhost && client_comm_bind(conn, localhost) < 0) { + perror("client: bind"); + exit(1); + } + if (client_comm_connect(conn, hostname, port, ping ? &tv1 : NULL) < 0) { + if (errno == 0) { + fprintf(stderr, "client: ERROR: Cannot connect to %s:%d: Host unknown.\n", hostname, port); + } else { + char tbuf[BUFSIZ]; + snprintf(tbuf, BUFSIZ, "client: ERROR: Cannot connect to %s:%d", + hostname, port); + perror(tbuf); + } + exit(1); + } + /* Send the HTTP request */ + bytesWritten = mywrite(conn, msg, strlen(msg)); + if (bytesWritten < 0) { + perror("client: ERROR: write"); + exit(1); + } else if ((unsigned) bytesWritten != strlen(msg)) { + fprintf(stderr, "client: ERROR: Cannot send request?: %s\n", msg); + exit(1); + } + if (put_file) { + int x; + lseek(put_fd, 0, SEEK_SET); + while ((x = myread(put_fd, buf, sizeof(buf))) > 0) { + x = mywrite(conn, buf, x); + total_bytes += x; + if (x <= 0) + break; + } + if (x != 0) + fprintf(stderr, "client: ERROR: Cannot send file.\n"); + } + /* Read the data */ + + while ((len = myread(conn, buf, sizeof(buf))) > 0) { + fsize += len; + if (to_stdout) + fwrite(buf, len, 1, stdout); + } + (void) close(conn); /* done with socket */ + + if (interrupted) + break; + + if (ping) { + struct tm *tmp; + time_t t2s; + long elapsed_msec; + + (void) Now(&tv2); + elapsed_msec = tvSubMsec(tv1, tv2); + t2s = tv2.tv_sec; + tmp = localtime(&t2s); + fprintf(stderr, "%d-%02d-%02d %02d:%02d:%02d [%d]: %ld.%03ld secs, %f KB/s\n", + tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec, i + 1, + elapsed_msec / 1000, elapsed_msec % 1000, + elapsed_msec ? (double) fsize / elapsed_msec : -1.0); + if (i == 0 || elapsed_msec < ping_min) + ping_min = elapsed_msec; + if (i == 0 || elapsed_msec > ping_max) + ping_max = elapsed_msec; + ping_sum += elapsed_msec; + /* Delay until next "ping_int" boundary */ + if ((loops == 0 || i + 1 < loops) && elapsed_msec < ping_int) { + struct timeval tvs; + long msec_left = ping_int - elapsed_msec; + + tvs.tv_sec = msec_left / 1000; + tvs.tv_usec = (msec_left % 1000) * 1000; + select(0, NULL, NULL, NULL, &tvs); + } + } + } + + if (ping && i) { + ping_mean = ping_sum / i; + fprintf(stderr, "%d requests, round-trip (secs) min/avg/max = " + "%ld.%03ld/%ld.%03ld/%ld.%03ld\n", i, + ping_min / 1000, ping_min % 1000, ping_mean / 1000, ping_mean % 1000, + ping_max / 1000, ping_max % 1000); + } + exit(0); + /*NOTREACHED */ + return 0; +} + +static int +client_comm_bind(int sock, const char *local_host) +{ + static const struct hostent *hp = NULL; + static struct sockaddr_in from_addr; + + /* Set up the source socket address from which to send. */ + if (hp == NULL) { + from_addr.sin_family = AF_INET; + + if ((hp = gethostbyname(local_host)) == 0) { + return (-1); + } + xmemcpy(&from_addr.sin_addr, hp->h_addr, hp->h_length); + from_addr.sin_port = 0; + } + return bind(sock, (struct sockaddr *) &from_addr, sizeof(struct sockaddr_in)); +} + +static int +client_comm_connect(int sock, const char *dest_host, u_short dest_port, struct timeval *tvp) +{ + static const struct hostent *hp = NULL; + static struct sockaddr_in to_addr; + + /* Set up the destination socket address for message to send to. */ + if (hp == NULL) { + to_addr.sin_family = AF_INET; + + if ((hp = gethostbyname(dest_host)) == 0) { + return (-1); + } + xmemcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length); + to_addr.sin_port = htons(dest_port); + } + if (tvp) + (void) Now(tvp); + return connect(sock, (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in)); +} + +static int +Now(struct timeval *tp) +{ +#if GETTIMEOFDAY_NO_TZP + return gettimeofday(tp); +#else + return gettimeofday(tp, NULL); +#endif +} /* ARGSUSED */ + +static void +catchSignal(int sig) +{ + interrupted = 1; + fprintf(stderr, "Interrupted.\n"); +} + +static void +pipe_handler(int sig) +{ + fprintf(stderr, "SIGPIPE received.\n"); +} + +static void +set_our_signal(void) +{ +#if HAVE_SIGACTION + struct sigaction sa; + sa.sa_handler = pipe_handler; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGPIPE, &sa, NULL) < 0) { + fprintf(stderr, "Cannot set PIPE signal.\n"); + exit(-1); + } +#else + signal(SIGPIPE, pipe_handler); +#endif + +} + +static ssize_t +myread(int fd, void *buf, size_t len) +{ + alarm(io_timeout); + return read(fd, buf, len); +} + +static ssize_t +mywrite(int fd, void *buf, size_t len) +{ + alarm(io_timeout); + return write(fd, buf, len); +} Index: squid/src/http.cc =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/http.cc,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -u -r1.1.2.4 -r1.1.2.5 --- squid/src/http.cc 4 Oct 2002 22:35:17 -0000 1.1.2.4 +++ squid/src/http.cc 5 Oct 2002 06:39:11 -0000 1.1.2.5 @@ -1,6 +1,6 @@ /* - * $Id: http.cc,v 1.1.2.4 2002/10/04 22:35:17 rbcollins Exp $ + * $Id: http.cc,v 1.1.2.5 2002/10/05 06:39:11 rbcollins Exp $ * * DEBUG: section 11 Hypertext Transfer Protocol (HTTP) * AUTHOR: Harvest Derived @@ -39,9 +39,9 @@ */ #include "squid.h" +#include "http.h" #include "authenticate.h" #include "Store.h" -#include "http.h" CBDATA_TYPE(HttpStateData); @@ -390,63 +390,71 @@ /* rewrite this later using new interfaces @?@ */ void -httpProcessReplyHeader(HttpStateData * httpState, const char *buf, int size) +HttpStateData::processReplyHeader(const char *buf, int size) { char *t = NULL; - StoreEntry *entry = httpState->entry; int room; size_t hdr_len; HttpReply *reply = entry->mem_obj->reply; Ctx ctx; debug(11, 3) ("httpProcessReplyHeader: key '%s'\n", storeKeyText((const cache_key *)(entry->hash.key))); - if (httpState->reply_hdr == NULL) - httpState->reply_hdr = (char *)memAllocate(MEM_8K_BUF); - assert(httpState->reply_hdr_state == 0); - hdr_len = httpState->reply_hdr_size; + if (reply_hdr == NULL) + reply_hdr = (char *)memAllocate(MEM_8K_BUF); + assert(reply_hdr_state == 0); + hdr_len = reply_hdr_size; room = 8191 - hdr_len; - xmemcpy(httpState->reply_hdr + hdr_len, buf, room < size ? room : size); + xmemcpy(reply_hdr + hdr_len, buf, room < size ? room : size); hdr_len += room < size ? room : size; - httpState->reply_hdr[hdr_len] = '\0'; - httpState->reply_hdr_size = hdr_len; - if (hdr_len > 4 && strncmp(httpState->reply_hdr, "HTTP/", 5)) { - debug(11, 3) ("httpProcessReplyHeader: Non-HTTP-compliant header: '%s'\n", httpState->reply_hdr); - httpState->reply_hdr_state += 2; + reply_hdr[hdr_len] = '\0'; + reply_hdr_size = hdr_len; + if (hdr_len > 4 && strncmp(reply_hdr, "HTTP/", 5)) { + debug(11, 3) ("httpProcessReplyHeader: Non-HTTP-compliant header: '%s'\n", reply_hdr); + reply_hdr_state += 2; reply->sline.status = HTTP_INVALID_HEADER; + if (eof == 1) { + fwdComplete(fwd); + comm_close(fd); + } return; } - t = httpState->reply_hdr + hdr_len; + t = reply_hdr + hdr_len; /* headers can be incomplete only if object still arriving */ - if (!httpState->eof) { - size_t k = headersEnd(httpState->reply_hdr, 8192); - if (0 == k) + if (!eof) { + size_t k = headersEnd(reply_hdr, 8192); + if (0 == k) { + if (eof == 1) { + fwdComplete(fwd); + comm_close(fd); + } return; /* headers not complete */ - t = httpState->reply_hdr + k; + } + t = reply_hdr + k; } *t = '\0'; - httpState->reply_hdr_state++; - assert(httpState->reply_hdr_state == 1); + reply_hdr_state++; + assert(reply_hdr_state == 1); ctx = ctx_enter(entry->mem_obj->url); - httpState->reply_hdr_state++; + reply_hdr_state++; debug(11, 9) ("GOT HTTP REPLY HDR:\n---------\n%s\n----------\n", - httpState->reply_hdr); + reply_hdr); /* Parse headers into reply structure */ /* what happens if we fail to parse here? */ - httpReplyParse(reply, httpState->reply_hdr, hdr_len); + httpReplyParse(reply, reply_hdr, hdr_len); storeTimestampsSet(entry); /* Check if object is cacheable or not based on reply code */ debug(11, 3) ("httpProcessReplyHeader: HTTP CODE: %d\n", reply->sline.status); if (neighbors_do_private_keys) httpMaybeRemovePublic(entry, reply->sline.status); - switch (httpCachableReply(httpState)) { + switch (httpCachableReply(this)) { case 1: if (httpHeaderHas(&reply->header, HDR_VARY) #if X_ACCELERATOR_VARY || httpHeaderHas(&reply->header, HDR_X_ACCELERATOR_VARY) #endif ) { - const char *vary = httpMakeVaryMark(httpState->orig_request, reply); + const char *vary = httpMakeVaryMark(orig_request, reply); if (vary) { entry->mem_obj->vary_headers = xstrdup(vary); /* Kill the old base object if a change in variance is detected */ @@ -474,22 +482,26 @@ else if (EBIT_TEST(reply->cache_control->mask, CC_MUST_REVALIDATE)) EBIT_SET(entry->flags, ENTRY_REVALIDATE); } - if (httpState->flags.keepalive) - if (httpState->_peer) - httpState->_peer->stats.n_keepalives_sent++; + if (flags.keepalive) + if (_peer) + _peer->stats.n_keepalives_sent++; if (reply->keep_alive) - if (httpState->_peer) - httpState->_peer->stats.n_keepalives_recv++; - if (reply->date > -1 && !httpState->_peer) { + if (_peer) + _peer->stats.n_keepalives_recv++; + if (reply->date > -1 && !_peer) { int skew = abs(reply->date - squid_curtime); if (skew > 86400) debug(11, 3) ("%s's clock is skewed by %d seconds!\n", - httpState->request->host, skew); + request->host, skew); } ctx_exit(ctx); #if HEADERS_LOG - headersLog(1, 0, httpState->request->method, reply); + headersLog(1, 0, request->method, reply); #endif + if (eof == 1) { + fwdComplete(fwd); + comm_close(fd); + } } static int @@ -631,12 +643,15 @@ * the end of headers, but now we are definately at EOF, so * we want to process the reply headers. */ - httpProcessReplyHeader(httpState, buf, len); - fwdComplete(httpState->fwd); - comm_close(fd); + /* doesn't return */ + httpState->processReplyHeader(buf, len); + else { + fwdComplete(httpState->fwd); + comm_close(fd); + } } else { if (httpState->reply_hdr_state < 2) { - httpProcessReplyHeader(httpState, buf, len); + httpState->processReplyHeader(buf, len); if (httpState->reply_hdr_state == 2) { http_status s = entry->mem_obj->reply->sline.status; #if WIP_FWD_LOG @@ -650,32 +665,38 @@ EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); } } - storeAppend(entry, buf, len); - if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { - /* - * the above storeAppend() call could ABORT this entry, - * in that case, the server FD should already be closed. - * there's nothing for us to do. - */ - (void) 0; - } else if (httpPconnTransferDone(httpState)) { - /* yes we have to clear all these! */ - commSetDefer(fd, NULL, NULL); - commSetTimeout(fd, -1, NULL, NULL); - commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); + httpState->processReplyData(buf, len); + } +} + +void +HttpStateData::processReplyData(const char *buf, int len) +{ + storeAppend(entry, buf, len); + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { + /* + * the above storeAppend() call could ABORT this entry, + * in that case, the server FD should already be closed. + * there's nothing for us to do. + */ + (void) 0; + } else if (httpPconnTransferDone(this)) { + /* yes we have to clear all these! */ + commSetDefer(fd, NULL, NULL); + commSetTimeout(fd, -1, NULL, NULL); + commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); #if DELAY_POOLS - delayClearNoDelay(fd); + delayClearNoDelay(fd); #endif - comm_remove_close_handler(fd, httpStateFree, httpState); - fwdUnregister(fd, httpState->fwd); - pconnPush(fd, request->host, request->port); - fwdComplete(httpState->fwd); - httpState->fd = -1; - httpStateFree(fd, httpState); - } else { - /* Wait for EOF condition */ - commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0); - } + comm_remove_close_handler(fd, httpStateFree, this); + fwdUnregister(fd, fwd); + pconnPush(fd, request->host, request->port); + fwdComplete(fwd); + fd = -1; + httpStateFree(fd, this); + } else { + /* Wait for EOF condition */ + commSetSelect(fd, COMM_SELECT_READ, httpReadReply, this, 0); } } Index: squid/src/http.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/http.h,v retrieving revision 1.1.6.1 retrieving revision 1.1.6.2 diff -u -r1.1.6.1 -r1.1.6.2 --- squid/src/http.h 4 Oct 2002 22:35:17 -0000 1.1.6.1 +++ squid/src/http.h 5 Oct 2002 06:39:11 -0000 1.1.6.2 @@ -1,6 +1,6 @@ /* - * $Id: http.h,v 1.1.6.1 2002/10/04 22:35:17 rbcollins Exp $ + * $Id: http.h,v 1.1.6.2 2002/10/05 06:39:11 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -38,6 +38,9 @@ class HttpStateData { public: + void processReplyHeader(const char *, int); + void processReplyData(const char *, int); + StoreEntry *entry; request_t *request; char *reply_hdr; @@ -51,6 +54,4 @@ FwdState *fwd; }; -void httpProcessReplyHeader(HttpStateData *, const char *, int); - #endif /* SQUID_HTTP_H */ --- squid/src/mem.c Wed Feb 14 01:07:20 2007 +++ /dev/null Wed Feb 14 01:05:20 2007 @@ -1,651 +0,0 @@ - -/* - * $Id: mem.c,v 1.21.6.3 2002/10/04 11:09:07 rbcollins Exp $ - * - * DEBUG: section 13 High Level Memory Pool Management - * AUTHOR: Harvest Derived - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "memMeter.h" -#include "Store.h" - -/* module globals */ - -/* local prototypes */ -static void memStringStats(StoreEntry * sentry); -static void memStats(StoreEntry * sentry); -static void memPoolReport(const MemPoolStats * mp_st, const MemPoolMeter * AllMeter, StoreEntry * e); - -/* module locals */ -static MemPool *MemPools[MEM_MAX]; -static double xm_time = 0; -static double xm_deltat = 0; - -/* string pools */ -#define mem_str_pool_count 3 -static const struct { - const char *name; - size_t obj_size; -} StrPoolsAttrs[mem_str_pool_count] = { - - { - "Short Strings", 36, - }, /* to fit rfc1123 and similar */ - { - "Medium Strings", 128, - }, /* to fit most urls */ - { - "Long Strings", 512 - } /* other */ -}; -static struct { - MemPool *pool; -} StrPools[mem_str_pool_count]; -static MemMeter StrCountMeter; -static MemMeter StrVolumeMeter; - -static MemMeter HugeBufCountMeter; -static MemMeter HugeBufVolumeMeter; - -/* local routines */ - -static void -memStringStats(StoreEntry * sentry) -{ - const char *pfmt = "%-20s\t %d\t %d\n"; - int i; - int pooled_count = 0; - size_t pooled_volume = 0; - /* heading */ - storeAppendPrintf(sentry, - "String Pool\t Impact\t\t\n" - " \t (%%strings)\t (%%volume)\n"); - /* table body */ - for (i = 0; i < mem_str_pool_count; i++) { - const MemPool *pool = StrPools[i].pool; - const int plevel = pool->meter.inuse.level; - storeAppendPrintf(sentry, pfmt, - pool->label, - xpercentInt(plevel, StrCountMeter.level), - xpercentInt(plevel * pool->obj_size, StrVolumeMeter.level)); - pooled_count += plevel; - pooled_volume += plevel * pool->obj_size; - } - /* malloc strings */ - storeAppendPrintf(sentry, pfmt, - "Other Strings", - xpercentInt(StrCountMeter.level - pooled_count, StrCountMeter.level), - xpercentInt(StrVolumeMeter.level - pooled_volume, StrVolumeMeter.level)); - storeAppendPrintf(sentry, "\n"); -} - -static void -memBufStats(StoreEntry * sentry) -{ - storeAppendPrintf(sentry, "Large buffers: %d (%d KB)\n", - HugeBufCountMeter.level, - HugeBufVolumeMeter.level / 1024); -} - -static void -memStats(StoreEntry * sentry) -{ - storeBuffer(sentry); - memReport(sentry); - memStringStats(sentry); - memBufStats(sentry); - storeBufferFlush(sentry); -} - -/* - * public routines - */ - -int -memPoolInUseCount(MemPool * pool) -{ - MemPoolStats stats; - assert(pool); - memPoolGetStats(&stats, pool); - return stats.items_inuse; -} - -int -memPoolsTotalAllocated(void) -{ - MemPoolGlobalStats stats; - memPoolGetGlobalStats(&stats); - return stats.TheMeter->alloc.level; -} - -/* - * we have a limit on _total_ amount of idle memory so we ignore - * max_pages for now - */ -void -memDataInit(mem_type type, const char *name, size_t size, int max_pages_notused) -{ - assert(name && size); - assert(MemPools[type] == NULL); - MemPools[type] = memPoolCreate(name, size); -} - - -/* find appropriate pool and use it (pools always init buffer with 0s) */ -void * -memAllocate(mem_type type) -{ - return memPoolAlloc(MemPools[type]); -} - -/* give memory back to the pool */ -void -memFree(void *p, int type) -{ - memPoolFree(MemPools[type], p); -} - -/* allocate a variable size buffer using best-fit pool */ -void * -memAllocString(size_t net_size, size_t * gross_size) -{ - int i; - MemPool *pool = NULL; - assert(gross_size); - for (i = 0; i < mem_str_pool_count; i++) { - if (net_size <= StrPoolsAttrs[i].obj_size) { - pool = StrPools[i].pool; - break; - } - } - *gross_size = pool ? pool->obj_size : net_size; - assert(*gross_size >= net_size); - memMeterInc(StrCountMeter); - memMeterAdd(StrVolumeMeter, *gross_size); - return pool ? memPoolAlloc(pool) : xcalloc(1, net_size); -} - -/* free buffer allocated with memAllocString() */ -void -memFreeString(size_t size, void *buf) -{ - int i; - MemPool *pool = NULL; - assert(size && buf); - for (i = 0; i < mem_str_pool_count; i++) { - if (size <= StrPoolsAttrs[i].obj_size) { - assert(size == StrPoolsAttrs[i].obj_size); - pool = StrPools[i].pool; - break; - } - } - memMeterDec(StrCountMeter); - memMeterDel(StrVolumeMeter, size); - pool ? memPoolFree(pool, buf) : xfree(buf); -} - -/* Find the best fit MEM_X_BUF type */ -static mem_type -memFindBufSizeType(size_t net_size, size_t * gross_size) -{ - mem_type type; - size_t size; - if (net_size <= 2 * 1024) { - type = MEM_2K_BUF; - size = 2 * 1024; - } else if (net_size <= 4 * 1024) { - type = MEM_4K_BUF; - size = 4 * 1024; - } else if (net_size <= 8 * 1024) { - type = MEM_8K_BUF; - size = 8 * 1024; - } else if (net_size <= 16 * 1024) { - type = MEM_16K_BUF; - size = 16 * 1024; - } else if (net_size <= 32 * 1024) { - type = MEM_32K_BUF; - size = 32 * 1024; - } else if (net_size <= 64 * 1024) { - type = MEM_64K_BUF; - size = 64 * 1024; - } else { - type = MEM_NONE; - size = net_size; - } - if (gross_size) - *gross_size = size; - return type; -} - -/* allocate a variable size buffer using best-fit pool */ -void * -memAllocBuf(size_t net_size, size_t * gross_size) -{ - mem_type type = memFindBufSizeType(net_size, gross_size); - if (type != MEM_NONE) - return memAllocate(type); - else { - memMeterInc(HugeBufCountMeter); - memMeterAdd(HugeBufVolumeMeter, *gross_size); - return xcalloc(1, net_size); - } -} - -/* resize a variable sized buffer using best-fit pool */ -void * -memReallocBuf(void *oldbuf, size_t net_size, size_t * gross_size) -{ - /* XXX This can be optimized on very large buffers to use realloc() */ - /* TODO: if the existing gross size is >= new gross size, do nothing */ - int new_gross_size; - void *newbuf = memAllocBuf(net_size, &new_gross_size); - if (oldbuf) { - int data_size = *gross_size; - if (data_size > net_size) - data_size = net_size; - memcpy(newbuf, oldbuf, data_size); - memFreeBuf(*gross_size, oldbuf); - } - *gross_size = new_gross_size; - return newbuf; -} - -/* free buffer allocated with memAllocBuf() */ -void -memFreeBuf(size_t size, void *buf) -{ - mem_type type = memFindBufSizeType(size, NULL); - if (type != MEM_NONE) - memFree(buf, type); - else { - xfree(buf); - memMeterDec(HugeBufCountMeter); - memMeterDel(HugeBufVolumeMeter, size); - } -} - -static double clean_interval = 15.0; /* time to live of idle chunk before release */ - -void -memPoolCleanIdlePools(void *unused) -{ - memPoolClean(clean_interval); - eventAdd("memPoolCleanIdlePools", memPoolCleanIdlePools, NULL, clean_interval, 1); -} - -static int mem_idle_limit = 0; - -void -memConfigure(void) -{ - int new_pool_limit; - /* set to configured value first */ - if (!Config.onoff.mem_pools) - new_pool_limit = 0; - else if (Config.MemPools.limit > 0) - new_pool_limit = Config.MemPools.limit; - else - new_pool_limit = mem_unlimited_size; - - if (mem_idle_limit > new_pool_limit) - debug(13, 1) ("Shrinking idle mem pools to %.2f MB\n", toMB(new_pool_limit)); - memPoolSetIdleLimit(new_pool_limit); - mem_idle_limit = new_pool_limit; -} - -void -memInit(void) -{ - int i; - - debug(13, 1) ("Memory pools are '%s'; limit: %.2f MB\n", - (Config.onoff.mem_pools ? "on" : "off"), toMB(mem_idle_limit)); - - /* set all pointers to null */ - memset(MemPools, '\0', sizeof(MemPools)); - /* - * it does not hurt much to have a lot of pools since sizeof(MemPool) is - * small; someday we will figure out what to do with all the entries here - * that are never used or used only once; perhaps we should simply use - * malloc() for those? @?@ - */ - memDataInit(MEM_2K_BUF, "2K Buffer", 2048, 10); - memDataInit(MEM_4K_BUF, "4K Buffer", 4096, 10); - memDataInit(MEM_8K_BUF, "8K Buffer", 8192, 10); - memDataInit(MEM_16K_BUF, "16K Buffer", 16384, 10); - memDataInit(MEM_32K_BUF, "32K Buffer", 32768, 10); - memDataInit(MEM_64K_BUF, "64K Buffer", 65536, 10); - memDataInit(MEM_ACL, "acl", sizeof(acl), 0); - memDataInit(MEM_ACL_DENY_INFO_LIST, "acl_deny_info_list", - sizeof(acl_deny_info_list), 0); - memDataInit(MEM_ACL_IP_DATA, "acl_ip_data", sizeof(acl_ip_data), 0); - memDataInit(MEM_ACL_LIST, "acl_list", sizeof(acl_list), 0); - memDataInit(MEM_ACL_NAME_LIST, "acl_name_list", sizeof(acl_name_list), 0); - memDataInit(MEM_ACL_TIME_DATA, "acl_time_data", sizeof(acl_time_data), 0); - memDataInit(MEM_ACL_PROXY_AUTH_MATCH, "acl_proxy_auth_match_cache", - sizeof(acl_proxy_auth_match_cache), 0); - memDataInit(MEM_ACL_USER_DATA, "acl_user_data", - sizeof(acl_user_data), 0); -#if USE_CACHE_DIGESTS - memDataInit(MEM_CACHE_DIGEST, "CacheDigest", sizeof(CacheDigest), 0); -#endif - memDataInit(MEM_LINK_LIST, "link_list", sizeof(link_list), 10); - memDataInit(MEM_DLINK_NODE, "dlink_node", sizeof(dlink_node), 10); - memDataInit(MEM_DREAD_CTRL, "dread_ctrl", sizeof(dread_ctrl), 0); - memDataInit(MEM_DWRITE_Q, "dwrite_q", sizeof(dwrite_q), 0); - memDataInit(MEM_FWD_SERVER, "FwdServer", sizeof(FwdServer), 0); - memDataInit(MEM_HTTP_REPLY, "HttpReply", sizeof(HttpReply), 0); - memDataInit(MEM_HTTP_HDR_ENTRY, "HttpHeaderEntry", sizeof(HttpHeaderEntry), 0); - memDataInit(MEM_HTTP_HDR_CC, "HttpHdrCc", sizeof(HttpHdrCc), 0); - memDataInit(MEM_HTTP_HDR_RANGE_SPEC, "HttpHdrRangeSpec", sizeof(HttpHdrRangeSpec), 0); - memDataInit(MEM_HTTP_HDR_RANGE, "HttpHdrRange", sizeof(HttpHdrRange), 0); - memDataInit(MEM_HTTP_HDR_CONTENT_RANGE, "HttpHdrContRange", sizeof(HttpHdrContRange), 0); - memDataInit(MEM_INTLIST, "intlist", sizeof(intlist), 0); - memDataInit(MEM_MEMOBJECT, "MemObject", sizeof(MemObject), - Squid_MaxFD >> 3); - memDataInit(MEM_MEM_NODE, "mem_node", sizeof(mem_node), 0); - memDataInit(MEM_NETDBENTRY, "netdbEntry", sizeof(netdbEntry), 0); - memDataInit(MEM_NET_DB_NAME, "net_db_name", sizeof(net_db_name), 0); - memDataInit(MEM_RELIST, "relist", sizeof(relist), 0); - memDataInit(MEM_REQUEST_T, "request_t", sizeof(request_t), - Squid_MaxFD >> 3); - memDataInit(MEM_WORDLIST, "wordlist", sizeof(wordlist), 0); - memDataInit(MEM_CLIENT_INFO, "ClientInfo", sizeof(ClientInfo), 0); - memDataInit(MEM_MD5_DIGEST, "MD5 digest", MD5_DIGEST_CHARS, 0); - memPoolSetChunkSize(MemPools[MEM_MD5_DIGEST], 512 * 1024); - memDataInit(MEM_HELPER_REQUEST, "helper_request", - sizeof(helper_request), 0); - memDataInit(MEM_HELPER_STATEFUL_REQUEST, "helper_stateful_request", - sizeof(helper_stateful_request), 0); - memDataInit(MEM_TLV, "storeSwapTLV", sizeof(tlv), 0); - memDataInit(MEM_SWAP_LOG_DATA, "storeSwapLogData", sizeof(storeSwapLogData), 0); - - /* init string pools */ - for (i = 0; i < mem_str_pool_count; i++) { - StrPools[i].pool = memPoolCreate(StrPoolsAttrs[i].name, StrPoolsAttrs[i].obj_size); - } - cachemgrRegister("mem", - "Memory Utilization", - memStats, 0, 1); -} - -/* - * Test that all entries are initialized - */ -void -memCheckInit(void) -{ - mem_type t; - for (t = MEM_NONE, t++; t < MEM_MAX; t++) { - if (MEM_DONTFREE == t) - continue; - /* - * If you hit this assertion, then you forgot to add a - * memDataInit() line for type 't'. - */ - assert(MemPools[t]); - } -} - -#if UNUSED_CODE -/* to-do: make debug level a parameter? */ -static void memPoolDescribe(const MemPool * pool); -static void -memPoolDescribe(const MemPool * pool) -{ - assert(pool); - debug(13, 2) ("%-20s: %6d x %4d bytes = %5d KB\n", - pool->label, memPoolInUseCount(pool), pool->obj_size, - toKB(pool->obj_size * pool->meter.inuse.level)); -} - -#endif - -void -memClean(void) -{ - MemPoolGlobalStats stats; - memPoolSetIdleLimit(0); - memPoolClean(0); - memPoolGetGlobalStats(&stats); - if (stats.tot_items_inuse) - debug(13, 2) ("memCleanModule: %d items in %d chunks and %d pools are left dirty\n", stats.tot_items_inuse, - stats.tot_chunks_inuse, stats.tot_pools_inuse); -} - -int -memInUse(mem_type type) -{ - return memPoolInUseCount(MemPools[type]); -} - -/* ick */ - -static void -memFree2K(void *p) -{ - memFree(p, MEM_2K_BUF); -} - -void -memFree4K(void *p) -{ - memFree(p, MEM_4K_BUF); -} - -void -memFree8K(void *p) -{ - memFree(p, MEM_8K_BUF); -} - -static void -memFree16K(void *p) -{ - memFree(p, MEM_16K_BUF); -} - -static void -memFree32K(void *p) -{ - memFree(p, MEM_32K_BUF); -} - -static void -memFree64K(void *p) -{ - memFree(p, MEM_64K_BUF); -} - -FREE * -memFreeBufFunc(size_t size) -{ - switch (size) { - case 2 * 1024: - return memFree2K; - case 4 * 1024: - return memFree4K; - case 8 * 1024: - return memFree8K; - case 16 * 1024: - return memFree16K; - case 32 * 1024: - return memFree32K; - case 64 * 1024: - return memFree64K; - default: - memMeterDec(HugeBufCountMeter); - memMeterDel(HugeBufVolumeMeter, size); - return xfree; - } -} - -/* MemPoolMeter */ - -static void -memPoolReport(const MemPoolStats * mp_st, const MemPoolMeter * AllMeter, StoreEntry * e) -{ - int excess = 0; - int needed = 0; - MemPoolMeter *pm = mp_st->meter; - - storeAppendPrintf(e, "%-20s\t %4d\t ", - mp_st->label, mp_st->obj_size); - - /* Chunks */ - storeAppendPrintf(e, "%4d\t %4d\t ", - toKB(mp_st->obj_size * mp_st->chunk_capacity), mp_st->chunk_capacity); - - if (mp_st->chunk_capacity) { - needed = mp_st->items_inuse / mp_st->chunk_capacity; - if (mp_st->items_inuse % mp_st->chunk_capacity) - needed++; - excess = mp_st->chunks_inuse - needed; - } - storeAppendPrintf(e, "%4d\t %4d\t %4d\t %4d\t %.1f\t ", - mp_st->chunks_alloc, mp_st->chunks_inuse, mp_st->chunks_free, mp_st->chunks_partial, - xpercent(excess, needed)); -/* - * Fragmentation calculation: - * needed = inuse.level / chunk_capacity - * excess = used - needed - * fragmentation = excess / needed * 100% - * - * Fragm = (alloced - (inuse / obj_ch) ) / alloced - */ - - storeAppendPrintf(e, - "%d\t %d\t %d\t %.2f\t %.1f\t" /* alloc */ - "%d\t %d\t %d\t %.1f\t" /* in use */ - "%d\t %d\t %d\t" /* idle */ - "%.0f\t %.1f\t %.1f\t %.1f\n", /* saved */ - /* alloc */ - mp_st->items_alloc, - toKB(mp_st->obj_size * pm->alloc.level), - toKB(mp_st->obj_size * pm->alloc.hwater_level), - (double) ((squid_curtime - pm->alloc.hwater_stamp) / 3600.), - xpercent(mp_st->obj_size * pm->alloc.level, AllMeter->alloc.level), - /* in use */ - mp_st->items_inuse, - toKB(mp_st->obj_size * pm->inuse.level), - toKB(mp_st->obj_size * pm->inuse.hwater_level), - xpercent(pm->inuse.level, pm->alloc.level), - /* idle */ - mp_st->items_idle, - toKB(mp_st->obj_size * pm->idle.level), - toKB(mp_st->obj_size * pm->idle.hwater_level), - /* saved */ - pm->gb_saved.count, - xpercent(pm->gb_saved.count, AllMeter->gb_saved.count), - xpercent(pm->gb_saved.bytes, AllMeter->gb_saved.bytes), - xdiv(pm->gb_saved.count - pm->gb_osaved.count, xm_deltat)); - pm->gb_osaved.count = pm->gb_saved.count; -} - -void -memReport(StoreEntry * e) -{ - static char buf[64]; - static MemPoolStats mp_stats; - static MemPoolGlobalStats mp_total; - int not_used = 0; - MemPoolIterator *iter; - MemPool *pool; - - /* caption */ - storeAppendPrintf(e, "Current memory usage:\n"); - /* heading */ - storeAppendPrintf(e, - "Pool\t Obj Size\t" - "Chunks\t\t\t\t\t\t\t" - "Allocated\t\t\t\t\t" - "In Use\t\t\t\t" - "Idle\t\t\t" - "Allocations Saved\t\t\t" - "Hit Rate\t" - "\n" - " \t (bytes)\t" - "KB/ch\t obj/ch\t" - "(#)\t used\t free\t part\t %%Frag\t " - "(#)\t (KB)\t high (KB)\t high (hrs)\t %%Tot\t" - "(#)\t (KB)\t high (KB)\t %%alloc\t" - "(#)\t (KB)\t high (KB)\t" - "(#)\t %%cnt\t %%vol\t" - "(#) / sec\t" - "\n"); - xm_deltat = current_dtime - xm_time; - xm_time = current_dtime; - - /* Get stats for Totals report line */ - memPoolGetGlobalStats(&mp_total); - - /* main table */ - iter = memPoolIterate(); - while ((pool = memPoolIterateNext(iter))) { - memPoolGetStats(&mp_stats, pool); - if (!mp_stats.pool) /* pool destroyed */ - continue; - if (mp_stats.pool->meter.gb_saved.count > 0) /* this pool has been used */ - memPoolReport(&mp_stats, mp_total.TheMeter, e); - else - not_used++; - } - memPoolIterateDone(&iter); - - mp_stats.pool = NULL; - mp_stats.label = "Total"; - mp_stats.meter = mp_total.TheMeter; - mp_stats.obj_size = 1; - mp_stats.chunk_capacity = 0; - mp_stats.chunk_size = 0; - mp_stats.chunks_alloc = mp_total.tot_chunks_alloc; - mp_stats.chunks_inuse = mp_total.tot_chunks_inuse; - mp_stats.chunks_partial = mp_total.tot_chunks_partial; - mp_stats.chunks_free = mp_total.tot_chunks_free; - mp_stats.items_alloc = mp_total.tot_items_alloc; - mp_stats.items_inuse = mp_total.tot_items_inuse; - mp_stats.items_idle = mp_total.tot_items_idle; - mp_stats.overhead = mp_total.tot_overhead; - - memPoolReport(&mp_stats, mp_total.TheMeter, e); - - /* Cumulative */ - storeAppendPrintf(e, "Cumulative allocated volume: %s\n", double_to_str(buf, 64, mp_total.TheMeter->gb_saved.bytes)); - /* overhead */ - storeAppendPrintf(e, "Current overhead: %d bytes (%.3f%%)\n", - mp_total.tot_overhead, xpercent(mp_total.tot_overhead, mp_total.TheMeter->inuse.level)); - /* limits */ - storeAppendPrintf(e, "Idle pool limit: %.2f MB\n", toMB(mp_total.mem_idle_limit)); - /* limits */ - storeAppendPrintf(e, "Total Pools created: %d\n", mp_total.tot_pools_alloc); - storeAppendPrintf(e, "Pools ever used: %d (shown above)\n", mp_total.tot_pools_alloc - not_used); - storeAppendPrintf(e, "Currently in use: %d\n", mp_total.tot_pools_inuse); -} --- /dev/null Wed Feb 14 01:05:20 2007 +++ squid/src/mem.cc Wed Feb 14 01:07:20 2007 @@ -0,0 +1,657 @@ + +/* + * $Id: mem.cc,v 1.1.2.1 2002/10/05 06:41:57 rbcollins Exp $ + * + * DEBUG: section 13 High Level Memory Pool Management + * AUTHOR: Harvest Derived + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" +#include "memMeter.h" +#include "Store.h" + +/* module globals */ + +/* local prototypes */ +static void memStringStats(StoreEntry * sentry); +static void memStats(StoreEntry * sentry); +static void memPoolReport(const MemPoolStats * mp_st, const MemPoolMeter * AllMeter, StoreEntry * e); + +/* module locals */ +static MemPool *MemPools[MEM_MAX]; +static double xm_time = 0; +static double xm_deltat = 0; + +/* string pools */ +#define mem_str_pool_count 3 +static const struct { + const char *name; + size_t obj_size; +} StrPoolsAttrs[mem_str_pool_count] = { + + { + "Short Strings", 36, + }, /* to fit rfc1123 and similar */ + { + "Medium Strings", 128, + }, /* to fit most urls */ + { + "Long Strings", 512 + } /* other */ +}; +static struct { + MemPool *pool; +} StrPools[mem_str_pool_count]; +static MemMeter StrCountMeter; +static MemMeter StrVolumeMeter; + +static MemMeter HugeBufCountMeter; +static MemMeter HugeBufVolumeMeter; + +/* local routines */ + +static void +memStringStats(StoreEntry * sentry) +{ + const char *pfmt = "%-20s\t %d\t %d\n"; + int i; + int pooled_count = 0; + size_t pooled_volume = 0; + /* heading */ + storeAppendPrintf(sentry, + "String Pool\t Impact\t\t\n" + " \t (%%strings)\t (%%volume)\n"); + /* table body */ + for (i = 0; i < mem_str_pool_count; i++) { + const MemPool *pool = StrPools[i].pool; + const int plevel = pool->meter.inuse.level; + storeAppendPrintf(sentry, pfmt, + pool->label, + xpercentInt(plevel, StrCountMeter.level), + xpercentInt(plevel * pool->obj_size, StrVolumeMeter.level)); + pooled_count += plevel; + pooled_volume += plevel * pool->obj_size; + } + /* malloc strings */ + storeAppendPrintf(sentry, pfmt, + "Other Strings", + xpercentInt(StrCountMeter.level - pooled_count, StrCountMeter.level), + xpercentInt(StrVolumeMeter.level - pooled_volume, StrVolumeMeter.level)); + storeAppendPrintf(sentry, "\n"); +} + +static void +memBufStats(StoreEntry * sentry) +{ + storeAppendPrintf(sentry, "Large buffers: %d (%d KB)\n", + HugeBufCountMeter.level, + HugeBufVolumeMeter.level / 1024); +} + +static void +memStats(StoreEntry * sentry) +{ + storeBuffer(sentry); + memReport(sentry); + memStringStats(sentry); + memBufStats(sentry); + storeBufferFlush(sentry); +} + +/* + * public routines + */ + +int +memPoolInUseCount(MemPool * pool) +{ + MemPoolStats stats; + assert(pool); + memPoolGetStats(&stats, pool); + return stats.items_inuse; +} + +int +memPoolsTotalAllocated(void) +{ + MemPoolGlobalStats stats; + memPoolGetGlobalStats(&stats); + return stats.TheMeter->alloc.level; +} + +/* + * we have a limit on _total_ amount of idle memory so we ignore + * max_pages for now + */ +void +memDataInit(mem_type type, const char *name, size_t size, int max_pages_notused) +{ + assert(name && size); + assert(MemPools[type] == NULL); + MemPools[type] = memPoolCreate(name, size); +} + + +/* find appropriate pool and use it (pools always init buffer with 0s) */ +void * +memAllocate(mem_type type) +{ + return memPoolAlloc(MemPools[type]); +} + +/* give memory back to the pool */ +void +memFree(void *p, int type) +{ + memPoolFree(MemPools[type], p); +} + +/* allocate a variable size buffer using best-fit pool */ +void * +memAllocString(size_t net_size, size_t * gross_size) +{ + int i; + MemPool *pool = NULL; + assert(gross_size); + for (i = 0; i < mem_str_pool_count; i++) { + if (net_size <= StrPoolsAttrs[i].obj_size) { + pool = StrPools[i].pool; + break; + } + } + *gross_size = pool ? pool->obj_size : net_size; + assert(*gross_size >= net_size); + memMeterInc(StrCountMeter); + memMeterAdd(StrVolumeMeter, *gross_size); + return pool ? memPoolAlloc(pool) : xcalloc(1, net_size); +} + +/* free buffer allocated with memAllocString() */ +void +memFreeString(size_t size, void *buf) +{ + int i; + MemPool *pool = NULL; + assert(size && buf); + for (i = 0; i < mem_str_pool_count; i++) { + if (size <= StrPoolsAttrs[i].obj_size) { + assert(size == StrPoolsAttrs[i].obj_size); + pool = StrPools[i].pool; + break; + } + } + memMeterDec(StrCountMeter); + memMeterDel(StrVolumeMeter, size); + pool ? memPoolFree(pool, buf) : xfree(buf); +} + +/* Find the best fit MEM_X_BUF type */ +static mem_type +memFindBufSizeType(size_t net_size, size_t * gross_size) +{ + mem_type type; + size_t size; + if (net_size <= 2 * 1024) { + type = MEM_2K_BUF; + size = 2 * 1024; + } else if (net_size <= 4 * 1024) { + type = MEM_4K_BUF; + size = 4 * 1024; + } else if (net_size <= 8 * 1024) { + type = MEM_8K_BUF; + size = 8 * 1024; + } else if (net_size <= 16 * 1024) { + type = MEM_16K_BUF; + size = 16 * 1024; + } else if (net_size <= 32 * 1024) { + type = MEM_32K_BUF; + size = 32 * 1024; + } else if (net_size <= 64 * 1024) { + type = MEM_64K_BUF; + size = 64 * 1024; + } else { + type = MEM_NONE; + size = net_size; + } + if (gross_size) + *gross_size = size; + return type; +} + +/* allocate a variable size buffer using best-fit pool */ +void * +memAllocBuf(size_t net_size, size_t * gross_size) +{ + mem_type type = memFindBufSizeType(net_size, gross_size); + if (type != MEM_NONE) + return memAllocate(type); + else { + memMeterInc(HugeBufCountMeter); + memMeterAdd(HugeBufVolumeMeter, *gross_size); + return xcalloc(1, net_size); + } +} + +/* resize a variable sized buffer using best-fit pool */ +void * +memReallocBuf(void *oldbuf, size_t net_size, size_t * gross_size) +{ + /* XXX This can be optimized on very large buffers to use realloc() */ + /* TODO: if the existing gross size is >= new gross size, do nothing */ + size_t new_gross_size; + void *newbuf = memAllocBuf(net_size, &new_gross_size); + if (oldbuf) { + size_t data_size = *gross_size; + if (data_size > net_size) + data_size = net_size; + memcpy(newbuf, oldbuf, data_size); + memFreeBuf(*gross_size, oldbuf); + } + *gross_size = new_gross_size; + return newbuf; +} + +/* free buffer allocated with memAllocBuf() */ +void +memFreeBuf(size_t size, void *buf) +{ + mem_type type = memFindBufSizeType(size, NULL); + if (type != MEM_NONE) + memFree(buf, type); + else { + xfree(buf); + memMeterDec(HugeBufCountMeter); + memMeterDel(HugeBufVolumeMeter, size); + } +} + +static double clean_interval = 15.0; /* time to live of idle chunk before release */ + +void +memPoolCleanIdlePools(void *unused) +{ + memPoolClean(static_cast(clean_interval)); + eventAdd("memPoolCleanIdlePools", memPoolCleanIdlePools, NULL, clean_interval, 1); +} + +static int mem_idle_limit = 0; + +void +memConfigure(void) +{ + int new_pool_limit; + /* set to configured value first */ + if (!Config.onoff.mem_pools) + new_pool_limit = 0; + else if (Config.MemPools.limit > 0) + new_pool_limit = Config.MemPools.limit; + else + new_pool_limit = mem_unlimited_size; + + if (mem_idle_limit > new_pool_limit) + debug(13, 1) ("Shrinking idle mem pools to %.2f MB\n", toMB(new_pool_limit)); + memPoolSetIdleLimit(new_pool_limit); + mem_idle_limit = new_pool_limit; +} + +void +memInit(void) +{ + int i; + + debug(13, 1) ("Memory pools are '%s'; limit: %.2f MB\n", + (Config.onoff.mem_pools ? "on" : "off"), toMB(mem_idle_limit)); + + /* set all pointers to null */ + memset(MemPools, '\0', sizeof(MemPools)); + /* + * it does not hurt much to have a lot of pools since sizeof(MemPool) is + * small; someday we will figure out what to do with all the entries here + * that are never used or used only once; perhaps we should simply use + * malloc() for those? @?@ + */ + memDataInit(MEM_2K_BUF, "2K Buffer", 2048, 10); + memDataInit(MEM_4K_BUF, "4K Buffer", 4096, 10); + memDataInit(MEM_8K_BUF, "8K Buffer", 8192, 10); + memDataInit(MEM_16K_BUF, "16K Buffer", 16384, 10); + memDataInit(MEM_32K_BUF, "32K Buffer", 32768, 10); + memDataInit(MEM_64K_BUF, "64K Buffer", 65536, 10); + memDataInit(MEM_ACL, "acl", sizeof(acl), 0); + memDataInit(MEM_ACL_DENY_INFO_LIST, "acl_deny_info_list", + sizeof(acl_deny_info_list), 0); + memDataInit(MEM_ACL_IP_DATA, "acl_ip_data", sizeof(acl_ip_data), 0); + memDataInit(MEM_ACL_LIST, "acl_list", sizeof(acl_list), 0); + memDataInit(MEM_ACL_NAME_LIST, "acl_name_list", sizeof(acl_name_list), 0); + memDataInit(MEM_ACL_TIME_DATA, "acl_time_data", sizeof(acl_time_data), 0); + memDataInit(MEM_ACL_PROXY_AUTH_MATCH, "acl_proxy_auth_match_cache", + sizeof(acl_proxy_auth_match_cache), 0); + memDataInit(MEM_ACL_USER_DATA, "acl_user_data", + sizeof(acl_user_data), 0); +#if USE_CACHE_DIGESTS + memDataInit(MEM_CACHE_DIGEST, "CacheDigest", sizeof(CacheDigest), 0); +#endif + memDataInit(MEM_LINK_LIST, "link_list", sizeof(link_list), 10); + memDataInit(MEM_DLINK_NODE, "dlink_node", sizeof(dlink_node), 10); + memDataInit(MEM_DREAD_CTRL, "dread_ctrl", sizeof(dread_ctrl), 0); + memDataInit(MEM_DWRITE_Q, "dwrite_q", sizeof(dwrite_q), 0); + memDataInit(MEM_FWD_SERVER, "FwdServer", sizeof(FwdServer), 0); + memDataInit(MEM_HTTP_REPLY, "HttpReply", sizeof(HttpReply), 0); + memDataInit(MEM_HTTP_HDR_ENTRY, "HttpHeaderEntry", sizeof(HttpHeaderEntry), 0); + memDataInit(MEM_HTTP_HDR_CC, "HttpHdrCc", sizeof(HttpHdrCc), 0); + memDataInit(MEM_HTTP_HDR_RANGE_SPEC, "HttpHdrRangeSpec", sizeof(HttpHdrRangeSpec), 0); + memDataInit(MEM_HTTP_HDR_RANGE, "HttpHdrRange", sizeof(HttpHdrRange), 0); + memDataInit(MEM_HTTP_HDR_CONTENT_RANGE, "HttpHdrContRange", sizeof(HttpHdrContRange), 0); + memDataInit(MEM_INTLIST, "intlist", sizeof(intlist), 0); + memDataInit(MEM_MEMOBJECT, "MemObject", sizeof(MemObject), + Squid_MaxFD >> 3); + memDataInit(MEM_MEM_NODE, "mem_node", sizeof(mem_node), 0); + memDataInit(MEM_NETDBENTRY, "netdbEntry", sizeof(netdbEntry), 0); + memDataInit(MEM_NET_DB_NAME, "net_db_name", sizeof(net_db_name), 0); + memDataInit(MEM_RELIST, "relist", sizeof(relist), 0); + memDataInit(MEM_REQUEST_T, "request_t", sizeof(request_t), + Squid_MaxFD >> 3); + memDataInit(MEM_WORDLIST, "wordlist", sizeof(wordlist), 0); + memDataInit(MEM_CLIENT_INFO, "ClientInfo", sizeof(ClientInfo), 0); + memDataInit(MEM_MD5_DIGEST, "MD5 digest", MD5_DIGEST_CHARS, 0); + memPoolSetChunkSize(MemPools[MEM_MD5_DIGEST], 512 * 1024); + memDataInit(MEM_HELPER_REQUEST, "helper_request", + sizeof(helper_request), 0); + memDataInit(MEM_HELPER_STATEFUL_REQUEST, "helper_stateful_request", + sizeof(helper_stateful_request), 0); + memDataInit(MEM_TLV, "storeSwapTLV", sizeof(tlv), 0); + memDataInit(MEM_SWAP_LOG_DATA, "storeSwapLogData", sizeof(storeSwapLogData), 0); + + /* init string pools */ + for (i = 0; i < mem_str_pool_count; i++) { + StrPools[i].pool = memPoolCreate(StrPoolsAttrs[i].name, StrPoolsAttrs[i].obj_size); + } + cachemgrRegister("mem", + "Memory Utilization", + memStats, 0, 1); +} + +mem_type &operator++ (mem_type &aMem) +{ + aMem = (mem_type)(++(int)aMem); + return aMem; +} + +/* + * Test that all entries are initialized + */ +void +memCheckInit(void) +{ + mem_type t; + for (t = MEM_NONE, ++t; t < MEM_MAX; ++t) { + if (MEM_DONTFREE == t) + continue; + /* + * If you hit this assertion, then you forgot to add a + * memDataInit() line for type 't'. + */ + assert(MemPools[t]); + } +} + +#if UNUSED_CODE +/* to-do: make debug level a parameter? */ +static void memPoolDescribe(const MemPool * pool); +static void +memPoolDescribe(const MemPool * pool) +{ + assert(pool); + debug(13, 2) ("%-20s: %6d x %4d bytes = %5d KB\n", + pool->label, memPoolInUseCount(pool), pool->obj_size, + toKB(pool->obj_size * pool->meter.inuse.level)); +} + +#endif + +void +memClean(void) +{ + MemPoolGlobalStats stats; + memPoolSetIdleLimit(0); + memPoolClean(0); + memPoolGetGlobalStats(&stats); + if (stats.tot_items_inuse) + debug(13, 2) ("memCleanModule: %d items in %d chunks and %d pools are left dirty\n", stats.tot_items_inuse, + stats.tot_chunks_inuse, stats.tot_pools_inuse); +} + +int +memInUse(mem_type type) +{ + return memPoolInUseCount(MemPools[type]); +} + +/* ick */ + +static void +memFree2K(void *p) +{ + memFree(p, MEM_2K_BUF); +} + +void +memFree4K(void *p) +{ + memFree(p, MEM_4K_BUF); +} + +void +memFree8K(void *p) +{ + memFree(p, MEM_8K_BUF); +} + +static void +memFree16K(void *p) +{ + memFree(p, MEM_16K_BUF); +} + +static void +memFree32K(void *p) +{ + memFree(p, MEM_32K_BUF); +} + +static void +memFree64K(void *p) +{ + memFree(p, MEM_64K_BUF); +} + +FREE * +memFreeBufFunc(size_t size) +{ + switch (size) { + case 2 * 1024: + return memFree2K; + case 4 * 1024: + return memFree4K; + case 8 * 1024: + return memFree8K; + case 16 * 1024: + return memFree16K; + case 32 * 1024: + return memFree32K; + case 64 * 1024: + return memFree64K; + default: + memMeterDec(HugeBufCountMeter); + memMeterDel(HugeBufVolumeMeter, size); + return xfree; + } +} + +/* MemPoolMeter */ + +static void +memPoolReport(const MemPoolStats * mp_st, const MemPoolMeter * AllMeter, StoreEntry * e) +{ + int excess = 0; + int needed = 0; + MemPoolMeter *pm = mp_st->meter; + + storeAppendPrintf(e, "%-20s\t %4d\t ", + mp_st->label, mp_st->obj_size); + + /* Chunks */ + storeAppendPrintf(e, "%4d\t %4d\t ", + toKB(mp_st->obj_size * mp_st->chunk_capacity), mp_st->chunk_capacity); + + if (mp_st->chunk_capacity) { + needed = mp_st->items_inuse / mp_st->chunk_capacity; + if (mp_st->items_inuse % mp_st->chunk_capacity) + needed++; + excess = mp_st->chunks_inuse - needed; + } + storeAppendPrintf(e, "%4d\t %4d\t %4d\t %4d\t %.1f\t ", + mp_st->chunks_alloc, mp_st->chunks_inuse, mp_st->chunks_free, mp_st->chunks_partial, + xpercent(excess, needed)); +/* + * Fragmentation calculation: + * needed = inuse.level / chunk_capacity + * excess = used - needed + * fragmentation = excess / needed * 100% + * + * Fragm = (alloced - (inuse / obj_ch) ) / alloced + */ + + storeAppendPrintf(e, + "%d\t %d\t %d\t %.2f\t %.1f\t" /* alloc */ + "%d\t %d\t %d\t %.1f\t" /* in use */ + "%d\t %d\t %d\t" /* idle */ + "%.0f\t %.1f\t %.1f\t %.1f\n", /* saved */ + /* alloc */ + mp_st->items_alloc, + toKB(mp_st->obj_size * pm->alloc.level), + toKB(mp_st->obj_size * pm->alloc.hwater_level), + (double) ((squid_curtime - pm->alloc.hwater_stamp) / 3600.), + xpercent(mp_st->obj_size * pm->alloc.level, AllMeter->alloc.level), + /* in use */ + mp_st->items_inuse, + toKB(mp_st->obj_size * pm->inuse.level), + toKB(mp_st->obj_size * pm->inuse.hwater_level), + xpercent(pm->inuse.level, pm->alloc.level), + /* idle */ + mp_st->items_idle, + toKB(mp_st->obj_size * pm->idle.level), + toKB(mp_st->obj_size * pm->idle.hwater_level), + /* saved */ + pm->gb_saved.count, + xpercent(pm->gb_saved.count, AllMeter->gb_saved.count), + xpercent(pm->gb_saved.bytes, AllMeter->gb_saved.bytes), + xdiv(pm->gb_saved.count - pm->gb_osaved.count, xm_deltat)); + pm->gb_osaved.count = pm->gb_saved.count; +} + +void +memReport(StoreEntry * e) +{ + static char buf[64]; + static MemPoolStats mp_stats; + static MemPoolGlobalStats mp_total; + int not_used = 0; + MemPoolIterator *iter; + MemPool *pool; + + /* caption */ + storeAppendPrintf(e, "Current memory usage:\n"); + /* heading */ + storeAppendPrintf(e, + "Pool\t Obj Size\t" + "Chunks\t\t\t\t\t\t\t" + "Allocated\t\t\t\t\t" + "In Use\t\t\t\t" + "Idle\t\t\t" + "Allocations Saved\t\t\t" + "Hit Rate\t" + "\n" + " \t (bytes)\t" + "KB/ch\t obj/ch\t" + "(#)\t used\t free\t part\t %%Frag\t " + "(#)\t (KB)\t high (KB)\t high (hrs)\t %%Tot\t" + "(#)\t (KB)\t high (KB)\t %%alloc\t" + "(#)\t (KB)\t high (KB)\t" + "(#)\t %%cnt\t %%vol\t" + "(#) / sec\t" + "\n"); + xm_deltat = current_dtime - xm_time; + xm_time = current_dtime; + + /* Get stats for Totals report line */ + memPoolGetGlobalStats(&mp_total); + + /* main table */ + iter = memPoolIterate(); + while ((pool = memPoolIterateNext(iter))) { + memPoolGetStats(&mp_stats, pool); + if (!mp_stats.pool) /* pool destroyed */ + continue; + if (mp_stats.pool->meter.gb_saved.count > 0) /* this pool has been used */ + memPoolReport(&mp_stats, mp_total.TheMeter, e); + else + not_used++; + } + memPoolIterateDone(&iter); + + mp_stats.pool = NULL; + mp_stats.label = "Total"; + mp_stats.meter = mp_total.TheMeter; + mp_stats.obj_size = 1; + mp_stats.chunk_capacity = 0; + mp_stats.chunk_size = 0; + mp_stats.chunks_alloc = mp_total.tot_chunks_alloc; + mp_stats.chunks_inuse = mp_total.tot_chunks_inuse; + mp_stats.chunks_partial = mp_total.tot_chunks_partial; + mp_stats.chunks_free = mp_total.tot_chunks_free; + mp_stats.items_alloc = mp_total.tot_items_alloc; + mp_stats.items_inuse = mp_total.tot_items_inuse; + mp_stats.items_idle = mp_total.tot_items_idle; + mp_stats.overhead = mp_total.tot_overhead; + + memPoolReport(&mp_stats, mp_total.TheMeter, e); + + /* Cumulative */ + storeAppendPrintf(e, "Cumulative allocated volume: %s\n", double_to_str(buf, 64, mp_total.TheMeter->gb_saved.bytes)); + /* overhead */ + storeAppendPrintf(e, "Current overhead: %d bytes (%.3f%%)\n", + mp_total.tot_overhead, xpercent(mp_total.tot_overhead, mp_total.TheMeter->inuse.level)); + /* limits */ + storeAppendPrintf(e, "Idle pool limit: %.2f MB\n", toMB(mp_total.mem_idle_limit)); + /* limits */ + storeAppendPrintf(e, "Total Pools created: %d\n", mp_total.tot_pools_alloc); + storeAppendPrintf(e, "Pools ever used: %d (shown above)\n", mp_total.tot_pools_alloc - not_used); + storeAppendPrintf(e, "Currently in use: %d\n", mp_total.tot_pools_inuse); +} --- squid/src/stmem.c Wed Feb 14 01:07:20 2007 +++ /dev/null Wed Feb 14 01:05:20 2007 @@ -1,171 +0,0 @@ - -/* - * $Id: stmem.c,v 1.8 2002/09/15 11:06:33 rbcollins Exp $ - * - * DEBUG: section 19 Store Memory Primitives - * AUTHOR: Harvest Derived - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" - -void -stmemFree(mem_hdr * mem) -{ - mem_node *p; - while ((p = mem->head)) { - mem->head = p->next; - store_mem_size -= SM_PAGE_SIZE; - if (p) { - memFree(p, MEM_MEM_NODE); - p = NULL; - } - } - mem->head = mem->tail = NULL; - mem->origin_offset = 0; -} - -int -stmemFreeDataUpto(mem_hdr * mem, int target_offset) -{ - int current_offset = mem->origin_offset; - mem_node *lastp; - mem_node *p = mem->head; - while (p && ((current_offset + p->len) <= target_offset)) { - if (p == mem->tail) { - /* keep the last one to avoid change to other part of code */ - mem->head = mem->tail; - mem->origin_offset = current_offset; - return current_offset; - } else { - lastp = p; - p = p->next; - current_offset += lastp->len; - store_mem_size -= SM_PAGE_SIZE; - if (lastp) { - memFree(lastp, MEM_MEM_NODE); - lastp = NULL; - } - } - } - mem->head = p; - mem->origin_offset = current_offset; - if (current_offset < target_offset) { - /* there are still some data left. */ - return current_offset; - } - assert(current_offset == target_offset); - return current_offset; -} - -/* Append incoming data. */ -void -stmemAppend(mem_hdr * mem, const char *data, int len) -{ - mem_node *p; - int avail_len; - int len_to_copy; - debug(19, 6) ("memAppend: len %d\n", len); - /* Does the last block still contain empty space? - * If so, fill out the block before dropping into the - * allocation loop */ - if (mem->head && mem->tail && (mem->tail->len < SM_PAGE_SIZE)) { - avail_len = SM_PAGE_SIZE - (mem->tail->len); - len_to_copy = XMIN(avail_len, len); - xmemcpy((mem->tail->data + mem->tail->len), data, len_to_copy); - /* Adjust the ptr and len according to what was deposited in the page */ - data += len_to_copy; - len -= len_to_copy; - mem->tail->len += len_to_copy; - } - while (len > 0) { - len_to_copy = XMIN(len, SM_PAGE_SIZE); - p = memAllocate(MEM_MEM_NODE); - p->next = NULL; - p->len = len_to_copy; - store_mem_size += SM_PAGE_SIZE; - xmemcpy(p->data, data, len_to_copy); - if (!mem->head) { - /* The chain is empty */ - mem->head = mem->tail = p; - } else { - /* Append it to existing chain */ - mem->tail->next = p; - mem->tail = p; - } - len -= len_to_copy; - data += len_to_copy; - } -} - -ssize_t -stmemCopy(const mem_hdr * mem, off_t offset, char *buf, size_t size) -{ - mem_node *p = mem->head; - off_t t_off = mem->origin_offset; - size_t bytes_to_go = size; - char *ptr_to_buf = NULL; - int bytes_from_this_packet = 0; - int bytes_into_this_packet = 0; - debug(19, 6) ("memCopy: offset %ld: size %u\n", (long int) offset, size); - if (p == NULL) - return 0; - /* RC: the next assert is useless */ - assert(size > 0); - /* Seek our way into store */ - while ((t_off + p->len) < offset) { - t_off += p->len; - if (!p->next) { - debug(19, 1) ("memCopy: p->next == NULL\n"); - return 0; - } - assert(p->next); - p = p->next; - } - /* Start copying begining with this block until - * we're satiated */ - bytes_into_this_packet = offset - t_off; - bytes_from_this_packet = XMIN(bytes_to_go, p->len - bytes_into_this_packet); - xmemcpy(buf, p->data + bytes_into_this_packet, bytes_from_this_packet); - bytes_to_go -= bytes_from_this_packet; - ptr_to_buf = buf + bytes_from_this_packet; - p = p->next; - while (p && bytes_to_go > 0) { - if (bytes_to_go > p->len) { - xmemcpy(ptr_to_buf, p->data, p->len); - ptr_to_buf += p->len; - bytes_to_go -= p->len; - } else { - xmemcpy(ptr_to_buf, p->data, bytes_to_go); - bytes_to_go -= bytes_to_go; - } - p = p->next; - } - return size - bytes_to_go; -} --- /dev/null Wed Feb 14 01:05:20 2007 +++ squid/src/stmem.cc Wed Feb 14 01:07:20 2007 @@ -0,0 +1,168 @@ + +/* + * $Id: stmem.cc,v 1.1.2.1 2002/10/05 06:41:57 rbcollins Exp $ + * + * DEBUG: section 19 Store Memory Primitives + * AUTHOR: Harvest Derived + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" + +void +stmemFree(mem_hdr * mem) +{ + mem_node *p; + while ((p = mem->head)) { + mem->head = p->next; + store_mem_size -= SM_PAGE_SIZE; + if (p) { + memFree(p, MEM_MEM_NODE); + p = NULL; + } + } + mem->head = mem->tail = NULL; + mem->origin_offset = 0; +} + +int +stmemFreeDataUpto(mem_hdr * mem, int target_offset) +{ + int current_offset = mem->origin_offset; + mem_node *lastp; + mem_node *p = mem->head; + while (p && ((current_offset + p->len) <= target_offset)) { + if (p == mem->tail) { + /* keep the last one to avoid change to other part of code */ + mem->head = mem->tail; + mem->origin_offset = current_offset; + return current_offset; + } else { + lastp = p; + p = p->next; + current_offset += lastp->len; + store_mem_size -= SM_PAGE_SIZE; + if (lastp) { + memFree(lastp, MEM_MEM_NODE); + lastp = NULL; + } + } + } + mem->head = p; + mem->origin_offset = current_offset; + if (current_offset < target_offset) { + /* there are still some data left. */ + return current_offset; + } + assert(current_offset == target_offset); + return current_offset; +} + +/* Append incoming data. */ +void +stmemAppend(mem_hdr * mem, const char *data, int len) +{ + int avail_len; + int len_to_copy; + debug(19, 6) ("memAppend: len %d\n", len); + /* Does the last block still contain empty space? + * If so, fill out the block before dropping into the + * allocation loop */ + if (mem->head && mem->tail && (mem->tail->len < SM_PAGE_SIZE)) { + avail_len = SM_PAGE_SIZE - (mem->tail->len); + len_to_copy = XMIN(avail_len, len); + xmemcpy((mem->tail->data + mem->tail->len), data, len_to_copy); + /* Adjust the ptr and len according to what was deposited in the page */ + data += len_to_copy; + len -= len_to_copy; + mem->tail->len += len_to_copy; + } + while (len > 0) { + len_to_copy = XMIN(len, SM_PAGE_SIZE); + mem_node *p = static_cast(memAllocate(MEM_MEM_NODE)); + p->next = NULL; + p->len = len_to_copy; + store_mem_size += SM_PAGE_SIZE; + xmemcpy(p->data, data, len_to_copy); + if (!mem->head) { + /* The chain is empty */ + mem->head = mem->tail = p; + } else { + /* Append it to existing chain */ + mem->tail->next = p; + mem->tail = p; + } + len -= len_to_copy; + data += len_to_copy; + } +} + +ssize_t +stmemCopy(const mem_hdr * mem, off_t offset, char *buf, size_t size) +{ + mem_node *p = mem->head; + off_t t_off = mem->origin_offset; + size_t bytes_to_go = size; + debug(19, 6) ("memCopy: offset %ld: size %u\n", (long int) offset, size); + if (p == NULL) + return 0; + /* RC: the next assert is useless */ + assert(size > 0); + /* Seek our way into store */ + while ((t_off + p->len) < offset) { + t_off += p->len; + if (!p->next) { + debug(19, 1) ("memCopy: p->next == NULL\n"); + return 0; + } + assert(p->next); + p = p->next; + } + /* Start copying begining with this block until + * we're satiated */ + int bytes_into_this_packet = offset - t_off; + assert (p->len >= bytes_into_this_packet); + int bytes_from_this_packet = XMIN(bytes_to_go, (size_t)(p->len - bytes_into_this_packet)); + xmemcpy(buf, p->data + bytes_into_this_packet, bytes_from_this_packet); + bytes_to_go -= bytes_from_this_packet; + char *ptr_to_buf = buf + bytes_from_this_packet; + p = p->next; + while (p && bytes_to_go > 0) { + if ((int)bytes_to_go > p->len) { + xmemcpy(ptr_to_buf, p->data, p->len); + ptr_to_buf += p->len; + bytes_to_go -= p->len; + } else { + xmemcpy(ptr_to_buf, p->data, bytes_to_go); + bytes_to_go = 0; + } + p = p->next; + } + return size - bytes_to_go; +}