VirtualBox

Changeset 31296 in vbox for trunk/src/VBox/Main/HostImpl.cpp


Ignore:
Timestamp:
Aug 2, 2010 1:13:14 PM (14 years ago)
Author:
vboxsync
Message:

Main: cleanup host drives management: do not return different IMedium objects every time Host::GetDVDDrives() or HOst::GetFloppyDrives() are called; refresh the internal list only when a public API is called, but not for every single internal use such as loading machine settings file; fix code duplication

File:
1 edited

Legend:

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

    r30764 r31296  
    155155{
    156156    Data()
     157        :
    157158#ifdef VBOX_WITH_USB
    158         : usbListsLock(LOCKCLASS_USBLIST)
     159          usbListsLock(LOCKCLASS_USBLIST),
    159160#endif
     161          fDVDDrivesListBuilt(false),
     162          fFloppyDrivesListBuilt(false)
    160163    {};
    161164
     
    171174    USBProxyService         *pUSBProxyService;
    172175#endif /* VBOX_WITH_USB */
     176
     177    // list of host drives; lazily created by getDVDDrives() and getFloppyDrives()
     178    MediaList               llDVDDrives,
     179                            llFloppyDrives;
     180    bool                    fDVDDrivesListBuilt,
     181                            fFloppyDrivesListBuilt;
    173182
    174183#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
     
    409418    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    410419
    411     MediaList list;
    412     HRESULT rc = getDVDDrives(list);
     420    MediaList *pList;
     421    HRESULT rc = getDrives(DeviceType_DVD, true /* fRefresh */, pList);
    413422    if (SUCCEEDED(rc))
    414423    {
    415         SafeIfaceArray<IMedium> array(list);
     424        SafeIfaceArray<IMedium> array(*pList);
    416425        array.detachTo(ComSafeArrayOutArg(aDrives));
    417426    }
     
    435444    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    436445
    437     MediaList list;
    438     HRESULT rc = getFloppyDrives(list);
     446    MediaList *pList;
     447    HRESULT rc = getDrives(DeviceType_Floppy, true /* fRefresh */, pList);
    439448    if (SUCCEEDED(rc))
    440449    {
    441         SafeIfaceArray<IMedium> collection(list);
     450        SafeIfaceArray<IMedium> collection(*pList);
    442451        collection.detachTo(ComSafeArrayOutArg(aDrives));
    443452    }
     
    15101519}
    15111520
    1512 HRESULT Host::getDVDDrives(MediaList &list)
     1521/**
     1522 * Sets the given pointer to point to the static list of DVD or floppy
     1523 * drives in the Host instance data, depending on the @a mediumType
     1524 * parameter.
     1525 *
     1526 * This builds the list on the first call; it adds or removes host drives
     1527 * that may have changed if fRefresh == true.
     1528 *
     1529 * The caller must hold the Host write lock before calling this.
     1530 * To protect the list to which the caller's pointer points, the caller
     1531 * must also hold the Host lock.
     1532 *
     1533 * @param mediumType Must be DeviceType_Floppy or DeviceType_DVD.
     1534 * @param fRefresh Whether to refresh the host drives list even if this is not the first call.
     1535 * @param pll Caller's pointer which gets set to the static list of host drives.
     1536 * @return
     1537 */
     1538HRESULT Host::getDrives(DeviceType_T mediumType,
     1539                        bool fRefresh,
     1540                        MediaList *&pll)
     1541{
     1542    HRESULT rc = S_OK;
     1543    Assert(isWriteLockOnCurrentThread());
     1544
     1545    MediaList llNew;
     1546    MediaList *pllCached;
     1547    bool *pfListBuilt = NULL;
     1548
     1549    switch (mediumType)
     1550    {
     1551        case DeviceType_DVD:
     1552            if (!m->fDVDDrivesListBuilt || fRefresh)
     1553            {
     1554                rc = buildDVDDrivesList(llNew);
     1555                if (FAILED(rc))
     1556                    return rc;
     1557                pfListBuilt = &m->fDVDDrivesListBuilt;
     1558            }
     1559            pllCached = &m->llDVDDrives;
     1560        break;
     1561
     1562        case DeviceType_Floppy:
     1563            if (!m->fFloppyDrivesListBuilt || fRefresh)
     1564            {
     1565                rc = buildFloppyDrivesList(llNew);
     1566                if (FAILED(rc))
     1567                    return rc;
     1568                pfListBuilt = &m->fFloppyDrivesListBuilt;
     1569            }
     1570            pllCached = &m->llFloppyDrives;
     1571        break;
     1572
     1573        default:
     1574            return E_INVALIDARG;
     1575    }
     1576
     1577    if (pfListBuilt)
     1578    {
     1579        // a list was built in llNew above:
     1580        if (!*pfListBuilt)
     1581        {
     1582            // this was the first call (instance bool is still false): then just copy the whole list and return
     1583            *pllCached = llNew;
     1584            // and mark the instance data as "built"
     1585            *pfListBuilt = true;
     1586        }
     1587        else
     1588        {
     1589            // list was built, and this was a subsequent call: then compare the old and the new lists
     1590
     1591            // remove drives from the cached list which are no longer present
     1592            for (MediaList::iterator itCached = pllCached->begin();
     1593                 itCached != pllCached->end();
     1594                 ++itCached)
     1595            {
     1596                Medium *pCached = *itCached;
     1597                const Utf8Str strLocationCached = pCached->getLocation();
     1598                bool fFound = false;
     1599                for (MediaList::iterator itNew = llNew.begin();
     1600                     itNew != llNew.end();
     1601                     ++itNew)
     1602                {
     1603                    Medium *pNew = *itNew;
     1604                    const Utf8Str strLocationNew = pNew->getLocation();
     1605                    if (strLocationNew == strLocationCached)
     1606                    {
     1607                        fFound = true;
     1608                        break;
     1609                    }
     1610                }
     1611                if (!fFound)
     1612                    itCached = pllCached->erase(itCached);
     1613            }
     1614
     1615            // add drives to the cached list that are not on there yet
     1616            for (MediaList::iterator itNew = llNew.begin();
     1617                 itNew != llNew.end();
     1618                 ++itNew)
     1619            {
     1620                Medium *pNew = *itNew;
     1621                const Utf8Str strLocationNew = pNew->getLocation();
     1622                bool fFound = false;
     1623                for (MediaList::iterator itCached = pllCached->begin();
     1624                     itCached != pllCached->end();
     1625                     ++itCached)
     1626                {
     1627                    Medium *pCached = *itCached;
     1628                    const Utf8Str strLocationCached = pCached->getLocation();
     1629                    if (strLocationNew == strLocationCached)
     1630                    {
     1631                        fFound = true;
     1632                        break;
     1633                    }
     1634                }
     1635
     1636                if (!fFound)
     1637                    pllCached->push_back(pNew);
     1638            }
     1639        }
     1640    }
     1641
     1642    // return cached list to caller
     1643    pll = pllCached;
     1644
     1645    return rc;
     1646}
     1647
     1648/**
     1649 * Goes through the list of host drives that would be returned by getDrives()
     1650 * and looks for a host drive with the given UUID. If found, it sets pMedium
     1651 * to that drive; otherwise returns VBOX_E_OBJECT_NOT_FOUND.
     1652 * @param mediumType Must be DeviceType_DVD or DeviceType_Floppy.
     1653 * @param uuid Medium UUID of host drive to look for.
     1654 * @param fRefresh Whether to refresh the host drives list (see getDrives())
     1655 * @param pMedium Medium object, if found…
     1656 * @return VBOX_E_OBJECT_NOT_FOUND if not found, or S_OK if found, or errors from getDrives().
     1657 */
     1658HRESULT Host::findHostDrive(DeviceType_T mediumType,
     1659                            const Guid &uuid,
     1660                            bool fRefresh,
     1661                            ComObjPtr<Medium> &pMedium)
     1662{
     1663    MediaList *pllMedia;
     1664
     1665    AutoWriteLock wlock(this COMMA_LOCKVAL_SRC_POS);
     1666    HRESULT rc = getDrives(mediumType, fRefresh, pllMedia);
     1667    if (SUCCEEDED(rc))
     1668    {
     1669        for (MediaList::iterator it = pllMedia->begin();
     1670             it != pllMedia->end();
     1671             ++it)
     1672        {
     1673            Medium *pThis = *it;
     1674            if (pThis->getId() == uuid)
     1675            {
     1676                pMedium = pThis;
     1677                return S_OK;
     1678            }
     1679        }
     1680    }
     1681
     1682    return VBOX_E_OBJECT_NOT_FOUND;
     1683}
     1684
     1685/**
     1686 * Called from getDrives() to build the DVD drives list.
     1687 * @param pll
     1688 * @return
     1689 */
     1690HRESULT Host::buildDVDDrivesList(MediaList &list)
    15131691{
    15141692    HRESULT rc = S_OK;
     
    16231801
    16241802/**
    1625  * Internal implementation for COMGETTER(FloppyDrives) which can be called
    1626  * from elsewhere. Caller must hold the Host object write lock!
     1803 * Called from getDrives() to build the floppy drives list.
    16271804 * @param list
    16281805 * @return
    16291806 */
    1630 HRESULT Host::getFloppyDrives(MediaList &list)
     1807HRESULT Host::buildFloppyDrivesList(MediaList &list)
    16311808{
    16321809    HRESULT rc = S_OK;
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