List:Commits« Previous MessageNext Message »
From:ahristov Date:January 31 2006 11:05am
Subject:bk commit into 5.1 tree (andrey:1.2097) BUG#16414
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
  1.2097 06/01/31 12:05:14 andrey@lmy004. +6 -0
  - fix for bug #16414 (Events: Crash or hang if event drops itself)
  WL#1034 (Internal CRON)

  sql/sql_parse.cc
    1.516 06/01/31 12:05:05 andrey@lmy004. +2 -0
    - some debug info about the status code returned.

  sql/event_timed.cc
    1.24 06/01/31 12:05:05 andrey@lmy004. +2 -12
    - use db_drop_event() and don't implement the dropping ourselves

  sql/event_priv.h
    1.16 06/01/31 12:05:05 andrey@lmy004. +3 -0
    - export the new function db_drop_event()

  sql/event.cc
    1.24 06/01/31 12:05:05 andrey@lmy004. +57 -12
    - evex_remove_from_cache reports back whether the in_memory
      object was deleted or was scheduled. In case scheduling then
      don't delete it from outside but let it do it itself
    - move out db interaction code out of evex_drop_event to db_drop_event
      so it can be called from outter space :)

  mysql-test/t/events.test
    1.13 06/01/31 12:05:05 andrey@lmy004. +67 -44
    use --sleep instead of select sleep()
    enable some scheduler related tests. They were disabled because of a hang that
    happened. The hang is fixed with this bugfix.

  mysql-test/r/events.result
    1.12 06/01/31 12:05:04 andrey@lmy004. +67 -9
    update the result

# 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:	lmy004.
# Root:	/work/mysql-5.1-events_i_s

--- 1.515/sql/sql_parse.cc	2006-01-30 13:31:20 +01:00
+++ 1.516/sql/sql_parse.cc	2006-01-31 12:05:05 +01:00
@@ -3723,6 +3723,8 @@
         res= evex_drop_event(thd, lex->et, lex->drop_if_exists, &rows_affected);
       default:;
       }
+      DBUG_PRINT("info", ("CREATE/ALTER/DROP returned error code=%d af_rows=%d",
+                  res, rows_affected));
       if (!res)
         send_ok(thd, rows_affected);
 

--- 1.11/mysql-test/r/events.result	2006-01-30 17:11:41 +01:00
+++ 1.12/mysql-test/r/events.result	2006-01-31 12:05:04 +01:00
@@ -15,20 +15,11 @@
 drop event event2;
 create event e_43 on schedule every 1 second do set @a = 5;
 set global event_scheduler = 1;
-select sleep(2);
-sleep(2)
-0
 alter event e_43 do alter event e_43 do set @a = 4;
-select sleep(3);
-sleep(3)
-0
 select db, name, body, status, interval_field, interval_value from mysql.event;
 db	name	body	status	interval_field	interval_value
 events_test	e_43	 set @a = 4	ENABLED	SECOND	1
 drop event e_43;
-select sleep(1);
-sleep(1)
-0
 set global event_scheduler = 0;
 create table t_event3 (a int, b float);
 drop event if exists event3;
@@ -121,6 +112,7 @@
 drop event three_event;
 drop user ev_test@localhost;
 drop event one_event;
+"Sleep a bit so the server closes the second connection"
 create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5;
 select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
 db	name	body	definer	convert_tz(execute_at, 'UTC', 'SYSTEM')	on_completion
@@ -137,4 +129,70 @@
 ERROR HY000: Variable 'event_scheduler' is a GLOBAL variable and should be set with SET GLOBAL
 set global event_scheduler=2;
 ERROR 42000: Variable 'event_scheduler' can't be set to the value of '2'
