[pgpool-hackers: 1205] changing the pcp_watchdog_info

Muhammad Usama m.usama at gmail.com
Fri Dec 11 00:29:50 JST 2015


Hi Ishii San

pcp_watchdog_info only gives the information of a single watchdog
node which might not be enough in some certain situations. And as we are
currently working on watchdog enhancements so I thought it would be good to
also enhance the pcp_watchdog_info utility. I have created a patch to add
a little more information about the watchdog cluster state and nodes in the
output of pcp_watchdog_info.

Can you please have a look at the attached patch specially for

1-) If you are good with all the new information shown by pcp_watchdog_info
utility or you want to add/remove something?

2-) inform watchdog info in pcp_worker violates the data serialization
technique used by PCP server for other functions and adopts the JSON data
formatted load to transmit the watchdog information to the client side.
Although I am of the point of view that someday we should shift all the
other functions to use JSON or some other serialization technique which is
more adaptable and then the current proprietary format. But for the time
being the watchdog informing part of PCP is different from all other.

with the new pcp_watchdog_info when node ID is given the utility shows the
information of that specific node while ID =0 means the local watchdog
node. And when no node ID is provided by user information of all nodes is
shown

--example--

[usama at localhost pgpool]$ bin/pcp_watchdog_info -h localhost -p 9893 -U
postgres -v
Password:
Watchdog Cluster Information
Total Nodes         : 3
Remote Nodes        : 2
Alive Remote Nodes  : 2
In Network Error    : NO
Local Node Escalated: NO
Master Node Name    : Linux_localhost.localdomain_9992

Watchdog Node Information
Node Number    : 0
Node Name      : Linux_localhost.localdomain_9993
Host Name      : localhost
Pgpool port    : 9993
Watchdog port  : 9003
Node priority  : 1
status         : 7
status Name    : STANDBY

Node Number    : 1
Node Name      : Linux_localhost.localdomain_9992
Host Name      : localhost
Pgpool port    : 9992
Watchdog port  : 9002
Node priority  : 1
status         : 4
status Name    : COORDINATOR

Node Number    : 2
Node Name      : Linux_localhost.localdomain_9991
Host Name      : localhost
Pgpool port    : 9991
Watchdog port  : 9001
Node priority  : 1
status         : 7
status Name    : STANDBY



Thanks
Best regards
Muhammad Usama
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.sraoss.jp/pipermail/pgpool-hackers/attachments/20151210/5e0463b4/attachment-0001.html>
-------------- next part --------------
diff --git a/src/include/pcp/pcp.h b/src/include/pcp/pcp.h
index e00a7e8..03108d3 100644
--- a/src/include/pcp/pcp.h
+++ b/src/include/pcp/pcp.h
@@ -34,6 +34,7 @@ typedef struct PCPWDNodeInfo
 	int state;
 	char nodeName[WD_MAX_HOST_NAMELEN];
 	char hostName[WD_MAX_HOST_NAMELEN];		/* host name */
+	char stateName[WD_MAX_HOST_NAMELEN];	/* state name */
 	int wd_port;							/* watchdog port */
 	int wd_priority;						/* node priority in leader election */
 	int pgpool_port;						/* pgpool port */
@@ -41,6 +42,18 @@ typedef struct PCPWDNodeInfo
 	int	id;
 }PCPWDNodeInfo;
 
+typedef struct PCPWDClusterInfo
+{
+	int remoteNodeCount;
+	int quorumStatus;
+	int aliveNodeCount;
+	bool escalated;
+	bool inNetworkError;
+	char masterNodeName[WD_MAX_HOST_NAMELEN];
+	int nodeCount;
+	PCPWDNodeInfo nodeList[1];
+}PCPWDClusterInfo;
+
 /* --------------------------------
  * pcp.c
  * --------------------------------
diff --git a/src/include/watchdog/wd_json_data.h b/src/include/watchdog/wd_json_data.h
index 53ff9d6..842851a 100644
--- a/src/include/watchdog/wd_json_data.h
+++ b/src/include/watchdog/wd_json_data.h
@@ -33,8 +33,10 @@ typedef struct WDNodeInfo
 	int state;
 	char nodeName[WD_MAX_HOST_NAMELEN];
 	char hostName[WD_MAX_HOST_NAMELEN];		/* host name */
+	char stateName[WD_MAX_HOST_NAMELEN];	/* watchdog state name */
 	int wd_port;							/* watchdog port */
 	int pgpool_port;						/* pgpool port */
+	int wd_priority;						/* node priority */
 	char delegate_ip[WD_MAX_HOST_NAMELEN];	/* delegate IP */
 	int	id;
 }WDNodeInfo;
