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