Add "last_status_change" column to "show pool_nodes" command.
authorTatsuo Ishii <ishii@postgresql.org>
Tue, 12 Jun 2018 12:53:04 +0000 (21:53 +0900)
committerTatsuo Ishii <ishii@postgresql.org>
Tue, 12 Jun 2018 12:53:04 +0000 (21:53 +0900)
The new column indicates the time when "status" or "role" has been
changed. See [pgpool-hackers: 2822] for the reasoning to add the
column.

Probably "last_status_change" should be added to pcp_node_info command
and pgpool_adm functions as well but they are not included in this
commit.

doc.ja/src/sgml/ref/show_pool_nodes.sgml
doc/src/sgml/ref/show_pool_nodes.sgml
src/include/pcp/libpcp_ext.h
src/include/pool.h
src/main/pgpool_main.c
src/protocol/pool_connection_pool.c
src/test/regression/tests/003.failover/create_expected.sql
src/test/regression/tests/003.failover/create_expected_node0.sql
src/test/regression/tests/003.failover/test.sh
src/utils/pool_process_reporting.c

index e7424f24939c93556a07b85db1f9cb5f9130fdec..aa86860963369387309591c79370256ad60561af 100644 (file)
@@ -42,28 +42,31 @@ SHOW POOL_NODES
       hostname, the port, the status, the weight (only meaningful if
       you use the load balancing mode), the role, the SELECT query
       counts issued to each backend, whether each node is the load
-      bakance node or not, and the replication delay (only if in
-      streaming replication mode). The possible values in the status
-      column are explained in the <xref linkend="pcp-node-info">
-      reference. If the hostname is something like "/tmp", that means
+      bakance node or not, the replication delay (only if in streaming
+      replication mode) and last status change time. The possible
+      values in the status column are explained in
+      the <xref linkend="pcp-node-info"> reference. If the hostname is
+      something like "/tmp", that means
       <productname>Pgpool-II</productname> is connecting to backend by
       using UNIX domain sockets. The SELECT count does not include
       internal queries used
       by <productname>Pgoool-II</productname>. Also the counters are
-      reset to zero upon starting up of pgpool-II.  displays the
-      current value of
-      <productname>Pgpool-II</productname> configuration parameters.
+      reset to zero upon starting up
+      of <productname>Pgpool-II</productname>.  The last status change
+      time is initially set to the
+      time <productname>Pgpool-II</productname> starts.  After that
+      whenever "status" or "role" is changed, it is updated.
       -->
-
     <command>SHOW POOL_NODES</command> はホスト名、ポート番号、状態、
     重み(ロードバランスモードで運用しているときにのみ意味があります)、
     ノードの役割、発行された SELECT の数、ロードバランスノードであるかどうか、
-    レプリケーション遅延 (ストリーミングレプリケーションモードのみ) が表示されます。
+    ã\83¬ã\83\97ã\83ªã\82±ã\83¼ã\82·ã\83§ã\83³é\81\85å»¶ (ã\82¹ã\83\88ã\83ªã\83¼ã\83\9fã\83³ã\82°ã\83¬ã\83\97ã\83ªã\82±ã\83¼ã\82·ã\83§ã\83³ã\83¢ã\83¼ã\83\89ã\81®ã\81¿) ã\80\81æ\9c\80çµ\82ç\8a¶æ\85\8bå¤\89æ\9b´æ\99\82å\88»ã\81\8c表示ã\81\95ã\82\8cã\81¾ã\81\99ã\80\82
     状態(status)の意味については、 <xref linkend="pcp-node-info"> リファレンスで説明されています。
     ホスト名が "/tmp" のように表示される場合、UNIX ドメインソケットを使用して
     <productname>Pgpool-II</productname> が <productname>PostgreSQL</productname> に接続していることを意味します。
     SELECT の数には、<productname>Pgpool-II</productname> 内部で発行されるクエリの数は含まれません。
     また、このカウンタは <productname>Pgpool-II</productname> がスタートした時に 0にリセットされます。
+    最終状態変更時刻は、<productname>Pgpool-II</productname>が起動した時にセットされたあとは、"status"あるいは"role"が変更される度に更新されます。
     </para>
     <para>
     <!--
@@ -72,10 +75,10 @@ SHOW POOL_NODES
     ここでは例を示します。
 <programlisting>
 test=# show pool_nodes;
