Changeset 23663 in vbox for trunk/src/VBox/Main
- Timestamp:
- Oct 9, 2009 6:14:30 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 53376
- Location:
- trunk/src/VBox/Main
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ConsoleImpl-LiveMigration.cpp
r23633 r23663 24 24 *******************************************************************************/ 25 25 #include "ConsoleImpl.h" 26 #include "Global.h" 26 27 #include "Logging.h" 28 #include "ProgressImpl.h" 27 29 28 30 #include <iprt/err.h> … … 43 45 *******************************************************************************/ 44 46 /** 45 * Argument package for Console::migrationServeConnection. 46 */ 47 typedef struct MIGRATIONSTATE 48 { 49 Console *pConsole; 50 IMachine *pMachine; 51 PVM pVM; 52 const char *pszPassword; 53 void *pvVMCallbackTask; 54 RTSOCKET hSocket; 55 uint64_t offStream; 56 int rc; 57 } MIGRATIONSTATE; 58 typedef MIGRATIONSTATE *PMIGRATIONSTATE; 47 * Base class for the migration state. 48 * 49 * These classes are used as advanced structs, not as proper classes. 50 */ 51 class MigrationState 52 { 53 public: 54 ComPtr<Console> mptrConsole; 55 PVM mpVM; 56 Utf8Str mstrPassword; 57 58 /** @name stream stuff 59 * @{ */ 60 RTSOCKET mhSocket; 61 uint64_t moffStream; 62 /** @} */ 63 64 MigrationState(Console *pConsole, PVM pVM) 65 : mptrConsole(pConsole) 66 , mpVM(pVM) 67 , mhSocket(NIL_RTSOCKET) 68 , moffStream(UINT64_MAX / 2) 69 { 70 } 71 }; 72 73 74 /** 75 * Migration state used by the source side. 76 */ 77 class MigrationStateSrc : public MigrationState 78 { 79 public: 80 ComPtr<Progress> mptrProgress; 81 Utf8Str mstrHostname; 82 uint32_t muPort; 83 84 MigrationStateSrc(Console *pConsole, PVM pVM) 85 : MigrationState(pConsole, pVM) 86 , muPort(UINT32_MAX) 87 { 88 } 89 }; 90 91 92 /** 93 * Migration state used by the destiation side. 94 */ 95 class MigrationStateDst : public MigrationState 96 { 97 public: 98 IMachine *mpMachine; 99 void *mpvVMCallbackTask; 100 int mRc; 101 102 MigrationStateDst(Console *pConsole, PVM pVM, IMachine *pMachine) 103 : MigrationState(pConsole, pVM) 104 , mpMachine(pMachine) 105 , mpvVMCallbackTask(NULL) 106 , mRc(VINF_SUCCESS) 107 { 108 } 109 }; 110 59 111 60 112 … … 66 118 67 119 /** 120 * Reads a string from the socket. 121 * 122 * @returns VBox status code. 123 * 124 * @param pState The live migration state structure. 125 * @param pszBuf The output buffer. 126 * @param cchBuf The size of the output buffer. 127 * 128 */ 129 static int migrationTcpReadLine(MigrationState *pState, char *pszBuf, size_t cchBuf) 130 { 131 char *pszStart = pszBuf; 132 RTSOCKET Sock = pState->mhSocket; 133 134 AssertReturn(cchBuf > 1, VERR_INTERNAL_ERROR); 135 136 /* dead simple (stupid) approach. */ 137 for (;;) 138 { 139 char ch; 140 int rc = RTTcpRead(Sock, &ch, sizeof(ch), NULL); 141 if (RT_FAILURE(rc)) 142 { 143 LogRel(("Migration: RTTcpRead -> %Rrc while reading string ('%s')\n", rc, pszStart)); 144 return rc; 145 } 146 if ( ch == '\n' 147 || ch == '\0') 148 return VINF_SUCCESS; 149 if (cchBuf <= 1) 150 { 151 LogRel(("Migration: String buffer overflow: '%s'\n", pszStart)); 152 return VERR_BUFFER_OVERFLOW; 153 } 154 *pszBuf++ = ch; 155 *pszBuf = '\0'; 156 cchBuf--; 157 } 158 } 159 160 161 static int migrationTcpWriteACK(MigrationState *pState) 162 { 163 int rc = RTTcpWrite(pState->mhSocket, "ACK\n", sizeof("ACK\n") - 1); 164 if (RT_FAILURE(rc)) 165 LogRel(("Migration: RTTcpWrite(,ACK,) -> %Rrc\n", rc)); 166 return rc; 167 } 168 169 170 static int migrationTcpWriteNACK(MigrationState *pState) 171 { 172 int rc = RTTcpWrite(pState->mhSocket, "NACK\n", sizeof("NACK\n") - 1); 173 if (RT_FAILURE(rc)) 174 LogRel(("Migration: RTTcpWrite(,NACK,) -> %Rrc\n", rc)); 175 return rc; 176 } 177 178 179 /** 180 * Reads an ACK or NACK. 181 * 182 * @returns S_OK on ACK, E_FAIL+setError() on failure or NACK. 183 * @param pState The live migration source state. 184 * 185 * @remarks the setError laziness forces this to be a Console member. 186 */ 187 HRESULT 188 Console::migrationSrcReadACK(MigrationStateSrc *pState) 189 { 190 char szMsg[128]; 191 int vrc = migrationTcpReadLine(pState, szMsg, sizeof(szMsg)); 192 if (RT_FAILURE(vrc)) 193 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"); 198 return setError(E_FAIL, tr("Expected ACK or NACK, got '%s'"), szMsg); 199 } 200 return S_OK; 201 } 202 203 /** 204 * Submitts a command to the destination and waits for the ACK. 205 * 206 * @returns S_OK on ACKed command, E_FAIL+setError() on failure. 207 * 208 * @param pState The live migration source state. 209 * @param pszCommand The command. 210 * 211 * @remarks the setError laziness forces this to be a Console member. 212 */ 213 HRESULT 214 Console::migrationSrcSubmitCommand(MigrationStateSrc *pState, const char *pszCommand) 215 { 216 size_t cchCommand = strlen(pszCommand); 217 int vrc = RTTcpWrite(pState->mhSocket, pszCommand, cchCommand); 218 if (RT_SUCCESS(vrc)) 219 vrc = RTTcpWrite(pState->mhSocket, "\n", sizeof("\n") - 1); 220 if (RT_FAILURE(vrc)) 221 return setError(E_FAIL, tr("Failed writing command '%s': %Rrc"), pszCommand, vrc); 222 return migrationSrcReadACK(pState); 223 } 224 225 226 /** 68 227 * @copydoc SSMSTRMOPS::pfnWrite 69 228 */ 70 229 static DECLCALLBACK(int) migrationTcpOpWrite(void *pvUser, uint64_t offStream, const void *pvBuf, size_t cbToWrite) 71 230 { 72 PMIGRATIONSTATE pState = (PMIGRATIONSTATE)pvUser;73 int rc = RTTcpWrite(pState-> hSocket, pvBuf, cbToWrite);231 MigrationState *pState = (MigrationState *)pvUser; 232 int rc = RTTcpWrite(pState->mhSocket, pvBuf, cbToWrite); 74 233 if (RT_SUCCESS(rc)) 75 234 { 76 pState-> offStream += cbToWrite;235 pState->moffStream += cbToWrite; 77 236 return VINF_SUCCESS; 78 237 } … … 86 245 static DECLCALLBACK(int) migrationTcpOpRead(void *pvUser, uint64_t offStream, void *pvBuf, size_t cbToRead, size_t *pcbRead) 87 246 { 88 PMIGRATIONSTATE pState = (PMIGRATIONSTATE)pvUser;89 int rc = RTTcpRead(pState-> hSocket, pvBuf, cbToRead, pcbRead);247 MigrationState *pState = (MigrationState *)pvUser; 248 int rc = RTTcpRead(pState->mhSocket, pvBuf, cbToRead, pcbRead); 90 249 if (RT_SUCCESS(rc)) 91 250 { 92 pState-> offStream += pcbRead ? *pcbRead : cbToRead;251 pState->moffStream += pcbRead ? *pcbRead : cbToRead; 93 252 return VINF_SUCCESS; 94 253 } … … 111 270 static DECLCALLBACK(uint64_t) migrationTcpOpTell(void *pvUser) 112 271 { 113 PMIGRATIONSTATE pState = (PMIGRATIONSTATE)pvUser;114 return pState-> offStream;272 MigrationState *pState = (MigrationState *)pvUser; 273 return pState->moffStream; 115 274 } 116 275 … … 161 320 162 321 /** 322 * Do the live migration. 323 * 324 * @returns VBox status code. 325 * @param pState The migration state. 326 */ 327 HRESULT 328 Console::migrationSrc(MigrationStateSrc *pState) 329 { 330 AutoCaller autoCaller(this); 331 CheckComRCReturnRC(autoCaller.rc()); 332 333 /* 334 * Wait for Console::Migrate to change the state. 335 */ 336 { AutoWriteLock autoLock(); } 337 338 /* 339 * Try connect to the destination machine. 340 * (Note. The caller cleans up mhSocket, so we can return without worries.) 341 */ 342 int vrc = RTTcpClientConnect(pState->mstrHostname.c_str(), pState->muPort, &pState->mhSocket); 343 if (RT_SUCCESS(vrc)) 344 return setError(E_FAIL, tr("Failed to connect to port %u on '%s': %Rrc"), 345 pState->muPort, pState->mstrHostname.c_str(), vrc); 346 347 /* Read and check the welcome message. */ 348 char szLine[RT_MAX(128, sizeof(g_szWelcome))]; 349 vrc = RTTcpRead(pState->mhSocket, szLine, sizeof(g_szWelcome) - 1, NULL); 350 if (RT_FAILURE(vrc)) 351 return setError(E_FAIL, tr("Failed to read welcome message: %Rrc"), vrc); 352 if (!strcmp(szLine, g_szWelcome)) 353 return setError(E_FAIL, tr("Unexpected welcome '%s'"), szLine); 354 355 /* password */ 356 pState->mstrPassword.append('\n'); 357 vrc = RTTcpWrite(pState->mhSocket, pState->mstrPassword.c_str(), pState->mstrPassword.length()); 358 if (RT_FAILURE(vrc)) 359 return setError(E_FAIL, tr("Failed to send password: %Rrc"), vrc); 360 361 /* ACK */ 362 HRESULT hrc = migrationSrcReadACK(pState); 363 if (FAILED(hrc)) 364 return hrc; 365 366 /* 367 * Do compatability checks of the VM config and the host hardware. 368 */ 369 /** @todo later */ 370 371 /* 372 * Start loading the state. 373 */ 374 hrc = migrationSrcSubmitCommand(pState, "load"); 375 if (FAILED(hrc)) 376 return hrc; 377 378 void *pvUser = static_cast<void *>(static_cast<MigrationState *>(pState)); 379 vrc = VMR3Migrate(pState->mpVM, &g_migrationTcpOps, pvUser, NULL/** @todo progress*/, pvUser); 380 if (vrc) 381 return setError(E_FAIL, tr("VMR3Migrate -> %Rrc"), vrc); 382 383 hrc = migrationSrcReadACK(pState); 384 if (FAILED(hrc)) 385 return hrc; 386 387 /* 388 * State fun? Automatic power off? 389 */ 390 391 return S_OK; 392 } 393 394 395 /** 396 * Static thread method wrapper. 397 * 398 * @returns VINF_SUCCESS (ignored). 399 * @param hThread The thread. 400 * @param pvUser Pointer to a MigrationStateSrc instance. 401 */ 402 /*static*/ DECLCALLBACK(int) 403 Console::migrationSrcThreadWrapper(RTTHREAD hThread, void *pvUser) 404 { 405 MigrationStateSrc *pState = (MigrationStateSrc *)pvUser; 406 407 HRESULT hrc = pState->mptrConsole->migrationSrc(pState); 408 pState->mptrProgress->notifyComplete(hrc); 409 410 if (pState->mhSocket != NIL_RTSOCKET) 411 { 412 RTTcpClientClose(pState->mhSocket); 413 pState->mhSocket = NIL_RTSOCKET; 414 } 415 delete pState; 416 417 return VINF_SUCCESS; 418 } 419 420 421 /** 163 422 * Start live migration to the specified target. 164 423 * … … 174 433 { 175 434 /* 176 * Validate parameters. 177 */ 178 179 /* 180 * Try change the state, create a progress object and spawn a worker thread. 181 */ 435 * Validate parameters, check+hold object status, write lock the object 436 * and validate the state. 437 */ 438 CheckComArgOutPointerValid(aProgress); 439 CheckComArgStrNotEmptyOrNull(aHostname); 440 CheckComArgNotNull(aHostname); 441 CheckComArgExprMsg(aPort, aPort > 0 && aPort <= 65535, ("is %u", aPort)); 442 443 AutoCaller autoCaller(this); 444 CheckComRCReturnRC(autoCaller.rc()); 445 446 AutoWriteLock autoLock(this); 447 LogFlowThisFunc(("mMachineState=%d\n", mMachineState)); 448 449 switch (mMachineState) 450 { 451 case MachineState_Running: 452 case MachineState_Paused: 453 break; 454 455 default: 456 return setError(VBOX_E_INVALID_VM_STATE, 457 tr("Invalid machine state: %s (must be Running, Paused or Stuck)"), 458 Global::stringifyMachineState(mMachineState)); 459 } 460 461 462 /* 463 * Create a progress object, spawn a worker thread and change the state. 464 * Note! The thread won't start working until we release the lock. 465 */ 466 LogFlowThisFunc(("Initiating LIVE MIGRATION request...\n")); 467 468 ComObjPtr<Progress> ptrMigrateProgress; 469 HRESULT hrc = ptrMigrateProgress.createObject(); 470 CheckComRCReturnRC(hrc); 471 hrc = ptrMigrateProgress->init(static_cast<IConsole *>(this), 472 Bstr(tr("Live Migration")), 473 TRUE /*aCancelable*/); 474 CheckComRCReturnRC(hrc); 475 476 MigrationStateSrc *pState = new MigrationStateSrc(this, mpVM); 477 pState->mstrPassword = aPassword; 478 pState->mstrHostname = aHostname; 479 pState->muPort = aPort; 480 pState->mptrProgress = ptrMigrateProgress; 481 482 int vrc = RTThreadCreate(NULL, Console::migrationSrcThreadWrapper, pState, 0 /*cbStack*/, 483 RTTHREADTYPE_EMULATION, 0 /*fFlags*/, "Migrate"); 484 if (RT_SUCCESS(vrc)) 485 delete pState; 182 486 183 487 return E_FAIL; … … 187 491 /** 188 492 * Creates a TCP server that listens for the source machine and passes control 189 * over to Console::migration ServeConnection().493 * over to Console::migrationDstServeConnection(). 190 494 * 191 495 * @returns VBox status code. … … 196 500 */ 197 501 int 198 Console::migration LoadRemote(PVM pVM, IMachine *pMachine, void *pvVMCallbackTask)502 Console::migrationDst(PVM pVM, IMachine *pMachine, void *pvVMCallbackTask) 199 503 { 200 504 /* … … 211 515 return VERR_GENERAL_FAILURE; 212 516 Utf8Str strPassword(bstrPassword); 213 strPassword.append('\n'); /* always ends with a newline. */214 517 215 518 Utf8Str strBind(""); … … 220 523 * Create the TCP server. 221 524 */ 222 int rc;525 int vrc; 223 526 PRTTCPSERVER hServer; 224 527 if (uPort) 225 rc = RTTcpServerCreateEx(pszBindAddress, uPort, &hServer);528 vrc = RTTcpServerCreateEx(pszBindAddress, uPort, &hServer); 226 529 else 227 530 { … … 229 532 { 230 533 uPort = RTRandU32Ex(cTries >= 8192 ? 49152 : 1024, 65534); 231 rc = RTTcpServerCreateEx(pszBindAddress, uPort, &hServer);232 if ( rc != VERR_NET_ADDRESS_IN_USE)534 vrc = RTTcpServerCreateEx(pszBindAddress, uPort, &hServer); 535 if (vrc != VERR_NET_ADDRESS_IN_USE) 233 536 break; 234 537 } 235 if (RT_SUCCESS( rc))538 if (RT_SUCCESS(vrc)) 236 539 { 237 540 HRESULT hrc = pMachine->COMSETTER(LiveMigrationPort)(uPort); … … 243 546 } 244 547 } 245 if (RT_FAILURE( rc))246 return rc;548 if (RT_FAILURE(vrc)) 549 return vrc; 247 550 248 551 /* … … 250 553 */ 251 554 RTTIMERLR hTimerLR; 252 rc = RTTimerLRCreateEx(&hTimerLR, 0 /*ns*/, RTTIMER_FLAGS_CPU_ANY, migrationTimeout, hServer);253 if (RT_SUCCESS( rc))254 { 255 rc = RTTimerLRStart(hTimerLR, 5*60*UINT64_C(1000000000) /*ns*/);256 if (RT_SUCCESS( rc))555 vrc = RTTimerLRCreateEx(&hTimerLR, 0 /*ns*/, RTTIMER_FLAGS_CPU_ANY, migrationTimeout, hServer); 556 if (RT_SUCCESS(vrc)) 557 { 558 vrc = RTTimerLRStart(hTimerLR, 5*60*UINT64_C(1000000000) /*ns*/); 559 if (RT_SUCCESS(vrc)) 257 560 { 258 561 /* 259 562 * Do the job, when it returns we're done. 260 563 */ 261 MIGRATIONSTATE State; 262 State.pConsole = this; 263 State.pMachine = pMachine; 264 State.pVM = pVM; 265 State.pszPassword = strPassword.c_str(); 266 State.hSocket = NIL_RTSOCKET; 267 State.offStream = UINT64_MAX / 2; 268 State.rc = VINF_SUCCESS; 269 270 rc = RTTcpServerListen(hServer, Console::migrationServeConnection, &State); 271 if (rc == VERR_TCP_SERVER_STOP) 272 rc = State.rc; 273 if (RT_FAILURE(rc)) 274 LogRel(("Migration: RTTcpServerListen -> %Rrc\n", rc)); 564 MigrationStateDst State(this, pVM, pMachine); 565 State.mstrPassword = strPassword; 566 567 vrc = RTTcpServerListen(hServer, Console::migrationDstServeConnection, &State); 568 if (vrc == VERR_TCP_SERVER_STOP) 569 vrc = State.mRc; 570 if (RT_FAILURE(vrc)) 571 LogRel(("Migration: RTTcpServerListen -> %Rrc\n", vrc)); 275 572 } 276 573 … … 279 576 RTTcpServerDestroy(hServer); 280 577 281 return rc; 282 } 283 284 285 /** 286 * Reads a string from the socket. 287 * 288 * @returns VBox status code. 289 * 290 * @param Sock The socket. 291 * @param pszBuf The output buffer. 292 * @param cchBuf The size of the output buffer. 293 * 294 */ 295 static int migrationReadLine(RTSOCKET Sock, char *pszBuf, size_t cchBuf) 296 { 297 char *pszStart = pszBuf; 298 AssertReturn(cchBuf > 1, VERR_INTERNAL_ERROR); 299 300 /* dead simple (stupid) approach. */ 301 for (;;) 302 { 303 char ch; 304 int rc = RTTcpRead(Sock, &ch, sizeof(ch), NULL); 305 if (RT_FAILURE(rc)) 306 { 307 LogRel(("Migration: RTTcpRead -> %Rrc while reading string ('%s')\n", rc, pszStart)); 308 return rc; 309 } 310 if ( ch == '\n' 311 || ch == '\0') 312 return VINF_SUCCESS; 313 if (cchBuf <= 1) 314 { 315 LogRel(("Migration: String buffer overflow: '%s'\n", pszStart)); 316 return VERR_BUFFER_OVERFLOW; 317 } 318 *pszBuf++ = ch; 319 *pszBuf = '\0'; 320 cchBuf--; 321 } 578 return vrc; 322 579 } 323 580 … … 325 582 /** 326 583 * @copydoc FNRTTCPSERVE 327 * VERR_TCP_SERVER_STOP328 584 */ 329 585 /*static*/ DECLCALLBACK(int) 330 Console::migrationServeConnection(RTSOCKET Sock, void *pvUser) 331 { 332 PMIGRATIONSTATE pState = (PMIGRATIONSTATE)pvUser; 333 Console *pConsole = pState->pConsole; 334 IMachine *pMachine = pState->pMachine; 586 Console::migrationDstServeConnection(RTSOCKET Sock, void *pvUser) 587 { 588 MigrationStateDst *pState = (MigrationStateDst *)pvUser; 335 589 336 590 /* 337 591 * Say hello. 338 592 */ 339 int rc = RTTcpWrite(Sock, g_szWelcome, sizeof(g_szWelcome) - 1);340 if (RT_FAILURE( rc))341 { 342 LogRel(("Migration: Failed to write welcome message: %Rrc\n", rc));593 int vrc = RTTcpWrite(Sock, g_szWelcome, sizeof(g_szWelcome) - 1); 594 if (RT_FAILURE(vrc)) 595 { 596 LogRel(("Migration: Failed to write welcome message: %Rrc\n", vrc)); 343 597 return VINF_SUCCESS; 344 598 } 345 599 346 600 /* 347 * Password (includes '\n', see migration LoadRemote). If it's right, tell601 * Password (includes '\n', see migrationDst). If it's right, tell 348 602 * the TCP server to stop listening (frees up host resources and makes sure 349 603 * this is the last connection attempt). 350 604 */ 351 const char *pszPassword = pState->pszPassword; 605 pState->mstrPassword.append('\n'); 606 const char *pszPassword = pState->mstrPassword.c_str(); 352 607 unsigned off = 0; 353 608 while (pszPassword[off]) 354 609 { 355 610 char ch; 356 rc = RTTcpRead(Sock, &ch, sizeof(ch), NULL); 357 if (RT_FAILURE(rc)) 611 vrc = RTTcpRead(Sock, &ch, sizeof(ch), NULL); 612 if ( RT_FAILURE(vrc) 613 || pszPassword[off] != ch) 614 { 615 if (RT_FAILURE(vrc)) 616 LogRel(("Migration: Password read failure (off=%u): %Rrc\n", off, vrc)); 617 else 618 LogRel(("Migration: Invalid password (off=%u)\n", off)); 619 migrationTcpWriteNACK(pState); 620 return VINF_SUCCESS; 621 } 622 off++; 623 } 624 vrc = migrationTcpWriteACK(pState); 625 if (RT_FAILURE(vrc)) 626 return vrc; 627 RTTcpServerShutdown((PRTTCPSERVER)pvUser); 628 629 /* 630 * Command processing loop. 631 */ 632 pState->mhSocket = Sock; 633 for (;;) 634 { 635 char szCmd[128]; 636 vrc = migrationTcpReadLine(pState, szCmd, sizeof(szCmd)); 637 if (RT_FAILURE(vrc)) 358 638 break; 359 if (pszPassword[off] != ch)360 {361 LogRel(("Migration: Invalid password (off=%u)\n", off));362 return VINF_SUCCESS;363 }364 off++;365 }366 367 RTTcpServerShutdown((PRTTCPSERVER)pvUser);368 369 /*370 * Command processing loop.371 */372 pState->hSocket = Sock;373 for (;;)374 {375 char szCmd[128];376 rc = migrationReadLine(Sock, szCmd, sizeof(szCmd));377 if (RT_FAILURE(rc))378 break;379 639 380 640 if (!strcmp(szCmd, "load")) 381 641 { 382 pState->offStream = 0; 383 rc = VMR3LoadFromStream(pState->pVM, &g_migrationTcpOps, pState, 384 Console::stateProgressCallback, pState->pvVMCallbackTask); 385 if (RT_FAILURE(rc)) 642 vrc = migrationTcpWriteACK(pState); 643 if (RT_FAILURE(vrc)) 644 break; 645 646 pState->moffStream = 0; 647 void *pvUser = static_cast<void *>(static_cast<MigrationState *>(pState)); 648 vrc = VMR3LoadFromStream(pState->mpVM, &g_migrationTcpOps, pvUser, 649 Console::stateProgressCallback, pState->mpvVMCallbackTask); 650 if (RT_FAILURE(vrc)) 386 651 { 387 LogRel(("Migration: VMR3LoadFromStream -> %Rrc\n", rc));652 LogRel(("Migration: VMR3LoadFromStream -> %Rrc\n", vrc)); 388 653 break; 389 654 } 655 656 vrc = migrationTcpWriteACK(pState); 657 if (RT_FAILURE(vrc)) 658 break; 390 659 } 391 660 /** @todo implement config verification and hardware compatability checks. Or 392 661 * maybe leave part of these to the saved state machinery? */ 393 662 else if (!strcmp(szCmd, "done")) 663 { 664 migrationTcpWriteACK(pState); 394 665 break; 666 } 395 667 else 396 668 { … … 399 671 } 400 672 } 401 pState-> hSocket = NIL_RTSOCKET;673 pState->mhSocket = NIL_RTSOCKET; 402 674 403 675 return VERR_TCP_SERVER_STOP; -
trunk/src/VBox/Main/ConsoleImpl.cpp
r23643 r23663 6746 6746 else if (task->mLiveMigrationTarget) 6747 6747 /* -> ConsoleImpl-LiveMigration.cpp */ 6748 vrc = console->migration LoadRemote(pVM, pMachine, static_cast<VMProgressTask*>(task.get()));6748 vrc = console->migrationDst(pVM, pMachine, static_cast<VMProgressTask*>(task.get())); 6749 6749 else if (task->mStartPaused) 6750 6750 /* done */ -
trunk/src/VBox/Main/include/ConsoleImpl.h
r23643 r23663 34 34 class Display; 35 35 class MachineDebugger; 36 class MigrationStateSrc; 36 37 class OUSBDevice; 37 38 class RemoteUSBDevice; … … 515 516 /** @name Live migration support 516 517 * @{ */ 517 int migrationLoadRemote(PVM pVM, IMachine *pMachine, void *pvVMCallbackTask); 518 static DECLCALLBACK(int) migrationServeConnection(RTSOCKET Sock, void *pvUser); 518 static DECLCALLBACK(int) migrationSrcThreadWrapper(RTTHREAD hThread, void *pvUser); 519 HRESULT migrationSrc(MigrationStateSrc *pState); 520 HRESULT migrationSrcReadACK(MigrationStateSrc *pState); 521 HRESULT migrationSrcSubmitCommand(MigrationStateSrc *pState, const char *pszCommand); 522 int migrationDst(PVM pVM, IMachine *pMachine, void *pvVMCallbackTask); 523 static DECLCALLBACK(int) migrationDstServeConnection(RTSOCKET Sock, void *pvUser); 519 524 /** @} */ 520 525
Note:
See TracChangeset
for help on using the changeset viewer.