- Minor fix: Set correct names in comments at top of file - New FileCore Class: - Writing data to output file - BufferCore: - Check for "EAGAIN" on write and retry write - FunctionCore: - Add new Output method that references LocalIO directly - SelectableCore: - New method SetAutomanage to specify auto re-open parameters - Re-open timer implemented to slow re-open events - Only call ProcessBuffer() if data received on socket - Force processing input data when no input marker set - Use new Output method to simplify code - Bug fix: Read correctly from buffer on multiple reads/writes on FD - Check for "EAGAIN" on write to FD and retry write
293 lines
7.9 KiB
C++
293 lines
7.9 KiB
C++
/*
|
|
* FunctionCore.cpp
|
|
*
|
|
* Created on: 18 May 2016
|
|
* Author: wentzelc
|
|
*/
|
|
|
|
// redA Libraries
|
|
#include "FunctionCore.h"
|
|
#include "TimingCore.h"
|
|
#include "LogCore.h"
|
|
|
|
// Standard C/C++ Libraries
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
extern char ProcessName[];
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Life cycle
|
|
CFunctionCore::CFunctionCore( const char * FunctionName, EDebugLevel pDebugLevel, int pOuputDisplay )
|
|
{
|
|
// Set name
|
|
if (FunctionName) {
|
|
Name = (char*)malloc( strlen(FunctionName)+1 );
|
|
strcpy( Name, FunctionName );
|
|
}
|
|
else {
|
|
Name = NULL;
|
|
}
|
|
|
|
// IO Functions
|
|
FirstIO = NULL;
|
|
|
|
// Output
|
|
OutputDisplay = pOuputDisplay;
|
|
DebugLevel = pDebugLevel;
|
|
|
|
// Report status
|
|
LogMessage( DebugLevel, dlLow, "%s: Function '%s' - Created", ProcessName, FunctionName );
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
CFunctionCore::~CFunctionCore()
|
|
{
|
|
TLocalIO * NextIO = NULL;
|
|
TLinkedIO * NextLinkedIO = NULL;
|
|
|
|
// Destroy IO
|
|
while (FirstIO)
|
|
{
|
|
// Destroy Parameters
|
|
if (FirstIO->Name) {
|
|
free( FirstIO->Name );
|
|
}
|
|
|
|
// Destroy Linked Inputs
|
|
while (FirstIO->FirstInput) {
|
|
if (FirstIO->FirstInput->IOName) {
|
|
free( FirstIO->FirstInput->IOName );
|
|
}
|
|
NextLinkedIO = FirstIO->FirstInput->Next;
|
|
free( FirstIO->FirstInput );
|
|
FirstIO->FirstInput = NextLinkedIO;
|
|
}
|
|
|
|
// Destroy Linked Outputs
|
|
while (FirstIO->FirstOutput) {
|
|
if (FirstIO->FirstOutput->IOName) {
|
|
free( FirstIO->FirstOutput->IOName );
|
|
}
|
|
NextLinkedIO = FirstIO->FirstOutput->Next;
|
|
free( FirstIO->FirstOutput );
|
|
FirstIO->FirstOutput = NextLinkedIO;
|
|
}
|
|
|
|
// Destroy Local IO
|
|
// Destroy Local IO
|
|
NextIO = FirstIO->Next;
|
|
free( FirstIO );
|
|
FirstIO = NextIO;
|
|
}
|
|
|
|
// Report status
|
|
LogMessage( DebugLevel, dlLow, "%s: Function '%s' - Destroyed", ProcessName, Name );
|
|
|
|
// Destroy Name
|
|
if (Name) {
|
|
free( Name );
|
|
}
|
|
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
TLocalIO * CFunctionCore::AddLocalIO( const char * IOName )
|
|
{
|
|
TLocalIO ** LocalIO = NULL;
|
|
|
|
// Validate
|
|
if (!IOName) {
|
|
return NULL;
|
|
}
|
|
|
|
// Check if exists
|
|
LocalIO = &FirstIO;
|
|
while (*LocalIO && strcmp( IOName, (*LocalIO)->Name )) {
|
|
LocalIO = &((*LocalIO)->Next);
|
|
}
|
|
|
|
// Create if not exist
|
|
if (!*LocalIO) {
|
|
// Create
|
|
*LocalIO = (TLocalIO*)malloc( sizeof(TLocalIO) );
|
|
memset( *LocalIO, 0, sizeof(TLocalIO) );
|
|
|
|
// Set Name
|
|
(*LocalIO)->Name = (char*)malloc( strlen(IOName)+1 );
|
|
strcpy( (*LocalIO)->Name, IOName );
|
|
|
|
// Log Event
|
|
LogMessage( DebugLevel, dlLow, "%s: Local IO '%s' - Created", Name, IOName );
|
|
}
|
|
|
|
return *LocalIO;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Automated Data Input/Output
|
|
bool CFunctionCore::AddInput( const char * IOName, CFunctionCore * OutFunction, const char * OutputName, bool Bidirectional )
|
|
{
|
|
TLocalIO * LocalIO = NULL;
|
|
TLinkedIO ** LinkedIO = NULL;
|
|
|
|
// Get IO
|
|
if (!OutFunction || !OutFunction || !(LocalIO = GetLocalIO( IOName ))) {
|
|
return false;
|
|
}
|
|
|
|
// Check if linked IO exists
|
|
LinkedIO = &(LocalIO->FirstInput);
|
|
while (*LinkedIO && (((*LinkedIO)->Function != OutFunction) || strcmp( (*LinkedIO)->IOName, OutputName ) )) {
|
|
LinkedIO = &((*LinkedIO)->Next);
|
|
}
|
|
|
|
// Create if not found
|
|
if (!*LinkedIO)
|
|
{
|
|
// Create
|
|
*LinkedIO = (TLinkedIO*)malloc( sizeof(TLinkedIO) );
|
|
memset( *LinkedIO, 0, sizeof( TLinkedIO ));
|
|
|
|
// Set Parameters
|
|
(*LinkedIO)->Function = OutFunction;
|
|
(*LinkedIO)->IOName = (char*)malloc( strlen(OutputName)+1 );
|
|
strcpy( (*LinkedIO)->IOName, OutputName );
|
|
|
|
// Log Event
|
|
LogMessage( DebugLevel, dlLow, "%s: Input Linked - '%s'/'%s' <-- '%s'/'%s'", Name, Name, IOName, OutFunction->GetName(), OutputName );
|
|
}
|
|
|
|
// Link Return direction as well
|
|
if (Bidirectional) {
|
|
return OutFunction->AddInput( OutputName, this, IOName, false );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
bool CFunctionCore::AddOutput( const char * IOName, CFunctionCore * InFunction, const char * InputName, bool Bidirectional )
|
|
{
|
|
TLocalIO * LocalIO = NULL;
|
|
TLinkedIO ** LinkedIO = NULL;
|
|
|
|
// Get IO
|
|
if (!InFunction || !InputName || !(LocalIO = GetLocalIO( IOName ))) {
|
|
return false;
|
|
}
|
|
|
|
// Check if linked IO exists
|
|
LinkedIO = &(LocalIO->FirstOutput);
|
|
while (*LinkedIO && (((*LinkedIO)->Function != InFunction) || strcmp( (*LinkedIO)->IOName, InputName ) )) {
|
|
LinkedIO = &((*LinkedIO)->Next);
|
|
}
|
|
|
|
// Create if not found
|
|
if (!*LinkedIO)
|
|
{
|
|
// Create
|
|
*LinkedIO = (TLinkedIO*)malloc( sizeof(TLinkedIO) );
|
|
memset( *LinkedIO, 0, sizeof( TLinkedIO ));
|
|
|
|
// Set Parameters
|
|
(*LinkedIO)->Function = InFunction;
|
|
(*LinkedIO)->IOName = (char*)malloc( strlen(InputName)+1 );
|
|
strcpy( (*LinkedIO)->IOName, InputName );
|
|
|
|
// Log Event
|
|
LogMessage( DebugLevel, dlLow, "%s: Output Linked - '%s'/'%s' --> '%s'/'%s'", Name, Name, IOName, InFunction->GetName(), InputName );
|
|
}
|
|
|
|
// Link return direction as well
|
|
if (Bidirectional) {
|
|
return InFunction->AddOutput( InputName, this, IOName, false );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Manual Data Input/Output
|
|
int CFunctionCore::Input( const char * IOName, const char * Data, int MaxLen )
|
|
{
|
|
TLocalIO * LocalIO = NULL;
|
|
|
|
// Validate
|
|
if (!IOName || !Data) {
|
|
return 0;
|
|
}
|
|
else if (MaxLen == -1) {
|
|
MaxLen = strlen( Data );
|
|
}
|
|
|
|
// Get IO
|
|
if (!(LocalIO = GetLocalIO( IOName )))
|
|
{
|
|
// Log event
|
|
LogMessage( DebugLevel, dlHigh, "%s: Local IO '%s' - Input rejected, Local IO not found", Name, IOName );
|
|
return 0;
|
|
}
|
|
|
|
// Log event
|
|
ShowOutput( DebugLevel, dlHigh, OutputDisplay, Data, MaxLen, "%s: Local IO '%s' - IN:", Name, IOName );
|
|
|
|
// Return processed bytes
|
|
return MaxLen;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
int CFunctionCore::Output( const char * IOName, const char * Data, int Len )
|
|
{
|
|
TLocalIO * LocalIO = NULL;
|
|
|
|
// Validate
|
|
if (!IOName || !Data) {
|
|
return 0;
|
|
} else if (Len == -1) {
|
|
Len = strlen( Data );
|
|
}
|
|
|
|
// Get IO
|
|
if (!(LocalIO = GetLocalIO( IOName )))
|
|
{
|
|
// Log Event
|
|
LogMessage( DebugLevel, dlHigh, "%s: Local IO '%s' - Output rejected, Local IO not found", Name, IOName );
|
|
return 0;
|
|
}
|
|
|
|
// Return processed bytes
|
|
return Output( LocalIO, Data, Len );
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
int CFunctionCore::Output( const TLocalIO * LocalIO, const char * Data, int Len )
|
|
{
|
|
TLinkedIO * Output = NULL;
|
|
|
|
// Validate
|
|
if (!LocalIO || !Data) {
|
|
return 0;
|
|
} else if (Len == -1) {
|
|
Len = strlen( Data );
|
|
}
|
|
|
|
// Log event
|
|
ShowOutput( DebugLevel, dlHigh, OutputDisplay, Data, Len, "%s: Local IO '%s' - OUT:", Name, LocalIO->Name );
|
|
|
|
// Pass output to all linked inputs
|
|
Output = LocalIO->FirstOutput;
|
|
while (Output) {
|
|
Output->Function->Input( Output->IOName, Data, Len );
|
|
Output = Output->Next;
|
|
}
|
|
|
|
// Return processed bytes
|
|
return Len;
|
|
}
|
|
//---------------------------------------------------------------------------
|