Enabled timer at MAC and SCH [Issue-ID: ODUHIGH-283]
[o-du/l2.git] / src / rlog / rl_postproc.cpp
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
5 #   Licensed under the Apache License, Version 2.0 (the "License");            #
6 #   you may not use this file except in compliance with the License.           #
7 #   You may obtain a copy of the License at                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
11 #   Unless required by applicable law or agreed to in writing, software        #
12 #   distributed under the License is distributed on an "AS IS" BASIS,          #
13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
14 #   See the License for the specific language governing permissions and        #
15 #   limitations under the License.                                             #
16 ################################################################################
17 *******************************************************************************/
18
19 /********************************************************************20**
20
21      Name:     Radisys Logging Framework
22      Type:     C++ source file
23      Desc:     This file contains logging framework implementation.
24      File:     postproc.cpp
25
26 *********************************************************************21*/
27 ///////////////////////////////////////////////////////////////////////////////
28 // @ description: This is source file  contains the implementaion of binary log
29 // postprocessor and has ability to connect to remote node and print live logs. 
30 ///////////////////////////////////////////////////////////////////////////////
31
32 #include <iostream>
33 #include <fstream>
34 #include <string>
35 #include <sstream>
36 #include <map>
37 #include <list>
38 #include <algorithm>
39 #include <unistd.h>
40 #include <pthread.h>
41 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <getopt.h>
44 #include <stdarg.h>
45 #include <arpa/inet.h>
46 #include <fcntl.h>
47 #include <string.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <netdb.h>
51 #include <sys/types.h>
52 #include <arpa/inet.h>
53 #include "rl_interface.h"
54 #include "rl_rlog.h"
55
56 #define TEST_MODE
57
58 namespace cmdlinearg {
59 int g_port = 0;
60 std::string g_sFileDb;  /* File DB */
61 std::string g_sLogDb;   /* Log DB */
62 std::string g_sOutFile; /* Output file */
63 std::string g_sBinLogFile; /* Input binary log file */
64 std::string g_ipAddr;
65 }
66
67 typedef struct
68 {
69   int lineno;
70   std::string modName;
71   std::string file;
72   std::string logStr;
73
74 } LOG_INFO;
75
76 static struct option long_options[] =
77 {
78    {"port",   required_argument,   0, 'p'},
79    {"logdb",   required_argument,   0, 'l'},
80    {"ofile",  required_argument,   0, 'o'},
81    {"blog",   required_argument,   0, 'b'},
82    {"ipaddr",   required_argument,   0, 'i'},
83    {0, 0, 0, 0}
84 };
85
86 std::map<unsigned short, std::string> g_mFileInfo;
87 std::map<LOGID, LOG_INFO> g_mLogInfo;
88 FILE* g_fp=stderr;
89 uint32_t g_ttiCount = 0;
90 time_t g_basetimeSec;
91
92 void readCmdLineArgs(int argc,char **argv);
93 void printLogTime(LOGTIME & ltime);
94 void loadLogDb();
95 void printUsage();
96 void logHexDump(ARGDATA & log);
97 bool invalidLogId(LOGID logId);
98 void openLogFile(const char* file);
99 void logLevN(LOGDATA & log, LOG_INFO & logInfo, const char* fmtStr, ...);
100 void logLevS(LOGDATA & log, LOG_INFO & logInfo, const char* fmtStr, const char *logStr);
101 void logString(ARGDATA & log);
102 void logIntArg(ARG4DATA* log);
103 void logArgSpl(SPL_ARGDATA* log);
104 void processLogs(int fd, bool (*fpReadLog)(int, ARGDATA &));
105
106 bool readRemoteLogs(int sockfd, ARGDATA & log);
107 bool readFileLogs(int fd, ARGDATA & log);
108 int openBinLogFile();
109 int connectToLogServer();
110
111 ///////////////////////////////////////////////////////////////////////////////////////////////////
112 // @arg[in] argc  - Number of arguments
113 // @arg[in] argv - Command line arguments
114 // This is main functions, which calls a function to parse command line arguments. Then it loads
115 // log metadata into memory. And then based on if its remote logging or binary log file parsing
116 // passes apropriate function pointer to read and convert logs.
117 ///////////////////////////////////////////////////////////////////////////////////////////////////
118 int main(int argc, char* argv[])
119 {
120   readCmdLineArgs(argc, argv);
121   loadLogDb();
122
123   if( !cmdlinearg::g_sBinLogFile.empty() ) 
124   {
125     if( !cmdlinearg::g_sOutFile.empty() )
126     {
127       openLogFile(cmdlinearg::g_sOutFile.c_str());
128
129       processLogs(openBinLogFile(), readFileLogs);
130       fclose(g_fp);
131     }
132   }
133
134   if( cmdlinearg::g_port != 0 ) {
135
136     if( !cmdlinearg::g_sOutFile.empty() ) {
137       openLogFile(cmdlinearg::g_sOutFile.c_str());
138     }
139       
140
141     processLogs(connectToLogServer(), readRemoteLogs);
142
143     fclose(g_fp);
144   }
145    return 0;
146 }
147
148 ///////////////////////////////////////////////////////////////////////////////////////////////////
149 // @param[in] file - Input log file name
150 // This function opens the log file in write mode.
151 ///////////////////////////////////////////////////////////////////////////////////////////////////
152 void openLogFile(const char* file)
153 {
154    g_fp = fopen(file, "w+");
155    
156   if( g_fp == NULL ) 
157   {
158       fprintf(stderr, "Failed to open log file %s\n", file);
159       _exit(0);
160    }
161
162    fprintf(stderr, "Log Output will be written in %s\n", file);
163 }
164
165 uint32_t swap_uint32( uint32_t val )
166 {
167     val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF ); 
168     return (val << 16) | (val >> 16);
169 }
170
171
172 unsigned long EndianSwap32(unsigned long x)
173 {
174     unsigned long y=0;
175     y += (x & 0x000000FF)<<24;
176     y += (x & 0xFF000000)>>24;
177     y += (x & 0x0000FF00)<<8;
178     y += (x & 0x00FF0000)>>8;
179     return y;
180 }
181
182 void print_hex(const char* str, const uint8_t *p, int len)
183 {
184   fprintf(stderr, "%s HEX \n", str);
185   for(int i=0; i<len; i++ ) fprintf(stderr, "%d ", p[i]);
186   fprintf(stderr, "\n");
187
188 }
189
190 ///////////////////////////////////////////////////////////////////////////////////////////////////
191 // This function open the log file in binary mode and checks if file header is correct or not.
192 // It also sets the environment variable for given time zone in log file, so that time information
193 // is converted to correct time zone times.
194 ///////////////////////////////////////////////////////////////////////////////////////////////////
195 int openBinLogFile()
196 {
197   int fd = open(cmdlinearg::g_sBinLogFile.c_str(), O_RDONLY );
198
199   if( fd == -1) {
200       fprintf(stderr, "Failed to open log file %s\n", cmdlinearg::g_sBinLogFile.c_str());
201     _exit(0);
202   }
203
204   FILE_HEADER fileHdr;
205
206   int len = read(fd, (void*)&fileHdr, sizeof(FILE_HEADER));
207
208   if( fileHdr.END_MARKER != 0xFFFF ) {
209     fprintf(stderr, "Invalid file header\n");
210     _exit(0);
211   }
212
213   fprintf(stderr, "FILE ENDIAN: %s\n", fileHdr.endianType == big_endian ? "BIG ENDIAN" : "LITTLE ENDIAN");
214   fprintf(stderr, "TIME ZONE: %s\n", fileHdr.szTimeZone);
215
216   setenv("TZ", fileHdr.szTimeZone, 1);
217   tzset();
218
219   if( fileHdr.endianType == big_endian ) {
220   }
221   g_basetimeSec = fileHdr.time_sec;
222   return fd;
223 }
224
225 ///////////////////////////////////////////////////////////////////////////////////////////////////
226 // This function connects to remote application which is using binary logging framework. If 
227 // connection is failed log application exits.
228 ///////////////////////////////////////////////////////////////////////////////////////////////////
229 int connectToLogServer()
230 {
231   int sockfd;
232   struct addrinfo hints;
233   struct addrinfo *res = NULL;
234   struct addrinfo *result = NULL;
235   int errcode;
236   char addrstr[100];
237   void *ptr = NULL;
238   struct sockaddr_in serv_addr;
239   struct sockaddr_in6 serv_addr6;
240   void *sockServAddr = NULL;
241   int ai_family = AF_UNSPEC;
242   int size = 0;
243
244   /* ccpu00147898 fixes */
245   memset(&hints, 0, sizeof(hints));
246   memset(&serv_addr, 0, sizeof(serv_addr));
247   memset(&serv_addr6, 0, sizeof(serv_addr6));
248   hints.ai_family = PF_UNSPEC;
249   hints.ai_socktype = SOCK_STREAM;
250   hints.ai_flags |= AI_CANONNAME;
251
252   errcode = getaddrinfo(cmdlinearg::g_ipAddr.c_str(), NULL, &hints, &res);
253   if(errcode != 0)
254   {
255     perror ("getaddrinfo");
256     return -1;
257   }
258
259   result = res;
260   while(res)
261   {
262     inet_ntop(res->ai_family, res->ai_addr->sa_data, addrstr, 100);
263
264     switch(res->ai_family)
265     {
266       case AF_INET:
267         ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr;
268         serv_addr.sin_addr = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
269         sockServAddr = &serv_addr;
270         ai_family = res->ai_family; 
271         serv_addr.sin_family = res->ai_family;
272         serv_addr.sin_port = htons(cmdlinearg::g_port);
273         size =  sizeof(serv_addr);
274         break;
275       case AF_INET6:
276         ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
277         sockServAddr = &serv_addr6; 
278         /* Copy IPv6 address(16bytes) into the destination */ 
279         memcpy((unsigned char*)serv_addr6.sin6_addr.s6_addr, (unsigned char *)
280          &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr, 16);
281         ai_family = res->ai_family;
282         serv_addr6.sin6_family = res->ai_family;
283         serv_addr6.sin6_port = htons(cmdlinearg::g_port);
284         size =  sizeof(serv_addr6);
285         break;
286       default:
287         sockServAddr = NULL;
288         break;
289     }
290
291     if(ptr != NULL)
292     {
293        inet_ntop(res->ai_family, ptr, addrstr, 100);
294        printf ("IPv%d address: %s (%s)\n", res->ai_family == PF_INET6 ? 6 : 4,
295              addrstr, res->ai_canonname);
296     }
297     res = res->ai_next;
298   }
299  
300   if(sockServAddr == NULL || size == 0)
301   {
302      fprintf(stderr, "Not able to parse server address\n");
303      _exit(0);
304   }
305
306   if( (sockfd = socket(ai_family, SOCK_STREAM,0)) < 0 ) {
307     fprintf(stderr, "Failed to create socket\n");
308     _exit(0);
309   }
310   
311   if( connect(sockfd, (const sockaddr*)sockServAddr, size) < 0 ) {
312     perror("ERROR Connecting");
313     _exit(0);
314   }
315
316   if(result != NULL)
317   {
318     freeaddrinfo(result);
319   }
320   return sockfd;
321 }
322
323 ///////////////////////////////////////////////////////////////////////////////////////////////////
324 // @param[in] sockfd - Socket file descriptor
325 // @paramp[in] log  - Log data buffer
326 // This function reads the log header and remaining log from socket descriptor. Will return false
327 // if socket operation fails.
328 ///////////////////////////////////////////////////////////////////////////////////////////////////
329 bool readRemoteLogs(int sockfd, ARGDATA & log)
330 {
331   int len;
332
333   while( (len = recv(sockfd, (void*)&log.logData, RLOG_FIXED_LENGTH_BUFFER_SIZE, MSG_WAITALL)) == 0 );
334   if( len < 0 ) {
335     return false;
336   }
337
338
339   return true;
340 }
341
342 ///////////////////////////////////////////////////////////////////////////////////////////////////
343 // @param[in] fd - input file descriptor
344 // @param[out] log - Log header 
345 // This function will read the log header and returns success if able to read.
346 ///////////////////////////////////////////////////////////////////////////////////////////////////
347 bool readFileLogs(int fd, ARGDATA & log)
348 {
349   int len = read(fd, (void*)&log.logData, sizeof(LOGDATA));
350
351   if( len <= 0 ) {
352     return false;
353   }
354
355 #ifdef RLOG_MULTI_CIRCULAR_BUFFER
356   if( log.logData.len && read(fd, (void*)log.buf, log.logData.len) <= 0 ) {
357     return false;
358   }
359 #else
360    uint16_t size = RLOG_FIXED_LENGTH_BUFFER_SIZE - sizeof(LOGDATA);
361 //  if( log.logData.len && read(fd, (void*)log.buf, size) <= 0 ) {
362   if( read(fd, (void*)log.buf, size) <= 0 ) {
363     return false;
364   }
365 #endif
366
367   return true;
368 }
369
370 ///////////////////////////////////////////////////////////////////////////////////////////////////
371 // @param[in] log1 - LOG 
372 // @param[in] log2 - Second Log
373 // This function compares the TTI of two consecutive logs.
374 ///////////////////////////////////////////////////////////////////////////////////////////////////
375 bool cmp_tti(ARGDATA & log1, ARGDATA & log2)
376 {
377   return log2.logData.logTime.ms_tti > log1.logData.logTime.ms_tti ? true : false;
378 }
379
380 ///////////////////////////////////////////////////////////////////////////////////////////////////
381 // @param[in] log - Log data
382 // This function calculates the time based on TTI & time reference associated with it. And thne 
383 // calls the function to print logs in aprpriate text format.
384 ///////////////////////////////////////////////////////////////////////////////////////////////////
385 void printLog(ARGDATA & log)
386 {
387
388   if( invalidLogId(log.logData.logId) )
389     return;
390   
391   switch( log.logData.argType )
392   {
393     case LOG_ARG_INT:
394       logIntArg((ARG4DATA*)&log);
395       break;
396
397     case  LOG_ARG_STR:
398       logString(log);
399       break;
400
401     case LOG_ARG_HEX:
402       logHexDump(log);
403       break;
404
405     case LOG_ARG_SPL:
406       logArgSpl((SPL_ARGDATA*)&log);
407       break;
408   }
409 }
410
411 ///////////////////////////////////////////////////////////////////////////////////////////////////
412 // @param[in] fd - File or socket descriptor
413 // @param[in] fpReadLog - Function pointer which reads either file or socket based log
414 // This function reads the binary log file and does sorting of logs based on TTI and then calls the
415 // function to print it
416 ///////////////////////////////////////////////////////////////////////////////////////////////////
417 void processLogs(int fd, bool (*fpReadLog)(int, ARGDATA &))
418 {
419   ARGDATA log;
420   bool bSortingRequired = false, bStartBuffering = false;
421   std::list<ARGDATA> logList;
422
423   while((*fpReadLog)(fd, log)) 
424   {
425     if( log.logData.logId == L_TIME_DELIMITER ) 
426     {
427       bStartBuffering = (bStartBuffering == false) ? true : false;
428       if( bStartBuffering == true ) {
429         bSortingRequired = true;
430         continue;
431       }
432     }
433
434     if( bStartBuffering ) {
435       logList.push_back(log);
436       continue;
437     }
438   
439     if( bSortingRequired ) {
440       logList.sort(cmp_tti);  
441       std::for_each(logList.begin(), logList.end(), printLog);
442       logList.clear();
443       bSortingRequired = false;
444       bStartBuffering = false;
445       continue;
446     }
447
448     printLog(log);
449   }
450
451   /* connection was closed due to some error, but we still have some logs */
452   if( bStartBuffering && !logList.empty() ) 
453   {
454     logList.sort(cmp_tti);  
455     std::for_each(logList.begin(), logList.end(), printLog);
456   }
457
458   close(fd);
459 }
460
461
462 ///////////////////////////////////////////////////////////////////////////////////////////////////
463 // @param[in] log - LOG Data
464 // This function convert binary log with integer data type into text format.
465 ///////////////////////////////////////////////////////////////////////////////////////////////////
466 void logIntArg(ARG4DATA* log)
467 {
468 #ifdef TEST_MODE
469 //  printf("LOG ARG: INT, LEVEL: %s\n", g_logStr[log->logData.logLevel]);
470 #endif
471   
472   LOG_INFO & logInfo = g_mLogInfo[log->logData.logId];
473   logLevN(log->logData,logInfo,logInfo.logStr.c_str(),log->arg1,log->arg2,log->arg3,log->arg4); 
474 }
475
476 ///////////////////////////////////////////////////////////////////////////////////////////////////
477 // @param[in] log - LOG Data
478 // This function converts binary log containg string into text format.
479 ///////////////////////////////////////////////////////////////////////////////////////////////////
480 void logString(ARGDATA & log)
481 {
482 #ifdef TEST_MODE
483 //  printf("LOG ID %ld LOG ARG STRING, LEVEL: %s\n", log.logData.logId, g_logStr[log.logData.logLevel]);
484 #endif
485   
486   LOG_INFO & logInfo = g_mLogInfo[log.logData.logId];
487   logLevS(log.logData, logInfo, logInfo.logStr.c_str(), log.buf); 
488 }
489
490 ///////////////////////////////////////////////////////////////////////////////////////////////////
491 // @param[in] log - LOG Data
492 // This function converts binary log containg hex dump into readable text format.
493 ///////////////////////////////////////////////////////////////////////////////////////////////////
494 void logHexDump(ARGDATA & log)
495 {
496 #ifdef TEST_MODE
497 //  printf("LOG ARG HEX, LEVEL: %s\n", g_logStr[log.logData.logLevel]);
498 #endif
499   
500   LOG_INFO & logInfo = g_mLogInfo[log.logData.logId];
501
502   char szHex[MAX_LOG_BUF_SIZE*3];
503    hextostr(szHex, log.buf, log.logData.len);
504
505   logLevN(log.logData, logInfo, logInfo.logStr.c_str(), szHex); 
506 }
507
508 ///////////////////////////////////////////////////////////////////////////////////////////////////
509 // @param[in] log - LOG Data
510 // @param[in] logInfo - Log information structure reference
511 // @param[in] fmtStr - Formatted string
512 // This function prints log into console or log file.
513 ///////////////////////////////////////////////////////////////////////////////////////////////////
514 void logLevN(LOGDATA & log, LOG_INFO & logInfo, const char* fmtStr, ...)
515 {
516    va_list argList;
517   const char* file = logInfo.file.c_str();
518
519   printLogTime(log.logTime);
520    fprintf(g_fp, "[%s]%s:%d\n%s:", logInfo.modName.c_str(), file, logInfo.lineno, g_logStr[log.logLevel]);
521
522    va_start(argList,fmtStr);
523    vfprintf(g_fp, fmtStr, argList);
524    va_end(argList);
525 }
526
527 ///////////////////////////////////////////////////////////////////////////////////////////////////
528 // @param[in] log - LOG Data
529 // @param[in] logInfo - Log information structure reference
530 // @param[in] fmtStr - Formatted string
531 // This function prints string log into console or log file.
532 ///////////////////////////////////////////////////////////////////////////////////////////////////
533 void logLevS(LOGDATA & log, LOG_INFO & logInfo, const char* fmtStr, const char* logStr)
534 {
535    const char* file = logInfo.file.c_str();
536    std::string argStr(logStr, log.len);
537    printLogTime(log.logTime);
538    fprintf(g_fp, "[%s]%s:%d\n%s:", logInfo.modName.c_str(), file, logInfo.lineno, g_logStr[log.logLevel]);
539    fprintf(g_fp, fmtStr, argStr.c_str());
540 }
541
542 ///////////////////////////////////////////////////////////////////////////////////////////////////
543 // @param[in] log - LOG Data
544 // @param[in] logInfo - Log information structure reference
545 // @param[in] fmtStr - Formatted string
546 // This function prints log into console or log file.
547 ///////////////////////////////////////////////////////////////////////////////////////////////////
548 void logLevSpl(SPL_ARGDATA* log, LOG_INFO & logInfo, const char* fmtStr, ...)
549 {
550    va_list argList;
551   const char* file = logInfo.file.c_str();
552
553   printLogTime(log->logData.logTime);
554    fprintf(g_fp, "[%s]%s:%d\n%s:%s:%d:", logInfo.modName.c_str(), file, logInfo.lineno, g_logStr[log->logData.logLevel], g_splStr[log->splEnum], log->splArg);
555
556    va_start(argList,fmtStr);
557    vfprintf(g_fp, fmtStr, argList);
558    va_end(argList);
559 }
560
561 ///////////////////////////////////////////////////////////////////////////////////////////////////
562 // @param[in] log - LOG Data
563 // This function converts binary log with special arguments into text format.
564 ///////////////////////////////////////////////////////////////////////////////////////////////////
565 void logArgSpl(SPL_ARGDATA* log)
566 {
567 #ifdef TEST_MODE
568 //  printf("LOG ARG SPL, LEVEL: %s\n", g_logStr[log->logData.logLevel]);
569 #endif
570   LOG_INFO & logInfo = g_mLogInfo[log->logData.logId];
571   const char* file = logInfo.file.c_str();
572
573   logLevSpl(log, logInfo, logInfo.logStr.c_str(),log->arg1, log->arg2, log->arg3, log->arg4);
574 }
575
576 ///////////////////////////////////////////////////////////////////////////////////////////////////
577 // @param[in] ltime - Log time
578 // This function prints log time using standard c formating function fprintf
579 ///////////////////////////////////////////////////////////////////////////////////////////////////
580 void printLogTime(LOGTIME & ltime)
581 {
582   struct tm* tm;
583   time_t curTimeSec;
584   uint32_t secElapsedFromBeg;
585   uint32_t ttiNum; 
586   uint32_t miliseconds;
587
588   ttiNum = ltime.ms_tti;
589   secElapsedFromBeg = ttiNum/1000;
590   miliseconds = ttiNum%1000;
591   curTimeSec   = g_basetimeSec + secElapsedFromBeg;
592
593   /* Obtain the time of day, and convert it to a tm struct. --*/
594   tm = localtime (&curTimeSec);
595
596   if(NULL != tm) 
597    {
598       fprintf(g_fp,"[%d-%d-%d %d:%d:%d.%03d]", tm->tm_mday, tm->tm_mon+1, tm->tm_year+1900,
599             tm->tm_hour, tm->tm_min,tm->tm_sec,miliseconds);
600    }
601 }
602
603 ///////////////////////////////////////////////////////////////////////////////////////////////////
604 // @param[in] logId - Log id which is unique to each log
605 // This function checks if the given log id is valid based on the logdb information loaded into 
606 // memory.
607 ///////////////////////////////////////////////////////////////////////////////////////////////////
608 bool invalidLogId(LOGID logId)
609 {
610    /* if this is a time reference this is valid log */
611    if( g_mLogInfo.find(logId) == g_mLogInfo.end() )
612    {
613       if(logId != L_TIME_REFERENCE)
614       {
615          fprintf(stderr, "Invalid log id %d\n",logId);
616       }
617       return true;
618    }
619    return false;
620 }
621
622 ///////////////////////////////////////////////////////////////////////////////////////////////////
623 // This function parse and reads the logdb file. Extracts the information and stores into map data
624 // structure.
625 ///////////////////////////////////////////////////////////////////////////////////////////////////
626 void loadLogDb()
627 {
628   std::ifstream logdb(cmdlinearg::g_sLogDb.c_str());
629
630   if(logdb.is_open() == false) {
631     fprintf(stderr, "Failed to open file %s\n", cmdlinearg::g_sLogDb.c_str());
632     _exit(0);
633   }
634
635   LOGID logId; LOG_INFO logInfo;
636   std::string line;
637    std::string & lstr = logInfo.logStr;
638   
639   while( getline(logdb, line) )
640   {
641     std::istringstream iss(line);
642     int pos = 0, newpos=0;
643
644     logId = atol( line.substr(pos, newpos=line.find(';', pos)).c_str() );
645
646     pos = newpos+1;
647     logInfo.lineno = atol( line.substr(pos, (newpos=line.find(';', pos)) - pos).c_str() );
648
649     pos = newpos+1;
650     logInfo.modName = line.substr(pos, (newpos=line.find(';', pos)) - pos);
651
652     pos = newpos+3;
653     logInfo.file = line.substr(pos, (newpos=line.find('\"', pos)) - pos);
654
655       pos=line.find('\"',newpos+1) + 1;
656     logInfo.logStr = line.substr(pos, (newpos=line.find_last_of("\"", pos)) - pos);
657       lstr.erase(std::remove(lstr.begin(),lstr.end(),'\"')++,lstr.end());
658
659
660 #ifdef TEST_MODE_0
661     std::cout << "LOG Id:" << logId << " FILE:" << logInfo.file << " lineno:" << logInfo.lineno;
662     std::cout << " MOD Name: " << logInfo.modName << std::endl;
663     std::cout << "LOG STR:[" << logInfo.logStr << "]" <<  std::endl;
664 #endif
665
666     logInfo.logStr+= "\n\n";
667
668     g_mLogInfo[logId] = logInfo;
669   }
670
671   logdb.close();
672
673   logInfo.file = "NULL";
674   logInfo.lineno = 0;
675   logInfo.modName = "RLOG";
676   logInfo.logStr =  RLOG_SEGFAULT_STR; 
677   g_mLogInfo[L_SIGSEGV] = logInfo;
678   
679 }
680
681 ///////////////////////////////////////////////////////////////////////////////////////////////////
682 // @arg[in] argc  - Number of arguments
683 // @arg[in] argv - Command line arguments
684 // This function parses the command line input parameters.
685 ///////////////////////////////////////////////////////////////////////////////////////////////////
686 void readCmdLineArgs(int argc,char **argv)
687 {
688   using namespace cmdlinearg;
689    /* getopt_long stores the option index here */
690    int c, option_index = 0;
691
692    while(  (c = getopt_long(argc, argv, "p:f:l:o:b:i:", long_options,&option_index)) != -1 )
693    {
694       switch(c)
695        {
696            case 'p':
697                 std::cout<<"option -p with value = " << optarg << std::endl;
698                 cmdlinearg::g_port = atoi(optarg);
699                 break;
700            case 'f':
701                 std::cout<<"option -f with value = "<< optarg << std::endl;
702                 cmdlinearg::g_sFileDb = optarg;
703                 break;
704            case 'l':
705                 std::cout<<"option -l with value = "<< optarg << std::endl;
706                 cmdlinearg::g_sLogDb = optarg;
707                 break;
708            case 'o': 
709                 std::cout<<"option -o with value = " << optarg << std::endl;
710                 cmdlinearg::g_sOutFile = optarg;
711                 break;
712            case 'b': 
713                 std::cout<<"option -b with value = " << optarg << std::endl;
714                 cmdlinearg::g_sBinLogFile = optarg;
715                 break;
716            case 'i': 
717                 std::cout<<"option -i with value = " << optarg << std::endl;
718                 cmdlinearg::g_ipAddr = optarg;
719                 break;
720         defult:
721           std::cout << "Invalid arguments" << std::endl;
722           exit(0);
723     }
724   }
725
726 //  if( g_port == 0 && g_sBinLogFile.empty() )
727 //    printUsage();
728
729 }
730
731 ///////////////////////////////////////////////////////////////////////////////////////////////////
732 // This functin prints the binary log application usage.
733 ///////////////////////////////////////////////////////////////////////////////////////////////////
734 void printUsage()
735 {
736   printf("Usage: postproc [-f <filedb> ] [-l <logdb>] [-b <binlog> | -p <port> ] [-o <outfile>] \n");
737   printf("\t[--filedb | -p <input file db > ]\n");
738   printf("\t[--logdb  | -l <input log db > ]\n");
739   printf("\t[--binlog | -b <input binary log file> ]\n");
740   printf("\t[--ofile  | -o <output text log file> ]\n");
741   printf("\t[--port   | -p <port number> ]\n");
742   _exit(0);
743 }
744
745 /**********************************************************************
746          End of file
747 **********************************************************************/