Fawkes API  Fawkes Development Version
event_trigger_manager.cpp
1 /***************************************************************************
2  * event_trigger_manager.cpp - Manager to realize triggers on events in the robot memory
3  *
4  *
5  * Created: 3:53:46 PM 2016
6  * Copyright 2016 Frederik Zwilling
7  ****************************************************************************/
8 
9 /* This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Library General Public License for more details.
18  *
19  * Read the full text in the LICENSE.GPL file in the doc directory.
20  */
21 
22 #include "event_trigger_manager.h"
23 
24 #include <boost/bind.hpp>
25 
26 using namespace fawkes;
27 using namespace mongo;
28 
29 /** @class EventTriggerManager event_trigger_manager.h
30  * Manager to realize triggers on events in the robot memory
31  * @author Frederik Zwilling
32  */
33 
34 /**
35  * Constructor for class managing EventTriggers
36  * @param logger Logger
37  * @param config Configuration
38  * @param mongo_connection_manager MongoDBConnCreator
39  */
41  Configuration * config,
42  MongoDBConnCreator *mongo_connection_manager)
43 : cfg_debug_(false)
44 {
45  logger_ = logger;
46  config_ = config;
47  mongo_connection_manager_ = mongo_connection_manager;
48 
49  con_local_ = mongo_connection_manager_->create_client("robot-memory-local");
50  if (config_->exists("/plugins/mongodb/clients/robot-memory-distributed/enabled")
51  && config_->get_bool("/plugins/mongodb/clients/robot-memory-distributed/enabled")) {
52  con_replica_ = mongo_connection_manager_->create_client("robot-memory-distributed");
53  }
54 
55  // create connections to running mongod instances because only there
56  std::string local_db = config_->get_string("/plugins/robot-memory/database");
57  dbnames_local_.push_back(local_db);
58  dbnames_distributed_ = config_->get_strings("/plugins/robot-memory/distributed-db-names");
59 
60  mutex_ = new Mutex();
61 
62  try {
63  cfg_debug_ = config->get_bool("/plugins/robot-memory/more-debug-output");
64  } catch (...) {
65  }
66 }
67 
68 EventTriggerManager::~EventTriggerManager()
69 {
70  for (EventTrigger *trigger : triggers) {
71  delete trigger;
72  }
73  mongo_connection_manager_->delete_client(con_local_);
74  mongo_connection_manager_->delete_client(con_replica_);
75  delete mutex_;
76 }
77 
78 void
79 EventTriggerManager::check_events()
80 {
81  //lock to be thread safe (e.g. registration during checking)
82  MutexLocker lock(mutex_);
83 
84  for (EventTrigger *trigger : triggers) {
85  bool ok = true;
86  try {
87  while (trigger->oplog_cursor->more()) {
88  BSONObj change = trigger->oplog_cursor->next();
89  //logger_->log_info(name.c_str(), "Triggering: %s", change.toString().c_str());
90  //actually call the callback function
91  trigger->callback(change);
92  }
93  } catch (mongo::DBException &e) {
94  logger_->log_error(name.c_str(), "Error while reading the oplog");
95  ok = false;
96  }
97  if (!ok || trigger->oplog_cursor->isDead()) {
98  if (cfg_debug_)
99  logger_->log_debug(name.c_str(), "Tailable Cursor is dead, requerying");
100  //check if collection is local or replicated
101  mongo::DBClientBase *con;
102  if (std::find(dbnames_distributed_.begin(),
103  dbnames_distributed_.end(),
104  get_db_name(trigger->ns_db))
105  != dbnames_distributed_.end()) {
106  con = con_replica_;
107  } else {
108  con = con_local_;
109  }
110 
111  trigger->oplog_cursor = create_oplog_cursor(con, "local.oplog.rs", trigger->oplog_query);
112  }
113  }
114 }
115 
116 /**
117  * Remove a previously registered trigger
118  * @param trigger Pointer to the trigger to remove
119  */
120 void
122 {
123  triggers.remove(trigger);
124  delete trigger;
125 }
126 
127 QResCursor
128 EventTriggerManager::create_oplog_cursor(mongo::DBClientBase *con,
129  std::string oplog,
130  mongo::Query query)
131 {
132  QResCursor res = con->query(oplog, query, 0, 0, 0, QueryOption_CursorTailable);
133  //Go to end of Oplog to get new updates from then on
134  while (res->more()) {
135  res->next();
136  }
137  return res;
138 }
139 
140 /** Split database name from namespace.
141  * @param ns namespace, format db.collection
142  * @return db part of @p ns
143  */
144 std::string
145 EventTriggerManager::get_db_name(const std::string &ns)
146 {
147  std::string::size_type dot_pos = ns.find(".");
148  if (dot_pos == std::string::npos) {
149  return "";
150  } else {
151  return ns.substr(0, dot_pos);
152  }
153 }
Fawkes library namespace.
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
Mutex locking helper.
Definition: mutex_locker.h:33
Class holding all information about an EventTrigger.
Definition: event_trigger.h:32
static std::string get_db_name(const std::string &ns)
Split database name from namespace.
virtual mongo::DBClientBase * create_client(const std::string &config_name="")=0
Create a new MongoDB client.
Interface for a MongoDB connection creator.
virtual void log_error(const char *component, const char *format,...)=0
Log error message.
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
virtual std::vector< std::string > get_strings(const char *path)=0
Get list of values from configuration which is of type string.
void remove_trigger(EventTrigger *trigger)
Remove a previously registered trigger.
EventTriggerManager(fawkes::Logger *logger, fawkes::Configuration *config, fawkes::MongoDBConnCreator *mongo_connection_manager)
Constructor for class managing EventTriggers.
virtual bool exists(const char *path)=0
Check if a given value exists.
Mutex mutual exclusion lock.
Definition: mutex.h:32
Interface for configuration handling.
Definition: config.h:64
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.
virtual void delete_client(mongo::DBClientBase *client)=0
Delete a client.
Interface for logging.
Definition: logger.h:41