1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-16 00:42:55 +03:00
Files
mariadb/sql/event.h
unknown f4781a7e4c fix for bug #17619 Scheduler race conditions
- Scheduler is either initialized at server start or never.
  Starting & stopping is now suspending & resuming.
- The scheduler has clear OO interface
- Now all calls to the scheduler are synchronous
- GLOBAL event_scheduler uses thd::sys_var_tmp (see set_var.cc)
- External API is encapsulated into class Events
- Includes fixes for all comments of Kostja's review of 19.05.2005

Starting to merge into 5.1-release (5.1.10) and push


BitKeeper/etc/ignore:
  Added libmysqld/event_scheduler.cc to the ignore list
libmysqld/Makefile.am:
  executor -> scheduler
mysql-test/r/events.result:
  update result
mysql-test/r/events_bugs.result:
  update result
mysql-test/r/events_logs_tests.result:
  update result
mysql-test/r/events_microsec.result:
  update result
mysql-test/r/events_scheduling.result:
  update result
mysql-test/r/events_stress.result:
  update result
mysql-test/t/disabled.def:
  enable these tests
mysql-test/t/events.test:
  optimize the test a bit for speed, save some seconds runtime
  remove FULL from SHOW EVENTS
  mostly use I_S.EVENTS
mysql-test/t/events_bugs.test:
  Skip irrelevant for the current design tests - all events are loaded
  on server startup. Change in mysql.event will be visible on next server start.
  Don't use numeric error codes.
mysql-test/t/events_logs_tests.test:
  optimize the test a bit for speed
mysql-test/t/events_microsec.test:
   Skip irrelevant for the current design tests - all events are loaded
      on server startup. Change in mysql.event will be visible on next server start.
      Don't use numeric error codes.
mysql-test/t/events_scheduling.test:
  broader test
mysql-test/t/events_stress.test:
  Rework the test to the new architecture of suspending/resuming.
  Use less events, no need for thousands, hundreds is still ok.
sql/Makefile.am:
  executor -> scheduler
sql/cmakelists.txt:
  executor -> scheduler
sql/event.cc:
  - remove todo comments
  - remove unneded evex_queue abstraction functions
  - move events_init() and events_shutdown() from event_executor.cc to here
  - export db_create_event
  - remove evex_load_and_compile_event, part of class Event_scheduler
  - integrate the public interface found in event.h and used by sql_parse.cc
    to use the new class Event_scheduler.
sql/event.h:
  - add COND_finished so if one thread kills a running event it waits on this
  - export callback event_timed_definer_equal, event_timed_identifier_equal(),
    event_timed_name_equal and event_timed_db_equal()
    to be used by Event_scheduler::drop_matching_events()
  - cleanup event.h
  - encapsulated all external interface into class Events
sql/event_executor.cc:
  make it empty, will delete after that
sql/event_priv.h:
  - more things in the private header
  - remove event queue abstraction functions. tightly bind to QUEUE
  - export privately db_drop_event, db_find_event, db_create_event()
  - made change_security_context() and restore_security_context() free functions
sql/event_timed.cc:
  - fix calculation of time when ENDS is set (STARTS is always set)
  - during Event_timed::compile() set the right Security_ctx. Prevents a crash
        during Event_scheduler::load_events_from_db()
  - add Event_timed::kill_thread()
  - implement event_timed_*_equal()
  - made change_security_context() and restore_security_context() free functions.
  - Comments cleanups
sql/lex.h:
  new word scheduler for SHOW SCHEDULER STATUS (available only debug builds)
sql/log.cc:
  move these from event_scheduler.cc
sql/mysql_priv.h:
  refactor kill_one_thread
  export sql_print_message_func and sql_print_message_handlers
sql/mysqld.cc:
  In close_connections, called by kill_server() skip the main scheduler
  thread and use events_shutdown() for shutting down the scheduler, in the same
  manner it's done for RPL.
  Add a new value to --event-scheduler :
  0 <- No scheduler available
  1 <- Start with scheduler enabled
  2 <- Start with scheduler suspended
sql/repl_failsafe.cc:
  refactor thd::system_thread to be an enum
sql/set_var.cc:
  move sys_var_event_executor::update() to set_var.cc
  executor -> scheduler
  use thd::sys_var_tmp
sql/set_var.h:
  executor -> scheduler
sql/share/errmsg.txt:
  3 new error messages
sql/sql_class.cc:
  refactor thd::system_thread to be an enum . more type-safety
sql/sql_class.h:
  refactor thd::system_thread to be an enum . more type-safety
sql/sql_db.cc:
  get the error from evex_drop_schema_events
sql/sql_error.h:
  export warning_level_names
sql/sql_lex.h:
  new command SHOW SCHEDULER STATUS, available only in debug build and
  for debug purposes.
sql/sql_parse.cc:
  refactor kill_one_thread() -> does the *dirty* work, and sql_kill
  just the reporting.
  add handler for SQLCOM_SHOW_SCHEDULER_STATUS
sql/sql_show.cc:
  fix verbosity handling (this will be obsoleted anyway by the fix for 17394).
sql/sql_yacc.yy:
  remove FULL from SHOW EVENTS
  add SHOW SCHEDULER STATUS in debug builds
sql/table.cc:
  Fix valgrind warning.
2006-05-22 20:46:13 +02:00

297 lines
6.0 KiB
C++

