VirtualBox

Ignore:
Timestamp:
May 12, 2010 1:27:04 AM (15 years ago)
Author:
vboxsync
Message:

GuestProperties: Try make sure the timestamp is somewhat unique because the code is making assumptions about this (RTTimeNow granularity is very coarse on windows). Fixed several derefernces of rend in getOldNotificationInternal that VC++'s strictness checks pointed out. Also cleaned up the method, dropping the unncessary and somewhat historical/puzzling RT_SUCCESS(rc) bits.

Location:
trunk/src/VBox/HostServices/GuestProperties
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/GuestProperties/service.cpp

    r28800 r29394  
    9797
    9898    /** Are two properties equal? */
    99     bool operator== (const Property &prop)
    100     {
    101         return (   mName == prop.mName
    102                 && mValue == prop.mValue
    103                 && mTimestamp == prop.mTimestamp
    104                 && mFlags == prop.mFlags
    105                );
     99    bool operator==(const Property &prop)
     100    {
     101        if (mTimestamp != prop.mTimestamp)
     102            return false;
     103        if (mFlags != prop.mFlags)
     104            return false;
     105        if (mName != prop.mName)
     106            return false;
     107        if (mValue != prop.mValue)
     108            return false;
     109        return true;
    106110    }
    107111
     
    164168    /** User data pointer to be supplied to the host callback function */
    165169    void *mpvHostData;
     170    /** The previous timestamp.
     171     * This is used by getCurrentTimestamp() to decrease the chance of
     172     * generating duplicate timestamps.  */
     173    uint64_t mPrevTimestamp;
     174    /** The number of consecutive timestamp adjustments that we've made.
     175     * Together with mPrevTimestamp, this defines a set of obsolete timestamp
     176     * values: {(mPrevTimestamp - mcTimestampAdjustments), ..., mPrevTimestamp} */
     177    uint64_t mcTimestampAdjustments;
    166178
    167179    /**
     
    193205         *  - Matches the pszPatterns
    194206         */
     207        /** @todo r=bird: This incorrectly ASSUMES that mTimestamp is unique.
     208         *  The timestamp resolution can be very coarse on windows for instance. */
    195209        PropertyList::const_iterator it = mGuestNotifications.begin();
    196210        for (;    it != mGuestNotifications.end()
    197                && it->mTimestamp != u64Timestamp; ++it) {}
     211               && it->mTimestamp != u64Timestamp; ++it)
     212            {}
    198213        if (it == mGuestNotifications.end())  /* Not found */
    199214            it = mGuestNotifications.begin();
     
    239254        , mpfnHostCallback(NULL)
    240255        , mpvHostData(NULL)
     256        , mPrevTimestamp(0)
     257        , mcTimestampAdjustments(0)
    241258    { }
    242259
     
    319336private:
    320337    static DECLCALLBACK(int) reqThreadFn(RTTHREAD ThreadSelf, void *pvUser);
     338    uint64_t getCurrentTimestamp(void);
    321339    int validateName(const char *pszName, uint32_t cbName);
    322340    int validateValue(const char *pszValue, uint32_t cbValue);
     
    344362
    345363/**
     364 * Gets the current timestamp.
     365 *
     366 * Since the RTTimeNow resolution can be very coarse, this method takes some
     367 * simple steps to try avoid returning the same timestamp for two consecutive
     368 * calls.  Code like getOldNotification() more or less assumes unique
     369 * timestamps.
     370 *
     371 * @returns Nanosecond timestamp.
     372 */
     373uint64_t Service::getCurrentTimestamp(void)
     374{
     375    RTTIMESPEC time;
     376    uint64_t u64NanoTS = RTTimeSpecGetNano(RTTimeNow(&time));
     377    if (mPrevTimestamp - u64NanoTS > mcTimestampAdjustments)
     378        mcTimestampAdjustments = 0;
     379    else
     380    {
     381        mcTimestampAdjustments++;
     382        u64NanoTS = mPrevTimestamp + 1;
     383    }
     384    this->mPrevTimestamp = u64NanoTS;
     385    return u64NanoTS;
     386}
     387
     388/**
    346389 * Check that a string fits our criteria for a property name.
    347390 *
     
    572615    uint32_t cchFlags = 0;
    573616    uint32_t fFlags = NILFLAG;
    574     RTTIMESPEC time;
    575     uint64_t u64TimeNano = RTTimeSpecGetNano(RTTimeNow(&time));
     617    uint64_t u64TimeNano = getCurrentTimestamp();
    576618
    577619    LogFlowThisFunc(("\n"));
     
    702744        if (rc == VINF_SUCCESS && found)
    703745        {
    704             RTTIMESPEC time;
    705             uint64_t u64Timestamp = RTTimeSpecGetNano(RTTimeNow(&time));
     746            uint64_t u64Timestamp = getCurrentTimestamp();
    706747            mProperties.erase(it);
    707748            // if (isGuest)  /* Notify the host even for properties that the host
     
    808849                                        Property *pProp)
    809850{
    810     int rc = VINF_SUCCESS;
    811     bool warn = false;
    812 
    813851    /* We count backwards, as the guest should normally be querying the
    814852     * most recent events. */
     853    int rc = VWRN_NOT_FOUND;
    815854    PropertyList::reverse_iterator it = mGuestNotifications.rbegin();
    816     for (; it->mTimestamp != u64Timestamp && it != mGuestNotifications.rend();
    817          ++it) {}
    818     /* Warn if the timestamp was not found. */
    819     if (it->mTimestamp != u64Timestamp)
    820         warn = true;
     855    for (; it != mGuestNotifications.rend(); ++it)
     856        if (it->mTimestamp == u64Timestamp)
     857        {
     858            rc = VINF_SUCCESS;
     859            break;
     860        }
     861
    821862    /* Now look for an event matching the patterns supplied.  The base()
    822863     * member conveniently points to the following element. */
    823864    PropertyList::iterator base = it.base();
    824     for (; !base->Matches(pszPatterns) && base != mGuestNotifications.end();
    825          ++base) {}
    826     if (RT_SUCCESS(rc) && base != mGuestNotifications.end())
    827         *pProp = *base;
    828     else if (RT_SUCCESS(rc))
    829         *pProp = Property();
    830     if (warn)
    831         rc = VWRN_NOT_FOUND;
     865    for (; base != mGuestNotifications.end(); ++base)
     866        if (base->Matches(pszPatterns))
     867        {
     868            *pProp = *base;
     869            return rc;
     870        }
     871    *pProp = Property();
    832872    return rc;
    833873}
  • trunk/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp

    r28800 r29394  
    727727    int rc = VINF_SUCCESS;
    728728    VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
    729     char chBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN];
     729    char achBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN];
    730730    static char szPattern[] = "";
    731731
     
    739739    paParms[0].setPointer ((void *) szPattern, sizeof(szPattern));
    740740    paParms[1].setUInt64 (u64Timestamp);
    741     paParms[2].setPointer ((void *) chBuffer, getNotifications[0].cchBuffer - 1);
     741    paParms[2].setPointer ((void *) achBuffer, getNotifications[0].cchBuffer - 1);
    742742    pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL,
    743743                    GET_NOTIFICATION, 4, paParms);
     
    760760        paParms[0].setPointer ((void *) szPattern, sizeof(szPattern));
    761761        paParms[1].setUInt64 (u64Timestamp);
    762         paParms[2].setPointer ((void *) chBuffer, sizeof(chBuffer));
     762        paParms[2].setPointer ((void *) achBuffer, sizeof(achBuffer));
    763763        pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL,
    764764                        GET_NOTIFICATION, 4, paParms);
     
    768768            || RT_FAILURE(paParms[3].getUInt32 (&u32Size))
    769769            || u32Size != getNotifications[i].cchBuffer
    770             || memcmp(chBuffer, getNotifications[i].pchBuffer, u32Size) != 0
     770            || memcmp(achBuffer, getNotifications[i].pchBuffer, u32Size) != 0
    771771           )
    772772        {
    773             RTPrintf("Failed to get notification for property '%s'.\n",
    774                      getNotifications[i].pchBuffer);
     773            RTPrintf("Failed to get notification for property '%s' (rc=%Rrc).\n",
     774                     getNotifications[i].pchBuffer, rc);
    775775            rc = VERR_UNRESOLVED_ERROR;
    776776        }
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