Hi,
Here is the patch allowing any node in the pgpool line to be promoted
manually as the new master.
It include a new file pcp/pcp_promote_node.c
Automatic promoting of the less lagging node will be implemented later
when this first patch will be reviewed and committed.
Regards,
--
Gilles Darold
http://dalibo.com - http://dalibo.org
diff -rNu pgpool-II/main.c pgpool-II-promote/main.c
--- pgpool-II/main.c 2011-01-11 01:43:30.000000000 +0100
+++ pgpool-II-promote/main.c 2011-01-25 17:50:25.000000000 +0100
@@ -75,6 +75,11 @@
failover(); \
failover_request = 0; \
} \
+ if (promote_request) \
+ { \
+ failover(); \
+ promote_request = 0; \
+ } \
if (sigchld_request) \
{ \
reaper(); \
@@ -160,6 +165,7 @@
volatile sig_atomic_t *InRecovery; /* non 0 if recovery is started */
volatile sig_atomic_t reload_config_request = 0;
static volatile sig_atomic_t failover_request = 0;
+static volatile sig_atomic_t promote_request = 0;
static volatile sig_atomic_t sigchld_request = 0;
static volatile sig_atomic_t wakeup_request = 0;
@@ -1367,6 +1373,13 @@
{
int i;
+ /* When pcp_promote_node is called we must force the new master node */
+ if (PREFERED_PRIMARY_NODE_ID > -1)
+ {
+ if (VALID_BACKEND(PREFERED_PRIMARY_NODE_ID))
+ return PREFERED_PRIMARY_NODE_ID;
+ }
+
for (i=0;i<pool_config->backend_desc->num_backends;i++)
{
/*
@@ -1518,7 +1531,6 @@
return;
}
}
-
new_master = get_next_master_node();
if (new_master < 0)
@@ -1591,12 +1603,6 @@
trigger_failover_command(i, pool_config->failover_command);
}
- if (new_master >= 0)
- {
- pool_log("failover_handler: set new master node: %d", new_master);
- Req_info->master_node_id = new_master;
- }
-
/* no need to wait since it will be done in reap_handler */
#ifdef NOT_USED
while (wait(NULL) > 0)
@@ -1609,6 +1615,12 @@
memset(Req_info->node_id, -1, sizeof(int) * MAX_NUM_BACKENDS);
pool_semaphore_unlock(REQUEST_INFO_SEM);
+ /* Save primary node id */
+ Req_info->primary_node_id = find_primary_node();
+ Req_info->master_node_id = Req_info->primary_node_id;
+ pool_log("Primary node id saved: %d", Req_info->primary_node_id);
+ Req_info->prefered_primary_node_id = -1;
+
/* fork the children */
for (i=0;i<pool_config->num_init_children;i++)
{
@@ -1629,9 +1641,6 @@
BACKEND_INFO(node_id).backend_port);
}
- /* Save primary node id */
- Req_info->primary_node_id = find_primary_node();
-
switching = 0;
/* kick wakeup_handler in pcp_child to notice that
@@ -2299,6 +2308,7 @@
{
if (!VALID_BACKEND(i))
continue;
+
/*
* Check to see if this is a standby node or not
*/
@@ -2312,13 +2322,13 @@
"");
if (!s)
{
- pool_error("find_primary_node: make_persistent_connetcion failed");
+ pool_error("find_primary_node: make_persistent_connection failed");
break;
}
con = s->con;
- status = do_query(con, "SELECT pg_is_in_recovery() AND pgpool_walrecrunning()",
- &res, PROTO_MAJOR_V3);
+ status = do_query(con, "SELECT not pg_is_in_recovery() AND not pgpool_walrecrunning();",
+ &res, PROTO_MAJOR_V3);
if (res->numrows <= 0)
{
pool_log("find_primary_node: do_query returns no rows");
@@ -2331,7 +2341,7 @@
{
pool_log("find_primary_node: do_query returns NULL");
}
- if (res->data[0] && !strcmp(res->data[0], "t"))
+ if (res->data[0] && !strcmp(res->data[0], "f"))
{
is_standby = true;
}
@@ -2360,3 +2370,15 @@
pool_log("find_primary_node: primary node id is %d", i);
return i;
}
+
+void notice_backend_promote(int node_id)
+{
+ int n = find_primary_node();
+
+ Req_info->prefered_primary_node_id = node_id;
+
+ pool_log("notice_backend_promote: primary node id %d will be degenerated. Node %d will be promoted as new master.", n, node_id);
+
+ degenerate_backend_set(&n, 1);
+}
+
diff -rNu pgpool-II/pcp/Makefile.am pgpool-II-promote/pcp/Makefile.am
--- pgpool-II/pcp/Makefile.am 2007-11-01 11:11:25.000000000 +0100
+++ pgpool-II-promote/pcp/Makefile.am 2011-01-25 17:50:25.000000000 +0100
@@ -11,7 +11,7 @@
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_systemdb_info pcp_detach_node pcp_attach_node pcp_recovery_node pcp_promote_node
pcp_stop_pgpool_SOURCES = pcp_stop_pgpool.c pcp.h
pcp_stop_pgpool_LDADD = libpcp.la
pcp_stop_pgpool_LDFLAGS =
@@ -31,3 +31,5 @@
pcp_attach_node_LDADD = libpcp.la
pcp_recovery_node_SOURCES = pcp_recovery_node.c pcp.h
pcp_recovery_node_LDADD = libpcp.la
+pcp_promote_node_SOURCES = pcp_promote_node.c pcp.h
+pcp_promote_node_LDADD = libpcp.la
diff -rNu pgpool-II/pcp/Makefile.in pgpool-II-promote/pcp/Makefile.in
--- pgpool-II/pcp/Makefile.in 2010-11-10 02:53:56.000000000 +0100
+++ pgpool-II-promote/pcp/Makefile.in 2011-01-25 17:50:25.000000000 +0100
@@ -38,7 +38,7 @@
pcp_node_info$(EXEEXT) pcp_proc_count$(EXEEXT) \
pcp_proc_info$(EXEEXT) pcp_systemdb_info$(EXEEXT) \
pcp_detach_node$(EXEEXT) pcp_attach_node$(EXEEXT) \
- pcp_recovery_node$(EXEEXT)
+ pcp_recovery_node$(EXEEXT) pcp_promote_node$(EXEEXT)
subdir = pcp
DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
@@ -88,6 +88,9 @@
am_pcp_recovery_node_OBJECTS = pcp_recovery_node.$(OBJEXT)
pcp_recovery_node_OBJECTS = $(am_pcp_recovery_node_OBJECTS)
pcp_recovery_node_DEPENDENCIES = libpcp.la
+am_pcp_promote_node_OBJECTS = pcp_promote_node.$(OBJEXT)
+pcp_promote_node_OBJECTS = $(am_pcp_promote_node_OBJECTS)
+pcp_promote_node_DEPENDENCIES = libpcp.la
am_pcp_stop_pgpool_OBJECTS = pcp_stop_pgpool.$(OBJEXT)
pcp_stop_pgpool_OBJECTS = $(am_pcp_stop_pgpool_OBJECTS)
pcp_stop_pgpool_DEPENDENCIES = libpcp.la
@@ -113,12 +116,14 @@
$(pcp_detach_node_SOURCES) $(pcp_node_count_SOURCES) \
$(pcp_node_info_SOURCES) $(pcp_proc_count_SOURCES) \
$(pcp_proc_info_SOURCES) $(pcp_recovery_node_SOURCES) \
- $(pcp_stop_pgpool_SOURCES) $(pcp_systemdb_info_SOURCES)
+ $(pcp_stop_pgpool_SOURCES) $(pcp_systemdb_info_SOURCES) \
+ $(pcp_promote_node_SOURCES)
DIST_SOURCES = $(libpcp_la_SOURCES) $(pcp_attach_node_SOURCES) \
$(pcp_detach_node_SOURCES) $(pcp_node_count_SOURCES) \
$(pcp_node_info_SOURCES) $(pcp_proc_count_SOURCES) \
$(pcp_proc_info_SOURCES) $(pcp_recovery_node_SOURCES) \
- $(pcp_stop_pgpool_SOURCES) $(pcp_systemdb_info_SOURCES)
+ $(pcp_stop_pgpool_SOURCES) $(pcp_systemdb_info_SOURCES) \
+ $(pcp_promote_node_SOURCES)
includeHEADERS_INSTALL = $(INSTALL_HEADER)
HEADERS = $(include_HEADERS)
ETAGS = etags
@@ -266,6 +271,8 @@
pcp_attach_node_LDADD = libpcp.la
pcp_recovery_node_SOURCES = pcp_recovery_node.c pcp.h
pcp_recovery_node_LDADD = libpcp.la
+pcp_promote_node_SOURCES = pcp_promote_node.c pcp.h
+pcp_promote_node_LDADD = libpcp.la
all: all-am
.SUFFIXES:
@@ -383,6 +390,9 @@
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_promote_node$(EXEEXT): $(pcp_promote_node_OBJECTS) $(pcp_promote_node_DEPENDENCIES)
+ @rm -f pcp_promote_node$(EXEEXT)
+ $(LINK) $(pcp_promote_node_OBJECTS) $(pcp_promote_node_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -403,6 +413,7 @@
@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_promote_node.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff -rNu pgpool-II/pcp/pcp.c pgpool-II-promote/pcp/pcp.c
--- pgpool-II/pcp/pcp.c 2010-08-06 01:37:43.000000000 +0200
+++ pgpool-II-promote/pcp/pcp.c 2011-01-25 17:50:25.000000000 +0100
@@ -50,6 +50,7 @@
static int pcp_authorize(char *username, char *password);
static int _pcp_detach_node(int nid, bool gracefully);
+static int _pcp_promote_node(int nid, bool gracefully);
/* --------------------------------
* pcp_connect - open connection to pgpool using given arguments
@@ -1331,3 +1332,100 @@
{
debug = 0;
}
+
+/* --------------------------------
+ * pcp_promote_node - promote a node given by the argument as new pgpool's master
+ *
+ * return 0 on success, -1 otherwise
+ * --------------------------------
+ */
+int
+pcp_promote_node(int nid)
+{
+ return _pcp_promote_node(nid, FALSE);
+}
+
+/* --------------------------------
+
+ * and promote a node given by the argument as new pgpool's master
+ *
+ * return 0 on success, -1 otherwise
+ * --------------------------------
+ */
+int
+pcp_promote_node_gracefully(int nid)
+{
+ return _pcp_promote_node(nid, TRUE);
+}
+
+static int _pcp_promote_node(int nid, bool gracefully)
+{
+ int wsize;
+ char node_id[16];
+ char tos;
+ char *buf = NULL;
+ int rsize;
+ char *sendchar;
+
+ if (pc == NULL)
+ {
+ if (debug) fprintf(stderr, "DEBUG: connection does not exist\n");
+ errorcode = NOCONNERR;
+ return -1;
+ }
+
+ snprintf(node_id, sizeof(node_id), "%d", nid);
+
+ if (gracefully)
+ sendchar = "e";
+ else
+ sendchar = "E";
+
+ pcp_write(pc, sendchar, 1);
+ wsize = htonl(strlen(node_id)+1 + sizeof(int));
+ pcp_write(pc, &wsize, sizeof(int));
+ pcp_write(pc, node_id, strlen(node_id)+1);
+ if (pcp_flush(pc) < 0)
+ {
+ if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n");
+ return -1;
+ }
+ if (debug) fprintf(stderr, "DEBUG: send: tos=\"E\", len=%d\n", ntohl(wsize));
+
+ if (pcp_read(pc, &tos, 1))
+ return -1;
+ if (pcp_read(pc, &rsize, sizeof(int)))
+ return -1;
+ rsize = ntohl(rsize);
+ buf = (char *)malloc(rsize);
+ if (buf == NULL)
+ {
+ errorcode = NOMEMERR;
+ return -1;
+ }
+ if (pcp_read(pc, buf, rsize - sizeof(int)))
+ {
+ free(buf);
+ return -1;
+ }
+ 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;
+ }
+ else if (tos == 'd')
+ {
+ /* strcmp() for success message, or fail */
+ if(strcmp(buf, "CommandComplete") == 0)
+ {
+ free(buf);
+ return 0;
+ }
+ }
+
+ free(buf);
+ return -1;
+}
+
diff -rNu pgpool-II/pcp/pcp.h pgpool-II-promote/pcp/pcp.h
--- pgpool-II/pcp/pcp.h 2010-08-05 10:08:44.000000000 +0200
+++ pgpool-II-promote/pcp/pcp.h 2011-01-25 17:50:25.000000000 +0100
@@ -65,6 +65,8 @@
extern int pcp_recovery_node(int nid);
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);
/* ------------------------------
* pcp_error.c
diff -rNu pgpool-II/pcp/pcp_promote_node.c pgpool-II-promote/pcp/pcp_promote_node.c
--- pgpool-II/pcp/pcp_promote_node.c 1970-01-01 01:00:00.000000000 +0100
+++ pgpool-II-promote/pcp/pcp_promote_node.c 2011-01-25 17:53:29.000000000 +0100
@@ -0,0 +1,185 @@
+/*
+ * $Header$
+ *
+ * pgpool: a language independent connection pool server for PostgreSQL
+ * written by Tatsuo Ishii
+ *
+ * Copyright (c) 2003-2010 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 "promote node" 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 nodeID;
+ int ch;
+ int optindex;
+ bool gracefully = false;
+ int sts;
+
+ static struct option long_options[] = {
+ {"debug", no_argument, NULL, 'd'},
+ {"gracefully", no_argument, NULL, 'g'},
+ {"help", no_argument, NULL, 'h'},
+ {NULL, 0, NULL, 0}
+ };
+
+ while ((ch = getopt_long(argc, argv, "hdg", long_options, &optindex)) != -1) {
+ switch (ch) {
+ case 'd':
+ pcp_enable_debug();
+ break;
+
+ case 'g':
+ gracefully = true;
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ usage();
+ exit(0);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (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]);
+
+ nodeID = atoi(argv[5]);
+ if (nodeID < 0 || nodeID > MAX_NUM_BACKENDS)
+ {
+ errorcode = INVALERR;
+ pcp_errorstr(errorcode);
+ myexit(errorcode);
+ }
+
+ pcp_set_timeout(timeout);
+
+ if (pcp_connect(host, port, user, pass))
+ {
+ pcp_errorstr(errorcode);
+ myexit(errorcode);
+ }
+
+ if (gracefully)
+ sts = pcp_promote_node_gracefully(nodeID);
+ else
+ sts = pcp_promote_node(nodeID);
+
+ if (sts)
+ {
+ pcp_errorstr(errorcode);
+ pcp_disconnect();
+ myexit(errorcode);
+ }
+
+ pcp_disconnect();
+
+ return 0;
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "pcp_promote_node - promote a node as new master from pgpool-II\n\n");
+ fprintf(stderr, "Usage: pcp_promote_node [-d][-g] timeout hostname port# username password nodeID\n");
+ fprintf(stderr, "Usage: pcp_promote_node -h\n\n");
+ fprintf(stderr, " -d, --debug : enable debug message (optional)\n");
+ fprintf(stderr, " -g, --gracefully : promote gracefully(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, " nodeID : ID of a node to be promoted\n");
+ fprintf(stderr, " -h, --help : print this help\n");
+}
+
+static void
+myexit(ErrorCode e)
+{
+ if (e == INVALERR)
+ {
+ usage();
+ exit(e);
+ }
+
+ exit(e);
+}
diff -rNu pgpool-II/pcp_child.c pgpool-II-promote/pcp_child.c
--- pgpool-II/pcp_child.c 2010-08-06 01:37:43.000000000 +0200
+++ pgpool-II-promote/pcp_child.c 2011-01-25 17:50:25.000000000 +0100
@@ -69,6 +69,7 @@
static RETSIGTYPE wakeup_handler(int sig);
static RETSIGTYPE reload_config_handler(int sig);
static int pool_detach_node(int node_id, bool gracefully);
+static int pool_promote_node(int node_id, bool gracefully);
extern int myargc;
extern char **myargv;
@@ -826,6 +827,53 @@
}
break;
+ case 'E': /* promote node */
+ case 'e': /* promote node gracefully */
+ {
+ int node_id;
+ int wsize;
+ char code[] = "CommandComplete";
+ bool gracefully;
+
+ if (tos == 'E')
+ gracefully = false;
+ else
+ gracefully = true;
+
+ node_id = atoi(buf);
+ if ( (node_id < 0) || (node_id >= pool_config->backend_desc->num_backends) )
+ {
+ char code[] = "NodeIdOutOfRange";
+
+ pool_error("pcp_child: node id %d is not valid", node_id);
+ 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);
+ }
+ exit(1);
+ }
+
+ pool_debug("pcp_child: promoting Node ID %d", node_id);
+ pool_promote_node(node_id, gracefully);
+
+ pcp_write(frontend, "d", 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);
+ }
+ break;
+ }
+
+
case 'F':
pool_debug("pcp_child: stop online recovery");
break;
@@ -1146,3 +1194,52 @@
return 0;
}
+
+/* Promote a node */
+static int pool_promote_node(int node_id, bool gracefully)
+{
+ if (!gracefully)
+ {
+ notice_backend_promote(node_id); /* send promote request */
+ return 0;
+ }
+
+ /*
+ * Wait until all frontends exit
+ */
+ *InRecovery = 1; /* This wiil ensure that new incoming
+ * connection requests are blocked */
+
+ if (wait_connection_closed())
+ {
+ /* wait timed out */
+ finish_recovery();
+ return -1;
+ }
+
+ /*
+ * Now all frontends have gone. Let's do failover.
+ */
+ notice_backend_promote(node_id); /* send promote request */
+
+ /*
+ * Wait for failover completed.
+ */
+ pcp_wakeup_request = 0;
+
+ while (!pcp_wakeup_request)
+ {
+ struct timeval t = {1, 0};
+ select(0, NULL, NULL, NULL, &t);
+ }
+ pcp_wakeup_request = 0;
+
+ /*
+ * Start to accept incoming connections and send SIGUSR2 to pgpool
+ * parent to distribute SIGUSR2 all pgpool children.
+ */
+ finish_recovery();
+
+ return 0;
+}
+
diff -rNu pgpool-II/pool_auth.c pgpool-II-promote/pool_auth.c
--- pgpool-II/pool_auth.c 2010-12-30 01:47:05.000000000 +0100
+++ pgpool-II-promote/pool_auth.c 2011-01-25 17:50:25.000000000 +0100
@@ -1304,7 +1304,7 @@
}
else
{
- if (kind != kind0)
+ if ( (kind != kind0) && ((kind == 'E') || (kind0 == 'E')) )
{
char *message;
diff -rNu pgpool-II/pool.h pgpool-II-promote/pool.h
--- pgpool-II/pool.h 2010-12-30 01:47:05.000000000 +0100
+++ pgpool-II-promote/pool.h 2011-01-25 17:50:25.000000000 +0100
@@ -296,6 +296,12 @@
#define REAL_PRIMARY_NODE_ID (Req_info->primary_node_id)
/*
+ * The prefered primary node id in streaming replication mode after a failover. If not in the
+ * mode or there's no prefered primary node, this macro returns -1
+ */
+#define PREFERED_PRIMARY_NODE_ID (Req_info->prefered_primary_node_id)
+
+/*
* "Virtual" master node id. It's same as REAL_MASTER_NODE_ID if not
* in load balance mode. If in load balance, it's the first load
* balance node.
@@ -348,7 +354,8 @@
NODE_UP_REQUEST = 0,
NODE_DOWN_REQUEST,
NODE_RECOVERY_REQUEST,
- CLOSE_IDLE_REQUEST
+ CLOSE_IDLE_REQUEST,
+ NODE_PROMOTE_REQUEST
} POOL_REQUEST_KIND;
typedef struct {
@@ -356,6 +363,7 @@
int node_id[MAX_NUM_BACKENDS]; /* request node id */
int master_node_id; /* the youngest node id which is not in down status */
int primary_node_id; /* the primary node id in streaming replication mode */
+ int prefered_primary_node_id; /* the prefered next primary node id in streaming replication mode */
int conn_counter;
} POOL_REQUEST_INFO;
@@ -448,6 +456,7 @@
extern void notice_backend_error(int node_id);
extern void degenerate_backend_set(int *node_id_set, int count);
extern void send_failback_request(int node_id);
+extern void notice_backend_promote(int node_id);
extern void pool_set_timeout(int timeoutval);
diff -rNu pgpool-II/pool_query_context.c pgpool-II-promote/pool_query_context.c
--- pgpool-II/pool_query_context.c 2010-10-20 03:08:55.000000000 +0200
+++ pgpool-II-promote/pool_query_context.c 2011-01-25 17:50:25.000000000 +0100
@@ -260,13 +260,22 @@
sc = pool_get_session_context();
if (!sc)
{
+ if (PREFERED_PRIMARY_NODE_ID == -1)
return REAL_MASTER_NODE_ID;
+ else
+ return PREFERED_PRIMARY_NODE_ID;
}
if (sc->query_context)
{
+ if (PREFERED_PRIMARY_NODE_ID == -1)
return sc->query_context->virtual_master_node_id;
+ else
+ return PREFERED_PRIMARY_NODE_ID;
}
+ if (PREFERED_PRIMARY_NODE_ID >= 0)
+ return PREFERED_PRIMARY_NODE_ID;
+
return REAL_MASTER_NODE_ID;
}
_______________________________________________
Pgpool-hackers mailing list
[email protected]
http://pgfoundry.org/mailman/listinfo/pgpool-hackers