diff --git a/src/libs/pcp/Makefile.am b/src/libs/pcp/Makefile.am
index e4be930..a85b498 100644
--- a/src/libs/pcp/Makefile.am
+++ b/src/libs/pcp/Makefile.am
@@ -5,7 +5,10 @@ libpcp_la_LDFLAGS = -version-info 1:0:0
 libpcp_la_SOURCES = pcp.c \
 					pcp_stream.c \
                     md5.c \
+					json.c \
 					../../utils/pool_path.c \
+					../../tools/fe_port.c \
+					../../tools/fe_memutils.c \
                     ../../utils/strlcpy.c
 
 include_HEADERS = ../../../src/include/pcp/pcp.h \
@@ -21,3 +24,5 @@ pcp_stream.c: ../../../src/utils/pcp/pcp_stream.c
 	rm -f $@ && ln -s $< .
 strlcpy.c: ../../../src/utils/strlcpy.c
 	rm -f $@ && ln -s $< .
+json.c: ../../../src/utils/json.c
+	rm -f $@ && ln -s $< .
diff --git a/src/libs/pcp/Makefile.in b/src/libs/pcp/Makefile.in
index 2c2abd2..3e41a80 100644
--- a/src/libs/pcp/Makefile.in
+++ b/src/libs/pcp/Makefile.in
@@ -128,8 +128,9 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
 LTLIBRARIES = $(lib_LTLIBRARIES)
 libpcp_la_LIBADD =
 am__dirstamp = $(am__leading_dot)dirstamp
-am_libpcp_la_OBJECTS = pcp.lo pcp_stream.lo md5.lo \
-	../../utils/pool_path.lo ../../utils/strlcpy.lo
+am_libpcp_la_OBJECTS = pcp.lo pcp_stream.lo md5.lo json.lo \
+	../../utils/pool_path.lo ../../tools/fe_port.lo \
+	../../tools/fe_memutils.lo ../../utils/strlcpy.lo
 libpcp_la_OBJECTS = $(am_libpcp_la_OBJECTS)
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
@@ -333,7 +334,10 @@ libpcp_la_LDFLAGS = -version-info 1:0:0
 libpcp_la_SOURCES = pcp.c \
 					pcp_stream.c \
                     md5.c \
+					json.c \
 					../../utils/pool_path.c \
+					../../tools/fe_port.c \
+					../../tools/fe_memutils.c \
                     ../../utils/strlcpy.c
 
 include_HEADERS = ../../../src/include/pcp/pcp.h \
@@ -418,6 +422,16 @@ clean-libLTLIBRARIES:
 	@: > ../../utils/$(DEPDIR)/$(am__dirstamp)
 ../../utils/pool_path.lo: ../../utils/$(am__dirstamp) \
 	../../utils/$(DEPDIR)/$(am__dirstamp)
+../../tools/$(am__dirstamp):
+	@$(MKDIR_P) ../../tools
+	@: > ../../tools/$(am__dirstamp)
+../../tools/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) ../../tools/$(DEPDIR)
+	@: > ../../tools/$(DEPDIR)/$(am__dirstamp)
+../../tools/fe_port.lo: ../../tools/$(am__dirstamp) \
+	../../tools/$(DEPDIR)/$(am__dirstamp)
+../../tools/fe_memutils.lo: ../../tools/$(am__dirstamp) \
+	../../tools/$(DEPDIR)/$(am__dirstamp)
 ../../utils/strlcpy.lo: ../../utils/$(am__dirstamp) \
 	../../utils/$(DEPDIR)/$(am__dirstamp)
 
