23 #include <plugins/clips/aspect/clips_env_manager.h> 24 #include <plugins/clips/aspect/clips_feature.h> 25 #include <logging/logger.h> 26 #include <utils/time/time.h> 31 #include <clips/clips.h> 40 #define ROUTER_NAME "fawkeslog" 46 CLIPSLogger(Logger *logger,
const char *component = NULL)
50 component_ = strdup(component);
63 void log(
const char *logical_name,
const char *str)
65 if (strcmp(str,
"\n") == 0) {
66 if (strcmp(logical_name,
"debug") == 0 || strcmp(logical_name,
"logdebug") == 0 ||
67 strcmp(logical_name, WTRACE) == 0)
69 logger_->log_debug(component_ ? component_ :
"CLIPS",
"%s", buffer_.c_str());
70 }
else if (strcmp(logical_name,
"warn") == 0 || strcmp(logical_name,
"logwarn") == 0 ||
71 strcmp(logical_name, WWARNING) == 0)
73 logger_->log_warn(component_ ? component_ :
"CLIPS",
"%s", buffer_.c_str());
74 }
else if (strcmp(logical_name,
"error") == 0 || strcmp(logical_name,
"logerror") == 0 ||
75 strcmp(logical_name, WERROR) == 0)
77 logger_->log_error(component_ ? component_ :
"CLIPS",
"%s", buffer_.c_str());
78 }
else if (strcmp(logical_name, WDIALOG) == 0) {
81 logger_->log_info(component_ ? component_ :
"CLIPS",
"%s", buffer_.c_str());
96 class CLIPSContextMaintainer {
98 CLIPSContextMaintainer(Logger *logger,
const char *log_component_name)
100 this->logger =
new CLIPSLogger(logger, log_component_name);
103 ~CLIPSContextMaintainer()
114 log_router_query(
void *env,
char *logical_name)
116 if (strcmp(logical_name,
"l") == 0)
return TRUE;
117 if (strcmp(logical_name,
"info") == 0)
return TRUE;
118 if (strcmp(logical_name,
"debug") == 0)
return TRUE;
119 if (strcmp(logical_name,
"warn") == 0)
return TRUE;
120 if (strcmp(logical_name,
"error") == 0)
return TRUE;
121 if (strcmp(logical_name,
"loginfo") == 0)
return TRUE;
122 if (strcmp(logical_name,
"logdebug") == 0)
return TRUE;
123 if (strcmp(logical_name,
"logwarn") == 0)
return TRUE;
124 if (strcmp(logical_name,
"logerror") == 0)
return TRUE;
125 if (strcmp(logical_name,
"stdout") == 0)
return TRUE;
126 if (strcmp(logical_name, WTRACE) == 0)
return TRUE;
127 if (strcmp(logical_name, WDIALOG) == 0)
return TRUE;
128 if (strcmp(logical_name, WWARNING) == 0)
return TRUE;
129 if (strcmp(logical_name, WERROR) == 0)
return TRUE;
130 if (strcmp(logical_name, WDISPLAY) == 0)
return TRUE;
135 log_router_print(
void *env,
char *logical_name,
char *str)
137 void *rc = GetEnvironmentRouterContext(env);
138 CLIPSLogger *logger =
static_cast<CLIPSLogger *
>(rc);
139 logger->log(logical_name, str);
144 log_router_exit(
void *env,
int exit_code)
169 clips_dir_ = clips_dir;
184 CLIPSEnvManager::new_env(
const std::string &log_component_name)
188 struct sigaction oldact;
189 if (sigaction(SIGINT, NULL, &oldact) == 0) {
194 clips->unwatch(
"all");
196 CLIPSContextMaintainer *cm =
197 new CLIPSContextMaintainer(logger_, log_component_name.c_str());
199 void *env = clips->cobj();
201 SetEnvironmentContext(env, cm);
203 EnvAddRouterWithContext(env, (
char *)ROUTER_NAME,
213 sigaction(SIGINT, &oldact, NULL);
217 throw Exception(
"CLIPS: Unable to backup " 218 "SIGINT sigaction for restoration.");
235 if (envs_.find(env_name) != envs_.end()) {
236 throw Exception(
"CLIPS environment '%s' already exists", env_name.c_str());
239 clips = new_env(log_component_name);
242 envs_[env_name].env = clips;
245 add_functions(env_name, clips);
248 assert_features(clips,
true);
250 guarded_load(env_name, clips_dir_ +
"utils.clp");
251 guarded_load(env_name, clips_dir_ +
"time.clp");
252 guarded_load(env_name, clips_dir_ +
"path.clp");
254 clips->evaluate(
"(path-add \"" + clips_dir_ +
"\")");
258 throw Exception(
"Failed to initialize CLIPS environment '%s'", env_name.c_str());
269 if (envs_.find(env_name) != envs_.end()) {
270 void *env = envs_[env_name].env->cobj();
271 CLIPSContextMaintainer *cm =
272 static_cast<CLIPSContextMaintainer *
>(GetEnvironmentContext(env));
274 EnvDeleteRouter(env, (
char *)ROUTER_NAME);
275 SetEnvironmentContext(env, NULL);
278 for (
auto feat : envs_[env_name].req_feat) {
279 if (features_.find(feat) != features_.end()) {
280 features_[feat]->clips_context_destroyed(env_name);
284 envs_.erase(env_name);
292 std::map<std::string, LockPtr<CLIPS::Environment>>
295 std::map<std::string, LockPtr<CLIPS::Environment>> rv;
296 for (
auto envd : envs_) {
297 rv[envd.first] = envd.second.env;
304 CLIPSEnvManager::clips_request_feature(std::string env_name, std::string feature_name)
308 logger_->log_debug(
"ClipsEnvManager",
"Environment %s requests feature %s",
309 env_name.c_str(), feature_name.c_str());
311 if (envs_.find(env_name) == envs_.end()) {
312 logger_->log_warn(
"ClipsEnvManager",
"Feature %s request from non-existent environment %s",
313 feature_name.c_str(), env_name.c_str());
314 return CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL);
316 if (features_.find(feature_name) == features_.end()) {
317 logger_->log_warn(
"ClipsEnvManager",
"Environment requested unavailable feature %s",
318 feature_name.c_str());
319 return CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL);
322 ClipsEnvData &envd = envs_[env_name];
323 if (std::binary_search(envd.req_feat.begin(), envd.req_feat.end(), feature_name)) {
324 logger_->log_warn(
"ClipsEnvManager",
"Environment %s requested feature %s *again*",
325 env_name.c_str(), feature_name.c_str());
326 return CLIPS::Value(
"TRUE", CLIPS::TYPE_SYMBOL);
330 features_[feature_name]->clips_context_init(env_name, envd.env);
331 envd.req_feat.push_back(feature_name);
332 envd.req_feat.sort();
335 std::string deffacts =
"(deffacts ff-features-loaded";
337 for (
auto feat : envd.req_feat) {
338 deffacts +=
" (ff-feature-loaded " + feat +
")";
342 envd.env->assert_fact_f(
"(ff-feature-loaded %s)", feature_name.c_str());
344 if (! envd.env->build(deffacts)) {
345 logger_->log_warn(
"ClipsEnvManager",
"Failed to build deffacts ff-features-loaded " 346 "for %s", env_name.c_str());
351 return CLIPS::Value(rv ?
"TRUE" :
"FALSE", CLIPS::TYPE_SYMBOL);
356 CLIPSEnvManager::clips_now()
369 clips->add_function(
"ff-feature-request", sigc::slot<CLIPS::Value, std::string>(sigc::bind<0>(sigc::mem_fun(*
this, &CLIPSEnvManager::clips_request_feature), env_name)));
370 clips->add_function(
"now", sigc::slot<CLIPS::Values>(sigc::mem_fun( *
this, &CLIPSEnvManager::clips_now)));
378 std::string deffacts =
"(deffacts ff-features-available";
380 for (
auto feat : features_) {
381 deffacts +=
" (ff-feature " + feat.first +
")";
382 if (immediate_assert) {
384 clips->assert_fact_f(
"(ff-feature %s)", feat.first.c_str());
389 if (! clips->build(deffacts)) {
390 logger_->log_warn(
"ClipsEnvManager",
"Failed to build deffacts ff-features-available");
401 for (
auto feat : features) {
402 const std::string &feature_name = feat->clips_feature_name;
404 if (features_.find(feature_name) != features_.end()) {
405 throw Exception(
"Feature '%s' has already been registered", feature_name.c_str());
408 logger_->log_info(
"ClipsEnvManager",
"Adding feature %s", feature_name.c_str());
410 features_[feature_name] = feat;
413 for (
auto env : envs_) {
414 env.second.env.lock();
415 assert_features(env.second.env,
false);
417 env.second.env->assert_fact_f(
"(ff-feature %s)", feature_name.c_str());
418 env.second.env.unlock();
434 for (
auto feat : features) {
435 const std::string &feature_name = feat->clips_feature_name;
437 for (
auto env : envs_) {
438 if (std::binary_search(env.second.req_feat.begin(), env.second.req_feat.end(), feature_name)) {
439 throw Exception(
"Cannot remove feature %s as environment %s depends on it",
440 feature_name.c_str(), env.first.c_str());
457 for (
auto feat : features) {
458 const std::string &feature_name = feat->clips_feature_name;
460 if (features_.find(feature_name) != features_.end()) {
461 features_.erase(feature_name);
468 CLIPSEnvManager::guarded_load(
const std::string &env_name,
const std::string &filename)
470 if (envs_.find(env_name) == envs_.end()) {
471 throw Exception(
"guarded_load: env %s has not been registered", env_name.c_str());
477 if ((load_rv = clips->load(filename)) != 1) {
479 destroy_env(env_name);
480 throw Exception(
"%s: cannot find %s", env_name.c_str(), filename.c_str());
482 destroy_env(env_name);
483 throw Exception(
"%s: CLIPS code error in %s",
484 env_name.c_str(), filename.c_str());
void remove_features(const std::list< CLIPSFeature *> &features)
Remove a feature by name.
virtual ~CLIPSEnvManager()
Destructor.
Fawkes library namespace.
CLIPSEnvManager(Logger *logger, Clock *clock, std::string &clips_dir)
Constructor.
This is supposed to be the central clock in Fawkes.
A class for handling time.
void destroy_env(const std::string &env_name)
Destroy the named environment.
void add_features(const std::list< CLIPSFeature *> &features)
Add a feature by name.
void assert_can_remove_features(const std::list< CLIPSFeature *> &features)
Assert that a feature can be removed.
Base class for exceptions in Fawkes.
LockPtr< CLIPS::Environment > create_env(const std::string &env_name, const std::string &log_component_name)
Create a new environment.
long get_sec() const
Get seconds.
long get_usec() const
Get microseconds.
std::map< std::string, LockPtr< CLIPS::Environment > > environments() const
Get map of environments.