Changeset 15375 in vbox for trunk/src/VBox/Main
- Timestamp:
- Dec 12, 2008 3:07:32 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/MachineImpl.cpp
r15334 r15375 6112 6112 6113 6113 /* quick path: recreate the whole tree of the snapshots */ 6114 if (op == SaveSS_UpdateAllOp && !aSnapshot)6114 if (op == SaveSS_UpdateAllOp && aSnapshot == NULL) 6115 6115 { 6116 6116 /* first, delete the entire root snapshot node if it exists */ … … 9596 9596 9597 9597 /** 9598 * Helper struct for SessionMachine::discardSnapshotHandler(). 9599 */ 9600 struct HardDiskDiscardRec 9601 { 9602 HardDiskDiscardRec() : chain (NULL) {} 9603 9604 HardDiskDiscardRec (const ComObjPtr <HardDisk2> &aHd, 9605 HardDisk2::MergeChain *aChain = NULL) 9606 : hd (aHd), chain (aChain) {} 9607 9608 HardDiskDiscardRec (const ComObjPtr <HardDisk2> &aHd, 9609 HardDisk2::MergeChain *aChain, 9610 const ComObjPtr <HardDisk2> &aReplaceHd, 9611 const ComObjPtr <HardDisk2Attachment> &aReplaceHda, 9612 const Guid &aSnapshotId) 9613 : hd (aHd), chain (aChain) 9614 , replaceHd (aReplaceHd), replaceHda (aReplaceHda) 9615 , snapshotId (aSnapshotId) {} 9616 9617 ComObjPtr <HardDisk2> hd; 9618 HardDisk2::MergeChain *chain; 9619 /* these are for the replace hard disk case: */ 9620 ComObjPtr <HardDisk2> replaceHd; 9621 ComObjPtr <HardDisk2Attachment> replaceHda; 9622 Guid snapshotId; 9623 }; 9624 9625 typedef std::list <HardDiskDiscardRec> HardDiskDiscardRecList; 9626 9627 /** 9598 9628 * Discard snapshot task handler. Must be called only by 9599 9629 * DiscardSnapshotTask::handler()! … … 9645 9675 Guid snapshotId = aTask.snapshot->data().mId; 9646 9676 9647 typedef std::list <std::pair <ComObjPtr <HardDisk2>, 9648 HardDisk2::MergeChain *> > ToDiscard; 9649 ToDiscard toDiscard; 9677 HardDiskDiscardRecList toDiscard; 9650 9678 9651 9679 bool settingsChanged = false; … … 9688 9716 CheckComRCThrowRC (rc); 9689 9717 9690 toDiscard.push_back (std::make_pair (hd, chain)); 9718 if (hd->parent().isNull() && chain != NULL) 9719 { 9720 /* it's a base hard disk so it will be a backward merge of its 9721 * only child to it (prepareDiscard() does necessary checks). We 9722 * need then to update the attachment that refers to the child 9723 * to refer to the parent insead. Don't forget to detach the 9724 * child (otherwise mergeTo() called by discard() will assert 9725 * because it will be going to delete the child) */ 9726 9727 /* The below assert would be nice but I don't want to move 9728 * HardDisk2::MergeChain to the header just for that 9729 /* Assert (!chain->isForward()); */ 9730 9731 Assert (hd->children().size() == 1); 9732 9733 ComObjPtr <HardDisk2> replaceHd = hd->children().front(); 9734 9735 Assert (replaceHd->backRefs().front().machineId == mData->mUuid); 9736 Assert (replaceHd->backRefs().front().snapshotIds.size() <= 1); 9737 9738 Guid snapshotId; 9739 if (replaceHd->backRefs().front().snapshotIds.size() == 1) 9740 snapshotId = replaceHd->backRefs().front().snapshotIds.front(); 9741 9742 HRESULT rc2 = S_OK; 9743 9744 /* adjust back references */ 9745 rc2 = replaceHd->detachFrom (mData->mUuid, snapshotId); 9746 AssertComRC (rc2); 9747 9748 rc2 = hd->attachTo (mData->mUuid, snapshotId); 9749 AssertComRC (rc2); 9750 9751 /* replace the hard disk in the attachment object */ 9752 HDData::AttachmentList::iterator it; 9753 if (snapshotId.isEmpty()) 9754 { 9755 /* in current state */ 9756 it = std::find_if (mHDData->mAttachments.begin(), 9757 mHDData->mAttachments.end(), 9758 HardDisk2Attachment::RefersTo (replaceHd)); 9759 AssertBreak (it != mHDData->mAttachments.end()); 9760 } 9761 else 9762 { 9763 /* in snapshot */ 9764 ComObjPtr <Snapshot> snapshot; 9765 rc2 = findSnapshot (snapshotId, snapshot); 9766 AssertComRC (rc2); 9767 9768 /* don't lock the snapshot; cannot be modified outside */ 9769 HDData::AttachmentList &snapAtts = 9770 snapshot->data().mMachine->mHDData->mAttachments; 9771 it = std::find_if (snapAtts.begin(), 9772 snapAtts.end(), 9773 HardDisk2Attachment::RefersTo (replaceHd)); 9774 AssertBreak (it != snapAtts.end()); 9775 } 9776 9777 AutoWriteLock attLock (*it); 9778 (*it)->updateHardDisk (hd, false /* aImplicit */); 9779 9780 toDiscard.push_back (HardDiskDiscardRec (hd, chain, replaceHd, 9781 *it, snapshotId)); 9782 continue; 9783 } 9784 9785 toDiscard.push_back (HardDiskDiscardRec (hd, chain)); 9691 9786 } 9692 9787 … … 9734 9829 if (aTask.snapshot->children().size() == 1) 9735 9830 { 9736 ComObjPtr <Snapshot> childSnapshot = aTask.snapshot->children().front(); 9831 ComObjPtr <Snapshot> childSnapshot = 9832 aTask.snapshot->children().front(); 9737 9833 ComAssertThrow ( 9738 9834 childSnapshot->data().mMachine->mData->mUuid == mData->mUuid, … … 9791 9887 /// warnings properly on the GUI side) 9792 9888 9793 for ( ToDiscard::iterator it = toDiscard.begin();9889 for (HardDiskDiscardRecList::iterator it = toDiscard.begin(); 9794 9890 it != toDiscard.end();) 9795 9891 { 9796 ComObjPtr <HardDisk2> replaceHd; 9797 Guid snapshotId; 9798 9799 if (it->first->parent().isNull() && it->second != NULL) 9800 { 9801 /* it's a base hard disk so it will be a backward merge of its 9802 * only child to it. We need then to update the attachment that 9803 * refers to the child so get it and detach the child 9804 * (otherwise mergeTo() called by discard() will assert because 9805 * it will be going to delete the child) */ 9806 9807 Assert (it->first->children().size() == 1); 9808 replaceHd = it->first->children().front(); 9809 9810 Assert (replaceHd->backRefs().front().machineId == mData->mUuid); 9811 Assert (replaceHd->backRefs().front().snapshotIds.size() <= 1); 9812 if (replaceHd->backRefs().front().snapshotIds.size() == 1) 9813 snapshotId = replaceHd->backRefs().front().snapshotIds.front(); 9814 9815 HRESULT rc2 = replaceHd->detachFrom (mData->mUuid, snapshotId); 9816 AssertComRC (rc2); 9817 } 9818 9819 rc = it->first->discard (aTask.progress, it->second); 9820 9821 if (FAILED (rc)) 9822 { 9823 /* attach the detached child again */ 9824 if (!replaceHd.isNull()) 9825 replaceHd->attachTo (mData->mUuid, snapshotId); 9826 break; 9827 } 9828 9829 if (SUCCEEDED (rc) && !replaceHd.isNull()) 9830 { 9831 /* replace the attachment on success */ 9832 alock.enter(); 9833 9834 HDData::AttachmentList::iterator jt; 9835 if (snapshotId.isEmpty()) 9836 { 9837 /* in current state */ 9838 jt = std::find_if (mHDData->mAttachments.begin(), 9839 mHDData->mAttachments.end(), 9840 HardDisk2Attachment::RefersTo (replaceHd)); 9841 AssertBreakStmt (jt != mHDData->mAttachments.end(), 9842 rc = E_FAIL); 9843 } 9844 else 9845 { 9846 /* in snapshot */ 9847 ComObjPtr <Snapshot> snapshot; 9848 findSnapshot (snapshotId, snapshot); 9849 AssertBreakStmt (!snapshot.isNull(), rc = E_FAIL); 9850 9851 /* don't lock the snapshot; cannot be modified outside */ 9852 HDData::AttachmentList &snapAtts = 9853 snapshot->data().mMachine->mHDData->mAttachments; 9854 jt = std::find_if (snapAtts.begin(), 9855 snapAtts.end(), 9856 HardDisk2Attachment::RefersTo (replaceHd)); 9857 AssertBreakStmt (jt != snapAtts.end(), rc = E_FAIL); 9858 } 9859 9860 { 9861 AutoWriteLock attLock (*jt); 9862 (*jt)->updateHardDisk (it->first, false /* aImplicit */); 9863 } 9864 9865 HRESULT rc2 = it->first->attachTo (mData->mUuid, snapshotId); 9866 AssertComRC (rc2); 9867 9868 alock.leave(); 9869 } 9892 rc = it->hd->discard (aTask.progress, it->chain); 9893 CheckComRCBreakRC (rc); 9870 9894 9871 9895 /* prevent from calling cancelDiscard() */ … … 9881 9905 if FAILED (rc) 9882 9906 { 9907 HRESULT rc2 = S_OK; 9908 9883 9909 /* un-prepare the remaining hard disks */ 9884 for ( ToDiscard::const_iterator it = toDiscard.begin();9910 for (HardDiskDiscardRecList::const_iterator it = toDiscard.begin(); 9885 9911 it != toDiscard.end(); ++ it) 9886 it->first->cancelDiscard (it->second); 9912 { 9913 it->hd->cancelDiscard (it->chain); 9914 9915 if (!it->replaceHd.isNull()) 9916 { 9917 /* undo hard disk replacement */ 9918 9919 rc2 = it->replaceHd->attachTo (mData->mUuid, it->snapshotId); 9920 AssertComRC (rc2); 9921 9922 rc2 = it->hd->detachFrom (mData->mUuid, it->snapshotId); 9923 AssertComRC (rc2); 9924 9925 AutoWriteLock attLock (it->replaceHda); 9926 it->replaceHda->updateHardDisk (it->replaceHd, false /* aImplicit */); 9927 } 9928 } 9887 9929 } 9888 9930
Note:
See TracChangeset
for help on using the changeset viewer.