- node_id | hostname | port  | status | lb_weight |  role   | select_cnt | load_balance_node | replication_delay
----------+----------+-------+--------+-----------+---------+------------+-------------------+-------------------
- 0       | /tmp     | 11002 | up     | 0.500000  | primary | 0          | false             | 0
- 1       | /tmp     | 11003 | up     | 0.500000  | standby | 0          | true              | 0
+ node_id | hostname | port  | status | lb_weight |  role   | select_cnt | load_balance_node | replication_delay | last_status_change  
+---------+----------+-------+--------+-----------+---------+------------+-------------------+-------------------+---------------------
+ 0       | /tmp     | 11002 | up     | 0.500000  | primary | 0          | true              | 0                 | 2018-06-12 21:45:59
+ 1       | /tmp     | 11003 | up     | 0.500000  | standby | 0          | false             | 0                 | 2018-06-12 21:45:59
 (2 rows)
 </programlisting>
     </para>
index fd129d8667c7fb568992291931086f5ecfc70089..b20b04b9ea3b45c5988e2f0293c7e36238d150d8 100644 (file)
@@ -35,24 +35,29 @@ SHOW POOL_NODES
       hostname, the port, the status, the weight (only meaningful if
       you use the load balancing mode), the role, the SELECT query
       counts issued to each backend, whether each node is the load
-      bakance node or not, and the replication delay (only if in
-      streaming replication mode). The possible values in the status
-      column are explained in the <xref linkend="pcp-node-info">
-      reference. If the hostname is something like "/tmp", that means
+      bakance node or not, the replication delay (only if in streaming
+      replication mode) and last status change time. The possible
+      values in the status column are explained in
+      the <xref linkend="pcp-node-info"> reference. If the hostname is
+      something like "/tmp", that means
       <productname>Pgpool-II</productname> is connecting to backend by
       using UNIX domain sockets. The SELECT count does not include
       internal queries used
       by <productname>Pgoool-II</productname>. Also the counters are
-      reset to zero upon starting up of <productname>Pgpool-II</productname>.
+      reset to zero upon starting up
+      of <productname>Pgpool-II</productname>.  The last status change
+      time is initially set to the
+      time <productname>Pgpool-II</productname> starts.  After that
+      whenever "status" or "role" is changed, it is updated.
     </para>
     <para>
       Here is an example session:
 <programlisting>
 test=# show pool_nodes;
- node_id | hostname | port  | status | lb_weight |  role   | select_cnt | load_balance_node | replication_delay
----------+----------+-------+--------+-----------+---------+------------+-------------------+-------------------
- 0       | /tmp     | 11002 | up     | 0.500000  | primary | 0          | false             | 0
- 1       | /tmp     | 11003 | up     | 0.500000  | standby | 0          | true              | 0
+ node_id | hostname | port  | status | lb_weight |  role   | select_cnt | load_balance_node | replication_delay | last_status_change  
+---------+----------+-------+--------+-----------+---------+------------+-------------------+-------------------+---------------------
+ 0       | /tmp     | 11002 | up     | 0.500000  | primary | 0          | true              | 0                 | 2018-06-12 21:45:59
+ 1       | /tmp     | 11003 | up     | 0.500000  | standby | 0          | false             | 0                 | 2018-06-12 21:45:59
 (2 rows)
 </programlisting>
     </para>
index 4c961077052b31f270b606c5827e311d00a6d57e..a1944405d06c4639b20b39188f55734697936be1 100644 (file)
@@ -4,7 +4,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL 
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2017     PgPool Global Development Group
+ * Copyright (c) 2003-2018     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -78,6 +78,7 @@ typedef struct {
        char backend_hostname[MAX_DB_HOST_NAMELEN];     /* backend host name */
        int backend_port;       /* backend port numbers */
        BACKEND_STATUS backend_status;  /* backend status */
+       time_t status_changed_time;     /* backend status changed time */
        double backend_weight;  /* normalized backend load balance ratio */
        double unnormalized_weight; /* descripted parameter */
        char backend_data_directory[MAX_PATH_LENGTH];
@@ -178,6 +179,7 @@ typedef struct {
        char select[POOLCONFIG_MAXWEIGHTLEN+1];
        char load_balance_node[POOLCONFIG_MAXWEIGHTLEN+1];
        char delay[POOLCONFIG_MAXWEIGHTLEN+1];
+       char last_status_change[POOLCONFIG_MAXDATELEN];
 } POOL_REPORT_NODES;
 
 /* processes report struct */
index 6276b8e61642aa9fa136a418206dcdb8cdd4c429..0e15058183a4e46c55f9465f32e7f52a691da2c5 100644 (file)
@@ -753,5 +753,6 @@ extern int write_status_file(void);
 extern void do_health_check_child(int *node_id);
 extern POOL_NODE_STATUS *verify_backend_node_status(POOL_CONNECTION_POOL_SLOT **slots);
 extern POOL_NODE_STATUS *pool_get_node_status(void);
+extern void pool_set_backend_status_changed_time(int backend_id);
 
 #endif /* POOL_H */
index 8074b938c91dfa4e5fb2ee328b44f6c1e7f27a54..619ae7be6eca14fa11bd70b8f8d82265ae4362f3 100644 (file)
@@ -1700,6 +1700,8 @@ static void failover(void)
                        all_backend_down = check_all_backend_down();
 
                        BACKEND_INFO(node_id).backend_status = CON_CONNECT_WAIT;        /* unset down status */
+                       pool_set_backend_status_changed_time(node_id);
+
                        if (!(request_details & REQ_DETAIL_UPDATE))
                        {
                                /* The request is a proper failbak request
@@ -1746,6 +1748,7 @@ static void failover(void)
                                                         BACKEND_INFO(node_id_set[i]).backend_port)));
 
                                        BACKEND_INFO(node_id_set[i]).backend_status = CON_DOWN; /* set down status */
+                                       pool_set_backend_status_changed_time(node_id_set[i]);
 
                                        if (reqkind == NODE_QUARANTINE_REQUEST)
                                        {
@@ -1959,6 +1962,7 @@ static void failover(void)
                                                                         bkinfo->backend_hostname,
                                                                         bkinfo->backend_port)));
                                                        bkinfo->backend_status = CON_DOWN;      /* set down status */
