Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #139, Do file writes in background #1148

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions fsw/cfe-core/src/es/cfe_es_apps.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,14 @@ bool CFE_ES_RunAppTableScan(uint32 ElapsedTime, void *Arg);
bool CFE_ES_RunExceptionScan(uint32 ElapsedTime, void *Arg);

/*
** Check if ER log dump request is pending
*/
bool CFE_ES_RunERLogDump(uint32 ElapsedTime, void *Arg);
* Background file write data getter for ER log entry
*/
bool CFE_ES_BackgroundERLogFileDataGetter(void *Meta, uint32 RecordNum, void **Buffer, size_t *BufSize);

/*
* Background file write event handler for ER log entry
*/
void CFE_ES_BackgroundERLogFileEventHandler(void *Meta, CFE_FS_FileWriteEvent_t Event, int32 Status, uint32 RecordNum, size_t BlockSize, size_t Position);

/*
** Perform the requested control action for an application
Expand Down
6 changes: 3 additions & 3 deletions fsw/cfe-core/src/es/cfe_es_backgroundtask.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ const CFE_ES_BackgroundJobEntry_t CFE_ES_BACKGROUND_JOB_TABLE[] =
.ActivePeriod = CFE_PLATFORM_ES_APP_SCAN_RATE,
.IdlePeriod = CFE_PLATFORM_ES_APP_SCAN_RATE
},
{ /* Check for ER log write requests */
.RunFunc = CFE_ES_RunERLogDump,
.JobArg = &CFE_ES_TaskData.BackgroundERLogDumpState,
{ /* Call FS to handle background file writes */
.RunFunc = CFE_FS_RunBackgroundFileDump,
.JobArg = NULL,
.ActivePeriod = CFE_PLATFORM_ES_APP_SCAN_RATE,
.IdlePeriod = CFE_PLATFORM_ES_APP_SCAN_RATE
}
Expand Down
186 changes: 89 additions & 97 deletions fsw/cfe-core/src/es/cfe_es_erlog.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,126 +181,118 @@ int32 CFE_ES_WriteToERLog( CFE_ES_LogEntryType_Enum_t EntryType, uint32 Reset
} /* End of CFE_ES_WriteToERLog() */

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Function: CFE_ES_RunERLogDump() */
/* Function: CFE_ES_BackgroundERLogFileDataGetter() */
/* */
/* Purpose: */
/* Write exception & reset log to a file. */
/* */
/* Implemented as an ES background job, but the entire file write is done */
/* in a single invocation, as the file is expected to be relatively small. */
/* Gets a single record from exception & reset log to write to a file. */
/* */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool CFE_ES_RunERLogDump(uint32 ElapsedTime, void *Arg)
bool CFE_ES_BackgroundERLogFileDataGetter(void *Meta, uint32 RecordNum, void **Buffer, size_t *BufSize)
{
CFE_ES_BackgroundLogDumpGlobal_t *State = (CFE_ES_BackgroundLogDumpGlobal_t *)Arg;
int32 Status;
int32 PspStatus;
CFE_FS_Header_t FileHdr;
CFE_ES_ERLog_FileEntry_t FileEntry;
CFE_ES_BackgroundLogDumpGlobal_t *BgFilePtr;
CFE_ES_ERLog_FileEntry_t *FileBufferPtr;
CFE_ES_ERLog_MetaData_t *EntryPtr;
uint32 FileSize;
uint32 i;
osal_id_t fd;

int32 PspStatus;

BgFilePtr = (CFE_ES_BackgroundLogDumpGlobal_t *)Meta;
FileBufferPtr = &BgFilePtr->EntryBuffer;

if (!State->IsPending)
if (RecordNum < CFE_PLATFORM_ES_ER_LOG_ENTRIES)
{
return false;
}
EntryPtr = &CFE_ES_ResetDataPtr->ERLog[RecordNum];

FileSize = 0;
Status = OS_OpenCreate(&fd, State->DataFileName, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY);
if(Status < 0)
{
CFE_EVS_SendEvent(CFE_ES_ERLOG2_ERR_EID,CFE_EVS_EventType_ERROR,
"Error creating file %s, RC = %d",
State->DataFileName, (int)Status);
}
else
{
CFE_FS_InitHeader(&FileHdr, CFE_ES_ER_LOG_DESC, CFE_FS_SubType_ES_ERLOG);
/* First wipe the buffer before re-use */
memset(FileBufferPtr, 0, sizeof(*FileBufferPtr));

CFE_ES_LockSharedData(__func__,__LINE__);

/* The basic info comes directly from the ES log */
FileBufferPtr->BaseInfo = EntryPtr->BaseInfo;

/* write the cFE header to the file */
Status = CFE_FS_WriteHeader(fd, &FileHdr);
if(Status != sizeof(CFE_FS_Header_t))
/*
* The context info, if available, comes from the PSP.
* This returns the actual size of the context info, or <0 on error.
*/
PspStatus = CFE_PSP_Exception_CopyContext(EntryPtr->PspContextId, &FileBufferPtr->Context,
sizeof(FileBufferPtr->Context));
if (PspStatus > 0)
{
CFE_ES_FileWriteByteCntErr(State->DataFileName,sizeof(CFE_FS_Header_t),Status);
FileBufferPtr->ContextSize = PspStatus;
}
else
{
FileSize += Status;

/* write a single ER log entry on each pass */
for(i=0;i<CFE_PLATFORM_ES_ER_LOG_ENTRIES;i++)
{
EntryPtr = &CFE_ES_ResetDataPtr->ERLog[i];

/* The basic info comes directly from the ES log */
FileEntry.BaseInfo = EntryPtr->BaseInfo;

/*
* The context info, if available, comes from the PSP.
* This returns the actual size of the context info, or <0 on error.
*/
PspStatus = CFE_PSP_Exception_CopyContext(EntryPtr->PspContextId, &FileEntry.Context, sizeof(FileEntry.Context));
if (PspStatus > 0)
{
FileEntry.ContextSize = PspStatus;
}
else
{
/*
* errors here are OK - just means there is no context available.
* Record a size of 0 in the log file.
*/
FileEntry.ContextSize = 0;
}

/*
* any unused context space should be cleared.
*
* This is for binary compatibility with historical log files, where a fixed amount
* of space is given per-entry, regardless of the actual size.
*/
if (FileEntry.ContextSize < sizeof(FileEntry.Context))
{
memset(&FileEntry.Context[FileEntry.ContextSize], 0,
sizeof(FileEntry.Context) - FileEntry.ContextSize);
}

/*
* Now write to file
*/
Status = OS_write(fd,&FileEntry,sizeof(FileEntry));

if(Status != sizeof(FileEntry))
{
CFE_ES_FileWriteByteCntErr(State->DataFileName,sizeof(FileEntry),Status);
break;
}/* end if */
/*
* errors here are OK - just means there is no context available.
* Record a size of 0 in the log file.
*/
FileBufferPtr->ContextSize = 0;
}

FileSize += Status;
CFE_ES_UnlockSharedData(__func__,__LINE__);

} /* end for */
/*
* Export data to caller for actual write
*/
*Buffer = FileBufferPtr;
*BufSize = sizeof(*FileBufferPtr);
}
else
{
*Buffer = NULL;
*BufSize = 0;
}

} /* end if */
/* Check for EOF (last entry) */
return (RecordNum >= (CFE_PLATFORM_ES_ER_LOG_ENTRIES-1));
}

