~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/plugin/event_observer.cc

Reverted 1103

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
38
 
 
39
 
namespace drizzled
40
 
{
41
 
 
42
 
namespace plugin
43
 
{
44
 
 
45
 
/*============================*/
46
 
  // Basic plugin registration stuff.
47
 
  EventObserverVector all_event_plugins;
48
 
 
49
 
  const EventObserverVector &EventObserver::getEventObservers(void)
50
 
  {
51
 
    return all_event_plugins;
52
 
  }
53
 
 
54
 
  //---------
55
 
  bool EventObserver::addPlugin(EventObserver *handler)
56
 
  {
57
 
    if (handler != NULL)
58
 
      all_event_plugins.push_back(handler);
59
 
    return false;
60
 
  }
61
 
 
62
 
  //---------
63
 
  void EventObserver::removePlugin(EventObserver *handler)
64
 
  {
65
 
    if (handler != NULL)
66
 
      all_event_plugins.erase(std::find(all_event_plugins.begin(), all_event_plugins.end(), handler));
67
 
  }
68
 
 
69
 
 
70
 
  /* 
71
 
   * The Event Observer list class in which plugins register which events they
72
 
   * are interested in.
73
 
   *
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
76
 
   * interested in.
77
 
 */
78
 
  class EventObserverList
79
 
  {
80
 
 
81
 
  public:
82
 
    typedef std::multimap<uint32_t, EventObserver *> ObserverMap;
83
 
 
84
 
  private:
85
 
    /* A list of lists indexed by event type. */
86
 
    std::vector<ObserverMap *> event_observer_lists;
87
 
 
88
 
  public:
89
 
 
90
 
    EventObserverList()
91
 
    {
92
 
                        // Initialize the list with NULL pointers.
93
 
                        event_observer_lists.assign(EventObserver::MAX_EVENT_COUNT, NULL);
94
 
    }
95
 
 
96
 
    ~EventObserverList()
97
 
    {
98
 
      std::for_each(event_observer_lists.begin(),
99
 
                    event_observer_lists.end(),
100
 
                    SafeDeletePtr());
101
 
      event_observer_lists.clear();
102
 
    }
103
 
 
104
 
    /* Add the observer to the observer list for the even, positioning it if required.
105
 
     *
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.
109
 
   */
110
 
    void addObserver(EventObserver *eventObserver, enum EventObserver::EventType event, int32_t position)
111
 
    {
112
 
      uint32_t event_pos;
113
 
      ObserverMap *observers;
114
 
 
115
 
      observers= event_observer_lists[event];
116
 
      if (observers == NULL) 
117
 
      {
118
 
        observers= new ObserverMap();
119
 
        event_observer_lists[event]= observers;
120
 
      }
121
 
 
122
 
      if (position == 0)
123
 
        event_pos= INT32_MAX; // Set the event position to be in the middle.
124
 
      else
125
 
        event_pos= (uint32_t) position;
126
 
 
127
 
      /* If positioned then check if the position is already taken. */
128
 
      if (position) 
129
 
      {
130
 
        if (observers->find(event_pos) != observers->end())
131
 
        {
132
 
          errmsg_printf(error::WARN,
133
 
                        _("EventObserverList::addEventObserver() Duplicate event position %d for event '%s' from EventObserver plugin '%s'"),
134
 
                        position,
135
 
                        EventObserver::eventName(event), 
136
 
                        eventObserver->getName().c_str());
137
 
        }
138
 
      }
139
 
 
140
 
      observers->insert(std::pair<uint32_t, EventObserver *>(event_pos, eventObserver) );
141
 
    }
142
 
 
143
 
 
144
 
    /* Get the observer list for an event type. Will return NULL if no observer exists.*/
145
 
    ObserverMap *getObservers(enum EventObserver::EventType event)
146
 
    {
147
 
      return event_observer_lists[event];
148
 
    }
149
 
  };
150
 
 
151
 
 
152
 
  //---------
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.
155
 
   */ 
156
 
  void EventObserver::registerEvent(EventObserverList &observers, EventType event, int32_t position)
157
 
  {
158
 
    observers.addObserver(this, event, position);
159
 
  }
160
 
 
161
 
  /*========================================================*/
162
 
  /*              Table Event Observer handling:           */
163
 
  /*========================================================*/
164
 
 
165
 
  //----------
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.
168
 
   */ 
169
 
  class RegisterTableEventsIterate : public std::unary_function<EventObserver *, void>
170
 
  {
171
 
    TableShare &table_share;
172
 
    EventObserverList &observers;
173
 
 
174
 
  public:
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)
178
 
    {
179
 
      eventObserver->registerTableEventsDo(table_share, observers);
180
 
    }
181
 
  };
182
 
 
183
 
  //----------
184
 
  /* 
185
 
   * registerTableEvents() is called by drizzle to register all plugins that
186
 
   * may be interested in table events on the newly created TableShare object.
187
 
   */ 
188
 
  void EventObserver::registerTableEvents(TableShare &table_share)
189
 
  {
190
 
    if (all_event_plugins.empty())
191
 
      return;
192
 
 
193
 
    EventObserverList *observers;
194
 
 
195
 
    observers= table_share.getTableObservers();
196
 
 
197
 
    if (observers != NULL) 
198
 
                {
199
 
                        errmsg_printf(error::WARN,
200
 
                                                                        _("EventObserver::registerTableEvents(): Table already has events registered on it: probable programming error."));
201
 
                        table_share.setTableObservers(NULL);
202
 
      delete observers;
203
 
    }
204
 
 
205
 
                observers= new EventObserverList();
206
 
                table_share.setTableObservers(observers);
207
 
 
208
 
 
209
 
    std::for_each(all_event_plugins.begin(), all_event_plugins.end(),
210
 
                  RegisterTableEventsIterate(table_share, *observers));
211
 
 
212
 
  }
213
 
 
214
 
  //----------
215
 
  /* Cleanup before freeing the TableShare object. */
216
 
  void EventObserver::deregisterTableEvents(TableShare &table_share)
217
 
  {
218
 
   if (all_event_plugins.empty())
219
 
      return;
220
 
 
221
 
    EventObserverList *observers;
222
 
 
223
 
    observers= table_share.getTableObservers();
224
 
 
225
 
    if (observers) 
226
 
    {
227
 
      table_share.setTableObservers(NULL);
228
 
      delete observers;
229
 
    }
230
 
  }
231
 
 
232
 
 
233
 
  /*========================================================*/
234
 
  /*              Schema Event Observer handling:           */
235
 
  /*========================================================*/
236
 
 
237
 
  //----------
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.
240
 
   */ 
241
 
  class RegisterSchemaEventsIterate : public std::unary_function<EventObserver *, void>
242
 
  {
243
 
    const std::string &db;
244
 
    EventObserverList &observers;
245
 
  public:
246
 
    RegisterSchemaEventsIterate(const std::string &db_arg, EventObserverList &observers_arg) :     
247
 
      db(db_arg),
248
 
      observers(observers_arg){}
249
 
 
250
 
    inline result_type operator() (argument_type eventObserver)
251
 
    {
252
 
      eventObserver->registerSchemaEventsDo(db, observers);
253
 
    }
254
 
  };
255
 
 
256
 
  //----------
257
 
  /* 
258
 
   * registerSchemaEvents() is called by drizzle to register all plugins that
259
 
   * may be interested in schema events on the database.
260
 
   */ 
261
 
  void EventObserver::registerSchemaEvents(Session &session, const std::string &db)
262
 
  {
263
 
    if (all_event_plugins.empty())
264
 
      return;
265
 
 
266
 
    EventObserverList *observers;
267
 
 
268
 
    observers= session.getSchemaObservers(db);
269
 
 
270
 
    if (observers == NULL) 
271
 
    {
272
 
      observers= new EventObserverList();
273
 
      session.setSchemaObservers(db, observers);
274
 
   }
275
 
 
276
 
    std::for_each(all_event_plugins.begin(), all_event_plugins.end(),
277
 
                  RegisterSchemaEventsIterate(db, *observers));
278
 
 
279
 
  }
280
 
 
281
 
  //----------
282
 
  /* Cleanup before freeing the Session object. */
283
 
  void EventObserver::deregisterSchemaEvents(Session &session, const std::string &db)
284
 
  {
285
 
    if (all_event_plugins.empty())
286
 
      return;
287
 
 
288
 
    EventObserverList *observers;
289
 
 
290
 
    observers= session.getSchemaObservers(db);
291
 
 
292
 
    if (observers) 
293
 
    {
294
 
      session.setSchemaObservers(db, NULL);
295
 
      delete observers;
296
 
    }
297
 
  }
298
 
 
299
 
  /*========================================================*/
300
 
  /*             Session Event Observer handling:           */
301
 
  /*========================================================*/
302
 
 
303
 
  //----------
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.
306
 
   */ 
307
 
  class RegisterSessionEventsIterate : public std::unary_function<EventObserver *, void>
308
 
  {
309
 
    Session &session;
310
 
    EventObserverList &observers;
311
 
  public:
312
 
    RegisterSessionEventsIterate(Session &session_arg, EventObserverList &observers_arg) : 
313
 
      session(session_arg), observers(observers_arg) {}
314
 
    inline result_type operator() (argument_type eventObserver)
315
 
    {
316
 
      eventObserver->registerSessionEventsDo(session, observers);
317
 
    }
318
 
  };
319
 
 
320
 
  //----------
321
 
  /* 
322
 
   * registerSessionEvents() is called by drizzle to register all plugins that
323
 
   * may be interested in session events on the newly created session.
324
 
   */ 
325
 
  void EventObserver::registerSessionEvents(Session &session)
326
 
  {
327
 
    if (all_event_plugins.empty())
328
 
      return;
329
 
 
330
 
    EventObserverList *observers;
331
 
 
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);
337
 
                        delete observers;
338
 
                }
