Component unloading patches.

These patches are the improved version of David Faconti's patches
for unloading components. I fine tuned the implementation and
did some renames wrt kickOut* methods.

See the patches for details.

Peter

[PATCH] Applied component-unloading patches from Davide Faconti

---
deployment/DeploymentComponent.cpp | 411 +++++++++++++++++++++++++++---------
deployment/DeploymentComponent.hpp | 80 +++++++-
2 files changed, 389 insertions(+), 102 deletions(-)

diff --git a/deployment/DeploymentComponent.cpp b/deployment/DeploymentComponent.cpp
index 09f8a60..76f9b59 100644
--- a/deployment/DeploymentComponent.cpp
+++ b/deployment/DeploymentComponent.cpp
@@ -52,7 +52,7 @@ namespace OCL
using namespace std;
using namespace RTT;

- std::vector
> DeploymentComponent::LoadedLibs;
+ std::vector< DeploymentComponent::LoadedLib > DeploymentComponent::loadedLibs;

/**
* I'm using a set to speed up lookups.
@@ -137,6 +137,14 @@ namespace OCL
this->methods()->addMethod( RTT::method("kickOut", &DeploymentComponent::kickOut, this),
"Calls stopComponents, cleanupComponents and unloadComponents in a row.");

+ this->methods()->addMethod( RTT::method("kickOutComponent", &DeploymentComponent::kickOutComponent, this),
+ "Calls stopComponents, cleanupComponent and unloadComponent in a row.",
+ "comp_name", "component name");
+
+ this->methods()->addMethod( RTT::method("kickOutFile", &DeploymentComponent::kickOutFile, this),
+ "Calls stopComponents, cleanupComponents and unloadComponents in a row.",
+ "File", "The file which contains the name of the components to kickOut (the same used in loadComponents, if you want).");
+
// Work around compiler ambiguity:
typedef bool(DeploymentComponent::*DCFun)(const std::string&, const std::string&);
DCFun cp = &DeploymentComponent::connectPeers;
@@ -226,7 +234,6 @@ namespace OCL

DeploymentComponent::~DeploymentComponent()
{
- clearConfiguration();
// Should we unload all loaded components here ?
if ( autoUnload.get() ) {
kickOut();
@@ -235,7 +242,7 @@ namespace OCL

bool DeploymentComponent::connectPeers(const std::string& one, const std::string& other)
{
- Logger::In in("DeploymentComponent");
+ Logger::In in("DeploymentComponent::connectPeers");
TaskContext* t1 = this->getPeer(one);
TaskContext* t2 = this->getPeer(other);
if (!t1) {
@@ -251,7 +258,7 @@ namespace OCL

bool DeploymentComponent::addPeer(const std::string& from, const std::string& to)
{
- Logger::In in("DeploymentComponent");
+ Logger::In in("DeploymentComponent::addPeer");
TaskContext* t1 = this->getPeer(from);
TaskContext* t2 = this->getPeer(to);
if (!t1) {
@@ -267,6 +274,7 @@ namespace OCL

bool DeploymentComponent::connectPorts(const std::string& one, const std::string& other)
{
+ Logger::In in("DeploymentComponent::connectPorts");
TaskContext* a, *b;
a = getPeer(one);
b = getPeer(other);
@@ -285,6 +293,7 @@ namespace OCL
bool DeploymentComponent::connectPorts(const std::string& one, const std::string& one_port,
const std::string& other, const std::string& other_port)
{
+ Logger::In in("DeploymentComponent::connectPorts");
TaskContext* a, *b;
a = getPeer(one);
b = getPeer(other);
@@ -445,7 +454,7 @@ namespace OCL
// Check if it is a propertybag.
Property comp = *it;
if ( !comp.ready() ) {
- log(Error)<< "Property '"<< *it <<"' is should be a struct, Include or Import statement." << endlog();
+ log(Error)<< "Property '"<< *it <<"' should be a struct, Include or Import statement." << endlog();
valid = false;
continue;
}
@@ -575,11 +584,27 @@ namespace OCL
valid = false;
}
// store the port
- if (valid) {
+ if (valid){
+ string port_name = ports->get().getProperty(*pit)->get();
+ bool to_add = true;
+ // go through the vector to avoid duplicate items.
+ // NOTE the sizes conmap[port_name].ports.size() and conmap[port_name].owners.size() are supposed to be equal
+ for(unsigned int a=0; a < conmap[port_name].ports.size(); a++)
+ {
+ if( conmap[port_name].ports.at(a) == p && conmap[port_name].owners.at(a) == c)
+ {
+ to_add = false;
+ continue;
+ }
+ }
+
+ if(to_add)
+ {
log(Debug)<<"storing Port: "<getName()<<"."<
getName();
- log(Debug)<<" in " << ports->get().getProperty(*pit)->get() < - conmap[ports->get().getProperty(*pit)->get()].ports.push_back( p );
- conmap[ports->get().getProperty(*pit)->get()].owners.push_back( c );
+ log(Debug)<<" in " << port_name < + conmap[port_name].ports.push_back( p );
+ conmap[port_name].owners.push_back( c );
+ }
}
}
}
@@ -745,7 +770,11 @@ namespace OCL
for (PropertyBag::const_iterator it= peers.rvalue().begin(); it != peers.rvalue().end();it++) {
Property nm = (*it);
if ( nm.ready() )
+ {
this->addPeer( comps[comp.getName()].instance->getName(), nm.value() );
+ log(Debug) << this->getName() << " connects to " <<
+ comps[comp.getName()].instance->getName()<< nm.value() << endlog();
+ }
else {
log(Error) << "Wrong property type in Peers struct. Expected property of type 'string',"
<< " got type "<< (*it)->getType() < @@ -755,35 +784,56 @@ namespace OCL
}

// Create data port connections:
- for(ConMap::iterator it = conmap.begin(); it != conmap.end(); ++it) {
- if ( it->second.ports.size() == 1 ){
- log(Warning) << "Can not form connection "<first<<" with only one Port from "<< it->second.owners[0]<< endlog();
+ for(ConMap::iterator it = conmap.begin(); it != conmap.end(); ++it)
+ {
+ ConnectionData *connection = &(it->second);
+ std::string connection_name = it->first;
+
+ if ( connection->ports.size() == 1 ){
+ log(Warning) << "Can not form connection "<owners[0]<< endlog();
continue;
}
// first find a write and a read port.
// This is quite complex since a 'ReadWritePort' can act as both.
PortInterface* writer = 0, *reader = 0;
- ConnectionData::Ports::iterator p = it->second.ports.begin();
- while (p != it->second.ports.end() && (writer == 0 || reader == 0) ) {
- if ( (*p)->getPortType() == PortInterface::WritePort ) {
+ ConnectionData::Ports::iterator p = connection->ports.begin();
+
+ while (p != connection->ports.end() )
+ {
+ (*p)->getName();
+ ++p;
+ }
+
+ p = connection->ports.begin();
+
+ while (p !=connection->ports.end() && (writer == 0 || reader == 0) )
+ {
+ if ( (*p)->getPortType() == PortInterface::WritePort )
+ {
if (writer && writer->getPortType() == PortInterface::ReadWritePort )
reader = writer;
writer = (*p);
}
- else
- if ( (*p)->getPortType() == PortInterface::ReadPort ) {
+ else{
+ if ( (*p)->getPortType() == PortInterface::ReadPort )
+ {
if (reader && reader->getPortType() == PortInterface::ReadWritePort )
writer = reader;
reader = (*p);
}
- else
+ else{
if ( (*p)->getPortType() == PortInterface::ReadWritePort )
- if (writer == 0) {
+ {
+ if (writer == 0)
+ {
writer = (*p);
}
else {
reader = (*p);
}
+ }
+ }
+ }
++p;
}
// Inform the user of non-optimal connections:
@@ -796,25 +846,29 @@ namespace OCL
log(Warning) << "Connecting only write-ports in connection " << it->first << endlog();
}
// Inform user which component initiates the connection:
- p = it->second.ports.begin();
+ p = connection->ports.begin();
while ( *p != writer ) ++p;
- std::string owner = it->second.owners[p - it->second.ports.begin()]->getName();
- log(Info) << "Creating Connection "<first<<" starting from TaskContext "<< owner <<":" < + std::string owner = connection->owners[p - connection->ports.begin()]->getName();
+ log(Info) << "Creating Connection "<< connection_name <<" starting from TaskContext "<< owner <<":" < // connect all ports to connection
- p = it->second.ports.begin();
- while (p != it->second.ports.end() ) {
+ p = connection->ports.begin();
+
+ while (p != connection->ports.end() )
+ {
// connect all readers to the first found writer.
- if ( *p != writer ) {
- owner = it->second.owners[p - it->second.ports.begin()]->getName();
- if ( (*p)->connectTo( writer ) == false) {
- log(Error) << "Could not connect Port "<< owner<<"."<< (*p)->getName() << " to connection " <first< + if ( *p != writer )
+ {
+ owner = connection->owners[p - connection->ports.begin()]->getName();
+ if ( (*p)->connectTo( writer ) == false)
+ {
+ log(Error) << "Could not connect Port "<< owner<<"."<< (*p)->getName() << " to connection " << connection_name < if ((*p)->connected())
log(Error) << "Port "<< owner<<"."<< (*p)->getName() << " already connected !"< else
log(Error) << "Port "<< owner<<"."<< (*p)->getName() << " has wrong type !"< valid = false;
} else
- log(Info) << "Connected Port "<< owner<<"."<< (*p)->getName() <<" to connection " << it->first < + log(Info) << "Connected Port "<< owner<<"."<< (*p)->getName() <<" to connection " << connection_name < }
++p;
}
@@ -895,9 +949,16 @@ namespace OCL

// AutoConf
if (comps[comp.getName()].autoconf )
+ {
+ if( !peer->isConfigured() || !peer->isRunning() )
+ {
if ( peer->configure() == false)
valid = false;
}
+ else
+ log(Warning) << "Apparently component "<< peer->getName()<< " don't need to be configured." < + }
+ }

// Finally, report success/failure:
if (!valid) {
@@ -955,6 +1016,7 @@ namespace OCL
for ( CompList::iterator cit = comps.begin(); cit != comps.end(); ++cit) {
ComponentData* it = &(cit->second);
if ( it->instance && !it->proxy )
+ {
if ( it->instance->engine()->getActivity() == 0 ||
it->instance->engine()->getActivity()->isActive() == false ||
it->instance->stop() ) {
@@ -964,6 +1026,7 @@ namespace OCL
valid = false;
}
}
+ }
return valid;
}

@@ -975,6 +1038,7 @@ namespace OCL
for ( CompList::iterator cit = comps.begin(); cit != comps.end(); ++cit) {
ComponentData* it = &(cit->second);
if (it->instance && !it->proxy)
+ {
if ( it->instance->getTaskState() <= TaskCore::Stopped ) {
it->instance->cleanup();
log(Info) << "Cleaned up "<< it->instance->getName() < @@ -983,6 +1047,7 @@ namespace OCL
valid = false;
}
}
+ }
return valid;
}

@@ -990,46 +1055,10 @@ namespace OCL
{
// 2. Disconnect and destroy all components.
bool valid = true;
- for ( CompList::iterator cit = comps.begin(); cit != comps.end(); ++cit) {
- ComponentData* it = &(cit->second);
-
- if ( it->loaded && it->instance ) {
- if ( it->instance->engine()->getActivity() == 0 ||
- it->instance->engine()->getActivity()->isActive() == false ) {
- std::string name = cit->first;
- if (!it->proxy ) {
- log(Debug) << "Disconnecting " < - it->instance->disconnect();
- log(Debug) << "Terminating " < - } else
- log(Debug) << "Removing proxy for " < - // delete the activity before the TC !
- delete it->act;
- it->act = 0;
- delete it->instance;
- it->instance = 0;
- log(Info) << "Disconnected and destroyed "<< name < - } else {
- log(Error) << "Could not unload Component "<< cit->first < - valid = false;
- }
- }
- }
- if ( !comps.empty() ) {
- // cleanup from ComponentData map:
+ while ( comps.size() > 0)
+ {
CompList::iterator cit = comps.begin();
- do {
- ComponentData* it = &(cit->second);
- // if deleted and loaded by us:
- if (it->instance == 0 && it->loaded) {
- log(Info) << "Completely removed "<< cit->first < - comps.erase(cit);
- cit = comps.begin();
- } else {
- log(Info) << "Keeping info on "<< cit->first < - ++cit;
- }
- } while ( cit != comps.end() );
+ valid &= this->unloadComponentImpl(cit);
}
return valid;
}
@@ -1076,6 +1105,7 @@ namespace OCL
while(i != n) {
std::string name = namelist[i]->d_name;
if (name != "." && name != ".." )
+ {
if (namelist[i]->d_type == DT_DIR) { //ignoring symlinks and subdirs here.
import( path +"/" +name );
} else {
@@ -1090,6 +1120,7 @@ namespace OCL
loadLibrary( path + "/" + name );
}
}
+ }
free(namelist[i]);
++i;
}
@@ -1133,14 +1164,47 @@ namespace OCL
// finally:
libname = libname.substr(0, libname.find(".so") );

- for(vector
>::iterator it = LoadedLibs.begin(); it != LoadedLibs.end(); ++it){
- if ( it->first == libname ) {
- log(Info) <<"Library "<< libname <<" already loaded."< - handle = it->second;
- return true;
+ // check if the library is already loaded
+ // NOTE if this library has been loaded, you can unload and reload it to apply changes (may be you have updated the dynamic library)
+ // anyway it is safe to do this only if thereisn't any istance whom type was loaded from this library
+
+ std::vector::iterator lib = loadedLibs.begin();
+ while (lib != loadedLibs.end())
+ {
+ // there is already a library with the same name
+ if ( lib->name == libname)
+ {
+ log(Warning) <<"Library "<< libname <<".so already loaded. " ;
+
+ bool can_unload = true;
+ CompList::iterator cit;
+ for( std::vector::iterator ctype = lib->components_type.begin(); ctype != lib->components_type.end() && can_unload; ++ctype)
+ {
+ for ( cit = comps.begin(); cit != comps.end(); ++cit)
+ {
+ if( (*ctype) == cit->second.type )
+ {
+ // the type of an allocated component was loaded from this library. it might be unsafe to reload the library
+ log(Warning) << "Can NOT reload because of the instance " << cit->second.type <<"::"<second.instance->getName() < + can_unload = false;
+ }
+ }
+ }
+ if( can_unload )
+ {
+ log(Warning) << "Try to RELOAD"< + dlclose(lib->handle);
+ // remove the library info from the vector
+ std::vector::iterator lib_un = lib;
+ loadedLibs.erase(lib_un);
+ lib = loadedLibs.end();
+ }
+ else return true;
}
+ else lib++;
}

+
std::vector errors;
// try form "liborocos-helloworld-gnulinux.so"
handle = dlopen ( so_name.c_str(), RTLD_NOW | RTLD_GLOBAL );
@@ -1215,8 +1279,8 @@ namespace OCL
return false;
}

- LoadedLibs.push_back(make_pair(libname,handle));
- log(Debug) <<"Storing "<< libname < + //------------- if you get here, the library has been loaded -------------
+ LoadedLib loading_lib(libname,handle);
dlerror(); /* Clear any existing error */

