VirtualBox

Changeset 32695 in vbox


Ignore:
Timestamp:
Sep 22, 2010 11:16:48 AM (14 years ago)
Author:
vboxsync
Message:

Main/Medium: new method exportFile which allows to export a medium using any VBoxHDD VFS implementation

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

Legend:

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

    r32691 r32695  
    561561};
    562562
     563class Medium::ExportTask : public Medium::Task
     564{
     565public:
     566    ExportTask(Medium *aMedium,
     567               Progress *aProgress,
     568               const char *aFilename,
     569               MediumFormat *aFormat,
     570               MediumVariant_T aVariant,
     571               void *aVDImageIOCallbacks,
     572               void *aVDImageIOUser,
     573               MediumLockList *aSourceMediumLockList,
     574               bool fKeepSourceMediumLockList = false)
     575        : Medium::Task(aMedium, aProgress),
     576          mpSourceMediumLockList(aSourceMediumLockList),
     577          mFilename(aFilename),
     578          mFormat(aFormat),
     579          mVariant(aVariant),
     580          mfKeepSourceMediumLockList(fKeepSourceMediumLockList)
     581    {
     582        AssertReturnVoidStmt(aSourceMediumLockList != NULL, mRC = E_FAIL);
     583
     584        mVDImageIfaces = aMedium->m->vdImageIfaces;
     585        if (aVDImageIOCallbacks)
     586        {
     587            int vrc = VDInterfaceAdd(&mVDInterfaceIO, "Medium::vdInterfaceIO",
     588                                     VDINTERFACETYPE_IO, aVDImageIOCallbacks,
     589                                     aVDImageIOUser, &mVDImageIfaces);
     590            AssertRCReturnVoidStmt(vrc, mRC = E_FAIL);
     591        }
     592    }
     593
     594    ~ExportTask()
     595    {
     596        if (!mfKeepSourceMediumLockList && mpSourceMediumLockList)
     597            delete mpSourceMediumLockList;
     598    }
     599
     600    MediumLockList *mpSourceMediumLockList;
     601    Utf8Str mFilename;
     602    ComObjPtr<MediumFormat> mFormat;
     603    MediumVariant_T mVariant;
     604    PVDINTERFACE mVDImageIfaces;
     605
     606private:
     607    virtual HRESULT handler();
     608
     609    bool mfKeepSourceMediumLockList;
     610    VDINTERFACE mVDInterfaceIO;
     611};
     612
    563613/**
    564614 * Thread function for time-consuming medium tasks.
     
    684734{
    685735    return mMedium->taskMergeHandler(*this);
     736}
     737
     738/**
     739 * Implementation code for the "export" task.
     740 */
     741HRESULT Medium::ExportTask::handler()
     742{
     743    return mMedium->taskExportHandler(*this);
    686744}
    687745
     
    50545112}
    50555113
     5114
     5115HRESULT Medium::exportFile(const char *aFilename,
     5116                           ComObjPtr<MediumFormat> aFormat,
     5117                           MediumVariant_T aVariant,
     5118                           void *aVDImageIOCallbacks, void *aVDImageIOUser,
     5119                           ComObjPtr<Progress> aProgress)
     5120{
     5121    return E_FAIL;
     5122
     5123    AssertPtrReturn(aFilename, E_INVALIDARG);
     5124    AssertReturn(!aFormat.isNull(), E_INVALIDARG);
     5125    AssertReturn(!aProgress.isNull(), E_INVALIDARG);
     5126
     5127    AutoCaller autoCaller(this);
     5128    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     5129
     5130    HRESULT rc = S_OK;
     5131    Medium::Task *pTask = NULL;
     5132
     5133    try
     5134    {
     5135        // locking: we need the tree lock first because we access parent pointers
     5136        AutoReadLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
     5137        // and we need to write-lock the media involved
     5138        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     5139
     5140        /* Build the source lock list. */
     5141        MediumLockList *pSourceMediumLockList(new MediumLockList());
     5142        rc = createMediumLockList(true /* fFailIfInaccessible */,
     5143                                  false /* fMediumLockWrite */,
     5144                                  NULL,
     5145                                  *pSourceMediumLockList);
     5146        if (FAILED(rc))
     5147        {
     5148            delete pSourceMediumLockList;
     5149            throw rc;
     5150        }
     5151
     5152        rc = pSourceMediumLockList->Lock();
     5153        if (FAILED(rc))
     5154        {
     5155            delete pSourceMediumLockList;
     5156            throw setError(rc,
     5157                           tr("Failed to lock source media '%s'"),
     5158                           getLocationFull().c_str());
     5159        }
     5160
     5161        /* setup task object to carry out the operation asynchronously */
     5162        pTask = new Medium::ExportTask(this, aProgress, aFilename, aFormat,
     5163                                       aVariant, aVDImageIOCallbacks,
     5164                                       aVDImageIOUser, pSourceMediumLockList);
     5165        rc = pTask->rc();
     5166        AssertComRC(rc);
     5167        if (FAILED(rc))
     5168            throw rc;
     5169    }
     5170    catch (HRESULT aRC) { rc = aRC; }
     5171
     5172    if (SUCCEEDED(rc))
     5173        rc = startThread(pTask);
     5174    else if (pTask != NULL)
     5175        delete pTask;
     5176
     5177    return rc;
     5178}
     5179
    50565180////////////////////////////////////////////////////////////////////////////////
    50575181//
     
    68466970}
    68476971
     6972/**
     6973 * Implementation code for the "export" task.
     6974 *
     6975 * This only gets started from Medium::exportFile() and always runs
     6976 * asynchronously. It doesn't touch anything configuration related, so
     6977 * we never save the VirtualBox.xml file here.
     6978 *
     6979 * @param task
     6980 * @return
     6981 */
     6982HRESULT Medium::taskExportHandler(Medium::ExportTask &task)
     6983{
     6984    HRESULT rc = S_OK;
     6985
     6986    try
     6987    {
     6988        /* Lock all in {parent,child} order. The lock is also used as a
     6989         * signal from the task initiator (which releases it only after
     6990         * RTThreadCreate()) that we can start the job. */
     6991        AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
     6992
     6993        PVBOXHDD hdd;
     6994        int vrc = VDCreate(m->vdDiskIfaces, &hdd);
     6995        ComAssertRCThrow(vrc, E_FAIL);
     6996
     6997        try
     6998        {
     6999            /* Open all media in the source chain. */
     7000            MediumLockList::Base::const_iterator sourceListBegin =
     7001                task.mpSourceMediumLockList->GetBegin();
     7002            MediumLockList::Base::const_iterator sourceListEnd =
     7003                task.mpSourceMediumLockList->GetEnd();
     7004            for (MediumLockList::Base::const_iterator it = sourceListBegin;
     7005                 it != sourceListEnd;
     7006                 ++it)
     7007            {
     7008                const MediumLock &mediumLock = *it;
     7009                const ComObjPtr<Medium> &pMedium = mediumLock.GetMedium();
     7010                AutoReadLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
     7011
     7012                /* sanity check */
     7013                Assert(pMedium->m->state == MediumState_LockedRead);
     7014
     7015                /** Open all media in read-only mode. */
     7016                vrc = VDOpen(hdd,
     7017                             pMedium->m->strFormat.c_str(),
     7018                             pMedium->m->strLocationFull.c_str(),
     7019                             VD_OPEN_FLAGS_READONLY,
     7020                             pMedium->m->vdImageIfaces);
     7021                if (RT_FAILURE(vrc))
     7022                    throw setError(VBOX_E_FILE_ERROR,
     7023                                   tr("Could not open the medium storage unit '%s'%s"),
     7024                                   pMedium->m->strLocationFull.c_str(),
     7025                                   vdError(vrc).c_str());
     7026            }
     7027
     7028            Utf8Str targetFormat(task.mFormat->getId());
     7029            Utf8Str targetLocation(task.mFilename);
     7030
     7031            Assert(m->state == MediumState_LockedRead);
     7032
     7033            /* unlock before the potentially lengthy operation */
     7034            thisLock.release();
     7035
     7036            /* ensure the target directory exists */
     7037            rc = VirtualBox::ensureFilePathExists(targetLocation);
     7038            if (FAILED(rc))
     7039                throw rc;
     7040
     7041            PVBOXHDD targetHdd;
     7042            vrc = VDCreate(m->vdDiskIfaces, &targetHdd);
     7043            ComAssertRCThrow(vrc, E_FAIL);
     7044
     7045            try
     7046            {
     7047                vrc = VDCopy(hdd,
     7048                             VD_LAST_IMAGE,
     7049                             targetHdd,
     7050                             targetFormat.c_str(),
     7051                             targetLocation.c_str(),
     7052                             false /* fMoveByRename */,
     7053                             0 /* cbSize */,
     7054                             task.mVariant,
     7055                             NULL /* pDstUuid */,
     7056                             NULL /* pVDIfsOperation */,
     7057                             task.mVDImageIfaces,
     7058                             task.mVDOperationIfaces);
     7059                if (RT_FAILURE(vrc))
     7060                    throw setError(VBOX_E_FILE_ERROR,
     7061                                   tr("Could not create the clone medium '%s'%s"),
     7062                                   targetLocation.c_str(), vdError(vrc).c_str());
     7063            }
     7064            catch (HRESULT aRC) { rc = aRC; }
     7065
     7066            VDDestroy(targetHdd);
     7067        }
     7068        catch (HRESULT aRC) { rc = aRC; }
     7069
     7070        VDDestroy(hdd);
     7071    }
     7072    catch (HRESULT aRC) { rc = aRC; }
     7073
     7074    /* Everything is explicitly unlocked when the task exits,
     7075     * as the task destruction also destroys the source chain. */
     7076
     7077    /* Make sure the source chain is released early, otherwise it can
     7078     * lead to deadlocks with concurrent IAppliance activities. */
     7079    task.mpSourceMediumLockList->Clear();
     7080
     7081    return rc;
     7082}
     7083
    68487084/* vi: set tabstop=4 shiftwidth=4 expandtab: */
  • trunk/src/VBox/Main/include/MediumImpl.h

    r31777 r32695  
    243243    HRESULT fixParentUuidOfChildren(const MediaList &childrenToReparent);
    244244
     245    /**
     246     * Used by IAppliance to export disk images.
     247     *
     248     * @param aFilename             Filename to create (UTF8).
     249     * @param aFormat               Which medium format to use.
     250     * @param aVariant              Which exact image format variant to use.
     251     * @param aVDImageIOCallbacks   Pointer to the callback table for a
     252     *                              VDINTERFACEIO interface. May be NULL.
     253     * @param aVDImageIOUser        Opaque data for the callbacks.
     254     * @param aProgress             Progress object to use.
     255     * @return
     256     */
     257    HRESULT exportFile(const char *aFilename,
     258                       ComObjPtr<MediumFormat> aFormat,
     259                       MediumVariant_T aVariant,
     260                       void *aVDImageIOCallbacks, void *aVDImageIOUser,
     261                       ComObjPtr<Progress> aProgress);
     262
    245263    /** Returns a preferred format for a differencing hard disk. */
    246264    Utf8Str getPreferredDiffFormat();
     
    293311    class DeleteTask;
    294312    class MergeTask;
     313    class ExportTask;
    295314    friend class Task;
    296315    friend class CreateBaseTask;
     
    302321    friend class DeleteTask;
    303322    friend class MergeTask;
     323    friend class ExportTask;
    304324
    305325    HRESULT startThread(Medium::Task *pTask);
     
    314334    HRESULT taskCompactHandler(Medium::CompactTask &task);
    315335    HRESULT taskResizeHandler(Medium::ResizeTask &task);
     336    HRESULT taskExportHandler(Medium::ExportTask &task);
    316337
    317338    struct Data;            // opaque data struct, defined in MediumImpl.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