339
 
 
340
 
        observers= new EventObserverList();
341
 
        session.setSessionObservers(observers);
342
 
 
343
 
  std::for_each(all_event_plugins.begin(), all_event_plugins.end(),
344
 
                RegisterSessionEventsIterate(session, *observers));
345
 
 
346
 
  }
347
 
 
348
 
  //----------
349
 
  /* Cleanup before freeing the session object. */
350
 
  void EventObserver::deregisterSessionEvents(Session &session)
351
 
  {
352
 
    if (all_event_plugins.empty())
353
 
      return;
354
 
 
355
 
    EventObserverList *observers;
356
 
 
357
 
    observers= session.getSessionObservers();
358
 
 
359
 
    if (observers) 
360
 
    {
361
 
      session.setSessionObservers(NULL);
362
 
      delete observers;
363
 
    }
364
 
  }
365
 
 
366
 
 
367
 
  /* Event observer list iterator: */
368
 
  //----------
369
 
  class EventIterate : public std::unary_function<std::pair<uint32_t, EventObserver *>, bool>
370
 
  {
371
 
    EventData &data;
372
 
 
373
 
  public:
374
 
    EventIterate(EventData &data_arg) :
375
 
      std::unary_function<std::pair<uint32_t, EventObserver *>, bool>(),
376
 
      data(data_arg)
377
 
    {}
378
 
 
379
 
    inline result_type operator()(argument_type handler)
380
 
    {
381
 
      bool result= handler.second->observeEventDo(data);
382
 
      if (result)
383
 
      {
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));
389
 
 
390
 
      }
