office-gobmx/configmgr/source/treecache/cachedata.cxx
Rüdiger Timm d8a35db6f2 INTEGRATION: CWS changefileheader (1.8.16); FILE MERGED
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.
2008-04-11 12:37:30 +00:00

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