Commit 4afaa793 authored by Guillaume Pasero's avatar Guillaume Pasero

ENH: faster application loading

parent b5e6d7f5
......@@ -17,7 +17,7 @@ if exist %CURRENT_SCRIPT_DIR%otbApplicationLauncherCommandLine.exe (
setlocal
:: works for install tree
if exist %CURRENT_SCRIPT_DIR%../@OTB_INSTALL_APP_DIR@ (
set ITK_AUTOLOAD_PATH=%CURRENT_SCRIPT_DIR%../@OTB_INSTALL_APP_DIR@;%ITK_AUTOLOAD_PATH%
set OTB_APPLICATION_PATH=%CURRENT_SCRIPT_DIR%../@OTB_INSTALL_APP_DIR@;%OTB_APPLICATION_PATH%
)
:: start the application
......
......@@ -19,11 +19,11 @@ fi
# works for install tree
if [ -d $CURRENT_SCRIPT_DIR/../@OTB_INSTALL_APP_DIR@ ]
then
ITK_AUTOLOAD_PATH=$CURRENT_SCRIPT_DIR/../@OTB_INSTALL_APP_DIR@:$ITK_AUTOLOAD_PATH
OTB_APPLICATION_PATH=$CURRENT_SCRIPT_DIR/../@OTB_INSTALL_APP_DIR@:$OTB_APPLICATION_PATH
fi
# export it to make it available to otbApplicationLauncherCommandLine environment
export ITK_AUTOLOAD_PATH
export OTB_APPLICATION_PATH
# start the application
$OTB_CLI_LAUNCHER "$@"
......@@ -17,7 +17,7 @@ if exist %CURRENT_SCRIPT_DIR%otbApplicationLauncherQt.exe (
setlocal
:: works for install tree
if exist %CURRENT_SCRIPT_DIR%../@OTB_INSTALL_APP_DIR@ (
set ITK_AUTOLOAD_PATH=%CURRENT_SCRIPT_DIR%../@OTB_INSTALL_APP_DIR@;%ITK_AUTOLOAD_PATH%
set OTB_APPLICATION_PATH=%CURRENT_SCRIPT_DIR%../@OTB_INSTALL_APP_DIR@;%OTB_APPLICATION_PATH%
)
set LC_NUMERIC=C
......
......@@ -19,11 +19,11 @@ fi
# use the default install tree path for applications
if [ -d $CURRENT_SCRIPT_DIR/../@OTB_INSTALL_APP_DIR@ ]
then
ITK_AUTOLOAD_PATH=$CURRENT_SCRIPT_DIR/../@OTB_INSTALL_APP_DIR@:$ITK_AUTOLOAD_PATH
OTB_APPLICATION_PATH=$CURRENT_SCRIPT_DIR/../@OTB_INSTALL_APP_DIR@:$OTB_APPLICATION_PATH
fi
# export it to make it available to otbApplicationLauncherCommandLine environment
export ITK_AUTOLOAD_PATH
export OTB_APPLICATION_PATH
# avoid numerical issues caused by locale
export LC_NUMERIC=C
......
......@@ -18,6 +18,7 @@
#ifndef __otbWrapperApplicationFactory_h
#define __otbWrapperApplicationFactory_h
#include "otbWrapperApplicationFactoryBase.h"
#include "itkVersion.h"
namespace otb
......@@ -26,12 +27,12 @@ namespace Wrapper
{
template < class TApplication >
class ITK_ABI_EXPORT ApplicationFactory : public itk::ObjectFactoryBase
class ITK_ABI_EXPORT ApplicationFactory : public ApplicationFactoryBase
{
public:
/** Standard class typedefs. */
typedef ApplicationFactory Self;
typedef itk::ObjectFactoryBase Superclass;
typedef ApplicationFactoryBase Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
......@@ -50,7 +51,7 @@ public:
itkFactorylessNewMacro(Self);
/** Run-time type information (and related methods). */
itkTypeMacro(ApplicationFactory, itk::ObjectFactoryBase);
itkTypeMacro(ApplicationFactory, ApplicationFactoryBase);
void SetClassName(const char* name)
{
......
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef __otbWrapperApplicationFactoryBase_h
#define __otbWrapperApplicationFactoryBase_h
#include "itkObjectFactoryBase.h"
#include "otbWrapperApplication.h"
namespace otb
{
namespace Wrapper
{
class ITK_ABI_EXPORT ApplicationFactoryBase : public itk::ObjectFactoryBase
{
public:
/** Standard class typedefs. */
typedef ApplicationFactoryBase Self;
typedef itk::ObjectFactoryBase Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Run-time type information (and related methods). */
itkTypeMacro(ApplicationFactoryBase, itk::ObjectFactoryBase);
/** Create an application using the CreateObject() method of the current factory */
Application::Pointer CreateApplication(const char* name);
protected:
ApplicationFactoryBase(){}
virtual ~ApplicationFactoryBase(){}
private:
ApplicationFactoryBase(const Self &); //purposely not implemented
void operator =(const Self&); //purposely not implemented
};
} // end namespace Wrapper
} //end namespace otb
#endif
......@@ -39,7 +39,7 @@ class ITK_ABI_EXPORT ApplicationRegistry : public itk::Object
{
public:
/** Standard class typedefs. */
typedef ApplicationRegistry Self;
typedef ApplicationRegistry Self;
typedef itk::Object Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
......@@ -64,6 +64,10 @@ public:
/** Create the specified Application */
static Application::Pointer CreateApplication(const std::string& applicationName);
/** Create the specified Application (faster)
* method using dynamic library name to load the right module */
static Application::Pointer CreateApplicationFaster(const std::string& applicationName);
protected:
ApplicationRegistry();
......@@ -72,6 +76,8 @@ protected:
private:
ApplicationRegistry(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
static void RefreshApplicationFactories();
};
......
......@@ -26,6 +26,7 @@ set(OTBApplicationEngine_SRC
otbWrapperApplication.cxx
otbWrapperChoiceParameter.cxx
otbWrapperApplicationRegistry.cxx
otbWrapperApplicationFactoryBase.cxx
)
add_library(OTBApplicationEngine ${OTBApplicationEngine_SRC})
......
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "otbWrapperApplicationFactoryBase.h"
namespace otb
{
namespace Wrapper
{
Application::Pointer
ApplicationFactoryBase::CreateApplication(const char* name)
{
Application::Pointer appli;
LightObject::Pointer obj = this->CreateObject(name);
if (obj.IsNotNull())
{
Application* app = dynamic_cast<Application*> (obj.GetPointer());
if (app)
{
appli = app;
}
}
return appli;
}
}
}
......@@ -16,8 +16,10 @@
=========================================================================*/
#include "otbWrapperApplicationRegistry.h"
#include "otbWrapperApplicationFactoryBase.h"
#include "otbMacro.h"
#include "itksys/SystemTools.hxx"
#include "itkDynamicLoader.h"
#include <iterator>
namespace otb
......@@ -37,23 +39,20 @@ void
ApplicationRegistry::SetApplicationPath(std::string newpath)
{
std::ostringstream putEnvPath;
putEnvPath << "ITK_AUTOLOAD_PATH=" << newpath;
putEnvPath << "OTB_APPLICATION_PATH=" << newpath;
// do NOT use putenv() directly, since the string memory must be managed carefully
itksys::SystemTools::PutEnv(putEnvPath.str().c_str());
// Reload factories to take into account new path
itk::ObjectFactoryBase::ReHash();
}
void
ApplicationRegistry::AddApplicationPath(std::string newpath)
{
std::ostringstream putEnvPath;
putEnvPath << "ITK_AUTOLOAD_PATH=";
putEnvPath << "OTB_APPLICATION_PATH=";
// Can be NULL if the env var is not set
const char* currentEnv = itksys::SystemTools::GetEnv("ITK_AUTOLOAD_PATH");
const char* currentEnv = itksys::SystemTools::GetEnv("OTB_APPLICATION_PATH");
#if defined(WIN32)
const char pathSeparator = ';';
......@@ -70,18 +69,6 @@ ApplicationRegistry::AddApplicationPath(std::string newpath)
// do NOT use putenv() directly, since the string memory must be managed carefully
itksys::SystemTools::PutEnv(putEnvPath.str().c_str());
// Reload factories to take into account new path
itk::ObjectFactoryBase::ReHash();
std::ostringstream resetEnvPath;
resetEnvPath << "ITK_AUTOLOAD_PATH=";
if (currentEnv)
{
resetEnvPath << currentEnv;
}
itksys::SystemTools::PutEnv(resetEnvPath.str().c_str());
}
Application::Pointer
......@@ -89,6 +76,16 @@ ApplicationRegistry::CreateApplication(const std::string& name)
{
ApplicationPointer appli;
// Fast search
appli = ApplicationRegistry::CreateApplicationFaster(name);
if (appli.IsNotNull())
{
return appli;
}
// Classic search
ApplicationRegistry::RefreshApplicationFactories();
LightObject::Pointer possibleApp = itk::ObjectFactoryBase::CreateInstance(name.c_str());
if (possibleApp.IsNotNull())
......@@ -109,11 +106,102 @@ ApplicationRegistry::CreateApplication(const std::string& name)
return appli;
}
typedef itk::ObjectFactoryBase * ( *ITK_LOAD_FUNCTION )();
Application::Pointer
ApplicationRegistry::CreateApplicationFaster(const std::string& name)
{
ApplicationPointer appli;
std::string appExtension = itksys::DynamicLoader::LibExtension();
#ifdef __APPLE__
appExtension = ".dylib";
#endif
std::ostringstream appLibName;
appLibName << "otbapp_" << name << appExtension;
#if defined(WIN32)
const char pathSeparator = ';';
#else
const char pathSeparator = ':';
#endif
#ifdef _WIN32
const char sep = '\\';
#else
const char sep = '/';
#endif
const char* otbAppPath = itksys::SystemTools::GetEnv("OTB_APPLICATION_PATH");
const char* itkLoadPath = itksys::SystemTools::GetEnv("ITK_AUTOLOAD_PATH");
std::ostringstream currentPath;
if (otbAppPath)
{
currentPath << otbAppPath << pathSeparator;
}
if (itkLoadPath)
{
currentPath << itkLoadPath;
}
std::vector<itksys::String> pathList = itksys::SystemTools::SplitString(currentPath.str().c_str(),pathSeparator,false);
for (unsigned int i=0 ; i<pathList.size() ; ++i)
{
std::string possiblePath = pathList[i];
if ( !possiblePath.empty() && possiblePath[possiblePath.size() - 1] != sep )
{
possiblePath += sep;
}
possiblePath += appLibName.str();
if (itksys::SystemTools::FileExists(possiblePath.c_str(),true))
{
itk::LibHandle lib = itk::DynamicLoader::OpenLibrary( possiblePath.c_str() );
if ( lib )
{
/**
* Look for the symbol itkLoad in the library
*/
ITK_LOAD_FUNCTION loadfunction =
( ITK_LOAD_FUNCTION ) itk::DynamicLoader::GetSymbolAddress(lib, "itkLoad");
/**
* if the symbol is found call it to create the factory
* from the library
*/
if ( loadfunction )
{
itk::ObjectFactoryBase *newfactory = ( *loadfunction )( );
if (dynamic_cast<ApplicationFactoryBase*>(newfactory))
{
ApplicationFactoryBase* appFactory = dynamic_cast<ApplicationFactoryBase*>(newfactory);
appli = appFactory->CreateApplication(name.c_str());
appli->Init();
break;
}
}
else
{
// In the past, some platforms crashed on the call
// DynamicLoader::CloseLibrary(lib) if the lib has symbols
// that the current executable is using.
itk::DynamicLoader::CloseLibrary(lib);
}
}
}
}
return appli;
}
std::vector<std::string>
ApplicationRegistry::GetAvailableApplications()
{
ApplicationPointer appli;
ApplicationRegistry::RefreshApplicationFactories();
std::list<ApplicationPointer> possibleApp;
std::list<LightObject::Pointer> allobjects = itk::ObjectFactoryBase::CreateAllInstance("otbWrapperApplication");
......@@ -147,6 +235,49 @@ ApplicationRegistry::GetAvailableApplications()
return appVec;
}
void
ApplicationRegistry::RefreshApplicationFactories()
{
std::ostringstream putEnvPath;
putEnvPath << "ITK_AUTOLOAD_PATH=";
// Can be NULL if the env var is not set
const char* currentEnv = itksys::SystemTools::GetEnv("ITK_AUTOLOAD_PATH");
// OTB specific application path
const char* otbApplicationPath = itksys::SystemTools::GetEnv("OTB_APPLICATION_PATH");
#if defined(WIN32)
const char pathSeparator = ';';
#else
const char pathSeparator = ':';
#endif
if (otbApplicationPath)
{
putEnvPath << otbApplicationPath << pathSeparator;
}
if (currentEnv)
{
putEnvPath << currentEnv;
}
// do NOT use putenv() directly, since the string memory must be managed carefully
itksys::SystemTools::PutEnv(putEnvPath.str().c_str());
// Reload factories to take into account new path
itk::ObjectFactoryBase::ReHash();
std::ostringstream resetEnvPath;
resetEnvPath << "ITK_AUTOLOAD_PATH=";
if (currentEnv)
{
resetEnvPath << currentEnv;
}
itksys::SystemTools::PutEnv(resetEnvPath.str().c_str());
}
} // end namespace Wrapper
} //end namespace otb
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