391
 
      return result;
392
 
    }
393
 
  };
394
 
 
395
 
 
396
 
  /*==========================================================*/
397
 
  /* Generic meathods called by drizzle to notify all interested  
398
 
   * plugins of an event,
399
 
 */
400
 
 
401
 
  // Call all event observers interested in the event.
402
 
  bool EventData::callEventObservers()
403
 
  {
404
 
    EventObserverList::ObserverMap *eventObservers;
405
 
 
406
 
    if (observerList == NULL)
407
 
      return false; // Nobody was interested in the event. :(
408
 
 
409
 
    eventObservers = observerList->getObservers(event);
410
 
 
411
 
    if (eventObservers == NULL)
412
 
      return false; // Nobody was interested in the event. :(
413
 
 
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 !=.
421
 
   */
422
 
    return iter != eventObservers->end();
423
 
  }
424
 
 
425
 
  //--------
426
 
  bool SessionEventData::callEventObservers()
427
 
  {
428
 
    observerList= session.getSessionObservers();
429
 
 
430
 
    return EventData::callEventObservers();
431
 
  }
432
 
 
433
 
  //--------
434
 
  bool SchemaEventData::callEventObservers()
435
 
  {
436
 
    observerList= session.getSchemaObservers(db);
437
 
    if (!observerList) 
438
 
    {
439
 
      EventObserver::registerSchemaEvents(session, db);
440
 
      observerList= session.getSchemaObservers(db);
441
 
    }
442
 
 
443
 
    return EventData::callEventObservers();
444
 
  }
