Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * exec_thread.cpp - Fawkes LuaAgent: Execution Thread 00004 * 00005 * Created: Thu Jan 01 11:12:13 2009 00006 * Copyright 2006-2009 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * Read the full text in the LICENSE.GPL file in the doc directory. 00021 */ 00022 00023 #include "exec_thread.h" 00024 00025 #include <core/exceptions/software.h> 00026 #include <core/exceptions/system.h> 00027 #include <core/threading/mutex.h> 00028 #include <utils/logging/component.h> 00029 00030 #include <lua/context.h> 00031 #include <lua/interface_importer.h> 00032 00033 #include <interfaces/SkillerInterface.h> 00034 #include <interfaces/SkillerDebugInterface.h> 00035 00036 #include <string> 00037 #include <cstring> 00038 00039 using namespace std; 00040 using namespace fawkes; 00041 00042 /** @class LuaAgentExecutionThread "exec_thread.h" 00043 * LuaAgent Execution Thread. 00044 * This thread runs and controls the Lua interpreter and passes data into the 00045 * execution engine. 00046 * 00047 * @author Tim Niemueller 00048 */ 00049 00050 /** Constructor. */ 00051 LuaAgentExecutionThread::LuaAgentExecutionThread() 00052 : Thread("LuaAgentExecutionThread", Thread::OPMODE_WAITFORWAKEUP), 00053 BlockedTimingAspect(BlockedTimingAspect::WAKEUP_HOOK_THINK) 00054 { 00055 __lua = NULL; 00056 } 00057 00058 00059 /** Destructor. */ 00060 LuaAgentExecutionThread::~LuaAgentExecutionThread() 00061 { 00062 } 00063 00064 00065 /** Clean up when init failed. 00066 * You may only call this from init(). Never ever call it from anywhere 00067 * else! 00068 */ 00069 void 00070 LuaAgentExecutionThread::init_failure_cleanup() 00071 { 00072 try { 00073 if ( __skiller_if ) { 00074 __skiller_if->msgq_enqueue(new SkillerInterface::ReleaseControlMessage()); 00075 blackboard->close(__skiller_if); 00076 } 00077 if ( __agdbg_if ) blackboard->close(__agdbg_if); 00078 00079 delete __lua_ifi; 00080 00081 } catch (...) { 00082 // we really screwed up, can't do anything about it, ignore error, logger is 00083 // initialized since this method is only called from init() which is only called if 00084 // all aspects had been initialized successfully 00085 logger->log_error(name(), "Really screwed up while finalizing, aborting cleanup. " 00086 "Fawkes is no longer in a clean state. Restart!"); 00087 } 00088 } 00089 00090 00091 void 00092 LuaAgentExecutionThread::init() 00093 { 00094 try { 00095 __cfg_agent = config->get_string("/luaagent/agent"); 00096 __cfg_watch_files = config->get_bool("/luaagent/watch_files"); 00097 } catch (Exception &e) { 00098 e.append("Insufficient configuration for LuaAgent"); 00099 throw; 00100 } 00101 00102 logger->log_debug("LuaAgentExecutionThread", "Agent: %s", __cfg_agent.c_str()); 00103 00104 __clog = new ComponentLogger(logger, "LuaAgentLua"); 00105 00106 __lua = NULL; 00107 __lua_ifi = NULL; 00108 __skiller_if = NULL; 00109 __agdbg_if = NULL; 00110 00111 std::string reading_prefix = "/luaagent/interfaces/" + __cfg_agent + "/reading/"; 00112 std::string writing_prefix = "/luaagent/interfaces/" + __cfg_agent + "/writing/"; 00113 00114 __skiller_if = blackboard->open_for_reading<SkillerInterface>("Skiller"); 00115 00116 __skiller_if->read(); 00117 if (__skiller_if->exclusive_controller() != 0) { 00118 throw Exception("Skiller already has an exclusive controller"); 00119 } 00120 00121 __skiller_if->msgq_enqueue(new SkillerInterface::AcquireControlMessage()); 00122 __agdbg_if = blackboard->open_for_writing<SkillerDebugInterface>("LuaAgent"); 00123 00124 try { 00125 __lua = new LuaContext(__cfg_watch_files); 00126 00127 __lua_ifi = new LuaInterfaceImporter(__lua, blackboard, config, logger); 00128 __lua_ifi->open_reading_interfaces(reading_prefix); 00129 __lua_ifi->open_writing_interfaces(writing_prefix); 00130 00131 __lua->add_package_dir(LUADIR); 00132 __lua->add_cpackage_dir(LUALIBDIR); 00133 00134 __lua->add_package("fawkesutils"); 00135 __lua->add_package("fawkesconfig"); 00136 __lua->add_package("fawkesinterface"); 00137 00138 __lua->set_string("AGENT", __cfg_agent.c_str()); 00139 __lua->set_usertype("config", config, "Configuration", "fawkes"); 00140 __lua->set_usertype("logger", __clog, "ComponentLogger", "fawkes"); 00141 __lua->set_usertype("clock", clock, "Clock", "fawkes"); 00142 00143 __lua_ifi->add_interface("skiller", __skiller_if); 00144 __lua_ifi->add_interface("agdbg", __agdbg_if); 00145 00146 __lua_ifi->push_interfaces(); 00147 00148 __lua->set_start_script(LUADIR"/luaagent/start.lua"); 00149 } catch (Exception &e) { 00150 init_failure_cleanup(); 00151 throw; 00152 } 00153 00154 __agdbg_if->set_graph(""); 00155 __agdbg_if->set_graph_fsm(__cfg_agent.c_str()); 00156 00157 } 00158 00159 00160 void 00161 LuaAgentExecutionThread::finalize() 00162 { 00163 if (__skiller_if->has_writer() ) { 00164 __skiller_if->msgq_enqueue(new SkillerInterface::ReleaseControlMessage()); 00165 } 00166 00167 blackboard->close(__skiller_if); 00168 blackboard->close(__agdbg_if); 00169 00170 delete __lua_ifi; 00171 delete __lua; 00172 delete __clog; 00173 } 00174 00175 void 00176 LuaAgentExecutionThread::process_agdbg_messages() 00177 { 00178 while ( ! __agdbg_if->msgq_empty() ) { 00179 if (__agdbg_if->msgq_first_is<SkillerDebugInterface::SetGraphDirectionMessage>() ) { 00180 SkillerDebugInterface::SetGraphDirectionMessage *m = __agdbg_if->msgq_first<SkillerDebugInterface::SetGraphDirectionMessage>(); 00181 try { 00182 std::string graphdir = "TB"; 00183 switch (m->graph_dir()) { 00184 case SkillerDebugInterface::GD_BOTTOM_TOP: graphdir = "BT"; break; 00185 case SkillerDebugInterface::GD_LEFT_RIGHT: graphdir = "LR"; break; 00186 case SkillerDebugInterface::GD_RIGHT_LEFT: graphdir = "RL"; break; 00187 default: break; 00188 } 00189 __lua->do_string("agentenv.set_graphdir(\"%s\")", graphdir.c_str()); 00190 } catch (Exception &e) { 00191 logger->log_warn("LuaAgentExecutionThread", "Failed to set graph direction, exception follows"); 00192 logger->log_warn("LuaAgentExecutionThread", e); 00193 } 00194 } else if (__agdbg_if->msgq_first_is<SkillerDebugInterface::SetGraphColoredMessage>() ) { 00195 SkillerDebugInterface::SetGraphColoredMessage *m = __agdbg_if->msgq_first<SkillerDebugInterface::SetGraphColoredMessage>(); 00196 try { 00197 __lua->do_string("agentenv.set_graph_colored(%s)", m->is_graph_colored() ? "true" : "false"); 00198 } catch (Exception &e) { 00199 logger->log_warn("LuaAgentExecutionThread", "Failed to set graph direction, exception follows"); 00200 logger->log_warn("LuaAgentExecutionThread", e); 00201 } 00202 } 00203 00204 __agdbg_if->msgq_pop(); 00205 } 00206 } 00207 00208 00209 void 00210 LuaAgentExecutionThread::loop() 00211 { 00212 #ifdef HAVE_INOTIFY 00213 __lua->process_fam_events(); 00214 #endif 00215 00216 process_agdbg_messages(); 00217 00218 __lua_ifi->read(); 00219 __skiller_if->read(); 00220 00221 try { 00222 // Stack: 00223 __lua->do_string("agentenv.execute()"); 00224 } catch (Exception &e) { 00225 logger->log_error("LuaAgentExecutionThread", "Execution of %s.execute() failed, exception follows", 00226 __cfg_agent.c_str()); 00227 logger->log_error("LuaAgentExecutionThread", e); 00228 } 00229 00230 __lua_ifi->write(); 00231 }