Files
redAcore/ApplicationCore.cpp
Charl Wentzel e71157b9ec Important Update:
- ApplicationCore:
  - Rename ConfigParser -> JSONparser
  - Make JSONparser a public parameter
- DataTreeCore:
  - Bug fix: Insufficient memory allocation on SetValue if Len = -1
2017-07-29 12:45:45 +02:00

376 lines
11 KiB
C++

/*
* FunctionListCore.cpp
*
* Created on: 12 Jul 2017
* Author: wentzelc
*/
// Standard C/C++ Libraries
/* none */
// redA Libraries
#include "ApplicationCore.h"
#include "WatchdogCore.h"
#include "FileCore.h"
//---------------------------------------------------------------------------
// Global Vars
extern char * ProcessName;
//---------------------------------------------------------------------------
CApplication::CApplication( EDebugLevel pLogLevel )
{
// Set signal handlers
ConfigureSignalHandlers();
// Variables used for configuration
ConfigMember = NULL;
FunctionConfigMember = NULL;
LinkConfigMember = NULL;
ConfigFile = NULL;
AddressFile = NULL;
// Create output logger
Log = new CLogCore( stdout );
LogLevel = pLogLevel;
LogOutput = OUT_NORMAL;
// Create Configuration
DataTree = new CDataTree();
JSONparser = new CJSONparse( DataTree );
// Selector
Selector = NULL;
// List
FirstFunction = NULL;
}
//---------------------------------------------------------------------------
CApplication::~CApplication()
{
TFunctionItem * NextFunction;
if (FirstFunction)
{
// Destroy functions
while (FirstFunction)
{
NextFunction = FirstFunction->Next;
delete( FirstFunction->Function );
free( FirstFunction );
FirstFunction = NextFunction;
}
}
// Show Completion
if (Log) Log->Message( dlLow, dlLow, "%s: Terminated.", ProcessName );
// Destroy tools
if (Selector) delete Selector;
if (Log) delete Log;
if (DataTree) delete DataTree;
if (JSONparser) delete JSONparser;
// Free Process Name
if (ProcessName) free( ProcessName );
}
//---------------------------------------------------------------------------
void CApplication::GetProcessName( char ** ProcessName, char * pFilePath )
{
char * TempStr;
// Remove Path
TempStr = strrchr( pFilePath, '/' );
if (TempStr[0] == '/') TempStr++;
// Copy Process Name
*ProcessName = (char*)malloc( strlen(TempStr)+1 );
strcpy( *ProcessName, TempStr );
// Remove extension
TempStr = strrchr( *ProcessName, '.' );
if (TempStr) TempStr[0] = 0;
}
//---------------------------------------------------------------------------
bool CApplication::LoadConfig( int argc, char *argv[], const char * pConfigPath )
{
// Read Parameters
if ((argc != 2))
{
// Get Process Name
GetProcessName( &ProcessName, argv[0] );
// Incorrect no of parameters, show correct usage
printf( "%s: Incorrect number of parameters\n", ProcessName );
printf( " usage: %s [ConfigFile]\n\n", ProcessName );
return false;
}
else
{
// Load parameters
GetProcessName( &ProcessName, argv[1] );
ConfigFile = argv[1];
}
// Load Application List
if (JSONparser->ReadFromFile( pConfigPath, ConfigFile )) {
if (Log) Log->Message( dlLow, dlLow, "%s: Config file loaded (%s)", ProcessName, ConfigFile );
} else {
if (Log) Log->Message( dlLow, dlLow, "%s: Fail to load config file (%s)- %s", ProcessName, ConfigFile, JSONparser->GetError() );
return false;
}
//JSONparser->WriteToScreen( pConfigPath, 2 );
// Loaded successfully
return true;
}
//---------------------------------------------------------------------------
bool CApplication::SaveConfig()
{
// Save updated configuration
if (ConfigFile && *ConfigFile)
JSONparser->WriteToFile( "config", ConfigFile );
if (AddressFile && *AddressFile )
JSONparser->WriteToFile( "address", AddressFile );
return true;
}
//---------------------------------------------------------------------------
bool CApplication::LoadConfigData()
{
TDataMember * TempMember;
EDebugLevel pLogLevel;
int pLogOutput;
char * TempStr;
// Get debug level
pLogLevel = dlNone;
TempStr = (char*)DataTree->GetStr( ConfigMember, "Log/Level", "Medium", true );
if (TempStr)
{
if (!strcasecmp( TempStr, "Low" ))
pLogLevel = dlLow;
else if (!strcasecmp( TempStr, "Medium" ))
pLogLevel = dlMedium;
else if (!strcasecmp( TempStr, "High" ))
pLogLevel = dlHigh;
}
// Set debug output
pLogOutput = 0;
TempMember = DataTree->GetFirstChild( ConfigMember, "Log/Output", true );
while (TempMember)
{
if (TempMember->Value)
{
if (!strcasecmp( TempMember->Value, "Normal"))
pLogOutput |= OUT_NORMAL;
else if (!strcasecmp( TempMember->Value, "Bin"))
pLogOutput |= OUT_BIN;
else if (!strcasecmp( TempMember->Value, "Hex"))
pLogOutput |= OUT_HEX;
else if (!strcasecmp( TempMember->Value, "Count"))
pLogOutput |= OUT_COUNT;
else if (!strcasecmp( TempMember->Value, "AsIs"))
pLogOutput |= OUT_ASIS;
else if (!strcasecmp( TempMember->Value, "CRLF"))
pLogOutput |= OUT_CRLF;
}
// Next
TempMember = DataTree->GetNextChild( TempMember );
}
SetLogParam( pLogLevel, pLogOutput );
// Load Address List
if ((AddressFile = (char*)DataTree->GetStr( ConfigMember, "AddressList/Path", NULL )))
{
if (JSONparser->ReadFromFile( "address", AddressFile )) {
if (Log) Log->Message( dlLow, dlLow, "%s: Address file loaded (%s)", ProcessName, AddressFile );
} else {
if (Log) Log->Message( dlLow, dlLow, "%s: Fail to load Address file (%s) - %s", ProcessName, AddressFile, JSONparser->GetError() );
}
//JSONparser->WriteToScreen( pAddressListPath, 2 );
}
// Configure Selector
if ((TempMember = DataTree->GetMember( ConfigMember, "Selector" )))
{
// Create Selector
Selector = new CSelect( (int)DataTree->GetInt( TempMember, "Wait", 5, true ), LogLevel );
}
return true;
}
//---------------------------------------------------------------------------
bool CApplication::SetLogParam( EDebugLevel pDebugLevel, int pOutputDisplay )
{
// Output
LogLevel = pDebugLevel;
LogOutput = pOutputDisplay;
return true;
}
//---------------------------------------------------------------------------
bool CApplication::Init()
{
// Report status
if (Log) Log->Message( LogLevel, dlLow, "%s: Application Initialised", ProcessName );
return true;
}
//---------------------------------------------------------------------------
bool CApplication::InitConfig( const char * pConfigPath )
{
// Check if Datatree exists
if (!DataTree || !(ConfigMember = DataTree->GetMember( NULL, pConfigPath ))) {
return false;
}
// LoadConfiguration
LoadConfigData();
Init();
return true;
}
//---------------------------------------------------------------------------
bool CApplication::InitFunctions( const char * pConfigPath )
{
CFunctionCore * Function;
TDataMember * TempMember;
char * Type;
// Check of path exists
if (!DataTree || !(FunctionConfigMember = DataTree->GetMember( NULL, pConfigPath )))
return false;
// Process each Channel
TempMember = DataTree->GetFirstChild( FunctionConfigMember );
while (TempMember)
{
// Get function parameters
Type = (char*)DataTree->GetStr( TempMember, "Type", "Custom", true );
// Get or create function
if (!strcasecmp( Type, "WatchdogClient" )) {
Function = new CWatchdogCore( TempMember->Name );
}
else if (!strcasecmp( Type, "Selectable" )) {
Function = new CSelectableCore( TempMember->Name );
}
else if (!strcasecmp( Type, "File" )) {
Function = new CFileCore( TempMember->Name );
}
else {
Function = GetFunction( TempMember->Name );
}
// Load Function configuration and Initialise
if (Function) {
Function->InitConfig( TempMember );
}
// Next
TempMember = TempMember->Next;
}
return true;
}
//---------------------------------------------------------------------------
bool CApplication::InitFunctionLinks( const char * pConfigPath )
{
TFunctionItem * FunctionItem;
TDataMember * TempMember;
// Check of path exists
if (!DataTree || !(LinkConfigMember = DataTree->GetMember( NULL, pConfigPath )))
return false;
// Process each Channel
FunctionItem = FirstFunction;
while (FunctionItem)
{
// Build links for function
if ((TempMember = DataTree->GetMember( LinkConfigMember, FunctionItem->Function->GetName() )))
FunctionItem->Function->InitChannelLinks( TempMember );
// Next
FunctionItem = FunctionItem->Next;
}
return true;
}
//---------------------------------------------------------------------------
// Build List
bool CApplication::AddFunction( CFunctionCore * Function )
{
TFunctionItem ** FunctionPtr;
// Check if unique, else get end of list
FunctionPtr = &FirstFunction;
while (*FunctionPtr && strcasecmp( (*FunctionPtr)->Function->GetName(), Function->GetName() ))
FunctionPtr = &((*FunctionPtr)->Next);
// Check if exists
if (*FunctionPtr)
return false;
// Add to end of list
*FunctionPtr = (TFunctionItem*)calloc( sizeof(TFunctionItem), 1 );
(*FunctionPtr)->Function = Function;
return true;
}
//---------------------------------------------------------------------------
// Search List
CFunctionCore * CApplication::GetFunction( const char * Name )
{
TFunctionItem * FunctionItem;
// Find in list
FunctionItem = FirstFunction;
while (FunctionItem && strcasecmp( FunctionItem->Function->GetName(), Name ))
FunctionItem = FunctionItem->Next;
return ((FunctionItem)? FunctionItem->Function : NULL);
}
//---------------------------------------------------------------------------
bool CApplication::Run( bool TerminateOnError )
{
bool AllGood = true;
TFunctionItem * FunctionItem;
// Check for FD Events/States
if (Selector) {
Selector->Test();
}
// Process Functions
for (FunctionItem = FirstFunction; FunctionItem; FunctionItem = FunctionItem->Next )
{
if (!FunctionItem->Function->Process())
{
if (TerminateOnError)
return false;
else {
AllGood = false;
}
}
}
return AllGood;
}
//---------------------------------------------------------------------------