1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2010 PrimeBase Technologies GmbH, Germany
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.
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.
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
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>
45
/*============================*/
46
// Basic plugin registration stuff.
47
EventObserverVector all_event_plugins;
49
const EventObserverVector &EventObserver::getEventObservers(void)
51
return all_event_plugins;
55
bool EventObserver::addPlugin(EventObserver *handler)
58
all_event_plugins.push_back(handler);
63
void EventObserver::removePlugin(EventObserver *handler)
66
all_event_plugins.erase(std::find(all_event_plugins.begin(), all_event_plugins.end(), handler));
71
* The Event Observer list class in which plugins register which events they
74
* Each table share for example, will have one of these hung on it to store
75
* a list off all event observers interested in it and which events they are
78
class EventObserverList
82
typedef std::multimap<uint32_t, EventObserver *> ObserverMap;
85
/* A list of lists indexed by event type. */
86
std::vector<ObserverMap *> event_observer_lists;
92
// Initialize the list with NULL pointers.
93
event_observer_lists.assign(EventObserver::MAX_EVENT_COUNT, NULL);
98
std::for_each(event_observer_lists.begin(),
99
event_observer_lists.end(),
101
event_observer_lists.clear();
104
/* Add the observer to the observer list for the even, positioning it if required.
106
* Note: Event observers are storted in a multimap object so that the order in which
107
* they are called can be sorted based on the requested position. Lookups are never done
108
* on the multimap, once filled it is used as a vector.
110
void addObserver(EventObserver *eventObserver, enum EventObserver::EventType event, int32_t position)
113
ObserverMap *observers;
115
observers= event_observer_lists[event];
116
if (observers == NULL)
118
observers= new ObserverMap();
119
event_observer_lists[event]= observers;
123
event_pos= INT32_MAX; // Set the event position to be in the middle.
125
event_pos= (uint32_t) position;
127
/* If positioned then check if the position is already taken. */
130
if (observers->find(event_pos) != observers->end())
132
errmsg_printf(error::WARN,
133
_("EventObserverList::addEventObserver() Duplicate event position %d for event '%s' from EventObserver plugin '%s'"),
135
EventObserver::eventName(event),
136
eventObserver->getName().c_str());
140
observers->insert(std::pair<uint32_t, EventObserver *>(event_pos, eventObserver) );
144
/* Get the observer list for an event type. Will return NULL if no observer exists.*/
145
ObserverMap *getObservers(enum EventObserver::EventType event)
147
return event_observer_lists[event];
153
/* registerEvent() is called from the event observer plugins to add themselves to
154
* the event observer list to be notified when the specified event takes place.
156
void EventObserver::registerEvent(EventObserverList &observers, EventType event, int32_t position)
158
observers.addObserver(this, event, position);
161
/*========================================================*/
162
/* Table Event Observer handling: */
163
/*========================================================*/
166
/* For each EventObserver plugin call its registerTableEventsDo() meathod so that it can
167
* register what events, if any, it is interested in on this table.
169
class RegisterTableEventsIterate : public std::unary_function<EventObserver *, void>
171
TableShare &table_share;
172
EventObserverList &observers;
175
RegisterTableEventsIterate(TableShare &table_share_arg, EventObserverList &observers_arg):
176
table_share(table_share_arg), observers(observers_arg) {}
177
inline result_type operator() (argument_type eventObserver)
179
eventObserver->registerTableEventsDo(table_share, observers);
185
* registerTableEvents() is called by drizzle to register all plugins that
186
* may be interested in table events on the newly created TableShare object.
188
void EventObserver::registerTableEvents(TableShare &table_share)
190
if (all_event_plugins.empty())
193
EventObserverList *observers;
195
observers= table_share.getTableObservers();
197
if (observers != NULL)
199
errmsg_printf(error::WARN,
200
_("EventObserver::registerTableEvents(): Table already has events registered on it: probable programming error."));
201
table_share.setTableObservers(NULL);
205
observers= new EventObserverList();
206
table_share.setTableObservers(observers);
209
std::for_each(all_event_plugins.begin(), all_event_plugins.end(),
210
RegisterTableEventsIterate(table_share, *observers));
215
/* Cleanup before freeing the TableShare object. */
216
void EventObserver::deregisterTableEvents(TableShare &table_share)
218
if (all_event_plugins.empty())
221
EventObserverList *observers;
223
observers= table_share.getTableObservers();
227
table_share.setTableObservers(NULL);
233
/*========================================================*/
234
/* Schema Event Observer handling: */
235
/*========================================================*/
238
/* For each EventObserver plugin call its registerSchemaEventsDo() meathod so that it can
239
* register what events, if any, it is interested in on the schema.
241
class RegisterSchemaEventsIterate : public std::unary_function<EventObserver *, void>
243
const std::string &db;
244
EventObserverList &observers;
246
RegisterSchemaEventsIterate(const std::string &db_arg, EventObserverList &observers_arg) :
248
observers(observers_arg){}
250
inline result_type operator() (argument_type eventObserver)
252
eventObserver->registerSchemaEventsDo(db, observers);
258
* registerSchemaEvents() is called by drizzle to register all plugins that
259
* may be interested in schema events on the database.
261
void EventObserver::registerSchemaEvents(Session &session, const std::string &db)
263
if (all_event_plugins.empty())
266
EventObserverList *observers;
268
observers= session.getSchemaObservers(db);
270
if (observers == NULL)
272
observers= new EventObserverList();
273
session.setSchemaObservers(db, observers);
276
std::for_each(all_event_plugins.begin(), all_event_plugins.end(),
277
RegisterSchemaEventsIterate(db, *observers));
282
/* Cleanup before freeing the Session object. */
283
void EventObserver::deregisterSchemaEvents(Session &session, const std::string &db)
285
if (all_event_plugins.empty())
288
EventObserverList *observers;
290
observers= session.getSchemaObservers(db);
294
session.setSchemaObservers(db, NULL);
299
/*========================================================*/
300
/* Session Event Observer handling: */
301
/*========================================================*/
304
/* For each EventObserver plugin call its registerSessionEventsDo() meathod so that it can
305
* register what events, if any, it is interested in on this session.
307
class RegisterSessionEventsIterate : public std::unary_function<EventObserver *, void>
310
EventObserverList &observers;
312
RegisterSessionEventsIterate(Session &session_arg, EventObserverList &observers_arg) :
313
session(session_arg), observers(observers_arg) {}
314
inline result_type operator() (argument_type eventObserver)
316
eventObserver->registerSessionEventsDo(session, observers);
322
* registerSessionEvents() is called by drizzle to register all plugins that
323
* may be interested in session events on the newly created session.
325
void EventObserver::registerSessionEvents(Session &session)
327
if (all_event_plugins.empty())
330
EventObserverList *observers;
332
observers= session.getSessionObservers();
333
if (observers) { // This should not happed
334
errmsg_printf(error::WARN,
335
_("EventObserver::registerSessionEvents(): Session already has events registered on it: probable programming error."));
336
session.setSessionObservers(NULL);
340
observers= new EventObserverList();
341
session.setSessionObservers(observers);
343
std::for_each(all_event_plugins.begin(), all_event_plugins.end(),
344
RegisterSessionEventsIterate(session, *observers));
349
/* Cleanup before freeing the session object. */
350
void EventObserver::deregisterSessionEvents(Session &session)
352
if (all_event_plugins.empty())
355
EventObserverList *observers;
357
observers= session.getSessionObservers();
361
session.setSessionObservers(NULL);
367
/* Event observer list iterator: */
369
class EventIterate : public std::unary_function<std::pair<uint32_t, EventObserver *>, bool>
374
EventIterate(EventData &data_arg) :
375
std::unary_function<std::pair<uint32_t, EventObserver *>, bool>(),
379
inline result_type operator()(argument_type handler)
381
bool result= handler.second->observeEventDo(data);
384
/* TRANSLATORS: The leading word "EventObserver" is the name
385
of the plugin api, and so should not be translated. */
386
errmsg_printf(error::ERROR,
387
_("EventIterate event handler '%s' failed for event '%s'"),
388
handler.second->getName().c_str(), handler.second->eventName(data.event));
396
/*==========================================================*/
397
/* Generic meathods called by drizzle to notify all interested
398
* plugins of an event,
401
// Call all event observers interested in the event.
402
bool EventData::callEventObservers()
404
EventObserverList::ObserverMap *eventObservers;
406
if (observerList == NULL)
407
return false; // Nobody was interested in the event. :(
409
eventObservers = observerList->getObservers(event);
411
if (eventObservers == NULL)
412
return false; // Nobody was interested in the event. :(
414
/* Use find_if instead of foreach so that we can collect return codes */
415
EventObserverList::ObserverMap::iterator iter=
416
std::find_if(eventObservers->begin(), eventObservers->end(),
417
EventIterate(*this));
418
/* If iter is == end() here, that means that all of the plugins returned
419
* false, which in this case means they all succeeded. Since we want to
420
* return false on success, we return the value of the two being !=.
422
return iter != eventObservers->end();
426
bool SessionEventData::callEventObservers()
428
observerList= session.getSessionObservers();
430
return EventData::callEventObservers();
434
bool SchemaEventData::callEventObservers()
436
observerList= session.getSchemaObservers(db);
439
EventObserver::registerSchemaEvents(session, db);
440
observerList= session.getSchemaObservers(db);
443
return EventData::callEventObservers();
447
bool TableEventData::callEventObservers()
449
observerList= table.getMutableShare()->getTableObservers();
451
return EventData::callEventObservers();
454
/*==========================================================*/
455
/* Static meathods called by drizzle to notify interested plugins
458
bool EventObserver::beforeDropTable(Session &session, const drizzled::identifier::Table &table)
460
if (all_event_plugins.empty())
463
BeforeDropTableEventData eventData(session, table);
464
return eventData.callEventObservers();
467
bool EventObserver::afterDropTable(Session &session, const drizzled::identifier::Table &table, int err)
469
if (all_event_plugins.empty())
472
AfterDropTableEventData eventData(session, table, err);
473
return eventData.callEventObservers();
476
bool EventObserver::beforeRenameTable(Session &session, const drizzled::identifier::Table &from, const drizzled::identifier::Table &to)
478
if (all_event_plugins.empty())
481
BeforeRenameTableEventData eventData(session, from, to);
482
return eventData.callEventObservers();
485
bool EventObserver::afterRenameTable(Session &session, const drizzled::identifier::Table &from, const drizzled::identifier::Table &to, int err)
487
if (all_event_plugins.empty())
490
AfterRenameTableEventData eventData(session, from, to, err);
491
return eventData.callEventObservers();
494
/*==========================================================*/
495
/* Static meathods called by drizzle to notify interested plugins
498
* A quick test is done first to see if there are any interested observers.
500
bool EventObserver::beforeInsertRecord(Table &table, unsigned char *buf)
502
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
505
BeforeInsertRecordEventData eventData(*(table.in_use), table, buf);
506
return eventData.callEventObservers();
509
bool EventObserver::afterInsertRecord(Table &table, const unsigned char *buf, int err)
511
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
514
AfterInsertRecordEventData eventData(*(table.in_use), table, buf, err);
515
return eventData.callEventObservers();
518
bool EventObserver::beforeDeleteRecord(Table &table, const unsigned char *buf)
520
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
523
BeforeDeleteRecordEventData eventData(*(table.in_use), table, buf);
524
return eventData.callEventObservers();
527
bool EventObserver::afterDeleteRecord(Table &table, const unsigned char *buf, int err)
529
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
532
AfterDeleteRecordEventData eventData(*(table.in_use), table, buf, err);
533
return eventData.callEventObservers();
536
bool EventObserver::beforeUpdateRecord(Table &table, const unsigned char *old_data, unsigned char *new_data)
538
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
541
BeforeUpdateRecordEventData eventData(*(table.in_use), table, old_data, new_data);
542
return eventData.callEventObservers();
545
bool EventObserver::afterUpdateRecord(Table &table, const unsigned char *old_data, unsigned char *new_data, int err)
547
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
550
AfterUpdateRecordEventData eventData(*(table.in_use), table, old_data, new_data, err);
551
return eventData.callEventObservers();
554
/*==========================================================*/
555
/* Static meathods called by drizzle to notify interested plugins
556
* of a session event.
558
* A quick test is done first to see if there are any interested observers.
560
bool EventObserver::beforeCreateDatabase(Session &session, const std::string &db)
562
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
565
BeforeCreateDatabaseEventData eventData(session, db);
566
return eventData.callEventObservers();
569
bool EventObserver::afterCreateDatabase(Session &session, const std::string &db, int err)
571
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
574
AfterCreateDatabaseEventData eventData(session, db, err);
575
return eventData.callEventObservers();
578
bool EventObserver::beforeDropDatabase(Session &session, const std::string &db)
580
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
583
BeforeDropDatabaseEventData eventData(session, db);
584
return eventData.callEventObservers();
587
bool EventObserver::afterDropDatabase(Session &session, const std::string &db, int err)
589
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
592
AfterDropDatabaseEventData eventData(session, db, err);
593
return eventData.callEventObservers();
596
bool EventObserver::connectSession(Session &session)
598
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
601
ConnectSessionEventData eventData(session);
602
return eventData.callEventObservers();
605
bool EventObserver::disconnectSession(Session &session)
607
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
610
DisconnectSessionEventData eventData(session);
611
return eventData.callEventObservers();
614
bool EventObserver::beforeStatement(Session &session)
616
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
619
BeforeStatementEventData eventData(session);
620
return eventData.callEventObservers();
623
bool EventObserver::afterStatement(Session &session)
625
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
628
AfterStatementEventData eventData(session);
629
return eventData.callEventObservers();
633
} /* namespace plugin */
634
} /* namespace drizzled */