Changeset 23881 in vbox
- Timestamp:
- Oct 19, 2009 6:07:38 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 53661
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/MachineImpl.cpp
r23880 r23881 7596 7596 : public SessionMachine::Task 7597 7597 { 7598 RestoreSnapshotTask(SessionMachine *m, Progress *p, bool discardCurSnapshot)7598 RestoreSnapshotTask(SessionMachine *m, ComObjPtr<Snapshot> &aSnapshot, Progress *p) 7599 7599 : Task(m, p), 7600 discardCurrentSnapshot(discardCurSnapshot)7600 pSnapshot(aSnapshot) 7601 7601 {} 7602 7602 … … 7606 7606 } 7607 7607 7608 const bool discardCurrentSnapshot;7608 ComObjPtr<Snapshot> pSnapshot; 7609 7609 }; 7610 7610 … … 8700 8700 8701 8701 AssertReturn(aInitiator, E_INVALIDARG); 8702 AssertReturn(a MachineState && aProgress, E_POINTER);8702 AssertReturn(aSnapshot && aMachineState && aProgress, E_POINTER); 8703 8703 8704 8704 AutoCaller autoCaller(this); … … 8710 8710 E_FAIL); 8711 8711 8712 if (mData->mCurrentSnapshot.isNull()) 8713 return setError(VBOX_E_INVALID_OBJECT_STATE, 8714 tr("Could not discard the current state of the machine '%ls' because it doesn't have any snapshots"), 8715 mUserData->mName.raw()); 8712 ComObjPtr<Snapshot> pSnapshot(static_cast<Snapshot*>(aSnapshot)); 8716 8713 8717 8714 /* create a progress object. The number of operations is: 1 (preparing) + # … … 8720 8717 progress.createObject(); 8721 8718 { 8722 ULONG opCount = 1 + (ULONG)mData->mCurrentSnapshot->getSnapshotMachine()->mMediaData->mAttachments.size(); 8723 if (mData->mCurrentSnapshot->stateFilePath()) 8724 ++opCount; 8725 progress->init (mParent, aInitiator, 8726 Bstr (tr ("Discarding current machine state")), 8727 FALSE /* aCancelable */, opCount, 8728 Bstr (tr ("Preparing to discard current state"))); 8719 ULONG opCount = 1 // preparing 8720 + (ULONG)pSnapshot->getSnapshotMachine()->mMediaData->mAttachments.size(); // one for each attachment @todo only for HDs! 8721 if (pSnapshot->stateFilePath()) 8722 ++opCount; // one for the saved state 8723 progress->init(mParent, aInitiator, 8724 Bstr(tr("Restoring snapshot")), 8725 FALSE /* aCancelable */, opCount, 8726 Bstr(tr("Preparing to restore machine state from snapshot"))); 8729 8727 } 8730 8728 8731 8729 /* create and start the task on a separate thread (note that it will not 8732 8730 * start working until we release alock) */ 8733 RestoreSnapshotTask *task = new RestoreSnapshotTask(this, p rogress, false /* discardCurSnapshot */);8731 RestoreSnapshotTask *task = new RestoreSnapshotTask(this, pSnapshot, progress); 8734 8732 int vrc = RTThreadCreate(NULL, 8735 8733 taskHandler, … … 9789 9787 9790 9788 /* saveSettings() needs mParent lock */ 9791 AutoWriteLock vboxLock 9789 AutoWriteLock vboxLock(mParent); 9792 9790 9793 9791 /* @todo We don't need mParent lock so far so unlock() it. Better is to … … 9809 9807 bool stateRestored = false; 9810 9808 9811 const bool isLastSnapshot = mData->mCurrentSnapshot->parent().isNull();9812 9813 9809 try 9814 9810 { … … 9817 9813 if (aTask.state == MachineState_Saved) 9818 9814 { 9819 Assert 9815 Assert(!mSSData->mStateFilePath.isEmpty()); 9820 9816 RTFileDelete(Utf8Str(mSSData->mStateFilePath).c_str()); 9821 9817 mSSData->mStateFilePath.setNull(); 9822 aTask.modifyLastState 9823 rc = saveStateSettings 9818 aTask.modifyLastState(MachineState_PoweredOff); 9819 rc = saveStateSettings(SaveSTS_StateFilePath); 9824 9820 CheckComRCThrowRC(rc); 9825 9821 } 9826 9822 9827 if (aTask.discardCurrentSnapshot && !isLastSnapshot)9828 {9829 /* the "discard current snapshot and state" task is in action, the9830 * current snapshot is not the last one. Discard the current9831 * snapshot first */9832 9833 DeleteSnapshotTask subTask (aTask, mData->mCurrentSnapshot);9834 subTask.subTask = true;9835 discardSnapshotHandler (subTask);9836 9837 AutoCaller progressCaller (aTask.progress);9838 AutoReadLock progressLock (aTask.progress);9839 if (aTask.progress->completed())9840 {9841 /* the progress can be completed by a subtask only if there was9842 * a failure */9843 rc = aTask.progress->resultCode();9844 Assert (FAILED(rc));9845 errorInSubtask = true;9846 throw rc;9847 }9848 }9849 9850 9823 RTTIMESPEC snapshotTimeStamp; 9851 RTTimeSpecSetMilli (&snapshotTimeStamp, 0); 9852 9853 { 9854 ComObjPtr<Snapshot> curSnapshot = mData->mCurrentSnapshot; 9855 AutoReadLock snapshotLock (curSnapshot); 9824 RTTimeSpecSetMilli(&snapshotTimeStamp, 0); 9825 9826 { 9827 AutoReadLock snapshotLock(aTask.pSnapshot); 9856 9828 9857 9829 /* remember the timestamp of the snapshot we're restoring from */ 9858 snapshotTimeStamp = curSnapshot->getTimeStamp();9859 9860 ComPtr<SnapshotMachine> pSnapshotMachine( curSnapshot->getSnapshotMachine());9861 9862 /* copy all hardware data from the currentsnapshot */9830 snapshotTimeStamp = aTask.pSnapshot->getTimeStamp(); 9831 9832 ComPtr<SnapshotMachine> pSnapshotMachine(aTask.pSnapshot->getSnapshotMachine()); 9833 9834 /* copy all hardware data from the snapshot */ 9863 9835 copyFrom(pSnapshotMachine); 9864 9836 9865 9837 LogFlowThisFunc(("Restoring hard disks from the snapshot...\n")); 9866 9838 9867 /* restore the attachmen ds from the snapshot */9839 /* restore the attachments from the snapshot */ 9868 9840 mMediaData.backup(); 9869 9841 mMediaData->mAttachments = pSnapshotMachine->mMediaData->mAttachments; … … 9889 9861 9890 9862 /* should not have a saved state file associated at this point */ 9891 Assert 9892 9893 if ( curSnapshot->stateFilePath())9863 Assert(mSSData->mStateFilePath.isNull()); 9864 9865 if (aTask.pSnapshot->stateFilePath()) 9894 9866 { 9895 Utf8Str snapStateFilePath = curSnapshot->stateFilePath(); 9896 9897 Utf8Str stateFilePath = Utf8StrFmt ("%ls%c{%RTuuid}.sav", 9898 mUserData->mSnapshotFolderFull.raw(), 9899 RTPATH_DELIMITER, mData->mUuid.raw()); 9867 Utf8Str snapStateFilePath = aTask.pSnapshot->stateFilePath(); 9868 9869 Utf8Str stateFilePath = Utf8StrFmt("%ls%c{%RTuuid}.sav", 9870 mUserData->mSnapshotFolderFull.raw(), 9871 RTPATH_DELIMITER, 9872 mData->mUuid.raw()); 9900 9873 9901 9874 LogFlowThisFunc(("Copying saved state file from '%s' to '%s'...\n", … … 9953 9926 int saveFlags = 0; 9954 9927 9955 if (aTask.discardCurrentSnapshot && isLastSnapshot)9956 {9957 /* commit changes to have unused diffs deassociated from this9958 * machine before deletion (see below) */9959 commit();9960 9961 /* delete the unused diffs now (and uninit them) because discard9962 * may fail otherwise (too many children of the hard disk to be9963 * discarded) */9964 for (std::list< ComObjPtr<Medium> >::const_iterator9965 it = diffs.begin(); it != diffs.end(); ++it)9966 {9967 /// @todo for now, we ignore errors since we've already9968 /// and therefore cannot fail. Later, we may want to report a9969 /// warning through the Progress object9970 HRESULT rc2 = (*it)->deleteStorageAndWait();9971 if (SUCCEEDED(rc2))9972 (*it)->uninit();9973 }9974 9975 /* prevent further deletion */9976 diffs.clear();9977 9978 /* discard the current snapshot and state task is in action, the9979 * current snapshot is the last one. Discard the current snapshot9980 * after discarding the current state. */9981 9982 DeleteSnapshotTask subTask (aTask, mData->mCurrentSnapshot);9983 subTask.subTask = true;9984 discardSnapshotHandler (subTask);9985 9986 AutoCaller progressCaller (aTask.progress);9987 AutoReadLock progressLock (aTask.progress);9988 if (aTask.progress->completed())9989 {9990 /* the progress can be completed by a subtask only if there9991 * was a failure */9992 rc = aTask.progress->resultCode();9993 Assert (FAILED(rc));9994 errorInSubtask = true;9995 }9996 9997 /* we've committed already, so inform callbacks anyway to ensure9998 * they don't miss some change */9999 /// @todo NEWMEDIA check if we need this informCallbacks at all10000 /// after updating discardCurrentSnapshot functionality10001 saveFlags |= SaveS_InformCallbacksAnyway;10002 }10003 10004 9928 /* @todo saveSettings() below needs a VirtualBox write lock and we need 10005 9929 * to leave this object's lock to do this to follow the {parent-child} … … 10013 9937 * state accordingly no matter of the discard snapshot result */ 10014 9938 if (mSSData->mStateFilePath) 10015 setMachineState 9939 setMachineState(MachineState_Saved); 10016 9940 else 10017 setMachineState 9941 setMachineState(MachineState_PoweredOff); 10018 9942 10019 9943 updateMachineStateOnClient(); … … 10021 9945 10022 9946 /* assign the timestamp from the snapshot */ 10023 Assert 9947 Assert(RTTimeSpecGetMilli (&snapshotTimeStamp) != 0); 10024 9948 mData->mLastStateChange = snapshotTimeStamp; 10025 9949 … … 10027 9951 * do so even if the subtask failed (errorInSubtask=true) because we've 10028 9952 * already committed machine data and deleted old diffs before 10029 * discarding the currentsnapshot so there is no way to rollback */9953 * discarding the snapshot so there is no way to rollback */ 10030 9954 HRESULT rc2 = saveSettings(SaveS_ResetCurStateModified | saveFlags); 10031 9955 … … 10039 9963 { 10040 9964 /* now, delete the unused diffs (only on success!) and uninit them*/ 10041 for (std::list< ComObjPtr<Medium> >::const_iterator 10042 it = diffs.begin(); it != diffs.end(); ++it) 9965 for (std::list< ComObjPtr<Medium> >::const_iterator it = diffs.begin(); 9966 it != diffs.end(); 9967 ++it) 10043 9968 { 10044 9969 /// @todo for now, we ignore errors since we've already … … 10067 9992 { 10068 9993 /* restore the machine state */ 10069 setMachineState 9994 setMachineState(aTask.state); 10070 9995 updateMachineStateOnClient(); 10071 9996 } … … 10079 10004 10080 10005 if (SUCCEEDED(rc)) 10081 mParent->onSnapshotDiscarded 10082 10083 LogFlowThisFunc(("Done discarding current state(rc=%08X)\n", rc));10006 mParent->onSnapshotDiscarded(mData->mUuid, Guid()); 10007 10008 LogFlowThisFunc(("Done restoring snapshot (rc=%08X)\n", rc)); 10084 10009 10085 10010 LogFlowThisFuncLeave();
Note:
See TracChangeset
for help on using the changeset viewer.