Changeset 36074 in vbox
- Timestamp:
- Feb 24, 2011 3:38:25 PM (14 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/MachineImpl.h
r36058 r36074 200 200 struct SSData 201 201 { 202 Utf8Str mStateFilePath;202 Utf8Str strStateFilePath; 203 203 }; 204 204 … … 645 645 Utf8Str queryLogFilename(ULONG idx); 646 646 647 void composeSavedStateFilename(Utf8Str &strStateFilePath); 648 647 649 HRESULT openRemoteSession(IInternalSessionControl *aControl, 648 650 IN_BSTR aType, IN_BSTR aEnvironment, … … 1007 1009 struct ConsoleTaskData 1008 1010 { 1009 ConsoleTaskData() : mLastState(MachineState_Null) {} 1011 ConsoleTaskData() 1012 : mLastState(MachineState_Null) 1013 { } 1010 1014 1011 1015 MachineState_T mLastState; … … 1016 1020 1017 1021 // used when saving state (either as part of a snapshot or separate) 1018 Utf8Str mStateFilePath;1022 Utf8Str strStateFilePath; 1019 1023 }; 1020 1024 … … 1034 1038 1035 1039 HRESULT endSavingState(HRESULT aRC, const Utf8Str &aErrMsg); 1040 void releaseSavedStateFile(const Utf8Str &strSavedStateFile, Snapshot *pSnapshotToIgnore); 1036 1041 1037 1042 void deleteSnapshotHandler(DeleteSnapshotTask &aTask); -
trunk/src/VBox/Main/include/SnapshotImpl.h
r35638 r36074 98 98 const ComObjPtr<Snapshot> getFirstChild() const; 99 99 100 const Utf8Str& stateFilePath() const; 101 HRESULT deleteStateFile(); 100 const Utf8Str& getStateFilePath() const; 102 101 103 102 ULONG getChildrenCount(); … … 119 118 const Utf8Str &strNewPath); 120 119 120 bool sharesSavedStateFile(const Utf8Str &strPath, 121 Snapshot *pSnapshotToIgnore); 122 121 123 HRESULT saveSnapshot(settings::Snapshot &data, bool aAttrsOnly); 122 124 HRESULT saveSnapshotImpl(settings::Snapshot &data, bool aAttrsOnly); -
trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
r36041 r36074 3076 3076 LogFlowFunc(("fTakingSnapshotOnline = %d, mMachineState = %d\n", fTakingSnapshotOnline, mMachineState)); 3077 3077 3078 if ( fTakingSnapshotOnline 3079 || mMachineState == MachineState_Saved 3080 ) 3078 if (fTakingSnapshotOnline) 3081 3079 { 3082 3080 ++cOperations; 3083 3084 3081 ulTotalOperationsWeight += ulMemSize; 3085 3082 } -
trunk/src/VBox/Main/src-server/MachineImpl.cpp
r36072 r36074 2333 2333 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 2334 2334 2335 mSSData-> mStateFilePath.cloneTo(aStateFilePath);2335 mSSData->strStateFilePath.cloneTo(aStateFilePath); 2336 2336 2337 2337 return S_OK; … … 4320 4320 { 4321 4321 // add the saved state file to the list of files the caller should delete 4322 Assert(!mSSData-> mStateFilePath.isEmpty());4323 mData->llFilesToDelete.push_back(mSSData-> mStateFilePath);4324 4325 mSSData-> mStateFilePath.setNull();4322 Assert(!mSSData->strStateFilePath.isEmpty()); 4323 mData->llFilesToDelete.push_back(mSSData->strStateFilePath); 4324 4325 mSSData->strStateFilePath.setNull(); 4326 4326 4327 4327 // unconditionally set the machine state to powered off, we now … … 5427 5427 uint32_t u32Height = 0; 5428 5428 5429 int vrc = readSavedGuestSize(mSSData-> mStateFilePath, uScreenId, &u32Width, &u32Height);5429 int vrc = readSavedGuestSize(mSSData->strStateFilePath, uScreenId, &u32Width, &u32Height); 5430 5430 if (RT_FAILURE(vrc)) 5431 5431 return setError(VBOX_E_IPRT_ERROR, … … 5460 5460 uint32_t u32Height = 0; 5461 5461 5462 int vrc = readSavedDisplayScreenshot(mSSData-> mStateFilePath, 0 /* u32Type */, &pu8Data, &cbData, &u32Width, &u32Height);5462 int vrc = readSavedDisplayScreenshot(mSSData->strStateFilePath, 0 /* u32Type */, &pu8Data, &cbData, &u32Width, &u32Height); 5463 5463 5464 5464 if (RT_FAILURE(vrc)) … … 5497 5497 uint32_t u32Height = 0; 5498 5498 5499 int vrc = readSavedDisplayScreenshot(mSSData-> mStateFilePath, 0 /* u32Type */, &pu8Data, &cbData, &u32Width, &u32Height);5499 int vrc = readSavedDisplayScreenshot(mSSData->strStateFilePath, 0 /* u32Type */, &pu8Data, &cbData, &u32Width, &u32Height); 5500 5500 5501 5501 if (RT_FAILURE(vrc)) … … 5560 5560 uint32_t u32Height = 0; 5561 5561 5562 int vrc = readSavedDisplayScreenshot(mSSData-> mStateFilePath, 0 /* u32Type */, &pu8Data, &cbData, &u32Width, &u32Height);5562 int vrc = readSavedDisplayScreenshot(mSSData->strStateFilePath, 0 /* u32Type */, &pu8Data, &cbData, &u32Width, &u32Height); 5563 5563 5564 5564 if (RT_FAILURE(vrc)) … … 5609 5609 uint32_t u32Height = 0; 5610 5610 5611 int vrc = readSavedDisplayScreenshot(mSSData-> mStateFilePath, 1 /* u32Type */, &pu8Data, &cbData, &u32Width, &u32Height);5611 int vrc = readSavedDisplayScreenshot(mSSData->strStateFilePath, 1 /* u32Type */, &pu8Data, &cbData, &u32Width, &u32Height); 5612 5612 5613 5613 if (RT_FAILURE(vrc)) … … 5646 5646 uint32_t u32Height = 0; 5647 5647 5648 int vrc = readSavedDisplayScreenshot(mSSData-> mStateFilePath, 1 /* u32Type */, &pu8Data, &cbData, &u32Width, &u32Height);5648 int vrc = readSavedDisplayScreenshot(mSSData->strStateFilePath, 1 /* u32Type */, &pu8Data, &cbData, &u32Width, &u32Height); 5649 5649 5650 5650 if (RT_FAILURE(vrc)) … … 6086 6086 logFolder.c_str(), RTPATH_DELIMITER, idx); 6087 6087 return log; 6088 } 6089 6090 /** 6091 * Composes a unique saved state filename based on the current system time. The filename is 6092 * granular to the second so this will work so long as no more than one snapshot is taken on 6093 * a machine per second. 6094 * 6095 * Before version 4.1, we used this formula for saved state files: 6096 * Utf8StrFmt("%s%c{%RTuuid}.sav", strFullSnapshotFolder.c_str(), RTPATH_DELIMITER, mData->mUuid.raw()) 6097 * which no longer works because saved state files can now be shared between the saved state of the 6098 * "saved" machine and an online snapshot, and the following would cause problems: 6099 * 1) save machine 6100 * 2) create online snapshot from that machine state --> reusing saved state file 6101 * 3) save machine again --> filename would be reused, breaking the online snapshot 6102 * 6103 * So instead we now use a timestamp. 6104 * 6105 * @param str 6106 */ 6107 void Machine::composeSavedStateFilename(Utf8Str &strStateFilePath) 6108 { 6109 AutoCaller autoCaller(this); 6110 AssertComRCReturnVoid(autoCaller.rc()); 6111 6112 { 6113 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 6114 calculateFullPath(mUserData->s.strSnapshotFolder, strStateFilePath); 6115 } 6116 6117 RTTIMESPEC ts; 6118 RTTimeNow(&ts); 6119 RTTIME time; 6120 RTTimeExplode(&time, &ts); 6121 6122 strStateFilePath += RTPATH_DELIMITER; 6123 strStateFilePath += Utf8StrFmt("%04ld-%02hd-%02hdT%02hd:%02hd:%02hdZ.sav", 6124 time.i32Year, 6125 (uint16_t)time.u8Month, 6126 (uint16_t)time.u8MonthDay, 6127 (uint16_t)time.u8Hour, 6128 (uint16_t)time.u8Minute, 6129 (uint16_t)time.u8Second); 6088 6130 } 6089 6131 … … 7115 7157 // stateFile (optional) 7116 7158 if (config.strStateFile.isEmpty()) 7117 mSSData-> mStateFilePath.setNull();7159 mSSData->strStateFilePath.setNull(); 7118 7160 else 7119 7161 { … … 7125 7167 config.strStateFile.c_str(), 7126 7168 vrc); 7127 mSSData-> mStateFilePath = stateFilePathFull;7169 mSSData->strStateFilePath = stateFilePathFull; 7128 7170 } 7129 7171 … … 7191 7233 if (config.fAborted) 7192 7234 { 7193 Assert(!mSSData-> mStateFilePath.isEmpty());7194 mSSData-> mStateFilePath.setNull();7235 Assert(!mSSData->strStateFilePath.isEmpty()); 7236 mSSData->strStateFilePath.setNull(); 7195 7237 7196 7238 /* no need to use setMachineState() during init() */ 7197 7239 mData->mMachineState = MachineState_Aborted; 7198 7240 } 7199 else if (!mSSData-> mStateFilePath.isEmpty())7241 else if (!mSSData->strStateFilePath.isEmpty()) 7200 7242 { 7201 7243 /* no need to use setMachineState() during init() */ … … 8054 8096 } 8055 8097 8056 /* update the saved state file path */ 8057 Utf8Str path = mSSData->mStateFilePath; 8058 if (RTPathStartsWith(path.c_str(), configDir.c_str())) 8059 mSSData->mStateFilePath = Utf8StrFmt("%s%s", 8060 newConfigDir.c_str(), 8061 path.c_str() + configDir.length()); 8062 8063 /* Update saved state file paths of all online snapshots. 8064 * Note that saveSettings() will recognize name change 8065 * and will save all snapshots in this case. */ 8098 // in the saved state file path, replace the old directory with the new directory 8099 if (RTPathStartsWith(mSSData->strStateFilePath.c_str(), configDir.c_str())) 8100 mSSData->strStateFilePath = newConfigDir.append(mSSData->strStateFilePath.c_str() + configDir.length()); 8101 8102 // and do the same thing for the saved state file paths of all the online snapshots 8066 8103 if (mData->mFirstSnapshot) 8067 8104 mData->mFirstSnapshot->updateSavedStatePaths(configDir.c_str(), … … 8296 8333 || mData->mMachineState == MachineState_DeletingSnapshotOnline 8297 8334 || mData->mMachineState == MachineState_DeletingSnapshotPaused) 8298 && (!mSSData-> mStateFilePath.isEmpty())8335 && (!mSSData->strStateFilePath.isEmpty()) 8299 8336 ) 8300 8337 ) 8301 8338 { 8302 Assert(!mSSData-> mStateFilePath.isEmpty());8339 Assert(!mSSData->strStateFilePath.isEmpty()); 8303 8340 /* try to make the file name relative to the settings file dir */ 8304 copyPathRelativeToMachine(mSSData-> mStateFilePath, config.strStateFile);8341 copyPathRelativeToMachine(mSSData->strStateFilePath, config.strStateFile); 8305 8342 } 8306 8343 else 8307 8344 { 8308 Assert(mSSData-> mStateFilePath.isEmpty() || mData->mMachineState == MachineState_Saving);8345 Assert(mSSData->strStateFilePath.isEmpty() || mData->mMachineState == MachineState_Saving); 8309 8346 config.strStateFile.setNull(); 8310 8347 } … … 8403 8440 Automatically upgrade from 1 to 2 when there is no saved state. (ugly!) */ 8404 8441 if ( mHWData->mHWVersion == "1" 8405 && mSSData-> mStateFilePath.isEmpty()8442 && mSSData->strStateFilePath.isEmpty() 8406 8443 ) 8407 8444 mHWData->mHWVersion = "2"; /** @todo Is this safe, to update mHWVersion here? If not some other point needs to be found where this can be done. */ … … 8755 8792 if (aFlags & SaveSTS_StateFilePath) 8756 8793 { 8757 if (!mSSData-> mStateFilePath.isEmpty())8794 if (!mSSData->strStateFilePath.isEmpty()) 8758 8795 /* try to make the file name relative to the settings file dir */ 8759 copyPathRelativeToMachine(mSSData-> mStateFilePath, mData->pMachineConfigFile->strStateFile);8796 copyPathRelativeToMachine(mSSData->strStateFilePath, mData->pMachineConfigFile->strStateFile); 8760 8797 else 8761 8798 mData->pMachineConfigFile->strStateFile.setNull(); … … 8765 8802 { 8766 8803 Assert( mData->mMachineState != MachineState_Aborted 8767 || mSSData-> mStateFilePath.isEmpty());8804 || mSSData->strStateFilePath.isEmpty()); 8768 8805 8769 8806 mData->pMachineConfigFile->timeLastStateChange = mData->mLastStateChange; … … 9554 9591 * 9555 9592 * @note Locks this object for writing! 9593 * 9594 * @todo r=dj this needs a pllRegistriesThatNeedSaving as well 9556 9595 */ 9557 9596 void Machine::rollbackMedia() … … 10429 10468 } 10430 10469 10431 Assert(mConsoleTaskData.mStateFilePath.isEmpty() || !mConsoleTaskData.mSnapshot); 10432 if (!mConsoleTaskData.mStateFilePath.isEmpty()) 10470 Assert( mConsoleTaskData.strStateFilePath.isEmpty() 10471 || !mConsoleTaskData.mSnapshot); 10472 if (!mConsoleTaskData.strStateFilePath.isEmpty()) 10433 10473 { 10434 10474 LogWarningThisFunc(("canceling failed save state request!\n")); … … 10442 10482 * their parents back by rolling back mMediaData) */ 10443 10483 rollbackMedia(); 10444 /* delete the saved state file (it might have been already created) */ 10445 if (mConsoleTaskData.mSnapshot->stateFilePath().length()) 10446 RTFileDelete(mConsoleTaskData.mSnapshot->stateFilePath().c_str()); 10447 10484 10485 // delete the saved state file (it might have been already created) 10486 // AFTER killing the snapshot so that releaseSavedStateFile() won't 10487 // think it's still in use 10488 Utf8Str strStateFile = mConsoleTaskData.mSnapshot->getStateFilePath(); 10448 10489 mConsoleTaskData.mSnapshot->uninit(); 10490 releaseSavedStateFile(strStateFile, NULL /* pSnapshotToIgnore */ ); 10449 10491 } 10450 10492 … … 11027 11069 AssertReturn( mData->mMachineState == MachineState_Paused 11028 11070 && mConsoleTaskData.mLastState == MachineState_Null 11029 && mConsoleTaskData. mStateFilePath.isEmpty(),11071 && mConsoleTaskData.strStateFilePath.isEmpty(), 11030 11072 E_FAIL); 11031 11073 … … 11038 11080 FALSE /* aCancelable */); 11039 11081 11040 Bstr stateFilePath;11082 Utf8Str strStateFilePath; 11041 11083 /* stateFilePath is null when the machine is not running */ 11042 11084 if (mData->mMachineState == MachineState_Paused) 11043 { 11044 Utf8Str strFullSnapshotFolder; 11045 calculateFullPath(mUserData->s.strSnapshotFolder, strFullSnapshotFolder); 11046 stateFilePath = Utf8StrFmt("%s%c{%RTuuid}.sav", 11047 strFullSnapshotFolder.c_str(), 11048 RTPATH_DELIMITER, 11049 mData->mUuid.raw()); 11050 } 11085 composeSavedStateFilename(strStateFilePath); 11051 11086 11052 11087 /* fill in the console task data */ 11053 11088 mConsoleTaskData.mLastState = mData->mMachineState; 11054 mConsoleTaskData. mStateFilePath = stateFilePath;11089 mConsoleTaskData.strStateFilePath = strStateFilePath; 11055 11090 mConsoleTaskData.mProgress = pProgress; 11056 11091 … … 11058 11093 setMachineState(MachineState_Saving); 11059 11094 11060 st ateFilePath.cloneTo(aStateFilePath);11095 strStateFilePath.cloneTo(aStateFilePath); 11061 11096 pProgress.queryInterfaceTo(aProgress); 11062 11097 … … 11080 11115 || (FAILED(iResult) && mData->mMachineState == MachineState_Saving)) 11081 11116 && mConsoleTaskData.mLastState != MachineState_Null 11082 && !mConsoleTaskData. mStateFilePath.isEmpty(),11117 && !mConsoleTaskData.strStateFilePath.isEmpty(), 11083 11118 E_FAIL); 11084 11119 … … 11122 11157 vrc); 11123 11158 11124 mSSData-> mStateFilePath = stateFilePathFull;11159 mSSData->strStateFilePath = stateFilePathFull; 11125 11160 11126 11161 /* The below setMachineState() will detect the state transition and will … … 11791 11826 if (SUCCEEDED(aRc)) 11792 11827 { 11793 mSSData-> mStateFilePath = mConsoleTaskData.mStateFilePath;11828 mSSData->strStateFilePath = mConsoleTaskData.strStateFilePath; 11794 11829 11795 11830 /* save all VM settings */ … … 11800 11835 else 11801 11836 { 11802 /* delete the saved state file (it might have been already created) */ 11803 RTFileDelete(mConsoleTaskData.mStateFilePath.c_str()); 11837 // delete the saved state file (it might have been already created); 11838 // we need not check whether this is shared with a snapshot here because 11839 // we certainly created this saved state file here anew 11840 RTFileDelete(mConsoleTaskData.strStateFilePath.c_str()); 11804 11841 } 11805 11842 … … 11821 11858 /* clear out the temporary saved state data */ 11822 11859 mConsoleTaskData.mLastState = MachineState_Null; 11823 mConsoleTaskData. mStateFilePath.setNull();11860 mConsoleTaskData.strStateFilePath.setNull(); 11824 11861 mConsoleTaskData.mProgress.setNull(); 11825 11862 11826 11863 LogFlowThisFuncLeave(); 11827 11864 return rc; 11865 } 11866 11867 /** 11868 * Deletes the given file if it is no longer in use by either the current machine state 11869 * (if the machine is "saved") or any of the machine's snapshots. 11870 * 11871 * Note: This checks mSSData->strStateFilePath, which is shared by the Machine and SessionMachine 11872 * but is different for each SnapshotMachine. When calling this, the order of calling this 11873 * function on the one hand and changing that variable OR the snapshots tree on the other hand 11874 * is therefore critical. I know, it's all rather messy. 11875 * 11876 * @param strStateFile 11877 * @param pSnapshotToIgnore Passed to Snapshot::sharesSavedStateFile(); this snapshot is ignored in the test for whether the saved state file is in use. 11878 */ 11879 void SessionMachine::releaseSavedStateFile(const Utf8Str &strStateFile, 11880 Snapshot *pSnapshotToIgnore) 11881 { 11882 // it is safe to delete this saved state file if it is not currently in use by the machine ... 11883 if ( (strStateFile.isNotEmpty()) 11884 && (strStateFile != mSSData->strStateFilePath) // session machine's saved state 11885 ) 11886 // ... and it must also not be shared with other snapshots 11887 if ( !mData->mFirstSnapshot 11888 || !mData->mFirstSnapshot->sharesSavedStateFile(strStateFile, pSnapshotToIgnore) 11889 // this checks the SnapshotMachine's state file paths 11890 ) 11891 RTFileDelete(strStateFile.c_str()); 11828 11892 } 11829 11893 … … 12079 12143 if (mRemoveSavedState) 12080 12144 { 12081 Assert(!mSSData->mStateFilePath.isEmpty()); 12082 RTFileDelete(mSSData->mStateFilePath.c_str()); 12083 } 12084 mSSData->mStateFilePath.setNull(); 12145 Assert(!mSSData->strStateFilePath.isEmpty()); 12146 12147 // it is safe to delete the saved state file if ... 12148 if ( !mData->mFirstSnapshot // ... we have no snapshots or 12149 || !mData->mFirstSnapshot->sharesSavedStateFile(mSSData->strStateFilePath, NULL /* pSnapshotToIgnore */) 12150 // ... none of the snapshots share the saved state file 12151 ) 12152 RTFileDelete(mSSData->strStateFilePath.c_str()); 12153 } 12154 12155 mSSData->strStateFilePath.setNull(); 12085 12156 stsFlags |= SaveSTS_StateFilePath; 12086 12157 } … … 12106 12177 { 12107 12178 /* the saved state file was adopted */ 12108 Assert(!mSSData-> mStateFilePath.isEmpty());12179 Assert(!mSSData->strStateFilePath.isEmpty()); 12109 12180 stsFlags |= SaveSTS_StateFilePath; 12110 12181 } -
trunk/src/VBox/Main/src-server/SnapshotImpl.cpp
r35984 r36074 428 428 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 429 429 430 *aOnline = !stateFilePath().isEmpty();430 *aOnline = getStateFilePath().isNotEmpty(); 431 431 return S_OK; 432 432 } … … 504 504 * Must be called from under the object's lock! 505 505 */ 506 const Utf8Str& Snapshot::stateFilePath() const 507 { 508 return m->pMachine->mSSData->mStateFilePath; 509 } 510 511 /** 512 * @note 513 * Must be called from under the object's write lock! 514 */ 515 HRESULT Snapshot::deleteStateFile() 516 { 517 int vrc = RTFileDelete(m->pMachine->mSSData->mStateFilePath.c_str()); 518 if (RT_SUCCESS(vrc)) 519 m->pMachine->mSSData->mStateFilePath.setNull(); 520 return RT_SUCCESS(vrc) ? S_OK : E_FAIL; 506 const Utf8Str& Snapshot::getStateFilePath() const 507 { 508 return m->pMachine->mSSData->strStateFilePath; 521 509 } 522 510 … … 688 676 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 689 677 690 const Utf8Str &path = m->pMachine->mSSData-> mStateFilePath;678 const Utf8Str &path = m->pMachine->mSSData->strStateFilePath; 691 679 LogFlowThisFunc(("Snap[%s].statePath={%s}\n", m->strName.c_str(), path.c_str())); 692 680 … … 696 684 ) 697 685 { 698 m->pMachine->mSSData-> mStateFilePath = Utf8StrFmt("%s%s",699 strNewPath.c_str(),700 path.c_str() + strOldPath.length());686 m->pMachine->mSSData->strStateFilePath = Utf8StrFmt("%s%s", 687 strNewPath.c_str(), 688 path.c_str() + strOldPath.length()); 701 689 LogFlowThisFunc(("-> updated: {%s}\n", path.c_str())); 702 690 } … … 710 698 } 711 699 } 700 701 /** 702 * Returns true if this snapshot or one of its children uses the given file, 703 * whose path must be fully qualified, as its saved state. When invoked on a 704 * machine's first snapshot, this can be used to check if a saved state file 705 * is shared with any snapshots. 706 * 707 * Caller must hold the machine lock, which protects the snapshots tree. 708 * 709 * @param strPath 710 * @param pSnapshotToIgnore If != NULL, this snapshot is ignored during the checks. 711 * @return 712 */ 713 bool Snapshot::sharesSavedStateFile(const Utf8Str &strPath, 714 Snapshot *pSnapshotToIgnore) 715 { 716 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 717 const Utf8Str &path = m->pMachine->mSSData->strStateFilePath; 718 719 if (!pSnapshotToIgnore || pSnapshotToIgnore != this) 720 if (path.isNotEmpty()) 721 if (path == strPath) 722 return true; // no need to recurse then 723 724 // but otherwise we must check children 725 for (SnapshotsList::const_iterator it = m->llChildren.begin(); 726 it != m->llChildren.end(); 727 ++it) 728 { 729 Snapshot *pChild = *it; 730 if (!pSnapshotToIgnore || pSnapshotToIgnore != pChild) 731 if (pChild->sharesSavedStateFile(strPath, pSnapshotToIgnore)) 732 return true; 733 } 734 735 return false; 736 } 737 712 738 713 739 /** … … 757 783 return S_OK; 758 784 759 / * stateFile (optional) */760 if ( !stateFilePath().isEmpty())761 m->pMachine->copyPathRelativeToMachine( stateFilePath(), data.strStateFile);785 // state file (only if this snapshot is online) 786 if (getStateFilePath().isNotEmpty()) 787 m->pMachine->copyPathRelativeToMachine(getStateFilePath(), data.strStateFile); 762 788 else 763 789 data.strStateFile.setNull(); … … 870 896 return rc; 871 897 872 // now report the saved state file 873 if (!m->pMachine->mSSData->mStateFilePath.isEmpty()) 874 llFilenames.push_back(m->pMachine->mSSData->mStateFilePath); 898 // report the saved state file if it's not on the list yet 899 if (!m->pMachine->mSSData->strStateFilePath.isEmpty()) 900 { 901 bool fFound = false; 902 for (std::list<Utf8Str>::const_iterator it = llFilenames.begin(); 903 it != llFilenames.end(); 904 ++it) 905 { 906 const Utf8Str &str = *it; 907 if (str == m->pMachine->mSSData->strStateFilePath) 908 { 909 fFound = true; 910 break; 911 } 912 } 913 if (!fFound) 914 llFilenames.push_back(m->pMachine->mSSData->strStateFilePath); 915 } 875 916 876 917 this->beginSnapshotDelete(); … … 952 993 /* SSData is always unique for SnapshotMachine */ 953 994 mSSData.allocate(); 954 mSSData-> mStateFilePath = aStateFilePath;995 mSSData->strStateFilePath = aStateFilePath; 955 996 956 997 HRESULT rc = S_OK; … … 1090 1131 /* SSData is always unique for SnapshotMachine */ 1091 1132 mSSData.allocate(); 1092 mSSData-> mStateFilePath = aStateFilePath;1133 mSSData->strStateFilePath = aStateFilePath; 1093 1134 1094 1135 /* create all other child objects that will be immutable private copies */ … … 1262 1303 RestoreSnapshotTask(SessionMachine *m, 1263 1304 Progress *p, 1264 Snapshot *s, 1265 ULONG ulStateFileSizeMB) 1266 : SnapshotTask(m, p, s), 1267 m_ulStateFileSizeMB(ulStateFileSizeMB) 1305 Snapshot *s) 1306 : SnapshotTask(m, p, s) 1268 1307 {} 1269 1308 … … 1272 1311 pMachine->restoreSnapshotHandler(*this); 1273 1312 } 1274 1275 ULONG m_ulStateFileSizeMB;1276 1313 }; 1277 1314 … … 1399 1436 Utf8Str strStateFilePath; 1400 1437 /* stateFilePath is null when the machine is not online nor saved */ 1401 if ( fTakingSnapshotOnline1402 || mData->mMachineState == MachineState_Saved)1403 {1404 Utf8Str strFullSnapshotFolder;1405 calculateFullPath(mUserData->s.strSnapshotFolder, strFullSnapshotFolder);1406 strStateFilePath = Utf8StrFmt("%s%c{%RTuuid}.sav",1407 strFullSnapshotFolder.c_str(), 1408 RTPATH_DELIMITER,1409 snapshotId.raw());1410 / * ensure the directory for the saved state file exists */1438 if (fTakingSnapshotOnline) 1439 // creating a new online snapshot: then we need a fresh saved state file 1440 composeSavedStateFilename(strStateFilePath); 1441 else if (mData->mMachineState == MachineState_Saved) 1442 // taking an online snapshot from machine in "saved" state: then use existing state file 1443 strStateFilePath = mSSData->strStateFilePath; 1444 1445 if (strStateFilePath.isNotEmpty()) 1446 { 1447 // ensure the directory for the saved state file exists 1411 1448 HRESULT rc = VirtualBox::ensureFilePathExists(strStateFilePath); 1412 1449 if (FAILED(rc)) return rc; … … 1464 1501 throw rc; 1465 1502 1466 if (mConsoleTaskData.mLastState == MachineState_Saved)1467 {1468 Utf8Str stateFrom = mSSData->mStateFilePath;1469 Utf8Str stateTo = mConsoleTaskData.mSnapshot->stateFilePath();1470 1471 LogFlowThisFunc(("Copying the execution state from '%s' to '%s'...\n",1472 stateFrom.c_str(), stateTo.c_str()));1473 1474 aConsoleProgress->SetNextOperation(Bstr(tr("Copying the execution state")).raw(),1475 1); // weight1476 1477 /* Leave the lock before a lengthy operation (machine is protected1478 * by "Saving" machine state now) */1479 alock.release();1480 1481 /* copy the state file */1482 int vrc = RTFileCopyEx(stateFrom.c_str(),1483 stateTo.c_str(),1484 0,1485 progressCallback,1486 aConsoleProgress);1487 alock.acquire();1488 1489 if (RT_FAILURE(vrc))1490 /** @todo r=bird: Delete stateTo when appropriate. */1491 throw setError(E_FAIL,1492 tr("Could not copy the state file '%s' to '%s' (%Rrc)"),1493 stateFrom.c_str(),1494 stateTo.c_str(),1495 vrc);1496 }1497 1498 1503 // if we got this far without an error, then save the media registries 1499 1504 // that got modified for the diff images … … 1596 1601 1597 1602 rc = saveSettings(NULL, flSaveSettings); 1598 // no need to change for whether VirtualBox.xml needs saving since1599 // we'll save the global settings below anyway1600 1603 } 1601 1604 … … 1618 1621 mData->mCurrentSnapshot = pOldCurrentSnap; // might have been changed above 1619 1622 1620 /* delete the saved state file (it might have been already created) */ 1621 if (mConsoleTaskData.mSnapshot->stateFilePath().length()) 1622 RTFileDelete(mConsoleTaskData.mSnapshot->stateFilePath().c_str()); 1623 // delete the saved state file (it might have been already created) 1624 if (fOnline) 1625 // no need to test for whether the saved state file is shared: an online 1626 // snapshot means that a new saved state file was created, which we must 1627 // clean up now 1628 RTFileDelete(mConsoleTaskData.mSnapshot->getStateFilePath().c_str()); 1623 1629 1624 1630 mConsoleTaskData.mSnapshot->uninit(); … … 1628 1634 mConsoleTaskData.mLastState = MachineState_Null; 1629 1635 mConsoleTaskData.mSnapshot.setNull(); 1630 1631 // save VirtualBox.xml (media registry most probably changed with diff image);1632 // for that we should hold only the VirtualBox lock1633 machineLock.release();1634 AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);1635 mParent->saveSettings();1636 1636 1637 1637 return rc; … … 1708 1708 } 1709 1709 1710 ULONG ulStateFileSizeMB = 0;1711 if (pSnapshot->stateFilePath().length())1712 {1713 ++ulOpCount; // one for the saved state1714 1715 uint64_t ullSize;1716 int irc = RTFileQuerySize(pSnapshot->stateFilePath().c_str(), &ullSize);1717 if (!RT_SUCCESS(irc))1718 // if we can't access the file here, then we'll be doomed later also, so fail right away1719 setError(E_FAIL, tr("Cannot access state file '%s', runtime error, %Rra"), pSnapshot->stateFilePath().c_str(), irc);1720 if (ullSize == 0) // avoid division by zero1721 ullSize = _1M;1722 1723 ulStateFileSizeMB = (ULONG)(ullSize / _1M);1724 LogFlowThisFunc(("op %d: saved state file '%s' has %RI64 bytes (%d MB)\n",1725 ulOpCount, pSnapshot->stateFilePath().c_str(), ullSize, ulStateFileSizeMB));1726 1727 ulTotalWeight += ulStateFileSizeMB;1728 }1729 1730 1710 ComObjPtr<Progress> pProgress; 1731 1711 pProgress.createObject(); … … 1742 1722 RestoreSnapshotTask *task = new RestoreSnapshotTask(this, 1743 1723 pProgress, 1744 pSnapshot, 1745 ulStateFileSizeMB); 1724 pSnapshot); 1746 1725 int vrc = RTThreadCreate(NULL, 1747 1726 taskHandler, … … 1822 1801 if (aTask.machineStateBackup == MachineState_Saved) 1823 1802 { 1824 Assert(!mSSData->mStateFilePath.isEmpty()); 1825 RTFileDelete(mSSData->mStateFilePath.c_str()); 1826 mSSData->mStateFilePath.setNull(); 1803 Assert(!mSSData->strStateFilePath.isEmpty()); 1804 1805 // release the saved state file AFTER unsetting the member variable 1806 // so that releaseSavedStateFile() won't think it's still in use 1807 Utf8Str strStateFile(mSSData->strStateFilePath); 1808 mSSData->strStateFilePath.setNull(); 1809 releaseSavedStateFile(strStateFile, NULL /* pSnapshotToIgnore */ ); 1810 1827 1811 aTask.modifyBackedUpState(MachineState_PoweredOff); 1812 1828 1813 rc = saveStateSettings(SaveSTS_StateFilePath); 1829 1814 if (FAILED(rc)) … … 1872 1857 1873 1858 /* should not have a saved state file associated at this point */ 1874 Assert(mSSData->mStateFilePath.isEmpty()); 1875 1876 if (!aTask.pSnapshot->stateFilePath().isEmpty()) 1877 { 1878 Utf8Str snapStateFilePath = aTask.pSnapshot->stateFilePath(); 1879 1880 Utf8Str strFullSnapshotFolder; 1881 calculateFullPath(mUserData->s.strSnapshotFolder, strFullSnapshotFolder); 1882 Utf8Str stateFilePath = Utf8StrFmt("%s%c{%RTuuid}.sav", 1883 strFullSnapshotFolder.c_str(), 1884 RTPATH_DELIMITER, 1885 mData->mUuid.raw()); 1886 1887 LogFlowThisFunc(("Copying saved state file from '%s' to '%s'...\n", 1888 snapStateFilePath.c_str(), stateFilePath.c_str())); 1889 1890 aTask.pProgress->SetNextOperation(Bstr(tr("Restoring the execution state")).raw(), 1891 aTask.m_ulStateFileSizeMB); // weight 1892 1893 /* leave the lock before the potentially lengthy operation */ 1894 snapshotLock.release(); 1895 alock.leave(); 1896 1897 /* copy the state file */ 1898 RTFileDelete(stateFilePath.c_str()); 1899 int vrc = RTFileCopyEx(snapStateFilePath.c_str(), 1900 stateFilePath.c_str(), 1901 0, 1902 progressCallback, 1903 static_cast<IProgress*>(aTask.pProgress)); 1904 1905 alock.enter(); 1906 snapshotLock.acquire(); 1907 1908 if (RT_SUCCESS(vrc)) 1909 mSSData->mStateFilePath = stateFilePath; 1910 else 1911 throw setError(E_FAIL, 1912 tr("Could not copy the state file '%s' to '%s' (%Rrc)"), 1913 snapStateFilePath.c_str(), 1914 stateFilePath.c_str(), 1915 vrc); 1916 } 1859 Assert(mSSData->strStateFilePath.isEmpty()); 1860 1861 const Utf8Str &strSnapshotStateFile = aTask.pSnapshot->getStateFilePath(); 1862 1863 if (strSnapshotStateFile.isNotEmpty()) 1864 // online snapshot: then share the state file 1865 mSSData->strStateFilePath = strSnapshotStateFile; 1917 1866 1918 1867 LogFlowThisFunc(("Setting new current snapshot {%RTuuid}\n", aTask.pSnapshot->getId().raw())); … … 1950 1899 /* we have already deleted the current state, so set the execution 1951 1900 * state accordingly no matter of the delete snapshot result */ 1952 if ( !mSSData->mStateFilePath.isEmpty())1901 if (mSSData->strStateFilePath.isNotEmpty()) 1953 1902 setMachineState(MachineState_Saved); 1954 1903 else … … 2144 2093 ULONG ulTotalWeight = 1; // one for preparations 2145 2094 2146 if (pSnapshot-> stateFilePath().length())2095 if (pSnapshot->getStateFilePath().length()) 2147 2096 { 2148 2097 ++ulOpCount; … … 2529 2478 AutoWriteLock machineLock(this COMMA_LOCKVAL_SRC_POS); 2530 2479 2531 Utf8Str stateFilePath = aTask.pSnapshot-> stateFilePath();2480 Utf8Str stateFilePath = aTask.pSnapshot->getStateFilePath(); 2532 2481 if (!stateFilePath.isEmpty()) 2533 2482 { … … 2535 2484 1); // weight 2536 2485 2537 aTask.pSnapshot->deleteStateFile(); 2538 // machine needs saving now 2486 releaseSavedStateFile(stateFilePath, aTask.pSnapshot /* pSnapshotToIgnore */); 2487 2488 // machine will need saving now 2539 2489 mParent->addGuidToListUniquely(llRegistriesThatNeedSaving, getId()); 2540 2490 }
Note:
See TracChangeset
for help on using the changeset viewer.