@@ -426,14 +440,19 @@ libpcp.la: $(libpcp_la_OBJECTS) $(libpcp_la_DEPENDENCIES) $(EXTRA_libpcp_la_DEPE
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
+	-rm -f ../../tools/*.$(OBJEXT)
+	-rm -f ../../tools/*.lo
 	-rm -f ../../utils/*.$(OBJEXT)
 	-rm -f ../../utils/*.lo
 
 distclean-compile:
 	-rm -f *.tab.c
 
+ at AMDEP_TRUE@@am__include@ @am__quote at ../../tools/$(DEPDIR)/fe_memutils.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ../../tools/$(DEPDIR)/fe_port.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ../../utils/$(DEPDIR)/pool_path.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ../../utils/$(DEPDIR)/strlcpy.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/json.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/md5.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/pcp.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/pcp_stream.Plo at am__quote@
@@ -467,6 +486,7 @@ mostlyclean-libtool:
 
 clean-libtool:
 	-rm -rf .libs _libs
+	-rm -rf ../../tools/.libs ../../tools/_libs
 	-rm -rf ../../utils/.libs ../../utils/_libs
 install-includeHEADERS: $(include_HEADERS)
 	@$(NORMAL_INSTALL)
@@ -605,6 +625,8 @@ clean-generic:
 distclean-generic:
 	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
 	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+	-rm -f ../../tools/$(DEPDIR)/$(am__dirstamp)
+	-rm -f ../../tools/$(am__dirstamp)
 	-rm -f ../../utils/$(DEPDIR)/$(am__dirstamp)
 	-rm -f ../../utils/$(am__dirstamp)
 
@@ -617,7 +639,7 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
 	mostlyclean-am
 
 distclean: distclean-am
-	-rm -rf ../../utils/$(DEPDIR) ./$(DEPDIR)
+	-rm -rf ../../tools/$(DEPDIR) ../../utils/$(DEPDIR) ./$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-tags
@@ -663,7 +685,7 @@ install-ps-am:
 installcheck-am:
 
 maintainer-clean: maintainer-clean-am
-	-rm -rf ../../utils/$(DEPDIR) ./$(DEPDIR)
+	-rm -rf ../../tools/$(DEPDIR) ../../utils/$(DEPDIR) ./$(DEPDIR)
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
@@ -709,6 +731,8 @@ pcp_stream.c: ../../../src/utils/pcp/pcp_stream.c
 	rm -f $@ && ln -s $< .
 strlcpy.c: ../../../src/utils/strlcpy.c
 	rm -f $@ && ln -s $< .
+json.c: ../../../src/utils/json.c
+	rm -f $@ && ln -s $< .
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/src/libs/pcp/pcp.c b/src/libs/pcp/pcp.c
index 7834c55..5a70364 100644
--- a/src/libs/pcp/pcp.c
+++ b/src/libs/pcp/pcp.c
@@ -44,6 +44,7 @@
 #include "utils/pool_path.h"
 #include "utils/palloc.h"
 #include "utils/pool_process_reporting.h"
+#include "utils/json.h"
 #include "auth/md5.h"
 
 #define PCPPASSFILE ".pcppass"
@@ -1279,6 +1280,202 @@ _pcp_promote_node(PCPConnInfo* pcpConn,int nid, bool gracefully)
 static void
 process_watchdog_info_response(PCPConnInfo* pcpConn, char* buf, int len)
 {
+	char *json_data = NULL;
+	PCPWDClusterInfo* wd_cluster_info = NULL;
+	int clusterDataSize = 0;
+	if (strcmp(buf, "CommandComplete") == 0)
+	{
+		int tempVal;
+		json_data = (char *) memchr(buf, '\0', len);
+		if(json_data == NULL)
+			goto INVALID_RESPONSE;
+		json_data +=1;
+		
+		json_value* root;
+		json_value* value;
+		int i,nodeCount;
+
+		root = json_parse(json_data,len);
+
+		/* The root node must be object */
+		if (root == NULL || root->type != json_object)
+		{
+			json_value_free(root);
+			goto INVALID_RESPONSE;
+		}
+
+		if (json_get_int_value_for_key(root, "NodeCount", &nodeCount))
+		{
+			json_value_free(root);
+			goto INVALID_RESPONSE;
+		}
+
+		/* find the WatchdogNodes array */
+		value = json_get_value_for_key(root,"WatchdogNodes");
+		if (value == NULL)
+		{
+			json_value_free(root);
+			goto INVALID_RESPONSE;
+		}
+		if (value->type != json_array)
+		{
+			json_value_free(root);
+			goto INVALID_RESPONSE;
+		}
+		if (nodeCount != value->u.array.length)
+		{
+			json_value_free(root);
+			goto INVALID_RESPONSE;
+		}
+
+		/* create the cluster object */
+		clusterDataSize = sizeof(PCPWDClusterInfo) + (sizeof(PCPWDNodeInfo) * nodeCount);
+		wd_cluster_info = malloc(clusterDataSize);
+
+		wd_cluster_info->nodeCount = nodeCount;
+
+		if (json_get_int_value_for_key(root, "RemoteNodeCount", &wd_cluster_info->remoteNodeCount))
+		{
+			json_value_free(root);
+			goto INVALID_RESPONSE;
+		}
+		if (json_get_int_value_for_key(root, "QuorumStatus", &wd_cluster_info->quorumStatus))
+		{
+			json_value_free(root);
+			goto INVALID_RESPONSE;
+		}
+		if (json_get_int_value_for_key(root, "AliveNodeCount", &wd_cluster_info->aliveNodeCount))
+		{
+			json_value_free(root);
+			goto INVALID_RESPONSE;
+		}
+		if (json_get_int_value_for_key(root, "Escalated", &tempVal))
+		{
+			json_value_free(root);
+			goto INVALID_RESPONSE;
+		}
+		wd_cluster_info->escalated = tempVal==0?false:true;
+		if (json_get_int_value_for_key(root, "NetworkError", &tempVal))
+		{
+			json_value_free(root);
+			goto INVALID_RESPONSE;
+		}
+		wd_cluster_info->inNetworkError = tempVal==0?false:true;;
+		char* ptr = json_get_string_value_for_key(root, "MasterNodeName");
+		if (ptr == NULL)
+		{
+			json_value_free(root);
+			goto INVALID_RESPONSE;
+		}
+		strncpy(wd_cluster_info->masterNodeName, ptr, sizeof(wd_cluster_info->masterNodeName) -1);
+
+		/* Get watchdog nodes data */
+		for (i = 0; i < nodeCount; i++)
+		{
+			char* ptr;
+			json_value* nodeInfoValue = value->u.array.values[i];
+			PCPWDNodeInfo* wdNodeInfo = &wd_cluster_info->nodeList[i];
+
+			if (nodeInfoValue->type != json_object)
+			{
+				json_value_free(root);
+				goto INVALID_RESPONSE;
+			}
+			
+			if (json_get_int_value_for_key(nodeInfoValue, "ID", &wdNodeInfo->id))
+			{
+				json_value_free(root);
+				goto INVALID_RESPONSE;
+			}
+			
+			ptr = json_get_string_value_for_key(nodeInfoValue, "NodeName");
+			if (ptr == NULL)
+			{
+				json_value_free(root);
+				goto INVALID_RESPONSE;
+			}
+			strncpy(wdNodeInfo->nodeName, ptr, sizeof(wdNodeInfo->nodeName) -1);
+			
+			ptr = json_get_string_value_for_key(nodeInfoValue, "HostName");
+			if (ptr == NULL)
+			{
+				json_value_free(root);
+				goto INVALID_RESPONSE;
+			}
+			strncpy(wdNodeInfo->hostName, ptr, sizeof(wdNodeInfo->hostName) -1);
+			
+			ptr = json_get_string_value_for_key(nodeInfoValue, "DelegateIP");
+			if (ptr == NULL)
+			{
+				json_value_free(root);
+				goto INVALID_RESPONSE;
+			}
+			strncpy(wdNodeInfo->delegate_ip, ptr, sizeof(wdNodeInfo->delegate_ip) -1);
+			
+			if (json_get_int_value_for_key(nodeInfoValue, "WdPort", &wdNodeInfo->wd_port))
+			{
+				json_value_free(root);
+				goto INVALID_RESPONSE;
+			}
+			
+			if (json_get_int_value_for_key(nodeInfoValue, "PgpoolPort", &wdNodeInfo->pgpool_port))
+			{
+				json_value_free(root);
+				goto INVALID_RESPONSE;
+			}
+			
+			if (json_get_int_value_for_key(nodeInfoValue, "State", &wdNodeInfo->state))
+			{
+				json_value_free(root);
+				goto INVALID_RESPONSE;
+			}
+			
+			ptr = json_get_string_value_for_key(nodeInfoValue, "StateName");
+			if (ptr == NULL)
+			{
+				json_value_free(root);
+				goto INVALID_RESPONSE;
+			}
+			strncpy(wdNodeInfo->stateName, ptr, sizeof(wdNodeInfo->stateName) -1);
+			
+			if (json_get_int_value_for_key(nodeInfoValue, "Priority", &wdNodeInfo->wd_priority))
+			{
+				json_value_free(root);
+				goto INVALID_RESPONSE;
+			}
+
+		}
+		json_value_free(root);
+
+		if (setNextResultBinaryData(pcpConn->pcpResInfo, (void *)wd_cluster_info,clusterDataSize , NULL) < 0)
+			goto INVALID_RESPONSE;
+		
+		setCommandSuccessful(pcpConn);
+	}
+	else
+	{
+		pcp_internal_error(pcpConn,
+						   "command failed with reason: \"%s\"\n",buf);
+		setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE);
+	}
+	
+	return;
+	
+INVALID_RESPONSE:
+	
+	if(wd_cluster_info)
+		pfree(wd_cluster_info);
+	pcp_internal_error(pcpConn,
+					   "command failed. invalid response\n");
+	setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE);
+	
+}
+
+/*
+
+static void
+process_watchdog_info_response(PCPConnInfo* pcpConn, char* buf, int len)
+{
 	PCPWDNodeInfo* watchdog_info = NULL;
 	if (strcmp(buf, "CommandComplete") == 0)
 	{
@@ -1290,9 +1487,9 @@ process_watchdog_info_response(PCPConnInfo* pcpConn, char* buf, int len)
 		if(index == NULL)
 			goto INVALID_RESPONSE;
 		index +=1;
-		strlcpy(watchdog_info->hostName, index, sizeof(watchdog_info->hostName)-1);
+		strlcpy(watchdog_info->hostName, index, sizeof(watchdog_info->hostName) -1);
 
-		index = (char *) memchr(buf, '\0', len);
+		index = (char *) memchr(index, '\0', len);
 		if(index == NULL)
 			goto INVALID_RESPONSE;
 		index +=1;
@@ -1316,6 +1513,18 @@ process_watchdog_info_response(PCPConnInfo* pcpConn, char* buf, int len)
 		index +=1;
 		watchdog_info->state = atof(index);
 
+		index = (char *) memchr(index, '\0', len);
+		if(index == NULL)
+			goto INVALID_RESPONSE;
+		index +=1;
+		strlcpy(watchdog_info->stateName, index, sizeof(watchdog_info->stateName) -1);
+
+		index = (char *) memchr(index, '\0', len);
+		if(index == NULL)
+			goto INVALID_RESPONSE;
+		index +=1;
+		watchdog_info->wd_priority = atof(index);
+
 		if (setNextResultBinaryData(pcpConn->pcpResInfo, (void *)watchdog_info,sizeof(PCPWDNodeInfo) , NULL) < 0)
 			goto INVALID_RESPONSE;
 
@@ -1339,7 +1548,7 @@ INVALID_RESPONSE:
 	setResultStatus(pcpConn, PCP_RES_BAD_RESPONSE);
 
 }
-
+*/
 /* --------------------------------
  * pcp_watchdog_info - get information of watchdog
  *
diff --git a/src/pcp_con/pcp_worker.c b/src/pcp_con/pcp_worker.c
index 805591b..791cf81 100644
--- a/src/pcp_con/pcp_worker.c
+++ b/src/pcp_con/pcp_worker.c
@@ -757,16 +757,18 @@ static void
 inform_watchdog_info(PCP_CONNECTION *frontend,char *buf)
 {
 	int wd_index;
+	int json_data_len;
 	int wsize;
 	char code[] = "CommandComplete";
 	char pgpool_port_str[6];
 	char wd_port_str[6];
+	char wd_priority_str[6];
 	char status[2];
 	json_value* root;
 	json_value* value;
 	char* json_data;
 	WDNodeInfo *nodeInfo;
-	
+
 	if (!pool_config->use_watchdog)
 		ereport(ERROR,
 			(errmsg("PCP: informing watchdog info failed"),
@@ -777,57 +779,31 @@ inform_watchdog_info(PCP_CONNECTION *frontend,char *buf)
 	json_data = wd_get_watchdog_nodes(wd_index);
 	if (json_data == NULL)
 		ereport(ERROR,
-				(errmsg("PCP: informing watchdog info failed"),
+			(errmsg("PCP: informing watchdog info failed"),
 				 errdetail("invalid watchdog index")));
 
 	ereport(DEBUG2,
-			(errmsg("PCP: informing watchdog info"),
-			 errdetail("retrieved node information from shared memory")));
-
-	root = json_parse(json_data,strlen(json_data));
-	
-	/* The root node must be object */
-	if (root == NULL || root->type != json_object)
-	{
-		if(root)
-			json_value_free(root);
-		ereport(ERROR,
-			(errmsg("unable to parse json data for watchdog node info")));
-	}
+		(errmsg("PCP: informing watchdog info"),
+			 errdetail("retrieved node information from IPC socket")));
 
