Changeset 37971 in vbox for trunk/src/VBox/Main
- Timestamp:
- Jul 14, 2011 3:01:07 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 72884
- Location:
- trunk/src/VBox/Main
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/MachineImplCloneVM.h
r37533 r37971 34 34 protected: 35 35 HRESULT run(); 36 HRESULT createDiffHelper(const ComObjPtr<Medium> &pParent, 37 const Utf8Str &strSnapshotFolder, 38 RTCList<ComObjPtr<Medium> > *pNewMedia, 39 ComObjPtr<Medium> *ppDiff); 36 40 void destroy(); 37 41 -
trunk/src/VBox/Main/src-server/MachineImpl.cpp
r37932 r37971 6260 6260 optList = com::SafeArray<CloneOptions_T>(ComSafeArrayInArg(options)).toList(); 6261 6261 6262 AssertReturn(!optList.contains(CloneOptions_Link) , E_NOTIMPL);6262 AssertReturn(!optList.contains(CloneOptions_Link) || (isSnapshotMachine() && mode == CloneMode_MachineState), E_INVALIDARG); 6263 6263 AssertReturn(!(optList.contains(CloneOptions_KeepAllMACs) && optList.contains(CloneOptions_KeepNATMACs)), E_INVALIDARG); 6264 6264 6265 6265 AutoCaller autoCaller(this); 6266 6266 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 6267 6267 6268 6268 6269 MachineCloneVM *pWorker = new MachineCloneVM(this, static_cast<Machine*>(pTarget), mode, optList); … … 9455 9456 /** 9456 9457 * Deletes implicit differencing hard disks created either by 9457 * #createImplicitDiffs() or by #Attach Medium() and rolls back mMediaData.9458 * 9459 * Note that to delete hard disks created by #Attach Medium() this method is9458 * #createImplicitDiffs() or by #AttachDevice() and rolls back mMediaData. 9459 * 9460 * Note that to delete hard disks created by #AttachDevice() this method is 9460 9461 * called from #fixupMedia() when the changes are rolled back. 9461 9462 * -
trunk/src/VBox/Main/src-server/MachineImplCloneVM.cpp
r37905 r37971 36 36 ComPtr<IMedium> pMedium; 37 37 ULONG uWeight; 38 } MEDIUMTASK;38 } MEDIUMTASK; 39 39 40 40 typedef struct … … 42 42 RTCList<MEDIUMTASK> chain; 43 43 bool fCreateDiffs; 44 }MEDIUMTASKCHAIN; 44 bool fAttachLinked; 45 } MEDIUMTASKCHAIN; 45 46 46 47 typedef struct … … 49 50 Utf8Str strSaveStateFile; 50 51 ULONG uWeight; 51 } SAVESTATETASK;52 } SAVESTATETASK; 52 53 53 54 // The private class … … 330 331 if (machine == d->pOldMachineState) 331 332 fCreateDiffs = true; 333 /* If we want to create a linked clone just attach the medium 334 * associated with the snapshot. The rest is taken care of by 335 * attach already, so no need to duplicate this. */ 336 bool fAttachLinked = false; 337 if (d->options.contains(CloneOptions_Link)) 338 fAttachLinked = true; 332 339 SafeIfaceArray<IMediumAttachment> sfaAttachments; 333 340 rc = machine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments)); … … 358 365 MEDIUMTASKCHAIN mtc; 359 366 mtc.fCreateDiffs = fCreateDiffs; 360 while(!pSrcMedium.isNull()) 367 mtc.fAttachLinked = fAttachLinked; 368 369 if (d->mode == CloneMode_MachineState) 361 370 { 362 371 /* Refresh the state so that the file size get read. */ … … 371 380 MEDIUMTASK mt; 372 381 mt.pMedium = pSrcMedium; 373 mt.uWeight = (lSize + _1M - 1) / _1M; 382 if (fAttachLinked) 383 mt.uWeight = 0; /* dummy */ 384 else 385 mt.uWeight = (lSize + _1M - 1) / _1M; 374 386 mtc.chain.append(mt); 375 376 /* Query next parent. */ 377 rc = pSrcMedium->COMGETTER(Parent)(pSrcMedium.asOutParam()); 378 if (FAILED(rc)) throw rc; 379 }; 380 /* Currently the creation of diff images involves reading at least 381 * the biggest parent in the previous chain. So even if the new 382 * diff image is small in size, it could need some time to create 383 * it. Adding the biggest size in the chain should balance this a 384 * little bit more, i.e. the weight is the sum of the data which 385 * needs to be read and written. */ 386 uint64_t uMaxSize = 0; 387 for (size_t e = mtc.chain.size(); e > 0; --e) 387 } 388 else 388 389 { 389 MEDIUMTASK &mt = mtc.chain.at(e - 1); 390 mt.uWeight += uMaxSize; 391 392 /* Calculate progress data */ 390 /** @todo r=klaus this puts way too many images in the list 391 * when cloning a snapshot (sub)tree, which means that more 392 * images are cloned than necessary. It is just the easiest 393 * way to get a working VM, as getting the image 394 * parent/child relationships right for only the bare 395 * minimum cloning is rather tricky. */ 396 while (!pSrcMedium.isNull()) 397 { 398 /* Refresh the state so that the file size get read. */ 399 MediumState_T e; 400 rc = pSrcMedium->RefreshState(&e); 401 if (FAILED(rc)) throw rc; 402 LONG64 lSize; 403 rc = pSrcMedium->COMGETTER(Size)(&lSize); 404 if (FAILED(rc)) throw rc; 405 406 /* Save the current medium, for later cloning. */ 407 MEDIUMTASK mt; 408 mt.pMedium = pSrcMedium; 409 mt.uWeight = (lSize + _1M - 1) / _1M; 410 mtc.chain.append(mt); 411 412 /* Query next parent. */ 413 rc = pSrcMedium->COMGETTER(Parent)(pSrcMedium.asOutParam()); 414 if (FAILED(rc)) throw rc; 415 } 416 } 417 418 if (fAttachLinked) 419 { 420 /* Implicit diff creation as part of attach is a pretty cheap 421 * operation, and does only need one operation per attachment. */ 393 422 ++uCount; 394 uTotalWeight += mt.uWeight; 395 396 /* Save the max size for better weighting of diff image 397 * creation. */ 398 uMaxSize = RT_MAX(uMaxSize, mt.uWeight); 423 uTotalWeight += 1; /* 1MB per attachment */ 424 } 425 else 426 { 427 /* Currently the copying of diff images involves reading at least 428 * the biggest parent in the previous chain. So even if the new 429 * diff image is small in size, it could need some time to create 430 * it. Adding the biggest size in the chain should balance this a 431 * little bit more, i.e. the weight is the sum of the data which 432 * needs to be read and written. */ 433 uint64_t uMaxSize = 0; 434 for (size_t e = mtc.chain.size(); e > 0; --e) 435 { 436 MEDIUMTASK &mt = mtc.chain.at(e - 1); 437 mt.uWeight += uMaxSize; 438 439 /* Calculate progress data */ 440 ++uCount; 441 uTotalWeight += mt.uWeight; 442 443 /* Save the max size for better weighting of diff image 444 * creation. */ 445 uMaxSize = RT_MAX(uMaxSize, mt.uWeight); 446 } 399 447 } 400 448 d->llMedias.append(mtc); … … 472 520 strTrgMachineFolder.stripFilename(); 473 521 474 RTCList< ComObjPtr<Medium> > newMedias;/* All created images */522 RTCList<ComObjPtr<Medium> > newMedia; /* All created images */ 475 523 RTCList<Utf8Str> newFiles; /* All extra created files (save states, ...) */ 476 524 try … … 499 547 trgMCF.llFirstSnapshot.clear(); 500 548 trgMCF.uuidCurrentSnapshot.clear(); 501 } else502 if ( d->mode == CloneMode_MachineAndChildStates503 && !sn.uuid.isEmpty())549 } 550 else if ( d->mode == CloneMode_MachineAndChildStates 551 && !sn.uuid.isEmpty()) 504 552 { 505 553 /* Copy the snapshot data to the current machine. */ … … 569 617 if (FAILED(rc)) throw rc; 570 618 571 /* Is a clone already there? */ 572 TStrMediumMap::iterator it = map.find(Utf8Str(bstrSrcId)); 573 if (it != map.end()) 574 pNewParent = it->second; 619 if (mtc.fAttachLinked) 620 { 621 IMedium *pTmp = pMedium; 622 ComObjPtr<Medium> pLMedium = static_cast<Medium*>(pTmp); 623 if (pLMedium.isNull()) 624 throw E_POINTER; 625 if (pLMedium->isReadOnly()) 626 { 627 ComObjPtr<Medium> pDiff; 628 /* create the diff under the snapshot medium */ 629 rc = createDiffHelper(pLMedium, strTrgSnapshotFolder, 630 &newMedia, &pDiff); 631 if (FAILED(rc)) throw rc; 632 map.insert(TStrMediumPair(Utf8Str(bstrSrcId), pDiff)); 633 /* diff image has to be used... */ 634 pNewParent = pDiff; 635 } 636 else 637 { 638 /* Attach the medium directly, as its type is not 639 * subject to diff creation. */ 640 newMedia.append(pLMedium); 641 map.insert(TStrMediumPair(Utf8Str(bstrSrcId), pLMedium)); 642 pNewParent = pLMedium; 643 } 644 } 575 645 else 576 646 { 577 ComPtr<IMediumFormat> pSrcFormat; 578 rc = pMedium->COMGETTER(MediumFormat)(pSrcFormat.asOutParam()); 579 ULONG uSrcCaps = 0; 580 rc = pSrcFormat->COMGETTER(Capabilities)(&uSrcCaps); 581 if (FAILED(rc)) throw rc; 582 583 /* Default format? */ 584 Utf8Str strDefaultFormat; 585 p->mParent->getDefaultHardDiskFormat(strDefaultFormat); 586 Bstr bstrSrcFormat(strDefaultFormat); 587 ULONG srcVar = MediumVariant_Standard; 588 /* Is the source file based? */ 589 if ((uSrcCaps & MediumFormatCapabilities_File) == MediumFormatCapabilities_File) 647 /* Is a clone already there? */ 648 TStrMediumMap::iterator it = map.find(Utf8Str(bstrSrcId)); 649 if (it != map.end()) 650 pNewParent = it->second; 651 else 590 652 { 591 /* Yes, just use the source format. Otherwise the defaults 592 * will be used. */ 593 rc = pMedium->COMGETTER(Format)(bstrSrcFormat.asOutParam()); 594 if (FAILED(rc)) throw rc; 595 rc = pMedium->COMGETTER(Variant)(&srcVar); 596 if (FAILED(rc)) throw rc; 653 ComPtr<IMediumFormat> pSrcFormat; 654 rc = pMedium->COMGETTER(MediumFormat)(pSrcFormat.asOutParam()); 655 ULONG uSrcCaps = 0; 656 rc = pSrcFormat->COMGETTER(Capabilities)(&uSrcCaps); 657 if (FAILED(rc)) throw rc; 658 659 /* Default format? */ 660 Utf8Str strDefaultFormat; 661 p->mParent->getDefaultHardDiskFormat(strDefaultFormat); 662 Bstr bstrSrcFormat(strDefaultFormat); 663 ULONG srcVar = MediumVariant_Standard; 664 /* Is the source file based? */ 665 if ((uSrcCaps & MediumFormatCapabilities_File) == MediumFormatCapabilities_File) 666 { 667 /* Yes, just use the source format. Otherwise the defaults 668 * will be used. */ 669 rc = pMedium->COMGETTER(Format)(bstrSrcFormat.asOutParam()); 670 if (FAILED(rc)) throw rc; 671 rc = pMedium->COMGETTER(Variant)(&srcVar); 672 if (FAILED(rc)) throw rc; 673 } 674 675 Guid newId; 676 newId.create(); 677 Utf8Str strNewName(bstrSrcName); 678 if (!fKeepDiskNames) 679 { 680 /* If the old disk name was in {uuid} format we also 681 * want the new name in this format, but with the 682 * updated id of course. If the old disk was called 683 * like the VM name, we change it to the new VM name. 684 * For all other disks we rename them with this 685 * template: "new name-disk1.vdi". */ 686 Utf8Str strSrcTest = Utf8Str(bstrSrcName).stripExt(); 687 if (strSrcTest == strOldVMName) 688 strNewName = Utf8StrFmt("%s%s", trgMCF.machineUserData.strName.c_str(), RTPathExt(Utf8Str(bstrSrcName).c_str())); 689 else if ( strSrcTest.startsWith("{") 690 && strSrcTest.endsWith("}")) 691 { 692 strSrcTest = strSrcTest.substr(1, strSrcTest.length() - 2); 693 if (isValidGuid(strSrcTest)) 694 strNewName = Utf8StrFmt("%s%s", newId.toStringCurly().c_str(), RTPathExt(strNewName.c_str())); 695 } 696 else 697 strNewName = Utf8StrFmt("%s-disk%d%s", trgMCF.machineUserData.strName.c_str(), ++cDisks, RTPathExt(Utf8Str(bstrSrcName).c_str())); 698 } 699 700 /* Check if this medium comes from the snapshot folder, if 701 * so, put it there in the cloned machine as well. 702 * Otherwise it goes to the machine folder. */ 703 Bstr bstrSrcPath; 704 Utf8Str strFile = Utf8StrFmt("%s%c%s", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, strNewName.c_str()); 705 rc = pMedium->COMGETTER(Location)(bstrSrcPath.asOutParam()); 706 if (FAILED(rc)) throw rc; 707 if ( !bstrSrcPath.isEmpty() 708 && RTPathStartsWith(Utf8Str(bstrSrcPath).c_str(), Utf8Str(bstrSrcSnapshotFolder).c_str())) 709 strFile = Utf8StrFmt("%s%c%s", strTrgSnapshotFolder.c_str(), RTPATH_DELIMITER, strNewName.c_str()); 710 else 711 strFile = Utf8StrFmt("%s%c%s", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, strNewName.c_str()); 712 713 /* Start creating the clone. */ 714 ComObjPtr<Medium> pTarget; 715 rc = pTarget.createObject(); 716 if (FAILED(rc)) throw rc; 717 718 rc = pTarget->init(p->mParent, 719 Utf8Str(bstrSrcFormat), 720 strFile, 721 Guid::Empty, /* empty media registry */ 722 NULL /* llRegistriesThatNeedSaving */); 723 if (FAILED(rc)) throw rc; 724 725 /* Update the new uuid. */ 726 pTarget->updateId(newId); 727 728 srcLock.release(); 729 /* Do the disk cloning. */ 730 ComPtr<IProgress> progress2; 731 rc = pMedium->CloneTo(pTarget, 732 srcVar, 733 pNewParent, 734 progress2.asOutParam()); 735 if (FAILED(rc)) throw rc; 736 737 /* Wait until the async process has finished. */ 738 rc = d->pProgress->WaitForAsyncProgressCompletion(progress2); 739 srcLock.acquire(); 740 if (FAILED(rc)) throw rc; 741 742 /* Check the result of the async process. */ 743 LONG iRc; 744 rc = progress2->COMGETTER(ResultCode)(&iRc); 745 if (FAILED(rc)) throw rc; 746 if (FAILED(iRc)) 747 { 748 /* If the thread of the progress object has an error, then 749 * retrieve the error info from there, or it'll be lost. */ 750 ProgressErrorInfo info(progress2); 751 throw p->setError(iRc, Utf8Str(info.getText()).c_str()); 752 } 753 /* Remember created medium. */ 754 newMedia.append(pTarget); 755 /* Get the medium type from the source and set it to the 756 * new medium. */ 757 MediumType_T type; 758 rc = pMedium->COMGETTER(Type)(&type); 759 if (FAILED(rc)) throw rc; 760 rc = pTarget->COMSETTER(Type)(type); 761 if (FAILED(rc)) throw rc; 762 map.insert(TStrMediumPair(Utf8Str(bstrSrcId), pTarget)); 763 /* register the new harddisk */ 764 { 765 AutoWriteLock tlock(p->mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 766 rc = p->mParent->registerHardDisk(pTarget, NULL /* pllRegistriesThatNeedSaving */); 767 if (FAILED(rc)) throw rc; 768 } 769 /* This medium becomes the parent of the next medium in the 770 * chain. */ 771 pNewParent = pTarget; 597 772 } 598 599 Guid newId;600 newId.create();601 Utf8Str strNewName(bstrSrcName);602 if (!fKeepDiskNames)603 {604 /* If the old disk name was in {uuid} format we also605 * want the new name in this format, but with the606 * updated id of course. If the old disk was called607 * like the VM name, we change it to the new VM name.608 * For all other disks we rename them with this609 * template: "new name-disk1.vdi". */610 Utf8Str strSrcTest = Utf8Str(bstrSrcName).stripExt();611 if (strSrcTest == strOldVMName)612 strNewName = Utf8StrFmt("%s%s", trgMCF.machineUserData.strName.c_str(), RTPathExt(Utf8Str(bstrSrcName).c_str()));613 else614 if (strSrcTest.startsWith("{") &&615 strSrcTest.endsWith("}"))616 {617 strSrcTest = strSrcTest.substr(1, strSrcTest.length() - 2);618 if (isValidGuid(strSrcTest))619 strNewName = Utf8StrFmt("%s%s", newId.toStringCurly().c_str(), RTPathExt(strNewName.c_str()));620 }621 else622 strNewName = Utf8StrFmt("%s-disk%d%s", trgMCF.machineUserData.strName.c_str(), ++cDisks, RTPathExt(Utf8Str(bstrSrcName).c_str()));623 }624 625 /* Check if this medium comes from the snapshot folder, if626 * so, put it there in the cloned machine as well.627 * Otherwise it goes to the machine folder. */628 Bstr bstrSrcPath;629 Utf8Str strFile = Utf8StrFmt("%s%c%s", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, strNewName.c_str());630 rc = pMedium->COMGETTER(Location)(bstrSrcPath.asOutParam());631 if (FAILED(rc)) throw rc;632 if ( !bstrSrcPath.isEmpty()633 && RTPathStartsWith(Utf8Str(bstrSrcPath).c_str(), Utf8Str(bstrSrcSnapshotFolder).c_str()))634 strFile = Utf8StrFmt("%s%c%s", strTrgSnapshotFolder.c_str(), RTPATH_DELIMITER, strNewName.c_str());635 else636 strFile = Utf8StrFmt("%s%c%s", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, strNewName.c_str());637 638 /* Start creating the clone. */639 ComObjPtr<Medium> pTarget;640 rc = pTarget.createObject();641 if (FAILED(rc)) throw rc;642 643 rc = pTarget->init(p->mParent,644 Utf8Str(bstrSrcFormat),645 strFile,646 Guid::Empty, /* empty media registry */647 NULL /* llRegistriesThatNeedSaving */);648 if (FAILED(rc)) throw rc;649 650 /* Update the new uuid. */651 pTarget->updateId(newId);652 653 srcLock.release();654 /* Do the disk cloning. */655 ComPtr<IProgress> progress2;656 rc = pMedium->CloneTo(pTarget,657 srcVar,658 pNewParent,659 progress2.asOutParam());660 if (FAILED(rc)) throw rc;661 662 /* Wait until the asynchrony process has finished. */663 rc = d->pProgress->WaitForAsyncProgressCompletion(progress2);664 srcLock.acquire();665 if (FAILED(rc)) throw rc;666 667 /* Check the result of the asynchrony process. */668 LONG iRc;669 rc = progress2->COMGETTER(ResultCode)(&iRc);670 if (FAILED(rc)) throw rc;671 if (FAILED(iRc))672 {673 /* If the thread of the progress object has an error, then674 * retrieve the error info from there, or it'll be lost. */675 ProgressErrorInfo info(progress2);676 throw p->setError(iRc, Utf8Str(info.getText()).c_str());677 }678 /* Remember created medias. */679 newMedias.append(pTarget);680 /* Get the medium type from the source and set it to the681 * new medium. */682 MediumType_T type;683 rc = pMedium->COMGETTER(Type)(&type);684 if (FAILED(rc)) throw rc;685 rc = pTarget->COMSETTER(Type)(type);686 if (FAILED(rc)) throw rc;687 map.insert(TStrMediumPair(Utf8Str(bstrSrcId), pTarget));688 /* Global register the new harddisk */689 {690 AutoWriteLock tlock(p->mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);691 rc = p->mParent->registerHardDisk(pTarget, NULL /* pllRegistriesThatNeedSaving */);692 if (FAILED(rc)) return rc;693 }694 /* This medium becomes the parent of the next medium in the695 * chain. */696 pNewParent = pTarget;697 773 } 698 774 } … … 701 777 if (mtc.fCreateDiffs) 702 778 { 703 Bstr bstrSrcId; 704 rc = pNewParent->COMGETTER(Id)(bstrSrcId.asOutParam()); 705 if (FAILED(rc)) throw rc; 706 ComObjPtr<Medium> diff; 707 diff.createObject(); 708 rc = diff->init(p->mParent, 709 pNewParent->getPreferredDiffFormat(), 710 Utf8StrFmt("%s%c", strTrgSnapshotFolder.c_str(), RTPATH_DELIMITER), 711 Guid::Empty, /* empty media registry */ 712 NULL); /* pllRegistriesThatNeedSaving */ 713 if (FAILED(rc)) throw rc; 714 MediumLockList *pMediumLockList(new MediumLockList()); 715 rc = diff->createMediumLockList(true /* fFailIfInaccessible */, 716 true /* fMediumLockWrite */, 717 pNewParent, 718 *pMediumLockList); 719 if (FAILED(rc)) throw rc; 720 rc = pMediumLockList->Lock(); 721 if (FAILED(rc)) throw rc; 722 rc = pNewParent->createDiffStorage(diff, MediumVariant_Standard, 723 pMediumLockList, 724 NULL /* aProgress */, 725 true /* aWait */, 726 NULL); // pllRegistriesThatNeedSaving 727 delete pMediumLockList; 728 if (FAILED(rc)) throw rc; 729 /* Remember created medias. */ 730 newMedias.append(diff); 731 /* Global register the new harddisk */ 779 if (pNewParent->isReadOnly()) 732 780 { 733 AutoWriteLock tlock(p->mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 734 rc = p->mParent->registerHardDisk(diff, NULL /* pllRegistriesThatNeedSaving */); 735 if (FAILED(rc)) return rc; 781 ComObjPtr<Medium> pDiff; 782 rc = createDiffHelper(pNewParent, strTrgSnapshotFolder, 783 &newMedia, &pDiff); 784 if (FAILED(rc)) throw rc; 785 /* diff image has to be used... */ 786 pNewParent = pDiff; 736 787 } 737 /* This medium becomes the parent of the next medium in the 738 * chain. */ 739 pNewParent = diff; 788 else 789 { 790 /* Attach the medium directly, as its type is not 791 * subject to diff creation. */ 792 newMedia.append(pNewParent); 793 } 740 794 } 741 795 Bstr bstrSrcId; … … 752 806 /* Make sure all disks know of the new machine uuid. We do this last to 753 807 * be able to change the medium type above. */ 754 for (size_t i = newMedia s.size(); i > 0; --i)755 { 756 ComObjPtr<Medium> &pMedium = newMedias.at(i - 1);808 for (size_t i = newMedia.size(); i > 0; --i) 809 { 810 const ComObjPtr<Medium> &pMedium = newMedia.at(i - 1); 757 811 AutoCaller mac(pMedium); 758 812 if (FAILED(mac.rc())) throw mac.rc(); 759 813 AutoWriteLock mlock(pMedium COMMA_LOCKVAL_SRC_POS); 760 pMedium->addRegistry(d-> pTrgMachine->mData->mUuid, false /* fRecursive */);814 pMedium->addRegistry(d->options.contains(CloneOptions_Link) ? d->pSrcMachine->mData->mUuid : d->pTrgMachine->mData->mUuid, false /* fRecurse */); 761 815 } 762 816 /* Check if a snapshot folder is necessary and if so doesn't already … … 812 866 rc = d->pTrgMachine->SaveSettings(); 813 867 if (FAILED(rc)) throw rc; 814 } 815 catch(HRESULT rc2) 868 trgLock.release(); 869 if (d->options.contains(CloneOptions_Link)) 870 { 871 srcLock.release(); 872 GuidList llRegistrySrc; 873 llRegistrySrc.push_back(d->pSrcMachine->mData->mUuid); 874 rc = p->mParent->saveRegistries(llRegistrySrc); 875 if (FAILED(rc)) throw rc; 876 } 877 } 878 catch (HRESULT rc2) 816 879 { 817 880 rc = rc2; … … 836 899 /* Delete all already created medias. (Reverse, cause there could be 837 900 * parent->child relations.) */ 838 for (size_t i = newMedias.size(); i > 0; --i) 839 { 840 bool fFile = false; 841 Utf8Str strLoc; 842 ComObjPtr<Medium> &pMedium = newMedias.at(i - 1); 843 { 844 AutoCaller mac(pMedium); 845 if (FAILED(mac.rc())) { continue; mrc = mac.rc(); } 846 AutoReadLock mlock(pMedium COMMA_LOCKVAL_SRC_POS); 847 fFile = pMedium->isMediumFormatFile(); 848 strLoc = pMedium->getLocationFull(); 849 } 850 if (fFile) 851 { 852 vrc = RTFileDelete(strLoc.c_str()); 853 if (RT_FAILURE(vrc)) 854 mrc = p->setError(VBOX_E_IPRT_ERROR, p->tr("Could not delete file '%s' (%Rrc)"), strLoc.c_str(), vrc); 855 } 901 for (size_t i = newMedia.size(); i > 0; --i) 902 { 903 const ComObjPtr<Medium> &pMedium = newMedia.at(i - 1); 904 mrc = pMedium->deleteStorage(NULL /* aProgress */, 905 true /* aWait */, 906 NULL /* llRegistriesThatNeedSaving */); 907 pMedium->Close(); 856 908 } 857 909 /* Delete the snapshot folder when not empty. */ … … 865 917 } 866 918 919 HRESULT MachineCloneVM::createDiffHelper(const ComObjPtr<Medium> &pParent, 920 const Utf8Str &strSnapshotFolder, 921 RTCList< ComObjPtr<Medium> > *pNewMedia, 922 ComObjPtr<Medium> *ppDiff) 923 { 924 DPTR(MachineCloneVM); 925 ComObjPtr<Machine> &p = d->p; 926 HRESULT rc = S_OK; 927 928 try 929 { 930 Bstr bstrSrcId; 931 rc = pParent->COMGETTER(Id)(bstrSrcId.asOutParam()); 932 if (FAILED(rc)) throw rc; 933 ComObjPtr<Medium> diff; 934 diff.createObject(); 935 rc = diff->init(p->mParent, 936 pParent->getPreferredDiffFormat(), 937 Utf8StrFmt("%s%c", strSnapshotFolder.c_str(), RTPATH_DELIMITER), 938 Guid::Empty, /* empty media registry */ 939 NULL); /* pllRegistriesThatNeedSaving */ 940 if (FAILED(rc)) throw rc; 941 MediumLockList *pMediumLockList(new MediumLockList()); 942 rc = diff->createMediumLockList(true /* fFailIfInaccessible */, 943 true /* fMediumLockWrite */, 944 pParent, 945 *pMediumLockList); 946 if (FAILED(rc)) throw rc; 947 rc = pMediumLockList->Lock(); 948 if (FAILED(rc)) throw rc; 949 /* this already registers the new diff image */ 950 rc = pParent->createDiffStorage(diff, MediumVariant_Standard, 951 pMediumLockList, 952 NULL /* aProgress */, 953 true /* aWait */, 954 NULL); // pllRegistriesThatNeedSaving 955 delete pMediumLockList; 956 if (FAILED(rc)) throw rc; 957 /* Remember created medium. */ 958 pNewMedia->append(diff); 959 *ppDiff = diff; 960 } 961 catch (HRESULT rc2) 962 { 963 rc = rc2; 964 } 965 catch (...) 966 { 967 rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS); 968 } 969 970 return rc; 971 } 972 867 973 void MachineCloneVM::destroy() 868 974 {
Note:
See TracChangeset
for help on using the changeset viewer.