Drizzled Public API Documentation

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