[Libreoffice-commits] core.git: cppuhelper/source desktop/Library_sofficeapp.mk desktop/source include/cppuhelper smoketest/libtest.cxx

Henry Castro hcastro at collabora.com
Mon Feb 15 14:35:55 UTC 2016


 cppuhelper/source/defaultbootstrap.cxx |   16 ++++
 cppuhelper/source/gcc3.map             |    5 +
 cppuhelper/source/servicemanager.cxx   |   35 ++++++++++
 cppuhelper/source/servicemanager.hxx   |    2 
 desktop/Library_sofficeapp.mk          |    1 
 desktop/source/lib/init.cxx            |  113 +++++++++++++++++++++++----------
 include/cppuhelper/detail/preinit.hxx  |   29 ++++++++
 smoketest/libtest.cxx                  |   24 ++++++-
 8 files changed, 193 insertions(+), 32 deletions(-)

New commits:
commit df5f7c6abab820070771c5304514faf2a07bc588
Author: Henry Castro <hcastro at collabora.com>
Date:   Fri Feb 12 11:46:37 2016 -0500

    Introduce lok_preinit() to preload all registered UNO implementations
    
    Intended to be used from an application like the LibreOffice On-Line
    server so that it can be called in a process that then will call
    fork() several times, and much space consuming data will end up being
    shared.
    
    Change-Id: I65341c57d00308d246ec90deab8050b2c4bb3e61

diff --git a/cppuhelper/source/defaultbootstrap.cxx b/cppuhelper/source/defaultbootstrap.cxx
index bede6b5..c0a2c2e 100644
--- a/cppuhelper/source/defaultbootstrap.cxx
+++ b/cppuhelper/source/defaultbootstrap.cxx
@@ -18,6 +18,7 @@
 #include <com/sun/star/uno/XComponentContext.hpp>
 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
 #include <cppuhelper/bootstrap.hxx>
+#include <cppuhelper/detail/preinit.hxx>
 #include <cppuhelper/component_context.hxx>
 #include <rtl/bootstrap.hxx>
 #include <rtl/ref.hxx>
@@ -107,4 +108,19 @@ cppu::defaultBootstrap_InitialComponentContext()
     return defaultBootstrap_InitialComponentContext(getUnoIniUri());
 }
 
+void
+cppu::preInitBootstrap()
+{
+    rtl::OUString iniUri(getUnoIniUri());
+    rtl::Bootstrap bs(iniUri);
+    if (bs.getHandle() == nullptr)
+        throw css::uno::DeploymentException("Cannot open uno ini " + iniUri);
+
+    // create the service manager
+    rtl::Reference< cppuhelper::ServiceManager > aManager(new cppuhelper::ServiceManager);
+    // read rdb files
+    aManager->init(getBootstrapVariable(bs, "UNO_SERVICES"));
+    aManager->loadAllImplementations();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/gcc3.map b/cppuhelper/source/gcc3.map
index 12c29834a..20d0e13 100644
--- a/cppuhelper/source/gcc3.map
+++ b/cppuhelper/source/gcc3.map
@@ -436,3 +436,8 @@ GLIBCXX_3.4 {
         _ZGVNSt7num_put*; _ZNSt7num_put*;
         _ZNSs4_Rep20_S_empty_rep_storageE;
 };
+
+PRIVATE_1.0 { # LibO 5.2
+    global:
+        _ZN4cppu16preInitBootstrapEv;
+};
diff --git a/cppuhelper/source/servicemanager.cxx b/cppuhelper/source/servicemanager.cxx
index 2d824d4..d89289a 100644
--- a/cppuhelper/source/servicemanager.cxx
+++ b/cppuhelper/source/servicemanager.cxx
@@ -34,6 +34,7 @@
 #include <cppuhelper/implbase3.hxx>
 #include <cppuhelper/supportsservice.hxx>
 #include <osl/file.hxx>
+#include <osl/module.hxx>
 #include <rtl/ref.hxx>
 #include <rtl/uri.hxx>
 #include <rtl/ustring.hxx>
@@ -875,6 +876,40 @@ void cppuhelper::ServiceManager::loadImplementation(
     }
 }
 
