00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef __linux__
00026 #include <sys/prctl.h>
00027 #endif
00028
00029 #include <algorithm>
00030 #include <set>
00031 #include <string>
00032 #include <sstream>
00033
00034 #include <boost/shared_ptr.hpp>
00035
00036 #include "WModuleInputConnector.h"
00037 #include "WModuleOutputConnector.h"
00038 #include "WModuleInputData.h"
00039 #include "WModuleOutputData.h"
00040 #include "WModuleConnectorSignals.h"
00041 #include "WModuleContainer.h"
00042 #include "WModuleFactory.h"
00043 #include "exceptions/WModuleSignalUnknown.h"
00044 #include "exceptions/WModuleSignalSubscriptionFailed.h"
00045 #include "exceptions/WModuleConnectorInitFailed.h"
00046 #include "exceptions/WModuleConnectorNotFound.h"
00047 #include "exceptions/WModuleUninitialized.h"
00048 #include "exceptions/WModuleRequirementNotMet.h"
00049 #include "../common/WException.h"
00050 #include "../common/exceptions/WNameNotUnique.h"
00051 #include "../common/WLogger.h"
00052 #include "../common/WCondition.h"
00053 #include "../common/WConditionOneShot.h"
00054 #include "../common/WConditionSet.h"
00055 #include "../common/WPathHelper.h"
00056 #include "../common/WProgressCombiner.h"
00057 #include "../common/WPredicateHelper.h"
00058
00059 #include "WModule.h"
00060
00061 WModule::WModule():
00062 WThreadedRunner(),
00063 WPrototyped(),
00064 m_initialized( new WCondition(), false ),
00065 m_isAssociated( new WCondition(), false ),
00066 m_isUsable( new WCondition(), false ),
00067 m_isReady( new WConditionOneShot(), false ),
00068 m_isCrashed( new WConditionOneShot(), false ),
00069 m_isReadyOrCrashed( new WConditionSet(), false ),
00070 m_isRunning( new WCondition(), false ),
00071 m_readyProgress( boost::shared_ptr< WProgress >( new WProgress( "Initializing Module" ) ) ),
00072 m_moduleState(),
00073 m_localPath( WPathHelper::getSharePath() )
00074 {
00075
00076 m_properties = boost::shared_ptr< WProperties >( new WProperties( "Properties", "Module's properties" ) );
00077 m_infoProperties = boost::shared_ptr< WProperties >( new WProperties( "Informational Properties", "Module's information properties" ) );
00078 m_infoProperties->setPurpose( PV_PURPOSE_INFORMATION );
00079
00080 m_runtimeName = m_properties->addProperty( "Name", "The name of the module defined by the user. This is, by default, the module name but "
00081 "can be changed by the user to provide some kind of simple identification upon many modules.",
00082 std::string( "" ), false );
00083
00084 m_active = m_properties->addProperty( "active", "Determines whether the module should be activated.", true, true );
00085 m_active->getCondition()->subscribeSignal( boost::bind( &WModule::activate, this ) );
00086
00087
00088 WConditionSet* cs = static_cast< WConditionSet* >( m_isReadyOrCrashed.getCondition().get() );
00089 cs->setResetable( true, false );
00090 cs->add( m_isReady.getCondition() );
00091 cs->add( m_isCrashed.getCondition() );
00092
00093 m_container = boost::shared_ptr< WModuleContainer >();
00094 m_progress = boost::shared_ptr< WProgressCombiner >( new WProgressCombiner() );
00095
00096
00097 m_progress->addSubProgress( m_readyProgress );
00098
00099
00100 m_moduleState.add( m_shutdownFlag.getCondition() );
00101 }
00102
00103 WModule::~WModule()
00104 {
00105
00106 }
00107
00108 void WModule::addConnector( boost::shared_ptr< WModuleInputConnector > con )
00109 {
00110 size_t c = std::count_if( m_inputConnectors.begin(), m_inputConnectors.end(),
00111 WPredicateHelper::Name< boost::shared_ptr< WModuleInputConnector > >( con->getName() )
00112 );
00113
00114 c += std::count_if( m_outputConnectors.begin(), m_outputConnectors.end(),
00115 WPredicateHelper::Name< boost::shared_ptr< WModuleOutputConnector > >( con->getName() )
00116 );
00117
00118
00119 if( c )
00120 {
00121 throw WNameNotUnique( std::string( "Could not add the connector " + con->getCanonicalName() + " since names must be unique." ) );
00122 }
00123
00124 m_inputConnectors.push_back( con );
00125 }
00126
00127 void WModule::addConnector( boost::shared_ptr< WModuleOutputConnector > con )
00128 {
00129 size_t c = std::count_if( m_inputConnectors.begin(), m_inputConnectors.end(),
00130 WPredicateHelper::Name< boost::shared_ptr< WModuleInputConnector > >( con->getName() )
00131 );
00132
00133 c += std::count_if( m_outputConnectors.begin(), m_outputConnectors.end(),
00134 WPredicateHelper::Name< boost::shared_ptr< WModuleOutputConnector > >( con->getName() )
00135 );
00136
00137
00138 if( c )
00139 {
00140 throw WNameNotUnique( std::string( "Could not add the connector " + con->getCanonicalName() + " since names must be unique." ) );
00141 }
00142
00143 m_outputConnectors.push_back( con );
00144 }
00145
00146 void WModule::disconnect()
00147 {
00148
00149 for( InputConnectorList::iterator listIter = m_inputConnectors.begin();
00150 listIter != m_inputConnectors.end(); ++listIter )
00151 {
00152 ( *listIter )->disconnectAll();
00153 }
00154 for( OutputConnectorList::iterator listIter = m_outputConnectors.begin();
00155 listIter != m_outputConnectors.end(); ++listIter )
00156 {
00157 ( *listIter )->disconnectAll();
00158 }
00159 }
00160
00161 WCombinerTypes::WDisconnectList WModule::getPossibleDisconnections()
00162 {
00163 WCombinerTypes::WDisconnectList discons;
00164
00165
00166 for( InputConnectorList::iterator listIter = m_inputConnectors.begin(); listIter != m_inputConnectors.end(); ++listIter )
00167 {
00168
00169 WCombinerTypes::WDisconnectGroup g = WCombinerTypes::WDisconnectGroup( ( *listIter )->getName(),
00170 ( *listIter )->getPossibleDisconnections() );
00171
00172 if( g.second.size() )
00173 {
00174 discons.push_back( g );
00175 }
00176 }
00177
00178
00179 for( OutputConnectorList::iterator listIter = m_outputConnectors.begin(); listIter != m_outputConnectors.end(); ++listIter )
00180 {
00181
00182 WCombinerTypes::WDisconnectGroup g = WCombinerTypes::WDisconnectGroup( ( *listIter )->getName(),
00183 ( *listIter )->getPossibleDisconnections() );
00184
00185 if( g.second.size() )
00186 {
00187 discons.push_back( g );
00188 }
00189 }
00190
00191 return discons;
00192 }
00193
00194 void WModule::removeConnectors()
00195 {
00196 m_initialized( false );
00197 m_isUsable( m_initialized() && m_isAssociated() );
00198
00199
00200 disconnect();
00201
00202
00203
00204 m_inputConnectors.clear();
00205 m_outputConnectors.clear();
00206 }
00207
00208 void WModule::connectors()
00209 {
00210 }
00211
00212 void WModule::properties()
00213 {
00214 }
00215
00216 void WModule::requirements()
00217 {
00218 }
00219
00220 void WModule::activate()
00221 {
00222 }
00223
00224 std::string WModule::deprecated() const
00225 {
00226 return "";
00227 }
00228
00229 void WModule::initialize()
00230 {
00231
00232 if( isInitialized()() )
00233 {
00234 throw WModuleConnectorInitFailed( std::string( "Could not initialize connectors for Module " ) + getName() +
00235 std::string( ". Reason: already initialized." ) );
00236 }
00237
00238
00239 m_runtimeName->set( getName() );
00240
00241
00242 requirements();
00243 connectors();
00244 properties();
00245
00246
00247 m_initialized( true );
00248 m_isUsable( m_initialized() && m_isAssociated() );
00249 }
00250
00251 void WModule::cleanup()
00252 {
00253
00254 removeConnectors();
00255 }
00256
00257 boost::shared_ptr< WModuleContainer > WModule::getAssociatedContainer() const
00258 {
00259 return m_container;
00260 }
00261
00262 void WModule::setAssociatedContainer( boost::shared_ptr< WModuleContainer > container )
00263 {
00264 m_container = container;
00265
00266
00267 m_isAssociated( m_container != boost::shared_ptr< WModuleContainer >() );
00268 m_isUsable( m_initialized() && m_isAssociated() );
00269 }
00270
00271 MODULE_TYPE WModule::getType() const
00272 {
00273 return MODULE_ARBITRARY;
00274 }
00275
00276 const WModule::InputConnectorList& WModule::getInputConnectors() const
00277 {
00278 return m_inputConnectors;
00279 }
00280
00281 const WModule::OutputConnectorList& WModule::getOutputConnectors() const
00282 {
00283 return m_outputConnectors;
00284 }
00285
00286 boost::shared_ptr< WModuleInputConnector > WModule::findInputConnector( std::string name )
00287 {
00288
00289 for( InputConnectorList::const_iterator listIter = m_inputConnectors.begin();
00290 listIter != m_inputConnectors.end(); ++listIter )
00291 {
00292
00293 if( ( name == ( *listIter )->getCanonicalName() ) || ( name == ( *listIter )->getName() ) )
00294 {
00295 return ( *listIter );
00296 }
00297 }
00298
00299 return boost::shared_ptr< WModuleInputConnector >();
00300 }
00301
00302 boost::shared_ptr< WModuleInputConnector > WModule::getInputConnector( std::string name )
00303 {
00304 boost::shared_ptr< WModuleInputConnector > p = findInputConnector( name );
00305
00306 if( !p )
00307 {
00308 throw WModuleConnectorNotFound( std::string( "The connector \"" ) + name +
00309 std::string( "\" does not exist in the module \"" ) + getName() + std::string( "\"." ) );
00310 }
00311
00312 return p;
00313 }
00314
00315 boost::shared_ptr< WModuleOutputConnector > WModule::findOutputConnector( std::string name )
00316 {
00317
00318 for( OutputConnectorList::const_iterator listIter = m_outputConnectors.begin();
00319 listIter != m_outputConnectors.end(); ++listIter )
00320 {
00321
00322 if( ( name == ( *listIter )->getCanonicalName() ) || ( name == ( *listIter )->getName() ) )
00323 {
00324 return ( *listIter );
00325 }
00326 }
00327
00328 return boost::shared_ptr< WModuleOutputConnector >();
00329 }
00330
00331 boost::shared_ptr< WModuleOutputConnector > WModule::getOutputConnector( std::string name )
00332 {
00333 boost::shared_ptr< WModuleOutputConnector > p = findOutputConnector( name );
00334
00335 if( !p )
00336 {
00337 throw WModuleConnectorNotFound( std::string( "The connector \"" ) + name +
00338 std::string( "\" does not exist in the module \"" ) + getName() +
00339 std::string( "\"." ) );
00340 }
00341
00342 return p;
00343 }
00344
00345 boost::shared_ptr< WModuleConnector > WModule::findConnector( std::string name )
00346 {
00347
00348 boost::shared_ptr< WModuleConnector > p = findInputConnector( name );
00349 if( p )
00350 {
00351 return p;
00352 }
00353
00354
00355 return findOutputConnector( name );
00356 }
00357
00358 boost::shared_ptr< WModuleConnector > WModule::getConnector( std::string name )
00359 {
00360 boost::shared_ptr< WModuleConnector > p = findConnector( name );
00361
00362 if( !p )
00363 {
00364 throw WModuleConnectorNotFound( std::string( "The connector \"" ) + name +
00365 std::string( "\" does not exist in the module \"" ) + getName() +
00366 std::string( "\"." ) );
00367 }
00368
00369 return p;
00370 }
00371
00372 boost::signals2::connection WModule::subscribeSignal( MODULE_SIGNAL signal, t_ModuleGenericSignalHandlerType notifier )
00373 {
00374 switch ( signal )
00375 {
00376 case WM_READY:
00377 return signal_ready.connect( notifier );
00378 default:
00379 std::ostringstream s;
00380 s << "Could not subscribe to unknown signal.";
00381 throw WModuleSignalSubscriptionFailed( s.str() );
00382 break;
00383 }
00384 }
00385
00386 boost::signals2::connection WModule::subscribeSignal( MODULE_SIGNAL signal, t_ModuleErrorSignalHandlerType notifier )
00387 {
00388 switch (signal)
00389 {
00390 case WM_ERROR:
00391 return signal_error.connect( notifier );
00392 default:
00393 std::ostringstream s;
00394 s << "Could not subscribe to unknown signal.";
00395 throw WModuleSignalSubscriptionFailed( s.str() );
00396 break;
00397 }
00398 }
00399
00400 const t_GenericSignalHandlerType WModule::getSignalHandler( MODULE_CONNECTOR_SIGNAL signal )
00401 {
00402 switch ( signal )
00403 {
00404 case CONNECTION_ESTABLISHED:
00405 return boost::bind( &WModule::notifyConnectionEstablished, this, _1, _2 );
00406 case CONNECTION_CLOSED:
00407 return boost::bind( &WModule::notifyConnectionClosed, this, _1, _2 );
00408 case DATA_CHANGED:
00409 return boost::bind( &WModule::notifyDataChange, this, _1, _2 );
00410 default:
00411 std::ostringstream s;
00412 s << "Could not subscribe to unknown signal. You need to implement this signal type explicitly in your module.";
00413 throw WModuleSignalUnknown( s.str() );
00414 break;
00415 }
00416 }
00417
00418 const WBoolFlag& WModule::isInitialized() const
00419 {
00420 return m_initialized;
00421 }
00422
00423 const WBoolFlag& WModule::isAssociated() const
00424 {
00425 return m_isAssociated;
00426 }
00427
00428 const WBoolFlag& WModule::isUseable() const
00429 {
00430 return m_isUsable;
00431
00432 }
00433
00434 const WBoolFlag& WModule::isReady() const
00435 {
00436 return m_isReady;
00437 }
00438
00439 const WBoolFlag& WModule::isCrashed() const
00440 {
00441 return m_isCrashed;
00442 }
00443
00444 const WBoolFlag& WModule::isReadyOrCrashed() const
00445 {
00446 return m_isReadyOrCrashed;
00447 }
00448
00449 const WBoolFlag& WModule::isRunning() const
00450 {
00451 return m_isRunning;
00452 }
00453
00454 void WModule::notifyConnectionEstablished( boost::shared_ptr< WModuleConnector > ,
00455 boost::shared_ptr< WModuleConnector > )
00456 {
00457
00458 }
00459
00460 void WModule::notifyConnectionClosed( boost::shared_ptr< WModuleConnector > ,
00461 boost::shared_ptr< WModuleConnector > )
00462 {
00463
00464 }
00465
00466 void WModule::notifyDataChange( boost::shared_ptr< WModuleConnector > ,
00467 boost::shared_ptr< WModuleConnector > )
00468 {
00469
00470 }
00471
00472 boost::shared_ptr< WProperties > WModule::getProperties() const
00473 {
00474 return m_properties;
00475 }
00476
00477 boost::shared_ptr< WProperties > WModule::getInformationProperties() const
00478 {
00479 return m_infoProperties;
00480 }
00481
00482 boost::shared_ptr< WProgressCombiner > WModule::getRootProgressCombiner()
00483 {
00484 return m_progress;
00485 }
00486
00487 const char** WModule::getXPMIcon() const
00488 {
00489
00490 static const char * o_xpm[] =
00491 {
00492 "1 1 1 1",
00493 " c None",
00494 " "
00495 };
00496 return o_xpm;
00497 }
00498
00499 void WModule::ready()
00500 {
00501 m_isReady( true );
00502 m_readyProgress->finish();
00503 signal_ready( shared_from_this() );
00504 }
00505
00506 const WRequirement* WModule::checkRequirements() const
00507 {
00508
00509 for( Requirements::const_iterator i = m_requirements.begin(); i != m_requirements.end(); ++i )
00510 {
00511 if( !( *i )->isComplied() )
00512 {
00513 return *i;
00514 }
00515 }
00516
00517 return NULL;
00518 }
00519
00520 void WModule::threadMain()
00521 {
00522 #ifdef __linux__
00523
00524 prctl( PR_SET_NAME, ( "openwalnut (" + getName() + ")" ).c_str() );
00525 #endif
00526
00527 try
00528 {
00529 WLogger::getLogger()->addLogMessage( "Starting module main method.", "Module (" + getName() + ")", LL_INFO );
00530
00531
00532 const WRequirement* failedReq = checkRequirements();
00533 if( failedReq )
00534 {
00535 throw WModuleRequirementNotMet( failedReq );
00536 }
00537
00538
00539 m_isRunning( true );
00540 moduleMain();
00541 }
00542 catch( const WException& e )
00543 {
00544 wlog::error( "Module (" + getName() +")" ) << "WException. Notifying. Message: " << e.what();
00545
00546
00547 signal_error( shared_from_this(), e );
00548
00549
00550 m_isCrashed( true );
00551 }
00552 catch( const std::exception& e )
00553 {
00554
00555 WException ce = WException( e );
00556
00557
00558 WLogger::getLogger()->addLogMessage( std::string( "Exception. Notifying. Message: " ) + e.what(), "Module (" + getName() + ")", LL_ERROR );
00559
00560
00561 signal_error( shared_from_this(), ce );
00562
00563
00564 m_isCrashed( true );
00565 }
00566
00567
00568
00569 disconnect();
00570 m_isRunning( false );
00571 }
00572
00573 wlog::WStreamedLogger WModule::infoLog() const
00574 {
00575 return wlog::info( getName() );
00576 }
00577
00578 wlog::WStreamedLogger WModule::errorLog() const
00579 {
00580 return wlog::error( getName() );
00581 }
00582
00583 wlog::WStreamedLogger WModule::debugLog() const
00584 {
00585 return wlog::debug( getName() );
00586 }
00587
00588 wlog::WStreamedLogger WModule::warnLog() const
00589 {
00590 return wlog::warn( getName() );
00591 }
00592
00593 void WModule::setLocalPath( boost::filesystem::path path )
00594 {
00595 m_localPath = path;
00596 }
00597
00598 boost::filesystem::path WModule::getLocalPath() const
00599 {
00600 return m_localPath;
00601 }
00602
00603 bool WModule::isDeprecated() const
00604 {
00605 return !deprecated().empty();
00606 }
00607
00608 std::string WModule::getDeprecationMessage() const
00609 {
00610 return deprecated();
00611 }
00612