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
00026
00027
00028
00029
00030 #include <rtt/RTT.hpp>
00031 #include "DeploymentComponent.hpp"
00032 #include <rtt/Activities.hpp>
00033 #include <rtt/Activity.hpp>
00034 #include <rtt/marsh/PropertyMarshaller.hpp>
00035 #include <rtt/marsh/PropertyDemarshaller.hpp>
00036
00037 #include <cstdio>
00038 #include "ocl/ComponentLoader.hpp"
00039 #include "ComponentLoader.hpp"
00040 #include <rtt/PropertyLoader.hpp>
00041 #include <rtt/os/PluginLoader.hpp>
00042
00043 #include <iostream>
00044 #include <fstream>
00045 #include <set>
00046
00047 using namespace Orocos;
00048
00049 namespace OCL
00050 {
00051 using namespace std;
00052 using namespace RTT;
00053 using namespace RTT::OS;
00054
00058 static std::set<string> valid_names;
00059
00060 #define ORO_str(s) ORO__str(s)
00061 #define ORO__str(s) #s
00062
00063 DeploymentComponent::DeploymentComponent(std::string name, std::string siteFile)
00064 : RTT::TaskContext(name, Stopped),
00065 compPath("RTT_COMPONENT_PATH", "Locations to look for components. Use a colon or semi-colon separated list of paths. Defaults to the environment variable with the same name."),
00066 autoUnload("AutoUnload",
00067 "Stop, cleanup and unload all components loaded by the DeploymentComponent when it is destroyed.",
00068 true),
00069 validConfig("Valid", false),
00070 sched_RT("ORO_SCHED_RT", ORO_SCHED_RT ),
00071 sched_OTHER("ORO_SCHED_OTHER", ORO_SCHED_OTHER ),
00072 lowest_Priority("LowestPriority", RTT::OS::LowestPriority ),
00073 highest_Priority("HighestPriority", RTT::OS::HighestPriority ),
00074 target("Target",
00075 ORO_str(OROCOS_TARGET) )
00076 {
00077 this->properties()->addProperty( &compPath );
00078 this->properties()->addProperty( &autoUnload );
00079
00080 this->attributes()->addAttribute( &target );
00081 this->attributes()->addAttribute( &validConfig );
00082 this->attributes()->addAttribute( &sched_RT );
00083 this->attributes()->addAttribute( &sched_OTHER );
00084 this->attributes()->addAttribute( &lowest_Priority );
00085 this->attributes()->addAttribute( &highest_Priority );
00086
00087
00088 this->methods()->addMethod( RTT::method("loadLibrary", &DeploymentComponent::loadLibrary, this),
00089 "Load a new library into memory. This may be an absolute filename or of the form subdirs/foo where libfoo.so must be loaded in the RTT_COMPONENT_PATH.",
00090 "Name", "The (relative) filename of the to be loaded library.");
00091 this->methods()->addMethod( RTT::method("import", &DeploymentComponent::import, this),
00092 "Load all libraries in Path into memory. The Path is relative to the RTT_COMPONENT_PATH.",
00093 "Path", "The name of the directory where libraries are located.");
00094
00095
00096 this->methods()->addMethod( RTT::method("loadComponent", &DeploymentComponent::loadComponent, this),
00097 "Load a new component instance from a library.",
00098 "Name", "The name of the to be created component",
00099 "Type", "The component type, used to lookup the library.");
00100 this->methods()->addMethod( RTT::method("unloadComponent", &DeploymentComponent::unloadComponent, this),
00101 "Unload a loaded component instance.",
00102 "Name", "The name of the to be created component");
00103 this->methods()->addMethod( RTT::method("displayComponentTypes", &DeploymentComponent::displayComponentTypes, this),
00104 "Print out a list of all component types this component can create.");
00105
00106 this->methods()->addMethod( RTT::method("loadConfiguration", &DeploymentComponent::loadConfiguration, this),
00107 "Load a new XML configuration from a file (identical to loadComponents).",
00108 "File", "The file which contains the new configuration.");
00109 this->methods()->addMethod( RTT::method("loadConfigurationString", &DeploymentComponent::loadConfigurationString, this),
00110 "Load a new XML configuration from a string.",
00111 "Text", "The string which contains the new configuration.");
00112 this->methods()->addMethod( RTT::method("clearConfiguration", &DeploymentComponent::clearConfiguration, this),
00113 "Clear all configuration settings.");
00114
00115 this->methods()->addMethod( RTT::method("loadComponents", &DeploymentComponent::loadComponents, this),
00116 "Load components listed in an XML configuration file.",
00117 "File", "The file which contains the new configuration.");
00118 this->methods()->addMethod( RTT::method("configureComponents", &DeploymentComponent::configureComponents, this),
00119 "Apply a loaded configuration to the components and configure() them if AutoConf is set.");
00120 this->methods()->addMethod( RTT::method("startComponents", &DeploymentComponent::startComponents, this),
00121 "Start the components configured for AutoStart.");
00122 this->methods()->addMethod( RTT::method("stopComponents", &DeploymentComponent::stopComponents, this),
00123 "Stop all the configured components (with or without AutoStart).");
00124 this->methods()->addMethod( RTT::method("cleanupComponents", &DeploymentComponent::cleanupComponents, this),
00125 "Cleanup all the configured components (with or without AutoConf).");
00126 this->methods()->addMethod( RTT::method("unloadComponents", &DeploymentComponent::unloadComponents, this),
00127 "Unload all the previously loaded components.");
00128
00129 this->methods()->addMethod( RTT::method("kickStart", &DeploymentComponent::kickStart, this),
00130 "Calls loadComponents, configureComponents and startComponents in a row.",
00131 "File", "The file which contains the XML configuration to use.");
00132 this->methods()->addMethod( RTT::method("kickOutAll", &DeploymentComponent::kickOutAll, this),
00133 "Calls stopComponents, cleanupComponents and unloadComponents in a row.");
00134
00135 this->methods()->addMethod( RTT::method("kickOutComponent", &DeploymentComponent::kickOutComponent, this),
00136 "Calls stopComponents, cleanupComponent and unloadComponent in a row.",
00137 "comp_name", "component name");
00138 this->methods()->addMethod( RTT::method("kickOut", &DeploymentComponent::kickOut, this),
00139 "Calls stopComponents, cleanupComponents and unloadComponents in a row.",
00140 "File", "The file which contains the name of the components to kickOut (for example, the same used in kickStart).");
00141
00142
00143 typedef bool(DeploymentComponent::*DCFun)(const std::string&, const std::string&);
00144 DCFun cp = &DeploymentComponent::connectPeers;
00145 this->methods()->addMethod( RTT::method("connectPeers", cp, this),
00146 "Connect two Components known to this Component.",
00147 "One", "The first component.","Two", "The second component.");
00148 cp = &DeploymentComponent::connectPorts;
00149 this->methods()->addMethod( RTT::method("connectPorts", cp, this),
00150 "Connect the Data Ports of two Components known to this Component.",
00151 "One", "The first component.","Two", "The second component.");
00152 cp = &DeploymentComponent::addPeer;
00153 typedef bool(DeploymentComponent::*DC4Fun)(const std::string&, const std::string&,
00154 const std::string&, const std::string&);
00155 DC4Fun cp4 = &DeploymentComponent::connectPorts;
00156 this->methods()->addMethod( RTT::method("connectDataPorts", cp4, this),
00157 "Connect two data ports of Components known to this Component.",
00158 "One", "The first component.","Two", "The second component.",
00159 "PortOne", "The port name of the first component.",
00160 "PortTwo", "The port name of the second component.");
00161
00162 this->methods()->addMethod( RTT::method("addPeer", cp, this),
00163 "Add a peer to a Component.",
00164 "From", "The first component.","To", "The other component.");
00165 typedef void(DeploymentComponent::*RPFun)(const std::string&);
00166 RPFun rp = &TaskContext::removePeer;
00167 this->methods()->addMethod( RTT::method("removePeer", rp, this),
00168 "Remove a peer from this Component.",
00169 "PeerName", "The name of the peer to remove.");
00170
00171 this->methods()->addMethod( RTT::method("setActivity", &DeploymentComponent::setActivity, this),
00172 "Attach an activity to a Component.",
00173 "CompName", "The name of the Component.",
00174 "Period", "The period of the activity (set to 0.0 for non periodic).",
00175 "Priority", "The priority of the activity.",
00176 "SchedType", "The scheduler type of the activity."
00177 );
00178 this->methods()->addMethod( RTT::method("setPeriodicActivity", &DeploymentComponent::setPeriodicActivity, this),
00179 "Attach a periodic activity to a Component.",
00180 "CompName", "The name of the Component.",
00181 "Period", "The period of the activity.",
00182 "Priority", "The priority of the activity.",
00183 "SchedType", "The scheduler type of the activity."
00184 );
00185 this->methods()->addMethod( RTT::method("setNonPeriodicActivity", &DeploymentComponent::setNonPeriodicActivity, this),
00186 "Attach a non periodic activity to a Component.",
00187 "CompName", "The name of the Component.",
00188 "Priority", "The priority of the activity.",
00189 "SchedType", "The scheduler type of the activity."
00190 );
00191 this->methods()->addMethod( RTT::method("setSequentialActivity", &DeploymentComponent::setSequentialActivity, this),
00192 "Attach a 'stand alone' sequential activity to a Component.",
00193 "CompName", "The name of the Component."
00194 );
00195 this->methods()->addMethod( RTT::method("setSlaveActivity", &DeploymentComponent::setSlaveActivity, this),
00196 "Attach a 'stand alone' slave activity to a Component.",
00197 "CompName", "The name of the Component.",
00198 "Period", "The period of the activity (set to zero for non periodic)."
00199 );
00200 this->methods()->addMethod( RTT::method("setMasterSlaveActivity", &DeploymentComponent::setMasterSlaveActivity, this),
00201 "Attach a slave activity with a master to a Component. The slave becomes a peer of the master as well.",
00202 "Master", "The name of the Component which is master of the Slave.",
00203 "Slave", "The name of the Component which gets the SlaveActivity."
00204 );
00205
00206 valid_names.insert("AutoUnload");
00207 valid_names.insert("UseNamingService");
00208 valid_names.insert("Server");
00209 valid_names.insert("AutoConf");
00210 valid_names.insert("AutoStart");
00211 valid_names.insert("AutoConnect");
00212 valid_names.insert("AutoSave");
00213 valid_names.insert("PropertyFile");
00214 valid_names.insert("UpdateProperties");
00215 valid_names.insert("LoadProperties");
00216 valid_names.insert("ProgramScript");
00217 valid_names.insert("StateMachineScript");
00218 valid_names.insert("Ports");
00219 valid_names.insert("Peers");
00220 valid_names.insert("Activity");
00221 valid_names.insert("Master");
00222 valid_names.insert("Properties");
00223
00224
00225 if (siteFile.empty())
00226 siteFile = this->getName() + "-site.cpf";
00227 std::ifstream hassite(siteFile.c_str());
00228 if ( !hassite ) {
00229
00230 this->configure();
00231 log(Debug) << "Not using site file." << endlog();
00232 return;
00233 }
00234
00235
00236 log(Info) << "Using site file '" << siteFile << "'." << endlog();
00237 this->kickStart( siteFile );
00238
00239 }
00240
00241 bool DeploymentComponent::configureHook()
00242 {
00243 char* paths = getenv("RTT_COMPONENT_PATH");
00244 if (compPath.value().empty() )
00245 {
00246 if (paths) {
00247 compPath = string(paths);
00248 } else {
00249 log(Info) <<"No RTT_COMPONENT_PATH set. Using default." <<endlog();
00250 compPath = default_comp_path ;
00251 }
00252 }
00253 log(Info) <<"RTT_COMPONENT_PATH was set to " << compPath << endlog();
00254 log(Info) <<"Re-scanning for plugins and components..."<<endlog();
00255 PluginLoader::Instance()->setPluginPath(compPath);
00256 PluginLoader::Instance()->loadTypekits("");
00257 PluginLoader::Instance()->loadPlugins("");
00258 deployment::ComponentLoader::Instance()->setComponentPath(compPath);
00259 deployment::ComponentLoader::Instance()->import("");
00260 return true;
00261 }
00262
00263 bool DeploymentComponent::componentLoaded(TaskContext* c) { return true; }
00264
00265 void DeploymentComponent::componentUnloaded(TaskContext* c) { }
00266
00267 DeploymentComponent::~DeploymentComponent()
00268 {
00269
00270 if ( autoUnload.get() ) {
00271 kickOutAll();
00272 }
00273 deployment::ComponentLoader::Release();
00274 }
00275
00276 bool DeploymentComponent::connectPeers(const std::string& one, const std::string& other)
00277 {
00278 Logger::In in("DeploymentComponent::connectPeers");
00279 TaskContext* t1 = this->getPeer(one);
00280 TaskContext* t2 = this->getPeer(other);
00281 if (!t1) {
00282 log(Error)<< "No such peer: "<<one<<endlog();
00283 return false;
00284 }
00285 if (!t2) {
00286 log(Error) << "No such peer: "<<other<<endlog();
00287 return false;
00288 }
00289 return t1->connectPeers(t2);
00290 }
00291
00292 bool DeploymentComponent::addPeer(const std::string& from, const std::string& to)
00293 {
00294 Logger::In in("DeploymentComponent::addPeer");
00295 TaskContext* t1 = this->getPeer(from);
00296 TaskContext* t2 = this->getPeer(to);
00297 if (!t1) {
00298 log(Error)<< "No such peer: "<<from<<endlog();
00299 return false;
00300 }
00301 if (!t2) {
00302 log(Error)<< "No such peer: "<<to<<endlog();
00303 return false;
00304 }
00305 return t1->addPeer(t2);
00306 }
00307
00308 bool DeploymentComponent::connectPorts(const std::string& one, const std::string& other)
00309 {
00310 Logger::In in("DeploymentComponent::connectPorts");
00311 TaskContext* a, *b;
00312 a = getPeer(one);
00313 b = getPeer(other);
00314 if ( !a ) {
00315 log(Error) << one <<" could not be found."<< endlog();
00316 return false;
00317 }
00318 if ( !b ) {
00319 log(Error) << other <<" could not be found."<< endlog();
00320 return false;
00321 }
00322
00323 return a->connectPorts(b);
00324 }
00325
00326 bool DeploymentComponent::connectPorts(const std::string& one, const std::string& one_port,
00327 const std::string& other, const std::string& other_port)
00328 {
00329 Logger::In in("DeploymentComponent::connectPorts");
00330 TaskContext* a, *b;
00331 a = getPeer(one);
00332 b = getPeer(other);
00333 if ( !a ) {
00334 log(Error) << one <<" could not be found."<< endlog();
00335 return false;
00336 }
00337 if ( !b ) {
00338 log(Error) << other <<" could not be found."<< endlog();
00339 return false;
00340 }
00341 PortInterface* ap, *bp;
00342 ap = a->ports()->getPort(one_port);
00343 bp = b->ports()->getPort(other_port);
00344 if ( !ap ) {
00345 log(Error) << one <<" does not have a port "<<one_port<< endlog();
00346 return false;
00347 }
00348 if ( !b ) {
00349 log(Error) << other <<" does not have a port "<<other_port<< endlog();
00350 return false;
00351 }
00352
00353
00354 if ( ap->ready() && bp->ready() ) {
00355 if (ap->connection() == bp->connection() ) {
00356 log(Info) << "Port '"<< ap->getName() << "' of Component '"<<a->getName()
00357 << "' is already connected to port '"<< bp->getName() << "' of Component '"<<b->getName()<<"'."<<endlog();
00358 return true;
00359 }
00360 log(Error) << "Port '"<< ap->getName() << "' of Component '"<<a->getName()
00361 << "' and port '"<< bp->getName() << "' of Component '"<<b->getName()
00362 << "' are already connected but (probably) not to each other."<<endlog();
00363 return false;
00364 }
00365
00366
00367 if ( ap->connectTo( bp ) ) {
00368
00369 log(Info)<< "Connected Port " << ap->getName() << " to peer Task "<< b->getName() <<"." << endlog();
00370 return true;
00371 } else {
00372 log(Error)<< "Failed to connect Port " << ap->getName() << " to peer Task "<< b->getName() <<"." << endlog();
00373 return true;
00374 }
00375 }
00376
00377 int string_to_oro_sched(const std::string& sched) {
00378 if ( sched == "ORO_SCHED_OTHER" )
00379 return ORO_SCHED_OTHER;
00380 if (sched == "ORO_SCHED_RT" )
00381 return ORO_SCHED_RT;
00382 log(Error)<<"Unknown scheduler type: "<< sched <<endlog();
00383 return -1;
00384 }
00385
00386 bool DeploymentComponent::loadConfigurationString(const std::string& text)
00387 {
00388 const char* tmpfile = ".loadConfigurationString.cpf";
00389 std::ofstream file( tmpfile );
00390 file << text.c_str();
00391 file.close();
00392 return this->loadConfiguration( tmpfile );
00393 }
00394
00395 bool DeploymentComponent::kickStart(const std::string& configurationfile)
00396 {
00397 if ( this->loadComponents(configurationfile) ) {
00398 if (this->configureComponents() ) {
00399 if ( this->startComponents() ) {
00400 log(Info) <<"Successfully loaded, configured and started components from "<< configurationfile <<endlog();
00401 return true;
00402 } else {
00403 log(Error) <<"Failed to start a component: aborting kick-start."<<endlog();
00404 }
00405 } else {
00406 log(Error) <<"Failed to configure a component: aborting kick-start."<<endlog();
00407 }
00408 } else {
00409 log(Error) <<"Failed to load a component: aborting kick-start."<<endlog();
00410 }
00411 return false;
00412 }
00413
00414 bool DeploymentComponent::kickOutAll()
00415 {
00416 bool sret = this->stopComponents();
00417 bool cret = this->cleanupComponents();
00418 bool uret = this->unloadComponents();
00419 if ( sret && cret && uret) {
00420 log(Info) << "Kick-out successful."<<endlog();
00421 return true;
00422 }
00423
00424 log(Critical) << "Kick-out failed: ";
00425 if (!sret)
00426 log(Critical) << " stopComponents() failed.";
00427 if (!cret)
00428 log(Critical) << " cleanupComponents() failed.";
00429 if (!uret)
00430 log(Critical) << " unloadComponents() failed.";
00431 log(Critical) << endlog();
00432 return false;
00433 }
00434
00435 bool DeploymentComponent::loadConfiguration(const std::string& configurationfile)
00436 {
00437 return this->loadComponents(configurationfile);
00438 }
00439
00440 bool DeploymentComponent::loadComponents(const std::string& configurationfile)
00441 {
00442 Logger::In in("DeploymentComponent::loadComponents");
00443
00444 PropertyBag from_file;
00445 log(Info) << "Loading '" <<configurationfile<<"'."<< endlog();
00446
00447 bool failure = false;
00448
00449 bool valid = validConfig.get();
00450 PropertyDemarshaller demarshaller(configurationfile);
00451 try {
00452 if ( demarshaller.deserialize( from_file ) )
00453 {
00454 valid = true;
00455 log(Info)<<"Validating new configuration..."<<endlog();
00456 if ( from_file.empty() ) {
00457 log(Error)<< "Configuration was empty !" <<endlog();
00458 valid = false;
00459 }
00460
00461
00462 for (PropertyBag::iterator it= from_file.begin(); it!=from_file.end();it++) {
00463
00464 if ( (*it)->getName() == "Import" ) {
00465 Property<std::string> importp = *it;
00466 if ( !importp.ready() ) {
00467 log(Error)<< "Found 'Import' statement, but it is not of type='string'."<<endlog();
00468 valid = false;
00469 continue;
00470 }
00471 if ( this->import( importp.get() ) == false )
00472 valid = false;
00473 continue;
00474 }
00475 if ( (*it)->getName() == "LoadLibrary" ) {
00476 Property<std::string> importp = *it;
00477 if ( !importp.ready() ) {
00478 log(Error)<< "Found 'LoadLibrary' statement, but it is not of type='string'."<<endlog();
00479 valid = false;
00480 continue;
00481 }
00482 if ( this->loadLibrary( importp.get() ) == false )
00483 valid = false;
00484 continue;
00485 }
00486 if ( (*it)->getName() == "Include" ) {
00487 Property<std::string> includep = *it;
00488 if ( !includep.ready() ) {
00489 log(Error)<< "Found 'Include' statement, but it is not of type='string'."<<endlog();
00490 valid = false;
00491 continue;
00492 }
00493
00494 if ( this->loadComponents( includep.get() ) == false )
00495 valid = false;
00496 continue;
00497 }
00498
00499 Property<PropertyBag> comp = *it;
00500 if ( !comp.ready() ) {
00501 log(Error)<< "Property '"<< *it <<"' should be a struct, Include or Import statement." << endlog();
00502 valid = false;
00503 continue;
00504 }
00505
00506 for (PropertyBag::const_iterator optit= comp.rvalue().begin(); optit != comp.rvalue().end();optit++) {
00507 if ( valid_names.find( (*optit)->getName() ) == valid_names.end() ) {
00508 log(Error) << "Unknown type syntax: '"<< (*optit)->getName() << "' in component struct "<< comp.getName() <<endlog();
00509 valid = false;
00510 continue;
00511 }
00512 if ( (*optit)->getName() == "AutoConnect" ) {
00513 Property<bool> ps = comp.rvalue().getProperty<bool>("AutoConnect");
00514 if (!ps.ready()) {
00515 log(Error) << "AutoConnect must be of type <boolean>" << endlog();
00516 valid = false;
00517 } else
00518 comps[comp.getName()].autoconnect = ps.get();
00519 continue;
00520 }
00521 if ( (*optit)->getName() == "AutoStart" ) {
00522 Property<bool> ps = comp.rvalue().getProperty<bool>("AutoStart");
00523 if (!ps.ready()) {
00524 log(Error) << "AutoStart must be of type <boolean>" << endlog();
00525 valid = false;
00526 } else
00527 comps[comp.getName()].autostart = ps.get();
00528 continue;
00529 }
00530 if ( (*optit)->getName() == "AutoSave" ) {
00531 Property<bool> ps = comp.rvalue().getProperty<bool>("AutoSave");
00532 if (!ps.ready()) {
00533 log(Error) << "AutoSave must be of type <boolean>" << endlog();
00534 valid = false;
00535 } else
00536 comps[comp.getName()].autosave = ps.get();
00537 continue;
00538 }
00539 if ( (*optit)->getName() == "AutoConf" ) {
00540 Property<bool> ps = comp.rvalue().getProperty<bool>("AutoConf");
00541 if (!ps.ready()) {
00542 log(Error) << "AutoConf must be of type <boolean>" << endlog();
00543 valid = false;
00544 } else
00545 comps[comp.getName()].autoconf = ps.get();
00546 continue;
00547 }
00548 if ( (*optit)->getName() == "Server" ) {
00549 Property<bool> ps = comp.rvalue().getProperty<bool>("Server");
00550 if (!ps.ready()) {
00551 log(Error) << "Server must be of type <boolean>" << endlog();
00552 valid = false;
00553 } else
00554 comps[comp.getName()].server = ps.get();
00555 continue;
00556 }
00557 if ( (*optit)->getName() == "UseNamingService" ) {
00558 Property<bool> ps = comp.rvalue().getProperty<bool>("UseNamingService");
00559 if (!ps.ready()) {
00560 log(Error) << "UseNamingService must be of type <boolean>" << endlog();
00561 valid = false;
00562 } else
00563 comps[comp.getName()].use_naming = ps.get();
00564 continue;
00565 }
00566 if ( (*optit)->getName() == "PropertyFile" ) {
00567 Property<string> ps = comp.rvalue().getProperty<string>("PropertyFile");
00568 if (!ps.ready()) {
00569 log(Error) << "PropertyFile must be of type <string>" << endlog();
00570 valid = false;
00571 } else
00572 comps[comp.getName()].configfile = ps.get();
00573 continue;
00574 }
00575 if ( (*optit)->getName() == "UpdateProperties" ) {
00576 Property<string> ps = comp.rvalue().getProperty<string>("UpdateProperties");
00577 if (!ps.ready()) {
00578 log(Error) << "UpdateProperties must be of type <string>" << endlog();
00579 valid = false;
00580 } else
00581 comps[comp.getName()].configfile = ps.get();
00582 continue;
00583 }
00584 if ( (*optit)->getName() == "LoadProperties" ) {
00585 Property<string> ps = comp.rvalue().getProperty<string>("LoadProperties");
00586 if (!ps.ready()) {
00587 log(Error) << "LoadProperties must be of type <string>" << endlog();
00588 valid = false;
00589 } else
00590 comps[comp.getName()].configfile = ps.get();
00591 continue;
00592 }
00593 if ( (*optit)->getName() == "Properties" ) {
00594 PropertyBase* ps = comp.rvalue().getProperty<PropertyBag>("Properties");
00595 if (!ps) {
00596 log(Error) << "Properties must be a <struct>" << endlog();
00597 valid = false;
00598 }
00599 continue;
00600 }
00601 if ( (*optit)->getName() == "ProgramScript" ) {
00602 PropertyBase* ps = comp.rvalue().getProperty<string>("ProgramScript");
00603 if (!ps) {
00604 log(Error) << "ProgramScript must be of type <string>" << endlog();
00605 valid = false;
00606 }
00607 continue;
00608 }
00609 if ( (*optit)->getName() == "StateMachineScript" ) {
00610 PropertyBase* ps = comp.rvalue().getProperty<string>("StateMachineScript");
00611 if (!ps) {
00612 log(Error) << "StateMachineScript must be of type <string>" << endlog();
00613 valid = false;
00614 }
00615 continue;
00616 }
00617 }
00618
00619
00620 TaskContext* c = 0;
00621 if ( (*it)->getName() == this->getName() )
00622 c = this;
00623 else
00624 c = this->getPeer( (*it)->getName() );
00625 if ( !c ) {
00626
00627 if (this->loadComponent( (*it)->getName(), comp.rvalue().getType() ) == false) {
00628 log(Warning)<< "Could not configure '"<< (*it)->getName() <<"': No such peer."<< endlog();
00629 valid = false;
00630 continue;
00631 }
00632 c = comps[(*it)->getName()].instance;
00633 } else {
00634
00635 comps[(*it)->getName()].instance = c;
00636 }
00637
00638 assert(c);
00639
00640
00641 if ( comp.get().getProperty<std::string>("PropFile") )
00642 comp.get().getProperty<std::string>("PropFile")->setName("PropertyFile");
00643
00644
00645 Property<PropertyBag>* ports = comp.get().getProperty<PropertyBag>("Ports");
00646 if ( ports != 0 ) {
00647 PropertyBag::Names pnams = ports->get().list();
00648 for (PropertyBag::Names::iterator pit= pnams.begin(); pit !=pnams.end(); pit++) {
00649 PortInterface* p = c->ports()->getPort(*pit);
00650 if ( !p ) {
00651 log(Error)<< "Component '"<< c->getName() <<"' does not have a Port '"<<*pit<<"'." << endlog();
00652 valid = false;
00653 }
00654 if ( ports->get().getProperty<std::string>(*pit) == 0) {
00655 log(Error)<< "Property '"<< *pit <<"' is not of type 'string'." << endlog();
00656 valid = false;
00657 }
00658
00659 if (valid){
00660 string port_name = ports->get().getProperty<string>(*pit)->get();
00661 bool to_add = true;
00662
00663
00664 for(unsigned int a=0; a < conmap[port_name].ports.size(); a++)
00665 {
00666 if( conmap[port_name].ports.at(a) == p && conmap[port_name].owners.at(a) == c)
00667 {
00668 to_add = false;
00669 continue;
00670 }
00671 }
00672
00673 if(to_add)
00674 {
00675 log(Debug)<<"storing Port: "<<c->getName()<<"."<<p->getName();
00676 log(Debug)<<" in " << port_name <<endlog();
00677 conmap[port_name].ports.push_back( p );
00678 conmap[port_name].owners.push_back( c );
00679 }
00680 }
00681 }
00682 }
00683
00684
00685
00686 if ( comp.value().find("Peers") != 0) {
00687 Property<PropertyBag> nm = comp.value().find("Peers");
00688 if ( !nm.ready() ) {
00689 log(Error)<<"Property 'Peers' must be a 'struct', was type "<< comp.value().find("Peers")->getType() << endlog();
00690 valid = false;
00691 } else {
00692 for (PropertyBag::const_iterator it= nm.rvalue().begin(); it != nm.rvalue().end();it++) {
00693 Property<std::string> pr = *it;
00694 if ( !pr.ready() ) {
00695 log(Error)<<"Property 'Peer' does not have type 'string'."<<endlog();
00696 valid = false;
00697 continue;
00698 }
00699 }
00700 }
00701 }
00702
00703
00704 if ( comp.value().find("Activity") != 0) {
00705 Property<PropertyBag> nm = comp.value().find("Activity");
00706 if ( !nm.ready() ) {
00707 log(Error)<<"Property 'Activity' must be a 'struct'."<<endlog();
00708 valid = false;
00709 } else {
00710 if ( nm.rvalue().getType() == "PeriodicActivity" || nm.rvalue().getType() == "Activity") {
00711 Property<double> per("Period","",0.0);
00712 if (nm.rvalue().getProperty<double>("Period") )
00713 per = nm.rvalue().getProperty<double>("Period");
00714 if ( !per.ready() && nm.rvalue().getType() == "PeriodicActivity") {
00715 log(Error)<<"Please specify period as <double> for "<< nm.rvalue().getType() <<endlog();
00716 valid = false;
00717 }
00718 Property<int> prio;
00719 if ( nm.rvalue().getProperty<int>("Priority") )
00720 prio = nm.rvalue().getProperty<int>("Priority");
00721 if ( !prio.ready() ) {
00722 log(Error)<<"Please specify priority as <short> for "<< nm.rvalue().getType()<<endlog();
00723 valid = false;
00724 }
00725 Property<string> sched;
00726 if (nm.rvalue().getProperty<string>("Scheduler") )
00727 sched = nm.rvalue().getProperty<string>("Scheduler");
00728 int scheduler = ORO_SCHED_RT;
00729 if ( sched.ready() ) {
00730 scheduler = string_to_oro_sched( sched.get());
00731 if (scheduler == -1 )
00732 valid = false;
00733 }
00734 if (valid) {
00735 this->setNamedActivity(comp.getName(), nm.rvalue().getType(), per.get(), prio.get(), scheduler );
00736 }
00737 } else
00738 if ( nm.rvalue().getType() == "NonPeriodicActivity" ) {
00739 Property<int> prio;
00740 if ( nm.rvalue().getProperty<int>("Priority") )
00741 prio = nm.rvalue().getProperty<int>("Priority");
00742 if ( !prio.ready() ) {
00743 log(Error)<<"Please specify priority <short> of NonPeriodicActivity."<<endlog();
00744 valid = false;
00745 }
00746 Property<string> sched;
00747 if (nm.rvalue().getProperty<string>("Scheduler") )
00748 sched = nm.rvalue().getProperty<string>("Scheduler");
00749 int scheduler = ORO_SCHED_RT;
00750 if ( sched.ready() ) {
00751 int scheduler = string_to_oro_sched( sched.get());
00752 if (scheduler == -1 )
00753 valid = false;
00754 }
00755 if (valid) {
00756 this->setNamedActivity(comp.getName(), nm.rvalue().getType(), 0.0, prio.get(), scheduler );
00757 }
00758 } else
00759 if ( nm.rvalue().getType() == "SlaveActivity" ) {
00760 double period = 0.0;
00761 string master;
00762 if ( nm.rvalue().getProperty<string>("Master") ) {
00763 master = nm.rvalue().getProperty<string>("Master")->get();
00764 if (valid) {
00765 this->setNamedActivity(comp.getName(), nm.rvalue().getType(), period, 0, 0, master );
00766 }
00767 } else {
00768
00769 if ( nm.rvalue().getProperty<double>("Period") )
00770 period = nm.rvalue().getProperty<double>("Period")->get();
00771 if (valid) {
00772 this->setNamedActivity(comp.getName(), nm.rvalue().getType(), period, 0, 0 );
00773 }
00774 }
00775 } else
00776 if ( nm.rvalue().getType() == "SequentialActivity" ) {
00777 this->setNamedActivity(comp.getName(), nm.rvalue().getType(), 0, 0, 0 );
00778 } else {
00779 log(Error) << "Unknown activity type: " << nm.rvalue().getType()<<endlog();
00780 valid = false;
00781 }
00782 }
00783 } else {
00784
00785
00786 }
00787
00788
00789
00790
00791
00792 string delimiter("@!#?<!");
00793 bool ret = updateProperty( root, from_file, comp.getName(), delimiter );
00794 if (!ret) {
00795 log(Error) << "Failed to store deployment properties for component " << comp.getName() <<endlog();
00796 valid = false;
00797 }
00798 }
00799
00800 deletePropertyBag( from_file );
00801 }
00802 else
00803 {
00804 log(Error)<< "Some error occured while parsing "<< configurationfile <<endlog();
00805 failure = true;
00806 }
00807 } catch (...)
00808 {
00809 log(Error)<< "Uncaught exception in loadcomponents() !"<< endlog();
00810 failure = true;
00811 }
00812 validConfig.set(valid);
00813 return !failure && valid;
00814 }
00815
00816 bool DeploymentComponent::configureComponents()
00817 {
00818 Logger::In in("DeploymentComponent::configureComponents");
00819 if ( root.empty() ) {
00820 Logger::log() << Logger::Error
00821 << "No configuration loaded !" <<endlog();
00822 return false;
00823 }
00824
00825 bool valid = true;
00826
00827
00828 for (PropertyBag::iterator it= root.begin(); it!=root.end();it++) {
00829
00830 Property<PropertyBag> comp = *it;
00831
00832 TaskContext* peer = comps[ comp.getName() ].instance;
00833 if ( !peer ) {
00834 log(Error) << "Peer not found: "<< comp.getName() <<endlog();
00835 valid=false;
00836 continue;
00837 }
00838
00839 comps[comp.getName()].instance = peer;
00840
00841
00842
00843 Property<PropertyBag> peers = comp.rvalue().find("Peers");
00844 if ( peers.ready() )
00845 for (PropertyBag::const_iterator it= peers.rvalue().begin(); it != peers.rvalue().end();it++) {
00846 Property<string> nm = (*it);
00847 if ( nm.ready() )
00848 {
00849 this->addPeer( comps[comp.getName()].instance->getName(), nm.value() );
00850 log(Debug) << this->getName() << " connects to " <<
00851 comps[comp.getName()].instance->getName()<< nm.value() << endlog();
00852 }
00853 else {
00854 log(Error) << "Wrong property type in Peers struct. Expected property of type 'string',"
00855 << " got type "<< (*it)->getType() <<endlog();
00856 valid = false;
00857 }
00858 }
00859 }
00860
00861
00862 for(ConMap::iterator it = conmap.begin(); it != conmap.end(); ++it) {
00863 ConnectionData *connection = &(it->second);
00864 std::string connection_name = it->first;
00865
00866 if ( connection->ports.size() == 1 ){
00867 log(Warning) << "Can not form connection "<<connection_name<<" with only one Port from "<< connection->owners[0]->getName()<< endlog();
00868 continue;
00869 }
00870
00871
00872 PortInterface* writer = 0, *reader = 0;
00873 ConnectionData::Ports::iterator p = connection->ports.begin();
00874
00875
00876 while (p !=connection->ports.end() && (writer == 0 ) ) {
00877 if ( (*p)->connected() )
00878 writer = *p;
00879 ++p;
00880 }
00881
00882
00883 p = connection->ports.begin();
00884 while (p !=connection->ports.end() && (writer == 0 || reader == 0) ) {
00885 if ( (*p)->getPortType() == PortInterface::WritePort )
00886 {
00887 if (!reader && writer && writer->getPortType() == PortInterface::ReadWritePort && !writer->connected() ) {
00888 reader = writer;
00889 writer = 0;
00890 }
00891 if (!writer)
00892 writer = (*p);
00893 }
00894 else{
00895 if ( (*p)->getPortType() == PortInterface::ReadPort )
00896 {
00897 if (!writer && reader && reader->getPortType() == PortInterface::ReadWritePort ) {
00898 writer = reader;
00899 reader = 0;
00900 }
00901 if (!reader)
00902 reader = (*p);
00903 }
00904 else{
00905 if ( (*p)->getPortType() == PortInterface::ReadWritePort )
00906 {
00907 if (writer == 0)
00908 {
00909 writer = (*p);
00910 }
00911 else {
00912 reader = (*p);
00913 }
00914 }
00915 }
00916 }
00917 ++p;
00918 }
00919
00920 if ( writer == 0 ) {
00921 log(Warning) << "Connecting only read-ports in connection " << it->first << endlog();
00922
00923 writer = reader;
00924 }
00925 if ( reader == 0 ) {
00926 log(Warning) << "Connecting only write-ports in connection " << it->first << endlog();
00927 }
00928
00929 p = connection->ports.begin();
00930 while ( *p != writer ) ++p;
00931 std::string owner = it->second.owners[p - it->second.ports.begin()]->getName();
00932 log(Info) << "Creating Connection "<<it->first<<" starting from "<< owner <<"."<<writer->getName()<<" :" <<endlog();
00933
00934 p = connection->ports.begin();
00935
00936 while (p != connection->ports.end() ) {
00937
00938 if ( *p != writer )
00939 {
00940 owner = connection->owners[p - connection->ports.begin()]->getName();
00941
00942 if ( ( writer->connected() && (*p)->connection() == writer->connection() ) ) {
00943 ++p;
00944 continue;
00945 }
00946
00947 if ( (*p)->connectTo( writer ) == false) {
00948 log(Error) << "Could not connect Port "<< owner<<"."<< (*p)->getName() << " to connection " << connection_name <<endlog();
00949 if ((*p)->connected())
00950 log(Error) << "Port "<< owner<<"."<< (*p)->getName() << " already connected to other connection !"<<endlog();
00951 else
00952 log(Error) << "Port "<< owner<<"."<< (*p)->getName() << " has wrong type !"<<endlog();
00953 valid = false;
00954 } else {
00955 log(Info) << "Connected Port "<< owner<<"."<< (*p)->getName() <<" to connection " << connection_name <<endlog();
00956 }
00957 }
00958 ++p;
00959 }
00960 }
00961
00962
00963 for (PropertyBag::iterator it= root.begin(); it!=root.end();it++) {
00964 Property<PropertyBag> comp = *it;
00965 if ( !comp.ready() )
00966 continue;
00967
00968 TaskContext* peer = comps[ comp.getName() ].instance;
00969
00970
00971 if ( comps[comp.getName()].autoconnect ) {
00972 TaskContext::PeerList peers = peer->getPeerList();
00973 for(TaskContext::PeerList::iterator pit = peers.begin(); pit != peers.end(); ++pit) {
00974 if ( comps.count( *pit ) && comps[ *pit ].autoconnect ) {
00975 TaskContext* other = peer->getPeer( *pit );
00976 ::RTT::connectPorts( peer, other );
00977 }
00978 }
00979 }
00980 }
00981
00982
00983 for (PropertyBag::iterator it= root.begin(); it!=root.end();it++) {
00984
00985 Property<PropertyBag> comp = *it;
00986 Property<string> dummy;
00987 TaskContext* peer = comps[ comp.getName() ].instance;
00988
00989
00990 if ( peer->getTaskState() > Stopped) {
00991 log(Warning) << "Component "<< peer->getName()<< " doesn't need to be configured (already Running)." <<endlog();
00992 continue;
00993 }
00994
00995
00996 for (PropertyBag::const_iterator pf = comp.rvalue().begin(); pf!= comp.rvalue().end(); ++pf) {
00997
00998 if ( (*pf)->getName() == "Properties"){
00999 Property<PropertyBag> props = *pf;
01000 bool ret = updateProperties( *peer->properties(), props);
01001 if (!ret) {
01002 log(Error) << "Failed to configure properties from main configuration file for component "<< comp.getName() <<endlog();
01003 valid = false;
01004 } else {
01005 log(Info) << "Configured Properties of "<< comp.getName() <<" from main configuration file." <<endlog();
01006 }
01007 }
01008 }
01009
01010 for (PropertyBag::const_iterator pf = comp.rvalue().begin(); pf!= comp.rvalue().end(); ++pf) {
01011
01012 if ( (*pf)->getName() == "PropertyFile" || (*pf)->getName() == "UpdateProperties" || (*pf)->getName() == "LoadProperties"){
01013 dummy = *pf;
01014 string filename = dummy.get();
01015 PropertyLoader pl;
01016 bool strict = (*pf)->getName() == "PropertyFile" ? true : false;
01017 bool load = (*pf)->getName() == "LoadProperties" ? true : false;
01018 bool ret;
01019 if (!load)
01020 ret = pl.configure( filename, peer, strict );
01021 else
01022 ret = pl.load(filename, peer);
01023 if (!ret) {
01024 log(Error) << "Failed to configure properties for component "<< comp.getName() <<endlog();
01025 valid = false;
01026 } else {
01027 log(Info) << "Configured Properties of "<< comp.getName() << " from "<<filename<<endlog();
01028 comps[ comp.getName() ].loadedProperties = true;
01029 }
01030 }
01031 }
01032
01033
01034 if ( comps[comp.getName()].act ) {
01035 if ( peer->getActivity() ) {
01036 log(Info) << "Re-setting activity of "<< comp.getName() <<endlog();
01037 } else {
01038 log(Info) << "Setting activity of "<< comp.getName() <<endlog();
01039 }
01040 peer->setActivity( comps[comp.getName()].act );
01041 assert( peer->engine()->getActivity() == comps[comp.getName()].act );
01042 comps[comp.getName()].act = 0;
01043 }
01044
01045
01046 for (PropertyBag::const_iterator ps = comp.rvalue().begin(); ps!= comp.rvalue().end(); ++ps) {
01047 Property<string> pscript;
01048 if ( (*ps)->getName() == "ProgramScript" )
01049 pscript = *ps;
01050 if ( pscript.ready() ) {
01051 valid = valid && peer->scripting()->loadPrograms( pscript.get(), false );
01052 }
01053 Property<string> sscript;
01054 if ( (*ps)->getName() == "StateMachineScript" )
01055 sscript = *ps;
01056 if ( sscript.ready() ) {
01057 valid = valid && peer->scripting()->loadStateMachines( sscript.get(), false );
01058 }
01059 }
01060
01061
01062 if (comps[comp.getName()].autoconf )
01063 {
01064 if( !peer->isActive() )
01065 {
01066 if ( peer->configure() == false)
01067 valid = false;
01068 }
01069 else
01070 log(Warning) << "Apparently component "<< peer->getName()<< " don't need to be configured." <<endlog();
01071 }
01072 }
01073
01074
01075
01076 if (!valid) {
01077 for ( CompList::iterator cit = comps.begin(); cit != comps.end(); ++cit) {
01078 ComponentData* cd = &(cit->second);
01079 if ( cd->loaded && cd->autoconf &&
01080 (cd->instance->getTaskState() != TaskCore::Stopped) &&
01081 (cd->instance->getTaskState() != TaskCore::Running))
01082 log(Error) << "Failed to configure component "<< cd->instance->getName()
01083 << ": state is " << cd->instance->getTaskState() <<endlog();
01084 }
01085 } else {
01086 log(Info) << "Configuration successful." <<endlog();
01087 }
01088
01089 validConfig.set(valid);
01090 return valid;
01091 }
01092
01093 bool DeploymentComponent::startComponents()
01094 {
01095 Logger::In in("DeploymentComponent::startComponents");
01096 if (validConfig.get() == false) {
01097 log(Error) << "Not starting components with invalid configuration." <<endlog();
01098 return false;
01099 }
01100 bool valid = true;
01101 for (PropertyBag::iterator it= root.begin(); it!=root.end();it++) {
01102
01103 TaskContext* peer = comps[ (*it)->getName() ].instance;
01104
01105
01106
01107 if (peer->isRunning())
01108 {
01109 continue;
01110 }
01111
01112
01113 if (comps[(*it)->getName()].autostart )
01114 if ( !peer || peer->start() == false)
01115 valid = false;
01116 }
01117
01118 if (!valid) {
01119 for ( CompList::iterator cit = comps.begin(); cit != comps.end(); ++cit) {
01120 ComponentData* it = &(cit->second);
01121 if ( it->instance == 0 ) {
01122 log(Error) << "Failed to start component "<< cit->first << ": not found." << endlog();
01123 continue;
01124 }
01125 if ( it->autostart && it->instance->getTaskState() != TaskCore::Running )
01126 log(Error) << "Failed to start component "<< it->instance->getName() <<endlog();
01127 }
01128 } else {
01129 log(Info) << "Startup successful." <<endlog();
01130 }
01131 return valid;
01132 }
01133
01134 bool DeploymentComponent::stopComponents()
01135 {
01136 Logger::In in("DeploymentComponent::stopComponents");
01137 bool valid = true;
01138
01139 for ( CompList::iterator cit = comps.begin(); cit != comps.end(); ++cit) {
01140 ComponentData* it = &(cit->second);
01141 if ( it->instance && !it->proxy ) {
01142 if ( it->instance->engine()->getActivity() == 0 ||
01143 it->instance->engine()->getActivity()->isActive() == false ||
01144 it->instance->stop() ) {
01145 log(Info) << "Stopped "<< it->instance->getName() <<endlog();
01146 } else {
01147 log(Error) << "Could not stop loaded Component "<< it->instance->getName() <<endlog();
01148 valid = false;
01149 }
01150 }
01151 }
01152 return valid;
01153 }
01154
01155 bool DeploymentComponent::cleanupComponents()
01156 {
01157 Logger::In in("DeploymentComponent::cleanupComponents");
01158 bool valid = true;
01159
01160 for ( CompList::iterator cit = comps.begin(); cit != comps.end(); ++cit) {
01161 ComponentData* it = &(cit->second);
01162 if (it->instance && !it->proxy) {
01163 if ( it->instance->getTaskState() <= TaskCore::Stopped ) {
01164 if ( it->autosave && !it->configfile.empty()) {
01165 if (it->loadedProperties) {
01166 string file = it->configfile;
01167 PropertyLoader pl;
01168 bool ret = pl.save( file, it->instance, true );
01169 if (!ret) {
01170 log(Error) << "Failed to save properties for component "<< it->instance->getName() <<endlog();
01171 valid = false;
01172 } else {
01173 log(Info) << "Saved Properties of "<< it->instance->getName() << " to "<<file<<endlog();
01174 }
01175 } else {
01176 log(Info) << "Refusing to save property file that was not loaded for "<< it->instance->getName() <<endlog();
01177 }
01178 } else if (it->autosave) {
01179 log(Error) << "AutoSave set but no property file specified. Specify one using the UpdateProperties simple element."<<endlog();
01180 }
01181 it->instance->cleanup();
01182 log(Info) << "Cleaned up "<< it->instance->getName() <<endlog();
01183 } else {
01184 log(Error) << "Could not cleanup Component "<< it->instance->getName() << " (not Stopped)"<<endlog();
01185 valid = false;
01186 }
01187 }
01188 }
01189 return valid;
01190 }
01191
01192 bool DeploymentComponent::unloadComponents()
01193 {
01194
01195 bool valid = true;
01196 while ( comps.size() > 0 && valid)
01197 {
01198 CompList::iterator cit = comps.begin();
01199 valid &= this->unloadComponentImpl(cit);
01200 }
01201 return valid;
01202 }
01203
01204 void DeploymentComponent::clearConfiguration()
01205 {
01206 log(Info) << "Clearing configuration options."<< endlog();
01207 conmap.clear();
01208 deletePropertyBag( root );
01209 }
01210
01211 bool DeploymentComponent::import(const std::string& path)
01212 {
01213 RTT::Logger::In in("DeploymentComponent::import");
01214 log(Debug) << "Importing Components, plugins and typekits from " << path << endlog();
01215 PluginLoader::Instance()->loadTypekits(path);
01216 PluginLoader::Instance()->loadPlugins(path);
01217 deployment::ComponentLoader::Instance()->import( path );
01218 return true;
01219 }
01220
01221 bool DeploymentComponent::loadLibrary(const std::string& name)
01222 {
01223 RTT::Logger::In in("DeploymentComponent::loadLibrary");
01224 return PluginLoader::Instance()->loadTypekit(name,".") || PluginLoader::Instance()->loadPlugin(name,".") || deployment::ComponentLoader::Instance()->import(name, ".");
01225 }
01226
01227
01228 bool DeploymentComponent::loadComponent(const std::string& name, const std::string& type)
01229 {
01230 Logger::In in("DeploymentComponent::loadComponent");
01231
01232 if ( type == "PropertyBag" )
01233 return false;
01234
01235 if ( this->getPeer(name) || ( comps.find(name) != comps.end() && comps[name].instance != 0) ) {
01236 log(Error) <<"Failed to load component with name "<<name<<": already present as peer or loaded."<<endlog();
01237 return false;
01238 }
01239
01240
01241 TaskContext* instance = deployment::ComponentLoader::Instance()->loadComponent(name, type);
01242
01243 if (!instance) {
01244 return false;
01245 }
01246
01247
01248 comps[name].instance = instance;
01249
01250 if (!this->componentLoaded( instance ) ) {
01251 log(Error) << "This deployer type refused to connect to "<< instance->getName() << ": aborting !" << endlog(Error);
01252 comps[name].instance = 0;
01253 deployment::ComponentLoader::Instance()->unloadComponent( instance );
01254 return false;
01255 }
01256
01257
01258 this->addPeer( instance );
01259 log(Info) << "Adding "<< instance->getName() << " as new peer: OK."<< endlog(Info);
01260
01261 comps[name].loaded = true;
01262
01263 return true;
01264 }
01265
01270 bool DeploymentComponent::unloadComponentImpl( CompList::iterator cit )
01271 {
01272 bool valid = true;
01273 ComponentData* it = &(cit->second);
01274 std::string name = cit->first;
01275
01276 if ( it->loaded && it->instance ) {
01277 if ( it->instance->engine()->getActivity() == 0 ||
01278 it->instance->engine()->getActivity()->isActive() == false ) {
01279 if (!it->proxy ) {
01280
01281 componentUnloaded( it->instance );
01282 log(Debug) << "Disconnecting " <<name <<endlog();
01283 it->instance->disconnect();
01284 log(Debug) << "Terminating " <<name <<endlog();
01285 } else
01286 log(Debug) << "Removing proxy for " <<name <<endlog();
01287
01288
01289 for( ConMap::iterator cmit = conmap.begin(); cmit != conmap.end(); ++cmit) {
01290 size_t n = 0;
01291 while ( n != cmit->second.owners.size() ) {
01292 if (cmit->second.owners[n] == it->instance ) {
01293 cmit->second.owners.erase( cmit->second.owners.begin() + n );
01294 cmit->second.ports.erase( cmit->second.ports.begin() + n );
01295 n = 0;
01296 } else
01297 ++n;
01298 }
01299 }
01300
01301 Property<PropertyBag>* pcomp = root.getProperty<PropertyBag>(name);
01302 if (pcomp) {
01303 root.remove(pcomp);
01304 deletePropertyBag( pcomp->value() );
01305 delete pcomp;
01306 }
01307
01308
01309 delete it->act;
01310 it->act = 0;
01311 deployment::ComponentLoader::Instance()->unloadComponent( it->instance );
01312 it->instance = 0;
01313 log(Info) << "Disconnected and destroyed "<< name <<endlog();
01314 } else {
01315 log(Error) << "Could not unload Component "<< name <<": still running." <<endlog();
01316 valid=false;
01317 }
01318 }
01319 if (valid) {
01320
01321
01322 comps.erase(cit);
01323 }
01324 return valid;
01325 }
01326
01327 bool DeploymentComponent::unloadComponent(const std::string& name)
01328 {
01329 CompList::iterator it;
01330
01331 if ( comps.count( name ) == 0 || comps[name].loaded == false ) {
01332 log(Error) << "Can't unload component '"<<name<<"': not loaded by "<<this->getName()<<endlog();
01333 return false;
01334 }
01335
01336
01337 it = comps.find(name);
01338
01339 if ( this->unloadComponentImpl( it ) == false )
01340 return false;
01341
01342 log(Info) << "Successfully unloaded component "<<name<<"."<<endlog();
01343 return true;
01344 }
01345
01346 void DeploymentComponent::displayComponentTypes() const
01347 {
01348 OCL::FactoryMap::iterator it;
01349 cout << "I can create the following component types: " <<endl;
01350 for(it = OCL::ComponentFactories::Instance().begin(); it != OCL::ComponentFactories::Instance().end(); ++it) {
01351 cout << " " << it->first << endl;
01352 }
01353 if ( OCL::ComponentFactories::Instance().size() == 0 )
01354 cout << " (none)"<<endl;
01355 }
01356
01357 bool DeploymentComponent::setActivity(const std::string& comp_name,
01358 double period, int priority,
01359 int scheduler)
01360 {
01361 if ( this->setNamedActivity(comp_name, "Activity", period, priority, scheduler) ) {
01362 assert( comps[comp_name].instance );
01363 assert( comps[comp_name].act );
01364 comps[comp_name].instance->setActivity( comps[comp_name].act );
01365 comps[comp_name].act = 0;
01366 return true;
01367 }
01368 return false;
01369 }
01370
01371 bool DeploymentComponent::setPeriodicActivity(const std::string& comp_name,
01372 double period, int priority,
01373 int scheduler)
01374 {
01375 if ( this->setNamedActivity(comp_name, "PeriodicActivity", period, priority, scheduler) ) {
01376 assert( comps[comp_name].instance );
01377 assert( comps[comp_name].act );
01378 comps[comp_name].instance->setActivity( comps[comp_name].act );
01379 comps[comp_name].act = 0;
01380 return true;
01381 }
01382 return false;
01383 }
01384
01385 bool DeploymentComponent::setNonPeriodicActivity(const std::string& comp_name,
01386 int priority,
01387 int scheduler)
01388 {
01389 if ( this->setNamedActivity(comp_name, "NonPeriodicActivity", 0.0, priority, scheduler) ) {
01390 assert( comps[comp_name].instance );
01391 assert( comps[comp_name].act );
01392 comps[comp_name].instance->setActivity( comps[comp_name].act );
01393 comps[comp_name].act = 0;
01394 return true;
01395 }
01396 return false;
01397 }
01398
01399 bool DeploymentComponent::setSlaveActivity(const std::string& comp_name,
01400 double period)
01401 {
01402 if ( this->setNamedActivity(comp_name, "SlaveActivity", period, 0, ORO_SCHED_OTHER ) ) {
01403 assert( comps[comp_name].instance );
01404 assert( comps[comp_name].act );
01405 comps[comp_name].instance->setActivity( comps[comp_name].act );
01406 comps[comp_name].act = 0;
01407 return true;
01408 }
01409 return false;
01410 }
01411
01412 bool DeploymentComponent::setSequentialActivity(const std::string& comp_name)
01413 {
01414 if ( this->setNamedActivity(comp_name, "SequentialActivity", 0, 0, 0 ) ) {
01415 assert( comps[comp_name].instance );
01416 assert( comps[comp_name].act );
01417 comps[comp_name].instance->setActivity( comps[comp_name].act );
01418 comps[comp_name].act = 0;
01419 return true;
01420 }
01421 return false;
01422 }
01423
01424 bool DeploymentComponent::setMasterSlaveActivity(const std::string& master,
01425 const std::string& slave)
01426 {
01427 if ( this->setNamedActivity(slave, "SlaveActivity", 0, 0, ORO_SCHED_OTHER, master ) ) {
01428 assert( comps[slave].instance );
01429 assert( comps[slave].act );
01430 comps[slave].instance->setActivity( comps[slave].act );
01431 comps[slave].act = 0;
01432 return true;
01433 }
01434 return false;
01435 }
01436
01437
01438 bool DeploymentComponent::setNamedActivity(const std::string& comp_name,
01439 const std::string& act_type,
01440 double period, int priority,
01441 int scheduler, const std::string& master_name)
01442 {
01443
01444
01445 TaskContext* peer = 0;
01446 ActivityInterface* master_act = 0;
01447 if ( comp_name == this->getName() )
01448 peer = this;
01449 else
01450 if ( comps.count(comp_name) )
01451 peer = comps[comp_name].instance;
01452 else
01453 peer = this->getPeer(comp_name);
01454 if (!peer) {
01455 log(Error) << "Can't create Activity: component "<<comp_name<<" not found."<<endlog();
01456 return false;
01457 }
01458 if ( !master_name.empty() ) {
01459 if ( master_name == this->getName() )
01460 master_act = this->engine()->getActivity();
01461 else
01462 if ( comps.count(master_name) )
01463 master_act = comps[master_name].act;
01464 else
01465 master_act = this->getPeer(master_name) ? getPeer(master_name)->engine()->getActivity() : 0;
01466
01467 if ( !this->getPeer(master_name) ) {
01468 log(Error) << "Can't create SlaveActivity: Master component "<<master_name<<" not known as peer."<<endlog();
01469 return false;
01470 }
01471
01472 if (!master_act) {
01473 log(Error) << "Can't create SlaveActivity: Master component "<<master_name<<" has no activity set."<<endlog();
01474 return false;
01475 }
01476 }
01477
01478 comps[comp_name].instance = peer;
01479 if ( peer->isRunning() ) {
01480 log(Error) << "Can't change activity of component "<<comp_name<<" since it is still running."<<endlog();
01481 return false;
01482 }
01483
01484 ActivityInterface* newact = 0;
01485 if ( act_type == "PeriodicActivity" && period != 0.0)
01486 newact = new PeriodicActivity(scheduler, priority, period);
01487 else
01488 if ( act_type == "NonPeriodicActivity" && period == 0.0)
01489 newact = new NonPeriodicActivity(scheduler, priority);
01490 else
01491 if ( act_type == "SlaveActivity" ) {
01492 if ( master_act == 0 )
01493 newact = new SlaveActivity(period);
01494 else {
01495 newact = new SlaveActivity(master_act);
01496 this->getPeer(master_name)->addPeer( peer );
01497 }
01498 }
01499 else
01500 if (act_type == "Activity") {
01501 newact = new Activity(scheduler, priority, period, 0, comp_name);
01502 }
01503 else
01504 if (act_type == "SequentialActivity") {
01505 newact = new SequentialActivity();
01506 }
01507
01508 if (newact == 0) {
01509 log(Error) << "Can't create "<< act_type << " for component "<<comp_name<<": incorrect arguments."<<endlog();
01510 return false;
01511 }
01512
01513
01514 assert( peer->isRunning() == false );
01515 delete comps[comp_name].act;
01516 comps[comp_name].act = newact;
01517
01518 return true;
01519 }
01520
01521 bool DeploymentComponent::configure(const std::string& name)
01522 {
01523 return configureFromFile( name, name + ".cpf" );
01524 }
01525
01526 bool DeploymentComponent::configureFromFile(const std::string& name, const std::string& filename)
01527 {
01528 Logger::In in("DeploymentComponent");
01529 TaskContext* c;
01530 if ( name == this->getName() )
01531 c = this;
01532 else
01533 c = this->getPeer(name);
01534 if (!c) {
01535 log(Error)<<"No such peer to configure: "<<name<<endlog();
01536 return false;
01537 }
01538
01539 PropertyLoader pl;
01540 return pl.configure( filename, c, true );
01541 }
01542
01543 FactoryMap& DeploymentComponent::getFactories()
01544 {
01545 return ComponentFactories::Instance();
01546 }
01547
01548 void DeploymentComponent::kickOut(const std::string& config_file)
01549 {
01550 Logger::In in("DeploymentComponent::kickOut");
01551 PropertyBag from_file;
01552 Property<std::string> import_file;
01553 std::vector<std::string> deleted_components_type;
01554
01555
01556 bool failure = false;
01557
01558 PropertyDemarshaller demarshaller(config_file);
01559 try {
01560 if ( demarshaller.deserialize( from_file ) ){
01561 for (PropertyBag::iterator it= from_file.begin(); it!=from_file.end();it++) {
01562 if ( (*it)->getName() == "Import" ) continue;
01563 if ( (*it)->getName() == "LoadLibrary" ) continue;
01564 if ( (*it)->getName() == "Include" ) continue;
01565
01566 kickOutComponent( (*it)->getName() );
01567 }
01568 deletePropertyBag( from_file );
01569 }
01570 else {
01571 log(Error)<< "Some error occured while parsing "<< config_file <<endlog();
01572 failure = true;
01573 }
01574 } catch (...)
01575 {
01576 log(Error)<< "Uncaught exception in kickOut() !"<< endlog();
01577 failure = true;
01578 }
01579 }
01580
01581 bool DeploymentComponent::cleanupComponent(RTT::TaskContext *instance)
01582 {
01583 Logger::In in("DeploymentComponent::cleanupComponent");
01584 bool valid = true;
01585
01586 if (instance) {
01587 if ( instance->getTaskState() <= TaskCore::Stopped ) {
01588 instance->cleanup();
01589 log(Info) << "Cleaned up "<< instance->getName() <<endlog();
01590 } else {
01591 log(Error) << "Could not cleanup Component "<< instance->getName() << " (not Stopped)"<<endlog();
01592 valid = false;
01593 }
01594 }
01595 return valid;
01596 }
01597
01598 bool DeploymentComponent::stopComponent(RTT::TaskContext *instance)
01599 {
01600 Logger::In in("DeploymentComponent::stopComponent");
01601 bool valid = true;
01602
01603 if ( instance ) {
01604 if ( instance->engine()->getActivity() == 0 ||
01605 instance->engine()->getActivity()->isActive() == false ||
01606 instance->stop() ) {
01607 log(Info) << "Stopped "<< instance->getName() <<endlog();
01608 }
01609 else {
01610 log(Error) << "Could not stop loaded Component "<< instance->getName() <<endlog();
01611 valid = false;
01612 }
01613 }
01614 return valid;
01615 }
01616
01617 bool DeploymentComponent::kickOutComponent(const std::string& comp_name)
01618 {
01619 Logger::In in("DeploymentComponent::kickOutComponent");
01620 PropertyBase *it = root.find( comp_name );
01621 if(!it) {
01622 log(Error) << "Peer "<< comp_name << " not found in PropertyBag root"<< endlog();
01623 return false;
01624 }
01625
01626 TaskContext* peer = comps[ comp_name ].instance;
01627
01628 if ( !peer ) {
01629 log(Error) << "Peer not found: "<< comp_name <<endlog();
01630 return false;
01631 }
01632 stopComponent( peer );
01633 cleanupComponent (peer );
01634 unloadComponent( comp_name);
01635 root.removeProperty( root.find( comp_name ) );
01636
01637 return true;
01638 }
01639 }