• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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".
StaticInstance(CountOperation count_operation,const TraceLevel level)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 
GetTrace(const TraceLevel level)56 TraceImpl* TraceImpl::GetTrace(const TraceLevel level)
57 {
58     return StaticInstance(kAddRefNoCreate, level);
59 }
60 
CreateInstance()61 TraceImpl* TraceImpl::CreateInstance()
62 {
63 #if defined(_WIN32)
64     return new TraceWindows();
65 #else
66     return new TracePosix();
67 #endif
68 }
69 
TraceImpl()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 
StopThread()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 
~TraceImpl()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 
AddLevel(char * szMessage,const TraceLevel level) const150 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 
AddModuleAndId(char * traceMessage,const TraceModule module,const WebRtc_Word32 id) const195 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 
SetTraceFileImpl(const WebRtc_Word8 * fileNameUTF8,const bool addFileCounter)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 
TraceFileImpl(WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize])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 
SetTraceCallbackImpl(TraceCallback * callback)388 WebRtc_Word32 TraceImpl::SetTraceCallbackImpl(TraceCallback* callback)
389 {
390     CriticalSectionScoped lock(_critsectInterface);
391     _callback = callback;
392     return 0;
393 }
394 
AddMessage(char * traceMessage,const char msg[WEBRTC_TRACE_MAX_MESSAGE_SIZE],const WebRtc_UWord16 writtenSoFar) const395 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 
AddMessageToList(const char traceMessage[WEBRTC_TRACE_MAX_MESSAGE_SIZE],const WebRtc_UWord16 length,const TraceLevel level)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 
Run(void * obj)484 bool TraceImpl::Run(void* obj)
485 {
486     return static_cast<TraceImpl*>(obj)->Process();
487 }
488 
Process()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 
WriteToFile()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 
AddImpl(const TraceLevel level,const TraceModule module,const WebRtc_Word32 id,const char msg[WEBRTC_TRACE_MAX_MESSAGE_SIZE])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 
TraceCheck(const TraceLevel level) const660 bool TraceImpl::TraceCheck(const TraceLevel level) const
661 {
662     return (level & levelFilter)? true:false;
663 }
664 
UpdateFileName(const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],const WebRtc_UWord32 newCount) const665 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 
CreateFileName(const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],const WebRtc_UWord32 newCount) const708 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 
CreateTrace()741 void Trace::CreateTrace()
742 {
743     TraceImpl::StaticInstance(kAddRef);
744 }
745 
ReturnTrace()746 void Trace::ReturnTrace()
747 {
748     TraceImpl::StaticInstance(kRelease);
749 }
750 
SetLevelFilter(WebRtc_UWord32 filter)751 WebRtc_Word32 Trace::SetLevelFilter(WebRtc_UWord32 filter)
752 {
753     levelFilter = filter;
754     return 0;
755 }
756 
LevelFilter(WebRtc_UWord32 & filter)757 WebRtc_Word32 Trace::LevelFilter(WebRtc_UWord32& filter)
758 {
759     filter = levelFilter;
760     return 0;
761 }
762 
TraceFile(WebRtc_Word8 fileName[FileWrapper::kMaxFileNameSize])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 
SetTraceFile(const WebRtc_Word8 * fileName,const bool addFileCounter)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 
SetTraceCallback(TraceCallback * callback)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 
Add(const TraceLevel level,const TraceModule module,const WebRtc_Word32 id,const char * msg,...)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