~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/hello_events/hello_events.cc

  • Committer: Olaf van der Spek
  • Date: 2011-02-12 18:24:24 UTC
  • mto: (2167.1.2 build) (2172.1.4 build)
  • mto: This revision was merged to the branch mainline in revision 2168.
  • Revision ID: olafvdspek@gmail.com-20110212182424-kgnm9osi7qo97at2
casts

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
 
 
42
namespace po= boost::program_options;
 
43
using namespace drizzled;
 
44
using namespace plugin;
 
45
using namespace std;
 
46
 
 
47
#define PLUGIN_NAME "hello_events1"
 
48
 
 
49
static bool sysvar_hello_events_enabled;
 
50
static HelloEvents *hello_events= NULL;
 
51
static string sysvar_db_list;
 
52
static string sysvar_table_list;
 
53
 
 
54
/*
 
55
 * Event observer positions are used to set the order in which
 
56
 * event observers are called in the case that more than one
 
57
 * plugin is interested in the same event. You should only specify
 
58
 * the order if it really matters because if more than one plugin 
 
59
 * request the same calling position only the first one gets it and
 
60
 * the others will not be registered for the event. For this reason
 
61
 * your plugin should always provide a way to reposition the event
 
62
 * observer to resolve such conflicts.
 
63
 *
 
64
 * If position matters you will always initialy ask for the first position (1)
 
65
 * or the last position (-1) in the calling order, for example it makes no sence 
 
66
 * to initially ask to be called in position 13.
 
67
 */
 
68
typedef constrained_check<uint64_t, INT32_MAX-1, 1> position_constraint;
 
69
typedef constrained_check<int32_t, -1, INT32_MIN+1> post_drop_constraint;
 
70
 
 
71
static position_constraint sysvar_before_write_position;      // Call this event observer first.
 
72
static position_constraint sysvar_before_update_position;
 
73
static post_drop_constraint sysvar_post_drop_db_position;  // I want my event observer to be called last. No reason, I just do!
 
74
 
 
75
 
 
76
//==================================
 
77
// My table event observers: 
 
78
static bool observeBeforeInsertRecord(BeforeInsertRecordEventData &data)
 
79
{
 
80
 
 
81
  static int count= 0;
 
82
  count++;
 
83
  data.session.setVariable("BEFORE_INSERT_RECORD", boost::lexical_cast<std::string>(count));
 
84
  return false;
 
85
}
 
86
 
 
87
//---
 
88
static void observeAfterInsertRecord(AfterInsertRecordEventData &data)
 
89
{
 
90
  static int count= 0;
 
91
  count++;
 
92
  data.session.setVariable("AFTER_INSERT_RECORD", boost::lexical_cast<std::string>(count));
 
93
}
 
94
 
 
95
//---
 
96
static bool observeBeforeDeleteRecord(BeforeDeleteRecordEventData &data)
 
97
{
 
98
  static int count= 0;
 
99
  count++;
 
100
  data.session.setVariable("AFTER_DELETE_RECORD", boost::lexical_cast<std::string>(count));
 
101
  return false;
 
102
}
 
103
 
 
104
//---
 
105
static void observeAfterDeleteRecord(AfterDeleteRecordEventData &data)
 
106
{
 
107
  static int count= 0;
 
108
  count++;
 
109
  data.session.setVariable("AFTER_DELETE_RECORD", boost::lexical_cast<std::string>(count));
 
110
}
 
111
 
 
112
//---
 
113
static bool observeBeforeUpdateRecord(BeforeUpdateRecordEventData &data)
 
114
{
 
115
  static int count= 0;
 
116
  count++;
 
117
  data.session.setVariable("BEFORE_UPDATE_RECORD", boost::lexical_cast<std::string>(count));
 
118
  return false;
 
119
}
 
120
 
 
121
//---
 
122
static void observeAfterUpdateRecord(AfterUpdateRecordEventData &data)
 
123
{
 
124
  static int count= 0;
 
125
  count++;
 
126
  data.session.setVariable("AFTER_UPDATE_RECORD", boost::lexical_cast<std::string>(count));
 
127
}
 
128
 
 
129
//==================================
 
130
// My schema event observers: 
 
