diff options
-rw-r--r-- | desktop/qa/desktop_lib/test_desktop_lib.cxx | 5 | ||||
-rw-r--r-- | desktop/source/lib/init.cxx | 18 | ||||
-rw-r--r-- | include/LibreOfficeKit/LibreOfficeKit.h | 3 | ||||
-rw-r--r-- | include/LibreOfficeKit/LibreOfficeKit.hxx | 9 | ||||
-rw-r--r-- | include/comphelper/lok.hxx | 2 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-curl/CurlSession.cxx | 43 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-curl/SerfLockStore.cxx | 35 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-curl/SerfLockStore.hxx | 12 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-curl/ucpdav1.component | 4 |
9 files changed, 117 insertions, 14 deletions
diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index 298e5a5d7a9b..4a09b10931f6 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -3594,11 +3594,12 @@ void DesktopLOKTest::testABI() CPPUNIT_ASSERT_EQUAL(classOffset(18), offsetof(struct _LibreOfficeKitClass, startURP)); CPPUNIT_ASSERT_EQUAL(classOffset(19), offsetof(struct _LibreOfficeKitClass, stopURP)); CPPUNIT_ASSERT_EQUAL(classOffset(20), offsetof(struct _LibreOfficeKitClass, joinThreads)); - CPPUNIT_ASSERT_EQUAL(classOffset(21), offsetof(struct _LibreOfficeKitClass, setForkedChild)); + CPPUNIT_ASSERT_EQUAL(classOffset(21), offsetof(struct _LibreOfficeKitClass, startThreads)); + CPPUNIT_ASSERT_EQUAL(classOffset(22), offsetof(struct _LibreOfficeKitClass, setForkedChild)); // When extending LibreOfficeKit with a new function pointer, add new assert for the offsetof the // new function pointer and bump this assert for the size of the class. - CPPUNIT_ASSERT_EQUAL(classOffset(22), sizeof(struct _LibreOfficeKitClass)); + CPPUNIT_ASSERT_EQUAL(classOffset(23), sizeof(struct _LibreOfficeKitClass)); CPPUNIT_ASSERT_EQUAL(documentClassOffset(0), offsetof(struct _LibreOfficeKitDocumentClass, destroy)); CPPUNIT_ASSERT_EQUAL(documentClassOffset(1), offsetof(struct _LibreOfficeKitDocumentClass, saveAs)); diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index f00edb9ec9c9..86f0efda8857 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -2602,6 +2602,8 @@ static void lo_stopURP(LibreOfficeKit* pThis, void* pSendURPToLOContext); static int lo_joinThreads(LibreOfficeKit* pThis); +static void lo_startThreads(LibreOfficeKit* pThis); + static void lo_setForkedChild(LibreOfficeKit* pThis, bool bIsChild); static void lo_runLoop(LibreOfficeKit* pThis, @@ -2649,6 +2651,7 @@ LibLibreOffice_Impl::LibLibreOffice_Impl() m_pOfficeClass->startURP = lo_startURP; m_pOfficeClass->stopURP = lo_stopURP; m_pOfficeClass->joinThreads = lo_joinThreads; + m_pOfficeClass->startThreads = lo_startThreads; m_pOfficeClass->setForkedChild = lo_setForkedChild; gOfficeClass = m_pOfficeClass; @@ -3399,6 +3402,12 @@ static int lo_joinThreads(LibreOfficeKit* /* pThis */) if (joinable && !joinable->joinThreads()) return 0; + auto ucpWebdav = xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.ucb.WebDAVManager", xContext); + joinable = dynamic_cast<comphelper::LibreOfficeKit::ThreadJoinable *>(ucpWebdav.get()); + if (joinable && !joinable->joinThreads()) + return 0; + // Ensure configmgr's write thread is down css::uno::Reference< css::util::XFlushable >( css::configuration::theDefaultProvider::get( @@ -3408,6 +3417,15 @@ static int lo_joinThreads(LibreOfficeKit* /* pThis */) return 1; } +static void lo_startThreads(LibreOfficeKit* /* pThis */) +{ + auto ucpWebdav = xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.ucb.WebDAVManager", xContext); + auto joinable = dynamic_cast<comphelper::LibreOfficeKit::ThreadJoinable *>(ucpWebdav.get()); + if (joinable) + joinable->startThreads(); +} + static void lo_setForkedChild(LibreOfficeKit* /* pThis */, bool bIsChild) { comphelper::LibreOfficeKit::setForkedChild(bIsChild); diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h index f57c7ad32843..2a0df3348f8d 100644 --- a/include/LibreOfficeKit/LibreOfficeKit.h +++ b/include/LibreOfficeKit/LibreOfficeKit.h @@ -144,6 +144,9 @@ struct _LibreOfficeKitClass /// @see lok::Office::joinThreads int (*joinThreads)(LibreOfficeKit* pThis); + /// @see lok::Office::startThreads + void (*startThreads)(LibreOfficeKit* pThis); + /// @see lok::Office::setForkedChild void (*setForkedChild)(LibreOfficeKit* pThis, bool bIsChild); }; diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx index af9ccd12ab2f..14ad6a86f913 100644 --- a/include/LibreOfficeKit/LibreOfficeKit.hxx +++ b/include/LibreOfficeKit/LibreOfficeKit.hxx @@ -1224,6 +1224,15 @@ public: } /** + * Starts all threads that are necessary to continue working + * after a joinThreads(). + */ + void startThreads() + { + mpThis->pClass->startThreads(mpThis); + } + + /** * Informs that this process is either a parent, or a child * process post-fork, allowing improved resource sharing. */ diff --git a/include/comphelper/lok.hxx b/include/comphelper/lok.hxx index 555b749fa6a1..f998c12dedc3 100644 --- a/include/comphelper/lok.hxx +++ b/include/comphelper/lok.hxx @@ -26,6 +26,8 @@ class COMPHELPER_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") ThreadJoinable public: /// shutdown and join threads, @returns true on success virtual bool joinThreads() = 0; + /// restart any required threads, usually are demand-restarted + virtual void startThreads() {} }; // Functions to be called only from the LibreOfficeKit implementation in desktop, not from other diff --git a/ucb/source/ucp/webdav-curl/CurlSession.cxx b/ucb/source/ucp/webdav-curl/CurlSession.cxx index e60bd6ef1d36..a80c19f6d690 100644 --- a/ucb/source/ucp/webdav-curl/CurlSession.cxx +++ b/ucb/source/ucp/webdav-curl/CurlSession.cxx @@ -14,9 +14,13 @@ #include "UCBDeadPropertyValue.hxx" #include "webdavresponseparser.hxx" +#include <cppuhelper/implbase.hxx> +#include <comphelper/processfactory.hxx> #include <comphelper/attributelist.hxx> #include <comphelper/scopeguard.hxx> #include <comphelper/string.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/supportsservice.hxx> #include <o3tl/safeint.hxx> #include <o3tl/string_view.hxx> @@ -26,6 +30,7 @@ #include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/io/Pipe.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/io/SequenceInputStream.hpp> #include <com/sun/star/io/SequenceOutputStream.hpp> #include <com/sun/star/xml/sax/Writer.hpp> @@ -2430,4 +2435,42 @@ auto CurlSession::NonInteractive_UNLOCK(OUString const& rURI) -> void } // namespace http_dav_ucp +namespace +{ +/// Manage lifecycle of global DAV worker threads +class WebDAVManager : public cppu::WeakImplHelper<css::lang::XServiceInfo>, + public comphelper::LibreOfficeKit::ThreadJoinable +{ +public: + WebDAVManager() {} + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override + { + return "com.sun.star.comp.WebDAVManager"; + } + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override + { + return cppu::supportsService(this, ServiceName); + } + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override + { + return { "com.sun.star.ucb.WebDAVManager" }; + } + + // comphelper::LibreOfficeKit::ThreadJoinable + virtual bool joinThreads() override { return g_Init.LockStore.joinThreads(); } + + virtual void startThreads() override { g_Init.LockStore.startThreads(); } +}; + +} // anonymous namespace + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +ucb_webdav_manager_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new WebDAVManager()); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/ucp/webdav-curl/SerfLockStore.cxx b/ucb/source/ucp/webdav-curl/SerfLockStore.cxx index 6d7b89e9e687..cfa6f666b056 100644 --- a/ucb/source/ucp/webdav-curl/SerfLockStore.cxx +++ b/ucb/source/ucp/webdav-curl/SerfLockStore.cxx @@ -101,10 +101,8 @@ SerfLockStore::~SerfLockStore() } } -void SerfLockStore::startTicker() +void SerfLockStore::startTicker(std::unique_lock<std::mutex> & /* rGuard is held */) { - std::unique_lock aGuard( m_aMutex ); - if ( !m_pTickerThread.is() ) { m_pTickerThread = new TickerThread( *this ); @@ -112,7 +110,6 @@ void SerfLockStore::startTicker() } } - void SerfLockStore::stopTicker(std::unique_lock<std::mutex> & rGuard) { rtl::Reference<TickerThread> pTickerThread; @@ -122,6 +119,7 @@ void SerfLockStore::stopTicker(std::unique_lock<std::mutex> & rGuard) m_pTickerThread->finish(); // needs mutex // the TickerThread may run refreshLocks() at most once after this pTickerThread = m_pTickerThread; + m_pTickerThread.clear(); } @@ -133,6 +131,25 @@ void SerfLockStore::stopTicker(std::unique_lock<std::mutex> & rGuard) } } +bool SerfLockStore::joinThreads() +{ + std::unique_lock aGuard(m_aMutex); + // FIXME: cure could be worse than the problem; we don't + // want to block on a long-standing webdav lock refresh request. + // perhaps we should timeout on a condition instead if a request + // is in progress. + if (m_pTickerThread.is()) + stopTicker(aGuard); + return true; +} + +void SerfLockStore::startThreads() +{ + std::unique_lock aGuard( m_aMutex ); + if (!m_aLockInfoMap.empty()) + startTicker(aGuard); +} + OUString const* SerfLockStore::getLockTokenForURI(OUString const& rURI, css::ucb::Lock const*const pLock) { @@ -175,14 +192,12 @@ void SerfLockStore::addLock( const OUString& rURI, sal_Int32 nLastChanceToSendRefreshRequest ) { assert(rURI.startsWith("http://") || rURI.startsWith("https://")); - { - std::unique_lock aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); - m_aLockInfoMap[ rURI ] - = LockInfo(sToken, rLock, xSession, nLastChanceToSendRefreshRequest); - } + m_aLockInfoMap[ rURI ] + = LockInfo(sToken, rLock, xSession, nLastChanceToSendRefreshRequest); - startTicker(); + startTicker(aGuard); } diff --git a/ucb/source/ucp/webdav-curl/SerfLockStore.hxx b/ucb/source/ucp/webdav-curl/SerfLockStore.hxx index 8b54901e1fb8..08a88746b0d0 100644 --- a/ucb/source/ucp/webdav-curl/SerfLockStore.hxx +++ b/ucb/source/ucp/webdav-curl/SerfLockStore.hxx @@ -26,6 +26,7 @@ #include <rtl/ustring.hxx> #include <com/sun/star/ucb/Lock.hpp> #include <utility> +#include <comphelper/lok.hxx> #include "CurlSession.hxx" @@ -57,7 +58,7 @@ struct LockInfo typedef std::map< OUString, LockInfo > LockInfoMap; -class SerfLockStore +class SerfLockStore : public comphelper::LibreOfficeKit::ThreadJoinable { std::mutex m_aMutex; rtl::Reference< TickerThread > m_pTickerThread; @@ -81,9 +82,16 @@ public: void refreshLocks(); + void joinThread(); + void restartThread(); + + // comphelper::LibreOfficeKit::ThreadJoinable + virtual bool joinThreads() override; + virtual void startThreads() override; + private: void removeLockImpl(std::unique_lock<std::mutex> & rGuard, const OUString& rURI); - void startTicker(); + void startTicker(std::unique_lock<std::mutex> & rGuard); void stopTicker(std::unique_lock<std::mutex> & rGuard); }; diff --git a/ucb/source/ucp/webdav-curl/ucpdav1.component b/ucb/source/ucp/webdav-curl/ucpdav1.component index bb16e3b3979d..678e860c1178 100644 --- a/ucb/source/ucp/webdav-curl/ucpdav1.component +++ b/ucb/source/ucp/webdav-curl/ucpdav1.component @@ -23,4 +23,8 @@ constructor="ucb_webdav_ContentProvider_get_implementation"> <service name="com.sun.star.ucb.WebDAVContentProvider"/> </implementation> + <implementation name="com.sun.star.comp.WebDAVManager" + constructor="ucb_webdav_manager_get_implementation" single-instance="true"> + <service name="com.sun.star.ucb.WebDAVManager"/> + </implementation> </component> |