~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/hello_events/hello_events.cc

  • Committer: Jay Pipes
  • Date: 2010-03-09 20:02:29 UTC
  • mto: This revision was merged to the branch mainline in revision 1339.
  • Revision ID: jpipes@serialcoder-20100309200229-dfrliy4fads9vyf4
Fixes Bug #535296 by only incrementing ha_commit_count when its a normal transaction commit.

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;