Add pcp_watchdog_info command
authorYugo Nagata <nagata@sraoss.co.jp>
Tue, 16 Jul 2013 09:28:51 +0000 (18:28 +0900)
committerYugo Nagata <nagata@sraoss.co.jp>
Tue, 16 Jul 2013 09:30:56 +0000 (18:30 +0900)
pcp_watchdog_info displays pgpool-II watchdog's information.

Usage: pcp_watchdog_info [-d] timeout hostname port# username password [watchdogID]
  -d, --debug    : enable debug message (optional)
  timeout        : connection timeout value in seconds. command exits on timeout
  hostname       : pgpool-II hostname
  port#          : PCP port number
  username       : username for PCP authentication
  password       : password for PCP authentication
  watchdogID     : ID of a other pgpool to get information for
                   If omitted then get one's self information

pcp/Makefile.am
pcp/Makefile.in
pcp/libpcp_ext.h
pcp/pcp.c
pcp/pcp.h
pcp/pcp_watchdog_info.c [new file with mode: 0644]
pcp_child.c
watchdog/watchdog.h
watchdog/wd_ext.h
watchdog/wd_list.c

index 3f045c17a41589b17e58fd7d663bc88d19849762..cf22320b3a87cf18c555d2683d37e184660f59d4 100644 (file)
@@ -11,7 +11,8 @@ md5.h: ../md5.h
        rm -f $@ && ln -s $< .
 
 bin_PROGRAMS =  pcp_stop_pgpool pcp_node_count pcp_node_info pcp_proc_count pcp_proc_info \
-               pcp_systemdb_info pcp_detach_node pcp_attach_node pcp_recovery_node pcp_promote_node pcp_pool_status
+               pcp_systemdb_info pcp_detach_node pcp_attach_node pcp_recovery_node pcp_promote_node \
+               pcp_pool_status pcp_watchdog_info
 pcp_stop_pgpool_SOURCES = pcp_stop_pgpool.c pcp.h ../getopt_long.c ../getopt_long.h
 pcp_stop_pgpool_LDADD = libpcp.la
 pcp_stop_pgpool_LDFLAGS =
@@ -35,3 +36,5 @@ pcp_pool_status_SOURCES = pcp_pool_status.c pcp.h ../getopt_long.c ../getopt_lon
 pcp_pool_status_LDADD = libpcp.la
 pcp_promote_node_SOURCES = pcp_promote_node.c pcp.h ../getopt_long.c ../getopt_long.h
 pcp_promote_node_LDADD = libpcp.la
+pcp_watchdog_info_SOURCES = pcp_watchdog_info.c pcp.h ../getopt_long.c ../getopt_long.h
+pcp_watchdog_info_LDADD = libpcp.la
index ba97d6db0f70aaacc9c651e5c0d4d3856000a5d3..930b7abe05ee755c2ce1ae222bd7bf364e010e1a 100644 (file)
@@ -41,7 +41,7 @@ bin_PROGRAMS = pcp_stop_pgpool$(EXEEXT) pcp_node_count$(EXEEXT) \
        pcp_proc_info$(EXEEXT) pcp_systemdb_info$(EXEEXT) \
        pcp_detach_node$(EXEEXT) pcp_attach_node$(EXEEXT) \
        pcp_recovery_node$(EXEEXT) pcp_promote_node$(EXEEXT) \
-       pcp_pool_status$(EXEEXT)
+       pcp_pool_status$(EXEEXT) pcp_watchdog_info$(EXEEXT)
 subdir = pcp
 DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
        $(srcdir)/Makefile.in
@@ -134,6 +134,10 @@ am_pcp_systemdb_info_OBJECTS = pcp_systemdb_info.$(OBJEXT) \
        getopt_long.$(OBJEXT)
 pcp_systemdb_info_OBJECTS = $(am_pcp_systemdb_info_OBJECTS)
 pcp_systemdb_info_DEPENDENCIES = libpcp.la
