Changeset 25170 in vbox for trunk/src/VBox/Main/VirtualBoxImpl.cpp
- Timestamp:
- Dec 3, 2009 3:40:52 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/VirtualBoxImpl.cpp
r25151 r25170 70 70 71 71 #include "Logging.h" 72 #include "objectslist.h" 72 73 73 74 #ifdef RT_OS_WINDOWS … … 82 83 83 84 #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 98 85 99 86 //////////////////////////////////////////////////////////////////////////////// … … 169 156 #endif 170 157 158 typedef ObjectsList<Machine> MachinesOList; 159 typedef ObjectsList<Medium> MediaOList; 160 typedef ObjectsList<GuestOSType> GuestOSTypesOList; 161 typedef ObjectsList<SharedFolder> SharedFoldersOList; 162 typedef ObjectsList<DHCPServer> DHCPServersOList; 163 164 typedef std::map<Guid, ComPtr<IProgress> > ProgressMap; 165 typedef std::map<Guid, ComObjPtr<Medium> > HardDiskMap; 166 171 167 /** 172 168 * Main VirtualBox data structure. … … 198 194 #endif /* VBOX_WITH_RESOURCE_USAGE_API */ 199 195 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; 202 214 203 215 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 in212 /// find() it seems213 HardDiskMap mapHardDisks;214 215 216 CallbackList llCallbacks; 216 217 217 218 RWLockHandle mtxProgressOperations; 218 219 // 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 through221 // Medium::treeLock, which returns exactly this222 RWLockHandle mtxChildrenMap;223 // used for VirtualBoxWithChildrenNEXT management224 220 225 221 // the following are data for the client watcher thread … … 373 369 Global::sOSTypes [i].numSerialEnabled); 374 370 if (SUCCEEDED(rc)) 375 m-> llGuestOSTypes.push_back(guestOSTypeObj);371 m->ollGuestOSTypes.addChild(guestOSTypeObj); 376 372 } 377 373 ComAssertComRCThrowRC (rc); … … 533 529 if (FAILED(rc)) return rc; 534 530 535 rc = register DVDImage(pImage, false /* aSaveRegistry */);531 rc = registerImage(pImage, DeviceType_DVD, false /* aSaveRegistry */); 536 532 if (FAILED(rc)) return rc; 537 533 } … … 548 544 if (FAILED(rc)) return rc; 549 545 550 rc = register FloppyImage(pImage, false /* aSaveRegistry */);546 rc = registerImage(pImage, DeviceType_Floppy, false /* aSaveRegistry */); 551 547 if (FAILED(rc)) return rc; 552 548 } … … 568 564 /* tell all our child objects we've been uninitialized */ 569 565 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(); 590 572 591 573 m->mapProgressOperations.clear(); 592 574 593 m-> llGuestOSTypes.clear();575 m->ollGuestOSTypes.uninitAll(); 594 576 595 577 /* Note that we release singleton children after we've all other children. … … 788 770 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 789 771 790 AutoReadLock alock(this); 791 792 SafeIfaceArray<IMachine> machines(m->llMachines); 772 AutoReadLock al(m->ollMachines.getLockHandle()); 773 SafeIfaceArray<IMachine> machines(m->ollMachines.getList()); 793 774 machines.detachTo(ComSafeArrayOutArg(aMachines)); 794 775 … … 804 785 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 805 786 806 AutoReadLock alock(this); 807 808 SafeIfaceArray<IMedium> hardDisks(m->llHardDisks); 787 AutoReadLock al(m->ollHardDisks.getLockHandle()); 788 SafeIfaceArray<IMedium> hardDisks(m->ollHardDisks.getList()); 809 789 hardDisks.detachTo(ComSafeArrayOutArg(aHardDisks)); 810 790 … … 812 792 } 813 793 814 STDMETHODIMP 815 VirtualBox::COMGETTER(DVDImages) (ComSafeArrayOut(IMedium *, aDVDImages)) 794 STDMETHODIMP VirtualBox::COMGETTER(DVDImages) (ComSafeArrayOut(IMedium *, aDVDImages)) 816 795 { 817 796 if (ComSafeArrayOutIsNull(aDVDImages)) … … 821 800 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 822 801 823 AutoReadLock alock(this); 824 825 SafeIfaceArray<IMedium> images(m->llDVDImages); 802 AutoReadLock al(m->ollDVDImages.getLockHandle()); 803 SafeIfaceArray<IMedium> images(m->ollDVDImages.getList()); 826 804 images.detachTo(ComSafeArrayOutArg(aDVDImages)); 827 805 … … 829 807 } 830 808 831 STDMETHODIMP 832 VirtualBox::COMGETTER(FloppyImages) (ComSafeArrayOut(IMedium *, aFloppyImages)) 809 STDMETHODIMP VirtualBox::COMGETTER(FloppyImages) (ComSafeArrayOut(IMedium *, aFloppyImages)) 833 810 { 834 811 if (ComSafeArrayOutIsNull(aFloppyImages)) … … 838 815 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 839 816 840 AutoReadLock alock(this); 841 842 SafeIfaceArray<IMedium> images(m->llFloppyImages); 817 AutoReadLock al(m->ollFloppyImages.getLockHandle()); 818 SafeIfaceArray<IMedium> images(m->ollFloppyImages.getList()); 843 819 images.detachTo(ComSafeArrayOutArg(aFloppyImages)); 844 820 … … 855 831 /* protect mProgressOperations */ 856 832 AutoReadLock safeLock(m->mtxProgressOperations); 857 858 833 SafeIfaceArray<IProgress> progress(m->mapProgressOperations); 859 834 progress.detachTo(ComSafeArrayOutArg(aOperations)); … … 869 844 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 870 845 871 AutoReadLock alock(this); 872 873 SafeIfaceArray<IGuestOSType> ostypes(m->llGuestOSTypes); 846 AutoReadLock al(m->ollGuestOSTypes.getLockHandle()); 847 SafeIfaceArray<IGuestOSType> ostypes(m->ollGuestOSTypes.getList()); 874 848 ostypes.detachTo(ComSafeArrayOutArg(aGuestOSTypes)); 875 849 … … 877 851 } 878 852 879 STDMETHODIMP 880 VirtualBox::COMGETTER(SharedFolders) (ComSafeArrayOut(ISharedFolder *, aSharedFolders)) 853 STDMETHODIMP VirtualBox::COMGETTER(SharedFolders) (ComSafeArrayOut(ISharedFolder *, aSharedFolders)) 881 854 { 882 855 #ifndef RT_OS_WINDOWS … … 919 892 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 920 893 921 AutoReadLock alock(this); 922 923 SafeIfaceArray<IDHCPServer> svrs (m->llDHCPServers); 894 AutoReadLock al(m->ollDHCPServers.getLockHandle()); 895 SafeIfaceArray<IDHCPServer> svrs (m->ollDHCPServers.getList()); 924 896 svrs.detachTo(ComSafeArrayOutArg(aDHCPServers)); 925 897 … … 1177 1149 1178 1150 /** @note Locks objects! */ 1179 STDMETHODIMP VirtualBox::RegisterMachine 1151 STDMETHODIMP VirtualBox::RegisterMachine(IMachine *aMachine) 1180 1152 { 1181 1153 CheckComArgNotNull(aMachine); … … 1190 1162 if (FAILED(rc)) return rc; 1191 1163 1192 /* We need the children map lock here to keep the getDependentChild() result1193 * valid until we finish */1194 AutoReadLock chLock (childrenLock());1195 1196 1164 /* We can safely cast child to Machine * here because only Machine 1197 1165 * 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); 1213 1172 /* fire an event */ 1214 1173 if (SUCCEEDED(rc)) 1215 onMachineRegistered( machine->getId(), TRUE);1174 onMachineRegistered(pMachine->getId(), TRUE); 1216 1175 1217 1176 return rc; … … 1219 1178 1220 1179 /** @note Locks objects! */ 1221 STDMETHODIMP VirtualBox::GetMachine 1180 STDMETHODIMP VirtualBox::GetMachine(IN_BSTR aId, IMachine **aMachine) 1222 1181 { 1223 1182 CheckComArgOutSafeArrayPointerValid(aMachine); … … 1236 1195 1237 1196 /** @note Locks this object for reading, then some machine objects for reading. */ 1238 STDMETHODIMP VirtualBox::FindMachine 1197 STDMETHODIMP VirtualBox::FindMachine(IN_BSTR aName, IMachine **aMachine) 1239 1198 { 1240 1199 LogFlowThisFuncEnter(); … … 1248 1207 1249 1208 /* 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) 1261 1215 { 1262 1216 ComObjPtr<Machine> &pMachine2 = *it; … … 1269 1223 AutoReadLock machLock(pMachine2); 1270 1224 if (pMachine2->getName() == aName) 1271 machine = pMachine2; 1225 { 1226 pMachineFound = pMachine2; 1227 break; 1228 } 1272 1229 } 1273 1230 } 1274 1231 1275 1232 /* this will set (*machine) to NULL if machineObj is null */ 1276 machine.queryInterfaceTo(aMachine);1277 1278 HRESULT rc = machine1233 pMachineFound.queryInterfaceTo(aMachine); 1234 1235 HRESULT rc = pMachineFound 1279 1236 ? S_OK 1280 : setError 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); 1282 1239 1283 1240 LogFlowThisFunc(("aName=\"%ls\", aMachine=%p, rc=%08X\n", aName, *aMachine, rc)); … … 1288 1245 1289 1246 /** @note Locks objects! */ 1290 STDMETHODIMP VirtualBox::UnregisterMachine 1291 1247 STDMETHODIMP VirtualBox::UnregisterMachine(IN_BSTR aId, 1248 IMachine **aMachine) 1292 1249 { 1293 1250 Guid id(aId); … … 1298 1255 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1299 1256 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 */ 1300 1269 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 */1314 1270 rc = saveSettings(); 1315 1271 1316 1272 /* return the unregistered machine to the caller */ 1317 machine.queryInterfaceTo(aMachine);1273 pMachine.queryInterfaceTo(aMachine); 1318 1274 1319 1275 /* fire an event */ 1320 onMachineRegistered 1276 onMachineRegistered(id, FALSE); 1321 1277 1322 1278 return rc; … … 1461 1417 if (SUCCEEDED(rc)) 1462 1418 { 1463 rc = register DVDImage (image);1419 rc = registerImage(image, DeviceType_DVD); 1464 1420 1465 1421 if (SUCCEEDED(rc)) … … 1528 1484 if (SUCCEEDED(rc)) 1529 1485 { 1530 rc = register FloppyImage (image);1486 rc = registerImage(image, DeviceType_Floppy); 1531 1487 1532 1488 if (SUCCEEDED(rc)) … … 1616 1572 *aType = NULL; 1617 1573 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) 1623 1578 { 1624 1579 const Bstr &typeId = (*it)->id(); … … 1637 1592 } 1638 1593 1639 STDMETHODIMP 1640 VirtualBox::CreateSharedFolder (IN_BSTR aName, IN_BSTR aHostPath, BOOL /* aWritable */) 1594 STDMETHODIMP VirtualBox::CreateSharedFolder(IN_BSTR aName, IN_BSTR aHostPath, BOOL /* aWritable */) 1641 1595 { 1642 1596 CheckComArgNotNull(aName); … … 1649 1603 } 1650 1604 1651 STDMETHODIMP VirtualBox::RemoveSharedFolder 1605 STDMETHODIMP VirtualBox::RemoveSharedFolder(IN_BSTR aName) 1652 1606 { 1653 1607 CheckComArgNotNull(aName); … … 2006 1960 void VirtualBox::dumpAllBackRefs() 2007 1961 { 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 } 2021 1981 } 2022 1982 } … … 2662 2622 { 2663 2623 ComObjPtr<GuestOSType> type; 2664 2665 2624 AutoCaller autoCaller(this); 2666 2625 AssertComRCReturn(autoCaller.rc(), type); 2667 2626 2668 AutoReadLock alock(this);2669 2670 2627 /* 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(); 2675 2631 } 2676 2632 … … 2703 2659 AutoReadLock alock(this); 2704 2660 2705 for (Machine List::iterator it = m->llMachines.begin();2706 it != m-> llMachines.end();2661 for (MachinesOList::iterator it = m->ollMachines.begin(); 2662 it != m->ollMachines.end(); 2707 2663 ++it) 2708 2664 { … … 2739 2695 ComObjPtr<Machine> *aMachine /* = NULL */) 2740 2696 { 2697 HRESULT rc = VBOX_E_OBJECT_NOT_FOUND; 2698 2741 2699 AutoCaller autoCaller(this); 2742 2700 AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); 2743 2701 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) 2752 2708 { 2753 2709 ComObjPtr<Machine> pMachine2 = *it; … … 2756 2712 AssertComRC(machCaller.rc()); 2757 2713 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()); 2772 2728 2773 2729 return rc; … … 2796 2752 AssertReturn(aId || aLocation, E_INVALIDARG); 2797 2753 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()); 2799 2757 2800 2758 /* first, look up by UUID in the map if UUID is provided */ 2801 2759 if (aId) 2802 2760 { 2803 HardDiskMap::const_iterator it = m->mapHardDisks.find 2761 HardDiskMap::const_iterator it = m->mapHardDisks.find(*aId); 2804 2762 if (it != m->mapHardDisks.end()) 2805 2763 { … … 2887 2845 } 2888 2846 2889 AutoReadLock alock( this);2847 AutoReadLock alock(m->ollDVDImages.getLockHandle()); 2890 2848 2891 2849 bool found = false; 2892 2850 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(); 2895 2853 ++ it) 2896 2854 { … … 2963 2921 } 2964 2922 2965 AutoReadLock alock( this);2923 AutoReadLock alock(m->ollFloppyImages.getLockHandle()); 2966 2924 2967 2925 bool found = false; 2968 2926 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(); 2971 2929 ++ it) 2972 2930 { … … 3009 2967 GuestOSType*& pGuestOSType) 3010 2968 { 3011 AutoReadLock alock(this);3012 3013 2969 /* Look for a GuestOSType object */ 3014 AssertMsg(m-> llGuestOSTypes.size() != 0,2970 AssertMsg(m->ollGuestOSTypes.size() != 0, 3015 2971 ("Guest OS types array must be filled")); 3016 2972 … … 3021 2977 } 3022 2978 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(); 3025 2982 ++it) 3026 2983 { … … 3166 3123 * @note Locks this object and media objects for reading. 3167 3124 */ 3168 HRESULT VirtualBox::checkMediaForConflicts2 3169 3170 3125 HRESULT VirtualBox::checkMediaForConflicts2(const Guid &aId, 3126 const Utf8Str &aLocation, 3127 Utf8Str &aConflict) 3171 3128 { 3172 3129 aConflict.setNull(); … … 3239 3196 HRESULT rc = S_OK; 3240 3197 3241 /* serialize file access (prevents concurrent reads and writes) */3242 AutoWriteLock alock(this);3243 3244 3198 try 3245 3199 { 3246 3200 // 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 } 3255 3212 } 3256 3213 3257 3214 // 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 } 3267 3227 } 3268 3228 3269 3229 /* 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 } 3279 3242 } 3280 3243 3281 3244 /* 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 3304 3284 3305 3285 /* host data (USB filters) */ … … 3310 3290 if (FAILED(rc)) throw rc; 3311 3291 3312 // now write out the XML3292 // and write out the XML, still under the lock 3313 3293 m->pMainConfigFile->write(m->strSettingsFilePath); 3314 3294 } … … 3348 3328 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 3349 3329 3350 AutoWriteLock alock(this);3351 3352 3330 HRESULT rc = S_OK; 3353 3331 … … 3379 3357 3380 3358 /* add to the collection of registered machines */ 3381 m-> llMachines.push_back(aMachine);3359 m->ollMachines.addChild(aMachine); 3382 3360 3383 3361 if (autoCaller.state() != InInit) … … 3410 3388 AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); 3411 3389 3412 AutoWriteLock alock(this); 3413 3414 AutoCaller hardDiskCaller (aHardDisk); 3390 AutoCaller hardDiskCaller(aHardDisk); 3415 3391 AssertComRCReturn(hardDiskCaller.rc(), hardDiskCaller.rc()); 3416 3392 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 } 3443 3429 3444 3430 if (aSaveRegistry) 3445 3431 { 3446 3432 rc = saveSettings(); 3447 if (FAILED 3433 if (FAILED(rc)) 3448 3434 unregisterHardDisk(aHardDisk, false /* aSaveRegistry */); 3449 3435 } … … 3475 3461 AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); 3476 3462 3477 AutoWriteLock alock(this);3478 3479 3463 AutoCaller hardDiskCaller (aHardDisk); 3480 3464 AssertComRCReturn(hardDiskCaller.rc(), hardDiskCaller.rc()); 3481 3465 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); 3492 3487 } 3493 3488 … … 3497 3492 { 3498 3493 rc = saveSettings(); 3499 if (FAILED 3494 if (FAILED(rc)) 3500 3495 registerHardDisk(aHardDisk, false /* aSaveRegistry */); 3501 3496 } … … 3505 3500 3506 3501 /** 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. 3510 3506 * @param aSaveRegistry @c true to save the image registry to disk (default). 3511 3507 * … … 3519 3515 * @note Locks this object for writing and @a aImage for reading. 3520 3516 */ 3521 HRESULT VirtualBox::registerDVDImage (Medium *aImage, 3522 bool aSaveRegistry /*= true*/) 3523 { 3524 AssertReturn(aImage != NULL, E_INVALIDARG); 3517 HRESULT VirtualBox::registerImage(Medium *argImage, 3518 DeviceType_T argType, 3519 bool argSaveRegistry /*= true*/) 3520 { 3521 AssertReturn(argImage != NULL, E_INVALIDARG); 3525 3522 3526 3523 AutoCaller autoCaller(this); 3527 3524 AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); 3528 3525 3529 AutoWriteLock alock(this); 3530 3531 AutoCaller imageCaller (aImage); 3526 AutoCaller imageCaller(argImage); 3532 3527 AssertComRCReturn(imageCaller.rc(), imageCaller.rc()); 3533 3528 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) 3556 3567 { 3557 3568 rc = saveSettings(); 3558 if (FAILED 3559 unregister DVDImage (aImage, false /* aSaveRegistry */);3569 if (FAILED(rc)) 3570 unregisterImage(argImage, argType, false /* aSaveRegistry */); 3560 3571 } 3561 3572 … … 3564 3575 3565 3576 /** 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). 3570 3582 * 3571 3583 * When @a aSaveRegistry is @c true, this operation may fail because of the … … 3578 3590 * @note Locks this object for writing and @a aImage for reading. 3579 3591 */ 3580 HRESULT VirtualBox::unregisterDVDImage (Medium *aImage, 3581 bool aSaveRegistry /*= true*/) 3582 { 3583 AssertReturn(aImage != NULL, E_INVALIDARG); 3592 HRESULT VirtualBox::unregisterImage(Medium *argImage, 3593 DeviceType_T argType, 3594 bool argSaveRegistry /*= true*/) 3595 { 3596 AssertReturn(argImage != NULL, E_INVALIDARG); 3584 3597 3585 3598 AutoCaller autoCaller(this); 3586 3599 AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); 3587 3600 3588 AutoWriteLock alock(this); 3589 3590 AutoCaller imageCaller (aImage); 3601 AutoCaller imageCaller(argImage); 3591 3602 AssertComRCReturn(imageCaller.rc(), imageCaller.rc()); 3592 3603 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); 3596 3616 3597 3617 HRESULT rc = S_OK; 3598 3618 3599 if (a SaveRegistry)3619 if (argSaveRegistry) 3600 3620 { 3601 3621 rc = saveSettings(); 3602 if (FAILED 3603 register DVDImage (aImage, false /* aSaveRegistry */);3622 if (FAILED(rc)) 3623 registerImage(argImage, argType, false /* aSaveRegistry */); 3604 3624 } 3605 3625 3606 3626 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 the3616 * failed #saveSettings() method it calls. In this case, the image object3617 * will not be remembered. It is therefore the responsibility of the caller to3618 * call this method as the last step of some action that requires registration3619 * in order to make sure that only fully functional image objects get3620 * 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 the3675 * failed #saveSettings() method it calls. In this case, the image object3676 * will NOT be removed from the registry when this method returns. It is3677 * therefore the responsibility of the caller to call this method as the first3678 * step of some action that requires unregistration, before calling uninit() on3679 * @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 will3715 * 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() result3730 * 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 Medium3739 * implementations of IMedium can be among our children */3740 3741 aTo = static_cast<Medium*>(child);3742 3743 return S_OK;3744 3627 } 3745 3628 … … 3754 3637 * @note Locks this object + DVD, Floppy and HardDisk children for writing. 3755 3638 */ 3756 HRESULT VirtualBox::updateSettings 3639 HRESULT VirtualBox::updateSettings(const char *aOldPath, const char *aNewPath) 3757 3640 { 3758 3641 LogFlowThisFunc(("aOldPath={%s} aNewPath={%s}\n", aOldPath, aNewPath)); … … 3764 3647 AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); 3765 3648 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(); 3771 3656 ++ it) 3772 3657 { 3773 3658 (*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);3790 3659 } 3791 3660 … … 3899 3768 RWLockHandle& VirtualBox::hardDiskTreeLockHandle() 3900 3769 { 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(); 3915 3771 } 3916 3772 … … 3924 3780 LogFlowFuncEnter(); 3925 3781 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; 3928 3787 3929 3788 SessionMachineVector machines; … … 3978 3837 { 3979 3838 /* machine mutex is released */ 3980 (machines 3839 (machines[rc - WAIT_OBJECT_0 - 1])->checkForDeath(); 3981 3840 update = true; 3982 3841 } … … 3984 3843 { 3985 3844 /* machine mutex is abandoned due to client process termination */ 3986 (machines 3845 (machines[rc - WAIT_ABANDONED_0 - 1])->checkForDeath(); 3987 3846 update = true; 3988 3847 } … … 3998 3857 { 3999 3858 /* 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()); 4004 3864 4005 3865 /* obtain a new set of opened machines */ … … 4007 3867 machines.clear(); 4008 3868 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) 4011 3872 { 4012 3873 /// @todo handle situations with more than 64 objects … … 4016 3877 ComObjPtr<SessionMachine> sm; 4017 3878 HANDLE ipcSem; 4018 if ((*it)->isSessionOpenOrClosing 3879 if ((*it)->isSessionOpenOrClosing(sm, NULL, &ipcSem)) 4019 3880 { 4020 machines.push_back 4021 handles 4022 ++ 3881 machines.push_back(sm); 3882 handles[1 + cnt] = ipcSem; 3883 ++cnt; 4023 3884 } 4024 3885 } … … 4030 3891 spawnedMachines.clear(); 4031 3892 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) 4034 3896 { 4035 3897 /// @todo handle situations with more than 64 objects … … 4038 3900 4039 3901 RTPROCESS pid; 4040 if ((*it)->isSessionSpawning 3902 if ((*it)->isSessionSpawning(&pid)) 4041 3903 { 4042 HANDLE ph = OpenProcess 3904 HANDLE ph = OpenProcess(SYNCHRONIZE, FALSE, pid); 4043 3905 AssertMsg (ph != NULL, ("OpenProcess (pid=%d) failed with %d\n", 4044 3906 pid, GetLastError())); 4045 3907 if (rc == 0) 4046 3908 { 4047 spawnedMachines.push_back 4048 handles 4049 ++ 3909 spawnedMachines.push_back(*it); 3910 handles[1 + cnt + cntSpawned] = ph; 3911 ++cntSpawned; 4050 3912 } 4051 3913 } … … 4053 3915 4054 3916 LogFlowFunc (("UPDATE: spawned session count = %d\n", cntSpawned)); 3917 3918 // machines lock unwinds here 4055 3919 } 4056 3920 } … … 4090 3954 autoCaller.release(); 4091 3955 4092 int vrc = RTSemEventWait 3956 int vrc = RTSemEventWait(that->m->updateReq, 500); 4093 3957 4094 3958 /* Restore the caller before using VirtualBox. If it fails, this … … 4129 3993 #ifdef DEBUG 4130 3994 { 4131 AutoReadLock machineLock (machines[semId]);3995 AutoReadLock machineLock(machines[semId]); 4132 3996 LogFlowFunc (("released mutex: machine='%ls'\n", 4133 machines 3997 machines[semId]->name().raw())); 4134 3998 } 4135 3999 #endif 4136 machines 4000 machines[semId]->checkForDeath(); 4137 4001 } 4138 4002 update = true; … … 4159 4023 #ifdef DEBUG 4160 4024 { 4161 AutoReadLock machineLock (machines[semId]);4162 LogFlowFunc 4163 machines[i]->name().raw()));4025 AutoReadLock machineLock(machines[semId]); 4026 LogFlowFunc(("mutex owner dead: machine='%ls'\n", 4027 machines[i]->name().raw())); 4164 4028 } 4165 4029 #endif 4166 machines 4030 machines[i]->checkForDeath(); 4167 4031 } 4168 4032 } … … 4198 4062 machines.clear(); 4199 4063 4200 for (Machine List::iterator it = that->m->llMachines.begin();4064 for (MachinesOList::iterator it = that->m->llMachines.begin(); 4201 4065 it != that->m->llMachines.end(); ++ it) 4202 4066 { … … 4211 4075 { 4212 4076 machines.push_back (sm); 4213 handles 4214 handles 4077 handles[cnt].hsemCur = (HSEM) ipcSem; 4078 handles[cnt].ulUser = cnt; 4215 4079 ++ cnt; 4216 4080 } … … 4236 4100 spawnedMachines.clear(); 4237 4101 4238 for (Machine List::iterator it = that->m->llMachines.begin();4102 for (MachinesOList::iterator it = that->m->llMachines.begin(); 4239 4103 it != that->m->llMachines.end(); ++ it) 4240 4104 { … … 4290 4154 /* RT_SUCCESS(rc) means an update event is signaled */ 4291 4155 4292 AutoReadLock thatLock (that); 4156 // lock the machines list for reading 4157 AutoReadLock thatLock(that->m->ollMachines.getLockHandle()); 4293 4158 4294 4159 if (RT_SUCCESS(rc) || update) … … 4297 4162 machines.clear(); 4298 4163 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) 4301 4167 { 4302 4168 ComObjPtr<SessionMachine> sm; 4303 if ((*it)->isSessionOpenOrClosing 4304 machines.push_back 4169 if ((*it)->isSessionOpenOrClosing(sm)) 4170 machines.push_back(sm); 4305 4171 } 4306 4172 4307 4173 cnt = machines.size(); 4308 LogFlowFunc 4174 LogFlowFunc(("UPDATE: direct session count = %d\n", cnt)); 4309 4175 } 4310 4176 … … 4314 4180 spawnedMachines.clear(); 4315 4181 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) 4318 4185 { 4319 4186 if ((*it)->isSessionSpawning()) 4320 spawnedMachines.push_back 4187 spawnedMachines.push_back(*it); 4321 4188 } 4322 4189 4323 4190 cntSpawned = spawnedMachines.size(); 4324 LogFlowFunc 4191 LogFlowFunc(("UPDATE: spawned session count = %d\n", cntSpawned)); 4325 4192 } 4193 4194 // machines lock unwinds here 4326 4195 } 4327 4196 … … 4490 4359 } 4491 4360 4492 //STDMETHODIMP VirtualBox::FindDHCPServerForInterface (IHostNetworkInterface * aIinterface, IDHCPServer ** aServer) 4493 //{ 4494 // return E_NOTIMPL; 4495 //} 4496 4497 STDMETHODIMP VirtualBox::FindDHCPServerByNetworkName (IN_BSTR aName, IDHCPServer ** aServer) 4361 STDMETHODIMP VirtualBox::FindDHCPServerByNetworkName(IN_BSTR aName, IDHCPServer ** aServer) 4498 4362 { 4499 4363 CheckComArgNotNull(aName); … … 4502 4366 AutoCaller autoCaller(this); 4503 4367 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 4504 4505 AutoWriteLock alock(this);4506 4368 4507 4369 HRESULT rc; … … 4509 4371 ComPtr<DHCPServer> found; 4510 4372 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()); 4517 4380 if (FAILED(rc)) throw rc; 4518 4381 4519 if (bstr == aName)4382 if (bstr == aName) 4520 4383 { 4521 4384 found = *it; … … 4558 4421 */ 4559 4422 HRESULT VirtualBox::registerDHCPServer(DHCPServer *aDHCPServer, 4560 bool aSaveRegistry /*= true*/)4423 bool aSaveRegistry /*= true*/) 4561 4424 { 4562 4425 AssertReturn(aDHCPServer != NULL, E_INVALIDARG); … … 4565 4428 AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); 4566 4429 4567 AutoWriteLock alock(this); 4568 4569 AutoCaller dhcpServerCaller (aDHCPServer); 4430 AutoCaller dhcpServerCaller(aDHCPServer); 4570 4431 AssertComRCReturn(dhcpServerCaller.rc(), dhcpServerCaller.rc()); 4571 4572 AutoReadLock dhcpServerLock (aDHCPServer);4573 4432 4574 4433 Bstr name; 4575 4434 HRESULT rc; 4576 rc = aDHCPServer->COMGETTER(NetworkName) 4435 rc = aDHCPServer->COMGETTER(NetworkName)(name.asOutParam()); 4577 4436 if (FAILED(rc)) return rc; 4578 4437 4579 4438 ComPtr<IDHCPServer> existing; 4580 4439 rc = FindDHCPServerByNetworkName(name.mutableRaw(), existing.asOutParam()); 4581 if (SUCCEEDED(rc))4440 if (SUCCEEDED(rc)) 4582 4441 { 4583 4442 return E_INVALIDARG; 4584 4443 } 4444 4585 4445 rc = S_OK; 4586 4446 4587 m-> llDHCPServers.push_back(aDHCPServer);4447 m->ollDHCPServers.addChild(aDHCPServer); 4588 4448 4589 4449 if (aSaveRegistry) … … 4625 4485 AssertComRCReturn(dhcpServerCaller.rc(), dhcpServerCaller.rc()); 4626 4486 4627 AutoReadLock dhcpServerLock (aDHCPServer); 4628 4629 m->llDHCPServers.remove (aDHCPServer); 4487 m->ollDHCPServers.removeChild(aDHCPServer); 4630 4488 4631 4489 HRESULT rc = S_OK;
Note:
See TracChangeset
for help on using the changeset viewer.