131
static void observeAfterDropTable(AfterDropTableEventData &data)
 
132
{
 
133
  static int count= 0;
 
134
  count++;
 
135
  data.session.setVariable("AFTER_DROP_TABLE", boost::lexical_cast<std::string>(count));
 
136
}
 
137
 
 
138
//---
 
139
static void observeAfterRenameTable(AfterRenameTableEventData &data)
 
140
{
 
141
  static int count= 0;
 
142
  count++;
 
143
  data.session.setVariable("AFTER_RENAME_TABLE", boost::lexical_cast<std::string>(count));
 
144
}
 
145
 
 
146
//---
 
147
static void observeAfterCreateDatabase(AfterCreateDatabaseEventData &data)
 
148
{
 
149
  static int count= 0;
 
150
  count++;
 
151
  data.session.setVariable("AFTER_CREATE_DATABASE", boost::lexical_cast<std::string>(count));
 
152
}
 
153
 
 
154
//---
 
155
static void observeAfterDropDatabase(AfterDropDatabaseEventData &data)
 
156
{
 
157
  static int count= 0;
 
158
  count++;
 
159
  data.session.setVariable("AFTER_DROP_DATABASE", boost::lexical_cast<std::string>(count));
 
160
}
 
161
 
 
162
//---
 
163
static void observeConnectSession(ConnectSessionEventData &data)
 
164
{
 
165
  static int count= 0;
 
166
  count++;
 
167
  data.session.setVariable("CONNECT_SESSION", boost::lexical_cast<std::string>(count));
 
168
}
 
169
 
 
170
//---
 
171
static void observeDisconnectSession(DisconnectSessionEventData &data)
 
172
{
 
173
  static int count= 0;
 
174
  count++;
 
175
  data.session.setVariable("DISCONNECT_SESSION", boost::lexical_cast<std::string>(count));
 
176
}
 
177
 
 
178
//---
 
179
static void observeBeforeStatement(BeforeStatementEventData &data)
 
180
{
 
181
  static int count= 0;
 
182
  count++;
 
183
  data.session.setVariable("BEFORE_STATEMENT", boost::lexical_cast<std::string>(count));
 
184
}
 
185
 
 
186
//---
 
187
static void observeAfterStatement(AfterStatementEventData &data)
 
188
{
 
189
  static int count= 0;
 
190
  count++;
 
191
  data.session.setVariable("AFTER_STATEMENT", boost::lexical_cast<std::string>(count));
 
192
}
 
193
 
 
194
HelloEvents::~HelloEvents()
 
195
{ }
 
196
 
 
197
//==================================
 
198
/* This is where I register which table events my pluggin is interested in.*/
 
199
void HelloEvents::registerTableEventsDo(TableShare &table_share, EventObserverList &observers)
 
200
{
 
201
  if ((is_enabled == false) 
 
202
    || !isTableInteresting(table_share.getTableName())
 
203
    || !isDatabaseInteresting(table_share.getSchemaName()))
 
204
    return;
 
205
    
 
206
  registerEvent(observers, BEFORE_INSERT_RECORD, sysvar_before_write_position.get());
 
207
  // I want to be called first if passible
 
208
  registerEvent(observers, AFTER_INSERT_RECORD);
 
209
  registerEvent(observers, BEFORE_UPDATE_RECORD, sysvar_before_update_position.get());
 
210
  registerEvent(observers, AFTER_UPDATE_RECORD);
 
211
  registerEvent(observers, BEFORE_DELETE_RECORD);
 
212
  registerEvent(observers, AFTER_DELETE_RECORD);
 
213
}
 
214
 
 
215
//==================================
 
216
/* This is where I register which schema events my pluggin is interested in.*/
 
217
void HelloEvents::registerSchemaEventsDo(const std::string &db, EventObserverList &observers)
 
218
{
 
219
  if ((is_enabled == false) 
 
220
    || !isDatabaseInteresting(db))
 
221
    return;
 
222
    
 
223
  registerEvent(observers, AFTER_DROP_TABLE);
 
224
  registerEvent(observers, AFTER_RENAME_TABLE);
 
225
}
 
226
 
 
227
//==================================
 
