blob: 1156519eb981123b186240019771431f5bb4c8a9 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
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
andrew@webrtc.org59ccd5c2011-12-15 00:17:43 +000017#include "trace_win.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000018#else
19#include <stdio.h>
20#include <time.h>
21#include <stdarg.h>
ajm@google.comb5c49ff2011-08-01 17:04:04 +000022#include "trace_posix.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000023#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
33namespace webrtc {
34static WebRtc_UWord32 levelFilter = kTraceDefault;
35
36// Construct On First Use idiom. Avoids "static initialization order fiasco".
henrike@webrtc.org315282c2011-12-09 17:46:20 +000037TraceImpl* TraceImpl::StaticInstance(CountOperation count_operation,
38 const TraceLevel level)
niklase@google.com470e71d2011-07-07 08:21:25 +000039{
henrike@webrtc.org315282c2011-12-09 17:46:20 +000040 // 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))
niklase@google.com470e71d2011-07-07 08:21:25 +000045 {
46 if(!(level & levelFilter))
47 {
48 return NULL;
49 }
50 }
henrike@webrtc.org315282c2011-12-09 17:46:20 +000051 TraceImpl* impl =
52 GetStaticInstance<TraceImpl>(count_operation);
53 return impl;
niklase@google.com470e71d2011-07-07 08:21:25 +000054}
55
niklase@google.com470e71d2011-07-07 08:21:25 +000056TraceImpl* TraceImpl::GetTrace(const TraceLevel level)
57{
henrike@webrtc.org315282c2011-12-09 17:46:20 +000058 return StaticInstance(kAddRefNoCreate, level);
niklase@google.com470e71d2011-07-07 08:21:25 +000059}
60
henrike@webrtc.org315282c2011-12-09 17:46:20 +000061TraceImpl* TraceImpl::CreateInstance()
niklase@google.com470e71d2011-07-07 08:21:25 +000062{
henrike@webrtc.org2f47b5a2011-12-10 00:44:47 +000063#if defined(_WIN32)
niklase@google.com470e71d2011-07-07 08:21:25 +000064 return new TraceWindows();
65#else
ajm@google.comb5c49ff2011-08-01 17:04:04 +000066 return new TracePosix();
niklase@google.com470e71d2011-07-07 08:21:25 +000067#endif
68}
69
70TraceImpl::TraceImpl()
henrike@webrtc.orgbfa80ce2011-12-15 17:59:58 +000071 : _critsectInterface(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000072 _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()),
henrike@webrtc.orgbfa80ce2011-12-15 17:59:58 +000079 _critsectArray(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000080 _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
102bool 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
132TraceImpl::~TraceImpl()
133{
134 StopThread();
135 delete &_event;
136 delete &_traceFile;
137 delete &_thread;
henrike@webrtc.orgbfa80ce2011-12-15 17:59:58 +0000138 delete _critsectInterface;
139 delete _critsectArray;
niklase@google.com470e71d2011-07-07 08:21:25 +0000140
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
150WebRtc_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
195WebRtc_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
347WebRtc_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
381WebRtc_Word32 TraceImpl::TraceFileImpl(
382 WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize])
383{
384 CriticalSectionScoped lock(_critsectInterface);
385 return _traceFile.FileName(fileNameUTF8, FileWrapper::kMaxFileNameSize);
386}
387
388WebRtc_Word32 TraceImpl::SetTraceCallbackImpl(TraceCallback* callback)
389{
390 CriticalSectionScoped lock(_critsectInterface);
391 _callback = callback;
392 return 0;
393}
394
395WebRtc_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
429void 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 {
henrike@webrtc.org1a2933c2011-10-06 17:55:56 +0000474 // 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);
niklase@google.com470e71d2011-07-07 08:21:25 +0000478 memcpy(_messageQueue[_activeQueue][_nextFreeIdx[_activeQueue]],
henrike@webrtc.org1a2933c2011-10-06 17:55:56 +0000479 warning_msg, _length[_activeQueue][idx]);
niklase@google.com470e71d2011-07-07 08:21:25 +0000480 _nextFreeIdx[_activeQueue]++;
481 }
482}
483
484bool TraceImpl::Run(void* obj)
485{
486 return static_cast<TraceImpl*>(obj)->Process();
487}
488
489bool 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
504void 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
603void 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
660bool TraceImpl::TraceCheck(const TraceLevel level) const
661{
662 return (level & levelFilter)? true:false;
663}
664
665bool 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_);
hellner@google.com064a8df2011-08-16 15:52:28 +0000702 sprintf(fileNameWithCounterUTF8+lengthTo_, "_%lu%s",
703 static_cast<long unsigned int> (newCount),
niklase@google.com470e71d2011-07-07 08:21:25 +0000704 fileNameUTF8+lengthWithoutFileEnding);
705 return true;
706}
707
708bool 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",
hellner@google.com064a8df2011-08-16 15:52:28 +0000736 static_cast<long unsigned int> (newCount),
737 fileNameUTF8+lengthWithoutFileEnding);
niklase@google.com470e71d2011-07-07 08:21:25 +0000738 return true;
739}
740
tommi@webrtc.orgcde1e7f2011-11-15 12:23:36 +0000741void Trace::CreateTrace()
742{
henrike@webrtc.org315282c2011-12-09 17:46:20 +0000743 TraceImpl::StaticInstance(kAddRef);
tommi@webrtc.orgcde1e7f2011-11-15 12:23:36 +0000744}
745
746void Trace::ReturnTrace()
747{
henrike@webrtc.org315282c2011-12-09 17:46:20 +0000748 TraceImpl::StaticInstance(kRelease);
tommi@webrtc.orgcde1e7f2011-11-15 12:23:36 +0000749}
750
niklase@google.com470e71d2011-07-07 08:21:25 +0000751WebRtc_Word32 Trace::SetLevelFilter(WebRtc_UWord32 filter)
752{
753 levelFilter = filter;
754 return 0;
tommi@webrtc.orgcde1e7f2011-11-15 12:23:36 +0000755}
niklase@google.com470e71d2011-07-07 08:21:25 +0000756
757WebRtc_Word32 Trace::LevelFilter(WebRtc_UWord32& filter)
758{
759 filter = levelFilter;
760 return 0;
tommi@webrtc.orgcde1e7f2011-11-15 12:23:36 +0000761}
niklase@google.com470e71d2011-07-07 08:21:25 +0000762
763WebRtc_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
775WebRtc_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
788WebRtc_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
800void 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}
tommi@webrtc.orgcde1e7f2011-11-15 12:23:36 +0000828
niklase@google.com470e71d2011-07-07 08:21:25 +0000829} // namespace webrtc