1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: cachedata.cxx,v $
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"
36 #include "updatehelper.hxx"
38 #include <osl/diagnose.h>
39 #include "configpath.hxx"
43 // ---------------------------- Client Acquire helper ----------------------------
45 struct CacheLineClientRef
47 rtl::Reference
<CacheLine
> xModule
;
49 CacheLineClientRef(rtl::Reference
<CacheLine
> const& _xModule
)
53 xModule
->clientAcquire();
56 ~CacheLineClientRef() // release the client reference unless it was 'kept'
59 xModule
->clientRelease();
62 void rebind(rtl::Reference
<CacheLine
> const& _xModule
)
65 _xModule
->clientAcquire();
67 xModule
->clientRelease();
71 /// release the contained module so that the client reference will be kept active
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
;
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 // -----------------------------------------------------------------------------
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 // -----------------------------------------------------------------------------
120 rtl::Reference
<CacheLine
> CacheData::internalGetModule(const configuration::AbsolutePath
& _aPath
) const
122 return internalGetModule( implExtractModuleName(_aPath
) );
124 // -----------------------------------------------------------------------------
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
);
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
);
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
206 // -----------------------------------------------------------------------------
207 sharable::Node
* CacheData::internalGetNode(const configuration::AbsolutePath
& aComponentName
) const
209 rtl::Reference
<CacheLine
> xModule
= internalGetModule(aComponentName
);
214 if ( xModule
->isEmpty() )
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
230 // -----------------------------------------------------------------------------
231 // -----------------------------------------------------------------------------
232 bool CacheData::acquireModule(rtl::OUString
const & _aModule
)
234 rtl::Reference
<CacheLine
> xModule
= internalGetModule(_aModule
);
238 CacheLineClientRef
aClientRef(xModule
);
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
257 OSL_ASSERT( aNodeAddr
== NULL
);
259 if (aNodeAddr
!= NULL
)
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
);
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
);
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
);
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 // -----------------------------------------------------------------------------
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();
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());
444 implExtended(xModule
)->addPending(_anUpdate
);
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
));
459 if (xModule
->hasPending())
460 return xModule
->releasePending();
462 return std::auto_ptr
<SubtreeChange
>();
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();
488 OSL_ASSERT( it
->second
.is() );
489 if ( implExtended(it
->second
)->hasPending() )
490 _rPendingList
.push_back( it
->first
);
493 // -----------------------------------------------------------------------------
495 // -----------------------------------------------------------------------------
496 } // namespace configmgr