228
/* This is where I register which session events my pluggin is interested in.*/
 
229
void HelloEvents::registerSessionEventsDo(Session &session, EventObserverList &observers)
 
230
{
 
231
  if ((is_enabled == false) 
 
232
    || !isSessionInteresting(session))
 
233
    return;
 
234
    
 
235
  registerEvent(observers, AFTER_CREATE_DATABASE);
 
236
  registerEvent(observers, AFTER_DROP_DATABASE, sysvar_post_drop_db_position.get());
 
237
  registerEvent(observers, DISCONNECT_SESSION);
 
238
  registerEvent(observers, CONNECT_SESSION);
 
239
  registerEvent(observers, BEFORE_STATEMENT);
 
240
  registerEvent(observers, AFTER_STATEMENT);
 
241
}
 
242
 
 
243
 
 
244
//==================================
 
245
/* The event observer.*/
 
246
bool HelloEvents::observeEventDo(EventData &data)
 
247
{
 
248
  bool result= false;
 
249
  
 
250
  switch (data.event) {
 
251
  case AFTER_DROP_TABLE:
 
252
    observeAfterDropTable((AfterDropTableEventData &)data);
 
253
    break;
 
254
    
 
255
  case AFTER_RENAME_TABLE:
 
256
    observeAfterRenameTable((AfterRenameTableEventData &)data);
 
257
    break;
 
258
    
 
259
  case BEFORE_INSERT_RECORD:
 
260
     result = observeBeforeInsertRecord((BeforeInsertRecordEventData &)data);
 
261
    break;
 
262
    
 
263
  case AFTER_INSERT_RECORD:
 
264
    observeAfterInsertRecord((AfterInsertRecordEventData &)data);
 
265
    break;     
 
266
       
 
267
  case BEFORE_UPDATE_RECORD:
 
268
    result = observeBeforeUpdateRecord((BeforeUpdateRecordEventData &)data);
 
269
    break;
 
270
             
 
271
  case AFTER_UPDATE_RECORD:
 
272
     observeAfterUpdateRecord((AfterUpdateRecordEventData &)data);
 
273
    break;     
 
274
    
 
275
  case BEFORE_DELETE_RECORD:
 
276
    result = observeBeforeDeleteRecord((BeforeDeleteRecordEventData &)data);
 
277
    break;
 
278
 
 
279
  case AFTER_DELETE_RECORD:
 
280
    observeAfterDeleteRecord((AfterDeleteRecordEventData &)data);
 
281
    break;
 
282
 
 
283
  case AFTER_CREATE_DATABASE:
 
284
    observeAfterCreateDatabase((AfterCreateDatabaseEventData &)data);
 
285
    break;
 
286
 
 
287
  case AFTER_DROP_DATABASE:
 
288
    observeAfterDropDatabase((AfterDropDatabaseEventData &)data);
 
289
    break;
 
290
 
 
291
  case CONNECT_SESSION:
 
292
    observeConnectSession((ConnectSessionEventData &)data);
 
293
    break;
 
294
 
 
295
  case DISCONNECT_SESSION:
 
296
    observeDisconnectSession((DisconnectSessionEventData &)data);
 
297
    break;
 
298
 
 
299
  case BEFORE_STATEMENT:
 
300
    observeBeforeStatement((BeforeStatementEventData &)data);
 
301
    break;
 
302
 
 
303
  case AFTER_STATEMENT:
 
304
    observeAfterStatement((AfterStatementEventData &)data);
 
305
    break;
 
306
 
 
307
  default:
 
308
    fprintf(stderr, "HelloEvents: Unexpected event '%s'\n", EventObserver::eventName(data.event));
 
309
 
 
310
  }
 
311
  
 
312
  return false;
 
313
}
 
314
 
 
315
//==================================
 
316
// Some custom things for my plugin:
 
317
 
 
318
 
 
319
/* Plugin initialization and system variables */
 
320
 
 
321
static void enable(Session*, sql_var_t)
 
322
{
 
323
  if (hello_events)
 
324
  {
 
325
    if (sysvar_hello_events_enabled)
 
326
    {
 
327
      hello_events->enable();
 
328
    }
 
329
    else
 
330
    {
 
331
      hello_events->disable();
 
332
    }
 
333
  }
 
334
}
 