-	value = json_get_value_for_key(root,"WatchdogNode");
-	if (value == NULL || root->type != json_object)
-	{
-		json_value_free(root);
-		ereport(ERROR,
-				(errmsg("unable to parse json data for watchdog node info")));
-	}
-
-	nodeInfo = get_WDNodeInfo_from_wd_node_json(value);
-	json_value_free(root);
-
-	snprintf(pgpool_port_str, sizeof(pgpool_port_str), "%d", nodeInfo->pgpool_port);
-	snprintf(wd_port_str, sizeof(wd_port_str), "%d", nodeInfo->wd_port);
-	snprintf(status, sizeof(status), "%d", nodeInfo->state);
-
-	pcp_write(frontend, "w", 1);
+	/*
+	 * This is the voilation of PCP protocol but I think
+	 * in future we should shift to more adaptable protocol for
+	 * data transmition.
+	 */
+	json_data_len = strlen(json_data);
 	wsize = htonl(sizeof(code) +
-				  strlen(nodeInfo->hostName)+1 +
-				  strlen(nodeInfo->nodeName)+1 +
-				  strlen(pgpool_port_str)+1 +
-				  strlen(wd_port_str)+1 +
-				  strlen(status)+1 +
+				  json_data_len+ 1 +
 				  sizeof(int));
