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