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


ocl
Author(s): OCL Development Team
autogenerated on Mon Sep 14 2015 14:21:46