update dev300-m58
[ooovba.git] / configmgr / source / treecache / cachecontroller.cxx
blob513e134e5ab94577370fa35da03936bbd97bbe74
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: cachecontroller.cxx,v $
10 * $Revision: 1.21 $
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"
40 #include "tracer.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"
48 #endif
51 #define RTL_LOGFILE_OU2A(rtlOUString) (::rtl::OUStringToOString((rtlOUString), RTL_TEXTENCODING_ASCII_US).getStr())
53 namespace configmgr
55 // -------------------------------------------------------------------------
56 namespace backend
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);
104 if (!aResult.is())
106 rtl::Reference<CacheLoadingAccess> aNewCache( new CacheLoadingAccess() );
107 aResult = m_aCacheMap.insert(_aOptions,aNewCache);
109 return aResult;
112 // -------------------------------------------------------------------------
114 // disposing
115 // -------------------------------------------------------------------------
116 void CacheController::disposeAll(bool _bFlushRemainingUpdates)
118 CFG_TRACE_INFO("CacheController: Disposing all data" );
119 CacheMap::Map aReleaseList;
121 if (m_pDisposer)
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))
139 UnoApiLock aLock;
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)
156 : m_aNotifier()
157 , m_xBackend(_xBackend)
158 , m_aCacheMap()
159 , m_aTemplates()
160 , m_pDisposer()
161 , m_pCacheWriter()
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.");
173 delete m_pDisposer;
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 // -------------------------------------------------------------------------
189 #if 0
190 static
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());
199 if (aReduced.get())
201 if (ISubtree* pReduced =aReduced->asISubtree())
203 aRet.reset(pReduced);
204 aReduced.release();
206 else
208 OSL_ENSURE(false, "Tree unexpectedly reduced to non-tree");
211 else
212 OSL_ENSURE(!_pSubtree.get(), "Tree unexpectedly reduced to nothing");
214 return aRet;
216 #endif
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());
242 else
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);
271 return aRet;
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);
283 return aRet;
285 // -------------------------------------------------------------------------
287 configuration::AbsolutePath CacheController::encodeTemplateLocation(const rtl::OUString& _rName, const rtl::OUString &_rModule) const
289 namespace Path = configuration::Path;
291 // static const
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 // -------------------------------------------------------------------------
304 #if 0
305 static
306 configuration::AbsolutePath templateLoadLocation(const configuration::AbsolutePath &_rTemplateLocation)
308 namespace Path = configuration::Path;
310 static const
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);
318 #endif
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);
332 else
333 OSL_ENSURE(false,"Requested multiple templates, got non-subtree node");
335 else
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);
389 //add-if-not-loaded
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) );
451 else
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);
465 e.unhandled();
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);
483 if (m_pCacheWriter)
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;
502 if (aReduced.get())
504 if (ISubtree* pReducedTree =aReduced->asISubtree())
506 aReduced.release();
507 aReducedTree.reset(pReducedTree);
509 else
511 OSL_ENSURE(false, "Tree unexpectedly reduced to non-tree");
514 else
515 OSL_ENSURE(false, "Tree unexpectedly reduced to nothing");
518 _aResult = aReducedTree;
519 bool retCode = _aResult.get()!=NULL ? true : false;
520 return retCode;
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");
551 return aResult;
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");
567 return aResult;
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");
601 else
602 CFG_TRACE_WARNING_NI("- no changes found - cannot save");
604 catch(uno::Exception& e)
606 (void)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");
614 throw;
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();
633 ++it )
637 this->savePendingChanges(_aCache, ComponentRequest(*it,_aOptions) );
639 catch (uno::Exception & )
641 CFG_TRACE_ERROR_NI("CacheController: Exception while saving one module - ignoring");
642 bSuccess = false;
645 CFG_TRACE_INFO_NI("Done saving pending changes for cache line");
647 return bSuccess;
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");
664 if (aCache.is())
666 if (aCache->releaseModule(_aRequest.getComponentName()) == 0)
668 // start the cleanup
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);
701 } else
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 // -------------------------------------------------------------------------
716 } // namespace
718 // -------------------------------------------------------------------------
719 } // namespace