VirtualBox

Changeset 75663 in vbox for trunk/src/VBox/Main/src-server


Ignore:
Timestamp:
Nov 22, 2018 2:00:59 PM (6 years ago)
Author:
vboxsync
Message:

Main/ExtPackManager+CloudProviderManager+VirtualBox: Handle runtime install and uninstall of extension packs containing cloud providers. This is a safeguard against uninstalling active cloud providers (which would cause crashes), and makes the install more convcenient. At the same time it eliminated the need to have a special "detect all cloud providers" logic when VBoxSVC is started. It achieves perfect singleton property of the per-extpack CloudProviderManager and the related CloudProvider objects. Nothing is ever created twice (which would cause trouble with coordinating e.g. the profile file updates).

Location:
trunk/src/VBox/Main/src-server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/CloudProviderManagerImpl.cpp

    r74926 r75663  
    2525#include "Logging.h"
    2626
    27 using namespace std;
    2827
    2928////////////////////////////////////////////////////////////////////////////////
     
    5352}
    5453
    55 HRESULT CloudProviderManager::init(VirtualBox *aParent)
     54HRESULT CloudProviderManager::init()
    5655{
    5756    // Enclose the state transition NotReady->InInit->Ready.
     
    6160    m_apCloudProviders.clear();
    6261
    63 #ifdef VBOX_WITH_EXTPACK
    64     // Engage the extension pack manager and get all the implementations of
    65     // this class and all implemented cloud providers.
    66     ExtPackManager *pExtPackMgr = aParent->i_getExtPackManager();
    67     mpExtPackMgr = pExtPackMgr;
    68     if (pExtPackMgr)
    69     {
    70         mcExtPackMgrUpdate = pExtPackMgr->i_getUpdateCounter();
    71         // Make sure that the current value doesn't match, forcing a refresh.
    72         mcExtPackMgrUpdate--;
    73         i_refreshProviders();
    74     }
    75 #else
    76     RT_NOREF(aParent);
    77 #endif
    78 
    7962    autoInitSpan.setSucceeded();
    8063    return S_OK;
     
    9073
    9174#ifdef VBOX_WITH_EXTPACK
    92 void CloudProviderManager::i_refreshProviders()
    93 {
    94     uint64_t cExtPackMgrUpdate;
    95     {
    96         AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    97         if (mpExtPackMgr.isNull())
    98             return;
    99         cExtPackMgrUpdate = mpExtPackMgr->i_getUpdateCounter();
    100         if (cExtPackMgrUpdate == mcExtPackMgrUpdate)
    101             return;
    102     }
     75bool CloudProviderManager::i_canRemoveExtPack(IExtPack *aExtPack)
     76{
     77    AssertReturn(aExtPack, false);
    10378
    10479    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    105     // Reread the current value to figure out if some other thead did the work
    106     // already before this thread got hold of the write lock.
    107     cExtPackMgrUpdate = mpExtPackMgr->i_getUpdateCounter();
    108     if (cExtPackMgrUpdate == mcExtPackMgrUpdate)
    109         return;
    110     mcExtPackMgrUpdate = cExtPackMgrUpdate;
    111 
    112     if (!m_mapCloudProviderManagers.empty())
    113     {
    114         /// @todo The code below will need to be extended to handle extpack
    115         // install and uninstall safely (and the latter needs non-trivial
    116         // checks if any extpack related cloud activity is pending.
    117         return;
    118     }
    119 
    120     std::vector<ComPtr<IUnknown> > apObjects;
     80
     81    // If any cloud provider in this extension pack fails to prepare the
     82    // uninstall it and the cloud provider will be kept, so that the user
     83    // can retry safely later. All other cloud providers in this extpack
     84    // will be done as usual. No attempt is made to bring back the other
     85    // cloud providers into working shape.
     86
     87    bool fRes = true;
     88    Bstr bstrName;
     89    aExtPack->GetName(bstrName.asOutParam());
     90    Utf8Str strName(bstrName);
     91    ExtPackNameCloudProviderManagerMap::iterator it = m_mapCloudProviderManagers.find(strName);
     92    if (it != m_mapCloudProviderManagers.end())
     93    {
     94        ComPtr<ICloudProviderManager> pTmp(it->second);
     95
     96        Assert(m_astrExtPackNames.size() == m_apCloudProviders.size());
     97        for (size_t i = 0; i < m_astrExtPackNames.size(); )
     98        {
     99            if (m_astrExtPackNames[i] != strName)
     100            {
     101                i++;
     102                continue;
     103            }
     104
     105            // pTmpProvider will point to an object with refcount > 0 until
     106            // the ComPtr is removed from m_apCloudProviders.
     107            HRESULT hrc = S_OK;
     108            ULONG uRefCnt = 1;
     109            ICloudProvider *pTmpProvider(m_apCloudProviders[i]);
     110            if (pTmpProvider)
     111            {
     112                hrc = pTmpProvider->PrepareUninstall();
     113                // Sanity check the refcount, it should be 1 at this point.
     114                pTmpProvider->AddRef();
     115                uRefCnt = pTmpProvider->Release();
     116                Assert(uRefCnt == 1);
     117            }
     118            if (SUCCEEDED(hrc) && uRefCnt == 1)
     119            {
     120                m_astrExtPackNames.erase(m_astrExtPackNames.begin() + i);
     121                m_apCloudProviders.erase(m_apCloudProviders.begin() + i);
     122            }
     123            else
     124            {
     125                LogRel(("CloudProviderManager: provider '%s' blocks extpack uninstall, result=%Rhrc, refcount=%u\n", strName.c_str(), hrc, uRefCnt));
     126                fRes = false;
     127                i++;
     128            }
     129        }
     130
     131        if (fRes)
     132            m_mapCloudProviderManagers.erase(it);
     133    }
     134
     135    return fRes;
     136}
     137
     138void CloudProviderManager::i_addExtPack(IExtPack *aExtPack)
     139{
     140    AssertReturnVoid(aExtPack);
     141
     142    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     143
     144    Bstr bstrName;
     145    aExtPack->GetName(bstrName.asOutParam());
     146    Utf8Str strName(bstrName);
     147    ComPtr<IUnknown> pObj;
    121148    std::vector<com::Utf8Str> astrExtPackNames;
    122149    com::Guid idObj(COM_IIDOF(ICloudProviderManager));
    123     mpExtPackMgr->i_queryObjects(idObj.toString(), apObjects, &astrExtPackNames);
    124     for (unsigned i = 0; i < apObjects.size(); i++)
    125     {
    126         ComPtr<ICloudProviderManager> pTmp;
    127         HRESULT hrc = apObjects[i].queryInterfaceTo(pTmp.asOutParam());
    128         if (SUCCEEDED(hrc))
    129             m_mapCloudProviderManagers[astrExtPackNames[i]] = pTmp;
    130         SafeIfaceArray<ICloudProvider> apProvidersFromCurrExtPack;
    131         hrc = pTmp->COMGETTER(Providers)(ComSafeArrayAsOutParam(apProvidersFromCurrExtPack));
    132         if (SUCCEEDED(hrc))
    133         {
    134             for (unsigned j = 0; j < apProvidersFromCurrExtPack.size(); j++)
    135                 m_apCloudProviders.push_back(apProvidersFromCurrExtPack[i]);
    136         }
     150    HRESULT hrc = aExtPack->QueryObject(Bstr(idObj.toString()).raw(), pObj.asOutParam());
     151    if (FAILED(hrc))
     152        return;
     153
     154    ComPtr<ICloudProviderManager> pTmp(pObj);
     155    if (pTmp.isNull())
     156        return;
     157
     158    SafeIfaceArray<ICloudProvider> apProvidersFromCurrExtPack;
     159    hrc = pTmp->COMGETTER(Providers)(ComSafeArrayAsOutParam(apProvidersFromCurrExtPack));
     160    if (FAILED(hrc))
     161        return;
     162
     163    m_mapCloudProviderManagers[strName] = pTmp;
     164    for (unsigned i = 0; i < apProvidersFromCurrExtPack.size(); i++)
     165    {
     166        Assert(m_astrExtPackNames.size() == m_apCloudProviders.size());
     167        m_astrExtPackNames.push_back(strName);
     168        m_apCloudProviders.push_back(apProvidersFromCurrExtPack[i]);
    137169    }
    138170}
  • trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp

    r75380 r75663  
    555555        rc = unconst(m->pCloudProviderManager).createObject();
    556556        if (SUCCEEDED(rc))
    557             rc = m->pCloudProviderManager->init(this);
     557            rc = m->pCloudProviderManager->init();
    558558        ComAssertComRCThrowRC(rc);
    559559        if (FAILED(rc)) throw rc;
     
    37683768}
    37693769
     3770CloudProviderManager *VirtualBox::i_getCloudProviderManager() const
     3771{
     3772    return m->pCloudProviderManager;
     3773}
     3774
    37703775#ifdef VBOX_WITH_EXTPACK
    37713776/**
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