Changeset 36074 in vbox for trunk/src/VBox/Main/src-server/SnapshotImpl.cpp
- Timestamp:
- Feb 24, 2011 3:38:25 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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.