// Lookup Component factories:
@@ -1259,8 +1323,11 @@ namespace OCL
}
ComponentFactories::Instance()[ cname ] = factory;
log(Info) << "Loaded component type '"<< cname <<"'"< + loading_lib.components_type.push_back( cname );
+
} else {
log(Info) << "Loaded single component library '"<< libname <<"'"< + loading_lib.components_type.push_back( libname );
}
is_component = true;
} else {
@@ -1293,7 +1360,7 @@ namespace OCL
if ( success )
log(Info) << "Loaded RTT Plugin '"<< plugname <<"'"< else {
- log(Error) << "Failed to load RTT Plutin '" <
+ log(Error) << "Failed to load RTT Plugin '" < return false;
}
return true;
@@ -1301,6 +1368,10 @@ namespace OCL
log(Debug) << error << endlog();
}

+ loadedLibs.push_back( loading_lib );
+ log(Info) <<"Storing "<< loading_lib.name < + dlerror(); /* Clear any existing error */
+

// plain library
if (is_component == false)
@@ -1377,42 +1448,85 @@ namespace OCL
this->addPeer( comps[name].instance );
log(Info) << "Adding "<< comps[name].instance->getName() << " as new peer: OK."<< endlog(Info);
comps[name].loaded = true;
+ comps[name].type = type;
return true;
}

