Changeset 25152 in vbox for trunk/src/VBox/Main
- Timestamp:
- Dec 2, 2009 5:37:39 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 55574
- Location:
- trunk/src/VBox/Main
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/MachineImpl.cpp
r25151 r25152 2625 2625 } 2626 2626 2627 snap = snap-> parent();2627 snap = snap->getParent(); 2628 2628 } 2629 2629 -
trunk/src/VBox/Main/MediumImpl.cpp
r25149 r25152 106 106 {} 107 107 108 /** weak VirtualBox parent */ 109 const ComObjPtr<VirtualBox, ComWeakRef> pVirtualBox; 110 108 111 const Guid id; 109 112 Utf8Str strDescription; … … 113 116 uint64_t size; 114 117 Utf8Str strLastAccessError; 118 119 // pParent and llChildren are protected by VirtualBox::hardDiskTreeLockHandle() 120 ComObjPtr<Medium> pParent; 121 MediaList llChildren; // to add a child, just call push_back; to remove a child, call child->deparent() which does a lookup 115 122 116 123 BackRefList backRefs; … … 366 373 * Medium::getTreeLock() is held in read mode. 367 374 */ 368 class Medium::MergeChain : public Medi um::List,375 class Medium::MergeChain : public MediaList, 369 376 public com::SupportErrorInfoBase 370 377 { … … 440 447 { 441 448 /* we will need parent to reparent target */ 442 if (!aMedium->m Parent.isNull())449 if (!aMedium->m->pParent.isNull()) 443 450 { 444 rc = aMedium->m Parent->addCaller();451 rc = aMedium->m->pParent->addCaller(); 445 452 if (FAILED(rc)) return rc; 446 453 447 mParent = aMedium->m Parent;454 mParent = aMedium->m->pParent; 448 455 } 449 456 } … … 451 458 { 452 459 /* we will need to reparent children */ 453 for ( List::const_iterator it = aMedium->getChildren().begin();460 for (MediaList::const_iterator it = aMedium->getChildren().begin(); 454 461 it != aMedium->getChildren().end(); 455 462 ++it) … … 535 542 bool isForward() const { return mForward; } 536 543 Medium *parent() const { return mParent; } 537 const List &children() const { return mChildren; }544 const MediaList& children() const { return mChildren; } 538 545 539 546 Medium *source() const … … 606 613 ComObjPtr <Medium> mParent; 607 614 /** Children of the source when backward merge (if any) */ 608 List mChildren;615 MediaList mChildren; 609 616 }; 610 617 … … 621 628 * Medium::getTreeLock() is held in read mode. 622 629 */ 623 class Medium::ImageChain : public Medi um::List,630 class Medium::ImageChain : public MediaList, 624 631 public com::SupportErrorInfoBase 625 632 { … … 633 640 if (begin() != end()) 634 641 { 635 List::const_iterator last = end();642 MediaList::const_iterator last = end(); 636 643 last--; 637 for ( List::const_iterator it = begin(); it != end(); ++ it)644 for (MediaList::const_iterator it = begin(); it != end(); ++ it) 638 645 { 639 646 AutoWriteLock alock(*it); … … 676 683 ErrorInfoKeeper eik(true /* aIsNull */); 677 684 MultiResult mrc(S_OK); 678 for ( List::const_iterator it = begin(); it != end(); ++ it)685 for (MediaList::const_iterator it = begin(); it != end(); ++ it) 679 686 { 680 687 HRESULT rc = S_OK; … … 729 736 ErrorInfoKeeper eik(true /* aIsNull */); 730 737 MultiResult mrc(S_OK); 731 List::const_iterator last = end();738 MediaList::const_iterator last = end(); 732 739 last--; 733 for ( List::const_iterator it = begin(); it != end(); ++ it)740 for (MediaList::const_iterator it = begin(); it != end(); ++ it) 734 741 { 735 742 HRESULT rc = S_OK; … … 887 894 888 895 /* share VirtualBox weakly (parent remains NULL so far) */ 889 unconst(m VirtualBox) = aVirtualBox;896 unconst(m->pVirtualBox) = aVirtualBox; 890 897 891 898 /* register with VirtualBox early, since uninit() will … … 929 936 m->state = MediumState_Created; 930 937 unconst(m->id).create(); 931 rc = m VirtualBox->registerHardDisk(this);938 rc = m->pVirtualBox->registerHardDisk(this); 932 939 933 940 /// @todo later we may want to use a pfnIsConfigSufficient backend info … … 986 993 987 994 /* share VirtualBox weakly (parent remains NULL so far) */ 988 unconst(m VirtualBox) = aVirtualBox;995 unconst(m->pVirtualBox) = aVirtualBox; 989 996 990 997 /* register with VirtualBox early, since uninit() will … … 1071 1078 1072 1079 /* share VirtualBox and parent weakly */ 1073 unconst(m VirtualBox) = aVirtualBox;1080 unconst(m->pVirtualBox) = aVirtualBox; 1074 1081 1075 1082 /* register with VirtualBox/parent early, since uninit() will 1076 1083 * unconditionally unregister on failure */ 1077 1084 if (aParent == NULL) 1085 // base disk: add to global list 1078 1086 aVirtualBox->addDependentChild(this); 1079 1087 else 1080 1088 { 1081 /* we set mParent */ 1082 AutoWriteLock treeLock(this->getTreeLock()); 1083 1084 mParent = aParent; 1085 aParent->addDependentChild(this); 1089 // differencing image: add to parent 1090 AutoWriteLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 1091 m->pParent = aParent; 1092 aParent->m->llChildren.push_back(this); 1086 1093 } 1087 1094 … … 1145 1152 { 1146 1153 /* type is only for base hard disks */ 1147 if (m Parent.isNull())1154 if (m->pParent.isNull()) 1148 1155 m->type = data.hdType; 1149 1156 } … … 1179 1186 if (FAILED(rc)) break; 1180 1187 1181 rc = m VirtualBox->registerHardDisk(pHD, false /* aSaveRegistry */);1188 rc = m->pVirtualBox->registerHardDisk(pHD, false /* aSaveRegistry */); 1182 1189 if (FAILED(rc)) break; 1183 1190 } … … 1218 1225 1219 1226 /* share VirtualBox weakly (parent remains NULL so far) */ 1220 unconst(m VirtualBox) = aVirtualBox;1227 unconst(m->pVirtualBox) = aVirtualBox; 1221 1228 aVirtualBox->addDependentChild(this); 1222 1229 … … 1282 1289 * Reparenting has already been done so don't touch it here (we are 1283 1290 * now orphans and remoeDependentChild() will assert) */ 1284 1285 Assert(mParent.isNull()); 1291 Assert(m->pParent.isNull()); 1286 1292 } 1287 1293 else … … 1289 1295 /* we uninit children and reset mParent 1290 1296 * and VirtualBox::removeDependentChild() needs a write lock */ 1291 AutoMultiWriteLock2 alock(mVirtualBox->lockHandle(), this->getTreeLock()); 1292 1293 uninitDependentChildren(); 1294 1295 if (!mParent.isNull()) 1296 { 1297 mParent->removeDependentChild(this); 1298 mParent.setNull(); 1297 AutoWriteLock alock1(m->pVirtualBox->lockHandle()); 1298 AutoWriteLock alock2(m->pVirtualBox->hardDiskTreeLockHandle()); 1299 1300 MediaList::iterator it; 1301 for (it = m->llChildren.begin(); 1302 it != m->llChildren.end(); 1303 ++it) 1304 { 1305 Medium *pChild = *it; 1306 pChild->m->pParent.setNull(); 1307 pChild->uninit(); 1308 } 1309 m->llChildren.clear(); // this unsets all the ComPtrs and probably calls delete 1310 1311 if (m->pParent) 1312 { 1313 // this is a differencing disk: then remove it from the parent's children list 1314 deparent(); 1299 1315 } 1300 1316 else 1301 mVirtualBox->removeDependentChild(this); 1317 // base image: remove it from the global list 1318 m->pVirtualBox->removeDependentChild(this); 1302 1319 } 1303 1320 … … 1306 1323 m->queryInfoSem = NIL_RTSEMEVENTMULTI; 1307 1324 1308 unconst(mVirtualBox).setNull(); 1325 unconst(m->pVirtualBox).setNull(); 1326 } 1327 1328 /** 1329 * Internal helper that removes "this" from the list of children of its 1330 * parent. Used in uninit() and other places when reparenting is necessary. 1331 * 1332 * The caller must hold the hard disk tree lock! 1333 */ 1334 void Medium::deparent() 1335 { 1336 MediaList &llParent = m->pParent->m->llChildren; 1337 for (MediaList::iterator it = llParent.begin(); 1338 it != llParent.end(); 1339 ++it) 1340 { 1341 Medium *pParentsChild = *it; 1342 if (this == pParentsChild) 1343 { 1344 llParent.erase(it); 1345 break; 1346 } 1347 } 1348 m->pParent.setNull(); 1309 1349 } 1310 1350 … … 1502 1542 1503 1543 /* VirtualBox::saveSettings() needs a write lock */ 1504 AutoMultiWriteLock2 alock(m VirtualBox, this);1544 AutoMultiWriteLock2 alock(m->pVirtualBox, this); 1505 1545 1506 1546 switch (m->state) … … 1520 1560 1521 1561 /* we access mParent & children() */ 1522 AutoReadLock treeLock( this->getTreeLock());1562 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 1523 1563 1524 1564 /* cannot change the type of a differencing hard disk */ 1525 if ( !mParent.isNull())1565 if (m->pParent) 1526 1566 return setError(E_FAIL, 1527 tr(" Hard disk '%s'is a differencing hard disk"),1567 tr("Cannot change the type of hard disk '%s' because it is a differencing hard disk"), 1528 1568 m->strLocationFull.raw()); 1529 1569 … … 1531 1571 if (m->backRefs.size() != 0) 1532 1572 return setError(E_FAIL, 1533 tr(" Hard disk '%s'is attached to %d virtual machines"),1573 tr("Cannot change the type of hard disk '%s' because it is attached to %d virtual machines"), 1534 1574 m->strLocationFull.raw(), m->backRefs.size()); 1535 1575 … … 1559 1599 m->type = aType; 1560 1600 1561 HRESULT rc = m VirtualBox->saveSettings();1601 HRESULT rc = m->pVirtualBox->saveSettings(); 1562 1602 1563 1603 return rc; … … 1573 1613 1574 1614 /* we access mParent */ 1575 AutoReadLock treeLock( this->getTreeLock());1576 1577 m Parent.queryInterfaceTo(aParent);1615 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 1616 1617 m->pParent.queryInterfaceTo(aParent); 1578 1618 1579 1619 return S_OK; … … 1589 1629 1590 1630 /* we access children */ 1591 AutoReadLock treeLock( this->getTreeLock());1631 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 1592 1632 1593 1633 SafeIfaceArray<IMedium> children(this->getChildren()); … … 1635 1675 1636 1676 /* we access mParent */ 1637 AutoReadLock treeLock( this->getTreeLock());1638 1639 if (m Parent.isNull())1677 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 1678 1679 if (m->pParent.isNull()) 1640 1680 { 1641 1681 *aLogicalSize = m->logicalSize; … … 1663 1703 AutoReadLock alock(this); 1664 1704 1665 if (m Parent.isNull())1705 if (m->pParent) 1666 1706 *aAutoReset = FALSE; 1667 1707 … … 1677 1717 1678 1718 /* VirtualBox::saveSettings() needs a write lock */ 1679 AutoMultiWriteLock2 alock(m VirtualBox, this);1680 1681 if (m Parent.isNull())1719 AutoMultiWriteLock2 alock(m->pVirtualBox, this); 1720 1721 if (m->pParent.isNull()) 1682 1722 return setError(VBOX_E_NOT_SUPPORTED, 1683 1723 tr("Hard disk '%s' is not differencing"), … … 1688 1728 m->autoReset = aAutoReset; 1689 1729 1690 return m VirtualBox->saveSettings();1730 return m->pVirtualBox->saveSettings(); 1691 1731 } 1692 1732 … … 2019 2059 * a mVirtualBox lock of course). */ 2020 2060 2021 AutoWriteLock vboxLock(m VirtualBox);2061 AutoWriteLock vboxLock(m->pVirtualBox); 2022 2062 2023 2063 bool wasCreated = true; … … 2090 2130 2091 2131 /* VirtualBox::saveSettings() needs a write lock */ 2092 AutoMultiWriteLock2 alock(m VirtualBox, this);2132 AutoMultiWriteLock2 alock(m->pVirtualBox, this); 2093 2133 2094 2134 switch (m->state) … … 2112 2152 it->second = aValue; 2113 2153 2114 HRESULT rc = m VirtualBox->saveSettings();2154 HRESULT rc = m->pVirtualBox->saveSettings(); 2115 2155 2116 2156 return rc; … … 2164 2204 2165 2205 /* VirtualBox::saveSettings() needs a write lock */ 2166 AutoMultiWriteLock2 alock(m VirtualBox, this);2206 AutoMultiWriteLock2 alock(m->pVirtualBox, this); 2167 2207 2168 2208 com::SafeArray<IN_BSTR> names(ComSafeArrayInArg(aNames)); … … 2193 2233 } 2194 2234 2195 HRESULT rc = m VirtualBox->saveSettings();2235 HRESULT rc = m->pVirtualBox->saveSettings(); 2196 2236 2197 2237 return rc; … … 2232 2272 progress.createObject(); 2233 2273 /// @todo include fixed/dynamic 2234 HRESULT rc = progress->init(mVirtualBox, static_cast<IMedium*>(this), 2235 (aVariant & MediumVariant_Fixed) 2236 ? BstrFmt(tr("Creating fixed hard disk storage unit '%s'"), m->strLocationFull.raw()) 2237 : BstrFmt(tr("Creating dynamic hard disk storage unit '%s'"), m->strLocationFull.raw()), 2238 TRUE /* aCancelable */); 2274 HRESULT rc = progress->init(m->pVirtualBox, 2275 static_cast<IMedium*>(this), 2276 (aVariant & MediumVariant_Fixed) 2277 ? BstrFmt(tr("Creating fixed hard disk storage unit '%s'"), m->strLocationFull.raw()) 2278 : BstrFmt(tr("Creating dynamic hard disk storage unit '%s'"), m->strLocationFull.raw()), 2279 TRUE /* aCancelable */); 2239 2280 if (FAILED(rc)) return rc; 2240 2281 … … 2293 2334 2294 2335 ComObjPtr<Medium> diff; 2295 HRESULT rc = m VirtualBox->cast(aTarget, diff);2336 HRESULT rc = m->pVirtualBox->cast(aTarget, diff); 2296 2337 if (FAILED(rc)) return rc; 2297 2338 … … 2346 2387 2347 2388 ComObjPtr <Medium> target; 2348 HRESULT rc = m VirtualBox->cast(aTarget, target);2389 HRESULT rc = m->pVirtualBox->cast(aTarget, target); 2349 2390 if (FAILED(rc)) return rc; 2350 2391 ComObjPtr <Medium> parent; 2351 2392 if (aParent) 2352 2393 { 2353 rc = m VirtualBox->cast(aParent, parent);2394 rc = m->pVirtualBox->cast(aParent, parent); 2354 2395 if (FAILED(rc)) return rc; 2355 2396 } … … 2373 2414 2374 2415 /* we walk the source tree */ 2375 AutoReadLock srcTreeLock(this->getTreeLock()); 2376 for (Medium *hd = this; hd; hd = hd->mParent) 2416 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 2417 for (Medium *hd = this; 2418 hd; 2419 hd = hd->m->pParent) 2377 2420 { 2378 2421 rc = srcChain->addImage(hd); … … 2385 2428 std::auto_ptr <ImageChain> parentChain(new ImageChain()); 2386 2429 2387 /* we walk the future parent tree */ 2388 AutoReadLock parentTreeLock; 2389 if (parent) 2390 parentTreeLock.attach(parent->getTreeLock()); 2391 for (Medium *hd = parent; hd; hd = hd->mParent) 2430 for (Medium *hd = parent; 2431 hd; 2432 hd = hd->m->pParent) 2392 2433 { 2393 2434 rc = parentChain->addImage(hd); … … 2410 2451 2411 2452 progress.createObject(); 2412 rc = progress->init(m VirtualBox, static_cast <IMedium *>(this),2413 BstrFmt(tr("Creating clone hard disk '%s'"),2414 target->m->strLocationFull.raw()),2415 TRUE /* aCancelable */);2453 rc = progress->init(m->pVirtualBox, 2454 static_cast <IMedium *>(this), 2455 BstrFmt(tr("Creating clone hard disk '%s'"), target->m->strLocationFull.raw()), 2456 TRUE /* aCancelable */); 2416 2457 if (FAILED(rc)) throw rc; 2417 2458 … … 2419 2460 * asynchronously */ 2420 2461 2421 std::auto_ptr 2462 std::auto_ptr<Task> task(new Task(this, progress, Task::Clone)); 2422 2463 AssertComRCThrowRC(task->m_autoCaller.rc()); 2423 2464 … … 2475 2516 2476 2517 /* we walk the image tree */ 2477 AutoReadLock srcTreeLock(this->getTreeLock()); 2478 for (Medium *hd = this; hd; hd = hd->mParent) 2518 AutoReadLock srcTreeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 2519 for (Medium *hd = this; 2520 hd; 2521 hd = hd->m->pParent) 2479 2522 { 2480 2523 rc = imgChain->addImage(hd); … … 2485 2528 2486 2529 progress.createObject(); 2487 rc = progress->init(mVirtualBox, static_cast <IMedium *>(this), 2488 BstrFmt(tr("Compacting hard disk '%s'"), m->strLocationFull.raw()), 2489 TRUE /* aCancelable */); 2530 rc = progress->init(m->pVirtualBox, 2531 static_cast <IMedium *>(this), 2532 BstrFmt(tr("Compacting hard disk '%s'"), m->strLocationFull.raw()), 2533 TRUE /* aCancelable */); 2490 2534 if (FAILED(rc)) throw rc; 2491 2535 … … 2541 2585 LogFlowThisFunc(("ENTER for medium %s\n", m->strLocationFull.c_str())); 2542 2586 2543 if (m Parent.isNull())2587 if (m->pParent.isNull()) 2544 2588 return setError(VBOX_E_NOT_SUPPORTED, 2545 2589 tr ("Hard disk '%s' is not differencing"), … … 2557 2601 { 2558 2602 progress.createObject(); 2559 rc = progress->init(m VirtualBox, static_cast <IMedium *>(this),2560 BstrFmt(tr("Resetting differencing hard disk '%s'"),2561 m->strLocationFull.raw()),2562 FALSE /* aCancelable */);2603 rc = progress->init(m->pVirtualBox, 2604 static_cast <IMedium *>(this), 2605 BstrFmt(tr("Resetting differencing hard disk '%s'"), m->strLocationFull.raw()), 2606 FALSE /* aCancelable */); 2563 2607 if (FAILED(rc)) throw rc; 2564 2608 … … 2604 2648 2605 2649 /** 2606 * Checks if the given change of \a aOldPath to \a aNewPath affects the location 2607 * of this media and updates it if necessary to reflect the new location. 2608 * 2609 * @param aOldPath Old path (full). 2610 * @param aNewPath New path (full). 2611 * 2612 * @note Locks this object for writing. 2650 * Internal method to return the medium's parent medium. Must have caller + locking! 2651 * @return 2613 2652 */ 2614 HRESULT Medium::updatePath(const char *aOldPath, const char *aNewPath) 2615 { 2616 AssertReturn(aOldPath, E_FAIL); 2617 AssertReturn(aNewPath, E_FAIL); 2618 2619 AutoCaller autoCaller(this); 2620 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 2621 2622 AutoWriteLock alock(this); 2623 2624 LogFlowThisFunc(("locationFull.before='%s'\n", m->strLocationFull.raw())); 2625 2626 Utf8Str path = m->strLocationFull; 2627 2628 if (RTPathStartsWith(path.c_str(), aOldPath)) 2629 { 2630 Utf8Str newPath = Utf8StrFmt("%s%s", aNewPath, 2631 path.raw() + strlen(aOldPath)); 2632 path = newPath; 2633 2634 mVirtualBox->calculateRelativePath(path, path); 2635 2636 unconst(m->strLocationFull) = newPath; 2637 unconst(m->strLocation) = path; 2638 2639 LogFlowThisFunc(("locationFull.after='%s'\n", m->strLocationFull.raw())); 2640 } 2641 2642 return S_OK; 2653 const ComObjPtr<Medium>& Medium::getParent() const 2654 { 2655 return m->pParent; 2656 } 2657 2658 /** 2659 * Internal method to return the medium's list of child media. Must have caller + locking! 2660 * @return 2661 */ 2662 const MediaList& Medium::getChildren() const 2663 { 2664 return m->llChildren; 2665 } 2666 2667 /** 2668 * Internal method to return the medium's GUID. Must have caller + locking! 2669 * @return 2670 */ 2671 const Guid& Medium::getId() const 2672 { 2673 return m->id; 2674 } 2675 2676 /** 2677 * Internal method to return the medium's GUID. Must have caller + locking! 2678 * @return 2679 */ 2680 MediumState_T Medium::getState() const 2681 { 2682 return m->state; 2683 } 2684 2685 /** 2686 * Internal method to return the medium's location. Must have caller + locking! 2687 * @return 2688 */ 2689 const Utf8Str& Medium::getLocation() const 2690 { 2691 return m->strLocation; 2692 } 2693 2694 /** 2695 * Internal method to return the medium's full location. Must have caller + locking! 2696 * @return 2697 */ 2698 const Utf8Str& Medium::getLocationFull() const 2699 { 2700 return m->strLocationFull; 2701 } 2702 2703 /** 2704 * Internal method to return the medium's size. Must have caller + locking! 2705 * @return 2706 */ 2707 uint64_t Medium::getSize() const 2708 { 2709 return m->size; 2643 2710 } 2644 2711 … … 2775 2842 } 2776 2843 2844 /** 2845 * Internal method to return the medium's list of backrefs. Must have caller + locking! 2846 * @return 2847 */ 2848 const Guid* Medium::getFirstMachineBackrefId() const 2849 { 2850 if (!m->backRefs.size()) 2851 return NULL; 2852 2853 return &m->backRefs.front().machineId; 2854 } 2855 2856 const Guid* Medium::getFirstMachineBackrefSnapshotId() const 2857 { 2858 if (!m->backRefs.size()) 2859 return NULL; 2860 2861 const BackRef &ref = m->backRefs.front(); 2862 if (!ref.llSnapshotIds.size()) 2863 return NULL; 2864 2865 return &ref.llSnapshotIds.front(); 2866 } 2867 2777 2868 #ifdef DEBUG 2778 2869 /** … … 2806 2897 2807 2898 /** 2808 * Internal method to return the medium's GUID. Must have caller + locking! 2809 * @return 2899 * Checks if the given change of \a aOldPath to \a aNewPath affects the location 2900 * of this media and updates it if necessary to reflect the new location. 2901 * 2902 * @param aOldPath Old path (full). 2903 * @param aNewPath New path (full). 2904 * 2905 * @note Locks this object for writing. 2810 2906 */ 2811 const Guid& Medium::getId() const 2812 { 2813 return m->id; 2814 } 2815 2816 /** 2817 * Internal method to return the medium's GUID. Must have caller + locking! 2818 * @return 2819 */ 2820 MediumState_T Medium::getState() const 2821 { 2822 return m->state; 2823 } 2824 2825 /** 2826 * Internal method to return the medium's location. Must have caller + locking! 2827 * @return 2828 */ 2829 const Utf8Str& Medium::getLocation() const 2830 { 2831 return m->strLocation; 2832 } 2833 2834 /** 2835 * Internal method to return the medium's full location. Must have caller + locking! 2836 * @return 2837 */ 2838 const Utf8Str& Medium::getLocationFull() const 2839 { 2840 return m->strLocationFull; 2841 } 2842 2843 /** 2844 * Internal method to return the medium's size. Must have caller + locking! 2845 * @return 2846 */ 2847 uint64_t Medium::getSize() const 2848 { 2849 return m->size; 2850 } 2851 2852 /** 2853 * Internal method to return the medium's list of backrefs. Must have caller + locking! 2854 * @return 2855 */ 2856 const Guid* Medium::getFirstMachineBackrefId() const 2857 { 2858 if (!m->backRefs.size()) 2859 return NULL; 2860 2861 return &m->backRefs.front().machineId; 2862 } 2863 2864 const Guid* Medium::getFirstMachineBackrefSnapshotId() const 2865 { 2866 if (!m->backRefs.size()) 2867 return NULL; 2868 2869 const BackRef &ref = m->backRefs.front(); 2870 if (!ref.llSnapshotIds.size()) 2871 return NULL; 2872 2873 return &ref.llSnapshotIds.front(); 2907 HRESULT Medium::updatePath(const char *aOldPath, const char *aNewPath) 2908 { 2909 AssertReturn(aOldPath, E_FAIL); 2910 AssertReturn(aNewPath, E_FAIL); 2911 2912 AutoCaller autoCaller(this); 2913 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 2914 2915 AutoWriteLock alock(this); 2916 2917 LogFlowThisFunc(("locationFull.before='%s'\n", m->strLocationFull.raw())); 2918 2919 Utf8Str path = m->strLocationFull; 2920 2921 if (RTPathStartsWith(path.c_str(), aOldPath)) 2922 { 2923 Utf8Str newPath = Utf8StrFmt("%s%s", aNewPath, 2924 path.raw() + strlen(aOldPath)); 2925 path = newPath; 2926 2927 m->pVirtualBox->calculateRelativePath(path, path); 2928 2929 unconst(m->strLocationFull) = newPath; 2930 unconst(m->strLocation) = path; 2931 2932 LogFlowThisFunc(("locationFull.after='%s'\n", m->strLocationFull.raw())); 2933 } 2934 2935 return S_OK; 2874 2936 } 2875 2937 … … 2895 2957 2896 2958 /* we access children() */ 2897 AutoReadLock treeLock( this->getTreeLock());2959 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 2898 2960 2899 2961 updatePath(aOldPath, aNewPath); 2900 2962 2901 2963 /* update paths of all children */ 2902 for ( List::const_iterator it = getChildren().begin();2964 for (MediaList::const_iterator it = getChildren().begin(); 2903 2965 it != getChildren().end(); 2904 2966 ++ it) … … 2929 2991 2930 2992 /* we access mParent */ 2931 AutoReadLock treeLock( this->getTreeLock());2993 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 2932 2994 2933 2995 pBase = this; 2934 2996 level = 0; 2935 2997 2936 if ( !mParent.isNull())2998 if (m->pParent) 2937 2999 { 2938 3000 for (;;) … … 2941 3003 AssertReturn(baseCaller.isOk(), pBase); 2942 3004 2943 if (pBase->m Parent.isNull())3005 if (pBase->m->pParent.isNull()) 2944 3006 break; 2945 3007 2946 pBase = pBase->m Parent;3008 pBase = pBase->m->pParent; 2947 3009 ++level; 2948 3010 } … … 2970 3032 2971 3033 /* we access children */ 2972 AutoReadLock treeLock( this->getTreeLock());3034 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 2973 3035 2974 3036 switch (m->type) … … 3017 3079 3018 3080 /* we access mParent */ 3019 AutoReadLock treeLock( this->getTreeLock());3081 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 3020 3082 3021 3083 data.uuid = m->id; … … 3024 3086 3025 3087 /* optional, only for diffs, default is false */ 3026 if ( !mParent.isNull())3088 if (m->pParent) 3027 3089 data.fAutoReset = !!m->autoReset; 3028 3090 else … … 3048 3110 3049 3111 /* only for base hard disks */ 3050 if (m Parent.isNull())3112 if (m->pParent.isNull()) 3051 3113 data.hdType = m->type; 3052 3114 3053 3115 /* save all children */ 3054 for ( List::const_iterator it = getChildren().begin();3116 for (MediaList::const_iterator it = getChildren().begin(); 3055 3117 it != getChildren().end(); 3056 3118 ++it) … … 3097 3159 { 3098 3160 location = Utf8StrFmt("%s%c%s", 3099 m VirtualBox->getDefaultHardDiskFolder().raw(),3161 m->pVirtualBox->getDefaultHardDiskFolder().raw(), 3100 3162 RTPATH_DELIMITER, 3101 3163 aLocation); 3102 3164 } 3103 3165 3104 int vrc = m VirtualBox->calculateFullPath(location, location);3166 int vrc = m->pVirtualBox->calculateFullPath(location, location); 3105 3167 if (RT_FAILURE(vrc)) 3106 3168 return setError(E_FAIL, … … 3144 3206 3145 3207 /* we access mParent & children() */ 3146 AutoReadLock treeLock( this->getTreeLock());3208 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 3147 3209 3148 3210 AssertReturn(m->type == MediumType_Normal, E_FAIL); … … 3152 3214 /* special treatment of the last hard disk in the chain: */ 3153 3215 3154 if (m Parent.isNull())3216 if (m->pParent.isNull()) 3155 3217 { 3156 3218 /* lock only, to prevent any usage; discard() will unlock */ … … 3197 3259 3198 3260 /* delegate the rest to the profi */ 3199 if (m Parent.isNull())3261 if (m->pParent.isNull()) 3200 3262 { 3201 3263 /* base hard disk, backward merge */ 3202 3203 3264 Assert(child->m->backRefs.size() == 1); 3204 3265 if (child->m->backRefs.front().machineId != m->backRefs.front().machineId) … … 3282 3343 3283 3344 /* we access mParent & children() */ 3284 AutoReadLock treeLock( this->getTreeLock());3345 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 3285 3346 3286 3347 Assert(getChildren().size() == 0); … … 3288 3349 /* special treatment of the last hard disk in the chain: */ 3289 3350 3290 if (m Parent.isNull())3351 if (m->pParent.isNull()) 3291 3352 { 3292 3353 rc = UnlockWrite(NULL); … … 3350 3411 3351 3412 /* we access mParent & children() */ 3352 AutoReadLock treeLock( this->getTreeLock());3413 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 3353 3414 3354 3415 Assert(getChildren().size() == 0); … … 3356 3417 /* special treatment of the last hard disk in the chain: */ 3357 3418 3358 if (m Parent.isNull())3419 if (m->pParent.isNull()) 3359 3420 { 3360 3421 HRESULT rc = UnlockWrite(NULL); … … 3393 3454 { 3394 3455 /* use the default format if not */ 3395 AutoReadLock propsLock(m VirtualBox->systemProperties());3396 strFormat = m VirtualBox->getDefaultHardDiskFormat();3456 AutoReadLock propsLock(m->pVirtualBox->systemProperties()); 3457 strFormat = m->pVirtualBox->getDefaultHardDiskFormat(); 3397 3458 } 3398 3459 … … 3407 3468 { 3408 3469 return m->type; 3409 }3410 3411 /**3412 * Returns VirtualBox::hardDiskTreeHandle(), for convenience. Don't forget3413 * to follow these locking rules:3414 *3415 * 1. The write lock on this handle must be either held alone on the thread3416 * or requested *after* the VirtualBox object lock. Mixing with other3417 * locks is prohibited.3418 *3419 * 2. The read lock on this handle may be intermixed with any other lock3420 * with the exception that it must be requested *after* the VirtualBox3421 * object lock.3422 */3423 RWLockHandle* Medium::getTreeLock()3424 {3425 return &mVirtualBox->hardDiskTreeLockHandle();3426 3470 } 3427 3471 … … 3520 3564 if (!RTPathHavePath(location.c_str())) 3521 3565 location = Utf8StrFmt("%s%c%s", 3522 m VirtualBox->getDefaultHardDiskFolder().raw(),3566 m->pVirtualBox->getDefaultHardDiskFolder().raw(), 3523 3567 RTPATH_DELIMITER, 3524 3568 location.raw()); … … 3526 3570 /* get the full file name */ 3527 3571 Utf8Str locationFull; 3528 int vrc = m VirtualBox->calculateFullPath(location, locationFull);3572 int vrc = m->pVirtualBox->calculateFullPath(location, locationFull); 3529 3573 if (RT_FAILURE(vrc)) 3530 3574 return setError(VBOX_E_FILE_ERROR, … … 3778 3822 location.c_str(), 3779 3823 mediumId.raw(), 3780 m VirtualBox->settingsFilePath().c_str());3824 m->pVirtualBox->settingsFilePath().c_str()); 3781 3825 throw S_OK; 3782 3826 } … … 3820 3864 Guid id = parentId; 3821 3865 ComObjPtr<Medium> parent; 3822 rc = m VirtualBox->findHardDisk(&id, NULL,3866 rc = m->pVirtualBox->findHardDisk(&id, NULL, 3823 3867 false /* aSetError */, 3824 3868 &parent); … … 3828 3872 tr("Parent hard disk with UUID {%RTuuid} of the hard disk '%s' is not found in the media registry ('%s')"), 3829 3873 &parentId, location.c_str(), 3830 m VirtualBox->settingsFilePath().c_str());3874 m->pVirtualBox->settingsFilePath().c_str()); 3831 3875 throw S_OK; 3832 3876 } … … 3834 3878 /* deassociate from VirtualBox, associate with parent */ 3835 3879 3836 m VirtualBox->removeDependentChild(this);3880 m->pVirtualBox->removeDependentChild(this); 3837 3881 3838 3882 /* we set mParent & children() */ 3839 AutoWriteLock treeLock( this->getTreeLock());3840 3841 Assert(m Parent.isNull());3842 m Parent = parent;3843 m Parent->addDependentChild(this);3883 AutoWriteLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 3884 3885 Assert(m->pParent.isNull()); 3886 m->pParent = parent; 3887 m->pParent->m->llChildren.push_back(this); 3844 3888 } 3845 3889 else 3846 3890 { 3847 3891 /* we access mParent */ 3848 AutoReadLock treeLock( this->getTreeLock());3892 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 3849 3893 3850 3894 /* check that parent UUIDs match. Note that there's no need … … 3852 3896 * it) */ 3853 3897 3854 if (m Parent.isNull())3898 if (m->pParent.isNull()) 3855 3899 { 3856 3900 lastAccessError = Utf8StrFmt( 3857 3901 tr("Hard disk '%s' is differencing but it is not associated with any parent hard disk in the media registry ('%s')"), 3858 3902 location.c_str(), 3859 m VirtualBox->settingsFilePath().c_str());3903 m->pVirtualBox->settingsFilePath().c_str()); 3860 3904 throw S_OK; 3861 3905 } 3862 3906 3863 AutoReadLock parentLock(m Parent);3864 if ( m Parent->getState() != MediumState_Inaccessible3865 && m Parent->getId() != parentId)3907 AutoReadLock parentLock(m->pParent); 3908 if ( m->pParent->getState() != MediumState_Inaccessible 3909 && m->pParent->getId() != parentId) 3866 3910 { 3867 3911 lastAccessError = Utf8StrFmt( 3868 tr 3912 tr("Parent UUID {%RTuuid} of the hard disk '%s' does not match UUID {%RTuuid} of its parent hard disk stored in the media registry ('%s')"), 3869 3913 &parentId, location.c_str(), 3870 m Parent->getId().raw(),3871 m VirtualBox->settingsFilePath().c_str());3914 m->pParent->getId().raw(), 3915 m->pVirtualBox->settingsFilePath().c_str()); 3872 3916 throw S_OK; 3873 3917 } … … 4043 4087 * it holds a mVirtualBox lock too of course). */ 4044 4088 4045 AutoMultiWriteLock2 alock(m VirtualBox->lockHandle(), this->lockHandle());4089 AutoMultiWriteLock2 alock(m->pVirtualBox->lockHandle(), this->lockHandle()); 4046 4090 LogFlowThisFunc(("aWait=%RTbool locationFull=%s\n", aWait, getLocationFull().c_str() )); 4047 4091 … … 4125 4169 { 4126 4170 progress.createObject(); 4127 rc = progress->init(m VirtualBox, static_cast<IMedium*>(this),4128 BstrFmt(tr("Deleting hard disk storage unit '%s'"),4129 m->strLocationFull.raw()),4130 FALSE /* aCancelable */);4171 rc = progress->init(m->pVirtualBox, 4172 static_cast<IMedium*>(this), 4173 BstrFmt(tr("Deleting hard disk storage unit '%s'"), m->strLocationFull.raw()), 4174 FALSE /* aCancelable */); 4131 4175 if (FAILED(rc)) return rc; 4132 4176 } … … 4263 4307 { 4264 4308 progress.createObject(); 4265 rc = progress->init(m VirtualBox, static_cast<IMedium*>(this),4266 BstrFmt(tr("Creating differencing hard disk storage unit '%s'"),4267 aTarget->m->strLocationFull.raw()),4268 TRUE /* aCancelable */);4309 rc = progress->init(m->pVirtualBox, 4310 static_cast<IMedium*>(this), 4311 BstrFmt(tr("Creating differencing hard disk storage unit '%s'"), aTarget->m->strLocationFull.raw()), 4312 TRUE /* aCancelable */); 4269 4313 if (FAILED(rc)) return rc; 4270 4314 } … … 4350 4394 4351 4395 /* we walk the tree */ 4352 AutoReadLock treeLock( this->getTreeLock());4396 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 4353 4397 4354 4398 HRESULT rc = S_OK; … … 4357 4401 bool forward; 4358 4402 { 4359 Medium *parent = m Parent;4403 Medium *parent = m->pParent; 4360 4404 while (parent != NULL && parent != aTarget) 4361 parent = parent->m Parent;4405 parent = parent->m->pParent; 4362 4406 if (parent == aTarget) 4363 4407 forward = false; 4364 4408 else 4365 4409 { 4366 parent = aTarget->m Parent;4410 parent = aTarget->m->pParent; 4367 4411 while (parent != NULL && parent != this) 4368 parent = parent->m Parent;4412 parent = parent->m->pParent; 4369 4413 if (parent == this) 4370 4414 forward = true; … … 4405 4449 break; 4406 4450 4407 last = last->m Parent;4451 last = last->m->pParent; 4408 4452 } 4409 4453 } … … 4509 4553 4510 4554 progress.createObject(); 4511 rc = progress->init(mVirtualBox, static_cast<IMedium*>(this), 4512 BstrFmt(tr("Merging hard disk '%s' to '%s'"), 4513 getName().raw(), 4514 aChain->target()->getName().raw()), 4515 TRUE /* aCancelable */); 4555 rc = progress->init(m->pVirtualBox, 4556 static_cast<IMedium*>(this), 4557 BstrFmt(tr("Merging hard disk '%s' to '%s'"), 4558 getName().raw(), 4559 aChain->target()->getName().raw()), 4560 TRUE /* aCancelable */); 4516 4561 if (FAILED(rc)) return rc; 4517 4562 } … … 4585 4630 /* get the format object first */ 4586 4631 { 4587 AutoReadLock propsLock(m VirtualBox->systemProperties());4632 AutoReadLock propsLock(m->pVirtualBox->systemProperties()); 4588 4633 4589 4634 unconst(m->formatObj) 4590 = m VirtualBox->systemProperties()->mediumFormat(aFormat);4635 = m->pVirtualBox->systemProperties()->mediumFormat(aFormat); 4591 4636 if (m->formatObj.isNull()) 4592 4637 return setError(E_INVALIDARG, … … 4629 4674 { 4630 4675 /* we access children */ 4631 AutoReadLock treeLock( this->getTreeLock());4676 AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 4632 4677 4633 4678 if (getChildren().size() != 0) … … 4651 4696 4652 4697 /* we modify mParent and access children */ 4653 AutoWriteLock treeLock( this->getTreeLock());4654 4655 const ComObjPtr<Medium, ComWeakRef> parent = mParent;4698 AutoWriteLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle()); 4699 4700 Medium *pParentBackup = m->pParent; 4656 4701 4657 4702 AssertReturn(getChildren().size() == 0, E_FAIL); 4658 4703 4659 if ( !mParent.isNull())4704 if (m->pParent) 4660 4705 { 4661 4706 /* deassociate from the parent, associate with VirtualBox */ 4662 mVirtualBox->addDependentChild(this); 4663 mParent->removeDependentChild(this); 4664 mParent.setNull(); 4707 m->pVirtualBox->addDependentChild(this); 4708 deparent(); 4665 4709 } 4666 4710 … … 4669 4713 { 4670 4714 case DeviceType_DVD: 4671 rc = m VirtualBox->unregisterDVDImage(this);4715 rc = m->pVirtualBox->unregisterDVDImage(this); 4672 4716 break; 4673 4717 case DeviceType_Floppy: 4674 rc = m VirtualBox->unregisterFloppyImage(this);4718 rc = m->pVirtualBox->unregisterFloppyImage(this); 4675 4719 break; 4676 4720 case DeviceType_HardDisk: 4677 rc = m VirtualBox->unregisterHardDisk(this);4721 rc = m->pVirtualBox->unregisterHardDisk(this); 4678 4722 break; 4679 4723 default: … … 4683 4727 if (FAILED(rc)) 4684 4728 { 4685 if ( !parent.isNull())4729 if (pParentBackup) 4686 4730 { 4687 4731 /* re-associate with the parent as we are still relatives in the 4688 4732 * registry */ 4689 m Parent = parent;4690 m Parent->addDependentChild(this);4691 m VirtualBox->removeDependentChild(this);4733 m->pParent = pParentBackup; 4734 m->pParent->m->llChildren.push_back(this); 4735 m->pVirtualBox->removeDependentChild(this); 4692 4736 } 4693 4737 } … … 4972 5016 * Created state only on success (leaving an orphan file is 4973 5017 * better than breaking media registry consistency) */ 4974 rc = that->m VirtualBox->registerHardDisk(that);5018 rc = that->m->pVirtualBox->registerHardDisk(that); 4975 5019 } 4976 5020 … … 5090 5134 /* we set mParent & children() (note that thatLock is released 5091 5135 * here), but lock VirtualBox first to follow the rule */ 5092 Auto MultiWriteLock2 alock(that->mVirtualBox->lockHandle(),5093 that->getTreeLock());5094 5095 Assert(target->m Parent.isNull());5136 AutoWriteLock alock1(that->m->pVirtualBox); 5137 AutoWriteLock alock2(that->m->pVirtualBox->hardDiskTreeLockHandle()); 5138 5139 Assert(target->m->pParent.isNull()); 5096 5140 5097 5141 /* associate the child with the parent and deassociate from 5098 5142 * VirtualBox */ 5099 target->m Parent = that;5100 that-> addDependentChild(target);5101 target->m VirtualBox->removeDependentChild(target);5143 target->m->pParent = that; 5144 that->m->llChildren.push_back(target); 5145 target->m->pVirtualBox->removeDependentChild(target); 5102 5146 5103 5147 /** @todo r=klaus neither target nor that->base() are locked, … … 5111 5155 * Created state only on success (leaving an orphan file is 5112 5156 * better than breaking media registry consistency) */ 5113 rc = that->m VirtualBox->registerHardDisk(target);5157 rc = that->m->pVirtualBox->registerHardDisk(target); 5114 5158 5115 5159 if (FAILED(rc)) 5116 5160 { 5117 5161 /* break the parent association on failure to register */ 5118 target->mVirtualBox->addDependentChild(target); 5119 that->removeDependentChild(target); 5120 target->mParent.setNull(); 5162 target->m->pVirtualBox->addDependentChild(target); 5163 that->deparent(); 5121 5164 } 5122 5165 } … … 5258 5301 if (chain->children().size() > 0) 5259 5302 { 5260 for (List::const_iterator it = chain->children().begin(); 5261 it != chain->children().end(); ++ it) 5303 for (MediaList::const_iterator it = chain->children().begin(); 5304 it != chain->children().end(); 5305 ++it) 5262 5306 { 5263 5307 /* VD_OPEN_FLAGS_INFO since UUID is wrong yet */ … … 5306 5350 /* we set mParent & children() (note that thatLock is released 5307 5351 * here), but lock VirtualBox first to follow the rule */ 5308 Auto MultiWriteLock2 alock(that->mVirtualBox->lockHandle(),5309 that->getTreeLock());5352 AutoWriteLock alock1(that->m->pVirtualBox); 5353 AutoWriteLock alock2(that->m->pVirtualBox->hardDiskTreeLockHandle()); 5310 5354 5311 5355 Medium *source = chain->source(); … … 5316 5360 /* first, unregister the target since it may become a base 5317 5361 * hard disk which needs re-registration */ 5318 rc2 = target->mVirtualBox-> 5319 unregisterHardDisk(target, false /* aSaveSettings */); 5362 rc2 = target->m->pVirtualBox->unregisterHardDisk(target, false /* aSaveSettings */); 5320 5363 AssertComRC(rc2); 5321 5364 5322 5365 /* then, reparent it and disconnect the deleted branch at 5323 5366 * both ends (chain->parent() is source's parent) */ 5324 target-> mParent->removeDependentChild(target);5325 target->m Parent = chain->parent();5326 if ( !target->mParent.isNull())5367 target->deparent(); 5368 target->m->pParent = chain->parent(); 5369 if (target->m->pParent) 5327 5370 { 5328 target->mParent->addDependentChild(target); 5329 target->mParent->removeDependentChild(source); 5330 source->mParent.setNull(); 5371 target->m->pParent->m->llChildren.push_back(target); 5372 source->deparent(); 5331 5373 } 5332 5374 else 5333 5375 { 5334 target->m VirtualBox->addDependentChild(target);5335 target->m VirtualBox->removeDependentChild(source);5376 target->m->pVirtualBox->addDependentChild(target); 5377 target->m->pVirtualBox->removeDependentChild(source); 5336 5378 } 5337 5379 5338 5380 /* then, register again */ 5339 rc2 = target->m VirtualBox->5381 rc2 = target->m->pVirtualBox-> 5340 5382 registerHardDisk(target, false /* aSaveSettings */); 5341 5383 AssertComRC(rc2); … … 5347 5389 5348 5390 /* disconnect the deleted branch at the elder end */ 5349 target->removeDependentChild(targetChild); 5350 targetChild->mParent.setNull(); 5351 5352 const List &children = chain->children(); 5391 targetChild->deparent(); 5392 5393 const MediaList &children = chain->children(); 5353 5394 5354 5395 /* reparent source's chidren and disconnect the deleted … … 5359 5400 AutoWriteLock sourceLock(source); 5360 5401 5361 for (List::const_iterator it = children.begin(); 5362 it != children.end(); ++ it) 5402 for (MediaList::const_iterator it = children.begin(); 5403 it != children.end(); 5404 ++it) 5363 5405 { 5364 5406 AutoWriteLock childLock(*it); 5365 5407 5366 (*it)->mParent = target; 5367 (*it)->mParent->addDependentChild(*it); 5368 source->removeDependentChild(*it); 5408 Medium *p = *it; 5409 p->deparent(); // removes p from source 5410 target->m->llChildren.push_back(p); 5411 p->m->pParent = target; 5369 5412 } 5370 5413 } … … 5372 5415 5373 5416 /* try to save the hard disk registry */ 5374 rc = that->m VirtualBox->saveSettings();5417 rc = that->m->pVirtualBox->saveSettings(); 5375 5418 5376 5419 if (SUCCEEDED(rc)) … … 5388 5431 } 5389 5432 5390 rc2 = (*it)->m VirtualBox->5433 rc2 = (*it)->m->pVirtualBox-> 5391 5434 unregisterHardDisk(*it, false /* aSaveSettings */); 5392 5435 AssertComRC(rc2); … … 5495 5538 { 5496 5539 /* Open all hard disk images in the source chain. */ 5497 for (List::const_iterator it = srcChain->begin(); 5498 it != srcChain->end(); ++ it) 5540 for (MediaList::const_iterator it = srcChain->begin(); 5541 it != srcChain->end(); 5542 ++it) 5499 5543 { 5500 5544 /* sanity check */ … … 5537 5581 { 5538 5582 /* Open all hard disk images in the parent chain. */ 5539 for (List::const_iterator it = parentChain->begin(); 5540 it != parentChain->end(); ++ it) 5583 for (MediaList::const_iterator it = parentChain->begin(); 5584 it != parentChain->end(); 5585 ++it) 5541 5586 { 5542 5587 /** @todo r=klaus (*it) is not locked, lots of … … 5594 5639 /* we set mParent & children() (note that thatLock is released 5595 5640 * here), but lock VirtualBox first to follow the rule */ 5596 Auto MultiWriteLock2 alock(that->mVirtualBox->lockHandle(),5597 that->getTreeLock());5598 5599 Assert(target->m Parent.isNull());5641 AutoWriteLock alock1(that->m->pVirtualBox); 5642 AutoWriteLock alock2(that->m->pVirtualBox->hardDiskTreeLockHandle()); 5643 5644 Assert(target->m->pParent.isNull()); 5600 5645 5601 5646 if (parent) … … 5603 5648 /* associate the clone with the parent and deassociate 5604 5649 * from VirtualBox */ 5605 target->m Parent = parent;5606 parent-> addDependentChild(target);5607 target->m VirtualBox->removeDependentChild(target);5650 target->m->pParent = parent; 5651 parent->m->llChildren.push_back(target); 5652 target->m->pVirtualBox->removeDependentChild(target); 5608 5653 5609 5654 /* register with mVirtualBox as the last step and move to 5610 5655 * Created state only on success (leaving an orphan file is 5611 5656 * better than breaking media registry consistency) */ 5612 rc = parent->m VirtualBox->registerHardDisk(target);5657 rc = parent->m->pVirtualBox->registerHardDisk(target); 5613 5658 5614 5659 if (FAILED(rc)) 5615 5660 { 5616 5661 /* break parent association on failure to register */ 5617 target->mVirtualBox->addDependentChild(target); 5618 parent->removeDependentChild(target); 5619 target->mParent.setNull(); 5662 target->m->pVirtualBox->addDependentChild(target); 5663 target->deparent(); // removes target from parent 5620 5664 } 5621 5665 } … … 5623 5667 { 5624 5668 /* just register */ 5625 rc = that->m VirtualBox->registerHardDisk(target);5669 rc = that->m->pVirtualBox->registerHardDisk(target); 5626 5670 } 5627 5671 } … … 5739 5783 Utf8Str location(that->m->strLocationFull); 5740 5784 5741 Guid parentId = that->mParent->m->id; 5742 Utf8Str parentFormat(that->mParent->m->strFormat); 5743 Utf8Str parentLocation(that->mParent->m->strLocationFull); 5785 Medium *pParent = that->m->pParent; 5786 Guid parentId = pParent->m->id; 5787 Utf8Str parentFormat(pParent->m->strFormat); 5788 Utf8Str parentLocation(pParent->m->strLocationFull); 5744 5789 5745 5790 Assert(that->m->state == MediumState_LockedWrite); … … 5837 5882 { 5838 5883 /* Open all hard disk images in the chain. */ 5839 List::const_iterator last = imgChain->end();5884 MediaList::const_iterator last = imgChain->end(); 5840 5885 last--; 5841 for (List::const_iterator it = imgChain->begin(); 5842 it != imgChain->end(); ++ it) 5886 for (MediaList::const_iterator it = imgChain->begin(); 5887 it != imgChain->end(); 5888 ++it) 5843 5889 { 5844 5890 /* sanity check */ -
trunk/src/VBox/Main/SnapshotImpl.cpp
r25151 r25152 87 87 ComObjPtr<SnapshotMachine> pMachine; 88 88 89 SnapshotsList llChildren; // protected by VirtualBox::snapshotTreeLockHandle() 89 /** weak VirtualBox parent */ 90 const ComObjPtr<VirtualBox, ComWeakRef> pVirtualBox; 91 92 // pParent and llChildren are protected by Machine::snapshotsTreeLockHandle() 93 ComObjPtr<Snapshot> pParent; 94 SnapshotsList llChildren; 90 95 }; 91 96 … … 137 142 138 143 /* share parent weakly */ 139 unconst(m VirtualBox) = aVirtualBox;140 141 m Parent = aParent;144 unconst(m->pVirtualBox) = aVirtualBox; 145 146 m->pParent = aParent; 142 147 143 148 m->uuid = aId; … … 177 182 { 178 183 Snapshot *pChild = *it; 179 pChild->m Parent.setNull();184 pChild->m->pParent.setNull(); 180 185 pChild->uninit(); 181 186 } 182 187 m->llChildren.clear(); // this unsets all the ComPtrs and probably calls delete 183 188 184 if (mParent) 185 { 186 SnapshotsList &llParent = mParent->m->llChildren; 187 for (it = llParent.begin(); 188 it != llParent.end(); 189 ++it) 190 { 191 Snapshot *pParentsChild = *it; 192 if (this == pParentsChild) 193 { 194 llParent.erase(it); 195 break; 196 } 197 } 198 199 mParent.setNull(); 200 } 189 if (m->pParent) 190 deparent(); 201 191 202 192 if (m->pMachine) … … 231 221 AssertReturnVoid(m->llChildren.size() <= 1); 232 222 233 ComObjPtr<Snapshot> parentSnapshot = parent();223 ComObjPtr<Snapshot> parentSnapshot = m->pParent; 234 224 235 225 /// @todo (dmik): … … 268 258 AutoWriteLock childLock(child); 269 259 270 child->m Parent = mParent;271 if (m Parent)272 m Parent->m->llChildren.push_back(child);260 child->m->pParent = m->pParent; 261 if (m->pParent) 262 m->pParent->m->llChildren.push_back(child); 273 263 } 274 264 275 265 // clear our own children list (since we reparented the children) 276 266 m->llChildren.clear(); 267 } 268 269 /** 270 * Internal helper that removes "this" from the list of children of its 271 * parent. Used in uninit() and other places when reparenting is necessary. 272 * 273 * The caller must hold the snapshots tree lock! 274 */ 275 void Snapshot::deparent() 276 { 277 SnapshotsList &llParent = m->pParent->m->llChildren; 278 for (SnapshotsList::iterator it = llParent.begin(); 279 it != llParent.end(); 280 ++it) 281 { 282 Snapshot *pParentsChild = *it; 283 if (this == pParentsChild) 284 { 285 llParent.erase(it); 286 break; 287 } 288 } 289 290 m->pParent.setNull(); 277 291 } 278 292 … … 420 434 AutoReadLock alock(this); 421 435 422 m Parent.queryInterfaceTo(aParent);436 m->pParent.queryInterfaceTo(aParent); 423 437 return S_OK; 424 438 } … … 447 461 448 462 /** 463 * Returns the parent snapshot or NULL if there's none. Must have caller + locking! 464 * @return 465 */ 466 const ComObjPtr<Snapshot>& Snapshot::getParent() const 467 { 468 return m->pParent; 469 } 470 471 /** 449 472 * @note 450 473 * Must be called from under the object's lock! … … 509 532 * @return 510 533 */ 511 ComPtr<SnapshotMachine> Snapshot::getSnapshotMachine() 512 { 513 return (SnapshotMachine*)m->pMachine;534 const ComObjPtr<SnapshotMachine>& Snapshot::getSnapshotMachine() const 535 { 536 return m->pMachine; 514 537 } 515 538 … … 1522 1545 1523 1546 ComObjPtr<Snapshot> pSnapshot(static_cast<Snapshot*>(aSnapshot)); 1524 Com Ptr<SnapshotMachine> pSnapMachine = pSnapshot->getSnapshotMachine();1547 ComObjPtr<SnapshotMachine> pSnapMachine = pSnapshot->getSnapshotMachine(); 1525 1548 1526 1549 // create a progress object. The number of operations is: … … 1961 1984 } 1962 1985 1963 Com Ptr<SnapshotMachine> pSnapMachine = pSnapshot->getSnapshotMachine();1986 ComObjPtr<SnapshotMachine> pSnapMachine = pSnapshot->getSnapshotMachine(); 1964 1987 1965 1988 /* create a progress object. The number of operations is: … … 2110 2133 aTask.pSnapshot->lockHandle()); 2111 2134 2112 Com Ptr<SnapshotMachine> pSnapMachine = aTask.pSnapshot->getSnapshotMachine();2135 ComObjPtr<SnapshotMachine> pSnapMachine = aTask.pSnapshot->getSnapshotMachine(); 2113 2136 /* no need to lock the snapshot machine since it is const by definiton */ 2114 2137 … … 2247 2270 2248 2271 { 2249 ComObjPtr<Snapshot> parentSnapshot = aTask.pSnapshot-> parent();2272 ComObjPtr<Snapshot> parentSnapshot = aTask.pSnapshot->getParent(); 2250 2273 Utf8Str stateFilePath = aTask.pSnapshot->stateFilePath(); 2251 2274 -
trunk/src/VBox/Main/include/MediumImpl.h
r25151 r25152 46 46 */ 47 47 class ATL_NO_VTABLE Medium : 48 public VirtualBoxBase WithTypedChildren<Medium>,48 public VirtualBoxBase, 49 49 public com::SupportErrorInfoImpl<Medium, IMedium>, 50 50 public VirtualBoxSupportTranslation<Medium>, … … 52 52 { 53 53 public: 54 55 typedef VirtualBoxBaseWithTypedChildren<Medium>::DependentChildren List;56 57 54 class MergeChain; 58 55 class ImageChain; … … 70 67 71 68 DECLARE_EMPTY_CTOR_DTOR(Medium) 69 70 HRESULT FinalConstruct(); 71 void FinalRelease(); 72 72 73 73 enum HDDOpenMode { OpenReadWrite, OpenReadOnly }; … … 99 99 CBSTR aDescription = NULL); 100 100 void uninit(); 101 102 void deparent(); 101 103 102 104 // IMedium properties … … 155 157 156 158 // public methods for internal purposes only 157 158 HRESULT FinalConstruct(); 159 void FinalRelease(); 160 161 HRESULT updatePath(const char *aOldPath, const char *aNewPath); 162 163 HRESULT attachTo(const Guid &aMachineId, 164 const Guid &aSnapshotId = Guid::Empty); 165 HRESULT detachFrom(const Guid &aMachineId, 166 const Guid &aSnapshotId = Guid::Empty); 167 168 #ifdef DEBUG 169 void dumpBackRefs(); 170 #endif 159 const ComObjPtr<Medium>& getParent() const; 160 const MediaList& getChildren() const; 171 161 172 162 const Guid& getId() const; … … 176 166 uint64_t getSize() const; 177 167 168 HRESULT attachTo(const Guid &aMachineId, 169 const Guid &aSnapshotId = Guid::Empty); 170 HRESULT detachFrom(const Guid &aMachineId, 171 const Guid &aSnapshotId = Guid::Empty); 172 178 173 const Guid* getFirstMachineBackrefId() const; 179 174 const Guid* getFirstMachineBackrefSnapshotId() const; 180 175 181 /** 182 * Shortcut to VirtualBoxBaseWithTypedChildrenNEXT::dependentChildren().183 */ 184 const List& getChildren() const { return dependentChildren(); } 185 176 #ifdef DEBUG 177 void dumpBackRefs(); 178 #endif 179 180 HRESULT updatePath(const char *aOldPath, const char *aNewPath); 186 181 void updatePaths(const char *aOldPath, const char *aNewPath); 187 182 … … 258 253 // unsafe inline public methods for internal purposes only (ensure there is 259 254 // a caller and a read lock before calling them!) 260 261 ComObjPtr<Medium> getParent() const { return static_cast<Medium *>(mParent); }262 255 MediumType_T getType() const; 263 256 264 257 /** For com::SupportErrorInfoImpl. */ 265 258 static const char *ComponentName() { return "Medium"; } 266 267 protected:268 269 RWLockHandle* getTreeLock();270 271 /** Reimplements VirtualBoxWithTypedChildren::childrenLock() to return272 * treeLock(). */273 RWLockHandle *childrenLock() { return getTreeLock(); }274 259 275 260 private: … … 292 277 293 278 HRESULT setStateError(); 294 295 /** weak VirtualBox parent */296 const ComObjPtr<VirtualBox, ComWeakRef> mVirtualBox;297 279 298 280 HRESULT deleteStorage(ComObjPtr<Progress> *aProgress, bool aWait); … … 327 309 static DECLCALLBACK(int) taskThread(RTTHREAD thread, void *pvUser); 328 310 329 /** weak parent */330 ComObjPtr<Medium, ComWeakRef> mParent;331 332 311 struct Task; 333 312 friend struct Task; -
trunk/src/VBox/Main/include/SnapshotImpl.h
r24196 r25152 73 73 void beginDiscard(); 74 74 75 void deparent(); 76 75 77 // ISnapshot properties 76 78 STDMETHOD(COMGETTER(Id)) (BSTR *aId); … … 88 90 89 91 // public methods only for internal purposes 92 const ComObjPtr<Snapshot>& getParent() const; 90 93 91 94 const Utf8Str& stateFilePath() const; 92 93 ComObjPtr<Snapshot> parent() const94 {95 return (Snapshot*)mParent;96 }97 95 98 96 ULONG getChildrenCount(); … … 100 98 ULONG getAllChildrenCountImpl(); 101 99 102 ComPtr<SnapshotMachine> getSnapshotMachine();100 const ComObjPtr<SnapshotMachine>& getSnapshotMachine() const; 103 101 104 102 Guid getId() const; … … 124 122 125 123 private: 126 127 /** weak VirtualBox parent */128 const ComObjPtr<VirtualBox, ComWeakRef> mVirtualBox;129 130 ComObjPtr<Snapshot, ComWeakRef> mParent;131 132 124 struct Data; // opaque, defined in SnapshotImpl.cpp 133 125 Data *m; -
trunk/src/VBox/Main/include/VirtualBoxBase.h
r25150 r25152 1918 1918 //////////////////////////////////////////////////////////////////////////////// 1919 1919 1920 /**1921 * Base class to track component's children of the particular type.1922 *1923 * This class is similar to VirtualBoxBaseWithChildrenNEXT with the exception1924 * that all children must be of the same type. For this reason, it's not1925 * necessary to use a map to store children -- a list is used instead.1926 *1927 * Also, as opposed to VirtualBoxBaseWithChildren, children added by1928 * #addDependentChild() are <b>strongly</b> referenced, so that they cannot be1929 * deleted (even by a third party) until #removeDependentChild() is called on1930 * them. This also means that a failure to call #removeDependentChild() and1931 * #uninitDependentChildren() at appropriate times as described in1932 * VirtualBoxBaseWithChildrenNEXT may cause stuck references that won't be able1933 * uninitialize themselves.1934 *1935 * See individual method descriptions for further information.1936 *1937 * @param C Type of child objects (must inherit VirtualBoxBase AND implement1938 * some interface).1939 *1940 * @todo This is a VirtualBoxBaseWithChildren equivalent that uses the1941 * VirtualBoxBaseNEXT implementation. Will completely supersede1942 * VirtualBoxBaseWithChildren after the old VirtualBoxBase implementation1943 * has gone.1944 */1945 template<class C>1946 class VirtualBoxBaseWithTypedChildren : public VirtualBoxBase1947 {1948 public:1949 1950 typedef std::list<ComObjPtr<C> > DependentChildren;1951 1952 VirtualBoxBaseWithTypedChildren()1953 {}1954 1955 virtual ~VirtualBoxBaseWithTypedChildren()1956 {}1957 1958 /**1959 * Lock handle to use when adding/removing child objects from the list of1960 * children. It is guaranteed that no any other lock is requested in methods1961 * of this class while holding this lock.1962 *1963 * @warning By default, this simply returns the general object's lock handle1964 * (see VirtualBoxBase::lockHandle()) which is sufficient for most1965 * cases.1966 */1967 virtual RWLockHandle *childrenLock() { return lockHandle(); }1968 1969 /**1970 * Adds the given child to the list of dependent children.1971 *1972 * Usually gets called from the child's init() method.1973 *1974 * @note @a aChild (unless it is in InInit state) must be protected by1975 * VirtualBoxBase::AutoCaller to make sure it is not uninitialized on1976 * another thread during this method's call.1977 *1978 * @note When #childrenLock() is not overloaded (returns the general object1979 * lock) and this method is called from under the child's read or1980 * write lock, make sure the {parent, child} locking order is1981 * preserved by locking the callee (this object) for writing before1982 * the child's lock.1983 *1984 * @param aChild Child object to add.1985 *1986 * @note Locks #childrenLock() for writing.1987 */1988 void addDependentChild(C *aChild)1989 {1990 AssertReturnVoid(aChild != NULL);1991 1992 AutoCaller autoCaller(this);1993 1994 /* sanity */1995 AssertReturnVoid(autoCaller.state() == InInit ||1996 autoCaller.state() == Ready ||1997 autoCaller.state() == Limited);1998 1999 AutoWriteLock chLock(childrenLock());2000 mDependentChildren.push_back(aChild);2001 }2002 2003 /**2004 * Removes the given child from the list of dependent children.2005 *2006 * Usually gets called from the child's uninit() method.2007 *2008 * Keep in mind that the called (parent) object may be no longer available2009 * (i.e. may be deleted deleted) after this method returns, so you must not2010 * call any other parent's methods after that!2011 *2012 * @note @a aChild (unless it is in InUninit state) must be protected by2013 * VirtualBoxBase::AutoCaller to make sure it is not uninitialized on2014 * another thread during this method's call.2015 *2016 * @note When #childrenLock() is not overloaded (returns the general object2017 * lock) and this method is called from under the child's read or2018 * write lock, make sure the {parent, child} locking order is2019 * preserved by locking the callee (this object) for writing before2020 * the child's lock. This is irrelevant when the method is called from2021 * under this object's AutoUninitSpan (i.e. in InUninit state) since2022 * in this case no locking is done.2023 *2024 * @param aChild Child object to remove.2025 *2026 * @note Locks #childrenLock() for writing.2027 */2028 void removeDependentChild(C *aChild)2029 {2030 AssertReturnVoid(aChild);2031 2032 AutoCaller autoCaller(this);2033 2034 /* sanity */2035 AssertReturnVoid(autoCaller.state() == InUninit ||2036 autoCaller.state() == InInit ||2037 autoCaller.state() == Ready ||2038 autoCaller.state() == Limited);2039 2040 /* return shortly; we are strongly referenced so the object won't get2041 * deleted if it calls init() before uninitDependentChildren() does2042 * and therefore the list will still contain a valid reference that will2043 * be correctly processed by uninitDependentChildren() anyway */2044 if (autoCaller.state() == InUninit)2045 return;2046 2047 AutoWriteLock chLock(childrenLock());2048 mDependentChildren.remove(aChild);2049 }2050 2051 protected:2052 2053 /**2054 * Returns the read-only list of all dependent children.2055 *2056 * @note Access the returned list (iterate, get size etc.) only after making2057 * sure #childrenLock() is locked for reading or for writing!2058 */2059 const DependentChildren &dependentChildren() const { return mDependentChildren; }2060 2061 /**2062 * Uninitializes all dependent children registered on this object with2063 * #addDependentChild().2064 *2065 * Must be called from within the VirtualBoxBaseProto::AutoUninitSpan (i.e.2066 * typically from this object's uninit() method) to uninitialize children2067 * before this object goes out of service and becomes unusable.2068 *2069 * Note that this method will call uninit() methods of child objects. If2070 * these methods need to call the parent object during uninitialization,2071 * #uninitDependentChildren() must be called before the relevant part of the2072 * parent is uninitialized: usually at the beginning of the parent2073 * uninitialization sequence.2074 *2075 * @note May lock something through the called children.2076 */2077 void uninitDependentChildren()2078 {2079 AutoCaller autoCaller(this);2080 2081 /* We don't want to hold the childrenLock() write lock here (necessary2082 * to protect mDependentChildren) when uninitializing children because2083 * we want to avoid a possible deadlock where we could get stuck in2084 * child->uninit() blocked by AutoUninitSpan waiting for the number of2085 * child's callers to drop to zero (or for another AutoUninitSpan to2086 * finish), while some other thread is stuck in our2087 * removeDependentChild() method called for that child and waiting for2088 * the childrenLock()'s write lock.2089 *2090 * The only safe place to not lock and keep accessing our data members2091 * is the InUninit state (no active call to our object may exist on2092 * another thread when we are in InUinint, provided that all such calls2093 * use the AutoCaller class of course). InUinint is also used as a flag2094 * by removeDependentChild() that prevents touching mDependentChildren2095 * from outside. Therefore, we assert. Note that InInit is also fine2096 * since no any object may access us by that time.2097 */2098 AssertReturnVoid(autoCaller.state() == InUninit ||2099 autoCaller.state() == InInit);2100 2101 if (mDependentChildren.size())2102 {2103 for (typename DependentChildren::iterator it = mDependentChildren.begin();2104 it != mDependentChildren.end(); ++ it)2105 {2106 C *child = (*it);2107 Assert(child);2108 2109 /* Note that if child->uninit() happens to be called on another2110 * thread right before us and is not yet finished, the second2111 * uninit() call will wait until the first one has done so2112 * (thanks to AutoUninitSpan). */2113 if (child)2114 child->uninit();2115 }2116 2117 /* release all strong references we hold */2118 mDependentChildren.clear();2119 }2120 }2121 2122 /**2123 * Removes (detaches) all dependent children registered with2124 * #addDependentChild(), without uninitializing them.2125 *2126 * @note @a |this| (unless it is in InUninit state) must be protected by2127 * VirtualBoxBase::AutoCaller to make sure it is not uninitialized on2128 * another thread during this method's call.2129 *2130 * @note Locks #childrenLock() for writing.2131 */2132 void removeDependentChildren()2133 {2134 AutoWriteLock chLock(childrenLock());2135 mDependentChildren.clear();2136 }2137 2138 private:2139 2140 DependentChildren mDependentChildren;2141 };2142 2143 ////////////////////////////////////////////////////////////////////////////////2144 1920 2145 1921 /// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
Note:
See TracChangeset
for help on using the changeset viewer.