+void cppuhelper::ServiceManager::loadAllImplementations()
+{
+    rtl::OUString aUri;
+    osl::MutexGuard g(rBHelper.rMutex);
+
+    for (Data::NamedImplementations::const_iterator iterator(
+            data_.namedImplementations.begin());
+            iterator != data_.namedImplementations.end(); ++iterator)
+    {
+        try
+        {
+            aUri = cppu::bootstrap_expandUri(iterator->second->info->uri);
+        }
+        catch (css::lang::IllegalArgumentException& aError)
+        {
+            throw css::uno::DeploymentException(
+                "Cannot expand URI" + iterator->second->info->uri + ": " + aError.Message,
+                static_cast< cppu::OWeakObject * >(this));
+        }
+
+        if (iterator->second->info->loader == "com.sun.star.loader.SharedLibrary" &&
+            iterator->second->status != Data::Implementation::STATUS_LOADED)
+        {
+            oslModule aModule = osl_loadModule( aUri.pData, SAL_LOADMODULE_NOW | SAL_LOADMODULE_GLOBAL );
+            SAL_INFO("lok", "loaded component library " << aUri << ( aModule ? " ok" : " no"));
+
+            // leak aModule
+            // osl_unloadModule(aModule);
+            if ( aModule )
+                iterator->second->status = Data::Implementation::STATUS_LOADED;
+        }
+    }
+}
+
 void cppuhelper::ServiceManager::disposing() {
     std::vector< css::uno::Reference<css::lang::XComponent> > sngls;
     std::vector< css::uno::Reference< css::lang::XComponent > > comps;
diff --git a/cppuhelper/source/servicemanager.hxx b/cppuhelper/source/servicemanager.hxx
index c217cbc..7e8f4e6 100644
--- a/cppuhelper/source/servicemanager.hxx
+++ b/cppuhelper/source/servicemanager.hxx
@@ -203,6 +203,8 @@ public:
         css::uno::Reference< css::uno::XComponentContext > const & context,
         std::shared_ptr< Data::Implementation > & implementation);
 
+    void loadAllImplementations();
+
 private:
     virtual ~ServiceManager();
 
diff --git a/desktop/Library_sofficeapp.mk b/desktop/Library_sofficeapp.mk
index 9be7c2d..d7b6dba 100644
--- a/desktop/Library_sofficeapp.mk
+++ b/desktop/Library_sofficeapp.mk
@@ -59,6 +59,7 @@ $(eval $(call gb_Library_use_libraries,sofficeapp,\
     ucbhelper \
     utl \
     vcl \
+    xmlreader \
 	$(gb_UWINAPI) \
 ))
 
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index f73a976..f24ecd2 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -28,6 +28,7 @@
 #include <rtl/strbuf.hxx>
 #include <rtl/uri.hxx>
 #include <cppuhelper/bootstrap.hxx>
+#include <cppuhelper/detail/preinit.hxx>
 #include <comphelper/dispatchcommand.hxx>
 #include <comphelper/lok.hxx>
 #include <comphelper/processfactory.hxx>
@@ -47,6 +48,8 @@
 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
 #include <com/sun/star/ucb/XContentProvider.hpp>
 #include <com/sun/star/ucb/XUniversalContentBroker.hpp>
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
 #include <com/sun/star/util/URLTransformer.hpp>
 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
 #include <com/sun/star/text/TextContentAnchorType.hpp>
@@ -1772,6 +1775,7 @@ static bool initialize_uno(const OUString& aAppProgramURL)
 #endif
 
     xContext = cppu::defaultBootstrap_InitialComponentContext();
