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 33namespace webrtc { 34static WebRtc_UWord32 levelFilter = kTraceDefault; 35 36// Construct On First Use idiom. Avoids "static initialization order fiasco". 37TraceImpl* 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 56TraceImpl* TraceImpl::GetTrace(const TraceLevel level) 57{ 58 return StaticInstance(kAddRefNoCreate, level); 59} 60 61TraceImpl* TraceImpl::CreateInstance() 62{ 63#if defined(_WIN32) 64 return new TraceWindows(); 65#else 66 return new TracePosix(); 67#endif 68} 69 70TraceImpl::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 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; 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 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 { 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 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_); 702 sprintf(fileNameWithCounterUTF8+lengthTo_, "_%lu%s", 703 static_cast<long unsigned int> (newCount), 704 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", 736 static_cast<long unsigned int> (newCount), 737 fileNameUTF8+lengthWithoutFileEnding); 738 return true; 739} 740 741void Trace::CreateTrace() 742{ 743 TraceImpl::StaticInstance(kAddRef); 744} 745 746void Trace::ReturnTrace() 747{ 748 TraceImpl::StaticInstance(kRelease); 749} 750 751WebRtc_Word32 Trace::SetLevelFilter(WebRtc_UWord32 filter) 752{ 753 levelFilter = filter; 754 return 0; 755} 756 757WebRtc_Word32 Trace::LevelFilter(WebRtc_UWord32& filter) 758{ 759 filter = levelFilter; 760 return 0; 761} 762 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} 828 829} // namespace webrtc 830