OS_close(fd);

CFE_EVS_SendEvent(CFE_ES_ERLOG2_EID, CFE_EVS_EventType_DEBUG,
"%s written:Size=%lu",State->DataFileName,(unsigned long)FileSize);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Function: CFE_ER_BackgroundERLogFileEventHandler() */
/* */
/* Purpose: */
/* Report events during writing exception & reset log to a file. */
/* */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void CFE_ES_BackgroundERLogFileEventHandler(void *Meta, CFE_FS_FileWriteEvent_t Event, int32 Status, uint32 RecordNum, size_t BlockSize, size_t Position)
{
CFE_ES_BackgroundLogDumpGlobal_t *BgFilePtr;

} /* end if */
BgFilePtr = (CFE_ES_BackgroundLogDumpGlobal_t *)Meta;

/*
* Always clear the "pending" flag whether successful or not.
* If unsuccessful, an operator needs to investigate the error and re-issue command.
* Note that this runs in the context of ES background task (file writer background job)
* It does NOT run in the context of the CFE_TBL app task.
*
* Events should use CFE_EVS_SendEventWithAppID() rather than CFE_EVS_SendEvent()
* to get proper association with TBL task.
*/
State->IsPending = false;

return false;
}/* end CFE_ES_RunERLogDump */

switch(Event)
{
case CFE_FS_FileWriteEvent_COMPLETE:
CFE_EVS_SendEvent(CFE_ES_ERLOG2_EID, CFE_EVS_EventType_DEBUG,
"%s written:Size=%lu",
BgFilePtr->FileWrite.FileName,(unsigned long)Position);
break;

case CFE_FS_FileWriteEvent_HEADER_WRITE_ERROR:
case CFE_FS_FileWriteEvent_RECORD_WRITE_ERROR:
CFE_EVS_SendEvent(CFE_ES_FILEWRITE_ERR_EID,CFE_EVS_EventType_ERROR,
"File write,byte cnt err,file %s,request=%u,actual=%u",
BgFilePtr->FileWrite.FileName, (int)BlockSize, (int)Status);
break;

case CFE_FS_FileWriteEvent_CREATE_ERROR:
CFE_EVS_SendEvent(CFE_ES_ERLOG2_ERR_EID,CFE_EVS_EventType_ERROR,
"Error creating file %s, RC = %d",
BgFilePtr->FileWrite.FileName, (int)Status);
break;

default:
/* unhandled event - ignore */
break;
}
}

