Skip to content

Commit

Permalink
Merge pull request #174 from jphickey/fix-40-writefile
Browse files Browse the repository at this point in the history
Fix #40, update traverse history/write file
  • Loading branch information
astrogeco authored Jan 18, 2022
2 parents 5d55254 + 045c739 commit fe02332
Show file tree
Hide file tree
Showing 10 changed files with 413 additions and 504 deletions.
6 changes: 3 additions & 3 deletions fsw/src/cf_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,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 @@ -788,7 +788,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 @@ -801,7 +801,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

0 comments on commit fe02332

Please sign in to comment.