+ /**
+ * This method removes all references to the component hold in \a cit,
+ * on the condition that it is not running.
+ * When this method returns true, you need to remove \a cit yourself from
+ * the this->conmap.
+ */
+ bool DeploymentComponent::unloadComponentImpl( CompList::iterator cit )
+ {
+ bool valid = true;
+ ComponentData* it = &(cit->second);
+ std::string name = cit->first;
+
+ if ( it->loaded && it->instance ) {
+ if ( it->instance->engine()->getActivity() == 0 ||
+ it->instance->engine()->getActivity()->isActive() == false ) {
+ if (!it->proxy ) {
+ log(Debug) << "Disconnecting " < + it->instance->disconnect();
+ log(Debug) << "Terminating " < + } else
+ log(Debug) << "Removing proxy for " < +
+ // Lookup and erase port+owner from conmap.
+ for( ConMap::iterator cmit = conmap.begin(); cmit != conmap.end(); ++cmit) {
+ size_t n = 0;
+ while ( n != cmit->second.owners.size() ) {
+ if (cmit->second.owners[n] == it->instance ) {
+ cmit->second.owners.erase( cmit->second.owners.begin() + n );
+ cmit->second.ports.erase( cmit->second.ports.begin() + n );
+ n = 0;
+ } else
+ ++n;
+ }
+ }
+ // Lookup in the property configuration and remove:
+ Property* pcomp = root.getProperty(name);
+ if (pcomp) {
+ root.remove(pcomp);
+ deletePropertyBag( pcomp->value() );
+ delete pcomp;
+ }
+
+ // Finally, delete the activity before the TC !
+ delete it->act;
+ it->act = 0;
+ delete it->instance;
+ it->instance = 0;
+ // NOTE there is no reason to keep the ComponentData in the vector.
+ // actually it may cause errors if we try to re-load the Component later.
+ comps.erase(cit);
+
+ log(Info) << "Disconnected and destroyed "<< name < + } else {
+ log(Error) << "Could not unload Component "<< name <<": still running." < + valid = false;
+ }
+ }
+ return valid;
+ }

bool DeploymentComponent::unloadComponent(const std::string& name)
{
- std::string regname = name;
- TaskContext* peer = this->getPeer(name);
- if (peer) {
- for(CompList::iterator it = comps.begin(); it != comps.end(); ++it)
- if (it->second.instance == peer) {
- regname = it->first;
- break;
- }
- } else {
+ CompList::iterator it;
// no such peer: try looking for the map name
if ( comps.count( name ) == 0 || comps[name].loaded == false ) {
log(Error) << "Can't unload component '"< getName()< return false;
}
- // regname and name are equal.
- peer = comps[name].instance;
- }

- assert(peer);
- if ( peer->isRunning() ) {
- log(Error) << "Can't unload component "< + // Ok. Go on with loaded component.
+ it = comps.find(name);
+
+ if ( this->unloadComponentImpl( it ) == false )
return false;
- }
- try {
- peer->disconnect(); // if it is no longer a peer of this, that's ok.
- } catch(...) {
- log(Warning) << "Disconnecting caused exception." < - }
- delete peer;
- comps.erase(regname);
+
log(Info) << "Successfully unloaded component "< return true;
}
@@ -1577,4 +1691,103 @@ namespace OCL
{
return ComponentFactories::Instance();
}
+
+ void DeploymentComponent::kickOutFile(const std::string& config_file)
+ {
+ Logger::In in("DeploymentComponent::kickOutFile");
+ PropertyBag from_file;
+ Property import_file;
+ std::vector deleted_components_type;
+
+ // demarshalling failures:
+ bool failure = false;
+
+ PropertyDemarshaller demarshaller(config_file);
+ try {
+ if ( demarshaller.deserialize( from_file ) ){
+ for (PropertyBag::iterator it= from_file.begin(); it!=from_file.end();it++)
+ {
+ if ( (*it)->getName() == "Import" ) continue;
+ if ( (*it)->getName() == "Include" ) continue;
+
+ kickOutComponent( (*it)->getName() );
+ }
+ deletePropertyBag( from_file );
+ }
+ else
+ {
+ log(Error)<< "Some error occured while parsing "<< config_file < + failure = true;
+ }
+ } catch (...)
+ {
+ log(Error)<< "Uncaught exception in loadcomponents() !"<< endlog();
+ failure = true;
+ }
+ }
+
+ bool DeploymentComponent::cleanupComponent(RTT::TaskContext *instance)
+ {
+ Logger::In in("DeploymentComponent::cleanupComponent");
+ bool valid = true;
+ // 1. Cleanup a single activities, give components chance to cleanup.
+ if (instance)
+ {
+ if ( instance->getTaskState() <= TaskCore::Stopped )
+ {
+ instance->cleanup();
+ log(Info) << "Cleaned up "<< instance->getName() < + } else {
+ log(Error) << "Could not cleanup Component "<< instance->getName() << " (not Stopped)"< + valid = false;
+ }
+ }
+ return valid;
+ }
+
+ bool DeploymentComponent::stopComponent(RTT::TaskContext *instance)
+ {
+ Logger::In in("DeploymentComponent::stopComponent");
+ bool valid = true;
+
+ if ( instance )
+ {
+ if ( instance->engine()->getActivity() == 0 ||
+ instance->engine()->getActivity()->isActive() == false ||
+ instance->stop() )
+ {
+ log(Info) << "Stopped "<< instance->getName() < + }
+ else {
+ log(Error) << "Could not stop loaded Component "<< instance->getName() < + valid = false;
+ }
+ }
+ return valid;
+ }
+
+ bool DeploymentComponent::kickOutComponent(const std::string& comp_name)
+ {
+ Logger::In in("DeploymentComponent::kickOutComponent");
+ PropertyBase *it = root.find( comp_name );
+ if(!it)
+ {
+ log(Error) << "Peer "<< comp_name << " not found in PropertyBag root"<< endlog();
+ return false;
+ }
+
+ TaskContext* peer = comps[ comp_name ].instance;
+
+ if ( !peer )
+ {
+ log(Error) << "Peer not found: "<< comp_name < + return false;
+ }
+ stopComponent( peer );
+ cleanupComponent (peer );
+ unloadComponent( comp_name);
+ root.removeProperty( root.find( comp_name ) );
+
+ return true;
+ }
}
diff --git a/deployment/DeploymentComponent.hpp b/deployment/DeploymentComponent.hpp
index 4b9861c..52b3a78 100644
--- a/deployment/DeploymentComponent.hpp
+++ b/deployment/DeploymentComponent.hpp
@@ -38,6 +38,7 @@
#include
#include
#include
+#include

namespace OCL
{
@@ -76,7 +77,7 @@ namespace OCL
: instance(0), act(0), loaded(false),
autostart(false), autoconf(false),
autoconnect(false), proxy(false), server(false),
- use_naming(true)
+ use_naming(true),type("")
{}
/**
* The component instance. This is always a valid pointer.
@@ -95,6 +96,7 @@ namespace OCL
bool loaded;
bool autostart, autoconf, autoconnect;
bool proxy, server, use_naming;
+ std::string type;
};

/**
@@ -123,14 +125,28 @@ namespace OCL
* Keep a list of all loaded libraries such that double
* loads are avoided during import/loadLibrary.
*/
- static std::vector > LoadedLibs;
+ class LoadedLib{
+ public:
+ LoadedLib(std::string n, void* h)
+ {
+ name = n;
+ handle = h;
+ }
+ std::string name;
+ void* handle;
+ std::vector components_type;
+ };
+
+ static std::vector< LoadedLib > loadedLibs;
+
+

/**
* Handle of last loaded library.
*/
void* handle;
/**
- * Name of last loaded libarary.
+ * Name of last loaded library.
*/
std::string libname;

@@ -140,6 +156,15 @@ namespace OCL
bool configureHook();

/**
+ * This method removes all references to the component hold in \a cit,
+ * on the condition that it is not running.
+ * When this method returns true, you need to remove \a cit yourself from
+ * the this->conmap.
+ */
+ bool unloadComponentImpl( CompList::iterator cit );
+
+
+ /**
* Hook function for subclasses. Allows a subclass
* to abort or extend the loading of a component.
* By default, this function returns true.
@@ -152,6 +177,8 @@ namespace OCL

~DeploymentComponent();

+ TaskContext* myGetPeer(std::string name) {return comps[ name ].instance; }
+
/**
* Establish a bidirectional connection between two tasks.
*
@@ -455,6 +482,53 @@ namespace OCL
* for the DeploymentComponent.
*/
FactoryMap& getFactories();
+
+ /**
+ * Stop a single loaded and running component.
+ * @param instance instance pointer of the component.
+ * @return true if successfully stopped.
+ */
+ bool stopComponent(RTT::TaskContext *instance);
+
+ /**
+ * Stop a single loaded and running components.
+ * @param comp_name name of the component.
+ * @return true if successfully stopped
+ */
+ bool stopComponent(const std::string& comp_name)
+ {
+ return this->stopComponent( this->getPeer(comp_name) );
+ }
+
+ /**
+ * Cleanup a single loaded and not running component.
+ * @param instance instance pointer of the component.
+ * @return true if successfully cleaned up
+ */
+ bool cleanupComponent(RTT::TaskContext *instance);
+
+ /**
+ * Cleanup a single loaded and not running component.
+ * @param comp_name name of the component.
+ * @return true if successfully cleaned up
+ */
+ bool cleanupComponent(const std::string& comp_name)
+ {
+ return this->cleanupComponent( this->getPeer(comp_name) );
+ }
+
+ /**
+ * Stop, cleanup and unload a single component which were loaded by this component.
+ * @param comp_name name of the component.
+ * @return true if successfully stopped, cleaned and unloaded
+ */
+ bool kickOutComponent(const std::string& comp_name);
+
+ /**
+ * Identical to \a kickOut, but it read the name of the Components to kickOut from a XML file
+ * @param config_file name of an XML file (probably the same used by loadComponents() ).
+ */
+ void kickOutFile(const std::string& config_file);
};

[PATCH] Reformated the patch by D.Faconti. Made the minor change

