Fix bug#156: problem with reloading.
authorTatsuo Ishii <ishii@postgresql.org>
Sun, 17 Jan 2016 12:57:49 +0000 (21:57 +0900)
committerTatsuo Ishii <ishii@postgresql.org>
Sun, 17 Jan 2016 12:57:49 +0000 (21:57 +0900)
While reloading pgpool.conf, the number of DB nodes is tentatively set
to 0, then counted up until reaching to the actual number of backends
by the pgpool main process. Unfortunately the variable is on the
shared memory and it confuses pgpool child process if they are using
the variable. To solve the problem, a local variable is used to count
up the number of backend. After finishing the counting, the value of
the local variable is assigned to the variable on the shared memory.

I will explain why we don't need interlocking:

1) If the number of backend has not changed before/after the loop,
   it's obviously fine.

2) If the number of backend has increased after the loop, the new
   backend is recognized as "CON_UNUSED" because all the status for
   each backend is set to "CON_UNUSED" beforehand.

3) If the number of backend has decreased after the loop, failover
   should have happened and child process should have restarted.

However, we should be careful so that the assignment of the variable
should happen in an atomic manner. For this purpose I change the data
type of the variable from int to sig_atomic_t.

pcp/libpcp_ext.h
pool_config.c
pool_config.l

index b10a8e971f12955df887c390d4fbd6e103a9b132..09cd196e7366a4c55f27d8ccc4b57d8e116ae7ce 100644 (file)
@@ -4,7 +4,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL 
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2015     PgPool Global Development Group
+ * Copyright (c) 2003-2016     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -25,7 +25,8 @@
 
 #ifndef LIBPCP_EXT_H
 #define LIBPCP_EXT_H
-
+#include <signal.h>
+#include <stdio.h>
 /*
  * startup packet definitions (v2) stolen from PostgreSQL
  */
@@ -62,7 +63,12 @@ typedef struct {
 } BackendInfo;
 
 typedef struct {
-       int num_backends;               /* number of used PostgreSQL backends */
+       sig_atomic_t num_backends;              /* Number of used PostgreSQL backends.
+                                                                        * This needs to be a sig_atomic_t type
+                                                                        * since it is replaced by a local
+                                                                        * variable while reloading pgpool.conf.
+                                                                        */
+
        BackendInfo backend_info[MAX_NUM_BACKENDS];
 } BackendDesc;
 /*
index 7adca584f7feb3d47c8c5c8fb33e6deb0a6b3ec6..ed2c1110924be8b0f7d65660ffb116b6e1136b22 100644 (file)
@@ -499,7 +499,7 @@ char *yytext;
  * pgpool: a language independent connection pool server for PostgreSQL 
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2013     PgPool Global Development Group
+ * Copyright (c) 2003-2016     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -2157,6 +2157,7 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
        double total_weight;
        int i;
     bool log_destination_changed = false;
+       sig_atomic_t local_num_backends;
 #ifdef USE_MEMCACHED
        bool use_memcached = true;
 #else
@@ -4303,7 +4304,7 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
                }
        }
 
-       pool_config->backend_desc->num_backends = 0;
+       local_num_backends = 0;
        total_weight = 0.0;
 
        for (i=0;i<MAX_CONNECTION_SLOTS;i++)
@@ -4317,7 +4318,7 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
                else
                {
                        total_weight += BACKEND_INFO(i).unnormalized_weight;
-                       pool_config->backend_desc->num_backends = i+1;
+                       local_num_backends = i+1;
                        
                        /* intialize backend_hostname with a default socket path if empty */
                        if (*(BACKEND_INFO(i).backend_hostname) == '\0') 
@@ -4335,6 +4336,8 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
                        }
                }       
        }
+       if (local_num_backends != pool_config->backend_desc->num_backends)
+                       pool_config->backend_desc->num_backends = local_num_backends;
 
        pool_debug("num_backends: %d total_weight: %f",
                           pool_config->backend_desc->num_backends, total_weight);
index 3fc8695b4dd58f224f11b5f7fd836ea960235937..54d6c67204d8b2ce4e86b2ac6754bbc73954ddc9 100644 (file)
@@ -6,7 +6,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL 
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2013     PgPool Global Development Group
+ * Copyright (c) 2003-2016     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -418,6 +418,7 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
        double total_weight;
        int i;
     bool log_destination_changed = false;
+       sig_atomic_t local_num_backends;
 #ifdef USE_MEMCACHED
        bool use_memcached = true;
 #else
@@ -2564,7 +2565,7 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
                }
        }
 
-       pool_config->backend_desc->num_backends = 0;
+       local_num_backends = 0;
        total_weight = 0.0;
 
        for (i=0;i<MAX_CONNECTION_SLOTS;i++)
@@ -2578,7 +2579,7 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
                else
                {
                        total_weight += BACKEND_INFO(i).unnormalized_weight;
-                       pool_config->backend_desc->num_backends = i+1;
+                       local_num_backends = i+1;
                        
                        /* intialize backend_hostname with a default socket path if empty */
                        if (*(BACKEND_INFO(i).backend_hostname) == '\0') 
@@ -2596,6 +2597,8 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
                        }
                }       
        }
+       if (local_num_backends != pool_config->backend_desc->num_backends)
+                       pool_config->backend_desc->num_backends = local_num_backends;
 
        pool_debug("num_backends: %d total_weight: %f",
                           pool_config->backend_desc->num_backends, total_weight);