Skip to content

Commit

Permalink
Fix nasa#139, move file writes to background task
Browse files Browse the repository at this point in the history
Implements a generic asynchronous "file write request" facility
in the FS subsystem.  Given a metadata/control block with the file
details and writer state and appropriate callbacks,, this will
execute the file write job as part of the ES background task.

The following file requests are changed to use this facility:
- ES ER Log dump
- SB Pipe Info
- SB Message Map
- SB Route Info
- TBL Registry Dump
  • Loading branch information
jphickey committed Feb 16, 2021
1 parent 6b9c267 commit 81cbc46
Show file tree
Hide file tree
Showing 25 changed files with 1,764 additions and 1,033 deletions.
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

0 comments on commit 81cbc46

Please sign in to comment.