+	pcp_write(frontend, "w", 1);
+
 	pcp_write(frontend, &wsize, sizeof(int));
 	pcp_write(frontend, code, sizeof(code));
 
-	pcp_write(frontend, nodeInfo->hostName, strlen(nodeInfo->hostName)+1);
-	pcp_write(frontend, nodeInfo->nodeName, strlen(nodeInfo->nodeName)+1);
-	pcp_write(frontend, pgpool_port_str, strlen(pgpool_port_str)+1);
-	pcp_write(frontend, wd_port_str, strlen(wd_port_str)+1);
-	pcp_write(frontend, status, strlen(status)+1);
+	pcp_write(frontend, json_data, json_data_len +1);
 	do_pcp_flush(frontend);
-	pfree(nodeInfo);
+
+	pfree(json_data);
 }
 
 static void
diff --git a/src/tools/pcp/pcp_frontend_client.c b/src/tools/pcp/pcp_frontend_client.c
index 018c80b..f18450f 100644
--- a/src/tools/pcp/pcp_frontend_client.c
+++ b/src/tools/pcp/pcp_frontend_client.c
@@ -317,7 +317,7 @@ main(int argc, char **argv)
 		}
 		else if (current_app_type->app_type == PCP_WATCHDOG_INFO)
 		{
-			nodeID = 0;
+			nodeID = -1;
 		}
 	}
 
