LCOV - code coverage report
Current view: top level - eq/client - init.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 94 178 52.8 %
Date: 2014-06-18 Functions: 7 9 77.8 %

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

Generated by: LCOV version 1.10