Changeset 44124 in vbox for trunk/src/VBox/Main
- Timestamp:
- Dec 13, 2012 5:11:48 PM (12 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-all/ProgressImpl.cpp
r44039 r44124 19 19 #include <iprt/types.h> 20 20 21 21 22 #if defined(VBOX_WITH_XPCOM) 22 23 #include <nsIServiceManager.h> … … 25 26 #endif /* defined(VBOX_WITH_XPCOM) */ 26 27 27 #include "Progress CombinedImpl.h"28 #include "ProgressImpl.h" 28 29 29 30 #include "VirtualBoxImpl.h" … … 37 38 38 39 #include <VBox/err.h> 40 #include "AutoCaller.h" 39 41 40 42 //////////////////////////////////////////////////////////////////////////////// … … 1322 1324 } 1323 1325 1324 ////////////////////////////////////////////////////////////////////////////////1325 // CombinedProgress class1326 ////////////////////////////////////////////////////////////////////////////////1327 1328 HRESULT CombinedProgress::FinalConstruct()1329 {1330 HRESULT rc = ProgressBase::FinalConstruct();1331 if (FAILED(rc)) return rc;1332 1333 mProgress = 0;1334 mCompletedOperations = 0;1335 1336 return BaseFinalConstruct();1337 }1338 1339 void CombinedProgress::FinalRelease()1340 {1341 uninit();1342 BaseFinalRelease();1343 }1344 1345 // public initializer/uninitializer for internal purposes only1346 ////////////////////////////////////////////////////////////////////////////////1347 1348 /**1349 * Initializes this object based on individual combined progresses.1350 * Must be called only from #init()!1351 *1352 * @param aAutoInitSpan AutoInitSpan object instantiated by a subclass.1353 * @param aParent See ProgressBase::init().1354 * @param aInitiator See ProgressBase::init().1355 * @param aDescription See ProgressBase::init().1356 * @param aId See ProgressBase::init().1357 */1358 HRESULT CombinedProgress::protectedInit(AutoInitSpan &aAutoInitSpan,1359 #if !defined(VBOX_COM_INPROC)1360 VirtualBox *aParent,1361 #endif1362 IUnknown *aInitiator,1363 CBSTR aDescription, OUT_GUID aId)1364 {1365 LogFlowThisFunc(("aDescription={%ls} mProgresses.size()=%d\n",1366 aDescription, mProgresses.size()));1367 1368 HRESULT rc = S_OK;1369 1370 rc = ProgressBase::protectedInit(aAutoInitSpan,1371 #if !defined(VBOX_COM_INPROC)1372 aParent,1373 #endif1374 aInitiator, aDescription, aId);1375 if (FAILED(rc)) return rc;1376 1377 mProgress = 0; /* the first object */1378 mCompletedOperations = 0;1379 1380 mCompleted = FALSE;1381 mCancelable = TRUE; /* until any progress returns FALSE */1382 mCanceled = FALSE;1383 1384 m_cOperations = 0; /* will be calculated later */1385 1386 m_ulCurrentOperation = 0;1387 rc = mProgresses[0]->COMGETTER(OperationDescription)(m_bstrOperationDescription.asOutParam());1388 if (FAILED(rc)) return rc;1389 1390 for (size_t i = 0; i < mProgresses.size(); i ++)1391 {1392 if (mCancelable)1393 {1394 BOOL cancelable = FALSE;1395 rc = mProgresses[i]->COMGETTER(Cancelable)(&cancelable);1396 if (FAILED(rc)) return rc;1397 1398 if (!cancelable)1399 mCancelable = FALSE;1400 }1401 1402 {1403 ULONG opCount = 0;1404 rc = mProgresses[i]->COMGETTER(OperationCount)(&opCount);1405 if (FAILED(rc)) return rc;1406 1407 m_cOperations += opCount;1408 }1409 }1410 1411 rc = checkProgress();1412 if (FAILED(rc)) return rc;1413 1414 return rc;1415 }1416 1417 /**1418 * Initializes the combined progress object given two normal progress1419 * objects.1420 *1421 * @param aParent See ProgressBase::init().1422 * @param aInitiator See ProgressBase::init().1423 * @param aDescription See ProgressBase::init().1424 * @param aProgress1 First normal progress object.1425 * @param aProgress2 Second normal progress object.1426 * @param aId See ProgressBase::init().1427 */1428 HRESULT CombinedProgress::init(1429 #if !defined(VBOX_COM_INPROC)1430 VirtualBox *aParent,1431 #endif1432 IUnknown *aInitiator,1433 CBSTR aDescription,1434 IProgress *aProgress1,1435 IProgress *aProgress2,1436 OUT_GUID aId /* = NULL */)1437 {1438 /* Enclose the state transition NotReady->InInit->Ready */1439 AutoInitSpan autoInitSpan(this);1440 AssertReturn(autoInitSpan.isOk(), E_FAIL);1441 1442 mProgresses.resize(2);1443 mProgresses[0] = aProgress1;1444 mProgresses[1] = aProgress2;1445 1446 HRESULT rc = protectedInit(autoInitSpan,1447 #if !defined(VBOX_COM_INPROC)1448 aParent,1449 #endif1450 aInitiator,1451 aDescription,1452 aId);1453 1454 /* Confirm a successful initialization when it's the case */1455 if (SUCCEEDED(rc))1456 autoInitSpan.setSucceeded();1457 1458 return rc;1459 }1460 1461 /**1462 * Uninitializes the instance and sets the ready flag to FALSE.1463 *1464 * Called either from FinalRelease() or by the parent when it gets destroyed.1465 */1466 void CombinedProgress::uninit()1467 {1468 LogFlowThisFunc(("\n"));1469 1470 /* Enclose the state transition Ready->InUninit->NotReady */1471 AutoUninitSpan autoUninitSpan(this);1472 if (autoUninitSpan.uninitDone())1473 return;1474 1475 mProgress = 0;1476 mProgresses.clear();1477 1478 ProgressBase::protectedUninit(autoUninitSpan);1479 }1480 1481 // IProgress properties1482 ////////////////////////////////////////////////////////////////////////////////1483 1484 STDMETHODIMP CombinedProgress::COMGETTER(Percent)(ULONG *aPercent)1485 {1486 CheckComArgOutPointerValid(aPercent);1487 1488 AutoCaller autoCaller(this);1489 if (FAILED(autoCaller.rc())) return autoCaller.rc();1490 1491 /* checkProgress needs a write lock */1492 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1493 1494 if (mCompleted && SUCCEEDED(mResultCode))1495 *aPercent = 100;1496 else1497 {1498 HRESULT rc = checkProgress();1499 if (FAILED(rc)) return rc;1500 1501 /* global percent =1502 * (100 / m_cOperations) * mOperation +1503 * ((100 / m_cOperations) / 100) * m_ulOperationPercent */1504 *aPercent = (100 * m_ulCurrentOperation + m_ulOperationPercent) / m_cOperations;1505 }1506 1507 return S_OK;1508 }1509 1510 STDMETHODIMP CombinedProgress::COMGETTER(Completed)(BOOL *aCompleted)1511 {1512 CheckComArgOutPointerValid(aCompleted);1513 1514 AutoCaller autoCaller(this);1515 if (FAILED(autoCaller.rc())) return autoCaller.rc();1516 1517 /* checkProgress needs a write lock */1518 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1519 1520 HRESULT rc = checkProgress();1521 if (FAILED(rc)) return rc;1522 1523 return ProgressBase::COMGETTER(Completed)(aCompleted);1524 }1525 1526 STDMETHODIMP CombinedProgress::COMGETTER(Canceled)(BOOL *aCanceled)1527 {1528 CheckComArgOutPointerValid(aCanceled);1529 1530 AutoCaller autoCaller(this);1531 if (FAILED(autoCaller.rc())) return autoCaller.rc();1532 1533 /* checkProgress needs a write lock */1534 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1535 1536 HRESULT rc = checkProgress();1537 if (FAILED(rc)) return rc;1538 1539 return ProgressBase::COMGETTER(Canceled)(aCanceled);1540 }1541 1542 STDMETHODIMP CombinedProgress::COMGETTER(ResultCode)(LONG *aResultCode)1543 {1544 CheckComArgOutPointerValid(aResultCode);1545 1546 AutoCaller autoCaller(this);1547 if (FAILED(autoCaller.rc())) return autoCaller.rc();1548 1549 /* checkProgress needs a write lock */1550 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1551 1552 HRESULT rc = checkProgress();1553 if (FAILED(rc)) return rc;1554 1555 return ProgressBase::COMGETTER(ResultCode)(aResultCode);1556 }1557 1558 STDMETHODIMP CombinedProgress::COMGETTER(ErrorInfo)(IVirtualBoxErrorInfo **aErrorInfo)1559 {1560 CheckComArgOutPointerValid(aErrorInfo);1561 1562 AutoCaller autoCaller(this);1563 if (FAILED(autoCaller.rc())) return autoCaller.rc();1564 1565 /* checkProgress needs a write lock */1566 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1567 1568 HRESULT rc = checkProgress();1569 if (FAILED(rc)) return rc;1570 1571 return ProgressBase::COMGETTER(ErrorInfo)(aErrorInfo);1572 }1573 1574 STDMETHODIMP CombinedProgress::COMGETTER(Operation)(ULONG *aOperation)1575 {1576 CheckComArgOutPointerValid(aOperation);1577 1578 AutoCaller autoCaller(this);1579 if (FAILED(autoCaller.rc())) return autoCaller.rc();1580 1581 /* checkProgress needs a write lock */1582 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1583 1584 HRESULT rc = checkProgress();1585 if (FAILED(rc)) return rc;1586 1587 return ProgressBase::COMGETTER(Operation)(aOperation);1588 }1589 1590 STDMETHODIMP CombinedProgress::COMGETTER(OperationDescription)(BSTR *aOperationDescription)1591 {1592 CheckComArgOutPointerValid(aOperationDescription);1593 1594 AutoCaller autoCaller(this);1595 if (FAILED(autoCaller.rc())) return autoCaller.rc();1596 1597 /* checkProgress needs a write lock */1598 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1599 1600 HRESULT rc = checkProgress();1601 if (FAILED(rc)) return rc;1602 1603 return ProgressBase::COMGETTER(OperationDescription)(aOperationDescription);1604 }1605 1606 STDMETHODIMP CombinedProgress::COMGETTER(OperationPercent)(ULONG *aOperationPercent)1607 {1608 CheckComArgOutPointerValid(aOperationPercent);1609 1610 AutoCaller autoCaller(this);1611 if (FAILED(autoCaller.rc())) return autoCaller.rc();1612 1613 /* checkProgress needs a write lock */1614 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1615 1616 HRESULT rc = checkProgress();1617 if (FAILED(rc)) return rc;1618 1619 return ProgressBase::COMGETTER(OperationPercent)(aOperationPercent);1620 }1621 1622 STDMETHODIMP CombinedProgress::COMSETTER(Timeout)(ULONG aTimeout)1623 {1624 NOREF(aTimeout);1625 AssertFailed();1626 return E_NOTIMPL;1627 }1628 1629 STDMETHODIMP CombinedProgress::COMGETTER(Timeout)(ULONG *aTimeout)1630 {1631 CheckComArgOutPointerValid(aTimeout);1632 1633 AssertFailed();1634 return E_NOTIMPL;1635 }1636 1637 // IProgress methods1638 /////////////////////////////////////////////////////////////////////////////1639 1640 /**1641 * @note XPCOM: when this method is called not on the main XPCOM thread, it1642 * simply blocks the thread until mCompletedSem is signalled. If the1643 * thread has its own event queue (hmm, what for?) that it must run, then1644 * calling this method will definitely freeze event processing.1645 */1646 STDMETHODIMP CombinedProgress::WaitForCompletion(LONG aTimeout)1647 {1648 LogFlowThisFuncEnter();1649 LogFlowThisFunc(("aTtimeout=%d\n", aTimeout));1650 1651 AutoCaller autoCaller(this);1652 if (FAILED(autoCaller.rc())) return autoCaller.rc();1653 1654 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1655 1656 /* if we're already completed, take a shortcut */1657 if (!mCompleted)1658 {1659 HRESULT rc = S_OK;1660 bool forever = aTimeout < 0;1661 int64_t timeLeft = aTimeout;1662 int64_t lastTime = RTTimeMilliTS();1663 1664 while (!mCompleted && (forever || timeLeft > 0))1665 {1666 alock.release();1667 rc = mProgresses.back()->WaitForCompletion(forever ? -1 : (LONG) timeLeft);1668 alock.acquire();1669 1670 if (SUCCEEDED(rc))1671 rc = checkProgress();1672 1673 if (FAILED(rc)) break;1674 1675 if (!forever)1676 {1677 int64_t now = RTTimeMilliTS();1678 timeLeft -= now - lastTime;1679 lastTime = now;1680 }1681 }1682 1683 if (FAILED(rc)) return rc;1684 }1685 1686 LogFlowThisFuncLeave();1687 1688 return S_OK;1689 }1690 1691 /**1692 * @note XPCOM: when this method is called not on the main XPCOM thread, it1693 * simply blocks the thread until mCompletedSem is signalled. If the1694 * thread has its own event queue (hmm, what for?) that it must run, then1695 * calling this method will definitely freeze event processing.1696 */1697 STDMETHODIMP CombinedProgress::WaitForOperationCompletion(ULONG aOperation, LONG aTimeout)1698 {1699 LogFlowThisFuncEnter();1700 LogFlowThisFunc(("aOperation=%d, aTimeout=%d\n", aOperation, aTimeout));1701 1702 AutoCaller autoCaller(this);1703 if (FAILED(autoCaller.rc())) return autoCaller.rc();1704 1705 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1706 1707 if (aOperation >= m_cOperations)1708 return setError(E_FAIL,1709 tr("Operation number must be in range [0, %d]"), m_ulCurrentOperation - 1);1710 1711 /* if we're already completed or if the given operation is already done,1712 * then take a shortcut */1713 if (!mCompleted && aOperation >= m_ulCurrentOperation)1714 {1715 HRESULT rc = S_OK;1716 1717 /* find the right progress object to wait for */1718 size_t progress = mProgress;1719 ULONG operation = 0, completedOps = mCompletedOperations;1720 do1721 {1722 ULONG opCount = 0;1723 rc = mProgresses[progress]->COMGETTER(OperationCount)(&opCount);1724 if (FAILED(rc))1725 return rc;1726 1727 if (completedOps + opCount > aOperation)1728 {1729 /* found the right progress object */1730 operation = aOperation - completedOps;1731 break;1732 }1733 1734 completedOps += opCount;1735 progress ++;1736 ComAssertRet(progress < mProgresses.size(), E_FAIL);1737 }1738 while (1);1739 1740 LogFlowThisFunc(("will wait for mProgresses [%d] (%d)\n",1741 progress, operation));1742 1743 bool forever = aTimeout < 0;1744 int64_t timeLeft = aTimeout;1745 int64_t lastTime = RTTimeMilliTS();1746 1747 while (!mCompleted && aOperation >= m_ulCurrentOperation &&1748 (forever || timeLeft > 0))1749 {1750 alock.release();1751 /* wait for the appropriate progress operation completion */1752 rc = mProgresses[progress]-> WaitForOperationCompletion(operation,1753 forever ? -1 : (LONG) timeLeft);1754 alock.acquire();1755 1756 if (SUCCEEDED(rc))1757 rc = checkProgress();1758 1759 if (FAILED(rc)) break;1760 1761 if (!forever)1762 {1763 int64_t now = RTTimeMilliTS();1764 timeLeft -= now - lastTime;1765 lastTime = now;1766 }1767 }1768 1769 if (FAILED(rc)) return rc;1770 }1771 1772 LogFlowThisFuncLeave();1773 1774 return S_OK;1775 }1776 1777 STDMETHODIMP CombinedProgress::Cancel()1778 {1779 AutoCaller autoCaller(this);1780 if (FAILED(autoCaller.rc())) return autoCaller.rc();1781 1782 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1783 1784 if (!mCancelable)1785 return setError(E_FAIL, tr("Operation cannot be canceled"));1786 1787 if (!mCanceled)1788 {1789 LogThisFunc(("Canceling\n"));1790 mCanceled = TRUE;1791 /** @todo Teleportation: Shouldn't this be propagated to mProgresses? If1792 * powerUp creates passes a combined progress object to the client, I1793 * won't get called back since I'm only getting the powerupProgress ...1794 * Or what? */1795 if (m_pfnCancelCallback)1796 m_pfnCancelCallback(m_pvCancelUserArg);1797 1798 }1799 else1800 LogThisFunc(("Already canceled\n"));1801 1802 return S_OK;1803 }1804 1805 // private methods1806 ////////////////////////////////////////////////////////////////////////////////1807 1808 /**1809 * Fetches the properties of the current progress object and, if it is1810 * successfully completed, advances to the next uncompleted or unsuccessfully1811 * completed object in the vector of combined progress objects.1812 *1813 * @note Must be called from under this object's write lock!1814 */1815 HRESULT CombinedProgress::checkProgress()1816 {1817 /* do nothing if we're already marked ourselves as completed */1818 if (mCompleted)1819 return S_OK;1820 1821 AssertReturn(mProgress < mProgresses.size(), E_FAIL);1822 1823 ComPtr<IProgress> progress = mProgresses[mProgress];1824 ComAssertRet(!progress.isNull(), E_FAIL);1825 1826 HRESULT rc = S_OK;1827 BOOL fCompleted = FALSE;1828 1829 do1830 {1831 rc = progress->COMGETTER(Completed)(&fCompleted);1832 if (FAILED(rc))1833 return rc;1834 1835 if (fCompleted)1836 {1837 rc = progress->COMGETTER(Canceled)(&mCanceled);1838 if (FAILED(rc))1839 return rc;1840 1841 LONG iRc;1842 rc = progress->COMGETTER(ResultCode)(&iRc);1843 if (FAILED(rc))1844 return rc;1845 mResultCode = iRc;1846 1847 if (FAILED(mResultCode))1848 {1849 rc = progress->COMGETTER(ErrorInfo)(mErrorInfo.asOutParam());1850 if (FAILED(rc))1851 return rc;1852 }1853 1854 if (FAILED(mResultCode) || mCanceled)1855 {1856 mCompleted = TRUE;1857 }1858 else1859 {1860 ULONG opCount = 0;1861 rc = progress->COMGETTER(OperationCount)(&opCount);1862 if (FAILED(rc))1863 return rc;1864 1865 mCompletedOperations += opCount;1866 mProgress ++;1867 1868 if (mProgress < mProgresses.size())1869 progress = mProgresses[mProgress];1870 else1871 mCompleted = TRUE;1872 }1873 }1874 }1875 while (fCompleted && !mCompleted);1876 1877 rc = progress->COMGETTER(OperationPercent)(&m_ulOperationPercent);1878 if (SUCCEEDED(rc))1879 {1880 ULONG operation = 0;1881 rc = progress->COMGETTER(Operation)(&operation);1882 if (SUCCEEDED(rc) && mCompletedOperations + operation > m_ulCurrentOperation)1883 {1884 m_ulCurrentOperation = mCompletedOperations + operation;1885 rc = progress->COMGETTER(OperationDescription)(m_bstrOperationDescription.asOutParam());1886 }1887 }1888 1889 return rc;1890 }1891 /* vi: set tabstop=4 shiftwidth=4 expandtab: */ -
trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
r44091 r44124 64 64 # include "UsbCardReader.h" 65 65 #endif 66 #include "Progress CombinedImpl.h"66 #include "ProgressImpl.h" 67 67 #include "ConsoleVRDPServer.h" 68 68 #include "VMMDev.h" … … 6697 6697 else 6698 6698 { 6699 / * create a combined progress object */6700 ComObjPtr< CombinedProgress> pProgress;6699 // Create a simple progress object 6700 ComObjPtr<Progress> pProgress; 6701 6701 pProgress.createObject(); 6702 6703 // Assign hard disk progresses to the progresses list 6702 6704 VMPowerUpTask::ProgressList progresses(task->hardDiskProgresses); 6703 progresses.push_back(ComPtr<IProgress> (pPowerupProgress)); 6705 6706 // Setup params to be used to initialize Progress object properties. 6707 ULONG cOperations = 1; 6708 ULONG ulTotalOperationsWeight = 1; 6709 6710 // Go round them and set number of operations and weight. 6711 for (VMPowerUpTask::ProgressList::const_iterator it = progresses.begin(); it != progresses.end(); ++it) 6712 { 6713 ++cOperations; 6714 ulTotalOperationsWeight += 1; 6715 } 6716 6704 6717 rc = pProgress->init(static_cast<IConsole *>(this), 6705 progressDesc.raw(), progresses.begin(), 6706 progresses.end()); 6718 progressDesc.raw(), 6719 TRUE, // Cancelable 6720 cOperations, 6721 ulTotalOperationsWeight, 6722 Bstr(tr("Starting Hard Disk operations")).raw(), // first sub-op decription 6723 1 ); 6707 6724 AssertComRCReturnRC(rc); 6708 pProgress.queryInterfaceTo(aProgress); 6725 6726 // Perform all the necessary operations. 6727 for (VMPowerUpTask::ProgressList::const_iterator it = progresses.begin(); it != progresses.end(); ++it) 6728 { 6729 rc = pProgress->SetNextOperation(BstrFmt(tr("Disk Image Reset Operation - Immutable Image")).raw(), 1); 6730 AssertComRCReturnRC(rc); 6731 rc = pProgress.queryInterfaceTo(aProgress); 6732 AssertComRCReturnRC(rc); 6733 } 6734 6735 // Now do the power up. 6736 rc = pPowerupProgress.queryInterfaceTo(aProgress); 6737 AssertComRCReturnRC(rc); 6709 6738 } 6710 6739 } -
trunk/src/VBox/Main/src-client/xpcom/module.cpp
r42865 r44124 49 49 #include "NATEngineImpl.h" 50 50 #include "NetworkAdapterImpl.h" 51 #include "ProgressCombinedImpl.h"52 51 #include "ProgressImpl.h" 53 52 #include "RemoteUSBDeviceImpl.h" … … 85 84 NS_DECL_CLASSINFO(Progress) 86 85 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(Progress, IProgress) 87 NS_DECL_CLASSINFO(CombinedProgress)88 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(CombinedProgress, IProgress)89 86 NS_DECL_CLASSINFO(OUSBDevice) 90 87 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(OUSBDevice, IUSBDevice) -
trunk/src/VBox/Main/src-server/xpcom/server.cpp
r41100 r44124 78 78 #include "NetworkAdapterImpl.h" 79 79 #include "ParallelPortImpl.h" 80 #include "ProgressCombinedImpl.h"81 80 #include "ProgressProxyImpl.h" 82 81 #include "SerialPortImpl.h" … … 135 134 NS_DECL_CLASSINFO(Progress) 136 135 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(Progress, IProgress) 137 138 NS_DECL_CLASSINFO(CombinedProgress)139 NS_IMPL_THREADSAFE_ISUPPORTS1_CI(CombinedProgress, IProgress)140 136 141 137 NS_DECL_CLASSINFO(ProgressProxy)
Note:
See TracChangeset
for help on using the changeset viewer.