/*
**---------------------------------------------------------------------------------------
Expand Down
45 changes: 35 additions & 10 deletions fsw/cfe-core/src/es/cfe_es_task.c
Original file line number Diff line number Diff line change
Expand Up @@ -1612,26 +1612,51 @@ int32 CFE_ES_ClearERLogCmd(const CFE_ES_ClearERLogCmd_t *data)
int32 CFE_ES_WriteERLogCmd(const CFE_ES_WriteERLogCmd_t *data)
{
const CFE_ES_FileNameCmd_Payload_t *CmdPtr = &data->Payload;
CFE_ES_BackgroundLogDumpGlobal_t *StatePtr;
int32 Status;

StatePtr = &CFE_ES_TaskData.BackgroundERLogDumpState;

/* check if pending before overwriting fields in the structure */
if (CFE_FS_BackgroundFileDumpIsPending(&StatePtr->FileWrite))
{
Status = CFE_STATUS_REQUEST_ALREADY_PENDING;
}
else
{
/* Reset the entire state object (just for good measure, ensure no stale data) */
memset(StatePtr, 0, sizeof(*StatePtr));

/*
* Fill out the remainder of meta data.
* This data is currently the same for every request
*/
StatePtr->FileWrite.FileSubType = CFE_FS_SubType_ES_ERLOG;
snprintf(StatePtr->FileWrite.Description, sizeof(StatePtr->FileWrite.Description), CFE_ES_ER_LOG_DESC);

StatePtr->FileWrite.GetData = CFE_ES_BackgroundERLogFileDataGetter;
StatePtr->FileWrite.OnEvent = CFE_ES_BackgroundERLogFileEventHandler;

if (CFE_ES_TaskData.BackgroundERLogDumpState.IsPending)
CFE_SB_MessageStringGet(StatePtr->FileWrite.FileName, CmdPtr->FileName,
CFE_PLATFORM_ES_DEFAULT_ER_LOG_FILE,
sizeof(StatePtr->FileWrite.FileName), sizeof(CmdPtr->FileName));

Status = CFE_FS_BackgroundFileDumpRequest(&StatePtr->FileWrite);
}

if (Status != CFE_SUCCESS)
{
CFE_EVS_SendEvent(CFE_ES_ERLOG_PENDING_ERR_EID,CFE_EVS_EventType_ERROR,
"Error log write to file %s already in progress",
CFE_ES_TaskData.BackgroundERLogDumpState.DataFileName);
StatePtr->FileWrite.FileName);

/* background dump already running, consider this an error */
CFE_ES_TaskData.CommandErrorCounter++;
}
}
else
{
CFE_SB_MessageStringGet(CFE_ES_TaskData.BackgroundERLogDumpState.DataFileName, (char *)CmdPtr->FileName,
CFE_PLATFORM_ES_DEFAULT_ER_LOG_FILE,
sizeof(CFE_ES_TaskData.BackgroundERLogDumpState.DataFileName), sizeof(CmdPtr->FileName));

CFE_ES_TaskData.BackgroundERLogDumpState.IsPending = true;
CFE_ES_TaskData.CommandCounter++;
CFE_ES_BackgroundWakeup();
}
}

return CFE_SUCCESS;
}/* end CFE_ES_WriteERLogCmd */
Expand Down
6 changes: 3 additions & 3 deletions fsw/cfe-core/src/es/cfe_es_task.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "cfe_es_events.h"
#include "cfe_es_msg.h"
#include "cfe_es_perf.h"
#include "private/cfe_es_erlog_typedef.h"

/*************************************************************************/

Expand Down Expand Up @@ -90,8 +91,8 @@
*/
typedef struct
{
volatile bool IsPending;
char DataFileName[OS_MAX_PATH_LEN];
CFE_FS_FileWriteMetaData_t FileWrite; /**< FS state data - must be first */
CFE_ES_ERLog_FileEntry_t EntryBuffer; /**< Temp holding area for record to write */
} CFE_ES_BackgroundLogDumpGlobal_t;

/*
Expand Down Expand Up @@ -164,7 +165,6 @@ void CFE_ES_TaskPipe(CFE_SB_Buffer_t *SBBufPtr);
*/
int32 CFE_ES_BackgroundInit(void);
void CFE_ES_BackgroundTask(void);
void CFE_ES_BackgroundWakeup(void);
void CFE_ES_BackgroundCleanup(void);

/*
Expand Down
Loading