Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "trace_impl.h"
     12 
     13 #include <cassert>
     14 #include <string.h> // memset
     15 
     16 #ifdef _WIN32
     17 #include "trace_win.h"
     18 #else
     19 #include <stdio.h>
     20 #include <time.h>
     21 #include <stdarg.h>
     22 #include "trace_posix.h"
     23 #endif // _WIN32
     24 
     25 #define KEY_LEN_CHARS 31
     26 
     27 #ifdef _WIN32
     28     #pragma warning(disable:4355)
     29 // VS 2005: Disable warnings for default initialized arrays.
     30     #pragma warning(disable:4351)
     31 #endif // _WIN32
     32 
     33 namespace webrtc {
     34 static WebRtc_UWord32 levelFilter = kTraceDefault;
     35 
     36 // Construct On First Use idiom. Avoids "static initialization order fiasco".
     37 TraceImpl* TraceImpl::StaticInstance(CountOperation count_operation,
     38                                      const TraceLevel level)
     39 {
     40     // Sanities to avoid taking lock unless absolutely necessary (for
     41     // performance reasons).
     42     // count_operation == kAddRefNoCreate implies that a message will be
     43     // written to file.
     44     if((level != kTraceAll) && (count_operation == kAddRefNoCreate))
     45     {
     46         if(!(level & levelFilter))
     47         {
     48             return NULL;
     49         }
     50     }
     51     TraceImpl* impl =
     52         GetStaticInstance<TraceImpl>(count_operation);
     53     return impl;
     54 }
     55 
     56 TraceImpl* TraceImpl::GetTrace(const TraceLevel level)
     57 {
     58     return StaticInstance(kAddRefNoCreate, level);
     59 }
     60 
     61 TraceImpl* TraceImpl::CreateInstance()
     62 {
     63 #if defined(_WIN32)
     64     return new TraceWindows();
     65 #else
     66     return new TracePosix();
     67 #endif
     68 }
     69 
     70 TraceImpl::TraceImpl()
     71     : _critsectInterface(CriticalSectionWrapper::CreateCriticalSection()),
     72       _callback(NULL),
     73       _rowCountText(0),
     74       _fileCountText(0),
     75       _traceFile(*FileWrapper::Create()),
     76       _thread(*ThreadWrapper::CreateThread(TraceImpl::Run, this,
     77                                            kHighestPriority, "Trace")),
     78       _event(*EventWrapper::Create()),
     79       _critsectArray(CriticalSectionWrapper::CreateCriticalSection()),
     80       _nextFreeIdx(),
     81       _level(),
     82       _length(),
     83       _messageQueue(),
     84       _activeQueue(0)
     85 {
     86     _nextFreeIdx[0] = 0;
     87     _nextFreeIdx[1] = 0;
     88 
     89     unsigned int tid = 0;
     90     _thread.Start(tid);
     91 
     92     for(int m = 0; m < WEBRTC_TRACE_NUM_ARRAY; m++)
     93     {
     94         for(int n = 0; n < WEBRTC_TRACE_MAX_QUEUE; n++)
     95         {
     96             _messageQueue[m][n] = new
     97                 WebRtc_Word8[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
     98         }
     99     }
    100 }
    101 
    102 bool TraceImpl::StopThread()
    103 {
    104     // Release the worker thread so that it can flush any lingering messages.
    105     _event.Set();
    106 
    107     // Allow 10 ms for pending messages to be flushed out.
    108     // TODO (hellner): why not use condition variables to do this? Or let the
    109     //                 worker thread die and let this thread flush remaining
    110     //                 messages?
    111 #ifdef _WIN32
    112     Sleep(10);
    113 #else
    114     timespec t;
    115     t.tv_sec = 0;
    116     t.tv_nsec = 10*1000000;
    117     nanosleep(&t,NULL);
    118 #endif
    119 
    120     _thread.SetNotAlive();
    121     // Make sure the thread finishes as quickly as possible (instead of having
    122     // to wait for the timeout).
    123     _event.Set();
    124     bool stopped = _thread.Stop();
    125 
    126     CriticalSectionScoped lock(_critsectInterface);
    127     _traceFile.Flush();
    128     _traceFile.CloseFile();
    129     return stopped;
    130 }
    131 
    132 TraceImpl::~TraceImpl()
    133 {
    134     StopThread();
    135     delete &_event;
    136     delete &_traceFile;
    137     delete &_thread;
    138     delete _critsectInterface;
    139     delete _critsectArray;
    140 
    141     for(int m = 0; m < WEBRTC_TRACE_NUM_ARRAY; m++)
    142     {
    143         for(int n = 0; n < WEBRTC_TRACE_MAX_QUEUE; n++)
    144         {
    145             delete [] _messageQueue[m][n];
    146         }
    147     }
    148 }
    149 
    150 WebRtc_Word32 TraceImpl::AddLevel(char* szMessage, const TraceLevel level) const
    151 {
    152     switch (level)
    153     {
    154         case kTraceStateInfo:
    155             sprintf (szMessage, "STATEINFO ; ");
    156             break;
    157         case kTraceWarning:
    158             sprintf (szMessage, "WARNING   ; ");
    159             break;
    160         case kTraceError:
    161             sprintf (szMessage, "ERROR     ; ");
    162             break;
    163         case kTraceCritical:
    164             sprintf (szMessage, "CRITICAL  ; ");
    165             break;
    166         case kTraceInfo:
    167             sprintf (szMessage, "DEBUGINFO ; ");
    168             break;
    169         case kTraceModuleCall:
    170             sprintf (szMessage, "MODULECALL; ");
    171             break;
    172         case kTraceMemory:
    173             sprintf (szMessage, "MEMORY    ; ");
    174             break;
    175         case kTraceTimer:
    176             sprintf (szMessage, "TIMER     ; ");
    177             break;
    178         case kTraceStream:
    179             sprintf (szMessage, "STREAM    ; ");
    180             break;
    181         case kTraceApiCall:
    182             sprintf (szMessage, "APICALL   ; ");
    183             break;
    184         case kTraceDebug:
    185             sprintf (szMessage, "DEBUG     ; ");
    186             break;
    187         default:
    188             assert(false);
    189             return 0;
    190     }
    191     // All messages are 12 characters.
    192     return 12;
    193 }
    194 
    195 WebRtc_Word32 TraceImpl::AddModuleAndId(char* traceMessage,
    196                                         const TraceModule module,
    197                                         const WebRtc_Word32 id) const
    198 {
    199     // Use long int to prevent problems with different definitions of
    200     // WebRtc_Word32.
    201     // TODO (hellner): is this actually a problem? If so, it should be better to
    202     //                 clean up WebRtc_Word32
    203     const long int idl = id;
    204     if(idl != -1)
    205     {
    206         const unsigned long int idEngine = id>>16;
    207         const unsigned long int idChannel = id & 0xffff;
    208 
    209         switch (module)
    210         {
    211             case kTraceVoice:
    212                 sprintf(traceMessage, "       VOICE:%5ld %5ld;", idEngine,
    213                         idChannel);
    214                 break;
    215             case kTraceVideo:
    216                 sprintf(traceMessage, "       VIDEO:%5ld %5ld;", idEngine,
    217                         idChannel);
    218                 break;
    219             case kTraceUtility:
    220                 sprintf(traceMessage, "     UTILITY:%5ld %5ld;", idEngine,
    221                         idChannel);
    222                 break;
    223             case kTraceRtpRtcp:
    224                 sprintf(traceMessage, "    RTP/RTCP:%5ld %5ld;", idEngine,
    225                         idChannel);
    226                 break;
    227             case kTraceTransport:
    228                 sprintf(traceMessage, "   TRANSPORT:%5ld %5ld;", idEngine,
    229                         idChannel);
    230                 break;
    231             case kTraceAudioCoding:
    232                 sprintf(traceMessage, "AUDIO CODING:%5ld %5ld;", idEngine,
    233                         idChannel);
    234                 break;
    235             case kTraceSrtp:
    236                 sprintf(traceMessage, "        SRTP:%5ld %5ld;", idEngine,
    237                         idChannel);
    238                 break;
    239             case kTraceAudioMixerServer:
    240                 sprintf(traceMessage, " AUDIO MIX/S:%5ld %5ld;", idEngine,
    241                         idChannel);
    242                 break;
    243             case kTraceAudioMixerClient:
    244                 sprintf(traceMessage, " AUDIO MIX/C:%5ld %5ld;", idEngine,
    245                         idChannel);
    246                 break;
    247             case kTraceVideoCoding:
    248                 sprintf(traceMessage, "VIDEO CODING:%5ld %5ld;", idEngine,
    249                         idChannel);
    250                 break;
    251             case kTraceVideoMixer:
    252                 // Print sleep time and API call
    253                 sprintf(traceMessage, "   VIDEO MIX:%5ld %5ld;", idEngine,
    254                         idChannel);
    255                 break;
    256             case kTraceFile:
    257                 sprintf(traceMessage, "        FILE:%5ld %5ld;", idEngine,
    258                         idChannel);
    259                 break;
    260             case kTraceAudioProcessing:
    261                 sprintf(traceMessage, "  AUDIO PROC:%5ld %5ld;", idEngine,
    262                         idChannel);
    263                 break;
    264             case kTraceAudioDevice:
    265                 sprintf(traceMessage, "AUDIO DEVICE:%5ld %5ld;", idEngine,
    266                         idChannel);
    267                 break;
    268             case kTraceVideoRenderer:
    269                 sprintf(traceMessage, "VIDEO RENDER:%5ld %5ld;", idEngine,
    270                         idChannel);
    271                 break;
    272             case kTraceVideoCapture:
    273                 sprintf(traceMessage, "VIDEO CAPTUR:%5ld %5ld;", idEngine,
    274                         idChannel);
    275                 break;
    276             case kTraceVideoPreocessing:
    277                 sprintf(traceMessage, "  VIDEO PROC:%5ld %5ld;", idEngine,
    278                         idChannel);
    279                 break;
    280             default:
    281                 assert(false);
    282                 return 0;
    283         }
    284     } else {
    285         switch (module)
    286         {
    287             case kTraceVoice:
    288                 sprintf (traceMessage, "       VOICE:%11ld;", idl);
    289                 break;
    290             case kTraceVideo:
    291                 sprintf (traceMessage, "       VIDEO:%11ld;", idl);
    292                 break;
    293             case kTraceUtility:
    294                 sprintf (traceMessage, "     UTILITY:%11ld;", idl);
    295                 break;
    296             case kTraceRtpRtcp:
    297                 sprintf (traceMessage, "    RTP/RTCP:%11ld;", idl);
    298                 break;
    299             case kTraceTransport:
    300                 sprintf (traceMessage, "   TRANSPORT:%11ld;", idl);
    301                 break;
    302             case kTraceAudioCoding:
    303                 sprintf (traceMessage, "AUDIO CODING:%11ld;", idl);
    304                 break;
    305             case kTraceSrtp:
    306                 sprintf (traceMessage, "        SRTP:%11ld;", idl);
    307                 break;
    308             case kTraceAudioMixerServer:
    309                 sprintf (traceMessage, " AUDIO MIX/S:%11ld;", idl);
    310                 break;
    311             case kTraceAudioMixerClient:
    312                 sprintf (traceMessage, " AUDIO MIX/C:%11ld;", idl);
    313                 break;
    314             case kTraceVideoCoding:
    315                 sprintf (traceMessage, "VIDEO CODING:%11ld;", idl);
    316                 break;
    317             case kTraceVideoMixer:
    318                 sprintf (traceMessage, "   VIDEO MIX:%11ld;", idl);
    319                 break;
    320             case kTraceFile:
    321                 sprintf (traceMessage, "        FILE:%11ld;", idl);
    322                 break;
    323             case kTraceAudioProcessing:
    324                 sprintf (traceMessage, "  AUDIO PROC:%11ld;", idl);
    325                 break;
    326             case kTraceAudioDevice:
    327                 sprintf (traceMessage, "AUDIO DEVICE:%11ld;", idl);
    328                 break;
    329             case kTraceVideoRenderer:
    330                 sprintf (traceMessage, "VIDEO RENDER:%11ld;", idl);
    331                 break;
    332             case kTraceVideoCapture:
    333                 sprintf (traceMessage, "VIDEO CAPTUR:%11ld;", idl);
    334                 break;
    335             case kTraceVideoPreocessing:
    336                 sprintf (traceMessage, "  VIDEO PROC:%11ld;", idl);
    337                 break;
    338             default:
    339                 assert(false);
    340                 return 0;
    341         }
    342     }
    343     // All messages are 25 characters.
    344     return 25;
    345 }
    346 
    347 WebRtc_Word32 TraceImpl::SetTraceFileImpl(const WebRtc_Word8* fileNameUTF8,
    348                                           const bool addFileCounter)
    349 {
    350     CriticalSectionScoped lock(_critsectInterface);
    351 
    352     _traceFile.Flush();
    353     _traceFile.CloseFile();
    354 
    355     if(fileNameUTF8)
    356     {
    357         if(addFileCounter)
    358         {
    359             _fileCountText = 1;
    360 
    361             WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize];
    362             CreateFileName(fileNameUTF8, fileNameWithCounterUTF8,
    363                            _fileCountText);
    364             if(_traceFile.OpenFile(fileNameWithCounterUTF8, false, false,
    365                                    true) == -1)
    366             {
    367                 return -1;
    368             }
    369         }else {
    370             _fileCountText = 0;
    371             if(_traceFile.OpenFile(fileNameUTF8, false, false, true) == -1)
    372             {
    373                 return -1;
    374             }
    375         }
    376     }
    377     _rowCountText = 0;
    378     return 0;
    379 }
    380 
    381 WebRtc_Word32 TraceImpl::TraceFileImpl(
    382     WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize])
    383 {
    384     CriticalSectionScoped lock(_critsectInterface);
    385     return _traceFile.FileName(fileNameUTF8, FileWrapper::kMaxFileNameSize);
    386 }
    387 
    388 WebRtc_Word32 TraceImpl::SetTraceCallbackImpl(TraceCallback* callback)
    389 {
    390     CriticalSectionScoped lock(_critsectInterface);
    391     _callback = callback;
    392     return 0;
    393 }
    394 
    395 WebRtc_Word32 TraceImpl::AddMessage(
    396     char* traceMessage,
    397     const char msg[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
    398     const WebRtc_UWord16 writtenSoFar) const
    399 
    400 {
    401     int length = 0;
    402     if(writtenSoFar >= WEBRTC_TRACE_MAX_MESSAGE_SIZE)
    403     {
    404         return -1;
    405     }
    406     // - 2 to leave room for newline and NULL termination
    407 #ifdef _WIN32
    408     length = _snprintf(traceMessage,
    409                        WEBRTC_TRACE_MAX_MESSAGE_SIZE - writtenSoFar - 2,
    410                        "%s",msg);
    411     if(length < 0)
    412     {
    413         length = WEBRTC_TRACE_MAX_MESSAGE_SIZE - writtenSoFar - 2;
    414         traceMessage[length] = 0;
    415     }
    416 #else
    417     length = snprintf(traceMessage,
    418                       WEBRTC_TRACE_MAX_MESSAGE_SIZE-writtenSoFar-2, "%s",msg);
    419     if(length < 0 || length > WEBRTC_TRACE_MAX_MESSAGE_SIZE-writtenSoFar - 2)
    420     {
    421         length = WEBRTC_TRACE_MAX_MESSAGE_SIZE - writtenSoFar - 2;
    422         traceMessage[length] = 0;
    423     }
    424 #endif
    425     // Length with NULL termination.
    426     return length+1;
    427 }
    428 
    429 void TraceImpl::AddMessageToList(
    430     const char traceMessage[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
    431     const WebRtc_UWord16 length,
    432     const TraceLevel level)
    433 {
    434     CriticalSectionScoped lock(_critsectArray);
    435 
    436     if(_nextFreeIdx[_activeQueue] >= WEBRTC_TRACE_MAX_QUEUE)
    437     {
    438         if( ! _traceFile.Open() &&
    439             !_callback)
    440         {
    441             // Keep at least the last 1/4 of old messages when not logging.
    442             // TODO (hellner): isn't this redundant. The user will make it known
    443             //                 when to start logging. Why keep messages before
    444             //                 that?
    445             for(int n = 0; n < WEBRTC_TRACE_MAX_QUEUE/4; n++)
    446             {
    447                 const int lastQuarterOffset = (3*WEBRTC_TRACE_MAX_QUEUE/4);
    448                 memcpy(_messageQueue[_activeQueue][n],
    449                        _messageQueue[_activeQueue][n + lastQuarterOffset],
    450                        WEBRTC_TRACE_MAX_MESSAGE_SIZE);
    451             }
    452             _nextFreeIdx[_activeQueue] = WEBRTC_TRACE_MAX_QUEUE/4;
    453         } else {
    454             // More messages are being written than there is room for in the
    455             // buffer. Drop any new messages.
    456             // TODO (hellner): its probably better to drop old messages instead
    457             //                 of new ones. One step further: if this happens
    458             //                 it's due to writing faster than what can be
    459             //                 processed. Maybe modify the filter at this point.
    460             //                 E.g. turn of STREAM.
    461             return;
    462         }
    463     }
    464 
    465     WebRtc_UWord16 idx = _nextFreeIdx[_activeQueue];
    466     _nextFreeIdx[_activeQueue]++;
    467 
    468     _level[_activeQueue][idx] = level;
    469     _length[_activeQueue][idx] = length;
    470     memcpy(_messageQueue[_activeQueue][idx], traceMessage, length);
    471 
    472     if(_nextFreeIdx[_activeQueue] == WEBRTC_TRACE_MAX_QUEUE-1)
    473     {
    474         // Logging more messages than can be worked off. Log a warning.
    475         const char warning_msg[] = "WARNING MISSING TRACE MESSAGES\n";
    476         _level[_activeQueue][_nextFreeIdx[_activeQueue]] = kTraceWarning;
    477         _length[_activeQueue][_nextFreeIdx[_activeQueue]] = strlen(warning_msg);
    478         memcpy(_messageQueue[_activeQueue][_nextFreeIdx[_activeQueue]],
    479                warning_msg, _length[_activeQueue][idx]);
    480         _nextFreeIdx[_activeQueue]++;
    481     }
    482 }
    483 
    484 bool TraceImpl::Run(void* obj)
    485 {
    486     return static_cast<TraceImpl*>(obj)->Process();
    487 }
    488 
    489 bool TraceImpl::Process()
    490 {
    491     if(_event.Wait(1000) == kEventSignaled)
    492     {
    493         if(_traceFile.Open() || _callback)
    494         {
    495             // File mode (not calback mode).
    496             WriteToFile();
    497         }
    498     } else {
    499         _traceFile.Flush();
    500     }
    501     return true;
    502 }
    503 
    504 void TraceImpl::WriteToFile()
    505 {
    506     WebRtc_UWord8 localQueueActive = 0;
    507     WebRtc_UWord16 localNextFreeIdx = 0;
    508 
    509     // There are two buffer. One for reading (for writing to file) and one for
    510     // writing (for storing new messages). Let new messages be posted to the
    511     // unused buffer so that the current buffer can be flushed safely.
    512     {
    513         CriticalSectionScoped lock(_critsectArray);
    514         localNextFreeIdx = _nextFreeIdx[_activeQueue];
    515         _nextFreeIdx[_activeQueue] = 0;
    516         localQueueActive = _activeQueue;
    517         if(_activeQueue == 0)
    518         {
    519             _activeQueue = 1;
    520         } else
    521         {
    522             _activeQueue = 0;
    523         }
    524     }
    525     if(localNextFreeIdx == 0)
    526     {
    527         return;
    528     }
    529 
    530     CriticalSectionScoped lock(_critsectInterface);
    531 
    532     for(WebRtc_UWord16 idx = 0; idx <localNextFreeIdx; idx++)
    533     {
    534         TraceLevel localLevel = _level[localQueueActive][idx];
    535         if(_callback)
    536         {
    537             _callback->Print(localLevel, _messageQueue[localQueueActive][idx],
    538                              _length[localQueueActive][idx]);
    539         }
    540         if(_traceFile.Open())
    541         {
    542             if(_rowCountText > WEBRTC_TRACE_MAX_FILE_SIZE)
    543             {
    544                 // wrap file
    545                 _rowCountText = 0;
    546                 _traceFile.Flush();
    547 
    548                 if(_fileCountText == 0)
    549                 {
    550                     _traceFile.Rewind();
    551                 } else
    552                 {
    553                     WebRtc_Word8 oldFileName[FileWrapper::kMaxFileNameSize];
    554                     WebRtc_Word8 newFileName[FileWrapper::kMaxFileNameSize];
    555 
    556                     // get current name
    557                     _traceFile.FileName(oldFileName,
    558                                         FileWrapper::kMaxFileNameSize);
    559                     _traceFile.CloseFile();
    560 
    561                     _fileCountText++;
    562 
    563                     UpdateFileName(oldFileName, newFileName, _fileCountText);
    564 
    565                     if(_traceFile.OpenFile(newFileName, false, false,
    566                                            true) == -1)
    567                     {
    568                         return;
    569                     }
    570                 }
    571             }
    572             if(_rowCountText ==  0)
    573             {
    574                 WebRtc_Word8 message[WEBRTC_TRACE_MAX_MESSAGE_SIZE + 1];
    575                 WebRtc_Word32 length = AddDateTimeInfo(message);
    576                 if(length != -1)
    577                 {
    578                     message[length] = 0;
    579                     message[length-1] = '\n';
    580                     _traceFile.Write(message, length);
    581                     _rowCountText++;
    582                 }
    583                 length = AddBuildInfo(message);
    584                 if(length != -1)
    585                 {
    586                     message[length+1] = 0;
    587                     message[length] = '\n';
    588                     message[length-1] = '\n';
    589                     _traceFile.Write(message, length+1);
    590                     _rowCountText++;
    591                     _rowCountText++;
    592                 }
    593             }
    594             WebRtc_UWord16 length = _length[localQueueActive][idx];
    595             _messageQueue[localQueueActive][idx][length] = 0;
    596             _messageQueue[localQueueActive][idx][length-1] = '\n';
    597             _traceFile.Write(_messageQueue[localQueueActive][idx], length);
    598             _rowCountText++;
    599         }
    600     }
    601 }
    602 
    603 void TraceImpl::AddImpl(const TraceLevel level, const TraceModule module,
    604                         const WebRtc_Word32 id,
    605                         const char msg[WEBRTC_TRACE_MAX_MESSAGE_SIZE])
    606 {
    607     if (TraceCheck(level))
    608     {
    609         char traceMessage[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
    610         char* meassagePtr = traceMessage;
    611 
    612         WebRtc_Word32 len = 0;
    613         WebRtc_Word32 ackLen = 0;
    614 
    615         len = AddLevel(meassagePtr, level);
    616         if(len == -1)
    617         {
    618             return;
    619         }
    620         meassagePtr += len;
    621         ackLen += len;
    622 
    623         len = AddTime(meassagePtr, level);
    624         if(len == -1)
    625         {
    626             return;
    627         }
    628         meassagePtr += len;
    629         ackLen += len;
    630 
    631         len = AddModuleAndId(meassagePtr, module, id);
    632         if(len == -1)
    633         {
    634             return;
    635         }
    636         meassagePtr += len;
    637         ackLen += len;
    638 
    639         len = AddThreadId(meassagePtr);
    640         if(len == -1)
    641         {
    642             return;
    643         }
    644         meassagePtr += len;
    645         ackLen += len;
    646 
    647         len = AddMessage(meassagePtr, msg, (WebRtc_UWord16)ackLen);
    648         if(len == -1)
    649         {
    650             return;
    651         }
    652         ackLen += len;
    653         AddMessageToList(traceMessage,(WebRtc_UWord16)ackLen, level);
    654 
    655         // Make sure that messages are written as soon as possible.
    656         _event.Set();
    657     }
    658 }
    659 
    660 bool TraceImpl::TraceCheck(const TraceLevel level) const
    661 {
    662     return (level & levelFilter)? true:false;
    663 }
    664 
    665 bool TraceImpl::UpdateFileName(
    666     const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],
    667     WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
    668     const WebRtc_UWord32 newCount) const
    669 {
    670     WebRtc_Word32 length = (WebRtc_Word32)strlen(fileNameUTF8);
    671     if(length < 0)
    672     {
    673         return false;
    674     }
    675 
    676     WebRtc_Word32 lengthWithoutFileEnding = length-1;
    677     while(lengthWithoutFileEnding > 0)
    678     {
    679         if(fileNameUTF8[lengthWithoutFileEnding] == '.')
    680         {
    681             break;
    682         } else {
    683             lengthWithoutFileEnding--;
    684         }
    685     }
    686     if(lengthWithoutFileEnding == 0)
    687     {
    688         lengthWithoutFileEnding = length;
    689     }
    690     WebRtc_Word32 lengthTo_ = lengthWithoutFileEnding - 1;
    691     while(lengthTo_ > 0)
    692     {
    693         if(fileNameUTF8[lengthTo_] == '_')
    694         {
    695             break;
    696         } else {
    697             lengthTo_--;
    698         }
    699     }
    700 
    701     memcpy(fileNameWithCounterUTF8, fileNameUTF8, lengthTo_);
    702     sprintf(fileNameWithCounterUTF8+lengthTo_, "_%lu%s",
    703             static_cast<long unsigned int> (newCount),
    704             fileNameUTF8+lengthWithoutFileEnding);
    705     return true;
    706 }
    707 
    708 bool TraceImpl::CreateFileName(
    709     const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],
    710     WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
    711     const WebRtc_UWord32 newCount) const
    712 {
    713     WebRtc_Word32 length = (WebRtc_Word32)strlen(fileNameUTF8);
    714     if(length < 0)
    715     {
    716         return false;
    717     }
    718 
    719     WebRtc_Word32 lengthWithoutFileEnding = length-1;
    720     while(lengthWithoutFileEnding > 0)
    721     {
    722         if(fileNameUTF8[lengthWithoutFileEnding] == '.')
    723         {
    724             break;
    725         }else
    726         {
    727             lengthWithoutFileEnding--;
    728         }
    729     }
    730     if(lengthWithoutFileEnding == 0)
    731     {
    732         lengthWithoutFileEnding = length;
    733     }
    734     memcpy(fileNameWithCounterUTF8, fileNameUTF8, lengthWithoutFileEnding);
    735     sprintf(fileNameWithCounterUTF8+lengthWithoutFileEnding, "_%lu%s",
    736             static_cast<long unsigned int> (newCount),
    737             fileNameUTF8+lengthWithoutFileEnding);
    738     return true;
    739 }
    740 
    741 void Trace::CreateTrace()
    742 {
    743     TraceImpl::StaticInstance(kAddRef);
    744 }
    745 
    746 void Trace::ReturnTrace()
    747 {
    748     TraceImpl::StaticInstance(kRelease);
    749 }
    750 
    751 WebRtc_Word32 Trace::SetLevelFilter(WebRtc_UWord32 filter)
    752 {
    753     levelFilter = filter;
    754     return 0;
    755 }
    756 
    757 WebRtc_Word32 Trace::LevelFilter(WebRtc_UWord32& filter)
    758 {
    759     filter = levelFilter;
    760     return 0;
    761 }
    762 
    763 WebRtc_Word32 Trace::TraceFile(WebRtc_Word8 fileName[FileWrapper::kMaxFileNameSize])
    764 {
    765     TraceImpl* trace = TraceImpl::GetTrace();
    766     if(trace)
    767     {
    768         int retVal = trace->TraceFileImpl(fileName);
    769         ReturnTrace();
    770         return retVal;
    771     }
    772     return -1;
    773 }
    774 
    775 WebRtc_Word32 Trace::SetTraceFile(const WebRtc_Word8* fileName,
    776                                   const bool addFileCounter)
    777 {
    778     TraceImpl* trace = TraceImpl::GetTrace();
    779     if(trace)
    780     {
    781         int retVal = trace->SetTraceFileImpl(fileName, addFileCounter);
    782         ReturnTrace();
    783         return retVal;
    784     }
    785     return -1;
    786 }
    787 
    788 WebRtc_Word32 Trace::SetTraceCallback(TraceCallback* callback)
    789 {
    790     TraceImpl* trace = TraceImpl::GetTrace();
    791     if(trace)
    792     {
    793         int retVal = trace->SetTraceCallbackImpl(callback);
    794         ReturnTrace();
    795         return retVal;
    796     }
    797     return -1;
    798 }
    799 
    800 void Trace::Add(const TraceLevel level, const TraceModule module,
    801                 const WebRtc_Word32 id, const char* msg, ...)
    802 
    803 {
    804     TraceImpl* trace = TraceImpl::GetTrace(level);
    805     if(trace)
    806     {
    807         if(trace->TraceCheck(level))
    808         {
    809             char tempBuff[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
    810             char* buff = 0;
    811             if(msg)
    812             {
    813                 va_list args;
    814                 va_start(args, msg);
    815 #ifdef _WIN32
    816                 _vsnprintf(tempBuff,WEBRTC_TRACE_MAX_MESSAGE_SIZE-1,msg,args);
    817 #else
    818                 vsnprintf(tempBuff,WEBRTC_TRACE_MAX_MESSAGE_SIZE-1,msg,args);
    819 #endif
    820                 va_end(args);
    821                 buff = tempBuff;
    822             }
    823             trace->AddImpl(level, module, id, buff);
    824         }
    825         ReturnTrace();
    826     }
    827 }
    828 
    829 } // namespace webrtc
    830