Parser.cpp
Go to the documentation of this file.
1 // **********************************************************************
2 //
3 // Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved.
4 //
5 // This copy of Ice is licensed to you under the terms described in the
6 // ICE_LICENSE file included in this distribution.
7 //
8 // **********************************************************************
9 
10 #include <algorithm>
11 
12 #include <Ice/ConsoleUtil.h>
13 #include <Ice/Ice.h>
15 #include <IceStorm/Parser.h>
16 #include <IceUtil/DisableWarnings.h>
17 
18 #ifdef HAVE_READLINE
19 #include <readline/history.h>
20 #include <readline/readline.h>
21 #endif
22 
23 extern FILE* yyin;
24 extern int yydebug;
25 
26 using namespace std;
27 using namespace Ice;
28 using namespace IceInternal;
29 using namespace IceStorm;
30 
31 namespace IceStorm
32 {
33 
35 
36 #ifdef _WIN32
37  Ice::StringConverterPtr windowsConsoleConverter = 0;
38 #endif
39 
40 } // namespace IceStorm
41 
42 namespace
43 {
44 
45  class UnknownManagerException : public Exception
46  {
47  public:
48  UnknownManagerException(const string& name, const char* file, int line) :
49  Exception(file, line), name(name)
50  {
51  }
52 
53 #ifndef ICE_CPP11_COMPILER
54  virtual ~UnknownManagerException() throw()
55  {
56  }
57 #endif
58 
59  virtual string
60  ice_id() const
61  {
62  return "::UnknownManagerException";
63  }
64 
65  virtual Exception*
66  ice_clone() const
67  {
68  return new UnknownManagerException(*this);
69  }
70 
71  virtual void
72  ice_throw() const
73  {
74  throw *this;
75  }
76 
77  const string name;
78  };
79 
80 } // namespace
81 
83 Parser::createParser(const CommunicatorPtr& communicator,
84  const TopicManagerPrx& admin,
85  const map<Ice::Identity, TopicManagerPrx>& managers)
86 {
87  return new Parser(communicator, admin, managers);
88 }
89 
90 void
91 Parser::usage()
92 {
93  consoleOut
94  << "help Print this message.\n"
95  "exit, quit Exit this program.\n"
96  "create TOPICS Add TOPICS.\n"
97  "destroy TOPICS Remove TOPICS.\n"
98  "link FROM TO [COST] Link FROM to TO with the optional given COST.\n"
99  "unlink FROM TO Unlink TO from FROM.\n"
100  "links [INSTANCE-NAME] Display all links for the topics in the current topic\n"
101  " manager, or in the given INSTANCE-NAME.\n"
102  "topics [INSTANCE-NAME] Display the names of all topics in the current topic\n"
103  " manager, or in the given INSTANCE-NAME.\n"
104  "current [INSTANCE-NAME] Display the current topic manager, or change it to\n"
105  " INSTANCE-NAME.\n"
106  "replica [INSTANCE-NAME] Display replication information for the given INSTANCE-NAME.\n"
107  "subscribers TOPICS List TOPICS subscribers.\n";
108 }
109 
110 void
111 Parser::create(const list<string>& args)
112 {
113  if (args.empty())
114  {
115  error("`create' requires at least one argument (type `help' for more info)");
116  return;
117  }
118 
119  for (list<string>::const_iterator i = args.begin(); i != args.end(); ++i)
120  {
121  try
122  {
123  string topicName;
124  TopicManagerPrx manager = findManagerById(*i, topicName);
125  manager->create(topicName);
126  }
127  catch (const Ice::Exception& ex)
128  {
129  exception(
130  ex,
131  args.size() >
132  1); // Print a warning if we're creating multiple topics, an error otherwise.
133  }
134  }
135 }
136 
137 void
138 Parser::destroy(const list<string>& args)
139 {
140  if (args.empty())
141  {
142  error("`destroy' requires at least one argument (type `help' for more info)");
143  return;
144  }
145 
146  for (list<string>::const_iterator i = args.begin(); i != args.end(); ++i)
147  {
148  try
149  {
150  findTopic(*i)->destroy();
151  }
152  catch (const Ice::Exception& ex)
153  {
154  exception(
155  ex,
156  args.size() >
157  1); // Print a warning if we're destroying multiple topics, an error otherwise.
158  }
159  }
160 }
161 
162 void
163 Parser::link(const list<string>& args)
164 {
165  if (args.size() != 2 && args.size() != 3)
166  {
167  error("`link' requires two or three arguments (type `help' for more info)");
168  return;
169  }
170 
171  try
172  {
173  list<string>::const_iterator p = args.begin();
174 
175  TopicPrx fromTopic = findTopic(*p++);
176  TopicPrx toTopic = findTopic(*p++);
177  Ice::Int cost = p != args.end() ? atoi(p->c_str()) : 0;
178 
179  fromTopic->link(toTopic, cost);
180  }
181  catch (const Exception& ex)
182  {
183  exception(ex);
184  }
185 }
186 
187 void
188 Parser::unlink(const list<string>& args)
189 {
190  if (args.size() != 2)
191  {
192  error("`unlink' requires exactly two arguments (type `help' for more info)");
193  return;
194  }
195 
196  try
197  {
198  list<string>::const_iterator p = args.begin();
199 
200  TopicPrx fromTopic = findTopic(*p++);
201  TopicPrx toTopic = findTopic(*p++);
202 
203  fromTopic->unlink(toTopic);
204  }
205  catch (const Exception& ex)
206  {
207  exception(ex);
208  }
209 }
210 
211 void
212 Parser::links(const list<string>& args)
213 {
214  if (args.size() > 1)
215  {
216  error("`links' requires at most one argument (type `help' for more info)");
217  return;
218  }
219 
220  try
221  {
222  TopicManagerPrx manager;
223  if (args.size() == 0)
224  {
225  manager = _defaultManager;
226  }
227  else
228  {
229  manager = findManagerByCategory(args.front());
230  }
231 
232  TopicDict d = manager->retrieveAll();
233  for (TopicDict::iterator i = d.begin(); i != d.end(); ++i)
234  {
235  LinkInfoSeq links = i->second->getLinkInfoSeq();
236  for (LinkInfoSeq::const_iterator p = links.begin(); p != links.end(); ++p)
237  {
238  consoleOut << i->first << " to " << p->name << " with cost " << p->cost << endl;
239  }
240  }
241  }
242  catch (const Exception& ex)
243  {
244  exception(ex);
245  }
246 }
247 
248 void
249 Parser::topics(const list<string>& args)
250 {
251  if (args.size() > 1)
252  {
253  error("`topics' requires at most one argument (type `help' for more info)");
254  return;
255  }
256 
257  try
258  {
259  TopicManagerPrx manager;
260  if (args.size() == 0)
261  {
262  manager = _defaultManager;
263  }
264  else
265  {
266  manager = findManagerByCategory(args.front());
267  }
268 
269  TopicDict d = manager->retrieveAll();
270  for (TopicDict::iterator i = d.begin(); i != d.end(); ++i)
271  {
272  consoleOut << i->first << endl;
273  }
274  }
275  catch (const Exception& ex)
276  {
277  exception(ex);
278  }
279 }
280 
281 void
282 Parser::replica(const list<string>& args)
283 {
284  if (args.size() > 1)
285  {
286  error("`replica' requires at most one argument (type `help' for more info)");
287  return;
288  }
289 
290  try
291  {
292  TopicManagerPrx m;
293  if (args.size() == 0)
294  {
295  m = _defaultManager;
296  }
297  else
298  {
299  m = findManagerByCategory(args.front());
300  }
301  TopicManagerInternalPrx manager = TopicManagerInternalPrx::uncheckedCast(m);
302  IceStormElection::NodePrx node = manager->getReplicaNode();
303  if (!node)
304  {
305  error("This topic is not replicated");
306  }
307  IceStormElection::NodeInfoSeq nodes = node->nodes();
308  consoleOut << "replica count: " << nodes.size() << endl;
309  for (IceStormElection::NodeInfoSeq::const_iterator p = nodes.begin(); p != nodes.end(); ++p)
310  {
311  try
312  {
313  IceStormElection::QueryInfo info = p->n->query();
314  consoleOut << p->id << ": id: " << info.id << endl;
315  consoleOut << p->id << ": coord: " << info.coord << endl;
316  consoleOut << p->id << ": group name: " << info.group << endl;
317  consoleOut << p->id << ": state: ";
318  switch (info.state)
319  {
321  consoleOut << "inactive";
322  break;
324  consoleOut << "election";
325  break;
327  consoleOut << "reorganization";
328  break;
330  consoleOut << "normal";
331  break;
332  default:
333  consoleOut << "unknown";
334  }
335  consoleOut << endl;
336  consoleOut << p->id << ": group: ";
337  for (IceStormElection::GroupInfoSeq::const_iterator q = info.up.begin();
338  q != info.up.end();
339  ++q)
340  {
341  if (q != info.up.begin())
342  {
343  consoleOut << ",";
344  }
345  consoleOut << q->id;
346  }
347  consoleOut << endl;
348  consoleOut << p->id << ": max: " << info.max << endl;
349  }
350  catch (const Exception& ex)
351  {
352  consoleOut << p->id << ": " << ex.ice_id() << endl;
353  }
354  }
355  }
356  catch (const Exception& ex)
357  {
358  exception(ex);
359  }
360 }
361 
362 void
363 Parser::subscribers(const list<string>& args)
364 {
365  if (args.empty())
366  {
367  error("subscribers' requires at least one argument (type `help' for more info) ");
368  return;
369  }
370  try
371  {
372  for (list<string>::const_iterator i = args.begin(); i != args.end(); ++i)
373  {
374  TopicPrx topic = _defaultManager->retrieve(*i);
375  consoleOut << (*i) << ": subscribers:" << endl;
376  IdentitySeq subscribers = topic->getSubscribers();
377  for (IdentitySeq::const_iterator j = subscribers.begin(); j != subscribers.end(); ++j)
378  {
379  consoleOut << "\t" << _communicator->identityToString(*j) << endl;
380  }
381  }
382  }
383  catch (const Exception& ex)
384  {
385  exception(ex);
386  }
387 }
388 
389 void
390 Parser::current(const list<string>& args)
391 {
392  if (args.empty())
393  {
394  consoleOut << _communicator->identityToString(_defaultManager->ice_getIdentity()) << endl;
395  return;
396  }
397  else if (args.size() > 1)
398  {
399  error("`current' requires at most one argument (type `help' for more info)");
400  return;
401  }
402 
403  try
404  {
405  TopicManagerPrx manager = findManagerByCategory(args.front());
406  manager->ice_ping();
407  _defaultManager = manager;
408  }
409  catch (const Exception& ex)
410  {
411  exception(ex);
412  }
413 }
414 
415 void
416 Parser::showBanner()
417 {
418  consoleOut << "Ice " << ICE_STRING_VERSION << " Copyright (c) 2003-2017 ZeroC, Inc." << endl;
419 }
420 
421 //
422 // With older flex version <= 2.5.35 YY_INPUT second
423 // paramenter is of type int&, in newer versions it
424 // changes to size_t&
425 //
426 void
427 Parser::getInput(char* buf, int& result, size_t maxSize)
428 {
429  size_t r = static_cast<size_t>(result);
430  getInput(buf, r, maxSize);
431  result = static_cast<int>(r);
432 }
433 
434 void
435 Parser::getInput(char* buf, size_t& result, size_t maxSize)
436 {
437  if (!_commands.empty())
438  {
439  if (_commands == ";")
440  {
441  result = 0;
442  }
443  else
444  {
445  result = min(maxSize, _commands.length());
446  strncpy(buf, _commands.c_str(), result);
447  _commands.erase(0, result);
448  if (_commands.empty())
449  {
450  _commands = ";";
451  }
452  }
453  }
454  else
455  {
456 #ifdef HAVE_READLINE
457 
458  const char* prompt = parser->getPrompt();
459  char* line = readline(const_cast<char*>(prompt));
460  if (!line)
461  {
462  result = 0;
463  }
464  else
465  {
466  if (*line)
467  {
468  add_history(line);
469  }
470 
471  result = strlen(line) + 1;
472  if (result > maxSize)
473  {
474  free(line);
475  error("input line too long");
476  result = 0;
477  }
478  else
479  {
480  strcpy(buf, line);
481  strcat(buf, "\n");
482  free(line);
483  }
484  }
485 
486 #else
487 
488  consoleOut << parser->getPrompt() << flush;
489 
490  string line;
491  while (true)
492  {
493  char c = static_cast<char>(getc(yyin));
494  if (c == static_cast<char>(EOF))
495  {
496  if (line.size())
497  {
498  line += '\n';
499  }
500  break;
501  }
502 
503  line += c;
504  if (c == '\n')
505  {
506  break;
507  }
508  }
509 #ifdef _WIN32
510  if (windowsConsoleConverter)
511  {
512  line = nativeToUTF8(line, windowsConsoleConverter);
513  }
514 #endif
515  result = line.length();
516  if (result > maxSize)
517  {
518  error("input line too long");
519  buf[0] = EOF;
520  result = 1;
521  }
522  else
523  {
524  strcpy(buf, line.c_str());
525  }
526 
527 #endif
528  }
529 }
530 
531 void
532 Parser::continueLine()
533 {
534  _continue = true;
535 }
536 
537 const char*
538 Parser::getPrompt()
539 {
540  assert(_commands.empty());
541 
542  if (_continue)
543  {
544  _continue = false;
545  return "(cont) ";
546  }
547  else
548  {
549  return ">>> ";
550  }
551 }
552 
553 void
554 Parser::error(const char* s)
555 {
556  consoleErr << "error: " << s << endl;
557  _errors++;
558 }
559 
560 void
561 Parser::error(const string& s)
562 {
563  error(s.c_str());
564 }
565 
566 void
567 Parser::warning(const char* s)
568 {
569  consoleErr << "warning: " << s << endl;
570 }
571 
572 void
573 Parser::warning(const string& s)
574 {
575  warning(s.c_str());
576 }
577 
578 void
579 Parser::invalidCommand(const string& s)
580 {
581  consoleErr << s << endl;
582 }
583 
584 int
585 Parser::parse(FILE* file, bool debug)
586 {
587  yydebug = debug ? 1 : 0;
588 
589  assert(!parser);
590  parser = this;
591 
592  _errors = 0;
593  bool commands_empty = _commands.empty();
594  (void)commands_empty;
595  yyin = file;
596  assert(yyin);
597 
598  _continue = false;
599 
600  int status = yyparse();
601  if (_errors)
602  {
603  status = EXIT_FAILURE;
604  }
605 
606  parser = 0;
607  return status;
608 }
609 
610 int
611 Parser::parse(const std::string& commands, bool debug)
612 {
613  yydebug = debug ? 1 : 0;
614 
615  assert(!parser);
616  parser = this;
617 
618  _errors = 0;
619  _commands = commands;
620  assert(!_commands.empty());
621  yyin = 0;
622 
623  _continue = false;
624 
625  int status = yyparse();
626  if (_errors)
627  {
628  status = EXIT_FAILURE;
629  }
630 
631  parser = 0;
632  return status;
633 }
634 
636 Parser::findManagerById(const string& full, string& arg) const
637 {
638  Ice::Identity id = Ice::stringToIdentity(full);
639  arg = id.name;
640  if (id.category.empty())
641  {
642  return _defaultManager;
643  }
644  id.name = "TopicManager";
645  map<Ice::Identity, TopicManagerPrx>::const_iterator p = _managers.find(id);
646  if (p == _managers.end())
647  {
648  throw UnknownManagerException(id.category, __FILE__, __LINE__);
649  }
650  return p->second;
651 }
652 
654 Parser::findManagerByCategory(const string& full) const
655 {
656  Ice::Identity id;
657  id.category = full;
658  id.name = "TopicManager";
659  map<Ice::Identity, TopicManagerPrx>::const_iterator p = _managers.find(id);
660  if (p == _managers.end())
661  {
662  throw UnknownManagerException(id.category, __FILE__, __LINE__);
663  }
664  return p->second;
665 }
666 
667 TopicPrx
668 Parser::findTopic(const string& full) const
669 {
670  string topicName;
671  TopicManagerPrx manager = findManagerById(full, topicName);
672  return manager->retrieve(topicName);
673 }
674 
675 Parser::Parser(const CommunicatorPtr& communicator,
676  const TopicManagerPrx& admin,
677  const map<Ice::Identity, TopicManagerPrx>& managers) :
678  _communicator(communicator), _defaultManager(admin), _managers(managers)
679 {
680 #ifdef _WIN32
681  if (!windowsConsoleConverter)
682  {
683  windowsConsoleConverter = Ice::createWindowsStringConverter(GetConsoleOutputCP());
684  }
685 #endif
686 }
687 
688 void
689 Parser::exception(const Ice::Exception& ex, bool warn)
690 {
691  ostringstream os;
692  try
693  {
694  ex.ice_throw();
695  }
696  catch (const LinkExists& ex)
697  {
698  os << "link `" << ex.name << "' already exists";
699  }
700  catch (const NoSuchLink& ex)
701  {
702  os << "couldn't find link `" << ex.name << "'";
703  }
704  catch (const TopicExists& ex)
705  {
706  os << "topic `" << ex.name << "' exists";
707  }
708  catch (const NoSuchTopic& ex)
709  {
710  os << "couldn't find topic `" << ex.name << "'";
711  }
712  catch (const UnknownManagerException& ex)
713  {
714  os << "couldn't find IceStorm service `" << ex.name << "'";
715  }
716  catch (const IdentityParseException& ex)
717  {
718  os << "invalid identity `" << ex.str << "'";
719  }
720  catch (const Ice::LocalException& ex)
721  {
722  os << "couldn't reach IceStorm service:\n" << ex;
723  }
724  catch (const Ice::Exception& ex)
725  {
726  os << ex;
727  }
728 
729  if (warn)
730  {
731  warning(os.str());
732  }
733  else
734  {
735  error(os.str());
736  }
737 }
IceStorm
Definition: DBTypes.ice:22
IceStorm::Parser::getPrompt
const char * getPrompt()
Parser.h
IceStorm::Parser
Definition: Parser.h:55
IceStormInternal.h
IceStormElection::QueryInfo::coord
int coord
The nodes coordinator.
Definition: Election.ice:183
IceStormElection::QueryInfo
Definition: Election.ice:177
IceStormElection::QueryInfo::up
GroupInfoSeq up
The sequence of nodes in this nodes group.
Definition: Election.ice:195
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
IceStormElection::NodeStateElection
@ NodeStateElection
The node is electing a leader.
Definition: Election.ice:142
IceStorm::Parser::warning
void warning(const char *)
IceStormElection::QueryInfo::id
int id
The node id.
Definition: Election.ice:180
IceInternal::Handle<::Ice::Communicator >
armarx::status
status
Definition: FiniteStateMachine.h:244
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:570
IceStormElection::NodeStateInactive
@ NodeStateInactive
The node is inactive and awaiting an election.
Definition: Election.ice:140
IceStormElection::QueryInfo::max
int max
The highest priority node that this node has seen.
Definition: Election.ice:198
IceStormElection::QueryInfo::group
string group
The nodes group name.
Definition: Election.ice:186
armarx::BatteryState::full
@ full
armarx::flush
const LogSender::manipulator flush
Definition: LogSender.h:251
armarx::ProxyType::topic
@ topic
IceStormElection::NodeStateReorganization
@ NodeStateReorganization
The replica group is reorganizing.
Definition: Election.ice:144
IceInternal
This file is part of ArmarX.
Definition: InstrumentationI.h:16
IceStormElection::NodeStateNormal
@ NodeStateNormal
The replica group is active & replicating.
Definition: Election.ice:146
yyin
FILE * yyin
Definition: Scanner.cpp:338
q
#define q
yyparse
int yyparse()
Definition: Grammar.cpp:1086
Ice
Definition: DBTypes.cpp:63
IceStorm::parser
Parser * parser
Definition: Parser.cpp:34
std
Definition: Application.h:66
IceStormElection::QueryInfo::state
NodeState state
The node state.
Definition: Election.ice:192
IceUtil::Handle
Definition: forward_declarations.h:30
IceStormElection::NodeInfoSeq
::std::vector<::IceStormElection::NodeInfo > NodeInfoSeq
A sequence of node info.
Definition: Election.h:1264
IceInternal::ProxyHandle
Definition: ObjectPoseClientWidget.h:45
IceStorm::Parser::error
void error(const char *)
armarx::VariantType::Int
const VariantTypeId Int
Definition: Variant.h:917
yydebug
int yydebug
Definition: Grammar.cpp:755
min
T min(T t1, T t2)
Definition: gdiam.h:44
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33