SOURCES: squid-fd-config.patch (NEW) - fix file descriptors proble...
baggins
baggins at pld-linux.org
Sun Mar 5 02:11:24 CET 2006
Author: baggins Date: Sun Mar 5 01:11:24 2006 GMT
Module: SOURCES Tag: HEAD
---- Log message:
- fix file descriptors problems once and for all, make it configurable
via squid.conf. Patch from Fedora
---- Files affected:
SOURCES:
squid-fd-config.patch (NONE -> 1.1) (NEW)
---- Diffs:
================================================================
Index: SOURCES/squid-fd-config.patch
diff -u /dev/null SOURCES/squid-fd-config.patch:1.1
--- /dev/null Sun Mar 5 02:11:24 2006
+++ SOURCES/squid-fd-config.patch Sun Mar 5 02:11:18 2006
@@ -0,0 +1,807 @@
+--- squid-2.5.STABLE12/configure.in.fdc 2005-10-22 11:56:01.000000000 +0200
++++ squid-2.5.STABLE12/configure.in 2005-12-06 14:07:43.000000000 +0100
+@@ -445,6 +445,16 @@
+ fi
+ ])
+
++AM_CONDITIONAL(USE_FD_CONFIG, false)
++AC_ARG_ENABLE(fd-config,
++[ --enable-fd-config Enable filedesc config to limit bandwidth usage],
++[ if test "$enableval" = "yes" ; then
++ echo "Filedesc config enabled"
++ AC_DEFINE(FD_CONFIG)
++ AM_CONDITIONAL(USE_FD_CONFIG, true)
++ fi
++])
++
+ dnl This is a developer only option. Developers know how to set defines
+ dnl
+ dnl AC_ARG_ENABLE(mem-gen-trace,
+--- squid-2.5.STABLE12/include/autoconf.h.in.fdc 2005-09-13 02:12:34.000000000 +0200
++++ squid-2.5.STABLE12/include/autoconf.h.in 2005-12-06 14:07:43.000000000 +0100
+@@ -125,6 +125,11 @@
+ #undef DELAY_POOLS
+
+ /*
++ * Filedesc managment
++ */
++#undef FD_CONFIG
++
++/*
+ * If you want to log User-Agent request header values, define this.
+ * By default, they are written to useragent.log in the Squid log
+ * directory.
+--- squid-2.5.STABLE12/acconfig.h~ 2004-06-01 10:34:19.000000000 +0200
++++ squid-2.5.STABLE12/acconfig.h 2006-03-05 02:00:21.000000000 +0100
+@@ -88,6 +88,11 @@
+ #undef DELAY_POOLS
+
+ /*
++ * Filedesc managment
++ */
++#undef FD_CONFIG
++
++/*
+ * If you want to log User-Agent request header values, define this.
+ * By default, they are written to useragent.log in the Squid log
+ * directory.
+--- squid-2.5.STABLE12/src/cf.data.pre.fdc 2005-12-06 14:07:43.000000000 +0100
++++ squid-2.5.STABLE12/src/cf.data.pre 2005-12-06 14:07:43.000000000 +0100
+@@ -4161,4 +4161,13 @@
+ If set to "off" then such HTTP errors will cause the request
+ or response to be rejected.
+ DOC_END
++
++NAME: max_filedesc
++IFDEF: FD_CONFIG
++TYPE: int
++DEFAULT: 8192
++LOC: Config.max_filedesc
++DOC_START
++ The maximum number of open file descriptors.
++DOC_END
+ EOF
+--- squid-2.5.STABLE12/src/tools.c.fdc 2005-12-06 14:07:43.000000000 +0100
++++ squid-2.5.STABLE12/src/tools.c 2005-12-06 14:09:02.000000000 +0100
+@@ -685,9 +685,11 @@
+ if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
+ debug(50, 0) ("setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
+ } else {
+- rl.rlim_cur = Squid_MaxFD;
++ rl.rlim_max = rl.rlim_cur = SQUID_NUMFD;
++/*
+ if (rl.rlim_cur > rl.rlim_max)
+- Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
++ rl.rlim_cur = rl.rlim_max;
++*/
+ if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
+ snprintf(tmp_error_buf, ERROR_BUF_SZ,
+ "setrlimit: RLIMIT_NOFILE: %s", xstrerror());
+@@ -698,9 +700,11 @@
+ if (getrlimit(RLIMIT_OFILE, &rl) < 0) {
+ debug(50, 0) ("setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
+ } else {
+- rl.rlim_cur = Squid_MaxFD;
++ rl.rlim_max = rl.rlim_cur = SQUID_NUMFD;
++/*
+ if (rl.rlim_cur > rl.rlim_max)
+- Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
++ rl.rlim_cur = rl.rlim_max;
++*/
+ if (setrlimit(RLIMIT_OFILE, &rl) < 0) {
+ snprintf(tmp_error_buf, ERROR_BUF_SZ,
+ "setrlimit: RLIMIT_OFILE: %s", xstrerror());
+--- squid-2.5.STABLE12/src/structs.h.fdc 2005-09-03 11:14:43.000000000 +0200
++++ squid-2.5.STABLE12/src/structs.h 2005-12-06 14:07:43.000000000 +0100
+@@ -714,6 +714,9 @@
+ char *store_dir_select_algorithm;
+ int sleep_after_fork; /* microseconds */
+ external_acl *externalAclHelperList;
++#if FD_CONFIG
++ int max_filedesc;
++#endif
+ };
+
+ struct _SquidConfig2 {
+--- /dev/null 2005-12-06 14:01:02.632036776 +0100
++++ squid-2.5.STABLE12/src/bit_array.h 2005-12-06 14:07:43.000000000 +0100
+@@ -0,0 +1,58 @@
++/* */
++
++#ifndef __BIT_ARRAY_H__
++#define __BIT_ARRAY_H__
++
++#if !BIT_ARRAY_ACTIVE
++
++#define BIT_ARRAY fd_set
++#define BA_INIT(arr,len)
++#define BA_FREE(arr)
++
++#define BA_ZERO(arr) FD_ZERO(&arr)
++#define BA_SET(fd,arr) FD_SET(fd,&arr)
++#define BA_CLR(fd,arr) FD_CLR(fd,&arr)
++#define BA_ISSET(fd,arr) FD_ISSET(fd,&arr)
++
++#else
++
++typedef struct _BIT_ARRAY {
++
++ int *p_pool;
++ int len;
++ int offset_mask;
++ int base_shift;
++
++} BIT_ARRAY;
++
++#define BA_INIT(arr,lenght) \
++{ \
++ int i,tmp = sizeof((arr).p_pool[0])*8; \
++ \
++ for(i = 2, (arr).base_shift = 1; i < tmp; i *= 2) \
++ (arr).base_shift++; \
++ (arr).offset_mask = (i-1); \
++ \
++ (arr).len = lenght / (sizeof((arr).p_pool[0])*8) + 1; \
++ (arr).p_pool = xmalloc(sizeof((arr).p_pool[0])*(arr).len); \
++} \
++
++
++#define BA_FREE(arr) \
++{ \
++ if((arr).p_pool) { \
++ xfree((arr).p_pool); \
++ (arr).p_pool = NULL; \
++ } \
++ (arr).len = 0; \
++} \
++
++
++#define BA_ZERO(arr) { memset((arr).p_pool, 0, sizeof((arr).p_pool[0])*(arr).len); }
++#define BA_SET(fdsp, arr) { (arr).p_pool[(fdsp)>>(arr).base_shift]|=(0x1<<((fdsp)&(arr).offset_mask)); }
++#define BA_CLR(fdsp, arr) { (arr).p_pool[(fdsp)>>(arr).base_shift]&=(~(0x1<<((fdsp)&(arr).offset_mask))); }
++#define BA_ISSET(fdsp, arr) ((arr).p_pool[(fdsp)>>(arr).base_shift]&(0x1<<((fdsp)&(arr).offset_mask)))
++
++#endif // BIT_ARRAY_ACTIVE
++
++#endif //__BIT_ARRAY_H__
+--- squid-2.5.STABLE12/src/fd.c.fdc 2003-12-14 13:30:36.000000000 +0100
++++ squid-2.5.STABLE12/src/fd.c 2005-12-06 14:07:43.000000000 +0100
+@@ -55,7 +55,7 @@
+ {
+ if (fd < Biggest_FD)
+ return;
+- assert(fd < Squid_MaxFD);
++ assert(fd < SQUID_NUMFD);
+ if (fd > Biggest_FD) {
+ /*
+ * assert that we are not closing a FD bigger than
+@@ -158,7 +158,7 @@
+ {
+ int i;
+ fde *F;
+- for (i = 0; i < Squid_MaxFD; i++) {
++ for (i = 0; i < SQUID_NUMFD; i++) {
+ F = &fd_table[i];
+ if (!F->flags.open)
+ continue;
+@@ -175,7 +175,7 @@
+ int
+ fdNFree(void)
+ {
+- return Squid_MaxFD - Number_FD - Opening_FD;
++ return SQUID_NUMFD - Number_FD - Opening_FD;
+ }
+
+ int
+@@ -204,10 +204,10 @@
+ /*
+ * Calculate a new reserve, based on current usage and a small extra
+ */
+- new = Squid_MaxFD - Number_FD + XMIN(25, Squid_MaxFD / 16);
++ new = SQUID_NUMFD - Number_FD + XMIN(25, SQUID_NUMFD / 16);
+ if (new <= RESERVED_FD)
+ return;
+- x = Squid_MaxFD - 20 - XMIN(25, Squid_MaxFD / 16);
++ x = SQUID_NUMFD - 20 - XMIN(25, SQUID_NUMFD / 16);
+ if (new > x) {
+ /* perhaps this should be fatal()? -DW */
+ debug(51, 0) ("WARNING: This machine has a serious shortage of filedescriptors.\n");
+--- squid-2.5.STABLE12/src/mem.c.fdc 2001-09-07 20:02:45.000000000 +0200
++++ squid-2.5.STABLE12/src/mem.c 2005-12-06 14:07:43.000000000 +0100
+@@ -224,13 +224,13 @@
+ 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);
++ SQUID_NUMFD >> 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);
++ SQUID_NUMFD >> 3);
+ memDataInit(MEM_STOREENTRY, "StoreEntry", sizeof(StoreEntry), 0);
+ memDataInit(MEM_WORDLIST, "wordlist", sizeof(wordlist), 0);
+ memDataInit(MEM_CLIENT_INFO, "ClientInfo", sizeof(ClientInfo), 0);
+--- squid-2.5.STABLE12/src/comm_select.c.fdc 2003-05-11 19:30:13.000000000 +0200
++++ squid-2.5.STABLE12/src/comm_select.c 2005-12-06 14:07:43.000000000 +0100
+@@ -66,10 +66,10 @@
+ #if !HAVE_POLL
+ static struct timeval zero_tv;
+ #endif
+-static fd_set global_readfds;
+-static fd_set global_writefds;
+ static int nreadfds;
+ static int nwritefds;
++static BIT_ARRAY global_readfds;
++static BIT_ARRAY global_writefds;
+
+ /*
+ * Automatic tuning for incoming requests:
+@@ -171,13 +171,39 @@
+ }
+
+ #if DELAY_POOLS
++
++#if FD_CONFIG
++static int *slowfdarr = NULL;
++static int slowfdmax;
++#else
++static int slowfdarr[SQUID_NUMFD];
++static int slowfdmax = SQUID_NUMFD;
++#endif
++
+ static int slowfdcnt = 0;
+-static int slowfdarr[SQUID_MAXFD];
++
++#if FD_CONFIG
++void
++comm_slow_fd_init(int fd_num)
++{
++ slowfdarr = xmalloc(sizeof(slowfdarr[0])*fd_num);
++ slowfdmax = fd_num;
++ slowfdcnt = 0;
++}
++
++void
++comm_slow_fd_destroy(void)
++{
++ xfree(slowfdarr);
++ slowfdarr = NULL;
++ slowfdmax = slowfdcnt = 0;
++}
++#endif
+
+ static void
+ commAddSlowFd(int fd)
+ {
+- assert(slowfdcnt < SQUID_MAXFD);
++ assert(slowfdcnt < slowfdmax);
+ slowfdarr[slowfdcnt++] = fd;
+ }
+
+@@ -308,9 +334,13 @@
+ int
+ comm_poll(int msec)
+ {
+- struct pollfd pfds[SQUID_MAXFD];
++#if FD_CONFIG
++ struct pollfd *pfds = NULL;
++#else
++ struct pollfd pfds[SQUID_NUMFD];
++#endif
+ #if DELAY_POOLS
+- fd_set slowfds;
++ BIT_ARRAY slowfds;
+ #endif
+ PF *hdl = NULL;
+ int fd;
+@@ -323,6 +353,12 @@
+ int calldns = 0;
+ static time_t last_timeout = 0;
+ double timeout = current_dtime + (msec / 1000.0);
++#if FD_CONFIG
++ pfds = xmalloc(sizeof(pfds[0])*SQUID_NUMFD);
++#endif
++#if DELAY_POOLS
++ BA_INIT(slowfds,SQUID_NUMFD);
++#endif
+ do {
+ #if !ALARM_UPDATES_TIME
+ double start;
+@@ -332,7 +368,7 @@
+ /* Handle any fs callbacks that need doing */
+ storeDirCallback();
+ #if DELAY_POOLS
+- FD_ZERO(&slowfds);
++ BA_ZERO(slowfds);
+ #endif
+ if (commCheckICPIncoming)
+ comm_poll_icp_incoming();
+@@ -358,7 +394,7 @@
+ #if DELAY_POOLS
+ case -1:
+ events |= POLLRDNORM;
+- FD_SET(i, &slowfds);
++ BA_SET(i, slowfds);
+ break;
+ #endif
+ default:
+@@ -378,6 +414,12 @@
+ }
+ if (nfds == 0) {
+ assert(shutting_down);
++#if DELAY_POOLS
++ BA_FREE(slowfds);
++#endif
++#if FD_CONFIG
++ xfree(pfds);
++#endif
+ return COMM_SHUTDOWN;
+ }
+ if (npending)
+@@ -394,6 +436,12 @@
+ continue;
+ debug(5, 0) ("comm_poll: poll failure: %s\n", xstrerror());
+ assert(errno != EINVAL);
++#if DELAY_POOLS
++ BA_FREE(slowfds);
++#endif
++#if FD_CONFIG
++ xfree(pfds);
++#endif
+ return COMM_ERROR;
+ /* NOTREACHED */
+ }
+@@ -437,7 +485,7 @@
+ if (NULL == (hdl = F->read_handler))
+ (void) 0;
+ #if DELAY_POOLS
+- else if (FD_ISSET(fd, &slowfds))
++ else if (BA_ISSET(fd, slowfds))
+ commAddSlowFd(fd);
+ #endif
+ else {
+@@ -518,10 +566,22 @@
+ getCurrentTime();
+ statCounter.select_time += (current_dtime - start);
+ #endif
++#if DELAY_POOLS
++ BA_FREE(slowfds);
++#endif
++#if FD_CONFIG
++ xfree(pfds);
++#endif
+ return COMM_OK;
+ }
+ while (timeout > current_dtime);
+ debug(5, 8) ("comm_poll: time out: %ld.\n", (long int) squid_curtime);
++#if DELAY_POOLS
++ BA_FREE(slowfds);
++#endif
++#if FD_CONFIG
++ xfree(pfds);
++#endif
+ return COMM_TIMEOUT;
+ }
+
+@@ -646,7 +706,7 @@
+ fd_set pendingfds;
+ fd_set writefds;
+ #if DELAY_POOLS
+- fd_set slowfds;
++ BIT_ARRAY slowfds;
+ #endif
+ PF *hdl = NULL;
+ int fd;
+@@ -668,6 +728,9 @@
+ struct timeval poll_time;
+ double timeout = current_dtime + (msec / 1000.0);
+ fde *F;
++#if DELAY_POOLS
++ BA_INIT(slowfds,SQUID_NUMFD);
++#endif
+ do {
+ #if !ALARM_UPDATES_TIME
+ double start;
+@@ -675,7 +738,7 @@
+ start = current_dtime;
+ #endif
+ #if DELAY_POOLS
+- FD_ZERO(&slowfds);
++ BA_ZERO(slowfds);
+ #endif
+ /* Handle any fs callbacks that need doing */
+ storeDirCallback();
+@@ -712,7 +771,7 @@
+ break;
+ #if DELAY_POOLS
+ case -1:
+- FD_SET(fd, &slowfds);
++ BA_SET(fd, slowfds);
+ break;
+ #endif
+ default:
+@@ -741,6 +800,9 @@
+ #endif
+ if (nreadfds + nwritefds == 0) {
+ assert(shutting_down);
++#if DELAY_POOLS
++ BA_FREE(slowfds);
++#endif
+ return COMM_SHUTDOWN;
+ }
+ if (msec > MAX_POLL_TIME)
+@@ -760,6 +822,9 @@
+ debug(50, 0) ("comm_select: select failure: %s\n",
+ xstrerror());
+ examine_select(&readfds, &writefds);
++#if DELAY_POOLS
++ BA_FREE(slowfds);
++#endif
+ return COMM_ERROR;
+ /* NOTREACHED */
+ }
+@@ -812,7 +877,7 @@
+ if (NULL == (hdl = F->read_handler))
+ (void) 0;
+ #if DELAY_POOLS
+- else if (FD_ISSET(fd, &slowfds))
++ else if (BA_ISSET(fd, slowfds))
+ commAddSlowFd(fd);
+ #endif
+ else {
+@@ -901,10 +966,16 @@
+ getCurrentTime();
+ statCounter.select_time += (current_dtime - start);
+ #endif
++#if DELAY_POOLS
++ BA_FREE(slowfds);
++#endif
+ return COMM_OK;
+ }
+ while (timeout > current_dtime);
+ debug(5, 8) ("comm_select: time out: %d\n", (int) squid_curtime);
++#if DELAY_POOLS
++ BA_FREE(slowfds);
++#endif
+ return COMM_TIMEOUT;
+ }
+ #endif
+@@ -950,8 +1021,12 @@
+ cachemgrRegister("comm_incoming",
+ "comm_incoming() stats",
+ commIncomingStats, 0, 1);
+- FD_ZERO(&global_readfds);
+- FD_ZERO(&global_writefds);
++
++ BA_INIT(global_readfds,SQUID_NUMFD);
++ BA_INIT(global_writefds,SQUID_NUMFD);
++
++ BA_ZERO(global_readfds);
++ BA_ZERO(global_writefds);
+ nreadfds = nwritefds = 0;
+ }
+
+@@ -977,7 +1052,7 @@
+ fde *F = NULL;
+ struct stat sb;
+ debug(5, 0) ("examine_select: Examining open file descriptors...\n");
+- for (fd = 0; fd < Squid_MaxFD; fd++) {
++ for (fd = 0; fd < SQUID_NUMFD; fd++) {
+ FD_ZERO(&read_x);
+ FD_ZERO(&write_x);
+ tv.tv_sec = tv.tv_usec = 0;
+@@ -1085,11 +1160,11 @@
+ void
+ commUpdateReadBits(int fd, PF * handler)
+ {
+- if (handler && !FD_ISSET(fd, &global_readfds)) {
+- FD_SET(fd, &global_readfds);
++ if (handler && !BA_ISSET(fd, global_readfds)) {
++ BA_SET(fd, global_readfds);
+ nreadfds++;
+- } else if (!handler && FD_ISSET(fd, &global_readfds)) {
+- FD_CLR(fd, &global_readfds);
++ } else if (!handler && BA_ISSET(fd, global_readfds)) {
++ BA_CLR(fd, global_readfds);
+ nreadfds--;
+ }
+ }
+@@ -1097,11 +1172,11 @@
+ void
+ commUpdateWriteBits(int fd, PF * handler)
+ {
+- if (handler && !FD_ISSET(fd, &global_writefds)) {
+- FD_SET(fd, &global_writefds);
++ if (handler && !BA_ISSET(fd, global_writefds)) {
++ BA_SET(fd, global_writefds);
+ nwritefds++;
+- } else if (!handler && FD_ISSET(fd, &global_writefds)) {
+- FD_CLR(fd, &global_writefds);
++ } else if (!handler && BA_ISSET(fd, global_writefds)) {
++ BA_CLR(fd, global_writefds);
+ nwritefds--;
+ }
+ }
+--- squid-2.5.STABLE12/src/globals.h.fdc 2005-06-14 00:26:21.000000000 +0200
++++ squid-2.5.STABLE12/src/globals.h 2005-12-06 14:07:43.000000000 +0100
+@@ -72,7 +72,6 @@
+ extern int NDnsServersAlloc; /* 0 */
+ extern int NHttpSockets; /* 0 */
+ extern int RESERVED_FD;
+-extern int Squid_MaxFD; /* SQUID_MAXFD */
+ extern int config_lineno; /* 0 */
+ extern int debugLevels[MAX_DEBUG_SECTIONS];
+ extern int do_mallinfo; /* 0 */
+--- squid-2.5.STABLE12/src/ident.c.fdc 2001-04-14 02:03:23.000000000 +0200
++++ squid-2.5.STABLE12/src/ident.c 2005-12-06 14:07:43.000000000 +0100
+@@ -238,7 +238,7 @@
+ identInit(void)
+ {
+ ident_hash = hash_create((HASHCMP *) strcmp,
+- hashPrime(Squid_MaxFD / 8),
++ hashPrime(SQUID_NUMFD / 8),
+ hash4);
+ }
+
+--- squid-2.5.STABLE12/src/snmp_agent.c.fdc 2004-06-01 00:39:00.000000000 +0200
++++ squid-2.5.STABLE12/src/snmp_agent.c 2005-12-06 14:07:43.000000000 +0100
+@@ -289,7 +289,7 @@
+ break;
+ case PERF_SYS_CURUNUSED_FD:
+ Answer = snmp_var_new_integer(Var->name, Var->name_length,
+- (snint) Squid_MaxFD - Number_FD,
++ (snint) SQUID_NUMFD - Number_FD,
+ SMI_GAUGE32);
+ break;
+ case PERF_SYS_CURRESERVED_FD:
+--- squid-2.5.STABLE12/src/comm.c.fdc 2005-09-10 12:17:55.000000000 +0200
++++ squid-2.5.STABLE12/src/comm.c 2005-12-06 14:07:43.000000000 +0100
+@@ -239,7 +239,7 @@
+ }
+
+ /*
+- * NOTE: set the listen queue to Squid_MaxFD/4 and rely on the kernel to
++ * NOTE: set the listen queue to Squid_MAXFD/4 and rely on the kernel to
+ * impose an upper limit. Solaris' listen(3n) page says it has
+ * no limit on this parameter, but sys/socket.h sets SOMAXCONN
+ * to 5. HP-UX currently has a limit of 20. SunOS is 5 and
+@@ -249,9 +249,9 @@
+ comm_listen(int sock)
+ {
+ int x;
+- if ((x = listen(sock, Squid_MaxFD >> 2)) < 0) {
++ if ((x = listen(sock, SQUID_NUMFD >> 2)) < 0) {
+ debug(50, 0) ("comm_listen: listen(%d, %d): %s\n",
+- Squid_MaxFD >> 2,
++ SQUID_NUMFD >> 2,
+ sock, xstrerror());
+ return x;
+ }
+@@ -441,7 +441,7 @@
+ fde *F;
+ debug(5, 3) ("commSetTimeout: FD %d timeout %d\n", fd, timeout);
+ assert(fd >= 0);
+- assert(fd < Squid_MaxFD);
++ assert(fd < SQUID_NUMFD);
+ F = &fd_table[fd];
+ assert(F->flags.open);
+ if (timeout < 0) {
<<Diff was trimmed, longer than 597 lines>>
More information about the pld-cvs-commit
mailing list