[Cluster-devel] [PATCH] rhel5 rgmanager: Pause during exit if we stopped services

Fabio M. Di Nitto fdinitto at redhat.com
Fri Apr 8 02:46:49 UTC 2011


ACK

On 04/07/2011 10:55 PM, Lon Hohberger wrote:
> A difference between rgmanager 1.9.x and later versions is that
> they rely on openais/corosync for messaging.  This messaging is
> quite reliable and has proved useful.
> 
> However, one drawback is that if you very quickly stop rgmanager
> and corosync/cman, the other nodes in the cluster can not restart
> services because message traffic is interrupted for the duration
> of the token timeout.
> 
> There is no simple solution to this problem.  Rgmanager could
> (in theory) find new placements for services prior to stopping,
> but this is a large amount of design work; it was never designed
> to run policies in the exit path.
> 
> A far simpler idea is to simply give the other nodes time to
> restart services.
> 
> NOTE: This solution does not and can not work with central
>       processing mode.
> 
> Resolves: rhbz#619468
> 
> Signed-off-by: Lon Hohberger <lhh at redhat.com>
> ---
>  rgmanager/include/event.h        |    1 +
>  rgmanager/include/resgroup.h     |    2 +-
>  rgmanager/src/daemons/groups.c   |   15 +++++++++++++--
>  rgmanager/src/daemons/main.c     |   14 ++++++++++++--
>  rgmanager/src/daemons/rg_event.c |    7 +++++++
>  5 files changed, 34 insertions(+), 5 deletions(-)
> 
> diff --git a/rgmanager/include/event.h b/rgmanager/include/event.h
> index 7e628d8..e63dffd 100644
> --- a/rgmanager/include/event.h
> +++ b/rgmanager/include/event.h
> @@ -136,6 +136,7 @@ int slang_process_event(event_table_t *event_table, event_t *ev);
>  
>  /* For distributed events. */
>  void set_transition_throttling(int nsecs);
> +int get_transition_throttling(void);
>  
>  /* Simplified service start. */
>  int service_op_start(char *svcName, int *target_list, int target_list_len,
> diff --git a/rgmanager/include/resgroup.h b/rgmanager/include/resgroup.h
> index 793ad3b..4be4dbc 100644
> --- a/rgmanager/include/resgroup.h
> +++ b/rgmanager/include/resgroup.h
> @@ -160,7 +160,7 @@ void send_ret(msgctx_t *ctx, char *name, int ret, int req, int newowner);
>  
>  /* do this op on all resource groups.  The handler for the request 
>     will sort out whether or not it's a valid request given the state */
> -void rg_doall(int request, int block, char *debugfmt);
> +int rg_doall(int request, int block, const char *debugfmt);
>  void do_status_checks(void); /* Queue status checks for locally running
>  				services */
>  
> diff --git a/rgmanager/src/daemons/groups.c b/rgmanager/src/daemons/groups.c
> index ecb7b85..b546421 100644
> --- a/rgmanager/src/daemons/groups.c
> +++ b/rgmanager/src/daemons/groups.c
> @@ -1292,12 +1292,21 @@ svc_exists(char *svcname)
>  }
>  
>  
> -void
> -rg_doall(int request, int block, char *debugfmt)
> +/*
> + * Perform an operation on all resources groups.
> + *
> + * Returns the number of requests queued.  This value is
> + * only used during shutdown, where we queue RG_STOP_EXITING
> + * only for services we have running locally as an optimization.
> + */
> +int
> +rg_doall(int request, int block,
> +	 const char *debugfmt)
>  {
>  	resource_node_t *curr;
>  	rg_state_t svcblk;
>  	char rg[64];
> +	int queued = 0;
>  
>  	pthread_rwlock_rdlock(&resource_lock);
>  	list_do(&_tree, curr) {
> @@ -1322,6 +1331,7 @@ rg_doall(int request, int block, char *debugfmt)
>  
>  		rt_enqueue_request(rg, request, NULL, 0,
>  				   0, 0, 0);
> +		++queued;
>  	} while (!list_done(&_tree, curr));
>  
>  	pthread_rwlock_unlock(&resource_lock);
> @@ -1331,6 +1341,7 @@ rg_doall(int request, int block, char *debugfmt)
>  	   other rgmanagers to complete. */
>  	if (block) 
>  		rg_wait_threads();
> +	return queued;
>  }
>  
>  
> diff --git a/rgmanager/src/daemons/main.c b/rgmanager/src/daemons/main.c
> index aa78cef..1c7f746 100644
> --- a/rgmanager/src/daemons/main.c
> +++ b/rgmanager/src/daemons/main.c
> @@ -72,6 +72,7 @@ static int signalled = 0;
>  static int port = RG_PORT;
>  static char *rgmanager_lsname = "rgmanager"; /* XXX default */
>  static int status_poll_interval = DEFAULT_CHECK_INTERVAL;
> +static int stops_queued = 0;
>  
>  int next_node_id(cluster_member_list_t *membership, int me);
>  
> @@ -1041,7 +1042,7 @@ void *
>  shutdown_thread(void __attribute__ ((unused)) *arg)
>  {
>  	rg_lockall(L_SYS|L_SHUTDOWN);
> -	rg_doall(RG_STOP_EXITING, 1, NULL);
> +	stops_queued = rg_doall(RG_STOP_EXITING, 1, NULL);
>  	running = 0;
>  
>  	pthread_exit(NULL);
> @@ -1219,8 +1220,17 @@ out_cleanup:
>  		clu_lock_finished(rgmanager_lsname);
>  
>  out:
> -	clulog(LOG_NOTICE, "Shutdown complete, exiting\n");
> +	clulog(LOG_DEBUG, "Stopped %d services\n", stops_queued);
> +	clulog(LOG_NOTICE, "Disconnecting from CMAN\n");
>  	cman_finish(clu);
> +
> +	if (stops_queued && !central_events_enabled()) {
> +		clulog(LOG_DEBUG, "Pausing to allow services to "
> +		       "start on other node(s)\n");
> +		sleep(get_transition_throttling() * 3);
> +	}
> +
> +	clulog(LOG_NOTICE, "Exiting\n");
>  	
>  	/*malloc_dump_table(); */ /* Only works if alloc.c us used */
>  	/*malloc_stats();*/
> diff --git a/rgmanager/src/daemons/rg_event.c b/rgmanager/src/daemons/rg_event.c
> index 82c20c0..606d41b 100644
> --- a/rgmanager/src/daemons/rg_event.c
> +++ b/rgmanager/src/daemons/rg_event.c
> @@ -69,6 +69,13 @@ set_transition_throttling(int nsecs)
>  }
>  
>  
> +int
> +get_transition_throttling(void)
> +{
> +	return transition_throttling;
> +}
> +
> +
>  void
>  set_central_events(int flag)
>  {




More information about the Cluster-devel mailing list