Changeset 14213 in vbox for trunk/src/VBox
- Timestamp:
- Nov 14, 2008 2:45:40 PM (16 years ago)
- Location:
- trunk/src/VBox/HostServices/GuestProperties
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/GuestProperties/service.cpp
r14104 r14213 64 64 65 65 /** 66 * Structure for holding a property 67 */ 68 struct 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 */ 119 typedef std::list <Property> PropertyList; 120 121 /** 122 * Structure for holding an uncompleted guest call 123 */ 124 struct 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 */ 144 typedef std::list <GuestCall> CallList; 145 146 /** 66 147 * Class containing the shared information service functionality. 67 148 */ … … 73 154 /** HGCM helper functions. */ 74 155 PVBOXHGCMSVCHELPERS mpHelpers; 75 /** Structure for holding a property */76 struct Property77 {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;102 156 /** The property list */ 103 157 PropertyList mProperties; 104 158 /** The list of property changes for guest notifications */ 105 159 PropertyList mGuestNotifications; 106 /** Structure for holding an uncompleted guest call */107 struct GuestCall108 {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;127 160 /** The list of outstanding guest notification calls */ 128 161 CallList mGuestWaiters; … … 140 173 void *mpvHostData; 141 174 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 142 222 public: 143 223 explicit Service(PVBOXHGCMSVCHELPERS pHelpers) … … 238 318 int getNotification(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, 239 319 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); 242 322 int getNotificationWriteOut(VBOXHGCMSVCPARM paParms[], Property prop); 243 323 void doNotifications(const char *pszProperty, uint64_t u64Timestamp); … … 704 784 * First repack the patterns into the format expected by RTStrSimplePatternMatch() 705 785 */ 706 bool matchAll = false;707 786 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'; 712 789 else 713 790 { … … 728 805 RT_SUCCESS(rc) && (it != mProperties.end()); ++it) 729 806 { 730 if ( matchAll 731 || RTStrSimplePatternMultiMatch(pszPatterns, RTSTR_MAX, 732 it->mName.c_str(), RTSTR_MAX, NULL) 733 ) 807 if (it->Matches(pszPatterns)) 734 808 { 735 809 char szFlags[MAX_FLAGS_LEN]; … … 768 842 } 769 843 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 */ 845 int Service::getOldNotificationInternal(const char *pszPatterns, 846 uint64_t u64Timestamp, 847 Property *pProp) 848 { 790 849 int rc = VINF_SUCCESS; 791 850 bool warn = false; … … 802 861 * member conveniently points to the following element. */ 803 862 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) {} 809 865 if (RT_SUCCESS(rc) && base != mGuestNotifications.end()) 810 866 *pProp = *base; … … 816 872 } 817 873 874 /** Helper query used by getNotification */ 818 875 int Service::getNotificationWriteOut(VBOXHGCMSVCPARM paParms[], Property prop) 819 876 { … … 884 941 885 942 /* 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. 887 945 */ 888 946 Property prop; 889 947 if (RT_SUCCESS(rc) && u64Timestamp != 0) 890 948 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()) 894 950 { 895 951 mGuestWaiters.push_back(GuestCall(callHandle, GET_NOTIFICATION, … … 897 953 rc = VINF_HGCM_ASYNC_EXECUTE; 898 954 } 955 /* 956 * Otherwise reply at once with the enqueued notification we found. 957 */ 899 958 else 900 959 { … … 918 977 void Service::doNotifications(const char *pszProperty, uint64_t u64Timestamp) 919 978 { 920 char *pszName = NULL, *pszValue = NULL, *pszFlags = NULL;921 979 int rc = VINF_SUCCESS; 922 980 … … 928 986 929 987 /* 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. 931 990 */ 932 991 Property prop; 992 prop.mName = pszProperty; 993 prop.mTimestamp = u64Timestamp; 994 /* prop is currently a delete event for pszProperty */ 933 995 bool found = false; 934 996 if (RT_SUCCESS(rc)) … … 938 1000 { 939 1001 found = true; 940 prop = *it; 1002 /* Make prop into a change event. */ 1003 prop.mValue = it->mValue; 1004 prop.mFlags = it->mFlags; 941 1005 } 942 1006 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 946 1047 if (found && mpfnHostCallback != NULL) 947 1048 { 948 #ifndef VBOX_GUEST_PROP_TEST_NOTHREAD949 1049 char szFlags[MAX_FLAGS_LEN]; 950 1050 /* Send out a host notification */ … … 962 1062 (uint32_t) RT_HIDWORD(u64Timestamp), 963 1063 (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 1005 1069 */ 1006 1070 if (!found && mpfnHostCallback != NULL) 1007 1071 { 1008 #ifndef VBOX_GUEST_PROP_TEST_NOTHREAD1009 1072 /* Send out a host notification */ 1010 1073 rc = RTStrDupEx(&pszName, pszProperty); … … 1015 1078 (uint32_t) RT_HIDWORD(u64Timestamp), 1016 1079 (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 } 1038 1081 if (RT_FAILURE(rc)) /* clean up if we failed somewhere */ 1039 1082 { … … 1042 1085 RTStrFree(pszFlags); 1043 1086 } 1087 #endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */ 1044 1088 } 1045 1089 -
trunk/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp
r14104 r14213 460 460 strncat(szValue, setProperties[i].pcszValue, sizeof(szValue)); 461 461 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); 465 465 if (setProperties[i].isHost) 466 466 callHandle.rc = pTable->pfnHostCall(pTable->pvService, command, … … 532 532 char szName[MAX_NAME_LEN] = ""; 533 533 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); 535 535 if (delProperties[i].isHost) 536 536 callHandle.rc = pTable->pfnHostCall(pTable->pvService, command, … … 609 609 rc = VERR_INTERNAL_ERROR); 610 610 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); 612 612 paParms[1].setPointer (szBuffer, sizeof(szBuffer)); 613 613 rc2 = pTable->pfnHostCall(pTable->pvService, GET_PROP_HOST, 4,
Note:
See TracChangeset
for help on using the changeset viewer.