Skip to content
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
6 changes: 3 additions & 3 deletions fsw/src/cf_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ void CF_CmdWriteQueue(CFE_SB_Buffer_t *msg)
/* process uplink queue data */
if ((wq->queue == q_all) || (wq->queue == q_active))
{
ret = CF_WriteQueueDataToFile(fd, c, CF_QueueIdx_RX);
ret = CF_WriteTxnQueueDataToFile(fd, c, CF_QueueIdx_RX);
if (ret)
{
CFE_EVS_SendEvent(CF_EID_ERR_CMD_WQ_WRITEQ_RX, CFE_EVS_EventType_ERROR,
Expand Down Expand Up @@ -747,7 +747,7 @@ void CF_CmdWriteQueue(CFE_SB_Buffer_t *msg)
static const int qs[2] = {CF_QueueIdx_TXA, CF_QueueIdx_TXW};
for (i = 0; i < 2; ++i)
{
ret = CF_WriteQueueDataToFile(fd, c, qs[i]);
ret = CF_WriteTxnQueueDataToFile(fd, c, qs[i]);
if (ret)
{
CFE_EVS_SendEvent(CF_EID_ERR_CMD_WQ_WRITEQ_TX, CFE_EVS_EventType_ERROR,
Expand All @@ -760,7 +760,7 @@ void CF_CmdWriteQueue(CFE_SB_Buffer_t *msg)
if ((wq->queue == q_all) || (wq->queue == q_pend))
{
/* write pending queue */
ret = CF_WriteQueueDataToFile(fd, c, CF_QueueIdx_PEND);
ret = CF_WriteTxnQueueDataToFile(fd, c, CF_QueueIdx_PEND);
if (ret)
{
CFE_EVS_SendEvent(CF_EID_ERR_CMD_WQ_WRITEQ_PEND, CFE_EVS_EventType_ERROR,
Expand Down
126 changes: 86 additions & 40 deletions fsw/src/cf_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@

#include "cf_assert.h"

#define LINEBUF_LEN ((CF_FILENAME_MAX_LEN * 2) + 128)

/*----------------------------------------------------------------
*
* Function: CF_FindUnusedTransaction
Expand Down Expand Up @@ -174,81 +172,123 @@ CF_Transaction_t *CF_FindTransactionBySequenceNumber(CF_Channel_t *c, CF_Transac

/*----------------------------------------------------------------
*
* Function: CF_TraverseHistory
* Function: CF_WriteHistoryEntryToFile
*
* Application-scope internal function
* See description in cf_utils.h for argument/return detail
*
*-----------------------------------------------------------------*/
int CF_TraverseHistory(CF_CListNode_t *n, CF_Traverse_WriteFileArg_t *context)
int CF_WriteHistoryEntryToFile(osal_id_t fd, const CF_History_t *h)
{
static const char *dstr[] = {"RX", "TX"};
int i;
int32 ret;
int32 len;
char linebuf[LINEBUF_LEN]; /* buffer for line data */
CF_History_t *h = container_of(n, CF_History_t, cl_node);

CF_Assert(h->dir < CF_Direction_NUM);
len = snprintf(linebuf, sizeof(linebuf) - 1, "SEQ (%d, %d)\tDIR: %s\tPEER %d\tCC: %d", h->src_eid, h->seq_num,
dstr[h->dir], h->peer_eid, h->cc);
for (i = 0; i < 2; ++i)
static const char *CF_DSTR[] = {"RX", "TX"}; /* conversion of CF_Direction_t to string */

int i;
int32 ret;
int32 len;
char linebuf[(CF_FILENAME_MAX_LEN * 2) + 128]; /* buffer for line data */

for (i = 0; i < 3; ++i)
{
static const char *fstr[] = {"SRC: %s", "DST: %s"};
const char *fnames[] = {h->fnames.src_filename, h->fnames.dst_filename};
len = snprintf(linebuf, sizeof(linebuf) - 1, fstr[i], fnames[i]);
ret = CF_WrappedWrite(context->fd, linebuf, len);
switch (i)
{
case 0:
CF_Assert(h->dir < CF_Direction_NUM);
snprintf(linebuf, sizeof(linebuf), "SEQ (%lu, %lu)\tDIR: %s\tPEER %lu\tCC: %u\t",
(unsigned long)h->src_eid, (unsigned long)h->seq_num, CF_DSTR[h->dir],
(unsigned long)h->peer_eid, (unsigned int)h->cc);
break;
case 1:
snprintf(linebuf, sizeof(linebuf), "SRC: %s\t", h->fnames.src_filename);
break;
case 2:
snprintf(linebuf, sizeof(linebuf), "DST: %s\n", h->fnames.dst_filename);
break;
}

len = strlen(linebuf);
ret = CF_WrappedWrite(fd, linebuf, len);
if (ret != len)
{
context->result = 1; /* failed */
CFE_EVS_SendEvent(CF_EID_ERR_CMD_WHIST_WRITE, CFE_EVS_EventType_ERROR,
"CF: writing queue file failed, expected 0x%08x got 0x%08x", len, ret);
"CF: writing queue file failed, expected %ld got %ld", (long)len, (long)ret);
return -1;
}
}

return 0;
}

/*----------------------------------------------------------------
*
* Function: CF_Traverse_WriteHistoryQueueEntryToFile
*
* Application-scope internal function
* See description in cf_utils.h for argument/return detail
*
*-----------------------------------------------------------------*/
int CF_Traverse_WriteHistoryQueueEntryToFile(CF_CListNode_t *n, void *arg)
{
CF_Traverse_WriteHistoryFileArg_t *context = arg;
CF_History_t *h = container_of(n, CF_History_t, cl_node);

/* if filter_dir is CF_Direction_NUM, this means both directions (all match) */
if (context->filter_dir == CF_Direction_NUM || h->dir == context->filter_dir)
{
if (CF_WriteHistoryEntryToFile(context->fd, h) < 0)
{
/* failed */
context->error = true;
return CF_CLIST_EXIT;
}

++context->counter;
}

return CF_CLIST_CONT;
}

/*----------------------------------------------------------------
*
* Function: CF_TraverseTransactions
* Function: CF_Traverse_WriteTxnQueueEntryToFile
*
* Application-scope internal function
* See description in cf_utils.h for argument/return detail
*
*-----------------------------------------------------------------*/
int CF_TraverseTransactions(CF_CListNode_t *n, CF_Traverse_WriteFileArg_t *context)
int CF_Traverse_WriteTxnQueueEntryToFile(CF_CListNode_t *n, void *arg)
{
CF_Transaction_t *t = container_of(n, CF_Transaction_t, cl_node);
CF_Traverse_WriteTxnFileArg_t *context = arg;
CF_Transaction_t *t = container_of(n, CF_Transaction_t, cl_node);

/* use CF_TraverseHistory to print filenames and direction */
/* NOTE: ok to ignore return value of CF_TraverseHistory. We care
* about the value in context->result. The reason for this confusion
* is CF_TraverseHistory is also a list traversal function. In this
* function we are just calling it directly. */
/* ignore return value */ CF_TraverseHistory(&t->history->cl_node, context);
if (context->result)
if (CF_WriteHistoryEntryToFile(context->fd, t->history) < 0)
{
/* failed */
context->error = true;
return CF_CLIST_EXIT;
}

++context->counter;
return CF_CLIST_CONT;
}

/*----------------------------------------------------------------
*
* Function: CF_WriteQueueDataToFile
* Function: CF_WriteTxnQueueDataToFile
*
* Application-scope internal function
* See description in cf_utils.h for argument/return detail
*
*-----------------------------------------------------------------*/
int32 CF_WriteQueueDataToFile(int32 fd, CF_Channel_t *c, CF_QueueIdx_t q)
int32 CF_WriteTxnQueueDataToFile(osal_id_t fd, CF_Channel_t *c, CF_QueueIdx_t q)
{
CF_Traverse_WriteFileArg_t arg = {fd, 0, 0};
CF_CList_Traverse(c->qs[q], (CF_CListFn_t)CF_TraverseTransactions, &arg);
return arg.result;
CF_Traverse_WriteTxnFileArg_t arg;

arg.fd = fd;
arg.error = false;
arg.counter = 0;

CF_CList_Traverse(c->qs[q], CF_Traverse_WriteTxnQueueEntryToFile, &arg);
return arg.error;
}

/*----------------------------------------------------------------
Expand All @@ -259,11 +299,17 @@ int32 CF_WriteQueueDataToFile(int32 fd, CF_Channel_t *c, CF_QueueIdx_t q)
* See description in cf_utils.h for argument/return detail
*
*-----------------------------------------------------------------*/
int32 CF_WriteHistoryQueueDataToFile(int32 fd, CF_Channel_t *c, CF_Direction_t dir)
int32 CF_WriteHistoryQueueDataToFile(osal_id_t fd, CF_Channel_t *c, CF_Direction_t dir)
{
CF_Traverse_WriteFileArg_t arg = {fd, 0, 0};
CF_CList_Traverse(c->qs[CF_QueueIdx_HIST], (CF_CListFn_t)CF_TraverseHistory, &arg);
return arg.result;
CF_Traverse_WriteHistoryFileArg_t arg;

arg.fd = fd;
arg.filter_dir = dir;
arg.error = false;
arg.counter = 0;

CF_CList_Traverse(c->qs[CF_QueueIdx_HIST], CF_Traverse_WriteHistoryQueueEntryToFile, &arg);
return arg.error;
}

/*----------------------------------------------------------------
Expand Down
85 changes: 67 additions & 18 deletions fsw/src/cf_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,40 @@ typedef struct CF_Traverse_TransSeqArg
} CF_Traverse_TransSeqArg_t;

/**
* @brief Argument structure for use with CList_Traverse()
* @brief Argument structure for use with CF_Traverse_WriteHistoryQueueEntryToFile()
*
* This is used for writing status files. It contains a designated
* file descriptor for output and counters.
*
* When traversing history, the list contains all entries, and may need additional
* filtering for direction (TX/RX) depending on what information the user has requested.
*/
typedef struct CF_Traverse_WriteHistoryFileArg
{
osal_id_t fd;
CF_Direction_t filter_dir;

bool error; /**< Will be set to true if any write failed */
uint32 counter; /**< Total number of entries written */
} CF_Traverse_WriteHistoryFileArg_t;

/**
* @brief Argument structure for use with CF_Traverse_WriteTxnQueueEntryToFile()
*
* This is used for writing status files. It contains a designated
* file descriptor for output and counters.
*
* When traversing transactions, the entire list is written to the file.
* No additional filtering is necessary, because the queues themselves are
* limited in what they contain (therefore "pre-filtered" to some degree).
*/
typedef struct CF_Traverse_WriteFileArg
typedef struct CF_Traverse_WriteTxnFileArg
{
osal_id_t fd;
int32 result;
int32 counter;
} CF_Traverse_WriteFileArg_t;

bool error; /**< Will be set to true if any write failed */
uint32 counter; /**< Total number of entries written */
} CF_Traverse_WriteTxnFileArg_t;

/**
* @brief Callback function type for use with CF_TraverseAllTransactions()
Expand Down Expand Up @@ -208,6 +231,27 @@ CF_Transaction_t *CF_FindTransactionBySequenceNumber(CF_Channel_t *c, CF_Transac
*/
int CF_FindTransactionBySequenceNumber_Impl(CF_CListNode_t *n, CF_Traverse_TransSeqArg_t *context);

/************************************************************************/
/** @brief Write a single history to a file.
*
* This creates a human-readable/string representation of the information in the
* history object, and writes that string to the indicated file.
*
* This implements the common code between writing the history queue and transaction
* queue to a file, as both ultimately store the same information in a CF_History_t
* object, but have a different method to get to it.
*
* @par Assumptions, External Events, and Notes:
* fd should be a valid file descriptor, open for writing.
*
* @param fd Open File descriptor to write to
* @param h Pointer to CF history object to write
*
* @retval 0 on success
* @retval -1 on error
*/
int CF_WriteHistoryEntryToFile(osal_id_t fd, const CF_History_t *h);

/************************************************************************/
/** @brief Write a transaction-based queue's transaction history to a file.
*
Expand All @@ -221,10 +265,10 @@ int CF_FindTransactionBySequenceNumber_Impl(CF_CListNode_t *n, CF_Traverse_Trans
* @retval 0 on success
* @retval 1 on error
*/
int32 CF_WriteQueueDataToFile(int32 fd, CF_Channel_t *c, CF_QueueIdx_t q);
int32 CF_WriteTxnQueueDataToFile(osal_id_t fd, CF_Channel_t *c, CF_QueueIdx_t q);

/************************************************************************/
/** @brief Write a history-based queue's transaction history to a file.
/** @brief Write a history-based queue's entries to a file.
*
* @par Assumptions, External Events, and Notes:
* c must not be NULL.
Expand All @@ -236,7 +280,7 @@ int32 CF_WriteQueueDataToFile(int32 fd, CF_Channel_t *c, CF_QueueIdx_t q);
* @retval 0 on success
* @retval 1 on error
*/
int32 CF_WriteHistoryQueueDataToFile(int32 fd, CF_Channel_t *c, CF_Direction_t dir);
int32 CF_WriteHistoryQueueDataToFile(osal_id_t fd, CF_Channel_t *c, CF_Direction_t dir);

/************************************************************************/
/** @brief Insert a transaction into a priority sorted transaction queue.
Expand Down Expand Up @@ -300,36 +344,41 @@ int CF_TraverseAllTransactions_All_Channels(CF_TraverseAllTransactions_fn_t fn,
int CF_TraverseAllTransactions_Impl(CF_CListNode_t *n, CF_TraverseAll_Arg_t *args);

/************************************************************************/
/** @brief Walks through a history queue and builds a human readable representation of it.
/** @brief Writes a human readable representation of a history queue entry to a file
*
* @par Description
* This function is used as both a list traversal function and a direct
* function call.
* This function is a wrapper around CF_WriteHistoryEntryToFile() that can be used with
* CF_Traverse() to write history queue entries to the file.
*
* This also implements a direction filter, so only matching entries are actually written
* to the file.
*
* @par Assumptions, External Events, and Notes:
* n must not be NULL. context must not be NULL.
*
* @param n Node being currently traversed
* @param context Pointer to object indicating the file descriptor and related information
* @param context Pointer to CF_Traverse_WriteHistoryFileArg_t indicating the file information
*
* @retval CF_CLIST_CONT if everything is going well
* @retval CF_CLIST_EXIT if a write error occurred, which means traversal should stop
*/
int CF_TraverseHistory(CF_CListNode_t *n, CF_Traverse_WriteFileArg_t *context);
int CF_Traverse_WriteHistoryQueueEntryToFile(CF_CListNode_t *n, void *arg);

/************************************************************************/
/** @brief Walk over all transactions and print information from their history.
/** @brief Writes a human readable representation of a transaction history entry to a file
*
* This function is a wrapper around CF_WriteHistoryEntryToFile() that can be used with
* CF_Traverse() to write transaction queue entries to the file.
*
* @par Assumptions, External Events, and Notes:
* None
* n must not be NULL. context must not be NULL.
*
* @param n Node being currently traversed
* @param context Pointer to object indicating the file descriptor and related information
* @param context Pointer to CF_Traverse_WriteTxnFileArg_t indicating the file information
*
* @retval CF_CLIST_CONT if everything is going well
* @retval CF_CLIST_EXIT if a write error occurred, which means traversal should stop
*/
int CF_TraverseTransactions(CF_CListNode_t *n, CF_Traverse_WriteFileArg_t *context);
int CF_Traverse_WriteTxnQueueEntryToFile(CF_CListNode_t *n, void *arg);

/************************************************************************/
/** @brief Searches for the first transaction with a lower priority than given.
Expand Down
Loading