[Spread-cvs] commit: r553 - in trunk: daemon docs

jschultz at spread.org jschultz at spread.org
Wed Mar 13 16:15:32 EDT 2013


Author: jschultz
Date: 2013-03-13 16:15:32 -0400 (Wed, 13 Mar 2013)
New Revision: 553

Modified:
   trunk/daemon/config_gram.l
   trunk/daemon/config_parse.y
   trunk/daemon/configuration.c
   trunk/daemon/configuration.h
   trunk/daemon/flow_control.c
   trunk/daemon/membership.c
   trunk/daemon/spread_params.h
   trunk/docs/sample.spread.conf
Log:
Export membership timeouts and flow control parameters to configuration file.  Reduce default flow control parameters.


Modified: trunk/daemon/config_gram.l
===================================================================
--- trunk/daemon/config_gram.l	2013-03-13 18:50:12 UTC (rev 552)
+++ trunk/daemon/config_gram.l	2013-03-13 20:15:32 UTC (rev 553)
@@ -98,6 +98,17 @@
 Hop                             { return PHOP; }
 TcpHop                          { return PTCPHOP; }
 RouteMatrix                     { return ROUTEMATRIX; }
+Window				{ return WINDOW; }
+PersonalWindow			{ return PERSONALWINDOW; }
+TokenTimeout                    { return TOKENTIMEOUT; }
+HurryTimeout                    { return HURRYTIMEOUT; }
+AliveTimeout                    { return ALIVETIMEOUT; }
+JoinTimeout                     { return JOINTIMEOUT; }
+RepTimeout                      { return REPTIMEOUT; }
+SegTimeout                      { return SEGTIMEOUT; }
+GatherTimeout                   { return GATHERTIMEOUT; }
+FormTimeout                     { return FORMTIMEOUT; }
+LookupTimeout                   { return LOOKUPTIMEOUT; }
 {true}|{yes}                    { yylval.boolean = TRUE; return SP_BOOL; }
 {false}|{no}                    { yylval.boolean = FALSE; return SP_BOOL; }
 {on}                            { yylval.number = 1; return SP_TRIVAL; }

Modified: trunk/daemon/config_parse.y
===================================================================
--- trunk/daemon/config_parse.y	2013-03-13 18:50:12 UTC (rev 552)
+++ trunk/daemon/config_parse.y	2013-03-13 20:15:32 UTC (rev 553)
@@ -327,6 +327,8 @@
 %token DEBUGINITIALSEQUENCE
 %token DANGEROUSMONITOR SOCKETPORTREUSE RUNTIMEDIR SPUSER SPGROUP ALLOWEDAUTHMETHODS REQUIREDAUTHMETHODS ACCESSCONTROLPOLICY
 %token MAXSESSIONMESSAGES
+%token WINDOW PERSONALWINDOW
+%token TOKENTIMEOUT HURRYTIMEOUT ALIVETIMEOUT JOINTIMEOUT REPTIMEOUT SEGTIMEOUT GATHERTIMEOUT FORMTIMEOUT LOOKUPTIMEOUT
 %token SP_BOOL SP_TRIVAL LINKPROTOCOL PHOP PTCPHOP
 %token IMONITOR ICLIENT IDAEMON
 %token ROUTEMATRIX LINKCOST
@@ -550,6 +552,50 @@
 			{
                             Conf_set_link_protocol(TCP_PROT);
 			}
