exec_thread.cpp

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 }

Generated on Tue Feb 22 13:31:29 2011 for Fawkes API by  doxygen 1.4.7