VirtualBox

Changeset 31228 in vbox


Ignore:
Timestamp:
Jul 29, 2010 7:44:50 PM (14 years ago)
Author:
vboxsync
Message:

Main: beginnings of deleting all snapshots in Machine::Unregister() -- works partially, more to be done

Location:
trunk/src/VBox/Main
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/MachineImpl.cpp

    r31225 r31228  
    35893589                        aDevice, aControllerPort, aControllerName);
    35903590
    3591     rc = detachDevice(pAttach, alock, &fNeedsSaveSettings);
     3591    rc = detachDevice(pAttach, alock, NULL /* pSnapshot */, &fNeedsSaveSettings);
    35923592
    35933593    if (fNeedsSaveSettings)
     
    40804080    // this list collects the files that should be reported
    40814081    // as to be deleted to the caller in aFiles
    4082     std::list<Bstr> llFilesForCaller;
     4082    std::list<Utf8Str> llFilesForCaller;
    40834083
    40844084    // discard saved state
     
    40874087        // add the saved state file to the list of files the caller should delete
    40884088        Assert(!mSSData->mStateFilePath.isEmpty());
    4089         llFilesForCaller.push_back(Bstr(mSSData->mStateFilePath));
     4089        llFilesForCaller.push_back(mSSData->mStateFilePath);
    40904090
    40914091        mSSData->mStateFilePath.setNull();
     
    40964096    }
    40974097
    4098     // @todo optionally nuke snapshots
    40994098    size_t snapshotCount = 0;
    41004099    if (mData->mFirstSnapshot)
    41014100        snapshotCount = mData->mFirstSnapshot->getAllChildrenCount() + 1;
    41024101    if (snapshotCount)
    4103         return setError(VBOX_E_INVALID_OBJECT_STATE,
    4104                         tr("Cannot unregister the machine '%ls' because it has %d snapshots"),
    4105                         mUserData->mName.raw(), snapshotCount);
     4102    {
     4103        if (fAutoCleanup)
     4104        {
     4105            // caller wants automatic detachment: then do that and report all media to the array
     4106
     4107            // Snapshot::beginDeletingSnapshot() needs the machine state to be this
     4108            MachineState_T oldState = mData->mMachineState;
     4109            mData->mMachineState = MachineState_DeletingSnapshot;
     4110
     4111            // make a copy of the first snapshot so the refcount does not drop to 0
     4112            // in beginDeletingSnapshot, which sets pFirstSnapshot to 0 (that hangs
     4113            // because of the AutoCaller voodoo)
     4114            ComObjPtr<Snapshot> pFirstSnapshot = mData->mFirstSnapshot;
     4115
     4116            // go!
     4117            pFirstSnapshot->uninitRecursively(alock, llMedia, llFilesForCaller);
     4118
     4119            mData->mMachineState = oldState;
     4120        }
     4121        else
     4122            return setError(VBOX_E_INVALID_OBJECT_STATE,
     4123                            tr("Cannot unregister the machine '%ls' because it has %d snapshots"),
     4124                            mUserData->mName.raw(), snapshotCount);
     4125    }
    41064126
    41074127    if (    !mMediaData.isNull()      // can be NULL if machine is inaccessible
     
    41094129       )
    41104130    {
    4111         // we have media attachments:
     4131        // we have media attachments: detach them all and add the Medium objects to our list
    41124132        if (fAutoCleanup)
    4113         {
    4114             // caller wants automatic detachment: then do that and report all media to the array
    4115 
    4116             // make a temporary list because detachDevice invalidates iterators into
    4117             // mMediaData->mAttachments
    4118             MediaData::AttachmentList llAttachments2 = mMediaData->mAttachments;
    4119 
    4120             for (MediaData::AttachmentList::iterator it = llAttachments2.begin();
    4121                  it != llAttachments2.end();
    4122                  ++it)
    4123             {
    4124                 ComObjPtr<MediumAttachment> pAttach = *it;
    4125                 ComObjPtr<Medium> pMedium = pAttach->getMedium();
    4126 
    4127                 if (!pMedium.isNull())
    4128                     llMedia.push_back(pMedium);
    4129 
    4130                 rc = detachDevice(pAttach,
    4131                                   alock,
    4132                                   NULL /* pfNeedsSaveSettings */);
    4133                 if (FAILED(rc))
    4134                     break;
    4135             };
    4136         }
     4133            detachAllMedia(alock, NULL /* pSnapshot */, llMedia);
    41374134        else
    41384135            return setError(VBOX_E_INVALID_OBJECT_STATE,
     
    41634160        {
    41644161            ComObjPtr<Medium> pMedium = *it;
    4165             Bstr bstrFile = pMedium->getLocationFull();
     4162            Utf8Str strFile = pMedium->getLocationFull();
    41664163
    41674164            AutoCaller autoCaller2(pMedium);
     
    41724169                                autoCaller2);
    41734170                // this uninitializes the medium
     4171
     4172            LogFlowThisFunc(("Medium::close() on %s yielded rc (%Rhra)\n", strFile.c_str(), rc));
    41744173
    41754174            if (rc == VBOX_E_OBJECT_IN_USE)
     
    41804179            else if (SUCCEEDED(rc))
    41814180                // report the path to the caller
    4182                 llFilesForCaller.push_back(bstrFile);
     4181                llFilesForCaller.push_back(strFile);
    41834182        }
    41844183    }
     
    41874186    SafeArray<BSTR> sfaFiles(llFilesForCaller.size());
    41884187    size_t i = 0;
    4189     for (std::list<Bstr>::iterator it = llFilesForCaller.begin();
     4188    for (std::list<Utf8Str>::iterator it = llFilesForCaller.begin();
    41904189         it != llFilesForCaller.end();
    41914190         ++it)
    4192         it->detachTo(&sfaFiles[i++]);
     4191        Bstr(*it).detachTo(&sfaFiles[i++]);
    41934192    sfaFiles.detachTo(ComSafeArrayOutArg(aFiles));
    41944193
     
    87108709 * @param pAttach Medium attachment to detach.
    87118710 * @param writeLock Machine write lock which the caller must have locked once. This may be released temporarily in here.
     8711 * @param pSnapshot If NULL, then the detachment is for the current machine. Otherwise this is for a SnapshotMachine, and this must be its snapshot.
    87128712 * @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
    87138713 *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
     
    87168716HRESULT Machine::detachDevice(MediumAttachment *pAttach,
    87178717                              AutoWriteLock &writeLock,
     8718                              Snapshot *pSnapshot,
    87188719                              bool *pfNeedsSaveSettings)
    87198720{
     
    87518752    mMediaData.backup();
    87528753
    8753     /* we cannot use erase (it) below because backup() above will create
    8754     * a copy of the list and make this copy active, but the iterator
    8755     * still refers to the original and is not valid for the copy */
     8754    // we cannot use erase (it) below because backup() above will create
     8755    // a copy of the list and make this copy active, but the iterator
     8756    // still refers to the original and is not valid for the copy
    87568757    mMediaData->mAttachments.remove(pAttach);
    87578758
    8758     /* For non-hard disk media, detach straight away. */
    8759     if (mediumType != DeviceType_HardDisk && !oldmedium.isNull())
    8760         oldmedium->detachFrom(mData->mUuid);
     8759    if (!oldmedium.isNull())
     8760    {
     8761        // if this is from a snapshot, do not defer detachment to commitMedia()
     8762        if (pSnapshot)
     8763            oldmedium->detachFrom(mData->mUuid, pSnapshot->getId());
     8764        // else if non-hard disk media, do not defer detachment to commitMedia() either
     8765        else if (mediumType != DeviceType_HardDisk)
     8766            oldmedium->detachFrom(mData->mUuid);
     8767    }
     8768
     8769    return S_OK;
     8770}
     8771
     8772/**
     8773 * Goes thru all medium attachments of the list and calls detachDevice() on each
     8774 * of them and attaches all Medium objects found in the process to the given list.
     8775 *
     8776 * This gets called from Machine::Unregister, both for the actual Machine and
     8777 * the SnapshotMachine objects that might be found in the snapshots.
     8778 *
     8779 * Requires caller and locking.
     8780 *
     8781 * @param writeLock Machine lock from top-level caller; this gets passed to detachDevice.
     8782 * @param llMedia Caller's list to receive Medium objects which got detached so caller can close() them.
     8783 * @param pSnapshot Must be NULL when called for a "real" Machine or a snapshot object if called for a SnapshotMachine.
     8784 * @return
     8785 */
     8786HRESULT Machine::detachAllMedia(AutoWriteLock &writeLock,
     8787                                Snapshot *pSnapshot,
     8788                                MediaList &llMedia)
     8789{
     8790    Assert(isWriteLockOnCurrentThread());
     8791
     8792    HRESULT rc;
     8793
     8794    // make a temporary list because detachDevice invalidates iterators into
     8795    // mMediaData->mAttachments
     8796    MediaData::AttachmentList llAttachments2 = mMediaData->mAttachments;
     8797
     8798    for (MediaData::AttachmentList::iterator it = llAttachments2.begin();
     8799         it != llAttachments2.end();
     8800         ++it)
     8801    {
     8802        ComObjPtr<MediumAttachment> pAttach = *it;
     8803        ComObjPtr<Medium> pMedium = pAttach->getMedium();
     8804
     8805        if (!pMedium.isNull())
     8806            llMedia.push_back(pMedium);
     8807
     8808        // real machine: then we need to use the proper method
     8809        rc = detachDevice(pAttach,
     8810                          writeLock,
     8811                          pSnapshot,
     8812                          NULL /* pfNeedsSaveSettings */);
     8813
     8814        if (FAILED(rc))
     8815            return rc;
     8816    }
    87618817
    87628818    return S_OK;
  • trunk/src/VBox/Main/SnapshotImpl.cpp

    r31224 r31228  
    251251
    252252        /* we've changed the base of the current state so mark it as
    253             * modified as it no longer guaranteed to be its copy */
     253         * modified as it no longer guaranteed to be its copy */
    254254        m->pMachine->mData->mCurrentStateModified = TRUE;
    255255    }
     
    809809
    810810    return saveSnapshotImpl(data, aAttrsOnly);
     811}
     812
     813/**
     814 * Part of the cleanup engine of Machine::Unregister().
     815 *
     816 * This recursively removes all medium attachments from the snapshot's machine
     817 * and returns the snapshot's saved state file name, if any, and then calls
     818 * uninit() on "this" itself.
     819 *
     820 * This recurses into children first, so the given MediaList receives child
     821 * media first before their parents. If the caller wants to close all media,
     822 * they should go thru the list from the beginning to the end because media
     823 * cannot be closed if they have children.
     824 *
     825 * This calls uninit() on itself, so the snapshots tree becomes invalid after this.
     826 * It does not alter the main machine's snapshot pointers (pFirstSnapshot, pCurrentSnapshot).
     827 *
     828 * Caller must hold the machine write lock (which protects the snapshots tree!)
     829 *
     830 * @param llFilenames
     831 * @return
     832 */
     833HRESULT Snapshot::uninitRecursively(AutoWriteLock &writeLock,
     834                                    MediaList &llMedia,
     835                                    std::list<Utf8Str> &llFilenames)
     836{
     837    Assert(m->pMachine->isWriteLockOnCurrentThread());
     838
     839    HRESULT rc = S_OK;
     840
     841    // recurse into children first so that the child media appear on
     842    // the list first; this way caller can close the media from the
     843    // beginning to the end because parent media can't be closed if
     844    // they have children
     845
     846    // make a copy of the children list since uninit() modifies it
     847    SnapshotsList llChildrenCopy(m->llChildren);
     848    for (SnapshotsList::iterator it = llChildrenCopy.begin();
     849         it != llChildrenCopy.end();
     850         ++it)
     851    {
     852        Snapshot *pChild = *it;
     853        rc = pChild->uninitRecursively(writeLock, llMedia, llFilenames);
     854        if (FAILED(rc))
     855            return rc;
     856    }
     857
     858    // now call detachAllMedia on the snapshot machine
     859    rc = m->pMachine->detachAllMedia(writeLock,
     860                                     this /* pSnapshot */,
     861                                     llMedia);
     862    if (FAILED(rc))
     863        return rc;
     864
     865    // now report the saved state file
     866    if (!m->pMachine->mSSData->mStateFilePath.isEmpty())
     867        llFilenames.push_back(m->pMachine->mSSData->mStateFilePath);
     868
     869    this->beginSnapshotDelete();
     870    this->uninit();
     871
     872    return S_OK;
    811873}
    812874
  • trunk/src/VBox/Main/include/MachineImpl.h

    r31218 r31228  
    778778    HRESULT detachDevice(MediumAttachment *pAttach,
    779779                         AutoWriteLock &writeLock,
     780                         Snapshot *pSnapshot,
    780781                         bool *pfNeedsSaveSettings);
     782    HRESULT detachAllMedia(AutoWriteLock &writeLock,
     783                           Snapshot *pSnapshot,
     784                           MediaList &llMedia);
    781785
    782786    void commitMedia(bool aOnline = false);
  • trunk/src/VBox/Main/include/SnapshotImpl.h

    r30764 r31228  
    3333
    3434class ATL_NO_VTABLE Snapshot :
    35     public VirtualBoxBase, // WithTypedChildren<Snapshot>,
     35    public VirtualBoxBase,
    3636    VBOX_SCRIPTABLE_IMPL(ISnapshot)
    3737{
     
    124124    HRESULT saveSnapshotImpl(settings::Snapshot &data, bool aAttrsOnly);
    125125
     126    HRESULT uninitRecursively(AutoWriteLock &writeLock,
     127                              MediaList &llMedia,
     128                              std::list<Utf8Str> &llFilenames);
     129
    126130private:
    127131    struct Data;            // opaque, defined in SnapshotImpl.cpp
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette