enum crmd_fsa_input last_input = I_NULL; enum crmd_fsa_input cur_input  = I_NULL;
s_crmd_fsa(enum crmd_fsa_cause cause){	time_t now;	fsa_data_t *fsa_data = NULL;	long long register_copy = fsa_input_register;	long long new_actions = A_NOTHING;	long long last_action = A_NOTHING;	enum crmd_fsa_input last_input = I_NULL;	enum crmd_fsa_input cur_input  = I_NULL;	enum crmd_fsa_input next_input = I_NULL;	enum crmd_fsa_state starting_state = fsa_state;	enum crmd_fsa_state last_state = starting_state;	enum crmd_fsa_state next_state = starting_state;		crm_debug_2("FSA invoked with Cause: %s\tState: %s",		    fsa_cause2string(cause),		    fsa_state2string(fsa_state));	/*	 * Process actions in order of priority but do only one	 * action at a time to avoid complicating the ordering.	 *	 * Actions may result in a new I_ event, these are added to	 * (not replace) existing actions before the next iteration.	 *	 */	do_fsa_stall = FALSE;	while(next_input != I_NULL || fsa_actions != A_NOTHING || is_message()){ 		msg_queue_helper();		if(do_fsa_stall) {			/* we may be waiting for an a-sync task to "happen"			 * and until it does, we cant do anything else			 */			crm_info("Wait until something else happens");			break;		} else if((is_message() && fsa_data == NULL)			  || (is_message() && fsa_actions == A_NOTHING && next_input == I_NULL)) {			fsa_data_t *stored_msg = NULL;			crm_debug_3("Finished with current input..."				  " Checking messages (%d remaining)",				  g_list_length(fsa_message_queue));			next_input = I_NULL;			stored_msg = get_message();			crm_debug("Processing queued input %d", stored_msg->id);						if(stored_msg == NULL) {				crm_crit("Invalid stored message");				exit(1);			}						delete_fsa_input(fsa_data);						if(stored_msg->fsa_cause == C_CCM_CALLBACK) {				crm_debug_3("FSA processing CCM callback from %s",					  stored_msg->origin);			} else if(stored_msg->fsa_cause == C_LRM_OP_CALLBACK) {				crm_debug_3("FSA processing LRM callback from %s",					  stored_msg->origin);			} else if(stored_msg->data == NULL) {				crm_debug_3("FSA processing input from %s",					  stored_msg->origin);							} else {				ha_msg_input_t *ha_input = fsa_typed_data_adv(					stored_msg, fsa_dt_ha_msg, __FUNCTION__);								crm_debug_3("FSA processing XML message from %s",					  stored_msg->origin);				crm_log_message(LOG_MSG, ha_input->msg);				crm_log_xml_debug_3(ha_input->xml,					      "FSA message data");			}			fsa_data = stored_msg;			/* set up the input */			next_input = fsa_data->fsa_input;			/* add any actions back to the queue */			fsa_actions |= fsa_data->actions;			/* update the cause */			cause = fsa_data->fsa_cause;			fsa_dump_actions(fsa_data->actions, "\tadded back");			do_dot_log(DOT_PREFIX"\t// FSA input: State=%s \tCause=%s"				" \tInput=%s \tOrigin=%s() \tid=%d",				fsa_state2string(fsa_state),				fsa_cause2string(fsa_data->fsa_cause),				fsa_input2string(fsa_data->fsa_input),				   fsa_data->origin, fsa_data->id);					} else if(fsa_data == NULL) {			crm_malloc0(fsa_data, sizeof(fsa_data_t));			fsa_data->fsa_input = I_NULL;			fsa_data->fsa_cause = cause;			fsa_data->actions   = A_NOTHING;			fsa_data->origin     = "s_crmd_fsa (enter)";			fsa_data->data      = NULL;			fsa_data->data_type = fsa_dt_none;			if(fsa_data->origin == NULL) {				crm_crit("Out of memory");				exit(1);			}					}				/* update input variables */		cur_input = next_input;		if(cur_input != I_NULL) {			/* record the most recent non I_NULL input */			crm_debug_3("Updating last_input to %s",				  fsa_input2string(cur_input));			last_input = cur_input;		}				/* get the next batch of actions */		new_actions = crmd_fsa_actions[cur_input][fsa_state];		if(new_actions != A_NOTHING) {#ifdef FSA_TRACE			crm_debug_2("Adding actions %.16llx for %s/%s",				    new_actions, fsa_input2string(cur_input),				    fsa_state2string(fsa_state));			fsa_dump_actions(new_actions, "\tscheduled");#endif			fsa_actions |= new_actions;		}		if(fsa_data == NULL) {			crm_err("No input for FSA.... terminating");			exit(1);		}#ifdef FSA_TRACE		crm_debug_2("FSA while loop:\tState: %s, Cause: %s,"			    " Input: %s, Origin=%s",			    fsa_state2string(crmd_fsa_state[cur_input][fsa_state]),			    fsa_cause2string(fsa_data->fsa_cause),			    fsa_input2string(cur_input),			    fsa_data->origin);#endif		/* logging : *before* the state is changed */		IF_FSA_ACTION(A_ERROR, do_log)		else IF_FSA_ACTION(A_WARN, do_log)		else IF_FSA_ACTION(A_LOG,  do_log)		/* this is always run, some inputs/states may make various		 * actions irrelevant/invalid		 */		fsa_actions = clear_flags(fsa_actions, cause, fsa_state, cur_input);		/* update state variables */		next_state  = crmd_fsa_state[cur_input][fsa_state];		last_state  = fsa_state;		fsa_state   = next_state;		/* start doing things... */		/*		 * Hook for change of state.		 * Allows actions to be added or removed when entering a state		 */		if(last_state != fsa_state){			fsa_actions = do_state_transition(				fsa_actions, cause, last_state, fsa_state,				cur_input, fsa_data);		}			/* regular action processing in order of action priority		 *		 * Make sure all actions that connect to required systems		 * are performed first		 */		/* get out of here NOW! before anything worse happens */		IF_FSA_ACTION(A_EXIT_1,		do_exit)		else IF_FSA_ACTION(A_ERROR, do_log)		else IF_FSA_ACTION(A_WARN, do_log)		else IF_FSA_ACTION(A_LOG,  do_log)		/* essential start tasks */		else IF_FSA_ACTION(A_HA_CONNECT,	do_ha_control)		else IF_FSA_ACTION(A_STARTUP,		do_startup)		else IF_FSA_ACTION(A_CIB_START,		do_cib_control)		else IF_FSA_ACTION(A_READCONFIG,	do_read_config)		/* sub-system start/connect */		else IF_FSA_ACTION(A_LRM_CONNECT,	do_lrm_control)		else IF_FSA_ACTION(A_CCM_CONNECT,	do_ccm_control)		else IF_FSA_ACTION(A_TE_START,		do_te_control)		else IF_FSA_ACTION(A_PE_START,		do_pe_control)				/* sub-system restart		 */		else IF_FSA_ACTION(O_CIB_RESTART,	do_cib_control)		else IF_FSA_ACTION(O_PE_RESTART,	do_pe_control)		else IF_FSA_ACTION(O_TE_RESTART,	do_te_control)				/* Timers *//* 		else IF_FSA_ACTION(O_DC_TIMER_RESTART,      do_timer_control) */		else IF_FSA_ACTION(A_DC_TIMER_STOP,         do_timer_control)		else IF_FSA_ACTION(A_INTEGRATE_TIMER_STOP,  do_timer_control)		else IF_FSA_ACTION(A_INTEGRATE_TIMER_START, do_timer_control)		else IF_FSA_ACTION(A_FINALIZE_TIMER_STOP,   do_timer_control)		else IF_FSA_ACTION(A_FINALIZE_TIMER_START,  do_timer_control)				/*		 * Highest priority actions		 */		else IF_FSA_ACTION(A_CIB_BUMPGEN,	do_cib_invoke)		else IF_FSA_ACTION(A_MSG_ROUTE,		do_msg_route)		else IF_FSA_ACTION(A_RECOVER,		do_recover)		else IF_FSA_ACTION(A_CL_JOIN_REQUEST,	do_cl_join_request)		else IF_FSA_ACTION(A_CL_JOIN_RESULT,	do_cl_join_result)		else IF_FSA_ACTION(A_SHUTDOWN_REQ,	do_shutdown_req)		else IF_FSA_ACTION(A_ELECTION_VOTE,	do_election_vote)		else IF_FSA_ACTION(A_ELECTION_COUNT,	do_election_count_vote)				/*		 * High priority actions		 * Update the cache first		 */		else IF_FSA_ACTION(A_CCM_UPDATE_CACHE,	do_ccm_update_cache)		else IF_FSA_ACTION(A_CCM_EVENT,		do_ccm_event)		else IF_FSA_ACTION(A_STARTED,		do_started)		else IF_FSA_ACTION(A_CL_JOIN_QUERY,     do_cl_join_query)		else IF_FSA_ACTION(A_DC_TIMER_START,    do_timer_control)				/*		 * Medium priority actions		 */		else IF_FSA_ACTION(A_DC_TAKEOVER,	 do_dc_takeover)		else IF_FSA_ACTION(A_DC_RELEASE,	 do_dc_release)		else IF_FSA_ACTION(A_ELECTION_START,	 do_election_vote)		else IF_FSA_ACTION(A_DC_JOIN_OFFER_ALL,	 do_dc_join_offer_all)		else IF_FSA_ACTION(A_DC_JOIN_OFFER_ONE,	 do_dc_join_offer_all)		else IF_FSA_ACTION(A_DC_JOIN_PROCESS_REQ,do_dc_join_req)		else IF_FSA_ACTION(A_DC_JOIN_PROCESS_ACK,do_dc_join_ack)				/*		 * Low(er) priority actions		 * Make sure the CIB is always updated before invoking the		 * PE, and the PE before the TE		 */		else IF_FSA_ACTION(A_CIB_INVOKE_LOCAL,	do_cib_invoke)		else IF_FSA_ACTION(A_CIB_INVOKE,	do_cib_invoke)		else IF_FSA_ACTION(A_DC_JOIN_FINALIZE,	do_dc_join_finalize)		else IF_FSA_ACTION(A_LRM_INVOKE,	do_lrm_invoke)		else IF_FSA_ACTION(A_LRM_EVENT,		do_lrm_event)		else IF_FSA_ACTION(A_TE_HALT,		do_te_invoke)		else IF_FSA_ACTION(A_TE_CANCEL,		do_te_invoke)		else IF_FSA_ACTION(A_PE_INVOKE,		do_pe_invoke)		else IF_FSA_ACTION(A_TE_INVOKE,		do_te_invoke)		else IF_FSA_ACTION(A_CL_JOIN_ANNOUNCE,	do_cl_join_announce)				/* sub-system stop */		else IF_FSA_ACTION(A_DC_RELEASED,	do_dc_release)		else IF_FSA_ACTION(A_PE_STOP,		do_pe_control)		else IF_FSA_ACTION(A_TE_STOP,		do_te_control)		else IF_FSA_ACTION(A_SHUTDOWN,		do_shutdown)		else IF_FSA_ACTION(A_STOP,		do_stop)		else IF_FSA_ACTION(A_CCM_DISCONNECT,	do_ccm_control)		else IF_FSA_ACTION(A_LRM_DISCONNECT,	do_lrm_control)		else IF_FSA_ACTION(A_HA_DISCONNECT,	do_ha_control)		else IF_FSA_ACTION(A_CIB_STOP,		do_cib_control)				/* exit gracefully */		else IF_FSA_ACTION(A_EXIT_0,	do_exit)/*		else IF_FSA_ACTION(A_, do_) */					/* Error checking and reporting */		else if(cur_input != I_NULL && fsa_actions == A_NOTHING) {			crm_debug(			       "No action specified for input,state (%s,%s)",			       fsa_input2string(cur_input),			       fsa_state2string(fsa_state));						next_input = I_NULL;					} else if(cur_input == I_NULL && fsa_actions == A_NOTHING) {#ifdef FSA_TRACE			crm_info("Nothing left to do...");			fsa_dump_actions(fsa_actions, "still here");#endif			break;					} else {			crm_err("Action %s (0x%llx) not supported ",			       fsa_action2string(fsa_actions), fsa_actions);			next_input = I_ERROR;		}	}		now = time(NULL);	do_dot_log(DOT_PREFIX"\t// ### Exiting the FSA (%s%s): %s",		  fsa_state2string(fsa_state), do_fsa_stall?": paused":"",		  asctime(localtime(&now)));	crm_debug("Exiting the FSA: is_message=%s, queue=%d, fsa_data=%p,"		  " fsa_actions=0x%llx, next_input=%s, stalled=%s",		  is_message()?"true":"false", g_list_length(fsa_message_queue),		  fsa_data, fsa_actions, fsa_input2string(next_input),		  do_fsa_stall?"true":"false");		/* cleanup inputs? */	delete_fsa_input(fsa_data);	if(register_copy != fsa_input_register) {		fsa_dump_inputs(LOG_DEBUG, fsa_input_register);	}		fsa_dump_queue(LOG_DEBUG_2);		return fsa_state;}