From 887843ebc15e188906d775fbd44209fb0e7b4f01 Mon Sep 17 00:00:00 2001 From: Anh D Van Date: Thu, 16 May 2024 18:19:09 +0000 Subject: [PATCH] Fix #441, cf delete files during error when tx Fix #441, Update to handle error during tx. 1. For polling, the file gets moved or deleted to pervent infinite loop 2. For others, the file does not get deleted. --- config/default_cf_tblstruct.h | 1 + fsw/src/cf_cfdp.c | 89 ++++++++++++++++++++++++++++++----- fsw/src/cf_cfdp.h | 10 ++++ fsw/tables/cf_def_config.c | 1 + 4 files changed, 89 insertions(+), 12 deletions(-) diff --git a/config/default_cf_tblstruct.h b/config/default_cf_tblstruct.h index 30df4779..9ed1a33e 100644 --- a/config/default_cf_tblstruct.h +++ b/config/default_cf_tblstruct.h @@ -51,6 +51,7 @@ typedef struct CF_ConfigTable uint16 outgoing_file_chunk_size; /**< \brief maximum size of outgoing file data chunk in a PDU. * Limited by CF_MAX_PDU_SIZE minus the PDU header(s) */ char tmp_dir[CF_FILENAME_MAX_PATH]; /**< \brief directory to put temp files */ + char fail_dir[CF_FILENAME_MAX_PATH]; /**< \brief fail directory */ } CF_ConfigTable_t; #endif diff --git a/fsw/src/cf_cfdp.c b/fsw/src/cf_cfdp.c index c79fa8d3..df3b02ae 100644 --- a/fsw/src/cf_cfdp.c +++ b/fsw/src/cf_cfdp.c @@ -1624,27 +1624,58 @@ void CF_CFDP_ResetTransaction(CF_Transaction_t *txn, int keep_history) if (OS_ObjectIdDefined(txn->fd)) { CF_WrappedClose(txn->fd); + if (!txn->keep) { - if (CF_CFDP_IsSender(txn)) + /* Sender and No Error */ + if (CF_CFDP_IsSender(txn) && !CF_TxnStatus_IsError(txn->history->txn_stat)) { - /* If move directory is defined attempt move */ - if (CF_AppData.config_table->chan[txn->chan_num].move_dir[0] != 0) - { - filename = strrchr(txn->history->fnames.src_filename, '/'); - if (filename != NULL) + + /* If move directory is defined attempt move */ + if (CF_AppData.config_table->chan[txn->chan_num].move_dir[0] != 0) { - snprintf(destination, sizeof(destination), "%s%s", - CF_AppData.config_table->chan[txn->chan_num].move_dir, filename); - status = OS_mv(txn->history->fnames.src_filename, destination); + filename = strrchr(txn->history->fnames.src_filename, '/'); + if (filename != NULL) + { + snprintf(destination, sizeof(destination), "%s%s", + CF_AppData.config_table->chan[txn->chan_num].move_dir, filename); + status = OS_mv(txn->history->fnames.src_filename, destination); + } } - } - if (status != OS_SUCCESS) + if (status != OS_SUCCESS) + { + OS_remove(txn->history->fnames.src_filename); + } + } + /* Sender and Error */ + else if(CF_CFDP_IsSender(txn) && CF_TxnStatus_IsError(txn->history->txn_stat)) + { + /* file inside an polling directory */ + if(CF_CFDP_IsPollingDir(txn->history->fnames.src_filename, txn->chan_num)) { - OS_remove(txn->history->fnames.src_filename); + /* + ** Attempt to move/delete or delete it. Otherwise, it gets stucking + ** in infinite loop. + */ + if(CF_AppData.config_table->fail_dir[0] != 0) + { + filename = strrchr(txn->history->fnames.src_filename, '/'); + if (filename != NULL) + { + snprintf(destination, sizeof(destination), "%s%s", + CF_AppData.config_table->fail_dir, filename); + status = OS_mv(txn->history->fnames.src_filename, destination); + } + } + + if (status != OS_SUCCESS) + { + OS_remove(txn->history->fnames.src_filename); + } } } + /* Not Sender */ else { OS_remove(txn->history->fnames.dst_filename); @@ -1845,3 +1876,37 @@ void CF_CFDP_DisableEngine(void) CFE_SB_DeletePipe(chan->pipe); } } + +/*---------------------------------------------------------------- + * + * Application-scope internal function + * See description in cf_cfdp.h for argument/return detail + * + *-----------------------------------------------------------------*/ +bool CF_CFDP_IsPollingDir(const char * src_file, uint8 chan_num) +{ + bool return_code = false; + char src_dir[CF_FILENAME_MAX_LEN] = "\0"; + CF_ChannelConfig_t *cc; + CF_PollDir_t * pd; + int i; + + char * last_slash = strrchr(src_file, '/'); + if(last_slash != NULL) + { + strncpy(src_dir, src_file, last_slash - src_file); + } + + cc = &CF_AppData.config_table->chan[chan_num]; + for (i = 0; i < CF_MAX_POLLING_DIR_PER_CHAN; ++i) + { + pd = &cc->polldir[i]; + if(strcmp(src_dir, pd->src_dir) == 0) + { + return_code = true; + break; + } + } + + return return_code; +} \ No newline at end of file diff --git a/fsw/src/cf_cfdp.h b/fsw/src/cf_cfdp.h index 1fa54db0..b7cd31ec 100644 --- a/fsw/src/cf_cfdp.h +++ b/fsw/src/cf_cfdp.h @@ -703,4 +703,14 @@ void CF_CFDP_ProcessPollingDirectories(CF_Channel_t *chan); */ CF_CListTraverse_Status_t CF_CFDP_DoTick(CF_CListNode_t *node, void *context); +/************************************************************************/ +/** @brief Check if source file came from polling directory + * + * + * @par Assumptions, External Events, and Notes: + * + * @retval true/false + */ +bool CF_CFDP_IsPollingDir(const char * src_file, uint8 chan_num); + #endif /* !CF_CFDP_H */ diff --git a/fsw/tables/cf_def_config.c b/fsw/tables/cf_def_config.c index 35bba669..425666ff 100644 --- a/fsw/tables/cf_def_config.c +++ b/fsw/tables/cf_def_config.c @@ -80,5 +80,6 @@ CF_ConfigTable_t CF_config_table = { .move_dir = ""}}, 480, /* outgoing_file_chunk_size */ "/cf/tmp", /* temporary file directory */ + "/cf/fail", /* Stores failed tx file for "polling directory" */ }; CFE_TBL_FILEDEF(CF_config_table, CF.config_table, CF config table, cf_def_config.tbl)