d8a35db6f2
2008/04/01 15:06:54 thb 1.8.16.3: #i85898# Stripping all external header guards 2008/04/01 12:27:34 thb 1.8.16.2: #i85898# Stripping all external header guards 2008/03/31 12:22:53 rt 1.8.16.1: #i87441# Change license header to LPGL v3.
506 lines
19 KiB
C++
506 lines
19 KiB
C++
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2008 by Sun Microsystems, Inc.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: cachedata.cxx,v $
|
|
* $Revision: 1.9 $
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_configmgr.hxx"
|
|
|
|
#include "cachedata.hxx"
|
|
#include "node.hxx"
|
|
#include "nodeaccess.hxx"
|
|
#include "updatehelper.hxx"
|
|
#include "tracer.hxx"
|
|
#include <osl/diagnose.h>
|
|
#include "configpath.hxx"
|
|
|
|
namespace configmgr
|
|
{
|
|
using namespace configuration;
|
|
// ---------------------------- Client Acquire helper ----------------------------
|
|
|
|
struct CacheLineClientRef
|
|
{
|
|
CacheLineRef xModule;
|
|
|
|
CacheLineClientRef(CacheLineRef const& _xModule)
|
|
: xModule(_xModule)
|
|
{
|
|
if (xModule.is())
|
|
xModule->clientAcquire();
|
|
}
|
|
|
|
~CacheLineClientRef() // release the client reference unless it was 'kept'
|
|
{
|
|
if (xModule.is())
|
|
xModule->clientRelease();
|
|
}
|
|
|
|
void rebind(CacheLineRef const& _xModule)
|
|
{
|
|
if (_xModule.is())
|
|
_xModule->clientAcquire();
|
|
if (xModule.is())
|
|
xModule->clientRelease();
|
|
xModule = _xModule;
|
|
}
|
|
|
|
/// release the contained module so that the client reference will be kept active
|
|
void keep()
|
|
{
|
|
xModule.clear();
|
|
OSL_ASSERT(!xModule.is());
|
|
}
|
|
|
|
/// return the contained module so that the client reference will be kept active
|
|
CacheLineRef keepModule()
|
|
{
|
|
CacheLineRef xRet = xModule;
|
|
this->keep();
|
|
return xRet;
|
|
}
|
|
private:
|
|
CacheLineClientRef(CacheLineClientRef const& );
|
|
CacheLineClientRef& operator=(CacheLineClientRef const& );
|
|
|
|
};
|
|
|
|
// -----------------------------------------------------------------------------
|
|
static inline CacheLine::Name implExtractModuleName(CacheLine::Path const& aConfigPath)
|
|
{
|
|
return aConfigPath.getModuleName();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
CacheData::CacheData()
|
|
{
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
CacheData::~CacheData()
|
|
{
|
|
CFG_TRACE_INFO("Discarding CacheData (Still holding %d module trees)", int (m_aModules.size()) );
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
CacheLine::Name CacheData::extractModuleName(CacheLine::Path const& _aPath)
|
|
{
|
|
return implExtractModuleName(_aPath);
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
inline
|
|
CacheLineRef CacheData::internalGetModule(const CacheLine::Name& _aModuleName ) const
|
|
{
|
|
OSL_ASSERT(!_aModuleName.isEmpty());
|
|
|
|
ModuleList::const_iterator it = m_aModules.find(_aModuleName);
|
|
|
|
return it!=m_aModules.end() ? it->second : CacheLineRef();
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
inline
|
|
CacheLineRef CacheData::internalGetModule(const CacheLine::Path& _aPath) const
|
|
{
|
|
return internalGetModule( implExtractModuleName(_aPath) );
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
inline
|
|
void CacheData::internalAddModule(const CacheLine::Name& _aName, const CacheLineRef & _aModule)
|
|
{
|
|
//OSL_PRECOND(m_aModules.find(_aName) == m_aModules.end(), "ERROR: Module already present in CacheData");
|
|
|
|
m_aModules[_aName] = _aModule;
|
|
|
|
CFG_TRACE_INFO("CacheData Data: Added new module tree for module %s", OUSTRING2ASCII(_aName.toString()) );
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
// -----------------------------------------------------------------------------
|
|
|
|
CacheLineRef CacheData::internalAttachModule(data::TreeAddress _aLocation, const CacheLine::Name& _aName) CFG_UNO_THROW_RTE( )
|
|
{
|
|
CacheLineRef aNewModule = doCreateAttachedModule(_aLocation,_aName);
|
|
|
|
internalAddModule( _aName, aNewModule );
|
|
|
|
return aNewModule;
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
void CacheData::attachModule(data::TreeAddress _aLocation, CacheLine::Name const & _aModule)
|
|
{
|
|
this->internalAttachModule(_aLocation,_aModule);
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
|
|
CacheLineRef CacheData::doCreateAttachedModule(data::TreeAddress _aLocation, const CacheLine::Name& _aName) CFG_UNO_THROW_RTE( )
|
|
{
|
|
return CacheLine::createAttached( _aName, _aLocation );
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
/// gets a data segment reference for the given path if exists
|
|
data::TreeAddress CacheData::getTreeAddress(const CacheLine::Name & _aModule) const
|
|
{
|
|
CacheLineRef aModule = internalGetModule(_aModule);
|
|
|
|
return aModule.is() ? aModule->getTreeAddress() : NULL;
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
|
|
bool CacheData::hasModule(const CacheLine::Name & _aModule) const
|
|
{
|
|
CacheLineRef aModule = internalGetModule(_aModule);
|
|
|
|
return aModule.is() && !aModule->isEmpty();
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
|
|
bool CacheData::hasModuleDefaults(const CacheLine::Name & _aModule) const
|
|
{
|
|
CacheLineRef aModule = internalGetModule(_aModule);
|
|
|
|
return aModule.is() && !aModule->hasDefaults();
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
|
|
data::TreeAddress CacheData::internalGetPartialTree(const CacheLine::Path& aComponentName ) const
|
|
{
|
|
CacheLineRef xModule = internalGetModule(aComponentName);
|
|
|
|
if ( !xModule.is() )
|
|
return NULL;
|
|
|
|
data::TreeAddress pSubtree = xModule->getPartialTree(aComponentName);
|
|
|
|
OSL_ENSURE( pSubtree == NULL || xModule->clientReferences() != 0 ,
|
|
"WARNING: returning subtree from module without clients\n" );
|
|
#ifdef CFG_ENABLE_TRACING
|
|
if( pSubtree != NULL && xModule->clientReferences() == 0)
|
|
{
|
|
CFG_TRACE_WARNING("CacheData data: returning subtree %s from module without clients", OUSTRING2ASCII( aComponentName.toString() ) );
|
|
}
|
|
#endif // CFG_ENABLE_TRACING
|
|
|
|
return pSubtree;
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
data::NodeAddress CacheData::internalGetNode(const CacheLine::Path& aComponentName ) const
|
|
{
|
|
CacheLineRef xModule = internalGetModule(aComponentName);
|
|
|
|
if ( !xModule.is() )
|
|
return data::NodeAddress();
|
|
|
|
if ( xModule->isEmpty() )
|
|
return data::NodeAddress();
|
|
|
|
data::NodeAddress pNode = xModule->getNode(aComponentName);
|
|
|
|
OSL_ENSURE( pNode == NULL || xModule->clientReferences() != 0,
|
|
"WARNING: returning node from module without clients\n" );
|
|
#ifdef CFG_ENABLE_TRACING
|
|
if( pNode != NULL && xModule->clientReferences() == 0)
|
|
{
|
|
CFG_TRACE_WARNING("CacheData data: returning node %s from module without clients", OUSTRING2ASCII( aComponentName.toString() ) );
|
|
}
|
|
#endif // CFG_ENABLE_TRACING
|
|
|
|
return pNode;
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
// -----------------------------------------------------------------------------
|
|
bool CacheData::acquireModule(CacheLine::Name const & _aModule)
|
|
{
|
|
CacheLineRef xModule = internalGetModule(_aModule);
|
|
|
|
if (xModule.is())
|
|
{
|
|
CacheLineClientRef aClientRef(xModule);
|
|
aClientRef.keep();
|
|
}
|
|
|
|
return xModule.is();
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
data::NodeAddress CacheData::acquireNode(CacheLine::Path const& _aPath)
|
|
{
|
|
CacheLineClientRef aClientRef(internalGetModule(_aPath));
|
|
|
|
data::NodeAddress aNodeAddr = internalGetNode(_aPath);
|
|
|
|
if (sharable::Node const * pNode = aNodeAddr)
|
|
{
|
|
if (pNode->isValue())
|
|
aNodeAddr = data::NodeAddress(); // invalid: cannot acquire single value
|
|
}
|
|
else
|
|
OSL_ASSERT( aNodeAddr == NULL );
|
|
|
|
if (aNodeAddr != NULL)
|
|
aClientRef.keep();
|
|
|
|
return aNodeAddr;
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
bool CacheData::insertDefaults( backend::NodeInstance const & _aDefaultInstance) CFG_UNO_THROW_RTE( )
|
|
{
|
|
OSL_PRECOND(_aDefaultInstance.data().get(), "insertDefaults: Data must not be NULL");
|
|
OSL_PRECOND(_aDefaultInstance.root().isModuleRoot(), "insertDefaults: Default tree being added must be for module");
|
|
|
|
// we should already have the module in cache !
|
|
CacheLineRef xModule = internalGetModule(_aDefaultInstance.root().location());
|
|
|
|
OSL_ENSURE( xModule.is(), "CacheData::insertDefaults: No module to insert the defaults to - where did the data segment come from ?");
|
|
|
|
if (!xModule.is()) return false;
|
|
|
|
// make sure to keep the module alive
|
|
CacheLineClientRef( xModule ).keep();
|
|
|
|
data::TreeAddress aResultTree = xModule->insertDefaults(_aDefaultInstance);
|
|
|
|
return aResultTree != NULL;
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void CacheData::applyUpdate( backend::UpdateInstance & _anUpdate ) CFG_UNO_THROW_RTE( )
|
|
{
|
|
// request the subtree, atleast one level must exist!
|
|
data::NodeAddress aNodeAddr = internalGetNode(_anUpdate.root().location());
|
|
|
|
if (aNodeAddr != NULL)
|
|
{
|
|
applyUpdateToTree(*_anUpdate.data(),aNodeAddr);
|
|
}
|
|
else
|
|
{
|
|
OSL_ENSURE(false, "CacheData::applyUpdate called for non-existing tree");
|
|
OUString aStr(RTL_CONSTASCII_USTRINGPARAM("CacheData: update to non-existing node: "));
|
|
|
|
aStr += _anUpdate.root().toString();
|
|
|
|
throw uno::RuntimeException(aStr,0);
|
|
}
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
oslInterlockedCount CacheData::releaseModule( CacheLine::Name const & _aModule, bool _bKeepDeadModule )
|
|
{
|
|
CacheLineRef xModule = internalGetModule(_aModule);
|
|
|
|
const oslInterlockedCount c_nErrorCount = -1;
|
|
|
|
OSL_ENSURE( xModule.is(), "ERROR: Releasing non-existent subtree");
|
|
if ( !xModule.is()) return c_nErrorCount;
|
|
|
|
OSL_ENSURE( xModule->clientReferences() > 0, "ERROR: Releasing non-referenced subtree");
|
|
|
|
oslInterlockedCount nResult = xModule->clientRelease();
|
|
|
|
if (nResult == 0 && !_bKeepDeadModule)
|
|
{
|
|
m_aModules.erase( _aModule );
|
|
}
|
|
return nResult;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
data::TreeAddress CacheData::getTemplateTree(CacheLine::Path const& aTemplateName ) const
|
|
{
|
|
return internalGetPartialTree(aTemplateName);
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
data::NodeAddress CacheData::getNode(const CacheLine::Path& _rPath)
|
|
{
|
|
return internalGetNode(_rPath);
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
bool CacheData::hasNode(const CacheLine::Path& _rPath) const
|
|
{
|
|
return internalGetNode(_rPath) != NULL;
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
data::TreeAddress TemplateCacheData::addTemplates( backend::ComponentData const & _aComponentInstance) CFG_UNO_THROW_RTE( )
|
|
{
|
|
OSL_PRECOND(_aComponentInstance.data.get(), "addTemplates: Data must not be NULL");
|
|
// we should already have the module in cache !
|
|
CacheLine::Name aModuleName ( _aComponentInstance.name);
|
|
CacheLineRef xModule = internalGetModule(aModuleName);
|
|
|
|
OSL_ENSURE( xModule.is(), "ExtendedCacheData::addTemplates: No module to add the templates to - where did the data segment come from ?");
|
|
|
|
if (!xModule.is()) return NULL;
|
|
|
|
// make sure to keep the module alive
|
|
CacheLineClientRef( xModule ).keep();
|
|
|
|
static const OUString aDummyTemplateName(RTL_CONSTASCII_USTRINGPARAM("cfg:Template"));
|
|
static const OUString aDummyTemplateModule(RTL_CONSTASCII_USTRINGPARAM("cfg:Templates"));
|
|
_aComponentInstance.data->makeSetNode(aDummyTemplateName,aDummyTemplateModule);
|
|
|
|
data::TreeAddress aResult = xModule->setComponentData(_aComponentInstance, true);
|
|
|
|
OSL_ASSERT(aResult != NULL);
|
|
|
|
return aResult;
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
CacheLineRef TemplateCacheData::doCreateAttachedModule(data::TreeAddress _aLocation, const CacheLine::Name& _aName) CFG_UNO_THROW_RTE( )
|
|
{
|
|
CacheLineRef aNewModule = CacheLine::createAttached(_aName, _aLocation);
|
|
|
|
return aNewModule.get();
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void TemplateCacheData::createModule(const CacheLine::Name& _aModule) CFG_UNO_THROW_RTE()
|
|
{
|
|
CacheLineRef aNewModule = CacheLine::createNew(_aModule);
|
|
|
|
internalAddModule( _aModule, aNewModule.get() );
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
// -----------------------------------------------------------------------------
|
|
inline
|
|
ExtendedCacheLineRef ExtendedCacheData::implExtended(const CacheLineRef& _aSimpleRef) const
|
|
{
|
|
CacheLine * pBasic = _aSimpleRef.get();
|
|
ExtendedCacheLine * pExtended = static_cast<ExtendedCacheLine *>(pBasic);
|
|
return ExtendedCacheLineRef(pExtended);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
CacheLineRef ExtendedCacheData::doCreateAttachedModule(data::TreeAddress _aLocation, const CacheLine::Name& _aName) CFG_UNO_THROW_RTE( )
|
|
{
|
|
ExtendedCacheLineRef aNewModule =
|
|
ExtendedCacheLine::createAttached(_aName, _aLocation);
|
|
|
|
return CacheLineRef( aNewModule.get() );
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void ExtendedCacheData::createModule(const CacheLine::Name& _aModule) CFG_UNO_THROW_RTE()
|
|
{
|
|
ExtendedCacheLineRef aNewModule = ExtendedCacheLine::createNew(_aModule);
|
|
|
|
internalAddModule( _aModule, aNewModule.get() );
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
data::TreeAddress ExtendedCacheData::addComponentData(backend::ComponentInstance const & _aComponentInstance,
|
|
bool _bWithDefaults) CFG_UNO_THROW_RTE( )
|
|
{
|
|
OSL_PRECOND(_aComponentInstance.data().get(), "addComponentData: Data must not be NULL");
|
|
// we should already have the module in cache !
|
|
//CacheLineRef xModule = internalGetModule(_aNodeInstance.root().location());
|
|
CacheLineRef xModule = internalGetModule(_aComponentInstance.component() );
|
|
|
|
OSL_ENSURE( xModule.is(), "ExtendedCacheData::addComponentData: No module to add the subtree to - where did the data segment come from ?");
|
|
|
|
if (!xModule.is()) return NULL;
|
|
|
|
CacheLineClientRef aClientRef( xModule );
|
|
|
|
data::TreeAddress aResult = xModule->setComponentData(_aComponentInstance.componentNodeData(), _bWithDefaults);
|
|
|
|
OSL_ASSERT(aResult != NULL);
|
|
|
|
if (aResult != NULL) aClientRef.keep();
|
|
|
|
return aResult;
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void ExtendedCacheData::addPending(backend::ConstUpdateInstance const & _anUpdate) CFG_UNO_THROW_RTE( )
|
|
{
|
|
// do we already have the module in cache ?
|
|
CacheLineRef xModule = internalGetModule(_anUpdate.root().location());
|
|
|
|
if (xModule.is())
|
|
{
|
|
implExtended(xModule)->addPending(_anUpdate);
|
|
}
|
|
else
|
|
{
|
|
OSL_ENSURE(false, "We can only change Nodes if we already know something about it. So this must be a big bug.");
|
|
}
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
std::auto_ptr<SubtreeChange> ExtendedCacheData::releasePending(CacheLine::Name const& _aModule)
|
|
{
|
|
ExtendedCacheLineRef xModule = implExtended(internalGetModule(_aModule));
|
|
|
|
if (xModule.is())
|
|
{
|
|
if (xModule->hasPending())
|
|
return xModule->releasePending();
|
|
else
|
|
return std::auto_ptr<SubtreeChange>();
|
|
}
|
|
else
|
|
{
|
|
OSL_ENSURE(false, "We can only get Nodes if we already know something about it.");
|
|
}
|
|
return std::auto_ptr<SubtreeChange>();
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
bool ExtendedCacheData::hasPending(CacheLine::Name const & _aModule)
|
|
{
|
|
ExtendedCacheLineRef xModule = implExtended(internalGetModule(_aModule));
|
|
|
|
return xModule.is() && xModule->hasPending();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void ExtendedCacheData::findPendingModules( PendingModuleList & _rPendingList )
|
|
{
|
|
ModuleList& rModules = CacheData::accessModuleList();
|
|
for (ModuleList::iterator it = rModules.begin();
|
|
it != rModules.end();
|
|
++it)
|
|
{
|
|
OSL_ASSERT( it->second.is() );
|
|
if ( implExtended(it->second)->hasPending() )
|
|
_rPendingList.push_back( it->first );
|
|
}
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
} // namespace configmgr
|
|
|
|
|