~drizzle-trunk/drizzle/development

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