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