---
deployment/DeploymentComponent.cpp | 437 +++++++++++++++++-------------------
deployment/DeploymentComponent.hpp | 142 ++++++------
2 files changed, 274 insertions(+), 305 deletions(-)

diff --git a/deployment/DeploymentComponent.cpp b/deployment/DeploymentComponent.cpp
index 76f9b59..7f491d4 100644
--- a/deployment/DeploymentComponent.cpp
+++ b/deployment/DeploymentComponent.cpp
@@ -137,14 +137,13 @@ namespace OCL
this->methods()->addMethod( RTT::method("kickOut", &DeploymentComponent::kickOut, this),
"Calls stopComponents, cleanupComponents and unloadComponents in a row.");

- this->methods()->addMethod( RTT::method("kickOutComponent", &DeploymentComponent::kickOutComponent, this),
- "Calls stopComponents, cleanupComponent and unloadComponent in a row.",
- "comp_name", "component name");
-
- this->methods()->addMethod( RTT::method("kickOutFile", &DeploymentComponent::kickOutFile, this),
- "Calls stopComponents, cleanupComponents and unloadComponents in a row.",
- "File", "The file which contains the name of the components to kickOut (the same used in loadComponents, if you want).");
-
+ this->methods()->addMethod( RTT::method("kickOutComponent", &DeploymentComponent::kickOutComponent, this),
+ "Calls stopComponents, cleanupComponent and unloadComponent in a row.",
+ "comp_name", "component name");
+ this->methods()->addMethod( RTT::method("kickOutFile", &DeploymentComponent::kickOutFile, this),
+ "Calls stopComponents, cleanupComponents and unloadComponents in a row.",
+ "File", "The file which contains the name of the components to kickOut (the same used in loadComponents, if you want).");
+
// Work around compiler ambiguity:
typedef bool(DeploymentComponent::*DCFun)(const std::string&, const std::string&);
DCFun cp = &DeploymentComponent::connectPeers;
@@ -585,26 +584,26 @@ namespace OCL
}
// store the port
if (valid){
- string port_name = ports->get().getProperty(*pit)->get();
- bool to_add = true;
- // go through the vector to avoid duplicate items.
- // NOTE the sizes conmap[port_name].ports.size() and conmap[port_name].owners.size() are supposed to be equal
- for(unsigned int a=0; a < conmap[port_name].ports.size(); a++)
- {
- if( conmap[port_name].ports.at(a) == p && conmap[port_name].owners.at(a) == c)
- {
- to_add = false;
- continue;
- }
- }
-
- if(to_add)
- {
- log(Debug)<<"storing Port: "<getName()<<"."<
getName();
- log(Debug)<<" in " << port_name < - conmap[port_name].ports.push_back( p );
- conmap[port_name].owners.push_back( c );
- }
+ string port_name = ports->get().getProperty(*pit)->get();
+ bool to_add = true;
+ // go through the vector to avoid duplicate items.
+ // NOTE the sizes conmap[port_name].ports.size() and conmap[port_name].owners.size() are supposed to be equal
+ for(unsigned int a=0; a < conmap[port_name].ports.size(); a++)
+ {
+ if( conmap[port_name].ports.at(a) == p && conmap[port_name].owners.at(a) == c)
+ {
+ to_add = false;
+ continue;
+ }
+ }
+
+ if(to_add)
+ {
+ log(Debug)<<"storing Port: "<getName()<<"."<
getName();
+ log(Debug)<<" in " << port_name < + conmap[port_name].ports.push_back( p );
+ conmap[port_name].owners.push_back( c );
+ }
}
}
}
@@ -770,11 +769,11 @@ namespace OCL
for (PropertyBag::const_iterator it= peers.rvalue().begin(); it != peers.rvalue().end();it++) {
Property nm = (*it);
if ( nm.ready() )
- {
- this->addPeer( comps[comp.getName()].instance->getName(), nm.value() );
- log(Debug) << this->getName() << " connects to " <<
- comps[comp.getName()].instance->getName()<< nm.value() << endlog();
- }
+ {
+ this->addPeer( comps[comp.getName()].instance->getName(), nm.value() );
+ log(Debug) << this->getName() << " connects to " <<
+ comps[comp.getName()].instance->getName()<< nm.value() << endlog();
+ }
else {
log(Error) << "Wrong property type in Peers struct. Expected property of type 'string',"
<< " got type "<< (*it)->getType() < @@ -784,56 +783,46 @@ namespace OCL
}

// Create data port connections:
- for(ConMap::iterator it = conmap.begin(); it != conmap.end(); ++it)
- {
- ConnectionData *connection = &(it->second);
- std::string connection_name = it->first;
+ for(ConMap::iterator it = conmap.begin(); it != conmap.end(); ++it) {
+ ConnectionData *connection = &(it->second);
+ std::string connection_name = it->first;

- if ( connection->ports.size() == 1 ){
- log(Warning) << "Can not form connection "<owners[0]<< endlog();
+ if ( connection->ports.size() == 1 ){
+ log(Warning) << "Can not form connection "<owners[0]<< endlog();
continue;
}
// first find a write and a read port.
// This is quite complex since a 'ReadWritePort' can act as both.
PortInterface* writer = 0, *reader = 0;
- ConnectionData::Ports::iterator p = connection->ports.begin();
+ ConnectionData::Ports::iterator p = connection->ports.begin();

- while (p != connection->ports.end() )
- {
- (*p)->getName();
- ++p;
- }
-
- p = connection->ports.begin();
-
- while (p !=connection->ports.end() && (writer == 0 || reader == 0) )
- {
+ while (p !=connection->ports.end() && (writer == 0 || reader == 0) ) {
if ( (*p)->getPortType() == PortInterface::WritePort )
- {
- if (writer && writer->getPortType() == PortInterface::ReadWritePort )
- reader = writer;
- writer = (*p);
- }
- else{
- if ( (*p)->getPortType() == PortInterface::ReadPort )
- {
- if (reader && reader->getPortType() == PortInterface::ReadWritePort )
- writer = reader;
- reader = (*p);
+ {
+ if (writer && writer->getPortType() == PortInterface::ReadWritePort )
+ reader = writer;
+ writer = (*p);
}
+ else{
+ if ( (*p)->getPortType() == PortInterface::ReadPort )
+ {
+ if (reader && reader->getPortType() == PortInterface::ReadWritePort )
+ writer = reader;
+ reader = (*p);
+ }
else{
if ( (*p)->getPortType() == PortInterface::ReadWritePort )
- {
- if (writer == 0)
- {
- writer = (*p);
- }
- else {
- reader = (*p);
+ {
+ if (writer == 0)
+ {
+ writer = (*p);
+ }
+ else {
+ reader = (*p);
+ }
}
- }
- }
- }
+ }
+ }
++p;
}
// Inform the user of non-optimal connections:
@@ -846,30 +835,29 @@ namespace OCL
log(Warning) << "Connecting only write-ports in connection " << it->first << endlog();
}
// Inform user which component initiates the connection:
- p = connection->ports.begin();
+ p = connection->ports.begin();
while ( *p != writer ) ++p;
- std::string owner = connection->owners[p - connection->ports.begin()]->getName();
- log(Info) << "Creating Connection "<< connection_name <<" starting from TaskContext "<< owner <<":" < + std::string owner = connection->owners[p - connection->ports.begin()]->getName();
+ log(Info) << "Creating Connection "<< connection_name <<" starting from TaskContext "<< owner <<":" < // connect all ports to connection
- p = connection->ports.begin();
+ p = connection->ports.begin();

- while (p != connection->ports.end() )
- {
+ while (p != connection->ports.end() ) {
// connect all readers to the first found writer.
if ( *p != writer )
- {
- owner = connection->owners[p - connection->ports.begin()]->getName();
- if ( (*p)->connectTo( writer ) == false)
- {
- log(Error) << "Could not connect Port "<< owner<<"."<< (*p)->getName() << " to connection " << connection_name < - if ((*p)->connected())
- log(Error) << "Port "<< owner<<"."<< (*p)->getName() << " already connected !"< - else
- log(Error) << "Port "<< owner<<"."<< (*p)->getName() << " has wrong type !"< - valid = false;
- } else
- log(Info) << "Connected Port "<< owner<<"."<< (*p)->getName() <<" to connection " << connection_name < - }
+ {
+ owner = connection->owners[p - connection->ports.begin()]->getName();
+ if ( (*p)->connectTo( writer ) == false)
+ {
+ log(Error) << "Could not connect Port "<< owner<<"."<< (*p)->getName() << " to connection " << connection_name < + if ((*p)->connected())
+ log(Error) << "Port "<< owner<<"."<< (*p)->getName() << " already connected !"< + else
+ log(Error) << "Port "<< owner<<"."<< (*p)->getName() << " has wrong type !"< + valid = false;
+ } else
+ log(Info) << "Connected Port "<< owner<<"."<< (*p)->getName() <<" to connection " << connection_name < + }
++p;
}
}
@@ -949,15 +937,15 @@ namespace OCL

// AutoConf
if (comps[comp.getName()].autoconf )
- {
- if( !peer->isConfigured() || !peer->isRunning() )
- {
- if ( peer->configure() == false)
- valid = false;
- }
- else
- log(Warning) << "Apparently component "<< peer->getName()<< " don't need to be configured." < - }
+ {
+ if( !peer->isActive() )
+ {
+ if ( peer->configure() == false)
+ valid = false;
+ }
+ else
+ log(Warning) << "Apparently component "<< peer->getName()<< " don't need to be configured." < + }
}

// Finally, report success/failure:
@@ -1015,8 +1003,7 @@ namespace OCL
// 1. Stop all activities, give components chance to cleanup.
for ( CompList::iterator cit = comps.begin(); cit != comps.end(); ++cit) {
ComponentData* it = &(cit->second);
- if ( it->instance && !it->proxy )
- {
+ if ( it->instance && !it->proxy ) {
if ( it->instance->engine()->getActivity() == 0 ||
it->instance->engine()->getActivity()->isActive() == false ||
it->instance->stop() ) {
@@ -1025,7 +1012,7 @@ namespace OCL
log(Error) << "Could not stop loaded Component "<< it->instance->getName() < valid = false;
}
- }
+ }
}
return valid;
}
@@ -1037,8 +1024,7 @@ namespace OCL
// 1. Cleanup all activities, give components chance to cleanup.
for ( CompList::iterator cit = comps.begin(); cit != comps.end(); ++cit) {
ComponentData* it = &(cit->second);
- if (it->instance && !it->proxy)
- {
+ if (it->instance && !it->proxy) {
if ( it->instance->getTaskState() <= TaskCore::Stopped ) {
it->instance->cleanup();
log(Info) << "Cleaned up "<< it->instance->getName() < @@ -1046,7 +1032,7 @@ namespace OCL
log(Error) << "Could not cleanup Component "<< it->instance->getName() << " (not Stopped)"< valid = false;
}
- }
+ }
}
return valid;
}
@@ -1055,11 +1041,11 @@ namespace OCL
{
// 2. Disconnect and destroy all components.
bool valid = true;
- while ( comps.size() > 0)
- {
- CompList::iterator cit = comps.begin();
- valid &= this->unloadComponentImpl(cit);
- }
+ while ( comps.size() > 0)
+ {
+ CompList::iterator cit = comps.begin();
+ valid &= this->unloadComponentImpl(cit);
+ }
return valid;
}

@@ -1104,8 +1090,7 @@ namespace OCL
int i = 0;
while(i != n) {
std::string name = namelist[i]->d_name;
- if (name != "." && name != ".." )
- {
+ if (name != "." && name != ".." ) {
if (namelist[i]->d_type == DT_DIR) { //ignoring symlinks and subdirs here.
import( path +"/" +name );
} else {
@@ -1120,7 +1105,7 @@ namespace OCL
loadLibrary( path + "/" + name );
}
}
- }
+ }
free(namelist[i]);
++i;
}
@@ -1164,44 +1149,38 @@ namespace OCL
// finally:
libname = libname.substr(0, libname.find(".so") );

- // check if the library is already loaded
- // NOTE if this library has been loaded, you can unload and reload it to apply changes (may be you have updated the dynamic library)
- // anyway it is safe to do this only if thereisn't any istance whom type was loaded from this library
+ // check if the library is already loaded
+ // NOTE if this library has been loaded, you can unload and reload it to apply changes (may be you have updated the dynamic library)
+ // anyway it is safe to do this only if thereisn't any istance whom type was loaded from this library

- std::vector::iterator lib = loadedLibs.begin();
- while (lib != loadedLibs.end())
- {
- // there is already a library with the same name
- if ( lib->name == libname)
- {
- log(Warning) <<"Library "<< libname <<".so already loaded. " ;
+ std::vector::iterator lib = loadedLibs.begin();
+ while (lib != loadedLibs.end()) {
+ // there is already a library with the same name
+ if ( lib->name == libname) {
+ log(Warning) <<"Library "<< libname <<".so already loaded. " ;

- bool can_unload = true;
- CompList::iterator cit;
- for( std::vector::iterator ctype = lib->components_type.begin(); ctype != lib->components_type.end() && can_unload; ++ctype)
- {
- for ( cit = comps.begin(); cit != comps.end(); ++cit)
- {
- if( (*ctype) == cit->second.type )
- {
- // the type of an allocated component was loaded from this library. it might be unsafe to reload the library
- log(Warning) << "Can NOT reload because of the instance " << cit->second.type <<"::"<second.instance->getName() < - can_unload = false;
- }
- }
- }
- if( can_unload )
- {
- log(Warning) << "Try to RELOAD"< - dlclose(lib->handle);
- // remove the library info from the vector
- std::vector::iterator lib_un = lib;
- loadedLibs.erase(lib_un);
- lib = loadedLibs.end();
- }
- else return true;
+ bool can_unload = true;
+ CompList::iterator cit;
+ for( std::vector::iterator ctype = lib->components_type.begin(); ctype != lib->components_type.end() && can_unload; ++ctype) {
+ for ( cit = comps.begin(); cit != comps.end(); ++cit) {
+ if( (*ctype) == cit->second.type ) {
+ // the type of an allocated component was loaded from this library. it might be unsafe to reload the library
+ log(Warning) << "Can NOT reload because of the instance " << cit->second.type <<"::"<second.instance->getName() < + can_unload = false;
+ }
+ }
+ }
+ if( can_unload ) {
+ log(Warning) << "Try to RELOAD"< + dlclose(lib->handle);
+ // remove the library info from the vector
+ std::vector::iterator lib_un = lib;
+ loadedLibs.erase(lib_un);
+ lib = loadedLibs.end();
+ }
+ else return true;
}
- else lib++;
+ else lib++;
}

@@ -1279,8 +1258,8 @@ namespace OCL
return false;
}

- //------------- if you get here, the library has been loaded -------------
- LoadedLib loading_lib(libname,handle);
+ //------------- if you get here, the library has been loaded -------------
+ LoadedLib loading_lib(libname,handle);
dlerror(); /* Clear any existing error */

// Lookup Component factories:
@@ -1323,11 +1302,11 @@ namespace OCL
}
ComponentFactories::Instance()[ cname ] = factory;
log(Info) << "Loaded component type '"<< cname <<"'"< - loading_lib.components_type.push_back( cname );
+ loading_lib.components_type.push_back( cname );

} else {
log(Info) << "Loaded single component library '"<< libname <<"'"< - loading_lib.components_type.push_back( libname );
+ loading_lib.components_type.push_back( libname );
}
is_component = true;
} else {
@@ -1368,9 +1347,9 @@ namespace OCL
log(Debug) << error << endlog();
}

