Changeset 23669 in vbox for trunk/src/VBox/Main
- Timestamp:
- Oct 10, 2009 3:02:01 AM (15 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ConsoleImpl-LiveMigration.cpp
r23663 r23669 60 60 RTSOCKET mhSocket; 61 61 uint64_t moffStream; 62 bool volatile mfStopReading; 62 63 /** @} */ 63 64 … … 67 68 , mhSocket(NIL_RTSOCKET) 68 69 , moffStream(UINT64_MAX / 2) 70 , mfStopReading(false) 69 71 { 70 72 } … … 98 100 IMachine *mpMachine; 99 101 void *mpvVMCallbackTask; 102 PRTTCPSERVER mhServer; 100 103 int mRc; 101 104 … … 104 107 , mpMachine(pMachine) 105 108 , mpvVMCallbackTask(NULL) 109 , mhServer(NULL) 106 110 , mRc(VINF_SUCCESS) 107 111 { … … 164 168 if (RT_FAILURE(rc)) 165 169 LogRel(("Migration: RTTcpWrite(,ACK,) -> %Rrc\n", rc)); 170 RTTcpFlush(pState->mhSocket); 166 171 return rc; 167 172 } … … 173 178 if (RT_FAILURE(rc)) 174 179 LogRel(("Migration: RTTcpWrite(,NACK,) -> %Rrc\n", rc)); 180 RTTcpFlush(pState->mhSocket); 175 181 return rc; 176 182 } … … 182 188 * @returns S_OK on ACK, E_FAIL+setError() on failure or NACK. 183 189 * @param pState The live migration source state. 190 * @param pszNAckMsg Optional NACK message. 184 191 * 185 192 * @remarks the setError laziness forces this to be a Console member. 186 193 */ 187 194 HRESULT 188 Console::migrationSrcReadACK(MigrationStateSrc *pState )195 Console::migrationSrcReadACK(MigrationStateSrc *pState, const char *pszNAckMsg /*= NULL*/) 189 196 { 190 197 char szMsg[128]; … … 192 199 if (RT_FAILURE(vrc)) 193 200 return setError(E_FAIL, tr("Failed reading ACK: %Rrc"), vrc); 194 if (strcmp(szMsg, "ACK \n"))195 { 196 if ( strcmp(szMsg, "NACK\n"))197 return setError(E_FAIL, "NACK");201 if (strcmp(szMsg, "ACK")) 202 { 203 if (!strcmp(szMsg, "NACK")) 204 return setError(E_FAIL, pszNAckMsg ? pszNAckMsg : "NACK"); 198 205 return setError(E_FAIL, tr("Expected ACK or NACK, got '%s'"), szMsg); 199 206 } … … 246 253 { 247 254 MigrationState *pState = (MigrationState *)pvUser; 248 int rc = RTTcpRead(pState->mhSocket, pvBuf, cbToRead, pcbRead); 249 if (RT_SUCCESS(rc)) 250 { 251 pState->moffStream += pcbRead ? *pcbRead : cbToRead; 252 return VINF_SUCCESS; 253 } 254 return rc; 255 256 for (;;) 257 { 258 int rc = RTTcpSelectOne(pState->mhSocket, 30); /** @todo fix this polling mess. */ 259 if (RT_SUCCESS(rc)) 260 { 261 rc = RTTcpRead(pState->mhSocket, pvBuf, cbToRead, pcbRead); 262 if (RT_FAILURE(rc)) 263 return rc; 264 pState->moffStream += pcbRead ? *pcbRead : cbToRead; 265 return VINF_SUCCESS; 266 } 267 if (rc != VERR_TIMEOUT) 268 return rc; 269 if (pState->mfStopReading) 270 return VERR_EOF; 271 } 255 272 } 256 273 … … 289 306 static DECLCALLBACK(int) migrationTcpOpClose(void *pvUser) 290 307 { 308 MigrationState *pState = (MigrationState *)pvUser; 309 ASMAtomicWriteBool(&pState->mfStopReading, true); 291 310 return VINF_SUCCESS; 292 311 } … … 336 355 { AutoWriteLock autoLock(); } 337 356 357 BOOL fCanceled = TRUE; 358 HRESULT hrc = pState->mptrProgress->COMGETTER(Canceled)(&fCanceled); 359 if (FAILED(hrc)) 360 return hrc; 361 if (fCanceled) 362 return setError(E_FAIL, tr("canceled")); 363 338 364 /* 339 365 * Try connect to the destination machine. … … 341 367 */ 342 368 int vrc = RTTcpClientConnect(pState->mstrHostname.c_str(), pState->muPort, &pState->mhSocket); 343 if (RT_ SUCCESS(vrc))369 if (RT_FAILURE(vrc)) 344 370 return setError(E_FAIL, tr("Failed to connect to port %u on '%s': %Rrc"), 345 371 pState->muPort, pState->mstrHostname.c_str(), vrc); … … 360 386 361 387 /* ACK */ 362 HRESULT hrc = migrationSrcReadACK(pState);388 hrc = migrationSrcReadACK(pState, tr("Invalid password")); 363 389 if (FAILED(hrc)) 364 390 return hrc; … … 407 433 HRESULT hrc = pState->mptrConsole->migrationSrc(pState); 408 434 pState->mptrProgress->notifyComplete(hrc); 435 436 if ( FAILED(hrc) 437 && pState->mptrConsole->mMachineState == MachineState_Saving) 438 { 439 VMSTATE enmVMState = VMR3GetState(pState->mpVM); 440 switch (enmVMState) 441 { 442 case VMSTATE_RUNNING: 443 case VMSTATE_RUNNING_LS: 444 case VMSTATE_DEBUGGING: 445 case VMSTATE_DEBUGGING_LS: 446 case VMSTATE_POWERING_OFF: 447 case VMSTATE_POWERING_OFF_LS: 448 case VMSTATE_RESETTING: 449 case VMSTATE_RESETTING_LS: 450 pState->mptrConsole->setMachineState(MachineState_Running); 451 break; 452 case VMSTATE_GURU_MEDITATION: 453 case VMSTATE_GURU_MEDITATION_LS: 454 pState->mptrConsole->setMachineState(MachineState_Stuck); 455 break; 456 default: 457 AssertMsgFailed(("%s\n", VMR3GetStateName(enmVMState))); 458 case VMSTATE_SUSPENDED: 459 case VMSTATE_SUSPENDED_LS: 460 case VMSTATE_SUSPENDING: 461 case VMSTATE_SUSPENDING_LS: 462 case VMSTATE_SUSPENDING_EXT_LS: 463 pState->mptrConsole->setMachineState(MachineState_Paused); 464 break; 465 } 466 } 409 467 410 468 if (pState->mhSocket != NIL_RTSOCKET) … … 480 538 pState->mptrProgress = ptrMigrateProgress; 481 539 482 int vrc = RTThreadCreate(NULL, Console::migrationSrcThreadWrapper, pState, 0 /*cbStack*/,540 int vrc = RTThreadCreate(NULL, Console::migrationSrcThreadWrapper, (void *)pState, 0 /*cbStack*/, 483 541 RTTHREADTYPE_EMULATION, 0 /*fFlags*/, "Migrate"); 484 542 if (RT_SUCCESS(vrc)) 543 { 544 hrc = setMachineState(MachineState_Saving); 545 if (SUCCEEDED(hrc)) 546 ptrMigrateProgress.queryInterfaceTo(aProgress); 547 else 548 ptrMigrateProgress->Cancel(); 549 } 550 else 551 { 485 552 delete pState; 486 487 return E_FAIL; 553 hrc = setError(E_FAIL, tr("RTThreadCreate -> %Rrc"), vrc); 554 } 555 556 return hrc; 488 557 } 489 558 … … 496 565 * @param pVM The VM handle 497 566 * @param pMachine The IMachine for the virtual machine. 567 * @param fStartPaused Whether to start it in the Paused (true) or 568 * Running (false) state, 498 569 * @param pvVMCallbackTask The callback task pointer for 499 570 * stateProgressCallback(). 500 571 */ 501 572 int 502 Console::migrationDst(PVM pVM, IMachine *pMachine, void *pvVMCallbackTask)573 Console::migrationDst(PVM pVM, IMachine *pMachine, bool fStartPaused, void *pvVMCallbackTask) 503 574 { 504 575 /* … … 515 586 return VERR_GENERAL_FAILURE; 516 587 Utf8Str strPassword(bstrPassword); 588 strPassword.append('\n'); /* To simplify password checking. */ 517 589 518 590 Utf8Str strBind(""); 519 591 /** @todo Add a bind address property. */ 520 592 const char *pszBindAddress = strBind.isEmpty() ? NULL : strBind.c_str(); 593 521 594 522 595 /* … … 563 636 */ 564 637 MigrationStateDst State(this, pVM, pMachine); 565 State.mstrPassword = strPassword; 638 State.mstrPassword = strPassword; 639 State.mhServer = hServer; 640 State.mpvVMCallbackTask = pvVMCallbackTask; 566 641 567 642 vrc = RTTcpServerListen(hServer, Console::migrationDstServeConnection, &State); 568 643 if (vrc == VERR_TCP_SERVER_STOP) 569 644 vrc = State.mRc; 570 if (RT_FAILURE(vrc)) 645 if (RT_SUCCESS(vrc)) 646 { 647 if (fStartPaused) 648 setMachineState(MachineState_Paused); 649 else 650 vrc = VMR3Resume(pVM); 651 } 652 else 653 { 571 654 LogRel(("Migration: RTTcpServerListen -> %Rrc\n", vrc)); 655 } 572 656 } 573 657 … … 586 670 Console::migrationDstServeConnection(RTSOCKET Sock, void *pvUser) 587 671 { 588 MigrationStateDst *pState = (MigrationStateDst *)pvUser; 672 MigrationStateDst *pState = (MigrationStateDst *)pvUser; 673 pState->mhSocket = Sock; 589 674 590 675 /* … … 603 688 * this is the last connection attempt). 604 689 */ 605 pState->mstrPassword.append('\n');606 690 const char *pszPassword = pState->mstrPassword.c_str(); 607 691 unsigned off = 0; … … 625 709 if (RT_FAILURE(vrc)) 626 710 return vrc; 627 RTTcpServerShutdown( (PRTTCPSERVER)pvUser);711 RTTcpServerShutdown(pState->mhServer); 628 712 629 713 /* 630 714 * Command processing loop. 631 715 */ 632 pState->mhSocket = Sock;633 716 for (;;) 634 717 { … … 671 754 } 672 755 } 756 673 757 pState->mhSocket = NIL_RTSOCKET; 674 675 758 return VERR_TCP_SERVER_STOP; 676 759 } -
trunk/src/VBox/Main/ConsoleImpl.cpp
r23664 r23669 4614 4614 } 4615 4615 4616 /* test and clear the LiveMigrationTarget property */ 4617 BOOL fLiveMigrationTarget; 4618 rc = mMachine->COMGETTER(LiveMigrationTarget)(&fLiveMigrationTarget); 4619 CheckComRCReturnRC(rc); 4620 if (fLiveMigrationTarget) 4621 { 4622 rc = mMachine->COMSETTER(LiveMigrationTarget)(FALSE); 4623 CheckComRCReturnRC(rc); 4624 } 4625 4616 4626 /* create a progress object to track progress of this operation */ 4617 4627 ComObjPtr<Progress> powerupProgress; … … 4620 4630 if (mMachineState == MachineState_Saved) 4621 4631 progressDesc = tr("Restoring virtual machine"); 4632 else if (fLiveMigrationTarget) 4633 progressDesc = tr("Migrating virtual machine"); 4622 4634 else 4623 4635 progressDesc = tr("Starting virtual machine"); … … 4638 4650 if (mMachineState == MachineState_Saved) 4639 4651 task->mSavedStateFile = savedStateFile; 4640 4641 /* test and clear the LiveMigrationTarget property */ 4642 rc = mMachine->COMGETTER(LiveMigrationTarget)(&task->mLiveMigrationTarget); 4643 CheckComRCReturnRC(rc); 4644 if (task->mLiveMigrationTarget) 4645 { 4646 rc = mMachine->COMSETTER(LiveMigrationTarget)(FALSE); 4647 CheckComRCReturnRC(rc); 4648 } 4652 task->mLiveMigrationTarget = fLiveMigrationTarget; 4649 4653 4650 4654 /* Reset differencing hard disks for which autoReset is true */ … … 4726 4730 * any error reporting and appropriate state change! */ 4727 4731 4728 if (mMachineState == MachineState_Saved) 4732 if ( mMachineState == MachineState_Saved 4733 || fLiveMigrationTarget) 4729 4734 setMachineState(MachineState_Restoring); 4730 4735 else … … 6743 6748 } 6744 6749 else if (task->mLiveMigrationTarget) 6750 { 6745 6751 /* -> ConsoleImpl-LiveMigration.cpp */ 6746 vrc = console->migrationDst(pVM, pMachine, static_cast<VMProgressTask*>(task.get())); 6752 vrc = console->migrationDst(pVM, pMachine, task->mStartPaused, 6753 static_cast<VMProgressTask*>(task.get())); 6754 if (RT_FAILURE(vrc)) 6755 VMR3PowerOff(pVM); 6756 } 6747 6757 else if (task->mStartPaused) 6748 6758 /* done */ -
trunk/src/VBox/Main/include/ConsoleImpl.h
r23663 r23669 518 518 static DECLCALLBACK(int) migrationSrcThreadWrapper(RTTHREAD hThread, void *pvUser); 519 519 HRESULT migrationSrc(MigrationStateSrc *pState); 520 HRESULT migrationSrcReadACK(MigrationStateSrc *pState );520 HRESULT migrationSrcReadACK(MigrationStateSrc *pState, const char *pszNAckMsg = NULL); 521 521 HRESULT migrationSrcSubmitCommand(MigrationStateSrc *pState, const char *pszCommand); 522 int migrationDst(PVM pVM, IMachine *pMachine, void *pvVMCallbackTask);522 int migrationDst(PVM pVM, IMachine *pMachine, bool fStartPaused, void *pvVMCallbackTask); 523 523 static DECLCALLBACK(int) migrationDstServeConnection(RTSOCKET Sock, void *pvUser); 524 524 /** @} */
Note:
See TracChangeset
for help on using the changeset viewer.