RSB  0.12.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ParticipantConfig.cpp
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is a part of the RSB project.
4  *
5  * Copyright (C) 2011 by Johannes Wienke <jwienke at techfak dot uni-bielefeld dot de>
6  *
7  * This file may be licensed under the terms of the
8  * GNU Lesser General Public License Version 3 (the ``LGPL''),
9  * or (at your option) any later version.
10  *
11  * Software distributed under the License is distributed
12  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13  * express or implied. See the LGPL for the specific language
14  * governing rights and limitations.
15  *
16  * You should have received a copy of the LGPL along with this
17  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
18  * or write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * The development of this software was supported by:
22  * CoR-Lab, Research Institute for Cognition and Robotics
23  * Bielefeld University
24  *
25  * ============================================================ */
26 
27 #include "ParticipantConfig.h"
28 
29 #include <stdexcept>
30 #include <fstream>
31 
32 #include <boost/format.hpp>
33 #include <boost/filesystem/fstream.hpp>
34 
35 #include <rsc/logging/Logger.h>
36 
37 using namespace std;
38 
39 using namespace boost;
40 using namespace boost::filesystem;
41 
42 using namespace rsc::config;
43 using namespace rsc::logging;
44 using namespace rsc::runtime;
45 
46 namespace rsb {
47 
48 ParticipantConfig::Transport::Transport(const string& name,
49  bool enabled) :
50  name(name) {
51  if (name.empty()) {
52  throw invalid_argument(
53  "The name of a transport configuration cannot be empty.");
54  }
55  if (!enabled) {
56  setEnabled(false);
57  }
58 }
59 
61 }
62 
64  return name;
65 }
66 
68  return this->converters;
69 }
70 
71 rsc::runtime::Properties ParticipantConfig::Transport::getOptions() const {
72  return this->options;
73 }
74 
75 rsc::runtime::Properties& ParticipantConfig::Transport::mutableOptions() {
76  return this->options;
77 }
78 
79 
81  this->options = options;
82 }
83 
85  return this->getOptions().getAs<bool> ("enabled", true);
86 }
87 
89  Properties options = this->getOptions();
90  options["enabled"] = lexical_cast<string>(value);
91  setOptions(options);
92 }
93 
94 void ParticipantConfig::Transport::handleOption(const vector<string>& key,
95  const string& value) {
96  if ((key.size() >= 2)
97  && (key[0] == "converter")
98  && (key[1] == "cpp")) {
99  if (key.size() != 3) {
100  throw invalid_argument(
101  str(
102  format(
103  "Option key `%1%' has invalid number of components; converter-related keys for transports has to have three components")
104  % key));
105  }
106  this->converters.insert(make_pair(key[2], value));
107  } else if ((key.size() >= 2) && (key[0] == "converter")) {
108  // ignore converters for other languages
109  } else {
110  if (key.size() != 1) {
111  throw invalid_argument(
112  str(
113  format(
114  "Key `%1%' has invalid number of components; transport option keys have to have one component.")
115  % key));
116  }
117  this->options[key[0]] = value;
118  }
119 }
120 
122  return name == other.name;
123 }
124 
126  return name < other.name;
127 }
128 
130  return "Transport";
131 }
132 
133 void ParticipantConfig::Transport::printContents(ostream& stream) const {
134  stream << "name = " << this->name
135  << ", converters = " << this->converters
136  << ", options = " << this->options;
137 }
138 
140  name(name) {
141 }
142 
144  return this->name;
145 }
146 
148  this->name = name;
149 }
150 
152  return this->options;
153 }
154 
156  return this->options;
157 }
158 
160  this->options = options;
161 }
162 
164  const string& value) {
165  if (key.size() != 1) {
166  throw invalid_argument(str(format("Key `%1%' has invalid number of components; transport option keys have to have one component.")
167  % key));
168  }
169 
170  this->options.set<string>(key.front(), value);
171 }
172 
174  stream << "name = " << this->name
175  << ", options = " << this->options;
176 }
177 
179  logger(Logger::getLogger("rsb.ParticipantConfig")),
181  eventReceivingStrategy("parallel"),
182  eventSendingStrategy("direct"),
183  introspection(true) {
184 }
185 
187 }
188 
190  return qosSpec;
191 }
192 
194  return qosSpec;
195 }
196 
198  const QualityOfServiceSpec& spec) {
199  this->qosSpec = spec;
200 }
201 
203  return errorStrategy;
204 }
205 
207  this->errorStrategy = strategy;
208 }
209 
211  map<string, Transport>::const_iterator it = this->transports.find(name);
212  if (it == this->transports.end()) {
213  throw rsc::runtime::NoSuchObject(name);
214  }
215  return it->second;
216 }
217 
219  map<string, Transport>::iterator it = this->transports.find(name);
220  if (it == this->transports.end()) {
221  throw rsc::runtime::NoSuchObject(name);
222  }
223  return it->second;
224 }
225 
226 set<ParticipantConfig::Transport> ParticipantConfig::getTransports(
227  bool includeDisabled) const {
228  set<Transport> result;
229  for (map<string, Transport>::const_iterator it = this->transports.begin(); it
230  != this->transports.end(); ++it) {
231  if (it->second.isEnabled() || includeDisabled) {
232  result.insert(it->second);
233  } else {
234  RSCDEBUG(logger, "Skipping disabled transport " << it->second);
235  }
236  }
237  return result;
238 }
239 
241  transports.erase(transport.getName());
242  transports.insert(make_pair(transport.getName(), transport));
243 }
244 
246  transports.erase(transport.getName());
247 }
248 
249 void ParticipantConfig::setTransports(const set<Transport>& transports) {
250  for (set<Transport>::const_iterator it = transports.begin(); it
251  != transports.end(); ++it) {
252  this->transports.insert(make_pair(it->getName(), *it));
253  }
254 }
255 
257  return this->eventReceivingStrategy;
258 }
259 
261  return this->eventReceivingStrategy;
262 }
263 
265  return this->eventSendingStrategy;
266 }
267 
269  return this->introspection;
270 }
271 
273  this->introspection = newValue;
274 }
275 
276 
277 rsc::runtime::Properties ParticipantConfig::getOptions() const {
278  return options;
279 }
280 
281 rsc::runtime::Properties& ParticipantConfig::mutableOptions() {
282  return options;
283 }
284 
285 void ParticipantConfig::setOptions(const Properties& options) {
286  this->options = options;
287 }
288 
289 void ParticipantConfig::handleOption(const vector<string>& key,
290  const string& value) {
291  // Quality of Service
292  if (key[0] == "qualityofservice") {
293  if (key.size() != 2) {
294  throw invalid_argument(
295  str(
296  format(
297  "Option key `%1%' has invalid number of components; options related to quality of service have to have two components.")
298  % key));
299  }
300  if (key[1] == "reliability") {
301  if (value == "UNRELIABLE") {
303  } else if (value == "RELIABLE") {
305  } else
306  throw invalid_argument(str(format(
307  "The value `%1%' is invalid for the key `%2%'.")
308  % value % key));
309  } else if (key[1] == "ordering") {
310  if (value == "UNORDERED") {
312  } else if (value == "ORDERED") {
314  } else
315  throw invalid_argument(str(format(
316  "The value `%1%' is invalid for the key `%2%'.")
317  % value % key));
318  }
319  // Error handling
320  } else if (key[0] == "errorhandling") {
321  if (key[1] == "onhandlererror") {
322  if (value == "LOG") {
324  } else if (value == "PRINT") {
326  } else if (value == "EXIT") {
328  } else {
329  throw invalid_argument(str(format(
330  "The value `%1%' is invalid for the key `%2%'.")
331  % value % key));
332  }
333  }
334  // Event processing
335  } else if (key[0] == "eventprocessing") {
336  EventProcessingStrategy* strategy;
337  if (key[1] == "receivingstrategy") {
338  strategy = &this->eventReceivingStrategy;
339  } else if (key[1] == "sendingstrategy") {
340  strategy = &this->eventSendingStrategy;
341  } else {
342  throw invalid_argument(
343  str(format("`%2%' is not a valid sub-key of `%1%'.")
344  % key[0] % key[1]));
345  }
346  if (key.size() == 2) {
347  strategy->setName(value);
348  } else {
349  vector<string> subKey;
350  copy(key.begin() + 2, key.end(), back_inserter(subKey));
351  strategy->handleOption(subKey, value);
352  }
353 
354  // Introspection
355  } else if (key[0] == "introspection") {
356  if ((key.size() == 2) && (key[1] == "enabled")) {
357  this->introspection = lexical_cast<bool>(value);
358  }
359 
360  // Transports
361  } else if (key[0] == "transport") {
362  if (key.size() < 3) {
363  throw invalid_argument(
364  str(
365  format(
366  "Option key `%1%' has invalid number of components; transport-related keys have to have at least three components.")
367  % key));
368  }
369  map<string, Transport>::iterator it = this->transports.find(key[1]);
370  if (it == this->transports.end()) {
371  addTransport(Transport(key[1]));
372  it = this->transports.find(key[1]);
373  }
374  Transport& transport = it->second;
375  vector<string> subKey;
376  copy(key.begin() + 2, key.end(), back_inserter(subKey));
377  transport.handleOption(subKey, value);
378  // Global (participant-wide) options
379  } else {
380  if (key.size() == 1) {
381  this->options[key[0]] = value;
382  }
383  }
384 }
385 
386 void ParticipantConfig::printContents(std::ostream& stream) const {
387  stream << "qosSpec = " << this->qosSpec
388  << ", errorStrategy = " << this->errorStrategy
389  << ", transports = " << this->getTransports(true)
390  << ", eventReceivingStrategy = " << this->eventReceivingStrategy
391  << ", eventSendingStrategy = " << this->eventSendingStrategy
392  << ", options = " << this->options << "]";
393 }
394 
395 }
void setOptions(const rsc::runtime::Properties &options)
Sets the additional options besides the transport-specific ones.
Specification of desired quality of service settings for sending and receiving events.
void setQualityOfServiceSpec(const QualityOfServiceSpec &spec)
Sets the desired QoS settings.
QualityOfServiceSpec qosSpec
Uses stderr for printing a message.
rsc::runtime::Properties getOptions() const
Returns the specified options for the transport.
rsc::runtime::Properties getOptions() const
Returns additional options besides the transport-specific ones.
rsc::runtime::Properties & mutableOptions()
Returns the options for the transport.
bool operator==(const Transport &other) const
Every listener receives the events of one informer in the order the informer sent the events...
void handleOption(const std::vector< std::string > &key, const std::string &value)
QualityOfServiceSpec & mutableQualityOfServiceSpec()
Returns mutable quality of service settings.
EventProcessingStrategy eventSendingStrategy
ErrorStrategy getErrorStrategy() const
Returns the selected error strategy for the configured participant.
std::string getName() const
Returns the name of the implementation to be selected.
std::string getName() const
Returns the name of this transport description.
EventProcessingStrategy eventReceivingStrategy
rsc::runtime::Properties getOptions() const
Returns the options for the strategy.
void handleOption(const std::vector< std::string > &key, const std::string &value)
rsc::logging::LoggerPtr logger
void printContents(std::ostream &stream) const
Events may be dropped and not be visible to a listener.
void addTransport(const Transport &transport)
Adds a transport to the list of desired transport mechanisms.
ConverterNames getConverters() const
void setName(const std::string &name)
Sets the name of the implementation to be selected.
rsc::runtime::Properties options
EventProcessingStrategy & mutableEventReceivingStrategy()
void setOptions(const rsc::runtime::Properties &options)
Sets the options for the strategy.
bool isIntrospectionEnabled() const
Indicates whether introspection should be enabled for the participant.
rsc::runtime::Properties & mutableOptions()
Returns the options for the strategy.
const EventProcessingStrategy & getEventReceivingStrategy() const
Description of a desired transport.
rsc::runtime::Properties & mutableOptions()
Returns a mutable reference to the freestyle options in this configuration.
bool operator<(const Transport &other) const
void removeTransport(const Transport &transport)
Removes a transport from the list of desired transports if it was present.
void printContents(std::ostream &stream) const
void setTransports(const std::set< Transport > &transports)
Sets all desired transports in this configuration.
The events are delivered in arbitrary order.
ErrorStrategy
Possible error handling strategies in user-provided code like event handlers.
Logs a message using the logging mechanism.
QualityOfServiceSpec getQualityOfServiceSpec() const
Returns the current settings for QoS.
Transport & mutableTransport(const std::string &name)
Returns a single configured transport which can be modified in place.
Instances of this class describe the selection and configuration of an event processing strategy...
void setIsIntrospectionEnabled(bool newValue)
Controls whether introspection should be enabled for the participant.
void setErrorStrategy(const ErrorStrategy &strategy)
Sets the desired error strategy for the participant.
void handleOption(const std::vector< std::string > &key, const std::string &value)
const EventProcessingStrategy & getEventSendingStrategy() const
std::map< std::string, Transport > transports
ParticipantConfig()
Constructs a new empty configuration using the default QoS settings and #LOG as error strategy...
std::set< Transport > getTransports(bool includeDisabled=false) const
Returns the set of desired transports for a participant.
std::set< std::pair< std::string, std::string > > ConverterNames
Messages are guaranteed to be delivered.
void setOptions(const rsc::runtime::Properties &options)
Sets the options for the transport.
void printContents(std::ostream &stream) const
Transport getTransport(const std::string &name) const
Returns an immutable copy of a single configured transport.