23 #include <logging/logger.h>
24 #include <plugins/clips/aspect/clips_env_manager.h>
25 #include <plugins/clips/aspect/clips_feature.h>
26 #include <utils/time/time.h>
31 #include <clips/clips.h>
36 #define ROUTER_NAME "fawkeslog"
42 CLIPSLogger(Logger *logger,
const char *component = NULL)
46 component_ = strdup(component);
60 log(
const char *logical_name,
const char *str)
62 if (strcmp(str,
"\n") == 0) {
63 if (strcmp(logical_name,
"debug") == 0 || strcmp(logical_name,
"logdebug") == 0
64 || strcmp(logical_name, WTRACE) == 0) {
65 logger_->log_debug(component_ ? component_ :
"CLIPS",
"%s", buffer_.c_str());
66 }
else if (strcmp(logical_name,
"warn") == 0 || strcmp(logical_name,
"logwarn") == 0
67 || strcmp(logical_name, WWARNING) == 0) {
68 logger_->log_warn(component_ ? component_ :
"CLIPS",
"%s", buffer_.c_str());
69 }
else if (strcmp(logical_name,
"error") == 0 || strcmp(logical_name,
"logerror") == 0
70 || strcmp(logical_name, WERROR) == 0) {
71 logger_->log_error(component_ ? component_ :
"CLIPS",
"%s", buffer_.c_str());
72 }
else if (strcmp(logical_name, WDIALOG) == 0) {
75 logger_->log_info(component_ ? component_ :
"CLIPS",
"%s", buffer_.c_str());
90 class CLIPSContextMaintainer
93 CLIPSContextMaintainer(Logger *logger,
const char *log_component_name)
94 : logger(logger, log_component_name)
98 ~CLIPSContextMaintainer()
107 log_router_query(
void *env,
char *logical_name)
109 if (strcmp(logical_name,
"l") == 0)
111 if (strcmp(logical_name,
"info") == 0)
113 if (strcmp(logical_name,
"debug") == 0)
115 if (strcmp(logical_name,
"warn") == 0)
117 if (strcmp(logical_name,
"error") == 0)
119 if (strcmp(logical_name,
"loginfo") == 0)
121 if (strcmp(logical_name,
"logdebug") == 0)
123 if (strcmp(logical_name,
"logwarn") == 0)
125 if (strcmp(logical_name,
"logerror") == 0)
127 if (strcmp(logical_name,
"stdout") == 0)
129 if (strcmp(logical_name, WTRACE) == 0)
131 if (strcmp(logical_name, WDIALOG) == 0)
133 if (strcmp(logical_name, WWARNING) == 0)
135 if (strcmp(logical_name, WERROR) == 0)
137 if (strcmp(logical_name, WDISPLAY) == 0)
143 log_router_print(
void *env,
char *logical_name,
char *str)
145 void * rc = GetEnvironmentRouterContext(env);
146 CLIPSLogger *logger =
static_cast<CLIPSLogger *
>(rc);
147 logger->
log(logical_name, str);
152 log_router_exit(
void *env,
int exit_code)
176 clips_dir_ = clips_dir;
190 CLIPSEnvManager::new_env(
const std::string &log_component_name)
194 struct sigaction oldact;
195 if (sigaction(SIGINT, NULL, &oldact) == 0) {
200 clips->unwatch(
"all");
202 CLIPSContextMaintainer *cm =
new CLIPSContextMaintainer(logger_, log_component_name.c_str());
204 void *env = clips->cobj();
206 SetEnvironmentContext(env, cm);
208 EnvAddRouterWithContext(env,
219 sigaction(SIGINT, &oldact, NULL);
223 throw Exception(
"CLIPS: Unable to backup "
224 "SIGINT sigaction for restoration.");
240 if (envs_.find(env_name) != envs_.end()) {
241 throw Exception(
"CLIPS environment '%s' already exists", env_name.c_str());
244 clips = new_env(log_component_name);
247 envs_[env_name].env = clips;
250 add_functions(env_name, clips);
253 assert_features(clips,
true);
255 guarded_load(env_name, clips_dir_ +
"utils.clp");
256 guarded_load(env_name, clips_dir_ +
"time.clp");
257 guarded_load(env_name, clips_dir_ +
"path.clp");
259 clips->evaluate(
"(path-add \"" + clips_dir_ +
"\")");
263 throw Exception(
"Failed to initialize CLIPS environment '%s'", env_name.c_str());
274 if (envs_.find(env_name) != envs_.end()) {
275 void * env = envs_[env_name].env->cobj();
276 CLIPSContextMaintainer *cm =
static_cast<CLIPSContextMaintainer *
>(GetEnvironmentContext(env));
278 EnvDeleteRouter(env, (
char *)ROUTER_NAME);
279 SetEnvironmentContext(env, NULL);
282 for (
auto feat : envs_[env_name].req_feat) {
283 if (features_.find(feat) != features_.end()) {
284 features_[feat]->clips_context_destroyed(env_name);
288 envs_.erase(env_name);
295 std::map<std::string, LockPtr<CLIPS::Environment>>
298 std::map<std::string, LockPtr<CLIPS::Environment>> rv;
299 for (
auto envd : envs_) {
300 rv[envd.first] = envd.second.env;
306 CLIPSEnvManager::clips_request_feature(std::string env_name, std::string feature_name)
311 "Environment %s requests feature %s",
313 feature_name.c_str());
315 if (envs_.find(env_name) == envs_.end()) {
316 logger_->
log_warn(
"ClipsEnvManager",
317 "Feature %s request from non-existent environment %s",
318 feature_name.c_str(),
320 return CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL);
322 if (features_.find(feature_name) == features_.end()) {
323 logger_->
log_warn(
"ClipsEnvManager",
324 "Environment requested unavailable feature %s",
325 feature_name.c_str());
326 return CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL);
329 ClipsEnvData &envd = envs_[env_name];
330 if (std::binary_search(envd.req_feat.begin(), envd.req_feat.end(), feature_name)) {
331 logger_->
log_warn(
"ClipsEnvManager",
332 "Environment %s requested feature %s *again*",
334 feature_name.c_str());
335 return CLIPS::Value(
"TRUE", CLIPS::TYPE_SYMBOL);
339 features_[feature_name]->clips_context_init(env_name, envd.env);
340 envd.req_feat.push_back(feature_name);
341 envd.req_feat.sort();
344 std::string deffacts =
"(deffacts ff-features-loaded";
346 for (
auto feat : envd.req_feat) {
347 deffacts +=
" (ff-feature-loaded " + feat +
")";
351 envd.env->assert_fact_f(
"(ff-feature-loaded %s)", feature_name.c_str());
353 if (!envd.env->build(deffacts)) {
354 logger_->
log_warn(
"ClipsEnvManager",
355 "Failed to build deffacts ff-features-loaded "
362 return CLIPS::Value(rv ?
"TRUE" :
"FALSE", CLIPS::TYPE_SYMBOL);
366 CLIPSEnvManager::clips_now()
370 rv.push_back(now.get_sec());
371 rv.push_back(now.get_usec());
376 CLIPSEnvManager::clips_now_systime()
388 CLIPSEnvManager::add_functions(
const std::string &env_name, LockPtr<CLIPS::Environment> &clips)
390 clips->add_function(
"ff-feature-request",
391 sigc::slot<CLIPS::Value, std::string>(
392 sigc::bind<0>(sigc::mem_fun(*
this, &CLIPSEnvManager::clips_request_feature),
394 clips->add_function(
"now",
395 sigc::slot<CLIPS::Values>(sigc::mem_fun(*
this, &CLIPSEnvManager::clips_now)));
396 clips->add_function(
"now-systime",
397 sigc::slot<CLIPS::Values>(
398 sigc::mem_fun(*
this, &CLIPSEnvManager::clips_now_systime)));
402 CLIPSEnvManager::assert_features(LockPtr<CLIPS::Environment> &clips,
bool immediate_assert)
405 std::string deffacts =
"(deffacts ff-features-available";
407 for (
auto feat : features_) {
408 deffacts +=
" (ff-feature " + feat.first +
")";
409 if (immediate_assert) {
411 clips->assert_fact_f(
"(ff-feature %s)", feat.first.c_str());
416 if (!clips->build(deffacts)) {
417 logger_->
log_warn(
"ClipsEnvManager",
"Failed to build deffacts ff-features-available");
427 for (
auto feat : features) {
428 const std::string &feature_name = feat->clips_feature_name;
430 if (features_.find(feature_name) != features_.end()) {
431 throw Exception(
"Feature '%s' has already been registered", feature_name.c_str());
434 logger_->
log_info(
"ClipsEnvManager",
"Adding feature %s", feature_name.c_str());
436 features_[feature_name] = feat;
439 for (
auto env : envs_) {
440 env.second.env.lock();
441 assert_features(env.second.env,
false);
443 env.second.env->assert_fact_f(
"(ff-feature %s)", feature_name.c_str());
444 env.second.env.unlock();
459 for (
auto feat : features) {
460 const std::string &feature_name = feat->clips_feature_name;
462 for (
auto env : envs_) {
463 if (std::binary_search(env.second.req_feat.begin(),
464 env.second.req_feat.end(),
466 throw Exception(
"Cannot remove feature %s as environment %s depends on it",
467 feature_name.c_str(),
485 for (
auto feat : features) {
486 features_.erase(feat->clips_feature_name);
491 CLIPSEnvManager::guarded_load(
const std::string &env_name,
const std::string &filename)
493 if (envs_.find(env_name) == envs_.end()) {
494 throw Exception(
"guarded_load: env %s has not been registered", env_name.c_str());
497 LockPtr<CLIPS::Environment> &clips = envs_[env_name].env;
500 if ((load_rv = clips->load(filename)) != 1) {
503 throw Exception(
"%s: cannot find %s", env_name.c_str(), filename.c_str());
506 throw Exception(
"%s: CLIPS code error in %s", env_name.c_str(), filename.c_str());