~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/hello_events/hello_events.cc

  • Committer: Andrew Hutchings
  • Date: 2010-11-01 22:14:18 UTC
  • mto: This revision was merged to the branch mainline in revision 1907.
  • Revision ID: andrew@linuxjedi.co.uk-20101101221418-9n9gmm4ms7fl8vo5
Fix copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2010 PrimeBase Technologies GmbH, Germany
 
3
 *
 
4
 *  This program is free software; you can redistribute it and/or modify
 
5
 *  it under the terms of the GNU General Public License as published by
 
6
 *  the Free Software Foundation; version 2 of the License.
 
7
 *
 
8
 *  This program is distributed in the hope that it will be useful,
 
9
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 *  GNU General Public License for more details.
 
12
 *
 
13
 *  You should have received a copy of the GNU General Public License
 
14
 *  along with this program; if not, write to the Free Software
 
15
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
16
 *
 
17
 * Barry Leslie
 
18
 *
 
19
 * 2010-05-12
 
20
 */
 
21
 
 
22
/**
 
23
 * @details
 
24
 *
 
25
 * This plugin is an example events plugin that just prints some info for
 
26
 * the events that it is tracking. 
 
27
 *  
 
28
set global hello_events1_enable = ON;
 
29
set global hello_events1_watch_databases = "x";   
 
30
set global hello_events1_watch_tables = "x,y";
 
31
 
 
32
 */
 
33
 
 
34
#include "config.h"
 
35
#include <string>
 
36
#include <cstdio>
 
37
#include <boost/program_options.hpp>
 
38
#include <drizzled/module/option_map.h>
 
39
#include "drizzled/session.h"
 
40
#include "hello_events.h"
 
41
namespace po= boost::program_options;
 
42
using namespace drizzled;
 
43
using namespace plugin;
 
44
using namespace std;
 
45
 
 
46
#define PLUGIN_NAME "hello_events1"
 
47
 
 
48
static bool sysvar_hello_events_enabled= true;
 
49
static HelloEvents *hello_events= NULL;
 
50
static char *sysvar_table_list= NULL;
 
51
static char *sysvar_db_list= NULL;
 
52
 
 
53
/*
 
54
 * Event observer positions are used to set the order in which
 
55
 * event observers are called in the case that more than one
 
56
 * plugin is interested in the same event. You should only specify
 
57
 * the order if it really matters because if more than one plugin 
 
58
 * request the same calling position only the first one gets it and
 
59
 * the others will not be registered for the event. For this reason
 
60
 * your plugin should always provide a way to reposition the event
 
61
 * observer to resolve such conflicts.
 
62
 *
 
63
 * If position matters you will always initialy ask for the first position (1)
 
64
 * or the last position (-1) in the calling order, for example it makes no sence 
 
65
 * to initially ask to be called in position 13.
 
66
 */
 
67
static int32_t sysvar_before_write_position= 1;      // Call this event observer first.
 
68
static int32_t sysvar_before_update_position= 1;
 
69
static int32_t sysvar_post_drop_db_position= -1;  // I want my event observer to be called last. No reason, I just do!
 
70
 
 
71
 
 
72
//==================================
 
73
// My table event observers: 
 
74
static bool observeBeforeInsertRecord(BeforeInsertRecordEventData &data)
 
75
{
 
76
 
 
77
  static int count= 0;
 
78
  count++;
 
79
  data.session.setVariable("BEFORE_INSERT_RECORD", boost::lexical_cast<std::string>(count));
 
80
  return false;
 
81
}
 
82
 
 
83
//---
 
84
static void observeAfterInsertRecord(AfterInsertRecordEventData &data)
 
85
{
 
86
  static int count= 0;
 
87
  count++;
 
88
  data.session.setVariable("AFTER_INSERT_RECORD", boost::lexical_cast<std::string>(count));
 
89
}
 
90
 
 
91
//---
 
92
static bool observeBeforeDeleteRecord(BeforeDeleteRecordEventData &data)
 
93
{
 
94
  static int count= 0;
 
95
  count++;
 
96
  data.session.setVariable("AFTER_DELETE_RECORD", boost::lexical_cast<std::string>(count));
 
97
  return false;
 
98
}
 
99
 
 
100
//---
 
101
static void observeAfterDeleteRecord(AfterDeleteRecordEventData &data)
 
