desktop/qa/desktop_lib/test_desktop_lib.cxx  |    7 ++--
 desktop/source/lib/init.cxx                  |   18 +++++++++++
 include/LibreOfficeKit/LibreOfficeKit.h      |    3 +
 include/LibreOfficeKit/LibreOfficeKit.hxx    |    9 +++++
 include/comphelper/lok.hxx                   |    2 +
 ucb/source/ucp/webdav-curl/CurlSession.cxx   |   43 +++++++++++++++++++++++++++
 ucb/source/ucp/webdav-curl/SerfLockStore.cxx |   35 +++++++++++++++------
 ucb/source/ucp/webdav-curl/SerfLockStore.hxx |   12 ++++++-
 ucb/source/ucp/webdav-curl/ucpdav1.component |    4 ++
 9 files changed, 118 insertions(+), 15 deletions(-)

New commits:
commit f9df8d71a9d4ad2e7bc2e221551d9ee007f9fc60
Author:     Michael Meeks <[email protected]>
AuthorDate: Sat May 18 22:08:22 2024 +0100
Commit:     Michael Meeks <[email protected]>
CommitDate: Fri Jul 26 13:37:26 2024 +0200

    lok: join Webdav Ticker thread.
    
    Add 'startThreads' lok method for the few thread scenarios where
    we need to have a background thread running that cannot be started
    opportunistically.
    
    Also add that to the ThreadJoinable interface so we can get into
    UNO components' implementations to handle their worker threads
    easily.
    
    Implement joining and re-starting in WebDAV ucp too.
    
    Change-Id: I329ef9decb32b263197e4c03a0d54952985fdd0e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167858
    Reviewed-by: Michael Meeks <[email protected]>
    Reviewed-by: Caolán McNamara <[email protected]>
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170979
    Tested-by: Jenkins

diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx 
b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index c5d981ca6c58..3636b8cd9df0 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -3589,12 +3589,13 @@ 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(22), offsetof(struct 
_LibreOfficeKitClass, extractDocumentStructureRequest));
+    CPPUNIT_ASSERT_EQUAL(classOffset(21), offsetof(struct 
_LibreOfficeKitClass, startThreads));
+    CPPUNIT_ASSERT_EQUAL(classOffset(22), offsetof(struct 
_LibreOfficeKitClass, setForkedChild));
+    CPPUNIT_ASSERT_EQUAL(classOffset(23), offsetof(struct 
_LibreOfficeKitClass, extractDocumentStructureRequest));
 
     // 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(23), sizeof(struct _LibreOfficeKitClass));
+    CPPUNIT_ASSERT_EQUAL(classOffset(24), 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 7d4b9d5041f6..442d88eaeecf 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -2575,6 +2575,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,
@@ -2625,6 +2627,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;
         m_pOfficeClass->extractDocumentStructureRequest = 
lo_extractDocumentStructureRequest;
 
@@ -3443,6 +3446,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(
@@ -3452,6 +3461,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 da1ddbe13d7f..8691d56131c6 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 3f165c3e5363..238168ebdb3b 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -1250,6 +1250,15 @@ public:
         return mpThis->pClass->joinThreads(mpThis);
     }
 
+    /**
+     * 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 65fc7e6481d7..bd7b3b64c71c 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>
@@ -2572,4 +2577,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>

Reply via email to