JeVois  1.0
JeVois Smart Embedded Machine Vision Toolkit
Manager.C
Go to the documentation of this file.
1 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // JeVois Smart Embedded Machine Vision Toolkit - Copyright (C) 2016 by Laurent Itti, the University of Southern
4 // California (USC), and iLab at USC. See http://iLab.usc.edu and http://jevois.org for information about this project.
5 //
6 // This file is part of the JeVois Smart Embedded Machine Vision Toolkit. This program is free software; you can
7 // redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software
8 // Foundation, version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
10 // License for more details. You should have received a copy of the GNU General Public License along with this program;
11 // if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
12 //
13 // Contact information: Laurent Itti - 3641 Watt Way, HNB-07A - Los Angeles, CA 90089-2520 - USA.
14 // Tel: +1 213 740 3527 - itti@pollux.usc.edu - http://iLab.usc.edu - http://jevois.org
15 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16 /*! \file */
17 
18 // This code is inspired by the Neuromorphic Robotics Toolkit (http://nrtkit.org)
19 
22 #include <jevois/Debug/Log.H>
23 #include <unordered_map>
24 #include <fstream>
25 
26 // ######################################################################
27 jevois::Manager::Manager(std::string const & instanceID) :
28  jevois::Component(instanceID), itsGotArgs(false)
29 { }
30 
31 // ######################################################################
32 jevois::Manager::Manager(int argc, char const* argv[], std::string const & instanceID) :
33  jevois::Component(instanceID), itsCommandLineArgs((char const **)(argv), (char const **)(argv+argc)),
34  itsGotArgs(true)
35 { }
36 
37 // ######################################################################
38 void jevois::Manager::setCommandLineArgs(int argc, char const* argv[])
39 {
40  itsCommandLineArgs = std::vector<std::string>((char const **)(argv), (char const **)(argv+argc));
41  itsGotArgs = true;
42 }
43 
44 // ######################################################################
46 { }
47 
48 // ######################################################################
50 {
51  if (itsGotArgs == false)
52  LERROR("No command-line arguments given; did you forget to call jevois::Manager::setArgs()?");
53 
54  if (itsCommandLineArgs.size() > 0) itsRemainingArgs = parseCommandLine(itsCommandLineArgs);
55 }
56 
57 // ######################################################################
59 {
60  // Note: exit() tries to uninit which can deadlock since we are in init() here...
61  //if (jevois::manager::help::get()) { printHelpMessage(); std::abort(); /*exit(0);*/ } // yes this is brutal!
62 
63  if (jevois::manager::help::get()) { printHelpMessage(); LINFO("JeVois: exit after help message"); exit(0); }
64 
65  // The --help parameter is only useful for parsing of command-line arguments. After that is done, we here hide it as
66  // we will instead provide a 'help' command:
67  help::freeze();
68 
69  // Do not confuse users with a non-working tracelevel parameter if tracing has not been compiled in:
70 #if !defined(JEVOIS_TRACE_ENABLE) || !defined(JEVOIS_LDEBUG_ENABLE)
71  tracelevel::freeze();
72 #endif
73 }
74 
75 // ######################################################################
77 {
78  constructHelpMessage(std::cout);
79 }
80 
81 // ######################################################################
82 void jevois::Manager::constructHelpMessage(std::ostream & out) const
83 {
84  std::unordered_map<std::string, // category:description
85  std::unordered_map<std::string, // --name (type) default=[def]
86  std::vector<std::pair<std::string, // component name
87  std::string // current param value
88  > > > > helplist;
89  // First our own options, excluding our subs:
90  this->populateHelpMessage("", helplist, false);
91 
92  // Then all our components/modules, we call them directly instead of just recursing down from us so that the manager
93  // name is omitted from all descriptors:
94  {
95  boost::shared_lock<boost::shared_mutex> lck(itsSubMtx);
96  for (std::shared_ptr<jevois::Component> c : itsSubComponents) c->populateHelpMessage("", helplist);
97  }
98 
99  // Helplist should never be empty since the Manager has options, but in any case...
100  if (helplist.empty()) { out << "NO PARAMETERS."; return; }
101 
102  out << "PARAMETERS:" << std::endl << std::endl;
103 
104  for (auto & c : helplist)
105  {
106  // Print out the category name and description
107  out << c.first << std::endl;
108 
109  // Print out the parameter details
110  for (auto const & n : c.second)
111  {
112  out << n.first << std::endl;
113 
114  // Print out the name of each component that exports this parameter definition, but strip the manager's name for
115  // brevity, unless that's the only thing in the descriptor:
116  out << " Exported By: ";
117  for (auto const & cp : n.second) // pair: <component, value>
118  {
119  out << cp.first; // component descriptor
120  if (cp.second.empty() == false) out << ' ' << cp.second; // value
121  if (cp != *(n.second.end()-1)) out << ", ";
122  }
123 
124  out << std::endl;
125  out << std::endl;
126  }
127  out << std::endl;
128  }
129  out << std::flush;
130 }
131 
132 // ######################################################################
133 std::vector<std::string> const jevois::Manager::parseCommandLine(std::vector<std::string> const & commandLineArgs)
134 {
135  // Start by pushing the program name into remaining args
136  std::vector<std::string> remainingArgs;
137  remainingArgs.push_back(commandLineArgs[0]);
138 
139  // process all the -- args, push other things into remaining args:
140  std::vector<std::string>::const_iterator argIt;
141  for (argIt = commandLineArgs.begin() + 1; argIt != commandLineArgs.end(); ++argIt)
142  {
143  // All arguments should start with "--", store as remaining arg anything that does not:
144  if (argIt->length() < 2 || (*argIt)[0] != '-' || (*argIt)[1] != '-') { remainingArgs.push_back(*argIt); continue; }
145 
146  // If the argument is just a lone "--", then we are done with command line parsing:
147  if (*argIt == "--") break;
148 
149  // Split the string by "=" to separate the parameter name from the value
150  size_t const equalsPos = argIt->find_first_of('=');
151  if (equalsPos < 3) LFATAL("Cannot parse command-line argument with no name [" << *argIt << ']');
152 
153  std::string const parameterName = argIt->substr(2, equalsPos - 2);
154  std::string const parameterValue = (equalsPos == std::string::npos) ? "true" : argIt->substr(equalsPos + 1);
155 
156  // Set the parameter recursively, will throw if not found, and here we allow multiple matches and set all matching
157  // parameters to the given value:
158  setParamString(parameterName, parameterValue);
159  }
160 
161  // Add anything after a lone -- to the remaining args:
162  while (argIt != commandLineArgs.end()) { remainingArgs.push_back(*argIt); ++argIt; }
163 
164  return remainingArgs;
165 }
166 
167 // ######################################################################
168 std::vector<std::string> const & jevois::Manager::remainingArgs() const
169 { return itsRemainingArgs; }
170 
171 // ######################################################################
172 void jevois::Manager::removeComponent(std::string const & instance, bool warnIfNotFound)
173 {
174  // Keep this code in sync with Componnet::removeSubComponent
175 
176  boost::upgrade_lock<boost::shared_mutex> uplck(itsSubMtx);
177 
178  for (auto itr = itsSubComponents.begin(); itr != itsSubComponents.end(); ++itr)
179  if ((*itr)->instanceName() == instance)
180  {
181  doRemoveSubComponent(itr, uplck, "Component");
182  return;
183  }
184 
185  if (warnIfNotFound) LERROR("Component [" << instance << "] not found. Ignored.");
186 }
187 // BEGIN_JEVOIS_CODE_SNIPPET manager3.C
188 
189 // ######################################################################
190 void jevois::Manager::onParamChange(jevois::manager::loglevel const & JEVOIS_UNUSED_PARAM(param),
191  jevois::manager::LogLevel const & newval)
192 {
193  switch(newval)
194  {
195  case jevois::manager::LogLevel::fatal: jevois::logLevel = LOG_CRIT; break;
196  case jevois::manager::LogLevel::error: jevois::logLevel = LOG_ERR; break;
197  case jevois::manager::LogLevel::info: jevois::logLevel = LOG_INFO; break;
198 #ifdef JEVOIS_LDEBUG_ENABLE
199  case jevois::manager::LogLevel::debug: jevois::logLevel = LOG_DEBUG; break;
200 #endif
201  }
202 }
203 
204 // ######################################################################
205 void jevois::Manager::onParamChange(jevois::manager::tracelevel const & JEVOIS_UNUSED_PARAM(param),
206  unsigned int const & newval)
207 {
208  if (newval)
209  {
210 #if !defined(JEVOIS_TRACE_ENABLE) || !defined(JEVOIS_LDEBUG_ENABLE)
211  LERROR("Debug trace has been disabled at compile-time, re-compile with -DJEVOIS_LDEBUG_ENABLE=ON and "
212  "-DJEVOIS_TRACE_ENABLE=ON to see trace info");
213 #endif
214  }
215 
216  jevois::traceLevel = newval;
217 }
218 
219 // END_JEVOIS_CODE_SNIPPET
void setCommandLineArgs(int argc, char const *argv[])
Set the command-line arguments, call this before start() if args were not passed at construction...
Definition: Manager.C:38
void preInit() override
Calls parseCommandLine()
Definition: Manager.C:49
void printHelpMessage() const
Constructs a help message and tries to send it to /usr/bin/less.
Definition: Manager.C:76
void onParamChange(manager::loglevel const &param, manager::LogLevel const &newval)
Parameter callback.
A component of a model hierarchy.
Definition: Component.H:176
void removeComponent(std::shared_ptr< Comp > &component)
Remove a top-level Component from the Manager, by shared_ptr.
Definition: ManagerImpl.H:100
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level. ...
Definition: Log.H:186
std::vector< std::string > const & remainingArgs() const
Get the remaining arguments that were not parsed by the command line.
Definition: Manager.C:168
int logLevel
Current log level.
Definition: Log.C:26
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level. ...
Definition: Log.H:205
int traceLevel
Current trace level.
Definition: Log.C:27
void postInit() override
Checks for the –help flag.
Definition: Manager.C:58
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
Definition: Log.H:169
void constructHelpMessage(std::ostream &out) const
Constructs a help message from all parameters in the model, and outputs it to 'out'.
Definition: Manager.C:82
virtual ~Manager()
Destructor.
Definition: Manager.C:45
Manager(std::string const &instance="TheManager")
Constructor without command-line args.
Definition: Manager.C:27