Changeset 23686 in vbox for trunk/src/VBox/Main
- Timestamp:
- Oct 12, 2009 12:41:10 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ConsoleImpl-LiveMigration.cpp
r23671 r23686 20 20 */ 21 21 22 22 23 /******************************************************************************* 23 24 * Header Files * … … 40 41 41 42 42 43 43 /******************************************************************************* 44 44 * Structures and Typedefs * … … 55 55 PVM mpVM; 56 56 Utf8Str mstrPassword; 57 bool const mfIsSource; 57 58 58 59 /** @name stream stuff … … 60 61 RTSOCKET mhSocket; 61 62 uint64_t moffStream; 63 uint32_t mcbReadBlock; 62 64 bool volatile mfStopReading; 65 bool volatile mfEndOfStream; 66 bool volatile mfIOError; 63 67 /** @} */ 64 68 65 MigrationState(Console *pConsole, PVM pVM )69 MigrationState(Console *pConsole, PVM pVM, bool fIsSource) 66 70 : mptrConsole(pConsole) 67 71 , mpVM(pVM) 72 , mfIsSource(fIsSource) 68 73 , mhSocket(NIL_RTSOCKET) 69 74 , moffStream(UINT64_MAX / 2) 75 , mcbReadBlock(0) 70 76 , mfStopReading(false) 77 , mfEndOfStream(false) 78 , mfIOError(false) 71 79 { 72 80 } … … 85 93 86 94 MigrationStateSrc(Console *pConsole, PVM pVM) 87 : MigrationState(pConsole, pVM )95 : MigrationState(pConsole, pVM, true /*fIsSource*/) 88 96 , muPort(UINT32_MAX) 89 97 { … … 104 112 105 113 MigrationStateDst(Console *pConsole, PVM pVM, IMachine *pMachine) 106 : MigrationState(pConsole, pVM )114 : MigrationState(pConsole, pVM, false /*fIsSource*/) 107 115 , mpMachine(pMachine) 108 116 , mpvVMCallbackTask(NULL) … … 113 121 }; 114 122 123 124 /** 125 * TCP stream header. 126 * 127 * This is an extra layer for fixing the problem with figuring out when the SSM 128 * stream ends. 129 */ 130 typedef struct MIGRATIONTCPHDR 131 { 132 /** Magic value. */ 133 uint32_t u32Magic; 134 /** The size of the data block following this header. 135 * 0 indicates the end of the stream. */ 136 uint32_t cb; 137 } MIGRATIONTCPHDR; 138 /** Magic value for MIGRATIONTCPHDR::u32Magic. (Egberto Gismonti Amin) */ 139 #define MIGRATIONTCPHDR_MAGIC UINT32_C(0x19471205) 140 /** The max block size. */ 141 #define MIGRATIONTCPHDR_MAX_SIZE UINT32_C(0x00fffff8) 115 142 116 143 … … 207 234 return S_OK; 208 235 } 236 209 237 210 238 /** … … 237 265 { 238 266 MigrationState *pState = (MigrationState *)pvUser; 239 int rc = RTTcpWrite(pState->mhSocket, pvBuf, cbToWrite); 240 if (RT_SUCCESS(rc)) 241 { 242 pState->moffStream += cbToWrite; 243 return VINF_SUCCESS; 244 } 267 268 AssertReturn(cbToWrite > 0, VINF_SUCCESS); 269 AssertReturn(pState->mfIsSource, VERR_INVALID_HANDLE); 270 271 for (;;) 272 { 273 /* Write block header. */ 274 MIGRATIONTCPHDR Hdr; 275 Hdr.u32Magic = MIGRATIONTCPHDR_MAGIC; 276 Hdr.cb = RT_MIN(cbToWrite, MIGRATIONTCPHDR_MAX_SIZE); 277 int rc = RTTcpWrite(pState->mhSocket, &Hdr, sizeof(Hdr)); 278 if (RT_FAILURE(rc)) 279 { 280 LogRel(("Migration/TCP: Header write error: %Rrc\n", rc)); 281 return rc; 282 } 283 284 /* Write the data. */ 285 rc = RTTcpWrite(pState->mhSocket, pvBuf, Hdr.cb); 286 if (RT_FAILURE(rc)) 287 { 288 LogRel(("Migration/TCP: Data write error: %Rrc (cb=%#x)\n", rc, Hdr.cb)); 289 return rc; 290 } 291 pState->moffStream += Hdr.cb; 292 if (Hdr.cb == cbToWrite) 293 return VINF_SUCCESS; 294 295 /* advance */ 296 cbToWrite -= Hdr.cb; 297 pvBuf = (uint8_t const *)pvBuf + Hdr.cb; 298 } 299 } 300 301 302 /** 303 * Selects and poll for close condition. 304 * 305 * We can use a relatively high poll timeout here since it's only used to get 306 * us out of error paths. In the normal cause of events, we'll get a 307 * end-of-stream header. 308 * 309 * @returns VBox status code. 310 * 311 * @param pState The migration state data. 312 */ 313 static int migrationTcpReadSelect(MigrationState *pState) 314 { 315 int rc; 316 do 317 { 318 rc = RTTcpSelectOne(pState->mhSocket, 1000); 319 if (RT_FAILURE(rc) && rc != VERR_TIMEOUT) 320 { 321 pState->mfIOError = true; 322 LogRel(("Migration/TCP: Header select error: %Rrc\n", rc)); 323 break; 324 } 325 if (pState->mfStopReading) 326 { 327 rc = VERR_EOF; 328 break; 329 } 330 } while (rc == VERR_TIMEOUT); 245 331 return rc; 246 332 } … … 253 339 { 254 340 MigrationState *pState = (MigrationState *)pvUser; 341 AssertReturn(!pState->mfIsSource, VERR_INVALID_HANDLE); 255 342 256 343 for (;;) 257 344 { 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); 345 int rc; 346 347 /* 348 * Check for various conditions and may have been signalled. 349 */ 350 if (pState->mfEndOfStream) 351 return VERR_EOF; 352 if (pState->mfStopReading) 353 return VERR_EOF; 354 if (pState->mfIOError) 355 return VERR_IO_GEN_FAILURE; 356 357 /* 358 * If there is no more data in the current block, read the next 359 * block header. 360 */ 361 if (!pState->mcbReadBlock) 362 { 363 rc = migrationTcpReadSelect(pState); 262 364 if (RT_FAILURE(rc)) 263 365 return rc; 264 pState->moffStream += pcbRead ? *pcbRead : cbToRead; 366 MIGRATIONTCPHDR Hdr; 367 rc = RTTcpRead(pState->mhSocket, &Hdr, sizeof(Hdr), NULL); 368 if (RT_FAILURE(rc)) 369 { 370 pState->mfIOError = true; 371 LogRel(("Migration/TCP: Header read error: %Rrc\n", rc)); 372 return rc; 373 } 374 if ( Hdr.u32Magic != MIGRATIONTCPHDR_MAGIC 375 || Hdr.cb > MIGRATIONTCPHDR_MAX_SIZE) 376 { 377 pState->mfIOError = true; 378 LogRel(("Migration/TCP: Invalid block: u32Magic=%#x cb=%#x\n", Hdr.u32Magic, Hdr.cb)); 379 return VERR_IO_GEN_FAILURE; 380 } 381 382 pState->mcbReadBlock = Hdr.cb; 383 if (!Hdr.cb) 384 { 385 pState->mfEndOfStream = true; 386 return VERR_EOF; 387 } 388 389 if (pState->mfStopReading) 390 return VERR_EOF; 391 } 392 393 /* 394 * Read more data. 395 */ 396 rc = migrationTcpReadSelect(pState); 397 if (RT_FAILURE(rc)) 398 return rc; 399 size_t cb = RT_MIN(pState->mcbReadBlock, cbToRead); 400 rc = RTTcpRead(pState->mhSocket, pvBuf, cb, pcbRead); 401 if (RT_FAILURE(rc)) 402 { 403 pState->mfIOError = true; 404 LogRel(("Migration/TCP: Data read error: %Rrc (cb=%#x)\n", rc, cb)); 405 return rc; 406 } 407 if (pcbRead) 408 { 409 pState->moffStream += *pcbRead; 410 pState->mcbReadBlock -= *pcbRead; 265 411 return VINF_SUCCESS; 266 412 } 267 if (rc != VERR_TIMEOUT) 268 return rc; 269 if (pState->mfStopReading) 270 return VERR_EOF; 413 pState->moffStream += cb; 414 pState->mcbReadBlock -= cb; 415 if (cbToRead == cb) 416 return VINF_SUCCESS; 417 418 /* Advance to the next block. */ 419 cbToRead -= cb; 420 pvBuf = (uint8_t *)pvBuf + cb; 271 421 } 272 422 } … … 307 457 { 308 458 MigrationState *pState = (MigrationState *)pvUser; 309 ASMAtomicWriteBool(&pState->mfStopReading, true); 459 460 if (pState->mfIsSource) 461 { 462 MIGRATIONTCPHDR EofHdr = { MIGRATIONTCPHDR_MAGIC, 0 }; 463 int rc = RTTcpWrite(pState->mhSocket, &EofHdr, sizeof(EofHdr)); 464 if (RT_FAILURE(rc)) 465 { 466 LogRel(("Migration/TCP: EOF Header write error: %Rrc\n", rc)); 467 return rc; 468 } 469 } 470 else 471 { 472 ASMAtomicWriteBool(&pState->mfStopReading, true); 473 RTTcpFlush(pState->mhSocket); 474 } 475 310 476 return VINF_SUCCESS; 311 477 }
Note:
See TracChangeset
for help on using the changeset viewer.