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 namespace RTC
31 {
32 
41  : rtclog("ModuleManager"), m_properties(prop)
42  {
43  m_configPath = coil::split(prop[CONFIG_PATH], ",");
45  m_loadPath = coil::split(prop[MOD_LOADPTH], ",");
46  for_each(m_loadPath.begin(), m_loadPath.end(), coil::eraseHeadBlank);
47  m_absoluteAllowed = coil::toBool(prop[ALLOW_ABSPATH], "yes", "no", false);
48  m_downloadAllowed = coil::toBool(prop[ALLOW_URL], "yes", "no", false);
51  }
52 
61  {
62  unloadAll();
63  }
64 
72  std::string ModuleManager::load(const std::string& file_name)
73  {
74  RTC_TRACE(("load(fname = %s)", file_name.c_str()));
75  if (file_name == "") throw InvalidArguments("Invalid file name.");
76 
77  if (coil::isURL(file_name))
78  {
79  if (!m_downloadAllowed)
80  {
81  throw NotAllowedOperation("Downloading module is not allowed.");
82  }
83  else
84  {
85  throw NotFound("Not implemented.");
86  }
87  }
88 
89  // Find local file from load path or absolute directory
90  std::string file_path;
91  if (coil::isAbsolutePath(file_name))
92  {
93  if (!m_absoluteAllowed)
94  {
95  throw NotAllowedOperation("Absolute path is not allowed");
96  }
97  else
98  {
99  file_path = file_name;
100  }
101  }
102  else
103  {
104  file_path = findFile(file_name, m_loadPath);
105  }
106 
107  // Now file_name is valid full path to module
108  if (file_path == "") throw InvalidArguments("Invalid file name.");
109  if (!fileExist(file_path)) throw FileNotFound(file_path.c_str());
110 
111  DLLEntity* dll(new DLLEntity());
112 
113  int retval = dll->dll.open(file_path.c_str());
114  if (retval != 0)
115  {
116  delete dll;
117  throw Error("DLL open failed.");
118  }
119  dll->properties["file_path"] = file_path;
120  bool ret = m_modules.registerObject(dll);
121  if (!ret) {
122  delete dll;
123  }
124 
125  return file_path;
126  }
127 
135  std::string ModuleManager::load(const std::string& file_name,
136  const std::string& init_func)
137  {
138  RTC_TRACE(("load(fname = %s, init_func = %s)",
139  file_name.c_str(), init_func.c_str()));
140  std::string name;
141  name = load(file_name);
142 
143  if (name == "")
144  {
145  throw InvalidOperation("Invalid file name");
146  }
147 
148  // if (!init_func)
149 
150  ModuleInitFunc init;
151 
152  init = (ModuleInitFunc)this->symbol(name.c_str(), init_func);
153 
154  init(&(Manager::instance()));
155 
156  return name;
157  }
158 
166  void ModuleManager::unload(const std::string& file_name)
167  {
168  DLLEntity* dll(m_modules.find(file_name.c_str()));
169  if (dll == NULL)
170  throw NotFound(file_name.c_str());
171 
172  dll->dll.close();
173  m_modules.unregisterObject(file_name.c_str());
174 
175  if (dll != NULL) {
176  delete dll;
177  }
178 
179  return;
180  }
181 
190  {
191  std::vector<DLLEntity*> dlls(m_modules.getObjects());
192 
193  for (int i(0), len(dlls.size()); i < len; ++i)
194  {
195  std::string ident(dlls[i]->properties["file_path"]);
196  DLLEntity* dll(m_modules.unregisterObject(ident.c_str()));
197  dll->dll.close();
198  }
199  return;
200  }
201 
209  void* ModuleManager::symbol(const std::string& file_name,
210  const std::string& func_name)
212  {
213  // "file_name" should be in modules map.
214  DLLEntity* dll(m_modules.find(file_name.c_str()));
215  if (dll == NULL)
216  {
217  throw ModuleNotFound(file_name);
218  }
219 
220  void* func;
221  func = dll->dll.symbol(func_name.c_str());
222 
223  if (!func)
224  {
225  throw SymbolNotFound(func_name);
226  }
227 
228  return func;
229  }
230 
238  void ModuleManager::setLoadpath(const std::vector<std::string>& load_path)
239  {
240  m_loadPath = load_path;
241  return;
242  }
243 
251  void ModuleManager::addLoadpath(const std::vector<std::string>& load_path)
252  {
253  StringVectorConstItr it(load_path.begin());
254  StringVectorConstItr it_end(load_path.end());
255 
256  while (it != it_end)
257  {
258  m_loadPath.push_back(*it);
259  ++it;
260  }
261 
262  return;
263  }
264 
272  std::vector<coil::Properties> ModuleManager::getLoadedModules()
273  {
274  std::vector< DLLEntity* > dlls(m_modules.getObjects());
275  std::vector<coil::Properties> modules;
276  for (int i(0), len(dlls.size()); i < len; ++i)
277  {
278  modules.push_back(dlls[i]->properties);
279  }
280  return modules;
281  }
282 
290  std::vector<coil::Properties> ModuleManager::getLoadableModules()
291  {
292  RTC_TRACE(("getLoadableModules()"));
293 
294  // getting loadable module file path list.
295  coil::Properties& gprop(Manager::instance().getConfig());
296  coil::vstring langs(coil::split(gprop["manager.supported_languages"], ","));
297  RTC_DEBUG(("langs: %s", gprop["manager.supported_languages"].c_str()));
298 
299  // for each languages
300  for (size_t l(0); l < langs.size(); ++l)
301  {
302  // 1. getting loadable files list
303  coil::vstring modules;
304  getModuleList(langs[l], modules);
305  RTC_DEBUG(("%s: %s", langs[l].c_str(), coil::flatten(modules).c_str()));
306 
307  // 2. getting module properties from loadable modules
308  vProperties tmpprops;
309  getModuleProfiles(langs[l], modules, tmpprops);
310  RTC_DEBUG(("Modile profile size: %d (newly founded modules)",
311  tmpprops.size()));
312  m_modprofs.insert(m_modprofs.end(), tmpprops.begin(), tmpprops.end());
313  }
314  RTC_DEBUG(("Modile profile size: %d", m_modprofs.size()));
315  // 3. removing module profiles for which module file does not exist
317  RTC_DEBUG(("Modile profile size: %d (invalid mod-profiles deleted)",
318  m_modprofs.size()));
319  return m_modprofs;
320  }
321 
329  std::string ModuleManager::findFile(const std::string& fname,
330  const std::vector<std::string>& load_path)
331  {
332  StringVectorConstItr it, it_end;
333  std::string file_name(fname);
334 
335  it = load_path.begin();
336  it_end = load_path.end();
337 
338  while (it != it_end)
339  {
340  std::string f((*it) + "/" + file_name);
341  if (fileExist(f))
342  {
343  return f;
344  }
345  ++it;
346  }
347 
348  return std::string("");
349  }
350 
358  bool ModuleManager::fileExist(const std::string& filename)
359  {
360  std::ifstream infile;
361  infile.open(filename.c_str(), std::ios::in);
362  // fial() 0: ok, !0: fail
363  if (infile.fail() != 0)
364  {
365  infile.close();
366  return false;
367  }
368  else
369  {
370  infile.close();
371  return true;
372  }
373 
374  return false;
375  }
376 
384  std::string ModuleManager::getInitFuncName(const std::string& file_path)
385  {
386  std::string base_name(coil::basename(file_path.c_str()));
387 
388  return m_initFuncPrefix + base_name + m_initFuncSuffix;
389  }
390 
391 
400  {
401  std::vector<coil::Properties>::iterator it(m_modprofs.begin());
402 
403  while (it < m_modprofs.end())
404  {
405  if (!fileExist((*it)["module_file_path"]))
406  {
407  it = m_modprofs.erase(it);
408  }
409  ++it;
410  }
411  }
412 
420  void ModuleManager::getModuleList(const std::string& lang,
421  coil::vstring& modules)
422  {
423  std::string l = "manager.modules." + lang;
424  coil::Properties& lprop(Manager::instance().getConfig().getNode(l));
425 
426  // load path: manager.modules.<lang>.load_path + manager.modules.load_path
427  coil::vstring paths(coil::split(lprop["load_paths"], ","));
428  paths.insert(paths.end(), m_loadPath.begin(), m_loadPath.end());
429 
430  coil::vstring suffixes(coil::split(lprop["suffixes"], ","));
431  RTC_DEBUG(("suffixes: %s", coil::flatten(suffixes).c_str()));
432 
433  // for each load path list
434  for (size_t i(0); i < paths.size(); ++i)
435  {
436  if (paths[i].empty())
437  {
438  RTC_WARN(("Given load path is empty"));
439  continue;
440  }
441  std::string& path(paths[i]);
442  RTC_DEBUG(("Module load path: %s", path.c_str()));
443 
444  // get file list for each suffixes
446  for (size_t s(0); s < suffixes.size(); ++s)
447  {
448  std::string glob("*."); glob += suffixes[s];
449  coil::vstring tmp = coil::filelist(path.c_str(), glob.c_str());
450  RTC_DEBUG(("File list (path:%s, ext:%s): %s", path.c_str(),
451  suffixes[s].c_str(), coil::flatten(tmp).c_str()));
452  flist.insert(flist.end(), tmp.begin(), tmp.end());
453  }
454 
455  // reformat file path and remove cached files
456  for (size_t j(0); j < flist.size(); ++j)
457  {
458  if (*(path.end() - 1) != '/') { path += "/"; }
459  std::string fpath(path + flist[j]);
460  addNewFile(fpath, modules);
461  }
462  }
463  }
464 
472  void ModuleManager::addNewFile(const std::string& fpath,
473  coil::vstring& modules)
474  {
475  bool exists(false);
476  for (size_t k(0); k < m_modprofs.size(); ++k)
477  {
478  if (m_modprofs[k]["module_file_path"] == fpath)
479  {
480  exists = true;
481  RTC_DEBUG(("Module %s already exists in cache.",
482  fpath.c_str()));
483  break;
484  }
485  }
486  if (!exists)
487  {
488  RTC_DEBUG(("New module: %s", fpath.c_str()));
489  modules.push_back(fpath);
490  }
491  }
492 
500  void ModuleManager::getModuleProfiles(const std::string& lang,
501  const coil::vstring& modules,
502  vProperties& modprops)
503  {
504  std::string l = "manager.modules." + lang;
505  coil::Properties& lprop(Manager::instance().getConfig().getNode(l));
506  std::vector<coil::Properties> prop;
507 
508  for (size_t i(0), len(modules.size()); i < len; ++i)
509  {
510  std::string cmd(lprop["profile_cmd"]);
511  cmd += " \"" + modules[i] + "\"";
512  FILE* fd;
513  if ((fd = popen(cmd.c_str(), "r")) == NULL)
514  {
515  std::cerr << "popen faild" << std::endl;
516  continue;
517  }
519  do
520  {
521  char str[512];
522  fgets(str, 512, fd);
523  std::string line(str);
524  line.erase(line.size() - 1);
525  std::string::size_type pos(line.find(":"));
526  if (pos != std::string::npos)
527  {
528  std::string key(line.substr(0, pos));
530  p[key] = line.substr(pos + 1);
531  coil::eraseBothEndsBlank(p[key]);
532  }
533  } while (!feof(fd));
534  pclose(fd);
535  RTC_DEBUG(("rtcprof cmd sub process done."));
536  if (p["implementation_id"].empty()) { continue; }
537  p["module_file_name"] = coil::basename(modules[i].c_str());
538  p["module_file_path"] = modules[i].c_str();
539  modprops.push_back(p);
540  }
541  }
542 }; // 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 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:262
vstring split(const std::string &input, const std::string &delimiter, bool ignore_empty)
Split string by delimiter.
Definition: stringutil.cpp:341
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:290
#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:465
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:549
#define RTC_TRACE(fmt)
def j(str, encoding="cp932")
Definition: RunAtFirst.py:198
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:484
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:410
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 Jun 10 2019 14:07:53