List:Commits« Previous MessageNext Message »
From:ahristov Date:September 6 2006 2:48pm
Subject:bk commit into 5.1 tree (andrey:1.2291)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of andrey. When andrey does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2006-09-06 16:48:18+02:00, andrey@stripped +9 -0
  WL#3337 (Event scheduler new architecture)
  
  Post-review fix for removing dependency of Event_queue on
  Event_db_repository. This introduces few new classes :
  - Event_worker_thread
  - Event_queue_element_for_exec
  
  This patch fixes a problem with race condition in 
  Event_queue::get_top_element_if_time() when the latter was
  dropping an event, which had to be dropped.

  sql/event_data_objects.cc@stripped, 2006-09-06 16:48:12+02:00, andrey@stripped +47 -29
    Introduced a new class Event_queue_element_for_exec
    According to Konstantin it should be named Event_name and hold
    only two LEX_STRINGs but `dropped` is not saved on disk and will
    require additional logic in Event_worker_thread class, after loading
    to compute whether the event should be dropped or not. It's easier
    just to pass this flag around.
    
    Removed Event_queue_element::drop(). This method was a source of a
    race condition. At the place where the event should be dropped we
    call Events::drop_event() which is the only code-flow for dropping.
    In addition, because ::drop_event() holds Events::LOCK_metadata there is
    no source of race conditions. Before this patch dropping from ::drop()
    wasn't under LOCK_metadata and races were possible.
    
    Because Events::open_event_table was removed as a method, provisionally
    events_event_db_repository was exported from events.cc till a solution is
    build where Event_queue_element does not access directly mysql.event.
    This will appear as a part of an additional patch.

  sql/event_data_objects.h@stripped, 2006-09-06 16:48:12+02:00, andrey@stripped +21 -4
    New class Event_queue_element_for_exec added which is returned
    from Event_queue::get_top_if_time() and passed through Event_scheduler
    to Event_worker_thread. There by using the (db)name Event_job_data is
    instanciated and executed.
    
    Dropped Event_queue_element::drop()
    
    thd was moved out of Event_job_data as it is now part of
    Event_queue_element_for_exec

  sql/event_queue.cc@stripped, 2006-09-06 16:48:12+02:00, andrey@stripped +21 -39
    Removed dependency of Event_queue on Event_db_repository.
    The instantiation of Event_job_data was moved to class Event_worker_thread
    In place is a return of an object of Event_queue_element_for_exec is used
    later for instantiating Event_job_data.
    
    The `dropped` flag of Event_queue_element is passed over
    Event_queue_element_for_exec to the code in Event_worker_thread.

  sql/event_queue.h@stripped, 2006-09-06 16:48:12+02:00, andrey@stripped +5 -10
    Removed dependency of Event_queue on Event_db_repository
    Removed dependency on Event_scheduler

  sql/event_scheduler.cc@stripped, 2006-09-06 16:48:12+02:00, andrey@stripped +101 -44
    Added class Event_worker_thread, which is used during
    the execution of an event. It has a static init() method
    to get a pointer to Event_db_repository to be used for
    instantiation of Event_job_data object. This object it then
    executed.

  sql/event_scheduler.h@stripped, 2006-09-06 16:48:12+02:00, andrey@stripped +27 -2
    Added class Event_worker_thread, which is used during
    the execution of an event.

  sql/events.cc@stripped, 2006-09-06 16:48:13+02:00, andrey@stripped +5 -35
    Removed Events::open_event_table() because it was  a product of
    a bad architecture.
    
    Not initializing the Event queue with Event_db_repository object
    as the dependency was removed.

  sql/events.h@stripped, 2006-09-06 16:48:13+02:00, andrey@stripped +1 -12
    Removed friend definition, unneeded.
    
    Fixed Events::drop_event() to have the previous signature without
    bool only_from_disk

  sql/sql_parse.cc@stripped, 2006-09-06 16:48:13+02:00, andrey@stripped +1 -2
    Fix call

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	andrey
# Host:	example.com
# Root:	/work/mysql-5.1-runtime-wl3337

--- 1.572/sql/sql_parse.cc	2006-09-06 16:48:28 +02:00
+++ 1.573/sql/sql_parse.cc	2006-09-06 16:48:28 +02:00
@@ -3954,8 +3954,7 @@ end_with_restore_list:
       if (!(res= Events::get_instance()->drop_event(thd,
                                                     lex->spname->m_db,
                                                     lex->spname->m_name,
-                                                    lex->drop_if_exists,
-                                                    FALSE)))
+                                                    lex->drop_if_exists)))
         send_ok(thd);
     }
     break;

