summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenry Castro <hcastro@collabora.com>2016-02-12 11:46:37 -0500
committerTor Lillqvist <tml@collabora.com>2016-02-15 16:17:53 +0200
commitdf5f7c6abab820070771c5304514faf2a07bc588 (patch)
tree274fd4813096c4db8911eaf84d0124ad08208be8
parent5b0c551b9b35f7075d210c9a23e7721e46a66bf9 (diff)
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
-rw-r--r--cppuhelper/source/defaultbootstrap.cxx16
-rw-r--r--cppuhelper/source/gcc3.map5
-rw-r--r--cppuhelper/source/servicemanager.cxx35
-rw-r--r--cppuhelper/source/servicemanager.hxx2
-rw-r--r--desktop/Library_sofficeapp.mk1
-rw-r--r--desktop/source/lib/init.cxx113
-rw-r--r--include/cppuhelper/detail/preinit.hxx29
-rw-r--r--smoketest/libtest.cxx24
8 files changed, 193 insertions, 32 deletions
diff --git a/cppuhelper/source/defaultbootstrap.cxx b/cppuhelper/source/defaultbootstrap.cxx
index bede6b518af0..c0a2c2edc6f7 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 12c29834ab16..20d0e137eef6 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 2d824d4aaa3f..d89289a165a4 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 c217cbce39f5..7e8f4e66e7e6 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 9be7c2dcb3bb..d7b6dbac4b2f 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 f73a97658bfc..f24ecd2553ad 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 000000000000..b21929aa58d8
--- /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 29959b07654d..98607fbd9609 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" );