VirtualBox

Changeset 53173 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Nov 1, 2014 11:29:05 PM (10 years ago)
Author:
vboxsync
Message:

IPRT,SUPDrv: Added new 'ringbuf[=size]' log destination for cases where only the last bit of the log is interesting and we can save space and time by not writing the whole log to disk/wherever. Since it changes the internal logger structure, it'll require a major SUPDrv version bump.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/log/log.cpp

    r51770 r53173  
    55
    66/*
    7  * Copyright (C) 2006-2013 Oracle Corporation
     7 * Copyright (C) 2006-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    6464
    6565/*******************************************************************************
     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"
     85AssertCompile(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"
     89AssertCompile(sizeof(RTLOG_RINGBUF_EYE_CATCHER_END) == 16);
     90
     91
     92/*******************************************************************************
    6693*   Structures and Typedefs                                                    *
    6794*******************************************************************************/
     
    103130    bool                    fPendingPrefix;
    104131    /** 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;
    106136
    107137    /** The max number of groups that there is room for in afGroups and papszGroups.
     
    117147    /** The max number of entries per group. */
    118148    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    /** @} */
    121175
    122176#ifdef IN_RING3 /* Note! Must be at the end! */
     
    148202
    149203/** The revision of the internal logger structure. */
    150 #define RTLOGGERINTERNAL_REV    UINT32_C(9)
     204#define RTLOGGERINTERNAL_REV    UINT32_C(10)
    151205
    152206#ifdef IN_RING3
     
    156210AssertCompileMemberAlignment(RTLOGGERINTERNAL, cbHistoryFileMax, sizeof(uint64_t));
    157211#endif
     212AssertCompileMemberAlignment(RTLOGGERINTERNAL, cbRingBufUnflushed, sizeof(uint64_t));
     213
    158214
    159215/*******************************************************************************
     
    164220#endif
    165221#ifdef IN_RING0
    166 static void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, const char *pszFormat, va_list va);
     222static void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, PRTLOGGERINTERNAL pInt,
     223                                    const char *pszFormat, va_list va);
    167224#endif
    168225#ifdef IN_RING3
    169226static int rtlogFileOpen(PRTLOGGER pLogger, char *pszErrorMsg, size_t cchErrorMsg);
    170227static void rtlogRotate(PRTLOGGER pLogger, uint32_t uTimeSlot, bool fFirst);
     228#endif
     229#ifndef IN_RC
     230static void rtLogRingBufFlush(PRTLOGGER pLogger);
    171231#endif
    172232static void rtlogFlush(PRTLOGGER pLogger);
     
    282342} const s_aLogDst[] =
    283343{
    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 },
    294355};
    295356
    296 /**
    297  * Log rotation backoff table, important on Windows host, especially for
    298  * VBoxSVC release logging. Only a medium term solution, until a proper fix
    299  * 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 */
     362static const uint32_t g_acMsLogBackoff[] =
    302363{ 10, 10, 10, 20, 50, 100, 200, 200, 200, 200, 500, 500, 500, 500, 1000, 1000, 1000, 1000, 1000, 1000, 1000 };
    303364
     
    434495
    435496# 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 */
     507static 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 */
     563static 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 */
     633static 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
    436774
    437775RTDECL(int) RTLogCreateExV(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings,
     
    490828        pLogger->pInt->afPadding1[1]            = false;
    491829        pLogger->pInt->afPadding1[2]            = false;
     830        pLogger->pInt->fCreated                 = false;
    492831        pLogger->pInt->cMaxGroups               = cGroups;
    493832        pLogger->pInt->papszGroups              = papszGroups;
     
    625964# endif  /* IN_RING3 */
    626965
     966            if ((pLogger->fDestFlags & RTLOGDEST_RINGBUF) && RT_SUCCESS(rc))
     967                rc = rtLogRingBufAdjust(pLogger, pLogger->pInt->cbRingBuf, true /*fForce*/);
     968
    627969            /*
    628970             * Create mutex and check how much it counts when entering the lock
     
    650992                        pLogger->pInt->pfnPhase(pLogger, RTLOGPHASE_BEGIN, rtlogPhaseMsgNormal);
    651993# endif
     994                    pLogger->pInt->fCreated = true;
    652995                    *ppLogger = pLogger;
    653996                    return VINF_SUCCESS;
     
    10011344        pInt->pacEntriesPerGroup= NULL;
    10021345
     1346    pInt->fCreated              = true;
    10031347    pLogger->u32Magic           = RTLOGGER_MAGIC;
    10041348    return VINF_SUCCESS;
     
    11021446
    11031447    /*
    1104      * Any thing to flush?
     1448     * Anything to flush?
    11051449     */
    11061450    if (    pLoggerR0->offScratch
     
    19192263                    if (!pszEnd)
    19202264                        pszEnd = strchr(pszValue, '\0');
     2265                    size_t cch = pszEnd - pszValue;
    19212266# 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
    19232274
    19242275                    /* log file name */
    1925                     if (i == 0 /* file */ && !fNo)
     2276                    else if (i == 0 /* file */ && !fNo)
    19262277                    {
    19272278                        AssertReturn(cch < sizeof(pLogger->pInt->szFilename), VERR_OUT_OF_RANGE);
    19282279                        memcpy(pLogger->pInt->szFilename, pszValue, cch);
    19292280                        pLogger->pInt->szFilename[cch] = '\0';
     2281                        /** @todo reopen log file if pLogger->pInt->fCreated is true ... */
    19302282                    }
    19312283                    /* log directory */
    19322284                    else if (i == 1 /* dir */ && !fNo)
    19332285                    {
    1934                         char        szTmp[sizeof(pLogger->pInt->szFilename)];
    19352286                        const char *pszFile = RTPathFilename(pLogger->pInt->szFilename);
    19362287                        size_t      cchFile = pszFile ? strlen(pszFile) : 0;
     
    19462297                        memcpy(&pLogger->pInt->szFilename[cch], szTmp, cchFile);
    19472298                        pLogger->pInt->szFilename[cch + cchFile] = '\0';
     2299                        /** @todo reopen log file if pLogger->pInt->fCreated is true ... */
    19482300                    }
    19492301                    else if (i == 2 /* history */)
     
    19512303                        if (!fNo)
    19522304                        {
    1953                             uint32_t    cHistory = 0;
    1954                             char        szTmp[32];
     2305                            uint32_t cHistory = 0;
    19552306                            int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszValue, cch);
    19562307                            if (RT_SUCCESS(rc))
     
    19662317                        if (!fNo)
    19672318                        {
    1968                             char szTmp[32];
    19692319                            int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszValue, cch);
    19702320                            if (RT_SUCCESS(rc))
     
    19812331                        if (!fNo)
    19822332                        {
    1983                             char szTmp[32];
    19842333                            int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszValue, cch);
    19852334                            if (RT_SUCCESS(rc))
     
    19922341                            pLogger->pInt->cSecsHistoryTimeSlot = UINT32_MAX;
    19932342                    }
     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                    }
    19942364                    else
    19952365                        AssertMsgFailedReturn(("Invalid destination value! %s%s doesn't take a value!\n",
    19962366                                               fNo ? "no" : "", s_aLogDst[i].pszInstr),
    19972367                                              VERR_INVALID_PARAMETER);
    1998 # endif /* IN_RING3 */
     2368
    19992369                    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;
    20002376                }
    20012377                break;
     
    20512427     */
    20522428    fDestFlags = pLogger->fDestFlags;
    2053     for (i = 2; i < RT_ELEMENTS(s_aLogDst); i++)
     2429    for (i = 6; i < RT_ELEMENTS(s_aLogDst); i++)
    20542430        if (s_aLogDst[i].fFlag & fDestFlags)
    20552431        {
     
    20662442        }
    20672443
     2444    char szNum[32];
     2445
    20682446# ifdef IN_RING3
    20692447    /*
     
    20792457            return rc;
    20802458        fNotFirst = true;
    2081     }
    2082 
    2083     if (fDestFlags & RTLOGDEST_FILE)
    2084     {
    2085         char szNum[32];
     2459
    20862460        if (pLogger->pInt->cHistory)
    20872461        {
     
    21112485# endif /* IN_RING3 */
    21122486
     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
    21132504    return VINF_SUCCESS;
    21142505}
     
    21432534     * Any thing to flush?
    21442535     */
    2145     if (pLogger->offScratch)
     2536    if (   pLogger->offScratch
     2537#ifndef IN_RC
     2538        || (pLogger->fDestFlags & RTLOGDEST_RINGBUF)
     2539#endif
     2540       )
    21462541    {
    21472542#ifndef IN_RC
     
    21592554
    21602555#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
    21612564        /*
    21622565         * Release the semaphore.
     
    24082811#ifdef IN_RING0
    24092812        if (pLogger->fDestFlags & ~RTLOGDEST_FILE)
    2410             rtR0LogLoggerExFallback(pLogger->fDestFlags, pLogger->fFlags, pszFormat, args);
     2813            rtR0LogLoggerExFallback(pLogger->fDestFlags, pLogger->fFlags, pLogger->pInt, pszFormat, args);
    24112814#endif
    24122815        return;
     
    24562859{
    24572860    /** The current scratch buffer offset. */
    2458     uint32_t offScratch;
     2861    uint32_t            offScratch;
    24592862    /** The destination flags. */
    2460     uint32_t fDestFlags;
     2863    uint32_t            fDestFlags;
     2864    /** For ring buffer output. */
     2865    PRTLOGGERINTERNAL   pInt;
    24612866    /** The scratch buffer. */
    2462     char achScratch[80];
     2867    char                achScratch[80];
    24632868} RTR0LOGLOGGERFALLBACK;
    24642869/** Pointer to RTR0LOGLOGGERFALLBACK which is used by
     
    24772882        return;
    24782883
    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);
    24902901
    24912902# 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);
    24942905# endif
     2906    }
    24952907
    24962908    /* empty the buffer. */
     
    25602972 * @param   fDestFlags  The destination flags.
    25612973 * @param   fFlags      The logger flags.
     2974 * @param   pInt        The internal logger data, for ring buffer output.
    25622975 * @param   pszFormat   The format string.
    25632976 * @param   va          The format arguments.
    25642977 */
    2565 static void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, const char *pszFormat, va_list va)
     2978static void rtR0LogLoggerExFallback(uint32_t fDestFlags, uint32_t fFlags, PRTLOGGERINTERNAL pInt,
     2979                                    const char *pszFormat, va_list va)
    25662980{
    25672981    RTR0LOGLOGGERFALLBACK This;
    25682982    This.fDestFlags = fDestFlags;
     2983    This.pInt = pInt;
    25692984
    25702985    /* fallback indicator. */
     
    26453060        fOpen |= RTFILE_O_WRITE_THROUGH;
    26463061
    2647     int rc;
    26483062    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++]);
    26513068        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
    26623081    {
    26633082        pLogger->pInt->hFile = NIL_RTFILE;
    26643083        if (pszErrorMsg)
    26653084            RTStrPrintf(pszErrorMsg, cchErrorMsg, N_("could not open file '%s' (fOpen=%#x)"), pLogger->pInt->szFilename, fOpen);
    2666     }
    2667     else
    2668     {
    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         }
    26763085    }
    26773086    return rc;
     
    27513160            RTStrPrintf(szNewName, sizeof(szNewName), "%s.%u", pLogger->pInt->szFilename, i + 1);
    27523161
    2753 
    2754 
    2755             int rc;
    27563162            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))
    27583166            {
     3167                RTThreadSleep(g_acMsLogBackoff[cBackoff++]);
    27593168                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                 }
    27673169            }
    2768             while (rc == VERR_SHARING_VIOLATION);
     3170
    27693171            if (rc == VERR_FILE_NOT_FOUND)
    27703172                RTFileDelete(szNewName);
     
    28063208    /* Restore saved values. */
    28073209    pLogger->pInt->cHistory = cSavedHistory;
    2808     pLogger->fFlags          = fSavedFlags;
     3210    pLogger->fFlags         = fSavedFlags;
    28093211}
    28103212
    28113213#endif /* IN_RING3 */
     3214
    28123215
    28133216/**
     
    28243227        return; /* nothing to flush. */
    28253228
    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    }
    28303241    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();
    28323250
    28333251#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);
    28393257
    28403258# 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        }
    28523270# endif
    28533271
    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);
    28593277
    28603278# 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);
    28633281# endif
    28643282#endif /* !IN_RC */
    28653283
    28663284#ifdef IN_RC
    2867     if (pLogger->pfnFlush)
    2868         pLogger->pfnFlush(pLogger);
     3285        if (pLogger->pfnFlush)
     3286            pLogger->pfnFlush(pLogger);
    28693287#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;
    28763294
    28773295#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    }
    28873306}
    28883307
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette