/* * FileCore.cpp * * Created on: 1 Jun 2016 * Author: wentzelc */ // Standard C/C++ Libraries #include #include #include // redA Libraries #include "ApplicationCore.h" #include "FileCore.h" //--------------------------------------------------------------------------- // Global Vars extern char * ProcessName; //extern CApplication * Application; //--------------------------------------------------------------------------- // Function Constructor CFunctionCore * NewFileCore( const char * Name ) { return (CFunctionCore*) new CFileCore( Name ); } //--------------------------------------------------------------------------- CFileCore::CFileCore( const char * pName, const char * pType ) : CFunctionCore( pName, pType ) { FirstFile = NULL; } //--------------------------------------------------------------------------- CFileCore::~CFileCore() { TFileHandle * NextFile = NULL; // Destroy file specs while (FirstFile) { // Close file if open CloseFile( FirstFile ); // Destroy file parameters if (FirstFile->Name) free( FirstFile->Name ); if (FirstFile->Path) free( FirstFile->Path ); // Destroy File NextFile = FirstFile->Next; delete FirstFile; FirstFile = NextFile; } } //--------------------------------------------------------------------------- TFileHandle * CFileCore::AddFile( const char * Name, const char * Path, bool Append, bool CreateChannel ) { TFileHandle ** FileHandle = NULL; // Validate if (!Name || !*Name || !Path || !*Path) { return NULL; } // Find File or End of list FileHandle = &FirstFile; while (*FileHandle && strcmp( Name, (*FileHandle)->Name )) { FileHandle = &((*FileHandle)->Next); } // Check if found if (!*FileHandle) { // Create new *FileHandle = (TFileHandle*)calloc( 1, sizeof(TFileHandle) ); // Set name & Path (*FileHandle)->Name = strdup( Name ); (*FileHandle)->Path = strdup( Path ); } // Create Channel if necessary if (CreateChannel) { AddChannel( Name, CH_ready ); } // Set Parameters (*FileHandle)->Append = Append; (*FileHandle)->FD = NO_FD; // Return File return (*FileHandle); } //--------------------------------------------------------------------------- bool CFileCore::SetFilePersistence( TFileHandle * FileHandle, bool Persistent, int PersistTimeout ) { // Validate if (!FileHandle) { return false; } // Set parameters FileHandle->Persistent = Persistent; FileHandle->PersistTimeout = PersistTimeout; // Open persistent file if (Persistent && (!PersistTimeout)) { OpenFile( FileHandle ); SetStartTime( &(FileHandle->PersistTime) ); } // Close non-persistent file else if (!Persistent && isOpen(FileHandle)) { CloseFile( FileHandle ); } return true; } //--------------------------------------------------------------------------- bool CFileCore::OpenFile( TFileHandle * FileHandle ) { // Validate if (!FileHandle) { return false; } // Open file if not already open if (!isOpen( FileHandle )) { // GEt file handle (FileHandle)->FD = open( FileHandle->Path, O_WRONLY | O_CREAT | ((FileHandle->Append)? O_APPEND : O_TRUNC), 0664 ); // Report event if (isOpen(FileHandle)) { // Set timer SetStartTime( &(FileHandle->PersistTime) ); // Report result if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: File '%s' - Opened", ProcessName, Name, FileHandle->Name ); } } // Check if failed if (!isOpen(FileHandle)) { // Report result if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: File '%s' - Could not open (%d) %s", ProcessName, Name, FileHandle->Name, errno, strerror(errno) ); return false; } return true; } //--------------------------------------------------------------------------- bool CFileCore::CloseFile( TFileHandle * FileHandle ) { // Validate if (!FileHandle) { return false; } // Close file if not already open if (isOpen(FileHandle)) { // Close file close( FileHandle->FD ); FileHandle->FD = NO_FD; // Report result if (!isOpen(FileHandle)) { if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: File '%s' - Closed", ProcessName, Name, FileHandle->Name ); } else { if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: File '%s' - Could not close", ProcessName, Name, FileHandle->Name ); } } return true; } //--------------------------------------------------------------------------- int CFileCore::ReadFromFD( int FD, char * Data, int MaxLen ) { int BytesRead = 0; int TotalRead = 0; int DataRemain = MaxLen; bool Error = false; // Check if buffer created if ((FD == -1) || !Data) { return 0; } // Read Data into buffer while (DataRemain) { // Read from file descriptor BytesRead = read( FD, &Data[TotalRead], DataRemain ); if (BytesRead <= 0) { Error = true; errno = (!BytesRead)? 0 : errno; // No error if no bytes written break; } // Update Data Pointers TotalRead += BytesRead; DataRemain -= BytesRead; if (DataRemain) { usleep( 500 ); } } return (Error)? -TotalRead : TotalRead; // Report negative total on error } //--------------------------------------------------------------------------- int CFileCore::WriteToFD( int FD, const char * Data, int Len ) { int BytesWritten = 0; int TotalWritten = 0; int DataRemain = (Len != -1)? Len : (Data)? strlen(Data) : 0; bool Error = false; // Check if buffer created if ((FD == -1) || !DataRemain) { return 0; } // Read Data into buffer while (DataRemain) { // Read from file descriptor BytesWritten = write( FD, &Data[TotalWritten], DataRemain ); if ((BytesWritten <= 0) && (errno != EAGAIN)) { Error = true; errno = (!BytesWritten)? 0 : errno; // No error if no bytes written break; } // Update Data Pointers TotalWritten += BytesWritten; DataRemain -= BytesWritten; if (DataRemain) { usleep( 500 ); } } return (Error)? -TotalWritten : TotalWritten; // Report negative total on error } //--------------------------------------------------------------------------- // Manual Data Input/Output int CFileCore::Input( const char * ChannelName, const char * SourceRef, const char * Data, int Len ) { TFileHandle * FileHandle = NULL; int BytesWritten = 0; // Validate if (!ChannelName || !Data) { return 0; } else if (Len == -1) { Len = strlen( Data ); }; // Get Channel if (!(FileHandle = GetFile( ChannelName ))) { // Log event if (Log) Log->Message( LogLevel, dlHigh, "%s/%s: Channel '%s' - Input rejected, Channel not found", ProcessName, Name, ChannelName ); return 0; } // Log event if (Log) Log->Output( LogLevel, dlHigh, LogOutput, Data, Len, "%s/%s: Channel '%s' - IN:", ProcessName, Name, ChannelName ); // Open file if (!OpenFile( FileHandle )) { return 0; } // Handle Incoming data BytesWritten = WriteToFD( FileHandle->FD, Data, Len ); SetStartTime( &(FileHandle->PersistTime) ); // Return processed bytes return BytesWritten; } //--------------------------------------------------------------------------- bool CFileCore::Process() { TFileHandle * FileHandle; // Close Persistent files not used FileHandle = FirstFile; while (FileHandle) { if (isOpen(FileHandle) && (!FileHandle->Persistent || (FileHandle->PersistTimeout && Timeout( FileHandle->PersistTime, FileHandle->PersistTimeout )))) { CloseFile( FileHandle ); } // Next FileHandle = FileHandle->Next; } return true; } //---------------------------------------------------------------------------