445
 
 
446
 
  //--------
447
 
  bool TableEventData::callEventObservers()
448
 
  {
449
 
    observerList= table.getMutableShare()->getTableObservers();
450
 
 
451
 
    return EventData::callEventObservers();
452
 
  }
453
 
 
454
 
  /*==========================================================*/
455
 
  /* Static meathods called by drizzle to notify interested plugins 
456
 
   * of a schema event.
457
 
 */
458
 
  bool EventObserver::beforeDropTable(Session &session, const drizzled::identifier::Table &table)
459
 
  {
460
 
    if (all_event_plugins.empty())
461
 
      return false;
462
 
 
463
 
    BeforeDropTableEventData eventData(session, table);
464
 
    return eventData.callEventObservers();
465
 
  }
466
 
 
467
 
  bool EventObserver::afterDropTable(Session &session, const drizzled::identifier::Table &table, int err)
468
 
  {
469
 
    if (all_event_plugins.empty())
470
 
      return false;
471
 
 
472
 
    AfterDropTableEventData eventData(session, table, err);
473
 
    return eventData.callEventObservers();
474
 
  }
475
 
 
476
 
  bool EventObserver::beforeRenameTable(Session &session, const drizzled::identifier::Table &from, const drizzled::identifier::Table &to)
477
 
  {
478
 
    if (all_event_plugins.empty())
479
 
      return false;
480
 
 
481
 
    BeforeRenameTableEventData eventData(session, from, to);
482
 
    return eventData.callEventObservers();
483
 
  }
484
 
 
485
 
  bool EventObserver::afterRenameTable(Session &session, const drizzled::identifier::Table &from, const drizzled::identifier::Table &to, int err)
486
 
  {
487
 
    if (all_event_plugins.empty())
488
 
      return false;
489
 
 
490
 
    AfterRenameTableEventData eventData(session, from, to, err);
491
 
    return eventData.callEventObservers();
492
 
  }
493
 
 
494
 
  /*==========================================================*/
495
 
  /* Static meathods called by drizzle to notify interested plugins 
496
 
   * of a table event.
497
 
   *
498
 
   * A quick test is done first to see if there are any interested observers.
499
 
 */
500
 
  bool EventObserver::beforeInsertRecord(Table &table, unsigned char *buf)
501
 
  {
502
 
    if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
503
 
      return false;
504
 
 
505
 
    BeforeInsertRecordEventData eventData(*(table.in_use), table, buf);
506
 
    return eventData.callEventObservers();
507
 
  }
508
 
 
509
 
  bool EventObserver::afterInsertRecord(Table &table, const unsigned char *buf, int err)
510
 
  {
511
 
    if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
512
 
      return false;
513
 
 
514
 
    AfterInsertRecordEventData eventData(*(table.in_use), table, buf, err);
515
 
    return eventData.callEventObservers();
516
 
  }
517
 
 
518
 
  bool EventObserver::beforeDeleteRecord(Table &table, const unsigned char *buf)
