OpenDDS  Snapshot(2023/04/28-20:55)
FederatorConfig.cpp
Go to the documentation of this file.
1 /*
2  *
3  *
4  * Distributed under the OpenDDS License.
5  * See: http://www.opendds.org/license.html
6  */
7 
8 #include "DcpsInfo_pch.h"
9 #include "dds/DCPS/debug.h"
10 #include "FederatorConfig.h"
11 #include "FederatorC.h"
12 #include "ace/Configuration.h"
14 #include "ace/Log_Priority.h"
15 #include "ace/Log_Msg.h"
16 #include "ace/OS_NS_stdlib.h"
17 #include "ace/OS_NS_strings.h"
18 #include "ace/OS_NS_sys_time.h"
19 
20 #include <algorithm>
21 
22 #if !defined (__ACE_INLINE__)
23 # include "FederatorConfig.inl"
24 #endif /* !__ACE_INLINE__ */
25 
27 
28 namespace {
29 
30 // FederationDomain key value.
31 const ACE_TCHAR FEDERATION_DOMAIN_KEY[] = ACE_TEXT("FederationDomain");
32 
33 // FederationId key value.
34 const ACE_TCHAR FEDERATION_ID_KEY[] = ACE_TEXT("FederationId");
35 
36 // FederationId key value.
37 const ACE_TCHAR FEDERATION_PORT_KEY[] = ACE_TEXT("FederationPort");
38 
39 /// Define an argument copying functor.
40 class ArgCopier {
41 public:
42  /// Identify the action to take on the next argument.
43  enum Action { COPY, FILENAME, IDVALUE, IORVALUE };
44 
45  /// Construct with a target pointer array.
47 
48  /// The Functor function operator.
49  void operator()(ACE_TCHAR* arg);
50 
51 private:
52  /// The configuration object.
54 
55  /// How to treat the next argument.
57 };
58 
59 ArgCopier::ArgCopier(OpenDDS::Federator::Config* config)
60  : config_(config),
61  action_(COPY)
62 {
63 
64 } // namespace
65 
66 void
68 {
69  // Search for command line arguments to process rather than copy.
71  // Configuration file option, filename value is next arg.
72  this->action_ = FILENAME;
73  return;
74 
76  // Federation Id option, Id value is next arg.
77  this->action_ = IDVALUE;
78  return;
79 
81  // Federate with option, IOR is next arg.
82  this->action_ = IORVALUE;
83  return;
84  }
85 
86  // Process unrecognized arguments and all values.
87  switch (this->action_) {
88  case FILENAME:
89  // Store the configuration file name.
90  this->config_->configFile(arg);
91  break;
92 
93  case IDVALUE:
94  // Capture the federation Id.
95  this->config_->federationId().id(ACE_OS::atoi(arg));
96  break;
97 
98  case IORVALUE:
99  // Capture the IOR to federate with.
100  this->config_->federateIor(arg);
101  break;
102 
103  case COPY:
104  // Copy other args verbatim.
105  this->config_->addArg(arg);
106  break;
107  }
108 
109  this->action_ = COPY;
110 }
111 
113 {
114  ACE_UINT64 msec;
115  ACE_OS::gettimeofday().msec(msec);
116  ACE_OS::srand((unsigned int)msec);
117  const int r = ACE_OS::rand();
118  return r;
119 }
120 
121 void hash_endpoint(::CORBA::Long& hash, const char* const endpoint, const size_t len)
122 {
123  std::string toprint(endpoint, len);
124  if (len > 0)
125  {
126  for (size_t i = 0; i < len; i++)
127  {
128  hash = 31 * hash + endpoint[i];
129  }
130  }
131 }
132 
133 #if defined (ACE_USES_WCHAR)
134 void hash_endpoint(::CORBA::Long& hash, const wchar_t* const endpoint, const size_t len)
135 {
136  // treat the wchar string as a double length string
137  hash_endpoint(hash, reinterpret_cast<const char*>(endpoint), len * 2);
138 }
139 #endif
140 
141 void hash_endpoints(::CORBA::Long& hash, const ACE_TCHAR* const endpoints_str)
142 {
143  const ACE_TCHAR* delim = ACE_TEXT(";");
144  const size_t len = ACE_OS::strlen(endpoints_str);
145  const ACE_TCHAR* curr = endpoints_str;
146  while (curr < endpoints_str + len) {
147  const ACE_TCHAR* next = ACE_OS::strstr(curr, delim);
148  if (next == 0)
149  next = endpoints_str + len;
150  hash_endpoint(hash, curr, (next - curr));
151  curr = next + 1;
152  }
153 }
154 
156 {
157  ::CORBA::Long hash = 0;
158  bool found = false;
159  for (int i = 0; i < argc - 1; ++i) {
160  if (ACE_OS::strncasecmp(argv[i], ACE_TEXT("-ORB"), ACE_OS::strlen(ACE_TEXT("-ORB"))) == 0 &&
161  (ACE_OS::strcasecmp(ACE_TEXT("-ORBEndpoint"), argv[i]) == 0 ||
162  ACE_OS::strcasecmp(ACE_TEXT("-ORBListenEndpoints"), argv[i]) == 0 ||
163  ACE_OS::strcasecmp(ACE_TEXT("-ORBLaneEndpoint"), argv[i]) == 0 ||
164  ACE_OS::strcasecmp(ACE_TEXT("-ORBLaneListenEndpoints"), argv[i]) == 0)) {
165  const ACE_TCHAR* enpoints = argv[++i];
166  hash_endpoints(hash, enpoints);
167  found = true;
168  }
169  }
170  if (!found) {
171  hash = random_id();
172  }
173  return hash;
174 }
175 
176 } // End of anonymous namespace
177 
178 namespace OpenDDS {
179 namespace Federator {
180 
181 const tstring
182 Config::FEDERATOR_CONFIG_OPTION(ACE_TEXT("-FederatorConfig"));
183 
184 const tstring
185 Config::FEDERATOR_ID_OPTION(ACE_TEXT("-FederationId"));
186 
187 const tstring
188 Config::FEDERATE_WITH_OPTION(ACE_TEXT("-FederateWith"));
189 
190 Config::Config(int argc, ACE_TCHAR** argv)
191  : argc_(0),
192  federationId_(hash_endpoints(argc, argv)),
193  federationDomain_(DEFAULT_FEDERATIONDOMAIN),
194  federationPort_(-1)
195 {
198  ACE_TEXT("(%P|%t) INFO: Federator::Config::Config()\n")));
199  }
200 
201  // Setup the internal storage.
202  this->argv_ = new ACE_TCHAR*[argc + 1](); // argv_[argc] == 0
203 
204  // Process the federation arguments. Copy the uninteresting arguments verbatim.
205  ArgCopier argCopier(this);
206  std::for_each(&argv[0], &argv[ argc], argCopier);
207 
208  // Read and process any configuration file.
209  this->processFile();
210 }
211 
213 {
216  ACE_TEXT("(%P|%t) INFO: Federator::Config::~FederatorConfig()\n")));
217  }
218 
219  // We prwn this
220  delete [] this->argv_;
221 }
222 
223 void
225 {
228  ACE_TEXT("(%P|%t) INFO: Federator::Config::process()\n")));
229  }
230 
231  if (this->configFile_.empty()) {
232  // No filename, no processing.
233  return;
234  }
235 
236  // Grab a spot to stick the configuration.
238 
239  if (0 != heap.open()) {
241  ACE_TEXT("(%P|%t) ERROR: Federator::Config::process - ")
242  ACE_TEXT("unable to open configuration heap.\n")));
243  return;
244  }
245 
246  // Import the file into our shiny new spot.
247  ACE_Ini_ImpExp import(heap);
248 
249  if (0 != import.import_config(this->configFile_.c_str())) {
251  ACE_TEXT("(%P|%t) ERROR: Federator::Config::process - ")
252  ACE_TEXT("unable to import configuration file.\n")));
253  return;
254  }
255 
256  // Configuration file format:
257  //
258  // FederationDomain = <number> (REQUIRED)
259  // FederationId = <number> (REQUIRED)
260  // FederationPort = <number> (REQUIRED)
261  //
262 
263  // Grab the common configuration settings.
264  const ACE_Configuration_Section_Key &root = heap.root_section();
265 
266  // Federation Domain value - REQUIRED
267  ACE_TString federationDomainString;
268 
269  if (0 != heap.get_string_value(root, FEDERATION_DOMAIN_KEY, federationDomainString)) {
271  ACE_TEXT("(%P|%t) ERROR: Federator::Config::process - ")
272  ACE_TEXT("Unable to obtain value for FederationDomain in root section\n")));
273  return;
274  }
275 
276  // Convert to numeric repository key value.
277  this->federationDomain_ = ACE_OS::atoi(federationDomainString.c_str());
278 
281  ACE_TEXT("(%P|%t) FederationDomain == %d\n"),
282  this->federationDomain_));
283  }
284 
285  // Federation Id value - REQUIRED
286  ACE_TString federationIdString;
287 
288  if (0 != heap.get_string_value(root, FEDERATION_ID_KEY, federationIdString)) {
290  ACE_TEXT("(%P|%t) ERROR: Federator::Config::process - ")
291  ACE_TEXT("Unable to obtain value for FederationId in root section\n")));
292  return;
293  }
294 
295  // Convert to numeric repository key value.
296  RepoKey idValue = ACE_OS::atoi(federationIdString.c_str());
297 
298  // Allow the command line to override the file value.
299  if (this->federationId_.overridden()) {
301  ACE_TEXT("(%P|%t) FederationId == %d from file ")
302  ACE_TEXT("overridden by value %d from command line.\n"),
303  idValue,
304  this->federationId_.id()));
305 
306  } else {
307  this->federationId_.id(idValue);
308 
311  ACE_TEXT("(%P|%t) FederationId == %d\n"),
312  this->federationId_.id()));
313  }
314  }
315 
316  // Federation port value - REQUIRED
317  ACE_TString federationPortString;
318 
319  if (0 != heap.get_string_value(root, FEDERATION_PORT_KEY, federationPortString)) {
321  ACE_TEXT("(%P|%t) ERROR: Federator::Config::process - ")
322  ACE_TEXT("Unable to obtain value for FederationPort in root section\n")));
323  return;
324  }
325 
326  // Convert to numeric repository key value.
327  this->federationPort_ = ACE_OS::atoi(federationPortString.c_str());
328 
331  ACE_TEXT("(%P|%t) FederationPort == %d\n"),
332  this->federationPort_));
333  }
334 }
335 
336 } // namespace Federator
337 } // namespace OpenDDS
338 
#define ACE_DEBUG(X)
OpenDDS::Federator::Config * config_
The configuration object.
ACE_CDR::Long Long
#define ACE_ERROR(X)
const char * c_str(void) const
int hash(const std::vector< const DDS::OctetSeq *> &src, DDS::OctetSeq &dst)
virtual int get_string_value(const ACE_Configuration_Section_Key &key, const ACE_TCHAR *name, ACE_TString &value)
int strncasecmp(const char *s, const char *t, size_t len)
Action
Identify the action to take on the next argument.
int rand(void)
virtual const ACE_Configuration_Section_Key & root_section(void) const
void operator()(ACE_TCHAR *arg)
The Functor function operator.
void configFile(const tstring &file)
Configuration filename.
Action action_
How to treat the next argument.
size_t strlen(const char *s)
void processFile()
Process a configuration file.
const FederationDomain DEFAULT_FEDERATIONDOMAIN
Definition: Federator.idl:37
LM_DEBUG
void addArg(ACE_TCHAR *arg)
Add an argument.
void hash_endpoints(::CORBA::Long &hash, const ACE_TCHAR *const endpoints_str)
char ACE_TCHAR
static const tstring FEDERATOR_ID_OPTION
Command line option specifying the federation Id value.
TAO_DDS_DCPSFederationId & federationId()
Federation Id value.
tstring configFile_
Configuration filename, if any.
TAO_DDS_DCPSFederationId federationId_
Configured Federation Id value.
std::basic_string< ACE_TCHAR > tstring
static const tstring FEDERATOR_CONFIG_OPTION
Command line option specifying the configuration file.
void federateIor(const tstring &ior)
Initial federation IOR value.
ACE_TEXT("TCP_Factory")
int atoi(const char *s)
long federationDomain_
Configured Federation Domain value.
unsigned long long ACE_UINT64
OpenDDS_Dcps_Export unsigned int DCPS_debug_level
Definition: debug.cpp:30
ACE_TCHAR ** argv_
Enhanced argv.
const char * strstr(const char *s, const char *t)
unsigned long msec(void) const
int strcasecmp(const char *s, const char *t)
Define an argument copying functor.
::CORBA::Long RepoKey
void srand(u_int seed)
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
ACE_Time_Value gettimeofday(void)
int open(const ACE_TCHAR *file_name, void *base_address=ACE_DEFAULT_BASE_ADDR, size_t default_map_size=ACE_DEFAULT_CONFIG_SECTION_SIZE)
static const tstring FEDERATE_WITH_OPTION
Command line option specifying a repository to federate with.
LM_ERROR
short federationPort_
Configured Federation Port value.
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28
void hash_endpoint(::CORBA::Long &hash, const char *const endpoint, const size_t len)
void id(RepoKey fedId)