#ifndef _EVENT_H_
#define _EVENT_H_
/* Copyright (C) 2004-2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define EVEX_OK 0
#define EVEX_KEY_NOT_FOUND -1
#define EVEX_OPEN_TABLE_FAILED -2
#define EVEX_WRITE_ROW_FAILED -3
#define EVEX_DELETE_ROW_FAILED -4
#define EVEX_GET_FIELD_FAILED -5
#define EVEX_PARSE_ERROR -6
#define EVEX_INTERNAL_ERROR -7
#define EVEX_NO_DB_ERROR -8
#define EVEX_COMPILE_ERROR -19
#define EVEX_GENERAL_ERROR -20
#define EVEX_BAD_IDENTIFIER -21
#define EVEX_BODY_TOO_LONG -22
#define EVEX_BAD_PARAMS -23
#define EVEX_NOT_RUNNING -24
#define EVEX_MICROSECOND_UNSUP -25
#define EVEX_CANT_KILL -26
#define EVENT_EXEC_NO_MORE (1L << 0)
#define EVENT_NOT_USED (1L << 1)
#define EVENT_FREE_WHEN_FINISHED (1L << 2)
class Event_timed;
class Events
{
public:
static ulong opt_event_scheduler;
static TYPELIB opt_typelib;
enum enum_table_field
{
FIELD_DB = 0,
FIELD_NAME,
FIELD_BODY,
FIELD_DEFINER,
FIELD_EXECUTE_AT,
FIELD_INTERVAL_EXPR,
FIELD_TRANSIENT_INTERVAL,
FIELD_CREATED,
FIELD_MODIFIED,
FIELD_LAST_EXECUTED,
FIELD_STARTS,
FIELD_ENDS,
FIELD_STATUS,
FIELD_ON_COMPLETION,
FIELD_SQL_MODE,
FIELD_COMMENT,
FIELD_COUNT /* a cool trick to count the number of fields :) */
};
static int
create_event(THD *thd, Event_timed *et, uint create_options,
uint *rows_affected);
static int
update_event(THD *thd, Event_timed *et, sp_name *new_name,
uint *rows_affected);
static int
drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
uint *rows_affected);
static int
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
static int
show_create_event(THD *thd, sp_name *spn, LEX_STRING definer);
static int
reconstruct_interval_expression(String *buf, interval_type interval,
longlong expression);
static int
drop_schema_events(THD *thd, char *db);
static int
dump_internal_status(THD *thd);
static int
init();
static void
shutdown();
static void
init_mutexes();
static void
destroy_mutexes();
private:
/* Prevent use of these */
Events(const Events &);
void operator=(Events &);
};
class sp_head;
class Event_timed
{
Event_timed(const Event_timed &); /* Prevent use of these */
void operator=(Event_timed &);
my_bool in_spawned_thread;
ulong locked_by_thread_id;
my_bool running;
ulong thread_id;
pthread_mutex_t LOCK_running;
pthread_cond_t COND_finished;
bool status_changed;
bool last_executed_changed;
public:
enum enum_status
{
ENABLED = 1,
DISABLED
};
enum enum_on_completion
{
ON_COMPLETION_DROP = 1,
ON_COMPLETION_PRESERVE
};
TIME last_executed;
LEX_STRING dbname;
LEX_STRING name;
LEX_STRING body;
LEX_STRING definer_user;
LEX_STRING definer_host;
LEX_STRING definer;// combination of user and host
LEX_STRING comment;
TIME starts;
TIME ends;
TIME execute_at;
my_bool starts_null;
my_bool ends_null;
my_bool execute_at_null;
longlong expression;
interval_type interval;
ulonglong created;
ulonglong modified;
enum enum_on_completion on_completion;
enum enum_status status;
sp_head *sphead;
ulong sql_mode;
const uchar *body_begin;
bool dropped;
bool free_sphead_on_delete;
uint flags;//all kind of purposes
static void *operator new(size_t size)
{
void *p;
DBUG_ENTER("Event_timed::new(size)");
p= my_malloc(size, MYF(0));
DBUG_PRINT("info", ("alloc_ptr=0x%lx", p));
DBUG_RETURN(p);
}
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
static void operator delete(void *ptr, size_t size)
{
DBUG_ENTER("Event_timed::delete(ptr,size)");
DBUG_PRINT("enter", ("free_ptr=0x%lx", ptr));
TRASH(ptr, size);
my_free((gptr) ptr, MYF(0));
DBUG_VOID_RETURN;
}
static void operator delete(void *ptr, MEM_ROOT *mem_root)
{
/*
Don't free the memory it will be done by the mem_root but
we need to call the destructor because we free other resources
which are not allocated on the root but on the heap, or we
deinit mutexes.
*/
DBUG_ASSERT(0);
}
Event_timed();
~Event_timed();
void
init();
void
deinit_mutexes();
int
init_definer(THD *thd);
int
init_execute_at(THD *thd, Item *expr);
int
init_interval(THD *thd, Item *expr, interval_type new_interval);
void
init_name(THD *thd, sp_name *spn);
int
init_starts(THD *thd, Item *starts);
int
init_ends(THD *thd, Item *ends);
void
init_body(THD *thd);
void
init_comment(THD *thd, LEX_STRING *set_comment);
int
load_from_row(MEM_ROOT *mem_root, TABLE *table);
bool
compute_next_execution_time();
int
drop(THD *thd);
void
mark_last_executed(THD *thd);
bool
update_fields(THD *thd);
int
get_create_event(THD *thd, String *buf);
int
execute(THD *thd, MEM_ROOT *mem_root);
int
compile(THD *thd, MEM_ROOT *mem_root);
bool
is_running();
int
spawn_now(void * (*thread_func)(void*), void *arg);
bool
spawn_thread_finish(THD *thd);
void
free_sp();
bool
has_equal_db(Event_timed *etn);
int
kill_thread(THD *thd);
void
set_thread_id(ulong tid) { thread_id= tid; }
};
#endif /* _EVENT_H_ */