ModuleManager.cpp
Go to the documentation of this file.
00001 // -*- C++ -*-
00020 #include <rtm/RTC.h>
00021 
00022 #include <coil/File.h>
00023 #include <coil/Process.h>
00024 
00025 // RTC includes
00026 #include <rtm/Manager.h>
00027 #include <rtm/ModuleManager.h>
00028 #include <coil/stringutil.h>
00029 
00030 namespace RTC
00031 {
00032   
00040   ModuleManager::ModuleManager(coil::Properties& prop)
00041     : rtclog("ModuleManager"), m_properties(prop)
00042   {
00043     m_configPath      = coil::split(prop[CONFIG_PATH], ",");
00044     for_each(m_configPath.begin(), m_configPath.end(), coil::eraseHeadBlank);
00045     m_loadPath        = coil::split(prop[MOD_LOADPTH], ",");
00046     for_each(m_loadPath.begin(), m_loadPath.end(), coil::eraseHeadBlank);
00047     m_absoluteAllowed = coil::toBool(prop[ALLOW_ABSPATH], "yes", "no", false);
00048     m_downloadAllowed = coil::toBool(prop[ALLOW_URL], "yes", "no", false);
00049     m_initFuncSuffix  = prop[INITFUNC_SFX];
00050     m_initFuncPrefix  = prop[INITFUNC_PFX];
00051   }
00052   
00060   ModuleManager::~ModuleManager()
00061   {
00062     unloadAll();
00063   }
00064   
00072   std::string ModuleManager::load(const std::string& file_name)
00073   {
00074     RTC_TRACE(("load(fname = %s)", file_name.c_str()));
00075     if (file_name == "") throw InvalidArguments("Invalid file name.");
00076     
00077     if (coil::isURL(file_name))
00078       {
00079         if (!m_downloadAllowed)
00080           {
00081             throw NotAllowedOperation("Downloading module is not allowed.");
00082           }
00083         else
00084           {
00085             throw NotFound("Not implemented.");
00086           }
00087       }
00088     
00089     // Find local file from load path or absolute directory
00090     std::string file_path;
00091     if (coil::isAbsolutePath(file_name))
00092       {
00093         if (!m_absoluteAllowed)
00094           {
00095             throw NotAllowedOperation("Absolute path is not allowed");
00096           }
00097         else
00098           {
00099             file_path = file_name;
00100           }
00101       }
00102     else
00103       {
00104         file_path = findFile(file_name, m_loadPath);
00105       }
00106     
00107     // Now file_name is valid full path to module
00108     if (file_path == "") throw InvalidArguments("Invalid file name.");
00109     if (!fileExist(file_path)) throw FileNotFound(file_path.c_str());
00110     
00111     DLLEntity* dll(new DLLEntity());
00112     
00113     int retval =  dll->dll.open(file_path.c_str());
00114     if (retval != 0)
00115       {
00116         delete dll;
00117         throw Error("DLL open failed.");
00118       }
00119     dll->properties["file_path"] = file_path;
00120     bool ret = m_modules.registerObject(dll);
00121     if (!ret) {
00122       delete dll;
00123     }
00124     
00125     return file_path;
00126   }
00127   
00135   std::string ModuleManager::load(const std::string& file_name,
00136                                   const std::string& init_func)
00137   {
00138     RTC_TRACE(("load(fname = %s, init_func = %s)",
00139                file_name.c_str(), init_func.c_str()));
00140     std::string name;
00141     name = load(file_name);
00142     
00143     if (name == "")
00144       {
00145         throw InvalidOperation("Invalid file name");
00146       }
00147     
00148     //  if (!init_func)
00149     
00150     ModuleInitFunc init;
00151     
00152     init = (ModuleInitFunc)this->symbol(name.c_str(), init_func);
00153     
00154     init(&(Manager::instance()));
00155     
00156     return name;
00157   }
00158   
00166   void ModuleManager::unload(const std::string& file_name)
00167   {
00168     DLLEntity* dll(m_modules.find(file_name.c_str()));
00169     if (dll == NULL)
00170       throw NotFound(file_name.c_str());
00171     
00172     dll->dll.close();
00173     m_modules.unregisterObject(file_name.c_str());
00174     
00175     if (dll != NULL) {
00176       delete dll;
00177     }
00178     
00179     return;
00180   }
00181   
00189   void ModuleManager::unloadAll()
00190   {
00191     std::vector<DLLEntity*> dlls(m_modules.getObjects());
00192     
00193     for (int i(0), len(dlls.size()); i < len; ++i)
00194       {
00195         std::string ident(dlls[i]->properties["file_path"]);
00196         DLLEntity* dll(m_modules.unregisterObject(ident.c_str()));
00197         dll->dll.close();
00198       }
00199     return;
00200   }
00201   
00209   void* ModuleManager::symbol(const std::string& file_name,
00210                               const std::string& func_name)
00211     throw (ModuleNotFound, SymbolNotFound)
00212   {
00213     // "file_name" should be in modules map.
00214     DLLEntity* dll(m_modules.find(file_name.c_str()));
00215     if (dll == NULL)
00216       {
00217         throw ModuleNotFound(file_name);
00218       }
00219     
00220     void* func;
00221     func = dll->dll.symbol(func_name.c_str());
00222     
00223     if (!func)
00224       {
00225         throw SymbolNotFound(func_name);
00226       }
00227     
00228     return func;
00229   }
00230   
00238   void ModuleManager::setLoadpath(const std::vector<std::string>& load_path)
00239   {
00240     m_loadPath = load_path;
00241     return;
00242   }
00243   
00251   void ModuleManager::addLoadpath(const std::vector<std::string>& load_path)
00252   {
00253     StringVectorConstItr it(load_path.begin());
00254     StringVectorConstItr it_end(load_path.end());
00255     
00256     while (it != it_end)
00257       {
00258         m_loadPath.push_back(*it);
00259         ++it;
00260       }
00261     
00262     return;
00263   }
00264   
00272   std::vector<coil::Properties> ModuleManager::getLoadedModules()
00273   {
00274     std::vector< DLLEntity* > dlls(m_modules.getObjects());
00275     std::vector<coil::Properties> modules;
00276     for (int i(0), len(dlls.size()); i < len; ++i)
00277       {
00278         modules.push_back(dlls[i]->properties);
00279       }
00280     return modules;
00281   }
00282   
00290   std::vector<coil::Properties> ModuleManager::getLoadableModules()
00291   {
00292     RTC_TRACE(("getLoadableModules()"));
00293 
00294     // getting loadable module file path list.
00295     coil::Properties& gprop(Manager::instance().getConfig());
00296     coil::vstring langs(coil::split(gprop["manager.supported_languages"], ","));
00297     RTC_DEBUG(("langs: %s", gprop["manager.supported_languages"].c_str()));
00298 
00299     // for each languages
00300     for (size_t l(0); l < langs.size(); ++l)
00301       {
00302         // 1. getting loadable files list
00303         coil::vstring modules;
00304         getModuleList(langs[l], modules);
00305         RTC_DEBUG(("%s: %s", langs[l].c_str(), coil::flatten(modules).c_str()));
00306 
00307         // 2. getting module properties from loadable modules
00308         vProperties tmpprops;
00309         getModuleProfiles(langs[l], modules, tmpprops);
00310         RTC_DEBUG(("Modile profile size: %d (newly founded modules)",
00311                    tmpprops.size()));
00312         m_modprofs.insert(m_modprofs.end(), tmpprops.begin(), tmpprops.end());
00313       }
00314     RTC_DEBUG(("Modile profile size: %d", m_modprofs.size()));
00315     // 3. removing module profiles for which module file does not exist
00316     removeInvalidModules();
00317     RTC_DEBUG(("Modile profile size: %d (invalid mod-profiles deleted)",
00318                m_modprofs.size()));
00319     return m_modprofs;
00320   }
00321   
00329   std::string ModuleManager::findFile(const std::string& fname,
00330                                       const std::vector<std::string>& load_path)
00331   {
00332     StringVectorConstItr it, it_end;
00333     std::string file_name(fname);
00334     
00335     it     = load_path.begin();
00336     it_end = load_path.end();
00337     
00338     while (it != it_end)
00339       {
00340         std::string f((*it) + "/" + file_name);
00341         if (fileExist(f))
00342           {
00343             return f;
00344           }
00345         ++it;
00346       }
00347     
00348     return std::string("");
00349   }
00350   
00358   bool ModuleManager::fileExist(const std::string& filename)
00359   {
00360     std::ifstream infile;
00361     infile.open(filename.c_str(), std::ios::in);
00362     // fial() 0: ok, !0: fail
00363     if (infile.fail() != 0) 
00364       {
00365         infile.close();
00366         return false;
00367       }
00368     else
00369       {
00370         infile.close();
00371         return true;
00372       }
00373     
00374     return false;
00375   }
00376   
00384   std::string ModuleManager::getInitFuncName(const std::string& file_path)
00385   {
00386     std::string base_name(coil::basename(file_path.c_str()));
00387     
00388     return m_initFuncPrefix + base_name + m_initFuncSuffix;
00389   }
00390 
00391 
00399   void ModuleManager::removeInvalidModules()
00400   {
00401     std::vector<coil::Properties>::iterator it(m_modprofs.begin());
00402 
00403     while (it < m_modprofs.end())
00404       {
00405         if (!fileExist((*it)["module_file_path"]))
00406           {
00407             it = m_modprofs.erase(it);
00408           }
00409         ++it;
00410       }
00411   }
00412 
00420   void ModuleManager::getModuleList(const std::string& lang,
00421                                     coil::vstring& modules)
00422   {
00423     std::string l = "manager.modules." + lang;
00424     coil::Properties& lprop(Manager::instance().getConfig().getNode(l));
00425 
00426     // load path: manager.modules.<lang>.load_path + manager.modules.load_path
00427     coil::vstring paths(coil::split(lprop["load_paths"], ","));
00428     paths.insert(paths.end(), m_loadPath.begin(), m_loadPath.end());
00429 
00430     coil::vstring suffixes(coil::split(lprop["suffixes"], ","));
00431     RTC_DEBUG(("suffixes: %s", coil::flatten(suffixes).c_str()));
00432 
00433     // for each load path list
00434     for (size_t i(0); i < paths.size(); ++i)
00435       {
00436         if (paths[i].empty())
00437           {
00438             RTC_WARN(("Given load path is empty"));
00439             continue;
00440           }
00441         std::string& path(paths[i]);
00442         RTC_DEBUG(("Module load path: %s", path.c_str()));
00443 
00444         // get file list for each suffixes
00445         coil::vstring flist;
00446         for (size_t s(0); s < suffixes.size(); ++s)
00447           {
00448             std::string glob("*."); glob += suffixes[s];
00449             coil::vstring tmp = coil::filelist(path.c_str(), glob.c_str());
00450             RTC_DEBUG(("File list (path:%s, ext:%s): %s", path.c_str(),
00451                        suffixes[s].c_str(), coil::flatten(tmp).c_str()));
00452             flist.insert(flist.end(), tmp.begin(), tmp.end());
00453           }
00454         
00455         // reformat file path and remove cached files
00456         for (size_t j(0); j < flist.size(); ++j)
00457           {
00458             if (*(path.end() - 1) != '/') { path += "/"; }
00459             std::string fpath(path + flist[j]);
00460             addNewFile(fpath, modules);
00461           }
00462       }
00463   }
00464 
00472   void ModuleManager::addNewFile(const std::string& fpath,
00473                                  coil::vstring& modules)
00474   {
00475     bool exists(false);
00476     for (size_t k(0); k < m_modprofs.size(); ++k)
00477       {
00478         if (m_modprofs[k]["module_file_path"] == fpath)
00479           {
00480             exists = true;
00481             RTC_DEBUG(("Module %s already exists in cache.",
00482                        fpath.c_str()));
00483             break;
00484           }
00485       }
00486     if (!exists)
00487       {
00488         RTC_DEBUG(("New module: %s", fpath.c_str()));
00489         modules.push_back(fpath);
00490       }
00491   }
00492 
00500   void ModuleManager::getModuleProfiles(const std::string& lang,
00501                                         const coil::vstring& modules,
00502                                         vProperties& modprops)
00503   {
00504     std::string l = "manager.modules." + lang;
00505     coil::Properties& lprop(Manager::instance().getConfig().getNode(l));
00506     std::vector<coil::Properties> prop;
00507 
00508     for (size_t i(0), len(modules.size()); i < len; ++i)
00509       {
00510         std::string cmd(lprop["profile_cmd"]);
00511         cmd += " \"" + modules[i] + "\"";
00512         FILE* fd;
00513         if ((fd = popen(cmd.c_str(), "r")) == NULL)
00514           {
00515             std::cerr << "popen faild" << std::endl;
00516             continue;
00517           }
00518         coil::Properties p;
00519         do
00520           {
00521             char str[512];
00522             fgets(str, 512, fd);
00523             std::string line(str);
00524             line.erase(line.size() - 1);
00525             std::string::size_type pos(line.find(":"));
00526             if (pos != std::string::npos)
00527               {
00528                 std::string key(line.substr(0, pos));
00529                 coil::eraseBothEndsBlank(key);
00530                 p[key] = line.substr(pos + 1);
00531                 coil::eraseBothEndsBlank(p[key]);
00532               }
00533           } while (!feof(fd));
00534         pclose(fd);
00535         RTC_DEBUG(("rtcprof cmd sub process done."));
00536         if (p["implementation_id"].empty()) { continue; }
00537         p["module_file_name"] = coil::basename(modules[i].c_str());
00538         p["module_file_path"] = modules[i].c_str();
00539         modprops.push_back(p);
00540       }
00541   }
00542 }; // namespace RTC


openrtm_aist
Author(s): Noriaki Ando
autogenerated on Sat Jun 8 2019 18:49:05