102
{
 
103
  static int count= 0;
 
104
  count++;
 
105
  data.session.setVariable("AFTER_DELETE_RECORD", boost::lexical_cast<std::string>(count));
 
106
}
 
107
 
 
108
//---
 
109
static bool observeBeforeUpdateRecord(BeforeUpdateRecordEventData &data)
 
110
{
 
111
  static int count= 0;
 
112
  count++;
 
113
  data.session.setVariable("BEFORE_UPDATE_RECORD", boost::lexical_cast<std::string>(count));
 
114
  return false;
 
115
}
 
116
 
 
117
//---
 
118
static void observeAfterUpdateRecord(AfterUpdateRecordEventData &data)
 
119
{
 
120
  static int count= 0;
 
121
  count++;
 
122
  data.session.setVariable("AFTER_UPDATE_RECORD", boost::lexical_cast<std::string>(count));
 
123
}
 
124
 
 
125
//==================================
 
126
// My schema event observers: 
 
127
static void observeAfterDropTable(AfterDropTableEventData &data)
 
128
{
 
129
  static int count= 0;
 
130
  count++;
 
131
  data.session.setVariable("AFTER_DROP_TABLE", boost::lexical_cast<std::string>(count));
 
132
}
 
133
 
 
134
//---
 
135
static void observeAfterRenameTable(AfterRenameTableEventData &data)
 
136
{
 
137
  static int count= 0;
 
138
  count++;
 
139
  data.session.setVariable("AFTER_RENAME_TABLE", boost::lexical_cast<std::string>(count));
 
140
}
 
141
 
 
142
//---
 
143
static void observeAfterCreateDatabase(AfterCreateDatabaseEventData &data)
 
144
{
 
145
  static int count= 0;
 
146
  count++;
 
147
  data.session.setVariable("AFTER_CREATE_DATABASE", boost::lexical_cast<std::string>(count));
 
148
}
 
149
 
 
150
//---
 
151
static void observeAfterDropDatabase(AfterDropDatabaseEventData &data)
 
152
{
 
153
  static int count= 0;
 
154
  count++;
 
155
  data.session.setVariable("AFTER_DROP_DATABASE", boost::lexical_cast<std::string>(count));
 
156
}
 
157
 
 
158
//---
 
159
static void observeConnectSession(ConnectSessionEventData &data)
 
160
{
 
161
  static int count= 0;
 
162
  count++;
 
163
  data.session.setVariable("CONNECT_SESSION", boost::lexical_cast<std::string>(count));
 
164
}
 
165
 
 
166
//---
 
167
static void observeDisconnectSession(DisconnectSessionEventData &data)
 
168
{
 
169
  static int count= 0;
 
170
  count++;
 
171
  data.session.setVariable("DISCONNECT_SESSION", boost::lexical_cast<std::string>(count));
 
172
}
 
173
 
 
174
//---
 
175
static void observeBeforeStatement(BeforeStatementEventData &data)
 
176
{
 
177
  static int count= 0;
 
178
  count++;
 
179
  data.session.setVariable("BEFORE_STATEMENT", boost::lexical_cast<std::string>(count));
 
180
}
 
181
 
 
182
//---
 
183
static void observeAfterStatement(AfterStatementEventData &data)
 
184
{
 
185
  static int count= 0;
 
186
  count++;
 
187
  data.session.setVariable("AFTER_STATEMENT", boost::lexical_cast<std::string>(count));
 
188
}
 
189
 
 
190
HelloEvents::~HelloEvents()
 
191
{
 
192
  /* These are strdup'd in option processing */
 
193
  if (sysvar_table_list) {
 
194
        free(sysvar_table_list);
 
195
        sysvar_table_list = NULL;
 
196
  }
 
197
  
 
198
  if (sysvar_db_list) {
 
199
        free(sysvar_db_list);
 
200
        sysvar_db_list = NULL;
 
201
  }
 
202
  
 
203
}
 
204
 
 
205
//==================================
 
206
/* This is where I register which table events my pluggin is interested in.*/
 
207
void HelloEvents::registerTableEventsDo(TableShare &table_share, EventObserverList &observers)
 
