--- deployment/DeploymentComponent.cpp 2008-11-04 10:23:15.000000000 +0100 +++ DeploymentComponent.cpp 2008-09-16 12:30:27.000000000 +0200 @@ -52,7 +52,7 @@ using namespace std; using namespace RTT; - std::vector< DeploymentComponent::LoadedLib > DeploymentComponent::loadedLibs; + std::vector > DeploymentComponent::LoadedLibs; /** * I'm using a set to speed up lookups. @@ -137,14 +137,6 @@ 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; @@ -229,6 +221,7 @@ DeploymentComponent::~DeploymentComponent() { + clearConfiguration(); // Should we unload all loaded components here ? if ( autoUnload.get() ) { kickOut(); @@ -237,7 +230,7 @@ bool DeploymentComponent::connectPeers(const std::string& one, const std::string& other) { - Logger::In in("DeploymentComponent::connectPeers"); + Logger::In in("DeploymentComponent"); TaskContext* t1 = this->getPeer(one); TaskContext* t2 = this->getPeer(other); if (!t1) { @@ -253,7 +246,7 @@ bool DeploymentComponent::addPeer(const std::string& from, const std::string& to) { - Logger::In in("DeploymentComponent::addPeer"); + Logger::In in("DeploymentComponent"); TaskContext* t1 = this->getPeer(from); TaskContext* t2 = this->getPeer(to); if (!t1) { @@ -269,7 +262,6 @@ 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); @@ -288,7 +280,6 @@ 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); @@ -449,7 +440,7 @@ // Check if it is a propertybag. Property comp = *it; if ( !comp.ready() ) { - log(Error)<< "Property '"<< *it <<"' should be a struct, Include or Import statement." << endlog(); + log(Error)<< "Property '"<< *it <<"' is should be a struct, Include or Import statement." << endlog(); valid = false; continue; } @@ -579,27 +570,11 @@ valid = false; } // 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) - { + if (valid) { log(Debug)<<"storing Port: "<getName()<<"."<getName(); - log(Debug)<<" in " << port_name <get().getProperty(*pit)->get() <get().getProperty(*pit)->get()].ports.push_back( p ); + conmap[ports->get().getProperty(*pit)->get()].owners.push_back( c ); } } } @@ -756,11 +731,7 @@ 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() <second); - std::string connection_name = it->first; - - if ( connection->ports.size() == 1 ){ - log(Warning) << "Can not form connection "<owners[0]<< endlog(); + 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(); 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(); - - 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 ) - { + ConnectionData::Ports::iterator p = it->second.ports.begin(); + while (p != it->second.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: @@ -832,29 +782,25 @@ log(Warning) << "Connecting only write-ports in connection " << it->first << endlog(); } // Inform user which component initiates the connection: - p = connection->ports.begin(); + p = it->second.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 <<":" <second.owners[p - it->second.ports.begin()]->getName(); + log(Info) << "Creating Connection "<first<<" starting from TaskContext "<< owner <<":" <ports.begin(); - - while (p != connection->ports.end() ) - { + p = it->second.ports.begin(); + while (p != it->second.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 <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<connected()) log(Error) << "Port "<< owner<<"."<< (*p)->getName() << " already connected !"<getName() << " has wrong type !"<getName() <<" to connection " << connection_name <getName() <<" to connection " << it->first <isConfigured() || !peer->isRunning() ) - { if ( peer->configure() == false) valid = false; } - else - log(Warning) << "Apparently component "<< peer->getName()<< " don't need to be configured." <second); if ( it->instance && !it->proxy ) - { if ( it->instance->engine()->getActivity() == 0 || it->instance->engine()->getActivity()->isActive() == false || it->instance->stop() ) { @@ -1012,7 +950,6 @@ valid = false; } } - } return valid; } @@ -1024,7 +961,6 @@ 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() < 0) - { + 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 " <instance->disconnect(); + log(Debug) << "Terminating " <act; + it->act = 0; + delete it->instance; + it->instance = 0; + log(Info) << "Disconnected and destroyed "<< name <first <unloadComponentImpl(cit); + do { + ComponentData* it = &(cit->second); + // if deleted and loaded by us: + if (it->instance == 0 && it->loaded) { + log(Info) << "Completely removed "<< cit->first <first <d_name; if (name != "." && name != ".." ) - { if (namelist[i]->d_type == DT_DIR) { //ignoring symlinks and subdirs here. import( path +"/" +name ); } else { @@ -1106,7 +1076,6 @@ loadLibrary( path + "/" + name ); } } - } free(namelist[i]); ++i; } @@ -1150,47 +1119,14 @@ // 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 - - 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() <handle); - // remove the library info from the vector - std::vector::iterator lib_un = lib; - loadedLibs.erase(lib_un); - lib = loadedLibs.end(); - } - else return true; + for(vector >::iterator it = LoadedLibs.begin(); it != LoadedLibs.end(); ++it){ + if ( it->first == libname ) { + log(Info) <<"Library "<< libname <<" already loaded."<second; + return true; } - else lib++; } - std::vector errors; // try form "liborocos-helloworld-gnulinux.so" handle = dlopen ( so_name.c_str(), RTLD_NOW | RTLD_GLOBAL ); @@ -1265,8 +1201,8 @@ return false; } - //------------- if you get here, the library has been loaded ------------- - LoadedLib loading_lib(libname,handle); + LoadedLibs.push_back(make_pair(libname,handle)); + log(Debug) <<"Storing "<< libname <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 " <instance->disconnect(); - log(Debug) << "Terminating " <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 <getPeer(name); + if (peer) { + for(CompList::iterator it = comps.begin(); it != comps.end(); ++it) + if (it->second.instance == peer) { + regname = it->first; + break; + } + } else { // 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()<unloadComponentImpl( it ) == false ) + assert(peer); + if ( peer->isRunning() ) { + log(Error) << "Can't unload component "<disconnect(); // if it is no longer a peer of this, that's ok. + } catch(...) { + log(Warning) << "Disconnecting caused exception." < 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 <getTaskState() <= TaskCore::Stopped ) - { - instance->cleanup(); - log(Info) << "Cleaned up "<< instance->getName() <getName() << " (not Stopped)"<engine()->getActivity() == 0 || - instance->engine()->getActivity()->isActive() == false || - instance->stop() ) - { - log(Info) << "Stopped "<< instance->getName() <getName() <