Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
b7578df0
Commit
b7578df0
authored
Dec 07, 2005
by
andrey@lmy004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WL #1034 updates after review
parent
bee85987
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
168 additions
and
172 deletions
+168
-172
sql/event.cc
sql/event.cc
+68
-83
sql/event_executor.cc
sql/event_executor.cc
+83
-83
sql/event_priv.h
sql/event_priv.h
+3
-0
sql/event_timed.cc
sql/event_timed.cc
+14
-6
No files found.
sql/event.cc
View file @
b7578df0
...
...
@@ -27,8 +27,6 @@
- Use timestamps instead of datetime.
- Don't use SP's functionality for opening and closing of tables
- CREATE EVENT should not go into binary log! Does it now? The SQL statements
issued by the EVENT are replicated.
I have an idea how to solve the problem at failover. So the status field
...
...
@@ -44,14 +42,6 @@
ENABLED to DISABLED status change and this is safe for replicating. As well
an event may be deleted which is also safe for RBR.
- Add a lock and use it for guarding access to events_array dynamic array.
- Add checks everywhere where new instance of THD is created. NULL can be
returned and this will crash the server. The server will crash probably
later but should not be in this code! Add a global variable, and a lock
to guard it, that will specify an error in a worker thread so preventing
new threads from being spawned.
- Maybe move all allocations during parsing to evex_mem_root thus saving
double parsing in evex_create_event!
...
...
@@ -60,15 +50,8 @@
- What happens if one renames an event in the DB while it is in memory?
Or even deleting it?
- created & modified in the table should be UTC?
- Add a lock to event_timed to serialize execution of an event - do not
allow parallel executions. Hmm, however how last_executed is marked
then? The call to event_timed::mark_last_executed() must be moved to
event_timed::execute()?
- Consider using conditional variable when doing shutdown instead of
waiting
some time (tries < 5)
.
waiting
till all worker threads end
.
- Make event_timed::get_show_create_event() work
- Add function documentation whenever needed.
- Add logging to file
...
...
@@ -77,7 +60,7 @@
- For now parallel execution is not possible because the same sp_head cannot be
executed few times!!! There is still no lock attached to particular event.
*/
*/
...
...
@@ -216,17 +199,17 @@ TABLE *evex_open_event_table(THD *thd, enum thr_lock_type lock_type)
table TABLE object for open mysql.event table.
RETURN VALUE
SP_OK
- Routine found
0
- Routine found
SP_KEY_NOT_FOUND- No routine with given name
*/
int
evex_db_find_routine_aux
(
THD
*
thd
,
const
LEX_STRING
dbname
,
const
LEX_STRING
r
name
,
TABLE
*
table
)
const
LEX_STRING
ev_
name
,
TABLE
*
table
)
{
byte
key
[
MAX_KEY_LENGTH
];
// db, name, optional key length type
DBUG_ENTER
(
"evex_db_find_routine_aux"
);
DBUG_PRINT
(
"enter"
,
(
"name: %.*s"
,
rname
.
length
,
r
name
.
str
));
DBUG_PRINT
(
"enter"
,
(
"name: %.*s"
,
ev_name
.
length
,
ev_
name
.
str
));
/*
Create key to find row. We have to use field->store() to be able to
...
...
@@ -235,16 +218,16 @@ evex_db_find_routine_aux(THD *thd, const LEX_STRING dbname,
'db' and 'name' and the first key is the primary key over the
same fields.
*/
if
(
r
name
.
length
>
table
->
field
[
1
]
->
field_length
)
DBUG_RETURN
(
SP
_KEY_NOT_FOUND
);
if
(
ev_
name
.
length
>
table
->
field
[
1
]
->
field_length
)
DBUG_RETURN
(
EVEX
_KEY_NOT_FOUND
);
table
->
field
[
0
]
->
store
(
dbname
.
str
,
dbname
.
length
,
&
my_charset_bin
);
table
->
field
[
1
]
->
store
(
rname
.
str
,
r
name
.
length
,
&
my_charset_bin
);
table
->
field
[
1
]
->
store
(
ev_name
.
str
,
ev_
name
.
length
,
&
my_charset_bin
);
key_copy
(
key
,
table
->
record
[
0
],
table
->
key_info
,
table
->
key_info
->
key_length
);
if
(
table
->
file
->
index_read_idx
(
table
->
record
[
0
],
0
,
key
,
table
->
key_info
->
key_length
,
HA_READ_KEY_EXACT
))
DBUG_RETURN
(
SP
_KEY_NOT_FOUND
);
DBUG_RETURN
(
EVEX
_KEY_NOT_FOUND
);
DBUG_RETURN
(
0
);
}
...
...
@@ -394,19 +377,18 @@ db_create_event(THD *thd, event_timed *et)
restore_record
(
table
,
s
->
default_values
);
// Get default values for fields
/* TODO : Uncomment these and add handling in sql_parse.cc or here
if (
sp->m_name.length > table->field[MYSQL_PROC
_FIELD_NAME]->field_length)
if
(
et
->
m_name
.
length
>
table
->
field
[
EVEX
_FIELD_NAME
]
->
field_length
)
{
ret= SP_BAD_IDENTIFIER
;
goto
done
;
my_error
(
ER_TOO_LONG_IDENT
,
MYF
(
0
),
et
->
m_name
.
str
)
;
goto
err
;
}
if (
sp->m_body.length > table->field[MYSQL_PROC
_FIELD_BODY]->field_length)
if
(
et
->
m_body
.
length
>
table
->
field
[
EVEX
_FIELD_BODY
]
->
field_length
)
{
ret= SP_BODY_TOO_LONG
;
goto
done
;
my_error
(
ER_TOO_LONG_BODY
,
MYF
(
0
),
et
->
m_name
.
str
)
;
goto
err
;
}
*/
if
(
!
(
et
->
m_expr
)
&&
!
(
et
->
m_execute_at
.
year
))
{
DBUG_PRINT
(
"error"
,
(
"neither m_expr nor m_execute_as are set!"
));
...
...
@@ -434,7 +416,8 @@ db_create_event(THD *thd, event_timed *et)
my_error
(
ER_EVENT_STORE_FAILED
,
MYF
(
0
),
et
->
m_name
.
str
);
goto
err
;
}
else
if
(
mysql_bin_log
.
is_open
())
if
(
mysql_bin_log
.
is_open
())
{
thd
->
clear_error
();
/* Such a statement can always go directly to binlog, no trans cache */
...
...
@@ -472,20 +455,20 @@ static int
db_update_event
(
THD
*
thd
,
sp_name
*
name
,
event_timed
*
et
)
{
TABLE
*
table
;
int
ret
;
int
ret
=
EVEX_OPEN_TABLE_FAILED
;
DBUG_ENTER
(
"db_update_event"
);
DBUG_PRINT
(
"enter"
,
(
"name: %.*s"
,
et
->
m_name
.
length
,
et
->
m_name
.
str
));
if
(
name
)
DBUG_PRINT
(
"enter"
,
(
"rename to: %.*s"
,
name
->
m_name
.
length
,
name
->
m_name
.
str
));
// Todo: Handle in sql_prepare.cc SP_OPEN_TABLE_FAILED
if
(
!
(
table
=
evex_open_event_table
(
thd
,
TL_WRITE
)))
{
my_error
(
ER_EVENT_OPEN_TABLE_FAILED
,
MYF
(
0
));
goto
err
;
}
if
(
evex_db_find_routine_aux
(
thd
,
et
->
m_db
,
et
->
m_name
,
table
)
==
SP_KEY_NOT_FOUND
)
if
(
EVEX_KEY_NOT_FOUND
==
evex_db_find_routine_aux
(
thd
,
et
->
m_db
,
et
->
m_name
,
table
))
{
my_error
(
ER_EVENT_DOES_NOT_EXIST
,
MYF
(
0
),
et
->
m_name
.
str
);
goto
err
;
...
...
@@ -526,8 +509,21 @@ db_update_event(THD *thd, sp_name *name, event_timed *et)
/*
Use sp_name for look up, return in **ett if found
Looks for a named event in mysql.event and in case of success returns
an object will data loaded from the table.
SYNOPSIS
db_find_event()
thd THD
name the name of the event to find
ett event's data if event is found
tbl TABLE object to use when not NULL
NOTES
1) Use sp_name for look up, return in **ett if found
2) tbl is not closed at exit
*/
static
int
db_find_event
(
THD
*
thd
,
sp_name
*
name
,
event_timed
**
ett
,
TABLE
*
tbl
)
{
...
...
@@ -581,6 +577,22 @@ db_find_event(THD *thd, sp_name *name, event_timed **ett, TABLE *tbl)
}
/*
Looks for a named event in mysql.event and then loads it from
the table, compiles it and insert it into the cache.
SYNOPSIS
evex_load_and_compile_event()
thd THD
spn the name of the event to alter
use_lock whether to obtain a lock on LOCK_event_arrays or not
RETURN VALUE
0 - OK
< 0 - error (in this case underlying functions call my_error()).
*/
static
int
evex_load_and_compile_event
(
THD
*
thd
,
sp_name
*
spn
,
bool
use_lock
)
{
...
...
@@ -727,7 +739,7 @@ evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock)
/*
Exported functions follow
-= Exported functions follow =-
*/
/*
...
...
@@ -754,15 +766,6 @@ evex_create_event(THD *thd, event_timed *et, uint create_options)
DBUG_PRINT
(
"enter"
,
(
"name: %*s options:%d"
,
et
->
m_name
.
length
,
et
->
m_name
.
str
,
create_options
));
/*
VOID(pthread_mutex_lock(&LOCK_evex_running));
if (!evex_is_running)
// TODO: put an warning to the user here.
// Is it needed? (Andrey, 051129)
{}
VOID(pthread_mutex_unlock(&LOCK_evex_running));
*/
if
((
ret
=
db_create_event
(
thd
,
et
))
==
EVEX_WRITE_ROW_FAILED
&&
(
create_options
&
HA_LEX_CREATE_IF_NOT_EXISTS
))
{
...
...
@@ -821,13 +824,6 @@ evex_update_event(THD *thd, sp_name *name, event_timed *et)
DBUG_ENTER
(
"evex_update_event"
);
DBUG_PRINT
(
"enter"
,
(
"name: %*s"
,
et
->
m_name
.
length
,
et
->
m_name
.
str
));
/*
VOID(pthread_mutex_lock(&LOCK_evex_running));
if (!evex_is_running)
// put an warning to the user here
{}
VOID(pthread_mutex_unlock(&LOCK_evex_running));
*/
/*
db_update_event() opens & closes the table to prevent
crash later in the code when loading and compiling the new definition
...
...
@@ -837,17 +833,8 @@ evex_update_event(THD *thd, sp_name *name, event_timed *et)
VOID
(
pthread_mutex_lock
(
&
LOCK_evex_running
));
if
(
!
evex_is_running
)
{
// not running - therefore no memory structures
VOID
(
pthread_mutex_unlock
(
&
LOCK_evex_running
));
goto
done
;
}
VOID
(
pthread_mutex_unlock
(
&
LOCK_evex_running
));
UNLOCK_MUTEX_AND_BAIL_OUT
(
LOCK_evex_running
,
done
);
/*
It is possible that 2 (or 1) pass(es) won't find the event in memory.
The reason is that DISABLED events are not cached.
*/
VOID
(
pthread_mutex_lock
(
&
LOCK_event_arrays
));
evex_remove_from_cache
(
&
et
->
m_db
,
&
et
->
m_name
,
false
);
if
(
et
->
m_status
==
MYSQL_EVENT_ENABLED
)
...
...
@@ -860,9 +847,14 @@ evex_update_event(THD *thd, sp_name *name, event_timed *et)
delete
spn
;
}
VOID
(
pthread_mutex_unlock
(
&
LOCK_event_arrays
));
VOID
(
pthread_mutex_unlock
(
&
LOCK_evex_running
));
done:
/*
It is possible that 2 (or 1) pass(es) won't find the event in memory.
The reason is that DISABLED events are not cached.
*/
done:
DBUG_RETURN
(
ret
);
}
...
...
@@ -882,24 +874,17 @@ int
evex_drop_event
(
THD
*
thd
,
event_timed
*
et
,
bool
drop_if_exists
)
{
TABLE
*
table
;
int
ret
;
int
ret
=
EVEX_OPEN_TABLE_FAILED
;
bool
opened
;
DBUG_ENTER
(
"evex_drop_event"
);
/*
VOID(pthread_mutex_lock(&LOCK_evex_running));
if (!evex_is_running)
// put an warning to the user here
{}
VOID(pthread_mutex_unlock(&LOCK_evex_running));
*/
////
if
(
!
(
table
=
evex_open_event_table
(
thd
,
TL_WRITE
)))
DBUG_RETURN
(
SP_OPEN_TABLE_FAILED
);
ret
=
evex_db_find_routine_aux
(
thd
,
et
->
m_db
,
et
->
m_name
,
table
);
{
my_error
(
ER_EVENT_OPEN_TABLE_FAILED
,
MYF
(
0
));
goto
done
;
}
if
(
ret
==
EVEX_OK
)
if
(
!
(
ret
=
evex_db_find_routine_aux
(
thd
,
et
->
m_db
,
et
->
m_name
,
table
))
)
{
if
(
ret
=
table
->
file
->
delete_row
(
table
->
record
[
0
]))
{
...
...
sql/event_executor.cc
View file @
b7578df0
...
...
@@ -21,7 +21,7 @@
#define DBUG_FAULTY_THR2
static
uint
workers_count
;
extern
ulong
thread_created
;
pthread_mutex_t
LOCK_event_arrays
,
...
...
@@ -33,10 +33,8 @@ bool evex_is_running= false;
ulong
opt_event_executor
;
my_bool
event_executor_running_global_var
=
false
;
extern
ulong
thread_created
;
static
my_bool
evex_mutexes_initted
=
false
;
static
uint
workers_count
;
static
int
evex_load_events_from_db
(
THD
*
thd
);
...
...
@@ -48,8 +46,11 @@ evex_load_events_from_db(THD *thd);
the main thread or not.
*/
pthread_handler_t
event_executor_worker
(
void
*
arg
);
pthread_handler_t
event_executor_main
(
void
*
arg
);
pthread_handler_t
event_executor_worker
(
void
*
arg
);
pthread_handler_t
event_executor_main
(
void
*
arg
);
static
void
evex_init_mutexes
()
...
...
@@ -142,8 +143,8 @@ init_event_thread(THD* thd)
DBUG_RETURN
(
0
);
}
pthread_handler_t
event_executor_main
(
void
*
arg
)
pthread_handler_t
event_executor_main
(
void
*
arg
)
{
THD
*
thd
;
/* needs to be first for thread_stack */
ulonglong
iter_num
=
0
;
...
...
@@ -152,14 +153,11 @@ pthread_handler_t event_executor_main(void *arg)
DBUG_ENTER
(
"event_executor_main"
);
DBUG_PRINT
(
"event_executor_main"
,
(
"EVEX thread started"
));
VOID
(
pthread_mutex_lock
(
&
LOCK_evex_running
));
evex_is_running
=
true
;
event_executor_running_global_var
=
opt_event_executor
;
VOID
(
pthread_mutex_unlock
(
&
LOCK_evex_running
));
// init memory root
init_alloc_root
(
&
evex_mem_root
,
MEM_ROOT_BLOCK_SIZE
,
MEM_ROOT_PREALLOC
);
// needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
my_thread_init
();
...
...
@@ -196,6 +194,15 @@ pthread_handler_t event_executor_main(void *arg)
VOID
(
my_init_dynamic_array
(
&
evex_executing_queue
,
sizeof
(
event_timed
*
),
50
,
100
));
VOID
(
pthread_mutex_unlock
(
&
LOCK_event_arrays
));
/*
eventually manifest that we are running, not to crashe because of
usage of non-initialized memory structures.
*/
VOID
(
pthread_mutex_lock
(
&
LOCK_evex_running
));
evex_is_running
=
true
;
event_executor_running_global_var
=
opt_event_executor
;
VOID
(
pthread_mutex_unlock
(
&
LOCK_evex_running
));
if
(
evex_load_events_from_db
(
thd
))
goto
err
;
...
...
@@ -208,7 +215,6 @@ pthread_handler_t event_executor_main(void *arg)
my_ulonglong
cnt
;
DBUG_PRINT
(
"info"
,
(
"EVEX External Loop %d"
,
++
cnt
));
// sql_print_information("[EVEX] External Loop!");
thd
->
proc_info
=
"Sleeping"
;
my_sleep
(
1000000
);
// sleep 1s
if
(
!
event_executor_running_global_var
)
...
...
@@ -216,16 +222,13 @@ pthread_handler_t event_executor_main(void *arg)
time
(
&
now
);
my_tz_UTC
->
gmt_sec_to_TIME
(
&
time_now
,
now
);
VOID
(
pthread_mutex_lock
(
&
LOCK_event_arrays
));
for
(
i
=
0
;
(
i
<
evex_executing_queue
.
elements
)
&&
!
thd
->
killed
;
++
i
)
{
event_timed
**
p_et
=
dynamic_element
(
&
evex_executing_queue
,
i
,
event_timed
**
);
event_timed
*
et
=
*
p_et
;
// sql_print_information("[EVEX] External Loop 2!");
event_timed
*
et
=
*
dynamic_element
(
&
evex_executing_queue
,
i
,
event_timed
**
);
// printf("%llu\n", TIME_to_ulonglong_datetime(&et->m_execute_at));
if
(
!
event_executor_running_global_var
)
break
;
// soon we will do only continue (see the code a bit above)
break
;
thd
->
proc_info
=
"Iterating"
;
THD_CHECK_SENTRY
(
thd
);
...
...
@@ -233,7 +236,7 @@ pthread_handler_t event_executor_main(void *arg)
if this is the first event which is after time_now then no
more need to iterate over more elements since the array is sorted.
*/
if
(
et
->
m_execute_at
.
year
&&
if
(
et
->
m_execute_at
.
year
>
1969
&&
my_time_compare
(
&
time_now
,
&
et
->
m_execute_at
)
==
-
1
)
break
;
...
...
@@ -250,8 +253,7 @@ pthread_handler_t event_executor_main(void *arg)
if
(
pthread_create
(
&
th
,
NULL
,
event_executor_worker
,
(
void
*
)
et
))
{
sql_print_error
(
"Problem while trying to create a thread"
);
VOID
(
pthread_mutex_unlock
(
&
LOCK_event_arrays
));
goto
err
;
// for now finish execution of the Executor
UNLOCK_MUTEX_AND_BAIL_OUT
(
LOCK_event_arrays
,
err
);
}
#else
event_executor_worker
((
void
*
)
et
);
...
...
@@ -272,12 +274,12 @@ pthread_handler_t event_executor_main(void *arg)
j
=
0
;
while
(
j
<
i
&&
j
<
evex_executing_queue
.
elements
)
{
event_timed
**
p_et
=
dynamic_element
(
&
evex_executing_queue
,
j
,
event_timed
**
);
event_timed
*
et
=
*
p_et
;
event_timed
*
et
=
*
dynamic_element
(
&
evex_executing_queue
,
j
,
event_timed
**
);
if
(
et
->
m_flags
&
EVENT_EXEC_NO_MORE
||
et
->
m_status
==
MYSQL_EVENT_DISABLED
)
{
delete_dynamic_element
(
&
evex_executing_queue
,
j
);
DBUG_PRINT
(
""
,
(
"DELETING FROM EXECUTION QUEUE [%s.%s]"
,
et
->
m_db
.
str
,
et
->
m_name
.
str
));
DBUG_PRINT
(
"EVEX main thread"
,
(
"DELETING FROM EXECUTION QUEUE [%s.%s]"
,
et
->
m_db
.
str
,
et
->
m_name
.
str
));
// nulling the position, will delete later
if
(
et
->
m_dropped
)
{
...
...
@@ -301,29 +303,44 @@ pthread_handler_t event_executor_main(void *arg)
);
VOID
(
pthread_mutex_unlock
(
&
LOCK_event_arrays
));
}
// while (!thd->killed)
}
err:
// First manifest that this thread does not work and then destroy
VOID
(
pthread_mutex_lock
(
&
LOCK_evex_running
));
evex_is_running
=
false
;
VOID
(
pthread_mutex_unlock
(
&
LOCK_evex_running
));
sql_print_information
(
"Event executor stopping"
);
// LEX_STRINGs reside in the memory root and will be destroyed with it.
// Hence no need of delete but only freeing of SP
for
(
i
=
0
;
i
<
events_array
.
elements
;
++
i
)
{
event_timed
*
et
=
dynamic_element
(
&
events_array
,
i
,
event_timed
*
);
et
->
free_sp
();
}
// TODO Andrey: USE lock here!
/*
TODO: A better will be with a conditional variable
*/
/*
Read workers_count without lock, no need for locking.
In the worst case we have to wait 1sec more.
*/
while
(
workers_count
)
my_sleep
(
1000000
);
// 1s
/*
LEX_STRINGs reside in the memory root and will be destroyed with it.
Hence no need of delete but only freeing of SP
*/
for
(
i
=
0
;
i
<
events_array
.
elements
;
++
i
)
dynamic_element
(
&
events_array
,
i
,
event_timed
*
)
->
free_sp
();
VOID
(
pthread_mutex_lock
(
&
LOCK_event_arrays
));
// No need to use lock here if EVEX is not running but anyway
delete_dynamic
(
&
evex_executing_queue
);
delete_dynamic
(
&
events_array
);
VOID
(
pthread_mutex_unlock
(
&
LOCK_evex_running
));
thd
->
proc_info
=
"Clearing"
;
DBUG_ASSERT
(
thd
->
net
.
buff
!=
0
);
net_end
(
&
thd
->
net
);
// destructor will not free it, because we are weird
THD_CHECK_SENTRY
(
thd
);
pthread_mutex_lock
(
&
LOCK_thread_count
);
thread_count
--
;
thread_running
--
;
...
...
@@ -331,28 +348,6 @@ pthread_handler_t event_executor_main(void *arg)
delete
thd
;
pthread_mutex_unlock
(
&
LOCK_thread_count
);
/*
sleeping some time may help not crash the server. sleeping
is done to wait for spawned threads to finish.
TODO: A better will be with a conditional variable
*/
{
uint
tries
=
0
;
while
(
tries
++
<
5
)
{
VOID
(
pthread_mutex_lock
(
&
LOCK_workers_count
));
if
(
!
workers_count
)
{
VOID
(
pthread_mutex_unlock
(
&
LOCK_workers_count
));
break
;
}
VOID
(
pthread_mutex_unlock
(
&
LOCK_workers_count
));
DBUG_PRINT
(
"info"
,
(
"Sleep %d"
,
tries
));
my_sleep
(
1000000
*
tries
);
// 1s
}
DBUG_PRINT
(
"info"
,
(
"Maybe now it is ok to kill the thread and evex MRoot"
));
}
err_no_thd:
VOID
(
pthread_mutex_lock
(
&
LOCK_evex_running
));
...
...
@@ -362,30 +357,25 @@ pthread_handler_t event_executor_main(void *arg)
free_root
(
&
evex_mem_root
,
MYF
(
0
));
sql_print_information
(
"Event executor stopped"
);
// shutdown_events();
my_thread_end
();
pthread_exit
(
0
);
DBUG_RETURN
(
0
);
// Can't return anything here
DBUG_RETURN
(
0
);
// Can't return anything here
}
pthread_handler_t
event_executor_worker
(
void
*
event_void
)
pthread_handler_t
event_executor_worker
(
void
*
event_void
)
{
THD
*
thd
;
/* needs to be first for thread_stack */
List
<
Item
>
empty_item_list
;
event_timed
*
event
=
(
event_timed
*
)
event_void
;
MEM_ROOT
mem_root
;
MEM_ROOT
worker_
mem_root
;
DBUG_ENTER
(
"event_executor_worker"
);
VOID
(
pthread_mutex_lock
(
&
LOCK_workers_count
));
++
workers_count
;
VOID
(
pthread_mutex_unlock
(
&
LOCK_workers_count
));
init_alloc_root
(
&
mem_root
,
MEM_ROOT_BLOCK_SIZE
,
MEM_ROOT_PREALLOC
);
//we pass this empty list as parameter to the SP_HEAD of the event
empty_item_list
.
empty
();
init_alloc_root
(
&
worker_mem_root
,
MEM_ROOT_BLOCK_SIZE
,
MEM_ROOT_PREALLOC
);
my_thread_init
();
...
...
@@ -395,8 +385,10 @@ pthread_handler_t event_executor_worker(void *event_void)
goto
err_no_thd
;
}
thd
->
thread_stack
=
(
char
*
)
&
thd
;
// remember where our stack is
thd
->
mem_root
=
&
mem_root
;
thd
->
mem_root
=
&
worker_mem_root
;
pthread_detach
(
pthread_self
());
if
(
init_event_thread
(
thd
))
goto
err
;
...
...
@@ -425,7 +417,7 @@ pthread_handler_t event_executor_worker(void *event_void)
my_TIME_to_str
(
&
event
->
m_execute_at
,
exec_time
);
DBUG_PRINT
(
"info"
,
(
" EVEX EXECUTING event for event %s.%s [EXPR:%d][EXECUTE_AT:%s]"
,
event
->
m_db
.
str
,
event
->
m_name
.
str
,(
int
)
event
->
m_expr
,
exec_time
));
sql_print_information
(
" EVEX EXECUTING event for event %s.%s [EXPR:%d][EXECUTE_AT:%s]"
,
event
->
m_db
.
str
,
event
->
m_name
.
str
,(
int
)
event
->
m_expr
,
exec_time
);
ret
=
event
->
execute
(
thd
,
&
mem_root
);
ret
=
event
->
execute
(
thd
,
&
worker_
mem_root
);
sql_print_information
(
" EVEX EXECUTED event for event %s.%s [EXPR:%d][EXECUTE_AT:%s]. RetCode=%d"
,
event
->
m_db
.
str
,
event
->
m_name
.
str
,(
int
)
event
->
m_expr
,
exec_time
,
ret
);
DBUG_PRINT
(
"info"
,
(
" EVEX EXECUTED event for event %s.%s [EXPR:%d][EXECUTE_AT:%s]"
,
event
->
m_db
.
str
,
event
->
m_name
.
str
,(
int
)
event
->
m_expr
,
exec_time
));
}
...
...
@@ -454,8 +446,7 @@ pthread_handler_t event_executor_worker(void *event_void)
err_no_thd:
free_root
(
&
mem_root
,
MYF
(
0
));
// sql_print_information(" Worker thread exiting");
free_root
(
&
worker_mem_root
,
MYF
(
0
));
VOID
(
pthread_mutex_lock
(
&
LOCK_workers_count
));
--
workers_count
;
...
...
@@ -496,29 +487,38 @@ evex_load_events_from_db(THD *thd)
}
DBUG_PRINT
(
"evex_load_events_from_db"
,
(
"Loading event from row."
));
if
(
et
->
load_from_row
(
&
evex_mem_root
,
table
))
//error loading!
continue
;
if
((
ret
=
et
->
load_from_row
(
&
evex_mem_root
,
table
)))
{
sql_print_error
(
"Error while loading from mysql.event. "
"Table probably corrupted"
);
goto
end
;
}
DBUG_PRINT
(
"evex_load_events_from_db"
,
(
"Event %s loaded from row. Time to compile"
,
et
->
m_name
.
str
));
if
(
et
->
compile
(
thd
,
&
evex_mem_root
))
//problem during compile
continue
;
if
((
ret
=
et
->
compile
(
thd
,
&
evex_mem_root
)))
{
sql_print_error
(
"Error while compiling %s.%s. Aborting load."
,
et
->
m_db
.
str
,
et
->
m_name
.
str
);
goto
end
;
}
// let's find when to be executed
et
->
compute_next_execution_time
();
DBUG_PRINT
(
"evex_load_events_from_db"
,
(
"Adding %s to the executor list."
,
et
->
m_name
.
str
));
VOID
(
push_dynamic
(
&
events_array
,(
gptr
)
et
));
// we always add at the end so the number of elements - 1 is the place
// in the buffer
/*
We always add at the end so the number of elements - 1 is the place
in the buffer.
DYNAMIC_ARRAY copies the object bit by bit so we have a hollow copy
in event_array. We don't need the original therefore we delete it.
*/
et_copy
=
dynamic_element
(
&
events_array
,
events_array
.
elements
-
1
,
event_timed
*
);
VOID
(
push_dynamic
(
&
evex_executing_queue
,(
gptr
)
&
et_copy
));
et
->
m_free_sphead_on_delete
=
false
;
DBUG_PRINT
(
"info"
,
(
""
));
delete
et
;
}
end_read_record
(
&
read_record_info
);
...
...
@@ -536,8 +536,7 @@ evex_load_events_from_db(THD *thd)
end:
close_thread_tables
(
thd
);
DBUG_PRINT
(
"evex_load_events_from_db"
,
(
"Events loaded from DB. Status code %d"
,
ret
));
DBUG_PRINT
(
"info"
,
(
"Finishing with status code %d"
,
ret
));
DBUG_RETURN
(
ret
);
}
...
...
@@ -547,7 +546,8 @@ bool sys_var_event_executor::update(THD *thd, set_var *var)
{
// here start the thread if not running.
VOID
(
pthread_mutex_lock
(
&
LOCK_evex_running
));
if
((
my_bool
)
var
->
save_result
.
ulong_value
&&
!
evex_is_running
)
{
if
((
my_bool
)
var
->
save_result
.
ulong_value
&&
!
evex_is_running
)
{
VOID
(
pthread_mutex_unlock
(
&
LOCK_evex_running
));
init_events
();
}
else
...
...
sql/event_priv.h
View file @
b7578df0
...
...
@@ -18,6 +18,9 @@
#define _EVENT_PRIV_H_
#define UNLOCK_MUTEX_AND_BAIL_OUT(__mutex, __label) \
{ VOID(pthread_mutex_unlock(&__mutex)); goto __label; }
enum
{
EVEX_FIELD_DB
=
0
,
...
...
sql/event_timed.cc
View file @
b7578df0
...
...
@@ -537,10 +537,19 @@ event_timed::compute_next_execution_time()
my_tz_UTC
->
gmt_sec_to_TIME
(
&
time_now
,
now
);
/*
sql_print_information("[%s.%s]", m_db.str, m_name.str);
sql_print_information("time_now : [%d-%d-%d %d:%d:%d ]", time_now.year, time_now.month, time_now.day, time_now.hour, time_now.minute, time_now.second);
sql_print_information("m_starts : [%d-%d-%d %d:%d:%d ]", m_starts.year, m_starts.month, m_starts.day, m_starts.hour, m_starts.minute, m_starts.second);
sql_print_information("m_ends : [%d-%d-%d %d:%d:%d ]", m_ends.year, m_ends.month, m_ends.day, m_ends.hour, m_ends.minute, m_ends.second);
sql_print_information("m_last_ex: [%d-%d-%d %d:%d:%d ]", m_last_executed.year, m_last_executed.month, m_last_executed.day, m_last_executed.hour, m_last_executed.minute, m_last_executed.second);
sql_print_information("time_now : [%d-%d-%d %d:%d:%d ]",
time_now.year, time_now.month, time_now.day,
time_now.hour, time_now.minute, time_now.second);
sql_print_information("m_starts : [%d-%d-%d %d:%d:%d ]", m_starts.year,
m_starts.month, m_starts.day, m_starts.hour,
m_starts.minute, m_starts.second);
sql_print_information("m_ends : [%d-%d-%d %d:%d:%d ]", m_ends.year,
m_ends.month, m_ends.day, m_ends.hour,
m_ends.minute, m_ends.second);
sql_print_information("m_last_ex: [%d-%d-%d %d:%d:%d ]", m_last_executed.year,
m_last_executed.month, m_last_executed.day,
m_last_executed.hour, m_last_executed.minute,
m_last_executed.second);
*/
//if time_now is after m_ends don't execute anymore
if
(
m_ends
.
year
&&
(
tmp
=
my_time_compare
(
&
m_ends
,
&
time_now
))
==
-
1
)
...
...
@@ -702,7 +711,6 @@ event_timed::mark_last_executed()
bool
event_timed
::
drop
(
THD
*
thd
)
{
return
(
bool
)
evex_drop_event
(
thd
,
this
,
false
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment