diff options
author | unknown <andrey@lmy004.> | 2006-07-13 10:59:58 +0200 |
---|---|---|
committer | unknown <andrey@lmy004.> | 2006-07-13 10:59:58 +0200 |
commit | 31caa8c433ace692ea5f31c2c2ae0d872533e8de (patch) | |
tree | fb7407480fd7ae1b764e1bf59ec33047559bf6dd | |
parent | 628be8a71611bc86f7f0cf809b27d63bdd9b12c8 (diff) | |
download | mariadb-git-31caa8c433ace692ea5f31c2c2ae0d872533e8de.tar.gz |
WL #3337 (Events new architecture)
Final stroke, events should be loaded from disk on server startup.
Also check the validity of their bodies if possible during loading.
sql/event_data_objects.cc:
Remove Event_job_data::free_sp(), move the code to the destructor
Change the way we change the security context
Steal some code from sql_parse.cc
sql/event_data_objects.h:
Remove free_sp()
Make compile() public, to be used when booting for verifying the integrity of mysql.event
sql/event_queue.cc:
Make the queue load events from disk on server boot.
Compile and thus check for integrity the events.
sql/event_queue.h:
shift methods around. add queue_loaded boolean.
sql/event_scheduler.cc:
Rename init_event_thread() to pre_init_event_thread()
and make it more generic.
Add post_init_event_thread()
Export these two as well as deinit_event_thread().
Now it is quite easy to write code to spawn a new event thread
whenever needed.
sql/event_scheduler.h:
export pre_init_event_thread(), post_init_event_thread() and deinit_event_thread()
to simplify writing of thread functions.
sql/events.cc:
Events::init() returns only one error code, then make it bool
sql/events.h:
Events::init() returns only one error code, then make it bool
sql/mysqld.cc:
Check the return code of Events::init()
sql/sp_head.cc:
Add trace info
sql/sql_class.cc:
Reorganize thd::change_security_context() to load main_security_ctx
sql/sql_class.h:
Reorganize thd::change_security_context() to load main_security_ctx
sql/sql_lex.cc:
Initialize lex->spname
sql/sql_yacc.yy:
Add a comment
-rw-r--r-- | mysql-test/r/events_restart_phase1.result | 10 | ||||
-rw-r--r-- | mysql-test/r/events_restart_phase2.result | 6 | ||||
-rw-r--r-- | mysql-test/r/events_restart_phase3.result | 9 | ||||
-rw-r--r-- | mysql-test/t/events_restart_phase1.test | 17 | ||||
-rw-r--r-- | mysql-test/t/events_restart_phase2-master.opt | 1 | ||||
-rw-r--r-- | mysql-test/t/events_restart_phase2.test | 9 | ||||
-rw-r--r-- | mysql-test/t/events_restart_phase3-master.opt | 1 | ||||
-rw-r--r-- | mysql-test/t/events_restart_phase3.test | 14 | ||||
-rw-r--r-- | sql/event_data_objects.cc | 55 | ||||
-rw-r--r-- | sql/event_data_objects.h | 9 | ||||
-rw-r--r-- | sql/event_queue.cc | 144 | ||||
-rw-r--r-- | sql/event_queue.h | 31 | ||||
-rw-r--r-- | sql/event_scheduler.cc | 114 | ||||
-rw-r--r-- | sql/event_scheduler.h | 9 | ||||
-rw-r--r-- | sql/events.cc | 11 | ||||
-rw-r--r-- | sql/events.h | 2 | ||||
-rw-r--r-- | sql/mysqld.cc | 3 | ||||
-rw-r--r-- | sql/sp_head.cc | 2 | ||||
-rw-r--r-- | sql/sql_class.cc | 18 | ||||
-rw-r--r-- | sql/sql_class.h | 3 | ||||
-rw-r--r-- | sql/sql_lex.cc | 1 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 7 |
22 files changed, 315 insertions, 161 deletions
diff --git a/mysql-test/r/events_restart_phase1.result b/mysql-test/r/events_restart_phase1.result new file mode 100644 index 00000000000..cf0a24c267d --- /dev/null +++ b/mysql-test/r/events_restart_phase1.result @@ -0,0 +1,10 @@ +create database if not exists mysqltest_events_test; +use mysqltest_events_test; +set global event_scheduler=2; +create table execution_log(name char(10)); +create event abc1 on schedule every 1 second do insert into execution_log value('abc1'); +create event abc2 on schedule every 1 second do insert into execution_log value('abc2'); +create event abc3 on schedule every 1 second do insert into execution_log value('abc3'); +insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1'); +insert into mysql.event values ('db1','bad2','sect','root@localhost',NULL,1000,'SECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment2'); +"Now we restart the server" diff --git a/mysql-test/r/events_restart_phase2.result b/mysql-test/r/events_restart_phase2.result new file mode 100644 index 00000000000..703cb92324f --- /dev/null +++ b/mysql-test/r/events_restart_phase2.result @@ -0,0 +1,6 @@ +use mysqltest_events_test; +"Should get 0 rows because the queue aborted run +select distinct name from execution_log order by name; +name +delete from mysql.event where name like 'bad%'; +"Now restart the server again" diff --git a/mysql-test/r/events_restart_phase3.result b/mysql-test/r/events_restart_phase3.result new file mode 100644 index 00000000000..398a9d06546 --- /dev/null +++ b/mysql-test/r/events_restart_phase3.result @@ -0,0 +1,9 @@ +use mysqltest_events_test; +"Should get 3 rows : abc1, abc2, abc3 +select distinct name from execution_log order by name; +name +drop event abc1; +drop event abc2; +drop event abc3; +drop table execution_log; +drop database mysqltest_events_test; diff --git a/mysql-test/t/events_restart_phase1.test b/mysql-test/t/events_restart_phase1.test new file mode 100644 index 00000000000..879591e6141 --- /dev/null +++ b/mysql-test/t/events_restart_phase1.test @@ -0,0 +1,17 @@ +# Can't test with embedded server that doesn't support grants +-- source include/not_embedded.inc + +--disable_warnings +create database if not exists mysqltest_events_test; +--enable_warnings + +use mysqltest_events_test; +set global event_scheduler=2; +create table execution_log(name char(10)); +create event abc1 on schedule every 1 second do insert into execution_log value('abc1'); +create event abc2 on schedule every 1 second do insert into execution_log value('abc2'); +create event abc3 on schedule every 1 second do insert into execution_log value('abc3'); + +insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1'); +insert into mysql.event values ('db1','bad2','sect','root@localhost',NULL,1000,'SECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment2'); +--echo "Now we restart the server" diff --git a/mysql-test/t/events_restart_phase2-master.opt b/mysql-test/t/events_restart_phase2-master.opt new file mode 100644 index 00000000000..656b9e1b017 --- /dev/null +++ b/mysql-test/t/events_restart_phase2-master.opt @@ -0,0 +1 @@ +--event-scheduler=1 diff --git a/mysql-test/t/events_restart_phase2.test b/mysql-test/t/events_restart_phase2.test new file mode 100644 index 00000000000..845472377ba --- /dev/null +++ b/mysql-test/t/events_restart_phase2.test @@ -0,0 +1,9 @@ +# Can't test with embedded server that doesn't support grants +-- source include/not_embedded.inc + +use mysqltest_events_test; +--sleep 1.5 +--echo "Should get 0 rows because the queue aborted run +select distinct name from execution_log order by name; +delete from mysql.event where name like 'bad%'; +--echo "Now restart the server again" diff --git a/mysql-test/t/events_restart_phase3-master.opt b/mysql-test/t/events_restart_phase3-master.opt new file mode 100644 index 00000000000..656b9e1b017 --- /dev/null +++ b/mysql-test/t/events_restart_phase3-master.opt @@ -0,0 +1 @@ +--event-scheduler=1 diff --git a/mysql-test/t/events_restart_phase3.test b/mysql-test/t/events_restart_phase3.test new file mode 100644 index 00000000000..76cd9d22752 --- /dev/null +++ b/mysql-test/t/events_restart_phase3.test @@ -0,0 +1,14 @@ +# Can't test with embedded server that doesn't support grants +-- source include/not_embedded.inc + +use mysqltest_events_test; +--sleep 2 +--echo "Should get 3 rows : abc1, abc2, abc3 +select distinct name from execution_log order by name; + +drop event abc1; +drop event abc2; +drop event abc3; +drop table execution_log; + +drop database mysqltest_events_test; diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index 8f67754a5b2..a367e058f0e 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -731,7 +731,7 @@ Event_timed::~Event_timed() */ Event_job_data::Event_job_data(): - thd(NULL), sphead(0), sql_mode(0) + thd(NULL), sphead(NULL), sql_mode(0) { } @@ -745,7 +745,10 @@ Event_job_data::Event_job_data(): Event_job_data::~Event_job_data() { - free_sp(); + DBUG_ENTER("Event_job_data::~Event_job_data"); + delete sphead; + sphead= NULL; + DBUG_VOID_RETURN; } @@ -1606,20 +1609,6 @@ Event_job_data::get_fake_create_event(THD *thd, String *buf) /* - Frees the memory of the sp_head object we hold - SYNOPSIS - Event_job_data::free_sp() -*/ - -void -Event_job_data::free_sp() -{ - delete sphead; - sphead= NULL; -} - - -/* Compiles an event before it's execution. Compiles the anonymous sp_head object held by the event @@ -1651,9 +1640,7 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root) CHARSET_INFO *old_character_set_client, *old_collation_connection, *old_character_set_results; - Security_context *save_ctx; - /* this one is local and not needed after exec */ - Security_context security_ctx; + Security_context save_ctx; DBUG_ENTER("Event_job_data::compile"); @@ -1699,10 +1686,9 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root) thd->query_length= show_create.length(); DBUG_PRINT("info", ("query:%s",thd->query)); - thd->change_security_context(definer_user, definer_host, dbname, - &security_ctx, &save_ctx); + thd->change_security_context(definer_user, definer_host, dbname, &save_ctx); thd->lex= &lex; - lex_start(thd, (uchar*)thd->query, thd->query_length); + mysql_init_query(thd, (uchar*) thd->query, thd->query_length); if (MYSQLparse((void *)thd) || thd->is_fatal_error) { DBUG_PRINT("error", ("error during compile or thd->is_fatal_error=%d", @@ -1713,13 +1699,10 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root) */ sql_print_error("error during compile of %s.%s or thd->is_fatal_error=%d", dbname.str, name.str, thd->is_fatal_error); - if (lex.sphead) - { - if (&lex != thd->lex) - thd->lex->sphead->restore_lex(thd); - delete lex.sphead; - lex.sphead= 0; - } + + lex.unit.cleanup(); + delete lex.sphead; + sphead= lex.sphead= NULL; ret= EVEX_COMPILE_ERROR; goto done; } @@ -1734,7 +1717,7 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root) done: lex_end(&lex); - thd->restore_security_context(save_ctx); + thd->restore_security_context(&save_ctx); DBUG_PRINT("note", ("return old data on its place. set back NAMES")); thd->lex= old_lex; @@ -1772,20 +1755,17 @@ done: int Event_job_data::execute(THD *thd) { - Security_context *save_ctx; + Security_context save_ctx; /* this one is local and not needed after exec */ - Security_context security_ctx; int ret= 0; DBUG_ENTER("Event_job_data::execute"); DBUG_PRINT("info", ("EXECUTING %s.%s", dbname.str, name.str)); - if ((ret= compile(thd, NULL))) goto done; - thd->change_security_context(definer_user, definer_host, dbname, - &security_ctx, &save_ctx); + thd->change_security_context(definer_user, definer_host, dbname, &save_ctx); /* THD::~THD will clean this or if there is DROP DATABASE in the SP then it will be free there. It should not point to our buffer which is allocated @@ -1810,9 +1790,10 @@ Event_job_data::execute(THD *thd) ret= -99; } - thd->restore_security_context(save_ctx); + thd->restore_security_context(&save_ctx); done: - free_sp(); + thd->end_statement(); + thd->cleanup_after_query(); DBUG_PRINT("info", ("EXECUTED %s.%s ret=%d", dbname.str, name.str, ret)); diff --git a/sql/event_data_objects.h b/sql/event_data_objects.h index e20d698161e..cf1bd5e390a 100644 --- a/sql/event_data_objects.h +++ b/sql/event_data_objects.h @@ -178,15 +178,12 @@ public: int execute(THD *thd); -private: - int - get_fake_create_event(THD *thd, String *buf); int compile(THD *thd, MEM_ROOT *mem_root); - - void - free_sp(); +private: + int + get_fake_create_event(THD *thd, String *buf); Event_job_data(const Event_job_data &); /* Prevent use of these */ void operator=(Event_job_data &); diff --git a/sql/event_queue.cc b/sql/event_queue.cc index 12eceee8cfb..69114c53118 100644 --- a/sql/event_queue.cc +++ b/sql/event_queue.cc @@ -35,6 +35,14 @@ #define LOCK_QUEUE_DATA() lock_data(SCHED_FUNC, __LINE__) #define UNLOCK_QUEUE_DATA() unlock_data(SCHED_FUNC, __LINE__) +struct event_queue_param +{ + THD *thd; + Event_queue *queue; + pthread_mutex_t LOCK_loaded; + pthread_cond_t COND_loaded; +}; + /* Compares the execute_at members of two Event_queue_element instances. @@ -64,6 +72,31 @@ event_queue_element_compare_q(void *vptr, byte* a, byte *b) } +pthread_handler_t +event_queue_loader_thread(void *arg) +{ + /* needs to be first for thread_stack */ + THD *thd= (THD *)((struct event_queue_param *) arg)->thd; + struct event_queue_param *param= (struct event_queue_param *) arg; + thd->thread_stack= (char *) &thd; + + if (post_init_event_thread(thd)) + goto end; + + DBUG_ENTER("event_queue_loader_thread"); + + pthread_mutex_lock(¶m->LOCK_loaded); + param->queue->load_events_from_db(thd); + pthread_cond_signal(¶m->COND_loaded); + pthread_mutex_unlock(¶m->LOCK_loaded); + +end: + deinit_event_thread(thd); + + DBUG_RETURN(0); // Against gcc warnings +} + + /* Constructor of class Event_queue. @@ -80,6 +113,8 @@ Event_queue::Event_queue() mutex_last_attempted_lock_in_func= ""; mutex_queue_data_locked= mutex_queue_data_attempting_lock= FALSE; + + queue_loaded= FALSE; } @@ -125,8 +160,11 @@ Event_queue::deinit_mutexes() bool Event_queue::init_queue(Event_db_repository *db_repo, Event_scheduler *sched) { - int i= 0; - bool ret= FALSE; + THD *new_thd; + pthread_t th; + bool res; + struct event_queue_param *event_queue_param_value= NULL; + DBUG_ENTER("Event_queue::init_queue"); DBUG_PRINT("enter", ("this=0x%lx", this)); @@ -139,8 +177,7 @@ Event_queue::init_queue(Event_db_repository *db_repo, Event_scheduler *sched) NULL, EVENT_QUEUE_EXTENT)) { sql_print_error("SCHEDULER: Can't initialize the execution queue"); - ret= TRUE; - goto end; + goto err; } if (sizeof(my_time_t) != sizeof(time_t)) @@ -148,13 +185,43 @@ Event_queue::init_queue(Event_db_repository *db_repo, Event_scheduler *sched) sql_print_error("SCHEDULER: sizeof(my_time_t) != sizeof(time_t) ." "The scheduler may not work correctly. Stopping."); DBUG_ASSERT(0); - ret= TRUE; - goto end; + goto err; } -end: + if (!(new_thd= new THD)) + goto err; + + pre_init_event_thread(new_thd); + + event_queue_param_value= (struct event_queue_param *) + my_malloc(sizeof(struct event_queue_param), MYF(0)); + event_queue_param_value->thd= new_thd; + event_queue_param_value->queue= this; + pthread_mutex_init(&event_queue_param_value->LOCK_loaded, MY_MUTEX_INIT_FAST); + pthread_cond_init(&event_queue_param_value->COND_loaded, NULL); + + pthread_mutex_lock(&event_queue_param_value->LOCK_loaded); + DBUG_PRINT("info", ("Forking new thread for scheduduler. THD=0x%lx", new_thd)); + if (!(res= pthread_create(&th, &connection_attrib, event_queue_loader_thread, + (void*)event_queue_param_value))) + { + do { + pthread_cond_wait(&event_queue_param_value->COND_loaded, + &event_queue_param_value->LOCK_loaded); + } while (queue_loaded == FALSE); + } + + pthread_mutex_unlock(&event_queue_param_value->LOCK_loaded); + pthread_mutex_destroy(&event_queue_param_value->LOCK_loaded); + pthread_cond_destroy(&event_queue_param_value->COND_loaded); + my_free((char *)event_queue_param_value, MYF(0)); + UNLOCK_QUEUE_DATA(); - DBUG_RETURN(ret); + DBUG_RETURN(res); + +err: + UNLOCK_QUEUE_DATA(); + DBUG_RETURN(TRUE); } @@ -498,7 +565,7 @@ Event_queue::load_events_from_db(THD *thd) READ_RECORD read_record_info; int ret= -1; uint count= 0; - bool clean_the_queue= FALSE; + bool clean_the_queue= TRUE; /* Compile the events on this root but only for syntax check, then discard */ MEM_ROOT boot_root; @@ -518,14 +585,12 @@ Event_queue::load_events_from_db(THD *thd) if (!(et= new Event_queue_element)) { DBUG_PRINT("info", ("Out of memory")); - clean_the_queue= TRUE; break; } DBUG_PRINT("info", ("Loading event from row.")); if ((ret= et->load_from_row(table))) { - clean_the_queue= TRUE; sql_print_error("SCHEDULER: Error while loading from mysql.event. " "Table probably corrupted"); break; @@ -536,27 +601,6 @@ Event_queue::load_events_from_db(THD *thd) delete et; continue; } -#if 0 - init_alloc_root(&boot_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); - DBUG_PRINT("info", ("Event %s loaded from row. ", et->name.str)); - - /* We load only on scheduler root just to check whether the body compiles */ - switch (ret= et->compile(thd, &boot_root)) { - case EVEX_MICROSECOND_UNSUP: - et->free_sp(); - sql_print_error("SCHEDULER: mysql.event is tampered. MICROSECOND is not " - "supported but found in mysql.event"); - goto end; - case EVEX_COMPILE_ERROR: - sql_print_error("SCHEDULER: Error while compiling %s.%s. Aborting load.", - et->dbname.str, et->name.str); - goto end; - default: - /* Free it, it will be compiled again on the worker thread */ - et->free_sp(); - break; - } - free_root(&boot_root, MYF(0)); /* let's find when to be executed */ if (et->compute_next_execution_time()) @@ -565,11 +609,40 @@ Event_queue::load_events_from_db(THD *thd) " Skipping", et->dbname.str, et->name.str); continue; } -#endif + + { + Event_job_data temp_job_data; + DBUG_PRINT("info", ("Event %s loaded from row. ", et->name.str)); + + temp_job_data.load_from_row(table); + + /* We load only on scheduler root just to check whether the body compiles */ + switch (ret= temp_job_data.compile(thd, thd->mem_root)) { + case EVEX_MICROSECOND_UNSUP: + sql_print_error("SCHEDULER: mysql.event is tampered. MICROSECOND is not " + "supported but found in mysql.event"); + break; + case EVEX_COMPILE_ERROR: + sql_print_error("SCHEDULER: Error while compiling %s.%s. Aborting load.", + et->dbname.str, et->name.str); + break; + default: + break; + } + thd->end_statement(); + thd->cleanup_after_query(); + } + if (ret) + { + delete et; + goto end; + } + DBUG_PRINT("load_events_from_db", ("Adding 0x%lx to the exec list.")); queue_insert_safe(&queue, (byte *) et); count++; } + clean_the_queue= FALSE; end: end_read_record(&read_record_info); @@ -585,10 +658,12 @@ end: } /* Force close to free memory */ - thd->version--; + thd->version--; close_thread_tables(thd); + queue_loaded= TRUE; + DBUG_PRINT("info", ("Status code %d. Loaded %d event(s)", ret, count)); DBUG_RETURN(ret); } @@ -713,6 +788,7 @@ Event_queue::empty_queue() uint i; DBUG_ENTER("Event_queue::empty_queue"); DBUG_PRINT("enter", ("Purging the queue. %d element(s)", queue.elements)); + sql_print_information("SCHEDULER: Purging queue. %u events", queue.elements); /* empty the queue */ for (i= 0; i < queue.elements; ++i) { diff --git a/sql/event_queue.h b/sql/event_queue.h index b7962d14a89..3270938e881 100644 --- a/sql/event_queue.h +++ b/sql/event_queue.h @@ -68,12 +68,13 @@ public: bool dump_internal_status(THD *thd); + int + load_events_from_db(THD *thd); + protected: Event_queue_element * find_n_remove_event(LEX_STRING db, LEX_STRING name); - int - load_events_from_db(THD *thd); void drop_matching_events(THD *thd, LEX_STRING pattern, @@ -82,11 +83,24 @@ protected: void empty_queue(); + void + notify_observers(); + + void + dbug_dump_queue(time_t now); + /* LOCK_event_queue is the mutex which protects the access to the queue. */ pthread_mutex_t LOCK_event_queue; Event_db_repository *db_repository; + Event_scheduler *scheduler; + + /* The sorted queue with the Event_job_data objects */ + QUEUE queue; + + bool queue_loaded; + uint mutex_last_locked_at_line; uint mutex_last_unlocked_at_line; uint mutex_last_attempted_lock_at_line; @@ -95,24 +109,13 @@ protected: const char* mutex_last_attempted_lock_in_func; bool mutex_queue_data_locked; bool mutex_queue_data_attempting_lock; - + /* helper functions for working with mutexes & conditionals */ void lock_data(const char *func, uint line); void unlock_data(const char *func, uint line); - - void - notify_observers(); - - void - dbug_dump_queue(time_t now); - - Event_scheduler *scheduler; - - /* The sorted queue with the Event_job_data objects */ - QUEUE queue; }; #endif /* _EVENT_QUEUE_H_ */ diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 85d357ec11e..5e6ffb090cb 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -40,9 +40,6 @@ struct scheduler_param Event_scheduler *scheduler; }; -struct scheduler_param scheduler_param_value; - - static LEX_STRING scheduler_states_names[] = @@ -103,25 +100,23 @@ evex_print_warnings(THD *thd, Event_job_data *et) /* - Inits an scheduler thread handler, both the main and a worker + Performs pre- pthread_create() initialisation of THD. Do this + in the thread that will pass THD to the child thread. In the + child thread call post_init_event_thread(). SYNOPSIS - init_event_thread() - thd - the THD of the thread. Has to be allocated by the caller. + pre_init_event_thread() + thd The THD of the thread. Has to be allocated by the caller. NOTES 1. The host of the thead is my_localhost 2. thd->net is initted with NULL - no communication. - - RETURN VALUE - 0 OK - -1 Error */ -static int -init_scheduler_thread(THD* thd) +void +pre_init_event_thread(THD* thd) { - DBUG_ENTER("init_event_thread"); + DBUG_ENTER("pre_init_event_thread"); thd->client_capabilities= 0; thd->security_ctx->master_access= 0; thd->security_ctx->db_access= 0; @@ -148,7 +143,36 @@ init_scheduler_thread(THD* thd) thd->version= refresh_version; thd->set_time(); - DBUG_RETURN(0); + DBUG_VOID_RETURN; +} + + +/* + Performs post initialization of structures in a new thread. + + SYNOPSIS + post_init_event_thread() + thd Thread +*/ + +bool +post_init_event_thread(THD *thd) +{ + my_thread_init(); + pthread_detach_this_thread(); + thd->real_id= pthread_self(); + if (init_thr_lock() || thd->store_globals()) + { + thd->cleanup(); + return TRUE; + } + +#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) + sigset_t set; + VOID(sigemptyset(&set)); // Get mask in use + VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals)); +#endif + return FALSE; } @@ -160,7 +184,7 @@ init_scheduler_thread(THD* thd) thd Thread */ -static void +void deinit_event_thread(THD *thd) { thd->proc_info= "Clearing"; @@ -192,29 +216,18 @@ pthread_handler_t event_scheduler_thread(void *arg) { /* needs to be first for thread_stack */ - THD *thd= (THD *)(*(struct scheduler_param *) arg).thd; + THD *thd= (THD *)((struct scheduler_param *) arg)->thd; + Event_scheduler *scheduler= ((struct scheduler_param *) arg)->scheduler; - thd->thread_stack= (char *)&thd; // remember where our stack is - DBUG_ENTER("event_scheduler_thread"); + my_free((char*)arg, MYF(0)); - my_thread_init(); - pthread_detach_this_thread(); - thd->real_id=pthread_self(); - if (init_thr_lock() || thd->store_globals()) - { - thd->cleanup(); - goto end; - } + thd->thread_stack= (char *)&thd; // remember where our stack is -#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) - sigset_t set; - VOID(sigemptyset(&set)); // Get mask in use - VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals)); -#endif + DBUG_ENTER("event_scheduler_thread"); - ((struct scheduler_param *) arg)->scheduler->run(thd); + if (!post_init_event_thread(thd)) + scheduler->run(thd); -end: deinit_event_thread(thd); DBUG_RETURN(0); // Against gcc warnings @@ -242,27 +255,13 @@ event_worker_thread(void *arg) int ret; thd= event->thd; - thd->thread_stack= (char *) &thd; + thd->thread_stack= (char *) &thd; // remember where our stack is + DBUG_ENTER("event_worker_thread"); - my_thread_init(); - pthread_detach_this_thread(); - thd->real_id=pthread_self(); - if (init_thr_lock() || thd->store_globals()) - { - thd->cleanup(); + if (post_init_event_thread(thd)) goto end; - } - -#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) - sigset_t set; - VOID(sigemptyset(&set)); // Get mask in use - VOID(pthread_sigmask(SIG_UNBLOCK, &set, &thd->block_signals)); -#endif - thd->init_for_queries(); - - DBUG_ENTER("event_worker_thread"); DBUG_PRINT("info", ("Baikonur, time is %d, BURAN reporting and operational." "THD=0x%lx", time(NULL), thd)); @@ -375,6 +374,7 @@ Event_scheduler::start() THD *new_thd= NULL; bool ret= FALSE; pthread_t th; + struct scheduler_param *scheduler_param_value; DBUG_ENTER("Event_scheduler::start"); LOCK_SCHEDULER_DATA(); @@ -382,21 +382,24 @@ Event_scheduler::start() if (state > INITIALIZED) goto end; - if (!(new_thd= new THD) || init_scheduler_thread(new_thd)) + if (!(new_thd= new THD)) { sql_print_error("SCHEDULER: Cannot init manager event thread."); ret= TRUE; goto end; } + pre_init_event_thread(new_thd); new_thd->system_thread= SYSTEM_THREAD_EVENT_SCHEDULER; new_thd->command= COM_DAEMON; - scheduler_param_value.thd= new_thd; - scheduler_param_value.scheduler= this; + scheduler_param_value= + (struct scheduler_param *)my_malloc(sizeof(struct scheduler_param), MYF(0)); + scheduler_param_value->thd= new_thd; + scheduler_param_value->scheduler= this; DBUG_PRINT("info", ("Forking new thread for scheduduler. THD=0x%lx", new_thd)); if (pthread_create(&th, &connection_attrib, event_scheduler_thread, - (void*)&scheduler_param_value)) + (void*)scheduler_param_value)) { DBUG_PRINT("error", ("cannot create a new thread")); state= INITIALIZED; @@ -588,9 +591,10 @@ Event_scheduler::execute_top(THD *thd, Event_job_data *job_data) pthread_t th; int res= 0; DBUG_ENTER("Event_scheduler::execute_top"); - if (!(new_thd= new THD) || init_scheduler_thread(new_thd)) + if (!(new_thd= new THD)) goto error; + pre_init_event_thread(new_thd); new_thd->system_thread= SYSTEM_THREAD_EVENT_WORKER; job_data->thd= new_thd; DBUG_PRINT("info", ("BURAN %s@%s ready for start t-3..2..1..0..ignition", diff --git a/sql/event_scheduler.h b/sql/event_scheduler.h index bf3e8e63e11..8e00b7b767f 100644 --- a/sql/event_scheduler.h +++ b/sql/event_scheduler.h @@ -19,6 +19,15 @@ class Event_queue; class Event_job_data; +void +pre_init_event_thread(THD* thd); + +bool +post_init_event_thread(THD* thd); + +void +deinit_event_thread(THD *thd); + class Event_scheduler { public: diff --git a/sql/events.cc b/sql/events.cc index 2a4ccbaf5ef..94ef8faa83d 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -556,11 +556,16 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) 1 Error in case the scheduler can't start */ -int +bool Events::init() { + int res; DBUG_ENTER("Events::init"); - event_queue->init_queue(db_repository, scheduler); + if (event_queue->init_queue(db_repository, scheduler)) + { + sql_print_information("SCHEDULER: Error while loading from disk."); + DBUG_RETURN(TRUE); + } scheduler->init_scheduler(event_queue); /* it should be an assignment! */ @@ -571,7 +576,7 @@ Events::init() DBUG_RETURN(scheduler->start()); } - DBUG_RETURN(0); + DBUG_RETURN(FALSE); } diff --git a/sql/events.h b/sql/events.h index 5f46c7bb7c5..f14aed0fbd1 100644 --- a/sql/events.h +++ b/sql/events.h @@ -52,7 +52,7 @@ public: static ulong opt_event_scheduler; static TYPELIB opt_typelib; - int + bool init(); void diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 8fc6155087e..1cc52a204eb 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3675,7 +3675,8 @@ we force server id to 2, but this MySQL server will not act as a slave."); if (!opt_noacl) { - Events::get_instance()->init(); + if (Events::get_instance()->init()) + unireg_abort(1); } #if defined(__NT__) || defined(HAVE_SMEM) handle_connections_methods(); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 81f5d502ec9..d8995da7c16 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -640,10 +640,12 @@ sp_head::create(THD *thd) sp_head::~sp_head() { + DBUG_ENTER("sp_head::~sp_head"); destroy(); delete m_next_cached_sp; if (m_thd) restore_thd_mem_root(m_thd); + DBUG_VOID_RETURN; } void diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 47381c6aecb..6ce5a8fa01d 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2085,21 +2085,20 @@ bool Security_context::set_user(char *user_arg) bool THD::change_security_context(LEX_STRING user, LEX_STRING host, - LEX_STRING db, Security_context *s_ctx, - Security_context **backup) + LEX_STRING db, Security_context *backup) { DBUG_ENTER("change_security_context"); DBUG_PRINT("info",("%s@%s@%s", user.str, host.str, db.str)); #ifndef NO_EMBEDDED_ACCESS_CHECKS - s_ctx->init(); - *backup= 0; - if (acl_getroot_no_password(s_ctx, user.str, host.str, host.str, db.str)) + + *backup= main_security_ctx; + if (acl_getroot_no_password(&main_security_ctx, user.str, host.str, host.str, + db.str)) { my_error(ER_NO_SUCH_USER, MYF(0), user.str, host.str); DBUG_RETURN(TRUE); } - *backup= security_ctx; - security_ctx= s_ctx; + security_ctx= &main_security_ctx; #endif DBUG_RETURN(FALSE); } @@ -2119,7 +2118,10 @@ THD::restore_security_context(Security_context *backup) DBUG_ENTER("restore_security_context"); #ifndef NO_EMBEDDED_ACCESS_CHECKS if (backup) - security_ctx= backup; + { + main_security_ctx= *backup; + security_ctx= &main_security_ctx; + } #endif DBUG_VOID_RETURN; } diff --git a/sql/sql_class.h b/sql/sql_class.h index 18cc53daf6d..1283f55cea6 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -871,8 +871,7 @@ public: bool change_security_context(LEX_STRING user, LEX_STRING host, - LEX_STRING db, Security_context *s_ctx, - Security_context **backup); + LEX_STRING db, Security_context *backup); void restore_security_context(Security_context *backup); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 386dece8813..1be70ea61d6 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -171,6 +171,7 @@ void lex_start(THD *thd, const uchar *buf, uint length) lex->sql_command= SQLCOM_END; lex->duplicates= DUP_ERROR; lex->ignore= 0; + lex->spname= NULL; lex->sphead= NULL; lex->spcont= NULL; lex->proc_list.first= 0; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 0dd87fbfac6..a29c5f3ee16 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4652,6 +4652,13 @@ alter: YYTHD->client_capabilities is set back to original value */ { + /* + It is safe to use Lex->spname because + ALTER EVENT xxx RENATE TO yyy DO ALTER EVENT RENAME TO + is not allowed. Lex->spname is used in the case of RENAME TO + If it had to be supported spname had to be added to + Event_parse_data. + */ Lex->spname= NULL; if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD))) |