update dev300-m58
[ooovba.git] / configmgr / source / treecache / cachedata.cxx
blob244614426da41207172293e3b0dc177a3ef1cce3
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cachedata.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
34 #include "cachedata.hxx"
35 #include "node.hxx"
36 #include "updatehelper.hxx"
37 #include "tracer.hxx"
38 #include <osl/diagnose.h>
39 #include "configpath.hxx"
41 namespace configmgr
43 // ---------------------------- Client Acquire helper ----------------------------
45 struct CacheLineClientRef
47 rtl::Reference<CacheLine> xModule;
49 CacheLineClientRef(rtl::Reference<CacheLine> const& _xModule)
50 : xModule(_xModule)
52 if (xModule.is())
53 xModule->clientAcquire();
56 ~CacheLineClientRef() // release the client reference unless it was 'kept'
58 if (xModule.is())
59 xModule->clientRelease();
62 void rebind(rtl::Reference<CacheLine> const& _xModule)
64 if (_xModule.is())
65 _xModule->clientAcquire();
66 if (xModule.is())
67 xModule->clientRelease();
68 xModule = _xModule;
71 /// release the contained module so that the client reference will be kept active
72 void keep()
74 xModule.clear();
75 OSL_ASSERT(!xModule.is());
78 /// return the contained module so that the client reference will be kept active
79 rtl::Reference<CacheLine> keepModule()
81 rtl::Reference<CacheLine> xRet = xModule;
82 this->keep();
83 return xRet;
85 private:
86 CacheLineClientRef(CacheLineClientRef const& );
87 CacheLineClientRef& operator=(CacheLineClientRef const& );
91 // -----------------------------------------------------------------------------
92 static inline rtl::OUString implExtractModuleName(configuration::AbsolutePath const& aConfigPath)
94 return aConfigPath.getModuleName();
97 // -----------------------------------------------------------------------------
99 CacheData::CacheData()
102 // -----------------------------------------------------------------------------
104 CacheData::~CacheData()
106 CFG_TRACE_INFO("Discarding CacheData (Still holding %d module trees)", int (m_aModules.size()) );
108 // -----------------------------------------------------------------------------
109 inline
110 rtl::Reference<CacheLine> CacheData::internalGetModule(rtl::OUString const & _aModuleName ) const
112 OSL_ASSERT(_aModuleName.getLength() != 0);
114 ModuleList::const_iterator it = m_aModules.find(_aModuleName);
116 return it!=m_aModules.end() ? it->second : rtl::Reference<CacheLine>();
118 // -----------------------------------------------------------------------------
119 inline
120 rtl::Reference<CacheLine> CacheData::internalGetModule(const configuration::AbsolutePath& _aPath) const
122 return internalGetModule( implExtractModuleName(_aPath) );
124 // -----------------------------------------------------------------------------
126 inline
127 void CacheData::internalAddModule(rtl::OUString const & _aName, const rtl::Reference<CacheLine> & _aModule)
129 //OSL_PRECOND(m_aModules.find(_aName) == m_aModules.end(), "ERROR: Module already present in CacheData");
131 m_aModules[_aName] = _aModule;
133 CFG_TRACE_INFO("CacheData Data: Added new module tree for module %s", OUSTRING2ASCII(_aName) );
135 // -----------------------------------------------------------------------------
136 // -----------------------------------------------------------------------------
138 rtl::Reference<CacheLine> CacheData::internalAttachModule(sharable::TreeFragment * _aLocation, rtl::OUString const & _aName) SAL_THROW((com::sun::star::uno::RuntimeException))
140 rtl::Reference<CacheLine> aNewModule = doCreateAttachedModule(_aLocation,_aName);
142 internalAddModule( _aName, aNewModule );
144 return aNewModule;
147 // -------------------------------------------------------------------------
149 void CacheData::attachModule(sharable::TreeFragment * _aLocation, rtl::OUString const & _aModule)
151 this->internalAttachModule(_aLocation,_aModule);
153 // -------------------------------------------------------------------------
155 rtl::Reference<CacheLine> CacheData::doCreateAttachedModule(sharable::TreeFragment * _aLocation, rtl::OUString const & _aName) SAL_THROW((com::sun::star::uno::RuntimeException))
157 return CacheLine::createAttached( _aName, _aLocation );
159 // -----------------------------------------------------------------------------
161 /// gets a data segment reference for the given path if exists
162 sharable::TreeFragment * CacheData::getTreeAddress(rtl::OUString const & _aModule) const
164 rtl::Reference<CacheLine> aModule = internalGetModule(_aModule);
166 return aModule.is() ? aModule->getTreeAddress() : NULL;
168 // -------------------------------------------------------------------------
170 bool CacheData::hasModule(rtl::OUString const & _aModule) const
172 rtl::Reference<CacheLine> aModule = internalGetModule(_aModule);
174 return aModule.is() && !aModule->isEmpty();
176 // -------------------------------------------------------------------------
178 bool CacheData::hasModuleDefaults(rtl::OUString const & _aModule) const
180 rtl::Reference<CacheLine> aModule = internalGetModule(_aModule);
182 return aModule.is() && !aModule->hasDefaults();
184 // -------------------------------------------------------------------------
186 sharable::TreeFragment * CacheData::internalGetPartialTree(const configuration::AbsolutePath& aComponentName ) const
188 rtl::Reference<CacheLine> xModule = internalGetModule(aComponentName);
190 if ( !xModule.is() )
191 return NULL;
193 sharable::TreeFragment * pSubtree = xModule->getPartialTree(aComponentName);
195 OSL_ENSURE( pSubtree == NULL || xModule->clientReferences() != 0 ,
196 "WARNING: returning subtree from module without clients\n" );
197 #ifdef CFG_ENABLE_TRACING
198 if( pSubtree != NULL && xModule->clientReferences() == 0)
200 CFG_TRACE_WARNING("CacheData data: returning subtree %s from module without clients", OUSTRING2ASCII( aComponentName.toString() ) );
202 #endif // CFG_ENABLE_TRACING
204 return pSubtree;
206 // -----------------------------------------------------------------------------
207 sharable::Node * CacheData::internalGetNode(const configuration::AbsolutePath& aComponentName ) const
209 rtl::Reference<CacheLine> xModule = internalGetModule(aComponentName);
211 if ( !xModule.is() )
212 return 0;
214 if ( xModule->isEmpty() )
215 return 0;
217 sharable::Node * pNode = xModule->getNode(aComponentName);
219 OSL_ENSURE( pNode == NULL || xModule->clientReferences() != 0,
220 "WARNING: returning node from module without clients\n" );
221 #ifdef CFG_ENABLE_TRACING
222 if( pNode != NULL && xModule->clientReferences() == 0)
224 CFG_TRACE_WARNING("CacheData data: returning node %s from module without clients", OUSTRING2ASCII( aComponentName.toString() ) );
226 #endif // CFG_ENABLE_TRACING
228 return pNode;
230 // -----------------------------------------------------------------------------
231 // -----------------------------------------------------------------------------
232 bool CacheData::acquireModule(rtl::OUString const & _aModule)
234 rtl::Reference<CacheLine> xModule = internalGetModule(_aModule);
236 if (xModule.is())
238 CacheLineClientRef aClientRef(xModule);
239 aClientRef.keep();
242 return xModule.is();
244 // -----------------------------------------------------------------------------
245 sharable::Node * CacheData::acquireNode(configuration::AbsolutePath const& _aPath)
247 CacheLineClientRef aClientRef(internalGetModule(_aPath));
249 sharable::Node * aNodeAddr = internalGetNode(_aPath);
251 if (sharable::Node const * pNode = aNodeAddr)
253 if (pNode->isValue())
254 aNodeAddr = 0; // invalid: cannot acquire single value
256 else
257 OSL_ASSERT( aNodeAddr == NULL );
259 if (aNodeAddr != NULL)
260 aClientRef.keep();
262 return aNodeAddr;
264 // -----------------------------------------------------------------------------
266 bool CacheData::insertDefaults( backend::NodeInstance const & _aDefaultInstance) SAL_THROW((com::sun::star::uno::RuntimeException))
268 OSL_PRECOND(_aDefaultInstance.data().get(), "insertDefaults: Data must not be NULL");
269 OSL_PRECOND(_aDefaultInstance.root().getDepth() == 1, "insertDefaults: Default tree being added must be for module");
271 // we should already have the module in cache !
272 rtl::Reference<CacheLine> xModule = internalGetModule(_aDefaultInstance.root());
274 OSL_ENSURE( xModule.is(), "CacheData::insertDefaults: No module to insert the defaults to - where did the data segment come from ?");
276 if (!xModule.is()) return false;
278 // make sure to keep the module alive
279 CacheLineClientRef( xModule ).keep();
281 sharable::TreeFragment * aResultTree = xModule->insertDefaults(_aDefaultInstance);
283 return aResultTree != NULL;
285 // -----------------------------------------------------------------------------
287 void CacheData::applyUpdate( backend::UpdateInstance & _anUpdate ) SAL_THROW((com::sun::star::uno::RuntimeException))
289 // request the subtree, atleast one level must exist!
290 sharable::Node * aNodeAddr = internalGetNode(_anUpdate.root());
292 if (aNodeAddr != NULL)
294 applyUpdateToTree(*_anUpdate.data(),aNodeAddr);
296 else
298 OSL_ENSURE(false, "CacheData::applyUpdate called for non-existing tree");
299 rtl::OUString aStr(RTL_CONSTASCII_USTRINGPARAM("CacheData: update to non-existing node: "));
301 aStr += _anUpdate.root().toString();
303 throw uno::RuntimeException(aStr,0);
306 // -----------------------------------------------------------------------------
307 oslInterlockedCount CacheData::releaseModule( rtl::OUString const & _aModule, bool _bKeepDeadModule )
309 rtl::Reference<CacheLine> xModule = internalGetModule(_aModule);
311 const oslInterlockedCount c_nErrorCount = -1;
313 OSL_ENSURE( xModule.is(), "ERROR: Releasing non-existent subtree");
314 if ( !xModule.is()) return c_nErrorCount;
316 OSL_ENSURE( xModule->clientReferences() > 0, "ERROR: Releasing non-referenced subtree");
318 oslInterlockedCount nResult = xModule->clientRelease();
320 if (nResult == 0 && !_bKeepDeadModule)
322 m_aModules.erase( _aModule );
324 return nResult;
327 // -----------------------------------------------------------------------------
328 sharable::TreeFragment * CacheData::getTemplateTree(configuration::AbsolutePath const& aTemplateName ) const
330 return internalGetPartialTree(aTemplateName);
332 // -----------------------------------------------------------------------------
333 sharable::Node * CacheData::getNode(const configuration::AbsolutePath& _rPath)
335 return internalGetNode(_rPath);
337 // -----------------------------------------------------------------------------
338 bool CacheData::hasNode(const configuration::AbsolutePath& _rPath) const
340 return internalGetNode(_rPath) != NULL;
342 // -----------------------------------------------------------------------------
344 sharable::TreeFragment * TemplateCacheData::addTemplates( backend::ComponentDataStruct const & _aComponentInstance) SAL_THROW((com::sun::star::uno::RuntimeException))
346 OSL_PRECOND(_aComponentInstance.data.get(), "addTemplates: Data must not be NULL");
347 // we should already have the module in cache !
348 rtl::OUString aModuleName ( _aComponentInstance.name);
349 rtl::Reference<CacheLine> xModule = internalGetModule(aModuleName);
351 OSL_ENSURE( xModule.is(), "ExtendedCacheData::addTemplates: No module to add the templates to - where did the data segment come from ?");
353 if (!xModule.is()) return NULL;
355 // make sure to keep the module alive
356 CacheLineClientRef( xModule ).keep();
358 static const rtl::OUString aDummyTemplateName(RTL_CONSTASCII_USTRINGPARAM("cfg:Template"));
359 static const rtl::OUString aDummyTemplateModule(RTL_CONSTASCII_USTRINGPARAM("cfg:Templates"));
360 _aComponentInstance.data->makeSetNode(aDummyTemplateName,aDummyTemplateModule);
362 sharable::TreeFragment * aResult = xModule->setComponentData(_aComponentInstance, true);
364 OSL_ASSERT(aResult != NULL);
366 return aResult;
368 // -----------------------------------------------------------------------------
370 rtl::Reference<CacheLine> TemplateCacheData::doCreateAttachedModule(sharable::TreeFragment * _aLocation, rtl::OUString const & _aName) SAL_THROW((com::sun::star::uno::RuntimeException))
372 rtl::Reference<CacheLine> aNewModule = CacheLine::createAttached(_aName, _aLocation);
374 return aNewModule.get();
376 // -----------------------------------------------------------------------------
378 void TemplateCacheData::createModule(rtl::OUString const & _aModule) SAL_THROW((com::sun::star::uno::RuntimeException))
380 rtl::Reference<CacheLine> aNewModule = CacheLine::createNew(_aModule);
382 internalAddModule( _aModule, aNewModule.get() );
384 // -----------------------------------------------------------------------------
385 // -----------------------------------------------------------------------------
386 inline
387 rtl::Reference<ExtendedCacheLine> ExtendedCacheData::implExtended(const rtl::Reference<CacheLine>& _aSimpleRef) const
389 CacheLine * pBasic = _aSimpleRef.get();
390 ExtendedCacheLine * pExtended = static_cast<ExtendedCacheLine *>(pBasic);
391 return rtl::Reference<ExtendedCacheLine>(pExtended);
394 // -----------------------------------------------------------------------------
396 rtl::Reference<CacheLine> ExtendedCacheData::doCreateAttachedModule(sharable::TreeFragment * _aLocation, rtl::OUString const & _aName) SAL_THROW((com::sun::star::uno::RuntimeException))
398 rtl::Reference<ExtendedCacheLine> aNewModule =
399 ExtendedCacheLine::createAttached(_aName, _aLocation);
401 return rtl::Reference<CacheLine>( aNewModule.get() );
403 // -----------------------------------------------------------------------------
405 void ExtendedCacheData::createModule(rtl::OUString const & _aModule) SAL_THROW((com::sun::star::uno::RuntimeException))
407 rtl::Reference<ExtendedCacheLine> aNewModule = ExtendedCacheLine::createNew(_aModule);
409 internalAddModule( _aModule, aNewModule.get() );
411 // -----------------------------------------------------------------------------
413 sharable::TreeFragment * ExtendedCacheData::addComponentData(backend::ComponentInstance const & _aComponentInstance,
414 bool _bWithDefaults) SAL_THROW((com::sun::star::uno::RuntimeException))
416 OSL_PRECOND(_aComponentInstance.data().get(), "addComponentData: Data must not be NULL");
417 // we should already have the module in cache !
418 //rtl::Reference<CacheLine> xModule = internalGetModule(_aNodeInstance.root().location());
419 rtl::Reference<CacheLine> xModule = internalGetModule(_aComponentInstance.component() );
421 OSL_ENSURE( xModule.is(), "ExtendedCacheData::addComponentData: No module to add the subtree to - where did the data segment come from ?");
423 if (!xModule.is()) return NULL;
425 CacheLineClientRef aClientRef( xModule );
427 sharable::TreeFragment * aResult = xModule->setComponentData(_aComponentInstance.componentNodeData(), _bWithDefaults);
429 OSL_ASSERT(aResult != NULL);
431 if (aResult != NULL) aClientRef.keep();
433 return aResult;
435 // -----------------------------------------------------------------------------
437 void ExtendedCacheData::addPending(backend::ConstUpdateInstance const & _anUpdate) SAL_THROW((com::sun::star::uno::RuntimeException))
439 // do we already have the module in cache ?
440 rtl::Reference<CacheLine> xModule = internalGetModule(_anUpdate.root());
442 if (xModule.is())
444 implExtended(xModule)->addPending(_anUpdate);
446 else
448 OSL_ENSURE(false, "We can only change Nodes if we already know something about it. So this must be a big bug.");
451 // -----------------------------------------------------------------------------
453 std::auto_ptr<SubtreeChange> ExtendedCacheData::releasePending(rtl::OUString const& _aModule)
455 rtl::Reference<ExtendedCacheLine> xModule = implExtended(internalGetModule(_aModule));
457 if (xModule.is())
459 if (xModule->hasPending())
460 return xModule->releasePending();
461 else
462 return std::auto_ptr<SubtreeChange>();
464 else
466 OSL_ENSURE(false, "We can only get Nodes if we already know something about it.");
468 return std::auto_ptr<SubtreeChange>();
470 // -----------------------------------------------------------------------------
472 bool ExtendedCacheData::hasPending(rtl::OUString const & _aModule)
474 rtl::Reference<ExtendedCacheLine> xModule = implExtended(internalGetModule(_aModule));
476 return xModule.is() && xModule->hasPending();
479 // -----------------------------------------------------------------------------
481 void ExtendedCacheData::findPendingModules( std::vector< rtl::OUString > & _rPendingList )
483 ModuleList& rModules = CacheData::accessModuleList();
484 for (ModuleList::iterator it = rModules.begin();
485 it != rModules.end();
486 ++it)
488 OSL_ASSERT( it->second.is() );
489 if ( implExtended(it->second)->hasPending() )
490 _rPendingList.push_back( it->first );
493 // -----------------------------------------------------------------------------
495 // -----------------------------------------------------------------------------
496 } // namespace configmgr