Skip to content

Commit

Permalink
Fix nasa#2588, Split up CFE_TBL_Load and remove early returns
Browse files Browse the repository at this point in the history
  • Loading branch information
thnkslprpt committed Aug 9, 2024
1 parent dab2f42 commit ce52b70
Show file tree
Hide file tree
Showing 4 changed files with 325 additions and 172 deletions.
227 changes: 59 additions & 168 deletions modules/tbl/fsw/src/cfe_tbl_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ CFE_Status_t CFE_TBL_Register(CFE_TBL_Handle_t *TblHandlePtr, const char *Name,
{
CFE_TBL_TxnState_t Txn;
CFE_TBL_RegistryRec_t *RegRecPtr = NULL;
CFE_TBL_CritRegRec_t * CritRegRecPtr = NULL;
CFE_TBL_CritRegRec_t *CritRegRecPtr = NULL;
CFE_Status_t Status;
CFE_ES_AppId_t ThisAppId;
char AppName[OS_MAX_API_NAME] = {"UNKNOWN"};
Expand Down Expand Up @@ -214,7 +214,7 @@ CFE_Status_t CFE_TBL_Share(CFE_TBL_Handle_t *TblHandlePtr, const char *TblName)
int32 Status;
CFE_ES_AppId_t ThisAppId;
CFE_TBL_AccessDescriptor_t *AccessDescPtr = NULL;
CFE_TBL_RegistryRec_t * RegRecPtr = NULL;
CFE_TBL_RegistryRec_t *RegRecPtr = NULL;
char AppName[OS_MAX_API_NAME] = {"UNKNOWN"};

if (TblHandlePtr == NULL || TblName == NULL)
Expand Down Expand Up @@ -356,13 +356,14 @@ CFE_Status_t CFE_TBL_Unregister(CFE_TBL_Handle_t TblHandle)
CFE_Status_t CFE_TBL_Load(CFE_TBL_Handle_t TblHandle, CFE_TBL_SrcEnum_t SrcType, const void *SrcDataPtr)
{
CFE_TBL_TxnState_t Txn;
int32 Status;
CFE_Status_t Status;
CFE_ES_AppId_t ThisAppId;
CFE_TBL_LoadBuff_t * WorkingBufferPtr;
CFE_TBL_LoadBuff_t *WorkingBufferPtr = NULL;
CFE_TBL_AccessDescriptor_t *AccessDescPtr;
CFE_TBL_RegistryRec_t * RegRecPtr;
CFE_TBL_RegistryRec_t *RegRecPtr;
char AppName[OS_MAX_API_NAME] = {"UNKNOWN"};
bool FirstTime = false;
bool IsFirstTime;
bool StillProcessing = true;

if (SrcDataPtr == NULL)
{
Expand All @@ -377,212 +378,102 @@ CFE_Status_t CFE_TBL_Load(CFE_TBL_Handle_t TblHandle, CFE_TBL_SrcEnum_t SrcType,
CFE_EVS_SendEventWithAppID(CFE_TBL_HANDLE_ACCESS_ERR_EID, CFE_EVS_EventType_ERROR,
CFE_TBL_Global.TableTaskAppId, "%s: No access to Tbl Handle=%d", AppName,
(int)TblHandle);

return Status;
}

AccessDescPtr = CFE_TBL_TxnAccDesc(&Txn);
RegRecPtr = CFE_TBL_TxnRegRec(&Txn);
ThisAppId = CFE_TBL_TxnAppId(&Txn);

/*
* This is not the end of the transaction - this is just put here for now
* until the many inline "return" statements in this function can be cleaned up.
*
* This means nearly everything is subject to race conditions, but it is no worse
* than it had been before.
*/
CFE_TBL_TxnFinish(&Txn);

/* Translate AppID of caller into App Name */
CFE_ES_GetAppName(AppName, ThisAppId, sizeof(AppName));

/* Initialize return pointer to NULL */
WorkingBufferPtr = NULL;

/* Check to see if this is a dump only table */
if (RegRecPtr->DumpOnly)
{
if ((!RegRecPtr->UserDefAddr) || (RegRecPtr->TableLoadedOnce))
{
CFE_EVS_SendEventWithAppID(CFE_TBL_LOADING_A_DUMP_ONLY_ERR_EID, CFE_EVS_EventType_ERROR,
CFE_TBL_Global.TableTaskAppId, "%s: Attempted to load Dump Only Tbl '%s'",
AppName, RegRecPtr->Name);

return CFE_TBL_ERR_DUMP_ONLY;
}
Status = CFE_TBL_LoadDumpOnlyTable(RegRecPtr, AppName, SrcDataPtr);

/* The Application is allowed to call Load once when the address */
/* of the dump only table is being defined by the application. */
RegRecPtr->Buffers[0].BufferPtr = (void *)SrcDataPtr;
RegRecPtr->TableLoadedOnce = true;

snprintf(RegRecPtr->Buffers[0].DataSource, sizeof(RegRecPtr->Buffers[0].DataSource), "Addr 0x%08lX",
(unsigned long)SrcDataPtr);

RegRecPtr->Buffers[0].FileTime = CFE_TIME_ZERO_VALUE;

CFE_EVS_SendEventWithAppID(CFE_TBL_LOAD_SUCCESS_INF_EID, CFE_EVS_EventType_DEBUG, CFE_TBL_Global.TableTaskAppId,
"Successfully loaded '%s' from '%s'", RegRecPtr->Name,
RegRecPtr->Buffers[0].DataSource);

return CFE_SUCCESS;
StillProcessing = false;
}

/* Loads by an Application are not allowed if a table load is already in progress */
if (RegRecPtr->LoadInProgress != CFE_TBL_NO_LOAD_IN_PROGRESS)
if (StillProcessing && RegRecPtr->LoadInProgress != CFE_TBL_NO_LOAD_IN_PROGRESS)
{
CFE_EVS_SendEventWithAppID(CFE_TBL_LOAD_IN_PROGRESS_ERR_EID, CFE_EVS_EventType_ERROR,
CFE_TBL_Global.TableTaskAppId, "%s: Load already in progress for '%s'", AppName,
RegRecPtr->Name);

return CFE_TBL_ERR_LOAD_IN_PROGRESS;
}

/* Obtain a working buffer (either the table's dedicated buffer or one of the shared buffers) */
Status = CFE_TBL_GetWorkingBuffer(&WorkingBufferPtr, RegRecPtr, true);

if (Status != CFE_SUCCESS)
{
CFE_EVS_SendEventWithAppID(CFE_TBL_NO_WORK_BUFFERS_ERR_EID, CFE_EVS_EventType_ERROR,
CFE_TBL_Global.TableTaskAppId, "%s: Failed to get Working Buffer (Stat=%u)", AppName,
(unsigned int)Status);
Status = CFE_TBL_ERR_LOAD_IN_PROGRESS;

return Status;
StillProcessing = false;
}

/* Perform appropriate update to working buffer */
/* Determine whether the load is to occur from a file or from a block of memory */
switch (SrcType)
if (StillProcessing)
{
case CFE_TBL_SRC_FILE:
/* Load the data from the file into the specified buffer */
Status = CFE_TBL_LoadFromFile(AppName, WorkingBufferPtr, RegRecPtr, (const char *)SrcDataPtr);

if ((Status == CFE_TBL_WARN_PARTIAL_LOAD) && (!RegRecPtr->TableLoadedOnce))
{
/* Uninitialized tables cannot be loaded with partial table loads */
/* Partial loads can only occur on previously loaded tables. */
CFE_EVS_SendEventWithAppID(CFE_TBL_PARTIAL_LOAD_ERR_EID, CFE_EVS_EventType_ERROR,
CFE_TBL_Global.TableTaskAppId,
"%s: Attempted to load from partial Tbl '%s' from '%s' (Stat=%u)", AppName,
RegRecPtr->Name, (const char *)SrcDataPtr, (unsigned int)Status);

Status = CFE_TBL_ERR_PARTIAL_LOAD;
}

break;
case CFE_TBL_SRC_ADDRESS:
/* When the source is a block of memory, it is assumed to be a complete load */
memcpy(WorkingBufferPtr->BufferPtr, (uint8 *)SrcDataPtr, RegRecPtr->Size);

snprintf(WorkingBufferPtr->DataSource, sizeof(WorkingBufferPtr->DataSource), "Addr 0x%08lX",
(unsigned long)SrcDataPtr);

WorkingBufferPtr->FileTime = CFE_TIME_ZERO_VALUE;

/* Compute the CRC on the specified table buffer */
WorkingBufferPtr->Crc =
CFE_ES_CalculateCRC(WorkingBufferPtr->BufferPtr, RegRecPtr->Size, 0, CFE_MISSION_ES_DEFAULT_CRC);
/* Obtain a working buffer (either the table's dedicated buffer or one of the shared buffers) */
Status = CFE_TBL_GetWorkingBuffer(&WorkingBufferPtr, RegRecPtr, true);

break;
default:
CFE_EVS_SendEventWithAppID(CFE_TBL_LOAD_TYPE_ERR_EID, CFE_EVS_EventType_ERROR,
CFE_TBL_Global.TableTaskAppId,
"%s: Attempted to load from illegal source type=%d", AppName, (int)SrcType);
if (Status != CFE_SUCCESS)
{
CFE_EVS_SendEventWithAppID(CFE_TBL_NO_WORK_BUFFERS_ERR_EID, CFE_EVS_EventType_ERROR,
CFE_TBL_Global.TableTaskAppId, "%s: Failed to get Working Buffer (Stat=%u)",
AppName, (unsigned int)Status);

Status = CFE_TBL_ERR_ILLEGAL_SRC_TYPE;
StillProcessing = false;
}
}

/* If the data was successfully loaded, then validate its contents */
if ((Status >= CFE_SUCCESS) && (RegRecPtr->ValidationFuncPtr != NULL))
if (StillProcessing)
{
Status = (RegRecPtr->ValidationFuncPtr)(WorkingBufferPtr->BufferPtr);
/* Perform appropriate update to working buffer */
/* Determine whether the load is to occur from a file or from a block of memory */
Status = CFE_TBL_LoadWorkingBuffer(SrcType, AppName, WorkingBufferPtr, RegRecPtr, SrcDataPtr);

if (Status > CFE_SUCCESS)
/* If the data was successfully loaded, then validate its contents */
if ((Status >= CFE_SUCCESS) && (RegRecPtr->ValidationFuncPtr != NULL))
{
CFE_EVS_SendEventWithAppID(CFE_TBL_LOAD_VAL_ERR_EID, CFE_EVS_EventType_ERROR, CFE_TBL_Global.TableTaskAppId,
"%s: Validation func return code invalid (Stat=%u) for '%s'", AppName,
(unsigned int)Status, RegRecPtr->Name);

Status = -1;
Status = CFE_TBL_ValidateWorkingBufferContents(RegRecPtr, WorkingBufferPtr, AppName);
}

if (Status < 0)
// Free the working buffer if there was an error up to this point
if (Status < CFE_SUCCESS)
{
CFE_EVS_SendEventWithAppID(CFE_TBL_VALIDATION_ERR_EID, CFE_EVS_EventType_ERROR,
CFE_TBL_Global.TableTaskAppId,
"%s: Validation func reports table invalid (Stat=%u) for '%s'", AppName,
(unsigned int)Status, RegRecPtr->Name);
/* The load has had a problem, free the working buffer for another attempt */
if ((!RegRecPtr->DoubleBuffered) && (RegRecPtr->TableLoadedOnce == true))
{
/* For single-buffered tables, freeing entails resetting flag */
CFE_TBL_Global.LoadBuffs[RegRecPtr->LoadInProgress].Taken = false;
}

/* Zero out the buffer to remove any bad data */
memset(WorkingBufferPtr->BufferPtr, 0, RegRecPtr->Size);
}
}
/* For double-buffered tables, freeing buffer is simple */
RegRecPtr->LoadInProgress = CFE_TBL_NO_LOAD_IN_PROGRESS;

/* Perform the table update to complete the load */
if (Status < CFE_SUCCESS)
{
/* The load has had a problem, free the working buffer for another attempt */
if ((!RegRecPtr->DoubleBuffered) && (RegRecPtr->TableLoadedOnce == true))
{
/* For single-buffered tables, freeing entails resetting flag */
CFE_TBL_Global.LoadBuffs[RegRecPtr->LoadInProgress].Taken = false;
StillProcessing = false;
}

/* For double-buffered tables, freeing buffer is simple */
RegRecPtr->LoadInProgress = CFE_TBL_NO_LOAD_IN_PROGRESS;

return Status;
}

FirstTime = !RegRecPtr->TableLoadedOnce;

/* If this is not the first load, then the data must be moved from the inactive buffer */
/* to the active buffer to complete the load. First loads are done directly to the active. */
if (!FirstTime)
if (StillProcessing)
{
/* Force the table update */
RegRecPtr->LoadPending = true;
IsFirstTime = !RegRecPtr->TableLoadedOnce;

Status = CFE_TBL_UpdateInternal(TblHandle, RegRecPtr, AccessDescPtr);
/* Perform the table update to complete the load */
Status = CFE_TBL_PerformUpdate(RegRecPtr, TblHandle, AccessDescPtr, AppName, WorkingBufferPtr, IsFirstTime);

if (Status != CFE_SUCCESS)
if (Status == CFE_SUCCESS)
{
CFE_EVS_SendEventWithAppID(CFE_TBL_UPDATE_ERR_EID, CFE_EVS_EventType_ERROR, CFE_TBL_Global.TableTaskAppId,
"%s: Failed to update '%s' (Stat=%u)", AppName, RegRecPtr->Name,
(unsigned int)Status);
}
}
else
{
/* On initial loads, make sure registry is given file/address of data source */
strncpy(RegRecPtr->LastFileLoaded, WorkingBufferPtr->DataSource, sizeof(RegRecPtr->LastFileLoaded) - 1);
RegRecPtr->LastFileLoaded[sizeof(RegRecPtr->LastFileLoaded) - 1] = '\0';

CFE_TBL_NotifyTblUsersOfUpdate(RegRecPtr);
/* The first time a table is loaded, the event message is DEBUG */
/* to help eliminate a flood of events during a startup */
CFE_EVS_SendEventWithAppID(CFE_TBL_LOAD_SUCCESS_INF_EID,
IsFirstTime ? CFE_EVS_EventType_DEBUG : CFE_EVS_EventType_INFORMATION,
CFE_TBL_Global.TableTaskAppId, "Successfully loaded '%s' from '%s'",
RegRecPtr->Name, RegRecPtr->LastFileLoaded);

/* If the table is a critical table, update the appropriate CDS with the new data */
if (RegRecPtr->CriticalTable == true)
{
CFE_TBL_UpdateCriticalTblCDS(RegRecPtr);
/* Save the index of the table for housekeeping telemetry */
CFE_TBL_Global.LastTblUpdated = AccessDescPtr->RegIndex;
}

Status = CFE_SUCCESS;
}

if (Status == CFE_SUCCESS)
{
/* The first time a table is loaded, the event message is DEBUG */
/* to help eliminate a flood of events during a startup */
CFE_EVS_SendEventWithAppID(CFE_TBL_LOAD_SUCCESS_INF_EID,
FirstTime ? CFE_EVS_EventType_DEBUG : CFE_EVS_EventType_INFORMATION,
CFE_TBL_Global.TableTaskAppId, "Successfully loaded '%s' from '%s'", RegRecPtr->Name,
RegRecPtr->LastFileLoaded);

/* Save the index of the table for housekeeping telemetry */
CFE_TBL_Global.LastTblUpdated = AccessDescPtr->RegIndex;
}
CFE_TBL_TxnFinish(&Txn);

return Status;
}
Expand All @@ -598,7 +489,7 @@ CFE_Status_t CFE_TBL_Update(CFE_TBL_Handle_t TblHandle)
CFE_TBL_TxnState_t Txn;
int32 Status;
CFE_ES_AppId_t ThisAppId;
CFE_TBL_RegistryRec_t * RegRecPtr = NULL;
CFE_TBL_RegistryRec_t *RegRecPtr = NULL;
CFE_TBL_AccessDescriptor_t *AccessDescPtr = NULL;
char AppName[OS_MAX_API_NAME] = {"UNKNOWN"};

Expand Down Expand Up @@ -841,11 +732,11 @@ CFE_Status_t CFE_TBL_Validate(CFE_TBL_Handle_t TblHandle)
{
CFE_TBL_TxnState_t Txn;
int32 Status;
CFE_TBL_RegistryRec_t * RegRecPtr;
CFE_TBL_RegistryRec_t *RegRecPtr;
char AppName[OS_MAX_API_NAME] = {"UNKNOWN"};
CFE_TBL_LoadBuff_t * BuffPtr;
CFE_TBL_LoadBuff_t *BuffPtr;
CFE_TBL_ValidationResult_t *ResultPtr;
const char * LogTagStr;
const char *LogTagStr;

ResultPtr = NULL;
BuffPtr = NULL;
Expand Down Expand Up @@ -1096,7 +987,7 @@ CFE_Status_t CFE_TBL_DumpToBuffer(CFE_TBL_Handle_t TblHandle)
int32 Status;
CFE_TBL_RegistryRec_t *RegRecPtr = NULL;
CFE_TBL_DumpControl_t *DumpCtrlPtr = NULL;
CFE_TBL_LoadBuff_t * ActiveBufPtr;
CFE_TBL_LoadBuff_t *ActiveBufPtr;

Status = CFE_TBL_TxnStartFromHandle(&Txn, TblHandle, CFE_TBL_TxnContext_ACCESSOR_APP);

Expand Down
Loading

0 comments on commit ce52b70

Please sign in to comment.