+		|	WINDOW EQUALS NUMBER
+			{
+			    Conf_set_window($3.number);
+			}
+		|	PERSONALWINDOW EQUALS NUMBER
+			{
+			    Conf_set_personal_window($3.number);
+			}
+		|	TOKENTIMEOUT EQUALS NUMBER
+			{
+			    Conf_set_token_timeout($3.number);
+			}
+		|	HURRYTIMEOUT EQUALS NUMBER
+			{
+			    Conf_set_hurry_timeout($3.number);
+			}
+		|	ALIVETIMEOUT EQUALS NUMBER
+			{
+			    Conf_set_alive_timeout($3.number);
+			}
+		|	JOINTIMEOUT EQUALS NUMBER
+			{
+			    Conf_set_join_timeout($3.number);
+			}
+		|	REPTIMEOUT EQUALS NUMBER
+			{
+			    Conf_set_rep_timeout($3.number);
+			}
+		|	SEGTIMEOUT EQUALS NUMBER
+			{
+			    Conf_set_seg_timeout($3.number);
+			}
+		|	GATHERTIMEOUT EQUALS NUMBER
+			{
+			    Conf_set_gather_timeout($3.number);
+			}
+		|	FORMTIMEOUT EQUALS NUMBER
+			{
+			    Conf_set_form_timeout($3.number);
+			}
+		|	LOOKUPTIMEOUT EQUALS NUMBER
+			{
+			    Conf_set_lookup_timeout($3.number);
+			}
 
 SegmentStruct	:    SEGMENT IPADDR OPENBRACE Segmentparams CLOSEBRACE
                         { int i;

Modified: trunk/daemon/configuration.c
===================================================================
--- trunk/daemon/configuration.c	2013-03-13 18:50:12 UTC (rev 552)
+++ trunk/daemon/configuration.c	2013-03-13 20:15:32 UTC (rev 553)
@@ -102,7 +102,35 @@
 
 static  int     MaxSessionMessages = DEFAULT_MAX_SESSION_MESSAGES;
 
+static  int     Window = DEFAULT_WINDOW;
+static  int     PersonalWindow = DEFAULT_PERSONAL_WINDOW;
 
+enum 
+{
+  TOKEN_TIMEOUT_CONF  = (0x1 << 0),
+  HURRY_TIMEOUT_CONF  = (0x1 << 1),
+  ALIVE_TIMEOUT_CONF  = (0x1 << 2),
+  JOIN_TIMEOUT_CONF   = (0x1 << 3),
+  REP_TIMEOUT_CONF    = (0x1 << 4),
+  SEG_TIMEOUT_CONF    = (0x1 << 5),
+  GATHER_TIMEOUT_CONF = (0x1 << 6),
+  FORM_TIMEOUT_CONF   = (0x1 << 7),
+  LOOKUP_TIMEOUT_CONF = (0x1 << 8),
+  ALL_TIMEOUT_CONF    = 0x1FF
+};
+
+static  int     TimeoutMask;
+
+static  int     TokenTimeout;
+static  int     HurryTimeout;
+static  int     AliveTimeout;
+static  int     JoinTimeout;
+static  int     RepTimeout;
+static  int     SegTimeout;
+static  int     GatherTimeout;
+static  int     FormTimeout;
+static  int     LookupTimeout;
+
 static  int     Link_Protocol;
 
 static  bool    Conf_Debug_Initial_Sequence = FALSE;
@@ -418,9 +446,9 @@
 			Alarm( EXIT, "Conf_load_conf_file: could not get my ip address (my name is %s)\n",
 				machine_name );
                 if (host_ptr->h_addrtype != AF_INET)
-                        Alarm(EXIT, "Conf_load_conf_file: Sorry, cannot handle addr types other than IPv4\n");
+                        Alarmp(SPLOG_FATAL, CONF_SYS, "Conf_load_conf_file: Sorry, cannot handle addr types other than IPv4\n");
                 if (host_ptr->h_length != 4)
-                        Alarm(EXIT, "Conf_load_conf_file: Bad IPv4 address length\n");
+                        Alarmp(SPLOG_FATAL, CONF_SYS, "Conf_load_conf_file: Bad IPv4 address length\n");
 	
 		i = -1;	/* in case host_ptr->h_length == 0 */
                 for (j = 0; host_ptr->h_addr_list[j] != NULL; j++) {
@@ -820,12 +848,12 @@
                 char *buf;
                 if (len > max_value_len)
                 {
-                    Alarm(EXIT, "set_param_if_valid: value string too long\n");
+                    Alarmp(SPLOG_FATAL, CONF_SYS, "set_param_if_valid: value string too long\n");
                 }
                 buf = Mem_alloc(len + 1);
                 if (buf == NULL)
                 {
-                        Alarm(EXIT, "set_param_if_valid: Out of memory\n");
+                        Alarmp(SPLOG_FATAL, CONF_SYS, "set_param_if_valid: Out of memory\n");
                 }
                 strncpy(buf, value, len);
                 buf[len] = '\0';
@@ -886,3 +914,185 @@
 {
         set_param_if_valid(&Group, group, "group name", 32);
 }
+
+void    Conf_set_window(int window)
+{
+        if (window <= 0) {
+	    Alarmp(SPLOG_FATAL, CONF_SYS, "Conf_set_window: Attempt to set window to non-positive (%d)!\n", window);
+        }
+        Alarmp(SPLOG_DEBUG, CONF_SYS, "Conf_set_window: Set Window to %d\n", window);
+        Window = window;
+}
+
+int     Conf_get_window(void)
+{
+	return Window;
+}
+
+void    Conf_set_personal_window(int pwindow)
+{
+        if (pwindow <= 0) {
+	    Alarmp(SPLOG_FATAL, CONF_SYS, "Conf_set_personal_window: Attempt to set personal window to non-positive (%d)!\n", pwindow);
+        }
+        Alarmp(SPLOG_DEBUG, CONF_SYS, "Conf_set_personal_window: Set Personal Window to %d\n", pwindow);
+        PersonalWindow = pwindow;
+}
+
+int     Conf_get_personal_window(void)
+{
+	return PersonalWindow;
+}
+
+int Conf_memb_timeouts_set(void)
+{
+  return TimeoutMask != 0;
+}
+
+int Conf_all_memb_timeouts_set(void)
+{
+  return TimeoutMask == ALL_TIMEOUT_CONF;
+}
+
+void Conf_set_token_timeout(int timeout) 
+{
+  if (timeout <= 0) {
+    Alarmp(SPLOG_FATAL, CONF_SYS, "Conf_set_token_timeout: Non-positive timeout (%d) specified!\n", timeout);
+  }
+
+  TimeoutMask |= TOKEN_TIMEOUT_CONF;
+
+  TokenTimeout = timeout;
+}
+
+int Conf_get_token_timeout(void) 
+{ 
+  return TokenTimeout; 
+}
+
+void Conf_set_hurry_timeout(int timeout) 
+{
+  if (timeout <= 0) {
+    Alarmp(SPLOG_FATAL, CONF_SYS, "Conf_set_hurry_timeout: Non-positive timeout (%d) specified!\n", timeout);
+  }
+
+  TimeoutMask |= HURRY_TIMEOUT_CONF;
+
+  HurryTimeout = timeout;
+}
+
+int Conf_get_hurry_timeout(void) 
+{ 
+  return HurryTimeout; 
+}
+
+void Conf_set_alive_timeout(int timeout) 
+{
+  if (timeout <= 0) {
+    Alarmp(SPLOG_FATAL, CONF_SYS, "Conf_set_alive_timeout: Non-positive timeout (%d) specified!\n", timeout);
+  }
+
+  TimeoutMask |= ALIVE_TIMEOUT_CONF;
+
+  AliveTimeout = timeout;
+}
+
+int Conf_get_alive_timeout(void) 
+{ 
+  return AliveTimeout; 
+}
+
+void Conf_set_join_timeout(int timeout) 
+{
+  if (timeout <= 0) {
+    Alarmp(SPLOG_FATAL, CONF_SYS, "Conf_set_join_timeout: Non-positive timeout (%d) specified!\n", timeout);
+  }
+
+  TimeoutMask |= JOIN_TIMEOUT_CONF;
+
+  JoinTimeout = timeout;
+}
+
+int Conf_get_join_timeout(void) 
+{ 
+  return JoinTimeout; 
+}
+
+void Conf_set_rep_timeout(int timeout) 
+{
+  if (timeout <= 0) {
+    Alarmp(SPLOG_FATAL, CONF_SYS, "Conf_set_rep_timeout: Non-positive timeout (%d) specified!\n", timeout);
+  }
+
+  TimeoutMask |= REP_TIMEOUT_CONF;
+
+  RepTimeout = timeout;
+}
+
+int Conf_get_rep_timeout(void) 
+{ 
+  return RepTimeout; 
+}
+
+void Conf_set_seg_timeout(int timeout) 
+{
+  if (timeout <= 0) {
+    Alarmp(SPLOG_FATAL, CONF_SYS, "Conf_set_seg_timeout: Non-positive timeout (%d) specified!\n", timeout);
+  }
+
+  TimeoutMask |= SEG_TIMEOUT_CONF;
+
+  SegTimeout = timeout;
+}
+
+int Conf_get_seg_timeout(void) 
+{ 
+  return SegTimeout; 
+}
+
+void Conf_set_gather_timeout(int timeout) 
+{
+  if (timeout <= 0) {
+    Alarmp(SPLOG_FATAL, CONF_SYS, "Conf_set_gather_timeout: Non-positive timeout (%d) specified!\n", timeout);
+  }
+
+  TimeoutMask |= GATHER_TIMEOUT_CONF;
+
+  GatherTimeout = timeout;
+}
+
+int Conf_get_gather_timeout(void) 
+{ 
+  return GatherTimeout; 
+}
+
+void Conf_set_form_timeout(int timeout) 
+{
+  if (timeout <= 0) {
+    Alarmp(SPLOG_FATAL, CONF_SYS, "Conf_set_form_timeout: Non-positive timeout (%d) specified!\n", timeout);
+  }
+
+  TimeoutMask |= FORM_TIMEOUT_CONF;
+
+  FormTimeout = timeout;
+}
+
+int Conf_get_form_timeout(void) 
+{ 
+  return FormTimeout; 
+}
+
+void Conf_set_lookup_timeout(int timeout) 
+{
+  if (timeout <= 0) {
+    Alarmp(SPLOG_FATAL, CONF_SYS, "Conf_set_lookup_timeout: Non-positive timeout (%d) specified!\n", timeout);
+  }
+
+  TimeoutMask |= LOOKUP_TIMEOUT_CONF;
+
+  LookupTimeout = timeout;
+}
+
+int Conf_get_lookup_timeout(void) 
+{ 
+  return LookupTimeout; 
+}

Modified: trunk/daemon/configuration.h
===================================================================
--- trunk/daemon/configuration.h	2013-03-13 18:50:12 UTC (rev 552)
+++ trunk/daemon/configuration.h	2013-03-13 20:15:32 UTC (rev 553)
@@ -140,5 +140,30 @@
 void            Conf_set_link_protocol(int protocol);
 void            Conf_set_max_session_messages(int max_messages);
 int             Conf_get_max_session_messages(void);
+void		Conf_set_window(int window);
+int		Conf_get_window(void);
+void		Conf_set_personal_window(int pwindow);
+int		Conf_get_personal_window(void);
 
+int             Conf_memb_timeouts_set(void);
+int             Conf_all_memb_timeouts_set(void);
+void		Conf_set_token_timeout(int timeout);
+int		Conf_get_token_timeout(void);
+void		Conf_set_hurry_timeout(int timeout);
+int		Conf_get_hurry_timeout(void);
+void		Conf_set_alive_timeout(int timeout);
+int		Conf_get_alive_timeout(void);
+void		Conf_set_join_timeout(int timeout);
+int		Conf_get_join_timeout(void);
+void		Conf_set_rep_timeout(int timeout);
+int		Conf_get_rep_timeout(void);
+void		Conf_set_seg_timeout(int timeout);
+int		Conf_get_seg_timeout(void);
+void		Conf_set_gather_timeout(int timeout);
+int		Conf_get_gather_timeout(void);
+void		Conf_set_form_timeout(int timeout);
+int		Conf_get_form_timeout(void);
+void		Conf_set_lookup_timeout(int timeout);
+int		Conf_get_lookup_timeout(void);
+
 #endif /* INC_CONFIGURATION */

Modified: trunk/daemon/flow_control.c
===================================================================
--- trunk/daemon/flow_control.c	2013-03-13 18:50:12 UTC (rev 552)
+++ trunk/daemon/flow_control.c	2013-03-13 20:15:32 UTC (rev 553)
@@ -45,8 +45,8 @@
 
 void	FC_init( )
 {
-	Window = 300;
-	Personal_window = 50;
+	Window = Conf_get_window();
+	Personal_window = Conf_get_personal_window();
 
 	GlobalStatus.window = Window;
 	GlobalStatus.personal_window = Personal_window;

Modified: trunk/daemon/membership.c
===================================================================
--- trunk/daemon/membership.c	2013-03-13 18:50:12 UTC (rev 552)
+++ trunk/daemon/membership.c	2013-03-13 20:15:32 UTC (rev 553)
@@ -151,41 +151,73 @@
 	reference_subnet = Cn->segments[0].procs[0]->id;
 	reference_subnet = reference_subnet & 0xffff0000;
 
-	Wide_network = 0;
-	for( i=1; i < num_seg; i++ )
-	{
-		current_subnet = Cn->segments[i].procs[0]->id;
-		current_subnet = current_subnet & 0xffff0000;
-		if( current_subnet != reference_subnet )
+	if (!Conf_memb_timeouts_set()) {
+
+		Wide_network = 0;
+		for( i=1; i < num_seg; i++ )
 		{
-			Wide_network = 1;
-			break;
+			current_subnet = Cn->segments[i].procs[0]->id;
+			current_subnet = current_subnet & 0xffff0000;
+			if( current_subnet != reference_subnet )
+			{
+				Wide_network = 1;
+				break;
+			}
 		}
-	}
 
-	if( Wide_network )
-	{
-		Token_timeout.sec  =   5; Token_timeout.usec  = 0;
-		Hurry_timeout.sec  =   1; Hurry_timeout.usec  = 500000;
+		if( Wide_network )
+		{
+			Token_timeout.sec  =   5; Token_timeout.usec  = 0;
+			Hurry_timeout.sec  =   1; Hurry_timeout.usec  = 500000;
 
-		Alive_timeout.sec  =   0; Alive_timeout.usec  = 250000;
-		Join_timeout.sec   =   0; Join_timeout.usec   = 250000;
-		Rep_timeout.sec    =   1; Rep_timeout.usec    = 250000;
-		Seg_timeout.sec    =   0; Seg_timeout.usec    = 500000;
-		Gather_timeout.sec =   2; Gather_timeout.usec = 500000;
-		Form_timeout.sec   =   2; Form_timeout.usec   = 500000;
-		Lookup_timeout.sec =  45; Lookup_timeout.usec = 0;
-	}else{
-		Token_timeout.sec  =   1; Token_timeout.usec  = 250000;
-		Hurry_timeout.sec  =   0; Hurry_timeout.usec  = 500000;
+			Alive_timeout.sec  =   0; Alive_timeout.usec  = 250000;
+			Join_timeout.sec   =   0; Join_timeout.usec   = 250000;
+			Rep_timeout.sec    =   1; Rep_timeout.usec    = 250000;
+			Seg_timeout.sec    =   0; Seg_timeout.usec    = 500000;
+			Gather_timeout.sec =   2; Gather_timeout.usec = 500000;
+			Form_timeout.sec   =   2; Form_timeout.usec   = 500000;
+			Lookup_timeout.sec =  45; Lookup_timeout.usec = 0;
+		}else{
+			Token_timeout.sec  =   1; Token_timeout.usec  = 250000;
+			Hurry_timeout.sec  =   0; Hurry_timeout.usec  = 500000;
 
-		Alive_timeout.sec  =   0; Alive_timeout.usec  = 250000;
-		Join_timeout.sec   =   0; Join_timeout.usec   = 250000;
-		Rep_timeout.sec    =   0; Rep_timeout.usec    = 625000;
-		Seg_timeout.sec    =   0; Seg_timeout.usec    = 500000;
-		Gather_timeout.sec =   1; Gather_timeout.usec = 250000;
-		Form_timeout.sec   =   1; Form_timeout.usec   = 250000;
-		Lookup_timeout.sec =  30; Lookup_timeout.usec = 0;
+			Alive_timeout.sec  =   0; Alive_timeout.usec  = 250000;
+			Join_timeout.sec   =   0; Join_timeout.usec   = 250000;
+			Rep_timeout.sec    =   0; Rep_timeout.usec    = 625000;
+			Seg_timeout.sec    =   0; Seg_timeout.usec    = 500000;
+			Gather_timeout.sec =   1; Gather_timeout.usec = 250000;
+			Form_timeout.sec   =   1; Form_timeout.usec   = 250000;
+			Lookup_timeout.sec =  30; Lookup_timeout.usec = 0;
+		}
+
+	} else {
+
+	  if (!Conf_all_memb_timeouts_set()) {
+	    Alarm(EXIT, "Memb_init: Only some of the membership timeouts were specified! If you specify any, then you must specify all!\n");
+	  }
+
+	  Token_timeout.sec  =  Conf_get_token_timeout() / 1000;  Token_timeout.usec  = Conf_get_token_timeout() % 1000 * 1000;
+	  Hurry_timeout.sec  =  Conf_get_hurry_timeout() / 1000;  Hurry_timeout.usec  = Conf_get_hurry_timeout() % 1000 * 1000;
+
+	  Alive_timeout.sec  =  Conf_get_alive_timeout() / 1000;  Alive_timeout.usec  = Conf_get_alive_timeout() % 1000 * 1000;
+	  Join_timeout.sec   =  Conf_get_join_timeout() / 1000;   Join_timeout.usec   = Conf_get_join_timeout() % 1000 * 1000;
+	  Rep_timeout.sec    =  Conf_get_rep_timeout() / 1000;    Rep_timeout.usec    = Conf_get_rep_timeout() % 1000 * 1000;
+	  Seg_timeout.sec    =  Conf_get_seg_timeout() / 1000;    Seg_timeout.usec    = Conf_get_seg_timeout() % 1000 * 1000;
+	  Gather_timeout.sec =  Conf_get_gather_timeout() / 1000; Gather_timeout.usec = Conf_get_gather_timeout() % 1000 * 1000;
+	  Form_timeout.sec   =  Conf_get_form_timeout() / 1000;   Form_timeout.usec   = Conf_get_form_timeout() % 1000 * 1000;
+	  Lookup_timeout.sec =  Conf_get_lookup_timeout() / 1000; Lookup_timeout.usec = Conf_get_lookup_timeout() % 1000 * 1000;
+
+	  /*
+	  Alarm(PRINT, "Token_Timeout: %d.%06d\n", Token_timeout.sec, Token_timeout.usec);
+	  Alarm(PRINT, "Hurry_Timeout: %d.%06d\n", Hurry_timeout.sec, Hurry_timeout.usec);
+	  Alarm(PRINT, "Alive_Timeout: %d.%06d\n", Alive_timeout.sec, Alive_timeout.usec);
+	  Alarm(PRINT, "Join_Timeout: %d.%06d\n", Join_timeout.sec, Join_timeout.usec);
+	  Alarm(PRINT, "Rep_Timeout: %d.%06d\n", Rep_timeout.sec, Rep_timeout.usec);
+	  Alarm(PRINT, "Seg_Timeout: %d.%06d\n", Seg_timeout.sec, Seg_timeout.usec);
+	  Alarm(PRINT, "Gather_Timeout: %d.%06d\n", Gather_timeout.sec, Gather_timeout.usec);
+	  Alarm(PRINT, "Form_Timeout: %d.%06d\n", Form_timeout.sec, Form_timeout.usec);
+	  Alarm(PRINT, "Lookup_Timeout: %d.%06d\n", Lookup_timeout.sec, Lookup_timeout.usec);
+	  */
 	}
 
 	Membership = Conf();

Modified: trunk/daemon/spread_params.h
===================================================================
--- trunk/daemon/spread_params.h	2013-03-13 18:50:12 UTC (rev 552)
+++ trunk/daemon/spread_params.h	2013-03-13 20:15:32 UTC (rev 553)
@@ -89,4 +89,7 @@
 
 #define         MAX_WRAP_SEQUENCE_VALUE (1<<30) /* Maximum value for token->seq before reseting to zero with membership */
 
+#define		DEFAULT_WINDOW 		100
+#define		DEFAULT_PERSONAL_WINDOW	 20
+
 #endif /* INC_SPREAD_PARAMS */

Modified: trunk/docs/sample.spread.conf
===================================================================
--- trunk/docs/sample.spread.conf	2013-03-13 18:50:12 UTC (rev 552)
+++ trunk/docs/sample.spread.conf	2013-03-13 20:15:32 UTC (rev 553)
@@ -234,3 +234,23 @@
 # just listening for all types of traffic and events on both the 192.168.0 and 1.2.3 
 # networks. If no letter is listed before the interface address then ALL types of 
 # events are handled on that interface.
+
+# Flow Control Parameters
+#
+#Window = 100
+#PersonalWindow = 20
+
+# Membership Timeouts (in terms of milliseconds)
+# 
+# If you specify any of these timeouts then you must specify all of them
+# (and ensure that they make sense collectively)
+#
+#TokenTimeout = 1250
+#HurryTimeout = 500
+#AliveTimeout = 250
+#JoinTimeout = 250
+#RepTimeout = 625
+#SegTimeout = 500
+#GatherTimeout = 1250
+#FormTimeout = 1250
+#LookupTimeout = 30000




More information about the Spread-cvs mailing list