VirtualBox

Changeset 14213 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Nov 14, 2008 2:45:40 PM (16 years ago)
Author:
vboxsync
Message:

HostServices/GuestProperties: some clean up

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

Legend:

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

    r14104 r14213  
    6464
    6565/**
     66 * Structure for holding a property
     67 */
     68struct Property
     69{
     70    /** The name of the property */
     71    std::string mName;
     72    /** The property value */
     73    std::string mValue;
     74    /** The timestamp of the property */
     75    uint64_t mTimestamp;
     76    /** The property flags */
     77    uint32_t mFlags;
     78
     79    /** Default constructor */
     80    Property() : mTimestamp(0), mFlags(NILFLAG) {}
     81    /** Constructor with const char * */
     82    Property(const char *pcszName, const char *pcszValue,
     83             uint64_t u64Timestamp, uint32_t u32Flags)
     84        : mName(pcszName), mValue(pcszValue), mTimestamp(u64Timestamp),
     85          mFlags(u32Flags) {}
     86    /** Constructor with std::string */
     87    Property(std::string name, std::string value, uint64_t u64Timestamp,
     88             uint32_t u32Flags)
     89        : mName(name), mValue(value), mTimestamp(u64Timestamp),
     90          mFlags(u32Flags) {}
     91
     92    /** Does the property name match one of a set of patterns? */
     93    bool Matches(const char *pszPatterns) const
     94    {
     95        return (   pszPatterns[0] == '\0'  /* match all */
     96                || RTStrSimplePatternMultiMatch(pszPatterns, RTSTR_MAX,
     97                                                mName.c_str(), RTSTR_MAX,
     98                                                NULL)
     99               );
     100    }
     101
     102    /** Are two properties equal? */
     103    bool operator== (const Property &prop)
     104    {
     105        return (   mName == prop.mName
     106                && mValue == prop.mValue
     107                && mTimestamp == prop.mTimestamp
     108                && mFlags == prop.mFlags
     109               );
     110    }
     111
     112    /* Is the property nil? */
     113    bool isNull()
     114    {
     115        return mName.empty();
     116    }
     117};
     118/** The properties list type */
     119typedef std::list <Property> PropertyList;
     120
     121/**
     122 * Structure for holding an uncompleted guest call
     123 */
     124struct GuestCall
     125{
     126    /** The call handle */
     127    VBOXHGCMCALLHANDLE mHandle;
     128    /** The function that was requested */
     129    uint32_t mFunction;
     130    /** The call parameters */
     131    VBOXHGCMSVCPARM *mParms;
     132    /** The default return value, used for passing warnings */
     133    int mRc;
     134
     135    /** The standard constructor */
     136    GuestCall() : mFunction(0) {}
     137    /** The normal contructor */
     138    GuestCall(VBOXHGCMCALLHANDLE aHandle, uint32_t aFunction,
     139              VBOXHGCMSVCPARM aParms[], int aRc)
     140              : mHandle(aHandle), mFunction(aFunction), mParms(aParms),
     141                mRc(aRc) {}
     142};
     143/** The guest call list type */
     144typedef std::list <GuestCall> CallList;
     145
     146/**
    66147 * Class containing the shared information service functionality.
    67148 */
     
    73154    /** HGCM helper functions. */
    74155    PVBOXHGCMSVCHELPERS mpHelpers;
    75     /** Structure for holding a property */
    76     struct Property
    77     {
    78         /** The name of the property */
    79         std::string mName;
    80         /** The property value */
    81         std::string mValue;
    82         /** The timestamp of the property */
    83         uint64_t mTimestamp;
    84         /** The property flags */
    85         uint32_t mFlags;
    86 
    87         /** Default constructor */
    88         Property() : mName(""), mValue(""), mTimestamp(0), mFlags(NILFLAG) {}
    89         /** Constructor with const char * */
    90         Property(const char *pcszName, const char *pcszValue,
    91                  uint64_t u64Timestamp, uint32_t u32Flags)
    92             : mName(pcszName), mValue(pcszValue), mTimestamp(u64Timestamp),
    93               mFlags(u32Flags) {}
    94         /** Constructor with std::string */
    95         Property(std::string name, std::string value, uint64_t u64Timestamp,
    96                  uint32_t u32Flags)
    97             : mName(name), mValue(value), mTimestamp(u64Timestamp),
    98               mFlags(u32Flags) {}
    99     };
    100     /** The properties list type */
    101     typedef std::list <Property> PropertyList;
    102156    /** The property list */
    103157    PropertyList mProperties;
    104158    /** The list of property changes for guest notifications */
    105159    PropertyList mGuestNotifications;
    106     /** Structure for holding an uncompleted guest call */
    107     struct GuestCall
    108     {
    109         /** The call handle */
    110         VBOXHGCMCALLHANDLE mHandle;
    111         /** The function that was requested */
    112         uint32_t mFunction;
    113         /** The call parameters */
    114         VBOXHGCMSVCPARM *mParms;
    115         /** The default return value, used for passing warnings */
    116         int mRc;
    117 
    118         /** The standard constructor */
    119         GuestCall() : mFunction(0) {}
    120         /** The normal contructor */
    121         GuestCall(VBOXHGCMCALLHANDLE aHandle, uint32_t aFunction,
    122                   VBOXHGCMSVCPARM aParms[], int aRc)
    123                   : mHandle(aHandle), mFunction(aFunction), mParms(aParms),
    124                     mRc(aRc) {}
    125     };
    126     typedef std::list <GuestCall> CallList;
    127160    /** The list of outstanding guest notification calls */
    128161    CallList mGuestWaiters;
     
    140173    void *mpvHostData;
    141174
     175    /**
     176     * Get the next property change notification from the queue of saved
     177     * notification based on the timestamp of the last notification seen.
     178     * Notifications will only be reported if the property name matches the
     179     * pattern given.
     180     *
     181     * @returns iprt status value
     182     * @returns VWRN_NOT_FOUND if the last notification was not found in the queue
     183     * @param   pszPatterns   the patterns to match the property name against
     184     * @param   u64Timestamp  the timestamp of the last notification
     185     * @param   pProp         where to return the property found.  If none is
     186     *                        found this will be set to nil.
     187     * @thread  HGCM
     188     */
     189    int getOldNotification(const char *pszPatterns, uint64_t u64Timestamp,
     190                           Property *pProp)
     191    {
     192        AssertPtrReturn(pszPatterns, VERR_INVALID_POINTER);
     193        /* Zero means wait for a new notification. */
     194        AssertReturn(u64Timestamp != 0, VERR_INVALID_PARAMETER);
     195        AssertPtrReturn(pProp, VERR_INVALID_POINTER);
     196        int rc = getOldNotificationInternal(pszPatterns, u64Timestamp, pProp);
     197#ifdef DEBUG
     198        /*
     199         * ENSURE that pProp is the first event in the notification queue that:
     200         *  - Appears later than u64Timestamp
     201         *  - Matches the pszPatterns
     202         */
     203        PropertyList::const_iterator it = mGuestNotifications.begin();
     204        for (;    it != mGuestNotifications.end()
     205               && it->mTimestamp != u64Timestamp; ++it) {}
     206        if (it == mGuestNotifications.end())  /* Not found */
     207            it = mGuestNotifications.begin();
     208        else
     209            ++it;  /* Next event */
     210        for (;    it != mGuestNotifications.end()
     211               && it->mTimestamp != pProp->mTimestamp; ++it)
     212            Assert(!it->Matches(pszPatterns));
     213        if (pProp->mTimestamp != 0)
     214        {
     215            Assert(*pProp == *it);
     216            Assert(pProp->Matches(pszPatterns));
     217        }
     218#endif
     219        return rc;
     220    }
     221
    142222public:
    143223    explicit Service(PVBOXHGCMSVCHELPERS pHelpers)
     
    238318    int getNotification(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms,
    239319                        VBOXHGCMSVCPARM paParms[]);
    240     int getOldNotification(const char *pszPattern, uint64_t u64Timestamp,
    241                            Property *pProp);
     320    int getOldNotificationInternal(const char *pszPattern,
     321                                   uint64_t u64Timestamp, Property *pProp);
    242322    int getNotificationWriteOut(VBOXHGCMSVCPARM paParms[], Property prop);
    243323    void doNotifications(const char *pszProperty, uint64_t u64Timestamp);
     
    704784     * First repack the patterns into the format expected by RTStrSimplePatternMatch()
    705785     */
    706     bool matchAll = false;
    707786    char pszPatterns[MAX_PATTERN_LEN];
    708     if (   (NULL == pcchPatterns)
    709         || (cchPatterns < 2)  /* An empty pattern string means match all */
    710        )
    711         matchAll = true;
     787    if (NULL == pcchPatterns)
     788        pszPatterns[0] = '\0';
    712789    else
    713790    {
     
    728805         RT_SUCCESS(rc) && (it != mProperties.end()); ++it)
    729806    {
    730         if (   matchAll
    731             || RTStrSimplePatternMultiMatch(pszPatterns, RTSTR_MAX,
    732                                             it->mName.c_str(), RTSTR_MAX, NULL)
    733            )
     807        if (it->Matches(pszPatterns))
    734808        {
    735809            char szFlags[MAX_FLAGS_LEN];
     
    768842}
    769843
    770 /**
    771  * Get the next property change notification from the queue of saved
    772  * notification based on the timestamp of the last notification seen.
    773  * Notifications will only be reported if the property name matches the
    774  * pattern given.
    775  *
    776  * @returns iprt status value
    777  * @returns VWRN_NOT_FOUND if the last notification was not found in the queue
    778  * @param   pszPatterns   the patterns to match the property name against
    779  * @param   u64Timestamp  the timestamp of the last notification
    780  * @param   pProp         where to return the property found.  If none is
    781  *                        found this will be set to nil.
    782  * @thread  HGCM
    783  */
    784 int Service::getOldNotification(const char *pszPatterns, uint64_t u64Timestamp,
    785                                 Property *pProp)
    786 {
    787     AssertPtrReturn(pszPatterns, VERR_INVALID_POINTER);
    788     AssertReturn(u64Timestamp != 0, VERR_INVALID_PARAMETER);  /* Zero means wait for a new notification. */
    789     AssertPtrReturn(pProp, VERR_INVALID_POINTER);
     844/** Helper query used by getOldNotification */
     845int Service::getOldNotificationInternal(const char *pszPatterns,
     846                                        uint64_t u64Timestamp,
     847                                        Property *pProp)
     848{
    790849    int rc = VINF_SUCCESS;
    791850    bool warn = false;
     
    802861     * member conveniently points to the following element. */
    803862    PropertyList::iterator base = it.base();
    804     for (;    pszPatterns[0] != '\0'
    805            && !RTStrSimplePatternMultiMatch(pszPatterns, RTSTR_MAX,
    806                                             base->mName.c_str(), RTSTR_MAX,
    807                                             NULL)
    808            && base != mGuestNotifications.end(); ++base) {}
     863    for (; !base->Matches(pszPatterns) && base != mGuestNotifications.end();
     864         ++base) {}
    809865    if (RT_SUCCESS(rc) && base != mGuestNotifications.end())
    810866        *pProp = *base;
     
    816872}
    817873
     874/** Helper query used by getNotification */
    818875int Service::getNotificationWriteOut(VBOXHGCMSVCPARM paParms[], Property prop)
    819876{
     
    884941
    885942    /*
    886      * Find the change to notify of.
     943     * If no timestamp was supplied or no notification was found in the queue
     944     * of old notifications, enqueue the request in the waiting queue.
    887945     */
    888946    Property prop;
    889947    if (RT_SUCCESS(rc) && u64Timestamp != 0)
    890948        rc = getOldNotification(pszPatterns, u64Timestamp, &prop);
    891     if (   (RT_SUCCESS(rc) && u64Timestamp == 0)
    892         || (RT_SUCCESS(rc) && prop.mName.size() == 1)  /* Empty name -> not found */
    893        )
     949    if (RT_SUCCESS(rc) && prop.isNull())
    894950    {
    895951        mGuestWaiters.push_back(GuestCall(callHandle, GET_NOTIFICATION,
     
    897953        rc = VINF_HGCM_ASYNC_EXECUTE;
    898954    }
     955    /*
     956     * Otherwise reply at once with the enqueued notification we found.
     957     */
    899958    else
    900959    {
     
    918977void Service::doNotifications(const char *pszProperty, uint64_t u64Timestamp)
    919978{
    920     char *pszName = NULL, *pszValue = NULL, *pszFlags = NULL;
    921979    int rc = VINF_SUCCESS;
    922980
     
    928986
    929987    /*
    930      * Try to find the property.
     988     * Try to find the property.  Create a change event if we find it and a
     989     * delete event if we do not.
    931990     */
    932991    Property prop;
     992    prop.mName = pszProperty;
     993    prop.mTimestamp = u64Timestamp;
     994    /* prop is currently a delete event for pszProperty */
    933995    bool found = false;
    934996    if (RT_SUCCESS(rc))
     
    9381000            {
    9391001                found = true;
    940                 prop = *it;
     1002                /* Make prop into a change event. */
     1003                prop.mValue = it->mValue;
     1004                prop.mFlags = it->mFlags;
    9411005            }
    9421006
    943     /*
    944      * First case: if the property exists then send its current value
    945      */
     1007
     1008    /* Release waiters if applicable and add the event to the queue for
     1009     * guest notifications */
     1010    if (RT_SUCCESS(rc))
     1011    {
     1012        try
     1013        {
     1014            for (CallList::iterator it = mGuestWaiters.begin();
     1015                 it != mGuestWaiters.end(); ++it)
     1016            {
     1017                const char *pszPatterns;
     1018                uint32_t cchPatterns;
     1019                it->mParms[0].getPointer((void **) &pszPatterns, &cchPatterns);
     1020                if (prop.Matches(pszPatterns))
     1021                {
     1022                    GuestCall call = mGuestWaiters.back();
     1023                    int rc2 = getNotificationWriteOut(call.mParms, prop);
     1024                    if (RT_SUCCESS(rc2))
     1025                        rc2 = call.mRc;
     1026                    mpHelpers->pfnCallComplete (call.mHandle, rc2);
     1027                    it = mGuestWaiters.erase(it);
     1028                }
     1029            }
     1030            mGuestNotifications.push_back(prop);
     1031        }
     1032        catch (std::bad_alloc)
     1033        {
     1034            rc = VERR_NO_MEMORY;
     1035        }
     1036    }
     1037    if (mGuestNotifications.size() > MAX_GUEST_NOTIFICATIONS)
     1038        mGuestNotifications.pop_front();
     1039
     1040#ifndef VBOX_GUEST_PROP_TEST_NOTHREAD
     1041    /*
     1042     * Host notifications - first case: if the property exists then send its
     1043     * current value
     1044     */
     1045    char *pszName = NULL, *pszValue = NULL, *pszFlags = NULL;
     1046
    9461047    if (found && mpfnHostCallback != NULL)
    9471048    {
    948 #ifndef VBOX_GUEST_PROP_TEST_NOTHREAD
    9491049        char szFlags[MAX_FLAGS_LEN];
    9501050        /* Send out a host notification */
     
    9621062                             (uint32_t) RT_HIDWORD(u64Timestamp),
    9631063                             (uint32_t) RT_LODWORD(u64Timestamp), pszFlags);
    964 #endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */
    965     }
    966     if (found)
    967     {
    968         /* Release waiters if applicable and add the change to the queue for
    969          * guest notifications */
    970         if (RT_SUCCESS(rc))
    971         {
    972             try
    973             {
    974                 for (CallList::iterator it = mGuestWaiters.begin();
    975                      it != mGuestWaiters.end(); ++it)
    976                 {
    977                     const char *pszPatterns;
    978                     uint32_t cchPatterns;
    979                     it->mParms[0].getPointer((void **) &pszPatterns, &cchPatterns);
    980                     if (   pszPatterns[0] == '\0'
    981                         || RTStrSimplePatternMultiMatch(pszPatterns, RTSTR_MAX,
    982                                                         pszProperty, RTSTR_MAX,
    983                                                         NULL))
    984                     {
    985                         GuestCall call = mGuestWaiters.back();
    986                         int rc2 = getNotificationWriteOut(call.mParms, prop);
    987                         if (RT_SUCCESS(rc2))
    988                             rc2 = call.mRc;
    989                         mpHelpers->pfnCallComplete (call.mHandle, rc2);
    990                         it = mGuestWaiters.erase(it);
    991                     }
    992                 }
    993                 mGuestNotifications.push_back(prop);
    994             }
    995             catch (std::bad_alloc)
    996             {
    997                 rc = VERR_NO_MEMORY;
    998             }
    999         }
    1000     }
    1001 
    1002     /*
    1003      * Second case: if the property does not exist then send the host an empty
    1004      * value
     1064    }
     1065
     1066    /*
     1067     * Host notifications - second case: if the property does not exist then
     1068     * send the host an empty value
    10051069     */
    10061070    if (!found && mpfnHostCallback != NULL)
    10071071    {
    1008 #ifndef VBOX_GUEST_PROP_TEST_NOTHREAD
    10091072        /* Send out a host notification */
    10101073        rc = RTStrDupEx(&pszName, pszProperty);
     
    10151078                             (uint32_t) RT_HIDWORD(u64Timestamp),
    10161079                             (uint32_t) RT_LODWORD(u64Timestamp), NULL);
    1017 #endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */
    1018     }
    1019     if (!found)
    1020     {
    1021         /* Add the change to the queue for guest notifications */
    1022         if (RT_SUCCESS(rc))
    1023         {
    1024             try
    1025             {
    1026                 mGuestNotifications.push_back(Property(pszProperty, "",
    1027                                                        u64Timestamp, NILFLAG)
    1028                                              );
    1029             }
    1030             catch (std::bad_alloc)
    1031             {
    1032                 rc = VERR_NO_MEMORY;
    1033             }
    1034         }
    1035     }
    1036     if (mGuestNotifications.size() > MAX_GUEST_NOTIFICATIONS)
    1037         mGuestNotifications.pop_front();
     1080    }
    10381081    if (RT_FAILURE(rc)) /* clean up if we failed somewhere */
    10391082    {
     
    10421085        RTStrFree(pszFlags);
    10431086    }
     1087#endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */
    10441088}
    10451089
  • trunk/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp

    r14104 r14213  
    460460        strncat(szValue, setProperties[i].pcszValue, sizeof(szValue));
    461461        strncat(szFlags, setProperties[i].pcszFlags, sizeof(szFlags));
    462         paParms[0].setPointer (szName, strlen(szName) + 1);
    463         paParms[1].setPointer (szValue, strlen(szValue) + 1);
    464         paParms[2].setPointer (szFlags, strlen(szFlags) + 1);
     462        paParms[0].setPointer (szName, (uint32_t)strlen(szName) + 1);
     463        paParms[1].setPointer (szValue, (uint32_t)strlen(szValue) + 1);
     464        paParms[2].setPointer (szFlags, (uint32_t)strlen(szFlags) + 1);
    465465        if (setProperties[i].isHost)
    466466            callHandle.rc = pTable->pfnHostCall(pTable->pvService, command,
     
    532532        char szName[MAX_NAME_LEN] = "";
    533533        strncat(szName, delProperties[i].pcszName, sizeof(szName));
    534         paParms[0].setPointer (szName, strlen(szName) + 1);
     534        paParms[0].setPointer (szName, (uint32_t)strlen(szName) + 1);
    535535        if (delProperties[i].isHost)
    536536            callHandle.rc = pTable->pfnHostCall(pTable->pvService, command,
     
    609609                        rc = VERR_INTERNAL_ERROR);
    610610        strncat(szName, getProperties[i].pcszName, sizeof(szName));
    611         paParms[0].setPointer (szName, strlen(szName) + 1);
     611        paParms[0].setPointer (szName, (uint32_t)strlen(szName) + 1);
    612612        paParms[1].setPointer (szBuffer, sizeof(szBuffer));
    613613        rc2 = pTable->pfnHostCall(pTable->pvService, GET_PROP_HOST, 4,
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