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/definition/table.h"
32
#include "drizzled/module/registry.h"
33
#include "drizzled/plugin/event_observer.h"
34
#include <drizzled/util/functors.h>
47
/*============================*/
48
// Basic plugin registration stuff.
49
EventObserverVector all_event_plugins;
51
const EventObserverVector &EventObserver::getEventObservers(void)
53
return all_event_plugins;
57
bool EventObserver::addPlugin(EventObserver *handler)
60
all_event_plugins.push_back(handler);
65
void EventObserver::removePlugin(EventObserver *handler)
68
all_event_plugins.erase(find(all_event_plugins.begin(), all_event_plugins.end(), handler));
73
* The Event Observer list class in which plugins register which events they
76
* Each table share for example, will have one of these hung on it to store
77
* a list off all event observers interested in it and which events they are
80
class EventObserverList
84
typedef multimap<uint32_t, EventObserver *> ObserverMap;
87
/* A list of lists indexed by event type. */
88
vector<ObserverMap *> event_observer_lists;
94
// Initialize the list with NULL pointers.
95
event_observer_lists.assign(EventObserver::MAX_EVENT_COUNT, NULL);
100
for_each(event_observer_lists.begin(),
101
event_observer_lists.end(),
103
event_observer_lists.clear();
106
/* Add the observer to the observer list for the even, positioning it if required.
108
* Note: Event observers are storted in a multimap object so that the order in which
109
* they are called can be sorted based on the requested position. Lookups are never done
110
* on the multimap, once filled it is used as a vector.
112
void addObserver(EventObserver *eventObserver, enum EventObserver::EventType event, int32_t position)
115
ObserverMap *observers;
117
observers= event_observer_lists[event];
118
if (observers == NULL)
120
observers= new ObserverMap();
121
event_observer_lists[event]= observers;
125
event_pos= INT32_MAX; // Set the event position to be in the middle.
127
event_pos= (uint32_t) position;
129
/* If positioned then check if the position is already taken. */
132
if (observers->find(event_pos) != observers->end())
134
errmsg_printf(ERRMSG_LVL_WARN,
135
_("EventObserverList::addEventObserver() Duplicate event position %d for event '%s' from EventObserver plugin '%s'"),
137
EventObserver::eventName(event),
138
eventObserver->getName().c_str());
142
observers->insert(pair<uint32_t, EventObserver *>(event_pos, eventObserver) );
146
/* Get the observer list for an event type. Will return NULL if no observer exists.*/
147
ObserverMap *getObservers(enum EventObserver::EventType event)
149
return event_observer_lists[event];
155
/* registerEvent() is called from the event observer plugins to add themselves to
156
* the event observer list to be notified when the specified event takes place.
158
void EventObserver::registerEvent(EventObserverList &observers, EventType event, int32_t position)
160
observers.addObserver(this, event, position);
163
/*========================================================*/
164
/* Table Event Observer handling: */
165
/*========================================================*/
168
/* For each EventObserver plugin call its registerTableEventsDo() meathod so that it can
169
* register what events, if any, it is interested in on this table.
171
class RegisterTableEventsIterate : public unary_function<EventObserver *, void>
173
TableShare &table_share;
174
EventObserverList &observers;
177
RegisterTableEventsIterate(TableShare &table_share_arg, EventObserverList &observers_arg):
178
table_share(table_share_arg), observers(observers_arg) {}
179
inline result_type operator() (argument_type eventObserver)
181
eventObserver->registerTableEventsDo(table_share, observers);
187
* registerTableEvents() is called by drizzle to register all plugins that
188
* may be interested in table events on the newly created TableShare object.
190
void EventObserver::registerTableEvents(TableShare &table_share)
192
if (all_event_plugins.empty())
195
EventObserverList *observers;
197
observers= table_share.getTableObservers();
199
if (observers != NULL)
201
errmsg_printf(ERRMSG_LVL_WARN,
202
_("EventObserver::registerTableEvents(): Table already has events registered on it: probable programming error."));
203
table_share.setTableObservers(NULL);
207
observers= new EventObserverList();
208
table_share.setTableObservers(observers);
211
for_each(all_event_plugins.begin(), all_event_plugins.end(),
212
RegisterTableEventsIterate(table_share, *observers));
217
/* Cleanup before freeing the TableShare object. */
218
void EventObserver::deregisterTableEvents(TableShare &table_share)
220
if (all_event_plugins.empty())
223
EventObserverList *observers;
225
observers= table_share.getTableObservers();
229
table_share.setTableObservers(NULL);
235
/*========================================================*/
236
/* Schema Event Observer handling: */
237
/*========================================================*/
240
/* For each EventObserver plugin call its registerSchemaEventsDo() meathod so that it can
241
* register what events, if any, it is interested in on the schema.
243
class RegisterSchemaEventsIterate : public unary_function<EventObserver *, void>
245
const std::string &db;
246
EventObserverList &observers;
248
RegisterSchemaEventsIterate(const std::string &db_arg, EventObserverList &observers_arg) :
250
observers(observers_arg){}
252
inline result_type operator() (argument_type eventObserver)
254
eventObserver->registerSchemaEventsDo(db, observers);
260
* registerSchemaEvents() is called by drizzle to register all plugins that
261
* may be interested in schema events on the database.
263
void EventObserver::registerSchemaEvents(Session &session, const std::string &db)
265
if (all_event_plugins.empty())
268
EventObserverList *observers;
270
observers= session.getSchemaObservers(db);
272
if (observers == NULL)
274
observers= new EventObserverList();
275
session.setSchemaObservers(db, observers);
278
for_each(all_event_plugins.begin(), all_event_plugins.end(),
279
RegisterSchemaEventsIterate(db, *observers));
284
/* Cleanup before freeing the Session object. */
285
void EventObserver::deregisterSchemaEvents(Session &session, const std::string &db)
287
if (all_event_plugins.empty())
290
EventObserverList *observers;
292
observers= session.getSchemaObservers(db);
296
session.setSchemaObservers(db, NULL);
301
/*========================================================*/
302
/* Session Event Observer handling: */
303
/*========================================================*/
306
/* For each EventObserver plugin call its registerSessionEventsDo() meathod so that it can
307
* register what events, if any, it is interested in on this session.
309
class RegisterSessionEventsIterate : public unary_function<EventObserver *, void>
312
EventObserverList &observers;
314
RegisterSessionEventsIterate(Session &session_arg, EventObserverList &observers_arg) :
315
session(session_arg), observers(observers_arg) {}
316
inline result_type operator() (argument_type eventObserver)
318
eventObserver->registerSessionEventsDo(session, observers);
324
* registerSessionEvents() is called by drizzle to register all plugins that
325
* may be interested in session events on the newly created session.
327
void EventObserver::registerSessionEvents(Session &session)
329
if (all_event_plugins.empty())
332
EventObserverList *observers;
334
observers= session.getSessionObservers();
335
if (observers) { // This should not happed
336
errmsg_printf(ERRMSG_LVL_WARN,
337
_("EventObserver::registerSessionEvents(): Session already has events registered on it: probable programming error."));
338
session.setSessionObservers(NULL);
342
observers= new EventObserverList();
343
session.setSessionObservers(observers);
345
for_each(all_event_plugins.begin(), all_event_plugins.end(),
346
RegisterSessionEventsIterate(session, *observers));
351
/* Cleanup before freeing the session object. */
352
void EventObserver::deregisterSessionEvents(Session &session)
354
if (all_event_plugins.empty())
357
EventObserverList *observers;
359
observers= session.getSessionObservers();
363
session.setSessionObservers(NULL);
369
/* Event observer list iterator: */
371
class EventIterate : public unary_function<pair<uint32_t, EventObserver *>, bool>
376
EventIterate(EventData &data_arg) :
377
unary_function<pair<uint32_t, EventObserver *>, bool>(),
381
inline result_type operator()(argument_type handler)
383
bool result= handler.second->observeEventDo(data);
386
/* TRANSLATORS: The leading word "EventObserver" is the name
387
of the plugin api, and so should not be translated. */
388
errmsg_printf(ERRMSG_LVL_ERROR,
389
_("EventIterate event handler '%s' failed for event '%s'"),
390
handler.second->getName().c_str(), handler.second->eventName(data.event));
398
/*==========================================================*/
399
/* Generic meathods called by drizzle to notify all interested
400
* plugins of an event,
403
// Call all event observers interested in the event.
404
bool EventData::callEventObservers()
406
EventObserverList::ObserverMap *eventObservers;
408
if (observerList == NULL)
409
return false; // Nobody was interested in the event. :(
411
eventObservers = observerList->getObservers(event);
413
if (eventObservers == NULL)
414
return false; // Nobody was interested in the event. :(
416
/* Use find_if instead of foreach so that we can collect return codes */
417
EventObserverList::ObserverMap::iterator iter=
418
find_if(eventObservers->begin(), eventObservers->end(),
419
EventIterate(*this));
420
/* If iter is == end() here, that means that all of the plugins returned
421
* false, which in this case means they all succeeded. Since we want to
422
* return false on success, we return the value of the two being !=.
424
return iter != eventObservers->end();
428
bool SessionEventData::callEventObservers()
430
observerList= session.getSessionObservers();
432
return EventData::callEventObservers();
436
bool SchemaEventData::callEventObservers()
438
observerList= session.getSchemaObservers(db);
441
EventObserver::registerSchemaEvents(session, db);
442
observerList= session.getSchemaObservers(db);
445
return EventData::callEventObservers();
449
bool TableEventData::callEventObservers()
451
observerList= table.getMutableShare()->getTableObservers();
453
return EventData::callEventObservers();
456
/*==========================================================*/
457
/* Static meathods called by drizzle to notify interested plugins
460
bool EventObserver::beforeDropTable(Session &session, const drizzled::TableIdentifier &table)
462
if (all_event_plugins.empty())
465
BeforeDropTableEventData eventData(session, table);
466
return eventData.callEventObservers();
469
bool EventObserver::afterDropTable(Session &session, const drizzled::TableIdentifier &table, int err)
471
if (all_event_plugins.empty())
474
AfterDropTableEventData eventData(session, table, err);
475
return eventData.callEventObservers();
478
bool EventObserver::beforeRenameTable(Session &session, const drizzled::TableIdentifier &from, const drizzled::TableIdentifier &to)
480
if (all_event_plugins.empty())
483
BeforeRenameTableEventData eventData(session, from, to);
484
return eventData.callEventObservers();
487
bool EventObserver::afterRenameTable(Session &session, const drizzled::TableIdentifier &from, const drizzled::TableIdentifier &to, int err)
489
if (all_event_plugins.empty())
492
AfterRenameTableEventData eventData(session, from, to, err);
493
return eventData.callEventObservers();
496
/*==========================================================*/
497
/* Static meathods called by drizzle to notify interested plugins
500
* A quick test is done first to see if there are any interested observers.
502
bool EventObserver::beforeInsertRecord(Table &table, unsigned char *buf)
504
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
507
BeforeInsertRecordEventData eventData(*(table.in_use), table, buf);
508
return eventData.callEventObservers();
511
bool EventObserver::afterInsertRecord(Table &table, const unsigned char *buf, int err)
513
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
516
AfterInsertRecordEventData eventData(*(table.in_use), table, buf, err);
517
return eventData.callEventObservers();
520
bool EventObserver::beforeDeleteRecord(Table &table, const unsigned char *buf)
522
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
525
BeforeDeleteRecordEventData eventData(*(table.in_use), table, buf);
526
return eventData.callEventObservers();
529
bool EventObserver::afterDeleteRecord(Table &table, const unsigned char *buf, int err)
531
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
534
AfterDeleteRecordEventData eventData(*(table.in_use), table, buf, err);
535
return eventData.callEventObservers();
538
bool EventObserver::beforeUpdateRecord(Table &table, const unsigned char *old_data, unsigned char *new_data)
540
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
543
BeforeUpdateRecordEventData eventData(*(table.in_use), table, old_data, new_data);
544
return eventData.callEventObservers();
547
bool EventObserver::afterUpdateRecord(Table &table, const unsigned char *old_data, unsigned char *new_data, int err)
549
if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
552
AfterUpdateRecordEventData eventData(*(table.in_use), table, old_data, new_data, err);
553
return eventData.callEventObservers();
556
/*==========================================================*/
557
/* Static meathods called by drizzle to notify interested plugins
558
* of a session event.
560
* A quick test is done first to see if there are any interested observers.
562
bool EventObserver::beforeCreateDatabase(Session &session, const std::string &db)
564
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
567
BeforeCreateDatabaseEventData eventData(session, db);
568
return eventData.callEventObservers();
571
bool EventObserver::afterCreateDatabase(Session &session, const std::string &db, int err)
573
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
576
AfterCreateDatabaseEventData eventData(session, db, err);
577
return eventData.callEventObservers();
580
bool EventObserver::beforeDropDatabase(Session &session, const std::string &db)
582
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
585
BeforeDropDatabaseEventData eventData(session, db);
586
return eventData.callEventObservers();
589
bool EventObserver::afterDropDatabase(Session &session, const std::string &db, int err)
591
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
594
AfterDropDatabaseEventData eventData(session, db, err);
595
return eventData.callEventObservers();
598
bool EventObserver::connectSession(Session &session)
600
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
603
ConnectSessionEventData eventData(session);
604
return eventData.callEventObservers();
607
bool EventObserver::disconnectSession(Session &session)
609
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
612
DisconnectSessionEventData eventData(session);
613
return eventData.callEventObservers();
616
bool EventObserver::beforeStatement(Session &session)
618
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
621
BeforeStatementEventData eventData(session);
622
return eventData.callEventObservers();
625
bool EventObserver::afterStatement(Session &session)
627
if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
630
AfterStatementEventData eventData(session);
631
return eventData.callEventObservers();
635
} /* namespace plugin */
636
} /* namespace drizzled */