- loadedLibs.push_back( loading_lib );
- log(Info) <<"Storing "<< loading_lib.name < - dlerror(); /* Clear any existing error */
+ loadedLibs.push_back( loading_lib );
+ log(Info) <<"Storing "<< loading_lib.name < + dlerror(); /* Clear any existing error */

// plain library
@@ -1448,7 +1427,7 @@ namespace OCL
this->addPeer( comps[name].instance );
log(Info) << "Adding "<< comps[name].instance->getName() << " as new peer: OK."<< endlog(Info);
comps[name].loaded = true;
- comps[name].type = type;
+ comps[name].type = type;
return true;
}

@@ -1694,100 +1673,92 @@ namespace OCL

void DeploymentComponent::kickOutFile(const std::string& config_file)
{
- Logger::In in("DeploymentComponent::kickOutFile");
- PropertyBag from_file;
- Property import_file;
- std::vector deleted_components_type;
+ Logger::In in("DeploymentComponent::kickOutFile");
+ PropertyBag from_file;
+ Property import_file;
+ std::vector deleted_components_type;

- // demarshalling failures:
- bool failure = false;
+ // demarshalling failures:
+ bool failure = false;

- PropertyDemarshaller demarshaller(config_file);
- try {
- if ( demarshaller.deserialize( from_file ) ){
- for (PropertyBag::iterator it= from_file.begin(); it!=from_file.end();it++)
- {
- if ( (*it)->getName() == "Import" ) continue;
- if ( (*it)->getName() == "Include" ) continue;
-
- kickOutComponent( (*it)->getName() );
- }
- deletePropertyBag( from_file );
- }
- else
- {
- log(Error)<< "Some error occured while parsing "<< config_file < - failure = true;
- }
- } catch (...)
- {
- log(Error)<< "Uncaught exception in loadcomponents() !"<< endlog();
- failure = true;
- }
+ PropertyDemarshaller demarshaller(config_file);
+ try {
+ if ( demarshaller.deserialize( from_file ) ){
+ for (PropertyBag::iterator it= from_file.begin(); it!=from_file.end();it++) {
+ if ( (*it)->getName() == "Import" ) continue;
+ if ( (*it)->getName() == "Include" ) continue;
+
+ kickOutComponent( (*it)->getName() );
+ }
+ deletePropertyBag( from_file );
+ }
+ else {
+ log(Error)<< "Some error occured while parsing "<< config_file < + failure = true;
+ }
+ } catch (...)
+ {
+ log(Error)<< "Uncaught exception in loadcomponents() !"<< endlog();
+ failure = true;
+ }
}