208
{
 
209
  if ((is_enabled == false) 
 
210
    || !isTableInteresting(table_share.getTableName())
 
211
    || !isDatabaseInteresting(table_share.getSchemaName()))
 
212
    return;
 
213
    
 
214
  registerEvent(observers, BEFORE_INSERT_RECORD, sysvar_before_write_position); // I want to be called first if passible
 
215
  registerEvent(observers, AFTER_INSERT_RECORD);
 
216
  registerEvent(observers, BEFORE_UPDATE_RECORD, sysvar_before_update_position);
 
217
  registerEvent(observers, AFTER_UPDATE_RECORD);
 
218
  registerEvent(observers, BEFORE_DELETE_RECORD);
 
219
  registerEvent(observers, AFTER_DELETE_RECORD);
 
220
}
 
221
 
 
222
//==================================
 
223
/* This is where I register which schema events my pluggin is interested in.*/
 
224
void HelloEvents::registerSchemaEventsDo(const std::string &db, EventObserverList &observers)
 
225
{
 
226
  if ((is_enabled == false) 
 
227
    || !isDatabaseInteresting(db))
 
228
    return;
 
229
    
 
230
  registerEvent(observers, AFTER_DROP_TABLE);
 
231
  registerEvent(observers, AFTER_RENAME_TABLE);
 
232
}
 
233
 
 
234
//==================================
 
235
/* This is where I register which session events my pluggin is interested in.*/
 
236
void HelloEvents::registerSessionEventsDo(Session &session, EventObserverList &observers)
 
237
{
 
238
  if ((is_enabled == false) 
 
239
    || !isSessionInteresting(session))
 
240
    return;
 
241
    
 
242
  registerEvent(observers, AFTER_CREATE_DATABASE);
 
243
  registerEvent(observers, AFTER_DROP_DATABASE, sysvar_post_drop_db_position);
 
244
  registerEvent(observers, DISCONNECT_SESSION);
 
245
  registerEvent(observers, CONNECT_SESSION);
 
246
  registerEvent(observers, BEFORE_STATEMENT);
 
247
  registerEvent(observers, AFTER_STATEMENT);
 
248
}
 
249
 
 
250
 
 
251
//==================================
 
252
/* The event observer.*/
 
253
bool HelloEvents::observeEventDo(EventData &data)
 
254
{
 
255
  bool result= false;
 
256
  
 
257
  switch (data.event) {
 
258
  case AFTER_DROP_TABLE:
 
259
    observeAfterDropTable((AfterDropTableEventData &)data);
 
260
    break;
 
261
    
 
262
  case AFTER_RENAME_TABLE:
 
263
    observeAfterRenameTable((AfterRenameTableEventData &)data);
 
264
    break;
 
265
    
 
266
  case BEFORE_INSERT_RECORD:
 
267
     result = observeBeforeInsertRecord((BeforeInsertRecordEventData &)data);
 
268
    break;
 
269
    
 
270
  case AFTER_INSERT_RECORD:
 
271
    observeAfterInsertRecord((AfterInsertRecordEventData &)data);
 
272
    break;     
 
273
       
 
274
  case BEFORE_UPDATE_RECORD:
 
275
    result = observeBeforeUpdateRecord((BeforeUpdateRecordEventData &)data);
 
276
    break;
 
277
             
 
278
  case AFTER_UPDATE_RECORD:
 
279
     observeAfterUpdateRecord((AfterUpdateRecordEventData &)data);
 
280
    break;     
 
281
    
 
282
  case BEFORE_DELETE_RECORD:
 
283
    result = observeBeforeDeleteRecord((BeforeDeleteRecordEventData &)data);
 
284
    break;
 
285
 
 
286
  case AFTER_DELETE_RECORD:
 
287
    observeAfterDeleteRecord((AfterDeleteRecordEventData &)data);
 
288
    break;
 
289
 
 
290
  case AFTER_CREATE_DATABASE:
 
291
    observeAfterCreateDatabase((AfterCreateDatabaseEventData &)data);
 
292
    break;
 
293
 
 
294
  case AFTER_DROP_DATABASE:
 
295
    observeAfterDropDatabase((AfterDropDatabaseEventData &)data);
 
296
    break;
 
297
 
 
298
  case CONNECT_SESSION:
 
299
    observeConnectSession((ConnectSessionEventData &)data);
 
300
    break;
 
301
 
 
302
  case DISCONNECT_SESSION:
 
303
    observeDisconnectSession((DisconnectSessionEventData &)data);
 
304
    break;
 
305
 
 
306
  case BEFORE_STATEMENT:
 
307
    observeBeforeStatement((BeforeStatementEventData &)data);
 
308
    break;
 
309
 
 
310
  case AFTER_STATEMENT:
 
311
    observeAfterStatement((AfterStatementEventData &)data);
 
312
    break;
 
313
 
 
314
  default:
 
315
    fprintf(stderr, "HelloEvents: Unexpected event '%s'\n", EventObserver::eventName(data.event));
 
316
 
 
317
  }
 
318
  
 
319
  return false;
 
320
}
 
