Commit 99adbd13 authored by unknown's avatar unknown
Browse files

WL#3337 (Event scheduler new architecture)

Post-review fixes. Mostly whitespace, int-to-bool return value, fixed comments


sql/Makefile.am:
  compile all submodules of Events before compiling the facade
sql/event_data_objects.cc:
  - Use initialization list
  - Clean whitespaces
  - Shorten comments
  - Fix comments
sql/event_data_objects.h:
  - Fix whitespace
sql/event_db_repository.cc:
  - Change return type from int to bool where only one error code is
    returned.
  - Don't use macros but get the maximal number of characters in a column
    from the column
  - Fix  comments
  - Make functions which has return value but it's not used - void.
sql/event_db_repository.h:
  - Methods with only one error code int -> bool return value
  - Remove declaration of fill_schema_events, a function that does not exist
sql/event_queue.cc:
  - Use initialization lists
  - Let find_n_remove_event delete the object thus making the code more robust.
    The caller could forget to destruct the object. In addition, find_n_remove_element()
    does not return a value.
  - Move check_system_tables() to class Events
  - Fix comments
sql/event_queue.h:
  - Whitespace changes
  - init_queue() should allow passing of THD
  - check_system_tables moved to class Events
  - find_n_remove_event() is now void
sql/event_scheduler.cc:
  - Initialize res before use
  - Remove end stop from message
sql/event_scheduler.h:
  Add uninitialized state. The scheduler is in it before init_scheduler()
  is called. The rationale is that otherwise state has no value before
  the call. If the system tables were damaged the scheduler won't be initialized
  but in Events::deinit() Event_scheduler::stop() will be called and this will
  touch state, generating valgrind warning at minimum.
sql/events.cc:
  - Whitespace changes
  - Fix comments
  - Make methods which have only one error code be bool instead of int
  - Create temporarily a THD to be used for the initialization of Event_queue
  - Event_queue::check_system_tables() moved to Events::check_system_tables
  - is_started() is renamed to is_execution_of_events_started()
sql/events.h:
  - Whitespace changes
  - When a method returns only one error code it should be bool, not int
  - is_started() renamed to is_execution_of_events_started()
sql/set_var.cc:
  is_started() is renamed to is_execution_of_events_started()
sql/sql_db.cc:
  The return code is not used, thus don't return anything and drop_schema_events()
  is now void.
sql/sql_yacc.yy:
  - Fix comments
  - Remove unneeded initialization which is performed in lex_init()
sql/share/errmsg.txt:
  New error message
sql/table.cc:
  - Fix comments
  - make table_check_intact() accespt const *table_def
sql/table.h:
  Make table_check_intact() accespt const *table_def
parent e5a2cb50
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -105,8 +105,8 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
			tztime.cc my_time.c my_user.c my_decimal.cc\
			sp_head.cc sp_pcontext.cc  sp_rcontext.cc sp.cc \
			sp_cache.cc parse_file.cc sql_trigger.cc \
                        event_scheduler.cc events.cc event_data_objects.cc \
                        event_queue.cc event_db_repository.cc \
                        event_scheduler.cc event_data_objects.cc \
                        event_queue.cc event_db_repository.cc events.cc \
			sql_plugin.cc sql_binlog.cc \
			sql_builtin.cc sql_tablespace.cc partition_info.cc

+36 −30
Original line number Diff line number Diff line
@@ -59,19 +59,17 @@ Event_parse_data::new_instance(THD *thd)
*/

