Le 03/08/2010 13:29, Guillaume Lelarge a écrit :
> Le 03/08/2010 12:23, Tatsuo Ishii a écrit :
>>> Le 03/08/2010 03:48, Tatsuo Ishii a écrit :
>>>>>>> AFAICT, it works really good. We still miss pgsql_pid. And should I add
>>>>>>> some other reports? what do other people need?
>>>>>>>
>>>>>>
>>>>>> No comments on this patch? meaning I should commit it or not?
>>>>>
>>>>> I was waiting for you add pgsql_pid. Have you done it?
>>>>
>>>> I have added new function:
>>>> /*
>>>>  * Return pointer to i th child, j th connection pool and k th backend
>>>>  * of connection info on shmem.
>>>>  */
>>>> ConnectionInfo *pool_coninfo(int child, int connection_pool, int backend)
>>>>
>>>> I hope this will make your implementation regarding pgsql_pid easier.
>>>> For example, pool_coninfo(10, 0, 1) will return pointer to
>>>> ConnectionInfo corresponds to 1th backend pid which is in 0th
>>>> connection pool in 10th pgpool child.
>>>
>>> Sorry for not answering sooner. I thought you were working on adding
>>> pgsql_pid. There was a little misunderstanding :)
>>
>> Oh, I thought I woould work on pcp command, you would work on show
>> command. 
>>
> 
> No problem :)
> 
> I'll work on it ASAP.
> 

With your last commits, it makes it quite easy to do. Here is my new
patch. I still have an issue and perhaps you have an idea on how to
resolve it. Is there a way to know which connection is the active one in
a pool?


-- 
Guillaume
 http://www.postgresql.fr
 http://dalibo.com
