Drizzled Public API Documentation

event_observer.cc
1 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3  *
4  * Copyright (C) 2010 PrimeBase Technologies GmbH, Germany
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  *
19  * Barry Leslie
20  *
21  * 2010-05-12
22  */
23 
24 #include <config.h>
25 
26 #include <string>
27 #include <vector>
28 
29 #include <drizzled/session.h>
30 #include <drizzled/table_list.h>
31 #include <drizzled/table/instance.h>
32 #include <drizzled/module/registry.h>
33 #include <drizzled/plugin/event_observer.h>
34 #include <drizzled/util/functors.h>
35 #include <algorithm>
36 
37 namespace drizzled {
38 namespace plugin {
39 
40  EventObserverVector all_event_plugins;
41 
42  const EventObserverVector &EventObserver::getEventObservers()
43  {
44  return all_event_plugins;
45  }
46 
47  bool EventObserver::addPlugin(EventObserver *handler)
48  {
49  if (handler != NULL)
50  all_event_plugins.push_back(handler);
51  return false;
52  }
53 
54  void EventObserver::removePlugin(EventObserver *handler)
55  {
56  if (handler != NULL)
57  all_event_plugins.erase(std::find(all_event_plugins.begin(), all_event_plugins.end(), handler));
58  }
59 
60 
61  /*
62  * The Event Observer list class in which plugins register which events they
63  * are interested in.
64  *
65  * Each table share for example, will have one of these hung on it to store
66  * a list off all event observers interested in it and which events they are
67  * interested in.
68  */
70  {
71 
72  public:
73  typedef std::multimap<uint32_t, EventObserver *> ObserverMap;
74 
75  private:
76  /* A list of lists indexed by event type. */
77  std::vector<ObserverMap *> event_observer_lists;
78 
79  public:
80 
82  {
83  // Initialize the list with NULL pointers.
84  event_observer_lists.assign(EventObserver::MAX_EVENT_COUNT, NULL);
85  }
86 
88  {
89  std::for_each(event_observer_lists.begin(),
90  event_observer_lists.end(),
91  DeletePtr());
92  event_observer_lists.clear();
93  }
94 
95  /* Add the observer to the observer list for the even, positioning it if required.
96  *
97  * Note: Event observers are storted in a multimap object so that the order in which
98  * they are called can be sorted based on the requested position. Lookups are never done
99  * on the multimap, once filled it is used as a vector.
100  */
101  void addObserver(EventObserver *eventObserver, enum EventObserver::EventType event, int32_t position)
102  {
103  uint32_t event_pos;
104  ObserverMap *observers;
105 
106  observers= event_observer_lists[event];
107  if (observers == NULL)
108  {
109  observers= new ObserverMap();
110  event_observer_lists[event]= observers;
111  }
112 
113  if (position == 0)
114  event_pos= INT32_MAX; // Set the event position to be in the middle.
115  else
116  event_pos= (uint32_t) position;
117 
118  /* If positioned then check if the position is already taken. */
119  if (position)
120  {
121  if (observers->count(event_pos))
122  {
123  errmsg_printf(error::WARN,
124  _("EventObserverList::addEventObserver() Duplicate event position %d for event '%s' from EventObserver plugin '%s'"),
125  position,
126  EventObserver::eventName(event),
127  eventObserver->getName().c_str());
128  }
129  }
130 
131  observers->insert(std::pair<uint32_t, EventObserver *>(event_pos, eventObserver) );
132  }
133 
134 
135  /* Get the observer list for an event type. Will return NULL if no observer exists.*/
136  ObserverMap *getObservers(enum EventObserver::EventType event)
137  {
138  return event_observer_lists[event];
139  }
140  };
141 
142 
143  //---------
144  /* registerEvent() is called from the event observer plugins to add themselves to
145  * the event observer list to be notified when the specified event takes place.
146  */
147  void EventObserver::registerEvent(EventObserverList &observers, EventType event, int32_t position)
148  {
149  observers.addObserver(this, event, position);
150  }
151 
152  /*========================================================*/
153  /* Table Event Observer handling: */
154  /*========================================================*/
155 
156  //----------
157  /* For each EventObserver plugin call its registerTableEventsDo() meathod so that it can
158  * register what events, if any, it is interested in on this table.
159  */
160  class RegisterTableEventsIterate : public std::unary_function<EventObserver *, void>
161  {
162  TableShare &table_share;
163  EventObserverList &observers;
164 
165  public:
166  RegisterTableEventsIterate(TableShare &table_share_arg, EventObserverList &observers_arg):
167  table_share(table_share_arg), observers(observers_arg) {}
168  inline result_type operator() (argument_type eventObserver)
169  {
170  eventObserver->registerTableEventsDo(table_share, observers);
171  }
172  };
173 
174  //----------
175  /*
176  * registerTableEvents() is called by drizzle to register all plugins that
177  * may be interested in table events on the newly created TableShare object.
178  */
179  void EventObserver::registerTableEvents(TableShare &table_share)
180  {
181  if (all_event_plugins.empty())
182  return;
183 
184  EventObserverList *observers;
185 
186  observers= table_share.getTableObservers();
187 
188  if (observers != NULL)
189  {
190  errmsg_printf(error::WARN,
191  _("EventObserver::registerTableEvents(): Table already has events registered on it: probable programming error."));
192  table_share.setTableObservers(NULL);
193  delete observers;
194  }
195 
196  observers= new EventObserverList();
197  table_share.setTableObservers(observers);
198 
199 
200  std::for_each(all_event_plugins.begin(), all_event_plugins.end(),
201  RegisterTableEventsIterate(table_share, *observers));
202 
203  }
204 
205  //----------
206  /* Cleanup before freeing the TableShare object. */
207  void EventObserver::deregisterTableEvents(TableShare &table_share)
208  {
209  if (all_event_plugins.empty())
210  return;
211 
212  EventObserverList *observers= table_share.getTableObservers();
213 
214  if (observers)
215  {
216  table_share.setTableObservers(NULL);
217  delete observers;
218  }
219  }
220 
221 
222  /*========================================================*/
223  /* Schema Event Observer handling: */
224  /*========================================================*/
225 
226  //----------
227  /* For each EventObserver plugin call its registerSchemaEventsDo() meathod so that it can
228  * register what events, if any, it is interested in on the schema.
229  */
230  class RegisterSchemaEventsIterate : public std::unary_function<EventObserver *, void>
231  {
232  const std::string &db;
233  EventObserverList &observers;
234  public:
235  RegisterSchemaEventsIterate(const std::string &db_arg, EventObserverList &observers_arg) :
236  db(db_arg),
237  observers(observers_arg){}
238 
239  inline result_type operator() (argument_type eventObserver)
240  {
241  eventObserver->registerSchemaEventsDo(db, observers);
242  }
243  };
244 
245  //----------
246  /*
247  * registerSchemaEvents() is called by drizzle to register all plugins that
248  * may be interested in schema events on the database.
249  */
250  void EventObserver::registerSchemaEvents(Session &session, const std::string &db)
251  {
252  if (all_event_plugins.empty())
253  return;
254  EventObserverList *observers= session.getSchemaObservers(db);
255  if (observers == NULL)
256  observers= session.setSchemaObservers(db, new EventObserverList());
257 
258  std::for_each(all_event_plugins.begin(), all_event_plugins.end(),
259  RegisterSchemaEventsIterate(db, *observers));
260 
261  }
262 
263  //----------
264  /* Cleanup before freeing the Session object. */
265  void EventObserver::deregisterSchemaEvents(EventObserverList *observers)
266  {
267  delete observers;
268  }
269 
270  /*========================================================*/
271  /* Session Event Observer handling: */
272  /*========================================================*/
273 
274  //----------
275  /* For each EventObserver plugin call its registerSessionEventsDo() meathod so that it can
276  * register what events, if any, it is interested in on this session.
277  */
278  class RegisterSessionEventsIterate : public std::unary_function<EventObserver *, void>
279  {
280  Session &session;
281  EventObserverList &observers;
282  public:
283  RegisterSessionEventsIterate(Session &session_arg, EventObserverList &observers_arg) :
284  session(session_arg), observers(observers_arg) {}
285  inline result_type operator() (argument_type eventObserver)
286  {
287  eventObserver->registerSessionEventsDo(session, observers);
288  }
289  };
290 
291  //----------
292  /*
293  * registerSessionEvents() is called by drizzle to register all plugins that
294  * may be interested in session events on the newly created session.
295  */
296  void EventObserver::registerSessionEvents(Session &session)
297  {
298  if (all_event_plugins.empty())
299  return;
300 
301  EventObserverList *observers;
302 
303  observers= session.getSessionObservers();
304  if (observers) { // This should not happed
305  errmsg_printf(error::WARN,
306  _("EventObserver::registerSessionEvents(): Session already has events registered on it: probable programming error."));
307  session.setSessionObservers(NULL);
308  delete observers;
309  }
310 
311  observers= new EventObserverList();
312  session.setSessionObservers(observers);
313 
314  std::for_each(all_event_plugins.begin(), all_event_plugins.end(),
315  RegisterSessionEventsIterate(session, *observers));
316 
317  }
318 
319  //----------
320  /* Cleanup before freeing the session object. */
321  void EventObserver::deregisterSessionEvents(EventObserverList *observers)
322  {
323  delete observers;
324  }
325 
326 
327  /* Event observer list iterator: */
328  //----------
329  class EventIterate : public std::unary_function<std::pair<uint32_t, EventObserver *>, bool>
330  {
331  EventData &data;
332 
333  public:
334  EventIterate(EventData &data_arg) :
335  std::unary_function<std::pair<uint32_t, EventObserver *>, bool>(),
336  data(data_arg)
337  {}
338 
339  inline result_type operator()(argument_type handler)
340  {
341  bool result= handler.second->observeEventDo(data);
342  if (result)
343  {
344  /* TRANSLATORS: The leading word "EventObserver" is the name
345  of the plugin api, and so should not be translated. */
346  errmsg_printf(error::ERROR,
347  _("EventIterate event handler '%s' failed for event '%s'"),
348  handler.second->getName().c_str(), handler.second->eventName(data.event));
349 
350  }
351  return result;
352  }
353  };
354 
355 
356  /*==========================================================*/
357  /* Generic meathods called by drizzle to notify all interested
358  * plugins of an event,
359  */
360 
361  // Call all event observers interested in the event.
362  bool EventData::callEventObservers()
363  {
364  EventObserverList::ObserverMap *eventObservers;
365 
366  if (observerList == NULL)
367  return false; // Nobody was interested in the event. :(
368 
369  eventObservers = observerList->getObservers(event);
370 
371  if (eventObservers == NULL)
372  return false; // Nobody was interested in the event. :(
373 
374  /* Use find_if instead of foreach so that we can collect return codes */
375  EventObserverList::ObserverMap::iterator iter=
376  std::find_if(eventObservers->begin(), eventObservers->end(),
377  EventIterate(*this));
378  /* If iter is == end() here, that means that all of the plugins returned
379  * false, which in this case means they all succeeded. Since we want to
380  * return false on success, we return the value of the two being !=.
381  */
382  return iter != eventObservers->end();
383  }
384 
385  //--------
386  bool SessionEventData::callEventObservers()
387  {
388  observerList= session.getSessionObservers();
389 
390  return EventData::callEventObservers();
391  }
392 
393  bool SessionEventData::hasEvents(Session &in_session)
394  {
395  return (in_session.getSessionObservers() != NULL);
396  }
397 
398  //--------
399  bool SchemaEventData::callEventObservers()
400  {
401  observerList= session.getSchemaObservers(db);
402  if (!observerList)
403  {
404  EventObserver::registerSchemaEvents(session, db);
405  observerList= session.getSchemaObservers(db);
406  }
407 
408  return EventData::callEventObservers();
409  }
410 
411  //--------
412  bool TableEventData::callEventObservers()
413  {
414  observerList= table.getMutableShare()->getTableObservers();
415 
416  return EventData::callEventObservers();
417  }
418 
419  bool TableEventData::hasEvents(Table &in_table)
420  {
421  return (in_table.getMutableShare()->getTableObservers() != NULL);
422  }
423 
424  /*==========================================================*/
425  /* Static meathods called by drizzle to notify interested plugins
426  * of a schema event.
427  */
428  bool EventObserver::beforeDropTable(Session &session, const drizzled::identifier::Table &table)
429  {
430  if (all_event_plugins.empty())
431  return false;
432 
433  BeforeDropTableEventData eventData(session, table);
434  return eventData.callEventObservers();
435  }
436 
437  bool EventObserver::afterDropTable(Session &session, const drizzled::identifier::Table &table, int err)
438  {
439  if (all_event_plugins.empty())
440  return false;
441 
442  AfterDropTableEventData eventData(session, table, err);
443  return eventData.callEventObservers();
444  }
445 
446  bool EventObserver::beforeRenameTable(Session &session, const drizzled::identifier::Table &from, const drizzled::identifier::Table &to)
447  {
448  if (all_event_plugins.empty())
449  return false;
450 
451  BeforeRenameTableEventData eventData(session, from, to);
452  return eventData.callEventObservers();
453  }
454 
455  bool EventObserver::afterRenameTable(Session &session, const drizzled::identifier::Table &from, const drizzled::identifier::Table &to, int err)
456  {
457  if (all_event_plugins.empty())
458  return false;
459 
460  AfterRenameTableEventData eventData(session, from, to, err);
461  return eventData.callEventObservers();
462  }
463 
464  /*==========================================================*/
465  /* Static meathods called by drizzle to notify interested plugins
466  * of a table event.
467  *
468  * A quick test is done first to see if there are any interested observers.
469  */
470  bool EventObserver::beforeInsertRecord(Table &table, unsigned char *buf)
471  {
472  if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
473  return false;
474 
475  BeforeInsertRecordEventData eventData(*(table.in_use), table, buf);
476  return eventData.callEventObservers();
477  }
478 
479  bool EventObserver::afterInsertRecord(Table &table, const unsigned char *buf, int err)
480  {
481  if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
482  return false;
483 
484  AfterInsertRecordEventData eventData(*(table.in_use), table, buf, err);
485  return eventData.callEventObservers();
486  }
487 
488  bool EventObserver::beforeDeleteRecord(Table &table, const unsigned char *buf)
489  {
490  if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
491  return false;
492 
493  BeforeDeleteRecordEventData eventData(*(table.in_use), table, buf);
494  return eventData.callEventObservers();
495  }
496 
497  bool EventObserver::afterDeleteRecord(Table &table, const unsigned char *buf, int err)
498  {
499  if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
500  return false;
501 
502  AfterDeleteRecordEventData eventData(*(table.in_use), table, buf, err);
503  return eventData.callEventObservers();
504  }
505 
506  bool EventObserver::beforeUpdateRecord(Table &table, const unsigned char *old_data, unsigned char *new_data)
507  {
508  if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
509  return false;
510 
511  BeforeUpdateRecordEventData eventData(*(table.in_use), table, old_data, new_data);
512  return eventData.callEventObservers();
513  }
514 
515  bool EventObserver::afterUpdateRecord(Table &table, const unsigned char *old_data, unsigned char *new_data, int err)
516  {
517  if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
518  return false;
519 
520  AfterUpdateRecordEventData eventData(*(table.in_use), table, old_data, new_data, err);
521  return eventData.callEventObservers();
522  }
523 
524  /*==========================================================*/
525  /* Static meathods called by drizzle to notify interested plugins
526  * of a session event.
527  *
528  * A quick test is done first to see if there are any interested observers.
529 */
530  bool EventObserver::beforeCreateDatabase(Session &session, const std::string &db)
531  {
532  if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
533  return false;
534 
535  BeforeCreateDatabaseEventData eventData(session, db);
536  return eventData.callEventObservers();
537  }
538 
539  bool EventObserver::afterCreateDatabase(Session &session, const std::string &db, int err)
540  {
541  if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
542  return false;
543 
544  AfterCreateDatabaseEventData eventData(session, db, err);
545  return eventData.callEventObservers();
546  }
547 
548  bool EventObserver::beforeDropDatabase(Session &session, const std::string &db)
549  {
550  if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
551  return false;
552 
553  BeforeDropDatabaseEventData eventData(session, db);
554  return eventData.callEventObservers();
555  }
556 
557  bool EventObserver::afterDropDatabase(Session &session, const std::string &db, int err)
558  {
559  if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
560  return false;
561 
562  AfterDropDatabaseEventData eventData(session, db, err);
563  return eventData.callEventObservers();
564  }
565 
566  bool EventObserver::connectSession(Session &session)
567  {
568  if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
569  return false;
570 
571  ConnectSessionEventData eventData(session);
572  return eventData.callEventObservers();
573  }
574 
575  bool EventObserver::disconnectSession(Session &session)
576  {
577  if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
578  return false;
579 
580  DisconnectSessionEventData eventData(session);
581  return eventData.callEventObservers();
582  }
583 
584  bool EventObserver::beforeStatement(Session &session)
585  {
586  if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
587  return false;
588 
589  BeforeStatementEventData eventData(session);
590  return eventData.callEventObservers();
591  }
592 
593  bool EventObserver::afterStatement(Session &session)
594  {
595  if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
596  return false;
597 
598  AfterStatementEventData eventData(session);
599  return eventData.callEventObservers();
600  }
601 
602 
603 } /* namespace plugin */
604 } /* namespace drizzled */
TODO: Rename this file - func.h is stupid.
Definition: engine.cc:41