Kaydet (Commit) df5f7c6a authored tarafından Henry Castro's avatar Henry Castro Kaydeden (comit) Tor Lillqvist

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
üst 5b0c551b
......@@ -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: */
......@@ -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;
};
......@@ -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;
......
......@@ -203,6 +203,8 @@ public:
css::uno::Reference< css::uno::XComponentContext > const & context,
std::shared_ptr< Data::Implementation > & implementation);
void loadAllImplementations();
private:
virtual ~ServiceManager();
......
......@@ -59,6 +59,7 @@ $(eval $(call gb_Library_use_libraries,sofficeapp,\
ucbhelper \
utl \
vcl \
xmlreader \
$(gb_UWINAPI) \
))
......
......@@ -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);
......
/* -*- 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: */
......@@ -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" );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment