Drizzled Public API Documentation

event_observer.cc

00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2010 PrimeBase Technologies GmbH, Germany
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  *
00019  * Barry Leslie
00020  *
00021  * 2010-05-12
00022  */
00023 
00024 #include <config.h>
00025 
00026 #include <string>
00027 #include <vector>
00028 
00029 #include <drizzled/session.h>
00030 #include <drizzled/table_list.h>
00031 #include <drizzled/table/instance.h>
00032 #include <drizzled/module/registry.h>
00033 #include <drizzled/plugin/event_observer.h>
00034 #include <drizzled/util/functors.h>
00035 #include <algorithm>
00036 
00037 
00038 
00039 namespace drizzled
00040 {
00041 
00042 namespace plugin
00043 {
00044 
00045 /*============================*/
00046   // Basic plugin registration stuff.
00047   EventObserverVector all_event_plugins;
00048 
00049   const EventObserverVector &EventObserver::getEventObservers(void)
00050   {
00051     return all_event_plugins;
00052   }
00053 
00054   //---------
00055   bool EventObserver::addPlugin(EventObserver *handler)
00056   {
00057     if (handler != NULL)
00058       all_event_plugins.push_back(handler);
00059     return false;
00060   }
00061 
00062   //---------
00063   void EventObserver::removePlugin(EventObserver *handler)
00064   {
00065     if (handler != NULL)
00066       all_event_plugins.erase(std::find(all_event_plugins.begin(), all_event_plugins.end(), handler));
00067   }
00068 
00069 
00070   /* 
00071    * The Event Observer list class in which plugins register which events they
00072    * are interested in.
00073    *
00074    * Each table share for example, will have one of these hung on it to store
00075    * a list off all event observers interested in it and which events they are
00076    * interested in.
00077  */
00078   class EventObserverList
00079   {
00080 
00081   public:
00082     typedef std::multimap<uint32_t, EventObserver *> ObserverMap;
00083 
00084   private:
00085     /* A list of lists indexed by event type. */
00086     std::vector<ObserverMap *> event_observer_lists;
00087 
00088   public:
00089 
00090     EventObserverList()
00091     {
00092       // Initialize the list with NULL pointers.
00093       event_observer_lists.assign(EventObserver::MAX_EVENT_COUNT, NULL);
00094     }
00095 
00096     ~EventObserverList()
00097     {
00098       std::for_each(event_observer_lists.begin(),
00099                     event_observer_lists.end(),
00100                     DeletePtr());
00101       event_observer_lists.clear();
00102     }
00103 
00104     /* Add the observer to the observer list for the even, positioning it if required.
00105      *
00106      * Note: Event observers are storted in a multimap object so that the order in which
00107      * they are called can be sorted based on the requested position. Lookups are never done
00108      * on the multimap, once filled it is used as a vector.
00109    */
00110     void addObserver(EventObserver *eventObserver, enum EventObserver::EventType event, int32_t position)
00111     {
00112       uint32_t event_pos;
00113       ObserverMap *observers;
00114 
00115       observers= event_observer_lists[event];
00116       if (observers == NULL) 
00117       {
00118         observers= new ObserverMap();
00119         event_observer_lists[event]= observers;
00120       }
00121 
00122       if (position == 0)
00123         event_pos= INT32_MAX; // Set the event position to be in the middle.
00124       else
00125         event_pos= (uint32_t) position;
00126 
00127       /* If positioned then check if the position is already taken. */
00128       if (position) 
00129       {
00130         if (observers->count(event_pos))
00131         {
00132           errmsg_printf(error::WARN,
00133                         _("EventObserverList::addEventObserver() Duplicate event position %d for event '%s' from EventObserver plugin '%s'"),
00134                         position,
00135                         EventObserver::eventName(event), 
00136                         eventObserver->getName().c_str());
00137         }
00138       }
00139 
00140       observers->insert(std::pair<uint32_t, EventObserver *>(event_pos, eventObserver) );
00141     }
00142 
00143 
00144     /* Get the observer list for an event type. Will return NULL if no observer exists.*/
00145     ObserverMap *getObservers(enum EventObserver::EventType event)
00146     {
00147       return event_observer_lists[event];
00148     }
00149   };
00150 
00151 
00152   //---------
00153   /* registerEvent() is called from the event observer plugins to add themselves to
00154    * the event observer list to be notified when the specified event takes place.
00155    */ 
00156   void EventObserver::registerEvent(EventObserverList &observers, EventType event, int32_t position)
00157   {
00158     observers.addObserver(this, event, position);
00159   }
00160 
00161   /*========================================================*/
00162   /*              Table Event Observer handling:           */
00163   /*========================================================*/
00164 
00165   //----------
00166   /* For each EventObserver plugin call its registerTableEventsDo() meathod so that it can
00167    * register what events, if any, it is interested in on this table.
00168    */ 
00169   class RegisterTableEventsIterate : public std::unary_function<EventObserver *, void>
00170   {
00171     TableShare &table_share;
00172     EventObserverList &observers;
00173 
00174   public:
00175     RegisterTableEventsIterate(TableShare &table_share_arg, EventObserverList &observers_arg): 
00176       table_share(table_share_arg), observers(observers_arg) {}
00177     inline result_type operator() (argument_type eventObserver)
00178     {
00179       eventObserver->registerTableEventsDo(table_share, observers);
00180     }
00181   };
00182 
00183   //----------
00184   /* 
00185    * registerTableEvents() is called by drizzle to register all plugins that
00186    * may be interested in table events on the newly created TableShare object.
00187    */ 
00188   void EventObserver::registerTableEvents(TableShare &table_share)
00189   {
00190     if (all_event_plugins.empty())
00191       return;
00192 
00193     EventObserverList *observers;
00194 
00195     observers= table_share.getTableObservers();
00196 
00197     if (observers != NULL) 
00198     {
00199       errmsg_printf(error::WARN,
00200                   _("EventObserver::registerTableEvents(): Table already has events registered on it: probable programming error."));
00201       table_share.setTableObservers(NULL);
00202       delete observers;
00203     }
00204 
00205     observers= new EventObserverList();
00206     table_share.setTableObservers(observers);
00207  
00208 
00209     std::for_each(all_event_plugins.begin(), all_event_plugins.end(),
00210                   RegisterTableEventsIterate(table_share, *observers));
00211 
00212   }
00213 
00214   //----------
00215   /* Cleanup before freeing the TableShare object. */
00216   void EventObserver::deregisterTableEvents(TableShare &table_share)
00217   {
00218    if (all_event_plugins.empty())
00219       return;
00220 
00221     EventObserverList *observers;
00222 
00223     observers= table_share.getTableObservers();
00224 
00225     if (observers) 
00226     {
00227       table_share.setTableObservers(NULL);
00228       delete observers;
00229     }
00230   }
00231 
00232 
00233   /*========================================================*/
00234   /*              Schema Event Observer handling:           */
00235   /*========================================================*/
00236 
00237   //----------
00238   /* For each EventObserver plugin call its registerSchemaEventsDo() meathod so that it can
00239    * register what events, if any, it is interested in on the schema.
00240    */ 
00241   class RegisterSchemaEventsIterate : public std::unary_function<EventObserver *, void>
00242   {
00243     const std::string &db;
00244     EventObserverList &observers;
00245   public:
00246     RegisterSchemaEventsIterate(const std::string &db_arg, EventObserverList &observers_arg) :     
00247       db(db_arg),
00248       observers(observers_arg){}
00249 
00250     inline result_type operator() (argument_type eventObserver)
00251     {
00252       eventObserver->registerSchemaEventsDo(db, observers);
00253     }
00254   };
00255 
00256   //----------
00257   /* 
00258    * registerSchemaEvents() is called by drizzle to register all plugins that
00259    * may be interested in schema events on the database.
00260    */ 
00261   void EventObserver::registerSchemaEvents(Session &session, const std::string &db)
00262   {
00263     if (all_event_plugins.empty())
00264       return;
00265 
00266     EventObserverList *observers;
00267 
00268     observers= session.getSchemaObservers(db);
00269 
00270     if (observers == NULL) 
00271     {
00272       observers= new EventObserverList();
00273       session.setSchemaObservers(db, observers);
00274    }
00275 
00276     std::for_each(all_event_plugins.begin(), all_event_plugins.end(),
00277                   RegisterSchemaEventsIterate(db, *observers));
00278 
00279   }
00280 
00281   //----------
00282   /* Cleanup before freeing the Session object. */
00283   void EventObserver::deregisterSchemaEvents(EventObserverList *observers)
00284   {
00285       delete observers;
00286    }
00287 
00288   /*========================================================*/
00289   /*             Session Event Observer handling:           */
00290   /*========================================================*/
00291 
00292   //----------
00293   /* For each EventObserver plugin call its registerSessionEventsDo() meathod so that it can
00294    * register what events, if any, it is interested in on this session.
00295    */ 
00296   class RegisterSessionEventsIterate : public std::unary_function<EventObserver *, void>
00297   {
00298     Session &session;
00299     EventObserverList &observers;
00300   public:
00301     RegisterSessionEventsIterate(Session &session_arg, EventObserverList &observers_arg) : 
00302       session(session_arg), observers(observers_arg) {}
00303     inline result_type operator() (argument_type eventObserver)
00304     {
00305       eventObserver->registerSessionEventsDo(session, observers);
00306     }
00307   };
00308 
00309   //----------
00310   /* 
00311    * registerSessionEvents() is called by drizzle to register all plugins that
00312    * may be interested in session events on the newly created session.
00313    */ 
00314   void EventObserver::registerSessionEvents(Session &session)
00315   {
00316     if (all_event_plugins.empty())
00317       return;
00318 
00319     EventObserverList *observers;
00320 
00321     observers= session.getSessionObservers();
00322     if (observers) { // This should not happed
00323       errmsg_printf(error::WARN,
00324                   _("EventObserver::registerSessionEvents(): Session already has events registered on it: probable programming error."));
00325       session.setSessionObservers(NULL);
00326       delete observers;
00327     }
00328 
00329   observers= new EventObserverList();
00330   session.setSessionObservers(observers);
00331 
00332   std::for_each(all_event_plugins.begin(), all_event_plugins.end(),
00333                 RegisterSessionEventsIterate(session, *observers));
00334 
00335   }
00336 
00337   //----------
00338   /* Cleanup before freeing the session object. */
00339   void EventObserver::deregisterSessionEvents(EventObserverList *observers)
00340   {
00341       delete observers;
00342   }
00343 
00344 
00345   /* Event observer list iterator: */
00346   //----------
00347   class EventIterate : public std::unary_function<std::pair<uint32_t, EventObserver *>, bool>
00348   {
00349     EventData &data;
00350 
00351   public:
00352     EventIterate(EventData &data_arg) :
00353       std::unary_function<std::pair<uint32_t, EventObserver *>, bool>(),
00354       data(data_arg)
00355     {}
00356 
00357     inline result_type operator()(argument_type handler)
00358     {
00359       bool result= handler.second->observeEventDo(data);
00360       if (result)
00361       {
00362         /* TRANSLATORS: The leading word "EventObserver" is the name
00363           of the plugin api, and so should not be translated. */
00364         errmsg_printf(error::ERROR,
00365                       _("EventIterate event handler '%s' failed for event '%s'"),
00366                       handler.second->getName().c_str(), handler.second->eventName(data.event));
00367 
00368       }
00369       return result;
00370     }
00371   };
00372 
00373 
00374   /*==========================================================*/
00375   /* Generic meathods called by drizzle to notify all interested  
00376    * plugins of an event,
00377  */
00378 
00379   // Call all event observers interested in the event.
00380   bool EventData::callEventObservers()
00381   {
00382     EventObserverList::ObserverMap *eventObservers;
00383 
00384     if (observerList == NULL)
00385       return false; // Nobody was interested in the event. :(
00386 
00387     eventObservers = observerList->getObservers(event);
00388 
00389     if (eventObservers == NULL)
00390       return false; // Nobody was interested in the event. :(
00391 
00392     /* Use find_if instead of foreach so that we can collect return codes */
00393     EventObserverList::ObserverMap::iterator iter=
00394       std::find_if(eventObservers->begin(), eventObservers->end(),
00395                    EventIterate(*this)); 
00396     /* If iter is == end() here, that means that all of the plugins returned
00397      * false, which in this case means they all succeeded. Since we want to 
00398      * return false on success, we return the value of the two being !=.
00399    */
00400     return iter != eventObservers->end();
00401   }
00402 
00403   //--------
00404   bool SessionEventData::callEventObservers()
00405   {
00406     observerList= session.getSessionObservers();
00407 
00408     return EventData::callEventObservers();
00409   }
00410 
00411   bool SessionEventData::hasEvents(Session &in_session)
00412   {
00413     return (in_session.getSessionObservers() != NULL);
00414   }
00415 
00416   //--------
00417   bool SchemaEventData::callEventObservers()
00418   {
00419     observerList= session.getSchemaObservers(db);
00420     if (!observerList) 
00421     {
00422       EventObserver::registerSchemaEvents(session, db);
00423       observerList= session.getSchemaObservers(db);
00424     }
00425 
00426     return EventData::callEventObservers();
00427   }
00428 
00429   //--------
00430   bool TableEventData::callEventObservers()
00431   {
00432     observerList= table.getMutableShare()->getTableObservers();
00433 
00434     return EventData::callEventObservers();
00435   }
00436 
00437   bool TableEventData::hasEvents(Table &in_table)
00438   {
00439     return (in_table.getMutableShare()->getTableObservers() != NULL);
00440   }
00441 
00442   /*==========================================================*/
00443   /* Static meathods called by drizzle to notify interested plugins 
00444    * of a schema event.
00445  */
00446   bool EventObserver::beforeDropTable(Session &session, const drizzled::identifier::Table &table)
00447   {
00448     if (all_event_plugins.empty())
00449       return false;
00450 
00451     BeforeDropTableEventData eventData(session, table);
00452     return eventData.callEventObservers();
00453   }
00454 
00455   bool EventObserver::afterDropTable(Session &session, const drizzled::identifier::Table &table, int err)
00456   {
00457     if (all_event_plugins.empty())
00458       return false;
00459 
00460     AfterDropTableEventData eventData(session, table, err);
00461     return eventData.callEventObservers();
00462   }
00463 
00464   bool EventObserver::beforeRenameTable(Session &session, const drizzled::identifier::Table &from, const drizzled::identifier::Table &to)
00465   {
00466     if (all_event_plugins.empty())
00467       return false;
00468 
00469     BeforeRenameTableEventData eventData(session, from, to);
00470     return eventData.callEventObservers();
00471   }
00472 
00473   bool EventObserver::afterRenameTable(Session &session, const drizzled::identifier::Table &from, const drizzled::identifier::Table &to, int err)
00474   {
00475     if (all_event_plugins.empty())
00476       return false;
00477 
00478     AfterRenameTableEventData eventData(session, from, to, err);
00479     return eventData.callEventObservers();
00480   }
00481 
00482   /*==========================================================*/
00483   /* Static meathods called by drizzle to notify interested plugins 
00484    * of a table event.
00485    *
00486    * A quick test is done first to see if there are any interested observers.
00487  */
00488   bool EventObserver::beforeInsertRecord(Table &table, unsigned char *buf)
00489   {
00490     if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
00491       return false;
00492 
00493     BeforeInsertRecordEventData eventData(*(table.in_use), table, buf);
00494     return eventData.callEventObservers();
00495   }
00496 
00497   bool EventObserver::afterInsertRecord(Table &table, const unsigned char *buf, int err)
00498   {
00499     if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
00500       return false;
00501 
00502     AfterInsertRecordEventData eventData(*(table.in_use), table, buf, err);
00503     return eventData.callEventObservers();
00504   }
00505 
00506   bool EventObserver::beforeDeleteRecord(Table &table, const unsigned char *buf)
00507   {
00508     if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
00509       return false;
00510 
00511     BeforeDeleteRecordEventData eventData(*(table.in_use), table, buf);
00512     return eventData.callEventObservers();
00513   }
00514 
00515   bool EventObserver::afterDeleteRecord(Table &table, const unsigned char *buf, int err)
00516   {
00517     if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
00518       return false;
00519 
00520     AfterDeleteRecordEventData eventData(*(table.in_use), table, buf, err);
00521     return eventData.callEventObservers();
00522   }
00523 
00524   bool EventObserver::beforeUpdateRecord(Table &table, const unsigned char *old_data, unsigned char *new_data)
00525   {
00526     if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
00527       return false;
00528 
00529     BeforeUpdateRecordEventData eventData(*(table.in_use), table, old_data, new_data);
00530     return eventData.callEventObservers();
00531   }
00532 
00533   bool EventObserver::afterUpdateRecord(Table &table, const unsigned char *old_data, unsigned char *new_data, int err)
00534   {
00535     if (all_event_plugins.empty() || !TableEventData::hasEvents(table))
00536       return false;
00537 
00538     AfterUpdateRecordEventData eventData(*(table.in_use), table, old_data, new_data, err);
00539     return eventData.callEventObservers();
00540   }
00541 
00542   /*==========================================================*/
00543   /* Static meathods called by drizzle to notify interested plugins 
00544    * of a session event.
00545    *
00546    * A quick test is done first to see if there are any interested observers.
00547 */
00548   bool EventObserver::beforeCreateDatabase(Session &session, const std::string &db)
00549   {
00550     if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
00551       return false;
00552 
00553     BeforeCreateDatabaseEventData eventData(session, db);
00554     return eventData.callEventObservers();
00555   }
00556 
00557   bool EventObserver::afterCreateDatabase(Session &session, const std::string &db, int err)
00558   {
00559     if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
00560       return false;
00561 
00562     AfterCreateDatabaseEventData eventData(session, db, err);
00563     return eventData.callEventObservers();
00564   }
00565 
00566   bool EventObserver::beforeDropDatabase(Session &session, const std::string &db)
00567   {
00568     if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
00569       return false;
00570 
00571     BeforeDropDatabaseEventData eventData(session, db);
00572     return eventData.callEventObservers();
00573   }
00574 
00575   bool EventObserver::afterDropDatabase(Session &session, const std::string &db, int err)
00576   {
00577     if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
00578       return false;
00579 
00580     AfterDropDatabaseEventData eventData(session, db, err);
00581     return eventData.callEventObservers();
00582   }
00583 
00584   bool EventObserver::connectSession(Session &session)
00585   {
00586     if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
00587       return false;
00588 
00589     ConnectSessionEventData eventData(session);
00590     return eventData.callEventObservers();
00591   }
00592 
00593   bool EventObserver::disconnectSession(Session &session)
00594   {
00595     if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
00596       return false;
00597 
00598     DisconnectSessionEventData eventData(session);
00599     return eventData.callEventObservers();
00600   }
00601 
00602   bool EventObserver::beforeStatement(Session &session)
00603   {
00604     if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
00605       return false;
00606 
00607     BeforeStatementEventData eventData(session);
00608     return eventData.callEventObservers();
00609   }
00610 
00611   bool EventObserver::afterStatement(Session &session)
00612   {
00613     if (all_event_plugins.empty() || !SessionEventData::hasEvents(session))
00614       return false;
00615 
00616     AfterStatementEventData eventData(session);
00617     return eventData.callEventObservers();
00618   }
00619 
00620 
00621 } /* namespace plugin */
00622 } /* namespace drizzled */