--- 1.65/sql/events.cc	2006-09-06 16:48:28 +02:00
+++ 1.66/sql/events.cc	2006-09-06 16:48:28 +02:00
@@ -98,7 +98,7 @@ Event_queue events_event_queue;
 static
 Event_scheduler events_event_scheduler;
 
-static
+
 Event_db_repository events_event_db_repository;
 
 Events Events::singleton;
@@ -297,29 +297,6 @@ Events::Events()
 
 
 /*
-  Opens mysql.event table with specified lock
-
-  SYNOPSIS
-    Events::open_event_table()
-    thd         Thread context
-    lock_type   How to lock the table
-    table       We will store the open table here
-
-  RETURN VALUE
-    1   Cannot lock table
-    2   The table is corrupted - different number of fields
-    0   OK
-*/
-
-int
-Events::open_event_table(THD *thd, enum thr_lock_type lock_type,
-                         TABLE **table)
-{
-  return db_repository->open_event_table(thd, lock_type, table);
-}
-
-
-/*
   The function exported to the world for creating of events.
 
   SYNOPSIS
@@ -441,10 +418,6 @@ Events::update_event(THD *thd, Event_par
       name            [in]  Event's name
       if_exists       [in]  When set and the event does not exist =>
                             warning onto the stack
-      only_from_disk  [in]  Whether to remove the event from the queue too.
-                            In case of Event_job_data::drop() it's needed to
-                            do only disk drop because Event_queue will handle
-                            removal from memory queue.
 
   RETURN VALUE
     FALSE  OK
@@ -452,8 +425,7 @@ Events::update_event(THD *thd, Event_par
 */
 
 bool
-Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists,
-                   bool only_from_disk)
+Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
 {
   int ret;
   DBUG_ENTER("Events::drop_event");
@@ -466,10 +438,7 @@ Events::drop_event(THD *thd, LEX_STRING 
   pthread_mutex_lock(&LOCK_event_metadata);
   /* On error conditions my_error() is called so no need to handle here */
   if (!(ret= db_repository->drop_event(thd, dbname, name, if_exists)))
-  {
-    if (!only_from_disk)
-      event_queue->drop_event(thd, dbname, name);
-  }
+    event_queue->drop_event(thd, dbname, name);
   pthread_mutex_unlock(&LOCK_event_metadata);
   DBUG_RETURN(ret);
 }
@@ -673,7 +642,7 @@ Events::init()
   }
   check_system_tables_error= FALSE;
 
-  if (event_queue->init_queue(thd, db_repository) || load_events_from_db(thd))
+  if (event_queue->init_queue(thd) || load_events_from_db(thd))
   {
     sql_print_error("SCHEDULER: Error while loading from disk.");
     goto end;
@@ -686,6 +655,7 @@ Events::init()
   if (opt_event_scheduler == Events::EVENTS_ON)
     res= scheduler->start();
 
+  Event_worker_thread::init(this, db_repository);
 end:
   delete thd;
   /* Remember that we don't have a THD */

--- 1.47/sql/events.h	2006-09-06 16:48:28 +02:00
+++ 1.48/sql/events.h	2006-09-06 16:48:28 +02:00
@@ -42,13 +42,6 @@ sortcmp_lex_string(LEX_STRING s, LEX_STR
 class Events
 {
 public:
-  /*
-    Quite NOT the best practice and will be removed once
-    Event_timed::drop() and Event_timed is fixed not do drop directly
-    or other scheme will be found.
-  */
-  friend class Event_queue_element;
-  
   /* The order should match the order in opt_typelib */
   enum enum_opt_event_scheduler
   {
@@ -92,14 +85,10 @@ public:
   update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to);
 
   bool
-  drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists,
-             bool only_from_disk);
+  drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists);
 
   void
   drop_schema_events(THD *thd, char *db);
-
-  int
-  open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
 
   bool
   show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name);

--- 1.15/sql/event_queue.cc	2006-09-06 16:48:28 +02:00
+++ 1.16/sql/event_queue.cc	2006-09-06 16:48:28 +02:00
@@ -17,7 +17,6 @@
 #include "mysql_priv.h"
 #include "event_queue.h"
 #include "event_data_objects.h"