+am_pcp_watchdog_info_OBJECTS = pcp_watchdog_info.$(OBJEXT) \
+       getopt_long.$(OBJEXT)
+pcp_watchdog_info_OBJECTS = $(am_pcp_watchdog_info_OBJECTS)
+pcp_watchdog_info_DEPENDENCIES = libpcp.la
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
@@ -152,13 +156,15 @@ SOURCES = $(libpcp_la_SOURCES) $(pcp_attach_node_SOURCES) \
        $(pcp_node_info_SOURCES) $(pcp_pool_status_SOURCES) \
        $(pcp_proc_count_SOURCES) $(pcp_proc_info_SOURCES) \
        $(pcp_promote_node_SOURCES) $(pcp_recovery_node_SOURCES) \
-       $(pcp_stop_pgpool_SOURCES) $(pcp_systemdb_info_SOURCES)
+       $(pcp_stop_pgpool_SOURCES) $(pcp_systemdb_info_SOURCES) \
+       $(pcp_watchdog_info_SOURCES)
 DIST_SOURCES = $(libpcp_la_SOURCES) $(pcp_attach_node_SOURCES) \
        $(pcp_detach_node_SOURCES) $(pcp_node_count_SOURCES) \
        $(pcp_node_info_SOURCES) $(pcp_pool_status_SOURCES) \
        $(pcp_proc_count_SOURCES) $(pcp_proc_info_SOURCES) \
        $(pcp_promote_node_SOURCES) $(pcp_recovery_node_SOURCES) \
-       $(pcp_stop_pgpool_SOURCES) $(pcp_systemdb_info_SOURCES)
+       $(pcp_stop_pgpool_SOURCES) $(pcp_systemdb_info_SOURCES) \
+       $(pcp_watchdog_info_SOURCES)
 HEADERS = $(include_HEADERS)
 ETAGS = etags
 CTAGS = ctags
@@ -314,6 +320,8 @@ pcp_pool_status_SOURCES = pcp_pool_status.c pcp.h ../getopt_long.c ../getopt_lon
 pcp_pool_status_LDADD = libpcp.la
 pcp_promote_node_SOURCES = pcp_promote_node.c pcp.h ../getopt_long.c ../getopt_long.h
 pcp_promote_node_LDADD = libpcp.la
+pcp_watchdog_info_SOURCES = pcp_watchdog_info.c pcp.h ../getopt_long.c ../getopt_long.h
+pcp_watchdog_info_LDADD = libpcp.la
 all: all-am
 
 .SUFFIXES:
