diff options
-rw-r--r-- | configmgr/source/components.cxx | 84 | ||||
-rw-r--r-- | configmgr/source/components.hxx | 8 | ||||
-rw-r--r-- | configmgr/source/configurationprovider.cxx | 16 | ||||
-rw-r--r-- | desktop/inc/app.hxx | 1 | ||||
-rw-r--r-- | desktop/source/app/app.cxx | 32 |
5 files changed, 127 insertions, 14 deletions
diff --git a/configmgr/source/components.cxx b/configmgr/source/components.cxx index cc5ea1e1e739..d812e54498ac 100644 --- a/configmgr/source/components.cxx +++ b/configmgr/source/components.cxx @@ -29,6 +29,7 @@ #include "sal/config.h" #include <algorithm> +#include <cstddef> #include <list> #include "com/sun/star/beans/Optional.hpp" @@ -43,8 +44,11 @@ #include "com/sun/star/uno/RuntimeException.hpp" #include "com/sun/star/uno/XComponentContext.hpp" #include "com/sun/star/uno/XInterface.hpp" +#include "osl/conditn.hxx" #include "osl/diagnose.h" #include "osl/file.hxx" +#include "osl/mutex.hxx" +#include "osl/thread.hxx" #include "rtl/bootstrap.hxx" #include "rtl/logfile.h" #include "rtl/ref.hxx" @@ -53,10 +57,12 @@ #include "rtl/ustring.h" #include "rtl/ustring.hxx" #include "sal/types.h" +#include "salhelper/simplereferenceobject.hxx" #include "additions.hxx" #include "components.hxx" #include "data.hxx" +#include "lock.hxx" #include "modifications.hxx" #include "node.hxx" #include "nodemap.hxx" @@ -148,6 +154,66 @@ static Components * singleton = 0; } +class Components::WriteThread: + public osl::Thread, public salhelper::SimpleReferenceObject +{ +public: + static void * operator new(std::size_t size) + { return Thread::operator new(size); } + + static void operator delete(void * pointer) + { Thread::operator delete(pointer); } + + WriteThread( + rtl::Reference< WriteThread > * reference, Components & components, + rtl::OUString const & url, Data const & data); + + void flush() { delay_.set(); } + +private: + virtual ~WriteThread() {} + + virtual void SAL_CALL run(); + + virtual void SAL_CALL onTerminated() { release(); } + + rtl::Reference< WriteThread > * reference_; + Components & components_; + rtl::OUString url_; + Data const & data_; + osl::Condition delay_; +}; + +Components::WriteThread::WriteThread( + rtl::Reference< WriteThread > * reference, Components & components, + rtl::OUString const & url, Data const & data): + reference_(reference), components_(components), url_(url), data_(data) +{ + OSL_ASSERT(reference != 0); + acquire(); +} + +void Components::WriteThread::run() { + TimeValue t = { 1, 0 }; // 1 sec + delay_.wait(&t); // must not throw; result_error is harmless and ignored + osl::MutexGuard g(lock); // must not throw + try { + try { + writeModFile(components_, url_, data_); + } catch (css::uno::RuntimeException & e) { + // Silently ignore write errors, instead of aborting: + OSL_TRACE( + "configmgr error writing modifications: %s", + rtl::OUStringToOString( + e.Message, RTL_TEXTENCODING_UTF8).getStr()); + } + } catch (...) { + reference_->clear(); + throw; + } + reference_->clear(); +} + void Components::initSingleton( css::uno::Reference< css::uno::XComponentContext > const & context) { @@ -238,7 +304,23 @@ void Components::addModification(Path const & path) { } void Components::writeModifications() { - writeModFile(*this, getModificationFileUrl(), data_); + if (!writeThread_.is()) { + writeThread_ = new WriteThread( + &writeThread_, *this, getModificationFileUrl(), data_); + writeThread_->create(); + } +} + +void Components::flushModifications() { + rtl::Reference< WriteThread > thread; + { + osl::MutexGuard g(lock); + thread = writeThread_; + } + if (thread.is()) { + thread->flush(); + thread->join(); + } } void Components::insertExtensionXcsFile( diff --git a/configmgr/source/components.hxx b/configmgr/source/components.hxx index 4fc47f791821..1c735efca6ba 100644 --- a/configmgr/source/components.hxx +++ b/configmgr/source/components.hxx @@ -94,6 +94,11 @@ public: void writeModifications(); + void flushModifications(); + // must be called with configmgr::lock unaquired; must be called before + // shutdown if writeModifications has ever been called (probably + // indirectly, via removeExtensionXcuFile) + void insertExtensionXcsFile(bool shared, rtl::OUString const & fileUri); void insertExtensionXcuFile( @@ -160,11 +165,14 @@ private: com::sun::star::beans::XPropertySet > > ExternalServices; + class WriteThread; + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > context_; Data data_; WeakRootSet roots_; ExternalServices externalServices_; + rtl::Reference< WriteThread > writeThread_; }; } diff --git a/configmgr/source/configurationprovider.cxx b/configmgr/source/configurationprovider.cxx index 78d71e73e7d5..3cd58b145bff 100644 --- a/configmgr/source/configurationprovider.cxx +++ b/configmgr/source/configurationprovider.cxx @@ -114,6 +114,8 @@ public: private: virtual ~Service() {} + virtual void SAL_CALL disposing() { flushModifications(); } + virtual rtl::OUString SAL_CALL getImplementationName() throw (css::uno::RuntimeException) { return configuration_provider::getImplementationName(); } @@ -166,6 +168,8 @@ private: virtual css::lang::Locale SAL_CALL getLocale() throw (css::uno::RuntimeException); + void flushModifications() const; + css::uno::Reference< css::uno::XComponentContext > context_; rtl::OUString locale_; }; @@ -326,7 +330,7 @@ void Service::removeRefreshListener( } void Service::flush() throw (css::uno::RuntimeException) { - //TODO + flushModifications(); cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer( cppu::UnoType< css::util::XFlushListener >::get()); if (cont != 0) { @@ -380,6 +384,16 @@ css::lang::Locale Service::getLocale() throw (css::uno::RuntimeException) { return loc; } +void Service::flushModifications() const { + Components * components; + { + osl::MutexGuard guard(lock); + Components::initSingleton(context_); + components = &Components::getSingleton(); + } + components->flushModifications(); +} + class Factory: public cppu::WeakImplHelper1< css::lang::XSingleComponentFactory >, private boost::noncopyable diff --git a/desktop/inc/app.hxx b/desktop/inc/app.hxx index fa7550812bbe..8eb4dd3cc25b 100644 --- a/desktop/inc/app.hxx +++ b/desktop/inc/app.hxx @@ -155,6 +155,7 @@ class Desktop : public Application sal_Bool InitializeInstallation( const rtl::OUString& rAppFilename ); sal_Bool InitializeConfiguration(); + void FlushConfiguration(); sal_Bool InitializeQuickstartMode( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rSMgr ); void HandleBootstrapPathErrors( ::utl::Bootstrap::Status, const ::rtl::OUString& aMsg ); diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx index f5d6979bc4b1..e77c1dcf48ac 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -754,6 +754,7 @@ void Desktop::DeInit() // instead of removing of the configManager just let it commit all the changes RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); utl::ConfigManager::GetConfigManager()->StoreConfigItems(); + FlushConfiguration(); RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); // close splashscreen if it's still open @@ -784,6 +785,7 @@ BOOL Desktop::QueryExit() { RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); utl::ConfigManager::GetConfigManager()->StoreConfigItems(); + FlushConfiguration(); RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); } catch ( RuntimeException& ) @@ -1436,18 +1438,7 @@ USHORT Desktop::Exception(USHORT nError) if ( bAllowRecoveryAndSessionManagement ) bRestart = SaveTasks(); - // because there is no method to flush the condiguration data, we must dispose the ConfigManager - Reference < XFlushable > xCFGFlush( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY ); - if (xCFGFlush.is()) - { - xCFGFlush->flush(); - } - else - { - Reference < XComponent > xCFGDispose( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY ); - if (xCFGDispose.is()) - xCFGDispose->dispose(); - } + FlushConfiguration(); switch( nError & EXC_MAJORTYPE ) { @@ -1976,6 +1967,7 @@ void Desktop::Main() // remove temp directory RemoveTemporaryDirectory(); + FlushConfiguration(); // The acceptors in the AcceptorMap must be released (in DeregisterServices) // with the solar mutex unlocked, to avoid deadlock: nAcquireCount = Application::ReleaseSolarMutex(); @@ -2073,6 +2065,22 @@ sal_Bool Desktop::InitializeConfiguration() return bOk; } +void Desktop::FlushConfiguration() +{ + Reference < XFlushable > xCFGFlush( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY ); + if (xCFGFlush.is()) + { + xCFGFlush->flush(); + } + else + { + // because there is no method to flush the condiguration data, we must dispose the ConfigManager + Reference < XComponent > xCFGDispose( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY ); + if (xCFGDispose.is()) + xCFGDispose->dispose(); + } +} + sal_Bool Desktop::InitializeQuickstartMode( Reference< XMultiServiceFactory >& rSMgr ) { try |