Changeset 73743 in vbox
- Timestamp:
- Aug 17, 2018 5:56:34 PM (6 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/idl/VirtualBox.xidl
r73716 r73743 14212 14212 <interface 14213 14213 name="IProgress" extends="$unknown" 14214 uuid=" e0026dc0-0c55-47b1-aa64-d340a396b418"14214 uuid="64c7fb5c-ce8f-4681-9c8c-d523cb4dea3d" 14215 14215 wsmap="managed" 14216 14216 reservedMethods="1" reservedAttributes="2" … … 14407 14407 <desc> 14408 14408 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 all14416 sub-operations) and forward all changes from the other progress to14417 this progress. This means sub-operation number, description, percent14418 and so on.14419 14420 You have to take care on setting up at least the same count on14421 sub-operations in this progress object like there are in the other14422 progress object.14423 14424 If the other progress object supports cancel and this object gets any14425 cancel request (when here enabled as well), it will be forwarded to14426 the other progress object.14427 14428 If there is an error in the other progress, this error isn't14429 automatically transfered to this progress object. So you have to14430 check any operation error within the other progress object, after14431 this method returns.14432 </desc>14433 14434 <param name="pProgressAsync" type="IProgress" dir="in">14435 <desc>14436 The progress object of the asynchrony process.14437 14409 </desc> 14438 14410 </param> -
trunk/src/VBox/Main/include/ApplianceImpl.h
r73133 r73743 130 130 const Utf8Str &strDescription, 131 131 SetUpProgressMode mode); 132 void i_waitForAsyncProgress(ComObjPtr<Progress> &pProgressThis, ComPtr<IProgress> &pProgressAsync);133 132 void i_addWarning(const char* aWarning, ...); 134 133 void i_disksWeight(); -
trunk/src/VBox/Main/include/ProgressImpl.h
r69500 r73743 138 138 HRESULT i_notifyCompleteEI(HRESULT aResultCode, 139 139 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); 140 162 141 163 bool i_notifyPointOfNoReturn(void); … … 213 235 HRESULT waitForOperationCompletion(ULONG aOperation, 214 236 LONG aTimeout); 215 HRESULT waitForAsyncProgressCompletion(const ComPtr<IProgress> &aPProgressAsync);216 237 HRESULT cancel(); 217 238 -
trunk/src/VBox/Main/src-all/ProgressImpl.cpp
r73716 r73743 486 486 } 487 487 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) 488 HRESULT Progress::i_waitForOtherProgressCompletion(const ComPtr<IProgress> &aProgressOther) 875 489 { 876 490 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. */ 987 493 988 494 HRESULT rc = S_OK; … … 994 500 ULONG cOp = 0; 995 501 /* Is the async process cancelable? */ 996 rc = aP ProgressAsync->COMGETTER(Cancelable)(&fCancelable);502 rc = aProgressOther->COMGETTER(Cancelable)(&fCancelable); 997 503 if (FAILED(rc)) return rc; 998 504 /* Loop as long as the sync process isn't completed. */ 999 while (SUCCEEDED(aP ProgressAsync->COMGETTER(Completed(&fCompleted))))505 while (SUCCEEDED(aProgressOther->COMGETTER(Completed(&fCompleted)))) 1000 506 { 1001 507 /* We can forward any cancel request to the async process only when … … 1007 513 if (fCanceled) 1008 514 { 1009 rc = aP ProgressAsync->Cancel();515 rc = aProgressOther->Cancel(); 1010 516 if (FAILED(rc)) return rc; 1011 517 } … … 1024 530 for (;;) 1025 531 { 1026 rc = aP ProgressAsync->COMGETTER(Operation(&curOp));532 rc = aProgressOther->COMGETTER(Operation(&curOp)); 1027 533 if (FAILED(rc)) return rc; 1028 534 if (cOp != curOp) … … 1030 536 Bstr bstr; 1031 537 ULONG currentWeight; 1032 rc = aP ProgressAsync->COMGETTER(OperationDescription(bstr.asOutParam()));538 rc = aProgressOther->COMGETTER(OperationDescription(bstr.asOutParam())); 1033 539 if (FAILED(rc)) return rc; 1034 rc = aP ProgressAsync->COMGETTER(OperationWeight(¤tWeight));540 rc = aProgressOther->COMGETTER(OperationWeight(¤tWeight)); 1035 541 if (FAILED(rc)) return rc; 1036 542 rc = SetNextOperation(bstr.raw(), currentWeight); … … 1042 548 } 1043 549 1044 rc = aP ProgressAsync->COMGETTER(OperationPercent(¤tPercent));550 rc = aProgressOther->COMGETTER(OperationPercent(¤tPercent)); 1045 551 if (FAILED(rc)) return rc; 1046 552 if (currentPercent != prevPercent) … … 1055 561 1056 562 /* Make sure the loop is not too tight */ 1057 rc = aP ProgressAsync->WaitForCompletion(100);563 rc = aProgressOther->WaitForCompletion(100); 1058 564 if (FAILED(rc)) return rc; 1059 565 } 1060 566 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 1061 578 LogFlowThisFuncLeave(); 1062 1063 579 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 */ 596 bool 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 */ 625 bool 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 684 HRESULT 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 692 HRESULT 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 } 699 HRESULT 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 717 HRESULT Progress::getCancelable(BOOL *aCancelable) 718 { 719 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 720 721 *aCancelable = mCancelable; 722 723 return S_OK; 724 } 725 726 HRESULT 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 753 HRESULT 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 781 HRESULT Progress::getCompleted(BOOL *aCompleted) 782 { 783 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 784 785 *aCompleted = mCompleted; 786 787 return S_OK; 788 } 789 790 HRESULT Progress::getCanceled(BOOL *aCanceled) 791 { 792 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 793 794 *aCanceled = mCanceled; 795 796 return S_OK; 797 } 798 799 HRESULT 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 811 HRESULT 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 823 HRESULT 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 832 HRESULT 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 841 HRESULT 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 850 HRESULT 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 862 HRESULT 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 871 HRESULT 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 880 HRESULT 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 */ 901 HRESULT 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 */ 932 HRESULT 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 */ 968 HRESULT 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 */ 1022 HRESULT 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; 1064 1074 } 1065 1075 -
trunk/src/VBox/Main/src-server/ApplianceImpl.cpp
r73132 r73743 1049 1049 } 1050 1050 1051 /**1052 * Called from the import and export background threads to synchronize the second1053 * background disk thread's progress object with the current progress object so1054 * that the user interface sees progress correctly and that cancel signals are1055 * 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 result1066 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 possible1077 that in the meantime more than one async operation was finished. So1078 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(¤tWeight));1091 if (FAILED(rc)) throw rc;1092 rc = pProgressThis->SetNextOperation(bstr.raw(), currentWeight);1093 if (FAILED(rc)) throw rc;1094 ++cOp;1095 }1096 else1097 break;1098 }1099 1100 rc = pProgressAsync->COMGETTER(OperationPercent(¤tPercent));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 operation1111 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, then1117 // retrieve the error info from there, or it'll be lost1118 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 1128 1051 void Appliance::i_addWarning(const char* aWarning, ...) 1129 1052 { -
trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp
r73665 r73743 2399 2399 ImportStack &stack) 2400 2400 { 2401 HRESULT rc; 2401 2402 char *pszAbsDstPath = RTPathAbsExDup(stack.strMachineFolder.c_str(), 2402 2403 strDstPath.c_str()); … … 2404 2405 RTStrFree(pszAbsDstPath); 2405 2406 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;2415 2407 2416 2408 /* Get the system properties. */ … … 2563 2555 if (FAILED(rc)) throw rc; 2564 2556 2557 ComPtr<IProgress> pProgressImport; 2565 2558 /* If strHref is empty we have to create a new file. */ 2566 2559 if (strSourceOVF.isEmpty()) … … 2572 2565 rc = pTargetMedium->CreateBaseStorage(di.iCapacity / _1M, 2573 2566 ComSafeArrayAsInParam(mediumVariant), 2574 ComPtr<IProgress>(pProgress).asOutParam());2567 pProgressImport.asOutParam()); 2575 2568 if (FAILED(rc)) throw rc; 2576 2569 … … 2631 2624 /* Start the source image cloning operation. */ 2632 2625 ComObjPtr<Medium> nullParent; 2626 ComObjPtr<Progress> pProgressImportTmp; 2633 2627 rc = pTargetMedium->i_importFile(strSrcFilePath.c_str(), 2634 2628 srcFormat, … … 2636 2630 hVfsIosReadAhead, 2637 2631 nullParent, 2638 pProgress); 2632 pProgressImportTmp); 2633 pProgressImportTmp.queryInterfaceTo(pProgressImport.asOutParam()); 2639 2634 RTVfsIoStrmRelease(hVfsIosReadAhead); 2640 2635 hVfsIosSrc = NIL_RTVFSIOSTREAM; … … 2651 2646 /* Now wait for the background import operation to complete; this throws 2652 2647 * HRESULTs on error. */ 2653 ComPtr<IProgress> pp(pProgress); 2654 i_waitForAsyncProgress(stack.pProgress, pp); 2648 stack.pProgress->i_waitForOtherProgressCompletion(pProgressImport); 2655 2649 } 2656 2650 } -
trunk/src/VBox/Main/src-server/MachineImpl.cpp
r73740 r73743 5484 5484 rc = pMedium->DeleteStorage(pProgress2.asOutParam()); 5485 5485 if (FAILED(rc)) throw rc; 5486 rc = task.m_pProgress-> WaitForAsyncProgressCompletion(pProgress2);5486 rc = task.m_pProgress->i_waitForOtherProgressCompletion(pProgress2); 5487 5487 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, then5493 * retrieve the error info from there, or it'll be lost. */5494 if (FAILED(iRc))5495 throw setError(ProgressErrorInfo(pProgress2));5496 5488 } 5497 5489 -
trunk/src/VBox/Main/src-server/MachineImplCloneVM.cpp
r73664 r73743 1290 1290 /* Wait until the async process has finished. */ 1291 1291 srcLock.release(); 1292 rc = d->pProgress-> WaitForAsyncProgressCompletion(progress2);1292 rc = d->pProgress->i_waitForOtherProgressCompletion(progress2); 1293 1293 srcLock.acquire(); 1294 1294 if (FAILED(rc)) throw rc; 1295 1295 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, then1301 * retrieve the error info from there, or it'll be lost. */1302 if (FAILED(iRc))1303 throw p->setError(ProgressErrorInfo(progress2));1304 1296 /* Remember created medium. */ 1305 1297 newMedia.append(pTarget); -
trunk/src/VBox/Main/src-server/MachineImplMoveVM.cpp
r73003 r73743 21 21 #include <iprt/cpp/utils.h> 22 22 #include <iprt/stream.h> 23 #include <VBox/com/ErrorInfo.h> 23 24 24 25 #include "MachineImplMoveVM.h" … … 26 27 #include "VirtualBoxImpl.h" 27 28 #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 28 34 29 35 /* This variable is global and used in the different places so it must be cleared each time before usage to avoid failure */ … … 1105 1111 { 1106 1112 /* In case of failure moveDiskProgress would be in the invalid state or not initialized at all 1107 * Call WaitForAsyncProgressCompletion only in success1113 * Call i_waitForOtherProgressCompletion only in success 1108 1114 */ 1109 /* Wait until the asyncprocess has finished. */1110 rc = m_pProgress-> WaitForAsyncProgressCompletion(moveDiskProgress);1115 /* Wait until the other process has finished. */ 1116 rc = m_pProgress->i_waitForOtherProgressCompletion(moveDiskProgress); 1111 1117 } 1112 1118 … … 1114 1120 machineLock.acquire(); 1115 1121 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 1116 1130 if (FAILED(rc)) throw rc; 1117 1131 1118 1132 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, then1125 * 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 }1134 1133 1135 1134 ++itMedium;
Note:
See TracChangeset
for help on using the changeset viewer.