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


ocl
Author(s): OCL Development Team
autogenerated on Sat Jun 8 2019 18:48:54