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: cachecontroller.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 "cachecontroller.hxx"
35 #include "disposetimer.hxx"
36 #include "cachewritescheduler.hxx"
37 #include "builddata.hxx"
38 #include "localizedtreeactions.hxx"
39 #include "configexcept.hxx"
41 #include <com/sun/star/lang/DisposedException.hpp>
42 #include <com/sun/star/container/NoSuchElementException.hpp>
43 #include <osl/diagnose.h>
44 #include <rtl/logfile.hxx>
46 #ifndef _CONFIGMGR_BOOTSTRAP_HXX
47 #include "bootstrap.hxx"
51 #define RTL_LOGFILE_OU2A(rtlOUString) (::rtl::OUStringToOString((rtlOUString), RTL_TEXTENCODING_ASCII_US).getStr())
55 // -------------------------------------------------------------------------
59 static const rtl::OUString
kCacheDisposeDelay(
60 RTL_CONSTASCII_USTRINGPARAM( CONTEXT_ITEM_PREFIX_
"CacheDisposeDelay"));
61 static const rtl::OUString
kCacheDisposeInterval(
62 RTL_CONSTASCII_USTRINGPARAM( CONTEXT_ITEM_PREFIX_
"CacheDisposeInterval"));
63 static const rtl::OUString
kCacheWriteInterval(
64 RTL_CONSTASCII_USTRINGPARAM( CONTEXT_ITEM_PREFIX_
"CacheWriteInterval"));
65 // -------------------------------------------------------------------------
67 OTreeDisposeScheduler
* CacheController::createDisposer(const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XComponentContext
>& _xContext
)
69 ContextReader
aReader(_xContext
);
70 sal_uInt32 c_nDefaultDelay
= 0;
71 rtl::OUString sDefaultDelay
;
72 aReader
.getBestContext()->getValueByName(kCacheDisposeDelay
) >>= sDefaultDelay
;
73 c_nDefaultDelay
= sDefaultDelay
.toInt32()==0?900:sDefaultDelay
.toInt32() ;
75 sal_uInt32 c_nDefaultInterval
= 0;
76 rtl::OUString sDefaultInterval
;
77 aReader
.getBestContext()->getValueByName(kCacheDisposeInterval
) >>= sDefaultInterval
;
78 c_nDefaultInterval
= sDefaultInterval
.toInt32()==0?60:sDefaultInterval
.toInt32();
80 TimeInterval
aDelay(c_nDefaultDelay
);
81 TimeInterval
aInterval(c_nDefaultInterval
);
83 return new OTreeDisposeScheduler(*this, aDelay
, aInterval
);
86 // -----------------------------------------------------------------------------
88 OCacheWriteScheduler
* CacheController::createCacheWriter(const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XComponentContext
>& _xContext
)
90 ContextReader
aReader(_xContext
);
91 sal_uInt32 c_nDefaultInterval
=0;
92 rtl::OUString sDefaultInterval
;
93 aReader
.getBestContext()->getValueByName(kCacheWriteInterval
) >>= sDefaultInterval
;
94 c_nDefaultInterval
= sDefaultInterval
.toInt32()==0?2:sDefaultInterval
.toInt32();
96 TimeInterval
aInterval(c_nDefaultInterval
);
97 return new OCacheWriteScheduler(*this, aInterval
);
99 // ----------------------------------------------------------------------------
101 rtl::Reference
<CacheLoadingAccess
> CacheController::getCacheAlways(RequestOptions
const & _aOptions
)
103 rtl::Reference
<CacheLoadingAccess
> aResult
= m_aCacheMap
.get(_aOptions
);
106 rtl::Reference
<CacheLoadingAccess
> aNewCache( new CacheLoadingAccess() );
107 aResult
= m_aCacheMap
.insert(_aOptions
,aNewCache
);
112 // -------------------------------------------------------------------------
115 // -------------------------------------------------------------------------
116 void CacheController::disposeAll(bool _bFlushRemainingUpdates
)
118 CFG_TRACE_INFO("CacheController: Disposing all data" );
119 CacheMap::Map aReleaseList
;
123 m_pDisposer
->stopAndClearTasks();
124 m_aCacheMap
.swap(aReleaseList
); // move data out of m_aCacheMap and empty m_aCacheMap
127 if (_bFlushRemainingUpdates
)
129 for (CacheMap::Map::iterator it
= aReleaseList
.begin(); it
!= aReleaseList
.end(); ++it
)
130 saveAllPendingChanges(it
->second
,it
->first
);
132 // free all the trees
133 aReleaseList
.clear();
136 // -------------------------------------------------------------------------
137 void CacheController::dispose() SAL_THROW((com::sun::star::uno::RuntimeException
))
141 CFG_TRACE_INFO("CacheController: dispose()" );
143 RTL_LOGFILE_CONTEXT_AUTHOR(aLog
, "configmgr::backend::CacheController", "jb99855", "configmgr: CacheController::dispose(), disable lazy write cache.");
144 m_bDisposing
= true; // we are in dispose, handling of errors must be something different.
146 // writing of pending updates
147 this->flushCacheWriter();
149 // cleaning the cache
150 this->disposeAll(true);
153 // -------------------------------------------------------------------------
154 CacheController::CacheController(rtl::Reference
< backend::IMergedDataProvider
> const & _xBackend
,
155 const uno::Reference
<uno::XComponentContext
>& xContext
)
157 , m_xBackend(_xBackend
)
162 , m_bDisposing(false)
164 m_pDisposer
= this->createDisposer(xContext
);
165 m_pCacheWriter
= this->createCacheWriter(xContext
);
168 // -------------------------------------------------------------------------
169 CacheController::~CacheController()
171 OSL_ENSURE(m_bDisposing
== true, "CacheController::dispose() wasn't called, something went wrong.");
174 delete m_pCacheWriter
;
177 // -------------------------------------------------------------------------
178 void CacheController::closeModules(std::vector
< rtl::Reference
<CacheLine
> > & _aList
, RequestOptions
const & _aOptions
)
180 //Remove listeners from Backend as module no longer in cache
181 for (sal_uInt32 i
=0; i
< _aList
.size(); ++i
)
183 rtl::OUString aModuleName
= _aList
[i
]->getModuleName();
184 ComponentRequest
aRequest(aModuleName
, _aOptions
);
185 m_xBackend
->removeRequestListener(this, aRequest
);
188 // -------------------------------------------------------------------------
191 std::auto_ptr
<ISubtree
> reduceSubtreeForLocale(std::auto_ptr
<ISubtree
> _pSubtree
, RequestOptions
const & _aOptions
)
193 OSL_ENSURE(!_pSubtree
.get() || !isLocalizedValueSet(*_pSubtree
), "Unexpected node. Expecting a subtree, Found a single localized value.");
195 std::auto_ptr
<ISubtree
> aRet
;
197 std::auto_ptr
<INode
> aReduced
= reduceExpandedForLocale(_pSubtree
, _aOptions
.getLocale());
201 if (ISubtree
* pReduced
=aReduced
->asISubtree())
203 aRet
.reset(pReduced
);
208 OSL_ENSURE(false, "Tree unexpectedly reduced to non-tree");
212 OSL_ENSURE(!_pSubtree
.get(), "Tree unexpectedly reduced to nothing");
218 // -------------------------------------------------------------------------
219 sharable::TreeFragment
* CacheController::loadComponent(ComponentRequest
const & _aRequest
)
221 CFG_TRACE_INFO("CacheController: loading component '%s'", OUSTRING2ASCII(_aRequest
.getComponentName()));
223 RTL_LOGFILE_CONTEXT_AUTHOR(aLog
, "configmgr::backend::CacheController", "jb99855", "configmgr: CacheController::loadComponent()");
224 RTL_LOGFILE_CONTEXT_TRACE1(aLog
, "component: %s", RTL_LOGFILE_OU2A(_aRequest
.getComponentName().toString()) );
226 rtl::Reference
<CacheLoadingAccess
> aCache
= this->getCacheAlways(_aRequest
.getOptions());
228 OSL_ENSURE(aCache
.is(), "Could not create CacheAccess");
230 sharable::TreeFragment
* aTemplateResultAdddress
;
232 OSL_ENSURE(!_aRequest
.isForcingReload(),"CacheController: No support for forced requests");
233 if (aCache
->hasModule(_aRequest
.getComponentName()))
235 CFG_TRACE_INFO_NI("CacheController: found node in cache");
236 if (_aRequest
.getOptions().isRefreshEnabled())
238 refreshComponent(_aRequest
);
240 aCache
->acquireModule(_aRequest
.getComponentName());
244 ResultHolder
< ComponentInstance
> aData
= this->loadDirectly(_aRequest
,true);
246 CFG_TRACE_INFO_NI("CacheController: adding loaded data to the cache");
248 aCache
->createModule(_aRequest
.getComponentName());
250 aCache
->addComponentData(aData
.instance(), true);
251 if (aData
.instance().templateData().get()!=NULL
)
252 aTemplateResultAdddress
= addTemplates(aData
.mutableInstance().componentTemplateData() );
254 // notify the new data to all clients
255 m_aNotifier
.notifyCreated(_aRequest
);
258 return aCache
->getTreeAddress(_aRequest
.getComponentName());
260 // -------------------------------------------------------------------------
262 ResultHolder
< ComponentInstance
> CacheController::getComponentData(ComponentRequest
const & _aRequest
,
263 bool _bAddListenter
) SAL_THROW((com::sun::star::uno::Exception
))
265 // TODO: Insert check here, if the data is in the cache already - and then clone
266 RTL_LOGFILE_CONTEXT_AUTHOR(aLog
, "configmgr::backend::CacheController", "jb99855", "configmgr: CacheController::getComponentData()");
267 RTL_LOGFILE_CONTEXT_TRACE1(aLog
, "component: %s", RTL_LOGFILE_OU2A(_aRequest
.getComponentName().toString()) );
269 ResultHolder
< ComponentInstance
> aRet
= this->loadDirectly(_aRequest
, _bAddListenter
);
273 // -------------------------------------------------------------------------
275 ResultHolder
< NodeInstance
> CacheController::getDefaultData(NodeRequest
const & _aRequest
) SAL_THROW((com::sun::star::uno::Exception
))
277 // TODO: Insert check here, if the data is in the cache already - and then clone
278 RTL_LOGFILE_CONTEXT_AUTHOR(aLog
, "configmgr::backend::CacheController", "jb99855", "configmgr: CacheController::getDefaultData()");
279 RTL_LOGFILE_CONTEXT_TRACE1(aLog
, "path: %s", RTL_LOGFILE_OU2A(_aRequest
.getPath().toString()) );
281 ResultHolder
< NodeInstance
> aRet
= this->loadDefaultsDirectly(_aRequest
);
285 // -------------------------------------------------------------------------
287 configuration::AbsolutePath
CacheController::encodeTemplateLocation(const rtl::OUString
& _rName
, const rtl::OUString
&_rModule
) const
289 namespace Path
= configuration::Path
;
292 // Component aTemplateRoot = wrapSimpleName(rtl::OUString::createFromAscii("org.openoffice.Templates"));
294 Path::Component aTemplateModule
= Path::wrapSimpleName(_rModule
);
295 Path::Component aTemplateName
= Path::wrapSimpleName(_rName
);
297 Path::Rep
aResult(aTemplateName
);
298 aResult
.prepend(aTemplateModule
);
299 // aResult.prepend(aTemplateRoot);
301 return configuration::AbsolutePath(aResult
);
303 // -------------------------------------------------------------------------
306 configuration::AbsolutePath
templateLoadLocation(const configuration::AbsolutePath
&_rTemplateLocation
)
308 namespace Path
= configuration::Path
;
311 Path::Component aTemplateRoot
= Path::wrapSimpleName(rtl::OUString::createFromAscii("org.openoffice.Templates"));
313 Path::Rep
aResult(_rTemplateLocation
.rep());
314 aResult
.prepend(aTemplateRoot
);
316 return configuration::AbsolutePath(aResult
);
319 // -------------------------------------------------------------------------
320 std::auto_ptr
<ISubtree
> CacheController::loadTemplateData(TemplateRequest
const & _aTemplateRequest
) SAL_THROW((com::sun::star::uno::Exception
))
322 std::auto_ptr
<ISubtree
> aMultiTemplates
;
323 ResultHolder
< TemplateInstance
> aTemplateInstance
= m_xBackend
->getTemplateData(_aTemplateRequest
);
324 if (aTemplateInstance
.is())
326 OSL_ASSERT(aTemplateInstance
->name().getLength() == 0);
327 if (ISubtree
* pMulti
= aTemplateInstance
->data()->asISubtree())
329 aTemplateInstance
.releaseAndClear();
330 aMultiTemplates
.reset(pMulti
);
333 OSL_ENSURE(false,"Requested multiple templates, got non-subtree node");
336 OSL_ENSURE(false,"Requested configuration template does not exist");
338 if (aMultiTemplates
.get() == NULL
)
340 CFG_TRACE_ERROR_NI("CacheController: could not load the templates");
341 throw uno::Exception(::rtl::OUString::createFromAscii("The template description could not be loaded. The template does not exist."), NULL
);
344 return aMultiTemplates
;
346 // -------------------------------------------------------------------------
347 sharable::TreeFragment
* CacheController::addTemplates ( backend::ComponentDataStruct
const & _aComponentInstance
)
349 OSL_PRECOND(_aComponentInstance
.data
.get(), "addTemplates: Data must not be NULL");
350 rtl::OUString aModuleName
= _aComponentInstance
.name
;
351 m_aTemplates
.createModule(aModuleName
);
352 configuration::AbsolutePath aTemplateLocation
= configuration::AbsolutePath::makeModulePath(_aComponentInstance
.name
);
353 sharable::TreeFragment
* aTemplateAddr
= NULL
;
355 if (!m_aTemplates
.hasNode(aTemplateLocation
))
357 CFG_TRACE_INFO_NI("CacheController: cache miss for that template - loading from backend");
358 aTemplateAddr
= m_aTemplates
.addTemplates(_aComponentInstance
);
360 OSL_ASSERT (aTemplateAddr
!= NULL
);
361 return aTemplateAddr
;
363 // -------------------------------------------------------------------------
365 sharable::TreeFragment
* CacheController::loadTemplate(TemplateRequest
const & _aRequest
) SAL_THROW((com::sun::star::uno::Exception
))
368 OSL_ENSURE(_aRequest
.getTemplateName().getLength() != 0, "CacheController::loadTemplate : invalid template name !");
369 RTL_LOGFILE_CONTEXT_AUTHOR(aLog
, "configmgr::backend::CacheController", "jb99855", "configmgr: CacheController::loadTemplate()");
370 RTL_LOGFILE_CONTEXT_TRACE2(aLog
, "requested template: %s/%s",
371 RTL_LOGFILE_OU2A(_aRequest
.getComponentName().toString()) ,
372 _aRequest
.isComponentRequest() ?
373 "*" : RTL_LOGFILE_OU2A(_aRequest
.getComponentName().toString()) );
376 configuration::AbsolutePath aTemplateLocation
= encodeTemplateLocation(_aRequest
.getTemplateName(), _aRequest
.getComponentName());
378 rtl::OUString aModuleName
= aTemplateLocation
.getModuleName();
380 configuration::AbsolutePath
aTemplateParent (aTemplateLocation
.getParentPath());
382 //Load-if-not-there (componentwise)
383 if (!m_aTemplates
.hasNode(aTemplateParent
))
385 OSL_ENSURE(aTemplateLocation
.getDepth() > 1, "CacheController::ensureTemplate : invalid template location !");
386 TemplateRequest aTemplateRequest
= TemplateRequest::forComponent(_aRequest
.getComponentName());
388 std::auto_ptr
<ISubtree
> aMultiTemplates
= loadTemplateData(aTemplateRequest
);
390 addTemplates(backend::ComponentDataStruct(aMultiTemplates
, aModuleName
));
393 sharable::TreeFragment
* aTemplateAddr
= m_aTemplates
.getTemplateTree(aTemplateLocation
);
394 if (aTemplateAddr
== NULL
)
395 throw uno::Exception(::rtl::OUString::createFromAscii("Unknown template. Type description could not be found in the given module."), NULL
);
397 return m_aTemplates
.getTreeAddress(aTemplateLocation
.getModuleName());
399 // -----------------------------------------------------------------------------
401 ResultHolder
< TemplateInstance
> CacheController::getTemplateData(TemplateRequest
const & _aRequest
)
402 SAL_THROW((com::sun::star::uno::Exception
))
404 RTL_LOGFILE_CONTEXT_AUTHOR(aLog
, "configmgr::backend::CacheController", "jb99855", "configmgr: CacheController::getTemplateData()");
405 RTL_LOGFILE_CONTEXT_TRACE2(aLog
, "requested template: %s/%s",
406 RTL_LOGFILE_OU2A(_aRequest
.getComponentName().toString()) ,
407 _aRequest
.isComponentRequest() ?
408 "*" : RTL_LOGFILE_OU2A(_aRequest
.getComponentName().toString()) );
410 configuration::AbsolutePath aTemplateLocation
= encodeTemplateLocation(_aRequest
.getTemplateName(), _aRequest
.getComponentName());
412 loadTemplate(_aRequest
);
413 //configuration::AbsolutePath aTemplateLocation = ensureTemplate(_aRequest.getTemplateName(), _aRequest.getComponentName());
415 sharable::TreeFragment
* aTemplateAddr
= m_aTemplates
.getTemplateTree(aTemplateLocation
);
416 if (aTemplateAddr
== NULL
)
417 throw uno::Exception(::rtl::OUString::createFromAscii("Unknown template. Type description could not be found in the given module."), NULL
);
419 std::auto_ptr
<INode
> aResultTree
= data::convertTree(aTemplateAddr
, true);
421 TemplateInstance
aResult(aResultTree
,_aRequest
.getTemplateName(), _aRequest
.getComponentName());
423 return ResultHolder
< TemplateInstance
>(aResult
);
425 // -----------------------------------------------------------------------------
427 void CacheController::saveAndNotify(UpdateRequest
const & _anUpdate
) SAL_THROW((com::sun::star::uno::Exception
))
429 RTL_LOGFILE_CONTEXT_AUTHOR(aLog
, "configmgr::backend::CacheController", "jb99855", "configmgr: CacheController::saveAndNotify()");
430 RTL_LOGFILE_CONTEXT_TRACE1(aLog
, "location: %s", RTL_LOGFILE_OU2A(_anUpdate
.getUpdateRoot().toString()) );
433 // ---------- preworking on the changes ----------
434 // caller must own a read lock on this cache line
435 CFG_TRACE_INFO("CacheController: saving an update for '%s'",OUSTRING2ASCII(_anUpdate
.getUpdateRoot().toString()));
437 rtl::Reference
<CacheLoadingAccess
> aCache
= m_aCacheMap
.get(_anUpdate
.getOptions());
439 OSL_ENSURE(aCache
.is(), "No cache data to update in saveAndNotify");
441 if (!aCache
.is()) throw lang::DisposedException(rtl::OUString::createFromAscii("Tree to be updated was already disposed"), NULL
);
443 aCache
->addChangesToPending(_anUpdate
.getUpdate());
445 if ( _anUpdate
.isSyncRequired()|| m_bDisposing
) // cannot do it asynchronously
447 CFG_TRACE_INFO_NI("Running synchronous write");
448 savePendingChanges( aCache
, getComponentRequest(_anUpdate
) );
453 CFG_TRACE_INFO_NI("Posting asynchronous write");
454 m_pCacheWriter
->scheduleWrite( getComponentRequest(_anUpdate
) );
457 CFG_TRACE_INFO_NI("Notifying the changes");
458 // notify the changes to all clients
459 m_aNotifier
.notifyChanged(_anUpdate
);
461 catch(configuration::Exception
& ex
)
463 CFG_TRACE_ERROR_NI("Got unexpected exception: %s", ex
.what());
464 configapi::ExceptionMapper
e(ex
);
469 // -----------------------------------------------------------------------------
471 void CacheController::flushPendingUpdates()SAL_THROW((com::sun::star::uno::Exception
))
473 CacheMap::Map aFlushList
= m_aCacheMap
.copy();
475 for (CacheMap::Map::iterator it
= aFlushList
.begin(); it
!= aFlushList
.end(); ++it
)
476 saveAllPendingChanges(it
->second
,it
->first
);
479 void CacheController::flushCacheWriter()SAL_THROW(())
481 //OSL_ASSERT(m_bDisposing);
485 CFG_TRACE_INFO("CacheController: flushing all pending updates");
487 m_pCacheWriter
->stopAndWriteCache();
490 // -----------------------------------------------------------------------------
492 bool CacheController::normalizeResult(std::auto_ptr
<ISubtree
> & _aResult
, RequestOptions
const & _aOptions
)
495 if (_aResult
.get()==NULL
) return false;
497 if (_aOptions
.isForAllLocales()) return true;
499 std::auto_ptr
<INode
> aReduced
= reduceExpandedForLocale(_aResult
, _aOptions
.getLocale());
501 std::auto_ptr
<ISubtree
> aReducedTree
;
504 if (ISubtree
* pReducedTree
=aReduced
->asISubtree())
507 aReducedTree
.reset(pReducedTree
);
511 OSL_ENSURE(false, "Tree unexpectedly reduced to non-tree");
515 OSL_ENSURE(false, "Tree unexpectedly reduced to nothing");
518 _aResult
= aReducedTree
;
519 bool retCode
= _aResult
.get()!=NULL
? true : false;
522 // -----------------------------------------------------------------------------
524 ResultHolder
< ComponentInstance
> CacheController::loadDirectly(ComponentRequest
const & _aRequest
, bool _bAddListenter
) SAL_THROW((com::sun::star::uno::Exception
))
526 CFG_TRACE_INFO("CacheController: loading data for component '%s' from the backend", OUSTRING2ASCII(_aRequest
.getComponentName()));
528 configuration::AbsolutePath aRequestPath
= configuration::AbsolutePath::makeModulePath(_aRequest
.getComponentName());
530 NodeRequest
aNodeRequest(aRequestPath
, _aRequest
.getOptions());
532 ResultHolder
< ComponentInstance
> aResult
= m_xBackend
->getNodeData(_aRequest
, this, _bAddListenter
?this:NULL
);
534 OSL_PRECOND(aResult
.mutableInstance().mutableData().get(), "loadDirectly: Data must not be NULL");
536 CFG_TRACE_INFO_NI("- loading data completed - normalizing result");
538 if (!normalizeResult( aResult
.mutableInstance().mutableData(),_aRequest
.getOptions()))
540 CFG_TRACE_ERROR_NI(" - cannot normalized result: failing");
542 rtl::OUString
sMsg(RTL_CONSTASCII_USTRINGPARAM("Requested data at '"));
543 sMsg
+= aRequestPath
.toString();
544 sMsg
+= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("'is not available: "));
546 throw com::sun::star::container::NoSuchElementException(sMsg
,NULL
);
549 CFG_TRACE_INFO_NI(" - returning normalized defaults");
553 // -----------------------------------------------------------------------------
555 ResultHolder
< NodeInstance
> CacheController::loadDefaultsDirectly(NodeRequest
const & _aRequest
) SAL_THROW((com::sun::star::uno::Exception
))
557 CFG_TRACE_INFO("CacheController: loading defaults for '%s' from the backend", OUSTRING2ASCII(_aRequest
.getPath().toString()));
559 ResultHolder
< NodeInstance
> aResult
= m_xBackend
->getDefaultData(_aRequest
);
561 CFG_TRACE_INFO_NI("- loading defaultscompleted - normalizing result");
563 normalizeResult(aResult
.mutableInstance().mutableData(),_aRequest
.getOptions());
565 CFG_TRACE_INFO_NI(" - returning normalized defaults");
569 // -----------------------------------------------------------------------------
571 void CacheController::saveDirectly(UpdateRequest
const & _anUpdate
) SAL_THROW((com::sun::star::uno::Exception
))
573 m_xBackend
->updateNodeData(_anUpdate
);
575 // -----------------------------------------------------------------------------
577 void CacheController::savePendingChanges(rtl::Reference
<CacheLoadingAccess
> const & _aCache
, ComponentRequest
const & _aComponent
) SAL_THROW((com::sun::star::uno::Exception
))
579 CFG_TRACE_INFO("CacheController: saving updates for tree: '%s'", OUSTRING2ASCII(_aComponent
.getComponentName()));
583 CFG_TRACE_INFO2("CacheController: saving updates for tree: '%s'", OUSTRING2ASCII(_aComponent
.getComponentName()));
585 std::auto_ptr
<SubtreeChange
> aChangeData
= _aCache
->releasePendingChanges(_aComponent
.getComponentName());
587 if (aChangeData
.get())
589 CFG_TRACE_INFO_NI("- found changes - sending to backend");
591 configuration::AbsolutePath aRootPath
= configuration::AbsolutePath::makeModulePath(_aComponent
.getComponentName());
593 backend::UpdateRequest
anUpdateSpec(aChangeData
.get(),aRootPath
,_aComponent
.getOptions());
595 // anUpdateSpec.setRequestId(pInfo->getRequestId(_aRootPath));
597 this->saveDirectly(anUpdateSpec
);
599 CFG_TRACE_INFO_NI("- saving changes completed successfully");
602 CFG_TRACE_WARNING_NI("- no changes found - cannot save");
604 catch(uno::Exception
& e
)
607 CFG_TRACE_ERROR_NI("CacheController: saving tree '%s' failed: %s",
608 OUSTRING2ASCII(_aComponent
.getComponentName()),
609 OUSTRING2ASCII(e
.Message
) );
611 refreshComponent(_aComponent
);
612 CFG_TRACE_INFO_NI("- component data invalidated");
617 // -----------------------------------------------------------------------------
619 bool CacheController::saveAllPendingChanges(rtl::Reference
<CacheLoadingAccess
> const & _aCache
, RequestOptions
const & _aOptions
)
620 SAL_THROW((com::sun::star::uno::RuntimeException
))
622 CFG_TRACE_INFO("CacheController: Saving all pending changes for cache line");
623 OSL_ASSERT(_aCache
.is());
625 std::vector
< rtl::OUString
> aPendingModules
;
626 _aCache
->findPendingChangedModules(aPendingModules
);
628 CFG_TRACE_INFO_NI("Found %d changed modules",int(aPendingModules
.size()));
630 bool bSuccess
= true;
631 for (std::vector
< rtl::OUString
>::iterator it
= aPendingModules
.begin();
632 it
!= aPendingModules
.end();
637 this->savePendingChanges(_aCache
, ComponentRequest(*it
,_aOptions
) );
639 catch (uno::Exception
& )
641 CFG_TRACE_ERROR_NI("CacheController: Exception while saving one module - ignoring");
645 CFG_TRACE_INFO_NI("Done saving pending changes for cache line");
649 // -----------------------------------------------------------------------------
652 //-----------------------------------------------------------------------------
653 void CacheController::freeComponent(ComponentRequest
const & _aRequest
) SAL_THROW(())
655 CFG_TRACE_INFO("CacheController: releasing module '%s' for user '%s' with locale '%s'",
656 OUSTRING2ASCII(_aRequest
.getComponentName()),
657 OUSTRING2ASCII(_aRequest
.getOptions().getEntity()),
658 OUSTRING2ASCII(_aRequest
.getOptions().getLocale()) );
660 rtl::Reference
<CacheLoadingAccess
> aCache
= m_aCacheMap
.get(_aRequest
.getOptions());
662 OSL_ENSURE(aCache
.is(), "Releasing a nonexisting module");
666 if (aCache
->releaseModule(_aRequest
.getComponentName()) == 0)
669 m_pDisposer
->scheduleCleanup(_aRequest
.getOptions());
673 // -----------------------------------------------------------------------------
674 void CacheController::dataChanged(const ComponentRequest
& _aRequest
) SAL_THROW(())
676 refreshComponent(_aRequest
);
678 // -----------------------------------------------------------------------------
679 void CacheController::refreshAllComponents() SAL_THROW((com::sun::star::uno::Exception
))
681 CacheMap::Map aRefreshList
= m_aCacheMap
.copy();
683 for (CacheMap::Map::iterator i
= aRefreshList
.begin();
684 i
!= aRefreshList
.end(); ++i
)
686 if (!i
->second
->isEmpty())
688 ExtendedCacheData aCacheData
= i
->second
->m_aData
;
689 RequestOptions aOption
= i
->first
;
690 CacheData::ModuleList aModuleList
= aCacheData
.accessModuleList();
691 for (CacheData::ModuleList::iterator itr
= aModuleList
.begin();
692 itr
!= aModuleList
.end(); ++itr
)
694 //Check the cacheline has atleast one client reference
697 if (itr
->second
->clientReferences() > 0)
699 ComponentRequest
aRequest(itr
->first
,i
->first
);
700 refreshComponent(aRequest
);
703 // FIXME: otherwise dispose now
704 // XXX: (lo) refresh all, preventing cache corruption.
705 // An unused component should be purged from the cache
706 // instead of being refreshed
707 ComponentRequest
aRequest(itr
->first
,i
->first
);
708 refreshComponent(aRequest
);
715 // -------------------------------------------------------------------------
718 // -------------------------------------------------------------------------