+
     if (!xContext.is())
     {
         gImpl->maLastExceptionMsg = "XComponentContext could not be created";
@@ -1804,6 +1808,9 @@ static void lo_startmain(void*)
 {
     osl_setThreadName("lo_startmain");
 
+    if (GetpApp())
+        Application::GetSolarMutex().tryToAcquire();
+
     soffice_main();
 }
 
@@ -1832,19 +1839,38 @@ static void lo_status_indicator_callback(void *data, comphelper::LibreOfficeKit:
 
 static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char* pUserProfilePath)
 {
+    enum {
+        PRE_INIT,     // setup shared data in master process
+        SECOND_INIT,  // complete init. after fork
+        FULL_INIT     // do a standard complete init.
+    } eStage;
+
+    // Did we do a pre-initialize
+    static bool bPreInited = false;
+
+    // What stage are we at ?
+    if (pThis == NULL)
+        eStage = PRE_INIT;
+    else if (bPreInited)
+        eStage = SECOND_INIT;
+    else
+        eStage = FULL_INIT;
+
     LibLibreOffice_Impl* pLib = static_cast<LibLibreOffice_Impl*>(pThis);
 
     if (bInitialized)
         return 1;
 
-    comphelper::LibreOfficeKit::setActive();
+    if (eStage != SECOND_INIT)
+        comphelper::LibreOfficeKit::setActive();
 
     static bool bViewCallback = getenv("LOK_VIEW_CALLBACK");
     comphelper::LibreOfficeKit::setViewCallback(bViewCallback);
 
-    comphelper::LibreOfficeKit::setStatusIndicatorCallback(lo_status_indicator_callback, pLib);
+    if (eStage != PRE_INIT)
+        comphelper::LibreOfficeKit::setStatusIndicatorCallback(lo_status_indicator_callback, pLib);
 
-    if (pUserProfilePath)
+    if (eStage != SECOND_INIT && pUserProfilePath)
         rtl::Bootstrap::set("UserInstallation", OUString(pUserProfilePath, strlen(pUserProfilePath), RTL_TEXTENCODING_UTF8));
 
     OUString aAppPath;
@@ -1867,22 +1893,34 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char
 
     try
     {
-        SAL_INFO("lok", "Attempting to initialize UNO");
-        if (!initialize_uno(aAppURL))
+        if (eStage != SECOND_INIT)
         {
-            return false;
-        }
-        force_c_locale();
+            SAL_INFO("lok", "Attempting to initialize UNO");
+
+            if (!initialize_uno(aAppURL))
+                return false;
 
-        // Force headless -- this is only for bitmap rendering.
-        rtl::Bootstrap::set("SAL_USE_VCLPLUGIN", "svp");
+            // Force headless -- this is only for bitmap rendering.
+            rtl::Bootstrap::set("SAL_USE_VCLPLUGIN", "svp");
 
-        // We specifically need to make sure we have the "headless"
-        // command arg set (various code specifically checks via
-        // CommandLineArgs):
-        desktop::Desktop::GetCommandLineArgs().setHeadless();
+            // We specifically need to make sure we have the "headless"
+            // command arg set (various code specifically checks via
+            // CommandLineArgs):
+            desktop::Desktop::GetCommandLineArgs().setHeadless();
 
-        Application::EnableHeadlessMode(true);
+            Application::EnableHeadlessMode(true);
+
+            if (eStage == PRE_INIT)
+            {
+                InitVCL();
+                // pre-load all component libraries.
+                cppu::preInitBootstrap();
+                // Release Solar Mutex, lo_startmain thread should acquire it.
+                Application::ReleaseSolarMutex();
+            }
+
+            force_c_locale();
+        }
 
         // This is horrible crack. I really would want to go back to simply just call
         // InitVCL() here. The OfficeIPCThread thing is just horrible.
@@ -1903,27 +1941,34 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char
         // the Thread from wherever (it's done again in Desktop::Main), and can
         // then use it to wait until we're definitely ready to continue.
 
-        SAL_INFO("lok", "Enabling OfficeIPCThread");
-        OfficeIPCThread::EnableOfficeIPCThread();
-        SAL_INFO("lok", "Starting soffice_main");
-        pLib->maThread = osl_createThread(lo_startmain, nullptr);
-        SAL_INFO("lok", "Waiting for OfficeIPCThread");
-        OfficeIPCThread::WaitForReady();
-        SAL_INFO("lok", "OfficeIPCThread ready -- continuing");
-
-        // If the Thread has been disabled again that indicates that a
-        // restart is required (or in any case we don't have a useable
-        // process around).
-        if (!OfficeIPCThread::IsEnabled())
+        if (eStage != PRE_INIT)
         {
-            fprintf(stderr, "LOK init failed -- restart required\n");
-            return false;
+            SAL_INFO("lok", "Enabling OfficeIPCThread");
+            OfficeIPCThread::EnableOfficeIPCThread();
+            SAL_INFO("lok", "Starting soffice_main");
+            pLib->maThread = osl_createThread(lo_startmain, nullptr);
+            SAL_INFO("lok", "Waiting for OfficeIPCThread");
+            OfficeIPCThread::WaitForReady();
+            SAL_INFO("lok", "OfficeIPCThread ready -- continuing");
+
+            // If the Thread has been disabled again that indicates that a
+            // restart is required (or in any case we don't have a useable
+            // process around).
+            if (!OfficeIPCThread::IsEnabled())
+            {
+                fprintf(stderr, "LOK init failed -- restart required\n");
+                return false;
+            }
         }
 
-        ErrorHandler::RegisterDisplay(aBasicErrorFunc);
+        if (eStage != SECOND_INIT)
+            ErrorHandler::RegisterDisplay(aBasicErrorFunc);
 
         SAL_INFO("lok", "LOK Initialized");
-        bInitialized = true;
+        if (eStage == PRE_INIT)
+            bPreInited = true;
+        else
+            bInitialized = true;
     }
     catch (css::uno::Exception& exception)
     {
@@ -1971,6 +2016,12 @@ LibreOfficeKit *libreofficekit_hook(const char* install_path)
     return libreofficekit_hook_2(install_path, nullptr);
 }
 
+SAL_JNI_EXPORT
+int lok_preinit(const char* install_path, const char* user_profile_path)
+{
+    return lo_initialize(NULL, install_path, user_profile_path);
+}
+
 static void lo_destroy(LibreOfficeKit* pThis)
 {
     LibLibreOffice_Impl* pLib = static_cast<LibLibreOffice_Impl*>(pThis);
diff --git a/include/cppuhelper/detail/preinit.hxx b/include/cppuhelper/detail/preinit.hxx
new file mode 100644
index 0000000..b21929a
--- /dev/null
+++ b/include/cppuhelper/detail/preinit.hxx
@@ -0,0 +1,29 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_CPPUHELPER_DETAIL_PREINIT_HXX
+#define INCLUDED_CPPUHELPER_DETAIL_PREINIT_HXX
+
+#include <cppuhelper/cppuhelperdllapi.h>
+
+namespace cppu
+{
+
+#if defined LIBO_INTERNAL_ONLY
+
+CPPUHELPER_DLLPUBLIC void SAL_CALL
+preInitBootstrap();
+
+#endif // LIBO_INTERNAL_ONLY
+
+} // namespace cppu
+
+#endif // INCLUDED_CPPUHELPER_DETAIL_PREINIT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/smoketest/libtest.cxx b/smoketest/libtest.cxx
index 29959b0..98607fb 100644
--- a/smoketest/libtest.cxx
+++ b/smoketest/libtest.cxx
@@ -82,7 +82,29 @@ int main (int argc, char **argv)
         return 1;
 
     // coverity[tainted_string] - build time test tool
-    Office *pOffice = lok_cpp_init( argv[1] );
+    char *install_path = argv[1];
+
+    if( argc > 4 )
+    {
+        fprintf( stderr, "testing preinit\n");
+        char *imp_lib;
+        void *dlhandle;
+        dlhandle = lok_dlopen( install_path, &imp_lib );
+        if( !dlhandle )
+        {
+            fprintf( stderr, "Failed to link '%s'\n", lok_dlerror() );
+            return -1;
+        }
+        LokHookPreInit *preinit = (LokHookPreInit *) lok_dlsym( dlhandle, "lok_preinit" );
+        if( !preinit )
+        {
+            fprintf( stderr, "Failed to find pre-init symbol: %s\n", lok_dlerror() );
+            return -1;
+        }
+        preinit( install_path, NULL );
+    }
+
+    Office *pOffice = lok_cpp_init( install_path );
     if( !pOffice )
     {
         fprintf( stderr, "Failed to initialize\n" );


More information about the Libreoffice-commits mailing list