335
 
 
336
 
 
337
static int set_db_list(Session *, set_var *var)
 
338
{
 
339
  const char *db_list= var->value->str_value.ptr();
 
340
  if (db_list == NULL)
 
341
    return 1;
 
342
 
 
343
  if (hello_events)
 
344
  {
 
345
    hello_events->setDatabasesOfInterest(db_list);
 
346
    sysvar_db_list.assign(db_list);
 
347
  }
 
348
  return 0;
 
349
}
 
350
 
 
351
static int set_table_list(Session *, set_var *var)
 
352
{
 
353
  const char *table_list= var->value->str_value.ptr();
 
354
  if (table_list == NULL)
 
355
    return 1;
 
356
 
 
357
  if (hello_events)
 
358
  {
 
359
    hello_events->setTablesOfInterest(table_list);
 
360
    sysvar_table_list.assign(table_list);
 
361
  }
 
362
  return 0;
 
363
}
 
364
 
 
365
 
 
366
static int init(module::Context &context)
 
367
{
 
368
  hello_events= new HelloEvents(PLUGIN_NAME);
 
369
 
 
370
  context.add(hello_events);
 
371
 
 
372
  if (sysvar_hello_events_enabled)
 
373
  {
 
374
    hello_events->enable();
 
375
  }
 
376
 
 
377
  context.registerVariable(new sys_var_bool_ptr("enable",
 
378
                                                &sysvar_hello_events_enabled,
 
379
                                                enable));
 
380
  context.registerVariable(new sys_var_std_string("watch_databases",
 
381
                                                  sysvar_db_list,
 
382
                                                  set_db_list));
 
383
  context.registerVariable(new sys_var_std_string("watch_tables",
 
384
                                                  sysvar_table_list,
 
385
                                                  set_table_list));
 
386
  context.registerVariable(new sys_var_constrained_value<uint64_t>("before_write_position",
 
387
                                                         sysvar_before_write_position));
 
388
  context.registerVariable(new sys_var_constrained_value<uint64_t>("before_update_position",
 
389
                                                         sysvar_before_update_position));
 
390
  context.registerVariable(new sys_var_constrained_value<int32_t>("post_drop_position",
 
391
                                                         sysvar_post_drop_db_position));
 
392
 
 
393
 
 
394
  return 0;
 
395
}
 
396
 
 
397
static void init_options(drizzled::module::option_context &context)
 
398
{
 
399
  context("enable",
 
400
          po::value<bool>(&sysvar_hello_events_enabled)->default_value(false)->zero_tokens(),
 
401
          N_("Enable Example Events Plugin"));
 
402
  context("watch-databases",
 
403
          po::value<string>(&sysvar_db_list)->default_value(""),
 
404
          N_("A comma delimited list of databases to watch"));
 
405
  context("watch-tables",
 
406
          po::value<string>(&sysvar_table_list)->default_value(""),
 
407
          N_("A comma delimited list of databases to watch"));
 
408
  context("before-write-position",
 
409
          po::value<position_constraint>(&sysvar_before_write_position)->default_value(1),
 
410
          N_("Before write row event observer call position"));
 
411
  context("before-update-position",
 
412
          po::value<position_constraint>(&sysvar_before_update_position)->default_value(1),
 
413
          N_("Before update row event observer call position"));
 
414
  context("post-drop-db-position",
 
415
          po::value<post_drop_constraint>(&sysvar_post_drop_db_position)->default_value(-1),
 
416
          N_("After drop database event observer call position"));
 
417
}
 
418
 
 
419
 
 
420
 
 
421
DRIZZLE_DECLARE_PLUGIN
 
422
{
 
423
  DRIZZLE_VERSION_ID,
 
424
  PLUGIN_NAME,
 
425
  "0.1",
 
426
  "Barry Leslie",
 
427
  N_("An example events Plugin"),
 
428
  PLUGIN_LICENSE_BSD,
 
429
  init,   /* Plugin Init      */
 
430
  NULL, /* depends */
 
431
  init_options    /* config options   */
 
432
}
 
433
DRIZZLE_DECLARE_PLUGIN_END;