23 #include "clips_robot_memory_thread.h" 25 #include <core/threading/mutex_locker.h> 36 ClipsRobotMemoryThread::ClipsRobotMemoryThread()
37 :
Thread(
"ClipsRobotMemoryThread",
Thread::OPMODE_WAITFORWAKEUP),
66 envs_[env_name] = clips;
71 clips->add_function(
"bson-create",
72 sigc::slot<CLIPS::Value>(
73 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_create)));
74 clips->add_function(
"bson-parse",
75 sigc::slot<CLIPS::Value, std::string>(
76 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_parse)));
77 clips->add_function(
"bson-destroy",
78 sigc::slot<void, void *>(
79 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_destroy)));
80 clips->add_function(
"bson-append",
81 sigc::slot<void, void *, std::string, CLIPS::Value>(
82 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_append)));
83 clips->add_function(
"bson-append-array",
84 sigc::slot<void, void *, std::string, CLIPS::Values>(
85 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_append_array)));
86 clips->add_function(
"bson-array-start",
87 sigc::slot<CLIPS::Value, void *, std::string>(
88 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_array_start)));
89 clips->add_function(
"bson-array-finish",
90 sigc::slot<void, void *>(
91 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_array_finish)));
92 clips->add_function(
"bson-array-append",
93 sigc::slot<void, void *, CLIPS::Value>(
94 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_array_append)));
96 clips->add_function(
"bson-append-time",
97 sigc::slot<void, void *, std::string, CLIPS::Values>(
98 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_append_time)));
99 clips->add_function(
"bson-tostring",
100 sigc::slot<std::string, void *>(
101 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_tostring)));
102 clips->add_function(
"robmem-insert",
103 sigc::slot<void, std::string, void *>(
104 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_robotmemory_insert)));
105 clips->add_function(
"robmem-upsert",
106 sigc::slot<void, std::string, void *, CLIPS::Value>(
107 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_robotmemory_upsert)));
108 clips->add_function(
"robmem-update",
109 sigc::slot<void, std::string, void *, CLIPS::Value>(
110 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_robotmemory_update)));
111 clips->add_function(
"robmem-replace",
112 sigc::slot<void, std::string, void *, CLIPS::Value>(
113 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_robotmemory_replace)));
114 clips->add_function(
"robmem-query",
115 sigc::slot<CLIPS::Value, std::string, void *>(
116 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_robotmemory_query)));
117 clips->add_function(
"robmem-remove",
118 sigc::slot<void, std::string, void *>(
119 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_robotmemory_remove)));
120 clips->add_function(
"robmem-query-sort",
121 sigc::slot<CLIPS::Value, std::string, void *, void *>(
123 &ClipsRobotMemoryThread::clips_robotmemory_query_sort)));
124 clips->add_function(
"robmem-cursor-destroy",
125 sigc::slot<void, void *>(
127 &ClipsRobotMemoryThread::clips_robotmemory_cursor_destroy)));
128 clips->add_function(
"robmem-cursor-more",
129 sigc::slot<CLIPS::Value, void *>(
131 &ClipsRobotMemoryThread::clips_robotmemory_cursor_more)));
132 clips->add_function(
"robmem-cursor-next",
133 sigc::slot<CLIPS::Value, void *>(
135 &ClipsRobotMemoryThread::clips_robotmemory_cursor_next)));
136 clips->add_function(
"robmem-trigger-register",
137 sigc::slot<CLIPS::Value, std::string, void *, std::string>(sigc::bind<0>(
139 &ClipsRobotMemoryThread::clips_robotmemory_register_trigger),
141 clips->add_function(
"robmem-trigger-destroy",
142 sigc::slot<void, void *>(
144 &ClipsRobotMemoryThread::clips_robotmemory_destroy_trigger)));
145 clips->add_function(
"bson-field-names",
146 sigc::slot<CLIPS::Values, void *>(
147 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_field_names)));
148 clips->add_function(
"bson-has-field",
149 sigc::slot<CLIPS::Value, void *, std::string>(
150 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_has_field)));
151 clips->add_function(
"bson-get",
152 sigc::slot<CLIPS::Value, void *, std::string>(
153 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_get)));
154 clips->add_function(
"bson-get-array",
155 sigc::slot<CLIPS::Values, void *, std::string>(
156 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_get_array)));
157 clips->add_function(
"bson-get-time",
158 sigc::slot<CLIPS::Values, void *, std::string>(
159 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_bson_get_time)));
160 clips->add_function(
"robmem-create-index",
161 sigc::slot<void, std::string, void *>(
163 &ClipsRobotMemoryThread::clips_robotmemory_create_index)));
164 clips->add_function(
"robmem-create-unique-index",
165 sigc::slot<void, std::string, void *>(sigc::mem_fun(
166 *
this, &ClipsRobotMemoryThread::clips_robotmemory_create_unique_index)));
168 clips->add_function(
"robmem-mutex-create",
169 sigc::slot<CLIPS::Value, std::string>(
171 &ClipsRobotMemoryThread::clips_robotmemory_mutex_create)));
172 clips->add_function(
"robmem-mutex-destroy",
173 sigc::slot<CLIPS::Value, std::string>(
175 &ClipsRobotMemoryThread::clips_robotmemory_mutex_destroy)));
176 clips->add_function(
"robmem-mutex-try-lock",
177 sigc::slot<CLIPS::Value, std::string, std::string>(
179 &ClipsRobotMemoryThread::clips_robotmemory_mutex_try_lock)));
180 clips->add_function(
"robmem-mutex-renew-lock",
181 sigc::slot<CLIPS::Value, std::string, std::string>(sigc::mem_fun(
182 *
this, &ClipsRobotMemoryThread::clips_robotmemory_mutex_renew_lock)));
183 clips->add_function(
"robmem-mutex-force-lock",
184 sigc::slot<CLIPS::Value, std::string, std::string>(sigc::mem_fun(
185 *
this, &ClipsRobotMemoryThread::clips_robotmemory_mutex_force_lock)));
186 clips->add_function(
"robmem-mutex-unlock",
187 sigc::slot<CLIPS::Value, std::string, std::string>(
189 &ClipsRobotMemoryThread::clips_robotmemory_mutex_unlock)));
190 clips->add_function(
"robmem-mutex-setup-ttl",
191 sigc::slot<CLIPS::Value, float>(
193 &ClipsRobotMemoryThread::clips_robotmemory_mutex_setup_ttl)));
194 clips->add_function(
"robmem-mutex-expire-locks",
195 sigc::slot<CLIPS::Value, float>(sigc::mem_fun(
196 *
this, &ClipsRobotMemoryThread::clips_robotmemory_mutex_expire_locks)));
198 clips->add_function(
"robmem-mutex-create-async",
199 sigc::slot<CLIPS::Values, std::string>(sigc::mem_fun(
200 *
this, &ClipsRobotMemoryThread::clips_robotmemory_mutex_create_async)));
201 clips->add_function(
"robmem-mutex-destroy-async",
202 sigc::slot<CLIPS::Values, std::string>(sigc::mem_fun(
203 *
this, &ClipsRobotMemoryThread::clips_robotmemory_mutex_destroy_async)));
205 "robmem-mutex-try-lock-async",
206 sigc::slot<CLIPS::Values, std::string, std::string>(sigc::bind<0>(
207 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_robotmemory_mutex_try_lock_async),
210 "robmem-mutex-renew-lock-async",
211 sigc::slot<CLIPS::Values, std::string, std::string>(sigc::bind<0>(
212 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_robotmemory_mutex_renew_lock_async),
214 clips->add_function(
"robmem-mutex-force-lock-async",
215 sigc::slot<CLIPS::Values, std::string, std::string>(sigc::mem_fun(
216 *
this, &ClipsRobotMemoryThread::clips_robotmemory_mutex_force_lock_async)));
217 clips->add_function(
"robmem-mutex-unlock-async",
218 sigc::slot<CLIPS::Values, std::string, std::string>(sigc::mem_fun(
219 *
this, &ClipsRobotMemoryThread::clips_robotmemory_mutex_unlock_async)));
221 "robmem-mutex-expire-locks-async",
222 sigc::slot<CLIPS::Value, float>(sigc::bind<0>(
223 sigc::mem_fun(*
this, &ClipsRobotMemoryThread::clips_robotmemory_mutex_expire_locks_async),
226 clips->build(
"(deffacts have-feature-mongodb (have-feature MongoDB))");
229 clips->batch_evaluate(SRCDIR
"/robot-memory.clp");
237 envs_.erase(env_name);
242 ClipsRobotMemoryThread::clips_bson_create()
244 mongo::BSONObjBuilder *b =
new mongo::BSONObjBuilder();
245 return CLIPS::Value(b);
249 ClipsRobotMemoryThread::clips_bson_parse(std::string document)
251 mongo::BSONObjBuilder *b =
new mongo::BSONObjBuilder();
253 b->appendElements(mongo::fromjson(document));
254 #ifdef HAVE_MONGODB_VERSION_H 255 }
catch (mongo::MsgAssertionException &e) {
257 }
catch (mongo::AssertionException &e) {
259 logger->
log_error(
"MongoDB",
"Parsing JSON doc failed: %s\n%s", e.what(), document.c_str());
261 return CLIPS::Value(b);
265 ClipsRobotMemoryThread::clips_bson_destroy(
void *bson)
267 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
272 ClipsRobotMemoryThread::clips_bson_tostring(
void *bson)
274 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
275 return b->asTempObj().jsonString(mongo::Strict,
true);
279 ClipsRobotMemoryThread::clips_bson_append(
void *bson, std::string field_name, CLIPS::Value value)
282 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
283 switch (value.type()) {
284 case CLIPS::TYPE_FLOAT: b->append(field_name, value.as_float());
break;
286 case CLIPS::TYPE_INTEGER: b->append(field_name, value.as_integer());
break;
288 case CLIPS::TYPE_SYMBOL:
289 case CLIPS::TYPE_INSTANCE_NAME:
290 case CLIPS::TYPE_STRING: b->append(field_name, value.as_string());
break;
291 case CLIPS::TYPE_EXTERNAL_ADDRESS: {
292 mongo::BSONObjBuilder *subb = static_cast<mongo::BSONObjBuilder *>(value.as_address());
293 b->append(field_name, subb->asTempObj());
297 logger->
log_warn(
"RefBox",
"Tried to add unknown type to BSON field %s", field_name.c_str());
300 #ifdef HAVE_MONGODB_VERSION_H 301 }
catch (mongo::MsgAssertionException &e) {
303 }
catch (mongo::AssertionException &e) {
306 "Failed to append array value to field %s: %s",
313 ClipsRobotMemoryThread::clips_bson_append_array(
void * bson,
314 std::string field_name,
315 CLIPS::Values values)
318 mongo::BSONObjBuilder * b = static_cast<mongo::BSONObjBuilder *>(bson);
319 mongo::BSONArrayBuilder ab(b->subarrayStart(field_name));
321 for (
auto value : values) {
322 switch (value.type()) {
323 case CLIPS::TYPE_FLOAT: ab.append(value.as_float());
break;
325 case CLIPS::TYPE_INTEGER: ab.append(value.as_integer());
break;
327 case CLIPS::TYPE_SYMBOL:
328 case CLIPS::TYPE_STRING:
329 case CLIPS::TYPE_INSTANCE_NAME: ab.append(value.as_string());
break;
331 case CLIPS::TYPE_EXTERNAL_ADDRESS: {
332 mongo::BSONObjBuilder *subb = static_cast<mongo::BSONObjBuilder *>(value.as_address());
333 ab.append(subb->asTempObj());
338 "Tried to add unknown type to BSON array field %s",
343 #ifdef HAVE_MONGODB_VERSION_H 344 }
catch (mongo::MsgAssertionException &e) {
346 }
catch (mongo::AssertionException &e) {
349 "Failed to append array value to field %s: %s",
356 ClipsRobotMemoryThread::clips_bson_array_start(
void *bson, std::string field_name)
358 mongo::BSONObjBuilder * b = static_cast<mongo::BSONObjBuilder *>(bson);
359 mongo::BufBuilder & bb = b->subarrayStart(field_name);
360 mongo::BSONArrayBuilder *arrb =
new mongo::BSONArrayBuilder(bb);
361 return CLIPS::Value(arrb);
365 ClipsRobotMemoryThread::clips_bson_array_finish(
void *barr)
367 mongo::BSONArrayBuilder *ab = static_cast<mongo::BSONArrayBuilder *>(barr);
372 ClipsRobotMemoryThread::clips_bson_array_append(
void *barr, CLIPS::Value value)
375 mongo::BSONArrayBuilder *ab = static_cast<mongo::BSONArrayBuilder *>(barr);
376 switch (value.type()) {
377 case CLIPS::TYPE_FLOAT: ab->append(value.as_float());
break;
379 case CLIPS::TYPE_INTEGER: ab->append(value.as_integer());
break;
381 case CLIPS::TYPE_SYMBOL:
382 case CLIPS::TYPE_STRING:
383 case CLIPS::TYPE_INSTANCE_NAME: ab->append(value.as_string());
break;
385 case CLIPS::TYPE_EXTERNAL_ADDRESS: {
386 mongo::BSONObjBuilder *subb = static_cast<mongo::BSONObjBuilder *>(value.as_address());
387 ab->append(subb->asTempObj());
390 default:
logger->
log_warn(
"RefBox",
"Tried to add unknown type to BSON array");
break;
392 #ifdef HAVE_MONGODB_VERSION_H 393 }
catch (mongo::MsgAssertionException &e) {
395 }
catch (mongo::AssertionException &e) {
397 logger->
log_error(
"MongoDB",
"Failed to append to array: %s", e.what());
402 ClipsRobotMemoryThread::clips_bson_append_time(
void * bson,
403 std::string field_name,
406 if (time.size() != 2) {
407 logger->
log_warn(
"MongoDB",
"Invalid time, %zu instead of 2 entries", time.size());
410 if (time[0].type() != CLIPS::TYPE_INTEGER || time[1].type() != CLIPS::TYPE_INTEGER) {
416 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
417 struct timeval now = {time[0].as_integer(), time[1].as_integer()};
418 mongo::Date_t nowd = now.tv_sec * 1000 + now.tv_usec / 1000;
419 b->appendDate(field_name, nowd);
420 #ifdef HAVE_MONGODB_VERSION_H 421 }
catch (mongo::MsgAssertionException &e) {
423 }
catch (mongo::AssertionException &e) {
426 "Failed to append time value to field %s: %s",
433 ClipsRobotMemoryThread::clips_robotmemory_insert(std::string collection,
void *bson)
435 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
439 }
catch (mongo::DBException &e) {
445 ClipsRobotMemoryThread::clips_robotmemory_create_index(std::string collection,
void *bson)
447 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
451 }
catch (mongo::DBException &e) {
452 logger->
log_warn(
"MongoDB",
"Creating index failed: %s", e.what());
457 ClipsRobotMemoryThread::clips_robotmemory_create_unique_index(std::string collection,
void *bson)
459 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
463 }
catch (mongo::DBException &e) {
464 logger->
log_warn(
"MongoDB",
"Creating unique index failed: %s", e.what());
469 ClipsRobotMemoryThread::robotmemory_update(std::string & collection,
471 CLIPS::Value & query,
475 mongo::BSONObj query_obj;
476 if (query.type() == CLIPS::TYPE_STRING) {
477 query_obj = mongo::fromjson(query.as_string());
478 }
else if (query.type() == CLIPS::TYPE_EXTERNAL_ADDRESS) {
479 mongo::BSONObjBuilder *qb = static_cast<mongo::BSONObjBuilder *>(query.as_address());
480 query_obj = qb->asTempObj();
482 logger->
log_warn(
"MongoDB",
"Invalid query, must be string or BSON document");
487 #ifdef HAVE_MONGODB_VERSION_H 488 }
catch (mongo::MsgAssertionException &e) {
490 }
catch (mongo::AssertionException &e) {
492 logger->
log_warn(
"MongoDB",
"Compiling query failed: %s", e.what());
493 }
catch (mongo::DBException &e) {
499 ClipsRobotMemoryThread::clips_robotmemory_upsert(std::string collection,
503 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
508 robotmemory_update(collection, b->asTempObj(), query,
true);
512 ClipsRobotMemoryThread::clips_robotmemory_update(std::string collection,
516 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
522 mongo::BSONObjBuilder update_doc;
523 update_doc.append(
"$set", b->asTempObj());
525 robotmemory_update(collection, update_doc.obj(), query,
false);
529 ClipsRobotMemoryThread::clips_robotmemory_replace(std::string collection,
533 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
536 robotmemory_update(collection, b->asTempObj(), query,
false);
540 ClipsRobotMemoryThread::clips_robotmemory_query_sort(std::string collection,
544 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
547 mongo::Query q(b->asTempObj());
549 mongo::BSONObjBuilder *bs = static_cast<mongo::BSONObjBuilder *>(bson_sort);
550 q.sort(bs->asTempObj());
553 #if __cplusplus >= 201103L 556 return CLIPS::Value(
new std::unique_ptr<mongo::DBClientCursor>(std::move(c)),
557 CLIPS::TYPE_EXTERNAL_ADDRESS);
561 return CLIPS::Value(
new std::auto_ptr<mongo::DBClientCursor>(c), CLIPS::TYPE_EXTERNAL_ADDRESS);
564 }
catch (mongo::DBException &e) {
566 return CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL);
571 ClipsRobotMemoryThread::clips_robotmemory_remove(std::string collection,
void *bson)
573 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
575 mongo::Query q(b->asTempObj());
577 }
catch (mongo::DBException &e) {
583 ClipsRobotMemoryThread::clips_robotmemory_query(
const std::string &collection,
void *bson)
585 return clips_robotmemory_query_sort(collection, bson, NULL);
589 ClipsRobotMemoryThread::clips_robotmemory_cursor_destroy(
void *cursor)
591 #if __cplusplus >= 201103L 592 std::unique_ptr<mongo::DBClientCursor> *c =
593 static_cast<std::unique_ptr<mongo::DBClientCursor> *
>(cursor);
595 std::auto_ptr<mongo::DBClientCursor> *c =
596 static_cast<std::auto_ptr<mongo::DBClientCursor> *
>(cursor);
599 if (!c || !c->get()) {
600 logger->
log_error(
"MongoDB",
"mongodb-cursor-destroy: got invalid cursor");
608 ClipsRobotMemoryThread::clips_robotmemory_cursor_more(
void *cursor)
610 #if __cplusplus >= 201103L 611 std::unique_ptr<mongo::DBClientCursor> *c =
612 static_cast<std::unique_ptr<mongo::DBClientCursor> *
>(cursor);
614 std::auto_ptr<mongo::DBClientCursor> *c =
615 static_cast<std::auto_ptr<mongo::DBClientCursor> *
>(cursor);
618 if (!c || !c->get()) {
619 logger->
log_error(
"MongoDB",
"mongodb-cursor-more: got invalid cursor");
620 return CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL);
623 return CLIPS::Value((*c)->more() ?
"TRUE" :
"FALSE", CLIPS::TYPE_SYMBOL);
627 ClipsRobotMemoryThread::clips_robotmemory_cursor_next(
void *cursor)
629 #if __cplusplus >= 201103L 630 std::unique_ptr<mongo::DBClientCursor> *c =
631 static_cast<std::unique_ptr<mongo::DBClientCursor> *
>(cursor);
633 std::auto_ptr<mongo::DBClientCursor> *c =
634 static_cast<std::auto_ptr<mongo::DBClientCursor> *
>(cursor);
637 if (!c || !c->get()) {
638 logger->
log_error(
"MongoDB",
"mongodb-cursor-next: got invalid cursor");
639 return CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL);
642 mongo::BSONObjBuilder *b =
new mongo::BSONObjBuilder();
644 b->appendElements((*c)->nextSafe());
645 #ifdef HAVE_MONGODB_VERSION_H 646 }
catch (mongo::MsgAssertionException &e) {
648 }
catch (mongo::AssertionException &e) {
651 "mongodb-cursor: No more objects in result cursor. What: %s",
653 return CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL);
655 return CLIPS::Value(b);
659 ClipsRobotMemoryThread::clips_bson_field_names(
void *bson)
661 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
664 logger->
log_error(
"MongoDB",
"mongodb-bson-field-names: invalid object");
666 rv.push_back(CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL));
670 std::set<std::string> field_names;
671 b->asTempObj().getFieldNames(field_names);
674 for (
const std::string &n : field_names) {
675 rv.push_back(CLIPS::Value(n));
681 ClipsRobotMemoryThread::clips_bson_get(
void *bson, std::string field_name)
683 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
687 return CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL);
691 mongo::BSONObj o(b->asTempObj());
693 mongo::BSONElement el = o.getFieldDotted(field_name);
696 case mongo::NumberDouble:
return CLIPS::Value(el.Double());
697 case mongo::String:
return CLIPS::Value(el.String());
698 case mongo::Bool:
return CLIPS::Value(el.Bool() ?
"TRUE" :
"FALSE", CLIPS::TYPE_SYMBOL);
699 case mongo::NumberInt:
return CLIPS::Value(el.Int());
700 case mongo::NumberLong:
return CLIPS::Value(el.Long());
701 case mongo::Object: {
702 mongo::BSONObjBuilder *b =
new mongo::BSONObjBuilder();
703 b->appendElements(el.Obj());
704 return CLIPS::Value(b);
707 return CLIPS::Value(el.OID().toString());
709 default:
return CLIPS::Value(
"INVALID_VALUE_TYPE", CLIPS::TYPE_SYMBOL);
711 }
catch (mongo::DBException &e) {
713 "mongodb-bson-get: failed to get '%s': %s",
716 return CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL);
721 ClipsRobotMemoryThread::clips_bson_has_field(
void *bson, std::string field_name)
723 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
727 return CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL);
730 mongo::BSONObj o(b->asTempObj());
732 if (o.getFieldDotted(field_name).eoo()) {
733 return CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL);
735 return CLIPS::Value(
"TRUE", CLIPS::TYPE_SYMBOL);
740 ClipsRobotMemoryThread::clips_bson_get_array(
void *bson, std::string field_name)
742 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
747 logger->
log_error(
"MongoDB",
"mongodb-bson-get-array: invalid object");
748 rv.push_back(CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL));
753 mongo::BSONObj o(b->asTempObj());
755 mongo::BSONElement el = o.getFieldDotted(field_name);
757 if (el.type() != mongo::Array) {
759 "mongodb-bson-get-array: field %s is not an array",
761 rv.push_back(CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL));
765 std::vector<mongo::BSONElement> elements(el.Array());
767 for (
const mongo::BSONElement &e : elements) {
769 case mongo::NumberDouble: rv.push_back(CLIPS::Value(e.Double()));
break;
770 case mongo::String: rv.push_back(CLIPS::Value(e.String()));
break;
772 rv.push_back(CLIPS::Value(e.Bool() ?
"TRUE" :
"FALSE", CLIPS::TYPE_SYMBOL));
774 case mongo::NumberInt: rv.push_back(CLIPS::Value(e.Int()));
break;
775 case mongo::NumberLong: rv.push_back(CLIPS::Value(e.Long()));
break;
776 case mongo::Object: {
777 mongo::BSONObjBuilder *b =
new mongo::BSONObjBuilder();
778 b->appendElements(e.Obj());
779 rv.push_back(CLIPS::Value(b));
783 rv.push_back(CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL));
788 }
catch (mongo::DBException &e) {
790 "mongodb-bson-get: failed to get '%s': %s",
794 rv.push_back(CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL));
800 ClipsRobotMemoryThread::clips_bson_get_time(
void *bson, std::string field_name)
802 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(bson);
808 rv.push_back(CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL));
813 mongo::BSONObj o(b->asTempObj());
815 mongo::BSONElement el = o.getFieldDotted(field_name);
818 if (el.type() == mongo::Date) {
819 mongo::Date_t d = el.Date();
821 }
else if (el.type() == mongo::Timestamp) {
822 mongo::Timestamp_t t = el.Timestamp();
823 ts = (int64_t)t.seconds() * 1000;
826 "mongodb-bson-get-time: field %s is not a time",
828 rv.push_back(CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL));
833 rv[0] = CLIPS::Value((
long long int)(ts / 1000));
834 rv[1] = CLIPS::Value((ts - (rv[0].as_integer() * 1000)) * 1000);
836 }
catch (mongo::DBException &e) {
837 rv.resize(2, CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL));
843 ClipsRobotMemoryThread::clips_robotmemory_register_trigger(std::string env_name,
844 std::string collection,
846 std::string assert_name)
848 mongo::BSONObjBuilder *b = static_cast<mongo::BSONObjBuilder *>(query);
850 mongo::Query q(b->asTempObj());
853 clips_trigger->set_trigger(
855 clips_triggers_.push_back(clips_trigger);
856 return CLIPS::Value(clips_trigger);
857 }
catch (mongo::DBException &e) {
858 logger->
log_warn(
"CLIPS RobotMemory",
"Trigger query failed: %s", e.what());
859 return CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL);
864 ClipsRobotMemoryThread::clips_robotmemory_destroy_trigger(
void *trigger)
866 ClipsRmTrigger *clips_trigger = static_cast<ClipsRmTrigger *>(trigger);
867 clips_triggers_.remove(clips_trigger);
868 delete clips_trigger;
872 ClipsRobotMemoryThread::clips_robotmemory_mutex_create(std::string name)
875 return CLIPS::Value(rv ?
"TRUE" :
"FALSE", CLIPS::TYPE_SYMBOL);
879 ClipsRobotMemoryThread::clips_robotmemory_mutex_destroy(std::string name)
882 return CLIPS::Value(rv ?
"TRUE" :
"FALSE", CLIPS::TYPE_SYMBOL);
886 ClipsRobotMemoryThread::clips_robotmemory_mutex_try_lock(std::string name, std::string identity)
889 return CLIPS::Value(rv ?
"TRUE" :
"FALSE", CLIPS::TYPE_SYMBOL);
893 ClipsRobotMemoryThread::clips_robotmemory_mutex_renew_lock(std::string name, std::string identity)
896 return CLIPS::Value(rv ?
"TRUE" :
"FALSE", CLIPS::TYPE_SYMBOL);
900 ClipsRobotMemoryThread::clips_robotmemory_mutex_force_lock(std::string name, std::string identity)
903 return CLIPS::Value(rv ?
"TRUE" :
"FALSE", CLIPS::TYPE_SYMBOL);
907 ClipsRobotMemoryThread::clips_robotmemory_mutex_unlock(std::string name, std::string identity)
910 return CLIPS::Value(rv ?
"TRUE" :
"FALSE", CLIPS::TYPE_SYMBOL);
914 ClipsRobotMemoryThread::clips_robotmemory_mutex_setup_ttl(
float max_age_sec)
917 return CLIPS::Value(rv ?
"TRUE" :
"FALSE", CLIPS::TYPE_SYMBOL);
921 ClipsRobotMemoryThread::clips_robotmemory_mutex_expire_locks(
float max_age_sec)
924 return CLIPS::Value(rv ?
"TRUE" :
"FALSE", CLIPS::TYPE_SYMBOL);
928 ClipsRobotMemoryThread::mutex_future_ready(
const std::string &name)
930 auto mf_it = mutex_futures_.find(
name);
931 if (mf_it != mutex_futures_.end()) {
932 auto fut_status = mutex_futures_[
name].wait_for(std::chrono::milliseconds(0));
933 if (fut_status != std::future_status::ready) {
936 mutex_futures_.erase(mf_it);
943 ClipsRobotMemoryThread::clips_robotmemory_mutex_create_async(std::string name)
946 if (!mutex_future_ready(
name)) {
947 rv.push_back(CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL));
948 rv.push_back(CLIPS::Value(
"Task already running for " +
name +
" (create failed)"));
955 mutex_futures_[
name] = std::move(fut);
957 rv.push_back(CLIPS::Value(
"TRUE", CLIPS::TYPE_SYMBOL));
962 ClipsRobotMemoryThread::clips_robotmemory_mutex_destroy_async(std::string name)
965 if (!mutex_future_ready(
name)) {
966 rv.push_back(CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL));
967 rv.push_back(CLIPS::Value(
"Task already running for " +
name +
" (destroy failed)"));
974 mutex_futures_[
name] = std::move(fut);
976 rv.push_back(CLIPS::Value(
"TRUE", CLIPS::TYPE_SYMBOL));
981 ClipsRobotMemoryThread::clips_robotmemory_mutex_try_lock_async(std::string env_name,
983 std::string identity)
986 if (!mutex_future_ready(
name)) {
987 rv.push_back(CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL));
988 rv.push_back(CLIPS::Value(
"Task already running for " +
name +
" (try-lock failed)"));
989 envs_[env_name]->assert_fact_f(
"(mutex-op-feedback try-lock-async FAIL %s)",
name.c_str());
993 auto fut = std::async(std::launch::async, [
this, env_name,
name, identity] {
997 envs_[env_name]->assert_fact_f(
"(mutex-op-feedback try-lock-async FAIL %s)",
name.c_str());
1002 mutex_futures_[
name] = std::move(fut);
1004 rv.push_back(CLIPS::Value(
"TRUE", CLIPS::TYPE_SYMBOL));
1009 ClipsRobotMemoryThread::clips_robotmemory_mutex_renew_lock_async(std::string env_name,
1011 std::string identity)
1014 if (!mutex_future_ready(
name)) {
1015 rv.push_back(CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL));
1016 rv.push_back(CLIPS::Value(
"Task already running for " +
name +
" (try-lock failed)"));
1018 envs_[env_name]->assert_fact_f(
"(mutex-op-feedback renew-lock-async FAIL %s)",
name.c_str());
1022 auto fut = std::async(std::launch::async, [
this, env_name,
name, identity] {
1025 envs_[env_name]->assert_fact_f(
"(mutex-op-feedback renew-lock-async %s %s)",
1031 mutex_futures_[
name] = std::move(fut);
1033 rv.push_back(CLIPS::Value(
"TRUE", CLIPS::TYPE_SYMBOL));
1038 ClipsRobotMemoryThread::clips_robotmemory_mutex_force_lock_async(std::string name,
1039 std::string identity)
1042 if (!mutex_future_ready(
name)) {
1043 rv.push_back(CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL));
1044 rv.push_back(CLIPS::Value(
"Task already running for " +
name +
" (force-lock failed)"));
1048 auto fut = std::async(std::launch::async, [
this,
name, identity] {
1052 mutex_futures_[
name] = std::move(fut);
1054 rv.push_back(CLIPS::Value(
"TRUE", CLIPS::TYPE_SYMBOL));
1059 ClipsRobotMemoryThread::clips_robotmemory_mutex_unlock_async(std::string name, std::string identity)
1062 if (!mutex_future_ready(
name)) {
1063 rv.push_back(CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL));
1064 rv.push_back(CLIPS::Value(
"Task already running for " +
name +
" (unlock failed)"));
1068 auto fut = std::async(std::launch::async, [
this,
name, identity] {
1072 mutex_futures_[
name] = std::move(fut);
1074 rv.push_back(CLIPS::Value(
"TRUE", CLIPS::TYPE_SYMBOL));
1079 ClipsRobotMemoryThread::clips_robotmemory_mutex_expire_locks_async(std::string env_name,
1083 if (mutex_expire_future_.valid()) {
1085 auto fut_status = mutex_expire_future_.wait_for(std::chrono::milliseconds(0));
1086 if (fut_status != std::future_status::ready) {
1088 envs_[env_name]->assert_fact_f(
"(mutex-op-feedback expire-locks-async FAIL)");
1089 return CLIPS::Value(
"FALSE", CLIPS::TYPE_SYMBOL);
1093 auto fut = std::async(std::launch::async, [
this, env_name, max_age_sec] {
1096 envs_[env_name]->assert_fact_f(
"(mutex-op-feedback expire-locks-async %s)", ok ?
"OK" :
"FAIL");
1100 mutex_expire_future_ = std::move(fut);
1102 return CLIPS::Value(
"TRUE", CLIPS::TYPE_SYMBOL);
Thread aspect to provide a feature to CLIPS environments.
QResCursor query(mongo::Query query, const std::string &collection="")
Query information from the robot memory.
virtual void finalize()
Finalize the thread.
bool mutex_unlock(const std::string &name, const std::string &identity)
Release lock on mutex.
int create_index(mongo::BSONObj keys, const std::string &collection="", bool unique=false)
Create an index on a collection.
int remove(mongo::Query query, const std::string &collection="")
Remove documents from the robot memory.
Fawkes library namespace.
int update(mongo::Query query, mongo::BSONObj update, const std::string &collection="", bool upsert=false)
Updates documents in the robot memory.
virtual void loop()
Code to execute in the thread.
void unlock() const
Unlock object mutex.
Thread class encapsulation of pthreads.
Logger * logger
This is the Logger member used to access the logger.
void callback(mongo::BSONObj update)
Callback function for the trigger.
int insert(mongo::BSONObj obj, const std::string &collection="")
Inserts a document into the robot memory.
bool mutex_try_lock(const std::string &name, bool force=false)
Try to acquire a lock for a mutex.
bool mutex_renew_lock(const std::string &name, const std::string &identity)
Renew a mutex.
virtual void clips_context_init(const std::string &env_name, fawkes::LockPtr< CLIPS::Environment > &clips)
Initialize a CLIPS context to use the provided feature.
bool mutex_setup_ttl(float max_age_sec)
Setup time-to-live index for mutexes.
CLIPS feature maintainer.
const char * name() const
Get name of thread.
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
virtual void log_error(const char *component, const char *format,...)=0
Log error message.
RobotMemory * robot_memory
RobotMemory object for storing and querying information.
bool mutex_create(const std::string &name)
Explicitly create a mutex.
EventTrigger * register_trigger(mongo::Query query, const std::string &collection, void(T::*callback)(mongo::BSONObj), T *_obj)
Register a trigger to be notified when the robot memory is updated and the updated document matches t...
bool mutex_destroy(const std::string &name)
Destroy a mutex.
virtual void clips_context_destroyed(const std::string &env_name)
Notification that a CLIPS environment has been destroyed.
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
bool mutex_expire_locks(float max_age_sec)
Expire old locks on mutexes.
void lock() const
Lock access to the encapsulated object.
virtual void init()
Initialize the thread.