bool DeploymentComponent::cleanupComponent(RTT::TaskContext *instance)
{
- Logger::In in("DeploymentComponent::cleanupComponent");
- bool valid = true;
- // 1. Cleanup a single activities, give components chance to cleanup.
- if (instance)
- {
- if ( instance->getTaskState() <= TaskCore::Stopped )
- {
- instance->cleanup();
- log(Info) << "Cleaned up "<< instance->getName() < - } else {
- log(Error) << "Could not cleanup Component "<< instance->getName() << " (not Stopped)"< - valid = false;
- }
- }
- return valid;
+ Logger::In in("DeploymentComponent::cleanupComponent");
+ bool valid = true;
+ // 1. Cleanup a single activities, give components chance to cleanup.
+ if (instance) {
+ if ( instance->getTaskState() <= TaskCore::Stopped ) {
+ instance->cleanup();
+ log(Info) << "Cleaned up "<< instance->getName() < + } else {
+ log(Error) << "Could not cleanup Component "<< instance->getName() << " (not Stopped)"< + valid = false;
+ }
+ }
+ return valid;
}

bool DeploymentComponent::stopComponent(RTT::TaskContext *instance)
{
- Logger::In in("DeploymentComponent::stopComponent");
- bool valid = true;
+ Logger::In in("DeploymentComponent::stopComponent");
+ bool valid = true;

- if ( instance )
- {
- if ( instance->engine()->getActivity() == 0 ||
- instance->engine()->getActivity()->isActive() == false ||
- instance->stop() )
- {
- log(Info) << "Stopped "<< instance->getName() < - }
- else {
- log(Error) << "Could not stop loaded Component "<< instance->getName() < - valid = false;
- }
- }
- return valid;
+ if ( instance ) {
+ if ( instance->engine()->getActivity() == 0 ||
+ instance->engine()->getActivity()->isActive() == false ||
+ instance->stop() ) {
+ log(Info) << "Stopped "<< instance->getName() < + }
+ else {
+ log(Error) << "Could not stop loaded Component "<< instance->getName() < + valid = false;
+ }
+ }
+ return valid;
}