+                                                       pool_set_backend_status_changed_time(i);
                                                        (void)write_status_file();
 
                                                        follow_cnt++;
@@ -1988,6 +1992,13 @@ static void failover(void)
                }
 
                /* Save primary node id */
+               if (Req_info->primary_node_id != new_primary)
+               {
+                       if (Req_info->primary_node_id >= 0)
+                               pool_set_backend_status_changed_time(Req_info->primary_node_id);
+                       if (new_primary >= 0)
+                               pool_set_backend_status_changed_time(new_primary);
+               }
                Req_info->primary_node_id = new_primary;
                ereport(LOG,
                                (errmsg("failover: set new primary node: %d", Req_info->primary_node_id)));
@@ -3442,6 +3453,7 @@ static int read_status_file(bool discard_status)
                        if (backend_rec.status[i] == CON_DOWN)
                        {
                                BACKEND_INFO(i).backend_status = CON_DOWN;
+                               pool_set_backend_status_changed_time(i);
                                (void)write_status_file();
                                ereport(LOG,
                                                (errmsg("read_status_file: %d th backend is set to down status", i)));
@@ -3450,6 +3462,7 @@ static int read_status_file(bool discard_status)
                                         BACKEND_INFO(i).backend_status == CON_UP)
                        {
                                BACKEND_INFO(i).backend_status = CON_CONNECT_WAIT;
+                               pool_set_backend_status_changed_time(i);
                                (void)write_status_file();
                                someone_wakeup = true;
                        }
@@ -3491,6 +3504,7 @@ static int read_status_file(bool discard_status)
                for (i=0;i<MAX_NUM_BACKENDS;i++)
                {
                        BACKEND_INFO(i).backend_status = CON_UNUSED;
+                       pool_set_backend_status_changed_time(i);
                }
 
                for (i=0;;i++)
@@ -3507,12 +3521,14 @@ static int read_status_file(bool discard_status)
                        else if (!strncasecmp("down", readbuf, 4))
                        {
                                BACKEND_INFO(i).backend_status = CON_DOWN;
+                               pool_set_backend_status_changed_time(i);
                                ereport(LOG,
                                                (errmsg("reading status file: %d th backend is set to down status", i)));
                        }
                        else if (!strncasecmp("unused", readbuf, 6))
                        {
                                BACKEND_INFO(i).backend_status = CON_UNUSED;
+                               pool_set_backend_status_changed_time(i);
                        }
                        else
                        {
@@ -3532,6 +3548,7 @@ static int read_status_file(bool discard_status)
                for (i=0;i< pool_config->backend_desc->num_backends;i++)
                {
                        BACKEND_INFO(i).backend_status = CON_CONNECT_WAIT;
+                       pool_set_backend_status_changed_time(i);
                }
                (void)write_status_file();
        }
