c2c8228d30
This commit does not have any functional or performance change. This change adds -std=c++11 compile option to Makefiles to enalbe using C++11 standard features. This change also cleans errors that c++11 standard complains: Werror=literal-suffix, e.g: "msg_seq=%"PRIi64"." error: invalid suffix on literal; C++11 requires a space between literal and identifier changed to: "msg_seq=%" PRIi64 "." Story: 2003493 Task: 24770 Change-Id: I0225a4326ff8320f36246cc5678698781e903617 Signed-off-by: Bin Qian <bin.qian@windriver.com>
2014 lines
72 KiB
C
2014 lines
72 KiB
C
//
|
|
// Copyright (c) 2014 Wind River Systems, Inc.
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
#include "sm_service_fsm.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "sm_limits.h"
|
|
#include "sm_types.h"
|
|
#include "sm_debug.h"
|
|
#include "sm_list.h"
|
|
#include "sm_selobj.h"
|
|
#include "sm_service_table.h"
|
|
#include "sm_service_engine.h"
|
|
#include "sm_service_initial_state.h"
|
|
#include "sm_service_unknown_state.h"
|
|
#include "sm_service_enabled_active_state.h"
|
|
#include "sm_service_enabled_go_standby_state.h"
|
|
#include "sm_service_enabled_go_active_state.h"
|
|
#include "sm_service_enabled_standby_state.h"
|
|
#include "sm_service_enabling_state.h"
|
|
#include "sm_service_enabling_throttle_state.h"
|
|
#include "sm_service_disabling_state.h"
|
|
#include "sm_service_disabled_state.h"
|
|
#include "sm_service_shutdown_state.h"
|
|
#include "sm_service_enable.h"
|
|
#include "sm_service_go_active.h"
|
|
#include "sm_service_go_standby.h"
|
|
#include "sm_service_disable.h"
|
|
#include "sm_service_audit.h"
|
|
#include "sm_service_heartbeat_api.h"
|
|
#include "sm_process_death.h"
|
|
#include "sm_log.h"
|
|
|
|
#define SM_SERVICE_FSM_PID_FILE_AUDIT_IN_MS 2000
|
|
|
|
static SmServiceHeartbeatCallbacksT _hb_callbacks;
|
|
static SmListT* _callbacks = NULL;
|
|
|
|
static SmErrorT sm_service_get_terminate_reason(SmServiceT* service,
|
|
char reason_text[], int len);
|
|
|
|
static bool remove_pid_file(char pid_file[]);
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Register Callback
|
|
// ===============================
|
|
SmErrorT sm_service_fsm_register_callback( SmServiceFsmCallbackT callback )
|
|
{
|
|
SM_LIST_PREPEND( _callbacks, (SmListEntryDataPtrT) callback );
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Deregister Callback
|
|
// =================================
|
|
SmErrorT sm_service_fsm_deregister_callback( SmServiceFsmCallbackT callback )
|
|
{
|
|
SM_LIST_REMOVE( _callbacks, (SmListEntryDataPtrT) callback );
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Notify
|
|
// ====================
|
|
static void sm_service_fsm_notify( SmServiceT* service )
|
|
{
|
|
SmListT* entry = NULL;
|
|
SmListEntryDataPtrT entry_data;
|
|
SmServiceFsmCallbackT callback;
|
|
|
|
SM_LIST_FOREACH( _callbacks, entry, entry_data )
|
|
{
|
|
callback = (SmServiceFsmCallbackT) entry_data;
|
|
|
|
callback( service->name, service->state, service->status,
|
|
service->condition );
|
|
}
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Fail Countdown Timeout
|
|
// ====================================
|
|
static bool sm_service_fsm_fail_countdown_timeout( SmTimerIdT timer_id,
|
|
int64_t user_data )
|
|
{
|
|
int64_t id = user_data;
|
|
SmServiceT* service;
|
|
|
|
service = sm_service_table_read_by_id( id );
|
|
if( NULL == service )
|
|
{
|
|
DPRINTFE( "Failed to read service, error=%s.",
|
|
sm_error_str(SM_NOT_FOUND) );
|
|
return( true );
|
|
}
|
|
|
|
if(( 0 < service->fail_count )&&
|
|
( SM_SERVICE_STATUS_FAILED != service->status ))
|
|
{
|
|
service->fail_count -= service->fail_countdown;
|
|
if( 0 > service->fail_count )
|
|
{
|
|
service->fail_count = 0;
|
|
|
|
DPRINTFI( "Fail count for service (%s) reset.",
|
|
service->name );
|
|
}
|
|
}
|
|
|
|
return( true );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Start Fail Countdown Timer
|
|
// ========================================
|
|
SmErrorT sm_service_fsm_start_fail_countdown_timer( SmServiceT* service )
|
|
{
|
|
char timer_name[80] = "";
|
|
SmTimerIdT fail_countdown_timer_id;
|
|
SmErrorT error;
|
|
|
|
DPRINTFD( "Start fail countdown timer for service (%s).", service->name );
|
|
|
|
snprintf( timer_name, sizeof(timer_name), "%s fail countdown",
|
|
service->name );
|
|
|
|
error = sm_timer_register( timer_name,
|
|
service->fail_countdown_interval_in_ms,
|
|
sm_service_fsm_fail_countdown_timeout,
|
|
service->id, &fail_countdown_timer_id );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to create fail countdown timer for "
|
|
"service (%s), error=%s.", service->name,
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
service->fail_countdown_timer_id = fail_countdown_timer_id;
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Stop Fail Countdown Timer
|
|
// =======================================
|
|
SmErrorT sm_service_fsm_stop_fail_countdown_timer( SmServiceT* service )
|
|
{
|
|
SmErrorT error;
|
|
|
|
DPRINTFD( "Stop fail countdown timer for service (%s).", service->name );
|
|
|
|
if( SM_TIMER_ID_INVALID != service->fail_countdown_timer_id )
|
|
{
|
|
error = sm_timer_deregister( service->fail_countdown_timer_id );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to cancel fail countdown timer for "
|
|
"service (%s), error=%s.", service->name,
|
|
sm_error_str( error ) );
|
|
}
|
|
|
|
service->fail_countdown_timer_id = SM_TIMER_ID_INVALID;
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Enter State
|
|
// =========================
|
|
static SmErrorT sm_service_fsm_enter_state( SmServiceT* service )
|
|
{
|
|
SmErrorT error;
|
|
|
|
switch( service->state )
|
|
{
|
|
case SM_SERVICE_STATE_INITIAL:
|
|
error = sm_service_initial_state_entry( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to enter state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_UNKNOWN:
|
|
error = sm_service_unknown_state_entry( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to enter state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_ACTIVE:
|
|
error = sm_service_enabled_active_state_entry( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to enter state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_GO_ACTIVE:
|
|
error = sm_service_enabled_go_active_state_entry( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to enter state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_GO_STANDBY:
|
|
error = sm_service_enabled_go_standby_state_entry( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to enter state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_STANDBY:
|
|
error = sm_service_enabled_standby_state_entry( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to enter state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
|
|
case SM_SERVICE_STATE_ENABLING_THROTTLE:
|
|
error = sm_service_enabling_throttle_state_entry( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to enter state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLING:
|
|
error = sm_service_enabling_state_entry( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to enter state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_DISABLING:
|
|
error = sm_service_disabling_state_entry( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to enter state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_DISABLED:
|
|
error = sm_service_disabled_state_entry( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to enter state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_SHUTDOWN:
|
|
error = sm_service_shutdown_state_entry( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to enter state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DPRINTFE( "Unknown service (%s) state (%s).", service->name,
|
|
sm_service_state_str( service->state ) );
|
|
break;
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Exit State
|
|
// ========================
|
|
static SmErrorT sm_service_fsm_exit_state( SmServiceT* service )
|
|
{
|
|
SmErrorT error;
|
|
|
|
switch( service->state )
|
|
{
|
|
case SM_SERVICE_STATE_INITIAL:
|
|
error = sm_service_initial_state_exit( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to exit state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_UNKNOWN:
|
|
error = sm_service_unknown_state_exit( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to exit state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_ACTIVE:
|
|
error = sm_service_enabled_active_state_exit( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to exit state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_GO_ACTIVE:
|
|
error = sm_service_enabled_go_active_state_exit( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to exit state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_GO_STANDBY:
|
|
error = sm_service_enabled_go_standby_state_exit( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to exit state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_STANDBY:
|
|
error = sm_service_enabled_standby_state_exit( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to exit state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLING_THROTTLE:
|
|
error = sm_service_enabling_throttle_state_exit( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to exit state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLING:
|
|
error = sm_service_enabling_state_exit( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to exit state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_DISABLING:
|
|
error = sm_service_disabling_state_exit( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to exit state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_DISABLED:
|
|
error = sm_service_disabled_state_exit( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to exit state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_SHUTDOWN:
|
|
error = sm_service_shutdown_state_exit( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to exit state (%s), error=%s.",
|
|
service->name, sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DPRINTFE( "Unknown service (%s) state (%s).", service->name,
|
|
sm_service_state_str( service->state ) );
|
|
break;
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Transition State
|
|
// ==============================
|
|
static SmErrorT sm_service_fsm_transition_state( SmServiceT* service,
|
|
SmServiceStateT from_state )
|
|
{
|
|
SmErrorT error;
|
|
|
|
switch( service->state )
|
|
{
|
|
case SM_SERVICE_STATE_INITIAL:
|
|
error = sm_service_initial_state_transition( service, from_state );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to transition from state (%s) "
|
|
"to state (%s), error=%s.", service->name,
|
|
sm_service_state_str( from_state ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_UNKNOWN:
|
|
error = sm_service_unknown_state_transition( service, from_state );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to transition from state (%s) "
|
|
"to state (%s), error=%s.", service->name,
|
|
sm_service_state_str( from_state ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_ACTIVE:
|
|
error = sm_service_enabled_active_state_transition( service,
|
|
from_state );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to transition from state (%s) "
|
|
"to state (%s), error=%s.", service->name,
|
|
sm_service_state_str( from_state ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_GO_ACTIVE:
|
|
error = sm_service_enabled_go_active_state_transition( service,
|
|
from_state );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to transition from state (%s) "
|
|
"to state (%s), error=%s.", service->name,
|
|
sm_service_state_str( from_state ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_GO_STANDBY:
|
|
error = sm_service_enabled_go_standby_state_transition( service,
|
|
from_state );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to transition from state (%s) "
|
|
"to state (%s), error=%s.", service->name,
|
|
sm_service_state_str( from_state ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_STANDBY:
|
|
error = sm_service_enabled_standby_state_transition( service,
|
|
from_state );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to transition from state (%s) "
|
|
"to state (%s), error=%s.", service->name,
|
|
sm_service_state_str( from_state ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLING_THROTTLE:
|
|
error = sm_service_enabling_throttle_state_transition( service, from_state );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to transition from state (%s) "
|
|
"to state (%s), error=%s.", service->name,
|
|
sm_service_state_str( from_state ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLING:
|
|
error = sm_service_enabling_state_transition( service, from_state );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to transition from state (%s) "
|
|
"to state (%s), error=%s.", service->name,
|
|
sm_service_state_str( from_state ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_DISABLING:
|
|
error = sm_service_disabling_state_transition( service, from_state );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to transition from state (%s) "
|
|
"to state (%s), error=%s.", service->name,
|
|
sm_service_state_str( from_state ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_DISABLED:
|
|
error = sm_service_disabled_state_transition( service, from_state );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to transition from state (%s) "
|
|
"to state (%s), error=%s.", service->name,
|
|
sm_service_state_str( from_state ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_SHUTDOWN:
|
|
error = sm_service_shutdown_state_transition( service, from_state );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to transition from state (%s) "
|
|
"to state (%s), error=%s.", service->name,
|
|
sm_service_state_str( from_state ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DPRINTFE( "Unknown service (%s) state (%s).", service->name,
|
|
sm_service_state_str( service->state ) );
|
|
break;
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Set State
|
|
// =======================
|
|
SmErrorT sm_service_fsm_set_state( SmServiceT* service, SmServiceStateT state )
|
|
{
|
|
SmServiceStateT prev_state;
|
|
SmErrorT error, error2;
|
|
|
|
prev_state = service->state;
|
|
|
|
error = sm_service_fsm_exit_state( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to exit state (%s) service (%s), error=%s.",
|
|
sm_service_state_str( service->state ),
|
|
service->name, sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
service->state = state;
|
|
|
|
error = sm_service_fsm_transition_state( service, prev_state );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to transition to state (%s) service (%s), "
|
|
"error=%s.", sm_service_state_str( service->state ),
|
|
service->name, sm_error_str( error ) );
|
|
goto STATE_CHANGE_ERROR;
|
|
}
|
|
|
|
error = sm_service_fsm_enter_state( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to enter state (%s) service (%s), error=%s.",
|
|
sm_service_state_str( service->state ),
|
|
service->name, sm_error_str( error ) );
|
|
goto STATE_CHANGE_ERROR;
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
|
|
STATE_CHANGE_ERROR:
|
|
error2 = sm_service_fsm_exit_state( service );
|
|
if( SM_OKAY != error2 )
|
|
{
|
|
DPRINTFE( "Failed to exit state (%s) service (%s), error=%s.",
|
|
sm_service_state_str( service->state ),
|
|
service->name, sm_error_str( error2 ) );
|
|
abort();
|
|
}
|
|
|
|
service->state = prev_state;
|
|
|
|
error2 = sm_service_fsm_transition_state( service, state );
|
|
if( SM_OKAY != error2 )
|
|
{
|
|
DPRINTFE( "Failed to transition to state (%s) service (%s), "
|
|
"error=%s.", sm_service_state_str( service->state ),
|
|
service->name, sm_error_str( error2 ) );
|
|
abort();
|
|
}
|
|
|
|
error2 = sm_service_fsm_enter_state( service );
|
|
if( SM_OKAY != error2 )
|
|
{
|
|
DPRINTFE( "Failed to enter state (%s) service (%s), error=%s.",
|
|
sm_service_state_str( service->state ),
|
|
service->name, sm_error_str( error2 ) );
|
|
abort();
|
|
}
|
|
|
|
return( error );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Set Status
|
|
// ========================
|
|
SmErrorT sm_service_fsm_set_status( SmServiceT* service,
|
|
SmServiceStatusT status, SmServiceConditionT condition )
|
|
{
|
|
bool persist = false;
|
|
|
|
switch( status )
|
|
{
|
|
case SM_SERVICE_STATUS_NIL:
|
|
case SM_SERVICE_STATUS_UNKNOWN:
|
|
// Ignore.
|
|
break;
|
|
|
|
case SM_SERVICE_STATUS_NONE:
|
|
service->status = SM_SERVICE_STATUS_NONE;
|
|
service->condition = SM_SERVICE_CONDITION_NONE;
|
|
persist = true;
|
|
break;
|
|
|
|
case SM_SERVICE_STATUS_WARN:
|
|
if(( SM_SERVICE_STATUS_DEGRADED != service->status )&&
|
|
( SM_SERVICE_STATUS_FAILED != service->status ))
|
|
{
|
|
service->status = status;
|
|
|
|
if(( SM_SERVICE_CONDITION_NIL != condition )&&
|
|
( SM_SERVICE_CONDITION_UNKNOWN != condition ))
|
|
{
|
|
service->condition = condition;
|
|
} else {
|
|
service->condition = SM_SERVICE_CONDITION_NONE;
|
|
}
|
|
persist = true;
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATUS_DEGRADED:
|
|
if( SM_SERVICE_STATUS_FAILED != service->status )
|
|
{
|
|
service->status = status;
|
|
|
|
if(( SM_SERVICE_CONDITION_NIL != condition )&&
|
|
( SM_SERVICE_CONDITION_UNKNOWN != condition ))
|
|
{
|
|
service->condition = condition;
|
|
} else {
|
|
service->condition = SM_SERVICE_CONDITION_NONE;
|
|
}
|
|
persist = true;
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATUS_FAILED:
|
|
service->status = status;
|
|
|
|
if(( SM_SERVICE_CONDITION_NIL != condition )&&
|
|
( SM_SERVICE_CONDITION_UNKNOWN != condition ))
|
|
{
|
|
service->condition = condition;
|
|
} else {
|
|
service->condition = SM_SERVICE_CONDITION_NONE;
|
|
}
|
|
persist = true;
|
|
break;
|
|
|
|
default:
|
|
DPRINTFE( "Uknown status (%i) for service (%s) given.", status,
|
|
service->name );
|
|
break;
|
|
}
|
|
|
|
if( persist )
|
|
{
|
|
SmErrorT error;
|
|
|
|
error = sm_service_table_persist( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to persist service (%s) data, error=%s.",
|
|
service->name, sm_error_str(error) );
|
|
return( error );
|
|
}
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Event Handler
|
|
// ===========================
|
|
SmErrorT sm_service_fsm_event_handler( char service_name[],
|
|
SmServiceEventT event, void* event_data[], const char reason_text[] )
|
|
{
|
|
SmServiceStateT prev_state;
|
|
SmServiceStatusT prev_status;
|
|
SmServiceConditionT prev_condition;
|
|
SmServiceT* service;
|
|
SmErrorT error;
|
|
|
|
service = sm_service_table_read( service_name );
|
|
if( NULL == service )
|
|
{
|
|
DPRINTFE( "Failed to read service (%s), error=%s.",
|
|
service_name, sm_error_str(SM_NOT_FOUND) );
|
|
return( SM_NOT_FOUND );
|
|
}
|
|
|
|
prev_state = service->state;
|
|
prev_status = service->status;
|
|
prev_condition = service->condition;
|
|
|
|
if( NULL != event_data )
|
|
{
|
|
if( NULL != event_data[SM_SERVICE_EVENT_DATA_IS_ACTION] )
|
|
{
|
|
bool is_action = *(bool*) event_data[SM_SERVICE_EVENT_DATA_IS_ACTION];
|
|
|
|
if( is_action )
|
|
{
|
|
SmServiceStatusT action_status;
|
|
SmServiceConditionT action_condition;
|
|
|
|
action_status = *(SmServiceStatusT*)
|
|
event_data[SM_SERVICE_EVENT_DATA_STATUS];
|
|
action_condition = *(SmServiceConditionT*)
|
|
event_data[SM_SERVICE_EVENT_DATA_CONDITION];
|
|
|
|
error = sm_service_fsm_set_status( service, action_status,
|
|
action_condition );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to set status (%s) and condition (%s) "
|
|
"of service (%s), error=%s.",
|
|
sm_service_status_str(action_status),
|
|
sm_service_condition_str(action_condition),
|
|
service->name, sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
switch( service->state )
|
|
{
|
|
case SM_SERVICE_STATE_INITIAL:
|
|
error = sm_service_initial_state_event_handler( service, event,
|
|
event_data );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to handle event (%s) "
|
|
"in state (%s), error=%s.", service_name,
|
|
sm_service_event_str( event ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_UNKNOWN:
|
|
error = sm_service_unknown_state_event_handler( service, event,
|
|
event_data );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to handle event (%s) "
|
|
"in state (%s), error=%s.", service_name,
|
|
sm_service_event_str( event ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_ACTIVE:
|
|
error = sm_service_enabled_active_state_event_handler( service,
|
|
event, event_data );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to handle event (%s) "
|
|
"in state (%s), error=%s.", service_name,
|
|
sm_service_event_str( event ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_GO_ACTIVE:
|
|
error = sm_service_enabled_go_active_state_event_handler( service,
|
|
event, event_data );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to handle event (%s) "
|
|
"in state (%s), error=%s.", service_name,
|
|
sm_service_event_str( event ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_GO_STANDBY:
|
|
error = sm_service_enabled_go_standby_state_event_handler( service,
|
|
event, event_data );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to handle event (%s) "
|
|
"in state (%s), error=%s.", service_name,
|
|
sm_service_event_str( event ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_STANDBY:
|
|
error = sm_service_enabled_standby_state_event_handler( service,
|
|
event, event_data );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to handle event (%s) "
|
|
"in state (%s), error=%s.", service_name,
|
|
sm_service_event_str( event ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLING_THROTTLE:
|
|
error = sm_service_enabling_throttle_state_event_handler( service, event,
|
|
event_data );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to handle event (%s) "
|
|
"in state (%s), error=%s.", service_name,
|
|
sm_service_event_str( event ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLING:
|
|
error = sm_service_enabling_state_event_handler( service, event,
|
|
event_data );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to handle event (%s) "
|
|
"in state (%s), error=%s.", service_name,
|
|
sm_service_event_str( event ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
|
|
case SM_SERVICE_STATE_DISABLING:
|
|
error = sm_service_disabling_state_event_handler( service, event,
|
|
event_data );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to handle event (%s) "
|
|
"in state (%s), error=%s.", service_name,
|
|
sm_service_event_str( event ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_DISABLED:
|
|
error = sm_service_disabled_state_event_handler( service, event,
|
|
event_data );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to handle event (%s) "
|
|
"in state (%s), error=%s.", service_name,
|
|
sm_service_event_str( event ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_SHUTDOWN:
|
|
error = sm_service_shutdown_state_event_handler( service, event,
|
|
event_data );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Service (%s) unable to handle event (%s) "
|
|
"in state (%s), error=%s.", service_name,
|
|
sm_service_event_str( event ),
|
|
sm_service_state_str( service->state ),
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DPRINTFE( "Unknown state (%s) for service (%s).",
|
|
sm_service_state_str( service->state ),
|
|
service_name );
|
|
break;
|
|
}
|
|
|
|
if(( prev_state != service->state )||( prev_status != service->status )||
|
|
( prev_condition != service->condition ))
|
|
{
|
|
DPRINTFI( "Service (%s) received event (%s) was in the %s%s%s state "
|
|
"and is now in the %s%s%s state%s%s.",
|
|
service_name,
|
|
sm_service_event_str( event ),
|
|
sm_service_state_str( prev_state ),
|
|
SM_SERVICE_STATUS_NONE == prev_status
|
|
? "" : "-",
|
|
SM_SERVICE_STATUS_NONE == prev_status
|
|
? "" : sm_service_status_str( prev_status ),
|
|
sm_service_state_str( service->state ),
|
|
SM_SERVICE_STATUS_NONE == service->status
|
|
? "" : "-",
|
|
SM_SERVICE_STATUS_NONE == service->status
|
|
? "" : sm_service_status_str( service->status ),
|
|
SM_SERVICE_CONDITION_NONE == service->condition
|
|
? "" : ", condition=",
|
|
SM_SERVICE_CONDITION_NONE == service->condition
|
|
? "" : sm_service_condition_str( service->condition ) );
|
|
|
|
error = sm_service_table_persist( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to persist service (%s) data, error=%s.",
|
|
service->name, sm_error_str(error) );
|
|
return( error );
|
|
}
|
|
|
|
if(( prev_state != service->state )||( prev_status != service->status ))
|
|
{
|
|
sm_log_service_state_change( service_name,
|
|
sm_service_state_str( prev_state ),
|
|
sm_service_status_str( prev_status ),
|
|
sm_service_state_str( service->state ),
|
|
sm_service_status_str( service->status ),
|
|
reason_text );
|
|
}
|
|
|
|
sm_service_fsm_notify( service );
|
|
|
|
if( prev_state != service->state )
|
|
{
|
|
error = sm_service_engine_signal( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to signal service (%s), error=%s.",
|
|
service_name, sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
}
|
|
} else if( SM_SERVICE_EVENT_AUDIT == event ) {
|
|
if(( SM_SERVICE_STATE_ENABLED_ACTIVE == service->state )||
|
|
( SM_SERVICE_STATE_ENABLED_STANDBY == service->state )||
|
|
( SM_SERVICE_STATE_DISABLED == service->state ))
|
|
{
|
|
sm_service_fsm_notify( service );
|
|
}
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Action Complete Handler
|
|
// =====================================
|
|
SmErrorT sm_service_fsm_action_complete_handler( char service_name[],
|
|
SmServiceActionT action, SmServiceActionResultT action_result,
|
|
SmServiceStateT state, SmServiceStatusT status,
|
|
SmServiceConditionT condition, const char reason_text[] )
|
|
{
|
|
bool is_action = true;
|
|
SmServiceT* service;
|
|
SmServiceEventT event = SM_SERVICE_EVENT_UNKNOWN;
|
|
void* event_data[SM_SERVICE_EVENT_DATA_MAX] = {0};
|
|
char event_reason_text[SM_LOG_REASON_TEXT_MAX_CHAR] = "";
|
|
SmErrorT error;
|
|
|
|
service = sm_service_table_read( service_name );
|
|
if( NULL == service )
|
|
{
|
|
DPRINTFE( "Failed to read service (%s), error=%s.",
|
|
service_name, sm_error_str(SM_NOT_FOUND) );
|
|
return( SM_NOT_FOUND );
|
|
}
|
|
|
|
event_data[SM_SERVICE_EVENT_DATA_IS_ACTION] = &is_action;
|
|
event_data[SM_SERVICE_EVENT_DATA_STATE] = &state;
|
|
event_data[SM_SERVICE_EVENT_DATA_STATUS] = &status;
|
|
event_data[SM_SERVICE_EVENT_DATA_CONDITION] = &condition;
|
|
|
|
switch( action )
|
|
{
|
|
case SM_SERVICE_ACTION_ENABLE:
|
|
switch( action_result )
|
|
{
|
|
case SM_SERVICE_ACTION_RESULT_SUCCESS:
|
|
event = SM_SERVICE_EVENT_ENABLE_SUCCESS;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"enable success" );
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_FATAL:
|
|
event = SM_SERVICE_EVENT_SHUTDOWN;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"enable fatal, shutting down" );
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_FAILED:
|
|
event = SM_SERVICE_EVENT_ENABLE_FAILED;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"enable failed" );
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_TIMEOUT:
|
|
event = SM_SERVICE_EVENT_ENABLE_TIMEOUT;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"enable timeout" );
|
|
break;
|
|
|
|
default:
|
|
DPRINTFE( "Unknown action result (%s) for action (%s) of "
|
|
"service (%s).",
|
|
sm_service_action_result_str( action_result ),
|
|
sm_service_action_str( action ), service_name );
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_GO_ACTIVE:
|
|
switch( action_result )
|
|
{
|
|
case SM_SERVICE_ACTION_RESULT_SUCCESS:
|
|
event = SM_SERVICE_EVENT_GO_ACTIVE_SUCCESS;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"go-active success" );
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_FATAL:
|
|
event = SM_SERVICE_EVENT_SHUTDOWN;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"go-active fatal, shutting down" );
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_FAILED:
|
|
event = SM_SERVICE_EVENT_GO_ACTIVE_FAILED;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"go-active failed" );
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_TIMEOUT:
|
|
event = SM_SERVICE_EVENT_GO_ACTIVE_TIMEOUT;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"go-active timeout" );
|
|
break;
|
|
|
|
default:
|
|
DPRINTFE( "Unknown action result (%s) for action (%s) of "
|
|
"service (%s).",
|
|
sm_service_action_result_str( action_result ),
|
|
sm_service_action_str( action ), service_name );
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_GO_STANDBY:
|
|
switch( action_result )
|
|
{
|
|
case SM_SERVICE_ACTION_RESULT_SUCCESS:
|
|
event = SM_SERVICE_EVENT_GO_STANDBY_SUCCESS;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"go-standby success" );
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_FATAL:
|
|
event = SM_SERVICE_EVENT_SHUTDOWN;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"go-standy fatal, shutting down" );
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_FAILED:
|
|
event = SM_SERVICE_EVENT_GO_STANDBY_FAILED;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"go-standby failed" );
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_TIMEOUT:
|
|
event = SM_SERVICE_EVENT_GO_STANDBY_TIMEOUT;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"go-standby timeout" );
|
|
break;
|
|
|
|
default:
|
|
DPRINTFE( "Unknown action result (%s) for action (%s) of "
|
|
"service (%s).",
|
|
sm_service_action_result_str( action_result ),
|
|
sm_service_action_str( action ), service_name );
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_DISABLE:
|
|
switch( action_result )
|
|
{
|
|
case SM_SERVICE_ACTION_RESULT_SUCCESS:
|
|
event = SM_SERVICE_EVENT_DISABLE_SUCCESS;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"disable success" );
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_FATAL:
|
|
event = SM_SERVICE_EVENT_SHUTDOWN;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"disable fatal, shutting down" );
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_FAILED:
|
|
event = SM_SERVICE_EVENT_DISABLE_FAILED;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"disable failed" );
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_TIMEOUT:
|
|
event = SM_SERVICE_EVENT_DISABLE_TIMEOUT;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"disable timeout" );
|
|
break;
|
|
|
|
default:
|
|
DPRINTFE( "Unknown action result (%s) for action (%s) of "
|
|
"service (%s).",
|
|
sm_service_action_result_str( action_result ),
|
|
sm_service_action_str( action ), service_name );
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_AUDIT_ENABLED:
|
|
case SM_SERVICE_ACTION_AUDIT_DISABLED:
|
|
switch( action_result )
|
|
{
|
|
case SM_SERVICE_ACTION_RESULT_SUCCESS:
|
|
switch( service->state )
|
|
{
|
|
case SM_SERVICE_STATE_INITIAL:
|
|
case SM_SERVICE_STATE_UNKNOWN:
|
|
event = SM_SERVICE_EVENT_AUDIT_SUCCESS;
|
|
snprintf( event_reason_text,
|
|
sizeof(event_reason_text),
|
|
"audit success" );
|
|
break;
|
|
|
|
case SM_SERVICE_STATE_ENABLED_GO_STANDBY:
|
|
if( SM_SERVICE_STATE_ENABLED_ACTIVE == state )
|
|
{
|
|
event = SM_SERVICE_EVENT_AUDIT_SUCCESS;
|
|
snprintf( event_reason_text,
|
|
sizeof(event_reason_text),
|
|
"audit success" );
|
|
} else {
|
|
event = SM_SERVICE_EVENT_AUDIT_MISMATCH;
|
|
snprintf( event_reason_text,
|
|
sizeof(event_reason_text),
|
|
"audit state mismatch" );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if( state == service->state )
|
|
{
|
|
event = SM_SERVICE_EVENT_AUDIT_SUCCESS;
|
|
snprintf( event_reason_text,
|
|
sizeof(event_reason_text),
|
|
"audit success" );
|
|
} else {
|
|
event = SM_SERVICE_EVENT_AUDIT_MISMATCH;
|
|
snprintf( event_reason_text,
|
|
sizeof(event_reason_text),
|
|
"audit state mismatch" );
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_FATAL:
|
|
event = SM_SERVICE_EVENT_SHUTDOWN;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"audit fatal, shutting down" );
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_FAILED:
|
|
event = SM_SERVICE_EVENT_AUDIT_FAILED;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"audit failed" );
|
|
break;
|
|
|
|
case SM_SERVICE_ACTION_RESULT_TIMEOUT:
|
|
event = SM_SERVICE_EVENT_AUDIT_TIMEOUT;
|
|
snprintf( event_reason_text, sizeof(event_reason_text),
|
|
"audit timeout" );
|
|
break;
|
|
|
|
default:
|
|
DPRINTFE( "Unknown action result (%s) for action (%s) of "
|
|
"service (%s).",
|
|
sm_service_action_result_str( action_result ),
|
|
sm_service_action_str( action ), service_name );
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DPRINTFE( "Unknown action (%s) for service (%s).",
|
|
sm_service_action_str( action ), service_name );
|
|
break;
|
|
}
|
|
|
|
if( SM_SERVICE_EVENT_UNKNOWN != event )
|
|
{
|
|
error = sm_service_fsm_event_handler( service_name, event,
|
|
event_data, event_reason_text );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Event (%s) not handled for service (%s).",
|
|
sm_service_event_str( event ), service_name );
|
|
return( error );
|
|
}
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Heartbeat Okay Callback
|
|
// ========================================
|
|
static void sm_service_fsm_heartbeat_okay_callback( char service_name[] )
|
|
{
|
|
SmServiceEventT event = SM_SERVICE_EVENT_HEARTBEAT_OKAY;
|
|
SmErrorT error;
|
|
|
|
DPRINTFI( "Service (%s) heartbeat okay.", service_name );
|
|
|
|
error = sm_service_fsm_event_handler( service_name, event, NULL,
|
|
"heartbeat okay" );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Event (%s) not handled for service (%s).",
|
|
sm_service_event_str( event ), service_name );
|
|
return;
|
|
}
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Heartbeat Warning Callback
|
|
// ========================================
|
|
static void sm_service_fsm_heartbeat_warn_callback( char service_name[] )
|
|
{
|
|
SmServiceEventT event = SM_SERVICE_EVENT_HEARTBEAT_WARN;
|
|
SmErrorT error;
|
|
|
|
DPRINTFI( "Service (%s) heartbeat warning.", service_name );
|
|
|
|
error = sm_service_fsm_event_handler( service_name, event, NULL,
|
|
"heartbeat warning threshold crossed" );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Event (%s) not handled for service (%s).",
|
|
sm_service_event_str( event ), service_name );
|
|
return;
|
|
}
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Heartbeat Degrade Callback
|
|
// ========================================
|
|
static void sm_service_fsm_heartbeat_degrade_callback( char service_name[] )
|
|
{
|
|
SmServiceEventT event = SM_SERVICE_EVENT_HEARTBEAT_DEGRADE;
|
|
SmErrorT error;
|
|
|
|
DPRINTFI( "Service (%s) heartbeat degrade.", service_name );
|
|
|
|
error = sm_service_fsm_event_handler( service_name, event, NULL,
|
|
"heartbeat degrade threshold crossed" );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Event (%s) not handled for service (%s).",
|
|
sm_service_event_str( event ), service_name );
|
|
return;
|
|
}
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Heartbeat Failure Callback
|
|
// ========================================
|
|
static void sm_service_fsm_heartbeat_fail_callback( char service_name[] )
|
|
{
|
|
SmServiceEventT event = SM_SERVICE_EVENT_HEARTBEAT_FAIL;
|
|
SmErrorT error;
|
|
|
|
DPRINTFI( "Service (%s) heartbeat failure.", service_name );
|
|
|
|
error = sm_service_fsm_event_handler( service_name, event, NULL,
|
|
"heartbeat failure" );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Event (%s) not handled for service (%s).",
|
|
sm_service_event_str( event ), service_name );
|
|
return;
|
|
}
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Process Failure Callback
|
|
// ======================================
|
|
static void sm_service_fsm_process_failure_callback( pid_t pid, int exit_code,
|
|
int64_t user_data )
|
|
{
|
|
char reason_text[SM_LOG_REASON_TEXT_MAX_CHAR] = "";
|
|
SmServiceT* service;
|
|
SmServiceEventT event = SM_SERVICE_EVENT_PROCESS_FAILURE;
|
|
SmErrorT error;
|
|
|
|
service = sm_service_table_read_by_pid( (int) pid );
|
|
if( NULL == service )
|
|
{
|
|
DPRINTFE( "Failed to read service based on pid (%" PRIu64 "), error=%s.",
|
|
user_data, sm_error_str(SM_NOT_FOUND) );
|
|
return;
|
|
}
|
|
|
|
DPRINTFI( "Service (%s) process failure, pid=%i, exit_code=%i.",
|
|
service->name, (int) pid, exit_code );
|
|
|
|
sm_service_get_terminate_reason(service, reason_text, sizeof(reason_text));
|
|
|
|
error = sm_service_fsm_event_handler( service->name, event, NULL,
|
|
reason_text );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Event (%s) not handled for service (%s).",
|
|
sm_service_event_str( event ), service->name );
|
|
return;
|
|
}
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Process Audit PID File Timer
|
|
// ==========================================
|
|
static bool sm_service_fsm_process_audit_pid_file_timer( SmTimerIdT timer_id,
|
|
int64_t user_data )
|
|
{
|
|
int64_t id = user_data;
|
|
SmServiceT* service;
|
|
SmErrorT error;
|
|
|
|
service = sm_service_table_read_by_id( id );
|
|
if( NULL == service )
|
|
{
|
|
DPRINTFE( "Failed to read service, error=%s.",
|
|
sm_error_str(SM_NOT_FOUND) );
|
|
goto EXIT;
|
|
}
|
|
|
|
service->pid_file_audit_timer_id = SM_TIMER_ID_INVALID;
|
|
|
|
error = sm_service_fsm_process_failure_register( service );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to register for process failure for "
|
|
"service (%s), error=%s.", service->name,
|
|
sm_error_str( error ) );
|
|
goto EXIT;
|
|
}
|
|
|
|
EXIT:
|
|
return( false );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Process Failure Register
|
|
// ======================================
|
|
SmErrorT sm_service_fsm_process_failure_register( SmServiceT* service )
|
|
{
|
|
int pid;
|
|
FILE* pid_file;
|
|
bool audit_pid_file = false;
|
|
char file_line[80] = "\0";
|
|
SmErrorT error;
|
|
|
|
if( '\0' != service->pid_file[0] )
|
|
{
|
|
pid_file = fopen ( service->pid_file, "r" );
|
|
|
|
if( NULL == pid_file )
|
|
{
|
|
DPRINTFE( "Failed to open pid file (%s) for service (%s).",
|
|
service->pid_file, service->name );
|
|
audit_pid_file = true;
|
|
goto EXIT;
|
|
}
|
|
|
|
if( NULL == fgets( file_line, sizeof(file_line), pid_file ) )
|
|
{
|
|
DPRINTFE( "Failed to read pid from pid file (%s) for "
|
|
"service (%s).", service->pid_file, service->name );
|
|
fclose( pid_file );
|
|
|
|
remove_pid_file(service->pid_file);
|
|
audit_pid_file = true;
|
|
goto EXIT;
|
|
}
|
|
|
|
fclose( pid_file );
|
|
|
|
if( 1 != sscanf( file_line, "%d", &pid ) )
|
|
{
|
|
DPRINTFE( "pid file (%s) for (%s) is invalid. content (%s).",
|
|
service->pid_file, service->name, file_line );
|
|
|
|
remove_pid_file( service->pid_file );
|
|
audit_pid_file = true;
|
|
goto EXIT;
|
|
}
|
|
|
|
if( 0 > pid )
|
|
{
|
|
DPRINTFE( "Invalid pid (%i) converted from line (%s) from file "
|
|
"(%s) for service (%s).", pid, file_line,
|
|
service->pid_file, service->name );
|
|
audit_pid_file = true;
|
|
goto EXIT;
|
|
}
|
|
|
|
if ( 0 != kill(pid, 0) )
|
|
{
|
|
DPRINTFE( "pid (%i) from file (%s) for service (%s)"
|
|
" is no longer valid.", pid,
|
|
service->pid_file, service->name );
|
|
remove_pid_file( service->pid_file );
|
|
service->pid = -1;
|
|
|
|
if( !sm_process_death_already_registered( pid,
|
|
sm_service_fsm_process_failure_callback ) )
|
|
{
|
|
sm_service_fsm_process_failure_deregister(service);
|
|
}
|
|
|
|
service->disable_check_dependency = false;
|
|
service->disable_skip_dependent = true;
|
|
SmServiceEventT event = SM_SERVICE_EVENT_DISABLE;
|
|
char reason_text[SM_LOG_REASON_TEXT_MAX_CHAR];
|
|
snprintf(reason_text, sizeof(reason_text),
|
|
"Service (%s) process failure, pid=%i, exit_code unknown",
|
|
service->name,
|
|
(int)pid);
|
|
|
|
error = sm_service_fsm_event_handler( service->name, event, NULL,
|
|
reason_text );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Event (%s) not handled for service (%s).",
|
|
sm_service_event_str( event ), service->name );
|
|
}
|
|
goto EXIT;
|
|
}
|
|
|
|
service->pid = pid;
|
|
|
|
if( sm_process_death_already_registered( pid,
|
|
sm_service_fsm_process_failure_callback ) )
|
|
{
|
|
DPRINTFD( "Already registered for process failure callback "
|
|
"for service (%s), pid=%i.", service->name, pid );
|
|
goto EXIT;
|
|
}
|
|
|
|
error = sm_process_death_register( pid, false,
|
|
sm_service_fsm_process_failure_callback,
|
|
service->id );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to register for process failure callback "
|
|
"for service (%s), pid=%i, error=%s.", service->name,
|
|
pid, sm_error_str( error ) );
|
|
goto EXIT;
|
|
}
|
|
}
|
|
|
|
EXIT:
|
|
if( audit_pid_file )
|
|
{
|
|
// Some services do not write their pid file right away when they
|
|
// enable, so register an audit to attempt to register the pid again.
|
|
char timer_name[80] = "";
|
|
SmTimerIdT audit_timer_id;
|
|
|
|
if( SM_TIMER_ID_INVALID != service->pid_file_audit_timer_id )
|
|
{
|
|
error = sm_timer_deregister( service->pid_file_audit_timer_id );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to cancel pid file audit timer, error=%s.",
|
|
sm_error_str( error ) );
|
|
}
|
|
|
|
service->pid_file_audit_timer_id = SM_TIMER_ID_INVALID;
|
|
}
|
|
|
|
snprintf( timer_name, sizeof(timer_name), "%s audit pid file",
|
|
service->name );
|
|
|
|
error = sm_timer_register( timer_name,
|
|
SM_SERVICE_FSM_PID_FILE_AUDIT_IN_MS,
|
|
sm_service_fsm_process_audit_pid_file_timer,
|
|
service->id, &audit_timer_id );
|
|
if( SM_OKAY == error )
|
|
{
|
|
service->pid_file_audit_timer_id = audit_timer_id;
|
|
|
|
} else {
|
|
DPRINTFE( "Failed to create pid file audit timer for "
|
|
"service (%s), error=%s.", service->name,
|
|
sm_error_str( error ) );
|
|
}
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Process Failure Deregister
|
|
// ========================================
|
|
SmErrorT sm_service_fsm_process_failure_deregister( SmServiceT* service )
|
|
{
|
|
SmErrorT error;
|
|
|
|
if( SM_TIMER_ID_INVALID != service->pid_file_audit_timer_id )
|
|
{
|
|
error = sm_timer_deregister( service->pid_file_audit_timer_id );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to cancel pid file audit timer, error=%s.",
|
|
sm_error_str( error ) );
|
|
}
|
|
|
|
service->pid_file_audit_timer_id = SM_TIMER_ID_INVALID;
|
|
}
|
|
|
|
if( 0 <= service->pid )
|
|
{
|
|
error = sm_process_death_deregister( service->pid );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to deregister for process failure callback "
|
|
"for service (%s), pid=%i, error=%s.", service->name,
|
|
service->pid, sm_error_str( error ) );
|
|
}
|
|
|
|
service->pid = -1;
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Initialize
|
|
// ========================
|
|
SmErrorT sm_service_fsm_initialize( void )
|
|
{
|
|
SmErrorT error;
|
|
|
|
memset( &_hb_callbacks, 0, sizeof(_hb_callbacks) );
|
|
|
|
error = sm_service_initial_state_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service initial state module, "
|
|
"error=%s.", sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_unknown_state_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service unknown state module, "
|
|
"error=%s.", sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_enabled_active_state_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service enabled active state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_enabled_go_active_state_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service enabled go-active state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_enabled_go_standby_state_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service enabled go-standby state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_enabled_standby_state_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service enabled standby state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_enabling_throttle_state_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service enabling throttle state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_enabling_state_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service enabling state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_disabling_state_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service disabling state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_disabled_state_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service disabled state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_shutdown_state_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service shutdown state module, "
|
|
"error=%s.", sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_enable_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service enable module, error=%s.",
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_go_active_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service go-active module, error=%s.",
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_go_standby_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service go-standby module, error=%s.",
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_disable_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service disable module, error=%s.",
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
error = sm_service_audit_initialize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to initialize service audit module, error=%s.",
|
|
sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
_hb_callbacks.okay_callback = sm_service_fsm_heartbeat_okay_callback;
|
|
_hb_callbacks.warn_callback = sm_service_fsm_heartbeat_warn_callback;
|
|
_hb_callbacks.degrade_callback = sm_service_fsm_heartbeat_degrade_callback;
|
|
_hb_callbacks.fail_callback = sm_service_fsm_heartbeat_fail_callback;
|
|
|
|
error = sm_service_heartbeat_api_register_callbacks( &_hb_callbacks );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to register service heartbeat callbacks, "
|
|
"error=%s.", sm_error_str( error ) );
|
|
return( error );
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - Finalize
|
|
// ======================
|
|
SmErrorT sm_service_fsm_finalize( void )
|
|
{
|
|
SmErrorT error;
|
|
|
|
error = sm_service_heartbeat_api_deregister_callbacks( &_hb_callbacks );
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to deregister service heartbeat callbacks, "
|
|
"error=%s.", sm_error_str( error ) );
|
|
}
|
|
|
|
memset( &_hb_callbacks, 0, sizeof(_hb_callbacks) );
|
|
|
|
error = sm_service_initial_state_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service initial state module, "
|
|
"error=%s.", sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_unknown_state_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service unknown state module, "
|
|
"error=%s.", sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_enabled_active_state_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service enabled active state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_enabled_go_active_state_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service enabled go-active state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_enabled_go_standby_state_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service enabled go-standby state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_enabled_standby_state_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service enabled standby state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_enabling_throttle_state_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service enabling throttle state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_enabling_state_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service enabling state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_disabling_state_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service disabling state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_disabled_state_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service disabled state "
|
|
"module, error=%s.", sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_shutdown_state_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service shutdown state module, "
|
|
"error=%s.", sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_enable_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service enable module, error=%s.",
|
|
sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_go_active_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service go-active module, error=%s.",
|
|
sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_go_standby_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service go-standby module, error=%s.",
|
|
sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_disable_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service disable module, error=%s.",
|
|
sm_error_str( error ) );
|
|
}
|
|
|
|
error = sm_service_audit_finalize();
|
|
if( SM_OKAY != error )
|
|
{
|
|
DPRINTFE( "Failed to finalize service audit module, error=%s.",
|
|
sm_error_str( error ) );
|
|
}
|
|
|
|
return( SM_OKAY );
|
|
}
|
|
// ****************************************************************************
|
|
|
|
// ****************************************************************************
|
|
// Service FSM - get service terminate reason
|
|
// ========================================
|
|
static SmErrorT sm_service_get_terminate_reason(SmServiceT* service,
|
|
char reason_text[], int len)
|
|
{
|
|
switch( service->state )
|
|
{
|
|
case SM_SERVICE_STATE_DISABLING:
|
|
case SM_SERVICE_STATE_DISABLED:
|
|
case SM_SERVICE_STATE_SHUTDOWN:
|
|
snprintf( reason_text, len, "process (pid=%i) terminated",
|
|
(int) service->pid );
|
|
break;
|
|
default:
|
|
snprintf( reason_text, len, "process (pid=%i) failed",
|
|
(int) service->pid );
|
|
break;
|
|
}
|
|
|
|
return SM_OKAY;
|
|
}
|
|
// ****************************************************************************
|
|
|
|
|
|
// ****************************************************************************
|
|
// util function for deleting an invalid pid file
|
|
// ========================================
|
|
static bool remove_pid_file(char pid_file[])
|
|
{
|
|
if ( 0 == remove( pid_file ) )
|
|
{
|
|
DPRINTFI( "pid file (%s) is deleted. ", pid_file );
|
|
return true;
|
|
}else
|
|
{
|
|
DPRINTFE( "Failed to delete pid file (%s). ", pid_file );
|
|
return false;
|
|
}
|
|
}
|
|
// ****************************************************************************
|