diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..570bbe350 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Autotools build artifacts +Makefile.in +aclocal.m4 +autom4te.cache/ +compile +config.guess +config.h.in +config.log +config.sub +configure +depcomp +install-sh +ltmain.sh +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 +missing +src/Makefile.in +src/unittest/Makefile.in +config.status +Makefile +src/Makefile +src/unittest/Makefile diff --git a/src/rrdCommon.h b/src/rrdCommon.h index b91ff6f7b..bc7915232 100644 --- a/src/rrdCommon.h +++ b/src/rrdCommon.h @@ -97,6 +97,7 @@ typedef struct mbuffer { bool inDynamic; bool appendMode; deepsleep_event_et dsEvent; + char *suffix; // Holds the suffix split from issue type string, if any } data_buf; /*Structure for Message Header*/ @@ -124,6 +125,7 @@ typedef struct cache { char *issueString; struct cache *next; struct cache *prev; + char *suffix; // Persist the suffix for later use } cacheData; /*Structure for Device Propertiesr*/ diff --git a/src/rrdDynamic.c b/src/rrdDynamic.c index 2deee32ab..85416fcd6 100644 --- a/src/rrdDynamic.c +++ b/src/rrdDynamic.c @@ -244,12 +244,12 @@ void RRDRdmManagerDownloadRequest(issueNodeData *pissueStructNode, char *dynJSON strcpy(appendData,rbuf->mdata); strcat(appendData,APPEND_SUFFIX); RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: Cache String updated in appendmode IssueStr:%s Length:%d\n", __FUNCTION__, __LINE__, appendData, strlen(appendData)); - append_item(strdup(msgDataString), strdup(appendData)); + append_item(strdup(msgDataString), strdup(appendData), rbuf->suffix); RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: Setting Parameters Success and Cache Updated ...%s IssueStr:%s Length:%d\n", __FUNCTION__, __LINE__, msgDataString, appendData, strlen(appendData)); } else { - append_item(strdup(msgDataString), strdup((char *)rbuf->mdata)); + append_item(strdup(msgDataString), strdup((char *)rbuf->mdata), rbuf->suffix); RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: Setting Parameters Success and Cache Updated ...%s IssueStr:%s Length:%d\n", __FUNCTION__, __LINE__, msgDataString, (char *)rbuf->mdata, strlen((char *)rbuf->mdata)); } } diff --git a/src/rrdEventProcess.c b/src/rrdEventProcess.c index 5164e7832..b73a74208 100644 --- a/src/rrdEventProcess.c +++ b/src/rrdEventProcess.c @@ -79,7 +79,10 @@ void processIssueTypeEvent(data_buf *rbuf) cmdBuff = (data_buf *)malloc(sizeof(data_buf)); if (cmdBuff) { - dataMsgLen = strlen(cmdMap[index]) + 1; + char base[128] = {0}; + char local_suffix[128] = {0}; + split_issue_type(cmdMap[index], base, sizeof(base), local_suffix, sizeof(local_suffix)); + dataMsgLen = strlen(base) + 1; RRD_data_buff_init(cmdBuff, EVENT_MSG, RRD_DEEPSLEEP_INVALID_DEFAULT); /* Setting Deafult Values*/ cmdBuff->inDynamic = rbuf->inDynamic; if(cmdBuff->inDynamic) @@ -88,9 +91,19 @@ void processIssueTypeEvent(data_buf *rbuf) } cmdBuff->appendMode = rbuf->appendMode; cmdBuff->mdata = (char *)calloc(1, dataMsgLen); + + /* Store suffix for this issue type */ + cmdBuff->suffix = NULL; + if (local_suffix[0] != '\0') { + cmdBuff->suffix = strdup(local_suffix); + if (cmdBuff->suffix == NULL) + { + RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "[%s:%d]: Failed to allocate memory for suffix... \n", __FUNCTION__, __LINE__); + } + } if (cmdBuff->mdata) { - strncpy((char *)cmdBuff->mdata, cmdMap[index], dataMsgLen); + strncpy((char *)cmdBuff->mdata, base, dataMsgLen); processIssueType(cmdBuff); } else @@ -99,6 +112,11 @@ void processIssueTypeEvent(data_buf *rbuf) } if(cmdBuff) { + if (cmdBuff->suffix) + { + free(cmdBuff->suffix); + cmdBuff->suffix = NULL; + } free(cmdBuff); cmdBuff = NULL; } @@ -639,7 +657,7 @@ static void removeSpecialCharacterfromIssueTypeList(char *str) while (str[source] != '\0') { - if (isalnum(str[source]) || str[source] == ',' || str[source] == '.') + if (isalnum(str[source]) || str[source] == ',' || str[source] == '.' || str[source] == '_'|| str[source] == '-') { str[destination] = str[source]; ++destination; @@ -648,7 +666,6 @@ static void removeSpecialCharacterfromIssueTypeList(char *str) } str[destination] = '\0'; } - /* * @function issueTypeSplitter * @brief Splits a given string into tokens based on a specified delimiter, and removes any @@ -698,4 +715,3 @@ static int issueTypeSplitter(char *input_str, const char delimeter, char ***args return cnt; } - diff --git a/src/rrdIarmEvents.c b/src/rrdIarmEvents.c index 323ba051a..1c72f8e3b 100644 --- a/src/rrdIarmEvents.c +++ b/src/rrdIarmEvents.c @@ -338,6 +338,12 @@ void _rdmManagerEventHandler(const char *owner, IARM_EventId_t eventId, void *da } RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: Cache.issueString=%s Cache.issueString.Len=%d\n", __FUNCTION__, __LINE__, cache->issueString, strlen(cache->issueString)); strncpy((char *)sendbuf->mdata, cache->issueString, recPkgNamelen); + if (cache->suffix) { + sendbuf->suffix = strdup(cache->suffix); + RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: Restored suffix from cache: %s\n", __FUNCTION__, __LINE__, cache->suffix); + } else { + sendbuf->suffix = NULL; + } RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: IssueType: %s...\n", __FUNCTION__, __LINE__, (char *)sendbuf->mdata); snprintf(sendbuf->jsonPath, strlen(eventData->rdm_pkg_info.pkg_inst_path) + rrdjsonlen + 1, "%s%s", eventData->rdm_pkg_info.pkg_inst_path, RRD_JSON_FILE); sendbuf->inDynamic = true; diff --git a/src/rrdInterface.c b/src/rrdInterface.c index b69dd8936..f7f9d5afd 100644 --- a/src/rrdInterface.c +++ b/src/rrdInterface.c @@ -275,6 +275,7 @@ void RRD_data_buff_init(data_buf *sbuf, message_type_et sndtype, deepsleep_event sbuf->inDynamic = false; sbuf->appendMode = false; sbuf->dsEvent = deepSleepEvent; + sbuf->suffix = NULL; } /*Function: RRD_data_buff_deAlloc @@ -295,6 +296,10 @@ void RRD_data_buff_deAlloc(data_buf *sbuf) { free(sbuf->jsonPath); } + if (sbuf->suffix) + { + free(sbuf->suffix); + } free(sbuf); } } @@ -382,6 +387,11 @@ void _rdmDownloadEventHandler(rbusHandle_t handle, rbusEvent_t const* event, rbu } RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: Cache.issueString=%s Cache.issueString.Len=%d\n", __FUNCTION__, __LINE__, cache->issueString, strlen(cache->issueString)); strncpy((char *)sendbuf->mdata, cache->issueString, recPkgNamelen); + if (cache->suffix && cache->suffix[0] != '\0') + { + sendbuf->suffix = strdup(cache->suffix); + RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: Restored suffix from cache struct: %s\n", __FUNCTION__, __LINE__, cache->suffix); + } RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: IssueType: %s...\n", __FUNCTION__, __LINE__, (char *)sendbuf->mdata); snprintf(sendbuf->jsonPath, strlen(pkg_inst_path) + rrdjsonlen + 1, "%s%s", pkg_inst_path, RRD_JSON_FILE); sendbuf->inDynamic = true; diff --git a/src/rrdJsonParser.c b/src/rrdJsonParser.c index e06d93ac2..ecbc2d6e2 100644 --- a/src/rrdJsonParser.c +++ b/src/rrdJsonParser.c @@ -46,6 +46,60 @@ void removeSpecialChar(char *str) } } +/* + * @function split_issue_type + * @brief Utility to split base and suffix from issue type string. + * Example: Input: Device.DeviceTime_Search-b6877385-9463-45fc-b19d-a24d77fd0790 + * Output: base = Device.DeviceTime, suffix = _Search-b6877385-9463-45fc-b19d-a24d77fd0790 + * @param const char *input - The input string to split. + * @param char *base - Buffer to store the base part (before the first underscore). + * @param size_t base_len - Size of the base buffer. + * @param char *suffix - Buffer to store the suffix part (from the first underscore onwards). + * @param size_t suffix_len - Size of the suffix buffer. + * @return void + */ + +void split_issue_type(const char *input, char *base, size_t base_len, char *suffix, size_t suffix_len) +{ + if (base && base_len > 0) + { + base[0] = '\0'; + } + if (suffix && suffix_len > 0) + { + suffix[0] = '\0'; + } + + if (!input || !base || !suffix) + { + return; + } + + if (base_len == 0 || suffix_len == 0) + { + return; + } + RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: split_issue_type called with input='%s'\n", __FUNCTION__, __LINE__, input); + const char *underscore = strchr(input, '_'); + if (underscore) + { + size_t b_len = underscore - input; + if (b_len >= base_len) b_len = base_len - 1; + strncpy(base, input, b_len); + base[b_len] = '\0'; + strncpy(suffix, underscore, suffix_len - 1); + suffix[suffix_len - 1] = '\0'; + } + else + { + strncpy(base, input, base_len - 1); + base[base_len - 1] = '\0'; + suffix[0] = '\0'; + } + RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s:%d]: split_issue_type result: base='%s', suffix='%s'\n", __FUNCTION__, __LINE__, base, suffix); +} + + /* * @function getParamcount * @brief Calculates the total number of nodes (elements) in the input string, excluding delimiters. @@ -515,7 +569,11 @@ void checkIssueNodeInfo(issueNodeData *issuestructNode, cJSON *jsoncfg, data_buf { RDK_LOG(RDK_LOG_ERROR,LOG_REMDEBUG,"[%s:%d]: Memory allocation failed for rfcbuf\n",__FUNCTION__,__LINE__); free(buff->mdata); // free rfc data + buff->mdata = NULL; free(buff->jsonPath); // free rrd path info + buff->jsonPath = NULL; + free(buff->suffix); // free suffix + buff->suffix = NULL; return; } @@ -535,7 +593,11 @@ void checkIssueNodeInfo(issueNodeData *issuestructNode, cJSON *jsoncfg, data_buf RDK_LOG(RDK_LOG_ERROR,LOG_REMDEBUG,"[%s:%d]: %s Directory creation failed!!!\n",__FUNCTION__,__LINE__,outdir); free(rfcbuf); // free duplicated rfc data free(buff->mdata); // free rfc data + buff->mdata = NULL; free(buff->jsonPath); // free rrd path info + buff->jsonPath = NULL; + free(buff->suffix); // free suffix + buff->suffix = NULL; return; } else @@ -576,7 +638,26 @@ void checkIssueNodeInfo(issueNodeData *issuestructNode, cJSON *jsoncfg, data_buf else { RDK_LOG(RDK_LOG_DEBUG,LOG_REMDEBUG,"[%s:%d]: Continue uploading Debug Report for %s from %s... \n",__FUNCTION__,__LINE__,buff->mdata,outdir); - status = uploadDebugoutput(outdir,buff->mdata); + // Use the persisted suffix from buff for upload + char tarName[512] = {0}; + int tar_name_len = 0; + if (buff->suffix && buff->suffix[0] != '\0') + { + tar_name_len = snprintf(tarName, sizeof(tarName), "%s%s", buff->mdata, buff->suffix); + } + else + { + tar_name_len = snprintf(tarName, sizeof(tarName), "%s", buff->mdata); + } + if ((tar_name_len < 0) || ((size_t)tar_name_len >= sizeof(tarName))) + { + RDK_LOG(RDK_LOG_ERROR,LOG_REMDEBUG,"[%s:%d]: Failed to build upload file name for %s. snprintf result:%d, buffer size:%zu\n", __FUNCTION__,__LINE__,buff->mdata,tar_name_len,sizeof(tarName)); + status = -1; + } + else + { + status = uploadDebugoutput(outdir, tarName); + } if(status != 0) { RDK_LOG(RDK_LOG_ERROR,LOG_REMDEBUG,"[%s:%d]: RRD Upload Script Execution Failed!!! status:%d\n",__FUNCTION__,__LINE__,status); @@ -588,14 +669,22 @@ void checkIssueNodeInfo(issueNodeData *issuestructNode, cJSON *jsoncfg, data_buf } free(rfcbuf); // free duplicated rfc data free(buff->mdata); // free rfc data + buff->mdata = NULL; free(buff->jsonPath); // free rrd path info + buff->jsonPath = NULL; + free(buff->suffix); // free suffix + buff->suffix = NULL; } else { RDK_LOG(RDK_LOG_ERROR,LOG_REMDEBUG,"[%s:%d]: No Command excuted as RRD Failed to change directory:%s\n",__FUNCTION__,__LINE__,outdir); free(rfcbuf); // free duplicated rfc data free(buff->mdata); // free rfc data + buff->mdata = NULL; free(buff->jsonPath); // free rrd path info + buff->jsonPath = NULL; + free(buff->suffix); // free suffix + buff->suffix = NULL; } } } diff --git a/src/rrdJsonParser.h b/src/rrdJsonParser.h index 299436101..87c4a2622 100644 --- a/src/rrdJsonParser.h +++ b/src/rrdJsonParser.h @@ -47,6 +47,8 @@ issueData* getIssueCommandInfo(issueNodeData *issuestructNode, cJSON *jsoncfg,ch bool processAllDebugCommand(cJSON *jsoncfg, issueNodeData *issuestructNode, char *rfcbuf); bool processAllDeepSleepAwkMetricsCommands(cJSON *jsoncfg, issueNodeData *issuestructNode, char *rfcbuf); +void split_issue_type(const char *input, char *base, size_t base_len, char *suffix, size_t suffix_len); + #ifdef __cplusplus } #endif diff --git a/src/rrdRunCmdThread.c b/src/rrdRunCmdThread.c index ce873d5d5..3b209b3f4 100644 --- a/src/rrdRunCmdThread.c +++ b/src/rrdRunCmdThread.c @@ -86,19 +86,17 @@ void print_items(cacheData *node) * @param char *issueTypeData - The issue type data to store in the cache node. * @return cacheData* - Pointer to the created cache node, or NULL on failure. */ -cacheData* createCache( char *pkgData, char *issueTypeData) +cacheData* createCache(char *pkgData, char *issueTypeData, char *suffix) { cacheData *cache = NULL; cache = (cacheData *)malloc(sizeof(cacheData)); - /*Check if memory alloacted to Cache*/ if(cache) { - cache->mdata = NULL; - cache->issueString = NULL; - cache->next = NULL; - cache->prev = NULL; cache->mdata = pkgData; cache->issueString = issueTypeData; + cache->suffix = suffix ? strdup(suffix) : NULL; + cache->next = NULL; + cache->prev = NULL; } return cache; } @@ -110,32 +108,25 @@ cacheData* createCache( char *pkgData, char *issueTypeData) * @param char *issueTypeData - The issue type data to append. * @return void */ -void append_item(char *pkgData, char *issueTypeData) +void append_item(char *pkgData, char *issueTypeData, char *suffix) { RDK_LOG(RDK_LOG_INFO,LOG_REMDEBUG,"[%s:%d]: Append Item with PkgData: %s and issue Type: %s to Cache \n",__FUNCTION__,__LINE__,pkgData,issueTypeData); - cacheData *rrdCachecnode = NULL; int i=0; i = pthread_mutex_lock(&rrdCacheMut); RDK_LOG(RDK_LOG_DEBUG,LOG_REMDEBUG,"[%s:%d]: RRD Mutex Lock...%d\n",__FUNCTION__,__LINE__,i); - - cacheData *tmp = createCache(pkgData,issueTypeData); - /* Check If the memory is allocated for new node*/ + cacheData *tmp = createCache(pkgData, issueTypeData, suffix); if(!tmp) { RDK_LOG(RDK_LOG_INFO,LOG_REMDEBUG,"[%s:%d]: Memory Allocation Failed : Cannot Append Item to Cache\n", __FUNCTION__, __LINE__); pthread_mutex_unlock(&rrdCacheMut); - return; + return; } - /* create Cache and store in node's data*/ - rrdCachecnode = cacheDataNode; - - /*Valid Cache, add node to list*/ if(rrdCachecnode != NULL) { tmp->next = rrdCachecnode; - rrdCachecnode->prev = tmp; + rrdCachecnode->prev = tmp; } cacheDataNode = tmp; pthread_mutex_unlock(&rrdCacheMut); @@ -235,6 +226,10 @@ void freecacheDataCacheNode(cacheData **node) { free(rrdCachetmpnode->mdata); free(rrdCachetmpnode->issueString); + if (rrdCachetmpnode->suffix) { + free(rrdCachetmpnode->suffix); + rrdCachetmpnode->suffix = NULL; + } rrdCachetmpnode->mdata = NULL; rrdCachetmpnode->issueString = NULL; free(rrdCachetmpnode); diff --git a/src/rrdRunCmdThread.h b/src/rrdRunCmdThread.h index a1bd9816a..430d8cf54 100644 --- a/src/rrdRunCmdThread.h +++ b/src/rrdRunCmdThread.h @@ -51,7 +51,8 @@ extern "C" /*Public Function*/ void initCache(void); -cacheData* createCache( char *pkgData, char *issueTypeData); +cacheData* createCache(char *pkgData, char *issueTypeData, char *suffix); +void append_item(char *pkgData, char *issueTypeData, char *suffix); void print_items(cacheData *node); void append_item(char *pkgData, char *issueTypeData); void remove_item(cacheData *cache); diff --git a/src/unittest/UTJson/device.properties b/src/unittest/UTJson/device.properties new file mode 100644 index 000000000..e69de29bb diff --git a/src/unittest/rrdUnitTestRunner.cpp b/src/unittest/rrdUnitTestRunner.cpp index 7b8c6c837..380933320 100644 --- a/src/unittest/rrdUnitTestRunner.cpp +++ b/src/unittest/rrdUnitTestRunner.cpp @@ -1347,7 +1347,8 @@ TEST(CreateCacheTest, HandlesNullPkgDataAndValidIssueTypeData) { char *pkgData = NULL; char *issueTypeData = strdup("ValidIssueTypeData"); - cacheData *result = createCache(pkgData, issueTypeData); + cacheData *result = createCache(pkgData, issueTypeData, NULL); + ASSERT_EQ(result->suffix, nullptr); ASSERT_NE(result, nullptr); ASSERT_EQ(result->mdata, nullptr); @@ -1363,7 +1364,8 @@ TEST(CreateCacheTest, HandlesValidPkgDataAndIssueTypeData) { char *pkgData = strdup("ValidPkgData"); char *issueTypeData = strdup("ValidIssueTypeData"); - cacheData *result = createCache(pkgData, issueTypeData); + cacheData *result = createCache(pkgData, issueTypeData, strdup("mysuffix")); + ASSERT_STREQ(result->suffix, "mysuffix"); ASSERT_NE(result, nullptr); ASSERT_STREQ(result->mdata, "ValidPkgData"); @@ -1380,7 +1382,8 @@ TEST(CreateCacheTest, HandlesValidPkgDataAndNullIssueTypeData) { char *pkgData = strdup("ValidPkgData"); char *issueTypeData = NULL; - cacheData *result = createCache(pkgData, issueTypeData); + cacheData *result = createCache(pkgData, issueTypeData, NULL); + ASSERT_EQ(result->suffix, nullptr); ASSERT_NE(result, nullptr); ASSERT_STREQ(result->mdata, "ValidPkgData"); @@ -1396,7 +1399,8 @@ TEST(CreateCacheTest, HandlesNullPkgDataAndIssueTypeData) { char *pkgData = NULL; char *issueTypeData = NULL; - cacheData *result = createCache(pkgData, issueTypeData); + cacheData *result = createCache(pkgData, issueTypeData, NULL); + ASSERT_EQ(result->suffix, nullptr); ASSERT_NE(result, nullptr); ASSERT_EQ(result->mdata, nullptr);