CCA
PortConfiguration.cpp
Go to the documentation of this file.
00001 /* ============================================================
00002  *
00003  * This file is a part of CCA project
00004  *
00005  * Copyright (C) 2011 by Arne Nordmann <anordman at cor-lab dot uni-bielefeld dot de>
00006  *
00007  * This file may be licensed under the terms of the
00008  * GNU Lesser General Public License Version 3 (the ``LGPL''),
00009  * or (at your option) any later version.
00010  *
00011  * Software distributed under the License is distributed
00012  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
00013  * express or implied. See the LGPL for the specific language
00014  * governing rights and limitations.
00015  *
00016  * You should have received a copy of the LGPL along with this
00017  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
00018  * or write to the Free Software Foundation, Inc.,
00019  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  * The development of this software was supported by:
00022  *   CoR-Lab, Research Institute for Cognition and Robotics
00023  *     Bielefeld University
00024  *
00025  * ============================================================ */
00026 
00027 #include "PortConfiguration.h"
00028 
00029 #include <string>
00030 #include <sstream>
00031 #include <iostream>
00032 
00033 #include <boost/shared_ptr.hpp>
00034 
00035 #include <rsc/config/Configuration.h>
00036 #include <rsc/config/OptionHandler.h>
00037 #include <rsc/logging/OptionBasedConfigurator.h>
00038 
00039 #include <rsb/Factory.h>
00040 #include <rsb/Informer.h>
00041 #include <rsb/Listener.h>
00042 #include <rsb/transport/transports.h>
00043 
00044 namespace cca {
00045 
00046 using namespace std;
00047 using namespace rsb;
00048 using namespace rsb::transport;
00049 using namespace boost;
00050 using namespace rsc;
00051 using namespace rsc::config;
00052 
00053 PortConfigurationPtr PortConfiguration::DEFAULT(const std::string &scope,
00054         unsigned int qsize, bool keepl) {
00055     return PortConfigurationPtr(new PortConfiguration(scope, qsize, keepl));
00056 }
00057 
00058 PortConfigurationPtr PortConfiguration::LOCAL(const std::string &scope,
00059         unsigned int qsize, bool keepl) {
00060     return PortConfigurationPtr(
00061             new PortConfiguration(scope, true, false, qsize, keepl));
00062 }
00063 
00064 PortConfigurationPtr PortConfiguration::REMOTE(const std::string &scope,
00065         unsigned int qsize, bool keepl) {
00066     return PortConfigurationPtr(
00067             new PortConfiguration(scope, false, true, qsize, keepl));
00068 }
00069 
00070 PortConfigurationPtr PortConfiguration::LOCALREMOTE(const std::string &scope,
00071         unsigned int qsize, bool keepl) {
00072     return PortConfigurationPtr(
00073             new PortConfiguration(scope, true, true, qsize, keepl));
00074 }
00075 
00076 PortConfigurationPtr PortConfiguration::PROFILE(const std::string &p,
00077         const std::string &scope, unsigned int qsize, bool keepl) {
00078     PortConfigurationPtr cfg(
00079             new PortConfiguration(scope, false, false, qsize, keepl));
00080 
00081     // TODO: Remove RSB lock-in
00082     std::string config_file = p + ".conf";
00083     rsc::config::configure((cfg->rsbConfigMutable()), config_file, "RSB_");
00084 
00085     return cfg;
00086 }
00087 
00088 PortConfigurationPtr PortConfiguration::create(Transport tr,
00089         const std::string &scope, unsigned int qsize, bool keepl) {
00090     switch (tr) {
00091     case PortConfiguration::CCALocal:
00092         return PortConfiguration::LOCAL(scope, qsize, keepl);
00093         break;
00094     case PortConfiguration::CCARemote:
00095         return PortConfiguration::REMOTE(scope, qsize, keepl);
00096         break;
00097     case PortConfiguration::CCALocalRemote:
00098     default:
00099         return PortConfiguration::LOCALREMOTE(scope, qsize, keepl);
00100     }
00101 }
00102 
00103 PortConfigurationPtr PortConfiguration::create(const std::string &profile,
00104         const std::string &scope, unsigned int qsize, bool keepl) {
00105     return PortConfiguration::PROFILE(profile, scope, qsize, keepl);
00106 }
00107 
00108 rsb::ScopePtr PortConfiguration::getScopePtr() const {
00109     return this->scope;
00110 }
00111 
00112 void PortConfiguration::setQueueSize(unsigned int qsize) {
00113     this->queuesize = qsize;
00114 }
00115 
00116 unsigned int PortConfiguration::getQueueSize() const {
00117     return this->queuesize;
00118 }
00119 
00120 void PortConfiguration::setKeepLatest(bool keepl) {
00121     this->keeplatest = keepl;
00122 }
00123 
00124 bool PortConfiguration::keepLatest() {
00125     return this->keeplatest;
00126 }
00127 
00128 rsb::ParticipantConfig PortConfiguration::rsbConfig() const {
00129     return this->rsbconfig;
00130 }
00131 
00132 rsb::ParticipantConfig& PortConfiguration::rsbConfigMutable() {
00133     return this->rsbconfig;
00134 }
00135 
00136 bool PortConfiguration::isLocalPort() const {
00137     return this->local;
00138 }
00139 
00140 bool PortConfiguration::isRemotePort() const {
00141     return this->remote;
00142 }
00143 
00144 PortConfiguration::PortConfiguration(const std::string &scp, unsigned int qsize,
00145         bool keepl) :
00146         local(false), remote(false), keeplatest(keepl), scope(new Scope(scp)),
00147                 queuesize(qsize) {
00148 
00149     // Participant configuration
00150     // TODO: Remove RSB lock-in
00151     this->rsbconfig = rsb::getFactory().getDefaultParticipantConfig();
00152 
00153     set<ParticipantConfig::Transport> transports =
00154             this->rsbconfig.getTransports(true);
00155 
00156     for (set<ParticipantConfig::Transport>::const_iterator it =
00157             transports.begin(); it != transports.end(); ++it) {
00158         ParticipantConfig::Transport transport = *it;
00159 
00160         if (    // transport ist available
00161         rsb::transport::isAvailable(transport.getName(),
00162                 DIRECTION_IN_PUSH | DIRECTION_OUT) &&
00163         // transport is remote
00164                 rsb::transport::isRemote(transport.getName())) {
00165             this->remote = true;
00166         } else {
00167             this->local = true;
00168         }
00169     }
00170 }
00171 
00172 PortConfiguration::PortConfiguration(const std::string &scp, bool loc, bool rem,
00173         unsigned int qsize, bool keepl) :
00174         local(loc), remote(rem), keeplatest(keepl), scope(new Scope(scp)),
00175                 queuesize(qsize) {
00176 
00177     // Participant configuration
00178     // TODO: Remove RSB lock-in
00179     this->rsbconfig = rsb::getFactory().getDefaultParticipantConfig();
00180 
00181     set<ParticipantConfig::Transport> transports =
00182             this->rsbconfig.getTransports(true);
00183 
00184     // Transport Configuration
00185     bool localSatisfied = true; // maybe later !this->local;
00186     bool remoteSatisfied = !this->remote;
00187     for (set<ParticipantConfig::Transport>::const_iterator it =
00188             transports.begin(); it != transports.end(); ++it) {
00189         ParticipantConfig::Transport transport = *it;
00190 
00191         // Only consider available transports
00192         if (rsb::transport::isAvailable(transport.getName(),
00193                 DIRECTION_IN_PUSH | DIRECTION_OUT)) {
00194 
00195             // Configure local transport
00196             if (!rsb::transport::isRemote(transport.getName())) {
00197                 transport.setEnabled(this->local);
00198             }
00199 
00200             // Configure remote transport
00201             // If the transport is enabled and we want remote transports,
00202             // just leave it enabled. Otherwise, disable the transport. If
00203             // we want remote transports, make sure, we found at least one
00204             // enabled remote transport.
00205             else {
00206                 if (transport.isEnabled()) {
00207                     if (this->remote) {
00208                         remoteSatisfied = true;
00209                     } else {
00210                         transport.setEnabled(false);
00211                     }
00212                 }
00213             }
00214 
00215             this->rsbconfig.addTransport(transport);
00216 
00217         }
00218     }
00219     if (!localSatisfied) {
00220         throw std::runtime_error("Local transport requested, but middleware "
00221                 "doesn't provide this in its current configuration.");
00222     }
00223     if (!remoteSatisfied) {
00224         throw std::runtime_error("Remote transport requested, but middleware"
00225                 " doesn't provide this in its current configuration.");
00226     }
00227 }
00228 
00229 PortConfiguration::~PortConfiguration() {
00230 }
00231 
00232 string PortConfiguration::print() const {
00233     ostringstream outstream(ostringstream::out);
00234     outstream.precision(3); // Precision when printing double values
00235     outstream << "<cfg:";
00236 
00237     set<rsb::ParticipantConfig::Transport> ts = this->rsbconfig.getTransports();
00238     for (set<rsb::ParticipantConfig::Transport>::const_iterator tsit =
00239             ts.begin(); tsit != ts.end(); ++tsit) {
00240         outstream << tsit->getName() << ",";
00241     }
00242 
00243     outstream << ">";
00244     return outstream.str();
00245 }
00246 
00247 bool operator==(PortConfigurationPtr const a, PortConfigurationPtr const b) {
00248     return ((a->getScopePtr() == b->getScopePtr())
00249             && (a->isLocalPort() == b->isLocalPort())
00250             && (a->isRemotePort() == b->isRemotePort()));
00251 }
00252 
00253 }