321
 
 
322
//==================================
 
323
// Some custom things for my plugin:
 
324
 
 
325
 
 
326
/* Plugin initialization and system variables */
 
327
 
 
328
static void enable(Session *,
 
329
                   drizzle_sys_var *,
 
330
                   void *var_ptr,
 
331
                   const void *save)
 
332
{
 
333
  if (hello_events)
 
334
  {
 
335
    if (*(bool *)save != false)
 
336
    {
 
337
      hello_events->enable();
 
338
      *(bool *) var_ptr= (bool) true;
 
339
    }
 
340
    else
 
341
    {
 
342
      hello_events->disable();
 
343
      *(bool *) var_ptr= (bool) false;
 
344
    }
 
345
  }
 
346
}
 
347
 
 
348
 
 
349
static void set_db_list(Session *,
 
350
                   drizzle_sys_var *, 
 
351
                   void *var_ptr,     
 
352
                   const void *save)
 
353
{
 
354
  if (hello_events)
 
355
  {
 
356
    hello_events->setDatabasesOfInterest(*(const char **) save);
 
357
    *(const char **) var_ptr= hello_events->getDatabasesOfInterest();
 
358
  }
 
359
}
 
360
 
 
361
static void set_table_list(Session *,
 
362
                   drizzle_sys_var *, 
 
363
                   void *var_ptr,     
 
364
                   const void *save)
 
365
{
 
366
  if (hello_events)
 
367
  {
 
368
    hello_events->setTablesOfInterest(*(const char **) save);
 
369
    *(const char **) var_ptr= hello_events->getTablesOfInterest();
 
370
  }
 
371
}
 
372
 
 
373
 
 
374
static int init(module::Context &context)
 
375
{
 
376
  const module::option_map &vm= context.getOptions();
 
377
  if (vm.count("before-write-position"))
 
378
  { 
 
379
    if (sysvar_before_write_position < 1 || sysvar_before_write_position > INT32_MAX -1)
 
380
    {
 
381
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of before-write-position\n"));
 
382
      exit(-1);
 
383
    }
 
384
  }
 
385
 
 
386
  if (vm.count("before-update-position"))
 
387
  { 
 
388
    if (sysvar_before_update_position < 1 || sysvar_before_update_position > INT32_MAX -1)
 
389
    {
 
390
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of before-update-position\n"));
 
391
      exit(-1);
 
392
    }
 
393
  }
 
394
 
 
395
  if (vm.count("post-drop-db-position"))
 
396
  { 
 
397
    if (sysvar_post_drop_db_position > -1 || sysvar_post_drop_db_position < INT32_MIN+1)
 
398
    {
 
399
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of before-update-position\n"));
 
400
      exit(-1);
 
401
    }
 
402
  }
 
403
 
 
404
  if (vm.count("watch-databases"))
 
405
  {
 
406
    sysvar_db_list= strdup(vm["watch-databases"].as<string>().c_str());
 
407
  }
 
408
 
 
409
  else
 
410
  {
 
411
    sysvar_db_list= strdup("");
 
412
  }
 
413
 
 
414
  if (vm.count("watch-tables"))
 
415
  {
 
416
    sysvar_table_list= strdup(vm["watch-tables"].as<string>().c_str());
 
417
  }
 
418
 
 
419
  else
 
420
  {
 
421
    sysvar_table_list= strdup("");
 
422
  }
 
423
  hello_events= new HelloEvents(PLUGIN_NAME);
 
424
 
 
425
  context.add(hello_events);
 
426
 
 
427
  if (sysvar_hello_events_enabled)
 
428
  {
 
429
    hello_events->enable();
 
430
  }
 
431
 
 
432
  return 0;
 
433
}
 
434
 
 
435
static void init_options(drizzled::module::option_context &context)
 
436
{
 
437
  context("watch-databases",
 
438
          po::value<string>(),
 
439
          N_("A comma delimited list of databases to watch"));
 
440
  context("watch-tables",
 
441
          po::value<string>(),
 
442
          N_("A comma delimited list of databases to watch"));
 
443
  context("enable",
 
444
          po::value<bool>(&sysvar_hello_events_enabled)->default_value(false)->zero_tokens(),
 
445
          N_("Enable Example Events Plugin"));
 
446
  context("before-write-position",
 
447
          po::value<int32_t>(&sysvar_before_write_position)->default_value(1),
 
448
          N_("Before write row event observer call position"));
 
449
  context("before-update-position",
 
450
          po::value<int32_t>(&sysvar_before_update_position)->default_value(1),
 
451
          N_("Before update row event observer call position"));
 
452
  context("post-drop-db-position",
 
453
          po::value<int32_t>(&sysvar_post_drop_db_position)->default_value(-1),
 
454
          N_("After drop database event observer call position"));
 
455
}
 
456
 
 
457
static DRIZZLE_SYSVAR_STR(watch_databases,
 
458
                           sysvar_db_list,
 
459
                           PLUGIN_VAR_OPCMDARG,
 
460
                           N_("A comma delimited list of databases to watch"),
 
461
                           NULL, /* check func */
 
462
                           set_db_list, /* update func */
 
463
                           "" /* default */);
 
464
 
 
465
static DRIZZLE_SYSVAR_STR(watch_tables,
 
466
                           sysvar_table_list,
 
467
                           PLUGIN_VAR_OPCMDARG,
 
468
                           N_("A comma delimited list of tables to watch"),
 
469
                           NULL, /* check func */
 
470
                           set_table_list, /* update func */
 
471
                           "" /* default */);
 
472
 
 
473
static DRIZZLE_SYSVAR_BOOL(enable,
 
474
                           sysvar_hello_events_enabled,
 
475
                           PLUGIN_VAR_NOCMDARG,
 
476
                           N_("Enable Example Events Plugin"),
 
477
                           NULL, /* check func */
 
478
                           enable, /* update func */
 
479
                           false /* default */);
 
480
 
 
481
static DRIZZLE_SYSVAR_INT(before_write_position,
 
482
                           sysvar_before_write_position,
 
483
                           PLUGIN_VAR_NOCMDARG,
 
484
                           N_("Before write row event observer call position"),
 
485
                           NULL, /* check func */
 
486
                           NULL, /* update func */
 
487
                           1, /* default */
 
488
                           1, /* min */
 
489
                           INT32_MAX -1, /* max */
 
490
                           0 /* blk */);
 
491
 
 
492
static DRIZZLE_SYSVAR_INT(before_update_position,
 
493
                           sysvar_before_update_position,
 
494
                           PLUGIN_VAR_NOCMDARG,
 
495
                           N_("Before update row event observer call position"),
 
496
                           NULL, /* check func */
 
497
                           NULL, /* update func */
 
498
                           1, /* default */
 
499
                           1, /* min */
 
500
                           INT32_MAX -1, /* max */
 
501
                           0 /* blk */);
 
502
 
 
503
static drizzle_sys_var* system_var[]= {
 
504
  DRIZZLE_SYSVAR(watch_databases),
 
505
  DRIZZLE_SYSVAR(watch_tables),
 
506
  DRIZZLE_SYSVAR(enable),
 
507
  DRIZZLE_SYSVAR(before_write_position),
 
508
  DRIZZLE_SYSVAR(before_update_position),
 
509
  NULL
 
510
};
 
511
 
 
512
DRIZZLE_DECLARE_PLUGIN
 
513
{
 
514
  DRIZZLE_VERSION_ID,
 
515
  PLUGIN_NAME,
 
516
  "0.1",
 
517
  "Barry Leslie",
 
518
  N_("An example events Plugin"),
 
519
  PLUGIN_LICENSE_BSD,
 
520
  init,   /* Plugin Init      */
 
521
  system_var, /* system variables */
 
522
  init_options    /* config options   */
 
523
}
 
524
DRIZZLE_DECLARE_PLUGIN_END;