00001
00020 #include <rtm/RTC.h>
00021
00022 #include <coil/File.h>
00023 #include <coil/Process.h>
00024
00025
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
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
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
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
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
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
00300 for (size_t l(0); l < langs.size(); ++l)
00301 {
00302
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
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
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
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
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
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
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
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 };