Fawkes API  Fawkes Development Version
clips_inifin.cpp
00001 
00002 /***************************************************************************
00003  *  clips_inifin.cpp - Fawkes CLIPSAspect initializer/finalizer
00004  *
00005  *  Created: Sat Jun 16 14:34:27 2012
00006  *  Copyright  2006-2012  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. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include <plugins/clips/aspect/clips_inifin.h>
00025 #include <core/threading/thread_finalizer.h>
00026 #include <logging/logger.h>
00027 #include <clipsmm.h>
00028 
00029 extern "C" {
00030 #include <clips/clips.h>
00031 }
00032 
00033 namespace fawkes {
00034 #if 0 /* just to make Emacs auto-indent happy */
00035 }
00036 #endif
00037 
00038 /// @cond INTERNALS
00039 
00040 class CLIPSLogger
00041 {
00042  public:
00043   CLIPSLogger(Logger *logger)
00044   {
00045     logger_ = logger;
00046   }
00047 
00048   void log(const char *str)
00049   {
00050     if (strcmp(str, "\n") == 0) {
00051       logger_->log_info("CLIPS", "%s", buffer_.c_str());
00052       buffer_.clear();
00053     } else {
00054       buffer_ += str;
00055     }
00056   }
00057 
00058  private:
00059   Logger *logger_;
00060   std::string buffer_;
00061 };
00062 
00063 static int
00064 log_router_query(void *env, char *logical_name)
00065 {
00066   if (strcmp(logical_name, "l") == 0) return TRUE;
00067   if (strcmp(logical_name, "stdout") == 0) return TRUE;
00068   return FALSE;
00069 }
00070 
00071 static int
00072 log_router_print(void *env, char *logical_name, char *str)
00073 {
00074   void *rc = GetEnvironmentRouterContext(env);
00075   CLIPSLogger *logger = static_cast<CLIPSLogger *>(rc);
00076   logger->log(str);
00077   return TRUE;
00078 }
00079 
00080 static int
00081 log_router_exit(void *env, int exit_code)
00082 {
00083   return TRUE;
00084 }
00085 
00086 /// @endcond
00087 
00088 /** @class CLIPSAspectIniFin <plugins/clips/aspect/clips_inifin.h>
00089  * CLIPSAspect initializer/finalizer.
00090  * This initializer/finalizer will provide the CLIPS node handle to
00091  * threads with the CLIPSAspect.
00092  * @author Tim Niemueller
00093  */
00094 
00095 /** Constructor. */
00096 CLIPSAspectIniFin::CLIPSAspectIniFin()
00097   : AspectIniFin("CLIPSAspect")
00098 {
00099   logger_ = NULL;
00100 }
00101 
00102 /** Destructor. */
00103 CLIPSAspectIniFin::~CLIPSAspectIniFin()
00104 {
00105   delete logger_;
00106 }
00107 
00108 void
00109 CLIPSAspectIniFin::init(Thread *thread)
00110 {
00111   CLIPSAspect *clips_thread;
00112   clips_thread = dynamic_cast<CLIPSAspect *>(thread);
00113   if (clips_thread == NULL) {
00114     throw CannotInitializeThreadException("Thread '%s' claims to have the "
00115                                           "CLIPSAspect, but RTTI says it "
00116                                           "has not. ", thread->name());
00117   }
00118 
00119   // CLIPS overwrites the SIGINT handler, restore it after
00120   // initializing the environment
00121   struct sigaction oldact;
00122   if (sigaction(SIGINT, NULL, &oldact) == 0) {
00123     LockPtr<CLIPS::Environment> clips(new CLIPS::Environment());
00124 
00125     void *env = clips->cobj();
00126     EnvAddRouterWithContext(env, (char *)"fawkeslog",
00127                             /* exclusive */ 50,
00128                             log_router_query,
00129                             log_router_print,
00130                             /* getc */   NULL,
00131                             /* ungetc */ NULL,
00132                             log_router_exit,
00133                             logger_);
00134 
00135     clips_thread->init_CLIPSAspect(clips);
00136     // restore old action
00137     sigaction(SIGINT, &oldact, NULL);
00138   } else {
00139     throw CannotInitializeThreadException("CLIPS for %s: Unable to backup "
00140                                           "SIGINT sigaction for restoration.",
00141                                           thread->name());
00142   }
00143 }
00144 
00145 void
00146 CLIPSAspectIniFin::finalize(Thread *thread)
00147 {
00148   CLIPSAspect *clips_thread;
00149   clips_thread = dynamic_cast<CLIPSAspect *>(thread);
00150   if (clips_thread == NULL) {
00151     throw CannotFinalizeThreadException("Thread '%s' claims to have the "
00152                                         "CLIPSAspect, but RTTI says it "
00153                                         "has not. ", thread->name());
00154   }
00155   clips_thread->finalize_CLIPSAspect();
00156 }
00157 
00158 
00159 
00160 /** Set the logger to use for logging (print to "l" output).
00161  * @param logger logger to use
00162  */
00163 void
00164 CLIPSAspectIniFin::set_logger(Logger *logger)
00165 {
00166   logger_ = new CLIPSLogger(logger);
00167 }
00168 
00169 } // end namespace fawkes