Index: pool_process_query.c
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_process_query.c,v
retrieving revision 1.233
diff -c -p -r1.233 pool_process_query.c
*** pool_process_query.c	3 Aug 2010 06:37:18 -0000	1.233
--- pool_process_query.c	5 Aug 2010 12:06:37 -0000
*************** POOL_STATUS pool_parallel_exec(POOL_CONN
*** 461,467 ****
  	fd_set writemask;
  	fd_set exceptmask;
  	unsigned long donemask[FD_SETSIZE / BITS];
! 	static char *sq = "show pool_status";
  	POOL_STATUS status;
  	struct timeval timeout;
  	int num_fds;
--- 461,471 ----
  	fd_set writemask;
  	fd_set exceptmask;
  	unsigned long donemask[FD_SETSIZE / BITS];
!  	static char *sq_config = "show pool_status";
!  	static char *sq_pools = "show pool_pools";
!  	static char *sq_processes = "show pool_processes";
!  	static char *sq_nodes = "show pool_nodes";
!  	static char *sq_version = "show pool_version";
  	POOL_STATUS status;
  	struct timeval timeout;
  	int num_fds;
*************** POOL_STATUS pool_parallel_exec(POOL_CONN
*** 488,501 ****
  	}
  
  	/* process status reporting? */
! 	if (strncasecmp(sq, string, strlen(sq)) == 0)
  	{
  		pool_debug("process reporting");
! 		process_reporting(frontend, backend);
  		pool_unset_query_in_progress();
  		return POOL_CONTINUE;
  	}
  
  	/* In this loop,forward the query to the all backends */
  	for (i=0;i<NUM_BACKENDS;i++)
  	{
--- 492,537 ----
  	}
  
  	/* process status reporting? */
!  	if (strncasecmp(sq_config, string, strlen(sq_config)) == 0)
!  	{
!  		pool_debug("config reporting");
!  		config_reporting(frontend, backend);
!  		pool_unset_query_in_progress();
!  		return POOL_CONTINUE;
!  	}
!  
!  	if (strncasecmp(sq_pools, string, strlen(sq_pools)) == 0)
! 	{
! 		pool_debug("pools reporting");
! 		pools_reporting(frontend, backend);
! 		pool_unset_query_in_progress();
! 		return POOL_CONTINUE;
! 	}
! 
!  	if (strncasecmp(sq_processes, string, strlen(sq_processes)) == 0)
  	{
  		pool_debug("process reporting");
! 		processes_reporting(frontend, backend);
  		pool_unset_query_in_progress();
  		return POOL_CONTINUE;
  	}
  
+  	if (strncasecmp(sq_nodes, string, strlen(sq_nodes)) == 0)
+  	{
+  		pool_debug("nodes reporting");
+  		nodes_reporting(frontend, backend);
+  		pool_unset_query_in_progress();
+  		return POOL_CONTINUE;
+  	}
+  
+  	if (strncasecmp(sq_version, string, strlen(sq_version)) == 0)
+  	{
+  		pool_debug("version reporting");
+  		version_reporting(frontend, backend);
+  		pool_unset_query_in_progress();
+  		return POOL_CONTINUE;
+  	}
+  
  	/* In this loop,forward the query to the all backends */
  	for (i=0;i<NUM_BACKENDS;i++)
  	{
Index: pool_process_reporting.c
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_process_reporting.c,v
retrieving revision 1.9
diff -c -p -r1.9 pool_process_reporting.c
*** pool_process_reporting.c	21 Jun 2010 05:46:57 -0000	1.9
--- pool_process_reporting.c	5 Aug 2010 12:06:38 -0000
***************
*** 18,34 ****
   * suitability of this software for any purpose.  It is provided "as
   * is" without express or implied warranty.
   *
!  * Process "show pool_status" query.
   */
  #include "pool.h"
  #include "pool_proto_modules.h"
  #include "pool_stream.h"
  #include "pool_config.h"
  
  #include <string.h>
  #include <netinet/in.h>
  
! void process_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
  {
  	static char *cursorname = "blank";
  	static short num_fields = 3;
--- 18,90 ----
   * suitability of this software for any purpose.  It is provided "as
   * is" without express or implied warranty.
   *
!  * Process pgPool-II "SHOW" queries.
   */
  #include "pool.h"
  #include "pool_proto_modules.h"
  #include "pool_stream.h"
  #include "pool_config.h"
+ #include "version.h"
  
  #include <string.h>
  #include <netinet/in.h>
  
! /* some length definitions */
! #define POOLCONFIG_MAXNAMELEN 32
! #define POOLCONFIG_MAXVALLEN 512
! #define POOLCONFIG_MAXDESCLEN 64
! #define POOLCONFIG_MAXIDENTLEN 63
! #define POOLCONFIG_MAXPORTLEN 6
! #define POOLCONFIG_MAXSTATLEN 2
! #define POOLCONFIG_MAXWEIGHTLEN 20
! #define POOLCONFIG_MAXDATELEN 20
! #define POOLCONFIG_MAXCOUNTLEN 16
! 
! /* config report struct*/
! typedef struct {
! 	char name[POOLCONFIG_MAXNAMELEN+1];
! 	char value[POOLCONFIG_MAXVALLEN+1];
! 	char desc[POOLCONFIG_MAXDESCLEN+1];
! } POOL_REPORT_STATUS;
! 
! /* nodes report struct */
! typedef struct {
! 	char hostname[POOLCONFIG_MAXIDENTLEN+1];
! 	char port[POOLCONFIG_MAXIDENTLEN+1];
! 	char status[POOLCONFIG_MAXSTATLEN+1];
! 	char lb_weight[POOLCONFIG_MAXWEIGHTLEN+1];
! } POOL_REPORT_NODES;
! 
! /* processes report struct */
! typedef struct {
! 	char pool_pid[POOLCONFIG_MAXCOUNTLEN+1];
! 	char database[POOLCONFIG_MAXIDENTLEN+1];
! 	char username[POOLCONFIG_MAXIDENTLEN+1];
! 	char start_time[POOLCONFIG_MAXDATELEN+1];
! 	char create_time[POOLCONFIG_MAXDATELEN+1];
! 	char pool_counter[POOLCONFIG_MAXCOUNTLEN+1];
! } POOL_REPORT_PROCESSES;
! 
! /* pools reporting struct */
! typedef struct {
! 	char pool_pid[POOLCONFIG_MAXCOUNTLEN+1];
! 	char pool_id[POOLCONFIG_MAXCOUNTLEN+1];
! 	char database[POOLCONFIG_MAXIDENTLEN+1];
! 	char username[POOLCONFIG_MAXIDENTLEN+1];
! 	char start_time[POOLCONFIG_MAXDATELEN+1];
! 	char create_time[POOLCONFIG_MAXDATELEN+1];
! 	char pool_majorversion[POOLCONFIG_MAXCOUNTLEN+1];
! 	char pool_minorversion[POOLCONFIG_MAXCOUNTLEN+1];
! 	char pool_counter[POOLCONFIG_MAXCOUNTLEN+1];
! 	char pool_backendpid[POOLCONFIG_MAXCOUNTLEN+1];
! } POOL_REPORT_POOLS;
! 
! /* version struct */
! typedef struct {
! 	char version[POOLCONFIG_MAXVALLEN+1];
! } POOL_REPORT_VERSION;
! 
! void config_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
  {
  	static char *cursorname = "blank";
  	static short num_fields = 3;
*************** void process_reporting(POOL_CONNECTION *
*** 45,60 ****
  	static unsigned char nullmap[2] = {0xff, 0xff};
  	int nbytes = (num_fields + 7)/8;
  
- #define POOLCONFIG_MAXNAMELEN 32
- #define POOLCONFIG_MAXVALLEN 512
- #define POOLCONFIG_MAXDESCLEN 64
- 
- 	typedef struct {
- 		char name[POOLCONFIG_MAXNAMELEN+1];
- 		char value[POOLCONFIG_MAXVALLEN+1];
- 		char desc[POOLCONFIG_MAXDESCLEN+1];
- 	} POOL_REPORT_STATUS;
- 
  /*
   * Report data buffer.
   * 128 is the max number of configuration items.
--- 101,106 ----
*************** void process_reporting(POOL_CONNECTION *
*** 522,528 ****
  			len += sizeof(int) + strlen(status[i].desc);
  			len = htonl(len);
  			pool_write(frontend, &len, sizeof(len));
! 			s = htons(3);
  			pool_write(frontend, &s, sizeof(s));
  
  			len = htonl(strlen(status[i].name));
--- 568,574 ----
  			len += sizeof(int) + strlen(status[i].desc);
  			len = htonl(len);
  			pool_write(frontend, &len, sizeof(len));
! 			s = htons(num_fields);
  			pool_write(frontend, &s, sizeof(s));
  
  			len = htonl(strlen(status[i].name));
*************** void process_reporting(POOL_CONNECTION *
*** 559,561 ****
--- 605,1402 ----
  
  	pool_flush(frontend);
  }
+ 
+ void nodes_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
+ {
+ 	static char *cursorname = "blank";
+ 	static short num_fields = 4;
+ 	static char *field_names[] = {"hostname", "port", "status", "lb_weight"};
+ 	static int oid = 0;
+ 	static short fsize = -1;
+ 	static int mod = 0;
+ 	short n;
+ 	int i;
+ 	short s;
+ 	int len;
+ 	short colnum;
+ 
+ 	static unsigned char nullmap[2] = {0xff, 0xff};
+ 	int nbytes = (num_fields + 7)/8;
+ 
+ 	POOL_REPORT_NODES nodes[NUM_BACKENDS];
+ 
+ 	short nrows;
+ 	int size;
+ 	int hsize;
+ 
+ 	i = 0;
+ 
+     char port_str[6];
+     char status[2];
+     char weight_str[20];
+ 
+ 	BackendInfo *bi = NULL;
+ 
+     for (i = 0; i < NUM_BACKENDS; i++)
+ 	{
+ 	    bi = pool_get_node_info(i);
+ 
+ 	    strncpy(nodes[i].hostname, bi->backend_hostname, strlen(bi->backend_hostname)+1);
+ 		snprintf(nodes[i].port, sizeof(port_str), "%d", bi->backend_port);
+ 		snprintf(nodes[i].status, sizeof(status), "%d", bi->backend_status);
+ 		snprintf(nodes[i].lb_weight, sizeof(weight_str), "%f", bi->backend_weight);
+ 	}
+ 
+ 	nrows = i;
+ 
+ 	if (MAJOR(backend) == PROTO_MAJOR_V2)
+ 	{
+ 		/* cursor response */
+ 		pool_write(frontend, "P", 1);
+ 		pool_write(frontend, cursorname, strlen(cursorname)+1);
+ 	}
+ 
+ 	/* row description */
+ 	pool_write(frontend, "T", 1);
+ 
+ 	if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 	{
+ 		len = sizeof(num_fields) + sizeof(len);
+ 
+ 		for (i=0;i<num_fields;i++)
+ 		{
+ 			char *f = field_names[i];
+ 			len += strlen(f)+1;
+ 			len += sizeof(oid);
+ 			len += sizeof(colnum);
+ 			len += sizeof(oid);
+ 			len += sizeof(s);
+ 			len += sizeof(mod);
+ 			len += sizeof(s);
+ 		}
+ 
+ 		len = htonl(len);
+ 		pool_write(frontend, &len, sizeof(len));
+ 	}
+ 
+ 	n = htons(num_fields);
+ 	pool_write(frontend, &n, sizeof(short));
+ 
+ 	for (i=0;i<num_fields;i++)
+ 	{
+ 		char *f = field_names[i];
+ 
+ 		pool_write(frontend, f, strlen(f)+1);		/* field name */
+ 
+ 		if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 		{
+ 			pool_write(frontend, &oid, sizeof(oid));	/* table oid */
+ 			colnum = htons(i);
+ 			pool_write(frontend, &colnum, sizeof(colnum));	/* column number */
+ 		}
+ 
+ 		pool_write(frontend, &oid, sizeof(oid));		/* data type oid */
+ 		s = htons(fsize);
+ 		pool_write(frontend, &s, sizeof(fsize));		/* field size */
+ 		pool_write(frontend, &mod, sizeof(mod));		/* modifier */
+ 
+ 		if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 		{
+ 			s = htons(0);
+ 			pool_write(frontend, &s, sizeof(fsize));	/* field format (text) */
+ 		}
+ 	}
+ 	pool_flush(frontend);
+ 
+ 	if (MAJOR(backend) == PROTO_MAJOR_V2)
+ 	{
+ 		/* ascii row */
+ 		for (i=0;i<nrows;i++)
+ 		{
+ 			pool_write(frontend, "D", 1);
+ 			pool_write_and_flush(frontend, nullmap, nbytes);
+ 
+ 			size = strlen(nodes[i].hostname);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, nodes[i].hostname, size);
+ 
+ 			size = strlen(nodes[i].port);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, nodes[i].port, size);
+ 
+ 			size = strlen(nodes[i].status);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, nodes[i].status, size);
+ 
+ 			size = strlen(nodes[i].lb_weight);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, nodes[i].lb_weight, size);
+ 		}
+ 	}
+ 	else
+ 	{
+ 		/* data row */
+ 		for (i=0;i<nrows;i++)
+ 		{
+ 			pool_write(frontend, "D", 1);
+ 			len = sizeof(len) + sizeof(nrows);
+ 			len += sizeof(int) + strlen(nodes[i].hostname);
+ 			len += sizeof(int) + strlen(nodes[i].port);
+ 			len += sizeof(int) + strlen(nodes[i].status);
+ 			len += sizeof(int) + strlen(nodes[i].lb_weight);
+ 			len = htonl(len);
+ 			pool_write(frontend, &len, sizeof(len));
+ 			s = htons(num_fields);
+ 			pool_write(frontend, &s, sizeof(s));
+ 
+ 			len = htonl(strlen(nodes[i].hostname));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, nodes[i].hostname, strlen(nodes[i].hostname));
+ 
+ 			len = htonl(strlen(nodes[i].port));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, nodes[i].port, strlen(nodes[i].port));
+ 
+ 			len = htonl(strlen(nodes[i].status));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, nodes[i].status, strlen(nodes[i].status));
+ 
+ 			len = htonl(strlen(nodes[i].lb_weight));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, nodes[i].lb_weight, strlen(nodes[i].lb_weight));
+ 		}
+ 	}
+ 
+ 	/* complete command response */
+ 	pool_write(frontend, "C", 1);
+ 	if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 	{
+ 		len = htonl(sizeof(len) + strlen("SELECT")+1);
+ 		pool_write(frontend, &len, sizeof(len));
+ 	}
+ 	pool_write(frontend, "SELECT", strlen("SELECT")+1);
+ 
+ 	/* ready for query */
+ 	pool_write(frontend, "Z", 1);
+ 	if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 	{
+ 		len = htonl(sizeof(len) + 1);
+ 		pool_write(frontend, &len, sizeof(len));
+ 		pool_write(frontend, "I", 1);
+ 	}
+ 
+ 	pool_flush(frontend);
+ }
+ 
+ void pools_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
+ {
+ 	static char *cursorname = "blank";
+ 	static short num_fields = 10;
+ 	static char *field_names[] = {"pool_pid", "pool_id", "database", "username", "start_time", "create_time",
+                                   "majorversion", "minorversion", "pool_counter", "pool_backendpid"};
+ 	static int oid = 0;
+ 	static short fsize = -1;
+ 	static int mod = 0;
+ 	short n;
+ 	int i, j;
+ 	short s;
+ 	int len;
+ 	short colnum;
+ 
+ 	static unsigned char nullmap[2] = {0xff, 0xff};
+ 	int nbytes = (num_fields + 7)/8;
+ 
+ 	POOL_REPORT_POOLS pools[MAX_NUM_BACKENDS * pool_config->max_pool];
+ 
+ 	short nrows;
+ 	int size;
+ 	int hsize;
+ 
+ 	i = 0;
+ 
+     ProcessInfo *pi = NULL;
+     int proc_id;
+ 
+     int k = 0;
+ 	for (i = 0; i < pool_config->num_init_children; i++)
+     {
+ 		proc_id = process_info[i].pid;
+ 	    pi = pool_get_process_info(proc_id);
+     
+         for (j=0;j<pool_config->max_pool;j++)
+         {
+             snprintf(pools[k].pool_pid, POOLCONFIG_MAXCOUNTLEN, "%d", proc_id);
+             snprintf(pools[k].pool_id, POOLCONFIG_MAXCOUNTLEN, "%d", j);
+             strncpy(pools[k].database, pi->connection_info[j].database, POOLCONFIG_MAXIDENTLEN);
+             strncpy(pools[k].username, pi->connection_info[j].user, POOLCONFIG_MAXIDENTLEN);
+             snprintf(pools[k].start_time, POOLCONFIG_MAXDATELEN, "%ld", pi->start_time);
+             snprintf(pools[k].create_time, POOLCONFIG_MAXDATELEN, "%ld", pi->connection_info[j].create_time);
+             snprintf(pools[k].pool_majorversion, POOLCONFIG_MAXCOUNTLEN, "%d", pi->connection_info[i].major);
+             snprintf(pools[k].pool_minorversion, POOLCONFIG_MAXCOUNTLEN, "%d", pi->connection_info[i].minor);
+             snprintf(pools[k].pool_counter, POOLCONFIG_MAXCOUNTLEN, "%d", pi->connection_info[j].counter);
+             snprintf(pools[k].pool_backendpid, POOLCONFIG_MAXCOUNTLEN, "%d", ntohl(pi->connection_info[j].pid));
+             k++;
+         }
+     }
+ 
+ 	nrows = k;
+ 
+ 	if (MAJOR(backend) == PROTO_MAJOR_V2)
+ 	{
+ 		/* cursor response */
+ 		pool_write(frontend, "P", 1);
+ 		pool_write(frontend, cursorname, strlen(cursorname)+1);
+ 	}
+ 
+ 	/* row description */
+ 	pool_write(frontend, "T", 1);
+ 
+ 	if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 	{
+ 		len = sizeof(num_fields) + sizeof(len);
+ 
+ 		for (i=0;i<num_fields;i++)
+ 		{
+ 			char *f = field_names[i];
+ 			len += strlen(f)+1;
+ 			len += sizeof(oid);
+ 			len += sizeof(colnum);
+ 			len += sizeof(oid);
+ 			len += sizeof(s);
+ 			len += sizeof(mod);
+ 			len += sizeof(s);
+ 		}
+ 
+ 		len = htonl(len);
+ 		pool_write(frontend, &len, sizeof(len));
+ 	}
+ 
+ 	n = htons(num_fields);
+ 	pool_write(frontend, &n, sizeof(short));
+ 
+ 	for (i=0;i<num_fields;i++)
+ 	{
+ 		char *f = field_names[i];
+ 
+ 		pool_write(frontend, f, strlen(f)+1);		/* field name */
+ 
+ 		if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 		{
+ 			pool_write(frontend, &oid, sizeof(oid));	/* table oid */
+ 			colnum = htons(i);
+ 			pool_write(frontend, &colnum, sizeof(colnum));	/* column number */
+ 		}
+ 
+ 		pool_write(frontend, &oid, sizeof(oid));		/* data type oid */
+ 		s = htons(fsize);
+ 		pool_write(frontend, &s, sizeof(fsize));		/* field size */
+ 		pool_write(frontend, &mod, sizeof(mod));		/* modifier */
+ 
+ 		if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 		{
+ 			s = htons(0);
+ 			pool_write(frontend, &s, sizeof(fsize));	/* field format (text) */
+ 		}
+ 	}
+ 	pool_flush(frontend);
+ 
+ 	if (MAJOR(backend) == PROTO_MAJOR_V2)
+ 	{
+ 		/* ascii row */
+ 		for (i=0;i<nrows;i++)
+ 		{
+ 			pool_write(frontend, "D", 1);
+ 			pool_write_and_flush(frontend, nullmap, nbytes);
+ 
+ 			size = strlen(pools[i].pool_pid);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, pools[i].pool_pid, size);
+ 
+ 			size = strlen(pools[i].pool_id);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, pools[i].pool_id, size);
+ 
+ 			size = strlen(pools[i].database);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, pools[i].database, size);
+ 
+ 			size = strlen(pools[i].username);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, pools[i].username, size);
+ 
+ 			size = strlen(pools[i].start_time);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, pools[i].start_time, size);
+ 
+ 			size = strlen(pools[i].create_time);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, pools[i].create_time, size);
+ 
+ 			size = strlen(pools[i].pool_majorversion);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, pools[i].pool_majorversion, size);
+ 
+ 			size = strlen(pools[i].pool_minorversion);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, pools[i].pool_minorversion, size);
+ 
+ 			size = strlen(pools[i].pool_counter);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, pools[i].pool_counter, size);
+ 
+ 			size = strlen(pools[i].pool_backendpid);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, pools[i].pool_backendpid, size);
+ 		}
+ 	}
+ 	else
+ 	{
+ 		/* data row */
+ 		for (i=0;i<nrows;i++)
+ 		{
+ 			pool_write(frontend, "D", 1);
+ 			len = sizeof(len) + sizeof(nrows);
+ 			len += sizeof(int) + strlen(pools[i].pool_pid);
+ 			len += sizeof(int) + strlen(pools[i].pool_id);
+ 			len += sizeof(int) + strlen(pools[i].database);
+ 			len += sizeof(int) + strlen(pools[i].username);
+ 			len += sizeof(int) + strlen(pools[i].start_time);
+ 			len += sizeof(int) + strlen(pools[i].create_time);
+ 			len += sizeof(int) + strlen(pools[i].pool_majorversion);
+ 			len += sizeof(int) + strlen(pools[i].pool_minorversion);
+ 			len += sizeof(int) + strlen(pools[i].pool_counter);
+ 			len += sizeof(int) + strlen(pools[i].pool_backendpid);
+ 			len = htonl(len);
+ 			pool_write(frontend, &len, sizeof(len));
+ 			s = htons(num_fields);
+ 			pool_write(frontend, &s, sizeof(s));
+ 
+ 			len = htonl(strlen(pools[i].pool_pid));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, pools[i].pool_pid, strlen(pools[i].pool_pid));
+ 
+ 			len = htonl(strlen(pools[i].pool_id));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, pools[i].pool_id, strlen(pools[i].pool_id));
+ 
+ 			len = htonl(strlen(pools[i].database));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, pools[i].database, strlen(pools[i].database));
+ 
+ 			len = htonl(strlen(pools[i].username));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, pools[i].username, strlen(pools[i].username));
+ 
+ 			len = htonl(strlen(pools[i].start_time));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, pools[i].start_time, strlen(pools[i].start_time));
+ 
+ 			len = htonl(strlen(pools[i].create_time));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, pools[i].create_time, strlen(pools[i].create_time));
+ 
+ 			len = htonl(strlen(pools[i].pool_majorversion));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, pools[i].pool_majorversion, strlen(pools[i].pool_majorversion));
+ 
+ 			len = htonl(strlen(pools[i].pool_minorversion));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, pools[i].pool_minorversion, strlen(pools[i].pool_minorversion));
+ 
+ 			len = htonl(strlen(pools[i].pool_counter));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, pools[i].pool_counter, strlen(pools[i].pool_counter));
+ 
+ 			len = htonl(strlen(pools[i].pool_backendpid));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, pools[i].pool_backendpid, strlen(pools[i].pool_backendpid));
+ 		}
+ 	}
+ 
+ 	/* complete command response */
+ 	pool_write(frontend, "C", 1);
+ 	if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 	{
+ 		len = htonl(sizeof(len) + strlen("SELECT")+1);
+ 		pool_write(frontend, &len, sizeof(len));
+ 	}
+ 	pool_write(frontend, "SELECT", strlen("SELECT")+1);
+ 
+ 	/* ready for query */
+ 	pool_write(frontend, "Z", 1);
+ 	if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 	{
+ 		len = htonl(sizeof(len) + 1);
+ 		pool_write(frontend, &len, sizeof(len));
+ 		pool_write(frontend, "I", 1);
+ 	}
+ 
+ 	pool_flush(frontend);
+ }
+ 
+ void processes_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
+ {
+ 	static char *cursorname = "blank";
+ 	static short num_fields = 6;
+ 	static char *field_names[] = {"pool_pid", "database", "username", "start_time", "create_time", "pool_counter"};
+ 	static int oid = 0;
+ 	static short fsize = -1;
+ 	static int mod = 0;
+ 	short n;
+ 	int i;
+ 	short s;
+ 	int len;
+ 	short colnum;
+ 
+ 	static unsigned char nullmap[2] = {0xff, 0xff};
+ 	int nbytes = (num_fields + 7)/8;
+ 
+ 	static POOL_REPORT_PROCESSES processes[MAX_NUM_BACKENDS];
+ 
+ 	short nrows;
+ 	int size;
+ 	int hsize;
+ 
+ 	i = 0;
+ 
+     ProcessInfo *pi = NULL;
+     int proc_id;
+ 
+ 	for (i = 0; i < pool_config->num_init_children; i++)
+     {
+ 		proc_id = process_info[i].pid;
+ 	    pi = pool_get_process_info(proc_id);
+     
+         snprintf(processes[i].pool_pid, POOLCONFIG_MAXCOUNTLEN, "%d", proc_id);
+ 	    strncpy(processes[i].database, pi->connection_info[0].database, POOLCONFIG_MAXIDENTLEN);
+ 	    strncpy(processes[i].username, pi->connection_info[0].user, POOLCONFIG_MAXIDENTLEN);
+         snprintf(processes[i].start_time, POOLCONFIG_MAXDATELEN, "%ld", pi->start_time);
+         snprintf(processes[i].create_time, POOLCONFIG_MAXDATELEN, "%ld", pi->connection_info[0].create_time);
+         //snprintf(majorversion, sizeof(majorversion), "%d", pi->connection_info[i].major);
+         //snprintf(minorversion, sizeof(minorversion), "%d", pi->connection_info[i].minor);
+         snprintf(processes[i].pool_counter, POOLCONFIG_MAXCOUNTLEN, "%d", pi->connection_info[0].counter);
+     }
+ 
+ 	nrows = i;
+ 
+ 	if (MAJOR(backend) == PROTO_MAJOR_V2)
+ 	{
+ 		/* cursor response */
+ 		pool_write(frontend, "P", 1);
+ 		pool_write(frontend, cursorname, strlen(cursorname)+1);
+ 	}
+ 
+ 	/* row description */
+ 	pool_write(frontend, "T", 1);
+ 
+ 	if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 	{
+ 		len = sizeof(num_fields) + sizeof(len);
+ 
+ 		for (i=0;i<num_fields;i++)
+ 		{
+ 			char *f = field_names[i];
+ 			len += strlen(f)+1;
+ 			len += sizeof(oid);
+ 			len += sizeof(colnum);
+ 			len += sizeof(oid);
+ 			len += sizeof(s);
+ 			len += sizeof(mod);
+ 			len += sizeof(s);
+ 		}
+ 
+ 		len = htonl(len);
+ 		pool_write(frontend, &len, sizeof(len));
+ 	}
+ 
+ 	n = htons(num_fields);
+ 	pool_write(frontend, &n, sizeof(short));
+ 
+ 	for (i=0;i<num_fields;i++)
+ 	{
+ 		char *f = field_names[i];
+ 
+ 		pool_write(frontend, f, strlen(f)+1);		/* field name */
+ 
+ 		if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 		{
+ 			pool_write(frontend, &oid, sizeof(oid));	/* table oid */
+ 			colnum = htons(i);
+ 			pool_write(frontend, &colnum, sizeof(colnum));	/* column number */
+ 		}
+ 
+ 		pool_write(frontend, &oid, sizeof(oid));		/* data type oid */
+ 		s = htons(fsize);
+ 		pool_write(frontend, &s, sizeof(fsize));		/* field size */
+ 		pool_write(frontend, &mod, sizeof(mod));		/* modifier */
+ 
+ 		if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 		{
+ 			s = htons(0);
+ 			pool_write(frontend, &s, sizeof(fsize));	/* field format (text) */
+ 		}
+ 	}
+ 	pool_flush(frontend);
+ 
+ 	if (MAJOR(backend) == PROTO_MAJOR_V2)
+ 	{
+ 		/* ascii row */
+ 		for (i=0;i<nrows;i++)
+ 		{
+ 			pool_write(frontend, "D", 1);
+ 			pool_write_and_flush(frontend, nullmap, nbytes);
+ 
+ 			size = strlen(processes[i].pool_pid);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, processes[i].pool_pid, size);
+ 
+ 			size = strlen(processes[i].database);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, processes[i].database, size);
+ 
+ 			size = strlen(processes[i].username);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, processes[i].username, size);
+ 
+ 			size = strlen(processes[i].start_time);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, processes[i].start_time, size);
+ 
+ 			size = strlen(processes[i].create_time);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, processes[i].create_time, size);
+ 
+ 			size = strlen(processes[i].pool_counter);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, processes[i].pool_counter, size);
+ 		}
+ 	}
+ 	else
+ 	{
+ 		/* data row */
+ 		for (i=0;i<nrows;i++)
+ 		{
+ 			pool_write(frontend, "D", 1);
+ 			len = sizeof(len) + sizeof(nrows);
+ 			len += sizeof(int) + strlen(processes[i].pool_pid);
+ 			len += sizeof(int) + strlen(processes[i].database);
+ 			len += sizeof(int) + strlen(processes[i].username);
+ 			len += sizeof(int) + strlen(processes[i].start_time);
+ 			len += sizeof(int) + strlen(processes[i].create_time);
+ 			len += sizeof(int) + strlen(processes[i].pool_counter);
+ 			len = htonl(len);
+ 			pool_write(frontend, &len, sizeof(len));
+ 			s = htons(num_fields);
+ 			pool_write(frontend, &s, sizeof(s));
+ 
+ 			len = htonl(strlen(processes[i].pool_pid));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, processes[i].pool_pid, strlen(processes[i].pool_pid));
+ 
+ 			len = htonl(strlen(processes[i].database));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, processes[i].database, strlen(processes[i].database));
+ 
+ 			len = htonl(strlen(processes[i].username));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, processes[i].username, strlen(processes[i].username));
+ 
+ 			len = htonl(strlen(processes[i].start_time));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, processes[i].start_time, strlen(processes[i].start_time));
+ 
+ 			len = htonl(strlen(processes[i].create_time));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, processes[i].create_time, strlen(processes[i].create_time));
+ 
+ 			len = htonl(strlen(processes[i].pool_counter));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, processes[i].pool_counter, strlen(processes[i].pool_counter));
+ 		}
+ 	}
+ 
+ 	/* complete command response */
+ 	pool_write(frontend, "C", 1);
+ 	if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 	{
+ 		len = htonl(sizeof(len) + strlen("SELECT")+1);
+ 		pool_write(frontend, &len, sizeof(len));
+ 	}
+ 	pool_write(frontend, "SELECT", strlen("SELECT")+1);
+ 
+ 	/* ready for query */
+ 	pool_write(frontend, "Z", 1);
+ 	if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 	{
+ 		len = htonl(sizeof(len) + 1);
+ 		pool_write(frontend, &len, sizeof(len));
+ 		pool_write(frontend, "I", 1);
+ 	}
+ 
+ 	pool_flush(frontend);
+ }
+ 
+ void version_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
+ {
+ 	static char *cursorname = "blank";
+ 	static short num_fields = 1;
+ 	static char *field_names[] = {"pool_version"};
+ 	static int oid = 0;
+ 	static short fsize = -1;
+ 	static int mod = 0;
+ 	short n;
+ 	int i;
+ 	short s;
+ 	int len;
+ 	short colnum;
+ 
+ 	static unsigned char nullmap[2] = {0xff, 0xff};
+ 	int nbytes = (num_fields + 7)/8;
+ 
+ /*
+  * Report data buffer.
+  * 1 for the version
+  */
+ 	static POOL_REPORT_VERSION version[1];
+ 
+ 	short nrows;
+ 	int size;
+ 	int hsize;
+ 
+ 	snprintf(version[0].version, POOLCONFIG_MAXVALLEN, "%s (%s)", VERSION, PGPOOLVERSION);
+ 
+ 	nrows = 1;
+ 
+ 	if (MAJOR(backend) == PROTO_MAJOR_V2)
+ 	{
+ 		/* cursor response */
+ 		pool_write(frontend, "P", 1);
+ 		pool_write(frontend, cursorname, strlen(cursorname)+1);
+ 	}
+ 
+ 	/* row description */
+ 	pool_write(frontend, "T", 1);
+ 
+ 	if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 	{
+ 		len = sizeof(num_fields) + sizeof(len);
+ 
+ 		for (i=0;i<num_fields;i++)
+ 		{
+ 			char *f = field_names[i];
+ 			len += strlen(f)+1;
+ 			len += sizeof(oid);
+ 			len += sizeof(colnum);
+ 			len += sizeof(oid);
+ 			len += sizeof(s);
+ 			len += sizeof(mod);
+ 			len += sizeof(s);
+ 		}
+ 
+ 		len = htonl(len);
+ 		pool_write(frontend, &len, sizeof(len));
+ 	}
+ 
+ 	n = htons(num_fields);
+ 	pool_write(frontend, &n, sizeof(short));
+ 
+ 	for (i=0;i<num_fields;i++)
+ 	{
+ 		char *f = field_names[i];
+ 
+ 		pool_write(frontend, f, strlen(f)+1);		/* field name */
+ 
+ 		if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 		{
+ 			pool_write(frontend, &oid, sizeof(oid));	/* table oid */
+ 			colnum = htons(i);
+ 			pool_write(frontend, &colnum, sizeof(colnum));	/* column number */
+ 		}
+ 
+ 		pool_write(frontend, &oid, sizeof(oid));		/* data type oid */
+ 		s = htons(fsize);
+ 		pool_write(frontend, &s, sizeof(fsize));		/* field size */
+ 		pool_write(frontend, &mod, sizeof(mod));		/* modifier */
+ 
+ 		if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 		{
+ 			s = htons(0);
+ 			pool_write(frontend, &s, sizeof(fsize));	/* field format (text) */
+ 		}
+ 	}
+ 	pool_flush(frontend);
+ 
+ 	if (MAJOR(backend) == PROTO_MAJOR_V2)
+ 	{
+ 		/* ascii row */
+ 		for (i=0;i<nrows;i++)
+ 		{
+ 			pool_write(frontend, "D", 1);
+ 			pool_write_and_flush(frontend, nullmap, nbytes);
+ 
+ 			size = strlen(version[i].version);
+ 			hsize = htonl(size+4);
+ 			pool_write(frontend, &hsize, sizeof(hsize));
+ 			pool_write(frontend, version[i].version, size);
+ 		}
+ 	}
+ 	else
+ 	{
+ 		/* data row */
+ 		for (i=0;i<nrows;i++)
+ 		{
+ 			pool_write(frontend, "D", 1);
+ 			len = sizeof(len) + sizeof(nrows);
+ 			len += sizeof(int) + strlen(version[i].version);
+ 			len = htonl(len);
+ 			pool_write(frontend, &len, sizeof(len));
+ 			s = htons(num_fields);
+ 			pool_write(frontend, &s, sizeof(s));
+ 
+ 			len = htonl(strlen(version[i].version));
+ 			pool_write(frontend, &len, sizeof(len));
+ 			pool_write(frontend, version[i].version, strlen(version[i].version));
+ 		}
+ 	}
+ 
+ 	/* complete command response */
+ 	pool_write(frontend, "C", 1);
+ 	if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 	{
+ 		len = htonl(sizeof(len) + strlen("SELECT")+1);
+ 		pool_write(frontend, &len, sizeof(len));
+ 	}
+ 	pool_write(frontend, "SELECT", strlen("SELECT")+1);
+ 
+ 	/* ready for query */
+ 	pool_write(frontend, "Z", 1);
+ 	if (MAJOR(backend) == PROTO_MAJOR_V3)
+ 	{
+ 		len = htonl(sizeof(len) + 1);
+ 		pool_write(frontend, &len, sizeof(len));
+ 		pool_write(frontend, "I", 1);
+ 	}
+ 
+ 	pool_flush(frontend);
+ }
+ 
Index: pool_proto_modules.c
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_proto_modules.c,v
retrieving revision 1.74
diff -c -p -r1.74 pool_proto_modules.c
*** pool_proto_modules.c	4 Aug 2010 02:58:38 -0000	1.74
--- pool_proto_modules.c	5 Aug 2010 12:06:38 -0000
*************** static int* find_victim_nodes(int *ntupl
*** 106,112 ****
  POOL_STATUS SimpleQuery(POOL_CONNECTION *frontend,
  						POOL_CONNECTION_POOL *backend, int len, char *contents)
  {
! 	static char *sq = "show pool_status";
  	int commit;
  	List *parse_tree_list;
  	Node *node = NULL;
--- 106,116 ----
  POOL_STATUS SimpleQuery(POOL_CONNECTION *frontend,
  						POOL_CONNECTION_POOL *backend, int len, char *contents)
  {
! 	static char *sq_config = "show pool_status";
! 	static char *sq_pools = "show pool_pools";
! 	static char *sq_processes = "show pool_processes";
!  	static char *sq_nodes = "show pool_nodes";
!  	static char *sq_version = "show pool_version";
  	int commit;
  	List *parse_tree_list;
  	Node *node = NULL;
*************** POOL_STATUS SimpleQuery(POOL_CONNECTION 
*** 235,248 ****
  			}
  		}
  
! 		/* process status reporting? */
! 		if (IsA(node, VariableShowStmt) && strncasecmp(sq, contents, strlen(sq)) == 0)
  		{
  			StartupPacket *sp;
  			char psbuf[1024];
  
! 			pool_debug("process reporting");
! 			process_reporting(frontend, backend);
  
  			/* show ps status */
  			sp = MASTER_CONNECTION(backend)->sp;
--- 239,279 ----
  			}
  		}
  
! 		/* status reporting? */
! 		if ((IsA(node, VariableShowStmt) && strncasecmp(sq_config, contents, strlen(sq_config)) == 0)
!          || (IsA(node, VariableShowStmt) && strncasecmp(sq_pools, contents, strlen(sq_pools)) == 0)
!          || (IsA(node, VariableShowStmt) && strncasecmp(sq_processes, contents, strlen(sq_processes)) == 0)
!          || (IsA(node, VariableShowStmt) && strncasecmp(sq_nodes, contents, strlen(sq_nodes)) == 0)
!          || (IsA(node, VariableShowStmt) && strncasecmp(sq_version, contents, strlen(sq_version)) == 0))
  		{
  			StartupPacket *sp;
  			char psbuf[1024];
  
! 			if (strncasecmp(sq_config, contents, strlen(sq_config)) == 0)
!             {
!                 pool_debug("config reporting");
!                 config_reporting(frontend, backend);
!             }
! 			else if (strncasecmp(sq_pools, contents, strlen(sq_pools)) == 0)
!             {
!                 pool_debug("pools reporting");
!                 pools_reporting(frontend, backend);
!             }
! 			else if (strncasecmp(sq_processes, contents, strlen(sq_processes)) == 0)
!             {
!                 pool_debug("processes reporting");
!                 processes_reporting(frontend, backend);
!             }
! 			else if (strncasecmp(sq_nodes, contents, strlen(sq_nodes)) == 0)
!             {
!                 pool_debug("nodes reporting");
!                 nodes_reporting(frontend, backend);
!             }
! 			else if (strncasecmp(sq_version, contents, strlen(sq_version)) == 0)
!             {
!                 pool_debug("version reporting");
!                 version_reporting(frontend, backend);
!             }
  
  			/* show ps status */
  			sp = MASTER_CONNECTION(backend)->sp;
Index: pool_proto_modules.h
===================================================================
RCS file: /cvsroot/pgpool/pgpool-II/pool_proto_modules.h,v
retrieving revision 1.17
diff -c -p -r1.17 pool_proto_modules.h
*** pool_proto_modules.h	4 Aug 2010 02:58:38 -0000	1.17
--- pool_proto_modules.h	5 Aug 2010 12:06:38 -0000
*************** extern bool is_partition_table(POOL_CONN
*** 174,180 ****
  extern POOL_STATUS pool_discard_packet(POOL_CONNECTION_POOL *cp);
  
  extern int is_drop_database(Node *node);		/* returns non 0 if this is a DROP DATABASE command */
! extern void process_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend);
  
  extern POOL_STATUS send_simplequery_message(POOL_CONNECTION *backend, int len, char *string, int major);
  extern POOL_STATUS send_extended_protocol_message(POOL_CONNECTION_POOL *backend,
--- 174,184 ----
  extern POOL_STATUS pool_discard_packet(POOL_CONNECTION_POOL *cp);
  
  extern int is_drop_database(Node *node);		/* returns non 0 if this is a DROP DATABASE command */
! extern void config_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend);
! extern void pools_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend);
! extern void processes_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend);
! extern void nodes_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend);
! extern void version_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend);
  
  extern POOL_STATUS send_simplequery_message(POOL_CONNECTION *backend, int len, char *string, int major);
  extern POOL_STATUS send_extended_protocol_message(POOL_CONNECTION_POOL *backend,
_______________________________________________
Pgpool-hackers mailing list
Pgpool-hackers@pgfoundry.org
http://pgfoundry.org/mailman/listinfo/pgpool-hackers

Reply via email to