LCOV - code coverage report
Current view: top level - eq - init.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 102 191 53.4 %
Date: 2016-07-30 05:04:55 Functions: 7 9 77.8 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2005-2015, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                    2010, Cedric Stalder <cedric.stalder@gmail.com>
       4             :  *                    2012, Daniel Nachbaur <danielnachbaur@gmail.com>
       5             :  *
       6             :  * This library is free software; you can redistribute it and/or modify it under
       7             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       8             :  * by the Free Software Foundation.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      11             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      12             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      13             :  * details.
      14             :  *
      15             :  * You should have received a copy of the GNU Lesser General Public License
      16             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      17             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             :  */
      19             : 
      20             : #include "init.h"
      21             : 
      22             : #ifdef EQUALIZER_USE_QT5WIDGETS
      23             : #  include <QApplication>
      24             : #  include "qt/windowSystem.h"
      25             : #endif
      26             : 
      27             : #include "client.h"
      28             : #include "config.h"
      29             : #include "global.h"
      30             : #include "nodeFactory.h"
      31             : #include "os.h"
      32             : #include "server.h"
      33             : 
      34             : #include <eq/version.h>
      35             : #include <eq/fabric/configParams.h>
      36             : #include <eq/fabric/init.h>
      37             : #include <co/global.h>
      38             : #include <lunchbox/file.h>
      39             : #include <pression/pluginRegistry.h>
      40             : 
      41             : #ifdef _WIN32
      42             : #  pragma warning( push )
      43             : #  pragma warning( disable : 4275 4251 )
      44             : #endif
      45             : #include <boost/filesystem.hpp>
      46             : #include <boost/foreach.hpp>
      47             : #include <boost/program_options/options_description.hpp>
      48             : #include <boost/program_options/parsers.hpp>
      49             : #include <boost/program_options/variables_map.hpp>
      50             : #ifdef _WIN32
      51             : #  pragma warning( pop )
      52             : #endif
      53             : 
      54             : #include <fstream>
      55             : 
      56             : #ifdef _MSC_VER
      57             : #  include <direct.h>
      58             : #  define getcwd _getcwd
      59             : #  define atoll _atoi64
      60             : #endif
      61             : #ifndef MAXPATHLEN
      62             : #  define MAXPATHLEN 1024
      63             : #endif
      64             : 
      65             : namespace arg = boost::program_options;
      66             : 
      67             : namespace eq
      68             : {
      69             : namespace
      70             : {
      71             : static std::ofstream* _logFile = 0;
      72          14 : static lunchbox::a_int32_t _initialized;
      73          14 : static std::vector< WindowSystemIF* > _windowSystems;
      74             : }
      75             : 
      76             : const char EQ_HELP[] = "eq-help";
      77             : const char EQ_LOGFILE[] = "eq-logfile";
      78             : const char EQ_SERVER[] = "eq-server";
      79             : const char EQ_CLIENT[] = "eq-client";
      80             : const char EQ_CONFIG[] = "eq-config";
      81             : const char EQ_CONFIG_FLAGS[] = "eq-config-flags";
      82             : const char EQ_CONFIG_PREFIXES[] = "eq-config-prefixes";
      83             : const char EQ_RENDER_CLIENT[] = "eq-render-client";
      84             : 
      85             : static bool _parseArguments( const int argc, char** argv );
      86             : static void _initPlugins();
      87             : static void _exitPlugins();
      88             : 
      89           5 : bool _init( const int argc, char** argv, NodeFactory* nodeFactory )
      90             : {
      91           5 :     const char *env = getenv( "EQ_LOG_LEVEL" );
      92           5 :     if( env )
      93           0 :         lunchbox::Log::level = lunchbox::Log::getLogLevel( env );
      94             : 
      95           5 :     env = getenv( "EQ_LOG_TOPICS" );
      96           5 :     if( env )
      97           0 :         lunchbox::Log::topics |= atoll( env );
      98             : 
      99           5 :     lunchbox::Log::instance().setThreadName( "Main" );
     100             : 
     101           5 :     if( ++_initialized > 1 ) // not first
     102             :     {
     103           0 :         LBERROR << "Equalizer client library initialized more than once"
     104           0 :                 << std::endl;
     105           0 :         return true;
     106             :     }
     107             : 
     108           5 :     if( !_parseArguments( argc, argv ))
     109           0 :         return false;
     110          25 :     LBDEBUG << "Equalizer v" << Version::getString() << " initializing"
     111          20 :             << std::endl;
     112             : 
     113             : #ifdef AGL
     114             :     GetCurrentEventQueue();
     115             : #endif
     116             : #ifdef GLX
     117           5 :     ::XInitThreads();
     118             : #endif
     119             : 
     120             : #ifdef EQUALIZER_USE_QT5WIDGETS
     121           5 :     if( QApplication::instance( ))
     122           0 :         _windowSystems.push_back( new qt::WindowSystem );
     123             : #endif
     124             : 
     125           5 :     LBASSERT( nodeFactory );
     126           5 :     Global::_nodeFactory = nodeFactory;
     127             : 
     128           5 :     const std::string& programName = Global::getProgramName();
     129           5 :     if( programName.empty() && argc > 0 )
     130           3 :         Global::setProgramName( argv[0] );
     131             : 
     132           5 :     const std::string& workDir = Global::getWorkDir();
     133           5 :     if( workDir.empty( ))
     134             :     {
     135             :         char cwd[MAXPATHLEN];
     136           5 :         Global::setWorkDir( getcwd( cwd, MAXPATHLEN ));
     137             :     }
     138             : 
     139           5 :     _initPlugins();
     140           5 :     return fabric::init( argc, argv );
     141             : }
     142             : 
     143           5 : bool exit()
     144             : {
     145           5 :     if( _initialized <= 0 )
     146             :     {
     147           0 :         LBERROR << "Equalizer client library not initialized" << std::endl;
     148           0 :         return false;
     149             :     }
     150           5 :     if( --_initialized > 0 ) // not last
     151           0 :         return true;
     152             : 
     153           5 :     BOOST_FOREACH( WindowSystemIF* windowSystem, _windowSystems )
     154           0 :         delete windowSystem;
     155           5 :     _windowSystems.clear();
     156             : 
     157           5 :     Global::_nodeFactory = 0;
     158           5 :     _exitPlugins();
     159           5 :     const bool ret = fabric::exit();
     160             : 
     161           5 :     if( _logFile )
     162             :     {
     163             : #ifdef NDEBUG
     164             :         lunchbox::Log::setOutput( std::cout );
     165             : #else
     166           0 :         lunchbox::Log::setOutput( std::cerr );
     167             : #endif
     168           0 :         _logFile->close();
     169           0 :         delete _logFile;
     170           0 :         _logFile = 0;
     171             :     }
     172           5 :     return ret;
     173             : }
     174             : 
     175           5 : bool _parseArguments( const int argc, char** argv )
     176             : {
     177             :     typedef stde::hash_map< std::string, uint32_t > Flags;
     178           5 :     Flags configFlags;
     179           5 :     configFlags["multiprocess"] = fabric::ConfigParams::FLAG_MULTIPROCESS;
     180           5 :     configFlags["multiprocess_db"] = fabric::ConfigParams::FLAG_MULTIPROCESS_DB;
     181           5 :     configFlags["ethernet"] = fabric::ConfigParams::FLAG_NETWORK_ETHERNET;
     182           5 :     configFlags["infiniband"] = fabric::ConfigParams::FLAG_NETWORK_INFINIBAND;
     183          10 :     configFlags["2D_horizontal"] =
     184           5 :         fabric::ConfigParams::FLAG_LOAD_EQ_HORIZONTAL;
     185          10 :     configFlags["2D_vertical"] =
     186           5 :         fabric::ConfigParams::FLAG_LOAD_EQ_VERTICAL;
     187          10 :     configFlags["2D_tiles"] =
     188           5 :         fabric::ConfigParams::FLAG_LOAD_EQ_2D;
     189             : 
     190          10 :     arg::options_description options( "Equalizer library options" );
     191             :     options.add_options()
     192          10 :         ( EQ_HELP, "Display usage information and exit" )
     193           5 :         ( EQ_LOGFILE, arg::value< std::string >(),
     194           5 :           "Redirect log output to given file" )
     195          10 :         ( EQ_SERVER, arg::value< std::string >(), "The server address" )
     196           5 :         ( EQ_CONFIG, arg::value< std::string >(),
     197           5 :           "The config filename or autoconfig session name" )
     198           5 :         ( EQ_CONFIG_FLAGS, arg::value< Strings >()->multitoken(),
     199           5 :           "The autoconfig flags" )
     200           5 :         ( EQ_CONFIG_PREFIXES, arg::value< Strings >()->multitoken(),
     201             :           "The network prefix filter(s) in CIDR notation for autoconfig "
     202           5 :           "(white-space separated)" )
     203           5 :         ( EQ_RENDER_CLIENT, arg::value< std::string >(),
     204             :           "The render client executable filename" )
     205           5 :     ;
     206             : 
     207          10 :     arg::variables_map vm;
     208             :     try
     209             :     {
     210           5 :         Strings args;
     211           8 :         for( int i = 0; i < argc; ++i )
     212             :         {
     213           3 :             if( strcmp( argv[i], "--" ) != 0 )
     214           3 :                 args.push_back( argv[i] );
     215             :         }
     216             :         arg::store( arg::command_line_parser( args )
     217           5 :                         .options( options ).allow_unregistered().run(), vm );
     218           5 :         arg::notify( vm );
     219             :     }
     220           0 :     catch( const std::exception& e )
     221             :     {
     222           0 :         LBERROR << "Error in argument parsing: " << e.what() << std::endl;
     223           0 :         return false;
     224             :     }
     225             : 
     226           5 :     if( vm.count( EQ_HELP ))
     227             :     {
     228           0 :         std::cout << options << std::endl;
     229           0 :         return false;
     230             :     }
     231             : 
     232           5 :     if( vm.count( EQ_LOGFILE ))
     233             :     {
     234           0 :         const std::string& newFile = vm["eq-logfile"].as< std::string >();
     235           0 :         std::ofstream* oldLog = _logFile;
     236           0 :         std::ofstream* newLog = new std::ofstream( newFile.c_str( ));
     237             : 
     238           0 :         if( newLog->is_open( ))
     239             :         {
     240           0 :             _logFile = newLog;
     241           0 :             lunchbox::Log::setOutput( *newLog );
     242             : 
     243           0 :             if( oldLog )
     244             :             {
     245           0 :                 *oldLog << "Redirected log to " << newFile << std::endl;
     246           0 :                 oldLog->close();
     247           0 :                 delete oldLog;
     248             :             }
     249             :             else
     250           0 :                 std::cout << "Redirected log to " << newFile << std::endl;
     251             :         }
     252             :         else
     253             :         {
     254           0 :             LBWARN << "Can't open log file " << newFile << ": "
     255           0 :                    << lunchbox::sysError << std::endl;
     256           0 :             delete newLog;
     257           0 :             newLog = 0;
     258             :         }
     259             :     }
     260             : 
     261           5 :     if( vm.count( EQ_SERVER ))
     262           0 :         Global::setServer( vm[EQ_SERVER].as< std::string >( ));
     263             : 
     264           5 :     if( vm.count( EQ_CONFIG ))
     265           0 :         Global::setConfigFile( vm[EQ_CONFIG].as< std::string >( ));
     266             : 
     267           5 :     if( vm.count( EQ_CONFIG_FLAGS ))
     268             :     {
     269           0 :         const Strings& flagStrings = vm[EQ_CONFIG_FLAGS].as< Strings >( );
     270           0 :         uint32_t flags = Global::getFlags();
     271           0 :         for( StringsCIter i = flagStrings.begin(); i != flagStrings.end(); ++i )
     272             :         {
     273           0 :             Flags::const_iterator j = configFlags.find( *i );
     274           0 :             if( j != configFlags.end( ))
     275           0 :                 flags |= j->second;
     276             :             else
     277           0 :                 LBWARN << "Unknown argument for --eq-config-flags: " << *i
     278           0 :                        << std::endl;
     279             :         }
     280           0 :         Global::setFlags( flags );
     281             :     }
     282             : 
     283           5 :     if( vm.count( EQ_CONFIG_PREFIXES ))
     284             :     {
     285           0 :         const Strings& prefixes = vm[EQ_CONFIG_PREFIXES].as< Strings >( );
     286           0 :         Global::setPrefixes( prefixes );
     287             :     }
     288             : 
     289           5 :     if( vm.count( EQ_CLIENT ))
     290             :     {
     291           0 :         const std::string& renderClient = vm[EQ_CLIENT].as< std::string >();
     292           0 :         const boost::filesystem::path path( renderClient );
     293             : 
     294           0 :         Global::setProgramName( renderClient );
     295           0 :         Global::setWorkDir( path.parent_path().string( ));
     296             :     }
     297             : 
     298          10 :     return true;
     299             : }
     300             : 
     301           5 : void _initPlugins()
     302             : {
     303           5 :     pression::PluginRegistry& plugins = co::Global::getPluginRegistry();
     304             : 
     305          10 :     plugins.addDirectory( lunchbox::getRootPath() +
     306           5 :                           "/share/Equalizer/plugins" ); // install dir
     307           5 :     plugins.addDirectory( "/usr/share/Equalizer/plugins" );
     308           5 :     plugins.addDirectory( "/usr/local/share/Equalizer/plugins" );
     309           5 :     plugins.addDirectory( ".eqPlugins" );
     310           5 :     plugins.addDirectory( "/opt/local/lib" ); // MacPorts
     311           5 :     plugins.addDirectory( "/usr/local/lib" ); // Homebrew
     312             : 
     313           5 :     const char* home = getenv( "HOME" );
     314           5 :     if( home )
     315           5 :         plugins.addDirectory( std::string( home ) + "/.eqPlugins" );
     316             : 
     317             : #ifdef EQUALIZER_DSO_NAME
     318           5 :     if( plugins.addPlugin( EQUALIZER_DSO_NAME )) // Found by LDD
     319          10 :         return;
     320             : 
     321             :     // Hard-coded compile locations as backup:
     322           0 :     std::string absDSO = std::string( EQ_BUILD_DIR ) + "lib/" +
     323           0 :                          EQUALIZER_DSO_NAME;
     324           0 :     if( plugins.addPlugin( absDSO ))
     325           0 :         return;
     326             : 
     327             : #  ifdef NDEBUG
     328             :     absDSO = std::string( EQ_BUILD_DIR ) + "lib/Release/" + EQUALIZER_DSO_NAME;
     329             : #  else
     330           0 :     absDSO = std::string( EQ_BUILD_DIR ) + "lib/Debug/" + EQUALIZER_DSO_NAME;
     331             : #  endif
     332             : 
     333           0 :     if( plugins.addPlugin( absDSO ))
     334           0 :         return;
     335             : 
     336           0 :     LBWARN << "Built-in Equalizer plugins not loaded: " << EQUALIZER_DSO_NAME
     337           0 :            << " not in library search path and " << absDSO << " not found"
     338           0 :            << std::endl;
     339             : #else
     340             : #  ifndef NDEBUG
     341             : #    error "EQUALIZER_DSO_NAME not defined"
     342             : #  endif
     343             :     LBWARN << "Built-in Equalizer plugins not loaded: EQUALIZER_DSO_NAME not "
     344             :            << "defined" << std::endl;
     345             : #endif
     346             : }
     347             : 
     348           5 : void _exitPlugins()
     349             : {
     350           5 :     pression::PluginRegistry& plugins = co::Global::getPluginRegistry();
     351             : 
     352          10 :     plugins.removeDirectory( lunchbox::getRootPath() +
     353           5 :                              "/share/Equalizer/plugins" );
     354           5 :     plugins.removeDirectory( "/usr/share/Equalizer/plugins" );
     355           5 :     plugins.removeDirectory( "/usr/local/share/Equalizer/plugins" );
     356           5 :     plugins.removeDirectory( ".eqPlugins" );
     357           5 :     plugins.removeDirectory( "/opt/local/lib" ); // MacPorts
     358           5 :     plugins.removeDirectory( "/usr/local/lib" ); // Homebrew
     359             : 
     360           5 :     const char* home = getenv( "HOME" );
     361           5 :     if( home )
     362           5 :         plugins.removeDirectory( std::string( home ) + "/.eqPlugins" );
     363           5 : }
     364             : 
     365           0 : Config* getConfig( const int argc, char** argv )
     366             : {
     367             :     // 1. initialization of a local client node
     368           0 :     ClientPtr client = new Client;
     369           0 :     if( client->initLocal( argc, argv ))
     370             :     {
     371             :         // 2. connect to server
     372           0 :         ServerPtr server = new Server;
     373           0 :         if( client->connectServer( server ))
     374             :         {
     375             :             // 3. choose configuration
     376           0 :             fabric::ConfigParams configParams;
     377           0 :             Config* config = server->chooseConfig( configParams );
     378           0 :             if( config )
     379           0 :                 return config;
     380             : 
     381           0 :             LBERROR << "No matching config on server" << std::endl;
     382             : 
     383             :             // -2. disconnect server
     384           0 :             client->disconnectServer( server );
     385             :         }
     386             :         else
     387           0 :             LBERROR << "Can't open server" << std::endl;
     388             : 
     389             :         // -1. exit local client node
     390           0 :         client->exitLocal();
     391             :     }
     392             :     else
     393           0 :         LBERROR << "Can't init local client node" << std::endl;
     394             : 
     395           0 :     return 0;
     396             : }
     397             : 
     398           0 : void releaseConfig( Config* config )
     399             : {
     400           0 :     if( !config )
     401           0 :         return;
     402             : 
     403           0 :     ServerPtr server = config->getServer();
     404           0 :     LBASSERT( server.isValid( ));
     405           0 :     server->releaseConfig( config );
     406             : 
     407           0 :     ClientPtr client = server->getClient();
     408           0 :     LBASSERT( client.isValid( ));
     409             : 
     410           0 :     client->disconnectServer( server );
     411           0 :     client->exitLocal();
     412             : 
     413           0 :     LBASSERTINFO( client->getRefCount() == 1, client->getRefCount( ));
     414           0 :     LBASSERTINFO( server->getRefCount() == 1, server->getRefCount( ));
     415             : }
     416             : 
     417          42 : }

Generated by: LCOV version 1.11