@@ -3832,6 +3849,7 @@ static void sync_backend_from_watchdog(void)
                        if (BACKEND_INFO(i).backend_status != CON_DOWN)
                        {
                                BACKEND_INFO(i).backend_status = CON_DOWN;
+                               pool_set_backend_status_changed_time(i);
                                my_backend_status[i] = &(BACKEND_INFO(i).backend_status);
                                reload_maste_node_id = true;
                                node_status_was_changed_to_down = true;
@@ -3850,6 +3868,7 @@ static void sync_backend_from_watchdog(void)
                                        node_status_was_changed_to_up = true;
 
                                BACKEND_INFO(i).backend_status = CON_CONNECT_WAIT;
+                               pool_set_backend_status_changed_time(i);
                                my_backend_status[i] = &(BACKEND_INFO(i).backend_status);
                                reload_maste_node_id = true;
 
@@ -4055,3 +4074,14 @@ static void get_info_from_conninfo(char *conninfo, char *host, char *port)
                *port = '\0';
        }
 }
+
+/*
+ * Set backend status changed time for specified backend id.
+ */
+void
+pool_set_backend_status_changed_time(int backend_id)
+{
+       time_t tval;
+       tval = time(NULL);
+       BACKEND_INFO(backend_id).status_changed_time = tval;
+}
index 320f76d17aba051cd025b9be8c777f096fecb86e..c02bec244794ccfcfe15ff16ae0a65b5cbc41328 100644 (file)
@@ -911,7 +911,11 @@ static POOL_CONNECTION_POOL *new_connection(POOL_CONNECTION_POOL *p)
 
                pool_init_params(&s->con->params);
        
-               BACKEND_INFO(i).backend_status = CON_UP;
+               if (BACKEND_INFO(i).backend_status != CON_UP)
+               {
+                       BACKEND_INFO(i).backend_status = CON_UP;
+                       pool_set_backend_status_changed_time(i);
+               }
                active_backend_count++;
        }
 
index 5be557659d82755b2da633c35e51199be327e81b..8821023a2e968124f66da1d9a22c70d71c9b422a 100644 (file)
@@ -8,14 +8,15 @@ CREATE TEMP TABLE tmp (
   select_cnt text,
   load_balance_node text,
   replication_delay text,
+  last_status_change text,
   mode text);
 
 INSERT INTO tmp VALUES
-('0',:dir,'11002','up','0.500000','primary','0','false','0','s'),
-('1',:dir,'11003','down','0.500000','standby','0','false','0','s'),
-('0',:dir,'11002','up','0.500000','master','0','false','0','r'),
-('1',:dir,'11003','down','0.500000','slave','0','false','0','r');
+('0',:dir,'11002','up','0.500000','primary','0','false','0','XXXX-XX-XX XX:XX:XX','s'),
+('1',:dir,'11003','down','0.500000','standby','0','false','0','XXXX-XX-XX XX:XX:XX','s'),
+('0',:dir,'11002','up','0.500000','master','0','false','0','XXXX-XX-XX XX:XX:XX','r'),
+('1',:dir,'11003','down','0.500000','slave','0','false','0','XXXX-XX-XX XX:XX:XX','r');
 
-SELECT node_id,hostname,port,status,lb_weight,role,select_cnt,load_balance_node,replication_delay
+SELECT node_id,hostname,port,status,lb_weight,role,select_cnt,load_balance_node,replication_delay,last_status_change
 FROM tmp
 WHERE mode = :mode
index abdd3bbebaddc47049e0d427a7175d2b0a24e7c9..ea5a1392f69d8a27aadcacf7520ec8b87b0f0525 100644 (file)
@@ -8,14 +8,15 @@ CREATE TEMP TABLE tmp (
   select_cnt text,
   load_balance_node text,
   replication_delay text,
+  last_status_change text,
   mode text);
 
 INSERT INTO tmp VALUES
-('0',:dir,'11002','down','0.500000','standby','0','false','0','s'),
-('1',:dir,'11003','up','0.500000','primary','0','false','0','s'),
-('0',:dir,'11002','down','0.500000','slave','0','false','0','r'),
-('1',:dir,'11003','up','0.500000','master','0','false','0','r');
+('0',:dir,'11002','down','0.500000','standby','0','false','0','XXXX-XX-XX XX:XX:XX','s'),
+('1',:dir,'11003','up','0.500000','primary','0','false','0','XXXX-XX-XX XX:XX:XX','s'),
+('0',:dir,'11002','down','0.500000','slave','0','false','0','XXXX-XX-XX XX:XX:XX','r'),
+('1',:dir,'11003','up','0.500000','master','0','false','0','XXXX-XX-XX XX:XX:XX','r');
 
-SELECT node_id,hostname,port,status,lb_weight,role,select_cnt,load_balance_node,replication_delay
+SELECT node_id,hostname,port,status,lb_weight,role,select_cnt,load_balance_node,replication_delay,last_status_change
 FROM tmp
 WHERE mode = :mode
