Hi,

This implements the feature discussed in the earlier thread of killing 
connections on backup servers when a non-backup server comes back up. For 
example, you can use this to route to a mysql master & slave and ensure 
clients don't stay on the slave after the master goes from down->up. I've done 
some minimal testing and it seems to work.

Today is the first time I ever looked at haproxy's code but this feature seemed 
straightforward enough to implement. I hope I've done it properly.

Justin
diff --git a/include/types/checks.h b/include/types/checks.h
index fd15c95..250a68f 100644
--- a/include/types/checks.h
+++ b/include/types/checks.h
@@ -80,6 +80,12 @@ enum {
 };
 
 enum {
+	HANA_ONMARKEDUP_NONE	= 0,
+
+	HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS,	/* Shutdown peer sessions */
+};
+
+enum {
 	HANA_OBS_NONE		= 0,
 
 	HANA_OBS_LAYER4,		/* Observe L4 - for example tcp */
diff --git a/include/types/server.h b/include/types/server.h
index aa2c4f8..1885eab 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -120,7 +120,8 @@ struct server {
 	int rise, fall;				/* time in iterations */
 	int consecutive_errors_limit;		/* number of consecutive errors that triggers an event */
 	short observe, onerror;			/* observing mode: one of HANA_OBS_*; what to do on error: on of ANA_ONERR_* */
-	short onmarkeddown;			/* what to do when marked down: on of HANA_ONMARKEDDOWN_* */
+	short onmarkeddown;			/* what to do when marked down: one of HANA_ONMARKEDDOWN_* */
+	short onmarkedup;			/* what to do when marked up: one of HANA_ONMARKEDUP_* */
 	int inter, fastinter, downinter;	/* checks: time in milliseconds */
 	int slowstart;				/* slowstart time in seconds (ms in the conf) */
 	int result;				/* health-check result : SRV_CHK_* */
diff --git a/include/types/session.h b/include/types/session.h
index f1b7451..a098002 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -67,6 +67,7 @@
 #define SN_ERR_INTERNAL	0x00007000	/* the proxy encountered an internal error */
 #define SN_ERR_DOWN	0x00008000	/* the proxy killed a session because the backend became unavailable */
 #define SN_ERR_KILLED	0x00009000	/* the proxy killed a session because it was asked to do so */
+#define SN_ERR_UP	0x0000a000	/* the proxy killed a session because a preferred backend became available */
 #define SN_ERR_MASK	0x0000f000	/* mask to get only session error flags */
 #define SN_ERR_SHIFT	12		/* bit shift */
 
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 5bd2cfc..92dd094 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -4392,6 +4392,18 @@ stats_error_parsing:
 
 				cur_arg += 2;
 			}
+			else if (!strcmp(args[cur_arg], "on-marked-up")) {
+				if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
+					newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
+				else {
+					Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
+						file, linenum, args[cur_arg], args[cur_arg + 1]);
+					err_code |= ERR_ALERT | ERR_FATAL;
+					goto out;
+				}
+
+				cur_arg += 2;
+			}
 			else if (!strcmp(args[cur_arg], "error-limit")) {
 				if (!*args[cur_arg + 1]) {
 					Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
diff --git a/src/checks.c b/src/checks.c
index febf77e..5299e98 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -358,15 +358,26 @@ static int check_for_pending(struct server *s)
 	return xferred;
 }
 
-/* Shutdown connections when their server goes down.
+/* Shutdown all connections of a server
  */
-static void shutdown_sessions(struct server *srv)
+static void shutdown_sessions(struct server *srv, int why)
 {
 	struct session *session, *session_bck;
 
 	list_for_each_entry_safe(session, session_bck, &srv->actconns, by_srv)
 		if (session->srv_conn == srv)
-			session_shutdown(session, SN_ERR_DOWN);
+			session_shutdown(session, why);
+}
+
+/* Shutdown all connections of all backup servers of a proxy
+ */
+static void shutdown_backup_sessions(struct proxy *px, int why)
+{
+	struct server *srv;
+
+	for (srv = px->srv; srv != NULL; srv = srv->next)
+		if (srv->state & SRV_BACKUP)
+			shutdown_sessions(srv, why);
 }
 
 /* Sets server <s> down, notifies by all available means, recounts the
@@ -394,7 +405,7 @@ void set_server_down(struct server *s)
 			s->proxy->lbprm.set_server_status_down(s);
 
 		if (s->onmarkeddown & HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS)
-			shutdown_sessions(s);
+			shutdown_sessions(s, SN_ERR_DOWN);
 
 		/* we might have sessions queued on this server and waiting for
 		 * a connection. Those which are redispatchable will be queued
@@ -465,6 +476,9 @@ void set_server_up(struct server *s) {
 		s->state |= SRV_RUNNING;
 		s->state &= ~SRV_MAINTAIN;
 
+		if (s->onmarkedup & HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS)
+			shutdown_backup_sessions(s->proxy, SN_ERR_UP);
+
 		if (s->slowstart > 0) {
 			s->state |= SRV_WARMINGUP;
 			if (s->proxy->lbprm.algo & BE_LB_PROP_DYN) {

Reply via email to