//
//
// Copyright (C) 2004 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// Copyright (C) 2004 Pingtel Corp.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// $$
//////////////////////////////////////////////////////////////////////////////
// SYSTEM INCLUDES
// DEFINES
#define IMDB_BAD_FILE SIPX_TMPDIR "/imdb.bad"
// APPLICATION INCLUDES
#include "os/OsQueuedEvent.h"
#include "os/OsEventMsg.h"
#include "os/OsTimer.h"
#include "os/OsDateTime.h"
#include "os/OsFS.h"
#include "IMDBTaskMonitor.h"
#include "ImportTask.h"
#include "DisplayTask.h"
#include "KeepAliveTask.h"
#include "HeartBeatMonitor.h"
extern UtlBoolean gShutdownFlag;
IMDBTaskMonitor::IMDBTaskMonitor (
const UtlString& rCommand,
const UtlString& rArgument,
const int& rMonitorSecs ) :
mErrno(0),
mMonitorSecs ( rMonitorSecs ),
mCommandName ( rCommand ),
mCommandEvent(),
mCommandCompleted (FALSE)
{
// Create the watchdog event/timer
mpTimeoutEvent = new OsQueuedEvent( *getMessageQueue(), 0 ) ;
//set subtype to signify user action
mpTimeoutEvent->setUserData( USER_TIMEOUT_EVENT);
mpWatchDogTimer = new OsTimer(*mpTimeoutEvent) ;
// Finally construct the heartbeat thread that hits the IMDB
mpIMDBWorkerTask = NULL;
if ( rCommand.compareTo("heartbeat", UtlString::ignoreCase) == 0 )
{
mpIMDBWorkerTask = new HeartBeatMonitor (
rArgument, *getMessageQueue(), mCommandEvent );
} else if ( rCommand.compareTo("keepalive", UtlString::ignoreCase) == 0 )
{
mpIMDBWorkerTask = new KeepAliveTask (
rArgument, *getMessageQueue(), mCommandEvent );
} else if ( rCommand.compareTo("display", UtlString::ignoreCase) == 0 )
{
mpIMDBWorkerTask = new DisplayTask (
rArgument, *getMessageQueue(), mCommandEvent );
} else if ( rCommand.compareTo("import", UtlString::ignoreCase) == 0 )
{
mpIMDBWorkerTask = new ImportTask (
rArgument, *getMessageQueue(), mCommandEvent );
} else
{
}
if (mpIMDBWorkerTask != NULL )
{
mpIMDBWorkerTask->start();
// arm the timer to fire periodically, starting one period later
mpWatchDogTimer->periodicEvery(
OsTime( rMonitorSecs, 0 ), // delay
OsTime( rMonitorSecs, 0 )); // every...
}
}
// Copy constructor
IMDBTaskMonitor::IMDBTaskMonitor( const IMDBTaskMonitor& rIMDBTaskMonitor ) :
mErrno(0), mCommandCompleted (FALSE)
{}
// Dtor
IMDBTaskMonitor::~IMDBTaskMonitor()
{
delete mpTimeoutEvent;
delete mpWatchDogTimer;
delete mpIMDBWorkerTask;
}
// Assignment operator
IMDBTaskMonitor&
IMDBTaskMonitor::operator=( const IMDBTaskMonitor& rhs )
{
if (this == &rhs) // handle the assignment to self case
return *this;
return *this;
}
OsStatus
IMDBTaskMonitor::getErrno ( int& rErrnum )
{
rErrnum = mErrno;
return OS_SUCCESS;
}
OsStatus
IMDBTaskMonitor::setErrno ( int errnum )
{
mErrno = errnum;
return OS_SUCCESS;
}
UtlBoolean
IMDBTaskMonitor::handleMessage ( OsMsg &rMsg )
{
UtlBoolean returnValue = TRUE;
// Check for a timer event (indicated by the MsgType)
if ( ( rMsg.getMsgType() == OsMsg::OS_EVENT ) )
{
// Timer Message, see if we still have a working task
if ( mpIMDBWorkerTask != NULL )
{
// test to see if the worker completed the last task
if ( !mCommandCompleted )
{
// firstly stop the timer as things have gone really wrong
mpWatchDogTimer->stop();
// kill the worker heartbeat test task and keep the timer alive
// we'll eventually be killed by the restart script
// it is important not to exit here as the watchdog will notice and
// restart us
osPrintf( "'%s' command [FAILED]\n", mCommandName.data() );
OsSysLog::add( LOG_FACILITY, PRI_DEBUG, "'%s' command [FAILED]\n", mCommandName.data() );
// timer expired waiting for the Ping command to complete
if ( mCommandName.compareTo("heartbeat", UtlString::ignoreCase) == 0 )
{
osPrintf( "Notifying 'pd_monitor' process via 'imdb.bad' file\n" );
OsSysLog::add( LOG_FACILITY, PRI_DEBUG, "Notifying pd_monitor process via 'imdb.bad' file\n" );
OsFile imdbBrokenIPCFile ( IMDB_BAD_FILE );
imdbBrokenIPCFile.touch();
imdbBrokenIPCFile.close();
mpIMDBWorkerTask->deleteForce();
delete mpIMDBWorkerTask;
mpIMDBWorkerTask = NULL;
}
// waiting around until we're killed off by the watchdog script
osPrintf ("Waiting for Watchdog Restart (or Ctrl+C)\n");
OsSysLog::add( LOG_FACILITY, PRI_DEBUG, "Waiting for Watchdog Restart (or Ctrl+C)\n");
setErrno (1);
} else
{ // complete the handshake by toggling the flag
mCommandCompleted = FALSE;
// signal the worker thread to immediately kick off another one
mCommandEvent.signal(0);
}
}
} else if ( (rMsg.getMsgType() == OsMsg::USER_START) && (rMsg.getMsgSubType() == USER_HEARTBEAT_SUCCESS_EVENT) )
{
// command completed successfully
mCommandCompleted = TRUE;
osPrintf ("%s [OK]\n", mCommandName.data());
OsSysLog::add(LOG_FACILITY, PRI_DEBUG, "%s [OK]\n", mCommandName.data());
setErrno (0);
} else if ( (rMsg.getMsgType() == OsMsg::USER_START) && (rMsg.getMsgSubType() == USER_IMPORT_SUCCESS_EVENT) )
{
// import command completed
mCommandCompleted = TRUE;
mpWatchDogTimer->stop();
osPrintf ("%s [OK]\n", mCommandName.data());
OsSysLog::add(LOG_FACILITY, PRI_DEBUG, "%s [OK]\n", mCommandName.data());
setErrno (0);
gShutdownFlag = TRUE;
} else if ( (rMsg.getMsgType() == OsMsg::USER_START) && (rMsg.getMsgSubType() == USER_DISPLAY_SUCCESS_EVENT) )
{
// display command completed
mCommandCompleted = TRUE;
mpWatchDogTimer->stop();
osPrintf ("%s [OK]\n", mCommandName.data());
OsSysLog::add(LOG_FACILITY, PRI_DEBUG, "%s [OK]\n", mCommandName.data());
setErrno (0);
gShutdownFlag = TRUE;
}
return( returnValue );
}
syntax highlighted by Code2HTML, v. 0.9.1