index de076415e8485fc8acd2cd1995edcd90be2ea592..74a569eac42707c1bf6185e52a5a5eaccff4fdc1 100755 (executable)
@@ -27,7 +27,7 @@ do
        # trigger failover on node 1
        $PG_CTL -D data1 -m f stop
        wait_for_pgpool_startup
-       $PSQL -c "show pool_nodes" test |sed -e 's/true /false/'> result
+       $PSQL -c "show pool_nodes" test |sed -e 's/true /false/' -e 's/....-..-.. ..:..:../XXXX-XX-XX XX:XX:XX/g'> result
 
        # check the output of "show pool_nodes".
        LANG=C $PSQL -f ../create_expected.sql -v mode="'$mode'" -v dir="'$PGSOCKET_DIR'" test | tail -n 6 > expected
@@ -44,7 +44,7 @@ do
        # trigger failover on node 0
        $PG_CTL -D data0 -m f stop
        wait_for_failover_done
-       $PSQL -c "show pool_nodes" test | sed -e 's/true /false/' > result
+       $PSQL -c "show pool_nodes" test |sed -e 's/true /false/' -e 's/....-..-.. ..:..:../XXXX-XX-XX XX:XX:XX/g'> result
        if [ ! -s result ];then
                ./shutdownall
                echo "result file is empty."
index a25097ab59d6931ca70f759c5adcce5967cffad8..fc8f6f32f6f9de62f81fc3f1a747b067c46f3694 100644 (file)
@@ -1150,6 +1150,7 @@ POOL_REPORT_NODES* get_nodes(int *nrows)
        POOL_REPORT_NODES* nodes = palloc(NUM_BACKENDS * sizeof(POOL_REPORT_NODES));
        BackendInfo *bi = NULL;
        POOL_SESSION_CONTEXT *session_context = pool_get_session_context(false);
+       struct tm tm;
 
     for (i = 0; i < NUM_BACKENDS; i++)
        {
@@ -1185,6 +1186,10 @@ POOL_REPORT_NODES* get_nodes(int *nrows)
                        else
                                snprintf(nodes[i].role, POOLCONFIG_MAXWEIGHTLEN, "%s", "slave");
                }
+
+               /* status last changed */
+               localtime_r(&bi->status_changed_time, &tm);
+               strftime(nodes[i].last_status_change, POOLCONFIG_MAXDATELEN, "%F %T", &tm);
        }
 
        *nrows = i;
@@ -1194,7 +1199,7 @@ POOL_REPORT_NODES* get_nodes(int *nrows)
 
 void nodes_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
 {
-       static char *field_names[] = {"node_id","hostname", "port", "status", "lb_weight", "role", "select_cnt", "load_balance_node", "replication_delay"};
+       static char *field_names[] = {"node_id","hostname", "port", "status", "lb_weight", "role", "select_cnt", "load_balance_node", "replication_delay", "last_status_change"};
        short num_fields = sizeof(field_names)/sizeof(char *);
        int i;
        short s;
@@ -1261,6 +1266,11 @@ void nodes_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
                        hsize = htonl(size+4);
                        pool_write(frontend, &hsize, sizeof(hsize));
                        pool_write(frontend, nodes[i].delay, size);
+
+                       size = strlen(nodes[i].last_status_change);
+                       hsize = htonl(size+4);
+                       pool_write(frontend, &hsize, sizeof(hsize));
+                       pool_write(frontend, nodes[i].last_status_change, size);
                }
        }
        else
@@ -1279,6 +1289,7 @@ void nodes_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
                        len += 4 + strlen(nodes[i].select);    /* int32 + data; */
                        len += 4 + strlen(nodes[i].load_balance_node);    /* int32 + data; */
                        len += 4 + strlen(nodes[i].delay);    /* int32 + data; */
+                       len += 4 + strlen(nodes[i].last_status_change);    /* int32 + data; */
                        len = htonl(len);
                        pool_write(frontend, &len, sizeof(len));
                        s = htons(num_fields);
@@ -1319,6 +1330,10 @@ void nodes_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend)
                        len = htonl(strlen(nodes[i].delay));
                        pool_write(frontend, &len, sizeof(len));
                        pool_write(frontend, nodes[i].delay, strlen(nodes[i].delay));
+
+                       len = htonl(strlen(nodes[i].last_status_change));
+                       pool_write(frontend, &len, sizeof(len));
+                       pool_write(frontend, nodes[i].last_status_change, strlen(nodes[i].last_status_change));
                }
        }