@@ -611,23 +611,50 @@ output_procinfo_result(PCPResultInfo* pcpResInfo, bool all, bool verbose)
 static void
 output_watchdog_info_result(PCPResultInfo* pcpResInfo, bool verbose)
 {
-	PCPWDNodeInfo *watchdog_info = (PCPWDNodeInfo *)pcp_get_binary_data(pcpResInfo,0);
+	int i;
+	PCPWDClusterInfo *cluster = (PCPWDClusterInfo *)pcp_get_binary_data(pcpResInfo,0);
 	if (verbose)
 	{
-		printf("NodeName     : %s\n",watchdog_info->nodeName);
-		printf("HostName     : %s\n",watchdog_info->hostName);
-		printf("Pgpool port  : %d\n",watchdog_info->pgpool_port);
-		printf("Watchdog port: %d\n",watchdog_info->wd_port);
-		printf("Node priority: %d\n",watchdog_info->wd_priority);
-		printf("status       : %d\n\n",watchdog_info->state);
+		printf("Watchdog Cluster Information \n");
+		printf("Total Nodes         : %d\n",cluster->remoteNodeCount +1);
+		printf("Remote Nodes        : %d\n",cluster->remoteNodeCount);
+		printf("Alive Remote Nodes  : %d\n",cluster->aliveNodeCount);
+		printf("In Network Error    : %s\n",cluster->inNetworkError?"YES":"NO");
+		printf("Local Node Escalated: %s\n",cluster->escalated?"YES":"NO");
+		printf("Master Node Name    : %s\n\n",cluster->masterNodeName);
+
+		printf("Watchdog Node Information \n");
+		for (i=0; i< cluster->nodeCount; i++)
+		{
+			PCPWDNodeInfo* watchdog_info = &cluster->nodeList[i];
+			printf("Node Number    : %d\n",i);
+			printf("Node Name      : %s\n",watchdog_info->nodeName);
+			printf("Host Name      : %s\n",watchdog_info->hostName);
+			printf("Pgpool port    : %d\n",watchdog_info->pgpool_port);
+			printf("Watchdog port  : %d\n",watchdog_info->wd_port);
+			printf("Node priority  : %d\n",watchdog_info->wd_priority);
+			printf("status         : %d\n",watchdog_info->state);
+			printf("status Name    : %s\n\n",watchdog_info->stateName);
+		}
 	}
 	else
 	{
-		printf("%s %d %d %d\n",
-			   watchdog_info->hostName,
-			   watchdog_info->pgpool_port,
-			   watchdog_info->wd_port,
-			   watchdog_info->state);
+		printf("%d %s %s %s \n\n",
+			   cluster->remoteNodeCount +1,
+			   cluster->inNetworkError?"YES":"NO",
+			   cluster->escalated?"YES":"NO",
+			   cluster->masterNodeName);
+
+		for (i=0; i< cluster->nodeCount; i++)
+		{
+			PCPWDNodeInfo* watchdog_info = &cluster->nodeList[i];
+			printf("[%d] %s %d %d %d %s\n",i,
+				   watchdog_info->hostName,
+				   watchdog_info->pgpool_port,
+				   watchdog_info->wd_port,
+				   watchdog_info->state,
+				   watchdog_info->stateName);
+		}
 	}
 }
 