-#include "event_db_repository.h"
 
 
 #define EVENT_QUEUE_INITIAL_SIZE 30
@@ -135,7 +134,7 @@ Event_queue::deinit_mutexes()
 */
 
 bool
-Event_queue::init_queue(THD *thd, Event_db_repository *db_repo)
+Event_queue::init_queue(THD *thd)
 {
   struct event_queue_param *event_queue_param_value= NULL;
 
@@ -143,7 +142,6 @@ Event_queue::init_queue(THD *thd, Event_
   DBUG_PRINT("enter", ("this=0x%lx", this));
 
   LOCK_QUEUE_DATA();
-  db_repository= db_repo;
 
   if (init_queue_ex(&queue, EVENT_QUEUE_INITIAL_SIZE , 0 /*offset*/,
                     0 /*max_on_top*/, event_queue_element_compare_q,
@@ -289,7 +287,7 @@ void
 Event_queue::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
 {
   DBUG_ENTER("Event_queue::drop_event");
-  DBUG_PRINT("enter", ("thd=0x%lx db=%s name=%s", thd, dbname, name));
+  DBUG_PRINT("enter", ("thd=0x%lx db=%s name=%s", thd, dbname.str, name.str));
 
   LOCK_QUEUE_DATA();
   find_n_remove_event(dbname, name);
@@ -470,7 +468,7 @@ Event_queue::empty_queue()
 {
   uint i;
   DBUG_ENTER("Event_queue::empty_queue");
-  DBUG_PRINT("enter", ("Purging the queue. %d element(s)", queue.elements));
+  DBUG_PRINT("enter", ("Purging the queue. %u element(s)", queue.elements));
   sql_print_information("SCHEDULER: Purging queue. %u events", queue.elements);
   /* empty the queue */
   for (i= 0; i < queue.elements; ++i)
@@ -527,35 +525,29 @@ static const char *queue_wait_msg= "Wait
 
   SYNOPSIS
     Event_queue::get_top_for_execution_if_time()
-      thd      [in]  Thread
-      now      [in]  Current timestamp
-      job_data [out] The object to execute
-      abstime  [out] Time to sleep
+      thd        [in]  Thread
+      now        [in]  Current timestamp
+      event_name [out] The object to execute
 
   RETURN VALUE
-    FALSE  No error. If *job_data==NULL then top not elligible for execution.
-           Could be that there is no top. If abstime->tv_sec is set to value
-           greater than zero then use abstime with pthread_cond_timedwait().
-           If abstime->tv_sec is zero then sleep with pthread_cond_wait().
-           abstime->tv_nsec is always zero.
-    TRUE   Error
-    
+    FALSE  No error. event_name != NULL
+    TRUE   Serious error
 */
 
 bool
-Event_queue::get_top_for_execution_if_time(THD *thd, Event_job_data **job_data)
+Event_queue::get_top_for_execution_if_time(THD *thd,
+                Event_queue_element_for_exec **event_name)
 {
   bool ret= FALSE;
   struct timespec top_time;
   struct timespec *abstime;
-  *job_data= NULL;
+  *event_name= NULL;
   DBUG_ENTER("Event_queue::get_top_for_execution_if_time");
 
   top_time.tv_nsec= 0;
   LOCK_QUEUE_DATA();
   for (;;)
   {
-    int res;
     Event_queue_element *top= NULL;
 
     thd->end_time();
@@ -598,39 +590,29 @@ Event_queue::get_top_for_execution_if_ti
       continue;
     }
 
-    DBUG_PRINT("info", ("Ready for execution"));
-    if (!(*job_data= new Event_job_data()))
-    {
-      ret= TRUE;
-      break;
-    }
-    if ((res= db_repository->load_named_event(thd, top->dbname, top->name,
-                                              *job_data)))
+    if (!(*event_name= new Event_queue_element_for_exec()) ||
+        (*event_name)->init(top->dbname, top->name))
     {
-      DBUG_PRINT("error", ("Got %d from load_named_event", res));
-      delete *job_data;
-      *job_data= NULL;
       ret= TRUE;
       break;
     }
 
+    DBUG_PRINT("info", ("Ready for execution"));
     top->mark_last_executed(thd);
     if (top->compute_next_execution_time())
       top->status= Event_queue_element::DISABLED;
     DBUG_PRINT("info", ("event %s status is %d", top->name.str, top->status));
 
-    (*job_data)->execution_count= top->execution_count;
+    top->execution_count++;
+    (*event_name)->dropped= top->dropped;
 
     top->update_timing_fields(thd);
-    if (((top->execute_at.year && !top->expression) || top->execute_at_null) ||
-        (top->status == Event_queue_element::DISABLED))
+    if (top->status == Event_queue_element::DISABLED)
     {
       DBUG_PRINT("info", ("removing from the queue"));
       sql_print_information("SCHEDULER: Last execution of %s.%s. %s",
                             top->dbname.str, top->name.str,
                             top->dropped? "Dropping.":"");
-      if (top->dropped)
-        top->drop(thd);
       delete top;
       queue_remove(&queue, 0);
     }
@@ -644,11 +626,11 @@ end:
   UNLOCK_QUEUE_DATA();
   
   DBUG_PRINT("info", ("returning %d. et_new=0x%lx abstime.tv_sec=%d ",
-             ret, *job_data, abstime? abstime->tv_sec:0));
+             ret, *event_name, abstime? abstime->tv_sec:0));
 
-  if (*job_data)
-    DBUG_PRINT("info", ("db=%s  name=%s definer=%s", (*job_data)->dbname.str,
-               (*job_data)->name.str, (*job_data)->definer.str));
+  if (*event_name)
+    DBUG_PRINT("info", ("db=%s  name=%s", (*event_name)->dbname.str,
+               (*event_name)->name.str));
 
   DBUG_RETURN(ret);
 }

--- 1.12/sql/event_queue.h	2006-09-06 16:48:28 +02:00
+++ 1.13/sql/event_queue.h	2006-09-06 16:48:28 +02:00
@@ -17,12 +17,10 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 class Event_basic;
-class Event_db_repository;
-class Event_job_data;
 class Event_queue_element;
+class Event_queue_element_for_exec;
 
 class THD;
-class Event_scheduler;
 
 class Event_queue
 {
@@ -36,7 +34,7 @@ public:
   deinit_mutexes();
 
   bool
-  init_queue(THD *thd, Event_db_repository *db_repo);
+  init_queue(THD *thd);
   
   void
   deinit_queue();
@@ -60,7 +58,8 @@ public:
   recalculate_activation_times(THD *thd);
 
   bool
-  get_top_for_execution_if_time(THD *thd, Event_job_data **job_data);
+  get_top_for_execution_if_time(THD *thd,
+                                Event_queue_element_for_exec **event_name);
 
   bool
   dump_internal_status(THD *thd);
@@ -84,11 +83,7 @@ protected:
   pthread_mutex_t LOCK_event_queue;
   pthread_cond_t COND_queue_state;
 
-  Event_db_repository *db_repository;
-
-  Event_scheduler *scheduler;
-
-  /* The sorted queue with the Event_job_data objects */
+  /* The sorted queue with the Event_queue_element objects */
   QUEUE queue;
 
   TIME next_activation_at;

--- 1.27/sql/event_scheduler.cc	2006-09-06 16:48:28 +02:00
+++ 1.28/sql/event_scheduler.cc	2006-09-06 16:48:28 +02:00
@@ -19,6 +19,7 @@
 #include "event_data_objects.h"
 #include "event_scheduler.h"
 #include "event_queue.h"
+#include "event_db_repository.h"
 
 #ifdef __GNUC__
 #if __GNUC__ >= 2
@@ -35,6 +36,11 @@
 
 extern pthread_attr_t connection_attrib;
 
+
+Event_db_repository *Event_worker_thread::db_repository;
+Events *Event_worker_thread::events_facade;
+
+
 static
 const LEX_STRING scheduler_states_names[] =
 {
@@ -61,8 +67,8 @@ struct scheduler_param {
       et   The event itself
 */
 
-static void
-evex_print_warnings(THD *thd, Event_job_data *et)
+void
+Event_worker_thread::print_warnings(THD *thd, Event_job_data *et)
 {
   MYSQL_ERROR *err;
   DBUG_ENTER("evex_print_warnings");
@@ -254,48 +260,99 @@ event_worker_thread(void *arg)
 {
   /* needs to be first for thread_stack */
   THD *thd; 
-  Event_job_data *event= (Event_job_data *)arg;
-  int ret;
+  Event_queue_element_for_exec *event= (Event_queue_element_for_exec *)arg;
 
   thd= event->thd;
-
   thd->thread_stack= (char *) &thd;             // remember where our stack is
-  DBUG_ENTER("event_worker_thread");
 
-  if (!post_init_event_thread(thd))
+  Event_worker_thread worker_thread;
+  worker_thread.run(thd, (Event_queue_element_for_exec *)arg);
+
+  deinit_event_thread(thd);
+
+  return 0;                                     // Can't return anything here
+}
+
+
+/*
+  Function that executes an event in a child thread. Setups the 
+  environment for the event execution and cleans after that.
+
+  SYNOPSIS
+    Event_worker_thread::run()
+      thd    Thread context
+      event  The Event_queue_element_for_exec object to be processed
+*/
+
+void
+Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event)
+{
+  int ret;
+  Event_job_data *job_data= NULL;
+  DBUG_ENTER("Event_worker_thread::run");
+  DBUG_PRINT("info", ("Baikonur, time is %d, BURAN reporting and operational."
+             "THD=0x%lx", time(NULL), thd));
+
+  if (post_init_event_thread(thd))
+    goto end;
+
+  if (!(job_data= new Event_job_data()))
+    goto end;
+  else if ((ret= db_repository->
+                  load_named_event(thd, event->dbname, event->name, job_data)))
   {
-    DBUG_PRINT("info", ("Baikonur, time is %d, BURAN reporting and operational."
-               "THD=0x%lx", time(NULL), thd));
+    DBUG_PRINT("error", ("Got %d from load_named_event", ret));
+    goto end;
+  }
+
+  sql_print_information("SCHEDULER: [%s.%s of %s] executing in thread %lu. ",
+                        job_data->dbname.str, job_data->name.str,
+                        job_data->definer.str, thd->thread_id);
+
+  thd->enable_slow_log= TRUE;
+
+  ret= job_data->execute(thd);
+
+  print_warnings(thd, job_data);
+
+  sql_print_information("SCHEDULER: [%s.%s of %s] executed in thread %lu. "
+                        "RetCode=%d", job_data->dbname.str, job_data->name.str,
+                        job_data->definer.str, thd->thread_id, ret);
+  if (ret == EVEX_COMPILE_ERROR)
+    sql_print_information("SCHEDULER: COMPILE ERROR for event %s.%s of %s",
+                          job_data->dbname.str, job_data->name.str,
+                          job_data->definer.str);
+  else if (ret == EVEX_MICROSECOND_UNSUP)
+    sql_print_information("SCHEDULER: MICROSECOND is not supported");
 
-    sql_print_information("SCHEDULER: [%s.%s of %s] executing in thread %lu. "
-                          "Execution %u",
-                          event->dbname.str, event->name.str,
-                          event->definer.str, thd->thread_id,
-                          event->execution_count);
-
-    thd->enable_slow_log= TRUE;
-
-    ret= event->execute(thd);
-
-    evex_print_warnings(thd, event);
-
-    sql_print_information("SCHEDULER: [%s.%s of %s] executed in thread %lu. "
-                          "RetCode=%d", event->dbname.str, event->name.str,
-                          event->definer.str, thd->thread_id, ret);
-    if (ret == EVEX_COMPILE_ERROR)
-      sql_print_information("SCHEDULER: COMPILE ERROR for event %s.%s of %s",
-                            event->dbname.str, event->name.str,
-                            event->definer.str);
-    else if (ret == EVEX_MICROSECOND_UNSUP)
-      sql_print_information("SCHEDULER: MICROSECOND is not supported");
+end:
+  delete job_data;
+
+  if (event->dropped)
+  {
+    sql_print_information("SCHEDULER: Dropping %s.%s", event->dbname.str,
+                          event->name.str);
+    /*
+      Using db_repository can lead to a race condition because we access
+      the table without holding LOCK_metadata.
+      Scenario:
+      1. CREATE EVENT xyz AT ...    (conn thread)
+      2. execute xyz                (worker)
+      3. CREATE EVENT XYZ EVERY ... (conn thread)
+      4. drop xyz                   (worker)
+      5. XYZ was just created on disk but `drop xyz` of the worker dropped it.
+         A consequent load to create Event_queue_element will fail.
+
+      If all operations are performed under LOCK_metadata there is no such
+      problem. However, this comes at the price of introduction bi-directional
+      association between class Events and class Event_worker_thread.
+    */
+    events_facade->drop_event(thd, event->dbname, event->name, FALSE);
   }
   DBUG_PRINT("info", ("BURAN %s.%s is landing!", event->dbname.str,
              event->name.str));
-  delete event;
 
-  deinit_event_thread(thd);
-
-  DBUG_RETURN(0);                               // Can't return anything here
+  delete event;
 }
 
 
@@ -453,20 +510,20 @@ Event_scheduler::run(THD *thd)
 
   while (is_running())
   {
-    Event_job_data *job_data;
+    Event_queue_element_for_exec *event_name;
 
     /* Gets a minimized version */
-    if (queue->get_top_for_execution_if_time(thd, &job_data))
+    if (queue->get_top_for_execution_if_time(thd, &event_name))
     {
       sql_print_information("SCHEDULER: Serious error during getting next "
                             "event to execute. Stopping");
       break;
     }
 
-    DBUG_PRINT("info", ("get_top returned job_data=0x%lx", job_data));
-    if (job_data)
+    DBUG_PRINT("info", ("get_top returned job_data=0x%lx", event_name));
+    if (event_name)
     {
-      if ((res= execute_top(thd, job_data)))
+      if ((res= execute_top(thd, event_name)))
         break;
     }
     else
@@ -500,7 +557,7 @@ Event_scheduler::run(THD *thd)
 */
 
 bool
-Event_scheduler::execute_top(THD *thd, Event_job_data *job_data)
+Event_scheduler::execute_top(THD *thd, Event_queue_element_for_exec *event_name)
 {
   THD *new_thd;
   pthread_t th;
@@ -511,13 +568,13 @@ Event_scheduler::execute_top(THD *thd, E
 
   pre_init_event_thread(new_thd);
   new_thd->system_thread= SYSTEM_THREAD_EVENT_WORKER;
-  job_data->thd= new_thd;
+  event_name->thd= new_thd;
   DBUG_PRINT("info", ("BURAN %s@%s ready for start t-3..2..1..0..ignition",
-             job_data->dbname.str, job_data->name.str));
+             event_name->dbname.str, event_name->name.str));
 
   /* Major failure */
   if ((res= pthread_create(&th, &connection_attrib, event_worker_thread,
-                           job_data)))
+                           event_name)))
     goto error;
 
   ++started_events;
@@ -538,7 +595,7 @@ error:
     delete new_thd;
     pthread_mutex_unlock(&LOCK_thread_count);
   }
-  delete job_data;
+  delete event_name;
   DBUG_RETURN(TRUE);
 }
 

--- 1.17/sql/event_scheduler.h	2006-09-06 16:48:28 +02:00
+++ 1.18/sql/event_scheduler.h	2006-09-06 16:48:28 +02:00
@@ -16,8 +16,11 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
+
 class Event_queue;
 class Event_job_data;
+class Event_db_repository;
+class Events;
 
 void
 pre_init_event_thread(THD* thd);
@@ -28,6 +31,29 @@ post_init_event_thread(THD* thd);
 void
 deinit_event_thread(THD *thd);
 
+
+class Event_worker_thread 
+{
+public:
+  static void
+  init(Events *events, Event_db_repository *db_repo)
+  {
+    db_repository= db_repo;
+    events_facade= events;
+  }
+
+  void
+  run(THD *thd, Event_queue_element_for_exec *event);
+
+private:
+  void
+  print_warnings(THD *thd, Event_job_data *et);
+
+  static Event_db_repository *db_repository;
+  static Events *events_facade;
+};
+
+
 class Event_scheduler
 {
 public:
@@ -72,10 +98,9 @@ private:
   uint
   workers_count();
 
-
   /* helper functions */
   bool
-  execute_top(THD *thd, Event_job_data *job_data);
+  execute_top(THD *thd, Event_queue_element_for_exec *event_name);
 
   /* helper functions for working with mutexes & conditionals */
   void

--- 1.76/sql/event_data_objects.cc	2006-09-06 16:48:28 +02:00
+++ 1.77/sql/event_data_objects.cc	2006-09-06 16:48:28 +02:00
@@ -21,6 +21,8 @@
 #include "event_db_repository.h"
 #include "sp_head.h"
 
+/* That's a provisional solution */
+extern Event_db_repository events_event_db_repository;
 
 #define EVEX_MAX_INTERVAL_VALUE 1000000000L
 
@@ -31,6 +33,47 @@ event_change_security_context(THD *thd, 
 static void
 event_restore_security_context(THD *thd, Security_context *backup);
 
+
+/*
+  Initiliazes dbname and name of an Event_queue_element_for_exec
+  object
+
+  SYNOPSIS
+    Event_queue_element_for_exec::init()
+
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error (OOM)
+*/
+
+bool
+Event_queue_element_for_exec::init(LEX_STRING db, LEX_STRING n)
+{
+  if (!(dbname.str= my_strndup(db.str, dbname.length= db.length, MYF(MY_WME))))
+    return TRUE;
+  if (!(name.str= my_strndup(n.str, name.length= n.length, MYF(MY_WME))))
+  {
+    my_free((gptr) dbname.str, MYF(0));
+    return TRUE;
+  }
+  return FALSE;
+}
+
+
+/*
+  Destructor
+
+  SYNOPSIS
+    Event_queue_element_for_exec::~Event_queue_element_for_exec()
+*/
+
+Event_queue_element_for_exec::~Event_queue_element_for_exec()
+{
+  my_free((gptr) dbname.str, MYF(0));
+  my_free((gptr) name.str, MYF(0));
+}
+
+
 /*
   Returns a new instance
 
@@ -735,7 +778,7 @@ Event_timed::~Event_timed()
 */
 
 Event_job_data::Event_job_data()
-  :thd(NULL), sphead(NULL), sql_mode(0)
+  :sphead(NULL), sql_mode(0)
 {
 }
 
@@ -1214,6 +1257,7 @@ Event_queue_element::compute_next_execut
     DBUG_PRINT("info", ("Dropped=%d", dropped));
     status= Event_queue_element::DISABLED;
     status_changed= TRUE;
+    dropped= TRUE;
 
     goto ret;
   }
@@ -1419,32 +1463,6 @@ Event_queue_element::mark_last_executed(
 
 
 /*
-  Drops the event
-
-  SYNOPSIS
-    Event_queue_element::drop()
-      thd   thread context
-
-  RETURN VALUE
-    0       OK
-   -1       Cannot open mysql.event
-   -2       Cannot find the event in mysql.event (already deleted?)
-
-   others   return code from SE in case deletion of the event row
-            failed.
-*/
-
-int
-Event_queue_element::drop(THD *thd)
-{
-  DBUG_ENTER("Event_queue_element::drop");
-
-  DBUG_RETURN(Events::get_instance()->
-                    drop_event(thd, dbname, name, FALSE, TRUE));
-}
-
-
-/*
   Saves status and last_executed_at to the disk if changed.
 
   SYNOPSIS
@@ -1475,13 +1493,13 @@ Event_queue_element::update_timing_field
 
   thd->reset_n_backup_open_tables_state(&backup);
 
-  if (Events::get_instance()->open_event_table(thd, TL_WRITE, &table))
+  if (events_event_db_repository.open_event_table(thd, TL_WRITE, &table))
   {
     ret= TRUE;
     goto done;
   }
   fields= table->field;
-  if ((ret= Events::get_instance()->db_repository->
+  if ((ret= events_event_db_repository.
                                  find_named_event(thd, dbname, name, table)))
     goto done;
 

--- 1.13/sql/event_data_objects.h	2006-09-06 16:48:28 +02:00
+++ 1.14/sql/event_data_objects.h	2006-09-06 16:48:28 +02:00
@@ -28,6 +28,27 @@ class sp_head;
 class Sql_alloc;
 
 
+class Event_queue_element_for_exec
+{
+public:
+  Event_queue_element_for_exec(){};
+  ~Event_queue_element_for_exec();
+
+  bool
+  init(LEX_STRING dbname, LEX_STRING name);
+
+  LEX_STRING dbname;
+  LEX_STRING name;
+  bool dropped;
+  THD *thd;
+
+private:
+  /* Prevent use of these */
+  Event_queue_element_for_exec(const Event_queue_element_for_exec &);
+  void operator=(Event_queue_element_for_exec &);
+};
+
+
 class Event_basic
 {
 protected:
@@ -97,9 +118,6 @@ public:
   bool
   compute_next_execution_time();
 
-  int
-  drop(THD *thd);
-
   void
   mark_last_executed(THD *thd);
 
@@ -161,7 +179,6 @@ public:
 class Event_job_data : public Event_basic
 {
 public:
-  THD *thd;
   sp_head *sphead;
 
   LEX_STRING body;
Thread
bk commit into 5.1 tree (andrey:1.2291)ahristov6 Sep