+"DISABLE the scheduler. Testing that it does not work when the variable is 0"
+set global event_scheduler=0;
+select definer, name, db from mysql.event;
+definer	name	db
+select get_lock("test_lock1", 20);
+get_lock("test_lock1", 20)
+1
+create event закачка on schedule every 10 hour do select get_lock("test_lock1", 20);
+"Should return 1 row"
+select definer, name, db from mysql.event;
+definer	name	db
+root@localhost	закачка	events_test
+"Should be only 1 process"
+show processlist;
+Id	User	Host	db	Command	Time	State	Info
+#	root	localhost	events_test	Query	#	NULL	show processlist
+select release_lock("test_lock1");
+release_lock("test_lock1")
+1
+drop event закачка;
+"Should have 0 events"
+select count(*) from mysql.event;
+count(*)
+0
+"ENABLE the scheduler and get a lock"
+set global event_scheduler=1;
+select get_lock("test_lock2", 20);
+get_lock("test_lock2", 20)
+1
+"Create an event which tries to acquire a mutex. The event locks on the mutex"
+create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20);
+"Let some time pass to the event starts"
+"Should have only 3 processes: the scheduler, our conn and the locked event"
+show processlist;
+Id	User	Host	db	Command	Time	State	Info
+#	root	localhost	events_test	Query	#	NULL	show processlist
+#	event_scheduler		NULL	Connect	#	Sleeping	NULL
+#	root		events_test	Connect	#	User lock	select get_lock("test_lock2", 20)
+"Release the mutex, the event worker should finish."
+select release_lock("test_lock2");
+release_lock("test_lock2")
+1
+drop event закачка;
+set global event_scheduler=1;
+select get_lock("test_lock2_1", 20);
+get_lock("test_lock2_1", 20)
+1
+create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20);
+"Should see 2 processes, one locked on get_lock("
+"Shutting down the scheduler, it should wait for the running event"
+set global event_scheduler=0;
+"Should have only 3 processes: the scheduler, our conn and the locked event"
+show processlist;
+Id	User	Host	db	Command	Time	State	Info
+#	root	localhost	events_test	Query	#	NULL	show processlist
+#	event_scheduler		NULL	Connect	#	Sleeping	NULL
+#	root		events_test	Connect	#	User lock	select get_lock("test_lock2_1", 20)
+"Release the lock so the child process should finish. Hence the scheduler also"
+select release_lock("test_lock2_1");
+release_lock("test_lock2_1")
+1
+"Should have only our process now:"
+show processlist;
+Id	User	Host	db	Command	Time	State	Info
+#	root	localhost	events_test	Query	#	NULL	show processlist
+drop event закачка21;
 drop database events_test;

--- 1.12/mysql-test/t/events.test	2006-01-30 17:11:42 +01:00
+++ 1.13/mysql-test/t/events.test	2006-01-31 12:05:05 +01:00
@@ -17,12 +17,12 @@
 
 create event e_43 on schedule every 1 second do set @a = 5;
 set global event_scheduler = 1;
-select sleep(2);
+--sleep 2
 alter event e_43 do alter event e_43 do set @a = 4;
-select sleep(3);
+--sleep 2
 select db, name, body, status, interval_field, interval_value from mysql.event;
 drop event e_43;
-select sleep(1);
+--sleep 1
 set global event_scheduler = 0;
 
 create table t_event3 (a int, b float);
@@ -107,8 +107,8 @@
 ##INFORMATION_SCHEMA.EVENTS test end
 #
 
-
-
+--echo "Sleep a bit so the server closes the second connection"
+--sleep 2
 
 create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5;
 select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
@@ -129,23 +129,38 @@
 --error 1231
 set global event_scheduler=2;
 
-#set global event_scheduler=0;
-#select count(*) from mysql.event;
-#select get_lock("test_lock1", 20);
-#create event закачка on schedule every 10 hour do select get_lock("test_lock1", 20);
-#select count(*) from mysql.event;
-##show processlist;
-#select release_lock("test_lock1");
-#drop event закачка;
-#select count(*) from mysql.event;
-#
-#set global event_scheduler=1;
-#select get_lock("test_lock2", 20);
-#create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20);
-#select sleep(2);
-#show processlist;
-#select release_lock("test_lock2");
-#drop event закачка;
+--echo "DISABLE the scheduler. Testing that it does not work when the variable is 0"
+set global event_scheduler=0;
+select definer, name, db from mysql.event;
+select get_lock("test_lock1", 20);
+create event закачка on schedule every 10 hour do select get_lock("test_lock1", 20);
+--echo "Should return 1 row"
+select definer, name, db from mysql.event;
+
+--echo "Should be only 1 process"
+--replace_column 1 # 6 #
+show processlist;
+select release_lock("test_lock1");
+drop event закачка;
+--echo "Should have 0 events"
+select count(*) from mysql.event;
+
+#
+#
+#
+--echo "ENABLE the scheduler and get a lock"
+set global event_scheduler=1;
+select get_lock("test_lock2", 20);
+--echo "Create an event which tries to acquire a mutex. The event locks on the mutex"
+create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20);
+--echo "Let some time pass to the event starts"
+--sleep 2
+--echo "Should have only 3 processes: the scheduler, our conn and the locked event"
+--replace_column 1 # 6 #
+show processlist;
+--echo "Release the mutex, the event worker should finish."
+select release_lock("test_lock2");
+drop event закачка;
 
 ##
 ## 1. get a lock