@@ -683,7 +710,8 @@ usage(void)
 	if (current_app_type->app_type == PCP_WATCHDOG_INFO)
 	{
 		fprintf(stderr, "  -n, --watchdog-id=ID   ID of a other pgpool to get information for\n");
-		fprintf(stderr, "                         If omitted then get one's self information\n");
+		fprintf(stderr, "                         ID 0 for the local watchdog\n");
+		fprintf(stderr, "                         If omitted then get information of all watchdog nodes\n");
 	}
 	if (current_app_type->app_type == PCP_PROC_INFO)
 	{
diff --git a/src/utils/json.c b/src/utils/json.c
index 56b024f..79587e8 100644
--- a/src/utils/json.c
+++ b/src/utils/json.c
@@ -59,15 +59,20 @@
 
 const struct _json_value json_value_none;
 #include "pool.h"
-#include "utils/palloc.h"
-#include "utils/memutils.h"
-#include "utils/elog.h"
 
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <math.h>
 
+#ifndef POOL_PRIVATE
+#include "utils/palloc.h"
+#include "utils/memutils.h"
+#include "utils/elog.h"
+#else
+#include "utils/fe_ports.h"
+#endif
+
 typedef unsigned int json_uchar;
 
 static unsigned char hex_value (json_char c)
diff --git a/src/utils/pcp/pcp_stream.c b/src/utils/pcp/pcp_stream.c
index 5d95964..29dca97 100644
--- a/src/utils/pcp/pcp_stream.c
+++ b/src/utils/pcp/pcp_stream.c
@@ -4,7 +4,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL 
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2014	PgPool Global Development Group
+ * Copyright (c) 2003-2015	PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
diff --git a/src/watchdog/watchdog.c b/src/watchdog/watchdog.c
index 95f4632..bd0ef0f 100644
--- a/src/watchdog/watchdog.c
+++ b/src/watchdog/watchdog.c
@@ -1472,7 +1472,7 @@ static IPC_CMD_PREOCESS_RES process_IPC_nodeList_command(WDIPCCommandData* IPCCo
 				(errmsg("unable to parse json data from get node list command")));
 		return IPC_CMD_ERROR;
 	}
