VirtualBox

Changeset 25888 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Jan 18, 2010 12:16:07 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
56697
Message:

Main: split up huge Medium task thread function, part 4 (done)

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

Legend:

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

    r25887 r25888  
    56415641}
    56425642
     5643/**
     5644 * Implementation code called from Medium::taskThread for the "delete" task.
     5645 * @return
     5646 */
     5647HRESULT Medium::taskThreadDelete()
     5648{
     5649    HRESULT rc = S_OK;
     5650
     5651    /* The lock is also used as a signal from the task initiator (which
     5652     * releases it only after RTThreadCreate()) that we can start the job */
     5653    AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
     5654
     5655    try
     5656    {
     5657        PVBOXHDD hdd;
     5658        int vrc = VDCreate(m->vdDiskIfaces, &hdd);
     5659        ComAssertRCThrow(vrc, E_FAIL);
     5660
     5661        Utf8Str format(m->strFormat);
     5662        Utf8Str location(m->strLocationFull);
     5663
     5664        /* unlock before the potentially lengthy operation */
     5665        Assert(m->state == MediumState_Deleting);
     5666        thisLock.leave();
     5667
     5668        try
     5669        {
     5670            vrc = VDOpen(hdd,
     5671                         format.c_str(),
     5672                         location.c_str(),
     5673                         VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
     5674                         m->vdDiskIfaces);
     5675            if (RT_SUCCESS(vrc))
     5676                vrc = VDClose(hdd, true /* fDelete */);
     5677
     5678            if (RT_FAILURE(vrc))
     5679                throw setError(E_FAIL,
     5680                                tr("Could not delete the hard disk storage unit '%s'%s"),
     5681                                location.raw(), vdError(vrc).raw());
     5682
     5683        }
     5684        catch (HRESULT aRC) { rc = aRC; }
     5685
     5686        VDDestroy(hdd);
     5687    }
     5688    catch (HRESULT aRC) { rc = aRC; }
     5689
     5690    thisLock.maybeEnter();
     5691
     5692    /* go to the NotCreated state even on failure since the storage
     5693        * may have been already partially deleted and cannot be used any
     5694        * more. One will be able to manually re-open the storage if really
     5695        * needed to re-register it. */
     5696    m->state = MediumState_NotCreated;
     5697
     5698    /* Reset UUID to prevent Create* from reusing it again */
     5699    unconst(m->id).clear();
     5700
     5701    return rc;
     5702}
     5703
     5704/**
     5705 * Implementation code called from Medium::taskThread for the "reset" task.
     5706 * @param task
     5707 * @param pvdOperationIfaces
     5708 * @return
     5709 */
     5710HRESULT Medium::taskThreadReset(void *pvdOperationIfaces, bool fIsAsync)
     5711{
     5712    HRESULT rc = S_OK;
     5713
     5714    PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces;
     5715
     5716    /* The lock is also used as a signal from the task initiator (which
     5717     * releases it only after RTThreadCreate()) that we can start the job */
     5718    AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
     5719
     5720    /// @todo Below we use a pair of delete/create operations to reset
     5721    /// the diff contents but the most efficient way will of course be
     5722    /// to add a VDResetDiff() API call
     5723
     5724    uint64_t size = 0, logicalSize = 0;
     5725
     5726    try
     5727    {
     5728        PVBOXHDD hdd;
     5729        int vrc = VDCreate(m->vdDiskIfaces, &hdd);
     5730        ComAssertRCThrow(vrc, E_FAIL);
     5731
     5732        Guid id = m->id;
     5733        Utf8Str format(m->strFormat);
     5734        Utf8Str location(m->strLocationFull);
     5735
     5736        Medium *pParent = m->pParent;
     5737        Guid parentId = pParent->m->id;
     5738        Utf8Str parentFormat(pParent->m->strFormat);
     5739        Utf8Str parentLocation(pParent->m->strLocationFull);
     5740
     5741        Assert(m->state == MediumState_LockedWrite);
     5742
     5743        /* unlock before the potentially lengthy operation */
     5744        thisLock.leave();
     5745
     5746        try
     5747        {
     5748            /* first, delete the storage unit */
     5749            vrc = VDOpen(hdd, format.c_str(), location.c_str(),
     5750                            VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
     5751                            m->vdDiskIfaces);
     5752            if (RT_SUCCESS(vrc))
     5753                vrc = VDClose(hdd, true /* fDelete */);
     5754
     5755            if (RT_FAILURE(vrc))
     5756            {
     5757                throw setError(E_FAIL,
     5758                                tr("Could not delete the hard disk storage unit '%s'%s"),
     5759                                location.raw(), vdError(vrc).raw());
     5760            }
     5761
     5762            /* next, create it again */
     5763            vrc = VDOpen(hdd, parentFormat.c_str(), parentLocation.c_str(),
     5764                            VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
     5765                            m->vdDiskIfaces);
     5766            if (RT_FAILURE(vrc))
     5767            {
     5768                throw setError(E_FAIL,
     5769                                tr("Could not open the hard disk storage unit '%s'%s"),
     5770                                parentLocation.raw(), vdError(vrc).raw());
     5771            }
     5772
     5773            vrc = VDCreateDiff(hdd, format.c_str(), location.c_str(),
     5774                                /// @todo use the same image variant as before
     5775                                VD_IMAGE_FLAGS_NONE,
     5776                                NULL, id.raw(),
     5777                                parentId.raw(),
     5778                                VD_OPEN_FLAGS_NORMAL,
     5779                                m->vdDiskIfaces,
     5780                                vdOperationIfaces);
     5781            if (RT_FAILURE(vrc))
     5782            {
     5783                throw setError(E_FAIL,
     5784                                tr("Could not create the differencing hard disk storage unit '%s'%s"),
     5785                                location.raw(), vdError(vrc).raw());
     5786            }
     5787
     5788            size = VDGetFileSize(hdd, 1);
     5789            logicalSize = VDGetSize(hdd, 1) / _1M;
     5790        }
     5791        catch (HRESULT aRC) { rc = aRC; }
     5792
     5793        VDDestroy(hdd);
     5794    }
     5795    catch (HRESULT aRC) { rc = aRC; }
     5796
     5797    thisLock.enter();
     5798
     5799    m->size = size;
     5800    m->logicalSize = logicalSize;
     5801
     5802    if (fIsAsync)
     5803    {
     5804        /* unlock ourselves when done */
     5805        HRESULT rc2 = UnlockWrite(NULL);
     5806        AssertComRC(rc2);
     5807    }
     5808
     5809    /* Note that in sync mode, it's the caller's responsibility to
     5810     * unlock the hard disk */
     5811
     5812    return rc;
     5813}
     5814
     5815/**
     5816 * Implementation code called from Medium::taskThread for the "compact" task.
     5817 * @param pvdOperationIfaces
     5818 * @return
     5819 */
     5820HRESULT Medium::taskThreadCompact(Task &task, void *pvdOperationIfaces)
     5821{
     5822    HRESULT rc = S_OK;
     5823
     5824    PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces;
     5825
     5826    /* Lock all in {parent,child} order. The lock is also used as a
     5827     * signal from the task initiator (which releases it only after
     5828     * RTThreadCreate()) that we can start the job. */
     5829    AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
     5830
     5831    ImageChain *imgChain = task.d.images.get();
     5832
     5833    try
     5834    {
     5835        PVBOXHDD hdd;
     5836        int vrc = VDCreate(m->vdDiskIfaces, &hdd);
     5837        ComAssertRCThrow(vrc, E_FAIL);
     5838
     5839        try
     5840        {
     5841            /* Open all hard disk images in the chain. */
     5842            MediaList::const_iterator last = imgChain->end();
     5843            last--;
     5844            for (MediaList::const_iterator it = imgChain->begin();
     5845                 it != imgChain->end();
     5846                 ++it)
     5847            {
     5848                /* sanity check */
     5849                if (it == last)
     5850                    Assert((*it)->m->state == MediumState_LockedWrite);
     5851                else
     5852                    Assert((*it)->m->state == MediumState_LockedRead);
     5853
     5854                /** Open all images but last in read-only mode. */
     5855                vrc = VDOpen(hdd,
     5856                             (*it)->m->strFormat.c_str(),
     5857                             (*it)->m->strLocationFull.c_str(),
     5858                             (it == last) ? VD_OPEN_FLAGS_NORMAL : VD_OPEN_FLAGS_READONLY,
     5859                             (*it)->m->vdDiskIfaces);
     5860                if (RT_FAILURE(vrc))
     5861                    throw setError(E_FAIL,
     5862                                   tr("Could not open the hard disk storage unit '%s'%s"),
     5863                                   (*it)->m->strLocationFull.raw(),
     5864                                   vdError(vrc).raw());
     5865            }
     5866
     5867            Assert(m->state == MediumState_LockedWrite);
     5868
     5869            Utf8Str location(m->strLocationFull);
     5870
     5871            /* unlock before the potentially lengthy operation */
     5872            thisLock.leave();
     5873
     5874            vrc = VDCompact(hdd, VD_LAST_IMAGE, vdOperationIfaces);
     5875            if (RT_FAILURE(vrc))
     5876            {
     5877                if (vrc == VERR_NOT_SUPPORTED)
     5878                    throw setError(VBOX_E_NOT_SUPPORTED,
     5879                                   tr("Compacting is not yet supported for hard disk '%s'"),
     5880                                   location.raw());
     5881                else if (vrc == VERR_NOT_IMPLEMENTED)
     5882                    throw setError(E_NOTIMPL,
     5883                                   tr("Compacting is not implemented, hard disk '%s'"),
     5884                                   location.raw());
     5885                else
     5886                    throw setError(E_FAIL,
     5887                                   tr("Could not compact hard disk '%s'%s"),
     5888                                   location.raw(),
     5889                                   vdError(vrc).raw());
     5890            }
     5891        }
     5892        catch (HRESULT aRC) { rc = aRC; }
     5893
     5894        VDDestroy(hdd);
     5895    }
     5896    catch (HRESULT aRC) { rc = aRC; }
     5897
     5898    /* Everything is explicitly unlocked when the task exits,
     5899     * as the task destruction also destroys the image chain. */
     5900
     5901    return rc;
     5902}
     5903
    56435904
    56445905/**
     
    56765937    AssertRCReturn(vrc1, E_FAIL);
    56775938
    5678     /// @todo ugly hack, fix ComAssert... later
    5679     #define setError that->setError
    5680 
    56815939    /* Note: no need in AutoCaller because Task does that */
    56825940
     
    57075965
    57085966        case Task::Delete:
    5709         {
    5710             /* The lock is also used as a signal from the task initiator (which
    5711              * releases it only after RTThreadCreate()) that we can start the job */
    5712             AutoWriteLock thatLock(that COMMA_LOCKVAL_SRC_POS);
    5713 
    5714             try
    5715             {
    5716                 PVBOXHDD hdd;
    5717                 int vrc = VDCreate(that->m->vdDiskIfaces, &hdd);
    5718                 ComAssertRCThrow(vrc, E_FAIL);
    5719 
    5720                 Utf8Str format(that->m->strFormat);
    5721                 Utf8Str location(that->m->strLocationFull);
    5722 
    5723                 /* unlock before the potentially lengthy operation */
    5724                 Assert(that->m->state == MediumState_Deleting);
    5725                 thatLock.leave();
    5726 
    5727                 try
    5728                 {
    5729                     vrc = VDOpen(hdd, format.c_str(), location.c_str(),
    5730                                  VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
    5731                                  that->m->vdDiskIfaces);
    5732                     if (RT_SUCCESS(vrc))
    5733                         vrc = VDClose(hdd, true /* fDelete */);
    5734 
    5735                     if (RT_FAILURE(vrc))
    5736                     {
    5737                         throw setError(E_FAIL,
    5738                                        tr("Could not delete the hard disk storage unit '%s'%s"),
    5739                                        location.raw(), that->vdError(vrc).raw());
    5740                     }
    5741 
    5742                 }
    5743                 catch (HRESULT aRC) { rc = aRC; }
    5744 
    5745                 VDDestroy(hdd);
    5746             }
    5747             catch (HRESULT aRC) { rc = aRC; }
    5748 
    5749             thatLock.maybeEnter();
    5750 
    5751             /* go to the NotCreated state even on failure since the storage
    5752              * may have been already partially deleted and cannot be used any
    5753              * more. One will be able to manually re-open the storage if really
    5754              * needed to re-register it. */
    5755             that->m->state = MediumState_NotCreated;
    5756 
    5757             /* Reset UUID to prevent Create* from reusing it again */
    5758             unconst(that->m->id).clear();
    5759 
    5760             break;
    5761         }
     5967            rc = that->taskThreadDelete();
     5968        break;
    57625969
    57635970        case Task::Reset:
    5764         {
    5765             /* The lock is also used as a signal from the task initiator (which
    5766              * releases it only after RTThreadCreate()) that we can start the job */
    5767             AutoWriteLock thatLock(that COMMA_LOCKVAL_SRC_POS);
    5768 
    5769             /// @todo Below we use a pair of delete/create operations to reset
    5770             /// the diff contents but the most efficient way will of course be
    5771             /// to add a VDResetDiff() API call
    5772 
    5773             uint64_t size = 0, logicalSize = 0;
    5774 
    5775             try
    5776             {
    5777                 PVBOXHDD hdd;
    5778                 int vrc = VDCreate(that->m->vdDiskIfaces, &hdd);
    5779                 ComAssertRCThrow(vrc, E_FAIL);
    5780 
    5781                 Guid id = that->m->id;
    5782                 Utf8Str format(that->m->strFormat);
    5783                 Utf8Str location(that->m->strLocationFull);
    5784 
    5785                 Medium *pParent = that->m->pParent;
    5786                 Guid parentId = pParent->m->id;
    5787                 Utf8Str parentFormat(pParent->m->strFormat);
    5788                 Utf8Str parentLocation(pParent->m->strLocationFull);
    5789 
    5790                 Assert(that->m->state == MediumState_LockedWrite);
    5791 
    5792                 /* unlock before the potentially lengthy operation */
    5793                 thatLock.leave();
    5794 
    5795                 try
    5796                 {
    5797                     /* first, delete the storage unit */
    5798                     vrc = VDOpen(hdd, format.c_str(), location.c_str(),
    5799                                  VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
    5800                                  that->m->vdDiskIfaces);
    5801                     if (RT_SUCCESS(vrc))
    5802                         vrc = VDClose(hdd, true /* fDelete */);
    5803 
    5804                     if (RT_FAILURE(vrc))
    5805                     {
    5806                         throw setError(E_FAIL,
    5807                                        tr("Could not delete the hard disk storage unit '%s'%s"),
    5808                                        location.raw(), that->vdError(vrc).raw());
    5809                     }
    5810 
    5811                     /* next, create it again */
    5812                     vrc = VDOpen(hdd, parentFormat.c_str(), parentLocation.c_str(),
    5813                                  VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
    5814                                  that->m->vdDiskIfaces);
    5815                     if (RT_FAILURE(vrc))
    5816                     {
    5817                         throw setError(E_FAIL,
    5818                                        tr("Could not open the hard disk storage unit '%s'%s"),
    5819                                        parentLocation.raw(), that->vdError(vrc).raw());
    5820                     }
    5821 
    5822                     vrc = VDCreateDiff(hdd, format.c_str(), location.c_str(),
    5823                                        /// @todo use the same image variant as before
    5824                                        VD_IMAGE_FLAGS_NONE,
    5825                                        NULL, id.raw(),
    5826                                        parentId.raw(),
    5827                                        VD_OPEN_FLAGS_NORMAL,
    5828                                        that->m->vdDiskIfaces,
    5829                                        vdOperationIfaces);
    5830                     if (RT_FAILURE(vrc))
    5831                     {
    5832                         throw setError(E_FAIL,
    5833                                        tr("Could not create the differencing hard disk storage unit '%s'%s"),
    5834                                        location.raw(), that->vdError(vrc).raw());
    5835                     }
    5836 
    5837                     size = VDGetFileSize(hdd, 1);
    5838                     logicalSize = VDGetSize(hdd, 1) / _1M;
    5839                 }
    5840                 catch (HRESULT aRC) { rc = aRC; }
    5841 
    5842                 VDDestroy(hdd);
    5843             }
    5844             catch (HRESULT aRC) { rc = aRC; }
    5845 
    5846             thatLock.enter();
    5847 
    5848             that->m->size = size;
    5849             that->m->logicalSize = logicalSize;
    5850 
    5851             if (fIsAsync)
    5852             {
    5853                 /* unlock ourselves when done */
    5854                 HRESULT rc2 = that->UnlockWrite(NULL);
    5855                 AssertComRC(rc2);
    5856             }
    5857 
    5858             /* Note that in sync mode, it's the caller's responsibility to
    5859              * unlock the hard disk */
    5860 
    5861             break;
    5862         }
    5863 
    5864         ////////////////////////////////////////////////////////////////////////
     5971            rc = that->taskThreadReset((void*)vdOperationIfaces, fIsAsync);
     5972        break;
    58655973
    58665974        case Task::Compact:
    5867         {
    5868             /* Lock all in {parent,child} order. The lock is also used as a
    5869              * signal from the task initiator (which releases it only after
    5870              * RTThreadCreate()) that we can start the job. */
    5871             AutoWriteLock thatLock(that COMMA_LOCKVAL_SRC_POS);
    5872 
    5873             ImageChain *imgChain = task->d.images.get();
    5874 
    5875             try
    5876             {
    5877                 PVBOXHDD hdd;
    5878                 int vrc = VDCreate(that->m->vdDiskIfaces, &hdd);
    5879                 ComAssertRCThrow(vrc, E_FAIL);
    5880 
    5881                 try
    5882                 {
    5883                     /* Open all hard disk images in the chain. */
    5884                     MediaList::const_iterator last = imgChain->end();
    5885                     last--;
    5886                     for (MediaList::const_iterator it = imgChain->begin();
    5887                          it != imgChain->end();
    5888                          ++it)
    5889                     {
    5890                         /* sanity check */
    5891                         if (it == last)
    5892                             Assert((*it)->m->state == MediumState_LockedWrite);
    5893                         else
    5894                             Assert((*it)->m->state == MediumState_LockedRead);
    5895 
    5896                         /** Open all images but last in read-only mode. */
    5897                         vrc = VDOpen(hdd, (*it)->m->strFormat.c_str(),
    5898                                      (*it)->m->strLocationFull.c_str(),
    5899                                      (it == last) ? VD_OPEN_FLAGS_NORMAL : VD_OPEN_FLAGS_READONLY,
    5900                                      (*it)->m->vdDiskIfaces);
    5901                         if (RT_FAILURE(vrc))
    5902                         {
    5903                             throw setError(E_FAIL,
    5904                                            tr("Could not open the hard disk storage unit '%s'%s"),
    5905                                            (*it)->m->strLocationFull.raw(),
    5906                                            that->vdError(vrc).raw());
    5907                         }
    5908                     }
    5909 
    5910                     Assert(that->m->state == MediumState_LockedWrite);
    5911 
    5912                     Utf8Str location(that->m->strLocationFull);
    5913 
    5914                     /* unlock before the potentially lengthy operation */
    5915                     thatLock.leave();
    5916 
    5917                     vrc = VDCompact(hdd, VD_LAST_IMAGE, vdOperationIfaces);
    5918                     if (RT_FAILURE(vrc))
    5919                     {
    5920                         if (vrc == VERR_NOT_SUPPORTED)
    5921                             throw setError(VBOX_E_NOT_SUPPORTED,
    5922                                            tr("Compacting is not yet supported for hard disk '%s'"),
    5923                                            location.raw());
    5924                         else if (vrc == VERR_NOT_IMPLEMENTED)
    5925                             throw setError(E_NOTIMPL,
    5926                                            tr("Compacting is not implemented, hard disk '%s'"),
    5927                                            location.raw());
    5928                         else
    5929                             throw setError(E_FAIL,
    5930                                            tr("Could not compact hard disk '%s'%s"),
    5931                                            location.raw(),
    5932                                            that->vdError(vrc).raw());
    5933                     }
    5934                 }
    5935                 catch (HRESULT aRC) { rc = aRC; }
    5936 
    5937                 VDDestroy(hdd);
    5938             }
    5939             catch (HRESULT aRC) { rc = aRC; }
    5940 
    5941             /* Everything is explicitly unlocked when the task exits,
    5942              * as the task destruction also destroys the image chain. */
    5943 
    5944             break;
    5945         }
     5975            rc = that->taskThreadCompact(*task, (void*)vdOperationIfaces);
     5976        break;
    59465977
    59475978        default:
  • trunk/src/VBox/Main/include/MediumImpl.h

    r25887 r25888  
    313313    HRESULT taskThreadMerge(Task &task, void *pvdOperationIfaces, bool fIsAsync);
    314314    HRESULT taskThreadClone(Task &task, void *pvdOperationIfaces);
     315    HRESULT taskThreadDelete();
     316    HRESULT taskThreadReset(void *pvdOperationIfaces, bool fIsAsync);
     317    HRESULT taskThreadCompact(Task &task, void *pvdOperationIfaces);
    315318
    316319    static DECLCALLBACK(int) taskThread(RTTHREAD thread, void *pvUser);
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