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/deployment/ComponentLoader.hpp>
00033 #include <rtt/extras/Activities.hpp>
00034 #include <rtt/extras/SequentialActivity.hpp>
00035 #include <rtt/extras/FileDescriptorActivity.hpp>
00036 #include <rtt/marsh/PropertyMarshaller.hpp>
00037 #include <rtt/marsh/PropertyDemarshaller.hpp>
00038 #include <rtt/scripting/Scripting.hpp>
00039 #include <rtt/ConnPolicy.hpp>
00040 #include <rtt/plugin/PluginLoader.hpp>
00041
00042 # if defined(_POSIX_VERSION)
00043 # define USE_SIGNALS 1
00044 # endif
00045
00046 #ifdef USE_SIGNALS
00047 #include <signal.h>
00048 #endif
00049
00050 #include <boost/algorithm/string.hpp>
00051 #include <rtt/base/OperationCallerBaseInvoker.hpp>
00052
00053 #include <cstdio>
00054 #include <cstdlib>
00055
00056 #include "ocl/Component.hpp"
00057 #include <rtt/marsh/PropertyLoader.hpp>
00058
00059 #undef _POSIX_C_SOURCE
00060 #include <sys/types.h>
00061 #include <iostream>
00062 #include <fstream>
00063 #include <set>
00064
00065
00066
00067 using namespace Orocos;
00068
00069 namespace OCL
00070 {
00071 using namespace std;
00072 using namespace RTT;
00073 using namespace RTT::marsh;
00074 using namespace RTT::detail;
00075
00079 static std::set<string> valid_names;
00080
00081 static int got_signal = -1;
00082
00083
00084 #if defined(USE_SIGNALS)
00085
00086 void ctrl_c_catcher(int sig)
00087 {
00088
00089 got_signal = sig;
00090 }
00091 #endif
00092
00093 #define ORO_str(s) ORO__str(s)
00094 #define ORO__str(s) #s
00095
00096 DeploymentComponent::DeploymentComponent(std::string name, std::string siteFile)
00097 : RTT::TaskContext(name, Stopped),
00098 autoUnload("AutoUnload",
00099 "Stop, cleanup and unload all components loaded by the DeploymentComponent when it is destroyed.",
00100 true),
00101 validConfig("Valid", false),
00102 sched_RT("ORO_SCHED_RT", ORO_SCHED_RT ),
00103 sched_OTHER("ORO_SCHED_OTHER", ORO_SCHED_OTHER ),
00104 lowest_Priority("LowestPriority", RTT::os::LowestPriority ),
00105 highest_Priority("HighestPriority", RTT::os::HighestPriority ),
00106 target("Target",
00107 ORO_str(OROCOS_TARGET) ),
00108 nextGroup(0)
00109 {
00110 this->addProperty( "RTT_COMPONENT_PATH", compPath ).doc("Locations to look for components. Use a colon or semi-colon separated list of paths. Defaults to the environment variable with the same name.");
00111 this->addProperty( autoUnload );
00112 this->addAttribute( target );
00113
00114 this->addAttribute( validConfig );
00115 this->addAttribute( sched_RT );
00116 this->addAttribute( sched_OTHER );
00117 this->addAttribute( lowest_Priority );
00118 this->addAttribute( highest_Priority );
00119
00120
00121 this->addOperation("reloadLibrary", &DeploymentComponent::reloadLibrary, this, ClientThread).doc("Reload a new component library into memory.").arg("FilePath", "The absolute file name of the to be reloaded library. Warning: this is a low-level function only to be used during development/testing.");
00122 this->addOperation("loadLibrary", &DeploymentComponent::loadLibrary, this, ClientThread).doc("Load a new library (component, plugin or typekit) into memory.").arg("Name", "The absolute or relative name of the to be loaded library. Warning: this is a low-level function you should only use if import() doesn't work for you.");
00123 this->addOperation("import", &DeploymentComponent::import, this, ClientThread).doc("Import all components, plugins and typekits from a given package or directory in the search path.").arg("Package", "The name absolute or relative name of a directory or package.");
00124 this->addOperation("path", &DeploymentComponent::path, this, ClientThread).doc("Add additional directories to the component search path without importing them.").arg("Paths", "A colon or semi-colon separated list of paths to search for packages.");
00125
00126 this->addOperation("loadComponent", &DeploymentComponent::loadComponent, this, ClientThread).doc("Load a new component instance from a library.").arg("Name", "The name of the to be created component").arg("Type", "The component type, used to lookup the library.");
00127 this->addOperation("configureComponent", (bool (DeploymentComponent::*)(const std::string&))&DeploymentComponent::configureComponent, this, ClientThread).doc("Configure a component who is a peer of this deployer by name.").arg("Name", "The component's name");
00128 this->addOperation("startComponent", (bool (DeploymentComponent::*)(const std::string&))&DeploymentComponent::startComponent, this, ClientThread).doc("Start a component who is a peer of this deployer by name.").arg("Name", "The component's name");
00129 this->addOperation("stopComponent", (bool (DeploymentComponent::*)(const std::string&))&DeploymentComponent::stopComponent, this, ClientThread).doc("Stop a component who is a peer of this deployer by name.").arg("Name", "The component's name");
00130
00131 this->provides()->removeOperation("loadService");
00132 this->addOperation("loadService", &DeploymentComponent::loadService, this, ClientThread).doc("Load a discovered service or plugin in an existing component.").arg("Name", "The name of the component which will receive the service").arg("Service", "The name of the service or plugin.");
00133 this->addOperation("unloadComponent", &DeploymentComponent::unloadComponent, this, ClientThread).doc("Unload a loaded component instance.").arg("Name", "The name of the to be created component");
00134 this->addOperation("displayComponentTypes", &DeploymentComponent::displayComponentTypes, this, ClientThread).doc("Print out a list of all component types this component can create.");
00135 this->addOperation("getComponentTypes", &DeploymentComponent::getComponentTypes, this, ClientThread).doc("return a vector of all component types this component can create.");
00136
00137 this->addOperation("loadConfiguration", &DeploymentComponent::loadConfiguration, this, ClientThread).doc("Load a new XML configuration from a file (identical to loadComponents).").arg("File", "The file which contains the new configuration.");
00138 this->addOperation("loadConfigurationString", &DeploymentComponent::loadConfigurationString, this, ClientThread).doc("Load a new XML configuration from a string.").arg("Text", "The string which contains the new configuration.");
00139 this->addOperation("clearConfiguration", &DeploymentComponent::clearConfiguration, this, ClientThread).doc("Clear all configuration settings.");
00140
00141 this->addOperation("loadComponents", &DeploymentComponent::loadComponents, this, ClientThread).doc("Load components listed in an XML configuration file.").arg("File", "The file which contains the new configuration.");
00142 this->addOperation("configureComponents", &DeploymentComponent::configureComponents, this, ClientThread).doc("Apply a loaded configuration to the components and configure() them if AutoConf is set.");
00143 this->addOperation("startComponents", &DeploymentComponent::startComponents, this, ClientThread).doc("Start the components configured for AutoStart.");
00144 this->addOperation("stopComponents", &DeploymentComponent::stopComponents, this, ClientThread).doc("Stop all the configured components (with or without AutoStart).");
00145 this->addOperation("cleanupComponents", &DeploymentComponent::cleanupComponents, this, ClientThread).doc("Cleanup all the configured components (with or without AutoConf).");
00146 this->addOperation("unloadComponents", &DeploymentComponent::unloadComponents, this, ClientThread).doc("Unload all the previously loaded components.");
00147
00148 this->addOperation("runScript", &DeploymentComponent::runScript, this, ClientThread).doc("Runs a script.").arg("File", "An Orocos program script.");
00149 this->addOperation("kickStart", &DeploymentComponent::kickStart, this, ClientThread).doc("Calls loadComponents, configureComponents and startComponents in a row.").arg("File", "The file which contains the XML configuration to use.");
00150 this->addOperation("kickOutAll", &DeploymentComponent::kickOutAll, this, ClientThread).doc("Calls stopComponents, cleanupComponents and unloadComponents in a row.");
00151
00152 this->addOperation("kickOutComponent", &DeploymentComponent::kickOutComponent, this, ClientThread).doc("Calls stopComponents, cleanupComponent and unloadComponent in a row.").arg("comp_name", "component name");
00153 this->addOperation("kickOut", &DeploymentComponent::kickOut, this, ClientThread).doc("Calls stopComponents, cleanupComponents and unloadComponents in a row.").arg("File", "The file which contains the name of the components to kickOut (for example, the same used in kickStart).");
00154
00155 this->addOperation("waitForInterrupt", &DeploymentComponent::waitForInterrupt, this, ClientThread).doc("This operation waits for the SIGINT signal and then returns. This allows you to wait in a script for ^C.");
00156 this->addOperation("waitForSignal", &DeploymentComponent::waitForSignal, this, ClientThread).doc("This operation waits for the signal of the argument and then returns. This allows you to wait in a script for any signal except SIGKILL and SIGSTOP.").arg("signal number","The signal number to wait for.");
00157
00158
00159
00160 typedef bool(DeploymentComponent::*DCFun)(const std::string&, const std::string&);
00161 DCFun cp = &DeploymentComponent::connectPeers;
00162 this->addOperation("connectPeers", cp, this, ClientThread).doc("Connect two Components known to this Component.").arg("One", "The first component.").arg("Two", "The second component.");
00163 cp = &DeploymentComponent::connectPorts;
00164 this->addOperation("connectPorts", cp, this, ClientThread).doc("DEPRECATED. Connect the Data Ports of two Components known to this Component.").arg("One", "The first component.").arg("Two", "The second component.");
00165 typedef bool(DeploymentComponent::*DC4Fun)(const std::string&, const std::string&,
00166 const std::string&, const std::string&);
00167 DC4Fun cp4 = &DeploymentComponent::connectPorts;
00168 this->addOperation("connectTwoPorts", cp4, this, ClientThread).doc("DEPRECATED. Connect two ports of Components known to this Component.")
00169 .arg("One", "The first component.")
00170 .arg("PortOne", "The port name of the first component.")
00171 .arg("Two", "The second component.")
00172 .arg("PortTwo", "The port name of the second component.");
00173 this->addOperation("createStream", &DeploymentComponent::createStream, this, ClientThread).doc("DEPRECATED. Creates a stream to or from a port.")
00174 .arg("component", "The component which owns 'port'.")
00175 .arg("port", "The port to create a stream from or to.")
00176 .arg("policy", "The connection policy which serves to describe the stream to be created.");
00177
00178
00179 this->addOperation("connect", &DeploymentComponent::connect, this, ClientThread).doc("Creates a connection between two ports.")
00180 .arg("portOne", "The first port of the connection. Use a dot-separated-path.")
00181 .arg("portTwo", "The second port of the connection. Use a dot-separated-path.")
00182 .arg("policy", "The connection policy which serves to describe the stream to be created. Use 'ConnPolicy()' to use the default.");
00183 this->addOperation("stream", &DeploymentComponent::stream, this, ClientThread).doc("Creates a stream to or from a port.")
00184 .arg("port", "The port to create a stream from or to. Use a dot-separated-path.")
00185 .arg("policy", "The connection policy which serves to describe the stream to be created. Use 'ConnPolicy()' to use the default.");
00186
00187 this->addOperation("connectServices", (bool(DeploymentComponent::*)(const std::string&, const std::string&))&DeploymentComponent::connectServices, this, ClientThread).doc("Connect the matching provides/requires services of two Components known to this Component.").arg("One", "The first component.").arg("Two", "The second component.");
00188 this->addOperation("connectOperations", &DeploymentComponent::connectOperations, this, ClientThread).doc("Connect the matching provides/requires operations of two Components known to this Component.").arg("Requested", "The requested operation (dot-separated path).").arg("Provided", "The provided operation (dot-separated path).");
00189
00190 cp = &DeploymentComponent::addPeer;
00191 this->addOperation("addPeer", cp, this, ClientThread).doc("Add a peer to a Component.").arg("From", "The first component.").arg("To", "The other component.");
00192 this->addOperation("aliasPeer", &DeploymentComponent::aliasPeer, this, ClientThread).doc("Add a peer to a Component with an alternative name.").arg("From", "The component which will see 'To' in its peer list.").arg("To", "The component which will be seen by 'From'.").arg("Alias","The name under which 'To' is known to 'From'");
00193 typedef void(DeploymentComponent::*RPFun)(const std::string&);
00194 RPFun rp = &RTT::TaskContext::removePeer;
00195 this->addOperation("removePeer", rp, this, ClientThread).doc("Remove a peer from this Component.").arg("PeerName", "The name of the peer to remove.");
00196
00197 this->addOperation("setActivity", &DeploymentComponent::setActivity, this, ClientThread).doc("Attach an activity to a Component.").arg("CompName", "The name of the Component.").arg("Period", "The period of the activity (set to 0.0 for non periodic).").arg("Priority", "The priority of the activity.").arg("SchedType", "The scheduler type of the activity.");
00198 this->addOperation("setActivityOnCPU", &DeploymentComponent::setActivityOnCPU, this, ClientThread).doc("Attach an activity to a Component.").arg("CompName", "The name of the Component.").arg("Period", "The period of the activity (set to 0.0 for non periodic).").arg("Priority", "The priority of the activity.").arg("SchedType", "The scheduler type of the activity.").arg("CPU","The CPU to run on, starting from zero.");
00199 this->addOperation("setPeriodicActivity", &DeploymentComponent::setPeriodicActivity, this, ClientThread).doc("Attach a periodic activity to a Component.").arg("CompName", "The name of the Component.").arg("Period", "The period of the activity.").arg("Priority", "The priority of the activity.").arg("SchedType", "The scheduler type of the activity.");
00200 this->addOperation("setSequentialActivity", &DeploymentComponent::setSequentialActivity, this, ClientThread).doc("Attach a 'stand alone' sequential activity to a Component.").arg("CompName", "The name of the Component.");
00201 this->addOperation("setSlaveActivity", &DeploymentComponent::setSlaveActivity, this, ClientThread).doc("Attach a 'stand alone' slave activity to a Component.").arg("CompName", "The name of the Component.").arg("Period", "The period of the activity (set to zero for non periodic).");
00202 this->addOperation("setMasterSlaveActivity", &DeploymentComponent::setMasterSlaveActivity, this, ClientThread).doc("Attach a slave activity with a master to a Component. The slave becomes a peer of the master as well.").arg("Master", "The name of the Component which is master of the Slave.").arg("Slave", "The name of the Component which gets the SlaveActivity.");
00203 this->addOperation("setFileDescriptorActivity", &DeploymentComponent::setFileDescriptorActivity, this, ClientThread)
00204 .doc("Attach a File Descriptor activity to a Component.")
00205 .arg("CompName", "The name of the Component.")
00206 .arg("Timeout", "The timeout of the activity (set to zero for no timeout).")
00207 .arg("Priority", "The priority of the activity.")
00208 .arg("SchedType", "The scheduler type of the activity.");
00209
00210 valid_names.insert("AutoUnload");
00211 valid_names.insert("UseNamingService");
00212 valid_names.insert("Server");
00213 valid_names.insert("AutoConf");
00214 valid_names.insert("AutoStart");
00215 valid_names.insert("AutoConnect");
00216 valid_names.insert("AutoSave");
00217 valid_names.insert("PropertyFile");
00218 valid_names.insert("UpdateProperties");
00219 valid_names.insert("LoadProperties");
00220 valid_names.insert("ProgramScript");
00221 valid_names.insert("StateMachineScript");
00222 valid_names.insert("Ports");
00223 valid_names.insert("Peers");
00224 valid_names.insert("Activity");
00225 valid_names.insert("Master");
00226 valid_names.insert("Properties");
00227 valid_names.insert("Service");
00228 valid_names.insert("Plugin");
00229 valid_names.insert("Provides");
00230 valid_names.insert("RunScript");
00231
00232
00233 if (siteFile.empty())
00234 siteFile = this->getName() + "-site.cpf";
00235 std::ifstream hassite(siteFile.c_str());
00236 if ( !hassite ) {
00237
00238 this->configure();
00239
00240
00241 log(Info) << "No site file was found. Importing 'ocl' by default." <<endlog();
00242 try {
00243 import("ocl");
00244 } catch (std::exception& e) {
00245
00246 }
00247 return;
00248 }
00249
00250
00251 log(Info) << "Using site file '" << siteFile << "'." << endlog();
00252 this->kickStart( siteFile );
00253
00254 }
00255
00256 bool DeploymentComponent::configureHook()
00257 {
00258 Logger::In in("configure");
00259 if (compPath.empty() )
00260 {
00261 compPath = ComponentLoader::Instance()->getComponentPath();
00262 } else {
00263 log(Info) <<"RTT_COMPONENT_PATH was set to " << compPath << endlog();
00264 log(Info) <<"Re-scanning for plugins and components..."<<endlog();
00265 PluginLoader::Instance()->setPluginPath(compPath);
00266 ComponentLoader::Instance()->setComponentPath(compPath);
00267 ComponentLoader::Instance()->import(compPath);
00268 }
00269 return true;
00270 }
00271
00272 bool DeploymentComponent::componentLoaded(RTT::TaskContext* c) { return true; }
00273
00274 void DeploymentComponent::componentUnloaded(TaskContext* c) { }
00275
00276 DeploymentComponent::~DeploymentComponent()
00277 {
00278
00279 if ( autoUnload.get() ) {
00280 kickOutAll();
00281 }
00282 ComponentLoader::Release();
00283 }
00284
00285 bool DeploymentComponent::waitForInterrupt() {
00286 if ( !waitForSignal(SIGINT) )
00287 return false;
00288 cout << "DeploymentComponent: Got interrupt !" <<endl;
00289 return true;
00290 }
00291
00292 bool DeploymentComponent::waitForSignal(int sig) {
00293 #ifdef USE_SIGNALS
00294 struct sigaction sa, sold;
00295 sa.sa_handler = ctrl_c_catcher;
00296 if ( ::sigaction(sig, &sa, &sold) != 0) {
00297 cout << "DeploymentComponent: Failed to install signal handler for signal " << sig << endl;
00298 return false;
00299 }
00300 while (got_signal != sig) {
00301 TIME_SPEC ts;
00302 ts.tv_sec = 1;
00303 ts.tv_nsec = 0;
00304 rtos_nanosleep(&ts, 0);
00305 }
00306 got_signal = -1;
00307
00308 if (sold.sa_handler || sold.sa_sigaction)
00309 ::sigaction(sig, &sold, NULL);
00310 return true;
00311 #else
00312 cout << "DeploymentComponent: Failed to install signal handler for signal " << sig << ": Not supported by this Operating System. "<<endl;
00313 return false;
00314 #endif
00315 }
00316
00317 bool DeploymentComponent::connectPeers(const std::string& one, const std::string& other)
00318 {
00319 RTT::Logger::In in("connectPeers");
00320 RTT::TaskContext* t1 = one == this->getName() ? this : this->getPeer(one);
00321 RTT::TaskContext* t2 = other == this->getName() ? this : this->getPeer(other);
00322 if (!t1) {
00323 log(Error)<< "No such peer: "<<one<<endlog();
00324 return false;
00325 }
00326 if (!t2) {
00327 log(Error) << "No such peer: "<<other<<endlog();
00328 return false;
00329 }
00330 return t1->connectPeers(t2);
00331 }
00332
00333 bool DeploymentComponent::addPeer(const std::string& from, const std::string& to)
00334 {
00335 RTT::Logger::In in("addPeer");
00336 RTT::TaskContext* t1 = from == this->getName() ? this : this->getPeer(from);
00337 RTT::TaskContext* t2 = to == this->getName() ? this : this->getPeer(to);
00338 if (!t1) {
00339 log(Error)<< "No such peer: "<<from<<endlog();
00340 return false;
00341 }
00342 if (!t2) {
00343 log(Error)<< "No such peer: "<<to<<endlog();
00344 return false;
00345 }
00346 if ( t1->hasPeer(t2->getName()) ) {
00347 log(Info) << "addPeer: "<< to << " is already a peer of " << from << endlog();
00348 return true;
00349 }
00350 return t1->addPeer(t2);
00351 }
00352
00353 bool DeploymentComponent::aliasPeer(const std::string& from, const std::string& to, const std::string& alias)
00354 {
00355 RTT::Logger::In in("addPeer");
00356 RTT::TaskContext* t1 = from == this->getName() ? this : this->getPeer(from);
00357 RTT::TaskContext* t2 = to == this->getName() ? this : this->getPeer(to);
00358 if (!t1) {
00359 log(Error)<< "No such peer known to deployer '"<< this->getName()<< "': "<<from<<endlog();
00360 return false;
00361 }
00362 if (!t2) {
00363 log(Error)<< "No such peer known to deployer '"<< this->getName()<< "': "<<to<<endlog();
00364 return false;
00365 }
00366 return t1->addPeer(t2, alias);
00367 }
00368
00369 Service::shared_ptr DeploymentComponent::stringToService(string const& names) {
00370 std::vector<std::string> strs;
00371 boost::split(strs, names, boost::is_any_of("."));
00372
00373
00374 if (strs.empty()) return Service::shared_ptr();
00375
00376 string component = strs.front();
00377 if (!hasPeer(component) && component != this->getName() ) {
00378 log(Error) << "No such component: '"<< component <<"'" <<endlog();
00379 if ( names.find('.') != string::npos )
00380 log(Error)<< " when looking for service '" << names <<"'" <<endlog();
00381 return Service::shared_ptr();
00382 }
00383
00384 Service::shared_ptr ret = (component != this->getName() ? getPeer(component)->provides() : this->provides());
00385
00386
00387 strs.erase( strs.begin() );
00388
00389
00390 while ( !strs.empty() && ret) {
00391 ret = ret->getService( strs.front() );
00392 if (ret)
00393 strs.erase( strs.begin() );
00394 }
00395 if (!ret) {
00396 log(Error) <<"No such service: '"<< strs.front() <<"' while looking for service '"<< names<<"'"<<endlog();
00397 }
00398 return ret;
00399 }
00400
00401 ServiceRequester::shared_ptr DeploymentComponent::stringToServiceRequester(string const& names) {
00402 std::vector<std::string> strs;
00403 boost::split(strs, names, boost::is_any_of("."));
00404
00405 string component = strs.front();
00406 if (!hasPeer(component) && component != this->getName() ) {
00407 log(Error) << "No such component: '"<< component <<"'" <<endlog();
00408 if ( names.find('.') != string::npos )
00409 log(Error)<< " when looking for service '" << names <<"'" <<endlog();
00410 return ServiceRequester::shared_ptr();
00411 }
00412
00413 ServiceRequester::shared_ptr ret = (component != this->getName() ? getPeer(component)->requires() : this->requires());
00414
00415
00416 strs.erase( strs.begin() );
00417
00418
00419 while ( !strs.empty() && ret) {
00420 ret = ret->requires( strs.front() );
00421 if (ret)
00422 strs.erase( strs.begin() );
00423 }
00424 if (!ret) {
00425 log(Error) <<"No such service: '"<< strs.front() <<"' while looking for service '"<< names<<"'"<<endlog();
00426 }
00427 return ret;
00428 }
00429
00430 base::PortInterface* DeploymentComponent::stringToPort(string const& names) {
00431 std::vector<std::string> strs;
00432 boost::split(strs, names, boost::is_any_of("."));
00433
00434
00435 if (strs.empty()) return 0;
00436
00437 string component = strs.front();
00438 if (!hasPeer(component) && component != this->getName() ) {
00439 log(Error) << "No such component: '"<< component <<"'" ;
00440 log(Error)<< " when looking for port '" << names <<"'" <<endlog();
00441 return 0;
00442 }
00443
00444 Service::shared_ptr serv = (component != this->getName() ? getPeer(component)->provides() : this->provides());
00445 base::PortInterface* ret = 0;
00446
00447
00448 strs.erase( strs.begin() );
00449
00450
00451 while ( strs.size() != 1 && serv) {
00452 serv = serv->getService( strs.front() );
00453 if (serv)
00454 strs.erase( strs.begin() );
00455 }
00456 if (!serv) {
00457 log(Error) <<"No such service: '"<< strs.front() <<"' while looking for port '"<< names<<"'"<<endlog();
00458 return 0;
00459 }
00460 ret = serv->getPort(strs.front());
00461 if (!ret) {
00462 log(Error) <<"No such port: '"<< strs.front() <<"' while looking for port '"<< names<<"'"<<endlog();
00463 }
00464
00465 return ret;
00466 }
00467
00468 bool DeploymentComponent::connectPorts(const std::string& one, const std::string& other)
00469 {
00470 RTT::Logger::In in("connectPorts");
00471 RTT::TaskContext* a, *b;
00472 a = getPeer(one);
00473 b = getPeer(other);
00474 if ( !a ) {
00475 log(Error) << one <<" could not be found."<< endlog();
00476 return false;
00477 }
00478 if ( !b ) {
00479 log(Error) << other <<" could not be found."<< endlog();
00480 return false;
00481 }
00482
00483 return a->connectPorts(b);
00484 }
00485
00486 bool DeploymentComponent::connectPorts(const std::string& one, const std::string& one_port,
00487 const std::string& other, const std::string& other_port)
00488 {
00489 RTT::Logger::In in("connectPorts");
00490 Service::shared_ptr a,b;
00491 a = stringToService(one);
00492 b = stringToService(other);
00493 if (!a || !b)
00494 return false;
00495 base::PortInterface* ap, *bp;
00496 ap = a->getPort(one_port);
00497 bp = b->getPort(other_port);
00498 if ( !ap ) {
00499 log(Error) << one <<" does not have a port "<<one_port<< endlog();
00500 return false;
00501 }
00502 if ( !bp ) {
00503 log(Error) << other <<" does not have a port "<<other_port<< endlog();
00504 return false;
00505 }
00506
00507
00508 if ( ap->connected() && bp->connected() ) {
00509 log(Debug) << "Port '"<< ap->getName() << "' of Component '"<<a->getName()
00510 << "' and port '"<< bp->getName() << "' of Component '"<<b->getName()
00511 << "' are already connected but (probably) not to each other. Connecting them anyway."<<endlog();
00512 }
00513
00514
00515 if ( ap->connectTo( bp ) ) {
00516
00517 log(Info)<< "Connected Port " << one +"." + one_port << " to "<< other +"." + other_port <<"." << endlog();
00518 return true;
00519 } else {
00520 log(Error)<< "Failed to connect Port " << one +"." + one_port << " to "<< other +"." + other_port <<"." << endlog();
00521 return true;
00522 }
00523 }
00524
00525 bool DeploymentComponent::createStream(const std::string& comp, const std::string& port, ConnPolicy policy)
00526 {
00527 Service::shared_ptr serv = stringToService(comp);
00528 if ( !serv )
00529 return false;
00530 PortInterface* porti = serv->getPort(port);
00531 if ( !porti ) {
00532 log(Error) <<"Service in component "<<comp<<" has no port "<< port << "."<< endlog();
00533 return false;
00534 }
00535 return porti->createStream( policy );
00536 }
00537
00538
00539 bool DeploymentComponent::connect(const std::string& one, const std::string& other, ConnPolicy cp)
00540 {
00541 RTT::Logger::In in("connect");
00542 base::PortInterface* ap, *bp;
00543 ap = stringToPort(one);
00544 bp = stringToPort(other);
00545 if (!ap || !bp)
00546 return false;
00547
00548
00549 if ( ap->connected() && bp->connected() ) {
00550 log(Debug) << "Port '"<< ap->getName() << "' of '"<< one
00551 << "' and port '"<< bp->getName() << "' of '"<< other
00552 << "' are already connected but (probably) not to each other. Connecting them anyway."<<endlog();
00553 }
00554
00555
00556 if ( ap->connectTo( bp, cp ) ) {
00557
00558 log(Info)<< "Connected Port " << one << " to "<< other <<"." << endlog();
00559 return true;
00560 } else {
00561 log(Error)<< "Failed to connect Port " << one << " to "<< other <<"." << endlog();
00562 return false;
00563 }
00564 }
00565
00566 bool DeploymentComponent::stream(const std::string& port, ConnPolicy policy)
00567 {
00568 base::PortInterface* porti = stringToPort(port);
00569 if ( !porti ) {
00570 return false;
00571 }
00572 return porti->createStream( policy );
00573 }
00574
00575 bool DeploymentComponent::connectServices(const std::string& one, const std::string& other)
00576 {
00577 RTT::Logger::In in("connectServices");
00578 RTT::TaskContext* a, *b;
00579 a = getPeer(one);
00580 b = getPeer(other);
00581 if ( !a ) {
00582 log(Error) << one <<" could not be found."<< endlog();
00583 return false;
00584 }
00585 if ( !b ) {
00586 log(Error) << other <<" could not be found."<< endlog();
00587 return false;
00588 }
00589
00590 return a->connectServices(b);
00591 }
00592
00593 bool DeploymentComponent::connectOperations(const std::string& required, const std::string& provided)
00594 {
00595 RTT::Logger::In in("connectOperations");
00596
00597 boost::iterator_range<std::string::const_iterator> reqs = boost::algorithm::find_last(required, ".");
00598 std::string reqs_name(required.begin(), reqs.begin());
00599 std::string rop_name(reqs.begin()+1, required.end());
00600 log(Debug) << "Looking for required operation " << rop_name << " in service " << reqs_name << endlog();
00601 ServiceRequester::shared_ptr r = this->stringToServiceRequester(reqs_name);
00602
00603 boost::iterator_range<std::string::const_iterator> pros = boost::algorithm::find_last(provided, ".");
00604 std::string pros_name(provided.begin(), pros.begin());
00605 std::string pop_name(pros.begin()+1, provided.end());
00606 log(Debug) << "Looking for provided operation " << pop_name << " in service " << pros_name << endlog();
00607 Service::shared_ptr p = this->stringToService(pros_name);
00608
00609 RTT::base::OperationCallerBaseInvoker* rop = r->getOperationCaller(rop_name);
00610 if (! rop) {
00611 log(Error) << "No requested operation " << rop_name << " found in service " << reqs_name << endlog();
00612 return false;
00613 }
00614 if ( rop->ready() ) {
00615 log(Error) << "Requested operation " << rop_name << " already connected to a provided operation!" << endlog();
00616 return false;
00617 }
00618
00619 if (! p->hasOperation(pop_name)) {
00620 log(Error) << "No provided operation " << pop_name << " found in service " << pros_name << endlog();
00621 return false;
00622 }
00623
00624 rop->setImplementation(p->getLocalOperation( pop_name ), r->getServiceOwner()->engine());
00625 if ( rop->ready() )
00626 log(Debug) << "Successfully set up OperationCaller for operation " << rop_name << endlog();
00627 return rop->ready();
00628 }
00629
00630 int string_to_oro_sched(const std::string& sched) {
00631 if ( sched == "ORO_SCHED_OTHER" )
00632 return ORO_SCHED_OTHER;
00633 if (sched == "ORO_SCHED_RT" )
00634 return ORO_SCHED_RT;
00635 log(Error)<<"Unknown scheduler type: "<< sched <<endlog();
00636 return -1;
00637 }
00638
00639 bool DeploymentComponent::loadConfigurationString(const std::string& text)
00640 {
00641 const char* tmpfile = ".loadConfigurationString.cpf";
00642 std::ofstream file( tmpfile );
00643 file << text.c_str();
00644 file.close();
00645 return this->loadConfiguration( tmpfile );
00646 }
00647
00648 bool DeploymentComponent::runScript(const std::string& file_name)
00649 {
00650 return this->getProvider<Scripting>("scripting")->runScript( file_name );
00651 }
00652
00653 bool DeploymentComponent::kickStart(const std::string& configurationfile)
00654 {
00655 int thisGroup = nextGroup;
00656 ++nextGroup;
00657 if ( this->loadComponentsInGroup(configurationfile, thisGroup) ) {
00658 if (this->configureComponentsGroup(thisGroup) ) {
00659 if ( this->startComponentsGroup(thisGroup) ) {
00660 log(Info) <<"Successfully loaded, configured and started components from "<< configurationfile <<endlog();
00661 return true;
00662 } else {
00663 log(Error) <<"Failed to start a component: aborting kick-start."<<endlog();
00664 }
00665 } else {
00666 log(Error) <<"Failed to configure a component: aborting kick-start."<<endlog();
00667 }
00668 } else {
00669 log(Error) <<"Failed to load a component: aborting kick-start."<<endlog();
00670 }
00671 return false;
00672 }
00673
00674 bool DeploymentComponent::kickOutAll()
00675 {
00676 bool ok = true;
00677 while (nextGroup != -1 )
00678 {
00679 ok &= kickOutGroup(nextGroup);
00680 --nextGroup;
00681 }
00682
00683 nextGroup = 0;
00684 return ok;
00685 }
00686
00687 bool DeploymentComponent::kickOutGroup(const int group)
00688 {
00689 bool sret = this->stopComponentsGroup(group);
00690 bool cret = this->cleanupComponentsGroup(group);
00691 bool uret = this->unloadComponentsGroup(group);
00692 if ( sret && cret && uret) {
00693 log(Info) << "Kick-out of group " << group << " successful."<<endlog();
00694 return true;
00695 }
00696
00697 log(Critical) << "Kick-out of group " << group << " failed: ";
00698 if (!sret)
00699 log(Critical) << " stopComponents() failed.";
00700 if (!cret)
00701 log(Critical) << " cleanupComponents() failed.";
00702 if (!uret)
00703 log(Critical) << " unloadComponents() failed.";
00704 log(Critical) << endlog();
00705 return false;
00706 }
00707
00708 bool DeploymentComponent::loadConfiguration(const std::string& configurationfile)
00709 {
00710 return this->loadComponents(configurationfile);
00711 }
00712
00713 bool DeploymentComponent::loadComponents(const std::string& configurationfile)
00714 {
00715 bool valid = loadComponentsInGroup(configurationfile, nextGroup);
00716 ++nextGroup;
00717 return valid;
00718 }
00719
00720 bool DeploymentComponent::loadComponentsInGroup(const std::string& configurationfile,
00721 const int group)
00722 {
00723 RTT::Logger::In in("loadComponents");
00724
00725 RTT::PropertyBag from_file;
00726 log(Info) << "Loading '" <<configurationfile<<"' in group " << group << "."<< endlog();
00727
00728 bool failure = false;
00729
00730 bool valid = validConfig.get();
00731 marsh::PropertyDemarshaller demarshaller(configurationfile);
00732 try {
00733 if ( demarshaller.deserialize( from_file ) )
00734 {
00735 valid = true;
00736 log(Info)<<"Validating new configuration..."<<endlog();
00737 if ( from_file.empty() ) {
00738 log(Error)<< "Configuration was empty !" <<endlog();
00739 valid = false;
00740 }
00741
00742
00743 for (RTT::PropertyBag::iterator it= from_file.begin(); it!=from_file.end();it++) {
00744
00745 if ( (*it)->getName() == "Import" ) {
00746 RTT::Property<std::string> importp = *it;
00747 if ( !importp.ready() ) {
00748 log(Error)<< "Found 'Import' statement, but it is not of type='string'."<<endlog();
00749 valid = false;
00750 continue;
00751 }
00752 if ( this->import( importp.get() ) == false )
00753 valid = false;
00754 continue;
00755 }
00756 if ( (*it)->getName() == "LoadLibrary" ) {
00757 RTT::Property<std::string> importp = *it;
00758 if ( !importp.ready() ) {
00759 log(Error)<< "Found 'LoadLibrary' statement, but it is not of type='string'."<<endlog();
00760 valid = false;
00761 continue;
00762 }
00763 if ( this->loadLibrary( importp.get() ) == false )
00764 valid = false;
00765 continue;
00766 }
00767 if ( (*it)->getName() == "Path" ) {
00768 RTT::Property<std::string> pathp = *it;
00769 if ( !pathp.ready() ) {
00770 log(Error)<< "Found 'Path' statement, but it is not of type='string'."<<endlog();
00771 valid = false;
00772 continue;
00773 }
00774 this->path( pathp.get() );
00775 continue;
00776 }
00777 if ( (*it)->getName() == "Include" ) {
00778 RTT::Property<std::string> includep = *it;
00779 if ( !includep.ready() ) {
00780 log(Error)<< "Found 'Include' statement, but it is not of type='string'."<<endlog();
00781 valid = false;
00782 continue;
00783 }
00784
00785 if ( this->loadComponentsInGroup( includep.get(), group ) == false )
00786 valid = false;
00787 continue;
00788 }
00789
00790 RTT::Property<RTT::PropertyBag> comp = *it;
00791 if ( !comp.ready() ) {
00792 log(Error)<< "RTT::Property '"<< *it <<"' should be a struct, Include, Path or Import statement." << endlog();
00793 valid = false;
00794 continue;
00795 }
00796
00797
00798
00799 Property<ConnPolicy> cp_prop((*it)->getName(),"");
00800 assert( cp_prop.ready() );
00801 if ( cp_prop.compose( comp ) ) {
00802
00803 conmap[cp_prop.getName()].policy = cp_prop.get();
00804 log(Debug) << "Saw connection policy " << (*it)->getName() << endlog();
00805 continue;
00806 }
00807
00808
00809 for (RTT::PropertyBag::const_iterator optit= comp.rvalue().begin(); optit != comp.rvalue().end();optit++) {
00810 if ( valid_names.find( (*optit)->getName() ) == valid_names.end() ) {
00811 log(Error) << "Unknown type syntax: '"<< (*optit)->getName() << "' in component struct "<< comp.getName() <<endlog();
00812 valid = false;
00813 continue;
00814 }
00815 if ( (*optit)->getName() == "AutoConnect" ) {
00816 RTT::Property<bool> ps = comp.rvalue().getProperty("AutoConnect");
00817 if (!ps.ready()) {
00818 log(Error) << "AutoConnect must be of type <boolean>" << endlog();
00819 valid = false;
00820 } else
00821 comps[comp.getName()].autoconnect = ps.get();
00822 continue;
00823 }
00824 if ( (*optit)->getName() == "AutoStart" ) {
00825 RTT::Property<bool> ps = comp.rvalue().getProperty("AutoStart");
00826 if (!ps.ready()) {
00827 log(Error) << "AutoStart must be of type <boolean>" << endlog();
00828 valid = false;
00829 } else
00830 comps[comp.getName()].autostart = ps.get();
00831 continue;
00832 }
00833 if ( (*optit)->getName() == "AutoSave" ) {
00834 RTT::Property<bool> ps = comp.rvalue().getProperty("AutoSave");
00835 if (!ps.ready()) {
00836 log(Error) << "AutoSave must be of type <boolean>" << endlog();
00837 valid = false;
00838 } else
00839 comps[comp.getName()].autosave = ps.get();
00840 continue;
00841 }
00842 if ( (*optit)->getName() == "AutoConf" ) {
00843 RTT::Property<bool> ps = comp.rvalue().getProperty("AutoConf");
00844 if (!ps.ready()) {
00845 log(Error) << "AutoConf must be of type <boolean>" << endlog();
00846 valid = false;
00847 } else
00848 comps[comp.getName()].autoconf = ps.get();
00849 continue;
00850 }
00851 if ( (*optit)->getName() == "Server" ) {
00852 RTT::Property<bool> ps = comp.rvalue().getProperty("Server");
00853 if (!ps.ready()) {
00854 log(Error) << "Server must be of type <boolean>" << endlog();
00855 valid = false;
00856 } else
00857 comps[comp.getName()].server = ps.get();
00858 continue;
00859 }
00860 if ( (*optit)->getName() == "Service" || (*optit)->getName() == "Plugin" || (*optit)->getName() == "Provides") {
00861 RTT::Property<string> ps = *optit;
00862 if (!ps.ready()) {
00863 log(Error) << (*optit)->getName() << " must be of type <string>" << endlog();
00864 valid = false;
00865 } else {
00866 comps[comp.getName()].plugins.push_back(ps.value());
00867 }
00868 continue;
00869 }
00870 if ( (*optit)->getName() == "UseNamingService" ) {
00871 RTT::Property<bool> ps = comp.rvalue().getProperty("UseNamingService");
00872 if (!ps.ready()) {
00873 log(Error) << "UseNamingService must be of type <boolean>" << endlog();
00874 valid = false;
00875 } else
00876 comps[comp.getName()].use_naming = ps.get();
00877 continue;
00878 }
00879 if ( (*optit)->getName() == "PropertyFile" ) {
00880 RTT::Property<string> ps = comp.rvalue().getProperty("PropertyFile");
00881 if (!ps.ready()) {
00882 log(Error) << "PropertyFile must be of type <string>" << endlog();
00883 valid = false;
00884 } else
00885 comps[comp.getName()].configfile = ps.get();
00886 continue;
00887 }
00888 if ( (*optit)->getName() == "UpdateProperties" ) {
00889 RTT::Property<string> ps = comp.rvalue().getProperty("UpdateProperties");
00890 if (!ps.ready()) {
00891 log(Error) << "UpdateProperties must be of type <string>" << endlog();
00892 valid = false;
00893 } else
00894 comps[comp.getName()].configfile = ps.get();
00895 continue;
00896 }
00897 if ( (*optit)->getName() == "LoadProperties" ) {
00898 RTT::Property<string> ps = comp.rvalue().getProperty("LoadProperties");
00899 if (!ps.ready()) {
00900 log(Error) << "LoadProperties must be of type <string>" << endlog();
00901 valid = false;
00902 } else
00903 comps[comp.getName()].configfile = ps.get();
00904 continue;
00905 }
00906 if ( (*optit)->getName() == "Properties" ) {
00907 base::PropertyBase* ps = comp.rvalue().getProperty("Properties");
00908 if (!ps) {
00909 log(Error) << "Properties must be a <struct>" << endlog();
00910 valid = false;
00911 }
00912 continue;
00913 }
00914 if ( (*optit)->getName() == "RunScript" ) {
00915 base::PropertyBase* ps = comp.rvalue().getProperty("RunScript");
00916 if (!ps) {
00917 log(Error) << "RunScript must be of type <string>" << endlog();
00918 valid = false;
00919 }
00920 continue;
00921 }
00922 if ( (*optit)->getName() == "ProgramScript" ) {
00923 log(Warning) << "ProgramScript tag is deprecated. Rename it to 'RunScript'." <<endlog();
00924 base::PropertyBase* ps = comp.rvalue().getProperty("ProgramScript");
00925 if (!ps) {
00926 log(Error) << "ProgramScript must be of type <string>" << endlog();
00927 valid = false;
00928 }
00929 continue;
00930 }
00931 if ( (*optit)->getName() == "StateMachineScript" ) {
00932 log(Warning) << "StateMachineScript tag is deprecated. Rename it to 'RunScript'." <<endlog();
00933 base::PropertyBase* ps = comp.rvalue().getProperty("StateMachineScript");
00934 if (!ps) {
00935 log(Error) << "StateMachineScript must be of type <string>" << endlog();
00936 valid = false;
00937 }
00938 continue;
00939 }
00940 }
00941
00942
00943 RTT::TaskContext* c = 0;
00944 if ( (*it)->getName() == this->getName() )
00945 c = this;
00946 else
00947 c = this->getPeer( (*it)->getName() );
00948 if ( !c ) {
00949
00950 if (this->loadComponent( (*it)->getName(), comp.rvalue().getType() ) == false) {
00951 log(Warning)<< "Could not configure '"<< (*it)->getName() <<"': No such peer."<< endlog();
00952 valid = false;
00953 continue;
00954 }
00955 c = comps[(*it)->getName()].instance;
00956 } else {
00957
00958 comps[(*it)->getName()].instance = c;
00959 }
00960
00961 assert(c);
00962
00963
00964 vector<string>& services = comps[(*it)->getName()].plugins;
00965 for (vector<string>::iterator svit = services.begin(); svit != services.end(); ++svit) {
00966 if ( c->provides()->hasService( *svit ) == false) {
00967 PluginLoader::Instance()->loadService(*svit, c);
00968 }
00969 }
00970
00971
00972 if ( comp.value().getProperty("PropFile") )
00973 comp.value().getProperty("PropFile")->setName("PropertyFile");
00974
00975
00976 RTT::Property<RTT::PropertyBag>* ports = comp.value().getPropertyType<PropertyBag>("Ports");
00977 if ( ports != 0 ) {
00978 for (RTT::PropertyBag::iterator pit = ports->value().begin(); pit != ports->value().end(); pit++) {
00979 Property<string> portcon = *pit;
00980 if ( !portcon.ready() ) {
00981 log(Error)<< "RTT::Property '"<< (*pit)->getName() <<"' is not of type 'string'." << endlog();
00982 valid = false;
00983 continue;
00984 }
00985 base::PortInterface* p = c->ports()->getPort( portcon.getName() );
00986 if ( !p ) {
00987 log(Error)<< "Component '"<< c->getName() <<"' does not have a Port '"<< portcon.getName()<<"'." << endlog();
00988 valid = false;
00989 }
00990
00991 if (valid){
00992 string conn_name = portcon.value();
00993 bool to_add = true;
00994
00995
00996 for(unsigned int a=0; a < conmap[conn_name].ports.size(); a++)
00997 {
00998 if( conmap[conn_name].ports.at(a) == p && conmap[conn_name].owners.at(a) == c)
00999 {
01000 to_add = false;
01001 continue;
01002 }
01003 }
01004
01005 if(to_add)
01006 {
01007 log(Debug)<<"storing Port: "<<c->getName()<<"."<< portcon.getName();
01008 log(Debug)<<" in " << conn_name <<endlog();
01009 conmap[conn_name].ports.push_back( p );
01010 conmap[conn_name].owners.push_back( c );
01011 }
01012 }
01013 }
01014 }
01015
01016
01017
01018 if ( comp.value().find("Peers") != 0) {
01019 RTT::Property<RTT::PropertyBag> nm = comp.value().find("Peers");
01020 if ( !nm.ready() ) {
01021 log(Error)<<"RTT::Property 'Peers' must be a 'struct', was type "<< comp.value().find("Peers")->getType() << endlog();
01022 valid = false;
01023 } else {
01024 for (RTT::PropertyBag::const_iterator it= nm.rvalue().begin(); it != nm.rvalue().end();it++) {
01025 RTT::Property<std::string> pr = *it;
01026 if ( !pr.ready() ) {
01027 log(Error)<<"RTT::Property 'Peer' does not have type 'string'."<<endlog();
01028 valid = false;
01029 continue;
01030 }
01031 }
01032 }
01033 }
01034
01035
01036 if ( comp.value().find("Activity") != 0) {
01037 RTT::Property<RTT::PropertyBag> nm = comp.value().find("Activity");
01038 if ( !nm.ready() ) {
01039 log(Error)<<"RTT::Property 'Activity' must be a 'struct'."<<endlog();
01040 valid = false;
01041 } else {
01042 if ( nm.rvalue().getType() == "PeriodicActivity" ) {
01043 RTT::Property<double> per = nm.rvalue().getProperty("Period");
01044 if ( !per.ready() ) {
01045 log(Error)<<"Please specify period <double> of PeriodicActivity."<<endlog();
01046 valid = false;
01047 }
01048 RTT::Property<int> prio = nm.rvalue().getProperty("Priority");
01049 if ( !prio.ready() ) {
01050 log(Error)<<"Please specify priority <short> of PeriodicActivity."<<endlog();
01051 valid = false;
01052 }
01053
01054 unsigned cpu_affinity = ~0;
01055 RTT::Property<unsigned> cpu_affinity_prop = nm.rvalue().getProperty("CpuAffinity");
01056 if(cpu_affinity_prop.ready()) {
01057 cpu_affinity = cpu_affinity_prop.get();
01058 }
01059
01060
01061 RTT::Property<string> sched;
01062 if (nm.rvalue().getProperty("Scheduler") )
01063 sched = nm.rvalue().getProperty("Scheduler");
01064 int scheduler = ORO_SCHED_RT;
01065 if ( sched.ready() ) {
01066 scheduler = string_to_oro_sched( sched.get());
01067 if (scheduler == -1 )
01068 valid = false;
01069 }
01070 if (valid) {
01071 this->setNamedActivity(comp.getName(), nm.rvalue().getType(), per.get(), prio.get(), scheduler, cpu_affinity );
01072 }
01073 } else
01074 if ( nm.rvalue().getType() == "Activity" || nm.rvalue().getType() == "NonPeriodicActivity" ) {
01075 RTT::Property<double> per = nm.rvalue().getProperty("Period");
01076 if ( !per.ready() ) {
01077 per = Property<double>("p","",0.0);
01078 }
01079 RTT::Property<int> prio = nm.rvalue().getProperty("Priority");
01080 if ( !prio.ready() ) {
01081 log(Error)<<"Please specify priority <short> of Activity."<<endlog();
01082 valid = false;
01083 }
01084
01085 unsigned int cpu_affinity = ~0;
01086 RTT::Property<unsigned int> cpu_affinity_prop = nm.rvalue().getProperty("CpuAffinity");
01087 if(cpu_affinity_prop.ready()) {
01088 cpu_affinity = cpu_affinity_prop.get();
01089 }
01090
01091
01092 RTT::Property<string> sched = nm.rvalue().getProperty("Scheduler");
01093 int scheduler = ORO_SCHED_RT;
01094 if ( sched.ready() ) {
01095 scheduler = string_to_oro_sched( sched.get());
01096 if (scheduler == -1 )
01097 valid = false;
01098 }
01099 if (valid) {
01100 this->setNamedActivity(comp.getName(), nm.rvalue().getType(), per.get(), prio.get(), scheduler, cpu_affinity );
01101 }
01102 } else
01103 if ( nm.rvalue().getType() == "SlaveActivity" ) {
01104 double period = 0.0;
01105 string master;
01106 if ( nm.rvalue().getProperty("Master") ) {
01107 master = nm.rvalue().getPropertyType<string>("Master")->get();
01108 if (valid) {
01109 this->setNamedActivity(comp.getName(), nm.rvalue().getType(), period, 0, 0, master );
01110 }
01111 } else {
01112
01113 if ( nm.rvalue().getProperty("Period") )
01114 period = nm.rvalue().getPropertyType<double>("Period")->get();
01115 if (valid) {
01116 this->setNamedActivity(comp.getName(), nm.rvalue().getType(), period, 0, 0 );
01117 }
01118 }
01119 } else
01120 if ( nm.rvalue().getType() == "SequentialActivity" ) {
01121 this->setNamedActivity(comp.getName(), nm.rvalue().getType(), 0, 0, 0 );
01122 } else
01123 if ( nm.rvalue().getType() == "FileDescriptorActivity" ) {
01124 RTT::Property<double> per = nm.rvalue().getProperty("Period");
01125 if ( !per.ready() ) {
01126 per = Property<double>("p","",0.0);
01127 }
01128
01129
01130 RTT::Property<int> prio = nm.rvalue().getProperty("Priority");
01131 if ( !prio.ready() ) {
01132 log(Error)<<"Please specify priority <short> of FileDescriptorActivity."<<endlog();
01133 valid = false;
01134 }
01135
01136 unsigned int cpu_affinity = ~0;
01137 RTT::Property<unsigned int> cpu_affinity_prop = nm.rvalue().getProperty("CpuAffinity");
01138 if(cpu_affinity_prop.ready()) {
01139 cpu_affinity = cpu_affinity_prop.get();
01140 }
01141
01142
01143 RTT::Property<string> sched = nm.rvalue().getProperty("Scheduler");
01144 int scheduler = ORO_SCHED_RT;
01145 if ( sched.ready() ) {
01146 scheduler = string_to_oro_sched( sched.get());
01147 if (scheduler == -1 )
01148 valid = false;
01149 }
01150 if (valid) {
01151 this->setNamedActivity(comp.getName(), nm.rvalue().getType(), per.get(), prio.get(), scheduler, cpu_affinity );
01152 }
01153 } else {
01154 log(Error) << "Unknown activity type: " << nm.rvalue().getType()<<endlog();
01155 valid = false;
01156 }
01157 }
01158 } else {
01159
01160
01161 }
01162
01163
01164
01165
01166 string delimiter("@!#?<!");
01167 bool ret = updateProperty( root, from_file, comp.getName(), delimiter );
01168 if (!ret) {
01169 log(Error) << "Failed to store deployment properties for component " << comp.getName() <<endlog();
01170 valid = false;
01171 }
01172 else
01173 {
01174 log(Info) << "Added component " << (*it)->getName() << " to group " << group << endlog();
01175 comps[(*it)->getName()].group = group;
01176 }
01177 }
01178
01179 deletePropertyBag( from_file );
01180 }
01181 else
01182 {
01183 log(Error)<< "Some error occured while parsing "<< configurationfile <<endlog();
01184 failure = true;
01185 }
01186 } catch (...)
01187 {
01188 log(Error)<< "Uncaught exception in loadcomponents() !"<< endlog();
01189 failure = true;
01190 }
01191 validConfig.set(valid);
01192 return !failure && valid;
01193 }
01194
01195 bool DeploymentComponent::configureComponents()
01196 {
01197 RTT::Logger::In in("configureComponents");
01198
01199 bool valid = true;
01200 for (int group = nextGroup - 1; group > 0; --group) {
01201 valid &= configureComponentsGroup(group);
01202 }
01203 return valid;
01204 }
01205
01206 bool DeploymentComponent::configureComponentsGroup(const int group)
01207 {
01208 RTT::Logger::In in("configureComponents");
01209 if ( root.empty() ) {
01210 RTT::Logger::log() << RTT::Logger::Error
01211 << "No components loaded by DeploymentComponent !" <<endlog();
01212 return false;
01213 }
01214
01215 bool valid = true;
01216 log(Info) << "Configuring components in group " << group << endlog();
01217
01218
01219 for (RTT::PropertyBag::iterator it= root.begin(); it!=root.end();it++) {
01220
01221 RTT::Property<RTT::PropertyBag> comp = *it;
01222
01223
01224 if (group != comps[ comp.getName() ].group) {
01225 continue;
01226 }
01227
01228 RTT::TaskContext* peer = comps[ comp.getName() ].instance;
01229 if ( !peer ) {
01230 log(Error) << "Peer not found: "<< comp.getName() <<endlog();
01231 valid=false;
01232 continue;
01233 }
01234
01235 comps[comp.getName()].instance = peer;
01236
01237
01238
01239 RTT::Property<RTT::PropertyBag> peers = comp.rvalue().find("Peers");
01240 if ( peers.ready() )
01241 for (RTT::PropertyBag::const_iterator it= peers.rvalue().begin(); it != peers.rvalue().end();it++) {
01242 RTT::Property<string> nm = (*it);
01243 if ( nm.ready() )
01244 {
01245 if ( this->addPeer( comps[comp.getName()].instance->getName(), nm.value() ) == false ) {
01246 log(Error) << this->getName() << " can't make " << nm.value() << " a peer of " <<
01247 comps[comp.getName()].instance->getName() << endlog();
01248 valid = false;
01249 } else {
01250 log(Info) << this->getName() << " makes " << nm.value() << " a peer of " <<
01251 comps[comp.getName()].instance->getName() << endlog();
01252 }
01253 }
01254 else {
01255 log(Error) << "Wrong property type in Peers struct. Expected property of type 'string',"
01256 << " got type "<< (*it)->getType() <<endlog();
01257 valid = false;
01258 }
01259 }
01260 }
01261
01262
01263 for(ConMap::iterator it = conmap.begin(); it != conmap.end(); ++it) {
01264 ConnectionData *connection = &(it->second);
01265 std::string connection_name = it->first;
01266
01267 if ( connection->ports.size() == 1 ){
01268 string owner = connection->owners[0]->getName();
01269 string portname = connection->ports.front()->getName();
01270 string porttype = dynamic_cast<InputPortInterface*>(connection->ports.front() ) ? "InputPort" : "OutputPort";
01271 if ( connection->ports.front()->createStream( connection->policy ) == false) {
01272 log(Warning) << "Creating stream with name "<<connection_name<<" with Port "<<portname<<" from "<< owner << " failed."<< endlog();
01273 } else {
01274 log(Info) << "Component "<< owner << "'s " + porttype<< " " + portname << " will stream to "<< connection->policy.name_id << endlog();
01275 }
01276 continue;
01277 }
01278
01279 base::PortInterface* writer = 0;
01280 ConnectionData::Ports::iterator p = connection->ports.begin();
01281
01282
01283 vector<OutputPortInterface*> writers;
01284 while (p !=connection->ports.end() ) {
01285 if ( OutputPortInterface* out = dynamic_cast<base::OutputPortInterface*>( *p ) ) {
01286 if ( writer ) {
01287 log(Info) << "Forming multi-output connections with additional OutputPort " << (*p)->getName() << "."<<endlog();
01288 } else
01289 writer = *p;
01290 writers.push_back( out );
01291 std::string owner = it->second.owners[p - it->second.ports.begin()]->getName();
01292 log(Info) << "Component "<< owner << "'s OutputPort "<< writer->getName()<< " will write topic "<<it->first<< endlog();
01293 }
01294 ++p;
01295 }
01296
01297
01298 if ( writer == 0 ) {
01299 log(Error) << "No OutputPort listed that writes " << it->first << endlog();
01300 valid = false;
01301 break;
01302 }
01303
01304
01305 p = connection->ports.begin();
01306 vector<OutputPortInterface*>::iterator w = writers.begin();
01307
01308 while (w != writers.end() ) {
01309 while (p != connection->ports.end() ) {
01310
01311 if ( dynamic_cast<base::InputPortInterface*>( *p ) )
01312 {
01313 string owner = connection->owners[p - connection->ports.begin()]->getName();
01314
01315
01316 if ( (*w)->connectTo( *p, connection->policy ) == false) {
01317 log(Error) << "Could not subscribe InputPort "<< owner<<"."<< (*p)->getName() << " to topic " << (*w)->getName() <<'/'<< connection_name <<endlog();
01318 valid = false;
01319 } else {
01320 log(Info) << "Subscribed InputPort "<< owner<<"."<< (*p)->getName() <<" to topic " << (*w)->getName() <<'/'<< connection_name <<endlog();
01321 }
01322 }
01323 ++p;
01324 }
01325 ++w;
01326 p = connection->ports.begin();
01327 }
01328 }
01329
01330
01331 for (RTT::PropertyBag::iterator it= root.begin(); it!=root.end();it++) {
01332 RTT::Property<RTT::PropertyBag> comp = *it;
01333 if ( !comp.ready() )
01334 continue;
01335
01336
01337 if (group != comps[ comp.getName() ].group) {
01338 continue;
01339 }
01340
01341 RTT::TaskContext* peer = comps[ comp.getName() ].instance;
01342
01343
01344
01345
01346 if ( comps[comp.getName()].autoconnect ) {
01347
01348 RTT::TaskContext::PeerList peers = peer->getPeerList();
01349 for(RTT::TaskContext::PeerList::iterator pit = peers.begin(); pit != peers.end(); ++pit) {
01350 if ( comps.count( *pit ) && comps[ *pit ].autoconnect ) {
01351 RTT::TaskContext* other = peer->getPeer( *pit );
01352 valid = RTT::connectPorts( peer, other ) && valid;
01353 }
01354 }
01355 }
01356 }
01357
01358
01359 for (RTT::PropertyBag::iterator it= root.begin(); it!=root.end();it++) {
01360
01361 RTT::Property<RTT::PropertyBag> comp = *it;
01362
01363
01364 if (group != comps[ comp.getName() ].group) {
01365 continue;
01366 }
01367
01368 RTT::Property<string> dummy;
01369 RTT::TaskContext* peer = comps[ comp.getName() ].instance;
01370
01371
01372 if ( peer->getTaskState() > Stopped) {
01373 log(Warning) << "Component "<< peer->getName()<< " doesn't need to be configured (already Running)." <<endlog();
01374 continue;
01375 }
01376
01377
01378 for (RTT::PropertyBag::const_iterator pf = comp.rvalue().begin(); pf!= comp.rvalue().end(); ++pf) {
01379
01380 if ( (*pf)->getName() == "Properties"){
01381 RTT::Property<RTT::PropertyBag> props = *pf;
01382 bool ret = updateProperties( *peer->properties(), props);
01383 if (!ret) {
01384 log(Error) << "Failed to configure properties from main configuration file for component "<< comp.getName() <<endlog();
01385 valid = false;
01386 } else {
01387 log(Info) << "Configured Properties of "<< comp.getName() <<" from main configuration file." <<endlog();
01388 }
01389 }
01390 }
01391
01392 for (RTT::PropertyBag::const_iterator pf = comp.rvalue().begin(); pf!= comp.rvalue().end(); ++pf) {
01393
01394 if ( (*pf)->getName() == "PropertyFile" || (*pf)->getName() == "UpdateProperties" || (*pf)->getName() == "LoadProperties"){
01395 dummy = *pf;
01396 string filename = dummy.get();
01397 marsh::PropertyLoader pl(peer);
01398 bool strict = (*pf)->getName() == "PropertyFile" ? true : false;
01399 bool load = (*pf)->getName() == "LoadProperties" ? true : false;
01400 bool ret;
01401 if (!load)
01402 ret = pl.configure( filename, strict );
01403 else
01404 ret = pl.load(filename);
01405 if (!ret) {
01406 log(Error) << "Failed to configure properties for component "<< comp.getName() <<endlog();
01407 valid = false;
01408 } else {
01409 log(Info) << "Configured Properties of "<< comp.getName() << " from "<<filename<<endlog();
01410 comps[ comp.getName() ].loadedProperties = true;
01411 }
01412 }
01413 }
01414
01415
01416 if ( comps[comp.getName()].act ) {
01417 if ( peer->getActivity() ) {
01418 log(Info) << "Re-setting activity of "<< comp.getName() <<endlog();
01419 } else {
01420 log(Info) << "Setting activity of "<< comp.getName() <<endlog();
01421 }
01422 if (peer->setActivity( comps[comp.getName()].act ) == false ) {
01423 valid = false;
01424 log(Error) << "Failed to set Activity of " << comp.getName() << endlog();
01425 } else {
01426 assert( peer->engine()->getActivity() == comps[comp.getName()].act );
01427 comps[comp.getName()].act = 0;
01428 }
01429 }
01430
01431
01432 for (RTT::PropertyBag::const_iterator ps = comp.rvalue().begin(); ps!= comp.rvalue().end(); ++ps) {
01433 RTT::Property<string> script;
01434 if ( (*ps)->getName() == "RunScript" )
01435 script = *ps;
01436 if ( script.ready() ) {
01437 valid = valid && peer->getProvider<Scripting>("scripting")->runScript( script.get() );
01438 }
01439
01440 RTT::Property<string> pscript;
01441 if ( (*ps)->getName() == "ProgramScript" )
01442 pscript = *ps;
01443 if ( pscript.ready() ) {
01444 valid = valid && peer->getProvider<Scripting>("scripting")->loadPrograms( pscript.get() );
01445 }
01446 RTT::Property<string> sscript;
01447 if ( (*ps)->getName() == "StateMachineScript" )
01448 sscript = *ps;
01449 if ( sscript.ready() ) {
01450 valid = valid && peer->getProvider<Scripting>("scripting")->loadStateMachines( sscript.get() );
01451 }
01452 }
01453
01454
01455 if (comps[comp.getName()].autoconf )
01456 {
01457 if( !peer->isRunning() )
01458 {
01459 OperationCaller<bool(void)> peerconfigure = peer->getOperation("configure");
01460 if ( peerconfigure() == false) {
01461 log(Error) << "Component " << peer->getName() << " returns false in configure()" << endlog();
01462 valid = false;
01463 }
01464 }
01465 else
01466 log(Warning) << "Apparently component "<< peer->getName()<< " don't need to be configured (already Running)." <<endlog();
01467 }
01468 }
01469
01470
01471
01472 if (!valid) {
01473 for ( CompList::iterator cit = comps.begin(); cit != comps.end(); ++cit) {
01474 ComponentData* cd = &(cit->second);
01475 if ( group == cd->group && cd->loaded && cd->autoconf &&
01476 (cd->instance->getTaskState() != TaskCore::Stopped) &&
01477 (cd->instance->getTaskState() != TaskCore::Running))
01478 log(Error) << "Failed to configure component "<< cd->instance->getName()
01479 << ": state is " << cd->instance->getTaskState() <<endlog();
01480 }
01481 } else {
01482 log(Info) << "Configuration successful for group " << group << "." <<endlog();
01483 }
01484
01485 validConfig.set(valid);
01486 return valid;
01487 }
01488
01489 bool DeploymentComponent::startComponents()
01490 {
01491
01492 bool valid = true;
01493 for (int group = nextGroup - 1; group > 0; --group) {
01494 valid &= startComponentsGroup(group);
01495 }
01496 return valid;
01497 }
01498
01499 bool DeploymentComponent::startComponentsGroup(const int group)
01500 {
01501 RTT::Logger::In in("startComponentsGroup");
01502 if (validConfig.get() == false) {
01503 log(Error) << "Not starting components with invalid configuration." <<endlog();
01504 return false;
01505 }
01506 bool valid = true;
01507 for (RTT::PropertyBag::iterator it= root.begin(); it!=root.end();it++) {
01508
01509
01510 if (group != comps[ (*it)->getName() ].group) {
01511 continue;
01512 }
01513
01514 TaskContext* peer = comps[ (*it)->getName() ].instance;
01515
01516
01517
01518 if (peer->isRunning())
01519 {
01520 continue;
01521 }
01522
01523
01524 OperationCaller<bool(void)> peerstart = peer->getOperation("start");
01525 if (comps[(*it)->getName()].autostart )
01526 if ( !peer || ( !peer->isRunning() && peerstart() == false) )
01527 valid = false;
01528 }
01529
01530 if (!valid) {
01531 for ( CompList::iterator cit = comps.begin(); cit != comps.end(); ++cit) {
01532 ComponentData* it = &(cit->second);
01533
01534
01535 if (group != it->group) {
01536 continue;
01537 }
01538
01539 if ( it->instance == 0 ) {
01540 log(Error) << "Failed to start component "<< cit->first << ": not found." << endlog();
01541 continue;
01542 }
01543 if ( it->autostart && it->instance->getTaskState() != base::TaskCore::Running )
01544 log(Error) << "Failed to start component "<< it->instance->getName() <<endlog();
01545 }
01546 } else {
01547 log(Info) << "Startup of 'AutoStart' components successful for group " << group << "." <<endlog();
01548 }
01549 return valid;
01550 }
01551
01552 bool DeploymentComponent::stopComponents()
01553 {
01554
01555 bool valid = true;
01556 for (int group = nextGroup ; group != -1; --group) {
01557 valid &= stopComponentsGroup(group);
01558 }
01559 return valid;
01560 }
01561
01562 bool DeploymentComponent::stopComponentsGroup(const int group)
01563 {
01564 RTT::Logger::In in("stopComponentsGroup");
01565 log(Info) << "Stopping group " << group << endlog();
01566 bool valid = true;
01567
01568 for ( CompList::iterator cit = comps.begin(); cit != comps.end(); ++cit) {
01569 ComponentData* it = &(cit->second);
01570 if ( (group == it->group) && it->instance && !it->proxy ) {
01571 OperationCaller<bool(void)> instancestop = it->instance->getOperation("stop");
01572 if ( !it->instance->isRunning() ||
01573 instancestop() ) {
01574 log(Info) << "Stopped "<< it->instance->getName() <<endlog();
01575 } else {
01576 log(Error) << "Could not stop loaded Component "<< it->instance->getName() <<endlog();
01577 valid = false;
01578 }
01579 }
01580 }
01581 return valid;
01582 }
01583
01584 bool DeploymentComponent::cleanupComponents()
01585 {
01586
01587 bool valid = true;
01588 for (int group = nextGroup ; group != -1; --group) {
01589 valid &= cleanupComponentsGroup(group);
01590 }
01591 return valid;
01592 }
01593
01594 bool DeploymentComponent::cleanupComponentsGroup(const int group)
01595 {
01596 RTT::Logger::In in("cleanupComponentsGroup");
01597 bool valid = true;
01598 log(Info) << "Cleaning up group " << group << endlog();
01599
01600 for ( CompList::iterator cit = comps.begin(); cit != comps.end(); ++cit) {
01601 ComponentData* it = &(cit->second);
01602
01603
01604 if (group != it->group) {
01605 continue;
01606 }
01607
01608 if (it->instance && !it->proxy) {
01609 if ( it->instance->getTaskState() <= base::TaskCore::Stopped ) {
01610 if ( it->autosave && !it->configfile.empty()) {
01611 if (it->loadedProperties) {
01612 string file = it->configfile;
01613 PropertyLoader pl(it->instance);
01614 bool ret = pl.save( file, true );
01615 if (!ret) {
01616 log(Error) << "Failed to save properties for component "<< it->instance->getName() <<endlog();
01617 valid = false;
01618 } else {
01619 log(Info) << "Refusing to save property file that was not loaded for "<< it->instance->getName() <<endlog();
01620 }
01621 } else if (it->autosave) {
01622 log(Error) << "AutoSave set but no property file specified. Specify one using the UpdateProperties simple element."<<endlog();
01623 }
01624 } else if (it->autosave) {
01625 log(Error) << "AutoSave set but no property file specified. Specify one using the UpdateProperties simple element."<<endlog();
01626 }
01627 OperationCaller<bool(void)> instancecleanup = it->instance->getOperation("cleanup");
01628 instancecleanup();
01629 log(Info) << "Cleaned up "<< it->instance->getName() <<endlog();
01630 } else {
01631 log(Error) << "Could not cleanup Component "<< it->instance->getName() << " (not Stopped)"<<endlog();
01632 valid = false;
01633 }
01634 }
01635 }
01636 return valid;
01637 }
01638
01639 bool DeploymentComponent::unloadComponents()
01640 {
01641
01642 bool valid = true;
01643 for (int group = nextGroup ; group != -1; --group) {
01644 valid &= unloadComponentsGroup(group);
01645 }
01646 return valid;
01647 }
01648
01649 bool DeploymentComponent::unloadComponentsGroup(const int group)
01650 {
01651 log(Info) << "Unloading group " << group << endlog();
01652
01653 bool valid = true;
01654 CompList::iterator cit = comps.begin();
01655 while ( valid && cit != comps.end())
01656 {
01657 ComponentData* it = &(cit->second);
01658 if (group == it->group)
01659 {
01660
01661 valid &= this->unloadComponentImpl(cit);
01662
01663 cit = comps.begin();
01664 }
01665 else
01666 {
01667 ++cit;
01668 }
01669 }
01670
01671
01672 return valid;
01673 }
01674
01675 void DeploymentComponent::clearConfiguration()
01676 {
01677 log(Info) << "Clearing configuration options."<< endlog();
01678 conmap.clear();
01679 deletePropertyBag( root );
01680 }
01681
01682 bool DeploymentComponent::import(const std::string& package)
01683 {
01684 RTT::Logger::In in("import");
01685 return ComponentLoader::Instance()->import( package, "" );
01686 }
01687
01688 void DeploymentComponent::path(const std::string& path)
01689 {
01690 RTT::Logger::In in("path");
01691 ComponentLoader::Instance()->setComponentPath( ComponentLoader::Instance()->getComponentPath() + path );
01692 PluginLoader::Instance()->setPluginPath( PluginLoader::Instance()->getPluginPath() + path );
01693 }
01694
01695 bool DeploymentComponent::loadLibrary(const std::string& name)
01696 {
01697 RTT::Logger::In in("loadLibrary");
01698 return PluginLoader::Instance()->loadLibrary(name) || ComponentLoader::Instance()->loadLibrary(name);
01699 }
01700
01701 bool DeploymentComponent::reloadLibrary(const std::string& name)
01702 {
01703 RTT::Logger::In in("reloadLibrary");
01704 return ComponentLoader::Instance()->reloadLibrary(name);
01705 }
01706
01707 bool DeploymentComponent::loadService(const std::string& name, const std::string& type) {
01708 TaskContext* peer = 0;
01709 if (name == getName() )
01710 peer = this;
01711 else if ( (peer = getPeer(name)) == 0) {
01712 log(Error)<<"No such peer: "<< name<< ". Can not load service '"<<type<<"'."<<endlog();
01713 return false;
01714 }
01715
01716
01717 if (peer->provides()->hasService(type))
01718 return true;
01719 return PluginLoader::Instance()->loadService(type, peer);
01720 }
01721
01722
01723 bool DeploymentComponent::loadComponent(const std::string& name, const std::string& type)
01724 {
01725 RTT::Logger::In in("loadComponent");
01726
01727 if ( type == "RTT::PropertyBag" )
01728 return false;
01729
01730 if ( this->getPeer(name) || ( comps.find(name) != comps.end() && comps[name].instance != 0) ) {
01731 log(Error) <<"Failed to load component with name "<<name<<": already present as peer or loaded."<<endlog();
01732 return false;
01733 }
01734
01735 TaskContext* instance = ComponentLoader::Instance()->loadComponent(name, type);
01736
01737 if (!instance) {
01738 return false;
01739 }
01740
01741
01742 comps[name].instance = instance;
01743
01744 if (!this->componentLoaded( instance ) ) {
01745 log(Error) << "This deployer type refused to connect to "<< instance->getName() << ": aborting !" << endlog(Error);
01746 comps[name].instance = 0;
01747 ComponentLoader::Instance()->unloadComponent( instance );
01748 return false;
01749 }
01750
01751
01752 this->addPeer( instance );
01753 log(Info) << "Adding "<< instance->getName() << " as new peer: OK."<< endlog(Info);
01754
01755 comps[name].loaded = true;
01756
01757 return true;
01758 }
01759
01764 bool DeploymentComponent::unloadComponentImpl( CompList::iterator cit )
01765 {
01766 bool valid = true;
01767 ComponentData* it = &(cit->second);
01768 std::string name = cit->first;
01769
01770 if ( it->loaded && it->instance ) {
01771 if ( !it->instance->isRunning() ) {
01772 if (!it->proxy ) {
01773
01774 componentUnloaded( it->instance );
01775 log(Debug) << "Disconnecting " <<name <<endlog();
01776 it->instance->disconnect();
01777 log(Debug) << "Terminating " <<name <<endlog();
01778 } else
01779 log(Debug) << "Removing proxy for " <<name <<endlog();
01780
01781
01782 for( ConMap::iterator cmit = conmap.begin(); cmit != conmap.end(); ++cmit) {
01783 size_t n = 0;
01784 while ( n != cmit->second.owners.size() ) {
01785 if (cmit->second.owners[n] == it->instance ) {
01786 cmit->second.owners.erase( cmit->second.owners.begin() + n );
01787 cmit->second.ports.erase( cmit->second.ports.begin() + n );
01788 n = 0;
01789 } else
01790 ++n;
01791 }
01792 }
01793
01794 RTT::Property<RTT::PropertyBag>* pcomp = root.getPropertyType<PropertyBag>(name);
01795 if (pcomp) {
01796 root.removeProperty(pcomp);
01797 }
01798
01799
01800 delete it->act;
01801 it->act = 0;
01802 ComponentLoader::Instance()->unloadComponent( it->instance );
01803 it->instance = 0;
01804 log(Info) << "Disconnected and destroyed "<< name <<endlog();
01805 } else {
01806 log(Error) << "Could not unload Component "<< name <<": still running." <<endlog();
01807 valid=false;
01808 }
01809 }
01810 if (valid) {
01811
01812
01813 comps.erase(cit);
01814 }
01815 return valid;
01816 }
01817
01818 bool DeploymentComponent::unloadComponent(const std::string& name)
01819 {
01820 CompList::iterator it;
01821
01822 if ( comps.count( name ) == 0 || comps[name].loaded == false ) {
01823 log(Error) << "Can't unload component '"<<name<<"': not loaded by "<<this->getName()<<endlog();
01824 return false;
01825 }
01826
01827
01828 it = comps.find(name);
01829
01830 if ( this->unloadComponentImpl( it ) == false )
01831 return false;
01832
01833 log(Info) << "Successfully unloaded component "<<name<<"."<<endlog();
01834 return true;
01835 }
01836
01837 void DeploymentComponent::displayComponentTypes() const
01838 {
01839 FactoryMap::const_iterator it;
01840 cout << "I can create the following component types: " <<endl;
01841 for(it = getFactories().begin(); it != getFactories().end(); ++it) {
01842 cout << " " << it->first << endl;
01843 }
01844 if ( getFactories().size() == 0 )
01845 cout << " (none)"<<endl;
01846 }
01847
01848 std::vector<std::string> DeploymentComponent::getComponentTypes() const
01849 {
01850 std::vector<std::string> s;
01851 FactoryMap::const_iterator it;
01852 for(it = getFactories().begin(); it != getFactories().end(); ++it)
01853 s.push_back(it->first);
01854
01855 return s;
01856 }
01857
01858 bool DeploymentComponent::setActivity(const std::string& comp_name,
01859 double period, int priority,
01860 int scheduler)
01861 {
01862 if ( this->setNamedActivity(comp_name, "Activity", period, priority, scheduler) ) {
01863 assert( comps[comp_name].instance );
01864 assert( comps[comp_name].act );
01865 comps[comp_name].instance->setActivity( comps[comp_name].act );
01866 comps[comp_name].act = 0;
01867 return true;
01868 }
01869 return false;
01870 }
01871
01872 bool DeploymentComponent::setFileDescriptorActivity(const std::string& comp_name,
01873 double timeout, int priority,
01874 int scheduler)
01875 {
01876 if ( this->setNamedActivity(comp_name, "FileDescriptorActivity", timeout, priority, scheduler) ) {
01877 assert( comps[comp_name].instance );
01878 assert( comps[comp_name].act );
01879 comps[comp_name].instance->setActivity( comps[comp_name].act );
01880 comps[comp_name].act = 0;
01881 return true;
01882 }
01883 return false;
01884 }
01885
01886 bool DeploymentComponent::setActivityOnCPU(const std::string& comp_name,
01887 double period, int priority,
01888 int scheduler, unsigned int cpu_nr)
01889 {
01890 unsigned int mask = 0x1 << cpu_nr;
01891 if ( this->setNamedActivity(comp_name, "Activity", period, priority, scheduler, mask) ) {
01892 assert( comps[comp_name].instance );
01893 assert( comps[comp_name].act );
01894 comps[comp_name].instance->setActivity( comps[comp_name].act );
01895 comps[comp_name].act = 0;
01896 return true;
01897 }
01898 return false;
01899 }
01900
01901 bool DeploymentComponent::setPeriodicActivity(const std::string& comp_name,
01902 double period, int priority,
01903 int scheduler)
01904 {
01905 if ( this->setNamedActivity(comp_name, "PeriodicActivity", period, priority, scheduler) ) {
01906 assert( comps[comp_name].instance );
01907 assert( comps[comp_name].act );
01908 comps[comp_name].instance->setActivity( comps[comp_name].act );
01909 comps[comp_name].act = 0;
01910 return true;
01911 }
01912 return false;
01913 }
01914
01915 bool DeploymentComponent::setSlaveActivity(const std::string& comp_name,
01916 double period)
01917 {
01918 if ( this->setNamedActivity(comp_name, "SlaveActivity", period, 0, ORO_SCHED_OTHER ) ) {
01919 assert( comps[comp_name].instance );
01920 assert( comps[comp_name].act );
01921 comps[comp_name].instance->setActivity( comps[comp_name].act );
01922 comps[comp_name].act = 0;
01923 return true;
01924 }
01925 return false;
01926 }
01927
01928 bool DeploymentComponent::setSequentialActivity(const std::string& comp_name)
01929 {
01930 if ( this->setNamedActivity(comp_name, "SequentialActivity", 0, 0, 0 ) ) {
01931 assert( comps[comp_name].instance );
01932 assert( comps[comp_name].act );
01933 comps[comp_name].instance->setActivity( comps[comp_name].act );
01934 comps[comp_name].act = 0;
01935 return true;
01936 }
01937 return false;
01938 }
01939
01940 bool DeploymentComponent::setMasterSlaveActivity(const std::string& master,
01941 const std::string& slave)
01942 {
01943 if ( this->setNamedActivity(slave, "SlaveActivity", 0, 0, ORO_SCHED_OTHER, master ) ) {
01944 assert( comps[slave].instance );
01945 assert( comps[slave].act );
01946 comps[slave].instance->setActivity( comps[slave].act );
01947 comps[slave].act = 0;
01948 return true;
01949 }
01950 return false;
01951 }
01952
01953
01954 bool DeploymentComponent::setNamedActivity(const std::string& comp_name,
01955 const std::string& act_type,
01956 double period, int priority,
01957 int scheduler, const std::string& master_name)
01958 {
01959 return setNamedActivity(comp_name,
01960 act_type,
01961 period,
01962 priority,
01963 scheduler,
01964 ~0,
01965 master_name);
01966 }
01967
01968 bool DeploymentComponent::setNamedActivity(const std::string& comp_name,
01969 const std::string& act_type,
01970 double period, int priority,
01971 int scheduler, unsigned cpu_affinity,
01972 const std::string& master_name)
01973 {
01974
01975
01976 RTT::TaskContext* peer = 0;
01977 base::ActivityInterface* master_act = 0;
01978 if ( comp_name == this->getName() )
01979 peer = this;
01980 else
01981 if ( comps.count(comp_name) )
01982 peer = comps[comp_name].instance;
01983 else
01984 peer = this->getPeer(comp_name);
01985 if (!peer) {
01986 log(Error) << "Can't create Activity: component "<<comp_name<<" not found."<<endlog();
01987 return false;
01988 }
01989 if ( !master_name.empty() ) {
01990 if ( master_name == this->getName() )
01991 master_act = this->engine()->getActivity();
01992 else
01993 if ( comps.count(master_name) && comps[master_name].act )
01994 master_act = comps[master_name].act;
01995 else
01996 master_act = this->getPeer(master_name) ? getPeer(master_name)->engine()->getActivity() : 0;
01997
01998 if ( !this->getPeer(master_name) ) {
01999 log(Error) << "Can't create SlaveActivity: Master component "<<master_name<<" not known as peer."<<endlog();
02000 return false;
02001 }
02002
02003 if (!master_act) {
02004 log(Error) << "Can't create SlaveActivity: Master component "<<master_name<<" has no activity set."<<endlog();
02005 return false;
02006 }
02007 }
02008
02009 comps[comp_name].instance = peer;
02010 if ( peer->isRunning() ) {
02011 log(Error) << "Can't change activity of component "<<comp_name<<" since it is still running."<<endlog();
02012 return false;
02013 }
02014
02015 base::ActivityInterface* newact = 0;
02016
02017 if ( act_type == "Activity")
02018 newact = new RTT::Activity(scheduler, priority, period, cpu_affinity, 0, comp_name);
02019 else
02020
02021 if ( act_type == "PeriodicActivity" && period != 0.0)
02022 newact = new RTT::extras::PeriodicActivity(scheduler, priority, period, cpu_affinity, 0);
02023 else
02024 if ( act_type == "NonPeriodicActivity" && period == 0.0)
02025 newact = new RTT::Activity(scheduler, priority, period, cpu_affinity, 0);
02026 else
02027 if ( act_type == "SlaveActivity" ) {
02028 if ( master_act == 0 )
02029 newact = new extras::SlaveActivity(period);
02030 else {
02031 newact = new extras::SlaveActivity(master_act);
02032 this->getPeer(master_name)->addPeer( peer );
02033 }
02034 }
02035 else
02036 if (act_type == "Activity") {
02037 newact = new Activity(scheduler, priority, period, cpu_affinity, 0, comp_name);
02038 }
02039 else
02040 if (act_type == "SequentialActivity") {
02041 newact = new SequentialActivity();
02042 }
02043 else if ( act_type == "FileDescriptorActivity") {
02044 using namespace RTT::extras;
02045 newact = new FileDescriptorActivity(scheduler, priority, period, cpu_affinity, 0);
02046 FileDescriptorActivity* fdact = dynamic_cast< RTT::extras::FileDescriptorActivity* > (newact);
02047 if (fdact) fdact->setTimeout(period);
02048 else newact = 0;
02049 }
02050 if (newact == 0) {
02051 log(Error) << "Can't create '"<< act_type << "' for component "<<comp_name<<": incorrect arguments."<<endlog();
02052 return false;
02053 }
02054
02055
02056 assert( peer->isRunning() == false );
02057 delete comps[comp_name].act;
02058 comps[comp_name].act = newact;
02059
02060 return true;
02061 }
02062
02063 bool DeploymentComponent::configure(const std::string& name)
02064 {
02065 return configureFromFile( name, name + ".cpf" );
02066 }
02067
02068 bool DeploymentComponent::configureFromFile(const std::string& name, const std::string& filename)
02069 {
02070 RTT::Logger::In in("DeploymentComponent");
02071 RTT::TaskContext* c;
02072 if ( name == this->getName() )
02073 c = this;
02074 else
02075 c = this->getPeer(name);
02076 if (!c) {
02077 log(Error)<<"No such peer to configure: "<<name<<endlog();
02078 return false;
02079 }
02080
02081 marsh::PropertyLoader pl(c);
02082 return pl.configure( filename, true );
02083 }
02084
02085 const FactoryMap& DeploymentComponent::getFactories() const
02086 {
02087 return RTT::ComponentLoader::Instance()->getFactories();
02088 }
02089
02090 void DeploymentComponent::kickOut(const std::string& config_file)
02091 {
02092 RTT::Logger::In in("kickOut");
02093 RTT::PropertyBag from_file;
02094 RTT::Property<std::string> import_file;
02095 std::vector<std::string> deleted_components_type;
02096
02097 marsh::PropertyDemarshaller demarshaller(config_file);
02098 try {
02099 if ( demarshaller.deserialize( from_file ) ){
02100 for (RTT::PropertyBag::iterator it= from_file.begin(); it!=from_file.end();it++) {
02101 if ( (*it)->getName() == "Import" ) continue;
02102 if ( (*it)->getName() == "Include" ) continue;
02103
02104 kickOutComponent( (*it)->getName() );
02105 }
02106 deletePropertyBag( from_file );
02107 }
02108 else {
02109 log(Error)<< "Some error occured while parsing "<< config_file <<endlog();
02110 }
02111 } catch (...)
02112 {
02113 log(Error)<< "Uncaught exception in kickOut() !"<< endlog();
02114 }
02115 }
02116
02117 bool DeploymentComponent::cleanupComponent(RTT::TaskContext *instance)
02118 {
02119 RTT::Logger::In in("cleanupComponent");
02120 bool valid = true;
02121
02122 if (instance) {
02123 if ( instance->getTaskState() <= base::TaskCore::Stopped ) {
02124 OperationCaller<bool(void)> instancecleanup = instance->getOperation("cleanup");
02125 instancecleanup();
02126 log(Info) << "Cleaned up "<< instance->getName() <<endlog();
02127 } else {
02128 log(Error) << "Could not cleanup Component "<< instance->getName() << " (not Stopped)"<<endlog();
02129 valid = false;
02130 }
02131 }
02132 return valid;
02133 }
02134
02135 bool DeploymentComponent::configureComponent(RTT::TaskContext *instance)
02136 {
02137 RTT::Logger::In in("configureComponent");
02138 bool valid = false;
02139
02140 if ( instance ) {
02141 OperationCaller<bool(void)> instanceconfigure = instance->getOperation("configure");
02142 if(instanceconfigure()) {
02143 log(Info) << "Configured " << instance->getName()<<endlog();
02144 valid = true;
02145 }
02146 else {
02147 log(Error) << "Could not configure loaded Component "<< instance->getName() <<endlog();
02148 }
02149 }
02150 return valid;
02151 }
02152
02153 bool DeploymentComponent::startComponent(RTT::TaskContext *instance)
02154 {
02155 RTT::Logger::In in("startComponent");
02156 bool valid = false;
02157
02158 if ( instance ) {
02159 OperationCaller<bool(void)> instancestart = instance->getOperation("start");
02160 if ( instance->isRunning() ||
02161 instancestart() ) {
02162 log(Info) << "Started "<< instance->getName() <<endlog();
02163 valid = true;
02164 }
02165 else {
02166 log(Error) << "Could not start loaded Component "<< instance->getName() <<endlog();
02167 }
02168 }
02169 return valid;
02170 }
02171
02172 bool DeploymentComponent::stopComponent(RTT::TaskContext *instance)
02173 {
02174 RTT::Logger::In in("stopComponent");
02175 bool valid = true;
02176
02177 if ( instance ) {
02178 OperationCaller<bool(void)> instancestop = instance->getOperation("stop");
02179 if ( !instance->isRunning() ||
02180 instancestop() ) {
02181 log(Info) << "Stopped "<< instance->getName() <<endlog();
02182 }
02183 else {
02184 log(Error) << "Could not stop loaded Component "<< instance->getName() <<endlog();
02185 valid = false;
02186 }
02187 }
02188 return valid;
02189 }
02190
02191 bool DeploymentComponent::kickOutComponent(const std::string& comp_name)
02192 {
02193 RTT::Logger::In in("kickOutComponent");
02194
02195 RTT::TaskContext* peer = comps.count(comp_name) ? comps[ comp_name ].instance : 0;
02196
02197 if ( !peer ) {
02198 log(Error) << "Component not loaded by this Deployer: "<< comp_name <<endlog();
02199 return false;
02200 }
02201 stopComponent( peer );
02202 cleanupComponent (peer );
02203 unloadComponent( comp_name);
02204
02205
02206 root.removeProperty( root.find( comp_name ) );
02207
02208 return true;
02209 }
02210
02211 void DeploymentComponent::shutdownDeployment()
02212 {
02213 static const char* PEER="Application";
02214 static const char* NAME="shutdownDeployment";
02215
02216
02217 static const char* WAIT_PROP_NAME="shutdownWait_ms";
02218 static const char* TOTAL_WAIT_PROP_NAME="shutdownTotalWait_ms";
02219
02220
02221 RTT::TaskContext* peer = getPeer(PEER);
02222 if (0 != peer)
02223 {
02224 RTT::OperationCaller<void(void)> ds =
02225 peer->getOperation(NAME);
02226 if (ds.ready())
02227 {
02228 log(Info) << "Shutting down deployment." << endlog();
02229 RTT::SendHandle<void(void)> handle = ds.send();
02230 if (handle.ready())
02231 {
02232
02233
02234
02235 int wait = 50;
02236
02237 int totalWait = 2000;
02238
02239
02240 RTT::Property<int> wait_prop =
02241 this->properties()->getProperty(WAIT_PROP_NAME);
02242 if (wait_prop.ready())
02243 {
02244 int w = wait_prop.rvalue();
02245 if (0 < w)
02246 {
02247 wait = w;
02248 log(Debug) << "Using override value for " << WAIT_PROP_NAME << endlog();
02249 }
02250 else
02251 {
02252 log(Warning) << "Ignoring illegal value for " << WAIT_PROP_NAME << endlog();
02253 }
02254 }
02255 else
02256 {
02257 log(Debug) << "Using default value for " << WAIT_PROP_NAME << endlog();
02258 }
02259
02260 RTT::Property<int> totalWait_prop =
02261 this->properties()->getProperty(TOTAL_WAIT_PROP_NAME);
02262 if (totalWait_prop.ready())
02263 {
02264 int w = totalWait_prop.rvalue();
02265 if (0 < w)
02266 {
02267 totalWait = w;
02268 log(Debug) << "Using override value for " << TOTAL_WAIT_PROP_NAME << endlog();
02269 }
02270
02271 {
02272 log(Warning) << "Ignoring illegal value for " << TOTAL_WAIT_PROP_NAME << endlog();
02273 }
02274 }
02275 else
02276 {
02277 log(Debug) << "Using default value for " << TOTAL_WAIT_PROP_NAME << endlog();
02278 }
02279
02280
02281 if (wait > totalWait)
02282 {
02283 wait = totalWait;
02284 log(Warning) << "Setting wait == totalWait" << endlog();
02285 }
02286
02287 const long int wait_ns = wait * 1000000LL;
02288 TIME_SPEC ts;
02289 ts.tv_sec = wait_ns / 1000000000LL;
02290 ts.tv_nsec = wait_ns % 1000000000LL;
02291
02292
02293 log(Debug) << "Waiting for deployment shutdown to complete ..." << endlog();
02294 int waited = 0;
02295 while ((RTT::SendNotReady == handle.collectIfDone()) &&
02296 (waited < totalWait))
02297 {
02298 (void)rtos_nanosleep(&ts, NULL);
02299 waited += wait;
02300 }
02301 if (waited >= totalWait)
02302 {
02303 log(Error) << "Timed out waiting for deployment shutdown to complete." << endlog();
02304 }
02305 else
02306 {
02307 log(Debug) << "Deployment shutdown completed." << endlog();
02308 }
02309 }
02310 else
02311 {
02312 log(Error) << "Failed to start operation: " << NAME << endlog();
02313 }
02314
02315 }
02316 else
02317 {
02318 log(Info) << "Ignoring missing deployment shutdown function." << endlog();
02319 }
02320 }
02321 else
02322 {
02323 log(Info) << "Ignoring deployment shutdown function due to missing peer." << endlog();
02324 }
02325 }
02326
02327 }