ModuleManager.cpp
Go to the documentation of this file.
1 // -*- C++ -*-
20 #include <rtm/RTC.h>
21 
22 #include <coil/File.h>
23 #include <coil/Process.h>
24 
25 // RTC includes
26 #include <rtm/Manager.h>
27 #include <rtm/ModuleManager.h>
28 #include <coil/stringutil.h>
29 
30 #ifdef __QNX__
31 using std::FILE;
32 using std::fgets;
33 using std::feof;
34 #endif
35 
36 namespace RTC
37 {
38 
47  : rtclog("ModuleManager"), m_properties(prop)
48  {
49  m_configPath = coil::split(prop[CONFIG_PATH], ",");
51  m_loadPath = coil::split(prop[MOD_LOADPTH], ",");
52  for_each(m_loadPath.begin(), m_loadPath.end(), coil::eraseHeadBlank);
53  m_absoluteAllowed = coil::toBool(prop[ALLOW_ABSPATH], "yes", "no", false);
54  m_downloadAllowed = coil::toBool(prop[ALLOW_URL], "yes", "no", false);
57  }
58 
67  {
68  unloadAll();
69  }
70 
78  std::string ModuleManager::load(const std::string& file_name)
79  {
80  RTC_TRACE(("load(fname = %s)", file_name.c_str()));
81  if (file_name == "") throw InvalidArguments("Invalid file name.");
82 
83  if (coil::isURL(file_name))
84  {
85  if (!m_downloadAllowed)
86  {
87  RTC_ERROR(("Downloading module is not allowed."));
88  throw NotAllowedOperation("Downloading module is not allowed.");
89  }
90  else
91  {
92  throw NotFound("Not implemented.");
93  }
94  }
95 
96  // Find local file from load path or absolute directory
97  std::string file_path;
98  if (coil::isAbsolutePath(file_name))
99  {
100  if (!m_absoluteAllowed)
101  {
102  RTC_ERROR(("Absolute path is not allowed"));
103  throw NotAllowedOperation("Absolute path is not allowed");
104  }
105  else
106  {
107  file_path = file_name;
108  }
109  }
110  else
111  {
112  file_path = findFile(file_name, m_loadPath);
113  }
114 
115  // Now file_name is valid full path to module
116  if (file_path == "")
117  {
118  RTC_ERROR(("Invalid file name: Empty file name."));
119  throw InvalidArguments("Invalid file name.");
120  }
121  if (!fileExist(file_path))
122  {
123  RTC_ERROR(("Module file not found: %s", file_path.c_str()));
124  throw FileNotFound(file_path.c_str());
125  }
126 
127  DLLEntity* dll(new DLLEntity());
128 
129  int retval = dll->dll.open(file_path.c_str());
130  if (retval != 0)
131  {
132  RTC_ERROR(("Module file %s load failed: %s",
133  file_path.c_str(), dll->dll.error()));
134  delete dll;
135  throw Error("DLL open failed.");
136  }
137  dll->properties["file_path"] = file_path;
138  bool ret = m_modules.registerObject(dll);
139  if (!ret)
140  {
141  RTC_ERROR(("Module registration failed: %s", file_path.c_str()));
142  delete dll;
143  }
144 
145  return file_path;
146  }
147 
155  std::string ModuleManager::load(const std::string& file_name,
156  const std::string& init_func)
157  {
158  RTC_TRACE(("load(fname = %s, init_func = %s)",
159  file_name.c_str(), init_func.c_str()));
160  std::string name;
161  name = load(file_name);
162 
163  if (name == "")
164  {
165  throw InvalidOperation("Invalid file name");
166  }
167 
168  // if (!init_func)
169 
170  ModuleInitFunc init;
171 
172  init = (ModuleInitFunc)this->symbol(name.c_str(), init_func);
173 
174  init(&(Manager::instance()));
175 
176  return name;
177  }
178 
186  void ModuleManager::unload(const std::string& file_name)
187  {
188  DLLEntity* dll(m_modules.find(file_name.c_str()));
189  if (dll == NULL)
190  throw NotFound(file_name.c_str());
191 
192  dll->dll.close();
193  m_modules.unregisterObject(file_name.c_str());
194 
195  if (dll != NULL) {
196  delete dll;
197  }
198 
199  return;
200  }
201 
210  {
211  RTC_TRACE(("unloadAll()"));
212  std::vector<DLLEntity*> dlls(m_modules.getObjects());
213 
214  for (int i(0), len(dlls.size()); i < len; ++i)
215  {
216  std::string ident(dlls[i]->properties["file_path"]);
217  DLLEntity* dll(m_modules.unregisterObject(ident.c_str()));
218  dll->dll.close();
219  }
220  return;
221  }
222 
230  void* ModuleManager::symbol(const std::string& file_name,
231  const std::string& func_name)
233  {
234  RTC_TRACE(("symbol(%s, %s)",
235  file_name.c_str(), func_name.c_str()))
236  // "file_name" should be in modules map.
237  DLLEntity* dll(m_modules.find(file_name.c_str()));
238  if (dll == NULL)
239  {
240  RTC_ERROR(("Module %s not found in module table.", file_name.c_str()));
241  throw ModuleNotFound(file_name);
242  }
243 
244  RTC_DEBUG(("Finding function symbol: %s in %s",
245  func_name.c_str(), file_name.c_str()));
246  void* func;
247  func = dll->dll.symbol(func_name.c_str());
248 
249  if (!func)
250  {
251  RTC_ERROR(("Specified symbol %s not found.", func_name.c_str()));
252  throw SymbolNotFound(func_name);
253  }
254 
255  return func;
256  }
257 
265  void ModuleManager::setLoadpath(const std::vector<std::string>& load_path)
266  {
267  RTC_TRACE(("setLoadpath(%s)", coil::flatten(load_path).c_str()));
268  m_loadPath = load_path;
269  return;
270  }
271 
279  void ModuleManager::addLoadpath(const std::vector<std::string>& load_path)
280  {
281  RTC_TRACE(("addLoadpath(%s)", coil::flatten(load_path).c_str()));
282  StringVectorConstItr it(load_path.begin());
283  StringVectorConstItr it_end(load_path.end());
284 
285  while (it != it_end)
286  {
287  m_loadPath.push_back(*it);
288  ++it;
289  }
290 
291  return;
292  }
293 
301  std::vector<coil::Properties> ModuleManager::getLoadedModules()
302  {
303  RTC_TRACE(("getLoadedModules()"));
304  std::vector< DLLEntity* > dlls(m_modules.getObjects());
305  std::vector<coil::Properties> modules;
306  for (int i(0), len(dlls.size()); i < len; ++i)
307  {
308  modules.push_back(dlls[i]->properties);
309  }
310  return modules;
311  }
312 
320  std::vector<coil::Properties> ModuleManager::getLoadableModules()
321  {
322  RTC_TRACE(("getLoadableModules()"));
323 
324  // getting loadable module file path list.
325  coil::Properties& gprop(Manager::instance().getConfig());
326  coil::vstring langs(coil::split(gprop["manager.supported_languages"], ","));
327  RTC_DEBUG(("langs: %s", gprop["manager.supported_languages"].c_str()));
328 
329  // for each languages
330  for (size_t l(0); l < langs.size(); ++l)
331  {
332  // 1. getting loadable files list
333  coil::vstring modules;
334  getModuleList(langs[l], modules);
335  RTC_DEBUG(("%s: %s", langs[l].c_str(), coil::flatten(modules).c_str()));
336 
337  // 2. getting module properties from loadable modules
338  vProperties tmpprops;
339  getModuleProfiles(langs[l], modules, tmpprops);
340  RTC_DEBUG(("Modile profile size: %d (newly founded modules)",
341  tmpprops.size()));
342  m_modprofs.insert(m_modprofs.end(), tmpprops.begin(), tmpprops.end());
343  }
344  RTC_DEBUG(("Modile profile size: %d", m_modprofs.size()));
345  // 3. removing module profiles for which module file does not exist
347  RTC_DEBUG(("Modile profile size: %d (invalid mod-profiles deleted)",
348  m_modprofs.size()));
349  return m_modprofs;
350  }
351 
359  std::string ModuleManager::findFile(const std::string& fname,
360  const std::vector<std::string>& load_path)
361  {
362  RTC_TRACE(("findFile(%s, %s)", fname.c_str(),
363  coil::flatten(load_path).c_str()));
364  StringVectorConstItr it, it_end;
365  std::string file_name(fname);
366 
367  it = load_path.begin();
368  it_end = load_path.end();
369 
370  while (it != it_end)
371  {
372  std::string f((*it) + "/" + file_name);
373  if (fileExist(f))
374  {
375  return f;
376  }
377  ++it;
378  }
379 
380  return std::string("");
381  }
382 
390  bool ModuleManager::fileExist(const std::string& filename)
391  {
392  RTC_TRACE(("fileExist(%s)", filename.c_str()));
393  std::ifstream infile;
394  infile.open(filename.c_str(), std::ios::in);
395  // fial() 0: ok, !0: fail
396  if (infile.fail() != 0)
397  {
398  infile.close();
399  return false;
400  }
401  else
402  {
403  infile.close();
404  return true;
405  }
406 
407  return false;
408  }
409 
417  std::string ModuleManager::getInitFuncName(const std::string& file_path)
418  {
419  RTC_TRACE(("getInitFuncName(%s)", file_path.c_str()));
420  std::string base_name(coil::basename(file_path.c_str()));
421 
422  return m_initFuncPrefix + base_name + m_initFuncSuffix;
423  }
424 
425 
434  {
435  std::vector<coil::Properties>::iterator it(m_modprofs.begin());
436 
437  while (it < m_modprofs.end())
438  {
439  if (!fileExist((*it)["module_file_path"]))
440  {
441  it = m_modprofs.erase(it);
442  }
443  ++it;
444  }
445  }
446 
454  void ModuleManager::getModuleList(const std::string& lang,
455  coil::vstring& modules)
456  {
457  std::string l = "manager.modules." + lang;
458  coil::Properties& lprop(Manager::instance().getConfig().getNode(l));
459 
460  // load path: manager.modules.<lang>.load_path + manager.modules.load_path
461  coil::vstring paths(coil::split(lprop["load_paths"], ","));
462  paths.insert(paths.end(), m_loadPath.begin(), m_loadPath.end());
463 
464  coil::vstring suffixes(coil::split(lprop["suffixes"], ","));
465  RTC_DEBUG(("suffixes: %s", coil::flatten(suffixes).c_str()));
466 
467  // for each load path list
468  for (size_t i(0); i < paths.size(); ++i)
469  {
470  if (paths[i].empty())
471  {
472  RTC_WARN(("Given load path is empty"));
473  continue;
474  }
475  std::string& path(paths[i]);
476  RTC_DEBUG(("Module load path: %s", path.c_str()));
477 
478  // get file list for each suffixes
480  for (size_t s(0); s < suffixes.size(); ++s)
481  {
482  std::string glob("*."); glob += suffixes[s];
483  coil::vstring tmp = coil::filelist(path.c_str(), glob.c_str());
484  RTC_DEBUG(("File list (path:%s, ext:%s): %s", path.c_str(),
485  suffixes[s].c_str(), coil::flatten(tmp).c_str()));
486  flist.insert(flist.end(), tmp.begin(), tmp.end());
487  }
488 
489  // reformat file path and remove cached files
490  for (size_t j(0); j < flist.size(); ++j)
491  {
492  if (*(path.end() - 1) != '/') { path += "/"; }
493  std::string fpath(path + flist[j]);
494  addNewFile(fpath, modules);
495  }
496  }
497  }
498 
506  void ModuleManager::addNewFile(const std::string& fpath,
507  coil::vstring& modules)
508  {
509  bool exists(false);
510  for (size_t k(0); k < m_modprofs.size(); ++k)
511  {
512  if (m_modprofs[k]["module_file_path"] == fpath)
513  {
514  exists = true;
515  RTC_DEBUG(("Module %s already exists in cache.",
516  fpath.c_str()));
517  break;
518  }
519  }
520  if (!exists)
521  {
522  RTC_DEBUG(("New module: %s", fpath.c_str()));
523  modules.push_back(fpath);
524  }
525  }
526 
534  void ModuleManager::getModuleProfiles(const std::string& lang,
535  const coil::vstring& modules,
536  vProperties& modprops)
537  {
538  std::string l = "manager.modules." + lang;
539  coil::Properties& lprop(Manager::instance().getConfig().getNode(l));
540  std::vector<coil::Properties> prop;
541 
542  for (size_t i(0), len(modules.size()); i < len; ++i)
543  {
544  std::string cmd(lprop["profile_cmd"]);
545  cmd += " \"" + modules[i] + "\"";
546  FILE* fd;
547  if ((fd = popen(cmd.c_str(), "r")) == NULL)
548  {
549  std::cerr << "popen faild" << std::endl;
550  continue;
551  }
553  do
554  {
555  char str[512];
556  fgets(str, 512, fd);
557  std::string line(str);
558  if (0 < line.size())
559  line.erase(line.size() - 1);
560  std::string::size_type pos(line.find(":"));
561  if (pos != std::string::npos)
562  {
563  std::string key(line.substr(0, pos));
565  p[key] = line.substr(pos + 1);
566  coil::eraseBothEndsBlank(p[key]);
567  }
568  } while (!feof(fd));
569  pclose(fd);
570  RTC_DEBUG(("rtcprof cmd sub process done."));
571  if (p["implementation_id"].empty()) { continue; }
572  p["module_file_name"] = coil::basename(modules[i].c_str());
573  p["module_file_path"] = modules[i].c_str();
574  modprops.push_back(p);
575  }
576  }
577 }; // namespace RTC
void * symbol(const std::string &file_name, const std::string &func_name)
Refer to the symbol of the module.
void(* ModuleInitFunc)(Manager *)
Structure for exception handling of unimplemented part and specified module missing.
std::vector< coil::Properties > vProperties
Definition: ModuleManager.h:76
#define RTC_ERROR(fmt)
Error log output macro.
Definition: SystemLogger.h:422
#define MOD_LOADPTH
Definition: ModuleManager.h:40
std::string getInitFuncName(const std::string &file_path)
Create initialization function symbol.
bool m_absoluteAllowed
Flag of absolute path when specify module for the load.
RT-Component.
Structure for exception handling when file open is failed.
void addLoadpath(const std::vector< std::string > &load_path)
Add the module load path.
~ModuleManager(void)
Destructor.
std::vector< coil::Properties > getLoadableModules()
Get the loadable module list.
list flist
Definition: omniwxs.py:84
void * symbol(const char *symbol_name)
Return an address of the memory where a symbol was loaded.
ObjectManager< const char *, DLLEntity, DllPred > m_modules
Module list that has already loaded.
#define CONFIG_PATH
Definition: ModuleManager.h:38
void setLoadpath(const std::vector< std::string > &load_path)
Set the module load path.
RTC::ReturnCode_t ret(RTC::Local::ReturnCode_t r)
void eraseHeadBlank(std::string &str)
Erase the head blank characters of string.
Definition: stringutil.cpp:267
vstring split(const std::string &input, const std::string &delimiter, bool ignore_empty)
Split string by delimiter.
Definition: stringutil.cpp:346
Structure for exception handling when specified symbol cannot be found.
std::string load(const std::string &file_name)
Load the module.
std::vector< coil::Properties > getLoadedModules()
Get the module list that has been loaded.
static Manager & instance()
Get instance of the manager.
Definition: Manager.cpp:140
#define ALLOW_URL
Definition: ModuleManager.h:44
void eraseBothEndsBlank(std::string &str)
Erase the head blank and the tail blank characters of string.
Definition: stringutil.cpp:295
#define RTC_WARN(fmt)
Warning log output macro.
Definition: SystemLogger.h:444
#define INITFUNC_SFX
Definition: ModuleManager.h:41
RTComponent manager class.
bool isAbsolutePath(const std::string &str)
Investigate whether the given string is absolute path or not.
Definition: stringutil.cpp:470
bool m_downloadAllowed
Flag of URL when specify module for the load.
Structure for exception handling when specified operation is invalid.
std::vector< std::string > vstring
Definition: stringutil.h:37
StringVector m_loadPath
Module load path list.
list cmd
Definition: omniwxs.py:88
StringVector m_configPath
Configuration path list.
Structure for exception handling when specified argument is invalid.
#define RTC_DEBUG(fmt)
Debug level log output macro.
Definition: SystemLogger.h:488
bool fileExist(const std::string &filename)
Check whether the file exists.
void addNewFile(const std::string &fpath, coil::vstring &modules)
Adding file path not existing cache.
std::string flatten(vstring sv)
Create CSV file from the given string list.
Definition: stringutil.cpp:554
#define RTC_TRACE(fmt)
Structure for exception handling when specified module cannot be found.
bool isURL(const std::string &str)
Investigate whether the given string is URL or not.
Definition: stringutil.cpp:489
Loadable modules manager class.
void removeInvalidModules()
Removing incalid module profiles.
FILE * popen(const char *cmd, const char *mode)
coil::vstring filelist(const char *path, const char *glob_str="")
Get file list.
prop
Organization::get_organization_property ();.
vProperties m_modprofs
Class represents a set of properties.
Definition: Properties.h:101
void unloadAll()
Unload all modules.
bool toBool(std::string str, std::string yes, std::string no, bool default_value)
Convert given string into bool value.
Definition: stringutil.cpp:415
Structure for exception handling when specified file cannot be found.
StringVector::const_iterator StringVectorConstItr
Structure for DLL management.
void unload(const std::string &file_name)
Unload the module.
virtual int close(void)
Unload of the Dynamic link library.
RTComponent header.
ModuleManager(coil::Properties &prop)
Constructor.
const char * basename(const char *path)
Get a file name part than a file pass.
Definition: ace/coil/File.h:33
void getModuleProfiles(const std::string &lang, const coil::vstring &modules, vProperties &modprops)
Getting module properties from given language and file list.
std::string findFile(const std::string &fname, const std::vector< std::string > &load_path)
Search the file from the LoadPath.
void pclose(FILE *fd)
void getModuleList(const std::string &lang, coil::vstring &modules)
Getting loadable file list on the loadpath for given language.
std::string m_initFuncSuffix
Initial execution function suffix.
#define INITFUNC_PFX
Definition: ModuleManager.h:42
Structure for exception handling when specified operation cannot be allowed.
Functor for_each(CorbaSequence &seq, Functor f)
Apply the functor to all CORBA sequence elements.
Definition: CORBA_SeqUtil.h:98
std::string m_initFuncPrefix
Initial execution function prefix.
#define ALLOW_ABSPATH
Definition: ModuleManager.h:43


openrtm_aist
Author(s): Noriaki Ando
autogenerated on Mon Feb 28 2022 23:00:43