519
 
  {
520
 
    if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
521
 
      return false;
522
 
 
523
 
    BeforeDeleteRecordEventData eventData(*(table.in_use), table, buf);
524
 
    return eventData.callEventObservers();
525
 
  }
526
 
 
527
 
  bool EventObserver::afterDeleteRecord(Table &table, const unsigned char *buf, int err)
528
 
  {
529
 
    if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
530
 
      return false;
531
 
 
532
 
    AfterDeleteRecordEventData eventData(*(table.in_use), table, buf, err);
533
 
    return eventData.callEventObservers();
534
 
  }
535
 
 
536
 
  bool EventObserver::beforeUpdateRecord(Table &table, const unsigned char *old_data, unsigned char *new_data)
537
 
  {
538
 
    if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
539
 
      return false;
540
 
 
541
 
    BeforeUpdateRecordEventData eventData(*(table.in_use), table, old_data, new_data);
542
 
    return eventData.callEventObservers();
543
 
  }
544
 
 
545
 
  bool EventObserver::afterUpdateRecord(Table &table, const unsigned char *old_data, unsigned char *new_data, int err)
546
 
  {
547
 
    if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
548
 
      return false;
549
 
 
550
 
    AfterUpdateRecordEventData eventData(*(table.in_use), table, old_data, new_data, err);
551
 
    return eventData.callEventObservers();
552
 
  }
553
 
 
554
 
  /*==========================================================*/
555
 
  /* Static meathods called by drizzle to notify interested plugins 
556
 
   * of a session event.
557
 
   *
558
 
   * A quick test is done first to see if there are any interested observers.
559
 
*/
560
 
  bool EventObserver::beforeCreateDatabase(Session &session, const std::string &db)
561
 
  {
562
 
    if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
563
 
      return false;
564
 
 
565
 
    BeforeCreateDatabaseEventData eventData(session, db);
566
 
    return eventData.callEventObservers();
567
 
  }
568
 
 
569
 
  bool EventObserver::afterCreateDatabase(Session &session, const std::string &db, int err)
570
 
  {
571
 
    if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
572
 
      return false;
573
 
 
574
 
    AfterCreateDatabaseEventData eventData(session, db, err);
575
 
    return eventData.callEventObservers();
576
 
  }
577
 
 
578
 
  bool EventObserver::beforeDropDatabase(Session &session, const std::string &db)
579
 
  {
580
 
    if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
581
 
      return false;
582
 
 
583
 
    BeforeDropDatabaseEventData eventData(session, db);
584
 
    return eventData.callEventObservers();
585
 
  }
586
 
 
587
 
  bool EventObserver::afterDropDatabase(Session &session, const std::string &db, int err)
588
 
  {
589
 
    if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
590
 
      return false;
591
 
 
592
 
    AfterDropDatabaseEventData eventData(session, db, err);
593
 
    return eventData.callEventObservers();
594
 
  }
595
 
 
596
 
  bool EventObserver::connectSession(Session &session)
597
 
  {
598
 
    if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
599
 
      return false;
600
 
 
601
 
    ConnectSessionEventData eventData(session);
602
 
    return eventData.callEventObservers();
603
 
  }
604
 
 
605
 
  bool EventObserver::disconnectSession(Session &session)
606
 
  {
607
 
    if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
608
 
      return false;
609
 
 
610
 
    DisconnectSessionEventData eventData(session);
611
 
    return eventData.callEventObservers();
612
 
  }
613
 
 
614
 
  bool EventObserver::beforeStatement(Session &session)
615
 
  {
616
 
    if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
617
 
      return false;
618
 
 
619
 
    BeforeStatementEventData eventData(session);
620
 
    return eventData.callEventObservers();
621
 
  }
622
 
 
623
 
  bool EventObserver::afterStatement(Session &session)
624
 
  {
625
 
    if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
626
 
      return false;
627
 
 
628
 
    AfterStatementEventData eventData(session);
629
 
    return eventData.callEventObservers();
630
 
  }
631
 
 
632
 
 
633
 
} /* namespace plugin */
634
 
} /* namespace drizzled */