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: cacheaccess.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 "cacheaccess.hxx"
36 #include "configpath.hxx"
40 // -------------------------------------------------------------------------
42 CacheClientAccess::CacheClientAccess(ConfigChangeBroadcastHelper
* _pBroadcastHelper
)
43 : m_pBroadcastHelper( _pBroadcastHelper
)
46 // -------------------------------------------------------------------------
48 CacheClientAccess::~CacheClientAccess()
50 OSL_ENSURE(!m_pBroadcastHelper
, "Forgot to dispose broadcast helper");
52 // -------------------------------------------------------------------------
54 ConfigChangeBroadcastHelper
* CacheClientAccess::releaseBroadcaster()
56 ConfigChangeBroadcastHelper
* pRet
= m_pBroadcastHelper
;
57 m_pBroadcastHelper
= NULL
;
61 // -------------------------------------------------------------------------
63 bool CacheClientAccess::hasModule(const configuration::AbsolutePath
& _aLocation
)
65 return this->m_aData
.hasModule(_aLocation
.getModuleName());
67 // -------------------------------------------------------------------------
69 bool CacheClientAccess::hasModuleDefaults(configuration::AbsolutePath
const& _aLocation
)
71 return this->m_aData
.hasModuleDefaults(_aLocation
.getModuleName());
73 // -------------------------------------------------------------------------
74 void CacheClientAccess::attachModule(sharable::TreeFragment
* _aLocation
, rtl::OUString
const & _aModule
)
76 this->m_aData
.attachModule(_aLocation
, _aModule
);
78 // -------------------------------------------------------------------------
80 sharable::Node
* CacheClientAccess::acquireNode(configuration::AbsolutePath
const& rLocation
)
82 CFG_TRACE_INFO("CacheClientAccess: Requesting data for path '%s'", OUSTRING2ASCII(rLocation
.toString()) );
84 sharable::Node
* aResult
= this->m_aData
.acquireNode(rLocation
);
88 CFG_TRACE_INFO_NI("- Data is available - returning Subtree");
91 CFG_TRACE_INFO_NI("- Data is not available - returning NULL");
95 // -------------------------------------------------------------------------
97 oslInterlockedCount
CacheClientAccess::releaseNode( configuration::AbsolutePath
const& rLocation
)
99 CFG_TRACE_INFO("Tree Info: Releasing subtree data for path '%s'", OUSTRING2ASCII(rLocation
.toString()) );
101 oslInterlockedCount nRet
= this->m_aData
.releaseModule(rLocation
.getModuleName(),false);
105 // -----------------------------------------------------------------------------
107 void CacheClientAccess::applyUpdate(backend::UpdateInstance
& _aUpdate
) SAL_THROW((com::sun::star::uno::RuntimeException
))
109 CFG_TRACE_INFO("CacheClientAccess: Merging changes into subtree '%s'", OUSTRING2ASCII(_aUpdate
.root().toString()) );
111 this->m_aData
.applyUpdate(_aUpdate
);
114 // -----------------------------------------------------------------------------
115 sharable::Node
* CacheClientAccess::findInnerNode( configuration::AbsolutePath
const& aComponentName
)
117 sharable::Node
* node
= m_aData
.getNode(aComponentName
);
118 return node
== 0 || node
->isValue() ? 0 : node
;
121 // -------------------------------------------------------------------------
123 bool CacheClientAccess::insertDefaults( backend::NodeInstance
const & _aDefaultData
) SAL_THROW((com::sun::star::uno::RuntimeException
))
125 CFG_TRACE_INFO("Tree Info: Adding default data for path '%s'", OUSTRING2ASCII(_aDefaultData
.root().toString()) );
127 return this->m_aData
.insertDefaults(_aDefaultData
);
129 // -------------------------------------------------------------------------
131 // -------------------------------------------------------------------------
132 // -------------------------------------------------------------------------
134 CacheLoadingAccess::CacheLoadingAccess()
138 // -------------------------------------------------------------------------
140 CacheLoadingAccess::~CacheLoadingAccess()
144 // -------------------------------------------------------------------------
146 /// gets a tree reference for the given path if exists
147 sharable::TreeFragment
* CacheLoadingAccess::getTreeAddress(rtl::OUString
const & _aModule
)
149 return this->m_aData
.getTreeAddress(_aModule
);
151 // -------------------------------------------------------------------------
152 void CacheLoadingAccess::createModule(rtl::OUString
const & _aModule
)
154 this->m_aData
.createModule(_aModule
);
156 // -------------------------------------------------------------------------
157 bool CacheLoadingAccess::hasModule(rtl::OUString
const & _aModule
)
159 return this->m_aData
.hasModule(_aModule
);
161 // -------------------------------------------------------------------------
163 bool CacheLoadingAccess::acquireModule(rtl::OUString
const & _aModule
)
165 CFG_TRACE_INFO("Tree Info: Requesting data for module '%s'", OUSTRING2ASCII(_aModule
));
167 if (this->m_aData
.acquireModule(_aModule
))
169 m_aDeadModules
.erase( _aModule
);
170 CFG_TRACE_INFO_NI("- Data is available - returning Subtree");
175 CFG_TRACE_INFO_NI("- Data is not available - returning NULL");
179 // -------------------------------------------------------------------------
181 oslInterlockedCount
CacheLoadingAccess::releaseModule( rtl::OUString
const & _aModule
)
183 CFG_TRACE_INFO("Tree Info: Releasing data for module '%s'", OUSTRING2ASCII(_aModule
) );
185 oslInterlockedCount nRet
= this->m_aData
.releaseModule(_aModule
,true); // keep
188 m_aDeadModules
[ _aModule
] = TimeStamp::getCurrentTime();
189 CFG_TRACE_INFO_NI("- Last reference released - marking data for cleanup");
194 // -----------------------------------------------------------------------------
196 bool CacheLoadingAccess::isEmpty()
198 ExtendedCacheData::ModuleList
& rModules
= this->m_aData
.accessModuleList();
200 bool bRet
= rModules
.empty();
202 if (bRet
) // while we are at it - clean up
203 m_aDeadModules
.clear();
207 // -------------------------------------------------------------------------
209 sharable::TreeFragment
* CacheLoadingAccess::addComponentData( backend::ComponentInstance
const & _aComponentInstance
,
210 bool _bIncludesDefaults
211 ) SAL_THROW((com::sun::star::uno::RuntimeException
))
213 CFG_TRACE_INFO("CacheLoadingAccess: Adding component data for module '%s' : %s",
214 OUSTRING2ASCII(_aComponentInstance
.component()),
215 _bIncludesDefaults
? "Data includes defaults." : "Data does not include defaults." );
217 sharable::TreeFragment
* aResult
= this->m_aData
.addComponentData(_aComponentInstance
, _bIncludesDefaults
);
220 m_aDeadModules
.erase( _aComponentInstance
.component() );
221 CFG_TRACE_INFO_NI("- Data added successfully - returning Subtree");
224 CFG_TRACE_INFO_NI("- Data not added - returning NULL");
228 // -------------------------------------------------------------------------
229 // -----------------------------------------------------------------------------
230 void CacheLoadingAccess::addChangesToPending( backend::ConstUpdateInstance
const& _anUpdate
) SAL_THROW((com::sun::star::uno::RuntimeException
))
232 // NICE: m_pPending[_rLocation] += pSubtreeChange;
233 CFG_TRACE_INFO("CacheLoadingAccess: Adding pending changes for subtree '%s'", OUSTRING2ASCII(_anUpdate
.root().toString()) );
235 this->m_aData
.addPending(_anUpdate
);
238 // -----------------------------------------------------------------------------
239 std::auto_ptr
<SubtreeChange
> CacheLoadingAccess::releasePendingChanges(rtl::OUString
const& _aComponentName
)
241 CFG_TRACE_INFO("Tree Info: extract pending changes from subtree '%s'", OUSTRING2ASCII(_aComponentName
) );
242 return this->m_aData
.releasePending(_aComponentName
);
245 // -----------------------------------------------------------------------------
246 bool CacheLoadingAccess::findPendingChangedModules( std::vector
< rtl::OUString
> & _rPendingList
)
248 this->m_aData
.findPendingModules(_rPendingList
);
249 return !_rPendingList
.empty();
252 // -------------------------------------------------------------------------
254 TimeStamp
CacheLoadingAccess::collectDisposeList(std::vector
< rtl::Reference
<CacheLine
> > & _rList
, TimeStamp
const & _aLimitTime
, TimeInterval
const & _aDelay
)
256 TimeStamp aRetTime
= TimeStamp::never();
258 CFG_TRACE_INFO("Tree Info: Collecting disposable module trees for cleanup" );
260 ExtendedCacheData::ModuleList
& rActiveModules
= this->m_aData
.accessModuleList();
262 std::map
< rtl::OUString
, TimeStamp
>::iterator it
= m_aDeadModules
.begin();
264 while (it
!= m_aDeadModules
.end())
266 std::map
< rtl::OUString
, TimeStamp
>::iterator current
= it
;
267 // increment here, as we may later erase(current)
270 #if (OSL_DEBUG_LEVEL > 0) || defined _DBG_UTIL || defined CFG_TRACE_ENABLE
271 rtl::OUString
sCurrentName( current
->first
);
273 TimeStamp aExpireTime
= current
->second
+ _aDelay
;
274 if (aExpireTime
<= _aLimitTime
)
276 ExtendedCacheData::ModuleList::iterator itModule
= rActiveModules
.find( current
->first
);
278 if (itModule
!= rActiveModules
.end())
280 rtl::Reference
<CacheLine
> xModule
= itModule
->second
;
282 bool bHandled
= false;
286 CFG_TRACE_ERROR_NI("- Unexpected: Module '%s' is NULL in active module list", OUSTRING2ASCII(sCurrentName
) );
289 else if (xModule
->clientReferences() != 0)// at least in temporary use
291 OSL_ENSURE( false, "Referenced entry in dead module list");
293 CFG_TRACE_WARNING_NI("- Module '%s' in (temporary ?) use - rescheduling", OUSTRING2ASCII(sCurrentName
) );
294 bHandled
= false; // still remove from the lists
296 else if (m_aData
.hasPending(current
->first
))
298 CFG_TRACE_WARNING_NI("- Module '%s' has pending changes - rescheduling disposal", OUSTRING2ASCII(sCurrentName
) );
301 else // now this really can be disposed
303 CFG_TRACE_INFO_NI("- Removing module '%s' for disposal", OUSTRING2ASCII(sCurrentName
) );
305 // It really is ok to dispose this entry
306 _rList
.push_back(xModule
);
315 rActiveModules
.erase(itModule
);
316 m_aDeadModules
.erase(current
);
321 TimeStamp aRetryTime
= _aLimitTime
+ _aDelay
;
322 OSL_ASSERT(aRetryTime
> _aLimitTime
);
324 current
->second
= _aLimitTime
; // ?
325 if (aRetryTime
< aRetTime
)
326 aRetTime
= aRetryTime
;
331 // obsolete dispose list entry - discard
332 OSL_ENSURE( false, "Obsolete entry in dead module list");
334 CFG_TRACE_WARNING_NI("- Module '%s' not found any more - obsolete entry in dead module list", OUSTRING2ASCII(sCurrentName
) );
336 m_aDeadModules
.erase(current
);
339 else // consider for restart time
341 CFG_TRACE_INFO_NI("- Module '%s' has not expired yet - rescheduling", OUSTRING2ASCII(sCurrentName
) );
343 if (aExpireTime
< aRetTime
)
344 aRetTime
= aExpireTime
;
348 OSL_ASSERT(aRetTime
> _aLimitTime
);
351 // -------------------------------------------------------------------------
353 } // namespace configmgr