@@ -155,26 +170,33 @@
 ## 5. kill the scheduler, it will wait for the child to stop
 ## 6. both processes should be there on show processlist
 ## 7. release the lock and sleep, both scheduler and child should end
-#set global event_scheduler=1;
-#select get_lock("test_lock2_1", 20);
-#create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20);
-#select sleep(2);
-##show processlist;
-#set global event_scheduler=0;
-#select sleep(2);
-##show processlist;
-#select release_lock("test_lock2_1");
-#select sleep(2);
-##show processlist;
-#drop event закачка21;
-
-#set global event_scheduler=1;
-#select get_lock("test_lock3", 20);
-#create event закачка on schedule every 10 hour do select get_lock("test_lock3", 20);
-#select sleep(2);
+set global event_scheduler=1;
+select get_lock("test_lock2_1", 20);
+create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20);
+--sleep 1
+--echo "Should see 2 processes, one locked on get_lock("
 #show processlist;
-#drop event закачка;
-#select release_lock("test_lock3");
+--echo "Shutting down the scheduler, it should wait for the running event"
+set global event_scheduler=0;
+--sleep 1
+--echo "Should have only 3 processes: the scheduler, our conn and the locked event"
+--replace_column 1 # 6 #
+show processlist;
+--echo "Release the lock so the child process should finish. Hence the scheduler also"
+select release_lock("test_lock2_1");
+--sleep 1
+--echo "Should have only our process now:"
+--replace_column 1 # 6 #
+show processlist;
+drop event закачка21;
+
+##set global event_scheduler=1;
+##select get_lock("test_lock3", 20);
+##create event закачка on schedule every 10 hour do select get_lock("test_lock3", 20);
+##select sleep(2);
+##show processlist;
+##drop event закачка;
+##select release_lock("test_lock3");
 
 #
 # test with very often occuring event
@@ -182,14 +204,15 @@
 ##select get_lock("test_lock4", 20);
 ##create event закачка4 on schedule every 1 second do select get_lock("test_lock4", 20);
 ##select sleep(3);
+##--replace_column 1 # 6 #
 ##show processlist;
 ##drop event закачка4;
 ##select release_lock("test_lock4");
 
-#set global event_scheduler=0;
-#select sleep(2);
+##set global event_scheduler=0;
+##select sleep(2);
+##--replace_column 1 # 6 #
 ##show processlist;
-##the following locks for some reason and is a bug, commented for now
 ##select count(*) from mysql.event;
 
 drop database events_test;

--- 1.23/sql/event.cc	2006-01-30 13:31:16 +01:00
+++ 1.24/sql/event.cc	2006-01-31 12:05:05 +01:00
@@ -704,11 +704,17 @@
 }
 
 
