commsfwtools/commstools/utracedecoder/src/utracedecoderapp.cpp
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <iostream>
       
    17 #include <sstream>
       
    18 #include <string>
       
    19 
       
    20 #include <windows.h>
       
    21 
       
    22 #include "utracedecoderapp.h"
       
    23 #include "utraceframe.h"
       
    24 #include "framesorter.h"
       
    25 #include "util.h"
       
    26 #include "logevents\traceeventbase.h"
       
    27 #include "version.h"
       
    28 
       
    29 const int KLogBufferSize = 16384;
       
    30 
       
    31 Parser::CDefinitionParser* gMsgDefParser;
       
    32 bool gQuiet;
       
    33 
       
    34 bool CUTraceDecoderApp::iUseTimes = false;
       
    35 CUTraceDecoderApp::TTimestampPeriod CUTraceDecoderApp::iPeriodType = CUTraceDecoderApp::EUnknown;
       
    36 double CUTraceDecoderApp::iPeriod1;
       
    37 double CUTraceDecoderApp::iPeriod2;
       
    38 
       
    39 CUTraceDecoderApp::CUTraceDecoderApp()
       
    40     {
       
    41     iFrameSorter = new CFrameSorter(*this);
       
    42 
       
    43     iDumpIdentifiers = false;
       
    44     iTesting = false;
       
    45     SetShowContextInfo(true);
       
    46     iCurrentFrame = 0;
       
    47     iUseQuotes = false;
       
    48     iTail = false;
       
    49 
       
    50     iInputBuffer = new unsigned char[KLogBufferSize];
       
    51     iBufferOffset = 0;
       
    52     iBufferSize = 0;
       
    53     iBufferValid = false;
       
    54 
       
    55     // There will only ever be one CUTraceDecoderApp so this isn't so bad
       
    56     // Needs refactoring though. gMsgDefParser is used by the Node Message Event
       
    57     ::gMsgDefParser = new Parser::CDefinitionParser();
       
    58 	::gQuiet = false;
       
    59     }
       
    60 
       
    61 
       
    62 CUTraceDecoderApp::~CUTraceDecoderApp()
       
    63     {
       
    64     delete iInputBuffer;
       
    65     }
       
    66 
       
    67 
       
    68 bool CUTraceDecoderApp::Initialise(int aArgc, char **aArgv) 
       
    69     {
       
    70     if (aArgc < 2)
       
    71 	    {
       
    72 	    return false;
       
    73 	    }
       
    74     
       
    75     // defaults
       
    76     SetShowContextInfo(true);
       
    77     SetNewLineEnabled(true);
       
    78     
       
    79     int currentArg = 1;
       
    80     while (currentArg < aArgc)
       
    81         {
       
    82         if (aArgv[currentArg][0] == '-' && aArgv[currentArg][1] == '-')
       
    83             {
       
    84             if (!_strcmpi(&aArgv[currentArg][2], "payload-only"))
       
    85                 {
       
    86                 SetShowContextInfo(false);
       
    87                 }
       
    88             else if (!_strcmpi(&aArgv[currentArg][2], "use-quotes"))
       
    89                 {
       
    90                 iUseQuotes = true;
       
    91                 }
       
    92             else if (!_strcmpi(&aArgv[currentArg][2], "use-times"))
       
    93                 {
       
    94                 iUseTimes = true;
       
    95                 }
       
    96             else if (!_strcmpi(&aArgv[currentArg][2], "tail"))
       
    97                 {
       
    98                 // EXPERIMENTAL: This is an experimental feature at the moment
       
    99                 iTail = true;
       
   100                 }
       
   101 			else if (!_strcmpi(&aArgv[currentArg][2], "quiet"))
       
   102 				{
       
   103 				::gQuiet = true;
       
   104 				}
       
   105             else if (!_strcmpi(&aArgv[currentArg][2], "message-def"))
       
   106                 {
       
   107                 currentArg++;
       
   108                 iMsgDefFile = aArgv[currentArg];
       
   109                 }
       
   110             else if (!_strcmpi(&aArgv[currentArg][2], "dump-frame"))
       
   111                 {
       
   112                 currentArg++;
       
   113                 char* startFrame = aArgv[currentArg];
       
   114 
       
   115                 char* endFrame = startFrame;
       
   116                 while (*endFrame != ',' && *endFrame != 0)
       
   117                     {
       
   118                     if (*endFrame < '0' || *endFrame > '9')
       
   119                         {
       
   120                         return false;
       
   121                         }
       
   122                     ++endFrame;
       
   123                     }
       
   124                 if (*endFrame == 0)
       
   125                     {
       
   126                     return false;
       
   127                     }
       
   128                 *endFrame = 0;
       
   129                 if (*startFrame == 0)
       
   130                     {
       
   131                     return false;
       
   132                     }
       
   133                 ++endFrame;
       
   134                 
       
   135                 char* tmp = endFrame;
       
   136                 while (*tmp != 0)
       
   137                     {
       
   138                     if (*tmp < '0' || *tmp > '9')
       
   139                         {
       
   140                         return false;
       
   141                         }
       
   142                     ++tmp;
       
   143                     }
       
   144 
       
   145                 iFrameSorter->SetDumpFrameRange(atol(startFrame), atol(endFrame));
       
   146                 }
       
   147             else if (!_strcmpi(&aArgv[currentArg][2], "dump-event"))
       
   148                 {
       
   149                 currentArg++;
       
   150                 char* startEvent = aArgv[currentArg];
       
   151 
       
   152                 char* endEvent = startEvent;
       
   153                 while (*endEvent != ',' && *endEvent != 0)
       
   154                     {
       
   155                     if (*endEvent < '0' || *endEvent > '9')
       
   156                         {
       
   157                         return false;
       
   158                         }
       
   159                     ++endEvent;
       
   160                     }
       
   161                 if (*endEvent == 0)
       
   162                     {
       
   163                     return false;
       
   164                     }
       
   165                 *endEvent = 0;
       
   166                 if (*startEvent == 0)
       
   167                     {
       
   168                     return false;
       
   169                     }
       
   170                 ++endEvent;
       
   171                 
       
   172                 char* tmp = endEvent;
       
   173                 while (*tmp != 0)
       
   174                     {
       
   175                     if (*tmp < '0' || *tmp > '9')
       
   176                         {
       
   177                         return false;
       
   178                         }
       
   179                     ++tmp;
       
   180                     }
       
   181 
       
   182                 iFrameSorter->SetDumpEventRange(atol(startEvent), atol(endEvent));
       
   183                 }
       
   184             else if (!_strcmpi(&aArgv[currentArg][2], "dump-message-def"))
       
   185                 {
       
   186                 iDumpIdentifiers = true;
       
   187                 }
       
   188             else if (!_strcmpi(&aArgv[currentArg][2], "test-message-def"))
       
   189                 {
       
   190                 iTesting = true;
       
   191                 }
       
   192             }
       
   193         else
       
   194             {
       
   195             if (iLogFile.length() > 0)
       
   196                 {
       
   197                 return false;
       
   198                 }
       
   199             iLogFile = aArgv[currentArg];
       
   200             }
       
   201 
       
   202         currentArg++;
       
   203         }
       
   204 
       
   205     if (iMsgDefFile.length() > 0)
       
   206         {
       
   207         if (iTesting)
       
   208             {
       
   209             gMsgDefParser->SetTestMode();
       
   210             }
       
   211 
       
   212         if (gMsgDefParser->ParseDefinitionFile(iMsgDefFile.c_str()) != Parser::ENoError)
       
   213             {
       
   214 //            std::cerr << "Error in message definition file" << std::endl;
       
   215             return false;
       
   216             }
       
   217         }
       
   218 
       
   219     if (iDumpIdentifiers)
       
   220         {
       
   221         gMsgDefParser->DumpIdentifiers();
       
   222         }
       
   223     
       
   224     if (iTesting)
       
   225         {
       
   226         if (iMsgDefFile.length() == 0)
       
   227             {
       
   228             std::cerr << "No message definition file specifed to check" << std::endl;
       
   229             }
       
   230         return true;
       
   231         }
       
   232 
       
   233     if (iLogFile.length() == 0)
       
   234         {
       
   235         return false;
       
   236         }
       
   237         
       
   238     return true;
       
   239     }
       
   240 
       
   241 
       
   242 void CUTraceDecoderApp::ProcessLog()
       
   243     {
       
   244     // csv header
       
   245     if (ShowContextInfo())
       
   246         {
       
   247         std::cout << "Sequence,Primary Filter,Sub Category,Time Stamp1,Time Stamp2,Context ID,Description" << std::endl;
       
   248         } 
       
   249 
       
   250     // Open the log file and fill the buffer
       
   251     if(!LoadUTraceLog()) 
       
   252         { // file couldn't be opened
       
   253         std::cerr << "Error: file " << iLogFile.c_str() << " could not be opened." << std::endl;
       
   254         return;
       
   255         }
       
   256 
       
   257     while (iBufferValid)
       
   258         {
       
   259         while (iBufferOffset < iBufferSize)
       
   260             {
       
   261             //grab a hunk of log
       
   262             int length = iInputBuffer[iBufferOffset];
       
   263             length = (length + 3) & ~3;
       
   264 
       
   265             // Minimum length is actually 4, but this would mean only the header was
       
   266             // present, so why was it logged
       
   267             if (length < 8 || length > KMaxBTraceRecordSize)
       
   268                 {
       
   269                 if (!iInputFile.eof())
       
   270                     {
       
   271                     std::cerr << "Error: Frame " << iCurrentFrame << " is corrupt - size is out of range (8-116)" << std::endl;
       
   272                     
       
   273                     // Dump what we have in the buffer, up to the max size of a frame
       
   274                     DumpBytes(std::cerr, &iInputBuffer[iBufferOffset], (KMaxBTraceRecordSize < (iBufferSize - iBufferOffset)) ? KMaxBTraceRecordSize : (iBufferSize - iBufferOffset));
       
   275                     }
       
   276                 return;
       
   277                 }
       
   278 
       
   279             if (length + iBufferOffset > iBufferSize)
       
   280                 {
       
   281                 break;
       
   282                 }
       
   283 	   		
       
   284             CUTraceFrame* frame = new CUTraceFrame(&iInputBuffer[iBufferOffset], iCurrentFrame);
       
   285             if (frame)
       
   286                 {
       
   287                 iFrameSorter->ProcessFrame(frame);
       
   288                 frame = NULL;
       
   289                 iCurrentFrame++;
       
   290                 }
       
   291             else
       
   292                 {
       
   293                 std::cerr << "Failed to create frame instance" << std::endl;
       
   294                 }
       
   295 	   		
       
   296             iBufferOffset += length;
       
   297             }
       
   298 		   
       
   299         RefillUTraceBuffer();
       
   300         }
       
   301     
       
   302     iInputFile.close();
       
   303 	
       
   304 	std::cerr << "Processed " << iCurrentFrame << " frames" << std::endl;
       
   305     }
       
   306 
       
   307 
       
   308 unsigned int CUTraceDecoderApp::CurrentFrame() const
       
   309     {
       
   310     return iCurrentFrame;
       
   311     }
       
   312 
       
   313 
       
   314 void CUTraceDecoderApp::WriteEvent(const CTraceEventBase& aEvent) const
       
   315     {
       
   316     if (NewLineEnabled())
       
   317         {
       
   318         if (ShowContextInfo())
       
   319             {
       
   320             aEvent.WriteContextInfo(std::cout);
       
   321             }
       
   322 
       
   323         if (iUseQuotes)
       
   324             {
       
   325             std::cout << "\"";
       
   326             }
       
   327         aEvent.WriteEventPrefix(std::cout);
       
   328         }
       
   329 
       
   330     if (iUseQuotes)
       
   331         {
       
   332         std::stringstream ss;
       
   333         aEvent.Describe(ss);
       
   334         std::string s = ss.str();
       
   335         // todo: replace " with ""
       
   336         std::cout << s;
       
   337         }
       
   338     else
       
   339         {
       
   340         aEvent.Describe(std::cout);
       
   341         }
       
   342 
       
   343     if (NewLineEnabled())
       
   344         {
       
   345         if (iUseQuotes)
       
   346             {
       
   347             std::cout << "\"";
       
   348             }
       
   349         std::cout << std::endl;
       
   350         }
       
   351     else
       
   352         {
       
   353         std::cout << " ";
       
   354         }
       
   355     };
       
   356 
       
   357 
       
   358 bool CUTraceDecoderApp::LoadUTraceLog()
       
   359     {
       
   360     iInputFile.open(iLogFile.c_str(), std::ios::in | std::ios::binary);
       
   361     if (iInputFile.is_open())
       
   362         {
       
   363         RefillUTraceBuffer();
       
   364         return true;
       
   365         }
       
   366 
       
   367     return false;
       
   368     }
       
   369 
       
   370 
       
   371 void CUTraceDecoderApp::RefillUTraceBuffer()
       
   372     {
       
   373     int bufferSpace = KLogBufferSize;
       
   374     int bufferInUse = 0;
       
   375 
       
   376     if (iBufferOffset)
       
   377         {
       
   378         bufferInUse = iBufferSize - iBufferOffset;
       
   379         bufferSpace = KLogBufferSize - bufferInUse;
       
   380         memcpy(iInputBuffer, &iInputBuffer[iBufferOffset], bufferInUse);
       
   381         }
       
   382 
       
   383     memset(&iInputBuffer[bufferInUse], 0, bufferSpace);
       
   384     iInputFile.read((char*)&iInputBuffer[bufferInUse], bufferSpace);
       
   385     iBufferSize = iInputFile.gcount();
       
   386 
       
   387 #ifdef _DEBUG
       
   388     std::cerr << std::dec << std::noshowbase << iBufferSize << " bytes read from log file" << std::endl;
       
   389 #endif
       
   390     iBufferValid = (iBufferSize > 0);
       
   391 
       
   392     if (!iBufferValid && iTail)
       
   393         {
       
   394         // EXPERIMENTAL: This is an experimental feature at the moment
       
   395         HANDLE fileChangeHandle;
       
   396         fileChangeHandle = FindFirstChangeNotificationA(iLogFile.c_str(), FALSE, FILE_NOTIFY_CHANGE_SIZE);
       
   397         if (fileChangeHandle != INVALID_HANDLE_VALUE)
       
   398             {
       
   399             iInputFile.read((char*)&iInputBuffer[bufferInUse], bufferSpace);
       
   400             iBufferSize = iInputFile.gcount();
       
   401 
       
   402             std::cerr << std::dec << std::noshowbase << iBufferSize << " bytes read from log file" << std::endl;
       
   403             iBufferValid = (iBufferSize > 0);
       
   404             FindCloseChangeNotification(fileChangeHandle);
       
   405             }
       
   406         }
       
   407 
       
   408     iBufferSize += bufferInUse;
       
   409     iBufferOffset = 0;
       
   410     }
       
   411 
       
   412 
       
   413 void CUTraceDecoderApp::ShowUsage()
       
   414     {
       
   415 	std::cerr
       
   416         << "utracedecoder " APPVERSION ":" << std::endl
       
   417 	    << "Log parser for utrace logs, converts a utrace generated log file into human readable and perl processable csv format" << std::endl
       
   418 	    << "utracedecoder [options] <path_to_log>" << std::endl
       
   419         << "    --payload-only                 Show only the message part of the trace" << std::endl
       
   420         << "    --use-quotes                   Wrap the description in quotes" << std::endl
       
   421         << "    --use-times                    \"time-in-seconds,0\" substituted for \"timestamp1,timestamp\" pair" << std::endl
       
   422         << "    --message-def <message_definition_file>  The file from which to load message and signature definition" << std::endl
       
   423         << "    --test-message-def             Tests the message definition file showing all errors then exits" << std::endl
       
   424         << std::endl << "Debugging options" << std::endl 
       
   425         << "    --dump-message-def             Dumps the parsed definition file details" << std::endl
       
   426         << "    --dump-frame <start_frame>,<end_frame>  Dumps the frames in the given range to stderr" << std::endl
       
   427         << "    --dump-event <first_event>,<last_event>  Dumps the events in the given range to stderr" << std::endl
       
   428 		<< "    --quiet                        Only output urgent warnings" << std::endl
       
   429         << std::endl;
       
   430     }
       
   431 
       
   432 void CUTraceDecoderApp::SetTimestampPeriod(CUTraceDecoderApp::TTimestampPeriod aType, double aPeriod1, double aPeriod2)
       
   433 	{
       
   434 	iPeriodType = aType;
       
   435 	iPeriod1 = aPeriod1;
       
   436 	iPeriod2 = aPeriod2;
       
   437 	}
       
   438