18922761a6
Signed-off-by: Dean Troyer <dtroyer@gmail.com>
306 lines
8.6 KiB
C++
306 lines
8.6 KiB
C++
/*
|
|
* Copyright (c) 2016-2017 Wind River Systems, Inc.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* Wind River Titanium Cloud Maintenance Alarm Manager Daemon Initialization
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <iostream>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <unistd.h> /* for close and usleep */
|
|
|
|
using namespace std;
|
|
|
|
#define __MODULE_PRIVATE__
|
|
|
|
#include "daemon_ini.h" /* Ini Parser Header */
|
|
#include "daemon_common.h" /* Common definitions and types for daemons */
|
|
#include "daemon_option.h" /* Common options for daemons */
|
|
|
|
#include "alarm.h" /* module header */
|
|
#include "msgClass.h" /* for ... socket message setup */
|
|
|
|
/** Local Identity */
|
|
static string my_hostname = "" ;
|
|
static string my_local_ip = "" ;
|
|
static string my_float_ip = "" ;
|
|
|
|
|
|
/** Maintenance Alarm request socket and port - UDP over lo */
|
|
msgClassSock * mtcalarm_req_sock_ptr = NULL ;
|
|
int mtcalarm_req_port = 0 ;
|
|
|
|
|
|
/** Common Daemon Config Struct */
|
|
static daemon_config_type _config ;
|
|
daemon_config_type * daemon_get_cfg_ptr () { return &_config ; }
|
|
|
|
|
|
/* Cleanup exit handler */
|
|
void daemon_exit ( void )
|
|
{
|
|
daemon_dump_info ();
|
|
daemon_files_fini ();
|
|
|
|
/* Close sockets */
|
|
if ( mtcalarm_req_sock_ptr )
|
|
{
|
|
delete (mtcalarm_req_sock_ptr );
|
|
mtcalarm_req_sock_ptr = NULL ;
|
|
mtcalarm_req_port = 0 ;
|
|
}
|
|
exit (0);
|
|
}
|
|
|
|
|
|
/** Client Config mask */
|
|
#define CONFIG_CLIENT_MASK (CONFIG_CLIENT_PULSE_PORT)
|
|
|
|
/* Startup config read */
|
|
static int _config_handler ( void * user,
|
|
const char * section,
|
|
const char * name,
|
|
const char * value)
|
|
{
|
|
daemon_config_type* config_ptr = (daemon_config_type*)user;
|
|
|
|
if (MATCH("client", "mtcalarm_req_port"))
|
|
{
|
|
config_ptr->mtcalarm_req_port = atoi(value);
|
|
config_ptr->mask |= CONFIG_CLIENT_PULSE_PORT ;
|
|
}
|
|
else
|
|
{
|
|
return (PASS);
|
|
}
|
|
return (FAIL);
|
|
}
|
|
|
|
/* Configure the daemon */
|
|
int daemon_configure ( void )
|
|
{
|
|
int rc = FAIL ;
|
|
|
|
if (ini_parse(MTCE_CONF_FILE, _config_handler, &_config) < 0)
|
|
{
|
|
elog("Failed to load '%s'\n", MTCE_CONF_FILE );
|
|
return(FAIL_LOAD_INI);
|
|
}
|
|
|
|
get_debug_options ( MTCE_CONF_FILE, &_config );
|
|
|
|
/* Verify loaded config against an expected mask
|
|
* as an ini file fault detection method */
|
|
if ( _config.mask != CONFIG_CLIENT_MASK )
|
|
{
|
|
elog ("Client configuration failed (%x)\n",
|
|
(( -1 ^ _config.mask ) & CONFIG_CLIENT_MASK) );
|
|
rc = FAIL_INI_CONFIG ;
|
|
}
|
|
else
|
|
{
|
|
ilog("Alarm Port : %d\n", _config.mtcalarm_req_port );
|
|
rc = PASS ;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************/
|
|
/* Initialization Utilities */
|
|
/****************************/
|
|
|
|
int daemon_socket_init ( void )
|
|
{
|
|
int rc = PASS ;
|
|
|
|
/***********************************************************/
|
|
/* Setup the Alarm Request Receiver Socket */
|
|
/***********************************************************/
|
|
|
|
mtcalarm_req_sock_ptr = new msgClassRx ( LOOPBACK_IP, _config.mtcalarm_req_port, IPPROTO_UDP);
|
|
if (rc)
|
|
return (rc) ;
|
|
if (mtcalarm_req_sock_ptr)
|
|
mtcalarm_req_sock_ptr->sock_ok(true);
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/* The main heartbeat service loop */
|
|
int daemon_init ( string iface, string nodeType_str )
|
|
{
|
|
int rc = PASS ;
|
|
UNUSED(nodeType_str);
|
|
|
|
/* Assign interface to config */
|
|
_config.mgmnt_iface = (char*)iface.data() ;
|
|
|
|
if ((rc = daemon_files_init ()) != PASS)
|
|
{
|
|
elog ("daemon_files_init failed (rc:%d)\n", rc );
|
|
return ( FAIL_FILES_INIT );
|
|
}
|
|
|
|
/* Bind signal handlers */
|
|
if ((rc = daemon_signal_init ()) != PASS)
|
|
{
|
|
elog ("daemon_signal_init failed (rc:%d)\n", rc );
|
|
return ( FAIL_SIGNAL_INIT );
|
|
}
|
|
|
|
/************************************************************************
|
|
* There is no point continuing with init ; i.e. running daemon_configure,
|
|
* initializing sockets and trying to query for an ip address until the
|
|
* daemon's configuration requirements are met. Here we wait for those
|
|
* flag files to be present before continuing.
|
|
************************************************************************
|
|
* Wait for /etc/platform/.initial_config_complete & /var/run/.goenabled */
|
|
daemon_wait_for_file ( CONFIG_COMPLETE_FILE , 0);
|
|
daemon_wait_for_file ( GOENABLED_MAIN_READY , 0);
|
|
|
|
/* Configure the client */
|
|
if ((rc = daemon_configure ()) != PASS)
|
|
{
|
|
elog ("daemon_configure failed (rc:%d)\n", rc );
|
|
rc = FAIL_DAEMON_CONFIG ;
|
|
}
|
|
|
|
/* Setup messaging sockets */
|
|
else if ((rc = daemon_socket_init ()) != PASS)
|
|
{
|
|
elog ("daemon_socket_init failed (rc:%d)\n", rc );
|
|
rc = FAIL_SOCKET_INIT;
|
|
}
|
|
|
|
alarmData_init ();
|
|
|
|
return (rc);
|
|
}
|
|
|
|
void daemon_service_run ( void )
|
|
{
|
|
int rc = PASS ;
|
|
if (( mtcalarm_req_sock_ptr ) && ( mtcalarm_req_sock_ptr->getFD() ))
|
|
{
|
|
std::list<int> socks ;
|
|
|
|
/* For select dispatch */
|
|
struct timeval waitd ;
|
|
fd_set readfds;
|
|
|
|
int failed_receiver_log_throttle = 0 ;
|
|
int failed_receiver_b2b_count = 0 ;
|
|
int failed_socket_log_throttle = 0 ;
|
|
|
|
socks.clear();
|
|
socks.push_front (mtcalarm_req_sock_ptr->getFD());
|
|
socks.sort();
|
|
|
|
/* Run service forever */
|
|
for ( ; ; )
|
|
{
|
|
daemon_signal_hdlr ();
|
|
waitd.tv_sec = 0;
|
|
waitd.tv_usec = SOCKET_WAIT;
|
|
|
|
/* Initialize the master fd_set */
|
|
FD_ZERO(&readfds);
|
|
FD_SET( mtcalarm_req_sock_ptr->getFD(), &readfds);
|
|
rc = select( socks.back()+1, &readfds, NULL, NULL, &waitd);
|
|
if (( rc < 0 ) || ( rc == 0 ))
|
|
{
|
|
if (( rc < 0 ) && ( errno != EINTR ))
|
|
{
|
|
wlog_throttled ( failed_socket_log_throttle, 100,
|
|
"Socket Select Failed (%d:%m)\n", errno);
|
|
}
|
|
}
|
|
|
|
if ( FD_ISSET(mtcalarm_req_sock_ptr->getFD(), &readfds))
|
|
{
|
|
failed_socket_log_throttle = 0 ;
|
|
if ( mtcalarm_req_sock_ptr && ( mtcalarm_req_sock_ptr->sock_ok() == true ))
|
|
{
|
|
char msg [MAX_ALARM_REQ_SIZE] ;
|
|
memset ( &msg , 0, MAX_ALARM_REQ_MSG_SIZE );
|
|
int bytes = mtcalarm_req_sock_ptr->read((char*)&msg, MAX_ALARM_REQ_SIZE-1 );
|
|
if ( bytes > 0 )
|
|
{
|
|
failed_receiver_b2b_count = 0 ;
|
|
failed_receiver_log_throttle = 0 ;
|
|
if ( ( rc = alarmHdlr_request_handler ( msg )) != PASS )
|
|
{
|
|
wlog ("failed to handle alarm request (rc:%d)\n", rc );
|
|
}
|
|
}
|
|
else if ( bytes < 0 )
|
|
{
|
|
failed_receiver_b2b_count++ ;
|
|
wlog_throttled ( failed_receiver_log_throttle, 20, "alarm request receive error ; thresholeded ; (%d:%m)\n", errno );
|
|
}
|
|
else
|
|
{
|
|
failed_receiver_b2b_count++ ;
|
|
wlog_throttled ( failed_receiver_log_throttle, 20, "alarm request receive ; no data\n" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
elog ("alarm request socket error ; fatal\n");
|
|
failed_receiver_b2b_count = MAX_FAILED_B2B_RECEIVES_B4_RESTART ;
|
|
}
|
|
|
|
if ( failed_receiver_b2b_count >= MAX_FAILED_B2B_RECEIVES_B4_RESTART )
|
|
{
|
|
/* exit and allow process restart by pmond */
|
|
elog ("max (%d) alarm request receive errors reached ; forcing process restart\n", MAX_FAILED_B2B_RECEIVES_B4_RESTART );
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
elog ("alarm request socket error ; not initialized ; exiting\n");
|
|
}
|
|
daemon_exit();
|
|
}
|
|
|
|
/* Push daemon state to log file */
|
|
void daemon_dump_info ( void )
|
|
{
|
|
daemon_dump_membuf_banner ();
|
|
daemon_dump_membuf();
|
|
}
|
|
|
|
const char MY_DATA [100] = { "eieio\n" } ;
|
|
const char * daemon_stream_info ( void )
|
|
{
|
|
return (&MY_DATA[0]);
|
|
}
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* Module Test Head *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
/** Teat Head Entry */
|
|
int daemon_run_testhead ( void )
|
|
{
|
|
int rc = PASS;
|
|
return (rc);
|
|
}
|