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 32namespace webrtc { 33static WebRtc_UWord32 levelFilter = kTraceDefault; 34 35// Construct On First Use idiom. Avoids "static initialization order fiasco". 36TraceImpl* 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 55TraceImpl* TraceImpl::GetTrace(const TraceLevel level) 56{ 57 return StaticInstance(kAddRefNoCreate, level); 58} 59 60TraceImpl* TraceImpl::CreateInstance() 61{ 62#if defined(_WIN32) 63 return new TraceWindows(); 64#else 65 return new TracePosix(); 66#endif 67} 68 69TraceImpl::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 101bool 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 124TraceImpl::~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 142WebRtc_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 148WebRtc_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 193WebRtc_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 339WebRtc_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 373WebRtc_Word32 TraceImpl::TraceFileImpl( 374 char fileNameUTF8[FileWrapper::kMaxFileNameSize]) 375{ 376 CriticalSectionScoped lock(_critsectInterface); 377 return _traceFile.FileName(fileNameUTF8, FileWrapper::kMaxFileNameSize); 378} 379 380WebRtc_Word32 TraceImpl::SetTraceCallbackImpl(TraceCallback* callback) 381{ 382 CriticalSectionScoped lock(_critsectInterface); 383 _callback = callback; 384 return 0; 385} 386 387WebRtc_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 421void 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 482bool TraceImpl::Run(void* obj) 483{ 484 return static_cast<TraceImpl*>(obj)->Process(); 485} 486 487bool 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 502void 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 601void 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 658bool TraceImpl::TraceCheck(const TraceLevel level) const 659{ 660 return (level & levelFilter)? true:false; 661} 662 663bool 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 706bool 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 739void Trace::CreateTrace() 740{ 741 TraceImpl::StaticInstance(kAddRef); 742} 743 744void Trace::ReturnTrace() 745{ 746 TraceImpl::StaticInstance(kRelease); 747} 748 749WebRtc_Word32 Trace::SetLevelFilter(WebRtc_UWord32 filter) 750{ 751 levelFilter = filter; 752 return 0; 753} 754 755WebRtc_Word32 Trace::LevelFilter(WebRtc_UWord32& filter) 756{ 757 filter = levelFilter; 758 return 0; 759} 760 761WebRtc_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 773WebRtc_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 786WebRtc_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 798void 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