VirtualBox

Changeset 73743 in vbox


Ignore:
Timestamp:
Aug 17, 2018 5:56:34 PM (6 years ago)
Author:
vboxsync
Message:

Main/Progress+Appliance+Machine: Turn IProgress::waitForAsyncProgressCompletion into an internal method. It is not needed by any client code outside the API, it's simply is too special. Also include the error propagation which it originally skipped (leding to reduntant code in the calling code). Remove a replicated version of it from the Appliance code which seems to be the half-forgotten ancestor of the method in IProgress. Adapt the users of the method to the new internal method, which made the code easier to read.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r73716 r73743  
    1421214212  <interface
    1421314213    name="IProgress" extends="$unknown"
    14214     uuid="e0026dc0-0c55-47b1-aa64-d340a396b418"
     14214    uuid="64c7fb5c-ce8f-4681-9c8c-d523cb4dea3d"
    1421514215    wsmap="managed"
    1421614216    reservedMethods="1" reservedAttributes="2"
     
    1440714407        <desc>
    1440814408          Maximum time in milliseconds to wait or -1 to wait indefinitely.
    14409         </desc>
    14410       </param>
    14411     </method>
    14412 
    14413     <method name="waitForAsyncProgressCompletion">
    14414       <desc>
    14415           Waits until the other task is completed (including all
    14416           sub-operations) and forward all changes from the other progress to
    14417           this progress. This means sub-operation number, description, percent
    14418           and so on.
    14419 
    14420           You have to take care on setting up at least the same count on
    14421           sub-operations in this progress object like there are in the other
    14422           progress object.
    14423 
    14424           If the other progress object supports cancel and this object gets any
    14425           cancel request (when here enabled as well), it will be forwarded to
    14426           the other progress object.
    14427 
    14428           If there is an error in the other progress, this error isn't
    14429           automatically transfered to this progress object. So you have to
    14430           check any operation error within the other progress object, after
    14431           this method returns.
    14432       </desc>
    14433 
    14434       <param name="pProgressAsync" type="IProgress" dir="in">
    14435         <desc>
    14436           The progress object of the asynchrony process.
    1443714409        </desc>
    1443814410      </param>
  • trunk/src/VBox/Main/include/ApplianceImpl.h

    r73133 r73743  
    130130                            const Utf8Str &strDescription,
    131131                            SetUpProgressMode mode);
    132     void i_waitForAsyncProgress(ComObjPtr<Progress> &pProgressThis, ComPtr<IProgress> &pProgressAsync);
    133132    void i_addWarning(const char* aWarning, ...);
    134133    void i_disksWeight();
  • trunk/src/VBox/Main/include/ProgressImpl.h

    r69500 r73743  
    138138    HRESULT i_notifyCompleteEI(HRESULT aResultCode,
    139139                               const ComPtr<IVirtualBoxErrorInfo> &aErrorInfo);
     140    /**
     141     * Waits until the other task is completed (including all sub-operations)
     142     * and forward all changes from the other progress to this progress. This
     143     * means sub-operation number, description, percent and so on.
     144     *
     145     * The caller is responsible for having at least the same count of
     146     * sub-operations in this progress object as there are in the other
     147     * progress object.
     148     *
     149     * If the other progress object supports cancel and this object gets any
     150     * cancel request (when here enabled as well), it will be forwarded to
     151     * the other progress object.
     152     *
     153     * Error information is automatically preserved (by transferring it to
     154     * the current thread's error information). If the caller wants to set it
     155     * as the completion state of this progress it needs to be done separately.
     156     *
     157     * @param   aProgressOther  Progress object from which the state is
     158     *                  forwarded until it is signalling completion.
     159     * @return COM error status, also reflecting the failed completion.
     160     */
     161    HRESULT i_waitForOtherProgressCompletion(const ComPtr<IProgress> &aProgressOther);
    140162
    141163    bool i_notifyPointOfNoReturn(void);
     
    213235    HRESULT waitForOperationCompletion(ULONG aOperation,
    214236                                       LONG aTimeout);
    215     HRESULT waitForAsyncProgressCompletion(const ComPtr<IProgress> &aPProgressAsync);
    216237    HRESULT cancel();
    217238
  • trunk/src/VBox/Main/src-all/ProgressImpl.cpp

    r73716 r73743  
    486486}
    487487
    488 /**
    489  * Notify the progress object that we're almost at the point of no return.
    490  *
    491  * This atomically checks for and disables cancelation.  Calls to
    492  * IProgress::Cancel() made after a successful call to this method will fail
    493  * and the user can be told.  While this isn't entirely clean behavior, it
    494  * prevents issues with an irreversible actually operation succeeding while the
    495  * user believe it was rolled back.
    496  *
    497  * @returns Success indicator.
    498  * @retval  true on success.
    499  * @retval  false if the progress object has already been canceled or is in an
    500  *          invalid state
    501  */
    502 bool Progress::i_notifyPointOfNoReturn(void)
    503 {
    504     AutoCaller autoCaller(this);
    505     AssertComRCReturn(autoCaller.rc(), false);
    506 
    507     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    508 
    509     if (mCanceled)
    510     {
    511         LogThisFunc(("returns false\n"));
    512         return false;
    513     }
    514 
    515     mCancelable = FALSE;
    516     LogThisFunc(("returns true\n"));
    517     return true;
    518 }
    519 
    520 /**
    521  * Sets the cancelation callback, checking for cancelation first.
    522  *
    523  * @returns Success indicator.
    524  * @retval  true on success.
    525  * @retval  false if the progress object has already been canceled or is in an
    526  *          invalid state
    527  *
    528  * @param   pfnCallback     The function to be called upon cancelation.
    529  * @param   pvUser          The callback argument.
    530  */
    531 bool Progress::i_setCancelCallback(void (*pfnCallback)(void *), void *pvUser)
    532 {
    533     AutoCaller autoCaller(this);
    534     AssertComRCReturn(autoCaller.rc(), false);
    535 
    536     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    537 
    538     i_checkForAutomaticTimeout();
    539     if (mCanceled)
    540         return false;
    541 
    542     m_pvCancelUserArg   = pvUser;
    543     m_pfnCancelCallback = pfnCallback;
    544     return true;
    545 }
    546 
    547 /**
    548  * @callback_method_impl{FNRTPROGRESS,
    549  *      Works the progress of the current operation.}
    550  */
    551 /*static*/ DECLCALLBACK(int) Progress::i_iprtProgressCallback(unsigned uPercentage, void *pvUser)
    552 {
    553     Progress *pThis = (Progress *)pvUser;
    554 
    555     /*
    556      * Same as setCurrentOperationProgress, except we don't fail on mCompleted.
    557      */
    558     AutoWriteLock alock(pThis COMMA_LOCKVAL_SRC_POS);
    559     int vrc = VINF_SUCCESS;
    560     if (!pThis->mCompleted)
    561     {
    562         pThis->i_checkForAutomaticTimeout();
    563         if (!pThis->mCanceled)
    564         {
    565             if (uPercentage > pThis->m_ulOperationPercent)
    566                 pThis->setCurrentOperationProgress(uPercentage);
    567         }
    568         else
    569         {
    570             Assert(pThis->mCancelable);
    571             vrc = VERR_CANCELLED;
    572         }
    573     }
    574     /* else ignored */
    575     return vrc;
    576 }
    577 
    578 /**
    579  * @callback_method_impl{FNVDPROGRESS,
    580  *      Progress::i_iprtProgressCallback with parameters switched around.}
    581  */
    582 /*static*/ DECLCALLBACK(int) Progress::i_vdProgressCallback(void *pvUser, unsigned uPercentage)
    583 {
    584     return i_iprtProgressCallback(uPercentage, pvUser);
    585 }
    586 
    587 // IProgress properties
    588 /////////////////////////////////////////////////////////////////////////////
    589 
    590 HRESULT Progress::getId(com::Guid &aId)
    591 {
    592     /* mId is constant during life time, no need to lock */
    593     aId = mId;
    594 
    595     return S_OK;
    596 }
    597 
    598 HRESULT Progress::getDescription(com::Utf8Str &aDescription)
    599 {
    600     /* mDescription is constant during life time, no need to lock */
    601     aDescription = mDescription;
    602 
    603     return S_OK;
    604 }
    605 HRESULT Progress::getInitiator(ComPtr<IUnknown> &aInitiator)
    606 {
    607     /* mInitiator/mParent are constant during life time, no need to lock */
    608 #if !defined(VBOX_COM_INPROC)
    609     if (mInitiator)
    610         mInitiator.queryInterfaceTo(aInitiator.asOutParam());
    611     else
    612     {
    613         ComObjPtr<VirtualBox> pVirtualBox(mParent);
    614         pVirtualBox.queryInterfaceTo(aInitiator.asOutParam());
    615     }
    616 #else
    617     mInitiator.queryInterfaceTo(aInitiator.asOutParam());
    618 #endif
    619 
    620     return S_OK;
    621 }
    622 
    623 HRESULT Progress::getCancelable(BOOL *aCancelable)
    624 {
    625     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    626 
    627     *aCancelable = mCancelable;
    628 
    629     return S_OK;
    630 }
    631 
    632 HRESULT Progress::getPercent(ULONG *aPercent)
    633 {
    634     /* i_checkForAutomaticTimeout requires a write lock. */
    635     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    636 
    637     if (mCompleted && SUCCEEDED(mResultCode))
    638         *aPercent = 100;
    639     else
    640     {
    641         ULONG ulPercent = (ULONG)i_calcTotalPercent();
    642         // do not report 100% until we're really really done with everything
    643         // as the Qt GUI dismisses progress dialogs in that case
    644         if (    ulPercent == 100
    645              && (    m_ulOperationPercent < 100
    646                   || (m_ulCurrentOperation < m_cOperations -1)
    647                 )
    648            )
    649             *aPercent = 99;
    650         else
    651             *aPercent = ulPercent;
    652     }
    653 
    654     i_checkForAutomaticTimeout();
    655 
    656     return S_OK;
    657 }
    658 
    659 HRESULT Progress::getTimeRemaining(LONG *aTimeRemaining)
    660 {
    661     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    662 
    663     if (mCompleted)
    664         *aTimeRemaining = 0;
    665     else
    666     {
    667         double dPercentDone = i_calcTotalPercent();
    668         if (dPercentDone < 1)
    669             *aTimeRemaining = -1;       // unreliable, or avoid division by 0 below
    670         else
    671         {
    672             uint64_t ullTimeNow = RTTimeMilliTS();
    673             uint64_t ullTimeElapsed = ullTimeNow - m_ullTimestamp;
    674             uint64_t ullTimeTotal = (uint64_t)((double)ullTimeElapsed * 100 / dPercentDone);
    675             uint64_t ullTimeRemaining = ullTimeTotal - ullTimeElapsed;
    676 
    677 //          LogFunc(("dPercentDone = %RI32, ullTimeNow = %RI64, ullTimeElapsed = %RI64, ullTimeTotal = %RI64, ullTimeRemaining = %RI64\n",
    678 //                   (uint32_t)dPercentDone, ullTimeNow, ullTimeElapsed, ullTimeTotal, ullTimeRemaining));
    679 
    680             *aTimeRemaining = (LONG)(ullTimeRemaining / 1000);
    681         }
    682     }
    683 
    684     return S_OK;
    685 }
    686 
    687 HRESULT Progress::getCompleted(BOOL *aCompleted)
    688 {
    689     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    690 
    691     *aCompleted = mCompleted;
    692 
    693     return S_OK;
    694 }
    695 
    696 HRESULT Progress::getCanceled(BOOL *aCanceled)
    697 {
    698     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    699 
    700     *aCanceled = mCanceled;
    701 
    702     return S_OK;
    703 }
    704 
    705 HRESULT Progress::getResultCode(LONG *aResultCode)
    706 {
    707     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    708 
    709     if (!mCompleted)
    710         return setError(E_FAIL, tr("Result code is not available, operation is still in progress"));
    711 
    712     *aResultCode = mResultCode;
    713 
    714     return S_OK;
    715 }
    716 
    717 HRESULT Progress::getErrorInfo(ComPtr<IVirtualBoxErrorInfo> &aErrorInfo)
    718 {
    719     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    720 
    721     if (!mCompleted)
    722         return setError(E_FAIL, tr("Error info is not available, operation is still in progress"));
    723 
    724     mErrorInfo.queryInterfaceTo(aErrorInfo.asOutParam());
    725 
    726     return S_OK;
    727 }
    728 
    729 HRESULT Progress::getOperationCount(ULONG *aOperationCount)
    730 {
    731     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    732 
    733     *aOperationCount = m_cOperations;
    734 
    735     return S_OK;
    736 }
    737 
    738 HRESULT Progress::getOperation(ULONG *aOperation)
    739 {
    740     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    741 
    742     *aOperation = m_ulCurrentOperation;
    743 
    744     return S_OK;
    745 }
    746 
    747 HRESULT Progress::getOperationDescription(com::Utf8Str &aOperationDescription)
    748 {
    749     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    750 
    751     aOperationDescription = m_operationDescription;
    752 
    753     return S_OK;
    754 }
    755 
    756 HRESULT Progress::getOperationPercent(ULONG *aOperationPercent)
    757 {
    758     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    759 
    760     if (mCompleted && SUCCEEDED(mResultCode))
    761         *aOperationPercent = 100;
    762     else
    763         *aOperationPercent = m_ulOperationPercent;
    764 
    765     return S_OK;
    766 }
    767 
    768 HRESULT Progress::getOperationWeight(ULONG *aOperationWeight)
    769 {
    770     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    771 
    772     *aOperationWeight = m_ulCurrentOperationWeight;
    773 
    774     return S_OK;
    775 }
    776 
    777 HRESULT Progress::getTimeout(ULONG *aTimeout)
    778 {
    779     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    780 
    781     *aTimeout = m_cMsTimeout;
    782 
    783     return S_OK;
    784 }
    785 
    786 HRESULT Progress::setTimeout(ULONG aTimeout)
    787 {
    788     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    789 
    790     if (!mCancelable)
    791         return setError(VBOX_E_INVALID_OBJECT_STATE, tr("Operation cannot be canceled"));
    792     m_cMsTimeout = aTimeout;
    793 
    794     return S_OK;
    795 }
    796 
    797 
    798 // IProgress methods
    799 /////////////////////////////////////////////////////////////////////////////
    800 
    801 /**
    802  * Updates the percentage value of the current operation.
    803  *
    804  * @param aPercent  New percentage value of the operation in progress
    805  *                  (in range [0, 100]).
    806  */
    807 HRESULT Progress::setCurrentOperationProgress(ULONG aPercent)
    808 {
    809     AssertMsgReturn(aPercent <= 100, ("%u\n", aPercent), E_INVALIDARG);
    810 
    811     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    812 
    813     i_checkForAutomaticTimeout();
    814     if (mCancelable && mCanceled)
    815         AssertReturn(!mCompleted, E_FAIL);
    816     AssertReturn(!mCompleted && !mCanceled, E_FAIL);
    817 
    818     if (m_ulOperationPercent != aPercent)
    819     {
    820         m_ulOperationPercent = aPercent;
    821         ULONG actualPercent = 0;
    822         getPercent(&actualPercent);
    823         fireProgressPercentageChangedEvent(pEventSource, mId.toUtf16().raw(), actualPercent);
    824     }
    825 
    826     return S_OK;
    827 }
    828 
    829 /**
    830  * Signals that the current operation is successfully completed and advances to
    831  * the next operation. The operation percentage is reset to 0.
    832  *
    833  * @param aNextOperationDescription  Description of the next operation.
    834  * @param aNextOperationsWeight     Weight of the next operation.
    835  *
    836  * @note The current operation must not be the last one.
    837  */
    838 HRESULT Progress::setNextOperation(const com::Utf8Str &aNextOperationDescription, ULONG aNextOperationsWeight)
    839 {
    840     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    841 
    842     if (mCanceled)
    843         return E_FAIL;
    844     AssertReturn(!mCompleted, E_FAIL);
    845     AssertReturn(m_ulCurrentOperation + 1 < m_cOperations, E_FAIL);
    846 
    847     ++m_ulCurrentOperation;
    848     m_ulOperationsCompletedWeight += m_ulCurrentOperationWeight;
    849 
    850     m_operationDescription = aNextOperationDescription;
    851     m_ulCurrentOperationWeight = aNextOperationsWeight;
    852     m_ulOperationPercent = 0;
    853 
    854     LogThisFunc(("%s: aNextOperationsWeight = %d; m_ulCurrentOperation is now %d, m_ulOperationsCompletedWeight is now %d\n",
    855                  m_operationDescription.c_str(), aNextOperationsWeight, m_ulCurrentOperation, m_ulOperationsCompletedWeight));
    856 
    857     /* wake up all waiting threads */
    858     if (mWaitersCount > 0)
    859         RTSemEventMultiSignal(mCompletedSem);
    860 
    861     ULONG actualPercent = 0;
    862     getPercent(&actualPercent);
    863     fireProgressPercentageChangedEvent(pEventSource, mId.toUtf16().raw(), actualPercent);
    864 
    865     return S_OK;
    866 }
    867 
    868 /**
    869  * @note XPCOM: when this method is not called on the main XPCOM thread, it
    870  *       simply blocks the thread until mCompletedSem is signalled. If the
    871  *       thread has its own event queue (hmm, what for?) that it must run, then
    872  *       calling this method will definitely freeze event processing.
    873  */
    874 HRESULT Progress::waitForCompletion(LONG aTimeout)
     488HRESULT Progress::i_waitForOtherProgressCompletion(const ComPtr<IProgress> &aProgressOther)
    875489{
    876490    LogFlowThisFuncEnter();
    877     LogFlowThisFunc(("aTimeout=%d\n", aTimeout));
    878 
    879     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    880 
    881     /* if we're already completed, take a shortcut */
    882     if (!mCompleted)
    883     {
    884         int vrc = VINF_SUCCESS;
    885         bool fForever = aTimeout < 0;
    886         int64_t timeLeft = aTimeout;
    887         int64_t lastTime = RTTimeMilliTS();
    888 
    889         while (!mCompleted && (fForever || timeLeft > 0))
    890         {
    891             mWaitersCount++;
    892             alock.release();
    893             vrc = RTSemEventMultiWait(mCompletedSem,
    894                                       fForever ? RT_INDEFINITE_WAIT : (RTMSINTERVAL)timeLeft);
    895             alock.acquire();
    896             mWaitersCount--;
    897 
    898             /* the last waiter resets the semaphore */
    899             if (mWaitersCount == 0)
    900                 RTSemEventMultiReset(mCompletedSem);
    901 
    902             if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT)
    903                 break;
    904 
    905             if (!fForever)
    906             {
    907                 int64_t now = RTTimeMilliTS();
    908                 timeLeft -= now - lastTime;
    909                 lastTime = now;
    910             }
    911         }
    912 
    913         if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT)
    914             return setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Failed to wait for the task completion (%Rrc)"), vrc);
    915     }
    916 
    917     LogFlowThisFuncLeave();
    918 
    919     return S_OK;
    920 }
    921 
    922 /**
    923  * @note XPCOM: when this method is not called on the main XPCOM thread, it
    924  *       simply blocks the thread until mCompletedSem is signalled. If the
    925  *       thread has its own event queue (hmm, what for?) that it must run, then
    926  *       calling this method will definitely freeze event processing.
    927  */
    928 HRESULT Progress::waitForOperationCompletion(ULONG aOperation, LONG aTimeout)
    929 
    930 {
    931     LogFlowThisFuncEnter();
    932     LogFlowThisFunc(("aOperation=%d, aTimeout=%d\n", aOperation, aTimeout));
    933 
    934     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    935 
    936     CheckComArgExpr(aOperation, aOperation < m_cOperations);
    937 
    938     /* if we're already completed or if the given operation is already done,
    939      * then take a shortcut */
    940     if (    !mCompleted
    941          && aOperation >= m_ulCurrentOperation)
    942     {
    943         int vrc = VINF_SUCCESS;
    944         bool fForever = aTimeout < 0;
    945         int64_t timeLeft = aTimeout;
    946         int64_t lastTime = RTTimeMilliTS();
    947 
    948         while (    !mCompleted && aOperation >= m_ulCurrentOperation
    949                 && (fForever || timeLeft > 0))
    950         {
    951             mWaitersCount ++;
    952             alock.release();
    953             vrc = RTSemEventMultiWait(mCompletedSem,
    954                                       fForever ? RT_INDEFINITE_WAIT : (unsigned) timeLeft);
    955             alock.acquire();
    956             mWaitersCount--;
    957 
    958             /* the last waiter resets the semaphore */
    959             if (mWaitersCount == 0)
    960                 RTSemEventMultiReset(mCompletedSem);
    961 
    962             if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT)
    963                 break;
    964 
    965             if (!fForever)
    966             {
    967                 int64_t now = RTTimeMilliTS();
    968                 timeLeft -= now - lastTime;
    969                 lastTime = now;
    970             }
    971         }
    972 
    973         if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT)
    974             return setErrorBoth(E_FAIL, vrc, tr("Failed to wait for the operation completion (%Rrc)"), vrc);
    975     }
    976 
    977     LogFlowThisFuncLeave();
    978 
    979     return S_OK;
    980 }
    981 
    982 HRESULT Progress::waitForAsyncProgressCompletion(const ComPtr<IProgress> &aPProgressAsync)
    983 {
    984     LogFlowThisFuncEnter();
    985 
    986     /* Note: we don't lock here, cause we just using public methods. */
     491
     492    /* Note: no locking needed, because we just use public methods. */
    987493
    988494    HRESULT rc           = S_OK;
     
    994500    ULONG cOp            = 0;
    995501    /* Is the async process cancelable? */
    996     rc = aPProgressAsync->COMGETTER(Cancelable)(&fCancelable);
     502    rc = aProgressOther->COMGETTER(Cancelable)(&fCancelable);
    997503    if (FAILED(rc)) return rc;
    998504    /* Loop as long as the sync process isn't completed. */
    999     while (SUCCEEDED(aPProgressAsync->COMGETTER(Completed(&fCompleted))))
     505    while (SUCCEEDED(aProgressOther->COMGETTER(Completed(&fCompleted))))
    1000506    {
    1001507        /* We can forward any cancel request to the async process only when
     
    1007513            if (fCanceled)
    1008514            {
    1009                 rc = aPProgressAsync->Cancel();
     515                rc = aProgressOther->Cancel();
    1010516                if (FAILED(rc)) return rc;
    1011517            }
     
    1024530            for (;;)
    1025531            {
    1026                 rc = aPProgressAsync->COMGETTER(Operation(&curOp));
     532                rc = aProgressOther->COMGETTER(Operation(&curOp));
    1027533                if (FAILED(rc)) return rc;
    1028534                if (cOp != curOp)
     
    1030536                    Bstr bstr;
    1031537                    ULONG currentWeight;
    1032                     rc = aPProgressAsync->COMGETTER(OperationDescription(bstr.asOutParam()));
     538                    rc = aProgressOther->COMGETTER(OperationDescription(bstr.asOutParam()));
    1033539                    if (FAILED(rc)) return rc;
    1034                     rc = aPProgressAsync->COMGETTER(OperationWeight(&currentWeight));
     540                    rc = aProgressOther->COMGETTER(OperationWeight(&currentWeight));
    1035541                    if (FAILED(rc)) return rc;
    1036542                    rc = SetNextOperation(bstr.raw(), currentWeight);
     
    1042548            }
    1043549
    1044             rc = aPProgressAsync->COMGETTER(OperationPercent(&currentPercent));
     550            rc = aProgressOther->COMGETTER(OperationPercent(&currentPercent));
    1045551            if (FAILED(rc)) return rc;
    1046552            if (currentPercent != prevPercent)
     
    1055561
    1056562        /* Make sure the loop is not too tight */
    1057         rc = aPProgressAsync->WaitForCompletion(100);
     563        rc = aProgressOther->WaitForCompletion(100);
    1058564        if (FAILED(rc)) return rc;
    1059565    }
    1060566
     567    /* Transfer error information if applicable and report the error status
     568     * back to the caller to make this as easy as possible. */
     569    LONG iRc;
     570    rc = aProgressOther->COMGETTER(ResultCode)(&iRc);
     571    if (FAILED(rc)) return rc;
     572    if (FAILED(iRc))
     573    {
     574        setError(ProgressErrorInfo(aProgressOther));
     575        rc = iRc;
     576    }
     577
    1061578    LogFlowThisFuncLeave();
    1062 
    1063579    return rc;
     580}
     581
     582/**
     583 * Notify the progress object that we're almost at the point of no return.
     584 *
     585 * This atomically checks for and disables cancelation.  Calls to
     586 * IProgress::Cancel() made after a successful call to this method will fail
     587 * and the user can be told.  While this isn't entirely clean behavior, it
     588 * prevents issues with an irreversible actually operation succeeding while the
     589 * user believe it was rolled back.
     590 *
     591 * @returns Success indicator.
     592 * @retval  true on success.
     593 * @retval  false if the progress object has already been canceled or is in an
     594 *          invalid state
     595 */
     596bool Progress::i_notifyPointOfNoReturn(void)
     597{
     598    AutoCaller autoCaller(this);
     599    AssertComRCReturn(autoCaller.rc(), false);
     600
     601    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     602
     603    if (mCanceled)
     604    {
     605        LogThisFunc(("returns false\n"));
     606        return false;
     607    }
     608
     609    mCancelable = FALSE;
     610    LogThisFunc(("returns true\n"));
     611    return true;
     612}
     613
     614/**
     615 * Sets the cancelation callback, checking for cancelation first.
     616 *
     617 * @returns Success indicator.
     618 * @retval  true on success.
     619 * @retval  false if the progress object has already been canceled or is in an
     620 *          invalid state
     621 *
     622 * @param   pfnCallback     The function to be called upon cancelation.
     623 * @param   pvUser          The callback argument.
     624 */
     625bool Progress::i_setCancelCallback(void (*pfnCallback)(void *), void *pvUser)
     626{
     627    AutoCaller autoCaller(this);
     628    AssertComRCReturn(autoCaller.rc(), false);
     629
     630    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     631
     632    i_checkForAutomaticTimeout();
     633    if (mCanceled)
     634        return false;
     635
     636    m_pvCancelUserArg   = pvUser;
     637    m_pfnCancelCallback = pfnCallback;
     638    return true;
     639}
     640
     641/**
     642 * @callback_method_impl{FNRTPROGRESS,
     643 *      Works the progress of the current operation.}
     644 */
     645/*static*/ DECLCALLBACK(int) Progress::i_iprtProgressCallback(unsigned uPercentage, void *pvUser)
     646{
     647    Progress *pThis = (Progress *)pvUser;
     648
     649    /*
     650     * Same as setCurrentOperationProgress, except we don't fail on mCompleted.
     651     */
     652    AutoWriteLock alock(pThis COMMA_LOCKVAL_SRC_POS);
     653    int vrc = VINF_SUCCESS;
     654    if (!pThis->mCompleted)
     655    {
     656        pThis->i_checkForAutomaticTimeout();
     657        if (!pThis->mCanceled)
     658        {
     659            if (uPercentage > pThis->m_ulOperationPercent)
     660                pThis->setCurrentOperationProgress(uPercentage);
     661        }
     662        else
     663        {
     664            Assert(pThis->mCancelable);
     665            vrc = VERR_CANCELLED;
     666        }
     667    }
     668    /* else ignored */
     669    return vrc;
     670}
     671
     672/**
     673 * @callback_method_impl{FNVDPROGRESS,
     674 *      Progress::i_iprtProgressCallback with parameters switched around.}
     675 */
     676/*static*/ DECLCALLBACK(int) Progress::i_vdProgressCallback(void *pvUser, unsigned uPercentage)
     677{
     678    return i_iprtProgressCallback(uPercentage, pvUser);
     679}
     680
     681// IProgress properties
     682/////////////////////////////////////////////////////////////////////////////
     683
     684HRESULT Progress::getId(com::Guid &aId)
     685{
     686    /* mId is constant during life time, no need to lock */
     687    aId = mId;
     688
     689    return S_OK;
     690}
     691
     692HRESULT Progress::getDescription(com::Utf8Str &aDescription)
     693{
     694    /* mDescription is constant during life time, no need to lock */
     695    aDescription = mDescription;
     696
     697    return S_OK;
     698}
     699HRESULT Progress::getInitiator(ComPtr<IUnknown> &aInitiator)
     700{
     701    /* mInitiator/mParent are constant during life time, no need to lock */
     702#if !defined(VBOX_COM_INPROC)
     703    if (mInitiator)
     704        mInitiator.queryInterfaceTo(aInitiator.asOutParam());
     705    else
     706    {
     707        ComObjPtr<VirtualBox> pVirtualBox(mParent);
     708        pVirtualBox.queryInterfaceTo(aInitiator.asOutParam());
     709    }
     710#else
     711    mInitiator.queryInterfaceTo(aInitiator.asOutParam());
     712#endif
     713
     714    return S_OK;
     715}
     716
     717HRESULT Progress::getCancelable(BOOL *aCancelable)
     718{
     719    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     720
     721    *aCancelable = mCancelable;
     722
     723    return S_OK;
     724}
     725
     726HRESULT Progress::getPercent(ULONG *aPercent)
     727{
     728    /* i_checkForAutomaticTimeout requires a write lock. */
     729    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     730
     731    if (mCompleted && SUCCEEDED(mResultCode))
     732        *aPercent = 100;
     733    else
     734    {
     735        ULONG ulPercent = (ULONG)i_calcTotalPercent();
     736        // do not report 100% until we're really really done with everything
     737        // as the Qt GUI dismisses progress dialogs in that case
     738        if (    ulPercent == 100
     739             && (    m_ulOperationPercent < 100
     740                  || (m_ulCurrentOperation < m_cOperations -1)
     741                )
     742           )
     743            *aPercent = 99;
     744        else
     745            *aPercent = ulPercent;
     746    }
     747
     748    i_checkForAutomaticTimeout();
     749
     750    return S_OK;
     751}
     752
     753HRESULT Progress::getTimeRemaining(LONG *aTimeRemaining)
     754{
     755    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     756
     757    if (mCompleted)
     758        *aTimeRemaining = 0;
     759    else
     760    {
     761        double dPercentDone = i_calcTotalPercent();
     762        if (dPercentDone < 1)
     763            *aTimeRemaining = -1;       // unreliable, or avoid division by 0 below
     764        else
     765        {
     766            uint64_t ullTimeNow = RTTimeMilliTS();
     767            uint64_t ullTimeElapsed = ullTimeNow - m_ullTimestamp;
     768            uint64_t ullTimeTotal = (uint64_t)((double)ullTimeElapsed * 100 / dPercentDone);
     769            uint64_t ullTimeRemaining = ullTimeTotal - ullTimeElapsed;
     770
     771//          LogFunc(("dPercentDone = %RI32, ullTimeNow = %RI64, ullTimeElapsed = %RI64, ullTimeTotal = %RI64, ullTimeRemaining = %RI64\n",
     772//                   (uint32_t)dPercentDone, ullTimeNow, ullTimeElapsed, ullTimeTotal, ullTimeRemaining));
     773
     774            *aTimeRemaining = (LONG)(ullTimeRemaining / 1000);
     775        }
     776    }
     777
     778    return S_OK;
     779}
     780
     781HRESULT Progress::getCompleted(BOOL *aCompleted)
     782{
     783    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     784
     785    *aCompleted = mCompleted;
     786
     787    return S_OK;
     788}
     789
     790HRESULT Progress::getCanceled(BOOL *aCanceled)
     791{
     792    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     793
     794    *aCanceled = mCanceled;
     795
     796    return S_OK;
     797}
     798
     799HRESULT Progress::getResultCode(LONG *aResultCode)
     800{
     801    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     802
     803    if (!mCompleted)
     804        return setError(E_FAIL, tr("Result code is not available, operation is still in progress"));
     805
     806    *aResultCode = mResultCode;
     807
     808    return S_OK;
     809}
     810
     811HRESULT Progress::getErrorInfo(ComPtr<IVirtualBoxErrorInfo> &aErrorInfo)
     812{
     813    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     814
     815    if (!mCompleted)
     816        return setError(E_FAIL, tr("Error info is not available, operation is still in progress"));
     817
     818    mErrorInfo.queryInterfaceTo(aErrorInfo.asOutParam());
     819
     820    return S_OK;
     821}
     822
     823HRESULT Progress::getOperationCount(ULONG *aOperationCount)
     824{
     825    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     826
     827    *aOperationCount = m_cOperations;
     828
     829    return S_OK;
     830}
     831
     832HRESULT Progress::getOperation(ULONG *aOperation)
     833{
     834    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     835
     836    *aOperation = m_ulCurrentOperation;
     837
     838    return S_OK;
     839}
     840
     841HRESULT Progress::getOperationDescription(com::Utf8Str &aOperationDescription)
     842{
     843    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     844
     845    aOperationDescription = m_operationDescription;
     846
     847    return S_OK;
     848}
     849
     850HRESULT Progress::getOperationPercent(ULONG *aOperationPercent)
     851{
     852    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     853
     854    if (mCompleted && SUCCEEDED(mResultCode))
     855        *aOperationPercent = 100;
     856    else
     857        *aOperationPercent = m_ulOperationPercent;
     858
     859    return S_OK;
     860}
     861
     862HRESULT Progress::getOperationWeight(ULONG *aOperationWeight)
     863{
     864    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     865
     866    *aOperationWeight = m_ulCurrentOperationWeight;
     867
     868    return S_OK;
     869}
     870
     871HRESULT Progress::getTimeout(ULONG *aTimeout)
     872{
     873    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     874
     875    *aTimeout = m_cMsTimeout;
     876
     877    return S_OK;
     878}
     879
     880HRESULT Progress::setTimeout(ULONG aTimeout)
     881{
     882    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     883
     884    if (!mCancelable)
     885        return setError(VBOX_E_INVALID_OBJECT_STATE, tr("Operation cannot be canceled"));
     886    m_cMsTimeout = aTimeout;
     887
     888    return S_OK;
     889}
     890
     891
     892// IProgress methods
     893/////////////////////////////////////////////////////////////////////////////
     894
     895/**
     896 * Updates the percentage value of the current operation.
     897 *
     898 * @param aPercent  New percentage value of the operation in progress
     899 *                  (in range [0, 100]).
     900 */
     901HRESULT Progress::setCurrentOperationProgress(ULONG aPercent)
     902{
     903    AssertMsgReturn(aPercent <= 100, ("%u\n", aPercent), E_INVALIDARG);
     904
     905    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     906
     907    i_checkForAutomaticTimeout();
     908    if (mCancelable && mCanceled)
     909        AssertReturn(!mCompleted, E_FAIL);
     910    AssertReturn(!mCompleted && !mCanceled, E_FAIL);
     911
     912    if (m_ulOperationPercent != aPercent)
     913    {
     914        m_ulOperationPercent = aPercent;
     915        ULONG actualPercent = 0;
     916        getPercent(&actualPercent);
     917        fireProgressPercentageChangedEvent(pEventSource, mId.toUtf16().raw(), actualPercent);
     918    }
     919
     920    return S_OK;
     921}
     922
     923/**
     924 * Signals that the current operation is successfully completed and advances to
     925 * the next operation. The operation percentage is reset to 0.
     926 *
     927 * @param aNextOperationDescription  Description of the next operation.
     928 * @param aNextOperationsWeight     Weight of the next operation.
     929 *
     930 * @note The current operation must not be the last one.
     931 */
     932HRESULT Progress::setNextOperation(const com::Utf8Str &aNextOperationDescription, ULONG aNextOperationsWeight)
     933{
     934    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     935
     936    if (mCanceled)
     937        return E_FAIL;
     938    AssertReturn(!mCompleted, E_FAIL);
     939    AssertReturn(m_ulCurrentOperation + 1 < m_cOperations, E_FAIL);
     940
     941    ++m_ulCurrentOperation;
     942    m_ulOperationsCompletedWeight += m_ulCurrentOperationWeight;
     943
     944    m_operationDescription = aNextOperationDescription;
     945    m_ulCurrentOperationWeight = aNextOperationsWeight;
     946    m_ulOperationPercent = 0;
     947
     948    LogThisFunc(("%s: aNextOperationsWeight = %d; m_ulCurrentOperation is now %d, m_ulOperationsCompletedWeight is now %d\n",
     949                 m_operationDescription.c_str(), aNextOperationsWeight, m_ulCurrentOperation, m_ulOperationsCompletedWeight));
     950
     951    /* wake up all waiting threads */
     952    if (mWaitersCount > 0)
     953        RTSemEventMultiSignal(mCompletedSem);
     954
     955    ULONG actualPercent = 0;
     956    getPercent(&actualPercent);
     957    fireProgressPercentageChangedEvent(pEventSource, mId.toUtf16().raw(), actualPercent);
     958
     959    return S_OK;
     960}
     961
     962/**
     963 * @note XPCOM: when this method is not called on the main XPCOM thread, it
     964 *       simply blocks the thread until mCompletedSem is signalled. If the
     965 *       thread has its own event queue (hmm, what for?) that it must run, then
     966 *       calling this method will definitely freeze event processing.
     967 */
     968HRESULT Progress::waitForCompletion(LONG aTimeout)
     969{
     970    LogFlowThisFuncEnter();
     971    LogFlowThisFunc(("aTimeout=%d\n", aTimeout));
     972
     973    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     974
     975    /* if we're already completed, take a shortcut */
     976    if (!mCompleted)
     977    {
     978        int vrc = VINF_SUCCESS;
     979        bool fForever = aTimeout < 0;
     980        int64_t timeLeft = aTimeout;
     981        int64_t lastTime = RTTimeMilliTS();
     982
     983        while (!mCompleted && (fForever || timeLeft > 0))
     984        {
     985            mWaitersCount++;
     986            alock.release();
     987            vrc = RTSemEventMultiWait(mCompletedSem,
     988                                      fForever ? RT_INDEFINITE_WAIT : (RTMSINTERVAL)timeLeft);
     989            alock.acquire();
     990            mWaitersCount--;
     991
     992            /* the last waiter resets the semaphore */
     993            if (mWaitersCount == 0)
     994                RTSemEventMultiReset(mCompletedSem);
     995
     996            if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT)
     997                break;
     998
     999            if (!fForever)
     1000            {
     1001                int64_t now = RTTimeMilliTS();
     1002                timeLeft -= now - lastTime;
     1003                lastTime = now;
     1004            }
     1005        }
     1006
     1007        if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT)
     1008            return setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Failed to wait for the task completion (%Rrc)"), vrc);
     1009    }
     1010
     1011    LogFlowThisFuncLeave();
     1012
     1013    return S_OK;
     1014}
     1015
     1016/**
     1017 * @note XPCOM: when this method is not called on the main XPCOM thread, it
     1018 *       simply blocks the thread until mCompletedSem is signalled. If the
     1019 *       thread has its own event queue (hmm, what for?) that it must run, then
     1020 *       calling this method will definitely freeze event processing.
     1021 */
     1022HRESULT Progress::waitForOperationCompletion(ULONG aOperation, LONG aTimeout)
     1023
     1024{
     1025    LogFlowThisFuncEnter();
     1026    LogFlowThisFunc(("aOperation=%d, aTimeout=%d\n", aOperation, aTimeout));
     1027
     1028    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     1029
     1030    CheckComArgExpr(aOperation, aOperation < m_cOperations);
     1031
     1032    /* if we're already completed or if the given operation is already done,
     1033     * then take a shortcut */
     1034    if (    !mCompleted
     1035         && aOperation >= m_ulCurrentOperation)
     1036    {
     1037        int vrc = VINF_SUCCESS;
     1038        bool fForever = aTimeout < 0;
     1039        int64_t timeLeft = aTimeout;
     1040        int64_t lastTime = RTTimeMilliTS();
     1041
     1042        while (    !mCompleted && aOperation >= m_ulCurrentOperation
     1043                && (fForever || timeLeft > 0))
     1044        {
     1045            mWaitersCount ++;
     1046            alock.release();
     1047            vrc = RTSemEventMultiWait(mCompletedSem,
     1048                                      fForever ? RT_INDEFINITE_WAIT : (unsigned) timeLeft);
     1049            alock.acquire();
     1050            mWaitersCount--;
     1051
     1052            /* the last waiter resets the semaphore */
     1053            if (mWaitersCount == 0)
     1054                RTSemEventMultiReset(mCompletedSem);
     1055
     1056            if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT)
     1057                break;
     1058
     1059            if (!fForever)
     1060            {
     1061                int64_t now = RTTimeMilliTS();
     1062                timeLeft -= now - lastTime;
     1063                lastTime = now;
     1064            }
     1065        }
     1066
     1067        if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT)
     1068            return setErrorBoth(E_FAIL, vrc, tr("Failed to wait for the operation completion (%Rrc)"), vrc);
     1069    }
     1070
     1071    LogFlowThisFuncLeave();
     1072
     1073    return S_OK;
    10641074}
    10651075
  • trunk/src/VBox/Main/src-server/ApplianceImpl.cpp

    r73132 r73743  
    10491049}
    10501050
    1051 /**
    1052  * Called from the import and export background threads to synchronize the second
    1053  * background disk thread's progress object with the current progress object so
    1054  * that the user interface sees progress correctly and that cancel signals are
    1055  * passed on to the second thread.
    1056  *
    1057  * @param pProgressThis Progress object of the current thread.
    1058  * @param pProgressAsync Progress object of asynchronous task running in background.
    1059  */
    1060 void Appliance::i_waitForAsyncProgress(ComObjPtr<Progress> &pProgressThis,
    1061                                        ComPtr<IProgress> &pProgressAsync)
    1062 {
    1063     HRESULT rc;
    1064 
    1065     // now loop until the asynchronous operation completes and then report its result
    1066     BOOL fCompleted;
    1067     BOOL fCanceled;
    1068     ULONG currentPercent;
    1069     ULONG cOp = 0;
    1070     while (SUCCEEDED(pProgressAsync->COMGETTER(Completed(&fCompleted))))
    1071     {
    1072         rc = pProgressThis->COMGETTER(Canceled)(&fCanceled);
    1073         if (FAILED(rc)) throw rc;
    1074         if (fCanceled)
    1075             pProgressAsync->Cancel();
    1076         /* Check if the current operation has changed. It is also possible
    1077            that in the meantime more than one async operation was finished. So
    1078            we have to loop as long as we reached the same operation count. */
    1079         ULONG curOp;
    1080         for (;;)
    1081         {
    1082             rc = pProgressAsync->COMGETTER(Operation(&curOp));
    1083             if (FAILED(rc)) throw rc;
    1084             if (cOp != curOp)
    1085             {
    1086                 Bstr bstr;
    1087                 ULONG currentWeight;
    1088                 rc = pProgressAsync->COMGETTER(OperationDescription(bstr.asOutParam()));
    1089                 if (FAILED(rc)) throw rc;
    1090                 rc = pProgressAsync->COMGETTER(OperationWeight(&currentWeight));
    1091                 if (FAILED(rc)) throw rc;
    1092                 rc = pProgressThis->SetNextOperation(bstr.raw(), currentWeight);
    1093                 if (FAILED(rc)) throw rc;
    1094                 ++cOp;
    1095             }
    1096             else
    1097                 break;
    1098         }
    1099 
    1100         rc = pProgressAsync->COMGETTER(OperationPercent(&currentPercent));
    1101         if (FAILED(rc)) throw rc;
    1102         pProgressThis->SetCurrentOperationProgress(currentPercent);
    1103         if (fCompleted)
    1104             break;
    1105 
    1106         /* Make sure the loop is not too tight */
    1107         rc = pProgressAsync->WaitForCompletion(100);
    1108         if (FAILED(rc)) throw rc;
    1109     }
    1110     // report result of asynchronous operation
    1111     LONG iRc;
    1112     rc = pProgressAsync->COMGETTER(ResultCode)(&iRc);
    1113     if (FAILED(rc)) throw rc;
    1114 
    1115 
    1116     // if the thread of the progress object has an error, then
    1117     // retrieve the error info from there, or it'll be lost
    1118     if (FAILED(iRc))
    1119     {
    1120         ProgressErrorInfo info(pProgressAsync);
    1121         Utf8Str str(info.getText());
    1122         const char *pcsz = str.c_str();
    1123         HRESULT rc2 = setError(iRc, pcsz);
    1124         throw rc2;
    1125     }
    1126 }
    1127 
    11281051void Appliance::i_addWarning(const char* aWarning, ...)
    11291052{
  • trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp

    r73665 r73743  
    23992399                                     ImportStack &stack)
    24002400{
     2401    HRESULT rc;
    24012402    char *pszAbsDstPath = RTPathAbsExDup(stack.strMachineFolder.c_str(),
    24022403                                         strDstPath.c_str());
     
    24042405    RTStrFree(pszAbsDstPath);
    24052406    pszAbsDstPath = NULL;
    2406 
    2407     ComObjPtr<Progress> pProgress;
    2408     pProgress.createObject();
    2409     HRESULT rc = pProgress->init(mVirtualBox,
    2410                                  static_cast<IAppliance*>(this),
    2411                                  BstrFmt(tr("Creating medium '%s'"),
    2412                                          strAbsDstPath.c_str()).raw(),
    2413                                  TRUE);
    2414     if (FAILED(rc)) throw rc;
    24152407
    24162408    /* Get the system properties. */
     
    25632555                if (FAILED(rc)) throw rc;
    25642556
     2557                ComPtr<IProgress> pProgressImport;
    25652558                /* If strHref is empty we have to create a new file. */
    25662559                if (strSourceOVF.isEmpty())
     
    25722565                    rc = pTargetMedium->CreateBaseStorage(di.iCapacity / _1M,
    25732566                                                      ComSafeArrayAsInParam(mediumVariant),
    2574                                                       ComPtr<IProgress>(pProgress).asOutParam());
     2567                                                      pProgressImport.asOutParam());
    25752568                    if (FAILED(rc)) throw rc;
    25762569
     
    26312624                    /* Start the source image cloning operation. */
    26322625                    ComObjPtr<Medium> nullParent;
     2626                    ComObjPtr<Progress> pProgressImportTmp;
    26332627                    rc = pTargetMedium->i_importFile(strSrcFilePath.c_str(),
    26342628                                                     srcFormat,
     
    26362630                                                     hVfsIosReadAhead,
    26372631                                                     nullParent,
    2638                                                      pProgress);
     2632                                                     pProgressImportTmp);
     2633                    pProgressImportTmp.queryInterfaceTo(pProgressImport.asOutParam());
    26392634                    RTVfsIoStrmRelease(hVfsIosReadAhead);
    26402635                    hVfsIosSrc = NIL_RTVFSIOSTREAM;
     
    26512646                /* Now wait for the background import operation to complete; this throws
    26522647                 * HRESULTs on error. */
    2653                 ComPtr<IProgress> pp(pProgress);
    2654                 i_waitForAsyncProgress(stack.pProgress, pp);
     2648                stack.pProgress->i_waitForOtherProgressCompletion(pProgressImport);
    26552649            }
    26562650        }
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r73740 r73743  
    54845484                rc = pMedium->DeleteStorage(pProgress2.asOutParam());
    54855485                if (FAILED(rc)) throw rc;
    5486                 rc = task.m_pProgress->WaitForAsyncProgressCompletion(pProgress2);
     5486                rc = task.m_pProgress->i_waitForOtherProgressCompletion(pProgress2);
    54875487                if (FAILED(rc)) throw rc;
    5488                 /* Check the result of the asynchronous process. */
    5489                 LONG iRc;
    5490                 rc = pProgress2->COMGETTER(ResultCode)(&iRc);
    5491                 if (FAILED(rc)) throw rc;
    5492                 /* If the thread of the progress object has an error, then
    5493                  * retrieve the error info from there, or it'll be lost. */
    5494                 if (FAILED(iRc))
    5495                     throw setError(ProgressErrorInfo(pProgress2));
    54965488            }
    54975489
  • trunk/src/VBox/Main/src-server/MachineImplCloneVM.cpp

    r73664 r73743  
    12901290                        /* Wait until the async process has finished. */
    12911291                        srcLock.release();
    1292                         rc = d->pProgress->WaitForAsyncProgressCompletion(progress2);
     1292                        rc = d->pProgress->i_waitForOtherProgressCompletion(progress2);
    12931293                        srcLock.acquire();
    12941294                        if (FAILED(rc)) throw rc;
    12951295
    1296                         /* Check the result of the async process. */
    1297                         LONG iRc;
    1298                         rc = progress2->COMGETTER(ResultCode)(&iRc);
    1299                         if (FAILED(rc)) throw rc;
    1300                         /* If the thread of the progress object has an error, then
    1301                          * retrieve the error info from there, or it'll be lost. */
    1302                         if (FAILED(iRc))
    1303                             throw p->setError(ProgressErrorInfo(progress2));
    13041296                        /* Remember created medium. */
    13051297                        newMedia.append(pTarget);
  • trunk/src/VBox/Main/src-server/MachineImplMoveVM.cpp

    r73003 r73743  
    2121#include <iprt/cpp/utils.h>
    2222#include <iprt/stream.h>
     23#include <VBox/com/ErrorInfo.h>
    2324
    2425#include "MachineImplMoveVM.h"
     
    2627#include "VirtualBoxImpl.h"
    2728#include "Logging.h"
     29
     30/** @todo r=klaus this file is abusing the release log by putting pretty much
     31 * everything there. Should be adjusted to use debug logging where appropriate
     32 * and if really necessary some LogRel2 and the like. */
     33
    2834
    2935/* This variable is global and used in the different places so it must be cleared each time before usage to avoid failure */
     
    11051111            {
    11061112                /* In case of failure moveDiskProgress would be in the invalid state or not initialized at all
    1107                  * Call WaitForAsyncProgressCompletion only in success
     1113                 * Call i_waitForOtherProgressCompletion only in success
    11081114                 */
    1109                 /* Wait until the async process has finished. */
    1110                 rc = m_pProgress->WaitForAsyncProgressCompletion(moveDiskProgress);
     1115                /* Wait until the other process has finished. */
     1116                rc = m_pProgress->i_waitForOtherProgressCompletion(moveDiskProgress);
    11111117            }
    11121118
     
    11141120            machineLock.acquire();
    11151121
     1122            /* @todo r=klaus get rid of custom error handling logic everywhere in this file */
     1123            if (FAILED(rc))
     1124            {
     1125                com::ErrorInfoKeeper eik;
     1126                Utf8Str errorDesc(eik.getText().raw());
     1127                errorsList.push_back(ErrorInfoItem(eik.getResultCode(), errorDesc.c_str()));
     1128            }
     1129
    11161130            if (FAILED(rc)) throw rc;
    11171131
    11181132            LogRelFunc(("Moving %s has been finished\n", strTargetImageName.c_str()));
    1119 
    1120             /* Check the result of the async process. */
    1121             LONG iRc;
    1122             rc = moveDiskProgress->COMGETTER(ResultCode)(&iRc);
    1123             if (FAILED(rc)) throw rc;
    1124             /* If the thread of the progress object has an error, then
    1125              * retrieve the error info from there, or it'll be lost. */
    1126             if (FAILED(iRc))
    1127             {
    1128                 ProgressErrorInfo pie(moveDiskProgress);
    1129                 Utf8Str errorDesc(pie.getText().raw());
    1130                 errorsList.push_back(ErrorInfoItem(pie.getResultCode(), errorDesc.c_str()));
    1131 
    1132                 throw machine->setError(ProgressErrorInfo(moveDiskProgress));
    1133             }
    11341133
    11351134            ++itMedium;
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