VirtualBox

Ignore:
Timestamp:
Dec 3, 2009 3:40:52 PM (15 years ago)
Author:
vboxsync
Message:

Main: rework VirtualBox implemenation to no longer use VirtualBoxBaseWithChildren; instead use individual lists for media, machines, shared folders etc. with individual locking; implement new ObjectsList class template for that

File:
1 edited

Legend:

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

    r25151 r25170  
    7070
    7171#include "Logging.h"
     72#include "objectslist.h"
    7273
    7374#ifdef RT_OS_WINDOWS
     
    8283
    8384#define VBOX_GLOBAL_SETTINGS_FILE "VirtualBox.xml"
    84 
    85 typedef std::vector< ComObjPtr<Machine> > MachineVector;
    86 
    87 typedef std::list< ComObjPtr<Machine> > MachineList;
    88 typedef std::vector< ComObjPtr<SessionMachine> > SessionMachineVector;
    89 typedef std::list< ComObjPtr<GuestOSType> > GuestOSTypeList;
    90 
    91 typedef std::map<Guid, ComPtr<IProgress> > ProgressMap;
    92 
    93 typedef std::list <ComObjPtr<SharedFolder> > SharedFolderList;
    94 typedef std::list <ComObjPtr<DHCPServer> > DHCPServerList;
    95 
    96 typedef std::map<Guid, ComObjPtr<Medium> > HardDiskMap;
    97 
    9885
    9986////////////////////////////////////////////////////////////////////////////////
     
    169156#endif
    170157
     158typedef ObjectsList<Machine> MachinesOList;
     159typedef ObjectsList<Medium> MediaOList;
     160typedef ObjectsList<GuestOSType> GuestOSTypesOList;
     161typedef ObjectsList<SharedFolder> SharedFoldersOList;
     162typedef ObjectsList<DHCPServer> DHCPServersOList;
     163
     164typedef std::map<Guid, ComPtr<IProgress> > ProgressMap;
     165typedef std::map<Guid, ComObjPtr<Medium> > HardDiskMap;
     166
    171167/**
    172168 *  Main VirtualBox data structure.
     
    198194#endif /* VBOX_WITH_RESOURCE_USAGE_API */
    199195
    200     MachineList                         llMachines;
    201     GuestOSTypeList                     llGuestOSTypes;
     196    // the following lists all have an RWLockHandle as a member and are locked
     197    // individually; getting the VirtualBox object lock is NOT necessary, but
     198    // see the remarks which ObjectsList method lock themselves and which require
     199    // external locking
     200    MachinesOList                       ollMachines;
     201    GuestOSTypesOList                   ollGuestOSTypes;
     202
     203    MediaOList                          ollHardDisks,           // only base hard disks; the RWLockHandle in here is also used
     204                                                                // for hardDiskTreeLockHandle()
     205                                        ollDVDImages,
     206                                        ollFloppyImages;
     207    SharedFoldersOList                  ollSharedFolders;
     208    DHCPServersOList                    ollDHCPServers;
     209
     210    // the hard disks map is an additional map sorted by UUID for quick lookup
     211    // and contains ALL hard disks (base and differencing);
     212    // the map must also be protected by ollHardDisks.getLockHandle()!
     213    HardDiskMap                         mapHardDisks;
    202214
    203215    ProgressMap                         mapProgressOperations;
    204 
    205     MediaList                           llHardDisks,
    206                                         llDVDImages,
    207                                         llFloppyImages;
    208     SharedFolderList                    llSharedFolders;
    209     DHCPServerList                      llDHCPServers;
    210 
    211     /// @todo NEWMEDIA do we really need this map? Used only in
    212     /// find() it seems
    213     HardDiskMap                         mapHardDisks;
    214 
    215216    CallbackList                        llCallbacks;
    216217
    217218    RWLockHandle                        mtxProgressOperations;
    218219            // protects mutex operations; "leaf" lock, no other lock may be requested after this
    219     RWLockHandle                        mtxHardDiskTree;
    220             // protects the hard disk tree; this is implemented here, but only requested through
    221             // Medium::treeLock, which returns exactly this
    222     RWLockHandle                        mtxChildrenMap;
    223             // used for VirtualBoxWithChildrenNEXT management
    224220
    225221    // the following are data for the client watcher thread
     
    373369                                          Global::sOSTypes [i].numSerialEnabled);
    374370                if (SUCCEEDED(rc))
    375                     m->llGuestOSTypes.push_back (guestOSTypeObj);
     371                    m->ollGuestOSTypes.addChild(guestOSTypeObj);
    376372            }
    377373            ComAssertComRCThrowRC (rc);
     
    533529        if (FAILED(rc)) return rc;
    534530
    535         rc = registerDVDImage(pImage, false /* aSaveRegistry */);
     531        rc = registerImage(pImage, DeviceType_DVD, false /* aSaveRegistry */);
    536532        if (FAILED(rc)) return rc;
    537533    }
     
    548544        if (FAILED(rc)) return rc;
    549545
    550         rc = registerFloppyImage(pImage, false /* aSaveRegistry */);
     546        rc = registerImage(pImage, DeviceType_Floppy, false /* aSaveRegistry */);
    551547        if (FAILED(rc)) return rc;
    552548    }
     
    568564    /* tell all our child objects we've been uninitialized */
    569565
    570     LogFlowThisFunc(("Uninitializing machines (%d)...\n", m->llMachines.size()));
    571     if (m->llMachines.size())
    572     {
    573         MachineList::iterator it = m->llMachines.begin();
    574         while (it != m->llMachines.end())
    575             (*it++)->uninit();
    576         m->llMachines.clear();
    577     }
    578 
    579     /* Uninit all other children still referenced by clients (unregistered
    580      * machines, hard disks, DVD/floppy images, server-side progress
    581      * operations). */
    582     uninitDependentChildren();
    583 
    584     m->mapHardDisks.clear();
    585 
    586     m->llFloppyImages.clear();
    587     m->llDVDImages.clear();
    588     m->llHardDisks.clear();
    589     m->llDHCPServers.clear();
     566    LogFlowThisFunc(("Uninitializing machines (%d)...\n", m->ollMachines.size()));
     567    m->ollMachines.uninitAll();
     568    m->ollFloppyImages.uninitAll();
     569    m->ollDVDImages.uninitAll();
     570    m->ollHardDisks.uninitAll();
     571    m->ollDHCPServers.uninitAll();
    590572
    591573    m->mapProgressOperations.clear();
    592574
    593     m->llGuestOSTypes.clear();
     575    m->ollGuestOSTypes.uninitAll();
    594576
    595577    /* Note that we release singleton children after we've all other children.
     
    788770    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    789771
    790     AutoReadLock alock(this);
    791 
    792     SafeIfaceArray<IMachine> machines(m->llMachines);
     772    AutoReadLock al(m->ollMachines.getLockHandle());
     773    SafeIfaceArray<IMachine> machines(m->ollMachines.getList());
    793774    machines.detachTo(ComSafeArrayOutArg(aMachines));
    794775
     
    804785    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    805786
    806     AutoReadLock alock(this);
    807 
    808     SafeIfaceArray<IMedium> hardDisks(m->llHardDisks);
     787    AutoReadLock al(m->ollHardDisks.getLockHandle());
     788    SafeIfaceArray<IMedium> hardDisks(m->ollHardDisks.getList());
    809789    hardDisks.detachTo(ComSafeArrayOutArg(aHardDisks));
    810790
     
    812792}
    813793
    814 STDMETHODIMP
    815 VirtualBox::COMGETTER(DVDImages) (ComSafeArrayOut(IMedium *, aDVDImages))
     794STDMETHODIMP VirtualBox::COMGETTER(DVDImages) (ComSafeArrayOut(IMedium *, aDVDImages))
    816795{
    817796    if (ComSafeArrayOutIsNull(aDVDImages))
     
    821800    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    822801
    823     AutoReadLock alock(this);
    824 
    825     SafeIfaceArray<IMedium> images(m->llDVDImages);
     802    AutoReadLock al(m->ollDVDImages.getLockHandle());
     803    SafeIfaceArray<IMedium> images(m->ollDVDImages.getList());
    826804    images.detachTo(ComSafeArrayOutArg(aDVDImages));
    827805
     
    829807}
    830808
    831 STDMETHODIMP
    832 VirtualBox::COMGETTER(FloppyImages) (ComSafeArrayOut(IMedium *, aFloppyImages))
     809STDMETHODIMP VirtualBox::COMGETTER(FloppyImages) (ComSafeArrayOut(IMedium *, aFloppyImages))
    833810{
    834811    if (ComSafeArrayOutIsNull(aFloppyImages))
     
    838815    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    839816
    840     AutoReadLock alock(this);
    841 
    842     SafeIfaceArray<IMedium> images(m->llFloppyImages);
     817    AutoReadLock al(m->ollFloppyImages.getLockHandle());
     818    SafeIfaceArray<IMedium> images(m->ollFloppyImages.getList());
    843819    images.detachTo(ComSafeArrayOutArg(aFloppyImages));
    844820
     
    855831    /* protect mProgressOperations */
    856832    AutoReadLock safeLock(m->mtxProgressOperations);
    857 
    858833    SafeIfaceArray<IProgress> progress(m->mapProgressOperations);
    859834    progress.detachTo(ComSafeArrayOutArg(aOperations));
     
    869844    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    870845
    871     AutoReadLock alock(this);
    872 
    873     SafeIfaceArray<IGuestOSType> ostypes(m->llGuestOSTypes);
     846    AutoReadLock al(m->ollGuestOSTypes.getLockHandle());
     847    SafeIfaceArray<IGuestOSType> ostypes(m->ollGuestOSTypes.getList());
    874848    ostypes.detachTo(ComSafeArrayOutArg(aGuestOSTypes));
    875849
     
    877851}
    878852
    879 STDMETHODIMP
    880 VirtualBox::COMGETTER(SharedFolders) (ComSafeArrayOut(ISharedFolder *, aSharedFolders))
     853STDMETHODIMP VirtualBox::COMGETTER(SharedFolders) (ComSafeArrayOut(ISharedFolder *, aSharedFolders))
    881854{
    882855#ifndef RT_OS_WINDOWS
     
    919892    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    920893
    921     AutoReadLock alock(this);
    922 
    923     SafeIfaceArray<IDHCPServer> svrs (m->llDHCPServers);
     894    AutoReadLock al(m->ollDHCPServers.getLockHandle());
     895    SafeIfaceArray<IDHCPServer> svrs (m->ollDHCPServers.getList());
    924896    svrs.detachTo(ComSafeArrayOutArg(aDHCPServers));
    925897
     
    11771149
    11781150/** @note Locks objects! */
    1179 STDMETHODIMP VirtualBox::RegisterMachine (IMachine *aMachine)
     1151STDMETHODIMP VirtualBox::RegisterMachine(IMachine *aMachine)
    11801152{
    11811153    CheckComArgNotNull(aMachine);
     
    11901162    if (FAILED(rc)) return rc;
    11911163
    1192     /* We need the children map lock here to keep the getDependentChild() result
    1193      * valid until we finish */
    1194     AutoReadLock chLock (childrenLock());
    1195 
    11961164    /* We can safely cast child to Machine * here because only Machine
    11971165     * implementations of IMachine can be among our children. */
    1198     Machine *machine = static_cast <Machine *> (getDependentChild (aMachine));
    1199     if (machine == NULL)
    1200     {
    1201         /* this machine was not created by CreateMachine() or opened by
    1202          * OpenMachine() or loaded during startup */
    1203         return setError (VBOX_E_INVALID_OBJECT_STATE,
    1204             tr ("The machine named '%ls' is not created within this "
    1205                 "VirtualBox instance"), name.raw());
    1206     }
    1207 
    1208     AutoCaller machCaller (machine);
    1209     ComAssertComRCRetRC (machCaller.rc());
    1210 
    1211     rc = registerMachine (machine);
    1212 
     1166    Machine *pMachine = static_cast<Machine*>(aMachine);
     1167
     1168    AutoCaller machCaller(pMachine);
     1169    ComAssertComRCRetRC(machCaller.rc());
     1170
     1171    rc = registerMachine(pMachine);
    12131172    /* fire an event */
    12141173    if (SUCCEEDED(rc))
    1215         onMachineRegistered(machine->getId(), TRUE);
     1174        onMachineRegistered(pMachine->getId(), TRUE);
    12161175
    12171176    return rc;
     
    12191178
    12201179/** @note Locks objects! */
    1221 STDMETHODIMP VirtualBox::GetMachine (IN_BSTR aId, IMachine **aMachine)
     1180STDMETHODIMP VirtualBox::GetMachine(IN_BSTR aId, IMachine **aMachine)
    12221181{
    12231182    CheckComArgOutSafeArrayPointerValid(aMachine);
     
    12361195
    12371196/** @note Locks this object for reading, then some machine objects for reading. */
    1238 STDMETHODIMP VirtualBox::FindMachine (IN_BSTR aName, IMachine **aMachine)
     1197STDMETHODIMP VirtualBox::FindMachine(IN_BSTR aName, IMachine **aMachine)
    12391198{
    12401199    LogFlowThisFuncEnter();
     
    12481207
    12491208    /* start with not found */
    1250     ComObjPtr<Machine> machine;
    1251     MachineList machines;
    1252     {
    1253         /* take a copy for safe iteration outside the lock */
    1254         AutoReadLock alock(this);
    1255         machines = m->llMachines;
    1256     }
    1257 
    1258     for (MachineList::iterator it = machines.begin();
    1259          !machine && it != machines.end();
    1260          ++ it)
     1209    ComObjPtr<Machine> pMachineFound;
     1210
     1211    AutoReadLock al(m->ollMachines.getLockHandle());
     1212    for (MachinesOList::iterator it = m->ollMachines.begin();
     1213         it != m->ollMachines.end();
     1214         ++it)
    12611215    {
    12621216        ComObjPtr<Machine> &pMachine2 = *it;
     
    12691223            AutoReadLock machLock(pMachine2);
    12701224            if (pMachine2->getName() == aName)
    1271                 machine = pMachine2;
     1225            {
     1226                pMachineFound = pMachine2;
     1227                break;
     1228            }
    12721229        }
    12731230    }
    12741231
    12751232    /* this will set (*machine) to NULL if machineObj is null */
    1276     machine.queryInterfaceTo(aMachine);
    1277 
    1278     HRESULT rc = machine
     1233    pMachineFound.queryInterfaceTo(aMachine);
     1234
     1235    HRESULT rc = pMachineFound
    12791236        ? S_OK
    1280         : setError (VBOX_E_OBJECT_NOT_FOUND,
    1281             tr ("Could not find a registered machine named '%ls'"), aName);
     1237        : setError(VBOX_E_OBJECT_NOT_FOUND,
     1238                   tr("Could not find a registered machine named '%ls'"), aName);
    12821239
    12831240    LogFlowThisFunc(("aName=\"%ls\", aMachine=%p, rc=%08X\n", aName, *aMachine, rc));
     
    12881245
    12891246/** @note Locks objects! */
    1290 STDMETHODIMP VirtualBox::UnregisterMachine (IN_BSTR  aId,
    1291                                             IMachine **aMachine)
     1247STDMETHODIMP VirtualBox::UnregisterMachine(IN_BSTR  aId,
     1248                                           IMachine **aMachine)
    12921249{
    12931250    Guid id(aId);
     
    12981255    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    12991256
     1257    // find machine from the given ID
     1258    ComObjPtr<Machine> pMachine;
     1259    HRESULT rc = findMachine(id, true /* setError */, &pMachine);
     1260    if (FAILED(rc)) return rc;
     1261
     1262    rc = pMachine->trySetRegistered(FALSE);
     1263    if (FAILED(rc)) return rc;
     1264
     1265    /* remove from the collection of registered machines */
     1266    m->ollMachines.removeChild(pMachine);
     1267
     1268    /* save the global registry */
    13001269    AutoWriteLock alock(this);
    1301 
    1302     ComObjPtr<Machine> machine;
    1303 
    1304     HRESULT rc = findMachine (id, true /* setError */, &machine);
    1305     if (FAILED(rc)) return rc;
    1306 
    1307     rc = machine->trySetRegistered (FALSE);
    1308     if (FAILED(rc)) return rc;
    1309 
    1310     /* remove from the collection of registered machines */
    1311     m->llMachines.remove (machine);
    1312 
    1313     /* save the global registry */
    13141270    rc = saveSettings();
    13151271
    13161272    /* return the unregistered machine to the caller */
    1317     machine.queryInterfaceTo(aMachine);
     1273    pMachine.queryInterfaceTo(aMachine);
    13181274
    13191275    /* fire an event */
    1320     onMachineRegistered (id, FALSE);
     1276    onMachineRegistered(id, FALSE);
    13211277
    13221278    return rc;
     
    14611417    if (SUCCEEDED(rc))
    14621418    {
    1463         rc = registerDVDImage (image);
     1419        rc = registerImage(image, DeviceType_DVD);
    14641420
    14651421        if (SUCCEEDED(rc))
     
    15281484    if (SUCCEEDED(rc))
    15291485    {
    1530         rc = registerFloppyImage (image);
     1486        rc = registerImage(image, DeviceType_Floppy);
    15311487
    15321488        if (SUCCEEDED(rc))
     
    16161572    *aType = NULL;
    16171573
    1618     AutoReadLock alock(this);
    1619 
    1620     for (GuestOSTypeList::iterator it = m->llGuestOSTypes.begin();
    1621          it != m->llGuestOSTypes.end();
    1622          ++ it)
     1574    AutoReadLock alock(m->ollGuestOSTypes.getLockHandle());
     1575    for (GuestOSTypesOList::iterator it = m->ollGuestOSTypes.begin();
     1576         it != m->ollGuestOSTypes.end();
     1577         ++it)
    16231578    {
    16241579        const Bstr &typeId = (*it)->id();
     
    16371592}
    16381593
    1639 STDMETHODIMP
    1640 VirtualBox::CreateSharedFolder (IN_BSTR aName, IN_BSTR aHostPath, BOOL /* aWritable */)
     1594STDMETHODIMP VirtualBox::CreateSharedFolder(IN_BSTR aName, IN_BSTR aHostPath, BOOL /* aWritable */)
    16411595{
    16421596    CheckComArgNotNull(aName);
     
    16491603}
    16501604
    1651 STDMETHODIMP VirtualBox::RemoveSharedFolder (IN_BSTR aName)
     1605STDMETHODIMP VirtualBox::RemoveSharedFolder(IN_BSTR aName)
    16521606{
    16531607    CheckComArgNotNull(aName);
     
    20061960void VirtualBox::dumpAllBackRefs()
    20071961{
    2008     for (MediaList::const_iterator mt = m->llHardDisks.begin();
    2009          mt != m->llHardDisks.end();
    2010          ++mt)
    2011     {
    2012         ComObjPtr<Medium> pMedium = *mt;
    2013         pMedium->dumpBackRefs();
    2014     }
    2015     for (MediaList::const_iterator mt = m->llDVDImages.begin();
    2016          mt != m->llDVDImages.end();
    2017          ++mt)
    2018     {
    2019         ComObjPtr<Medium> pMedium = *mt;
    2020         pMedium->dumpBackRefs();
     1962    {
     1963        AutoReadLock al(m->ollHardDisks.getLockHandle());
     1964        for (MediaList::const_iterator mt = m->ollHardDisks.begin();
     1965             mt != m->ollHardDisks.end();
     1966             ++mt)
     1967        {
     1968            ComObjPtr<Medium> pMedium = *mt;
     1969            pMedium->dumpBackRefs();
     1970        }
     1971    }
     1972    {
     1973        AutoReadLock al(m->ollDVDImages.getLockHandle());
     1974        for (MediaList::const_iterator mt = m->ollDVDImages.begin();
     1975             mt != m->ollDVDImages.end();
     1976             ++mt)
     1977        {
     1978            ComObjPtr<Medium> pMedium = *mt;
     1979            pMedium->dumpBackRefs();
     1980        }
    20211981    }
    20221982}
     
    26622622{
    26632623    ComObjPtr<GuestOSType> type;
    2664 
    26652624    AutoCaller autoCaller(this);
    26662625    AssertComRCReturn(autoCaller.rc(), type);
    26672626
    2668     AutoReadLock alock(this);
    2669 
    26702627    /* unknown type must always be the first */
    2671     ComAssertRet (m->llGuestOSTypes.size() > 0, type);
    2672 
    2673     type = m->llGuestOSTypes.front();
    2674     return type;
     2628    ComAssertRet(m->ollGuestOSTypes.size() > 0, type);
     2629
     2630    return m->ollGuestOSTypes.front();
    26752631}
    26762632
     
    27032659    AutoReadLock alock(this);
    27042660
    2705     for (MachineList::iterator it = m->llMachines.begin();
    2706          it != m->llMachines.end();
     2661    for (MachinesOList::iterator it = m->ollMachines.begin();
     2662         it != m->ollMachines.end();
    27072663         ++it)
    27082664    {
     
    27392695                                ComObjPtr<Machine> *aMachine /* = NULL */)
    27402696{
     2697    HRESULT rc = VBOX_E_OBJECT_NOT_FOUND;
     2698
    27412699    AutoCaller autoCaller(this);
    27422700    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    27432701
    2744     bool found = false;
    2745 
    2746     {
    2747         AutoReadLock alock(this);
    2748 
    2749         for (MachineList::iterator it = m->llMachines.begin();
    2750              !found && it != m->llMachines.end();
    2751              ++ it)
     2702    {
     2703        AutoReadLock al(m->ollMachines.getLockHandle());
     2704
     2705        for (MachinesOList::iterator it = m->ollMachines.begin();
     2706             it != m->ollMachines.end();
     2707             ++it)
    27522708        {
    27532709            ComObjPtr<Machine> pMachine2 = *it;
     
    27562712            AssertComRC(machCaller.rc());
    27572713
    2758             found = pMachine2->getId() == aId;
    2759             if (found && aMachine)
    2760                 *aMachine = pMachine2;
    2761         }
    2762     }
    2763 
    2764     HRESULT rc = found ? S_OK : VBOX_E_OBJECT_NOT_FOUND;
    2765 
    2766     if (aSetError && !found)
    2767     {
    2768         setError (VBOX_E_OBJECT_NOT_FOUND,
    2769             tr ("Could not find a registered machine with UUID {%RTuuid}"),
    2770             aId.raw());
    2771     }
     2714            if (pMachine2->getId() == aId)
     2715            {
     2716                rc = S_OK;
     2717                if (aMachine)
     2718                    *aMachine = pMachine2;
     2719                break;
     2720            }
     2721        }
     2722    }
     2723
     2724    if (aSetError && FAILED(rc))
     2725        setError(VBOX_E_OBJECT_NOT_FOUND,
     2726                 tr("Could not find a registered machine with UUID {%RTuuid}"),
     2727                 aId.raw());
    27722728
    27732729    return rc;
     
    27962752    AssertReturn(aId || aLocation, E_INVALIDARG);
    27972753
    2798     AutoReadLock alock(this);
     2754    // we use the hard disks map, but it is protected by the
     2755    // hard disk _list_ lock handle
     2756    AutoReadLock alock(m->ollHardDisks.getLockHandle());
    27992757
    28002758    /* first, look up by UUID in the map if UUID is provided */
    28012759    if (aId)
    28022760    {
    2803         HardDiskMap::const_iterator it = m->mapHardDisks.find (*aId);
     2761        HardDiskMap::const_iterator it = m->mapHardDisks.find(*aId);
    28042762        if (it != m->mapHardDisks.end())
    28052763        {
     
    28872845    }
    28882846
    2889     AutoReadLock alock(this);
     2847    AutoReadLock alock(m->ollDVDImages.getLockHandle());
    28902848
    28912849    bool found = false;
    28922850
    2893     for (MediaList::const_iterator it = m->llDVDImages.begin();
    2894          it != m->llDVDImages.end();
     2851    for (MediaList::const_iterator it = m->ollDVDImages.begin();
     2852         it != m->ollDVDImages.end();
    28952853         ++ it)
    28962854    {
     
    29632921    }
    29642922
    2965     AutoReadLock alock(this);
     2923    AutoReadLock alock(m->ollFloppyImages.getLockHandle());
    29662924
    29672925    bool found = false;
    29682926
    2969     for (MediaList::const_iterator it = m->llFloppyImages.begin();
    2970          it != m->llFloppyImages.end();
     2927    for (MediaList::const_iterator it = m->ollFloppyImages.begin();
     2928         it != m->ollFloppyImages.end();
    29712929         ++ it)
    29722930    {
     
    30092967                                    GuestOSType*& pGuestOSType)
    30102968{
    3011     AutoReadLock alock(this);
    3012 
    30132969    /* Look for a GuestOSType object */
    3014     AssertMsg(m->llGuestOSTypes.size() != 0,
     2970    AssertMsg(m->ollGuestOSTypes.size() != 0,
    30152971              ("Guest OS types array must be filled"));
    30162972
     
    30212977    }
    30222978
    3023     for (GuestOSTypeList::const_iterator it = m->llGuestOSTypes.begin();
    3024          it != m->llGuestOSTypes.end();
     2979    AutoReadLock alock(m->ollGuestOSTypes.getLockHandle());
     2980    for (GuestOSTypesOList::const_iterator it = m->ollGuestOSTypes.begin();
     2981         it != m->ollGuestOSTypes.end();
    30252982         ++it)
    30262983    {
     
    31663123 * @note Locks this object and media objects for reading.
    31673124 */
    3168 HRESULT VirtualBox::checkMediaForConflicts2 (const Guid &aId,
    3169                                              const Utf8Str &aLocation,
    3170                                              Utf8Str &aConflict)
     3125HRESULT VirtualBox::checkMediaForConflicts2(const Guid &aId,
     3126                                            const Utf8Str &aLocation,
     3127                                            Utf8Str &aConflict)
    31713128{
    31723129    aConflict.setNull();
     
    32393196    HRESULT rc = S_OK;
    32403197
    3241     /* serialize file access (prevents concurrent reads and writes) */
    3242     AutoWriteLock alock(this);
    3243 
    32443198    try
    32453199    {
    32463200        // machines
    3247         m->pMainConfigFile->llMachines.clear();
    3248         for (MachineList::iterator it = m->llMachines.begin();
    3249              it != m->llMachines.end();
    3250              ++it)
    3251         {
    3252             settings::MachineRegistryEntry mre;
    3253             rc = (*it)->saveRegistryEntry(mre);
    3254             m->pMainConfigFile->llMachines.push_back(mre);
     3201        settings::MachinesRegistry machinesTemp;
     3202        {
     3203            AutoReadLock al(m->ollMachines.getLockHandle());
     3204            for (MachinesOList::iterator it = m->ollMachines.begin();
     3205                 it != m->ollMachines.end();
     3206                 ++it)
     3207            {
     3208                settings::MachineRegistryEntry mre;
     3209                rc = (*it)->saveRegistryEntry(mre);
     3210                machinesTemp.push_back(mre);
     3211            }
    32553212        }
    32563213
    32573214        // hard disks
    3258         m->pMainConfigFile->llHardDisks.clear();
    3259         for (MediaList::const_iterator it = m->llHardDisks.begin();
    3260              it != m->llHardDisks.end();
    3261              ++it)
    3262         {
    3263             settings::Medium med;
    3264             rc = (*it)->saveSettings(med);
    3265             m->pMainConfigFile->llHardDisks.push_back(med);
    3266             if (FAILED(rc)) throw rc;
     3215        settings::MediaList hardDisksTemp;
     3216        {
     3217            AutoReadLock al(m->ollHardDisks.getLockHandle());
     3218            for (MediaList::const_iterator it = m->ollHardDisks.begin();
     3219                 it != m->ollHardDisks.end();
     3220                 ++it)
     3221            {
     3222                settings::Medium med;
     3223                rc = (*it)->saveSettings(med);
     3224                if (FAILED(rc)) throw rc;
     3225                hardDisksTemp.push_back(med);
     3226            }
    32673227        }
    32683228
    32693229        /* CD/DVD images */
    3270         m->pMainConfigFile->llDvdImages.clear();
    3271         for (MediaList::const_iterator it = m->llDVDImages.begin();
    3272              it != m->llDVDImages.end();
    3273              ++it)
    3274         {
    3275             settings::Medium med;
    3276             rc = (*it)->saveSettings(med);
    3277             if (FAILED(rc)) throw rc;
    3278             m->pMainConfigFile->llDvdImages.push_back(med);
     3230        settings::MediaList dvdsTemp;
     3231        {
     3232            AutoReadLock al(m->ollDVDImages.getLockHandle());
     3233            for (MediaList::const_iterator it = m->ollDVDImages.begin();
     3234                 it != m->ollDVDImages.end();
     3235                 ++it)
     3236            {
     3237                settings::Medium med;
     3238                rc = (*it)->saveSettings(med);
     3239                if (FAILED(rc)) throw rc;
     3240                dvdsTemp.push_back(med);
     3241            }
    32793242        }
    32803243
    32813244        /* floppy images */
    3282         m->pMainConfigFile->llFloppyImages.clear();
    3283         for (MediaList::const_iterator it = m->llFloppyImages.begin();
    3284              it != m->llFloppyImages.end();
    3285              ++it)
    3286         {
    3287             settings::Medium med;
    3288             rc = (*it)->saveSettings(med);
    3289             if (FAILED(rc)) throw rc;
    3290             m->pMainConfigFile->llFloppyImages.push_back(med);
    3291         }
    3292 
    3293         m->pMainConfigFile->llDhcpServers.clear();
    3294         for (DHCPServerList::const_iterator it =
    3295                 m->llDHCPServers.begin();
    3296                 it != m->llDHCPServers.end();
    3297                 ++ it)
    3298         {
    3299             settings::DHCPServer d;
    3300             rc = (*it)->saveSettings(d);
    3301             if (FAILED(rc)) throw rc;
    3302             m->pMainConfigFile->llDhcpServers.push_back(d);
    3303         }
     3245        settings::MediaList floppiesTemp;
     3246        {
     3247            AutoReadLock al(m->ollFloppyImages.getLockHandle());
     3248            for (MediaList::const_iterator it = m->ollFloppyImages.begin();
     3249                 it != m->ollFloppyImages.end();
     3250                 ++it)
     3251            {
     3252                settings::Medium med;
     3253                rc = (*it)->saveSettings(med);
     3254                if (FAILED(rc)) throw rc;
     3255                floppiesTemp.push_back(med);
     3256            }
     3257        }
     3258
     3259        settings::DHCPServersList dhcpServersTemp;
     3260        {
     3261            AutoReadLock al(m->ollDHCPServers.getLockHandle());
     3262            for (DHCPServersOList::const_iterator it = m->ollDHCPServers.begin();
     3263                 it != m->ollDHCPServers.end();
     3264                 ++it)
     3265            {
     3266                settings::DHCPServer d;
     3267                rc = (*it)->saveSettings(d);
     3268                if (FAILED(rc)) throw rc;
     3269                dhcpServersTemp.push_back(d);
     3270            }
     3271        }
     3272
     3273        /* finally, lock VirtualBox object for writing */
     3274        AutoWriteLock alock(this);
     3275
     3276        /* now copy the temp data to the config file under the VirtualBox lock */
     3277        m->pMainConfigFile->llMachines = machinesTemp;
     3278        m->pMainConfigFile->llHardDisks = hardDisksTemp;
     3279        m->pMainConfigFile->llDvdImages = dvdsTemp;
     3280        m->pMainConfigFile->llFloppyImages = floppiesTemp;
     3281        m->pMainConfigFile->llDhcpServers = dhcpServersTemp;
     3282
     3283        // leave extra data alone, it's still in the config file
    33043284
    33053285        /* host data (USB filters) */
     
    33103290        if (FAILED(rc)) throw rc;
    33113291
    3312         // now write out the XML
     3292        // and write out the XML, still under the lock
    33133293        m->pMainConfigFile->write(m->strSettingsFilePath);
    33143294    }
     
    33483328    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    33493329
    3350     AutoWriteLock alock(this);
    3351 
    33523330    HRESULT rc = S_OK;
    33533331
     
    33793357
    33803358    /* add to the collection of registered machines */
    3381     m->llMachines.push_back(aMachine);
     3359    m->ollMachines.addChild(aMachine);
    33823360
    33833361    if (autoCaller.state() != InInit)
     
    34103388    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    34113389
    3412     AutoWriteLock alock(this);
    3413 
    3414     AutoCaller hardDiskCaller (aHardDisk);
     3390    AutoCaller hardDiskCaller(aHardDisk);
    34153391    AssertComRCReturn(hardDiskCaller.rc(), hardDiskCaller.rc());
    34163392
    3417     AutoReadLock hardDiskLock (aHardDisk);
    3418 
    3419     Utf8Str strConflict;
    3420     HRESULT rc = checkMediaForConflicts2(aHardDisk->getId(),
    3421                                          aHardDisk->getLocationFull(),
    3422                                          strConflict);
    3423     if (FAILED(rc)) return rc;
    3424 
    3425     if (strConflict.length())
    3426     {
    3427         return setError(E_INVALIDARG,
    3428                         tr("Cannot register the hard disk '%s' with UUID {%RTuuid} because a %s already exists in the media registry ('%s')"),
    3429                         aHardDisk->getLocationFull().raw(),
    3430                         aHardDisk->getId().raw(),
    3431                         strConflict.raw(),
    3432                         m->strSettingsFilePath.raw());
    3433     }
    3434 
    3435     if (aHardDisk->getParent().isNull())
    3436     {
    3437         /* base (root) hard disk */
    3438         m->llHardDisks.push_back (aHardDisk);
    3439     }
    3440 
    3441     m->mapHardDisks.insert(HardDiskMap::value_type(aHardDisk->getId(),
    3442                                                    HardDiskMap::mapped_type(aHardDisk)));
     3393    Guid id;
     3394    Utf8Str strLocationFull;
     3395    ComObjPtr<Medium> pParent;
     3396    {
     3397        AutoReadLock hardDiskLock(aHardDisk);
     3398        id = aHardDisk->getId();
     3399        strLocationFull = aHardDisk->getLocationFull();
     3400        pParent = aHardDisk->getParent();
     3401    }
     3402
     3403    HRESULT rc;
     3404    {
     3405        // lock the hard disk lists (list + map) while checking for conflicts
     3406        AutoWriteLock al(m->ollHardDisks.getLockHandle());
     3407
     3408        Utf8Str strConflict;
     3409        rc = checkMediaForConflicts2(id,
     3410                                     strLocationFull,
     3411                                     strConflict);
     3412        if (FAILED(rc)) return rc;
     3413        if (strConflict.length())
     3414            return setError(E_INVALIDARG,
     3415                            tr("Cannot register the hard disk '%s' with UUID {%RTuuid} because a %s already exists in the media registry ('%s')"),
     3416                            strLocationFull.raw(),
     3417                            id.raw(),
     3418                            strConflict.raw(),
     3419                            m->strSettingsFilePath.raw());
     3420
     3421        // store base (root) hard disks in the list
     3422        if (pParent.isNull())
     3423            m->ollHardDisks.getList().push_back(aHardDisk);
     3424                    // access the list directly because we already locked the list above
     3425
     3426        // store all hard disks (even differencing images) in the map
     3427        m->mapHardDisks[id] = aHardDisk;
     3428    }
    34433429
    34443430    if (aSaveRegistry)
    34453431    {
    34463432        rc = saveSettings();
    3447         if (FAILED (rc))
     3433        if (FAILED(rc))
    34483434            unregisterHardDisk(aHardDisk, false /* aSaveRegistry */);
    34493435    }
     
    34753461    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    34763462
    3477     AutoWriteLock alock(this);
    3478 
    34793463    AutoCaller hardDiskCaller (aHardDisk);
    34803464    AssertComRCReturn(hardDiskCaller.rc(), hardDiskCaller.rc());
    34813465
    3482     AutoReadLock hardDiskLock (aHardDisk);
    3483 
    3484     size_t cnt = m->mapHardDisks.erase(aHardDisk->getId());
    3485     Assert(cnt == 1);
    3486     NOREF(cnt);
    3487 
    3488     if (aHardDisk->getParent().isNull())
    3489     {
    3490         /* base (root) hard disk */
    3491         m->llHardDisks.remove(aHardDisk);
     3466    Guid id;
     3467    ComObjPtr<Medium> pParent;
     3468    {
     3469        AutoReadLock hardDiskLock(aHardDisk);
     3470        id = aHardDisk->getId();
     3471        pParent = aHardDisk->getParent();
     3472    }
     3473
     3474    {
     3475        // lock the hard disk lists (list + map)
     3476        AutoWriteLock al(m->ollHardDisks.getLockHandle());
     3477
     3478        // remove base (root) hard disks from the list
     3479        if (pParent.isNull())
     3480            m->ollHardDisks.getList().remove(aHardDisk);
     3481                    // access the list directly because we already locked the list above
     3482
     3483        // remove all hard disks (even differencing images) from map
     3484        size_t cnt = m->mapHardDisks.erase(id);
     3485        Assert(cnt == 1);
     3486        NOREF(cnt);
    34923487    }
    34933488
     
    34973492    {
    34983493        rc = saveSettings();
    3499         if (FAILED (rc))
     3494        if (FAILED(rc))
    35003495            registerHardDisk(aHardDisk, false /* aSaveRegistry */);
    35013496    }
     
    35053500
    35063501/**
    3507  * Remembers the given image by storing it in the CD/DVD image registry.
    3508  *
    3509  * @param aImage        Image object to remember.
     3502 * Remembers the given image by storing it in the CD/DVD or floppy image registry.
     3503 *
     3504 * @param argImage      Image object to remember.
     3505 * @param argType       Either DeviceType_DVD or DeviceType_Floppy.
    35103506 * @param aSaveRegistry @c true to save the image registry to disk (default).
    35113507 *
     
    35193515 * @note Locks this object for writing and @a aImage for reading.
    35203516 */
    3521 HRESULT VirtualBox::registerDVDImage (Medium *aImage,
    3522                                       bool aSaveRegistry /*= true*/)
    3523 {
    3524     AssertReturn(aImage != NULL, E_INVALIDARG);
     3517HRESULT VirtualBox::registerImage(Medium *argImage,
     3518                                  DeviceType_T argType,
     3519                                  bool argSaveRegistry /*= true*/)
     3520{
     3521    AssertReturn(argImage != NULL, E_INVALIDARG);
    35253522
    35263523    AutoCaller autoCaller(this);
    35273524    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    35283525
    3529     AutoWriteLock alock(this);
    3530 
    3531     AutoCaller imageCaller (aImage);
     3526    AutoCaller imageCaller(argImage);
    35323527    AssertComRCReturn(imageCaller.rc(), imageCaller.rc());
    35333528
    3534     AutoReadLock imageLock (aImage);
    3535 
    3536     Utf8Str strConflict;
    3537     HRESULT rc = checkMediaForConflicts2(aImage->getId(),
    3538                                          aImage->getLocationFull(),
    3539                                          strConflict);
    3540     if (FAILED(rc)) return rc;
    3541 
    3542     if (strConflict.length())
    3543     {
    3544         return setError(VBOX_E_INVALID_OBJECT_STATE,
    3545                         tr("Cannot register the CD/DVD image '%s' with UUID {%RTuuid} because a %s already exists in the media registry ('%s')"),
    3546                         aImage->getLocationFull().raw(),
    3547                         aImage->getId().raw(),
    3548                         strConflict.raw(),
    3549                         m->strSettingsFilePath.raw());
    3550     }
    3551 
    3552     /* add to the collection */
    3553     m->llDVDImages.push_back (aImage);
    3554 
    3555     if (aSaveRegistry)
     3529    Guid id;
     3530    Utf8Str strLocationFull;
     3531    ComObjPtr<Medium> pParent;
     3532    {
     3533        AutoReadLock al(argImage);
     3534        id = argImage->getId();
     3535        strLocationFull = argImage->getLocationFull();
     3536        pParent = argImage->getParent();
     3537    }
     3538
     3539    // work on DVDs or floppies list?
     3540    ObjectsList<Medium> &oll = (argType == DeviceType_DVD) ? m->ollDVDImages : m->ollFloppyImages;
     3541
     3542    HRESULT rc;
     3543    {
     3544        // lock the images lists (list + map) while checking for conflicts
     3545        AutoWriteLock al(oll.getLockHandle());
     3546
     3547        Utf8Str strConflict;
     3548        rc = checkMediaForConflicts2(id,
     3549                                     strLocationFull,
     3550                                     strConflict);
     3551        if (FAILED(rc)) return rc;
     3552
     3553        if (strConflict.length())
     3554            return setError(VBOX_E_INVALID_OBJECT_STATE,
     3555                            tr("Cannot register the image '%s' with UUID {%RTuuid} because a %s already exists in the media registry ('%s')"),
     3556                            strLocationFull.raw(),
     3557                            id.raw(),
     3558                            strConflict.raw(),
     3559                            m->strSettingsFilePath.raw());
     3560
     3561        // add to the collection
     3562        oll.getList().push_back(argImage);
     3563                // access the list directly because we already locked the list above
     3564    }
     3565
     3566    if (argSaveRegistry)
    35563567    {
    35573568        rc = saveSettings();
    3558         if (FAILED (rc))
    3559             unregisterDVDImage (aImage, false /* aSaveRegistry */);
     3569        if (FAILED(rc))
     3570            unregisterImage(argImage, argType, false /* aSaveRegistry */);
    35603571    }
    35613572
     
    35643575
    35653576/**
    3566  * Removes the given image from the CD/DVD image registry registry.
    3567  *
    3568  * @param aImage        Image object to remove.
    3569  * @param aSaveRegistry @c true to save hard disk registry to disk (default).
     3577 * Removes the given image from the CD/DVD or floppy image registry.
     3578 *
     3579 * @param argImage        Image object to remove.
     3580 * @param argType         Either DeviceType_DVD or DeviceType_Floppy.
     3581 * @param argSaveRegistry @c true to save hard disk registry to disk (default).
    35703582 *
    35713583 * When @a aSaveRegistry is @c true, this operation may fail because of the
     
    35783590 * @note Locks this object for writing and @a aImage for reading.
    35793591 */
    3580 HRESULT VirtualBox::unregisterDVDImage (Medium *aImage,
    3581                                         bool aSaveRegistry /*= true*/)
    3582 {
    3583     AssertReturn(aImage != NULL, E_INVALIDARG);
     3592HRESULT VirtualBox::unregisterImage(Medium *argImage,
     3593                                    DeviceType_T argType,
     3594                                    bool argSaveRegistry /*= true*/)
     3595{
     3596    AssertReturn(argImage != NULL, E_INVALIDARG);
    35843597
    35853598    AutoCaller autoCaller(this);
    35863599    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    35873600
    3588     AutoWriteLock alock(this);
    3589 
    3590     AutoCaller imageCaller (aImage);
     3601    AutoCaller imageCaller(argImage);
    35913602    AssertComRCReturn(imageCaller.rc(), imageCaller.rc());
    35923603
    3593     AutoReadLock imageLock (aImage);
    3594 
    3595     m->llDVDImages.remove (aImage);
     3604    Guid id;
     3605    ComObjPtr<Medium> pParent;
     3606    {
     3607        AutoReadLock al(argImage);
     3608        id = argImage->getId();
     3609        pParent = argImage->getParent();
     3610    }
     3611
     3612    // work on DVDs or floppies list?
     3613    ObjectsList<Medium> &oll = (argType == DeviceType_DVD) ? m->ollDVDImages : m->ollFloppyImages;
     3614
     3615    oll.removeChild(argImage);
    35963616
    35973617    HRESULT rc = S_OK;
    35983618
    3599     if (aSaveRegistry)
     3619    if (argSaveRegistry)
    36003620    {
    36013621        rc = saveSettings();
    3602         if (FAILED (rc))
    3603             registerDVDImage (aImage, false /* aSaveRegistry */);
     3622        if (FAILED(rc))
     3623            registerImage(argImage, argType, false /* aSaveRegistry */);
    36043624    }
    36053625
    36063626    return rc;
    3607 }
    3608 
    3609 /**
    3610  * Remembers the given image by storing it in the floppy image registry.
    3611  *
    3612  * @param aImage        Image object to remember.
    3613  * @param aSaveRegistry @c true to save the image registry to disk (default).
    3614  *
    3615  * When @a aSaveRegistry is @c true, this operation may fail because of the
    3616  * failed #saveSettings() method it calls. In this case, the image object
    3617  * will not be remembered. It is therefore the responsibility of the caller to
    3618  * call this method as the last step of some action that requires registration
    3619  * in order to make sure that only fully functional image objects get
    3620  * registered.
    3621  *
    3622  * @note Locks this object for writing and @a aImage for reading.
    3623  */
    3624 HRESULT VirtualBox::registerFloppyImage(Medium *aImage,
    3625                                         bool aSaveRegistry /*= true*/)
    3626 {
    3627     AssertReturn(aImage != NULL, E_INVALIDARG);
    3628 
    3629     AutoCaller autoCaller(this);
    3630     AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    3631 
    3632     AutoWriteLock alock(this);
    3633 
    3634     AutoCaller imageCaller (aImage);
    3635     AssertComRCReturn(imageCaller.rc(), imageCaller.rc());
    3636 
    3637     AutoReadLock imageLock (aImage);
    3638 
    3639     Utf8Str strConflict;
    3640     HRESULT rc = checkMediaForConflicts2(aImage->getId(),
    3641                                          aImage->getLocationFull(),
    3642                                          strConflict);
    3643     if (FAILED(rc)) return rc;
    3644 
    3645     if (strConflict.length())
    3646     {
    3647         return setError(VBOX_E_INVALID_OBJECT_STATE,
    3648                         tr("Cannot register the floppy image '%s' with UUID {%RTuuid} because a %s already exists in the media registry ('%s')"),
    3649                         aImage->getLocationFull().raw(),
    3650                         aImage->getId().raw(),
    3651                         strConflict.raw(),
    3652                         m->strSettingsFilePath.raw());
    3653     }
    3654 
    3655     /* add to the collection */
    3656     m->llFloppyImages.push_back (aImage);
    3657 
    3658     if (aSaveRegistry)
    3659     {
    3660         rc = saveSettings();
    3661         if (FAILED (rc))
    3662             unregisterFloppyImage(aImage, false /* aSaveRegistry */);
    3663     }
    3664 
    3665     return rc;
    3666 }
    3667 
    3668 /**
    3669  * Removes the given image from the floppy image registry registry.
    3670  *
    3671  * @param aImage        Image object to remove.
    3672  * @param aSaveRegistry @c true to save hard disk registry to disk (default).
    3673  *
    3674  * When @a aSaveRegistry is @c true, this operation may fail because of the
    3675  * failed #saveSettings() method it calls. In this case, the image object
    3676  * will NOT be removed from the registry when this method returns. It is
    3677  * therefore the responsibility of the caller to call this method as the first
    3678  * step of some action that requires unregistration, before calling uninit() on
    3679  * @a aImage.
    3680  *
    3681  * @note Locks this object for writing and @a aImage for reading.
    3682  */
    3683 HRESULT VirtualBox::unregisterFloppyImage(Medium *aImage,
    3684                                           bool aSaveRegistry /*= true*/)
    3685 {
    3686     AssertReturn(aImage != NULL, E_INVALIDARG);
    3687 
    3688     AutoCaller autoCaller(this);
    3689     AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    3690 
    3691     AutoWriteLock alock(this);
    3692 
    3693     AutoCaller imageCaller (aImage);
    3694     AssertComRCReturn(imageCaller.rc(), imageCaller.rc());
    3695 
    3696     AutoReadLock imageLock (aImage);
    3697 
    3698     m->llFloppyImages.remove (aImage);
    3699 
    3700     HRESULT rc = S_OK;
    3701 
    3702     if (aSaveRegistry)
    3703     {
    3704         rc = saveSettings();
    3705         if (FAILED (rc))
    3706             registerFloppyImage (aImage, false /* aSaveRegistry */);
    3707     }
    3708 
    3709     return rc;
    3710 }
    3711 
    3712 /**
    3713  * Attempts to cast from a raw interface pointer to an underlying object.
    3714  * On success, @a aTo will contain the object reference. On failure, @a aTo will
    3715  * be set to @c null and an extended error info will be returned.
    3716  *
    3717  * @param aFrom     Interface pointer to cast from.
    3718  * @param aTo       Where to store a reference to the underlying object.
    3719  *
    3720  * @note Locks #childrenLock() for reading.
    3721  */
    3722 HRESULT VirtualBox::cast (IMedium *aFrom, ComObjPtr<Medium> &aTo)
    3723 {
    3724     AssertReturn(aFrom != NULL, E_INVALIDARG);
    3725 
    3726     AutoCaller autoCaller(this);
    3727     AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    3728 
    3729     /* We need the children map lock here to keep the getDependentChild() result
    3730      * valid until we finish */
    3731     AutoReadLock chLock (childrenLock());
    3732 
    3733     VirtualBoxBase *child = getDependentChild (aFrom);
    3734     if (!child)
    3735         return setError (E_FAIL, tr ("The given hard disk object is not created "
    3736                                      "within this VirtualBox instance"));
    3737 
    3738     /* we can safely cast child to Medium * here because only Medium
    3739      * implementations of IMedium can be among our children */
    3740 
    3741     aTo = static_cast<Medium*>(child);
    3742 
    3743     return S_OK;
    37443627}
    37453628
     
    37543637 * @note Locks this object + DVD, Floppy and HardDisk children for writing.
    37553638 */
    3756 HRESULT VirtualBox::updateSettings (const char *aOldPath, const char *aNewPath)
     3639HRESULT VirtualBox::updateSettings(const char *aOldPath, const char *aNewPath)
    37573640{
    37583641    LogFlowThisFunc(("aOldPath={%s} aNewPath={%s}\n", aOldPath, aNewPath));
     
    37643647    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    37653648
    3766     AutoWriteLock alock(this);
    3767 
    3768     /* check DVD paths */
    3769     for (MediaList::iterator it = m->llDVDImages.begin();
    3770          it != m->llDVDImages.end();
     3649    ObjectsList<Medium> ollAll;
     3650    ollAll.appendOtherList(m->ollDVDImages);
     3651    ollAll.appendOtherList(m->ollFloppyImages);
     3652    ollAll.appendOtherList(m->ollHardDisks);
     3653
     3654    for (MediaList::iterator it = ollAll.begin();
     3655         it != ollAll.end();
    37713656         ++ it)
    37723657    {
    37733658        (*it)->updatePath(aOldPath, aNewPath);
    3774     }
    3775 
    3776     /* check Floppy paths */
    3777     for (MediaList::iterator it = m->llFloppyImages.begin();
    3778          it != m->llFloppyImages  .end();
    3779          ++ it)
    3780     {
    3781         (*it)->updatePath(aOldPath, aNewPath);
    3782     }
    3783 
    3784     /* check HardDisk paths */
    3785     for (MediaList::const_iterator it = m->llHardDisks.begin();
    3786          it != m->llHardDisks.end();
    3787          ++ it)
    3788     {
    3789         (*it)->updatePaths(aOldPath, aNewPath);
    37903659    }
    37913660
     
    38993768RWLockHandle& VirtualBox::hardDiskTreeLockHandle()
    39003769{
    3901     return m->mtxHardDiskTree;
    3902 }
    3903 
    3904 /**
    3905  * Reimplements VirtualBoxWithTypedChildren::childrenLock() to return a
    3906  * dedicated lock instead of the main object lock. The dedicated lock for
    3907  * child map operations frees callers of init() methods of these children
    3908  * from acquiring a write parent (VirtualBox) lock (which would be mandatory
    3909  * otherwise). Since VirtualBox has a lot of heterogenous children which
    3910  * init() methods are called here and there, it definitely makes sense.
    3911  */
    3912 RWLockHandle* VirtualBox::childrenLock()
    3913 {
    3914     return &m->mtxChildrenMap;
     3770    return m->ollHardDisks.getLockHandle();
    39153771}
    39163772
     
    39243780    LogFlowFuncEnter();
    39253781
    3926     VirtualBox *that = (VirtualBox *) pvUser;
    3927     Assert (that);
     3782    VirtualBox *that = (VirtualBox*)pvUser;
     3783    Assert(that);
     3784
     3785    typedef std::vector< ComObjPtr<Machine> > MachineVector;
     3786    typedef std::vector< ComObjPtr<SessionMachine> > SessionMachineVector;
    39283787
    39293788    SessionMachineVector machines;
     
    39783837            {
    39793838                /* machine mutex is released */
    3980                 (machines [rc - WAIT_OBJECT_0 - 1])->checkForDeath();
     3839                (machines[rc - WAIT_OBJECT_0 - 1])->checkForDeath();
    39813840                update = true;
    39823841            }
     
    39843843            {
    39853844                /* machine mutex is abandoned due to client process termination */
    3986                 (machines [rc - WAIT_ABANDONED_0 - 1])->checkForDeath();
     3845                (machines[rc - WAIT_ABANDONED_0 - 1])->checkForDeath();
    39873846                update = true;
    39883847            }
     
    39983857            {
    39993858                /* close old process handles */
    4000                 for (size_t i = 1 + cnt; i < 1 + cnt + cntSpawned; ++ i)
    4001                     CloseHandle (handles [i]);
    4002 
    4003                 AutoReadLock thatLock (that);
     3859                for (size_t i = 1 + cnt; i < 1 + cnt + cntSpawned; ++i)
     3860                    CloseHandle(handles[i]);
     3861
     3862                // lock the machines list for reading
     3863                AutoReadLock thatLock(that->m->ollMachines.getLockHandle());
    40043864
    40053865                /* obtain a new set of opened machines */
     
    40073867                machines.clear();
    40083868
    4009                 for (MachineList::iterator it = that->m->llMachines.begin();
    4010                      it != that->m->llMachines.end(); ++ it)
     3869                for (MachinesOList::iterator it = that->m->ollMachines.begin();
     3870                     it != that->m->ollMachines.end();
     3871                     ++it)
    40113872                {
    40123873                    /// @todo handle situations with more than 64 objects
     
    40163877                    ComObjPtr<SessionMachine> sm;
    40173878                    HANDLE ipcSem;
    4018                     if ((*it)->isSessionOpenOrClosing (sm, NULL, &ipcSem))
     3879                    if ((*it)->isSessionOpenOrClosing(sm, NULL, &ipcSem))
    40193880                    {
    4020                         machines.push_back (sm);
    4021                         handles [1 + cnt] = ipcSem;
    4022                         ++ cnt;
     3881                        machines.push_back(sm);
     3882                        handles[1 + cnt] = ipcSem;
     3883                        ++cnt;
    40233884                    }
    40243885                }
     
    40303891                spawnedMachines.clear();
    40313892
    4032                 for (MachineList::iterator it = that->m->llMachines.begin();
    4033                      it != that->m->llMachines.end(); ++ it)
     3893                for (MachinesOList::iterator it = that->m->ollMachines.begin();
     3894                     it != that->m->ollMachines.end();
     3895                     ++it)
    40343896                {
    40353897                    /// @todo handle situations with more than 64 objects
     
    40383900
    40393901                    RTPROCESS pid;
    4040                     if ((*it)->isSessionSpawning (&pid))
     3902                    if ((*it)->isSessionSpawning(&pid))
    40413903                    {
    4042                         HANDLE ph = OpenProcess (SYNCHRONIZE, FALSE, pid);
     3904                        HANDLE ph = OpenProcess(SYNCHRONIZE, FALSE, pid);
    40433905                        AssertMsg (ph != NULL, ("OpenProcess (pid=%d) failed with %d\n",
    40443906                                                pid, GetLastError()));
    40453907                        if (rc == 0)
    40463908                        {
    4047                             spawnedMachines.push_back (*it);
    4048                             handles [1 + cnt + cntSpawned] = ph;
    4049                             ++ cntSpawned;
     3909                            spawnedMachines.push_back(*it);
     3910                            handles[1 + cnt + cntSpawned] = ph;
     3911                            ++cntSpawned;
    40503912                        }
    40513913                    }
     
    40533915
    40543916                LogFlowFunc (("UPDATE: spawned session count = %d\n", cntSpawned));
     3917
     3918                // machines lock unwinds here
    40553919            }
    40563920        }
     
    40903954            autoCaller.release();
    40913955
    4092             int vrc = RTSemEventWait (that->m->updateReq, 500);
     3956            int vrc = RTSemEventWait(that->m->updateReq, 500);
    40933957
    40943958            /* Restore the caller before using VirtualBox. If it fails, this
     
    41293993#ifdef DEBUG
    41303994                            {
    4131                                 AutoReadLock machineLock (machines [semId]);
     3995                                AutoReadLock machineLock(machines[semId]);
    41323996                                LogFlowFunc (("released mutex: machine='%ls'\n",
    4133                                               machines [semId]->name().raw()));
     3997                                              machines[semId]->name().raw()));
    41343998                            }
    41353999#endif
    4136                             machines [semId]->checkForDeath();
     4000                            machines[semId]->checkForDeath();
    41374001                        }
    41384002                        update = true;
     
    41594023#ifdef DEBUG
    41604024                                    {
    4161                                         AutoReadLock machineLock (machines [semId]);
    4162                                         LogFlowFunc (("mutex owner dead: machine='%ls'\n",
    4163                                                       machines [i]->name().raw()));
     4025                                        AutoReadLock machineLock(machines[semId]);
     4026                                        LogFlowFunc(("mutex owner dead: machine='%ls'\n",
     4027                                                     machines[i]->name().raw()));
    41644028                                    }
    41654029#endif
    4166                                     machines [i]->checkForDeath();
     4030                                    machines[i]->checkForDeath();
    41674031                                }
    41684032                            }
     
    41984062                    machines.clear();
    41994063
    4200                     for (MachineList::iterator it = that->m->llMachines.begin();
     4064                    for (MachinesOList::iterator it = that->m->llMachines.begin();
    42014065                         it != that->m->llMachines.end(); ++ it)
    42024066                    {
     
    42114075                        {
    42124076                            machines.push_back (sm);
    4213                             handles [cnt].hsemCur = (HSEM) ipcSem;
    4214                             handles [cnt].ulUser = cnt;
     4077                            handles[cnt].hsemCur = (HSEM) ipcSem;
     4078                            handles[cnt].ulUser = cnt;
    42154079                            ++ cnt;
    42164080                        }
     
    42364100                    spawnedMachines.clear();
    42374101
    4238                     for (MachineList::iterator it = that->m->llMachines.begin();
     4102                    for (MachinesOList::iterator it = that->m->llMachines.begin();
    42394103                         it != that->m->llMachines.end(); ++ it)
    42404104                    {
     
    42904154                /* RT_SUCCESS(rc) means an update event is signaled */
    42914155
    4292                 AutoReadLock thatLock (that);
     4156                // lock the machines list for reading
     4157                AutoReadLock thatLock(that->m->ollMachines.getLockHandle());
    42934158
    42944159                if (RT_SUCCESS(rc) || update)
     
    42974162                    machines.clear();
    42984163
    4299                     for (MachineList::iterator it = that->m->llMachines.begin();
    4300                          it != that->m->llMachines.end(); ++ it)
     4164                    for (MachinesOList::iterator it = that->m->ollMachines.begin();
     4165                         it != that->m->ollMachines.end();
     4166                         ++it)
    43014167                    {
    43024168                        ComObjPtr<SessionMachine> sm;
    4303                         if ((*it)->isSessionOpenOrClosing (sm))
    4304                             machines.push_back (sm);
     4169                        if ((*it)->isSessionOpenOrClosing(sm))
     4170                            machines.push_back(sm);
    43054171                    }
    43064172
    43074173                    cnt = machines.size();
    4308                     LogFlowFunc (("UPDATE: direct session count = %d\n", cnt));
     4174                    LogFlowFunc(("UPDATE: direct session count = %d\n", cnt));
    43094175                }
    43104176
     
    43144180                    spawnedMachines.clear();
    43154181
    4316                     for (MachineList::iterator it = that->m->llMachines.begin();
    4317                          it != that->m->llMachines.end(); ++ it)
     4182                    for (MachinesOList::iterator it = that->m->ollMachines.begin();
     4183                         it != that->m->ollMachines.end();
     4184                         ++it)
    43184185                    {
    43194186                        if ((*it)->isSessionSpawning())
    4320                             spawnedMachines.push_back (*it);
     4187                            spawnedMachines.push_back(*it);
    43214188                    }
    43224189
    43234190                    cntSpawned = spawnedMachines.size();
    4324                     LogFlowFunc (("UPDATE: spawned session count = %d\n", cntSpawned));
     4191                    LogFlowFunc(("UPDATE: spawned session count = %d\n", cntSpawned));
    43254192                }
     4193
     4194                // machines lock unwinds here
    43264195            }
    43274196
     
    44904359}
    44914360
    4492 //STDMETHODIMP VirtualBox::FindDHCPServerForInterface (IHostNetworkInterface * aIinterface, IDHCPServer ** aServer)
    4493 //{
    4494 //    return E_NOTIMPL;
    4495 //}
    4496 
    4497 STDMETHODIMP VirtualBox::FindDHCPServerByNetworkName (IN_BSTR aName, IDHCPServer ** aServer)
     4361STDMETHODIMP VirtualBox::FindDHCPServerByNetworkName(IN_BSTR aName, IDHCPServer ** aServer)
    44984362{
    44994363    CheckComArgNotNull(aName);
     
    45024366    AutoCaller autoCaller(this);
    45034367    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    4504 
    4505     AutoWriteLock alock(this);
    45064368
    45074369    HRESULT rc;
     
    45094371    ComPtr<DHCPServer> found;
    45104372
    4511     for (DHCPServerList::const_iterator it =
    4512             m->llDHCPServers.begin();
    4513          it != m->llDHCPServers.end();
    4514          ++ it)
    4515     {
    4516         rc = (*it)->COMGETTER(NetworkName) (bstr.asOutParam());
     4373    AutoReadLock alock(m->ollDHCPServers.getLockHandle());
     4374
     4375    for (DHCPServersOList::const_iterator it = m->ollDHCPServers.begin();
     4376         it != m->ollDHCPServers.end();
     4377         ++it)
     4378    {
     4379        rc = (*it)->COMGETTER(NetworkName)(bstr.asOutParam());
    45174380        if (FAILED(rc)) throw rc;
    45184381
    4519         if(bstr == aName)
     4382        if (bstr == aName)
    45204383        {
    45214384            found = *it;
     
    45584421 */
    45594422HRESULT VirtualBox::registerDHCPServer(DHCPServer *aDHCPServer,
    4560                                      bool aSaveRegistry /*= true*/)
     4423                                       bool aSaveRegistry /*= true*/)
    45614424{
    45624425    AssertReturn(aDHCPServer != NULL, E_INVALIDARG);
     
    45654428    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    45664429
    4567     AutoWriteLock alock(this);
    4568 
    4569     AutoCaller dhcpServerCaller (aDHCPServer);
     4430    AutoCaller dhcpServerCaller(aDHCPServer);
    45704431    AssertComRCReturn(dhcpServerCaller.rc(), dhcpServerCaller.rc());
    4571 
    4572     AutoReadLock dhcpServerLock (aDHCPServer);
    45734432
    45744433    Bstr name;
    45754434    HRESULT rc;
    4576     rc = aDHCPServer->COMGETTER(NetworkName) (name.asOutParam());
     4435    rc = aDHCPServer->COMGETTER(NetworkName)(name.asOutParam());
    45774436    if (FAILED(rc)) return rc;
    45784437
    45794438    ComPtr<IDHCPServer> existing;
    45804439    rc = FindDHCPServerByNetworkName(name.mutableRaw(), existing.asOutParam());
    4581     if(SUCCEEDED(rc))
     4440    if (SUCCEEDED(rc))
    45824441    {
    45834442        return E_INVALIDARG;
    45844443    }
     4444
    45854445    rc = S_OK;
    45864446
    4587     m->llDHCPServers.push_back (aDHCPServer);
     4447    m->ollDHCPServers.addChild(aDHCPServer);
    45884448
    45894449    if (aSaveRegistry)
     
    46254485    AssertComRCReturn(dhcpServerCaller.rc(), dhcpServerCaller.rc());
    46264486
    4627     AutoReadLock dhcpServerLock (aDHCPServer);
    4628 
    4629     m->llDHCPServers.remove (aDHCPServer);
     4487    m->ollDHCPServers.removeChild(aDHCPServer);
    46304488
    46314489    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