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();
433
bool SessionEventData::hasEvents(Session &in_session)
435
return (in_session.getSessionObservers() != NULL);
439
bool SchemaEventData::callEventObservers()
441
observerList= session.getSchemaObservers(db);
444
EventObserver::registerSchemaEvents(session, db);
445
observerList= session.getSchemaObservers(db);
448
return EventData::callEventObservers();
452
bool TableEventData::callEventObservers()
454
observerList= table.getMutableShare()->getTableObservers();
456
return EventData::callEventObservers();
459
bool TableEventData::hasEvents(Table &in_table)
461
return (in_table.getMutableShare()->getTableObservers() != NULL);
464
/*==========================================================*/
465
/* Static meathods called by drizzle to notify interested plugins
468
bool EventObserver::beforeDropTable(Session &session, const drizzled::identifier::Table &table)
470
if (all_event_plugins.empty())
473
BeforeDropTableEventData eventData(session, table);
474
return eventData.callEventObservers();
477
bool EventObserver::afterDropTable(Session &session, const drizzled::identifier::Table &table, int err)
479
if (all_event_plugins.empty())
482
AfterDropTableEventData eventData(session, table, err);
483
return eventData.callEventObservers();
486
bool EventObserver::beforeRenameTable(Session &session, const drizzled::identifier::Table &from, const drizzled::identifier::Table &to)
488
if (all_event_plugins.empty())
491
BeforeRenameTableEventData eventData(session, from, to);
492
return eventData.callEventObservers();
495
bool EventObserver::afterRenameTable(Session &session, const drizzled::identifier::Table &from, const drizzled::identifier::Table &to, int err)
497
if (all_event_plugins.empty())
500
AfterRenameTableEventData eventData(session, from, to, err);
501
return eventData.callEventObservers();
504
/*==========================================================*/
505
/* Static meathods called by drizzle to notify interested plugins
508
* A quick test is done first to see if there are any interested observers.
510
bool EventObserver::beforeInsertRecord(Table &table, unsigned char *buf)
512
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
515
BeforeInsertRecordEventData eventData(*(table.in_use), table, buf);
516
return eventData.callEventObservers();
519
bool EventObserver::afterInsertRecord(Table &table, const unsigned char *buf, int err)
521
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
524
AfterInsertRecordEventData eventData(*(table.in_use), table, buf, err);
525
return eventData.callEventObservers();
528
bool EventObserver::beforeDeleteRecord(Table &table, const unsigned char *buf)
530
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
533
BeforeDeleteRecordEventData eventData(*(table.in_use), table, buf);
534
return eventData.callEventObservers();
537
bool EventObserver::afterDeleteRecord(Table &table, const unsigned char *buf, int err)
539
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
542
AfterDeleteRecordEventData eventData(*(table.in_use), table, buf, err);
543
return eventData.callEventObservers();
546
bool EventObserver::beforeUpdateRecord(Table &table, const unsigned char *old_data, unsigned char *new_data)
548
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
551
BeforeUpdateRecordEventData eventData(*(table.in_use), table, old_data, new_data);
552
return eventData.callEventObservers();
555
bool EventObserver::afterUpdateRecord(Table &table, const unsigned char *old_data, unsigned char *new_data, int err)
557
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
560
AfterUpdateRecordEventData eventData(*(table.in_use), table, old_data, new_data, err);
561
return eventData.callEventObservers();
564
/*==========================================================*/
565
/* Static meathods called by drizzle to notify interested plugins
566
* of a session event.
568
* A quick test is done first to see if there are any interested observers.
570
bool EventObserver::beforeCreateDatabase(Session &session, const std::string &db)
572
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
575
BeforeCreateDatabaseEventData eventData(session, db);
576
return eventData.callEventObservers();
579
bool EventObserver::afterCreateDatabase(Session &session, const std::string &db, int err)
581
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
584
AfterCreateDatabaseEventData eventData(session, db, err);
585
return eventData.callEventObservers();
588
bool EventObserver::beforeDropDatabase(Session &session, const std::string &db)
590
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
593
BeforeDropDatabaseEventData eventData(session, db);
594
return eventData.callEventObservers();
597
bool EventObserver::afterDropDatabase(Session &session, const std::string &db, int err)
599
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
602
AfterDropDatabaseEventData eventData(session, db, err);
603
return eventData.callEventObservers();
606
bool EventObserver::connectSession(Session &session)
608
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
611
ConnectSessionEventData eventData(session);
612
return eventData.callEventObservers();
615
bool EventObserver::disconnectSession(Session &session)
617
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
620
DisconnectSessionEventData eventData(session);
621
return eventData.callEventObservers();
624
bool EventObserver::beforeStatement(Session &session)
626
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
629
BeforeStatementEventData eventData(session);
630
return eventData.callEventObservers();
633
bool EventObserver::afterStatement(Session &session)
635
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
638
AfterStatementEventData eventData(session);
639
return eventData.callEventObservers();
643
} /* namespace plugin */
644
} /* namespace drizzled */