VirtualBox

Changeset 25152 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Dec 2, 2009 5:37:39 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
55574
Message:

Main: kill VirtualBoxBaseWithTypedChildren template and rework Medium to no longer use it; adjust Snapshot for consistency

Location:
trunk/src/VBox/Main
Files:
6 edited

Legend:

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

    r25151 r25152  
    26252625                }
    26262626
    2627                 snap = snap->parent();
     2627                snap = snap->getParent();
    26282628            }
    26292629
  • trunk/src/VBox/Main/MediumImpl.cpp

    r25149 r25152  
    106106    {}
    107107
     108    /** weak VirtualBox parent */
     109    const ComObjPtr<VirtualBox, ComWeakRef> pVirtualBox;
     110
    108111    const Guid id;
    109112    Utf8Str strDescription;
     
    113116    uint64_t size;
    114117    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
    115122
    116123    BackRefList backRefs;
     
    366373 *       Medium::getTreeLock() is held in read mode.
    367374 */
    368 class Medium::MergeChain : public Medium::List,
     375class Medium::MergeChain : public MediaList,
    369376                           public com::SupportErrorInfoBase
    370377{
     
    440447        {
    441448            /* we will need parent to reparent target */
    442             if (!aMedium->mParent.isNull())
     449            if (!aMedium->m->pParent.isNull())
    443450            {
    444                 rc = aMedium->mParent->addCaller();
     451                rc = aMedium->m->pParent->addCaller();
    445452                if (FAILED(rc)) return rc;
    446453
    447                 mParent = aMedium->mParent;
     454                mParent = aMedium->m->pParent;
    448455            }
    449456        }
     
    451458        {
    452459            /* we will need to reparent children */
    453             for (List::const_iterator it = aMedium->getChildren().begin();
     460            for (MediaList::const_iterator it = aMedium->getChildren().begin();
    454461                 it != aMedium->getChildren().end();
    455462                 ++it)
     
    535542    bool isForward() const { return mForward; }
    536543    Medium *parent() const { return mParent; }
    537     const List &children() const { return mChildren; }
     544    const MediaList& children() const { return mChildren; }
    538545
    539546    Medium *source() const
     
    606613    ComObjPtr <Medium> mParent;
    607614    /** Children of the source when backward merge (if any) */
    608     List mChildren;
     615    MediaList mChildren;
    609616};
    610617
     
    621628 *       Medium::getTreeLock() is held in read mode.
    622629 */
    623 class Medium::ImageChain : public Medium::List,
     630class Medium::ImageChain : public MediaList,
    624631                           public com::SupportErrorInfoBase
    625632{
     
    633640        if (begin() != end())
    634641        {
    635             List::const_iterator last = end();
     642            MediaList::const_iterator last = end();
    636643            last--;
    637             for (List::const_iterator it = begin(); it != end(); ++ it)
     644            for (MediaList::const_iterator it = begin(); it != end(); ++ it)
    638645            {
    639646                AutoWriteLock alock(*it);
     
    676683        ErrorInfoKeeper eik(true /* aIsNull */);
    677684        MultiResult mrc(S_OK);
    678         for (List::const_iterator it = begin(); it != end(); ++ it)
     685        for (MediaList::const_iterator it = begin(); it != end(); ++ it)
    679686        {
    680687            HRESULT rc = S_OK;
     
    729736        ErrorInfoKeeper eik(true /* aIsNull */);
    730737        MultiResult mrc(S_OK);
    731         List::const_iterator last = end();
     738        MediaList::const_iterator last = end();
    732739        last--;
    733         for (List::const_iterator it = begin(); it != end(); ++ it)
     740        for (MediaList::const_iterator it = begin(); it != end(); ++ it)
    734741        {
    735742            HRESULT rc = S_OK;
     
    887894
    888895    /* share VirtualBox weakly (parent remains NULL so far) */
    889     unconst(mVirtualBox) = aVirtualBox;
     896    unconst(m->pVirtualBox) = aVirtualBox;
    890897
    891898    /* register with VirtualBox early, since uninit() will
     
    929936        m->state = MediumState_Created;
    930937        unconst(m->id).create();
    931         rc = mVirtualBox->registerHardDisk(this);
     938        rc = m->pVirtualBox->registerHardDisk(this);
    932939
    933940        /// @todo later we may want to use a pfnIsConfigSufficient backend info
     
    986993
    987994    /* share VirtualBox weakly (parent remains NULL so far) */
    988     unconst(mVirtualBox) = aVirtualBox;
     995    unconst(m->pVirtualBox) = aVirtualBox;
    989996
    990997    /* register with VirtualBox early, since uninit() will
     
    10711078
    10721079    /* share VirtualBox and parent weakly */
    1073     unconst(mVirtualBox) = aVirtualBox;
     1080    unconst(m->pVirtualBox) = aVirtualBox;
    10741081
    10751082    /* register with VirtualBox/parent early, since uninit() will
    10761083     * unconditionally unregister on failure */
    10771084    if (aParent == NULL)
     1085        // base disk: add to global list
    10781086        aVirtualBox->addDependentChild(this);
    10791087    else
    10801088    {
    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);
    10861093    }
    10871094
     
    11451152    {
    11461153        /* type is only for base hard disks */
    1147         if (mParent.isNull())
     1154        if (m->pParent.isNull())
    11481155            m->type = data.hdType;
    11491156    }
     
    11791186        if (FAILED(rc)) break;
    11801187
    1181         rc = mVirtualBox->registerHardDisk(pHD, false /* aSaveRegistry */);
     1188        rc = m->pVirtualBox->registerHardDisk(pHD, false /* aSaveRegistry */);
    11821189        if (FAILED(rc)) break;
    11831190    }
     
    12181225
    12191226    /* share VirtualBox weakly (parent remains NULL so far) */
    1220     unconst(mVirtualBox) = aVirtualBox;
     1227    unconst(m->pVirtualBox) = aVirtualBox;
    12211228    aVirtualBox->addDependentChild(this);
    12221229
     
    12821289         * Reparenting has already been done so don't touch it here (we are
    12831290         * now orphans and remoeDependentChild() will assert) */
    1284 
    1285         Assert(mParent.isNull());
     1291        Assert(m->pParent.isNull());
    12861292    }
    12871293    else
     
    12891295        /* we uninit children and reset mParent
    12901296         * 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();
    12991315        }
    13001316        else
    1301             mVirtualBox->removeDependentChild(this);
     1317            // base image: remove it from the global list
     1318            m->pVirtualBox->removeDependentChild(this);
    13021319    }
    13031320
     
    13061323    m->queryInfoSem = NIL_RTSEMEVENTMULTI;
    13071324
    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 */
     1334void 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();
    13091349}
    13101350
     
    15021542
    15031543    /* VirtualBox::saveSettings() needs a write lock */
    1504     AutoMultiWriteLock2 alock(mVirtualBox, this);
     1544    AutoMultiWriteLock2 alock(m->pVirtualBox, this);
    15051545
    15061546    switch (m->state)
     
    15201560
    15211561    /* we access mParent & children() */
    1522     AutoReadLock treeLock(this->getTreeLock());
     1562    AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle());
    15231563
    15241564    /* cannot change the type of a differencing hard disk */
    1525     if (!mParent.isNull())
     1565    if (m->pParent)
    15261566        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"),
    15281568                        m->strLocationFull.raw());
    15291569
     
    15311571    if (m->backRefs.size() != 0)
    15321572        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"),
    15341574                        m->strLocationFull.raw(), m->backRefs.size());
    15351575
     
    15591599    m->type = aType;
    15601600
    1561     HRESULT rc = mVirtualBox->saveSettings();
     1601    HRESULT rc = m->pVirtualBox->saveSettings();
    15621602
    15631603    return rc;
     
    15731613
    15741614    /* we access mParent */
    1575     AutoReadLock treeLock(this->getTreeLock());
    1576 
    1577     mParent.queryInterfaceTo(aParent);
     1615    AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle());
     1616
     1617    m->pParent.queryInterfaceTo(aParent);
    15781618
    15791619    return S_OK;
     
    15891629
    15901630    /* we access children */
    1591     AutoReadLock treeLock(this->getTreeLock());
     1631    AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle());
    15921632
    15931633    SafeIfaceArray<IMedium> children(this->getChildren());
     
    16351675
    16361676        /* we access mParent */
    1637         AutoReadLock treeLock(this->getTreeLock());
    1638 
    1639         if (mParent.isNull())
     1677        AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle());
     1678
     1679        if (m->pParent.isNull())
    16401680        {
    16411681            *aLogicalSize = m->logicalSize;
     
    16631703    AutoReadLock alock(this);
    16641704
    1665     if (mParent.isNull())
     1705    if (m->pParent)
    16661706        *aAutoReset = FALSE;
    16671707
     
    16771717
    16781718    /* VirtualBox::saveSettings() needs a write lock */
    1679     AutoMultiWriteLock2 alock(mVirtualBox, this);
    1680 
    1681     if (mParent.isNull())
     1719    AutoMultiWriteLock2 alock(m->pVirtualBox, this);
     1720
     1721    if (m->pParent.isNull())
    16821722        return setError(VBOX_E_NOT_SUPPORTED,
    16831723                        tr("Hard disk '%s' is not differencing"),
     
    16881728        m->autoReset = aAutoReset;
    16891729
    1690         return mVirtualBox->saveSettings();
     1730        return m->pVirtualBox->saveSettings();
    16911731    }
    16921732
     
    20192059     * a mVirtualBox lock of course). */
    20202060
    2021     AutoWriteLock vboxLock(mVirtualBox);
     2061    AutoWriteLock vboxLock(m->pVirtualBox);
    20222062
    20232063    bool wasCreated = true;
     
    20902130
    20912131    /* VirtualBox::saveSettings() needs a write lock */
    2092     AutoMultiWriteLock2 alock(mVirtualBox, this);
     2132    AutoMultiWriteLock2 alock(m->pVirtualBox, this);
    20932133
    20942134    switch (m->state)
     
    21122152        it->second = aValue;
    21132153
    2114     HRESULT rc = mVirtualBox->saveSettings();
     2154    HRESULT rc = m->pVirtualBox->saveSettings();
    21152155
    21162156    return rc;
     
    21642204
    21652205    /* VirtualBox::saveSettings() needs a write lock */
    2166     AutoMultiWriteLock2 alock(mVirtualBox, this);
     2206    AutoMultiWriteLock2 alock(m->pVirtualBox, this);
    21672207
    21682208    com::SafeArray<IN_BSTR> names(ComSafeArrayInArg(aNames));
     
    21932233    }
    21942234
    2195     HRESULT rc = mVirtualBox->saveSettings();
     2235    HRESULT rc = m->pVirtualBox->saveSettings();
    21962236
    21972237    return rc;
     
    22322272    progress.createObject();
    22332273    /// @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 */);
    22392280    if (FAILED(rc)) return rc;
    22402281
     
    22932334
    22942335    ComObjPtr<Medium> diff;
    2295     HRESULT rc = mVirtualBox->cast(aTarget, diff);
     2336    HRESULT rc = m->pVirtualBox->cast(aTarget, diff);
    22962337    if (FAILED(rc)) return rc;
    22972338
     
    23462387
    23472388    ComObjPtr <Medium> target;
    2348     HRESULT rc = mVirtualBox->cast(aTarget, target);
     2389    HRESULT rc = m->pVirtualBox->cast(aTarget, target);
    23492390    if (FAILED(rc)) return rc;
    23502391    ComObjPtr <Medium> parent;
    23512392    if (aParent)
    23522393    {
    2353         rc = mVirtualBox->cast(aParent, parent);
     2394        rc = m->pVirtualBox->cast(aParent, parent);
    23542395        if (FAILED(rc)) return rc;
    23552396    }
     
    23732414
    23742415        /* 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)
    23772420        {
    23782421            rc = srcChain->addImage(hd);
     
    23852428        std::auto_ptr <ImageChain> parentChain(new ImageChain());
    23862429
    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)
    23922433        {
    23932434            rc = parentChain->addImage(hd);
     
    24102451
    24112452        progress.createObject();
    2412         rc = progress->init(mVirtualBox, 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 */);
    24162457        if (FAILED(rc)) throw rc;
    24172458
     
    24192460         * asynchronously */
    24202461
    2421         std::auto_ptr <Task> task(new Task(this, progress, Task::Clone));
     2462        std::auto_ptr<Task> task(new Task(this, progress, Task::Clone));
    24222463        AssertComRCThrowRC(task->m_autoCaller.rc());
    24232464
     
    24752516
    24762517        /* 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)
    24792522        {
    24802523            rc = imgChain->addImage(hd);
     
    24852528
    24862529        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 */);
    24902534        if (FAILED(rc)) throw rc;
    24912535
     
    25412585    LogFlowThisFunc(("ENTER for medium %s\n", m->strLocationFull.c_str()));
    25422586
    2543     if (mParent.isNull())
     2587    if (m->pParent.isNull())
    25442588        return setError(VBOX_E_NOT_SUPPORTED,
    25452589                        tr ("Hard disk '%s' is not differencing"),
     
    25572601    {
    25582602        progress.createObject();
    2559         rc = progress->init(mVirtualBox, 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 */);
    25632607        if (FAILED(rc)) throw rc;
    25642608
     
    26042648
    26052649/**
    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
    26132652 */
    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;
     2653const 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 */
     2662const 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 */
     2671const 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 */
     2680MediumState_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 */
     2689const 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 */
     2698const 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 */
     2707uint64_t Medium::getSize() const
     2708{
     2709    return m->size;
    26432710}
    26442711
     
    27752842}
    27762843
     2844/**
     2845 * Internal method to return the medium's list of backrefs. Must have caller + locking!
     2846 * @return
     2847 */
     2848const Guid* Medium::getFirstMachineBackrefId() const
     2849{
     2850    if (!m->backRefs.size())
     2851        return NULL;
     2852
     2853    return &m->backRefs.front().machineId;
     2854}
     2855
     2856const 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
    27772868#ifdef DEBUG
    27782869/**
     
    28062897
    28072898/**
    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.
    28102906 */
    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();
     2907HRESULT 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;
    28742936}
    28752937
     
    28952957
    28962958    /* we access children() */
    2897     AutoReadLock treeLock(this->getTreeLock());
     2959    AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle());
    28982960
    28992961    updatePath(aOldPath, aNewPath);
    29002962
    29012963    /* update paths of all children */
    2902     for (List::const_iterator it = getChildren().begin();
     2964    for (MediaList::const_iterator it = getChildren().begin();
    29032965         it != getChildren().end();
    29042966         ++ it)
     
    29292991
    29302992    /* we access mParent */
    2931     AutoReadLock treeLock(this->getTreeLock());
     2993    AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle());
    29322994
    29332995    pBase = this;
    29342996    level = 0;
    29352997
    2936     if (!mParent.isNull())
     2998    if (m->pParent)
    29372999    {
    29383000        for (;;)
     
    29413003            AssertReturn(baseCaller.isOk(), pBase);
    29423004
    2943             if (pBase->mParent.isNull())
     3005            if (pBase->m->pParent.isNull())
    29443006                break;
    29453007
    2946             pBase = pBase->mParent;
     3008            pBase = pBase->m->pParent;
    29473009            ++level;
    29483010        }
     
    29703032
    29713033    /* we access children */
    2972     AutoReadLock treeLock(this->getTreeLock());
     3034    AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle());
    29733035
    29743036    switch (m->type)
     
    30173079
    30183080    /* we access mParent */
    3019     AutoReadLock treeLock(this->getTreeLock());
     3081    AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle());
    30203082
    30213083    data.uuid = m->id;
     
    30243086
    30253087    /* optional, only for diffs, default is false */
    3026     if (!mParent.isNull())
     3088    if (m->pParent)
    30273089        data.fAutoReset = !!m->autoReset;
    30283090    else
     
    30483110
    30493111    /* only for base hard disks */
    3050     if (mParent.isNull())
     3112    if (m->pParent.isNull())
    30513113        data.hdType = m->type;
    30523114
    30533115    /* save all children */
    3054     for (List::const_iterator it = getChildren().begin();
     3116    for (MediaList::const_iterator it = getChildren().begin();
    30553117         it != getChildren().end();
    30563118         ++it)
     
    30973159        {
    30983160            location = Utf8StrFmt("%s%c%s",
    3099                                   mVirtualBox->getDefaultHardDiskFolder().raw(),
     3161                                  m->pVirtualBox->getDefaultHardDiskFolder().raw(),
    31003162                                  RTPATH_DELIMITER,
    31013163                                  aLocation);
    31023164        }
    31033165
    3104         int vrc = mVirtualBox->calculateFullPath(location, location);
     3166        int vrc = m->pVirtualBox->calculateFullPath(location, location);
    31053167        if (RT_FAILURE(vrc))
    31063168            return setError(E_FAIL,
     
    31443206
    31453207    /* we access mParent & children() */
    3146     AutoReadLock treeLock(this->getTreeLock());
     3208    AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle());
    31473209
    31483210    AssertReturn(m->type == MediumType_Normal, E_FAIL);
     
    31523214        /* special treatment of the last hard disk in the chain: */
    31533215
    3154         if (mParent.isNull())
     3216        if (m->pParent.isNull())
    31553217        {
    31563218            /* lock only, to prevent any usage; discard() will unlock */
     
    31973259
    31983260    /* delegate the rest to the profi */
    3199     if (mParent.isNull())
     3261    if (m->pParent.isNull())
    32003262    {
    32013263        /* base hard disk, backward merge */
    3202 
    32033264        Assert(child->m->backRefs.size() == 1);
    32043265        if (child->m->backRefs.front().machineId != m->backRefs.front().machineId)
     
    32823343
    32833344            /* we access mParent & children() */
    3284             AutoReadLock treeLock(this->getTreeLock());
     3345            AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle());
    32853346
    32863347            Assert(getChildren().size() == 0);
     
    32883349            /* special treatment of the last hard disk in the chain: */
    32893350
    3290             if (mParent.isNull())
     3351            if (m->pParent.isNull())
    32913352            {
    32923353                rc = UnlockWrite(NULL);
     
    33503411
    33513412        /* we access mParent & children() */
    3352         AutoReadLock treeLock(this->getTreeLock());
     3413        AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle());
    33533414
    33543415        Assert(getChildren().size() == 0);
     
    33563417        /* special treatment of the last hard disk in the chain: */
    33573418
    3358         if (mParent.isNull())
     3419        if (m->pParent.isNull())
    33593420        {
    33603421            HRESULT rc = UnlockWrite(NULL);
     
    33933454    {
    33943455        /* use the default format if not */
    3395         AutoReadLock propsLock(mVirtualBox->systemProperties());
    3396         strFormat = mVirtualBox->getDefaultHardDiskFormat();
     3456        AutoReadLock propsLock(m->pVirtualBox->systemProperties());
     3457        strFormat = m->pVirtualBox->getDefaultHardDiskFormat();
    33973458    }
    33983459
     
    34073468{
    34083469    return m->type;
    3409 }
    3410 
    3411 /**
    3412  * Returns VirtualBox::hardDiskTreeHandle(), for convenience. Don't forget
    3413  * to follow these locking rules:
    3414  *
    3415  * 1. The write lock on this handle must be either held alone on the thread
    3416  *    or requested *after* the VirtualBox object lock. Mixing with other
    3417  *    locks is prohibited.
    3418  *
    3419  * 2. The read lock on this handle may be intermixed with any other lock
    3420  *    with the exception that it must be requested *after* the VirtualBox
    3421  *    object lock.
    3422  */
    3423 RWLockHandle* Medium::getTreeLock()
    3424 {
    3425     return &mVirtualBox->hardDiskTreeLockHandle();
    34263470}
    34273471
     
    35203564        if (!RTPathHavePath(location.c_str()))
    35213565            location = Utf8StrFmt("%s%c%s",
    3522                                   mVirtualBox->getDefaultHardDiskFolder().raw(),
     3566                                  m->pVirtualBox->getDefaultHardDiskFolder().raw(),
    35233567                                  RTPATH_DELIMITER,
    35243568                                  location.raw());
     
    35263570        /* get the full file name */
    35273571        Utf8Str locationFull;
    3528         int vrc = mVirtualBox->calculateFullPath(location, locationFull);
     3572        int vrc = m->pVirtualBox->calculateFullPath(location, locationFull);
    35293573        if (RT_FAILURE(vrc))
    35303574            return setError(VBOX_E_FILE_ERROR,
     
    37783822                            location.c_str(),
    37793823                            mediumId.raw(),
    3780                             mVirtualBox->settingsFilePath().c_str());
     3824                            m->pVirtualBox->settingsFilePath().c_str());
    37813825                        throw S_OK;
    37823826                    }
     
    38203864                    Guid id = parentId;
    38213865                    ComObjPtr<Medium> parent;
    3822                     rc = mVirtualBox->findHardDisk(&id, NULL,
     3866                    rc = m->pVirtualBox->findHardDisk(&id, NULL,
    38233867                                                   false /* aSetError */,
    38243868                                                   &parent);
     
    38283872                            tr("Parent hard disk with UUID {%RTuuid} of the hard disk '%s' is not found in the media registry ('%s')"),
    38293873                            &parentId, location.c_str(),
    3830                             mVirtualBox->settingsFilePath().c_str());
     3874                            m->pVirtualBox->settingsFilePath().c_str());
    38313875                        throw S_OK;
    38323876                    }
     
    38343878                    /* deassociate from VirtualBox, associate with parent */
    38353879
    3836                     mVirtualBox->removeDependentChild(this);
     3880                    m->pVirtualBox->removeDependentChild(this);
    38373881
    38383882                    /* we set mParent & children() */
    3839                     AutoWriteLock treeLock(this->getTreeLock());
    3840 
    3841                     Assert(mParent.isNull());
    3842                     mParent = parent;
    3843                     mParent->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);
    38443888                }
    38453889                else
    38463890                {
    38473891                    /* we access mParent */
    3848                     AutoReadLock treeLock(this->getTreeLock());
     3892                    AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle());
    38493893
    38503894                    /* check that parent UUIDs match. Note that there's no need
     
    38523896                     * it) */
    38533897
    3854                     if (mParent.isNull())
     3898                    if (m->pParent.isNull())
    38553899                    {
    38563900                        lastAccessError = Utf8StrFmt(
    38573901                            tr("Hard disk '%s' is differencing but it is not associated with any parent hard disk in the media registry ('%s')"),
    38583902                            location.c_str(),
    3859                             mVirtualBox->settingsFilePath().c_str());
     3903                            m->pVirtualBox->settingsFilePath().c_str());
    38603904                        throw S_OK;
    38613905                    }
    38623906
    3863                     AutoReadLock parentLock(mParent);
    3864                     if (    mParent->getState() != MediumState_Inaccessible
    3865                          && mParent->getId() != parentId)
     3907                    AutoReadLock parentLock(m->pParent);
     3908                    if (    m->pParent->getState() != MediumState_Inaccessible
     3909                         && m->pParent->getId() != parentId)
    38663910                    {
    38673911                        lastAccessError = Utf8StrFmt(
    3868                             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')"),
     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')"),
    38693913                            &parentId, location.c_str(),
    3870                             mParent->getId().raw(),
    3871                             mVirtualBox->settingsFilePath().c_str());
     3914                            m->pParent->getId().raw(),
     3915                            m->pVirtualBox->settingsFilePath().c_str());
    38723916                        throw S_OK;
    38733917                    }
     
    40434087     * it holds a mVirtualBox lock too of course). */
    40444088
    4045     AutoMultiWriteLock2 alock(mVirtualBox->lockHandle(), this->lockHandle());
     4089    AutoMultiWriteLock2 alock(m->pVirtualBox->lockHandle(), this->lockHandle());
    40464090    LogFlowThisFunc(("aWait=%RTbool locationFull=%s\n", aWait, getLocationFull().c_str() ));
    40474091
     
    41254169        {
    41264170            progress.createObject();
    4127             rc = progress->init(mVirtualBox, 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 */);
    41314175            if (FAILED(rc)) return rc;
    41324176        }
     
    42634307        {
    42644308            progress.createObject();
    4265             rc = progress->init(mVirtualBox, 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 */);
    42694313            if (FAILED(rc)) return rc;
    42704314        }
     
    43504394
    43514395    /* we walk the tree */
    4352     AutoReadLock treeLock(this->getTreeLock());
     4396    AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle());
    43534397
    43544398    HRESULT rc = S_OK;
     
    43574401    bool forward;
    43584402    {
    4359         Medium *parent = mParent;
     4403        Medium *parent = m->pParent;
    43604404        while (parent != NULL && parent != aTarget)
    4361             parent = parent->mParent;
     4405            parent = parent->m->pParent;
    43624406        if (parent == aTarget)
    43634407            forward = false;
    43644408        else
    43654409        {
    4366             parent = aTarget->mParent;
     4410            parent = aTarget->m->pParent;
    43674411            while (parent != NULL && parent != this)
    4368                 parent = parent->mParent;
     4412                parent = parent->m->pParent;
    43694413            if (parent == this)
    43704414                forward = true;
     
    44054449                break;
    44064450
    4407             last = last->mParent;
     4451            last = last->m->pParent;
    44084452        }
    44094453    }
     
    45094553
    45104554            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 */);
    45164561            if (FAILED(rc)) return rc;
    45174562        }
     
    45854630    /* get the format object first */
    45864631    {
    4587         AutoReadLock propsLock(mVirtualBox->systemProperties());
     4632        AutoReadLock propsLock(m->pVirtualBox->systemProperties());
    45884633
    45894634        unconst(m->formatObj)
    4590             = mVirtualBox->systemProperties()->mediumFormat(aFormat);
     4635            = m->pVirtualBox->systemProperties()->mediumFormat(aFormat);
    45914636        if (m->formatObj.isNull())
    45924637            return setError(E_INVALIDARG,
     
    46294674{
    46304675    /* we access children */
    4631     AutoReadLock treeLock(this->getTreeLock());
     4676    AutoReadLock treeLock(m->pVirtualBox->hardDiskTreeLockHandle());
    46324677
    46334678    if (getChildren().size() != 0)
     
    46514696
    46524697    /* 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;
    46564701
    46574702    AssertReturn(getChildren().size() == 0, E_FAIL);
    46584703
    4659     if (!mParent.isNull())
     4704    if (m->pParent)
    46604705    {
    46614706        /* 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();
    46654709    }
    46664710
     
    46694713    {
    46704714        case DeviceType_DVD:
    4671             rc = mVirtualBox->unregisterDVDImage(this);
     4715            rc = m->pVirtualBox->unregisterDVDImage(this);
    46724716            break;
    46734717        case DeviceType_Floppy:
    4674             rc = mVirtualBox->unregisterFloppyImage(this);
     4718            rc = m->pVirtualBox->unregisterFloppyImage(this);
    46754719            break;
    46764720        case DeviceType_HardDisk:
    4677             rc = mVirtualBox->unregisterHardDisk(this);
     4721            rc = m->pVirtualBox->unregisterHardDisk(this);
    46784722            break;
    46794723        default:
     
    46834727    if (FAILED(rc))
    46844728    {
    4685         if (!parent.isNull())
     4729        if (pParentBackup)
    46864730        {
    46874731            /* re-associate with the parent as we are still relatives in the
    46884732             * registry */
    4689             mParent = parent;
    4690             mParent->addDependentChild(this);
    4691             mVirtualBox->removeDependentChild(this);
     4733            m->pParent = pParentBackup;
     4734            m->pParent->m->llChildren.push_back(this);
     4735            m->pVirtualBox->removeDependentChild(this);
    46924736        }
    46934737    }
     
    49725016                 * Created state only on success (leaving an orphan file is
    49735017                 * better than breaking media registry consistency) */
    4974                 rc = that->mVirtualBox->registerHardDisk(that);
     5018                rc = that->m->pVirtualBox->registerHardDisk(that);
    49755019            }
    49765020
     
    50905134                /* we set mParent & children() (note that thatLock is released
    50915135                 * here), but lock VirtualBox first to follow the rule */
    5092                 AutoMultiWriteLock2 alock(that->mVirtualBox->lockHandle(),
    5093                                           that->getTreeLock());
    5094 
    5095                 Assert(target->mParent.isNull());
     5136                AutoWriteLock alock1(that->m->pVirtualBox);
     5137                AutoWriteLock alock2(that->m->pVirtualBox->hardDiskTreeLockHandle());
     5138
     5139                Assert(target->m->pParent.isNull());
    50965140
    50975141                /* associate the child with the parent and deassociate from
    50985142                 * VirtualBox */
    5099                 target->mParent = that;
    5100                 that->addDependentChild(target);
    5101                 target->mVirtualBox->removeDependentChild(target);
     5143                target->m->pParent = that;
     5144                that->m->llChildren.push_back(target);
     5145                target->m->pVirtualBox->removeDependentChild(target);
    51025146
    51035147                /** @todo r=klaus neither target nor that->base() are locked,
     
    51115155                 * Created state only on success (leaving an orphan file is
    51125156                 * better than breaking media registry consistency) */
    5113                 rc = that->mVirtualBox->registerHardDisk(target);
     5157                rc = that->m->pVirtualBox->registerHardDisk(target);
    51145158
    51155159                if (FAILED(rc))
    51165160                {
    51175161                    /* 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();
    51215164                }
    51225165            }
     
    52585301                        if (chain->children().size() > 0)
    52595302                        {
    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)
    52625306                            {
    52635307                                /* VD_OPEN_FLAGS_INFO since UUID is wrong yet */
     
    53065350                /* we set mParent & children() (note that thatLock is released
    53075351                 * here), but lock VirtualBox first to follow the rule */
    5308                 AutoMultiWriteLock2 alock(that->mVirtualBox->lockHandle(),
    5309                                           that->getTreeLock());
     5352                AutoWriteLock alock1(that->m->pVirtualBox);
     5353                AutoWriteLock alock2(that->m->pVirtualBox->hardDiskTreeLockHandle());
    53105354
    53115355                Medium *source = chain->source();
     
    53165360                    /* first, unregister the target since it may become a base
    53175361                     * hard disk which needs re-registration */
    5318                     rc2 = target->mVirtualBox->
    5319                         unregisterHardDisk(target, false /* aSaveSettings */);
     5362                    rc2 = target->m->pVirtualBox->unregisterHardDisk(target, false /* aSaveSettings */);
    53205363                    AssertComRC(rc2);
    53215364
    53225365                    /* then, reparent it and disconnect the deleted branch at
    53235366                     * both ends (chain->parent() is source's parent) */
    5324                     target->mParent->removeDependentChild(target);
    5325                     target->mParent = chain->parent();
    5326                     if (!target->mParent.isNull())
     5367                    target->deparent();
     5368                    target->m->pParent = chain->parent();
     5369                    if (target->m->pParent)
    53275370                    {
    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();
    53315373                    }
    53325374                    else
    53335375                    {
    5334                         target->mVirtualBox->addDependentChild(target);
    5335                         target->mVirtualBox->removeDependentChild(source);
     5376                        target->m->pVirtualBox->addDependentChild(target);
     5377                        target->m->pVirtualBox->removeDependentChild(source);
    53365378                    }
    53375379
    53385380                    /* then, register again */
    5339                     rc2 = target->mVirtualBox->
     5381                    rc2 = target->m->pVirtualBox->
    53405382                        registerHardDisk(target, false /* aSaveSettings */);
    53415383                    AssertComRC(rc2);
     
    53475389
    53485390                    /* 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();
    53535394
    53545395                    /* reparent source's chidren and disconnect the deleted
     
    53595400                        AutoWriteLock sourceLock(source);
    53605401
    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)
    53635405                        {
    53645406                            AutoWriteLock childLock(*it);
    53655407
    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;
    53695412                        }
    53705413                    }
     
    53725415
    53735416                /* try to save the hard disk registry */
    5374                 rc = that->mVirtualBox->saveSettings();
     5417                rc = that->m->pVirtualBox->saveSettings();
    53755418
    53765419                if (SUCCEEDED(rc))
     
    53885431                        }
    53895432
    5390                         rc2 = (*it)->mVirtualBox->
     5433                        rc2 = (*it)->m->pVirtualBox->
    53915434                            unregisterHardDisk(*it, false /* aSaveSettings */);
    53925435                        AssertComRC(rc2);
     
    54955538                {
    54965539                    /* 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)
    54995543                    {
    55005544                        /* sanity check */
     
    55375581                    {
    55385582                        /* 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)
    55415586                        {
    55425587                            /** @todo r=klaus (*it) is not locked, lots of
     
    55945639                    /* we set mParent & children() (note that thatLock is released
    55955640                     * here), but lock VirtualBox first to follow the rule */
    5596                     AutoMultiWriteLock2 alock(that->mVirtualBox->lockHandle(),
    5597                                                that->getTreeLock());
    5598 
    5599                     Assert(target->mParent.isNull());
     5641                    AutoWriteLock alock1(that->m->pVirtualBox);
     5642                    AutoWriteLock alock2(that->m->pVirtualBox->hardDiskTreeLockHandle());
     5643
     5644                    Assert(target->m->pParent.isNull());
    56005645
    56015646                    if (parent)
     
    56035648                        /* associate the clone with the parent and deassociate
    56045649                         * from VirtualBox */
    5605                         target->mParent = parent;
    5606                         parent->addDependentChild(target);
    5607                         target->mVirtualBox->removeDependentChild(target);
     5650                        target->m->pParent = parent;
     5651                        parent->m->llChildren.push_back(target);
     5652                        target->m->pVirtualBox->removeDependentChild(target);
    56085653
    56095654                        /* register with mVirtualBox as the last step and move to
    56105655                         * Created state only on success (leaving an orphan file is
    56115656                         * better than breaking media registry consistency) */
    5612                         rc = parent->mVirtualBox->registerHardDisk(target);
     5657                        rc = parent->m->pVirtualBox->registerHardDisk(target);
    56135658
    56145659                        if (FAILED(rc))
    56155660                        {
    56165661                            /* 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
    56205664                        }
    56215665                    }
     
    56235667                    {
    56245668                        /* just register  */
    5625                         rc = that->mVirtualBox->registerHardDisk(target);
     5669                        rc = that->m->pVirtualBox->registerHardDisk(target);
    56265670                    }
    56275671                }
     
    57395783                Utf8Str location(that->m->strLocationFull);
    57405784
    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);
    57445789
    57455790                Assert(that->m->state == MediumState_LockedWrite);
     
    58375882                {
    58385883                    /* Open all hard disk images in the chain. */
    5839                     List::const_iterator last = imgChain->end();
     5884                    MediaList::const_iterator last = imgChain->end();
    58405885                    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)
    58435889                    {
    58445890                        /* sanity check */
  • trunk/src/VBox/Main/SnapshotImpl.cpp

    r25151 r25152  
    8787    ComObjPtr<SnapshotMachine>  pMachine;
    8888
    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;
    9095};
    9196
     
    137142
    138143    /* share parent weakly */
    139     unconst(mVirtualBox) = aVirtualBox;
    140 
    141     mParent = aParent;
     144    unconst(m->pVirtualBox) = aVirtualBox;
     145
     146    m->pParent = aParent;
    142147
    143148    m->uuid = aId;
     
    177182    {
    178183        Snapshot *pChild = *it;
    179         pChild->mParent.setNull();
     184        pChild->m->pParent.setNull();
    180185        pChild->uninit();
    181186    }
    182187    m->llChildren.clear();          // this unsets all the ComPtrs and probably calls delete
    183188
    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();
    201191
    202192    if (m->pMachine)
     
    231221    AssertReturnVoid(m->llChildren.size() <= 1);
    232222
    233     ComObjPtr<Snapshot> parentSnapshot = parent();
     223    ComObjPtr<Snapshot> parentSnapshot = m->pParent;
    234224
    235225    /// @todo (dmik):
     
    268258        AutoWriteLock childLock(child);
    269259
    270         child->mParent = mParent;
    271         if (mParent)
    272             mParent->m->llChildren.push_back(child);
     260        child->m->pParent = m->pParent;
     261        if (m->pParent)
     262            m->pParent->m->llChildren.push_back(child);
    273263    }
    274264
    275265    // clear our own children list (since we reparented the children)
    276266    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 */
     275void 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();
    277291}
    278292
     
    420434    AutoReadLock alock(this);
    421435
    422     mParent.queryInterfaceTo(aParent);
     436    m->pParent.queryInterfaceTo(aParent);
    423437    return S_OK;
    424438}
     
    447461
    448462/**
     463 * Returns the parent snapshot or NULL if there's none.  Must have caller + locking!
     464 * @return
     465 */
     466const ComObjPtr<Snapshot>& Snapshot::getParent() const
     467{
     468    return m->pParent;
     469}
     470
     471/**
    449472 *  @note
    450473 *      Must be called from under the object's lock!
     
    509532 * @return
    510533 */
    511 ComPtr<SnapshotMachine> Snapshot::getSnapshotMachine()
    512 {
    513     return (SnapshotMachine*)m->pMachine;
     534const ComObjPtr<SnapshotMachine>& Snapshot::getSnapshotMachine() const
     535{
     536    return m->pMachine;
    514537}
    515538
     
    15221545
    15231546    ComObjPtr<Snapshot> pSnapshot(static_cast<Snapshot*>(aSnapshot));
    1524     ComPtr<SnapshotMachine> pSnapMachine = pSnapshot->getSnapshotMachine();
     1547    ComObjPtr<SnapshotMachine> pSnapMachine = pSnapshot->getSnapshotMachine();
    15251548
    15261549    // create a progress object. The number of operations is:
     
    19611984    }
    19621985
    1963     ComPtr<SnapshotMachine> pSnapMachine = pSnapshot->getSnapshotMachine();
     1986    ComObjPtr<SnapshotMachine> pSnapMachine = pSnapshot->getSnapshotMachine();
    19641987
    19651988    /* create a progress object. The number of operations is:
     
    21102133                              aTask.pSnapshot->lockHandle());
    21112134
    2112     ComPtr<SnapshotMachine> pSnapMachine = aTask.pSnapshot->getSnapshotMachine();
     2135    ComObjPtr<SnapshotMachine> pSnapMachine = aTask.pSnapshot->getSnapshotMachine();
    21132136    /* no need to lock the snapshot machine since it is const by definiton */
    21142137
     
    22472270
    22482271        {
    2249             ComObjPtr<Snapshot> parentSnapshot = aTask.pSnapshot->parent();
     2272            ComObjPtr<Snapshot> parentSnapshot = aTask.pSnapshot->getParent();
    22502273            Utf8Str stateFilePath = aTask.pSnapshot->stateFilePath();
    22512274
  • trunk/src/VBox/Main/include/MediumImpl.h

    r25151 r25152  
    4646 */
    4747class ATL_NO_VTABLE Medium :
    48     public VirtualBoxBaseWithTypedChildren<Medium>,
     48    public VirtualBoxBase,
    4949    public com::SupportErrorInfoImpl<Medium, IMedium>,
    5050    public VirtualBoxSupportTranslation<Medium>,
     
    5252{
    5353public:
    54 
    55     typedef VirtualBoxBaseWithTypedChildren<Medium>::DependentChildren List;
    56 
    5754    class MergeChain;
    5855    class ImageChain;
     
    7067
    7168    DECLARE_EMPTY_CTOR_DTOR(Medium)
     69
     70    HRESULT FinalConstruct();
     71    void FinalRelease();
    7272
    7373    enum HDDOpenMode  { OpenReadWrite, OpenReadOnly };
     
    9999                 CBSTR aDescription = NULL);
    100100    void uninit();
     101
     102    void deparent();
    101103
    102104    // IMedium properties
     
    155157
    156158    // 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;
    171161
    172162    const Guid& getId() const;
     
    176166    uint64_t getSize() const;
    177167
     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
    178173    const Guid* getFirstMachineBackrefId() const;
    179174    const Guid* getFirstMachineBackrefSnapshotId() const;
    180175
    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);
    186181    void updatePaths(const char *aOldPath, const char *aNewPath);
    187182
     
    258253    // unsafe inline public methods for internal purposes only (ensure there is
    259254    // a caller and a read lock before calling them!)
    260 
    261     ComObjPtr<Medium> getParent() const { return static_cast<Medium *>(mParent); }
    262255    MediumType_T getType() const;
    263256
    264257    /** For com::SupportErrorInfoImpl. */
    265258    static const char *ComponentName() { return "Medium"; }
    266 
    267 protected:
    268 
    269     RWLockHandle* getTreeLock();
    270 
    271     /** Reimplements VirtualBoxWithTypedChildren::childrenLock() to return
    272      *  treeLock(). */
    273     RWLockHandle *childrenLock() { return getTreeLock(); }
    274259
    275260private:
     
    292277
    293278    HRESULT setStateError();
    294 
    295     /** weak VirtualBox parent */
    296     const ComObjPtr<VirtualBox, ComWeakRef> mVirtualBox;
    297279
    298280    HRESULT deleteStorage(ComObjPtr<Progress> *aProgress, bool aWait);
     
    327309    static DECLCALLBACK(int) taskThread(RTTHREAD thread, void *pvUser);
    328310
    329     /** weak parent */
    330     ComObjPtr<Medium, ComWeakRef> mParent;
    331 
    332311    struct Task;
    333312    friend struct Task;
  • trunk/src/VBox/Main/include/SnapshotImpl.h

    r24196 r25152  
    7373    void beginDiscard();
    7474
     75    void deparent();
     76
    7577    // ISnapshot properties
    7678    STDMETHOD(COMGETTER(Id)) (BSTR *aId);
     
    8890
    8991    // public methods only for internal purposes
     92    const ComObjPtr<Snapshot>& getParent() const;
    9093
    9194    const Utf8Str& stateFilePath() const;
    92 
    93     ComObjPtr<Snapshot> parent() const
    94     {
    95         return (Snapshot*)mParent;
    96     }
    9795
    9896    ULONG getChildrenCount();
     
    10098    ULONG getAllChildrenCountImpl();
    10199
    102     ComPtr<SnapshotMachine> getSnapshotMachine();
     100    const ComObjPtr<SnapshotMachine>& getSnapshotMachine() const;
    103101
    104102    Guid getId() const;
     
    124122
    125123private:
    126 
    127     /** weak VirtualBox parent */
    128     const ComObjPtr<VirtualBox, ComWeakRef> mVirtualBox;
    129 
    130     ComObjPtr<Snapshot, ComWeakRef> mParent;
    131 
    132124    struct Data;            // opaque, defined in SnapshotImpl.cpp
    133125    Data *m;
  • trunk/src/VBox/Main/include/VirtualBoxBase.h

    r25150 r25152  
    19181918////////////////////////////////////////////////////////////////////////////////
    19191919
    1920 /**
    1921  * Base class to track component's children of the particular type.
    1922  *
    1923  * This class is similar to VirtualBoxBaseWithChildrenNEXT with the exception
    1924  * that all children must be of the same type. For this reason, it's not
    1925  * necessary to use a map to store children -- a list is used instead.
    1926  *
    1927  * Also, as opposed to VirtualBoxBaseWithChildren, children added by
    1928  * #addDependentChild() are <b>strongly</b> referenced, so that they cannot be
    1929  * deleted (even by a third party) until #removeDependentChild() is called on
    1930  * them. This also means that a failure to call #removeDependentChild() and
    1931  * #uninitDependentChildren() at appropriate times as described in
    1932  * VirtualBoxBaseWithChildrenNEXT may cause stuck references that won't be able
    1933  * uninitialize themselves.
    1934  *
    1935  * See individual method descriptions for further information.
    1936  *
    1937  * @param C Type of child objects (must inherit VirtualBoxBase AND implement
    1938  *          some interface).
    1939  *
    1940  * @todo This is a VirtualBoxBaseWithChildren equivalent that uses the
    1941  *       VirtualBoxBaseNEXT implementation. Will completely supersede
    1942  *       VirtualBoxBaseWithChildren after the old VirtualBoxBase implementation
    1943  *       has gone.
    1944  */
    1945 template<class C>
    1946 class VirtualBoxBaseWithTypedChildren : public VirtualBoxBase
    1947 {
    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 of
    1960      * children. It is guaranteed that no any other lock is requested in methods
    1961      * of this class while holding this lock.
    1962      *
    1963      * @warning By default, this simply returns the general object's lock handle
    1964      *          (see VirtualBoxBase::lockHandle()) which is sufficient for most
    1965      *          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 by
    1975      *       VirtualBoxBase::AutoCaller to make sure it is not uninitialized on
    1976      *       another thread during this method's call.
    1977      *
    1978      * @note When #childrenLock() is not overloaded (returns the general object
    1979      *       lock) and this method is called from under the child's read or
    1980      *       write lock, make sure the {parent, child} locking order is
    1981      *       preserved by locking the callee (this object) for writing before
    1982      *       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 available
    2009      * (i.e. may be deleted deleted) after this method returns, so you must not
    2010      * call any other parent's methods after that!
    2011      *
    2012      * @note @a aChild (unless it is in InUninit state) must be protected by
    2013      *       VirtualBoxBase::AutoCaller to make sure it is not uninitialized on
    2014      *       another thread during this method's call.
    2015      *
    2016      * @note When #childrenLock() is not overloaded (returns the general object
    2017      *       lock) and this method is called from under the child's read or
    2018      *       write lock, make sure the {parent, child} locking order is
    2019      *       preserved by locking the callee (this object) for writing before
    2020      *       the child's lock. This is irrelevant when the method is called from
    2021      *       under this object's AutoUninitSpan (i.e. in InUninit state) since
    2022      *       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 get
    2041          * deleted if it calls init() before uninitDependentChildren() does
    2042          * and therefore the list will still contain a valid reference that will
    2043          * 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 making
    2057      *       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 with
    2063      * #addDependentChild().
    2064      *
    2065      * Must be called from within the VirtualBoxBaseProto::AutoUninitSpan (i.e.
    2066      * typically from this object's uninit() method) to uninitialize children
    2067      * before this object goes out of service and becomes unusable.
    2068      *
    2069      * Note that this method will call uninit() methods of child objects. If
    2070      * these methods need to call the parent object during uninitialization,
    2071      * #uninitDependentChildren() must be called before the relevant part of the
    2072      * parent is uninitialized: usually at the beginning of the parent
    2073      * 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 (necessary
    2082          * to protect mDependentChildren) when uninitializing children because
    2083          * we want to avoid a possible deadlock where we could get stuck in
    2084          * child->uninit() blocked by AutoUninitSpan waiting for the number of
    2085          * child's callers to drop to zero (or for another AutoUninitSpan to
    2086          * finish), while some other thread is stuck in our
    2087          * removeDependentChild() method called for that child and waiting for
    2088          * the childrenLock()'s write lock.
    2089          *
    2090          * The only safe place to not lock and keep accessing our data members
    2091          * is the InUninit state (no active call to our object may exist on
    2092          * another thread when we are in InUinint, provided that all such calls
    2093          * use the AutoCaller class of course). InUinint is also used as a flag
    2094          * by removeDependentChild() that prevents touching mDependentChildren
    2095          * from outside. Therefore, we assert. Note that InInit is also fine
    2096          * 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 another
    2110                  * thread right before us and is not yet finished, the second
    2111                  * uninit() call will wait until the first one has done so
    2112                  * (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 with
    2124      * #addDependentChild(), without uninitializing them.
    2125      *
    2126      * @note @a |this| (unless it is in InUninit state) must be protected by
    2127      *       VirtualBoxBase::AutoCaller to make sure it is not uninitialized on
    2128      *       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 ////////////////////////////////////////////////////////////////////////////////
    21441920
    21451921/// @todo (dmik) remove after we switch to VirtualBoxBaseNEXT completely
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette