VirtualBox

Ignore:
Timestamp:
Jan 26, 2013 7:52:47 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
83369
Message:

Main/SnapshotImpl: Select merge direction based on the image size

File:
1 edited

Legend:

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

    r44381 r44395  
    45194519    else
    45204520        return setStateError();
     4521}
     4522
     4523/**
     4524 * Queries the preferred merge direction from this to the other medium, i.e.
     4525 * the one which requires the least amount of I/O and therefore time and
     4526 * disk consumption.
     4527 *
     4528 * @returns Status code.
     4529 * @retval  E_FAIL in case determining the merge direction fails for some reason,
     4530 *          for example if getting the size of the media fails. There is no
     4531 *          error set though and the caller is free to continue to find out
     4532 *          what was going wrong later. Leaves fMergeForward unset.
     4533 * @retval  VBOX_E_INVALID_OBJECT_STATE if both media are not related to each other
     4534 *          An error is set.
     4535 * @param pOther           The other medium to merge with.
     4536 * @param fMergeForward    Resulting preferred merge direction (out).
     4537 */
     4538HRESULT Medium::queryPreferredMergeDirection(const ComObjPtr<Medium> &pOther,
     4539                                             bool &fMergeForward)
     4540{
     4541    AssertReturn(pOther != NULL, E_FAIL);
     4542    AssertReturn(pOther != this, E_FAIL);
     4543
     4544    AutoCaller autoCaller(this);
     4545    AssertComRCReturnRC(autoCaller.rc());
     4546
     4547    AutoCaller otherCaller(pOther);
     4548    AssertComRCReturnRC(otherCaller.rc());
     4549
     4550    HRESULT rc = S_OK;
     4551    bool fThisParent = false; /**<< Flag whether this medium is the parent of pOther. */
     4552
     4553    try
     4554    {
     4555        // locking: we need the tree lock first because we access parent pointers
     4556        AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
     4557
     4558        /* more sanity checking and figuring out the current merge direction */
     4559        ComObjPtr<Medium> pMedium = getParent();
     4560        while (!pMedium.isNull() && pMedium != pOther)
     4561            pMedium = pMedium->getParent();
     4562        if (pMedium == pOther)
     4563            fThisParent = false;
     4564        else
     4565        {
     4566            pMedium = pOther->getParent();
     4567            while (!pMedium.isNull() && pMedium != this)
     4568                pMedium = pMedium->getParent();
     4569            if (pMedium == this)
     4570                fThisParent = true;
     4571            else
     4572            {
     4573                Utf8Str tgtLoc;
     4574                {
     4575                    AutoReadLock alock(pOther COMMA_LOCKVAL_SRC_POS);
     4576                    tgtLoc = pOther->getLocationFull();
     4577                }
     4578
     4579                AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     4580                throw setError(VBOX_E_INVALID_OBJECT_STATE,
     4581                               tr("Media '%s' and '%s' are unrelated"),
     4582                               m->strLocationFull.c_str(), tgtLoc.c_str());
     4583            }
     4584        }
     4585
     4586        /*
     4587         * Figure out the preferred merge direction. The current way is to
     4588         * get the current sizes of file based images and select the merge
     4589         * direction depending on the size.
     4590         *
     4591         * Can't use the VD API to get current size here as the media might
     4592         * be write locked by a running VM. Resort to RTFileQuerySize().
     4593         */
     4594        int vrc = VINF_SUCCESS;
     4595        uint64_t cbMediumThis = 0;
     4596        uint64_t cbMediumOther = 0;
     4597
     4598        if (isMediumFormatFile() && pOther->isMediumFormatFile())
     4599        {
     4600            vrc = RTFileQuerySize(this->getLocationFull().c_str(), &cbMediumThis);
     4601            if (RT_SUCCESS(vrc))
     4602            {
     4603                vrc = RTFileQuerySize(pOther->getLocationFull().c_str(),
     4604                                      &cbMediumOther);
     4605            }
     4606
     4607            if (RT_FAILURE(vrc))
     4608                rc = E_FAIL;
     4609            else
     4610            {
     4611                /*
     4612                 * Check which merge direction might be more optimal.
     4613                 * This method is not bullet proof of course as there might
     4614                 * be overlapping blocks in the images so the file size is
     4615                 * not the best indicator but it is good enough for our purpose
     4616                 * and everything else is too complicated, especially when the
     4617                 * media are used by a running VM.
     4618                 */
     4619                bool fMergeIntoThis = cbMediumThis > cbMediumOther;
     4620                fMergeForward = fMergeIntoThis ^ fThisParent;
     4621            }
     4622        }
     4623    }
     4624    catch (HRESULT aRC) { rc = aRC; }
     4625
     4626    return rc;
    45214627}
    45224628
Note: See TracChangeset for help on using the changeset viewer.

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