00001 /********************************************************************* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2013, Institute for Artificial Intelligence, 00005 * Universität Bremen. 00006 * All rights reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions 00010 * are met: 00011 * 00012 * * Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * * Redistributions in binary form must reproduce the above 00015 * copyright notice, this list of conditions and the following 00016 * disclaimer in the documentation and/or other materials provided 00017 * with the distribution. 00018 * * Neither the name of the Institute for Artificial Intelligence, 00019 * Universität Bremen, nor the names of its contributors may be 00020 * used to endorse or promote products derived from this software 00021 * without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00024 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00025 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00026 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00027 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00028 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00029 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00032 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00033 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00034 * POSSIBILITY OF SUCH DAMAGE. 00035 *********************************************************************/ 00036 00040 #include <PluginInstance.h> 00041 00042 00043 namespace beliefstate { 00044 PluginInstance::PluginInstance() { 00045 m_strName = ""; 00046 m_vdLibHandle = NULL; 00047 m_piInstance = NULL; 00048 m_thrdPluginCycle = NULL; 00049 m_bRunCycle = true; 00050 m_resCycleResult = defaultResult(); 00051 00052 this->setMessagePrefixLabel("plugin-instance"); 00053 } 00054 00055 PluginInstance::~PluginInstance() { 00056 } 00057 00058 Result PluginInstance::loadPluginLibrary(std::string strFilepath) { 00059 Result resLoad = defaultResult(); 00060 00061 std::fstream fsFile; 00062 fsFile.open(strFilepath.c_str(), std::fstream::in); 00063 00064 if(fsFile.is_open()) { 00065 fsFile.close(); 00066 00067 m_vdLibHandle = dlopen(strFilepath.c_str(), RTLD_LAZY); 00068 if(m_vdLibHandle) { 00069 plugins::Plugin* (*createInstance)(); 00070 createInstance = (plugins::Plugin* (*)())dlsym(m_vdLibHandle, "createInstance"); 00071 m_piInstance = (plugins::Plugin*)createInstance(); 00072 00073 m_strName = strFilepath; 00074 00075 // Remove path 00076 const size_t last_slash_idx = m_strName.find_last_of("\\/"); 00077 if(std::string::npos != last_slash_idx) { 00078 m_strName.erase(0, last_slash_idx + 1); 00079 } 00080 00081 // Remove extension 00082 const size_t period_idx = m_strName.rfind('.'); 00083 if(std::string::npos != period_idx) { 00084 m_strName.erase(period_idx); 00085 } 00086 00087 // Remove plugin prefix 00088 std::string strPrefix = "libbs_plugin_"; 00089 m_strName = m_strName.substr(strPrefix.size()); 00090 00091 std::string strVersionString = m_piInstance->pluginVersion(); 00092 00093 this->info("Loaded plugin '" + m_strName + "'" + (strVersionString == "" ? "" : " (version: " + strVersionString + ")")); 00094 m_piInstance->setPluginName(m_strName); 00095 } else { 00096 resLoad.riResultIdentifier = RI_PLUGIN_LOADING_FAILED; 00097 resLoad.bSuccess = false; 00098 resLoad.strErrorMessage = "Failed to load library `" + strFilepath + "'."; 00099 this->fail("Could not open shared library: " + string(dlerror())); 00100 } 00101 } else { 00102 resLoad.riResultIdentifier = RI_FILE_NOT_FOUND; 00103 resLoad.bSuccess = false; 00104 resLoad.strErrorMessage = "File `" + strFilepath + "' could not be found."; 00105 } 00106 00107 return resLoad; 00108 } 00109 00110 Result PluginInstance::init(int argc, char** argv) { 00111 Result resInit = m_piInstance->init(argc, argv); 00112 00113 if(resInit.bSuccess) { 00114 this->success("Initialized plugin '" + m_strName + "'"); 00115 } else { 00116 this->fail("Failed to initialize plugin '" + m_strName + "'."); 00117 } 00118 00119 return resInit; 00120 } 00121 00122 void PluginInstance::setDevelopmentPlugin(bool bDevelopmentPlugin) { 00123 if(m_vdLibHandle) { 00124 m_piInstance->setDevelopmentPlugin(bDevelopmentPlugin); 00125 } 00126 } 00127 00128 bool PluginInstance::developmentPlugin() { 00129 if(m_vdLibHandle) { 00130 return m_piInstance->developmentPlugin(); 00131 } 00132 00133 return false; 00134 } 00135 00136 void PluginInstance::unload() { 00137 if(m_vdLibHandle) { 00138 m_piInstance->deinit(); 00139 00140 void (*destroyInstance)(plugins::Plugin*); 00141 destroyInstance = (void (*)(plugins::Plugin*))dlsym(m_vdLibHandle, "destroyInstance"); 00142 destroyInstance(m_piInstance); 00143 dlclose(m_vdLibHandle); 00144 00145 this->info("Unloaded plugin '" + m_strName + "'"); 00146 } 00147 } 00148 00149 int PluginInstance::pluginID() { 00150 return m_piInstance->pluginID(); 00151 } 00152 00153 Result PluginInstance::cycle() { 00154 if(m_thrdPluginCycle == NULL) { 00155 m_thrdPluginCycle = new std::thread(&PluginInstance::spinCycle, this); 00156 } 00157 00158 return this->currentResult(); 00159 } 00160 00161 void PluginInstance::spinCycle() { 00162 while(m_bRunCycle) { 00163 Result resCycle = m_piInstance->cycle(); 00164 00165 m_mtxCycleResults.lock(); 00166 for(Event evCurrent : resCycle.lstEvents) { 00167 m_resCycleResult.lstEvents.push_back(evCurrent); 00168 } 00169 resCycle.lstEvents.clear(); 00170 00171 for(ServiceEvent seCurrent : resCycle.lstServiceEvents) { 00172 m_resCycleResult.lstServiceEvents.push_back(seCurrent); 00173 } 00174 resCycle.lstServiceEvents.clear(); 00175 00176 for(StatusMessage smCurrent : resCycle.lstStatusMessages) { 00177 m_resCycleResult.lstStatusMessages.push_back(smCurrent); 00178 } 00179 // TODO(winkler): Maybe there is a `clear` missing here. Check this. 00180 00181 m_mtxCycleResults.unlock(); 00182 00183 usleep(10); 00184 } 00185 } 00186 00187 std::list<std::string> PluginInstance::dependencies() { 00188 return m_piInstance->dependencies(); 00189 } 00190 00191 bool PluginInstance::subscribedToEvent(std::string strEventName) { 00192 return m_piInstance->subscribedToEvent(strEventName); 00193 } 00194 00195 void PluginInstance::consumeEvent(Event evEvent) { 00196 m_piInstance->consumeEvent(evEvent); 00197 } 00198 00199 bool PluginInstance::offersService(std::string strServiceName) { 00200 return m_piInstance->offersService(strServiceName); 00201 } 00202 00203 Event PluginInstance::consumeServiceEvent(ServiceEvent seServiceEvent) { 00204 return m_piInstance->consumeServiceEvent(seServiceEvent); 00205 } 00206 00207 std::string PluginInstance::name() { 00208 return m_strName; 00209 } 00210 00211 Result PluginInstance::currentResult() { 00212 Result resReturn = defaultResult(); 00213 00214 if(m_mtxCycleResults.try_lock()) { 00215 resReturn = m_resCycleResult; 00216 m_resCycleResult = defaultResult(); 00217 m_mtxCycleResults.unlock(); 00218 } 00219 00220 return resReturn; 00221 } 00222 00223 void PluginInstance::setRunning(bool bRunCycle) { 00224 m_bRunCycle = bRunCycle; 00225 00226 m_piInstance->setRunning(bRunCycle); 00227 } 00228 00229 void PluginInstance::waitForJoin() { 00230 m_thrdPluginCycle->join(); 00231 delete m_thrdPluginCycle; 00232 } 00233 }