+/*
+   0 - OK can drop from outside
+   1 - Scheduled from dropping, don't drop from outside
+*/
+
 static int
 evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock,
                        bool is_drop)
 {
   uint i;
+  int ret= 0;
 
   DBUG_ENTER("evex_remove_from_cache");
   /*
@@ -738,7 +744,8 @@
         DBUG_PRINT("evex_remove_from_cache",
                ("running.defer mem free. is_drop=%d", is_drop));
         et->flags|= EVENT_EXEC_NO_MORE;
-        et->dropped= is_drop;
+        if (et->dropped= is_drop)
+          ret= 1;
       }
       DBUG_PRINT("evex_remove_from_cache", ("delete from queue"));
       evex_queue_delete_element(&EVEX_EQ_NAME, i);
@@ -751,7 +758,7 @@
   if (use_lock)
     VOID(pthread_mutex_unlock(&LOCK_event_arrays));
 
-  DBUG_RETURN(0);
+  DBUG_RETURN(ret);
 }
 
 
@@ -866,21 +873,25 @@
  Drops an event
 
  SYNOPSIS
-   evex_drop_event()
+   db_drop_event()
      thd             THD
      et              event's name
      drop_if_exists  if set and the event not existing => warning onto the stack
+     rows_affected   affected number of rows is returned heres
           
 */
 
-int
-evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists,
-                uint *rows_affected)
+int db_drop_event(THD *thd, event_timed *et, bool drop_if_exists,
+                  uint *rows_affected)
 {
   TABLE *table;
-  int ret= EVEX_OPEN_TABLE_FAILED;
-  DBUG_ENTER("evex_drop_event");
+  Open_tables_state backup;
+  uint ret;
+
+  DBUG_ENTER("db_drop_event");
+  ret= EVEX_OPEN_TABLE_FAILED;
 
+  thd->reset_n_backup_open_tables_state(&backup);
   if (evex_open_event_table(thd, TL_WRITE, &table))
   {
     my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
@@ -908,10 +919,6 @@
     goto done;
   }
 
-  VOID(pthread_mutex_lock(&LOCK_evex_running));
-  if (evex_is_running)
-    ret= evex_remove_from_cache(&et->dbname, &et->name, true, true);
-  VOID(pthread_mutex_unlock(&LOCK_evex_running));
 
 done:
   /*
@@ -919,6 +926,44 @@
     we have to close our thread tables.
   */
   close_thread_tables(thd);
+  thd->restore_backup_open_tables_state(&backup);
+  DBUG_RETURN(ret);
+}
+
+
+/*
+ Drops an event
+
+ SYNOPSIS
+   evex_drop_event()
+     thd             THD
+     et              event's name
+     drop_if_exists  if set and the event not existing => warning onto the stack
+     rows_affected   affected number of rows is returned heres
+          
+*/
+
+int
+evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists,
+                uint *rows_affected)
+{
+  TABLE *table;
+  int ret= 0;
+
+  DBUG_ENTER("evex_drop_event");
+
+
+  VOID(pthread_mutex_lock(&LOCK_evex_running));
+  if (evex_is_running)
+    ret= evex_remove_from_cache(&et->dbname, &et->name, true, true);
+  VOID(pthread_mutex_unlock(&LOCK_evex_running));
+  
+  if (ret == 1)
+    ret= 0;
+  else if (ret == 0)   
+    ret= db_drop_event(thd, et, drop_if_exists, rows_affected);
+  else
+    my_error(ER_UNKNOWN_ERROR, MYF(0));
 
   DBUG_RETURN(ret);
 }

--- 1.15/sql/event_priv.h	2006-01-30 13:31:17 +01:00
+++ 1.16/sql/event_priv.h	2006-01-31 12:05:05 +01:00
@@ -40,6 +40,9 @@
 int 
 event_timed_compare_q(void *vptr, byte* a, byte *b);
 
+int db_drop_event(THD *thd, event_timed *et, bool drop_if_exists,
+                uint *rows_affected);
+
 
 #define EXEC_QUEUE_QUEUE_NAME executing_queue
 #define EXEC_QUEUE_DARR_NAME evex_executing_queue

--- 1.23/sql/event_timed.cc	2006-01-30 17:11:42 +01:00
+++ 1.24/sql/event_timed.cc	2006-01-31 12:05:05 +01:00
@@ -877,20 +877,10 @@
 event_timed::drop(THD *thd)
 {
   TABLE *table;
-  int ret= 0;
+  uint tmp= 0;
   DBUG_ENTER("event_timed::drop");
 
-  if (evex_open_event_table(thd, TL_WRITE, &table))
-    DBUG_RETURN(-1);
-
-  if (evex_db_find_event_aux(thd, dbname, name, definer, table))
-    DBUG_RETURN(-2);
-
-  if ((ret= table->file->ha_delete_row(table->record[0])))
-    DBUG_RETURN(ret);
-    
-  close_thread_tables(thd);
-  DBUG_RETURN(0);
+  DBUG_RETURN(db_drop_event(thd, this, false, &tmp));
 }
 
 
Thread
bk commit into 5.1 tree (andrey:1.2097) BUG#16414ahristov31 Jan