Changeset 53173 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Nov 1, 2014 11:29:05 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/log/log.cpp
r51770 r53173 5 5 6 6 /* 7 * Copyright (C) 2006-201 3Oracle Corporation7 * Copyright (C) 2006-2014 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 64 64 65 65 /******************************************************************************* 66 * Defined Constants And Macros * 67 *******************************************************************************/ 68 /** @def RTLOG_RINGBUF_DEFAULT_SIZE 69 * The default ring buffer size. */ 70 /** @def RTLOG_RINGBUF_MAX_SIZE 71 * The max ring buffer size. */ 72 /** @def RTLOG_RINGBUF_MIN_SIZE 73 * The min ring buffer size. */ 74 #ifdef IN_RING0 75 # define RTLOG_RINGBUF_DEFAULT_SIZE _64K 76 # define RTLOG_RINGBUF_MAX_SIZE _4M 77 # define RTLOG_RINGBUF_MIN_SIZE _1K 78 #elif defined(IN_RING3) || defined(DOXYGEN_RUNNING) 79 # define RTLOG_RINGBUF_DEFAULT_SIZE _512K 80 # define RTLOG_RINGBUF_MAX_SIZE _1G 81 # define RTLOG_RINGBUF_MIN_SIZE _4K 82 #endif 83 /** The start of ring buffer eye catcher (16 bytes). */ 84 #define RTLOG_RINGBUF_EYE_CATCHER "START RING BUF\0" 85 AssertCompile(sizeof(RTLOG_RINGBUF_EYE_CATCHER) == 16); 86 /** The end of ring buffer eye catcher (16 bytes). This also ensures that the ring buffer 87 * forms are properly terminated C string (leading zero chars). */ 88 #define RTLOG_RINGBUF_EYE_CATCHER_END "\0\0\0END RING BUF" 89 AssertCompile(sizeof(RTLOG_RINGBUF_EYE_CATCHER_END) == 16); 90 91 92 /******************************************************************************* 66 93 * Structures and Typedefs * 67 94 *******************************************************************************/ … … 103 130 bool fPendingPrefix; 104 131 /** Alignment padding. */ 105 bool afPadding1[3]; 132 bool afPadding1[2]; 133 /** Set if fully created. Used to avoid confusing in a few functions used to 134 * parse logger settings from environment variables. */ 135 bool fCreated; 106 136 107 137 /** The max number of groups that there is room for in afGroups and papszGroups. … … 117 147 /** The max number of entries per group. */ 118 148 uint32_t cMaxEntriesPerGroup; 119 /** Padding. */ 120 uint32_t u32Padding2; 149 150 /** @name Ring buffer logging 151 * The ring buffer records the last cbRingBuf - 1 of log output. The 152 * other configured log destinations are not touched until someone calls 153 * RTLogFlush(), when the ring buffer content is written to them all. 154 * 155 * The aim here is a fast logging destination, that avoids wasting storage 156 * space saving disk space when dealing with huge log volumes where the 157 * interesting bits usually are found near the end of the log. This is 158 * typically the case for scenarios that crashes or hits assertions. 159 * 160 * RTLogFlush() is called implicitly when hitting an assertion. While on a 161 * crash the most debuggers are able to make calls these days, it's usually 162 * possible to view the ring buffer memory. 163 * 164 * @{ */ 165 /** Ring buffer size (including both eye catchers). */ 166 uint32_t cbRingBuf; 167 /** Number of bytes passing thru the ring buffer since last RTLogFlush call. 168 * (This is used to avoid writing out the same bytes twice.) */ 169 uint64_t volatile cbRingBufUnflushed; 170 /** Ring buffer pointer (points at RTLOG_RINGBUF_EYE_CATCHER). */ 171 char *pszRingBuf; 172 /** Current ring buffer position (where to write the next char). */ 173 char * volatile pchRingBufCur; 174 /** @} */ 121 175 122 176 #ifdef IN_RING3 /* Note! Must be at the end! */ … … 148 202 149 203 /** The revision of the internal logger structure. */ 150 #define RTLOGGERINTERNAL_REV UINT32_C( 9)204 #define RTLOGGERINTERNAL_REV UINT32_C(10) 151 205 152 206 #ifdef IN_RING3 … … 156 210 AssertCompileMemberAlignment(RTLOGGERINTERNAL, cbHistoryFileMax, sizeof(uint64_t)); 157 211 #endif 212 AssertCompileMemberAlignment(RTLOGGERINTERNAL, cbRingBufUnflushed, sizeof(uint64_t)); 213 158 214 159 215 /******************************************************************************* … … 164 220 #endif 165 221 #ifdef IN_RING0 166 static void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, const char *pszFormat, va_list va); 222 static void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, PRTLOGGERINTERNAL pInt, 223 const char *pszFormat, va_list va); 167 224 #endif 168 225 #ifdef IN_RING3 169 226 static int rtlogFileOpen(PRTLOGGER pLogger, char *pszErrorMsg, size_t cchErrorMsg); 170 227 static void rtlogRotate(PRTLOGGER pLogger, uint32_t uTimeSlot, bool fFirst); 228 #endif 229 #ifndef IN_RC 230 static void rtLogRingBufFlush(PRTLOGGER pLogger); 171 231 #endif 172 232 static void rtlogFlush(PRTLOGGER pLogger); … … 282 342 } const s_aLogDst[] = 283 343 { 284 { "file", sizeof("file" ) - 1, RTLOGDEST_FILE }, /* Must be 1st! */ 285 { "dir", sizeof("dir" ) - 1, RTLOGDEST_FILE }, /* Must be 2nd! */ 286 { "history", sizeof("history" ) - 1, 0 }, /* Must be 3rd! */ 287 { "histsize", sizeof("histsize") - 1, 0 }, /* Must be 4th! */ 288 { "histtime", sizeof("histtime") - 1, 0 }, /* Must be 5th! */ 289 { "stdout", sizeof("stdout" ) - 1, RTLOGDEST_STDOUT }, 290 { "stderr", sizeof("stderr" ) - 1, RTLOGDEST_STDERR }, 291 { "debugger", sizeof("debugger") - 1, RTLOGDEST_DEBUGGER }, 292 { "com", sizeof("com" ) - 1, RTLOGDEST_COM }, 293 { "user", sizeof("user" ) - 1, RTLOGDEST_USER }, 344 { RT_STR_TUPLE("file"), RTLOGDEST_FILE }, /* Must be 1st! */ 345 { RT_STR_TUPLE("dir"), RTLOGDEST_FILE }, /* Must be 2nd! */ 346 { RT_STR_TUPLE("history"), 0 }, /* Must be 3rd! */ 347 { RT_STR_TUPLE("histsize"), 0 }, /* Must be 4th! */ 348 { RT_STR_TUPLE("histtime"), 0 }, /* Must be 5th! */ 349 { RT_STR_TUPLE("ringbuf"), RTLOGDEST_RINGBUF }, /* Must be 6th! */ 350 { RT_STR_TUPLE("stdout"), RTLOGDEST_STDOUT }, 351 { RT_STR_TUPLE("stderr"), RTLOGDEST_STDERR }, 352 { RT_STR_TUPLE("debugger"), RTLOGDEST_DEBUGGER }, 353 { RT_STR_TUPLE("com"), RTLOGDEST_COM }, 354 { RT_STR_TUPLE("user"), RTLOGDEST_USER }, 294 355 }; 295 356 296 /** 297 * Log rotation backoff table, important on Windows host, especially for298 * VBoxSVC release logging. Only a medium term solution, until a proper fix299 * for log file handling is available.10 seconds total.300 */ 301 static const uint32_t s_aLogBackoff[] =357 /** Log rotation backoff table - millisecond sleep intervals. 358 * Important on Windows host, especially for VBoxSVC release logging. Only a 359 * medium term solution, until a proper fix for log file handling is available. 360 * 10 seconds total. 361 */ 362 static const uint32_t g_acMsLogBackoff[] = 302 363 { 10, 10, 10, 20, 50, 100, 200, 200, 200, 200, 500, 500, 500, 500, 1000, 1000, 1000, 1000, 1000, 1000, 1000 }; 303 364 … … 434 495 435 496 # endif /* IN_RING3 */ 497 498 /** 499 * Adjusts the ring buffer. 500 * 501 * @returns IPRT status code. 502 * @param pLogger The logger instance. 503 * @param cbNewSize The new ring buffer size (0 == default). 504 * @param fForce Whether to do this even if the logger instance hasn't 505 * really been fully created yet (i.e. during RTLogCreate). 506 */ 507 static int rtLogRingBufAdjust(PRTLOGGER pLogger, uint32_t cbNewSize, bool fForce) 508 { 509 /* 510 * If this is early logger init, don't do anything. 511 */ 512 if (!pLogger->pInt->fCreated && !fForce) 513 return VINF_SUCCESS; 514 515 /* 516 * Lock the logger and make the necessary changes. 517 */ 518 int rc = rtlogLock(pLogger); 519 if (RT_SUCCESS(rc)) 520 { 521 if (cbNewSize == 0) 522 cbNewSize = RTLOG_RINGBUF_DEFAULT_SIZE; 523 if ( pLogger->pInt->cbRingBuf != cbNewSize 524 || !pLogger->pInt->pchRingBufCur) 525 { 526 uintptr_t offOld = pLogger->pInt->pchRingBufCur - pLogger->pInt->pszRingBuf; 527 if (offOld < sizeof(RTLOG_RINGBUF_EYE_CATCHER)) 528 offOld = sizeof(RTLOG_RINGBUF_EYE_CATCHER); 529 else if (offOld >= cbNewSize) 530 { 531 memmove(pLogger->pInt->pszRingBuf, &pLogger->pInt->pszRingBuf[offOld - cbNewSize], cbNewSize); 532 offOld = sizeof(RTLOG_RINGBUF_EYE_CATCHER); 533 } 534 535 void *pvNew = RTMemRealloc(pLogger->pInt->pchRingBufCur, cbNewSize); 536 if (pvNew) 537 { 538 pLogger->pInt->pszRingBuf = (char *)pvNew; 539 pLogger->pInt->pchRingBufCur = (char *)pvNew + offOld; 540 pLogger->pInt->cbRingBuf = cbNewSize; 541 memcpy(pvNew, RTLOG_RINGBUF_EYE_CATCHER, sizeof(RTLOG_RINGBUF_EYE_CATCHER)); 542 memcpy((char *)pvNew + cbNewSize - sizeof(RTLOG_RINGBUF_EYE_CATCHER_END), 543 RTLOG_RINGBUF_EYE_CATCHER_END, sizeof(RTLOG_RINGBUF_EYE_CATCHER_END)); 544 rc = VINF_SUCCESS; 545 } 546 else 547 rc = VERR_NO_MEMORY; 548 } 549 rtlogUnlock(pLogger); 550 } 551 552 return rc; 553 } 554 555 556 /** 557 * Writes text to the ring buffer. 558 * 559 * @param pInt The internal logger data structure. 560 * @param pachText The text to write. 561 * @param cchText The number of chars (bytes) to write. 562 */ 563 static void rtLogRingBufWrite(PRTLOGGERINTERNAL pInt, const char *pachText, size_t cchText) 564 { 565 /* 566 * Get the ring buffer data, adjusting it to only describe the writable 567 * part of the buffer. 568 */ 569 char * const pchStart = &pInt->pszRingBuf[sizeof(RTLOG_RINGBUF_EYE_CATCHER)]; 570 size_t const cchBuf = pInt->cbRingBuf - sizeof(RTLOG_RINGBUF_EYE_CATCHER) - sizeof(RTLOG_RINGBUF_EYE_CATCHER_END); 571 char *pchCur = pInt->pchRingBufCur; 572 size_t cchLeft = pchCur - pchStart; 573 if (RT_LIKELY(cchLeft < cchBuf)) 574 cchLeft = cchBuf - cchLeft; 575 else 576 { 577 /* May happen in ring-0 where a thread or two went ahead without getting the lock. */ 578 pchCur = pchStart; 579 cchLeft = cchBuf; 580 } 581 Assert(cchBuf < pInt->cbRingBuf); 582 583 if (cchText < cchLeft) 584 { 585 /* 586 * The text fits in the remaining space. 587 */ 588 memcpy(pchCur, pachText, cchText); 589 pchCur[cchText] = '\0'; 590 pInt->pchRingBufCur = &pchCur[cchText]; 591 pInt->cbRingBufUnflushed += cchText; 592 } 593 else 594 { 595 /* 596 * The text wraps around. Taking the simple but inefficient approach 597 * to input texts that are longer than the ring buffer since that 598 * is unlikely to the be a frequent case. 599 */ 600 /* Fill to the end of the buffer. */ 601 memcpy(pchCur, pachText, cchLeft); 602 pachText += cchLeft; 603 cchText -= cchLeft; 604 pInt->cbRingBufUnflushed += cchLeft; 605 pInt->pchRingBufCur = pchStart; 606 607 /* Ring buffer overflows (the plainly inefficient bit). */ 608 while (cchText >= cchBuf) 609 { 610 memcpy(pchStart, pachText, cchBuf); 611 pachText += cchBuf; 612 cchText -= cchBuf; 613 pInt->cbRingBufUnflushed += cchBuf; 614 } 615 616 /* The final bit, if any. */ 617 if (cchText > 0) 618 { 619 memcpy(pchStart, pachText, cchText); 620 pInt->cbRingBufUnflushed += cchText; 621 } 622 pchStart[cchText] = '\0'; 623 pInt->pchRingBufCur = &pchStart[cchText]; 624 } 625 } 626 627 628 /** 629 * Flushes the ring buffer to all the other log destinations. 630 * 631 * @param pLogger The logger instance which ring buffer should be flushed. 632 */ 633 static void rtLogRingBufFlush(PRTLOGGER pLogger) 634 { 635 const char *pszPreamble; 636 size_t cchPreamble; 637 const char *pszFirst; 638 size_t cchFirst; 639 const char *pszSecond; 640 size_t cchSecond; 641 642 /* 643 * Get the ring buffer data, adjusting it to only describe the writable 644 * part of the buffer. 645 */ 646 uint64_t cchUnflushed = pLogger->pInt->cbRingBufUnflushed; 647 char * const pszBuf = &pLogger->pInt->pszRingBuf[sizeof(RTLOG_RINGBUF_EYE_CATCHER)]; 648 size_t const cchBuf = pLogger->pInt->cbRingBuf - sizeof(RTLOG_RINGBUF_EYE_CATCHER) - sizeof(RTLOG_RINGBUF_EYE_CATCHER_END); 649 size_t offCur = pLogger->pInt->pchRingBufCur - pszBuf; 650 size_t cchAfter; 651 if (RT_LIKELY(offCur < cchBuf)) 652 cchAfter = cchBuf - offCur; 653 else /* May happen in ring-0 where a thread or two went ahead without getting the lock. */ 654 { 655 offCur = 0; 656 cchAfter = cchBuf; 657 } 658 659 pLogger->pInt->cbRingBufUnflushed = 0; 660 661 /* 662 * Figure out whether there are one or two segments that needs writing, 663 * making the last segment is terminated. (The first is always 664 * terminated because of the eye-catcher at the end of the buffer.) 665 */ 666 if (cchUnflushed == 0) 667 return; 668 pszBuf[offCur] = '\0'; 669 if (cchUnflushed >= cchBuf) 670 { 671 pszFirst = &pszBuf[offCur + 1]; 672 cchFirst = cchAfter ? cchAfter - 1 : 0; 673 pszSecond = pszBuf; 674 cchSecond = offCur; 675 pszPreamble = "\n*FLUSH RING BUF*\n"; 676 cchPreamble = sizeof("\n*FLUSH RING BUF*\n") - 1; 677 } 678 else if ((size_t)cchUnflushed <= offCur) 679 { 680 cchFirst = (size_t)cchUnflushed; 681 pszFirst = &pszBuf[offCur - cchFirst]; 682 pszSecond = ""; 683 cchSecond = 0; 684 pszPreamble = ""; 685 cchPreamble = 0; 686 } 687 else 688 { 689 cchFirst = (size_t)cchUnflushed - offCur; 690 pszFirst = &pszBuf[cchBuf - cchFirst]; 691 pszSecond = pszBuf; 692 cchSecond = offCur; 693 pszPreamble = ""; 694 cchPreamble = 0; 695 } 696 697 /* 698 * Write the ring buffer to all other destiations. 699 */ 700 if (pLogger->fDestFlags & RTLOGDEST_USER) 701 { 702 if (cchPreamble) 703 RTLogWriteUser(pszPreamble, cchPreamble); 704 if (cchFirst) 705 RTLogWriteUser(pszFirst, cchFirst); 706 if (cchSecond) 707 RTLogWriteUser(pszSecond, cchSecond); 708 } 709 710 if (pLogger->fDestFlags & RTLOGDEST_DEBUGGER) 711 { 712 if (cchPreamble) 713 RTLogWriteDebugger(pszPreamble, cchPreamble); 714 if (cchFirst) 715 RTLogWriteDebugger(pszFirst, cchFirst); 716 if (cchSecond) 717 RTLogWriteDebugger(pszSecond, cchSecond); 718 } 719 720 # ifdef IN_RING3 721 if (pLogger->fDestFlags & RTLOGDEST_FILE) 722 { 723 if (pLogger->pInt->hFile != NIL_RTFILE) 724 { 725 if (cchPreamble) 726 RTFileWrite(pLogger->pInt->hFile, pszPreamble, cchPreamble, NULL); 727 if (cchFirst) 728 RTFileWrite(pLogger->pInt->hFile, pszFirst, cchFirst, NULL); 729 if (cchSecond) 730 RTFileWrite(pLogger->pInt->hFile, pszSecond, cchSecond, NULL); 731 if (pLogger->fFlags & RTLOGFLAGS_FLUSH) 732 RTFileFlush(pLogger->pInt->hFile); 733 } 734 if (pLogger->pInt->cHistory) 735 pLogger->pInt->cbHistoryFileWritten += cchFirst + cchSecond; 736 } 737 # endif 738 739 if (pLogger->fDestFlags & RTLOGDEST_STDOUT) 740 { 741 if (cchPreamble) 742 RTLogWriteStdOut(pszPreamble, cchPreamble); 743 if (cchFirst) 744 RTLogWriteStdOut(pszFirst, cchFirst); 745 if (cchSecond) 746 RTLogWriteStdOut(pszSecond, cchSecond); 747 } 748 749 if (pLogger->fDestFlags & RTLOGDEST_STDERR) 750 { 751 if (cchPreamble) 752 RTLogWriteStdErr(pszPreamble, cchPreamble); 753 if (cchFirst) 754 RTLogWriteStdErr(pszFirst, cchFirst); 755 if (cchSecond) 756 RTLogWriteStdErr(pszSecond, cchSecond); 757 } 758 759 # if defined(IN_RING0) && !defined(LOG_NO_COM) 760 if (pLogger->fDestFlags & RTLOGDEST_COM) 761 { 762 if (cchPreamble) 763 RTLogWriteCom(pszPreamble, cchPreamble); 764 if (cchFirst) 765 RTLogWriteCom(pszFirst, cchFirst); 766 if (cchSecond) 767 RTLogWriteCom(pszSecond, cchSecond); 768 } 769 # endif 770 } 771 772 773 436 774 437 775 RTDECL(int) RTLogCreateExV(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings, … … 490 828 pLogger->pInt->afPadding1[1] = false; 491 829 pLogger->pInt->afPadding1[2] = false; 830 pLogger->pInt->fCreated = false; 492 831 pLogger->pInt->cMaxGroups = cGroups; 493 832 pLogger->pInt->papszGroups = papszGroups; … … 625 964 # endif /* IN_RING3 */ 626 965 966 if ((pLogger->fDestFlags & RTLOGDEST_RINGBUF) && RT_SUCCESS(rc)) 967 rc = rtLogRingBufAdjust(pLogger, pLogger->pInt->cbRingBuf, true /*fForce*/); 968 627 969 /* 628 970 * Create mutex and check how much it counts when entering the lock … … 650 992 pLogger->pInt->pfnPhase(pLogger, RTLOGPHASE_BEGIN, rtlogPhaseMsgNormal); 651 993 # endif 994 pLogger->pInt->fCreated = true; 652 995 *ppLogger = pLogger; 653 996 return VINF_SUCCESS; … … 1001 1344 pInt->pacEntriesPerGroup= NULL; 1002 1345 1346 pInt->fCreated = true; 1003 1347 pLogger->u32Magic = RTLOGGER_MAGIC; 1004 1348 return VINF_SUCCESS; … … 1102 1446 1103 1447 /* 1104 * Any 1448 * Anything to flush? 1105 1449 */ 1106 1450 if ( pLoggerR0->offScratch … … 1919 2263 if (!pszEnd) 1920 2264 pszEnd = strchr(pszValue, '\0'); 2265 size_t cch = pszEnd - pszValue; 1921 2266 # ifdef IN_RING3 1922 size_t cch = pszEnd - pszValue; 2267 char szTmp[sizeof(pLogger->pInt->szFilename)]; 2268 # else 2269 char szTmp[32]; 2270 # endif 2271 if (0) 2272 { /* nothing */ } 2273 #ifdef IN_RING3 1923 2274 1924 2275 /* log file name */ 1925 if (i == 0 /* file */ && !fNo)2276 else if (i == 0 /* file */ && !fNo) 1926 2277 { 1927 2278 AssertReturn(cch < sizeof(pLogger->pInt->szFilename), VERR_OUT_OF_RANGE); 1928 2279 memcpy(pLogger->pInt->szFilename, pszValue, cch); 1929 2280 pLogger->pInt->szFilename[cch] = '\0'; 2281 /** @todo reopen log file if pLogger->pInt->fCreated is true ... */ 1930 2282 } 1931 2283 /* log directory */ 1932 2284 else if (i == 1 /* dir */ && !fNo) 1933 2285 { 1934 char szTmp[sizeof(pLogger->pInt->szFilename)];1935 2286 const char *pszFile = RTPathFilename(pLogger->pInt->szFilename); 1936 2287 size_t cchFile = pszFile ? strlen(pszFile) : 0; … … 1946 2297 memcpy(&pLogger->pInt->szFilename[cch], szTmp, cchFile); 1947 2298 pLogger->pInt->szFilename[cch + cchFile] = '\0'; 2299 /** @todo reopen log file if pLogger->pInt->fCreated is true ... */ 1948 2300 } 1949 2301 else if (i == 2 /* history */) … … 1951 2303 if (!fNo) 1952 2304 { 1953 uint32_t cHistory = 0; 1954 char szTmp[32]; 2305 uint32_t cHistory = 0; 1955 2306 int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszValue, cch); 1956 2307 if (RT_SUCCESS(rc)) … … 1966 2317 if (!fNo) 1967 2318 { 1968 char szTmp[32];1969 2319 int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszValue, cch); 1970 2320 if (RT_SUCCESS(rc)) … … 1981 2331 if (!fNo) 1982 2332 { 1983 char szTmp[32];1984 2333 int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszValue, cch); 1985 2334 if (RT_SUCCESS(rc)) … … 1992 2341 pLogger->pInt->cSecsHistoryTimeSlot = UINT32_MAX; 1993 2342 } 2343 # endif /* IN_RING3 */ 2344 else if (i == 5 /* ringbuf */ && !fNo) 2345 { 2346 int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszValue, cch); 2347 uint32_t cbRingBuf; 2348 if (RT_SUCCESS(rc)) 2349 rc = RTStrToUInt32Full(szTmp, 0, &cbRingBuf); 2350 AssertMsgRCReturn(rc, ("Invalid ring buffer size value '%s' (%Rrc)!\n", szTmp, rc), rc); 2351 2352 if (cbRingBuf == 0) 2353 cbRingBuf = RTLOG_RINGBUF_DEFAULT_SIZE; 2354 else if (cbRingBuf < RTLOG_RINGBUF_MIN_SIZE) 2355 cbRingBuf = RTLOG_RINGBUF_MIN_SIZE; 2356 else if (cbRingBuf > RTLOG_RINGBUF_MAX_SIZE) 2357 cbRingBuf = RTLOG_RINGBUF_MAX_SIZE; 2358 else 2359 cbRingBuf = RT_ALIGN_32(cbRingBuf, 64); 2360 rc = rtLogRingBufAdjust(pLogger, cbRingBuf, false /*fForce*/); 2361 if (RT_FAILURE(rc)) 2362 return rc; 2363 } 1994 2364 else 1995 2365 AssertMsgFailedReturn(("Invalid destination value! %s%s doesn't take a value!\n", 1996 2366 fNo ? "no" : "", s_aLogDst[i].pszInstr), 1997 2367 VERR_INVALID_PARAMETER); 1998 # endif /* IN_RING3 */ 2368 1999 2369 pszValue = pszEnd + (*pszEnd != '\0'); 2370 } 2371 else if (i == 5 /* ringbuf */ && !fNo && !pLogger->pInt->pszRingBuf) 2372 { 2373 int rc = rtLogRingBufAdjust(pLogger, pLogger->pInt->cbRingBuf, false /*fForce*/); 2374 if (RT_FAILURE(rc)) 2375 return rc; 2000 2376 } 2001 2377 break; … … 2051 2427 */ 2052 2428 fDestFlags = pLogger->fDestFlags; 2053 for (i = 2; i < RT_ELEMENTS(s_aLogDst); i++)2429 for (i = 6; i < RT_ELEMENTS(s_aLogDst); i++) 2054 2430 if (s_aLogDst[i].fFlag & fDestFlags) 2055 2431 { … … 2066 2442 } 2067 2443 2444 char szNum[32]; 2445 2068 2446 # ifdef IN_RING3 2069 2447 /* … … 2079 2457 return rc; 2080 2458 fNotFirst = true; 2081 } 2082 2083 if (fDestFlags & RTLOGDEST_FILE) 2084 { 2085 char szNum[32]; 2459 2086 2460 if (pLogger->pInt->cHistory) 2087 2461 { … … 2111 2485 # endif /* IN_RING3 */ 2112 2486 2487 /* 2488 * Add the ring buffer. 2489 */ 2490 if (fDestFlags & RTLOGDEST_RINGBUF) 2491 { 2492 if (pLogger->pInt->cbRingBuf == RTLOG_RINGBUF_DEFAULT_SIZE) 2493 rc = RTStrCopyP(&pszBuf, &cchBuf, fNotFirst ? " ringbuf" : "ringbuf"); 2494 else 2495 { 2496 RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? " ringbuf=%#x" : "ringbuf=%#x", pLogger->pInt->cbRingBuf); 2497 rc = RTStrCopyP(&pszBuf, &cchBuf, szNum); 2498 } 2499 if (RT_FAILURE(rc)) 2500 return rc; 2501 fNotFirst = true; 2502 } 2503 2113 2504 return VINF_SUCCESS; 2114 2505 } … … 2143 2534 * Any thing to flush? 2144 2535 */ 2145 if (pLogger->offScratch) 2536 if ( pLogger->offScratch 2537 #ifndef IN_RC 2538 || (pLogger->fDestFlags & RTLOGDEST_RINGBUF) 2539 #endif 2540 ) 2146 2541 { 2147 2542 #ifndef IN_RC … … 2159 2554 2160 2555 #ifndef IN_RC 2556 /* 2557 * Since this is an explicit flush call, the ring buffer content should 2558 * be flushed to the other destinations if active. 2559 */ 2560 if ( (pLogger->fDestFlags & RTLOGDEST_RINGBUF) 2561 && pLogger->pInt->pszRingBuf /* paranoia */) 2562 rtLogRingBufFlush(pLogger); 2563 2161 2564 /* 2162 2565 * Release the semaphore. … … 2408 2811 #ifdef IN_RING0 2409 2812 if (pLogger->fDestFlags & ~RTLOGDEST_FILE) 2410 rtR0LogLoggerExFallback(pLogger->fDestFlags, pLogger->fFlags, p szFormat, args);2813 rtR0LogLoggerExFallback(pLogger->fDestFlags, pLogger->fFlags, pLogger->pInt, pszFormat, args); 2411 2814 #endif 2412 2815 return; … … 2456 2859 { 2457 2860 /** The current scratch buffer offset. */ 2458 uint32_t offScratch;2861 uint32_t offScratch; 2459 2862 /** The destination flags. */ 2460 uint32_t fDestFlags; 2863 uint32_t fDestFlags; 2864 /** For ring buffer output. */ 2865 PRTLOGGERINTERNAL pInt; 2461 2866 /** The scratch buffer. */ 2462 char achScratch[80];2867 char achScratch[80]; 2463 2868 } RTR0LOGLOGGERFALLBACK; 2464 2869 /** Pointer to RTR0LOGLOGGERFALLBACK which is used by … … 2477 2882 return; 2478 2883 2479 if (pThis->fDestFlags & RTLOGDEST_USER) 2480 RTLogWriteUser(pThis->achScratch, pThis->offScratch); 2481 2482 if (pThis->fDestFlags & RTLOGDEST_DEBUGGER) 2483 RTLogWriteDebugger(pThis->achScratch, pThis->offScratch); 2484 2485 if (pThis->fDestFlags & RTLOGDEST_STDOUT) 2486 RTLogWriteStdOut(pThis->achScratch, pThis->offScratch); 2487 2488 if (pThis->fDestFlags & RTLOGDEST_STDERR) 2489 RTLogWriteStdErr(pThis->achScratch, pThis->offScratch); 2884 if ( (pThis->fDestFlags & RTLOGDEST_RINGBUF) 2885 && pThis->pInt 2886 && pThis->pInt->pszRingBuf /* paranoia */) 2887 rtLogRingBufWrite(pThis->pInt, pThis->achScratch, pThis->offScratch); 2888 else 2889 { 2890 if (pThis->fDestFlags & RTLOGDEST_USER) 2891 RTLogWriteUser(pThis->achScratch, pThis->offScratch); 2892 2893 if (pThis->fDestFlags & RTLOGDEST_DEBUGGER) 2894 RTLogWriteDebugger(pThis->achScratch, pThis->offScratch); 2895 2896 if (pThis->fDestFlags & RTLOGDEST_STDOUT) 2897 RTLogWriteStdOut(pThis->achScratch, pThis->offScratch); 2898 2899 if (pThis->fDestFlags & RTLOGDEST_STDERR) 2900 RTLogWriteStdErr(pThis->achScratch, pThis->offScratch); 2490 2901 2491 2902 # ifndef LOG_NO_COM 2492 if (pThis->fDestFlags & RTLOGDEST_COM)2493 RTLogWriteCom(pThis->achScratch, pThis->offScratch);2903 if (pThis->fDestFlags & RTLOGDEST_COM) 2904 RTLogWriteCom(pThis->achScratch, pThis->offScratch); 2494 2905 # endif 2906 } 2495 2907 2496 2908 /* empty the buffer. */ … … 2560 2972 * @param fDestFlags The destination flags. 2561 2973 * @param fFlags The logger flags. 2974 * @param pInt The internal logger data, for ring buffer output. 2562 2975 * @param pszFormat The format string. 2563 2976 * @param va The format arguments. 2564 2977 */ 2565 static void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, const char *pszFormat, va_list va) 2978 static void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, PRTLOGGERINTERNAL pInt, 2979 const char *pszFormat, va_list va) 2566 2980 { 2567 2981 RTR0LOGLOGGERFALLBACK This; 2568 2982 This.fDestFlags = fDestFlags; 2983 This.pInt = pInt; 2569 2984 2570 2985 /* fallback indicator. */ … … 2645 3060 fOpen |= RTFILE_O_WRITE_THROUGH; 2646 3061 2647 int rc;2648 3062 unsigned cBackoff = 0; 2649 do 2650 { 3063 int rc = RTFileOpen(&pLogger->pInt->hFile, pLogger->pInt->szFilename, fOpen); 3064 while ( rc == VERR_SHARING_VIOLATION 3065 && cBackoff < RT_ELEMENTS(g_acMsLogBackoff)) 3066 { 3067 RTThreadSleep(g_acMsLogBackoff[cBackoff++]); 2651 3068 rc = RTFileOpen(&pLogger->pInt->hFile, pLogger->pInt->szFilename, fOpen); 2652 if (rc == VERR_SHARING_VIOLATION) 2653 { 2654 if (cBackoff >= RT_ELEMENTS(s_aLogBackoff)) 2655 break; 2656 RTThreadSleep(s_aLogBackoff[cBackoff]); 2657 cBackoff++; 2658 } 2659 } 2660 while (rc == VERR_SHARING_VIOLATION); 2661 if (RT_FAILURE(rc)) 3069 } 3070 if (RT_SUCCESS(rc)) 3071 { 3072 rc = RTFileGetSize(pLogger->pInt->hFile, &pLogger->pInt->cbHistoryFileWritten); 3073 if (RT_FAILURE(rc)) 3074 { 3075 /* Don't complain if this fails, assume the file is empty. */ 3076 pLogger->pInt->cbHistoryFileWritten = 0; 3077 rc = VINF_SUCCESS; 3078 } 3079 } 3080 else 2662 3081 { 2663 3082 pLogger->pInt->hFile = NIL_RTFILE; 2664 3083 if (pszErrorMsg) 2665 3084 RTStrPrintf(pszErrorMsg, cchErrorMsg, N_("could not open file '%s' (fOpen=%#x)"), pLogger->pInt->szFilename, fOpen); 2666 }2667 else2668 {2669 rc = RTFileGetSize(pLogger->pInt->hFile, &pLogger->pInt->cbHistoryFileWritten);2670 if (RT_FAILURE(rc))2671 {2672 /* Don't complain if this fails, assume the file is empty. */2673 pLogger->pInt->cbHistoryFileWritten = 0;2674 rc = VINF_SUCCESS;2675 }2676 3085 } 2677 3086 return rc; … … 2751 3160 RTStrPrintf(szNewName, sizeof(szNewName), "%s.%u", pLogger->pInt->szFilename, i + 1); 2752 3161 2753 2754 2755 int rc;2756 3162 unsigned cBackoff = 0; 2757 do 3163 int rc = RTFileRename(szOldName, szNewName, RTFILEMOVE_FLAGS_REPLACE); 3164 while ( rc == VERR_SHARING_VIOLATION 3165 && cBackoff < RT_ELEMENTS(g_acMsLogBackoff)) 2758 3166 { 3167 RTThreadSleep(g_acMsLogBackoff[cBackoff++]); 2759 3168 rc = RTFileRename(szOldName, szNewName, RTFILEMOVE_FLAGS_REPLACE); 2760 if (rc == VERR_SHARING_VIOLATION)2761 {2762 if (cBackoff >= RT_ELEMENTS(s_aLogBackoff))2763 break;2764 RTThreadSleep(s_aLogBackoff[cBackoff]);2765 cBackoff++;2766 }2767 3169 } 2768 while (rc == VERR_SHARING_VIOLATION); 3170 2769 3171 if (rc == VERR_FILE_NOT_FOUND) 2770 3172 RTFileDelete(szNewName); … … 2806 3208 /* Restore saved values. */ 2807 3209 pLogger->pInt->cHistory = cSavedHistory; 2808 pLogger->fFlags 3210 pLogger->fFlags = fSavedFlags; 2809 3211 } 2810 3212 2811 3213 #endif /* IN_RING3 */ 3214 2812 3215 2813 3216 /** … … 2824 3227 return; /* nothing to flush. */ 2825 3228 2826 /* Make sure the string is terminated. On Windows, RTLogWriteDebugger 2827 will get upset if it isn't. */ 2828 if (RT_LIKELY(cchScratch < sizeof(pLogger->achScratch))) 2829 pLogger->achScratch[cchScratch] = '\0'; 3229 #ifndef IN_RC 3230 /* 3231 * If the ring buffer is active, the other destinations are only written 3232 * to when the ring buffer is flushed by RTLogFlush(). 3233 */ 3234 if ( (pLogger->fDestFlags & RTLOGDEST_RINGBUF) 3235 && pLogger->pInt 3236 && pLogger->pInt->pszRingBuf /* paraoia */) 3237 { 3238 rtLogRingBufWrite(pLogger->pInt, pLogger->achScratch, pLogger->offScratch); 3239 pLogger->offScratch = 0; /* empty the buffer. */ 3240 } 2830 3241 else 2831 AssertFailed(); 3242 #endif 3243 { 3244 /* Make sure the string is terminated. On Windows, RTLogWriteDebugger 3245 will get upset if it isn't. */ 3246 if (RT_LIKELY(cchScratch < sizeof(pLogger->achScratch))) 3247 pLogger->achScratch[cchScratch] = '\0'; 3248 else 3249 AssertFailed(); 2832 3250 2833 3251 #ifndef IN_RC 2834 if (pLogger->fDestFlags & RTLOGDEST_USER)2835 RTLogWriteUser(pLogger->achScratch, cchScratch);2836 2837 if (pLogger->fDestFlags & RTLOGDEST_DEBUGGER)2838 RTLogWriteDebugger(pLogger->achScratch, cchScratch);3252 if (pLogger->fDestFlags & RTLOGDEST_USER) 3253 RTLogWriteUser(pLogger->achScratch, cchScratch); 3254 3255 if (pLogger->fDestFlags & RTLOGDEST_DEBUGGER) 3256 RTLogWriteDebugger(pLogger->achScratch, cchScratch); 2839 3257 2840 3258 # ifdef IN_RING3 2841 if (pLogger->fDestFlags &RTLOGDEST_FILE)2842 {2843 if (pLogger->pInt->hFile != NIL_RTFILE)2844 {2845 RTFileWrite(pLogger->pInt->hFile, pLogger->achScratch, cchScratch, NULL);2846 if (pLogger->fFlags & RTLOGFLAGS_FLUSH)2847 RTFileFlush(pLogger->pInt->hFile);2848 }2849 if (pLogger->pInt->cHistory)2850 pLogger->pInt->cbHistoryFileWritten += cchScratch;2851 }3259 if ((pLogger->fDestFlags & (RTLOGDEST_FILE | RTLOGDEST_RINGBUF)) == RTLOGDEST_FILE) 3260 { 3261 if (pLogger->pInt->hFile != NIL_RTFILE) 3262 { 3263 RTFileWrite(pLogger->pInt->hFile, pLogger->achScratch, cchScratch, NULL); 3264 if (pLogger->fFlags & RTLOGFLAGS_FLUSH) 3265 RTFileFlush(pLogger->pInt->hFile); 3266 } 3267 if (pLogger->pInt->cHistory) 3268 pLogger->pInt->cbHistoryFileWritten += cchScratch; 3269 } 2852 3270 # endif 2853 3271 2854 if (pLogger->fDestFlags & RTLOGDEST_STDOUT)2855 RTLogWriteStdOut(pLogger->achScratch, cchScratch);2856 2857 if (pLogger->fDestFlags & RTLOGDEST_STDERR)2858 RTLogWriteStdErr(pLogger->achScratch, cchScratch);3272 if (pLogger->fDestFlags & RTLOGDEST_STDOUT) 3273 RTLogWriteStdOut(pLogger->achScratch, cchScratch); 3274 3275 if (pLogger->fDestFlags & RTLOGDEST_STDERR) 3276 RTLogWriteStdErr(pLogger->achScratch, cchScratch); 2859 3277 2860 3278 # if (defined(IN_RING0) || defined(IN_RC)) && !defined(LOG_NO_COM) 2861 if (pLogger->fDestFlags & RTLOGDEST_COM)2862 RTLogWriteCom(pLogger->achScratch, cchScratch);3279 if (pLogger->fDestFlags & RTLOGDEST_COM) 3280 RTLogWriteCom(pLogger->achScratch, cchScratch); 2863 3281 # endif 2864 3282 #endif /* !IN_RC */ 2865 3283 2866 3284 #ifdef IN_RC 2867 if (pLogger->pfnFlush)2868 pLogger->pfnFlush(pLogger);3285 if (pLogger->pfnFlush) 3286 pLogger->pfnFlush(pLogger); 2869 3287 #else 2870 if (pLogger->pInt->pfnFlush)2871 pLogger->pInt->pfnFlush(pLogger);2872 #endif 2873 2874 /* empty the buffer. */2875 pLogger->offScratch = 0;3288 if (pLogger->pInt->pfnFlush) 3289 pLogger->pInt->pfnFlush(pLogger); 3290 #endif 3291 3292 /* empty the buffer. */ 3293 pLogger->offScratch = 0; 2876 3294 2877 3295 #ifdef IN_RING3 2878 /* 2879 * Rotate the log file if configured. Must be done after everything is 2880 * flushed, since this will also use logging/flushing to write the header 2881 * and footer messages. 2882 */ 2883 if ( (pLogger->fDestFlags & RTLOGDEST_FILE) 2884 && pLogger->pInt->cHistory) 2885 rtlogRotate(pLogger, RTTimeProgramSecTS() / pLogger->pInt->cSecsHistoryTimeSlot, false /* fFirst */); 2886 #endif 3296 /* 3297 * Rotate the log file if configured. Must be done after everything is 3298 * flushed, since this will also use logging/flushing to write the header 3299 * and footer messages. 3300 */ 3301 if ( (pLogger->fDestFlags & RTLOGDEST_FILE) 3302 && pLogger->pInt->cHistory) 3303 rtlogRotate(pLogger, RTTimeProgramSecTS() / pLogger->pInt->cSecsHistoryTimeSlot, false /* fFirst */); 3304 #endif 3305 } 2887 3306 } 2888 3307
Note:
See TracChangeset
for help on using the changeset viewer.