Event_parse_data::Event_parse_data()
  :on_completion(ON_COMPLETION_DROP), status(ENABLED),
   item_starts(NULL), item_ends(NULL), item_execute_at(NULL),
   starts_null(TRUE), ends_null(TRUE), execute_at_null(TRUE),
   item_expression(NULL), expression(0)
{
  DBUG_ENTER("Event_parse_data::Event_parse_data");

  item_execute_at= item_expression= item_starts= item_ends= NULL;
  status= ENABLED;
  on_completion= ON_COMPLETION_DROP;
  expression= 0;

  /* Actually in the parser STARTS is always set */
  set_zero_time(&starts, MYSQL_TIMESTAMP_DATETIME);
  set_zero_time(&ends, MYSQL_TIMESTAMP_DATETIME);
  set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
  starts_null= ends_null= execute_at_null= TRUE;

  body.str= comment.str= NULL;
  body.length= comment.length= 0;
@@ -736,8 +734,8 @@ Event_timed::~Event_timed()
    Event_job_data::Event_job_data()
*/

Event_job_data::Event_job_data():
  thd(NULL), sphead(NULL), sql_mode(0)
Event_job_data::Event_job_data()
  :thd(NULL), sphead(NULL), sql_mode(0)
{
}

@@ -1115,14 +1113,16 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec,
    interval.month= (diff_months / months)*months;
    /*
      Check if the same month as last_exec (always set - prerequisite)
      An event happens at most once per month so there is no way to schedule
      it two times for the current month. This saves us from two calls to
      date_add_interval() if the event was just executed.  But if the scheduler
      is started and there was at least 1 scheduled date skipped this one does
      not help and two calls to date_add_interval() will be done, which is a
      bit more expensive but compared to the rareness of the case is neglectable.
      An event happens at most once per month so there is no way to
      schedule it two times for the current month. This saves us from two
      calls to date_add_interval() if the event was just executed.  But if
      the scheduler is started and there was at least 1 scheduled date
      skipped this one does not help and two calls to date_add_interval()
      will be done, which is a bit more expensive but compared to the
      rareness of the case is neglectable.
    */
    if (time_now->year==last_exec->year && time_now->month==last_exec->month)
    if (time_now->year == last_exec->year &&
        time_now->month == last_exec->month)
      interval.month+= months;

    tmp= *start;
@@ -1454,7 +1454,8 @@ Event_queue_element::drop(THD *thd)

  RETURN VALUE
    FALSE   OK
    TRUE    Error while opening mysql.event for writing or during write on disk
    TRUE    Error while opening mysql.event for writing or during
            write on disk
*/

bool
@@ -1645,9 +1646,9 @@ Event_job_data::execute(THD *thd)
  event_change_security_context(thd, 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
    on a mem_root.
    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 on a mem_root.
  */
  thd->db= my_strdup(dbname.str, MYF(0));
  thd->db_length= dbname.length;
@@ -1719,7 +1720,6 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root)

  switch (get_fake_create_event(thd, &show_create)) {
  case EVEX_MICROSECOND_UNSUP:
    sql_print_error("Scheduler");
    DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
  case 0:
    break;
@@ -1769,7 +1769,8 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root)
      Free lex associated resources
      QQ: Do we really need all this stuff here?
    */
    sql_print_error("error during compile of %s.%s or thd->is_fatal_error=%d",
    sql_print_error("SCHEDULER: Error during compilation of %s.%s or "
                    "thd->is_fatal_error=%d",
                    dbname.str, name.str, thd->is_fatal_error);

    lex.unit.cleanup();
@@ -1832,10 +1833,13 @@ event_basic_db_equal(LEX_STRING db, Event_basic *et)


/*
  Checks whether two events are equal by identifiers
  Checks whether an event has equal `db` and `name`

  SYNOPSIS
    event_basic_identifier_equal()
      db   Schema
      name Name
      et   The event object

  RETURN VALUE
    TRUE   Equal
@@ -1851,7 +1855,8 @@ event_basic_identifier_equal(LEX_STRING db, LEX_STRING name, Event_basic *b)


/*
  Switches the security context
  Switches the security context.

  SYNOPSIS
    event_change_security_context()
      thd     Thread
@@ -1887,7 +1892,8 @@ event_change_security_context(THD *thd, LEX_STRING user, LEX_STRING host,


/*
  Restores the security context
  Restores the security context.

  SYNOPSIS
    event_restore_security_context()
      thd     Thread
+4 −4
Original line number Diff line number Diff line
@@ -237,7 +237,7 @@ class Event_parse_data : public Sql_alloc
  new_instance(THD *thd);

  bool
  check_parse_data(THD *);
  check_parse_data(THD *thd);

  void
  init_body(THD *thd);
+66 −86
Original line number Diff line number Diff line
@@ -22,14 +22,12 @@
#include "sp.h"
#include "sp_head.h"

#define EVEX_DB_FIELD_LEN 64
#define EVEX_NAME_FIELD_LEN 64


static
time_t mysql_event_last_create_time= 0L;

static
TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] =
TABLE_FIELD_W_TYPE const event_table_fields[ET_FIELD_COUNT] =
{
  {
    {(char *) STRING_WITH_LEN("db")},
@@ -250,18 +248,18 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
/*
  Performs an index scan of event_table (mysql.event) and fills schema_table.

  Synopsis
  SYNOPSIS
    Event_db_repository::index_read_for_db_for_i_s()
      thd          Thread
      schema_table The I_S.EVENTS table
      event_table  The event table to use for loading (mysql.event)

  Returns
  RETURN VALUE
    0  OK
    1  Error
*/

int
bool
Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table,
                                               TABLE *event_table, char *db)
{
@@ -305,33 +303,34 @@ Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table,
  event_table->file->ha_index_end(); 
  /*  ret is guaranteed to be != 0 */
  if (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND)
    DBUG_RETURN(0);
  DBUG_RETURN(1);
    DBUG_RETURN(FALSE);

  DBUG_RETURN(TRUE);
}


/*
  Performs a table scan of event_table (mysql.event) and fills schema_table.

  Synopsis
  SYNOPSIS
    Events_db_repository::table_scan_all_for_i_s()
      thd          Thread
      schema_table The I_S.EVENTS in memory table
      event_table  The event table to use for loading.

  Returns
    0  OK
    1  Error
  RETURN VALUE
    FALSE  OK
    TRUE   Error
*/

int
bool
Event_db_repository::table_scan_all_for_i_s(THD *thd, TABLE *schema_table,
                                            TABLE *event_table)
{
  int ret;
  READ_RECORD read_record_info;

  DBUG_ENTER("Event_db_repository::table_scan_all_for_i_s");

  init_read_record(&read_record_info, thd, event_table, NULL, 1, 0);

  /*
@@ -350,7 +349,7 @@ Event_db_repository::table_scan_all_for_i_s(THD *thd, TABLE *schema_table,
  end_read_record(&read_record_info);

  /*  ret is guaranteed to be != 0 */
  DBUG_RETURN(ret == -1? 0:1);
  DBUG_RETURN(ret == -1? FALSE:TRUE);
}


@@ -358,15 +357,15 @@ Event_db_repository::table_scan_all_for_i_s(THD *thd, TABLE *schema_table,
  Fills I_S.EVENTS with data loaded from mysql.event. Also used by
  SHOW EVENTS

  Synopsis
  SYNOPSIS
    Event_db_repository::fill_schema_events()
      thd     Thread
      tables  The schema table
      db      If not NULL then get events only from this schema

  Returns
    0  OK
    1  Error
  RETURN VALUE
    FALSE  OK
    TRUE   Error
*/

int
@@ -459,12 +458,12 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type,

  SYNOPSIS
    check_parse_params()
       thd            THD
       et             event's data
      thd         Thread context
      parse_data  Event's data
  
   RETURNS
     0                OK
     EVEX_BAD_PARAMS  Error (reported)
  RETURN VALUE
    FALSE  OK
    TRUE   Error (reported)
*/

static int
@@ -504,7 +503,7 @@ check_parse_params(THD *thd, Event_parse_data *parse_data)
  SYNOPSIS
    Event_db_repository::create_event()
      thd             [in]  THD
      et              [in]  Object containing info about the event
      parse_data      [in]  Object containing info about the event
      create_if_not   [in]  Whether to generate anwarning in case event exists
      rows_affected   [out] How many rows were affected

@@ -517,7 +516,7 @@ check_parse_params(THD *thd, Event_parse_data *parse_data)
    ::update_event. The name of the event is inside "et".
*/

int
bool
Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
                                  my_bool create_if_not, uint *rows_affected)
{
@@ -531,6 +530,9 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
  DBUG_ENTER("Event_db_repository::create_event");

  *rows_affected= 0;
  if (check_parse_params(thd, parse_data))
    goto err;

  DBUG_PRINT("info", ("open mysql.event for update"));
  if (open_event_table(thd, TL_WRITE, &table))
  {
@@ -538,8 +540,6 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
    goto err;
  }

  if (check_parse_params(thd, parse_data))
    goto err;

  DBUG_PRINT("info", ("name: %.*s", parse_data->name.length,
             parse_data->name.str));
@@ -570,16 +570,17 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,

  if (system_charset_info->cset->
        numchars(system_charset_info, parse_data->dbname.str,
                 parse_data->dbname.str +
                 parse_data->dbname.length) > EVEX_DB_FIELD_LEN)
                 parse_data->dbname.str + parse_data->dbname.length) >
      table->field[ET_FIELD_DB]->char_length())
  {
    my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->dbname.str);
    goto err;
  }

  if (system_charset_info->cset->
        numchars(system_charset_info, parse_data->name.str,
                 parse_data->name.str +
                 parse_data->name.length) > EVEX_DB_FIELD_LEN)
                 parse_data->name.str + parse_data->name.length) >
      table->field[ET_FIELD_NAME]->char_length())
  {
    my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->name.str);
    goto err;
