VirtualBox

Changeset 19036 in vbox


Ignore:
Timestamp:
Apr 20, 2009 3:55:29 PM (16 years ago)
Author:
vboxsync
Message:

Main/HardDisk: implement compact functionality

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

Legend:

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

    r18813 r19036  
    5959{
    6060    enum Operation { CreateBase, CreateDiff,
    61                      Merge, Clone, Delete, Reset };
     61                     Merge, Clone, Delete, Reset, Compact };
    6262
    6363    HardDisk *that;
     
    104104    }
    105105
    106     void setData (CloneChain *aSrcChain, CloneChain *aParentChain)
     106    void setData (ImageChain *aSrcChain, ImageChain *aParentChain)
    107107    {
    108108        AssertReturnVoid (aSrcChain != NULL);
     
    112112    }
    113113
     114    void setData (ImageChain *aImgChain)
     115    {
     116        AssertReturnVoid (aImgChain != NULL);
     117        d.images.reset (aImgChain);
     118    }
     119
    114120    HRESULT startThread();
    115121    HRESULT runNow();
     
    134140
    135141        /** Hard disks to open, in {parent,child} order */
    136         std::auto_ptr <CloneChain> source;
     142        std::auto_ptr <ImageChain> source;
    137143        /** Hard disks which are parent of target, in {parent,child} order */
    138         std::auto_ptr <CloneChain> parent;
     144        std::auto_ptr <ImageChain> parent;
    139145        /** The to-be parent hard disk object */
    140146        ComObjPtr<HardDisk> parentDisk;
     
    144150        /** Hard disks to merge, in {parent,child} order */
    145151        std::auto_ptr <MergeChain> chain;
     152
     153        /* Compact */
     154
     155        /** Hard disks to open, in {parent,child} order */
     156        std::auto_ptr <ImageChain> images;
    146157    }
    147158    d;
     
    458469
    459470/**
    460  * Helper class for clone operations.
     471 * Helper class for image operations involving the entire parent chain.
    461472 *
    462473 * @note It is assumed that when modifying methods of this class are called,
    463474 *       HardDisk::treeLock() is held in read mode.
    464475 */
    465 class HardDisk::CloneChain : public HardDisk::List,
     476class HardDisk::ImageChain : public HardDisk::List,
    466477                             public com::SupportErrorInfoBase
    467478{
    468479public:
    469480
    470     CloneChain () {}
    471 
    472     ~CloneChain()
    473     {
    474         for (iterator it = begin(); it != end(); ++ it)
     481    ImageChain () {}
     482
     483    ~ImageChain()
     484    {
     485        List::const_iterator last = end();
     486        last--;
     487        for (List::const_iterator it = begin(); it != end(); ++ it)
    475488        {
    476489            AutoWriteLock alock (*it);
    477             Assert ((*it)->m.state == MediaState_LockedRead);
    478             if ((*it)->m.state == MediaState_LockedRead)
    479                 (*it)->UnlockRead (NULL);
     490            if (it == last)
     491            {
     492                Assert (   (*it)->m.state == MediaState_LockedRead
     493                        || (*it)->m.state == MediaState_LockedWrite);
     494                if ((*it)->m.state == MediaState_LockedRead)
     495                    (*it)->UnlockRead (NULL);
     496                else if ((*it)->m.state == MediaState_LockedWrite)
     497                    (*it)->UnlockWrite (NULL);
     498            }
     499            else
     500            {
     501                Assert ((*it)->m.state == MediaState_LockedRead);
     502                if ((*it)->m.state == MediaState_LockedRead)
     503                    (*it)->UnlockRead (NULL);
     504            }
    480505
    481506            (*it)->releaseCaller();
     
    512537                CheckComRCReturnRC (rc);
    513538                Assert (mediaState == MediaState_LockedRead);
     539
     540                /* Note that we locked the medium already, so use the error
     541                 * value to see if there was an accessibility failure */
     542                Bstr error;
     543                rc = (*it)->COMGETTER(LastAccessError) (error.asOutParam());
     544                CheckComRCReturnRC (rc);
     545
     546                if (!error.isNull())
     547                {
     548                    Bstr loc;
     549                    rc = (*it)->COMGETTER(Location) (loc.asOutParam());
     550                    CheckComRCThrowRC (rc);
     551
     552                    /* collect multiple errors */
     553                    eik.restore();
     554
     555                    /* be in sync with MediumBase::setStateError() */
     556                    Assert (!error.isEmpty());
     557                    mrc = setError (E_FAIL,
     558                        tr ("Medium '%ls' is not accessible. %ls"),
     559                        loc.raw(), error.raw());
     560
     561                    eik.fetch();
     562                }
     563            }
     564        }
     565
     566        eik.restore();
     567        CheckComRCReturnRC ((HRESULT) mrc);
     568
     569        return S_OK;
     570    }
     571
     572    HRESULT lockImagesReadAndLastWrite ()
     573    {
     574        /* Lock all disks in the chain in {parent, child} order,
     575         * and make sure they are accessible. */
     576        /// @todo code duplication with SessionMachine::lockMedia, see below
     577        ErrorInfoKeeper eik (true /* aIsNull */);
     578        MultiResult mrc (S_OK);
     579        List::const_iterator last = end();
     580        last--;
     581        for (List::const_iterator it = begin(); it != end(); ++ it)
     582        {
     583            HRESULT rc = S_OK;
     584            MediaState_T mediaState;
     585            if (it == last)
     586                rc = (*it)->LockWrite(&mediaState);
     587            else
     588                rc = (*it)->LockRead(&mediaState);
     589            CheckComRCReturnRC (rc);
     590
     591            if (mediaState == MediaState_Inaccessible)
     592            {
     593                rc = (*it)->COMGETTER(State) (&mediaState);
     594                CheckComRCReturnRC (rc);
     595                if (it == last)
     596                    Assert (mediaState == MediaState_LockedWrite);
     597                else
     598                    Assert (mediaState == MediaState_LockedRead);
    514599
    515600                /* Note that we locked the medium already, so use the error
     
    14891574
    14901575        /* Build the source chain and lock images in the proper order. */
    1491         std::auto_ptr <CloneChain> srcChain (new CloneChain ());
     1576        std::auto_ptr <ImageChain> srcChain (new ImageChain ());
    14921577
    14931578        /* we walk the source tree */
     
    15021587
    15031588        /* Build the parent chain and lock images in the proper order. */
    1504         std::auto_ptr <CloneChain> parentChain (new CloneChain ());
     1589        std::auto_ptr <ImageChain> parentChain (new ImageChain ());
    15051590
    15061591        /* we walk the future parent tree */
     
    15631648    CheckComRCReturnRC (autoCaller.rc());
    15641649
    1565     ReturnComNotImplemented();
     1650    AutoWriteLock alock (this);
     1651
     1652    ComObjPtr <Progress> progress;
     1653
     1654    HRESULT rc = S_OK;
     1655
     1656    try
     1657    {
     1658        /** @todo separate out creating/locking an image chain from
     1659         * SessionMachine::lockMedia and use it from here too.
     1660         * logically this belongs into HardDisk functionality. */
     1661
     1662        /* Build the image chain and lock images in the proper order. */
     1663        std::auto_ptr <ImageChain> imgChain (new ImageChain ());
     1664
     1665        /* we walk the image tree */
     1666        AutoReadLock srcTreeLock (this->treeLock());
     1667        for (HardDisk *hd = this; hd; hd = hd->mParent)
     1668        {
     1669            rc = imgChain->addImage(hd);
     1670            CheckComRCThrowRC (rc);
     1671        }
     1672        rc = imgChain->lockImagesReadAndLastWrite();
     1673        CheckComRCThrowRC (rc);
     1674
     1675        progress.createObject();
     1676        rc = progress->init (mVirtualBox, static_cast <IHardDisk *> (this),
     1677            BstrFmt (tr ("Compacting hard disk '%ls'"), m.locationFull.raw()),
     1678            TRUE /* aCancelable */);
     1679        CheckComRCThrowRC (rc);
     1680
     1681        /* setup task object and thread to carry out the operation
     1682         * asynchronously */
     1683
     1684        std::auto_ptr <Task> task (new Task (this, progress, Task::Compact));
     1685        AssertComRCThrowRC (task->autoCaller.rc());
     1686
     1687        task->setData (imgChain.release());
     1688
     1689        rc = task->startThread();
     1690        CheckComRCThrowRC (rc);
     1691
     1692        /* task is now owned (or already deleted) by taskThread() so release it */
     1693        task.release();
     1694    }
     1695    catch (HRESULT aRC)
     1696    {
     1697        rc = aRC;
     1698    }
     1699
     1700    if (SUCCEEDED (rc))
     1701    {
     1702        /* return progress to the caller */
     1703        progress.queryInterfaceTo (aProgress);
     1704    }
     1705
     1706    return rc;
    15661707}
    15671708
     
    41094250            AutoMultiWriteLock3 thatLock (that, target, parent);
    41104251
    4111             CloneChain *srcChain = task->d.source.get();
    4112             CloneChain *parentChain = task->d.parent.get();
     4252            ImageChain *srcChain = task->d.source.get();
     4253            ImageChain *parentChain = task->d.parent.get();
    41134254
    41144255            uint64_t size = 0, logicalSize = 0;
     
    44574598        }
    44584599
     4600        ////////////////////////////////////////////////////////////////////////
     4601
     4602        case Task::Compact:
     4603        {
     4604            /* Lock all in {parent,child} order. The lock is also used as a
     4605             * signal from the task initiator (which releases it only after
     4606             * RTThreadCreate()) that we can start the job. */
     4607            AutoWriteLock thatLock (that);
     4608
     4609            ImageChain *imgChain = task->d.images.get();
     4610
     4611            try
     4612            {
     4613                PVBOXHDD hdd;
     4614                int vrc = VDCreate (that->mm.vdDiskIfaces, &hdd);
     4615                ComAssertRCThrow (vrc, E_FAIL);
     4616
     4617                try
     4618                {
     4619                    /* Open all hard disk images in the chain. */
     4620                    List::const_iterator last = imgChain->end();
     4621                    last--;
     4622                    for (List::const_iterator it = imgChain->begin();
     4623                         it != imgChain->end(); ++ it)
     4624                    {
     4625                        /* sanity check */
     4626                        if (it == last)
     4627                            Assert ((*it)->m.state == MediaState_LockedWrite);
     4628                        else
     4629                            Assert ((*it)->m.state == MediaState_LockedRead);
     4630
     4631                        /** Open all images but last in read-only mode. */
     4632                        vrc = VDOpen (hdd, Utf8Str ((*it)->mm.format),
     4633                                      Utf8Str ((*it)->m.locationFull),
     4634                                      (it == last) ? VD_OPEN_FLAGS_NORMAL : VD_OPEN_FLAGS_READONLY,
     4635                                      (*it)->mm.vdDiskIfaces);
     4636                        if (RT_FAILURE (vrc))
     4637                        {
     4638                            throw setError (E_FAIL,
     4639                                tr ("Could not open the hard disk storage "
     4640                                    "unit '%s'%s"),
     4641                                Utf8Str ((*it)->m.locationFull).raw(),
     4642                                that->vdError (vrc).raw());
     4643                        }
     4644                    }
     4645
     4646                    /* unlock before the potentially lengthy operation */
     4647                    thatLock.leave();
     4648
     4649                    Assert (that->m.state == MediaState_LockedWrite);
     4650
     4651                    /* needed for vdProgressCallback */
     4652                    that->mm.vdProgress = task->progress;
     4653
     4654                    vrc = VDCompact (hdd, VD_LAST_IMAGE, that->mm.vdDiskIfaces);
     4655
     4656                    that->mm.vdProgress = NULL;
     4657
     4658                    if (RT_FAILURE (vrc))
     4659                    {
     4660                        if (vrc == VERR_NOT_SUPPORTED)
     4661                            throw setError(VBOX_E_NOT_SUPPORTED,
     4662                                           tr("Compacting is not supported yet for hard disk '%s'"),
     4663                                           Utf8Str (that->m.locationFull).raw());
     4664                        else if (vrc == VERR_NOT_IMPLEMENTED)
     4665                            throw setError(E_NOTIMPL,
     4666                                           tr("Compacting is not implemented, hard disk '%s'"),
     4667                                           Utf8Str (that->m.locationFull).raw());
     4668                        else
     4669                            throw setError (E_FAIL,
     4670                                tr ("Could not compact hard disk '%s'%s"),
     4671                                    Utf8Str (that->m.locationFull).raw(),
     4672                                    that->vdError (vrc).raw());
     4673                    }
     4674                }
     4675                catch (HRESULT aRC) { rc = aRC; }
     4676
     4677                VDDestroy (hdd);
     4678            }
     4679            catch (HRESULT aRC) { rc = aRC; }
     4680
     4681            /* Everything is explicitly unlocked when the task exits,
     4682             * as the task destruction also destroys the image chain. */
     4683
     4684            break;
     4685        }
     4686
    44594687        default:
    44604688            AssertFailedReturn (VERR_GENERAL_FAILURE);
  • trunk/src/VBox/Main/include/HardDiskImpl.h

    r18388 r19036  
    5656
    5757    class MergeChain;
    58     class CloneChain;
     58    class ImageChain;
    5959
    6060    VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE (HardDisk)
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