Fawkes API  Fawkes Development Version
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
clips_inifin.cpp
1 
2 /***************************************************************************
3  * clips_inifin.cpp - Fawkes CLIPSAspect initializer/finalizer
4  *
5  * Created: Sat Jun 16 14:34:27 2012
6  * Copyright 2006-2012 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
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_WRE file in the doc directory.
22  */
23 
24 #include <plugins/clips/aspect/clips_inifin.h>
25 #include <core/threading/thread_finalizer.h>
26 #include <logging/logger.h>
27 #include <clipsmm.h>
28 
29 extern "C" {
30 #include <clips/clips.h>
31 }
32 
33 namespace fawkes {
34 #if 0 /* just to make Emacs auto-indent happy */
35 }
36 #endif
37 
38 /// @cond INTERNALS
39 
40 class CLIPSLogger
41 {
42  public:
43  CLIPSLogger(Logger *logger)
44  {
45  logger_ = logger;
46  }
47 
48  void log(const char *str)
49  {
50  if (strcmp(str, "\n") == 0) {
51  logger_->log_info("CLIPS", "%s", buffer_.c_str());
52  buffer_.clear();
53  } else {
54  buffer_ += str;
55  }
56  }
57 
58  private:
59  Logger *logger_;
60  std::string buffer_;
61 };
62 
63 static int
64 log_router_query(void *env, char *logical_name)
65 {
66  if (strcmp(logical_name, "l") == 0) return TRUE;
67  if (strcmp(logical_name, "stdout") == 0) return TRUE;
68  return FALSE;
69 }
70 
71 static int
72 log_router_print(void *env, char *logical_name, char *str)
73 {
74  void *rc = GetEnvironmentRouterContext(env);
75  CLIPSLogger *logger = static_cast<CLIPSLogger *>(rc);
76  logger->log(str);
77  return TRUE;
78 }
79 
80 static int
81 log_router_exit(void *env, int exit_code)
82 {
83  return TRUE;
84 }
85 
86 /// @endcond
87 
88 /** @class CLIPSAspectIniFin <plugins/clips/aspect/clips_inifin.h>
89  * CLIPSAspect initializer/finalizer.
90  * This initializer/finalizer will provide the CLIPS node handle to
91  * threads with the CLIPSAspect.
92  * @author Tim Niemueller
93  */
94 
95 /** Constructor. */
96 CLIPSAspectIniFin::CLIPSAspectIniFin()
97  : AspectIniFin("CLIPSAspect")
98 {
99  logger_ = NULL;
100 }
101 
102 /** Destructor. */
104 {
105  delete logger_;
106 }
107 
108 void
110 {
111  CLIPSAspect *clips_thread;
112  clips_thread = dynamic_cast<CLIPSAspect *>(thread);
113  if (clips_thread == NULL) {
114  throw CannotInitializeThreadException("Thread '%s' claims to have the "
115  "CLIPSAspect, but RTTI says it "
116  "has not. ", thread->name());
117  }
118 
119  // CLIPS overwrites the SIGINT handler, restore it after
120  // initializing the environment
121  struct sigaction oldact;
122  if (sigaction(SIGINT, NULL, &oldact) == 0) {
123  LockPtr<CLIPS::Environment> clips(new CLIPS::Environment());
124 
125  void *env = clips->cobj();
126  EnvAddRouterWithContext(env, (char *)"fawkeslog",
127  /* exclusive */ 50,
128  log_router_query,
129  log_router_print,
130  /* getc */ NULL,
131  /* ungetc */ NULL,
132  log_router_exit,
133  logger_);
134 
135  clips_thread->init_CLIPSAspect(clips);
136  // restore old action
137  sigaction(SIGINT, &oldact, NULL);
138  } else {
139  throw CannotInitializeThreadException("CLIPS for %s: Unable to backup "
140  "SIGINT sigaction for restoration.",
141  thread->name());
142  }
143 }
144 
145 void
147 {
148  CLIPSAspect *clips_thread;
149  clips_thread = dynamic_cast<CLIPSAspect *>(thread);
150  if (clips_thread == NULL) {
151  throw CannotFinalizeThreadException("Thread '%s' claims to have the "
152  "CLIPSAspect, but RTTI says it "
153  "has not. ", thread->name());
154  }
155  clips_thread->finalize_CLIPSAspect();
156 }
157 
158 
159 
160 /** Set the logger to use for logging (print to "l" output).
161  * @param logger logger to use
162  */
163 void
165 {
166  logger_ = new CLIPSLogger(logger);
167 }
168 
169 } // end namespace fawkes
virtual void init(Thread *thread)
Initialize thread.
virtual void finalize(Thread *thread)
Finalize thread.
~CLIPSAspectIniFin()
Destructor.
Thread class encapsulation of pthreads.
Definition: thread.h:42
Thread cannot be initialized.
const char * name() const
Get name of thread.
Definition: thread.h:95
Thread cannot be finalized.
void set_logger(Logger *logger)
Set the logger to use for logging (print to &quot;l&quot; output).
Thread aspect to get access to a CLIPS environment.
Definition: clips.h:39
Aspect initializer/finalizer base class.
Definition: inifin.h:36
Interface for logging.
Definition: logger.h:34