Changeset 41286 in vbox for trunk/src/VBox/Frontends/VBoxBalloonCtrl
- Timestamp:
- May 14, 2012 2:46:29 PM (13 years ago)
- Location:
- trunk/src/VBox/Frontends/VBoxBalloonCtrl
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModAPIMonitor.cpp
r40014 r41286 22 22 *******************************************************************************/ 23 23 #ifndef VBOX_ONLY_DOCS 24 # include <iprt/message.h> 24 25 # include <VBox/com/errorprint.h> 25 26 #endif /* !VBOX_ONLY_DOCS */ … … 53 54 { 54 55 /** Unknown / unhandled response. */ 55 APIMON_RESPONSE_UNKNOWN = 0, 56 APIMON_RESPONSE_NONE = 0, 57 /** Does a hard power off. */ 58 APIMON_RESPONSE_POWEROFF = 200, 59 /** Tries to save the current machine state. */ 60 APIMON_RESPONSE_SAVE = 250, 56 61 /** Tries to shut down all running VMs in 57 62 * a gentle manner. */ 58 APIMON_RESPONSE_SHUTDOWN = 20063 APIMON_RESPONSE_SHUTDOWN = 300 59 64 }; 60 65 61 static Bstr g_strAPIMonGroups; 62 63 static APIMON_RESPONSE g_enmAPIMonIslnResp = APIMON_RESPONSE_ UNKNOWN;66 /** The VM group(s) the API monitor handles. If none, all VMs get handled. */ 67 static mapGroups g_vecAPIMonGroups; 68 static APIMON_RESPONSE g_enmAPIMonIslnResp = APIMON_RESPONSE_NONE; 64 69 static unsigned long g_ulAPIMonIslnTimeoutMS = 0; 65 70 static Bstr g_strAPIMonIslnLastBeat; 66 71 static uint64_t g_uAPIMonIslnLastBeatMS = 0; 67 72 68 int apimonResponseToEnum(const char *pszResponse, APIMON_RESPONSE *pResp)73 static int apimonResponseToEnum(const char *pszResponse, APIMON_RESPONSE *pResp) 69 74 { 70 75 AssertPtrReturn(pszResponse, VERR_INVALID_POINTER); … … 72 77 73 78 int rc = VINF_SUCCESS; 74 if ( !RTStrICmp(pszResponse, "shutdown") 75 || !RTStrICmp(pszResponse, "poweroff")) 79 if ( !RTStrICmp(pszResponse, "poweroff") 80 || !RTStrICmp(pszResponse, "powerdown")) 81 { 82 *pResp = APIMON_RESPONSE_POWEROFF; 83 } 84 else if ( !RTStrICmp(pszResponse, "shutdown") 85 || !RTStrICmp(pszResponse, "shutoff")) 76 86 { 77 87 *pResp = APIMON_RESPONSE_SHUTDOWN; 78 88 } 89 else if (!RTStrICmp(pszResponse, "save")) 90 { 91 *pResp = APIMON_RESPONSE_SAVE; 92 } 79 93 else 80 *pResp = APIMON_RESPONSE_UNKNOWN; 81 82 return (*pResp > APIMON_RESPONSE_UNKNOWN ? VINF_SUCCESS : VERR_INVALID_PARAMETER); 83 } 84 85 int apimonMachineControl(const Bstr &strUuid, PVBOXWATCHDOG_MACHINE pMachine, 86 APIMON_RESPONSE enmResp) 94 { 95 *pResp = APIMON_RESPONSE_NONE; 96 rc = VERR_INVALID_PARAMETER; 97 } 98 99 return rc; 100 } 101 102 static const char* apimonResponseToStr(APIMON_RESPONSE enmResp) 103 { 104 if (APIMON_RESPONSE_POWEROFF == enmResp) 105 return "powering off"; 106 else if (APIMON_RESPONSE_SHUTDOWN == enmResp) 107 return "shutting down"; 108 else if (APIMON_RESPONSE_SAVE == enmResp) 109 return "saving state"; 110 else if (APIMON_RESPONSE_NONE == enmResp) 111 return "none"; 112 113 return "unknown"; 114 } 115 116 /* Copied from VBoxManageInfo.cpp. */ 117 static const char *apimonMachineStateToName(MachineState_T machineState, bool fShort) 118 { 119 switch (machineState) 120 { 121 case MachineState_PoweredOff: 122 return fShort ? "poweroff" : "powered off"; 123 case MachineState_Saved: 124 return "saved"; 125 case MachineState_Aborted: 126 return "aborted"; 127 case MachineState_Teleported: 128 return "teleported"; 129 case MachineState_Running: 130 return "running"; 131 case MachineState_Paused: 132 return "paused"; 133 case MachineState_Stuck: 134 return fShort ? "gurumeditation" : "guru meditation"; 135 case MachineState_LiveSnapshotting: 136 return fShort ? "livesnapshotting" : "live snapshotting"; 137 case MachineState_Teleporting: 138 return "teleporting"; 139 case MachineState_Starting: 140 return "starting"; 141 case MachineState_Stopping: 142 return "stopping"; 143 case MachineState_Saving: 144 return "saving"; 145 case MachineState_Restoring: 146 return "restoring"; 147 case MachineState_TeleportingPausedVM: 148 return fShort ? "teleportingpausedvm" : "teleporting paused vm"; 149 case MachineState_TeleportingIn: 150 return fShort ? "teleportingin" : "teleporting (incoming)"; 151 case MachineState_RestoringSnapshot: 152 return fShort ? "restoringsnapshot" : "restoring snapshot"; 153 case MachineState_DeletingSnapshot: 154 return fShort ? "deletingsnapshot" : "deleting snapshot"; 155 case MachineState_DeletingSnapshotOnline: 156 return fShort ? "deletingsnapshotlive" : "deleting snapshot live"; 157 case MachineState_DeletingSnapshotPaused: 158 return fShort ? "deletingsnapshotlivepaused" : "deleting snapshot live paused"; 159 case MachineState_SettingUp: 160 return fShort ? "settingup" : "setting up"; 161 default: 162 break; 163 } 164 return "unknown"; 165 } 166 167 static int apimonMachineControl(const Bstr &strUuid, PVBOXWATCHDOG_MACHINE pMachine, 168 APIMON_RESPONSE enmResp, unsigned long ulTimeout) 87 169 { 88 170 /** @todo Add other commands (with enmResp) here. */ 89 AssertPtrReturn(pMachine, VERR_INVALID_PARAMETER); 90 91 serviceLog("Shutting down machine \"%ls\"\n", strUuid.raw()); 171 AssertPtrReturn(pMachine, VERR_INVALID_POINTER); 172 173 serviceLogVerbose(("apimon: Triggering \"%s\" (%RU32ms timeout) for machine \"%ls\"\n", 174 apimonResponseToStr(enmResp), ulTimeout, strUuid.raw())); 175 176 if ( enmResp == APIMON_RESPONSE_NONE 177 || g_fDryrun) 178 return VINF_SUCCESS; /* Nothing to do. */ 179 180 HRESULT rc; 181 ComPtr <IMachine> machine; 182 CHECK_ERROR_RET(g_pVirtualBox, FindMachine(strUuid.raw(), 183 machine.asOutParam()), VERR_NOT_FOUND); 92 184 93 185 /* Open a session for the VM. */ 94 HRESULT rc;95 CHECK_ERROR_RET(pMachine->machine, LockMachine(g_pSession, LockType_Shared), VERR_ACCESS_DENIED); 186 CHECK_ERROR_RET(machine, LockMachine(g_pSession, LockType_Shared), VERR_ACCESS_DENIED); 187 96 188 do 97 189 { 98 /* get the associated console */ 190 191 /* Get the associated console. */ 99 192 ComPtr<IConsole> console; 100 193 CHECK_ERROR_BREAK(g_pSession, COMGETTER(Console)(console.asOutParam())); 101 194 102 if (!g_fDryrun) 195 /* Query the machine's state to avoid unnecessary IPC. */ 196 MachineState_T machineState; 197 CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState)); 198 if ( machineState == MachineState_Running 199 || machineState == MachineState_Paused) 103 200 { 104 201 ComPtr<IProgress> progress; 105 CHECK_ERROR_BREAK(console, PowerDown(progress.asOutParam())); 106 if (g_fVerbose)202 203 switch (enmResp) 107 204 { 108 serviceLogVerbose(("Waiting for shutting down machine \"%ls\" ...\n", 109 strUuid.raw())); 110 progress->WaitForCompletion(-1); 205 case APIMON_RESPONSE_POWEROFF: 206 CHECK_ERROR_BREAK(console, PowerDown(progress.asOutParam())); 207 serviceLogVerbose(("apimon: Waiting for powering off machine \"%ls\" ...\n", 208 strUuid.raw())); 209 progress->WaitForCompletion(ulTimeout); 210 CHECK_PROGRESS_ERROR(progress, ("Failed to power off machine \"%ls\"", 211 strUuid.raw())); 212 break; 213 214 case APIMON_RESPONSE_SAVE: 215 { 216 /* First pause so we don't trigger a live save which needs more time/resources. */ 217 bool fPaused = false; 218 rc = console->Pause(); 219 if (FAILED(rc)) 220 { 221 bool fError = true; 222 if (rc == VBOX_E_INVALID_VM_STATE) 223 { 224 /* Check if we are already paused. */ 225 MachineState_T machineState; 226 CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState)); 227 /* The error code was lost by the previous instruction. */ 228 rc = VBOX_E_INVALID_VM_STATE; 229 if (machineState != MachineState_Paused) 230 { 231 serviceLog("apimon: Machine \"%s\" in invalid state %d -- %s\n", 232 strUuid.raw(), machineState, apimonMachineStateToName(machineState, false)); 233 } 234 else 235 { 236 fError = false; 237 fPaused = true; 238 } 239 } 240 if (fError) 241 break; 242 } 243 244 serviceLogVerbose(("apimon: Waiting for saving state of machine \"%ls\" ...\n", 245 strUuid.raw())); 246 247 ComPtr<IProgress> progress; 248 CHECK_ERROR(console, SaveState(progress.asOutParam())); 249 if (FAILED(rc)) 250 { 251 if (!fPaused) 252 console->Resume(); 253 break; 254 } 255 256 progress->WaitForCompletion(ulTimeout); 257 CHECK_PROGRESS_ERROR(progress, ("Failed to save machine state of machine \"%ls\"", 258 strUuid.raw())); 259 if (FAILED(rc)) 260 { 261 if (!fPaused) 262 console->Resume(); 263 } 264 265 break; 266 } 267 268 case APIMON_RESPONSE_SHUTDOWN: 269 CHECK_ERROR_BREAK(console, PowerButton()); 270 serviceLogVerbose(("apimon: Waiting for shutdown of machine \"%ls\" ...\n", 271 strUuid.raw())); 272 progress->WaitForCompletion(ulTimeout); 273 CHECK_PROGRESS_ERROR(progress, ("Failed to shutdown machine \"%ls\"", 274 strUuid.raw())); 275 break; 276 277 default: 278 AssertMsgFailed(("Response %d not implemented", enmResp)); 279 break; 111 280 } 112 281 } 282 else 283 serviceLog("apimon: Machine \"%s\" is in invalid state \"%s\" (%d) for triggering \"%s\"\n", 284 strUuid.raw(), apimonMachineStateToName(machineState, false), machineState, 285 apimonResponseToStr(enmResp)); 113 286 } while (0); 114 287 … … 119 292 } 120 293 121 int apimonTrigger(APIMON_RESPONSE enmResp) 294 static bool apimonHandleVM(const PVBOXWATCHDOG_MACHINE pMachine) 295 { 296 bool fHandleVM = false; 297 298 try 299 { 300 mapGroupsIterConst itVMGroup = pMachine->groups.begin(); 301 while ( itVMGroup != pMachine->groups.end() 302 && !fHandleVM) 303 { 304 mapGroupsIterConst itInGroup = g_vecAPIMonGroups.find(itVMGroup->first); 305 if (itInGroup != g_vecAPIMonGroups.end()) 306 fHandleVM = true; 307 308 itVMGroup++; 309 } 310 } 311 catch (...) 312 { 313 AssertFailed(); 314 } 315 316 return fHandleVM; 317 } 318 319 static int apimonTrigger(APIMON_RESPONSE enmResp) 122 320 { 123 321 int rc = VINF_SUCCESS; 124 322 125 /** @todo Add proper grouping support! */ 126 bool fAllGroups = g_strAPIMonGroups.isEmpty(); 323 bool fAllGroups = g_vecAPIMonGroups.empty(); 127 324 mapVMIter it = g_mapVM.begin(); 325 326 if (it == g_mapVM.end()) 327 { 328 serviceLog("apimon: No machines in list, skipping ...\n"); 329 return rc; 330 } 331 128 332 while (it != g_mapVM.end()) 129 333 { 130 if ( !it->second.group.compare(g_strAPIMonGroups, Bstr::CaseInsensitive) 131 || fAllGroups) 132 { 133 rc = apimonMachineControl(it->first /* Uuid */, 134 &it->second, enmResp); 135 } 334 bool fHandleVM = fAllGroups; 335 try 336 { 337 if (!fHandleVM) 338 fHandleVM = apimonHandleVM(&it->second); 339 340 if (fHandleVM) 341 { 342 int rc2 = apimonMachineControl(it->first /* Uuid */, 343 &it->second /* Machine */, enmResp, 30 * 1000 /* 30s timeout */); 344 if (RT_FAILURE(rc2)) 345 serviceLog("apimon: Controlling machine \"%ls\" (action: %s) failed with rc=%Rrc", 346 it->first.raw(), apimonResponseToStr(enmResp), rc); 347 348 if (RT_SUCCESS(rc)) 349 rc = rc2; /* Store original error. */ 350 /* Keep going. */ 351 } 352 } 353 catch (...) 354 { 355 AssertFailed(); 356 } 357 136 358 it++; 137 359 } … … 176 398 case GETOPTDEF_APIMON_ISLN_TIMEOUT: 177 399 g_ulAPIMonIslnTimeoutMS = ValueUnion.u32; 178 if (g_ulAPIMonIslnTimeoutMS < 1000) 400 if (g_ulAPIMonIslnTimeoutMS < 1000) /* Don't allow timeouts < 1s. */ 179 401 g_ulAPIMonIslnTimeoutMS = 1000; 180 402 break; 181 403 182 404 case GETOPTDEF_APIMON_GROUPS: 183 g_strAPIMonGroups = ValueUnion.psz; 405 { 406 rc = groupAdd(g_vecAPIMonGroups, ValueUnion.psz, 0 /* Flags */); 407 if (RT_FAILURE(rc)) 408 rc = -1; /* Option unknown. */ 184 409 break; 410 } 185 411 186 412 default: … … 211 437 if (!g_ulAPIMonIslnTimeoutMS) /* Still not set? Use a default. */ 212 438 { 213 serviceLogVerbose((" API monitor isolation timeout not given, defaulting to 30s\n"));439 serviceLogVerbose(("apimon: API monitor isolation timeout not given, defaulting to 30s\n")); 214 440 215 441 /* Default is 30 seconds timeout. */ … … 218 444 219 445 /* VM groups to watch for. */ 220 if (g_ strAPIMonGroups.isEmpty()) /* Not set by command line? */446 if (g_vecAPIMonGroups.empty()) /* Not set by command line? */ 221 447 { 222 448 CHECK_ERROR_BREAK(g_pVirtualBox, GetExtraData(Bstr("Watchdog/APIMonitor/Groups").raw(), 223 g_strAPIMonGroups.asOutParam())); 449 strValue.asOutParam())); 450 if (!strValue.isEmpty()) 451 { 452 int rc2 = groupAdd(g_vecAPIMonGroups, Utf8Str(strValue).c_str(), 0 /* Flags */); 453 if (RT_FAILURE(rc2)) 454 serviceLog("apimon: Warning: API monitor groups string invalid (%ls)\n", strValue.raw()); 455 } 224 456 } 225 457 226 458 /* Host isolation command response. */ 227 if (g_enmAPIMonIslnResp == APIMON_RESPONSE_ UNKNOWN) /* Not set by command line? */459 if (g_enmAPIMonIslnResp == APIMON_RESPONSE_NONE) /* Not set by command line? */ 228 460 { 229 461 CHECK_ERROR_BREAK(g_pVirtualBox, GetExtraData(Bstr("Watchdog/APIMonitor/IsolationResponse").raw(), … … 233 465 int rc2 = apimonResponseToEnum(Utf8Str(strValue).c_str(), &g_enmAPIMonIslnResp); 234 466 if (RT_FAILURE(rc2)) 235 { 236 serviceLog("Warning: API monitor response string invalid (%ls), default to shutdown\n", 467 serviceLog("apimon: Warning: API monitor response string invalid (%ls), defaulting to no action\n", 237 468 strValue.raw()); 238 g_enmAPIMonIslnResp = APIMON_RESPONSE_SHUTDOWN;239 }240 469 } 241 else242 g_enmAPIMonIslnResp = APIMON_RESPONSE_SHUTDOWN;243 470 } 244 471 } while (0); … … 257 484 uint64_t uNow = RTTimeProgramMilliTS(); 258 485 uint64_t uDelta = uNow - uLastRun; 259 if (uDelta < 1000) 486 if (uDelta < 1000) /* Only check every second (or later). */ 260 487 return VINF_SUCCESS; 261 488 uLastRun = uNow; … … 264 491 HRESULT rc; 265 492 266 serviceLogVerbose(("Checking for API heartbeat (%RU64ms) ...\n", 493 #ifdef DEBUG 494 serviceLogVerbose(("apimon: Checking for API heartbeat (%RU64ms) ...\n", 267 495 g_ulAPIMonIslnTimeoutMS)); 496 #endif 268 497 269 498 do … … 276 505 && g_strAPIMonIslnLastBeat.compare(strHeartbeat, Bstr::CaseSensitive)) 277 506 { 278 serviceLogVerbose((" API heartbeat received, resetting timeout\n"));507 serviceLogVerbose(("apimon: API heartbeat received, resetting timeout\n")); 279 508 280 509 g_uAPIMonIslnLastBeatMS = 0; … … 286 515 if (g_uAPIMonIslnLastBeatMS > g_ulAPIMonIslnTimeoutMS) 287 516 { 288 serviceLogVerbose((" No API heartbeat within time received (%RU64ms)\n",517 serviceLogVerbose(("apimon: No API heartbeat within time received (%RU64ms)\n", 289 518 g_ulAPIMonIslnTimeoutMS)); 290 519 … … 329 558 { 330 559 if (!fAvailable) 331 apimonTrigger(g_enmAPIMonIslnResp); 560 { 561 serviceLog(("apimon: VBoxSVC became unavailable, triggering action\n")); 562 return apimonTrigger(g_enmAPIMonIslnResp); 563 } 332 564 return VINF_SUCCESS; 333 565 } -
trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModBallooning.cpp
r40011 r41286 205 205 /* Only do ballooning if we have a maximum balloon size set. */ 206 206 PVBOXWATCHDOG_BALLOONCTRL_PAYLOAD pData = (PVBOXWATCHDOG_BALLOONCTRL_PAYLOAD) 207 getPayload(pMachine, VBOX_MOD_BALLOONING_NAME);207 payloadFrom(pMachine, VBOX_MOD_BALLOONING_NAME); 208 208 AssertPtr(pData); 209 209 pData->ulBalloonSizeMax = pMachine->machine.isNull() … … 298 298 299 299 PVBOXWATCHDOG_BALLOONCTRL_PAYLOAD pData = (PVBOXWATCHDOG_BALLOONCTRL_PAYLOAD) 300 getPayload(pMachine, VBOX_MOD_BALLOONING_NAME);300 payloadFrom(pMachine, VBOX_MOD_BALLOONING_NAME); 301 301 AssertPtr(pData); 302 302 … … 316 316 lDelta > 0 ? "Inflating" : "Deflating", lDelta, lBalloonCur); 317 317 318 HRESULT rc;319 320 318 if (!g_fDryrun) 321 319 { 322 320 /* Open a session for the VM. */ 321 HRESULT rc; 323 322 CHECK_ERROR(pMachine->machine, LockMachine(g_pSession, LockType_Shared)); 324 323 … … 336 335 serviceLog("Error: Unable to set new balloon size %ld for machine \"%ls\", rc=%Rhrc", 337 336 lBalloonCur, strUuid.raw(), rc); 337 if (FAILED(rc)) 338 vrc = VERR_COM_IPRT_ERROR; 338 339 } while (0); 339 340 -
trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdog.cpp
r41100 r41286 137 137 static int machineAdd(const Bstr &strUuid); 138 138 static int machineRemove(const Bstr &strUuid); 139 static HRESULTwatchdogSetup();139 static int watchdogSetup(); 140 140 static void watchdogShutdown(); 141 141 … … 264 264 { 265 265 serviceLog("VBoxSVC became available\n"); 266 HRESULT hrc= watchdogSetup();267 if ( FAILED(hrc))268 serviceLog("Unable to re-set up watchdog (rc=%R hrc)!\n", hrc);266 int rc2 = watchdogSetup(); 267 if (RT_FAILURE(rc2)) 268 serviceLog("Unable to re-set up watchdog (rc=%Rrc)!\n", rc2); 269 269 } 270 270 … … 347 347 Assert(!machine.isNull()); 348 348 349 Bstr strGroup; 349 /* Note: Currently only one group per VM supported? We don't care. */ 350 Bstr strGroups; 350 351 CHECK_ERROR_BREAK(machine, GetExtraData(Bstr("VBoxInternal2/VMGroup").raw(), 351 strGroup .asOutParam()));352 strGroups.asOutParam())); 352 353 353 354 /* … … 356 357 VBOXWATCHDOG_MACHINE m; 357 358 m.machine = machine; 358 m.group = strGroup; 359 int rc2 = groupAdd(m.groups, Utf8Str(strGroups).c_str(), 0 /* Flags */); 360 AssertRC(rc2); 359 361 360 362 mapVMIter it = g_mapVM.find(strUuid); … … 366 368 * Get the machine's VM group(s). 367 369 */ 368 if (!strGroup.isEmpty())369 {370 serviceLogVerbose(("Machine \"%ls\" is in VM group \"%ls\"\n",371 strUuid.raw(), strGroup.raw()));372 373 /** @todo Support more than one group! */ 370 mapGroupsIterConst itGroup = m.groups.begin(); 371 while (itGroup != m.groups.end()) 372 { 373 serviceLogVerbose(("Machine \"%ls\" is in VM group \"%s\"\n", 374 strUuid.raw(), itGroup->first.c_str())); 375 374 376 /* Add machine to group(s). */ 375 mapGroupIter itGroup = g_mapGroup.find(strGroup);376 if (itGroup == g_mapGroup.end())377 mapGroupIter itGroups = g_mapGroup.find(itGroup->first); 378 if (itGroups == g_mapGroup.end()) 377 379 { 378 380 vecGroupMembers vecMembers; 379 381 vecMembers.push_back(strUuid); 380 g_mapGroup.insert(std::make_pair( strGroup, vecMembers));381 382 itGroup = g_mapGroup.find(strGroup);383 Assert(itGroup != g_mapGroup.end());382 g_mapGroup.insert(std::make_pair(itGroup->first, vecMembers)); 383 384 itGroups = g_mapGroup.find(itGroup->first); 385 Assert(itGroups != g_mapGroup.end()); 384 386 } 385 387 else 386 itGroup ->second.push_back(strUuid);388 itGroups->second.push_back(strUuid); 387 389 serviceLogVerbose(("Group \"%ls\" now has %ld machine(s)\n", 388 strGroup.raw(), itGroup->second.size())); 389 } 390 else 391 serviceLogVerbose(("Machine \"%ls\" has no VM group assigned\n", 392 strUuid.raw())); 390 itGroup->first.c_str(), itGroups->second.size())); 391 itGroup++; 392 } 393 393 394 394 /* … … 432 432 serviceLogVerbose(("Removing machine \"%ls\"\n", strUuid.raw())); 433 433 434 mapVMIter itVM = g_mapVM.find(strUuid); 435 Assert(itVM != g_mapVM.end()); 436 437 /* Remove machine from group(s). */ 438 /** @todo Add support for multiple groups! */ 439 Bstr strGroup = itVM->second.group; 440 if (!strGroup.isEmpty()) 441 { 442 mapGroupIter itGroup = g_mapGroup.find(strGroup); 443 Assert(itGroup != g_mapGroup.end()); 444 445 vecGroupMembers vecMembers = itGroup->second; 446 vecGroupMembersIter itMember = std::find(vecMembers.begin(), 447 vecMembers.end(), 448 strUuid); 449 Assert(itMember != vecMembers.end()); 450 vecMembers.erase(itMember); 451 452 serviceLogVerbose(("Group \"%ls\" has %ld machines left\n", 453 itGroup->first.raw(), vecMembers.size())); 454 if (!vecMembers.size()) 455 g_mapGroup.erase(itGroup); 456 } 434 try 435 { 436 mapVMIter itVM = g_mapVM.find(strUuid); 437 Assert(itVM != g_mapVM.end()); 438 439 /* Remove machine from group(s). */ 440 mapGroupsIterConst itGroups = itVM->second.groups.begin(); 441 while (itGroups != itVM->second.groups.end()) 442 { 443 mapGroupIter itGroup = g_mapGroup.find(itGroups->first); 444 Assert(itGroup != g_mapGroup.end()); 445 446 vecGroupMembers vecMembers = itGroup->second; 447 vecGroupMembersIter itMember = std::find(vecMembers.begin(), 448 vecMembers.end(), 449 strUuid); 450 Assert(itMember != vecMembers.end()); 451 vecMembers.erase(itMember); 452 453 serviceLogVerbose(("Group \"%s\" has %ld machines left\n", 454 itGroup->first.c_str(), vecMembers.size())); 455 if (!vecMembers.size()) 456 { 457 serviceLogVerbose(("Deleteting group \"%s\n", itGroup->first.c_str())); 458 g_mapGroup.erase(itGroup); 459 } 460 461 itGroups++; 462 } 457 463 458 464 #ifndef VBOX_WATCHDOG_GLOBAL_PERFCOL 459 itVM->second.collector.setNull();465 itVM->second.collector.setNull(); 460 466 #endif 461 itVM->second.machine.setNull(); 462 463 /* 464 * Remove machine from map. 465 */ 466 g_mapVM.erase(itVM); 467 itVM->second.machine.setNull(); 468 469 /* 470 * Remove machine from map. 471 */ 472 g_mapVM.erase(itVM); 473 } 474 catch (...) 475 { 476 AssertFailed(); 477 } 467 478 468 479 return rc; … … 880 891 * @return HRESULT 881 892 */ 882 static HRESULTwatchdogSetup()893 static int watchdogSetup() 883 894 { 884 895 serviceLogVerbose(("Setting up ...\n")); 885 896 897 /* 898 * Setup VirtualBox + session interfaces. 899 */ 886 900 HRESULT rc = g_pVirtualBoxClient->COMGETTER(VirtualBox)(g_pVirtualBox.asOutParam()); 887 if (FAILED(rc)) 888 { 889 RTMsgError("Failed to get VirtualBox object (rc=%Rhrc)!", rc); 890 } 891 else 901 if (SUCCEEDED(rc)) 892 902 { 893 903 rc = g_pSession.createInprocObject(CLSID_Session); … … 895 905 RTMsgError("Failed to create a session object (rc=%Rhrc)!", rc); 896 906 } 897 898 do 899 { 900 /* 901 * Setup metrics. 902 */ 907 else 908 RTMsgError("Failed to get VirtualBox object (rc=%Rhrc)!", rc); 909 910 if (FAILED(rc)) 911 return VERR_COM_OBJECT_NOT_FOUND; 912 913 /* 914 * Setup metrics. 915 */ 903 916 #ifdef VBOX_WATCHDOG_GLOBAL_PERFCOL 904 CHECK_ERROR_BREAK(g_pVirtualBox, COMGETTER(PerformanceCollector)(g_pPerfCollector.asOutParam())); 917 CHECK_ERROR_RET(g_pVirtualBox, 918 COMGETTER(PerformanceCollector)(g_pPerfCollector.asOutParam()), VERR_COM_UNEXPECTED); 905 919 #endif 906 920 907 int vrc = RTCritSectInit(&g_csMachines); 908 if (RT_FAILURE(vrc)) 909 { 910 rc = VBOX_E_IPRT_ERROR; 911 break; 912 } 921 int vrc = RTCritSectInit(&g_csMachines); 922 if (RT_SUCCESS(vrc)) 923 { 913 924 914 925 /* … … 916 927 */ 917 928 vrc = vmListBuild(); 918 if (RT_FAILURE(vrc)) 919 { 920 rc = VBOX_E_IPRT_ERROR; 921 break; 922 } 923 924 } while (0); 925 926 return rc; 929 } 930 931 return vrc; 927 932 } 928 933 … … 1073 1078 if (RT_FAILURE(rc)) 1074 1079 return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to daemonize, rc=%Rrc. exiting.", rc); 1075 1076 1080 /* create release logger, to file */ 1077 1081 rc = com::VBoxLogRelCreate("Watchdog", pszLogFile, … … 1083 1087 if (RT_FAILURE(rc)) 1084 1088 return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to open release log (%s, %Rrc)", szError, rc); 1089 AssertPtr(pLoggerReleaseFile); 1085 1090 } 1086 1091 #endif … … 1122 1127 serviceLog("Running in dryrun mode\n"); 1123 1128 1124 hrc = watchdogSetup();1125 if ( FAILED(hrc))1129 rc = watchdogSetup(); 1130 if (RT_FAILURE(rc)) 1126 1131 return RTEXITCODE_FAILURE; 1127 1132 -
trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdogInternal.h
r40877 r41286 32 32 #endif /* !VBOX_ONLY_DOCS */ 33 33 34 #include <algorithm> 34 35 #include <map> 36 #include <sstream> 37 #include <string> 35 38 #include <vector> 36 39 … … 74 77 typedef std::map<const char*, VBOXWATCHDOG_MODULE_PAYLOAD>::const_iterator mapPayloadIterConst; 75 78 76 struct VBOXWATCHDOG_VM_GROUP; 79 /** Group list (plus additional per-group flags, not used yet) for one VM. 80 * Primary key is the group name, secondary specify flags (if any). */ 81 typedef std::map<Utf8Str, uint32_t> mapGroups; 82 typedef std::map<Utf8Str, uint32_t>::iterator mapGroupsIter; 83 typedef std::map<Utf8Str, uint32_t>::const_iterator mapGroupsIterConst; 77 84 78 85 /** A machine's internal entry. … … 84 91 ComPtr<IPerformanceCollector> collector; 85 92 #endif 86 /** The machine's VM group(s). */ 87 Bstr group; 93 /** The VM group(s) this machine belongs to. 94 * Contains groups from per-machine "VBoxInternal2/VMGroup". */ 95 mapGroups groups; 88 96 /** Map containing the individual 89 97 * module payloads. */ … … 94 102 typedef std::map<Bstr, VBOXWATCHDOG_MACHINE>::const_iterator mapVMIterConst; 95 103 96 /** Members of a VM group; currently only represented by the machine's UUID. */ 104 /** Members of a VM group; currently only represented by the machine's UUID. 105 * Primary key is the machine's UUID. */ 97 106 typedef std::vector<Bstr> vecGroupMembers; 98 107 typedef std::vector<Bstr>::iterator vecGroupMembersIter; 99 108 typedef std::vector<Bstr>::const_iterator vecGroupMembersIterConst; 100 109 101 /** A VM group. Can contain none, one or more group members. */ 102 typedef std::map<Bstr, vecGroupMembers> mapGroup; 103 typedef std::map<Bstr, vecGroupMembers>::iterator mapGroupIter; 104 typedef std::map<Bstr, vecGroupMembers>::const_iterator mapGroupIterConst; 110 /** A VM group. Can contain none, one or more group members. 111 * Primary key is the group's name. */ 112 typedef std::map<Utf8Str, vecGroupMembers> mapGroup; 113 typedef std::map<Utf8Str, vecGroupMembers>::iterator mapGroupIter; 114 typedef std::map<Utf8Str, vecGroupMembers>::const_iterator mapGroupIterConst; 105 115 106 116 /** … … 216 226 #define serviceLogVerbose(a) if (g_fVerbose) { serviceLog a; } 217 227 228 int groupAdd(mapGroups &groups, const char *pszGroupsToAdd, uint32_t fFlags); 229 218 230 extern int getMetric(PVBOXWATCHDOG_MACHINE pMachine, const Bstr& strName, LONG *pulData); 219 void* getPayload(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule);231 void* payloadFrom(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule); 220 232 int payloadAlloc(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule, size_t cbSize, void **ppszPayload); 221 233 void payloadFree(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule); -
trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdogUtils.cpp
r39986 r41286 23 23 #include "VBoxWatchdogInternal.h" 24 24 25 26 /** 27 * Adds a group / a set of groups to the specified map. 28 * If a group in the group map exists there will be no action. 29 * 30 * @return IPRT status code. 31 * @param groups Map to add group(s) to. 32 * @param pszGroupsToAdd Comma-separated string of one or more groups to add. 33 * @param fFlags Flags to set to the groups added. 34 */ 35 int groupAdd(mapGroups &groups, const char *pszGroupsToAdd, uint32_t fFlags) 36 { 37 AssertPtrReturn(pszGroupsToAdd, VERR_INVALID_POINTER); 38 39 try 40 { 41 std::istringstream strGroups(pszGroupsToAdd); 42 for(std::string strToken; getline(strGroups, strToken, ','); ) 43 { 44 strToken.erase(remove_if(strToken.begin(), strToken.end(), isspace), strToken.end()); 45 46 Utf8Str strTokenUtf8(strToken.c_str()); 47 mapGroupsIterConst it = groups.find(strTokenUtf8); 48 49 if (it == groups.end()) 50 groups.insert(std::make_pair(strTokenUtf8, fFlags)); 51 } 52 } 53 catch (...) 54 { 55 AssertFailed(); 56 } 57 58 return VINF_SUCCESS; 59 } 25 60 26 61 /** … … 105 140 * @param pszModule Module name to get payload from. 106 141 */ 107 void* getPayload(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule)142 void* payloadFrom(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule) 108 143 { 109 144 AssertPtrReturn(pMachine, NULL);
Note:
See TracChangeset
for help on using the changeset viewer.