Merge pull request #2829 from elpaso/server-static-initializers-construct-on-firts-use

Moved static vars to functions
This commit is contained in:
Alessandro Pasotti 2016-02-24 16:37:04 +01:00
commit 1af724f78a
5 changed files with 108 additions and 79 deletions

View File

@ -36,8 +36,7 @@ int fcgi_accept()
int main( int argc, char * argv[] ) int main( int argc, char * argv[] )
{ {
QgsServer server; QgsServer server( argc, argv );
server.init( argc, argv );
// Starts FCGI loop // Starts FCGI loop
while ( fcgi_accept() >= 0 ) while ( fcgi_accept() >= 0 )
{ {

View File

@ -54,25 +54,36 @@
#include <stdlib.h> #include <stdlib.h>
// Static initialisers, default values for fcgi server
QgsApplication* QgsServer::mQgsApplication = nullptr;
bool QgsServer::mInitialised = false;
QString QgsServer::mServerName( "qgis_server" );
bool QgsServer::mCaptureOutput = false;
char* QgsServer::mArgv[1];
int QgsServer::mArgc = 1;
QString QgsServer::mConfigFilePath;
QgsMapRenderer* QgsServer::mMapRenderer = nullptr;
QgsCapabilitiesCache* QgsServer::mCapabilitiesCache;
// Server status static initialisers.
// Default values are for C++, SIP bindings will override their
// options in in init()
QString QgsServer::sConfigFilePath = QString();
QgsCapabilitiesCache* QgsServer::sCapabilitiesCache = nullptr;
QgsMapRenderer* QgsServer::sMapRenderer = nullptr;
#ifdef HAVE_SERVER_PYTHON_PLUGINS #ifdef HAVE_SERVER_PYTHON_PLUGINS
bool QgsServer::mInitPython = true; QgsServerInterfaceImpl*QgsServer::sServerInterface = nullptr;
QgsServerInterfaceImpl* QgsServer::mServerInterface = nullptr; bool QgsServer::sInitPython = true;
#endif #endif
// Initialization must run once for all servers
bool QgsServer::sInitialised = false;
char* QgsServer::sArgv[1];
int QgsServer::sArgc;
QgsApplication* QgsServer::sQgsApplication = nullptr;
bool QgsServer::sCaptureOutput = false;
QgsServer::QgsServer( int &argc, char **argv )
{
init( argc, argv );
}
QgsServer::QgsServer() QgsServer::QgsServer()
{ {
init();
} }
@ -81,6 +92,13 @@ QgsServer::~QgsServer()
} }
QString& QgsServer::serverName()
{
static QString* name = new QString( "qgis_server" );
return *name;
}
QFileInfo QgsServer::defaultAdminSLD() QFileInfo QgsServer::defaultAdminSLD()
{ {
return QFileInfo( "admin.sld" ); return QFileInfo( "admin.sld" );
@ -292,17 +310,18 @@ QString QgsServer::configPath( const QString& defaultConfigPath, const QMap<QStr
*/ */
bool QgsServer::init() bool QgsServer::init()
{ {
if ( mInitialised ) if ( sInitialised )
{ {
return false; return false;
} }
mArgv[0] = mServerName.toUtf8().data();
mArgc = 1; sArgv[0] = serverName().toUtf8().data();
mCaptureOutput = true; sArgc = 1;
sCaptureOutput = true;
#ifdef HAVE_SERVER_PYTHON_PLUGINS #ifdef HAVE_SERVER_PYTHON_PLUGINS
mInitPython = false; sInitPython = false;
#endif #endif
return init( mArgc , mArgv ); return init( sArgc , sArgv );
} }
@ -311,7 +330,7 @@ bool QgsServer::init()
*/ */
bool QgsServer::init( int & argc, char ** argv ) bool QgsServer::init( int & argc, char ** argv )
{ {
if ( mInitialised ) if ( sInitialised )
{ {
return false; return false;
} }
@ -330,7 +349,7 @@ bool QgsServer::init( int & argc, char ** argv )
QSettings::setPath( QSettings::IniFormat, QSettings::UserScope, optionsPath ); QSettings::setPath( QSettings::IniFormat, QSettings::UserScope, optionsPath );
} }
mQgsApplication = new QgsApplication( argc, argv, getenv( "DISPLAY" ), QString(), "server" ); sQgsApplication = new QgsApplication( argc, argv, getenv( "DISPLAY" ), QString(), "server" );
QCoreApplication::setOrganizationName( QgsApplication::QGIS_ORGANIZATION_NAME ); QCoreApplication::setOrganizationName( QgsApplication::QGIS_ORGANIZATION_NAME );
QCoreApplication::setOrganizationDomain( QgsApplication::QGIS_ORGANIZATION_DOMAIN ); QCoreApplication::setOrganizationDomain( QgsApplication::QGIS_ORGANIZATION_DOMAIN );
@ -386,24 +405,24 @@ bool QgsServer::init( int & argc, char ** argv )
} }
if ( !defaultConfigFilePath.isEmpty() ) if ( !defaultConfigFilePath.isEmpty() )
{ {
mConfigFilePath = defaultConfigFilePath; sConfigFilePath = defaultConfigFilePath;
} }
//create cache for capabilities XML //create cache for capabilities XML
mCapabilitiesCache = new QgsCapabilitiesCache(); sCapabilitiesCache = new QgsCapabilitiesCache();
mMapRenderer = new QgsMapRenderer; sMapRenderer = new QgsMapRenderer;
mMapRenderer->setLabelingEngine( new QgsPalLabeling() ); sMapRenderer->setLabelingEngine( new QgsPalLabeling() );
#ifdef ENABLE_MS_TESTS #ifdef ENABLE_MS_TESTS
QgsFontUtils::loadStandardTestFonts( QStringList() << "Roman" << "Bold" ); QgsFontUtils::loadStandardTestFonts( QStringList() << "Roman" << "Bold" );
#endif #endif
#ifdef HAVE_SERVER_PYTHON_PLUGINS #ifdef HAVE_SERVER_PYTHON_PLUGINS
mServerInterface = new QgsServerInterfaceImpl( mCapabilitiesCache ); sServerInterface = new QgsServerInterfaceImpl( sCapabilitiesCache );
if ( mInitPython ) if ( sInitPython )
{ {
// Init plugins // Init plugins
if ( ! QgsServerPlugins::initPlugins( mServerInterface ) ) if ( ! QgsServerPlugins::initPlugins( sServerInterface ) )
{ {
QgsMessageLog::logMessage( "No server python plugins are available", "Server", QgsMessageLog::INFO ); QgsMessageLog::logMessage( "No server python plugins are available", "Server", QgsMessageLog::INFO );
} }
@ -415,7 +434,7 @@ bool QgsServer::init( int & argc, char ** argv )
#endif #endif
QgsEditorWidgetRegistry::initEditors(); QgsEditorWidgetRegistry::initEditors();
mInitialised = true; sInitialised = true;
QgsMessageLog::logMessage( "Server initialized", "Server", QgsMessageLog::INFO ); QgsMessageLog::logMessage( "Server initialized", "Server", QgsMessageLog::INFO );
return true; return true;
} }
@ -436,12 +455,6 @@ void QgsServer::putenv( const QString &var, const QString &val )
*/ */
QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryString ) QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryString )
{ {
// Run init if handleRequest was called without previously initialising
// the server
if ( ! mInitialised )
{
init();
}
/* /*
* This is mainly for python bindings, passing QUERY_STRING * This is mainly for python bindings, passing QUERY_STRING
@ -453,7 +466,7 @@ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryStri
int logLevel = QgsServerLogger::instance()->logLevel(); int logLevel = QgsServerLogger::instance()->logLevel();
QTime time; //used for measuring request time if loglevel < 1 QTime time; //used for measuring request time if loglevel < 1
QgsMapLayerRegistry::instance()->removeAllMapLayers(); QgsMapLayerRegistry::instance()->removeAllMapLayers();
mQgsApplication->processEvents(); sQgsApplication->processEvents();
if ( logLevel < 1 ) if ( logLevel < 1 )
{ {
time.start(); time.start();
@ -461,7 +474,7 @@ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryStri
} }
//Request handler //Request handler
QScopedPointer<QgsRequestHandler> theRequestHandler( createRequestHandler( mCaptureOutput ) ); QScopedPointer<QgsRequestHandler> theRequestHandler( createRequestHandler( sCaptureOutput ) );
try try
{ {
@ -476,10 +489,10 @@ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryStri
#ifdef HAVE_SERVER_PYTHON_PLUGINS #ifdef HAVE_SERVER_PYTHON_PLUGINS
// Set the request handler into the interface for plugins to manipulate it // Set the request handler into the interface for plugins to manipulate it
mServerInterface->setRequestHandler( theRequestHandler.data() ); sServerInterface->setRequestHandler( theRequestHandler.data() );
// Iterate filters and call their requestReady() method // Iterate filters and call their requestReady() method
QgsServerFiltersMap::const_iterator filtersIterator; QgsServerFiltersMap::const_iterator filtersIterator;
QgsServerFiltersMap filters = mServerInterface->filters(); QgsServerFiltersMap filters = sServerInterface->filters();
for ( filtersIterator = filters.constBegin(); filtersIterator != filters.constEnd(); ++filtersIterator ) for ( filtersIterator = filters.constBegin(); filtersIterator != filters.constEnd(); ++filtersIterator )
{ {
filtersIterator.value()->requestReady(); filtersIterator.value()->requestReady();
@ -488,22 +501,22 @@ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryStri
//Pass the filters to the requestHandler, this is needed for the following reasons: //Pass the filters to the requestHandler, this is needed for the following reasons:
// 1. allow core services to access plugin filters and implement thir own plugin hooks // 1. allow core services to access plugin filters and implement thir own plugin hooks
// 2. allow requestHandler to call sendResponse plugin hook // 2. allow requestHandler to call sendResponse plugin hook
theRequestHandler->setPluginFilters( mServerInterface->filters() ); theRequestHandler->setPluginFilters( sServerInterface->filters() );
#endif #endif
// Copy the parameters map // Copy the parameters map
QMap<QString, QString> parameterMap( theRequestHandler->parameterMap() ); QMap<QString, QString> parameterMap( theRequestHandler->parameterMap() );
#ifdef HAVE_SERVER_PYTHON_PLUGINS #ifdef HAVE_SERVER_PYTHON_PLUGINS
const QgsAccessControl* accessControl = nullptr; const QgsAccessControl* accessControl = nullptr;
accessControl = mServerInterface->accessControls(); accessControl = sServerInterface->accessControls();
#endif #endif
printRequestParameters( parameterMap, logLevel ); printRequestParameters( parameterMap, logLevel );
QMap<QString, QString>::const_iterator paramIt; QMap<QString, QString>::const_iterator paramIt;
//Config file path //Config file path
QString configFilePath = configPath( mConfigFilePath, parameterMap ); QString configFilePath = configPath( sConfigFilePath, parameterMap );
#ifdef HAVE_SERVER_PYTHON_PLUGINS #ifdef HAVE_SERVER_PYTHON_PLUGINS
mServerInterface->setConfigFilePath( configFilePath ); sServerInterface->setConfigFilePath( configFilePath );
#endif #endif
//Service parameter //Service parameter
QString serviceString = theRequestHandler->parameter( "SERVICE" ); QString serviceString = theRequestHandler->parameter( "SERVICE" );
@ -600,8 +613,8 @@ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryStri
, parameterMap , parameterMap
, p , p
, theRequestHandler.data() , theRequestHandler.data()
, mMapRenderer , sMapRenderer
, mCapabilitiesCache , sCapabilitiesCache
#ifdef HAVE_SERVER_PYTHON_PLUGINS #ifdef HAVE_SERVER_PYTHON_PLUGINS
, accessControl , accessControl
#endif #endif
@ -617,14 +630,14 @@ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryStri
#ifdef HAVE_SERVER_PYTHON_PLUGINS #ifdef HAVE_SERVER_PYTHON_PLUGINS
// Iterate filters and call their responseComplete() method // Iterate filters and call their responseComplete() method
filters = mServerInterface->filters(); filters = sServerInterface->filters();
for ( filtersIterator = filters.constBegin(); filtersIterator != filters.constEnd(); ++filtersIterator ) for ( filtersIterator = filters.constBegin(); filtersIterator != filters.constEnd(); ++filtersIterator )
{ {
filtersIterator.value()->responseComplete(); filtersIterator.value()->responseComplete();
} }
// We are done using theRequestHandler in plugins, make sure we don't access // We are done using theRequestHandler in plugins, make sure we don't access
// to a deleted request handler from Python bindings // to a deleted request handler from Python bindings
mServerInterface->clearRequestHandler(); sServerInterface->clearRequestHandler();
#endif #endif
theRequestHandler->sendResponse(); theRequestHandler->sendResponse();

View File

@ -47,11 +47,16 @@
class SERVER_EXPORT QgsServer class SERVER_EXPORT QgsServer
{ {
public: public:
/**
* Standard ctor for CGI/FCGI
* @note Not available in Python bindings
*/
QgsServer( int & argc, char ** argv );
//! The following is mainly for python bindings, that do not pass argc/argv
QgsServer(); QgsServer();
~QgsServer(); ~QgsServer();
/** Server initialization: intialise QGIS ang QT core application. /** Server initialization: intialise QGIS ang QT core application.
* This method is automatically called by handleRequest if it wasn't
* explicitly called before
* @note Not available in Python bindings * @note Not available in Python bindings
*/ */
static bool init( int & argc, char ** argv ); static bool init( int & argc, char ** argv );
@ -84,7 +89,7 @@ class SERVER_EXPORT QgsServer
/** Returns a pointer to the server interface */ /** Returns a pointer to the server interface */
#ifdef HAVE_SERVER_PYTHON_PLUGINS #ifdef HAVE_SERVER_PYTHON_PLUGINS
QgsServerInterfaceImpl* serverInterface() { return mServerInterface; } QgsServerInterfaceImpl* serverInterface() { return sServerInterface; }
#endif #endif
private: private:
@ -106,20 +111,23 @@ class SERVER_EXPORT QgsServer
//! Create and return a request handler instance //! Create and return a request handler instance
static QgsRequestHandler* createRequestHandler( const bool captureOutput = false ); static QgsRequestHandler* createRequestHandler( const bool captureOutput = false );
// Server status // Return the server name
static QString mConfigFilePath; static QString &serverName();
static QgsCapabilitiesCache* mCapabilitiesCache;
static QgsMapRenderer* mMapRenderer; // Status
static QString sConfigFilePath;
static QgsCapabilitiesCache* sCapabilitiesCache;
static QgsMapRenderer* sMapRenderer;
#ifdef HAVE_SERVER_PYTHON_PLUGINS #ifdef HAVE_SERVER_PYTHON_PLUGINS
static QgsServerInterfaceImpl* mServerInterface; static QgsServerInterfaceImpl* sServerInterface;
static bool mInitPython; static bool sInitPython;
#endif #endif
static bool mInitialised; //! Initialization must run once for all servers
static QString mServerName; static bool sInitialised;
static char* mArgv[1]; static char* sArgv[1];
static int mArgc; static int sArgc;
static QgsApplication* mQgsApplication; static QgsApplication* sQgsApplication;
static bool mCaptureOutput; static bool sCaptureOutput;
}; };
#endif // QGSSERVER_H #endif // QGSSERVER_H

View File

@ -26,14 +26,22 @@
#include <QLibrary> #include <QLibrary>
// Initialize static members
QgsPythonUtils* QgsServerPlugins::sPythonUtils;
QgsServerPlugins::QgsServerPlugins() QgsServerPlugins::QgsServerPlugins()
{ {
} }
// Initialize static members // Construct on first use
QgsPythonUtils* QgsServerPlugins::mPythonUtils; QStringList &QgsServerPlugins::serverPlugins()
// Initialize static members {
QStringList QgsServerPlugins::mServerPlugins; static QStringList* pluginList = new QStringList();
return *pluginList;
}
// This code is mainly borrowed from QGIS desktop Python plugin initialization // This code is mainly borrowed from QGIS desktop Python plugin initialization
bool QgsServerPlugins::initPlugins( QgsServerInterface *interface ) bool QgsServerPlugins::initPlugins( QgsServerInterface *interface )
@ -73,10 +81,10 @@ bool QgsServerPlugins::initPlugins( QgsServerInterface *interface )
} }
QgsDebugMsg( "Python support library's instance() symbol resolved." ); QgsDebugMsg( "Python support library's instance() symbol resolved." );
mPythonUtils = pythonlib_inst(); sPythonUtils = pythonlib_inst();
mPythonUtils->initServerPython( interface ); sPythonUtils->initServerPython( interface );
if ( mPythonUtils && mPythonUtils->isEnabled() ) if ( sPythonUtils && sPythonUtils->isEnabled() )
{ {
QgsDebugMsg( "Python support ENABLED :-)" ); QgsDebugMsg( "Python support ENABLED :-)" );
} }
@ -88,20 +96,20 @@ bool QgsServerPlugins::initPlugins( QgsServerInterface *interface )
//Init plugins: loads a list of installed plugins and filter them //Init plugins: loads a list of installed plugins and filter them
//for "server" metadata //for "server" metadata
QListIterator<QString> plugins( mPythonUtils->pluginList() ); QListIterator<QString> plugins( sPythonUtils->pluginList() );
bool atLeastOneEnabled = false; bool atLeastOneEnabled = false;
while ( plugins.hasNext() ) while ( plugins.hasNext() )
{ {
QString pluginName = plugins.next(); QString pluginName = plugins.next();
QString pluginService = mPythonUtils->getPluginMetadata( pluginName, "server" ); QString pluginService = sPythonUtils->getPluginMetadata( pluginName, "server" );
if ( pluginService == "True" ) if ( pluginService == "True" )
{ {
if ( mPythonUtils->loadPlugin( pluginName ) ) if ( sPythonUtils->loadPlugin( pluginName ) )
{ {
if ( mPythonUtils->startServerPlugin( pluginName ) ) if ( sPythonUtils->startServerPlugin( pluginName ) )
{ {
atLeastOneEnabled = true; atLeastOneEnabled = true;
mServerPlugins.append( pluginName ); serverPlugins().append( pluginName );
QgsMessageLog::logMessage( QString( "Server plugin %1 loaded!" ).arg( pluginName ), "Server", QgsMessageLog::INFO ); QgsMessageLog::logMessage( QString( "Server plugin %1 loaded!" ).arg( pluginName ), "Server", QgsMessageLog::INFO );
} }
else else
@ -115,6 +123,7 @@ bool QgsServerPlugins::initPlugins( QgsServerInterface *interface )
} }
} }
} }
return mPythonUtils && mPythonUtils->isEnabled() && atLeastOneEnabled; return sPythonUtils && sPythonUtils->isEnabled() && atLeastOneEnabled;
} }

View File

@ -37,10 +37,10 @@ class SERVER_EXPORT QgsServerPlugins
* @return bool true on success * @return bool true on success
*/ */
static bool initPlugins( QgsServerInterface* interface ); static bool initPlugins( QgsServerInterface* interface );
//! Pointer to QgsPythonUtils
static QgsPythonUtils* mPythonUtils;
//! List of available server plugin names //! List of available server plugin names
static QStringList mServerPlugins; static QStringList& serverPlugins();
//! Pointer to QgsPythonUtils
static QgsPythonUtils* sPythonUtils;
}; };
#endif // QGSSERVERPLUGINS_H #endif // QGSSERVERPLUGINS_H