VirtualBox

Changeset 40432 in vbox for trunk


Ignore:
Timestamp:
Mar 12, 2012 4:04:28 PM (13 years ago)
Author:
vboxsync
Message:

Main/VirtualBox+Machine+Medium: redesign the medium registry save logic, as the local lists in the threads caused inconsistencies with concurrent operations and the return of spurious errors

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/MachineImpl.h

    r40418 r40432  
    841841    HRESULT saveStateSettings(int aFlags);
    842842
    843     void addMediumToRegistry(ComObjPtr<Medium> &pMedium,
    844                              GuidList &llRegistriesThatNeedSaving,
    845                              Guid *puuid);
     843    void addMediumToRegistry(ComObjPtr<Medium> &pMedium);
    846844
    847845    HRESULT createImplicitDiffs(IProgress *aProgress,
    848846                                ULONG aWeight,
    849                                 bool aOnline,
    850                                 GuidList *pllRegistriesThatNeedSaving);
    851     HRESULT deleteImplicitDiffs(GuidList *pllRegistriesThatNeedSaving);
     847                                bool aOnline);
     848    HRESULT deleteImplicitDiffs();
    852849
    853850    MediumAttachment* findAttachment(const MediaData::AttachmentList &ll,
     
    862859    HRESULT detachDevice(MediumAttachment *pAttach,
    863860                         AutoWriteLock &writeLock,
    864                          Snapshot *pSnapshot,
    865                          GuidList *pllRegistriesThatNeedSaving);
     861                         Snapshot *pSnapshot);
    866862
    867863    HRESULT detachAllMedia(AutoWriteLock &writeLock,
     
    937933    typedef std::list<ComObjPtr<StorageController> > StorageControllerList;
    938934    Backupable<StorageControllerList> mStorageControllers;
     935
     936    uint64_t                        uRegistryNeedsSaving;
    939937
    940938    friend class SessionMachine;
  • trunk/src/VBox/Main/include/MediumImpl.h

    r40257 r40432  
    77
    88/*
    9  * Copyright (C) 2008-2011 Oracle Corporation
     9 * Copyright (C) 2008-2012 Oracle Corporation
    1010 *
    1111 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    7070                 const Utf8Str &aFormat,
    7171                 const Utf8Str &aLocation,
    72                  const Guid &uuidMachineRegistry,
    73                  GuidList *pllRegistriesThatNeedSaving);
     72                 const Guid &uuidMachineRegistry);
    7473
    7574    // initializer for opening existing media
     
    183182    bool isInRegistry(const Guid& id);
    184183    bool getFirstRegistryMachineId(Guid &uuid) const;
    185     HRESULT addToRegistryIDList(GuidList &llRegistryIDs);
    186184
    187185    HRESULT addBackReference(const Guid &aMachineId,
     
    218216                              MediumLockList *pMediumLockList,
    219217                              ComObjPtr<Progress> *aProgress,
    220                               bool aWait,
    221                               GuidList *pllRegistriesThatNeedSaving);
     218                              bool aWait);
    222219    Utf8Str getPreferredDiffFormat();
    223220
    224     HRESULT close(GuidList *pllRegistriesThatNeedSaving, AutoCaller &autoCaller);
    225     HRESULT deleteStorage(ComObjPtr<Progress> *aProgress, bool aWait, GuidList *pllRegistriesThatNeedSaving);
     221    HRESULT close(AutoCaller &autoCaller);
     222    HRESULT deleteStorage(ComObjPtr<Progress> *aProgress, bool aWait);
    226223    HRESULT markForDeletion();
    227224    HRESULT unmarkForDeletion();
     
    243240                    MediumLockList *aMediumLockList,
    244241                    ComObjPtr<Progress> *aProgress,
    245                     bool aWait,
    246                     GuidList *pllRegistriesThatNeedSaving);
     242                    bool aWait);
    247243    void cancelMergeTo(const MediaList &aChildrenToReparent,
    248244                       MediumLockList *aMediumLockList);
     
    273269
    274270    HRESULT canClose();
    275     HRESULT unregisterWithVirtualBox(GuidList *pllRegistriesThatNeedSaving);
     271    HRESULT unregisterWithVirtualBox();
     272    void markRegistriesModified();
    276273
    277274    HRESULT setStateError();
     
    333330
    334331    HRESULT startThread(Medium::Task *pTask);
    335     HRESULT runNow(Medium::Task *pTask, GuidList *pllRegistriesThatNeedSaving);
     332    HRESULT runNow(Medium::Task *pTask);
    336333
    337334    HRESULT taskCreateBaseHandler(Medium::CreateBaseTask &task);
  • trunk/src/VBox/Main/include/VirtualBoxBase.h

    r40418 r40432  
    44
    55/*
    6  * Copyright (C) 2006-2010 Oracle Corporation
     6 * Copyright (C) 2006-2012 Oracle Corporation
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    5353class Host;
    5454typedef std::list< ComObjPtr<Medium> > MediaList;
    55 typedef std::list<Guid> GuidList;
    5655
    5756////////////////////////////////////////////////////////////////////////////////
  • trunk/src/VBox/Main/include/VirtualBoxImpl.h

    r40262 r40432  
    260260    void copyPathRelativeToConfig(const Utf8Str &strSource, Utf8Str &strTarget);
    261261
    262     HRESULT registerMedium(const ComObjPtr<Medium> &pMedium, ComObjPtr<Medium> *ppMedium, DeviceType_T argType, GuidList *pllRegistriesThatNeedSaving);
    263     HRESULT unregisterMedium(Medium *pMedium, GuidList *pllRegistriesThatNeedSaving);
     262    HRESULT registerMedium(const ComObjPtr<Medium> &pMedium, ComObjPtr<Medium> *ppMedium, DeviceType_T argType);
     263    HRESULT unregisterMedium(Medium *pMedium);
    264264
    265265    void pushMediumToListWithChildren(MediaList &llMedia, Medium *pMedium);
     
    276276    HRESULT saveSettings();
    277277
    278     static void addGuidToListUniquely(GuidList &llRegistriesThatNeedSaving, const Guid &uuid);
    279     HRESULT saveRegistries(const GuidList &llRegistriesThatNeedSaving);
     278    void markRegistryModified(const Guid &uuid);
     279    void saveModifiedRegistries();
    280280
    281281    static HRESULT ensureFilePathExists(const Utf8Str &strFileName, bool fCreate);
  • trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp

    r40329 r40432  
    66
    77/*
    8  * Copyright (C) 2008-2011 Oracle Corporation
     8 * Copyright (C) 2008-2012 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    18471847                             strTrgFormat,
    18481848                             strTargetPath,
    1849                              Guid::Empty,       // media registry: none yet
    1850                              NULL /* llRegistriesThatNeedSaving */);
     1849                             Guid::Empty /* media registry: none yet */);
    18511850        if (FAILED(rc)) throw rc;
    18521851
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r40418 r40432  
    55
    66/*
    7  * Copyright (C) 2006-2011 Oracle Corporation
     7 * Copyright (C) 2006-2012 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    241241    : mCollectorGuest(NULL),
    242242      mPeer(NULL),
    243       mParent(NULL)
     243      mParent(NULL),
     244      uRegistryNeedsSaving(0)
    244245{}
    245246
     
    768769
    769770    Assert(!isWriteLockOnCurrentThread());
     771
     772    Assert(!uRegistryNeedsSaving);
     773    if (uRegistryNeedsSaving)
     774    {
     775        AutoCaller autoCaller(this);
     776        if (SUCCEEDED(autoCaller.rc()))
     777        {
     778            AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     779            saveSettings(NULL, Machine::SaveS_Force);
     780        }
     781    }
    770782
    771783    /* Enclose the state transition Ready->InUninit->NotReady */
     
    34833495    HRESULT rc = checkStateDependency(MutableStateDep);
    34843496    if (FAILED(rc)) return rc;
    3485 
    3486     GuidList llRegistriesThatNeedSaving;
    34873497
    34883498    /// @todo NEWMEDIA implicit machine registration
     
    37923802            // put the parent in the machine registry then
    37933803            mediumLock.release();
    3794             addMediumToRegistry(medium, llRegistriesThatNeedSaving, &uuidRegistryParent);
     3804            addMediumToRegistry(medium);
    37953805            mediumLock.acquire();
     3806            medium->getFirstRegistryMachineId(uuidRegistryParent);
    37963807        }
    37973808        rc = diff->init(mParent,
    37983809                        medium->getPreferredDiffFormat(),
    37993810                        strFullSnapshotFolder.append(RTPATH_SLASH_STR),
    3800                         uuidRegistryParent,
    3801                         &llRegistriesThatNeedSaving);
     3811                        uuidRegistryParent);
    38023812        if (FAILED(rc)) return rc;
    38033813
     
    38383848                                               pMediumLockList,
    38393849                                               NULL /* aProgress */,
    3840                                                true /* aWait */,
    3841                                                &llRegistriesThatNeedSaving);
     3850                                               true /* aWait */);
    38423851
    38433852                alock.acquire();
     
    38863895
    38873896        mediumLock.release();
    3888         addMediumToRegistry(medium,
    3889                             llRegistriesThatNeedSaving,
    3890                             NULL /* Guid *puuid */);
     3897        addMediumToRegistry(medium);
    38913898        mediumLock.acquire();
    38923899    }
     
    39043911        rc = onStorageDeviceChange(attachment, FALSE /* aRemove */);
    39053912
    3906     mParent->saveRegistries(llRegistriesThatNeedSaving);
     3913    mParent->saveModifiedRegistries();
    39073914
    39083915    return rc;
     
    39193926    AutoCaller autoCaller(this);
    39203927    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    3921 
    3922     GuidList llRegistriesThatNeedSaving;
    39233928
    39243929    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     
    39733978
    39743979    /* If we are here everything went well and we can delete the implicit now. */
    3975     rc = detachDevice(pAttach, alock, NULL /* pSnapshot */, &llRegistriesThatNeedSaving);
     3980    rc = detachDevice(pAttach, alock, NULL /* pSnapshot */);
    39763981
    39773982    alock.release();
    39783983
    3979     if (SUCCEEDED(rc))
    3980         rc = mParent->saveRegistries(llRegistriesThatNeedSaving);
     3984    mParent->saveModifiedRegistries();
    39813985
    39823986    return rc;
     
    42914295    setModified(IsModified_Storage);
    42924296    mMediaData.backup();
    4293 
    4294     GuidList llRegistriesThatNeedSaving;
    42954297
    42964298    {
     
    43094311
    43104312            mediumLock.release();
    4311             addMediumToRegistry(pMedium, llRegistriesThatNeedSaving, NULL /* Guid *puuid */ );
     4313            addMediumToRegistry(pMedium);
    43124314            mediumLock.acquire();
    43134315        }
     
    43454347    multiLock.release();
    43464348
    4347     mParent->saveRegistries(llRegistriesThatNeedSaving);
     4349    mParent->saveModifiedRegistries();
    43484350
    43494351    return rc;
     
    47434745
    47444746    mParent->unregisterMachine(this, id);
    4745             // calls VirtualBox::saveSettings()
     4747            // calls VirtualBox::saveSettings() and VirtualBox::saveModifiedRegistries()
    47464748
    47474749    return S_OK;
     
    47544756    std::list<Utf8Str>          llFilesToDelete;
    47554757    ComObjPtr<Progress>         pProgress;
    4756     GuidList                    llRegistriesThatNeedSaving;
    47574758};
    47584759
     
    50005001        alock.release();
    50015002
    5002         rc = mParent->saveRegistries(task.llRegistriesThatNeedSaving);
    5003         if (FAILED(rc)) throw rc;
     5003        mParent->saveModifiedRegistries();
    50045004    }
    50055005    catch (HRESULT aRC) { rc = aRC; }
     
    95069506 * Ensures that the given medium is added to a media registry. If this machine
    95079507 * was created with 4.0 or later, then the machine registry is used. Otherwise
    9508  * the global VirtualBox media registry is used. If the medium was actually
    9509  * added to a registry (because it wasn't in the registry yet), the UUID of
    9510  * that registry is added to the given list so that the caller can save the
    9511  * registry.
     9508 * the global VirtualBox media registry is used.
    95129509 *
    95139510 * Caller must hold machine read lock and at least media tree read lock!
     
    95159512 *
    95169513 * @param pMedium
    9517  * @param llRegistriesThatNeedSaving
    9518  * @param puuid Optional buffer that receives the registry UUID that was used.
    95199514 */
    9520 void Machine::addMediumToRegistry(ComObjPtr<Medium> &pMedium,
    9521                                   GuidList &llRegistriesThatNeedSaving,
    9522                                   Guid *puuid)
     9515void Machine::addMediumToRegistry(ComObjPtr<Medium> &pMedium)
    95239516{
    95249517    ComObjPtr<Medium> pBase = pMedium->getBase();
     
    95359528        uuid = mParent->getGlobalRegistryId(); // VirtualBox global registry UUID
    95369529
    9537     bool fAdd = false;
    95389530    if (pMedium->addRegistry(uuid, false /* fRecurse */))
    9539     {
    9540         // registry actually changed:
    9541         VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, uuid);
    9542         fAdd = true;
    9543     }
     9531        mParent->markRegistryModified(uuid);
    95449532
    95459533    /* For more complex hard disk structures it can happen that the base
     
    95479535    if (pMedium != pBase)
    95489536    {
    9549         if (   pBase->addRegistry(uuid, true /* fRecurse */)
    9550             && !fAdd)
    9551         {
    9552             VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, uuid);
    9553             fAdd = true;
    9554         }
    9555     }
    9556 
    9557     if (puuid)
    9558         *puuid = uuid;
     9537        if (pBase->addRegistry(uuid, true /* fRecurse */))
     9538            mParent->markRegistryModified(uuid);
     9539    }
    95599540}
    95609541
     
    95849565 *                          attached).
    95859566 * @param aOnline           Whether the VM was online prior to this operation.
    9586  * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs to receive the registry IDs that need saving
    95879567 *
    95889568 * @note The progress object is not marked as completed, neither on success nor
     
    95939573HRESULT Machine::createImplicitDiffs(IProgress *aProgress,
    95949574                                     ULONG aWeight,
    9595                                      bool aOnline,
    9596                                      GuidList *pllRegistriesThatNeedSaving)
     9575                                     bool aOnline)
    95979576{
    95989577    LogFlowThisFunc(("aOnline=%d\n", aOnline));
     
    97299708                            pMedium->getPreferredDiffFormat(),
    97309709                            strFullSnapshotFolder.append(RTPATH_SLASH_STR),
    9731                             uuidRegistryParent,
    9732                             pllRegistriesThatNeedSaving);
     9710                            uuidRegistryParent);
    97339711            if (FAILED(rc)) throw rc;
    97349712
     
    97559733                                            pMediumLockList,
    97569734                                            NULL /* aProgress */,
    9757                                             true /* aWait */,
    9758                                             pllRegistriesThatNeedSaving);
     9735                                            true /* aWait */);
    97599736            alock.acquire();
    97609737            if (FAILED(rc)) throw rc;
     
    98129789
    98139790        alock.release();
    9814         mrc = deleteImplicitDiffs(pllRegistriesThatNeedSaving);
     9791        mrc = deleteImplicitDiffs();
    98159792    }
    98169793
     
    98259802 * called from #fixupMedia() when the changes are rolled back.
    98269803 *
    9827  * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs to receive the registry IDs that need saving
    9828  *
    98299804 * @note Locks this object for writing.
    98309805 */
    9831 HRESULT Machine::deleteImplicitDiffs(GuidList *pllRegistriesThatNeedSaving)
     9806HRESULT Machine::deleteImplicitDiffs()
    98329807{
    98339808    AutoCaller autoCaller(this);
     
    99069881            ComObjPtr<Medium> hd = (*it)->getMedium();
    99079882
    9908             rc = hd->deleteStorage(NULL /*aProgress*/, true /*aWait*/,
    9909                                    pllRegistriesThatNeedSaving);
     9883            rc = hd->deleteStorage(NULL /*aProgress*/, true /*aWait*/);
    99109884            AssertMsg(SUCCEEDED(rc), ("rc=%Rhrc it=%s hd=%s\n", rc, (*it)->getLogName(), hd->getLocationFull().c_str() ));
    99119885            mrc = rc;
     
    100109984 * @param writeLock Machine write lock which the caller must have locked once. This may be released temporarily in here.
    100119985 * @param pSnapshot If NULL, then the detachment is for the current machine. Otherwise this is for a SnapshotMachine, and this must be its snapshot.
    10012  * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs to receive the registry IDs that need saving
    100139986 * @return
    100149987 */
    100159988HRESULT Machine::detachDevice(MediumAttachment *pAttach,
    100169989                              AutoWriteLock &writeLock,
    10017                               Snapshot *pSnapshot,
    10018                               GuidList *pllRegistriesThatNeedSaving)
     9990                              Snapshot *pSnapshot)
    100199991{
    100209992    ComObjPtr<Medium> oldmedium = pAttach->getMedium();
     
    1004110013
    1004210014        HRESULT rc = oldmedium->deleteStorage(NULL /*aProgress*/,
    10043                                               true /*aWait*/,
    10044                                               pllRegistriesThatNeedSaving);
     10015                                              true /*aWait*/);
    1004510016
    1004610017        writeLock.acquire();
     
    1015210123
    1015310124        // real machine: then we need to use the proper method
    10154         rc = detachDevice(pAttach,
    10155                           writeLock,
    10156                           pSnapshot,
    10157                           NULL /* pfNeedsSaveSettings */);
     10125        rc = detachDevice(pAttach, writeLock, pSnapshot);
    1015810126
    1015910127        if (FAILED(rc))
     
    1034810316 * backed up).
    1034910317 *
    10350  * @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
    10351  *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
    10352  *
    1035310318 * @note Locks this object for writing!
    10354  *
    10355  * @todo r=dj this needs a pllRegistriesThatNeedSaving as well
    1035610319 */
    1035710320void Machine::rollbackMedia()
     
    1040410367    /** @todo convert all this Machine-based voodoo to MediumAttachment
    1040510368     * based rollback logic. */
    10406     // @todo r=dj the below totally fails if this gets called from Machine::rollback(),
    10407     // which gets called if Machine::registeredInit() fails...
    10408     deleteImplicitDiffs(NULL /*pfNeedsSaveSettings*/);
     10369    deleteImplicitDiffs();
    1040910370
    1041010371    return;
  • trunk/src/VBox/Main/src-server/MachineImplCloneVM.cpp

    r40257 r40432  
    661661                        pParent->getPreferredDiffFormat(),
    662662                        Utf8StrFmt("%s%c", strSnapshotFolder.c_str(), RTPATH_DELIMITER),
    663                         Guid::Empty, /* empty media registry */
    664                         NULL);       /* pllRegistriesThatNeedSaving */
     663                        Guid::Empty /* empty media registry */);
    665664        if (FAILED(rc)) throw rc;
    666665
     
    678677                                        pMediumLockList,
    679678                                        NULL /* aProgress */,
    680                                         true /* aWait */,
    681                                         NULL); // pllRegistriesThatNeedSaving
     679                                        true /* aWait */);
    682680        delete pMediumLockList;
    683681        if (FAILED(rc)) throw rc;
     
    10251023        typedef std::pair<Utf8Str, ComObjPtr<Medium> > TStrMediumPair;
    10261024        TStrMediumMap map;
    1027         GuidList llRegistriesThatNeedSaving;
    10281025        size_t cDisks = 0;
    10291026        for (size_t i = 0; i < d->llMedias.size(); ++i)
     
    11551152                                           Utf8Str(bstrSrcFormat),
    11561153                                           strFile,
    1157                                            Guid::Empty,  /* empty media registry */
    1158                                            NULL          /* llRegistriesThatNeedSaving */);
     1154                                           Guid::Empty /* empty media registry */);
    11591155                        if (FAILED(rc)) throw rc;
    11601156
     
    12021198                            AutoWriteLock tlock(p->mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
    12031199                            rc = p->mParent->registerMedium(pTarget, &pTarget,
    1204                                                             DeviceType_HardDisk,
    1205                                                             NULL /* pllRegistriesThatNeedSaving */);
     1200                                                            DeviceType_HardDisk);
    12061201                            if (FAILED(rc)) throw rc;
    12071202                        }
     
    12761271                    AutoReadLock mlock2(pParent COMMA_LOCKVAL_SRC_POS);
    12771272                    if (pParent->getFirstRegistryMachineId(uuid))
    1278                         VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, uuid);
     1273                        p->mParent->markRegistryModified(uuid);
    12791274                }
    12801275                mlock.acquire();
     
    13471342
    13481343        /* Any additional machines need saving? */
    1349         if (!llRegistriesThatNeedSaving.empty())
    1350         {
    1351             rc = p->mParent->saveRegistries(llRegistriesThatNeedSaving);
    1352             if (FAILED(rc)) throw rc;
    1353         }
     1344        p->mParent->saveModifiedRegistries();
    13541345    }
    13551346    catch (HRESULT rc2)
     
    13801371            const ComObjPtr<Medium> &pMedium = newMedia.at(i - 1);
    13811372            mrc = pMedium->deleteStorage(NULL /* aProgress */,
    1382                                          true /* aWait */,
    1383                                          NULL /* llRegistriesThatNeedSaving */);
     1373                                         true /* aWait */);
    13841374            pMedium->Close();
    13851375        }
  • trunk/src/VBox/Main/src-server/MediumImpl.cpp

    r40259 r40432  
    4040
    4141#include <algorithm>
     42#include <list>
     43
     44typedef std::list<Guid> GuidList;
    4245
    4346////////////////////////////////////////////////////////////////////////////////
     
    198201    Task(Medium *aMedium, Progress *aProgress)
    199202        : mVDOperationIfaces(NULL),
    200           m_pllRegistriesThatNeedSaving(NULL),
    201203          mMedium(aMedium),
    202204          mMediumCaller(aMedium),
     
    245247    PVDINTERFACE mVDOperationIfaces;
    246248
    247     // Whether the caller needs to call VirtualBox::saveRegistries() after
    248     // the task function returns. Only used in synchronous (wait) mode;
    249     // otherwise the task will save the settings itself.
    250     GuidList *m_pllRegistriesThatNeedSaving;
    251 
    252249    const ComObjPtr<Medium> mMedium;
    253250    AutoCaller mMediumCaller;
    254251
    255     friend HRESULT Medium::runNow(Medium::Task*, GuidList *);
     252    friend HRESULT Medium::runNow(Medium::Task*);
    256253
    257254protected:
     
    928925 * @param aLocation     Storage unit location.
    929926 * @param uuidMachineRegistry The registry to which this medium should be added (global registry UUID or machine UUID or empty if none).
    930  * @param pllRegistriesThatNeedSaving Optional list to receive the UUIDs of the media registries that need saving.
    931927 */
    932928HRESULT Medium::init(VirtualBox *aVirtualBox,
    933929                     const Utf8Str &aFormat,
    934930                     const Utf8Str &aLocation,
    935                      const Guid &uuidMachineRegistry,
    936                      GuidList *pllRegistriesThatNeedSaving)
     931                     const Guid &uuidMachineRegistry)
    937932{
    938933    AssertReturn(aVirtualBox != NULL, E_FAIL);
     
    979974        AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
    980975        ComObjPtr<Medium> pMedium;
    981         rc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk,
    982                                             pllRegistriesThatNeedSaving);
     976        rc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk);
    983977        Assert(this == pMedium);
    984978    }
     
    12561250        if (FAILED(rc)) break;
    12571251
    1258         rc = m->pVirtualBox->registerMedium(pHD, &pHD, DeviceType_HardDisk,
    1259                                             NULL /* pllRegistriesThatNeedSaving */ );
     1252        rc = m->pVirtualBox->registerMedium(pHD, &pHD, DeviceType_HardDisk);
    12601253        if (FAILED(rc)) break;
    12611254    }
     
    17491742
    17501743    // save the settings
    1751     GuidList llRegistriesThatNeedSaving;
    1752     addToRegistryIDList(llRegistriesThatNeedSaving);
     1744    markRegistriesModified();
    17531745    mlock.release();
    17541746    treeLock.release();
    1755     HRESULT rc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
    1756 
    1757     return rc;
     1747    m->pVirtualBox->saveModifiedRegistries();
     1748
     1749    return S_OK;
    17581750}
    17591751
     
    18891881                        m->strLocationFull.c_str());
    18901882
    1891     HRESULT rc = S_OK;
    1892 
    18931883    if (m->autoReset != !!aAutoReset)
    18941884    {
     
    18961886
    18971887        // save the settings
    1898         GuidList llRegistriesThatNeedSaving;
    1899         addToRegistryIDList(llRegistriesThatNeedSaving);
     1888        markRegistriesModified();
    19001889        mlock.release();
    1901         rc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
    1902     }
    1903 
    1904     return rc;
     1890        m->pVirtualBox->saveModifiedRegistries();
     1891    }
     1892
     1893    return S_OK;
    19051894}
    19061895
     
    22082197    ComObjPtr<VirtualBox> pVirtualBox(m->pVirtualBox);
    22092198
    2210     GuidList llRegistriesThatNeedSaving;
    2211     MultiResult mrc = close(&llRegistriesThatNeedSaving, autoCaller);
    2212     /* Must save the registries, since an entry was most likely removed. */
    2213     mrc = pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
     2199    MultiResult mrc = close(autoCaller);
     2200
     2201    pVirtualBox->saveModifiedRegistries();
    22142202
    22152203    return mrc;
     
    22632251
    22642252    // save the settings
    2265     GuidList llRegistriesThatNeedSaving;
    2266     addToRegistryIDList(llRegistriesThatNeedSaving);
     2253    markRegistriesModified();
    22672254    mlock.release();
    2268     HRESULT rc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
    2269 
    2270     return rc;
     2255    m->pVirtualBox->saveModifiedRegistries();
     2256
     2257    return S_OK;
    22712258}
    22722259
     
    23412328
    23422329    // save the settings
    2343     GuidList llRegistriesThatNeedSaving;
    2344     addToRegistryIDList(llRegistriesThatNeedSaving);
     2330    markRegistriesModified();
    23452331    mlock.release();
    2346     HRESULT rc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
    2347 
    2348     return rc;
     2332    m->pVirtualBox->saveModifiedRegistries();
     2333
     2334    return S_OK;
    23492335}
    23502336
     
    24272413    ComObjPtr<Progress> pProgress;
    24282414
    2429     GuidList llRegistriesThatNeedSaving;
    24302415    MultiResult mrc = deleteStorage(&pProgress,
    2431                                     false /* aWait */,
    2432                                     &llRegistriesThatNeedSaving);
     2416                                    false /* aWait */);
    24332417    /* Must save the registries in any case, since an entry was removed. */
    2434     mrc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
     2418    m->pVirtualBox->saveModifiedRegistries();
    24352419
    24362420    if (SUCCEEDED(mrc))
     
    24992483        /* since this medium has been just created it isn't associated yet */
    25002484        diff->m->llRegistryIDs.push_back(parentMachineRegistry);
     2485        diff->markRegistriesModified();
    25012486    }
    25022487
     
    25062491
    25072492    rc = createDiffStorage(diff, (MediumVariant_T)aVariant, pMediumLockList,
    2508                            &pProgress, false /* aWait */,
    2509                            NULL /* pfNeedsGlobalSaveSettings*/);
     2493                           &pProgress, false /* aWait */);
    25102494    if (FAILED(rc))
    25112495        delete pMediumLockList;
     
    25412525
    25422526    rc = mergeTo(pTarget, fMergeForward, pParentForTarget, childrenToReparent,
    2543                  pMediumLockList, &pProgress, false /* aWait */,
    2544                  NULL /* pfNeedsGlobalSaveSettings */);
     2527                 pMediumLockList, &pProgress, false /* aWait */);
    25452528    if (FAILED(rc))
    25462529        cancelMergeTo(childrenToReparent, pMediumLockList);
     
    32363219
    32373220/**
    3238  * Adds all the IDs of the registries in which this medium is registered to the given list
    3239  * of UUIDs, but only if they are not on the list yet.
    3240  * @param llRegistryIDs
    3241  */
    3242 HRESULT Medium::addToRegistryIDList(GuidList &llRegistryIDs)
     3221 * Marks all the registries in which this medium is registered as modified.
     3222 */
     3223void Medium::markRegistriesModified()
    32433224{
    32443225    AutoCaller autoCaller(this);
    3245     if (FAILED(autoCaller.rc())) return false;
     3226    if (FAILED(autoCaller.rc())) return;
    32463227
    32473228    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     
    32513232         ++it)
    32523233    {
    3253         VirtualBox::addGuidToListUniquely(llRegistryIDs, *it);
    3254     }
    3255 
    3256     return S_OK;
     3234        m->pVirtualBox->markRegistryModified(*it);
     3235    }
    32573236}
    32583237
     
    38163795 * @param aWait             @c true if this method should block instead of
    38173796 *                          creating an asynchronous thread.
    3818  * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs that will receive the registry IDs that need saving.
    3819  *                          This only works in "wait" mode; otherwise saveRegistries is called automatically by the thread that
    3820  *                          was created, and this parameter is ignored.
    38213797 *
    38223798 * @note Locks this object and @a aTarget for writing.
     
    38263802                                  MediumLockList *aMediumLockList,
    38273803                                  ComObjPtr<Progress> *aProgress,
    3828                                   bool aWait,
    3829                                   GuidList *pllRegistriesThatNeedSaving)
     3804                                  bool aWait)
    38303805{
    38313806    AssertReturn(!aTarget.isNull(), E_FAIL);
     
    39183893    {
    39193894        if (aWait)
    3920             rc = runNow(pTask, pllRegistriesThatNeedSaving);
     3895            rc = runNow(pTask);
    39213896        else
    39223897            rc = startThread(pTask);
     
    39603935 * the object is no longer usable ("not ready" state).
    39613936 *
    3962  * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs that will receive the registry IDs that need saving.
    39633937 * @param autoCaller AutoCaller instance which must have been created on the caller's stack for this medium. This gets released here
    39643938 *                   upon which the Medium instance gets uninitialized.
    39653939 * @return
    39663940 */
    3967 HRESULT Medium::close(GuidList *pllRegistriesThatNeedSaving,
    3968                       AutoCaller &autoCaller)
     3941HRESULT Medium::close(AutoCaller &autoCaller)
    39693942{
    39703943    // we're accessing parent/child and backrefs, so lock the tree first, then ourselves
     
    40033976        // uninitialization (to keep the media registry consistent on
    40043977        // failure to do so)
    4005         rc = unregisterWithVirtualBox(pllRegistriesThatNeedSaving);
     3978        rc = unregisterWithVirtualBox();
    40063979        if (FAILED(rc)) return rc;
    40073980    }
     
    40374010 * @param aWait         @c true if this method should block instead of creating
    40384011 *                      an asynchronous thread.
    4039  * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
    4040  *                by this function if the caller should invoke VirtualBox::saveRegistries() because the global settings have changed.
    4041  *                This only works in "wait" mode; otherwise saveRegistries gets called automatically by the thread that was created,
    4042  *                and this parameter is ignored.
    40434012 *
    40444013 * @note Locks mVirtualBox and this object for writing. Locks medium tree for
     
    40464015 */
    40474016HRESULT Medium::deleteStorage(ComObjPtr<Progress> *aProgress,
    4048                               bool aWait,
    4049                               GuidList *pllRegistriesThatNeedSaving)
     4017                              bool aWait)
    40504018{
    40514019    AssertReturn(aProgress != NULL || aWait == true, E_FAIL);
     
    41534121         * which would have been broken if unregisterWithVirtualBox() failed
    41544122         * after we successfully deleted the storage) */
    4155         rc = unregisterWithVirtualBox(pllRegistriesThatNeedSaving);
     4123        rc = unregisterWithVirtualBox();
    41564124        if (FAILED(rc))
    41574125            throw rc;
     
    41894157    {
    41904158        if (aWait)
    4191             rc = runNow(pTask, NULL /* pfNeedsGlobalSaveSettings*/);
     4159            rc = runNow(pTask);
    41924160        else
    41934161            rc = startThread(pTask);
     
    46724640 * @param aWait         @c true if this method should block instead of creating
    46734641 *                      an asynchronous thread.
    4674  * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
    4675  *                by this function if the caller should invoke VirtualBox::saveRegistries() because the global settings have changed.
    4676  *                This only works in "wait" mode; otherwise saveRegistries gets called automatically by the thread that was created,
    4677  *                and this parameter is ignored.
    46784642 *
    46794643 * @note Locks the tree lock for writing. Locks the media from the chain
     
    46864650                        MediumLockList *aMediumLockList,
    46874651                        ComObjPtr <Progress> *aProgress,
    4688                         bool aWait,
    4689                         GuidList *pllRegistriesThatNeedSaving)
     4652                        bool aWait)
    46904653{
    46914654    AssertReturn(pTarget != NULL, E_FAIL);
     
    47494712    {
    47504713        if (aWait)
    4751             rc = runNow(pTask, pllRegistriesThatNeedSaving);
     4714            rc = runNow(pTask);
    47524715        else
    47534716            rc = startThread(pTask);
     
    58035766 * Unregisters this medium with mVirtualBox. Called by close() under the medium tree lock.
    58045767 *
    5805  * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs that will receive the registry IDs that need saving.
    5806  *
    58075768 * @note Caller must have locked the media tree lock for writing!
    58085769 */
    5809 HRESULT Medium::unregisterWithVirtualBox(GuidList *pllRegistriesThatNeedSaving)
     5770HRESULT Medium::unregisterWithVirtualBox()
    58105771{
    58115772    /* Note that we need to de-associate ourselves from the parent to let
     
    58205781        deparent();
    58215782
    5822     HRESULT rc = m->pVirtualBox->unregisterMedium(this, pllRegistriesThatNeedSaving);
     5783    HRESULT rc = m->pVirtualBox->unregisterMedium(this);
    58235784    if (FAILED(rc))
    58245785    {
     
    58305791        }
    58315792    }
     5793    m->pVirtualBox->saveModifiedRegistries();
    58325794
    58335795    return rc;
     
    64536415 *       complete the progress object in this case.
    64546416 */
    6455 HRESULT Medium::runNow(Medium::Task *pTask,
    6456                        GuidList *pllRegistriesThatNeedSaving)
     6417HRESULT Medium::runNow(Medium::Task *pTask)
    64576418{
    64586419#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
     
    64636424    Assert(!AutoLockHoldsLocksInClass(getLockingClass()));
    64646425#endif
    6465 
    6466     pTask->m_pllRegistriesThatNeedSaving = pllRegistriesThatNeedSaving;
    64676426
    64686427    /* NIL_RTTHREAD indicates synchronous call. */
     
    65676526        AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
    65686527        ComObjPtr<Medium> pMedium;
    6569         rc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk,
    6570                                             NULL /* pllRegistriesThatNeedSaving */);
     6528        rc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk);
    65716529        Assert(this == pMedium);
    65726530    }
     
    65826540        m->logicalSize = logicalSize;
    65836541        m->variant = variant;
     6542
     6543        markRegistriesModified();
     6544        if (task.isAsync())
     6545        {
     6546            // in asynchronous mode, save settings now
     6547            thisLock.release();
     6548            m->pVirtualBox->saveModifiedRegistries();
     6549        }
    65846550    }
    65856551    else
     
    66016567 * This task always gets started from Medium::createDiffStorage() and can run
    66026568 * synchronously or asynchronously depending on the "wait" parameter passed to
    6603  * that function. If we run synchronously, the caller expects the bool
    6604  * *pfNeedsGlobalSaveSettings to be set before returning; otherwise (in asynchronous
     6569 * that function. If we run synchronously, the caller expects the medium
     6570 * registry modification to be set before returning; otherwise (in asynchronous
    66056571 * mode), we save the settings ourselves.
    66066572 *
     
    66176583    MediumVariant_T variant = MediumVariant_Standard;
    66186584    bool fGenerateUuid = false;
    6619 
    6620     GuidList llRegistriesThatNeedSaving;        // gets copied to task pointer later in synchronous mode
    66216585
    66226586    try
     
    67476711         * better than breaking media registry consistency) */
    67486712        ComObjPtr<Medium> pMedium;
    6749         mrc = m->pVirtualBox->registerMedium(pTarget, &pMedium, DeviceType_HardDisk,
    6750                                              &llRegistriesThatNeedSaving);
     6713        mrc = m->pVirtualBox->registerMedium(pTarget, &pMedium, DeviceType_HardDisk);
    67516714        Assert(pTarget == pMedium);
    67526715
     
    67826745    --m->numCreateDiffTasks;
    67836746
     6747    markRegistriesModified();
    67846748    if (task.isAsync())
    67856749    {
     6750        // in asynchronous mode, save settings now
    67866751        mediaLock.release();
    6787         mrc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
    6788     }
    6789     else
    6790         // synchronous mode: report save settings result to caller
    6791         if (task.m_pllRegistriesThatNeedSaving)
    6792             *task.m_pllRegistriesThatNeedSaving = llRegistriesThatNeedSaving;
     6752        m->pVirtualBox->saveModifiedRegistries();
     6753    }
    67936754
    67946755    /* Note that in sync mode, it's the caller's responsibility to
     
    68036764 * This task always gets started from Medium::mergeTo() and can run
    68046765 * synchronously or asynchronously depending on the "wait" parameter passed to
    6805  * that function. If we run synchronously, the caller expects the bool
    6806  * *pfNeedsGlobalSaveSettings to be set before returning; otherwise (in asynchronous
     6766 * that function. If we run synchronously, the caller expects the medium
     6767 * registry modification to be set before returning; otherwise (in asynchronous
    68076768 * mode), we save the settings ourselves.
    68086769 *
     
    69686929            /* first, unregister the target since it may become a base
    69696930             * medium which needs re-registration */
    6970             rc2 = m->pVirtualBox->unregisterMedium(pTarget, NULL /*pfNeedsGlobalSaveSettings*/);
     6931            rc2 = m->pVirtualBox->unregisterMedium(pTarget);
    69716932            AssertComRC(rc2);
    69726933
     
    69846945            ComObjPtr<Medium> pMedium;
    69856946            rc2 = m->pVirtualBox->registerMedium(pTarget, &pMedium,
    6986                                                  DeviceType_HardDisk,
    6987                                                  NULL /* pllRegistriesThatNeedSaving */ );
     6947                                                 DeviceType_HardDisk);
    69886948            AssertComRC(rc2);
    69896949        }
     
    70386998            }
    70396999
    7040             rc2 = pMedium->m->pVirtualBox->unregisterMedium(pMedium,
    7041                                                             NULL /*pfNeedsGlobalSaveSettings*/);
     7000            rc2 = pMedium->m->pVirtualBox->unregisterMedium(pMedium);
    70427001            AssertComRC(rc2);
    70437002
     
    70727031    }
    70737032
     7033    markRegistriesModified();
    70747034    if (task.isAsync())
    70757035    {
    70767036        // in asynchronous mode, save settings now
    7077         GuidList llRegistriesThatNeedSaving;
    7078         addToRegistryIDList(llRegistriesThatNeedSaving);
    7079         /* collect multiple errors */
    70807037        eik.restore();
    7081         mrc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
     7038        m->pVirtualBox->saveModifiedRegistries();
    70827039        eik.fetch();
    70837040    }
    7084     else
    7085         // synchronous mode: report save settings result to caller
    7086         if (task.m_pllRegistriesThatNeedSaving)
    7087             pTarget->addToRegistryIDList(*task.m_pllRegistriesThatNeedSaving);
    70887041
    70897042    if (FAILED(mrc))
     
    73367289            ComObjPtr<Medium> pMedium;
    73377290            mrc = pParent->m->pVirtualBox->registerMedium(pTarget, &pMedium,
    7338                                                           DeviceType_HardDisk,
    7339                                                           NULL /* pllRegistriesThatNeedSaving */);
     7291                                                          DeviceType_HardDisk);
    73407292            Assert(pTarget == pMedium);
    73417293            eik.fetch();
     
    73517303            ComObjPtr<Medium> pMedium;
    73527304            mrc = m->pVirtualBox->registerMedium(pTarget, &pMedium,
    7353                                                  DeviceType_HardDisk,
    7354                                                  NULL /* pllRegistriesThatNeedSaving */);
     7305                                                 DeviceType_HardDisk);
    73557306            Assert(pTarget == pMedium);
    73567307            eik.fetch();
     
    73857336    {
    73867337        // save the settings
    7387         GuidList llRegistriesThatNeedSaving;
    7388         addToRegistryIDList(llRegistriesThatNeedSaving);
     7338        markRegistriesModified();
    73897339        /* collect multiple errors */
    73907340        eik.restore();
    7391         mrc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
     7341        m->pVirtualBox->saveModifiedRegistries();
    73927342        eik.fetch();
    73937343    }
     
    81198069            ComObjPtr<Medium> pMedium;
    81208070            mrc = pParent->m->pVirtualBox->registerMedium(this, &pMedium,
    8121                                                           DeviceType_HardDisk,
    8122                                                           NULL /* llRegistriesThatNeedSaving */);
     8071                                                          DeviceType_HardDisk);
    81238072            Assert(this == pMedium);
    81248073            eik.fetch();
     
    81338082            eik.restore();
    81348083            ComObjPtr<Medium> pMedium;
    8135             mrc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk,
    8136                                                  NULL /* pllRegistriesThatNeedSaving */);
     8084            mrc = m->pVirtualBox->registerMedium(this, &pMedium, DeviceType_HardDisk);
    81378085            Assert(this == pMedium);
    81388086            eik.fetch();
     
    81668114    {
    81678115        // save the settings
    8168         GuidList llRegistriesThatNeedSaving;
    8169         addToRegistryIDList(llRegistriesThatNeedSaving);
     8116        markRegistriesModified();
    81708117        /* collect multiple errors */
    81718118        eik.restore();
    8172         mrc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
     8119        m->pVirtualBox->saveModifiedRegistries();
    81738120        eik.fetch();
    81748121    }
  • trunk/src/VBox/Main/src-server/SnapshotImpl.cpp

    r40418 r40432  
    13971397    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    13981398
    1399     GuidList llRegistriesThatNeedSaving;
    1400 
    14011399    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    14021400
     
    14851483        rc = createImplicitDiffs(aConsoleProgress,
    14861484                                 1,            // operation weight; must be the same as in Console::TakeSnapshot()
    1487                                  !!fTakingSnapshotOnline,
    1488                                  &llRegistriesThatNeedSaving);
     1485                                 !!fTakingSnapshotOnline);
    14891486        if (FAILED(rc))
    14901487            throw rc;
     
    14931490        // that got modified for the diff images
    14941491        alock.release();
    1495         mParent->saveRegistries(llRegistriesThatNeedSaving);
     1492        mParent->saveModifiedRegistries();
    14961493    }
    14971494    catch (HRESULT hrc)
     
    16231620    mConsoleTaskData.mLastState = MachineState_Null;
    16241621    mConsoleTaskData.mSnapshot.setNull();
     1622
     1623    machineLock.release();
     1624
     1625    mParent->saveModifiedRegistries();
    16251626
    16261627    return rc;
     
    17741775
    17751776    bool stateRestored = false;
    1776     GuidList llRegistriesThatNeedSaving;
    17771777
    17781778    try
     
    18411841            rc = createImplicitDiffs(aTask.pProgress,
    18421842                                     1,
    1843                                      false /* aOnline */,
    1844                                      &llRegistriesThatNeedSaving);
     1843                                     false /* aOnline */);
    18451844            if (FAILED(rc))
    18461845                throw rc;
     
    19491948        // unconditionally add the parent registry. We do similar in SessionMachine::EndTakingSnapshot
    19501949        // (mParent->saveSettings())
    1951         VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, mParent->getGlobalRegistryId());
     1950        mParent->markRegistryModified(mParent->getGlobalRegistryId());
    19521951
    19531952        // let go of the locks while we're deleting image files below
     
    19631962
    19641963            HRESULT rc2 = pMedium->deleteStorage(NULL /* aProgress */,
    1965                                                  true /* aWait */,
    1966                                                  &llRegistriesThatNeedSaving);
     1964                                                 true /* aWait */);
    19671965            // ignore errors here because we cannot roll back after saveSettings() above
    19681966            if (SUCCEEDED(rc2))
     
    19911989    }
    19921990
    1993     mParent->saveRegistries(llRegistriesThatNeedSaving);
     1991    mParent->saveModifiedRegistries();
    19941992
    19951993    /* set the result (this will try to fetch current error info on failure) */
     
    22922290    }
    22932291
     2292    HRESULT rc = S_OK;
    22942293    MediumDeleteRecList toDelete;
    2295 
    2296     HRESULT rc = S_OK;
    2297 
    2298     GuidList llRegistriesThatNeedSaving;
    2299 
    23002294    Guid snapshotId;
    23012295
     
    24992493
    25002494                // machine will need saving now
    2501                 VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, getId());
     2495                mParent->markRegistryModified(getId());
    25022496            }
    25032497        }
     
    25462540                    mLock.release();
    25472541                    rc = pMedium->deleteStorage(&aTask.pProgress,
    2548                                                 true /* aWait */,
    2549                                                 &llRegistriesThatNeedSaving);
     2542                                                true /* aWait */);
    25502543                    if (FAILED(rc))
    25512544                        throw rc;
     
    25802573                                               it->mpMediumLockList,
    25812574                                               &aTask.pProgress,
    2582                                                true /* aWait */,
    2583                                                &llRegistriesThatNeedSaving);
     2575                                               true /* aWait */);
    25842576                }
    25852577
     
    26742666
    26752667            // One attachment is merged, must save the settings
    2676             VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, getId());
     2668            mParent->markRegistryModified(getId());
    26772669
    26782670            // prevent calling cancelDeleteSnapshotMedium() for this attachment
     
    26932685            aTask.pSnapshot->uninit();
    26942686
    2695             VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, getId());
     2687            mParent->markRegistryModified(getId());
    26962688        }
    26972689    }
     
    27332725        updateMachineStateOnClient();
    27342726
    2735         mParent->saveRegistries(llRegistriesThatNeedSaving);
     2727        mParent->saveModifiedRegistries();
    27362728    }
    27372729
     
    32713263        // first, unregister the target since it may become a base
    32723264        // hard disk which needs re-registration
    3273         rc = mParent->unregisterMedium(pTarget, NULL /*&fNeedsGlobalSaveSettings*/);
     3265        rc = mParent->unregisterMedium(pTarget);
    32743266        AssertComRC(rc);
    32753267
     
    32823274
    32833275        // then, register again
    3284         rc = mParent->registerMedium(pTarget, &pTarget, DeviceType_HardDisk,
    3285                                      NULL /* pllRegistriesThatNeedSaving */);
     3276        rc = mParent->registerMedium(pTarget, &pTarget, DeviceType_HardDisk);
    32863277        AssertComRC(rc);
    32873278    }
     
    33563347        else
    33573348        {
    3358             rc = mParent->unregisterMedium(pMedium, NULL /*pfNeedsGlobalSaveSettings*/);
     3349            rc = mParent->unregisterMedium(pMedium);
    33593350            AssertComRC(rc);
    33603351
  • trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp

    r40262 r40432  
    185185        : pMainConfigFile(NULL),
    186186          uuidMediaRegistry("48024e5c-fdd9-470f-93af-ec29f7ea518c"),
     187          uRegistryNeedsSaving(0),
    187188          lockMachines(LOCKCLASS_LISTOFMACHINES),
    188189          allMachines(lockMachines),
     
    223224    // constant pseudo-machine ID for global media registry
    224225    const Guid                          uuidMediaRegistry;
     226
     227    // counter if global media registry needs saving, updated using atomic
     228    // operations, without requiring any locks
     229    uint64_t                            uRegistryNeedsSaving;
    225230
    226231    // const objects not requiring locking
     
    628633        if (FAILED(rc)) return rc;
    629634
    630         rc = registerMedium(pHardDisk, &pHardDisk, DeviceType_HardDisk,
    631                             NULL /* pllRegistriesThatNeedSaving */);
     635        rc = registerMedium(pHardDisk, &pHardDisk, DeviceType_HardDisk);
    632636        if (FAILED(rc)) return rc;
    633637    }
     
    649653        if (FAILED(rc)) return rc;
    650654
    651         rc = registerMedium(pImage, &pImage, DeviceType_DVD,
    652                             NULL /* pllRegistriesThatNeedSaving */);
     655        rc = registerMedium(pImage, &pImage, DeviceType_DVD);
    653656        if (FAILED(rc)) return rc;
    654657    }
     
    670673        if (FAILED(rc)) return rc;
    671674
    672         rc = registerMedium(pImage, &pImage, DeviceType_Floppy,
    673                             NULL /* pllRegistriesThatNeedSaving */);
     675        rc = registerMedium(pImage, &pImage, DeviceType_Floppy);
    674676        if (FAILED(rc)) return rc;
    675677    }
     
    682684void VirtualBox::uninit()
    683685{
     686    Assert(!m->uRegistryNeedsSaving);
     687    if (m->uRegistryNeedsSaving)
     688        saveSettings();
     689
    684690    /* Enclose the state transition Ready->InUninit->NotReady */
    685691    AutoUninitSpan autoUninitSpan(this);
     
    16521658                                format,
    16531659                                aLocation,
    1654                                 Guid::Empty,   // media registry: none yet
    1655                                 NULL /* pllRegistriesThatNeedSaving */);
     1660                                Guid::Empty /* media registry: none yet */);
    16561661
    16571662    if (SUCCEEDED(rc))
     
    17221727        if (SUCCEEDED(rc))
    17231728        {
    1724             rc = registerMedium(pMedium, &pMedium, deviceType,
    1725                                 NULL /* pllRegistriesThatNeedSaving */);
     1729            rc = registerMedium(pMedium, &pMedium, deviceType);
    17261730
    17271731            treeLock.release();
     
    35433547 *                  created.
    35443548 * @param argType   Either DeviceType_HardDisk, DeviceType_DVD or DeviceType_Floppy.
    3545  * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs of media registries that need saving.
    35463549 * @return
    35473550 */
    35483551HRESULT VirtualBox::registerMedium(const ComObjPtr<Medium> &pMedium,
    35493552                                   ComObjPtr<Medium> *ppMedium,
    3550                                    DeviceType_T argType,
    3551                                    GuidList *pllRegistriesThatNeedSaving)
     3553                                   DeviceType_T argType)
    35523554{
    35533555    AssertReturn(pMedium != NULL, E_INVALIDARG);
     
    36223624            m->mapHardDisks[id] = pMedium;
    36233625
    3624         if (pllRegistriesThatNeedSaving)
    3625             pMedium->addToRegistryIDList(*pllRegistriesThatNeedSaving);
    3626 
    36273626        *ppMedium = pMedium;
    36283627    }
     
    36443643 *
    36453644 * @param pMedium    Hard disk object to remove.
    3646  * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
    3647  *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
    36483645 *
    36493646 * @note Caller must hold the media tree lock for writing; in addition, this locks @a pMedium for reading
    36503647 */
    3651 HRESULT VirtualBox::unregisterMedium(Medium *pMedium,
    3652                                      GuidList *pllRegistriesThatNeedSaving)
     3648HRESULT VirtualBox::unregisterMedium(Medium *pMedium)
    36533649{
    36543650    AssertReturn(pMedium != NULL, E_INVALIDARG);
     
    37013697    }
    37023698
    3703     if (pllRegistriesThatNeedSaving)
    3704         pMedium->addToRegistryIDList(*pllRegistriesThatNeedSaving);
    3705 
    37063699    return S_OK;
    37073700}
     
    37773770        Log(("Closing medium %RTuuid\n", pMedium->getId().raw()));
    37783771        AutoCaller mac(pMedium);
    3779         pMedium->close(NULL /* pfNeedsGlobalSaveSettings*/, mac);
     3772        pMedium->close(mac);
    37803773    }
    37813774
     
    38133806     * become inaccessible.
    38143807     */
    3815     GuidList llRegistriesThatNeedSaving;
    38163808    {
    38173809        AutoReadLock tlock(getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
     
    38373829                    pMedium->addRegistry(*puuidBetter, true /* fRecurse */);
    38383830                    // 3) and make sure the registry is saved below
    3839                     VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, *puuidBetter);
     3831                    markRegistryModified(*puuidBetter);
    38403832                }
    38413833            }
     
    38433835    }
    38443836
    3845     saveRegistries(llRegistriesThatNeedSaving);
     3837    saveModifiedRegistries();
    38463838
    38473839    /* fire an event */
     
    38523844
    38533845/**
    3854  * Adds uuid to llRegistriesThatNeedSaving unless it's already on the list.
    3855  *
    3856  * @todo maybe there's something in libstdc++ for this
    3857  *
    3858  * @param llRegistriesThatNeedSaving
     3846 * Marks the registry for @a uuid as modified, so that it's saved in a later
     3847 * call to saveModifiedRegistries().
     3848 *
    38593849 * @param uuid
    38603850 */
    3861 /* static */
    3862 void VirtualBox::addGuidToListUniquely(GuidList &llRegistriesThatNeedSaving,
    3863                                        const Guid &uuid)
    3864 {
    3865     for (GuidList::const_iterator it = llRegistriesThatNeedSaving.begin();
    3866          it != llRegistriesThatNeedSaving.end();
    3867          ++it)
    3868     {
    3869         if (*it == uuid)
    3870             // uuid is already in list:
    3871             return;
    3872     }
    3873 
    3874     llRegistriesThatNeedSaving.push_back(uuid);
    3875 }
    3876 
    3877 /**
    3878  * Saves all settings files according to the given list of UUIDs, which are
    3879  * either machine IDs (in which case Machine::saveSettings is invoked) or
    3880  * the global registry UUID (in which case VirtualBox::saveSettings is invoked).
     3851void VirtualBox::markRegistryModified(const Guid &uuid)
     3852{
     3853    if (uuid == getGlobalRegistryId())
     3854        ASMAtomicIncU64(&m->uRegistryNeedsSaving);
     3855    else
     3856    {
     3857        ComObjPtr<Machine> pMachine;
     3858        HRESULT rc = findMachine(uuid,
     3859                                 false /* fPermitInaccessible */,
     3860                                 false /* aSetError */,
     3861                                 &pMachine);
     3862        if (SUCCEEDED(rc))
     3863        {
     3864            AutoCaller machineCaller(pMachine);
     3865            if (SUCCEEDED(machineCaller.rc()))
     3866                ASMAtomicIncU64(&pMachine->uRegistryNeedsSaving);
     3867        }
     3868    }
     3869}
     3870
     3871/**
     3872 * Saves all settings files according to the modified flags in the Machine
     3873 * objects and in the VirtualBox object.
    38813874 *
    38823875 * This locks machines and the VirtualBox object as necessary, so better not
    38833876 * hold any locks before calling this.
    38843877 *
    3885  * @param llRegistriesThatNeedSaving
    38863878 * @return
    38873879 */
    3888 HRESULT VirtualBox::saveRegistries(const GuidList &llRegistriesThatNeedSaving)
    3889 {
     3880void VirtualBox::saveModifiedRegistries()
     3881{
     3882    HRESULT rc = S_OK;
    38903883    bool fNeedsGlobalSettings = false;
    3891     HRESULT rc = S_OK;
    3892 
    3893     for (GuidList::const_iterator it = llRegistriesThatNeedSaving.begin();
    3894          it != llRegistriesThatNeedSaving.end();
     3884    uint64_t uOld;
     3885
     3886    for (MachinesOList::iterator it = m->allMachines.begin();
     3887         it != m->allMachines.end();
    38953888         ++it)
    38963889    {
    3897         const Guid &uuid = *it;
    3898 
    3899         if (uuid == getGlobalRegistryId())
    3900             fNeedsGlobalSettings = true;
    3901         else
    3902         {
    3903             // should be machine ID then:
    3904             ComObjPtr<Machine> pMachine;
    3905             rc = findMachine(uuid,
    3906                              false /* fPermitInaccessible */,
    3907                              false /* aSetError */,
    3908                              &pMachine);
    3909             if (SUCCEEDED(rc))
    3910             {
    3911                 AutoCaller autoCaller(pMachine);
    3912                 if (FAILED(autoCaller.rc())) return autoCaller.rc();
    3913                 AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
    3914                 rc = pMachine->saveSettings(&fNeedsGlobalSettings,
    3915                                             Machine::SaveS_Force);           // caller said save, so stop arguing
    3916             }
    3917 
    3918             if (FAILED(rc))
    3919                 return rc;
    3920         }
    3921     }
    3922 
    3923     if (fNeedsGlobalSettings)
    3924     {
    3925         AutoWriteLock vlock(this COMMA_LOCKVAL_SRC_POS);
     3890        const ComObjPtr<Machine> &pMachine = *it;
     3891
     3892        for (;;)
     3893        {
     3894            uOld = ASMAtomicReadU64(&pMachine->uRegistryNeedsSaving);
     3895            if (!uOld)
     3896                break;
     3897            if (ASMAtomicCmpXchgU64(&pMachine->uRegistryNeedsSaving, 0, uOld))
     3898                break;
     3899            ASMNopPause();
     3900        }
     3901        if (uOld)
     3902        {
     3903            AutoCaller autoCaller(pMachine);
     3904            if (FAILED(autoCaller.rc())) continue;
     3905            AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
     3906            rc = pMachine->saveSettings(&fNeedsGlobalSettings,
     3907                                        Machine::SaveS_Force);           // caller said save, so stop arguing
     3908        }
     3909    }
     3910
     3911    for (;;)
     3912    {
     3913        uOld = ASMAtomicReadU64(&m->uRegistryNeedsSaving);
     3914        if (!uOld)
     3915            break;
     3916        if (ASMAtomicCmpXchgU64(&m->uRegistryNeedsSaving, 0, uOld))
     3917            break;
     3918        ASMNopPause();
     3919    }
     3920    if (uOld || fNeedsGlobalSettings)
     3921    {
     3922        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    39263923        rc = saveSettings();
    39273924    }
    3928 
    3929     return S_OK;
    39303925}
    39313926
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