-	/* If it is a node function ?*/
+
 	if (json_get_int_value_for_key(root, "NodeID", &NodeID))
 	{
 		json_value_free(root);
@@ -2403,10 +2403,12 @@ static bool add_nodeinfo_to_json(JsonNode* jNode, WatchdogNode* node)
 	jw_put_int(jNode, "State",node?node->state:-1);
 	jw_put_string(jNode, "NodeName",node?node->nodeName:"Not Set");
 	jw_put_string(jNode, "HostName", node?node->hostname:"Not Set");
+	jw_put_string(jNode, "StateName", node?wd_state_names[node->state]:"Not Set");
 	jw_put_string(jNode, "DelegateIP",node?node->delegate_ip:"Not Set");
 	jw_put_int(jNode, "WdPort", node?node->wd_port:0);
 	jw_put_int(jNode, "PgpoolPort", node?node->pgpool_port:0);
-	
+	jw_put_int(jNode, "Priority", node?node->wd_priority:0);
+
 	jw_end_element(jNode);
 	
 	return true;
@@ -2416,15 +2418,22 @@ static JsonNode* get_node_list_json(int id)
 {
 	int i;
 	JsonNode* jNode = jw_create_with_object(true);
-	/* add the node count */
+	update_connected_node_count();
+	jw_put_int(jNode, "RemoteNodeCount", g_cluster.remoteNodeCount);
+	jw_put_int(jNode, "QuorumStatus", g_cluster.quorum_status);
+	jw_put_int(jNode, "AliveNodeCount", g_cluster.aliveNodeCount);
+	jw_put_int(jNode, "Escalated", g_cluster.escalated?1:0);
+	jw_put_int(jNode, "NetworkError", g_cluster.network_error?1:0);
+	jw_put_string(jNode, "MasterNodeName",g_cluster.masterNode?g_cluster.masterNode->nodeName:"Not Set");
 	if (id < 0)
 	{
 		jw_put_int(jNode, "NodeCount", g_cluster.remoteNodeCount + 1);
+
 		/* add the array */
 		jw_start_array(jNode, "WatchdogNodes");
 		/* add the local node info */
 		add_nodeinfo_to_json(jNode,g_cluster.localNode);
-		/* add remote nodes */
+		/* add all remote nodes */
 		for (i=0; i< g_cluster.remoteNodeCount; i++)
 		{
 			WatchdogNode* wdNode = &(g_cluster.remoteNodes[i]);
@@ -2434,6 +2443,9 @@ static JsonNode* get_node_list_json(int id)
 	else
 	{
 		jw_put_int(jNode, "NodeCount", 1);
+		/* add the array */
+		jw_start_array(jNode, "WatchdogNodes");
+
 		if (id == 0)
 		{
 			/* add the local node info */
diff --git a/src/watchdog/wd_json_data.c b/src/watchdog/wd_json_data.c
index 91bff37..f9537ae 100644
--- a/src/watchdog/wd_json_data.c
+++ b/src/watchdog/wd_json_data.c
@@ -363,13 +363,13 @@ WDNodeInfo* get_WDNodeInfo_from_wd_node_json(json_value* source)
 	WDNodeInfo* wdNodeInfo = palloc0(sizeof(WDNodeInfo));
 	if (source->type != json_object)
 		ereport(ERROR,
-				(errmsg("invalid json data"),
+			(errmsg("invalid json data"),
 				 errdetail("node is not of object type")));
 	
 	if (json_get_int_value_for_key(source, "ID", &wdNodeInfo->id))
 	{
 		ereport(ERROR,
-				(errmsg("invalid json data"),
+			(errmsg("invalid json data"),
 				 errdetail("unable to find Watchdog Node ID")));
 	}
 	
@@ -377,7 +377,7 @@ WDNodeInfo* get_WDNodeInfo_from_wd_node_json(json_value* source)
 	if (ptr == NULL)
 	{
 		ereport(ERROR,
-				(errmsg("invalid json data"),
+			(errmsg("invalid json data"),
 				 errdetail("unable to find Watchdog Node Name")));
 	}
 	strncpy(wdNodeInfo->nodeName, ptr, sizeof(wdNodeInfo->nodeName) -1);
@@ -386,7 +386,7 @@ WDNodeInfo* get_WDNodeInfo_from_wd_node_json(json_value* source)
 	if (ptr == NULL)
 	{
 		ereport(ERROR,
-				(errmsg("invalid json data"),
+			(errmsg("invalid json data"),
 				 errdetail("unable to find Watchdog Host Name")));
 	}
 	strncpy(wdNodeInfo->hostName, ptr, sizeof(wdNodeInfo->hostName) -1);
@@ -395,12 +395,12 @@ WDNodeInfo* get_WDNodeInfo_from_wd_node_json(json_value* source)
 	if (ptr == NULL)
 	{
 		ereport(ERROR,
-				(errmsg("invalid json data"),
+			(errmsg("invalid json data"),
 				 errdetail("unable to find Watchdog delegate IP")));
 	}
 	strncpy(wdNodeInfo->delegate_ip, ptr, sizeof(wdNodeInfo->delegate_ip) -1);
 	
-	if (json_get_int_value_for_key(source, "PgpoolPort", &wdNodeInfo->wd_port))
+	if (json_get_int_value_for_key(source, "WdPort", &wdNodeInfo->wd_port))
 	{
 		ereport(ERROR,
 				(errmsg("invalid json data"),
@@ -413,13 +413,29 @@ WDNodeInfo* get_WDNodeInfo_from_wd_node_json(json_value* source)
 				(errmsg("invalid json data"),
 				 errdetail("unable to find PgpoolPort")));
 	}
-	
+
 	if (json_get_int_value_for_key(source, "State", &wdNodeInfo->state))
 	{
 		ereport(ERROR,
 				(errmsg("invalid json data"),
 				 errdetail("unable to find state")));
 	}
+
+	ptr = json_get_string_value_for_key(source, "StateName");
+	if (ptr == NULL)
+	{
+		ereport(ERROR,
+			(errmsg("invalid json data"),
+				 errdetail("unable to find Watchdog State Name")));
+	}
+	strncpy(wdNodeInfo->stateName, ptr, sizeof(wdNodeInfo->stateName) -1);
+
+	if (json_get_int_value_for_key(source, "Priority", &wdNodeInfo->wd_priority))
+	{
+		ereport(ERROR,
+				(errmsg("invalid json data"),
+				 errdetail("unable to find state")));
+	}
 	
 	return wdNodeInfo;
 	


More information about the pgpool-hackers mailing list