@@ -622,36 +623,18 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
  if (dbchanged)
    (void) mysql_change_db(thd, old_db.str, 1);
  /*
    When valgrinded, the following call may lead to the following error:
    
    Syscall param pwrite64(buf) points to uninitialised byte(s)
      at 0x406003B: do_pwrite64 (in /lib/tls/libpthread.so.0)
      by 0x40600EF: pwrite64 (in /lib/tls/libpthread.so.0)
      by 0x856FF74: my_pwrite (my_pread.c:146)
      by 0x85734E1: flush_cached_blocks (mf_keycache.c:2280)
    ....
    Address 0x6618110 is 56 bytes inside a block of size 927,772 alloc'd
     at 0x401C451: malloc (vg_replace_malloc.c:149)
      by 0x8578CDC: _mymalloc (safemalloc.c:138)
      by 0x858E5E2: my_large_malloc (my_largepage.c:65)
      by 0x8570634: init_key_cache (mf_keycache.c:343)
      by 0x82EDA51: ha_init_key_cache(char const*, st_key_cache*) (handler.cc:2509)
      by 0x8212071: process_key_caches(int (*)(char const*, st_key_cache*))
                                                                  (set_var.cc:3824)
      by 0x8206D75: init_server_components() (mysqld.cc:3304)
      by 0x8207163: main (mysqld.cc:3578)

    I think it is safe not to think about it.
    This statement may cause a spooky valgrind warning at startup
    inside init_key_cache on my system (ahristov, 2006/08/10) 
  */
  close_thread_tables(thd);
  DBUG_RETURN(0);
  DBUG_RETURN(FALSE);

