RDK Documentation (Open Sourced RDK Components)
dca.c
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2016 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 /**
21  * @defgroup DCA Data Collection and Analysis
22  * - Data Collection and Analysis (DCA) is responsible for collecting the data from various log files and send to server.
23  *
24  * @defgroup DCA_TYPES DCA Data types
25  * @ingroup DCA
26  *
27  * @defgroup DCA_APIS DCA API
28  * @ingroup DCA
29  *
30  **/
31 
32 
33 /**
34  * @defgroup dca
35  * @{
36  **/
37 
38 
39 /**
40  * @defgroup dca
41  * @{
42  * @defgroup src
43  * @{
44  **/
45 
46 
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <unistd.h>
51 #include <ctype.h>
52 
53 #include "glib.h"
54 #include "cJSON.h"
55 
56 #include "dcautils.h"
57 #include "dcalist.h"
58 #include "safec_lib.h"
59 
60 
61 
62 #ifdef USE_TR181_CCSP_MESSAGEBUS
63 #include "dcatr181.h"
64 #define TR181BUF_LENGTH 512
65 #define OBJ_DELIMITER "{i}"
66 #define DELIMITER_SIZE 3
67 #define NOE strlen("NumberOfEntries")
68 #endif
69 
70 // Using same error code used by safeclib for buffer overflow for easy metrics collection
71 #define INVALID_COUNT "-406"
72 
73 #define LOG_FILE "dcmscript.log"
74 
75 #define NUM_OF_LOG_TYPES (sizeof(log_type_table)/sizeof(log_type_table[0]))
76 
77 enum logType_e {
78  TOPLOG,
79  MESSAGE_BUS,
80 };
81 
82 typedef struct logtype_pair{
83  char *name;
84  enum logType_e type;
85 } LOGTYPE_PAIR;
86 
87 LOGTYPE_PAIR log_type_table[] = {
88  { "top_log.txt", TOPLOG },
89 #ifdef USE_TR181_CCSP_MESSAGEBUS
90  {"<message_bus>", MESSAGE_BUS },
91 #endif
92 };
93 
94 int get_log_type_from_name(char *name, enum logType_e *type_ptr)
95 {
96  errno_t rc = -1;
97  int ind = -1;
98  int i = 0;
99  size_t strsize = 0;
100 
101  if((name == NULL) || (type_ptr == NULL))
102  return 0;
103 
104  strsize = strlen(name);
105 
106  for (i = 0 ; i < NUM_OF_LOG_TYPES ; ++i)
107  {
108  rc = strcmp_s(name, strsize, log_type_table[i].name, &ind);
109  ERR_CHK(rc);
110  if((rc == EOK) && (!ind))
111  {
112  *type_ptr = log_type_table[i].type;
113  return 1;
114  }
115  }
116  return 0;
117 }
118 
119 
120 /**
121  * @addtogroup DCA_TYPES
122  * @{
123  */
124 
125 char *PERSISTENT_PATH = NULL;
126 char *LOG_PATH = NULL;
127 char *DEVICE_TYPE = NULL;
128 cJSON *SEARCH_RESULT_JSON = NULL, *ROOT_JSON = NULL;
129 int CUR_EXEC_COUNT = 0;
130 long LAST_SEEK_VALUE = 0;
131 
132 
133 /* @} */ // End of group DCA_TYPES
134 
135 /**
136  * @addtogroup DCA_APIS
137  * @{
138  */
139 
140 
141 /** @brief This API processes the top command log file patterns to retrieve load average and process usage.
142  *
143  * @param[in] logfile top_log file
144  * @param[in] pchead Node head
145  * @param[in] pcIndex Node count
146  *
147  * @return Returns the status of the operation.
148  * @retval Returns zero on success, appropriate errorcode otherwise.
149  */
150 int processTopPattern(char *logfile, GList *pchead, int pcIndex)
151 {
152  UNREFERENCED_PARAMETER(logfile);
153  UNREFERENCED_PARAMETER(pcIndex);
154  GList *tlist = pchead;
155  pcdata_t *tmp = NULL;
156  while (NULL != tlist) {
157  tmp = tlist->data;
158  if (NULL != tmp) {
159  if ((NULL != tmp->header) && (NULL != strstr(tmp->header, "Load_Average"))) {
160  if (0 == getLoadAvg()) {
161  LOG("getLoadAvg() Failed with error");
162  }
163  } else {
164  if (NULL != tmp->pattern) {
165  getProcUsage(tmp->pattern);
166  }
167  }
168  }
169  tlist = g_list_next(tlist);
170  }
171  return 0;
172 }
173 
174 #ifdef USE_TR181_CCSP_MESSAGEBUS
175 
176 /** @brief This API appends tr181 object value to telemetry node.
177  *
178  * @param[in] dst Object node
179  * @param[in] src Data value
180  */
181 static void appendData( pcdata_t* dst, const char* src)
182 {
183  /* Coverity FIX CID:143052 REVERSE_INULL */
184 
185  if(NULL == dst || NULL == src)
186  return;
187 
188  int dst_len, src_len = 0;
189  errno_t rc = -1;
190 
191  src_len = strlen(src) + 1;
192  //Copy data
193  if(NULL == dst->data) {
194  if((dst->data = strdup(src)) == NULL)
195  {
196  LOG("Failed to allocate memory for telemetry node data\n");
197  }
198  } else { //Append data
199  dst_len = strlen(dst->data) + 1;
200  dst->data = (char*)realloc(dst->data, dst_len+src_len);
201  if(NULL != dst->data) {
202  rc = sprintf_s((dst->data)+(dst_len-1),src_len+1, ",%s", src);
203  if(rc < EOK)
204  {
205  ERR_CHK(rc);
206  free(dst->data);
207  dst->data = NULL;
208  return;
209  }
210  } else {
211  LOG("Failed to re-allocate memory for telemetry node data\n");
212  }
213  }
214 }
215 
216 /**
217  * @brief This API process tr181 objects through ccsp message bus
218  *
219  * @param[in] logfile DCA pattern file
220  * @param[in] pchead Node head
221  * @param[in] pcIndex Node count
222  *
223  * @return Returns status of the operation.
224  * @retval Returns 1 on failure, 0 on success
225  */
226 static int processTr181Objects(char *logfile, GList *pchead, int pcIndex)
227 {
228  UNREFERENCED_PARAMETER(logfile);
229  UNREFERENCED_PARAMETER(pcIndex);
230  int ret_val,length, obj_count, i = 0;
231  GList *tlist = NULL;
232  pcdata_t *tmp = NULL;
233  char tr181data_buff[TR181BUF_LENGTH];
234  int bufflength = TR181BUF_LENGTH + NOE;
235  char tr181obj_buff[bufflength];
236  char *tck, *first_tck = NULL;
237  errno_t rc = -1;
238  int ind =-1;
239  int entry_flag = -1;
240  //Initialize message bus handler
241  ret_val = ccsp_handler_init();
242  if ( 0 != ret_val ) {
243  LOG("ccsp_handler_init is failed\n");
244  return ret_val;
245  }
246 
247  //Get the value of TR181 telemetry MessageBusSource RFC
248  ret_val = get_tr181param_value("Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.Telemetry.MessageBusSource.Enable", tr181data_buff, TR181BUF_LENGTH);
249 
250  if(0 == ret_val)
251  {
252  rc = strcmp_s("true",strlen("true"),tr181data_buff,&ind);
253  ERR_CHK(rc);
254  if((rc == EOK) && (ind == 0))
255  entry_flag = 1;
256  }
257  if(entry_flag == 1 ) {
258  //Loop through the given list and fill the data field of each node
259  for(tlist=pchead; tlist!=NULL; tlist=g_list_next(tlist)) {
260  tmp = tlist->data;
261  if (NULL != tmp) {
262  if(NULL != tmp->header && NULL != tmp->pattern && strlen(tmp->pattern) < TR181BUF_LENGTH && NULL == tmp->data) {
263  //Check whether given object has multi-instance token, if no token found it will be treated as a single instance object
264  //Or if more than one token found, skip the object as it is not valid/supported
265  //Check for first multi-instance token
266  tck = strstr(tmp->pattern, OBJ_DELIMITER);
267  if(NULL == tck) { //Single instance check
268  ret_val = get_tr181param_value(tmp->pattern, tr181data_buff, TR181BUF_LENGTH);
269  if (0 == ret_val) {
270  appendData(tmp, tr181data_buff);
271  } else {
272  LOG("Telemetry data source not found. Type = <message_bus>. Content string = %s\n", tmp->pattern);
273  }
274  } else { //Multi-instance check
275  first_tck = tck;
276  //Check for a next multi-instance token
277  tck = strstr(tck+DELIMITER_SIZE, OBJ_DELIMITER);
278  if(NULL == tck) {
279  //Get NumberOfEntries of a multi-instance object
280  length = first_tck - tmp->pattern;
281  rc = strncpy_s(tr181obj_buff,sizeof(tr181obj_buff),tmp->pattern,(length-1));
282  if(rc != EOK)
283  {
284  ERR_CHK(rc);
285  return 1;
286  }
287  tr181obj_buff[length-1] = '\0';
288  rc = strcat_s(tr181obj_buff,sizeof(tr181obj_buff),"NumberOfEntries");
289  if(rc != EOK)
290  {
291  ERR_CHK(rc);
292  return 1;
293  }
294  ret_val = get_tr181param_value(tr181obj_buff, tr181data_buff, TR181BUF_LENGTH);
295  if(0 == ret_val) {
296  obj_count = atoi(tr181data_buff);
297  //Collect all all instance value of a object
298  if(obj_count > 0) {
299  for(i=1; i<=obj_count; i++) {
300  //Replace multi-instance token with an object instance number
301  rc = strncpy_s(tr181obj_buff,sizeof(tr181obj_buff),tmp->pattern,length);
302  if(rc != EOK)
303  {
304  ERR_CHK(rc);
305  continue ;
306  }
307  tr181obj_buff[length] = '\0';
308  ret_val = sprintf_s(tr181obj_buff+length, bufflength-length,"%d%s", i, (tmp->pattern + length + DELIMITER_SIZE));
309  if (ret_val < EOK || ret_val >= (bufflength-length))
310  {
311  ERR_CHK(ret_val);
312  LOG("Error: Buffer overflow - return value:%d", ret_val);
313  }
314  ret_val = get_tr181param_value(tr181obj_buff, tr181data_buff, TR181BUF_LENGTH);
315  if(0 == ret_val) {
316  appendData(tmp, tr181data_buff);
317  } else {
318  LOG("Telemetry data source not found. Type = <message_bus>. Content string = %s\n", tr181obj_buff);
319  }
320  }//End of for loop
321  }
322  } else {
323  LOG("Failed to get NumberOfEntries. Type = <message_bus>. Content string = %s\n", tr181obj_buff);
324  }
325  } else {
326  LOG("Skipping Telemetry object due to invalid format. Type = <message_bus>. Content string = %s\n", tmp->pattern);
327  }
328  }//End of Mult-instance check
329  }
330  }
331  } //End of node loop through for loop
332  } else {
333  LOG("The TR181 MessageBusSource is disabled via RFC\n");
334  }
336  return 0;
337 }
338 #endif
339 
340 /**
341  * @brief This function adds the value to the telemetry output json object.
342  *
343  * @param[in] pchead Header field in the telemetry profile
344  *
345  * @return Returns status of operation.
346  */
347 int addToJson(GList *pchead)
348 {
349  GList *tlist = pchead;
350  pcdata_t *tmp = NULL;
351  errno_t rc = -1;
352  while (NULL != tlist) {
353  tmp = tlist->data;
354  if (NULL != tmp) {
355  if (tmp->pattern)
356  {
357  if (tmp->d_type == INT) {
358  if (tmp->count != 0) {
359  char tmp_str[5] = {'\0'};
360  rc = sprintf_s(tmp_str,sizeof(tmp_str),"%d", tmp->count);
361  if(rc < EOK)
362  {
363  ERR_CHK(rc);
364  addToSearchResult(tmp->header, INVALID_COUNT);
365  }else {
366  addToSearchResult(tmp->header, tmp_str);
367  }
368  }
369  } else if(tmp->d_type == STR) {
370  if ((NULL != tmp->data) && !((tmp->data[0] == '0') && (tmp->data[1] == '\0'))) {
371  addToSearchResult(tmp->header, tmp->data);
372  }
373  }
374  }
375  }
376  tlist = g_list_next(tlist);
377  }
378 return 0;
379 }
380 
381 /**
382  * @brief Function to process pattern if it has split text in the header
383  *
384  * @param[in] line Log file matched line
385  * @param[in] pcnode Pattern to be verified.
386  *
387  * @return Returns status of operation.
388  * @retval Return 0 on success, -1 on failure
389  */
390 int getIPVideo(char *line, pcdata_t *pcnode)
391 {
392  char *strFound = NULL;
393  strFound = strstr(line, pcnode->pattern);
394  errno_t rc = -1;
395 
396  if (strFound != NULL ) {
397  int tlen = 0, plen = 0, vlen = 0;
398  tlen = (int)strlen(line);
399  plen = (int)strlen(pcnode->pattern);
400  strFound = strFound + plen ;
401  if (tlen > plen) {
402  vlen = strlen(strFound) ;
403  // If value is only single char make sure its not an empty space .
404  // Ideally component should not print logs with empty values but we have to consider logs from OSS components
405  if (( 1 == vlen ) && isspace(strFound[plen]))
406  return 0 ;
407 
408  if ( vlen > 0 ) {
409  if (NULL == pcnode->data){
410  pcnode->data = (char *) malloc(MAXLINE);
411  memset(pcnode->data, '\0', MAXLINE);
412  }
413 
414  if (NULL == pcnode->data)
415  return (-1);
416 
417  rc = strcpy_s(pcnode->data,MAXLINE,strFound);
418  if(rc != EOK)
419  {
420  ERR_CHK(rc);
421  return -1;
422  }
423  pcnode->data[tlen-plen] = '\0'; //For Boundary Safety
424  }
425  }
426  }
427  return 0;
428 }
429 
430 /**
431  * @brief To get RDK error code.
432  *
433  * @param[in] str Source string.
434  * @param[out] ec Error code.
435  *
436  * @return Returns status of operation.
437  * @retval Return 0 upon success.
438  */
439 int getErrorCode(char *str, char *ec, int ec_length)
440 {
441  int i = 0, j = 0, len = strlen(str);
442  char tmpEC[LEN] = {0};
443  errno_t rc = -1;
444 
445  while (str[i] != '\0') {
446  if (len >=4 && str[i] == 'R' && str[i+1] == 'D' && str[i+2] =='K' && str[i+3] == '-') {
447  i += 4;
448  j = 0;
449  if (str[i] == '0' || str[i] == '1') {
450  tmpEC[j] = str[i];
451  i++; j++;
452  if (str[i] == '0' || str[i] == '3') {
453  tmpEC[j] = str[i];
454  i++; j++;
455  if (0 != isdigit(str[i])) {
456  while (i<=len && 0 != isdigit(str[i]) && j<RDK_EC_MAXLEN) {
457  tmpEC[j] = str[i];
458  i++; j++;
459  ec[j] = '\0';
460  rc = strcpy_s(ec,ec_length, tmpEC);
461  if(rc != EOK)
462  {
463  ERR_CHK(rc);
464  continue;
465  }
466  }
467  break;
468  }
469  }
470  }
471  }
472  i++;
473  }
474  return 0;
475 }
476 
477 /**
478  * @brief Function to handle error codes received from the log file.
479  *
480  * @param[in] rdkec_head Node head.
481  * @param[in] line Logfile matched line.
482  *
483  * @return Returns status of operation.
484  * @retval Return 0 upon success, -1 on failure.
485  */
486 int handleRDKErrCodes(GList **rdkec_head, char *line)
487 {
488  char err_code[20] = {0}, rdkec[20] = {0};
489  pcdata_t *tnode = NULL;
490  errno_t rc = -1;
491  getErrorCode(line, err_code, sizeof(err_code));
492 
493  if (err_code[0] != '\0') {
494  rc = sprintf_s(rdkec,sizeof(rdkec), "%s%s", "RDK-",err_code);
495  if(rc < EOK)
496  {
497  ERR_CHK(rc);
498  return -1;
499  }
500  tnode = searchPCNode(*rdkec_head, rdkec);
501  if (NULL != tnode) {
502  tnode->count++;
503  } else {
504  /* Args: GList **pch, char *pattern, char *header, DType_t dtype, int count, char *data */
505  insertPCNode(rdkec_head, rdkec, rdkec, INT, 1, NULL);
506  }
507  return 0;
508  }
509  return -1;
510 }
511 
512 
513 /**
514  * @brief Function to process pattern count (loggrep)
515  *
516  * @param[in] logfile Current log file
517  * @param[in] pchead Node head
518  * @param[in] pcIndex Node count
519  * @param[in] rdkec_head RDK errorcode head
520  *
521  * @return Returns status of operation.
522  * @retval Return 0 upon success, -1 on failure.
523  */
524 int processCountPattern(char *logfile, GList *pchead, int pcIndex, GList **rdkec_head)
525 {
526  UNREFERENCED_PARAMETER(pcIndex);
527  char temp[MAXLINE];
528 
529  while (getsRotatedLog(temp, MAXLINE, logfile) != NULL ) {
530  int len = strlen(temp);
531  if (len > 0 && temp[len-1] == '\n')
532  temp[--len] = '\0';
533  pcdata_t *pc_node = searchPCNode(pchead, temp);
534  if (NULL != pc_node) {
535  if (pc_node->d_type == INT) {
536  pc_node->count++;
537  } else {
538  if (NULL != pc_node->header) {
539  if (NULL != strstr(pc_node->header, "split")) {
540  getIPVideo(temp, pc_node);
541  }
542  }
543  }
544  } else {
545 
546  if (NULL != strstr(temp, "RDK-") && ( 0 != strncmp(logfile, LOG_FILE, MAXLINE))) {
547  handleRDKErrCodes(rdkec_head, temp);
548  }
549  }
550  usleep(USLEEP_SEC);
551  }
552  return 0;
553 }
554 
555 /**
556  * @brief Generic pattern function based on pattern to call top/count or using ccsp message bus.
557  *
558  * @param[in] prev_file The previous log file.
559  * @param[in] logfile The current log file.
560  * @param[in] rdkec_head RDK errorcode head
561  * @param[in] pchead Node head
562  * @param[in] pcIndex Node count
563  *
564  * @return Returns status on operation.
565  * @retval Returns 0 upon success.
566  */
567 int processPattern(char **prev_file, char *logfile, GList **rdkec_head, GList *pchead, int pcIndex)
568 {
569  errno_t rc = -1;
570  int ind = -1;
571  int entry_flag = -1;
572 
573  if (NULL != logfile) {
574 
575  if (NULL == *prev_file)
576  {
577  entry_flag =1;
578  }
579  else
580  {
581  rc = strcmp_s(logfile, strlen(logfile), *prev_file , &ind);
582  ERR_CHK(rc);
583  if((ind) && (rc == EOK))
584  {
585  entry_flag =1;
586  }
587  }
588 
589  if (1 == entry_flag) {
590  if (NULL == *prev_file) {
591  *prev_file = malloc(strlen(logfile) + 1);
592  } else {
593  char *tmp = NULL;
594  writeLogSeek(*prev_file, LAST_SEEK_VALUE);
595  tmp = realloc(*prev_file, strlen(logfile) + 1);
596  if (NULL != tmp) {
597  *prev_file = tmp;
598  } else {
599  free(*prev_file);
600  *prev_file = NULL;
601  }
602  }
603 
604  if (NULL != *prev_file) {
605  rc = strcpy_s(*prev_file, strlen(logfile) + 1,logfile);
606  if(rc != EOK)
607  {
608  ERR_CHK(rc);
609  free(*prev_file);
610  *prev_file = NULL;
611  return -1;
612  }
613 
614  }
615  }
616 
617  // Process
618  if (NULL != pchead) {
619  enum logType_e type;
620 
621  if(get_log_type_from_name(logfile, &type))
622  {
623  if (type == TOPLOG)
624  {
625  processTopPattern(logfile, pchead, pcIndex);
626  }
627 #ifdef USE_TR181_CCSP_MESSAGEBUS
628  else if (type == MESSAGE_BUS )
629  {
630  processTr181Objects(logfile, pchead, pcIndex);
631  addToJson(pchead);
632  }
633 #endif
634  }
635  else {
636  processCountPattern(logfile, pchead, pcIndex, rdkec_head);
637  addToJson(pchead);
638  }
639 
640  }
641 
642  // clear nodes memory after process
643  // printPCNodes(pchead);
644  clearPCNodes(&pchead);
645  }
646  return 0;
647 }
648 
649 
650 /**
651  * @brief Function like strstr but based on the string delimiter.
652  *
653  * @param[in] str String.
654  * @param[in] delim Delimiter.
655  *
656  * @return Returns the output string.
657  */
658 char *strSplit(char *str, char *delim) {
659  static char *next_str;
660  char *last = NULL;
661 
662  if (NULL != str) {
663  next_str = str;
664  }
665 
666  if (NULL == next_str) {
667  return next_str;
668  }
669 
670  last = strstr(next_str, delim);
671  if (NULL == last) {
672  char *ret = next_str;
673  next_str = NULL;
674  return ret;
675  }
676 
677  char *ret = next_str;
678  *last = '\0';
679  next_str = last + strlen(delim);
680  return ret;
681 }
682 
683 /**
684  * @brief To get node data type based on pattern.
685  *
686  * @param[in] filename Conf filename.
687  * @param[in] header node header.
688  * @param[out] dtype Data type
689  *
690  * @return Returns status of operation.
691  */
692 void getDType(char *filename, char *header, DType_t *dtype)
693 {
694 enum logType_e type;
695 
696 if (NULL != header) {
697 
698  if (NULL != strstr(header, "split")) {
699  *dtype = STR;
700  }
701  else if(get_log_type_from_name(filename, &type))
702  {
703  if(type == TOPLOG)
704  {
705  *dtype = STR;
706  }
707 #ifdef USE_TR181_CCSP_MESSAGEBUS
708  else if (type == MESSAGE_BUS )
709  {
710  *dtype = STR;
711  }
712 #endif
713  }
714  else {
715  *dtype = INT;
716  }
717 
718  }
719 
720 }
721 
722 /**
723  * @brief Main logic function to parse sorted MAP file and to process pattern list.
724  *
725  * MAP file is of the form $header<#=#>$content<#=#>$logFileName<#=#>$skipInterval.
726  *
727  * @param[in] fname Configuration file.
728  *
729  * @return Returns status of the operation.
730  * @retval Return 0 upon success, -1 on failure.
731  */
732 int parseFile(char *fname)
733 {
734  FILE *sfp = NULL;
735  char line[MAXLINE];
736  char *filename = NULL, *prevfile = NULL;
737  int pcIndex = 0;
738  GList *pchead = NULL, *rdkec_head = NULL;
739  errno_t rc = -1;
740  int ind = -1;
741  int snmp_len = strlen("snmp");
742 
743  if (NULL == (sfp = fopen(fname, "r"))) {
744  return (-1);
745  }
746 
747  while (NULL != fgets(line, MAXLINE, sfp)) {
748  // Remove new line
749  int len = strlen(line);
750  if (len > 0 && line[len-1] == '\n')
751  line[--len] = '\0';
752 
753  // multiple string split
754  char *temp_header = strSplit(line, DELIMITER);
755  char *temp_pattern = strSplit(NULL, DELIMITER);
756  char *temp_file = strSplit(NULL, DELIMITER);
757  char *temp_skip_interval = strSplit(NULL, DELIMITER);
758  int tmp_skip_interval, is_skip_param;
759  DType_t dtype;
760 
761  if (NULL == temp_file || NULL == temp_pattern || NULL == temp_header || NULL == temp_skip_interval)
762  continue;
763 
764  //LOG(">l:%s,f:%s,p:%s<", line, temp_file, temp_pattern);
765  if ((temp_pattern[0] == '\0' ) || (temp_file[0] == '\0') )
766  continue;
767  rc = strcasecmp_s( "snmp",snmp_len,temp_file,&ind);
768  ERR_CHK(rc);
769  if((0 == ind) && (rc == EOK))
770  continue;
771 
772  getDType(temp_file, temp_header, &dtype);
773  tmp_skip_interval = atoi(temp_skip_interval);
774 
775  if (tmp_skip_interval <= 0)
776  tmp_skip_interval = 0;
777 
778  is_skip_param = isSkipParam(tmp_skip_interval);
779 
780 
781  if (NULL == filename) {
782  filename = malloc(strlen(temp_file) + 1);
783  pchead = NULL;
784  if (is_skip_param == 0 && (0 == insertPCNode(&pchead, temp_pattern, temp_header, dtype, 0, NULL))) {
785  pcIndex = 1;
786  }
787  } else {
788  rc = strcmp_s(filename, strlen(filename), temp_file , &ind);
789  ERR_CHK(rc);
790 
791  if ((!ind) && (rc == EOK) && pcIndex <= MAX_PROCESS ) {
792  if (is_skip_param == 0 && (0 == insertPCNode(&pchead, temp_pattern, temp_header, dtype, 0, NULL))) {
793  pcIndex++;
794  }
795  } else {
796  char *tmp = NULL;
797  processPattern(&prevfile, filename, &rdkec_head, pchead, pcIndex);
798  pchead = NULL;
799  tmp = realloc(filename, strlen(temp_file) + 1);
800  if (NULL != tmp) {
801  filename = tmp;
802  } else {
803  free(filename);
804  filename = NULL;
805  }
806  if (is_skip_param == 0 && (0 == insertPCNode(&pchead, temp_pattern, temp_header, dtype, 0, NULL))) {
807  pcIndex = 1;
808  }
809  }
810  }
811  if (NULL != filename) {
812  rc = strcpy_s(filename,strlen(temp_file) + 1,temp_file);
813  if(rc != EOK)
814  {
815  ERR_CHK(rc);
816  free(filename);
817  if(prevfile)
818  free(prevfile);
819  fclose(sfp);
820  return -1;
821  }
822  }
823  usleep(USLEEP_SEC);
824  }
825  processPattern(&prevfile, filename, &rdkec_head, pchead, pcIndex);
826  writeLogSeek(filename, LAST_SEEK_VALUE);
827  pchead = NULL;
828 
829  /* max limit not maintained for rdkec_head FIXME */
830  if (NULL != rdkec_head) {
831  addToJson(rdkec_head);
832  // clear nodes memory after process
833  clearPCNodes(&rdkec_head);
834  rdkec_head = NULL;
835  }
836 
837  addToSearchResult("<remaining_keys>", "<remaining_values>");
838 
839  if (NULL != filename)
840  free(filename);
841 
842  if (NULL != prevfile)
843  free(prevfile);
844 
845  fclose(sfp);
846  return 0;
847 }
848 
849 /**
850  * @brief Main Function.
851  *
852  * @param[in] Command line arguments(Sorted pattern conf file, previous log path, Custom persistent path).
853  *
854  * @return Returns status of the operation.
855  * @retval Returns the return code of parseFile function.
856  */
857 int main(int argc, char *argv[]) {
858  char *fname = NULL;
859  char *logPath = NULL;
860  char *persistentPath = NULL;
861  int rc = -1;
862 
863  if (argc >= 2) {
864  fname = argv[1];
865  }
866  if (argc >= 3) {
867  logPath = argv[2];
868  }
869  if (argc >= 4) {
870  persistentPath = argv[3];
871  }
872 
873  if (NULL != fname) {
874  LOG("Conf File = %s ", fname);
875  if (NULL != logPath) {
876  LOG("Log Path = %s ", logPath);
877  }
878  if (NULL != persistentPath) {
879  LOG("Persistent Path = %s ", persistentPath);
880  }
881  updateConfVal(logPath, persistentPath);
883  initSearchResultJson(&ROOT_JSON, &SEARCH_RESULT_JSON);
884  rc = parseFile(fname);
885  printJson(ROOT_JSON);
886  clearSearchResultJson(&ROOT_JSON);
887  clearConfVal();
888  }
889  return rc;
890 }
891 
892 /** @} */ //END OF GROUP DCA_APIS
893 
894 
895 /** @} */
896 
897 
898 /** @} */
899 /** @} */
insertPCNode
int insertPCNode(GList **pch, char *pattern, char *header, DType_t dtype, int count, char *data)
To insert a new pattern node at the beginning of the list.
Definition: dcalist.c:58
getLoadAvg
int getLoadAvg()
This API is to find the load average of system and add it to the SearchResult JSON.
Definition: dcautils.c:57
handleRDKErrCodes
int handleRDKErrCodes(GList **rdkec_head, char *line)
Function to handle error codes received from the log file.
Definition: dca.c:486
processTopPattern
int processTopPattern(char *logfile, GList *pchead, int pcIndex)
This API processes the top command log file patterns to retrieve load average and process usage.
Definition: dca.c:150
updateConfVal
void updateConfVal(char *logpath, char *perspath)
Function to update the configuration values from device.properties file.
Definition: dcautils.c:491
getDType
void getDType(char *filename, char *header, DType_t *dtype)
To get node data type based on pattern.
Definition: dca.c:692
clearConfVal
void clearConfVal(void)
This function is to clear/free the global paths.
Definition: dcautils.c:101
get_tr181param_value
int get_tr181param_value(const char *path_namespace, char *parm_value, int len)
This API is to retrieve the value of TR181 telemetry.
Definition: dcatr181.c:101
ccsp_handler_exit
void ccsp_handler_exit()
This API is to uninitialize message bus.
Definition: dcatr181.c:89
writeLogSeek
void writeLogSeek(char *name, long seek_value)
Function to write the rotated Log file.
Definition: dcautils.c:678
clearPCNodes
void clearPCNodes(GList **pch)
To delete/clear all the nodes in the list.
Definition: dcalist.c:208
getErrorCode
int getErrorCode(char *str, char *ec, int ec_length)
To get RDK error code.
Definition: dca.c:439
addToSearchResult
void addToSearchResult(char *key, char *value)
This API is to append the key/value pair to the SearchResult JSON array .
Definition: dcajson.c:71
searchPCNode
pcdata_t * searchPCNode(GList *pch, char *pattern)
To search node from the list based on the given pattern.
Definition: dcalist.c:135
getIPVideo
int getIPVideo(char *line, pcdata_t *pcnode)
Function to process pattern if it has split text in the header.
Definition: dca.c:390
printJson
void printJson(cJSON *root)
This API is to print Json result.
Definition: dcajson.c:99
processPattern
int processPattern(char **prev_file, char *logfile, GList **rdkec_head, GList *pchead, int pcIndex)
Generic pattern function based on pattern to call top/count or using ccsp message bus.
Definition: dca.c:567
getProcUsage
int getProcUsage(char *processName)
To get process usage.
Definition: dcaproc.c:106
logtype_pair
Definition: dca.c:82
updateExecCounter
void updateExecCounter()
To update current dca execution count.
Definition: dcautils.c:116
processCountPattern
int processCountPattern(char *logfile, GList *pchead, int pcIndex, GList **rdkec_head)
Function to process pattern count (loggrep)
Definition: dca.c:524
strSplit
char * strSplit(char *str, char *delim)
Function like strstr but based on the string delimiter.
Definition: dca.c:658
addToJson
int addToJson(GList *pchead)
This function adds the value to the telemetry output json object.
Definition: dca.c:347
initSearchResultJson
void initSearchResultJson(cJSON **root, cJSON **sr)
This API creates "searchResult" JSON array.
Definition: dcajson.c:57
parseFile
int parseFile(char *fname)
Main logic function to parse sorted MAP file and to process pattern list.
Definition: dca.c:732
getsRotatedLog
char * getsRotatedLog(char *buf, int buflen, char *name)
Function to return rotated log file.
Definition: dcautils.c:190
isSkipParam
int isSkipParam(int skipInterval)
This API is to verify whether to skip this telemetry marker.
Definition: dcautils.c:163
main
int main(int argc, char *argv[])
Main Function.
Definition: dca.c:857
clearSearchResultJson
void clearSearchResultJson(cJSON **root)
This API deletes the result JSON object.
Definition: dcajson.c:87
pclist
Definition: dcalist.h:48
ccsp_handler_init
int ccsp_handler_init()
This API initalizes the ccsp message bus.
Definition: dcatr181.c:68