@@ -457,6 +465,9 @@ pcp_stop_pgpool$(EXEEXT): $(pcp_stop_pgpool_OBJECTS) $(pcp_stop_pgpool_DEPENDENC
 pcp_systemdb_info$(EXEEXT): $(pcp_systemdb_info_OBJECTS) $(pcp_systemdb_info_DEPENDENCIES) 
        @rm -f pcp_systemdb_info$(EXEEXT)
        $(LINK) $(pcp_systemdb_info_OBJECTS) $(pcp_systemdb_info_LDADD) $(LIBS)
+pcp_watchdog_info$(EXEEXT): $(pcp_watchdog_info_OBJECTS) $(pcp_watchdog_info_DEPENDENCIES) 
+       @rm -f pcp_watchdog_info$(EXEEXT)
+       $(LINK) $(pcp_watchdog_info_OBJECTS) $(pcp_watchdog_info_LDADD) $(LIBS)
 
 mostlyclean-compile:
        -rm -f *.$(OBJEXT)
@@ -480,6 +491,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcp_stop_pgpool.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcp_stream.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcp_systemdb_info.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcp_watchdog_info.Po@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
index 4613f08e7a153ec0fb8926565cc533c1c520d244..09aa605d8406b686de54c74ca7a3ec9f1498f5a1 100644 (file)
@@ -155,7 +155,6 @@ typedef struct {
        QueryCacheTableInfo query_cache_table_info; /* query cache db session info */
        BACKEND_STATUS system_db_status;
 } SystemDBInfo;
-
 /*
  * reporting types
  */
@@ -218,6 +217,9 @@ typedef struct {
        char version[POOLCONFIG_MAXVALLEN+1];
 } POOL_REPORT_VERSION;
 
+struct WdInfo;
+//typedef struct WdInfo WdInfo;
+
 extern int pcp_connect(char *hostname, int port, char *username, char *password);
 extern void pcp_disconnect(void);
 extern int pcp_terminate_pgpool(char mode);
@@ -237,6 +239,7 @@ extern void pcp_enable_debug(void);
 extern void pcp_disable_debug(void);
 extern int pcp_promote_node(int nid);
 extern int pcp_promote_node_gracefully(int nid);
+extern struct WdInfo *pcp_watchdog_info(int nid);
 
 /* ------------------------------
  * pcp_error.c
index 997fddf0ddece73f2f0f7983704a9788249d1615..f923679e94547bb25cf5b5f37391b5edc6256400 100644 (file)
--- a/pcp/pcp.c
+++ b/pcp/pcp.c
@@ -1551,3 +1551,103 @@ static int _pcp_promote_node(int nid, bool gracefully)
        free(buf);
        return -1;
 }
+
+/* --------------------------------
+ * pcp_watchdog_info - get information of watchdog
+ *
+ * return structure of watchdog information on success, -1 otherwise
+ * --------------------------------
+ */
+WdInfo *
+pcp_watchdog_info(int nid)
+{
+       int wsize;
+       char wd_index[16];
+       char tos;
+       char *buf = NULL;
+       int rsize;
+
+       if (pc == NULL)
+       {
+               if (debug) fprintf(stderr, "DEBUG: connection does not exist\n");
+               errorcode = NOCONNERR;
+               return NULL;
+       }
+
+       snprintf(wd_index, sizeof(wd_index), "%d", nid);
+
+       pcp_write(pc, "W", 1);
+       wsize = htonl(strlen(wd_index)+1 + sizeof(int));
+       pcp_write(pc, &wsize, sizeof(int));
+       pcp_write(pc, wd_index, strlen(wd_index)+1);
+       if (pcp_flush(pc) < 0)
+       {
+               if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n");
+               return NULL;
+       }
+       if (debug) fprintf(stderr, "DEBUG: send: tos=\"W\", len=%d\n", ntohl(wsize));
+
+       if (pcp_read(pc, &tos, 1))
+               return NULL;    
+       if (pcp_read(pc, &rsize, sizeof(int)))
+               return NULL;    
+       rsize = ntohl(rsize);
+       buf = (char *)malloc(rsize);
+       if (buf == NULL)
+       {
+               errorcode = NOMEMERR;
+               return NULL;
+       }
+       if (pcp_read(pc, buf, rsize - sizeof(int)))
+       {
+               free(buf);
+               return NULL;
+       }
+
+       if (debug) fprintf(stderr, "DEBUG: recv: tos=\"%c\", len=%d, data=%s\n", tos, rsize, buf);
+
+       if (tos == 'e')
+       {
+               if (debug) fprintf(stderr, "DEBUG: command failed. reason=%s\n", buf);
+               errorcode = BACKENDERR;
+               free(buf);
+               return NULL;
+       }
+       else if (tos == 'w')
+       {
+               if (strcmp(buf, "CommandComplete") == 0)
+               {
+                       char *index = NULL;
+                       WdInfo* watchdog_info = NULL;
+
+                       watchdog_info = (WdInfo *)malloc(sizeof(WdInfo));
+                       if (watchdog_info == NULL)
+                       {
+                               errorcode = NOMEMERR;
+                               free(buf);
+                               return NULL;
+                       }
+
+                       index = (char *) memchr(buf, '\0', rsize) + 1;
+                       if (index != NULL)
+                               strcpy(watchdog_info->hostname, index);
+
+                       index = (char *) memchr(index, '\0', rsize) + 1;
+                       if (index != NULL)
+                               watchdog_info->pgpool_port = atoi(index);
+
+                       index = (char *) memchr(index, '\0', rsize) + 1;
+                       if (index != NULL)
+                               watchdog_info->wd_port = atoi(index);
+
+                       index = (char *) memchr(index, '\0', rsize) + 1;
+                       if (index != NULL)
+                               watchdog_info->status = atof(index);
+
+                       free(buf);
+                       return watchdog_info;
+               }
+       }
+
+       free(buf);
+}
index 6196b5295bf22dea747671b86b0ca5a92fe7cbee..364f12c06d7214f67cace234cd266ff3ea51aca5 100644 (file)
--- a/pcp/pcp.h
+++ b/pcp/pcp.h
@@ -25,6 +25,7 @@
 #define PCP_H
 
 #include "pool_type.h"
+#include "watchdog/watchdog.h"
 
 #define MAX_USER_PASSWD_LEN    128
 
diff --git a/pcp/pcp_watchdog_info.c b/pcp/pcp_watchdog_info.c
new file mode 100644 (file)
index 0000000..c3abded
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * $Header$
+ *
+ * pgpool: a language independent connection pool server for PostgreSQL
+ * written by Tatsuo Ishii
+ *
+ * Copyright (c) 2003-2013     PgPool Global Development Group
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of the
+ * author not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. The author makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * Client program to send "watchdog info" command.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+#include "getopt_long.h"
+#endif
+
+#include "pcp.h"
+
+static void usage(void);
+static void myexit(ErrorCode e);
+
+int
+main(int argc, char **argv)
+{
+       long timeout;
+       char host[MAX_DB_HOST_NAMELEN];
+       int port;
+       char user[MAX_USER_PASSWD_LEN];
+       char pass[MAX_USER_PASSWD_LEN];
+       int wd_index;
+       WdInfo *watchdog_info;
+       int ch;
+       int optindex;
+       bool verbose = false;
+
+       static struct option long_options[] = {
+               {"debug", no_argument, NULL, 'd'},
+               {"help", no_argument, NULL, 'h'},
+               {"verbose", no_argument, NULL, 'v'},
+               {NULL, 0, NULL, 0}
+       };
+       
+       while ((ch = getopt_long(argc, argv, "hdv", long_options, &optindex)) != -1) {
+               switch (ch) {
+               case 'd':
+                       pcp_enable_debug();
+                       break;
+
+               case 'v':
+                       verbose = true;
+                       break;
+
+               case 'h':
+               case '?':
+               default:
+                       usage();
+                       exit(0);
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       if (!(argc == 5 || argc == 6))
+       {
+               errorcode = INVALERR;
+               pcp_errorstr(errorcode);
+               myexit(errorcode);
+       }
+
+       timeout = atol(argv[0]);
+       if (timeout < 0) {
+               errorcode = INVALERR;
+               pcp_errorstr(errorcode);
+               myexit(errorcode);
+       }
+
+       if (strlen(argv[1]) >= MAX_DB_HOST_NAMELEN)
+       {
+               errorcode = INVALERR;
+               pcp_errorstr(errorcode);
+               myexit(errorcode);
+       }
+       strcpy(host, argv[1]);
+
+       port = atoi(argv[2]);
+       if (port <= 1024 || port > 65535)
+       {
+               errorcode = INVALERR;
+               pcp_errorstr(errorcode);
+               myexit(errorcode);
+       }
+
+       if (strlen(argv[3]) >= MAX_USER_PASSWD_LEN)
+       {
+               errorcode = INVALERR;
+               pcp_errorstr(errorcode);
+               myexit(errorcode);
+       }
+       strcpy(user, argv[3]);
+
+       if (strlen(argv[4]) >= MAX_USER_PASSWD_LEN)
+       {
+               errorcode = INVALERR;
+               pcp_errorstr(errorcode);
+               myexit(errorcode);
+       }
+       strcpy(pass, argv[4]);
+
+       if (argc == 6)
+       {
+               wd_index = atoi(argv[5]);
+               if (wd_index < 0 || wd_index > MAX_WATCHDOG_NUM)
+               {
+                       errorcode = INVALERR;
+                       pcp_errorstr(errorcode);
+                       myexit(errorcode);
+               }
+               wd_index++;
+       }
+       else
+       {
+               wd_index = 0;
+       }
+
+       pcp_set_timeout(timeout);
+
+       if (pcp_connect(host, port, user, pass))
+       {
+               pcp_errorstr(errorcode);
+               myexit(errorcode);
+       }
+
+       if ((watchdog_info = pcp_watchdog_info(wd_index)) == NULL)
+       {
+               pcp_errorstr(errorcode);
+               pcp_disconnect();
+               myexit(errorcode);
+       }
+       else
+       {
+               if (verbose)
+               {
+                       printf("Hostname     : %s\nPgpool port  : %d\nWatchdog port: %d\nStatus       : %d\n",
+                              watchdog_info->hostname,
+                              watchdog_info->pgpool_port,
+                              watchdog_info->wd_port,
+                              watchdog_info->status);
+               }
+               else
+               {
+                       printf("%s %d %d %d\n",
+                              watchdog_info->hostname,
+                              watchdog_info->pgpool_port,
+                              watchdog_info->wd_port,
+                              watchdog_info->status);
+               }
+
+               free(watchdog_info);
+       }
+
+       pcp_disconnect();
+
+       return 0;
+}
+
+static void
+usage(void)
+{
+       fprintf(stderr, "pcp_watchdog_info - display a pgpool-II watchdog's information\n\n");
+       fprintf(stderr, "Usage: pcp_watchdog_info [-d] timeout hostname port# username password [watchdogID]\n");
+       fprintf(stderr, "  -d, --debug    : enable debug message (optional)\n");
+       fprintf(stderr, "  timeout        : connection timeout value in seconds. command exits on timeout\n");
+       fprintf(stderr, "  hostname       : pgpool-II hostname\n");
+       fprintf(stderr, "  port#          : PCP port number\n");
+       fprintf(stderr, "  username       : username for PCP authentication\n");
+       fprintf(stderr, "  password       : password for PCP authentication\n");
+       fprintf(stderr, "  watchdogID     : ID of a other pgpool to get information for\n");
+       fprintf(stderr, "                   If omitted then get one's self information\n\n");
+       fprintf(stderr, "Usage: pcp_watchdog_info [options]\n");
+       fprintf(stderr, "  Options available are:\n");
+       fprintf(stderr, "  -h, --help     : print this help\n");
+       fprintf(stderr, "  -v, --verbose  : display one line per information with a header\n");
+}
+
+static void
+myexit(ErrorCode e)
+{
+       if (e == INVALERR)
+       {
+               usage();
+               exit(e);
+       }
+
+       exit(e);
+}
index b279071f78de9356861f0afda2cbc79b6eaa2774..dec1607c397cf51b47bf72c008876a67db26e1aa 100644 (file)
@@ -56,6 +56,7 @@
 #include "pool_config.h"
 #include "pool_process_context.h"
 #include "pool_process_reporting.h"
+#include "watchdog/wd_ext.h"
 
 #define MAX_FILE_LINE_LEN    512
 #define MAX_USER_PASSWD_LEN  128
@@ -747,6 +748,85 @@ pcp_do_child(int unix_fd, int inet_fd, char *pcp_conf_file)
                                break;
                        }
 
+                       case 'W':                       /* watchdog info */
+                       {
+                               int wd_index;
+                               int wsize;
+
+                               WdInfo *wi = NULL;
+
+                               if (!pool_config->use_watchdog)
+                               {
+                                       char code[] = "watchdog not enabled";
+
+                                       pcp_write(frontend, "e", 1);
+                                       wsize = htonl(sizeof(code) + sizeof(int));
+                                       pcp_write(frontend, &wsize, sizeof(int));
+                                       pcp_write(frontend, code, sizeof(code));
+                                       if (pcp_flush(frontend) < 0)
+                                       {
+                                               pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
+                                               exit(1);
+                                       }
+
+                                       pool_debug("pcp_child: watcdhog not enabled");
+                                       break;
+                               }
+
+                               wd_index = atoi(buf);
+                               wi = wd_get_watchdog_info(wd_index);
+
+                               if (wi == NULL) {
+                                       char code[] = "Invalid watchdog index";
+
+                                       pcp_write(frontend, "e", 1);
+                                       wsize = htonl(sizeof(code) + sizeof(int));
+                                       pcp_write(frontend, &wsize, sizeof(int));
+                                       pcp_write(frontend, code, sizeof(code));
+                                       if (pcp_flush(frontend) < 0)
+                                       {
+                                               pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
+                                               exit(1);
+                                       }
+
+                                       pool_debug("pcp_child: invalid watchdog index");
+                               }
+                               else
+                               {
+                                       char code[] = "CommandComplete";
+                                       char pgpool_port_str[6];
+                                       char wd_port_str[6];
+                                       char status[2];
+
+                                       snprintf(pgpool_port_str, sizeof(pgpool_port_str), "%d", wi->pgpool_port);
+                                       snprintf(wd_port_str, sizeof(wd_port_str), "%d", wi->wd_port);
+                                       snprintf(status, sizeof(status), "%d", wi->status);
+
+                                       pcp_write(frontend, "w", 1);
+                                       wsize = htonl(sizeof(code) +
+                                                                 strlen(wi->hostname)+1 +
+                                                                 strlen(pgpool_port_str)+1 +
+                                                                 strlen(wd_port_str)+1 +
+                                                                 strlen(status)+1 +
+                                                                 sizeof(int));
+                                       pcp_write(frontend, &wsize, sizeof(int));
+                                       pcp_write(frontend, code, sizeof(code));
+
+                                       pcp_write(frontend, wi->hostname, strlen(wi->hostname)+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);
+                                       if (pcp_flush(frontend) < 0)
+                                       {
+                                               pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
+                                               exit(1);
+                                       }
+
+                                       pool_debug("pcp_child: retrieved node information from shared memory");
+                               }
+                               break;
+                       }
+
                        case 'D':                       /* detach node */
                        case 'd':                       /* detach node gracefully */
                        {
index 0c3f03242ffae41c1aa10f7b98a5dfd5a9fe1c1d..a1ee399b81cd10896b4e6be904728e90958622bc 100644 (file)
@@ -123,7 +123,7 @@ typedef enum {
 /*
  * watchdog list
  */
-typedef struct {
+typedef struct WdInfo {
        WD_STATUS status;                                               /* status */
        struct timeval tv;                                              /* startup time value */
        char hostname[WD_MAX_HOST_NAMELEN];             /* host name */
index 120079ea12758e16cb4aa7a8e262b43c0c5c405e..8f0e513c9601d72ec9fc36fe0f77c4fdc3603afb 100644 (file)
@@ -56,6 +56,7 @@ extern void wd_set_lock_holder(WdInfo *p, bool value);
 extern void wd_set_interlocking(WdInfo *info, bool value);
 extern void wd_clear_interlocking_info(void);
 extern bool wd_is_contactable_master(void);
+extern WdInfo * wd_get_watchdog_info(int num);
 
 /* wd_packet.c */
 extern int wd_startup(void);
index f82b44f0c79c358b1efc295fab5e50cb118a9555..83ec4e92727452592ebfae30549e747fba65529d 100644 (file)
@@ -394,3 +394,15 @@ wd_is_contactable_master(void)
 
        return false;
 }
+
+/*
+ * get watchdog information of specified index
+ */
+WdInfo *
+wd_get_watchdog_info(int wd_index)
+{
+       if (wd_index < 0 || wd_index > pool_config->other_wd->num_wd)
+               return NULL;
+
+       return &WD_List[wd_index];
+}