err:
  if (dbchanged)
    (void) mysql_change_db(thd, old_db.str, 1);
  if (table)
    close_thread_tables(thd);
  DBUG_RETURN(EVEX_GENERAL_ERROR);
  DBUG_RETURN(TRUE);
}


@@ -665,8 +648,8 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
      et       event's data

  RETURN VALUE
    0  OK
    EVEX_GENERAL_ERROR  Error occured and reported
    FALSE  OK
    TRUE   Error (reported)

  NOTES
    sp_name is passed since this is the name of the event to
@@ -679,7 +662,6 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
{
  CHARSET_INFO *scs= system_charset_info;
  TABLE *table= NULL;
  int ret;
  DBUG_ENTER("Event_db_repository::update_event");

  if (open_event_table(thd, TL_WRITE, &table))
@@ -698,7 +680,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
    DBUG_PRINT("info", ("rename to: %s@%s", new_dbname->str, new_name->str));

  /* first look whether we overwrite */
  if (new_dbname)
  if (new_name)
  {
    if (!sortcmp_lex_string(parse_data->name, *new_name, scs) &&
        !sortcmp_lex_string(parse_data->dbname, *new_dbname, scs))
@@ -747,9 +729,10 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
  if (end_active_trans(thd))
    goto err;

  if (table->file->ha_update_row(table->record[1], table->record[0]))
  int res;
  if ((res= table->file->ha_update_row(table->record[1], table->record[0])))
  {
    my_error(ER_EVENT_STORE_FAILED, MYF(0), parse_data->name.str, ret);
    my_error(ER_EVENT_STORE_FAILED, MYF(0), parse_data->name.str, res);
    goto err;
  }

@@ -887,16 +870,14 @@ Event_db_repository::find_named_event(THD *thd, LEX_STRING db, LEX_STRING name,
    Event_db_repository::drop_schema_events()
      thd     Thread
      schema  The database to clean from events

  RETURN VALUE
    0  OK
   !0  Error (Reported)
*/

int
void
Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
{
  return drop_events_by_field(thd, ET_FIELD_DB, schema);
  DBUG_ENTER("Event_db_repository::drop_schema_events");
  drop_events_by_field(thd, ET_FIELD_DB, schema);
  DBUG_VOID_RETURN;
}


@@ -909,28 +890,29 @@ Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
      table       mysql.event TABLE
      field       Which field of the row to use for matching
      field_value The value that should match

  RETURN VALUE
     0  OK
    !0  Error from ha_delete_row
*/

int
void
Event_db_repository::drop_events_by_field(THD *thd,  
                                          enum enum_events_table_field field,
                                          LEX_STRING field_value)
{
  int ret= 0;
  TABLE *table= NULL;
  Open_tables_state backup;
  READ_RECORD read_record_info;
  DBUG_ENTER("Event_db_repository::drop_events_by_field");  
  DBUG_PRINT("enter", ("field=%d field_value=%s", field, field_value.str));

  if (open_event_table(thd, TL_WRITE, &table))
  {
    /*
      Currently being used only for DROP DATABASE - In this case we don't need
      error message since the OK packet has been sent. But for DROP USER we
      could need it.

      my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
    DBUG_RETURN(1);
    */
    DBUG_VOID_RETURN;
  }

  /* only enabled events are in memory, so we go now and delete the rest */
@@ -946,15 +928,13 @@ Event_db_repository::drop_events_by_field(THD *thd,
    if (!sortcmp_lex_string(et_field_lex, field_value, system_charset_info))
    {
      DBUG_PRINT("info", ("Dropping"));
      if ((ret= table->file->ha_delete_row(table->record[0])))
        my_error(ER_EVENT_DROP_FAILED, MYF(0),
                 get_field(thd->mem_root, table->field[ET_FIELD_NAME]));
      ret= table->file->ha_delete_row(table->record[0]);
    }
  }
  end_read_record(&read_record_info);
  thd->version--;   /* Force close to free memory */
  close_thread_tables(thd);

  DBUG_RETURN(ret);
  DBUG_VOID_RETURN;
}


@@ -964,10 +944,10 @@ Event_db_repository::drop_events_by_field(THD *thd,

  SYNOPSIS
    Event_db_repository::load_named_event()
      thd      [in]  THD
      thd      [in]  Thread context
      dbname   [in]  Event's db name
      name     [in]  Event's name
      etn_new  [out] The loaded event
      etn      [out] The loaded event

  RETURN VALUE
    FALSE  OK
+5 −9
Original line number Diff line number Diff line
@@ -47,9 +47,6 @@ events_table_index_read_for_db(THD *thd, TABLE *schema_table,
int
events_table_scan_all(THD *thd, TABLE *schema_table, TABLE *event_table);

int
fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */);

class Event_basic;
class Event_parse_data;

@@ -58,7 +55,7 @@ class Event_db_repository
public:
  Event_db_repository(){}

  int
  bool
  create_event(THD *thd, Event_parse_data *parse_data, my_bool create_if_not,
               uint *rows_affected);

@@ -70,7 +67,7 @@ class Event_db_repository
  drop_event(THD *thd, LEX_STRING db, LEX_STRING name, bool drop_if_exists,
             uint *rows_affected);

  int
  void
  drop_schema_events(THD *thd, LEX_STRING schema);

  bool
@@ -79,7 +76,6 @@ class Event_db_repository
  bool
  load_named_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_basic *et);


  int
  open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);

@@ -87,14 +83,14 @@ class Event_db_repository
  fill_schema_events(THD *thd, TABLE_LIST *tables, char *db);

private:
  int
  void
  drop_events_by_field(THD *thd, enum enum_events_table_field field,
                       LEX_STRING field_value);
  int
  bool
  index_read_for_db_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table,
                            char *db);

  int
  bool
  table_scan_all_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table);

  static bool
Loading