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