Fawkes API  Fawkes Development Version
eclipse_thread.cpp
1 
2 /***************************************************************************
3  * eclipse_thread.cpp - Fawkes ECLiPSe Thread
4  *
5  * Created: Wed Jul 16 10:42:49 2009
6  * Copyright 2009 Daniel Beck
7  * 2013-2014 Gesche Gierse
8  * 2014 Tim Niemueller
9  ****************************************************************************/
10 
11 /* This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL file in the doc directory.
22  */
23 
24 #include "eclipse_thread.h"
25 #include "externals/blackboard.h"
26 #include "externals/fawkes_logger.h"
27 #include "externals/eclipse_path.h"
28 #include "externals/eclipseclp_config.h"
29 
30 #include <interfaces/TestInterface.h>
31 #include <core/threading/mutex_locker.h>
32 #include <core/exception.h>
33 #include <eclipseclass.h>
34 
35 #include <cstdio>
36 #include <cstdlib>
37 #include <cstring>
38 #include <vector>
39 
40 namespace fawkes{
42 };
43 
44 using namespace std;
45 using namespace fawkes;
46 
47 /** @class EclipseAgentThread "eclipse_thread.h"
48  * This thread creates an ECLiPSe context in which the ECLiPSe
49  * interpreter and the program are loaded.
50  * @author Daniel Beck
51  */
52 
53 extern "C" int ec_external( dident, int (*) (...), dident );
54 
55 EclipseAgentThread* EclipseAgentThread::m_instance = NULL;
56 
57 /** Constructor. */
59  : Thread( "ECLiPSe thread", fawkes::Thread::OPMODE_CONTINUOUS ),
60  m_initialized( false )
61 {
63  m_instance = this;
64  mutex = new fawkes::Mutex();
65 }
66 
67 /** Destructor. */
69 {
70  delete mutex;
71 }
72 
73 void
75 {
76  _running = false;
79  // set ECLiPSe installation directory
80  char* eclipse_dir = NULL;
81  try
82  {
83  eclipse_dir = strdup( config->get_string( "/eclipse-clp/eclipse_dir" ).c_str() );
84  logger->log_info( name(), "Setting ECLIPSEDIR to %s", eclipse_dir );
85  ec_set_option_ptr( EC_OPTION_ECLIPSEDIR, (void*) eclipse_dir );
86  }
87  catch (...)
88  {
89  // ignore
90  }
91 
92  agent = config->get_string( "/eclipse-clp/agent" );
93 
94  try{
95  //set default module in which goals called from the top-level will be executed
96  ec_set_option_ptr(EC_OPTION_DEFAULT_MODULE, (void*) agent.c_str());
97 
98  }
99  catch (...){
100  throw fawkes::Exception( "Failed to set default ECLiPSe module");
101  }
102  // initialize ECLiPSe context
103  if ( 0 != ec_init() )
104  { throw fawkes::Exception( "Failed to initialize ECLiPSe context" ); }
105 
106  free( eclipse_dir );
107 
108 
109  m_initialized = true;
110 
111  std::vector<std::string> paths = config->get_strings("/eclipse-clp/file_path");
112 
113  // initialise pathfinding utility
115  EclipsePath::instance()->add_regex(boost::regex("@AGENT@"), agent);
116  for (size_t i = 0; i < paths.size(); ++i) {
117  EclipsePath::instance()->add_path(paths[i]);
118  }
119 
121 
122  // debug
124 
125  // make locate_file/2 available
126  std::string filepath_path = EclipsePath::instance()->locate_file("filepath.ecl");
127  if (filepath_path.empty()) {
128  throw Exception("Failed to determine path to filepath module");
129  }
130  load_file(filepath_path.c_str());
131 
132  // load interpreter and agent
133  std::string agent_path = EclipsePath::instance()->locate_file(agent + ".ecl");
134  if (agent_path.empty()) {
135  throw Exception("Failed to determine path to agent module");
136  }
137  load_file( agent_path.c_str() );
138 
139  // check if navgraph is used and pass config value
140  if (config->get_bool( ("/eclipse-clp/"+agent+"/use_graph").c_str() )){
141  graph_path = CONFDIR + config->get_string( ("/eclipse-clp/"+agent+"/rel_graph_path").c_str());
142 
143  logger->log_info( name(), "Setting graph_path to %s", graph_path.c_str() );
144  post_goal( term(EC_functor("load_graph",1), graph_path.c_str()) );
145  if ( EC_succeed != EC_resume() )
146  { throw Exception( "Error loading graph config to agent" ); }
147  }
148 
149  // register external predicates
150  if ( EC_succeed != ec_external( ec_did( "log", 2 ), p_log, ec_did( agent.c_str(), 0 ) ) )
151  { throw Exception( "Registering external predicate log/2 failed" ); }
152 
153 }
154 
155 void
157 {
158  ec_cleanup();
160 }
161 
162 
163 void
165 {
166  post_goal( "run" );
167  int res = EC_resume();
168  if(EC_yield == res){
169  //terminate
170  } else {
171  if ( EC_succeed != res) {
172  logger->log_error(name(), "Running the agent program failed");
173  }
174  }
175 }
176 
177 /** Check if the agent is running
178  * @return true if ECLiPSe agent is running
179  */
180 bool EclipseAgentThread::running()
181 {
182  MutexLocker lock(mutex);
183  return _running;
184 }
185 
186 /*
187 void
188 EclipseAgentThread::loop()
189 {
190  if (!running()){
191  mutex->lock();
192  _running = true;
193  mutex->unlock();
194 
195  post_goal( "cycle" );
196  if ( EC_succeed != EC_resume() )
197  { throw Exception( "Error running agent program" ); }
198 
199  mutex->lock();
200  _running = false;
201  mutex->unlock();
202  }
203 }
204 */
205 
206 /** Post an event to the ECLiPSe context.
207  * @param event the name of the event
208  */
209 void
210 EclipseAgentThread::post_event( const char* event )
211 {
212  if ( !m_initialized ) { return; }
213 
214  // send event to the interpreter
215  char* atom = strdup( event );
216  ::post_event( EC_atom( atom ) );
217  free( atom );
218 }
219 
220 
221 /** Load a file into the ECLiPSe context.
222  * @param filename the name of the file
223  * @return false if the ECLiPSe context hasn't been intialized yet
224  */
225 bool
226 EclipseAgentThread::load_file( const char* filename )
227 {
228  if ( !m_initialized ) { return false; }
229 
230  char* ensure_loaded = strdup( "ensure_loaded" );
231  post_goal( term( EC_functor( ensure_loaded, 1 ), filename ) );
232  free( ensure_loaded );
233 
234  if ( EC_succeed != ec_resume() )
235  { throw Exception( "File %s could not be loaded", filename ); }
236 
237  return true;
238 }
239 
240 
241 /** Get the logger.
242  * @return the logger
243  */
246 {
247  return logger;
248 }
249 
250 /** Get the EclipseAgentThread instance.
251  * @return the instance
252  */
255 {
256  if ( !m_instance )
257  { throw Exception( "No instance of type EclipseThread instantiated" ); }
258 
259  return m_instance;
260 }
EclipseAgentThread()
Constructor.
virtual void log_info(const char *component, const char *format,...)=0
Log informational message.
void apply_regexes()
Apply the regexes to all paths.
virtual void finalize()
Finalize the thread.
void add_regex(boost::regex re, std::string str)
Add a regex.
static EclipsePath * instance()
Get the EclipsePath instance.
fawkes::Logger * get_logger()
Get the logger.
Fawkes library namespace.
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
Mutex locking helper.
Definition: mutex_locker.h:33
STL namespace.
Thread class encapsulation of pthreads.
Definition: thread.h:42
void set_prepfin_conc_loop(bool concurrent=true)
Set concurrent execution of prepare_finalize() and loop().
Definition: thread.cpp:727
virtual ~EclipseAgentThread()
Destructor.
Logger * logger
This is the Logger member used to access the logger.
Definition: logging.h:44
static void cleanup_instance()
Delete the current EclExternalBlackBoard instance and set it to NULL.
Definition: blackboard.cpp:85
static void create_initial_object(BlackBoard *bb)
Creates the initial EclExternalBlackBoard object.
Definition: blackboard.cpp:79
void post_event(const char *)
Post an event to the ECLiPSe context.
void print_all_paths()
Debug method to print all path to the command line.
static EclipseAgentThread * instance()
Get the EclipseAgentThread instance.
Base class for exceptions in Fawkes.
Definition: exception.h:36
Wrapper class for using the blackboard in the implementation of the external predicates.
Definition: blackboard.h:39
const char * name() const
Get name of thread.
Definition: thread.h:95
virtual void log_error(const char *component, const char *format,...)=0
Log error message.
This thread creates an ECLiPSe context in which the ECLiPSe interpreter and the program are loaded...
virtual void init()
Initialize the thread.
static void create_initial_object(Configuration *config)
Creates the initial EclExternalConfig object.
virtual std::vector< std::string > get_strings(const char *path)=0
Get list of values from configuration which is of type string.
virtual void once()
Execute an action exactly once.
static void create_initial_object()
Create the initial EclipsePath object.
std::string locate_file(std::string filename)
Locate a file by filename.
Mutex mutual exclusion lock.
Definition: mutex.h:32
Configuration * config
This is the Configuration member used to access the configuration.
Definition: configurable.h:44
void add_path(std::string path)
Add a new path.
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.
BlackBoard * blackboard
This is the BlackBoard instance you can use to interact with the BlackBoard.
Definition: blackboard.h:44
Interface for logging.
Definition: logger.h:34