bool DeploymentComponent::kickOutComponent(const std::string& comp_name)
{
- Logger::In in("DeploymentComponent::kickOutComponent");
- PropertyBase *it = root.find( comp_name );
- if(!it)
- {
- log(Error) << "Peer "<< comp_name << " not found in PropertyBag root"<< endlog();
- return false;
- }
+ Logger::In in("DeploymentComponent::kickOutComponent");
+ PropertyBase *it = root.find( comp_name );
+ if(!it) {
+ log(Error) << "Peer "<< comp_name << " not found in PropertyBag root"<< endlog();
+ return false;
+ }

- TaskContext* peer = comps[ comp_name ].instance;
+ TaskContext* peer = comps[ comp_name ].instance;

- if ( !peer )
- {
- log(Error) << "Peer not found: "<< comp_name < - return false;
- }
- stopComponent( peer );
- cleanupComponent (peer );
- unloadComponent( comp_name);
- root.removeProperty( root.find( comp_name ) );
+ if ( !peer ) {
+ log(Error) << "Peer not found: "<< comp_name < + return false;
+ }
+ stopComponent( peer );
+ cleanupComponent (peer );
+ unloadComponent( comp_name);
+ root.removeProperty( root.find( comp_name ) );

- return true;
+ return true;
}
}
diff --git a/deployment/DeploymentComponent.hpp b/deployment/DeploymentComponent.hpp
index 52b3a78..ce7ef21 100644
--- a/deployment/DeploymentComponent.hpp
+++ b/deployment/DeploymentComponent.hpp
@@ -125,21 +125,19 @@ namespace OCL
* Keep a list of all loaded libraries such that double
* loads are avoided during import/loadLibrary.
*/
- class LoadedLib{
+ class LoadedLib{
public:
- LoadedLib(std::string n, void* h)
- {
- name = n;
- handle = h;
- }
- std::string name;
- void* handle;
- std::vector components_type;
- };
-
- static std::vector< LoadedLib > loadedLibs;
+ LoadedLib(std::string n, void* h)
+ {
+ name = n;
+ handle = h;
+ }
+ std::string name;
+ void* handle;
+ std::vector components_type;
+ };

-
+ static std::vector< LoadedLib > loadedLibs;

/**
* Handle of last loaded library.
@@ -156,11 +154,11 @@ namespace OCL
bool configureHook();

/**
- * This method removes all references to the component hold in \a cit,
- * on the condition that it is not running.
- * When this method returns true, you need to remove \a cit yourself from
- * the this->conmap.
- */
+ * This method removes all references to the component hold in \a cit,
+ * on the condition that it is not running.
+ * When this method returns true, you need to remove \a cit yourself from
+ * the this->conmap.
+ */
bool unloadComponentImpl( CompList::iterator cit );

@@ -177,7 +175,7 @@ namespace OCL

~DeploymentComponent();

- TaskContext* myGetPeer(std::string name) {return comps[ name ].instance; }
+ TaskContext* myGetPeer(std::string name) {return comps[ name ].instance; }

/**
* Establish a bidirectional connection between two tasks.
@@ -404,20 +402,20 @@ namespace OCL
*/
void clearConfiguration();

- /**
- * Stop all loaded and running components.
- */
- bool stopComponents();
+ /**
+ * Stop all loaded and running components.
+ */
+ bool stopComponents();

- /**
- * Cleanup all loaded and not running components.
- */
- bool cleanupComponents();
+ /**
+ * Cleanup all loaded and not running components.
+ */
+ bool cleanupComponents();

- /**
- * Unload all loaded and not running components.
- */
- bool unloadComponents();
+ /**
+ * Unload all loaded and not running components.
+ */
+ bool unloadComponents();

/**
* This function runs loadComponents, configureComponents and startComponents
@@ -483,52 +481,52 @@ namespace OCL
*/
FactoryMap& getFactories();

- /**
- * Stop a single loaded and running component.
- * @param instance instance pointer of the component.
- * @return true if successfully stopped.
- */
- bool stopComponent(RTT::TaskContext *instance);
+ /**
+ * Stop a single loaded and running component.
+ * @param instance instance pointer of the component.
+ * @return true if successfully stopped.
+ */
+ bool stopComponent(RTT::TaskContext *instance);

- /**
- * Stop a single loaded and running components.
- * @param comp_name name of the component.
- * @return true if successfully stopped
- */
- bool stopComponent(const std::string& comp_name)
- {
- return this->stopComponent( this->getPeer(comp_name) );
- }
+ /**
+ * Stop a single loaded and running components.
+ * @param comp_name name of the component.
+ * @return true if successfully stopped
+ */
+ bool stopComponent(const std::string& comp_name)
+ {
+ return this->stopComponent( this->getPeer(comp_name) );
+ }

- /**
- * Cleanup a single loaded and not running component.
- * @param instance instance pointer of the component.
- * @return true if successfully cleaned up
- */
- bool cleanupComponent(RTT::TaskContext *instance);
+ /**
+ * Cleanup a single loaded and not running component.
+ * @param instance instance pointer of the component.
+ * @return true if successfully cleaned up
+ */
+ bool cleanupComponent(RTT::TaskContext *instance);

- /**
- * Cleanup a single loaded and not running component.
- * @param comp_name name of the component.
- * @return true if successfully cleaned up
- */
- bool cleanupComponent(const std::string& comp_name)
- {
- return this->cleanupComponent( this->getPeer(comp_name) );
- }
+ /**
+ * Cleanup a single loaded and not running component.
+ * @param comp_name name of the component.
+ * @return true if successfully cleaned up
+ */
+ bool cleanupComponent(const std::string& comp_name)
+ {
+ return this->cleanupComponent( this->getPeer(comp_name) );
+ }

- /**
- * Stop, cleanup and unload a single component which were loaded by this component.
- * @param comp_name name of the component.
- * @return true if successfully stopped, cleaned and unloaded
- */
- bool kickOutComponent(const std::string& comp_name);
+ /**
+ * Stop, cleanup and unload a single component which were loaded by this component.
+ * @param comp_name name of the component.
+ * @return true if successfully stopped, cleaned and unloaded
+ */
+ bool kickOutComponent(const std::string& comp_name);

- /**
- * Identical to \a kickOut, but it read the name of the Components to kickOut from a XML file
- * @param config_file name of an XML file (probably the same used by loadComponents() ).
- */
- void kickOutFile(const std::string& config_file);
+ /**
+ * Identical to \a kickOut, but it read the name of the Components to kickOut from a XML file
+ * @param config_file name of an XML file (probably the same used by loadComponents() ).
+ */
+ void kickOutFile(const std::string& config_file);
};