Merge lp:~vlad-lesin/percona-server/5.6-sql_timeout_twitter into lp:percona-server/5.6
- 5.6-sql_timeout_twitter
- Merge into 5.6
Status: | Merged |
---|---|
Approved by: | Alexey Kopytov |
Approved revision: | no longer in the source branch. |
Merged at revision: | 428 |
Proposed branch: | lp:~vlad-lesin/percona-server/5.6-sql_timeout_twitter |
Merge into: | lp:percona-server/5.6 |
Diff against target: |
2612 lines (+1997/-29) 40 files modified
Percona-Server/config.h.cmake (+4/-0) Percona-Server/configure.cmake (+19/-1) Percona-Server/include/my_global.h (+13/-0) Percona-Server/include/my_timer.h (+69/-0) Percona-Server/include/mysql/plugin.h (+7/-0) Percona-Server/include/mysql/plugin_audit.h.pp (+1/-0) Percona-Server/include/mysql/plugin_auth.h.pp (+1/-0) Percona-Server/include/mysql/plugin_ftparser.h.pp (+1/-0) Percona-Server/include/mysql/thread_pool_priv.h (+6/-0) Percona-Server/libmysqld/CMakeLists.txt (+3/-0) Percona-Server/mysql-test/include/have_statement_timeout.inc (+4/-0) Percona-Server/mysql-test/r/have_statement_timeout.require (+2/-0) Percona-Server/mysql-test/r/max_statement_time_func.result (+116/-0) Percona-Server/mysql-test/r/mysqld--help-notwin.result (+4/-0) Percona-Server/mysql-test/r/mysqld--help-win.result (+4/-0) Percona-Server/mysql-test/suite/sys_vars/r/have_statement_timeout_basic.result (+53/-0) Percona-Server/mysql-test/suite/sys_vars/r/max_statement_time_basic.result (+89/-0) Percona-Server/mysql-test/suite/sys_vars/t/have_statement_timeout_basic.test (+55/-0) Percona-Server/mysql-test/suite/sys_vars/t/max_statement_time_basic.test (+78/-0) Percona-Server/mysql-test/t/max_statement_time_func.test (+154/-0) Percona-Server/mysys/CMakeLists.txt (+8/-0) Percona-Server/mysys/kqueue_timers.c (+219/-0) Percona-Server/mysys/posix_timers.c (+256/-0) Percona-Server/sql/CMakeLists.txt (+4/-0) Percona-Server/sql/handler.cc (+18/-0) Percona-Server/sql/handler.h (+4/-0) Percona-Server/sql/mysqld.cc (+22/-0) Percona-Server/sql/set_var.h (+1/-0) Percona-Server/sql/share/errmsg-utf8.txt (+3/-0) Percona-Server/sql/signal_handler.cc (+3/-0) Percona-Server/sql/sql_class.cc (+39/-15) Percona-Server/sql/sql_class.h (+13/-0) Percona-Server/sql/sql_parse.cc (+89/-1) Percona-Server/sql/sql_timer.cc (+253/-0) Percona-Server/sql/sql_timer.h (+50/-0) Percona-Server/sql/sys_vars.cc (+10/-0) Percona-Server/storage/innobase/handler/ha_innodb.cc (+49/-3) Percona-Server/storage/innobase/include/lock0lock.h (+10/-0) Percona-Server/storage/innobase/include/lock0priv.h (+0/-9) Percona-Server/unittest/mysys/my_timer-t.c (+263/-0) |
To merge this branch: | bzr merge lp:~vlad-lesin/percona-server/5.6-sql_timeout_twitter |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alexey Kopytov (community) | Approve | ||
Sergei Glushchenko (community) | g2 | Needs Fixing | |
Review via email: mp+146919@code.launchpad.net |
Commit message
Description of the change
The implementation of this https:/
Jenkins: http://
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
Vlad,
Some minor comments:
lines 2279-2280 redundant change
likewise 2585
likewise 3023
in have_statement_
it has been said that error 'Readonly variable' is expected but what really
is expected is the 'Unknown column 'have_statement
error and it is raised as well.
Sergei Glushchenko (sergei.glushchenko) : | # |
Vlad Lesin (vlad-lesin) wrote : | # |
> I see you encountered same issue as I did also. performance_schema *digest*
> tables are rely heavily on sql_yacc.yy grammar. So if someone just add new
> token (or even rule?) many of statement's digests will change.
...
> Do you have any thoughts on how to workaround this?
Digest calculation is based on token IDs. So every time we add new token in the middle of tokens list we just shift token IDs that are after just inserted token. So I see two variants how to avoid that. The first is add new tokens at the end of the list. The second - calculate digest using text representation of query instead of set of tokens.
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
First option obviously wouldn't work because there are additional PFS-specific tokens which are generated automatically (in gen_pfs_
Maybe it isn't that bad to update test cases with new digests. I just wondering why that method of digest calculation has been chosen. Probably nobody should refer to digests in their scripts/
Vlad Lesin (vlad-lesin) wrote : | # |
> Vlad,
> Some minor comments:
>
> lines 2279-2280 redundant change
> likewise 2585
> likewise 3023
>
> in have_statement_
> it has been said that error 'Readonly variable' is expected but what really
> is expected is the 'Unknown column 'have_statement
> error and it is raised as well.
Fixed.
Vlad Lesin (vlad-lesin) wrote : | # |
> Maybe it isn't that bad to update test cases with new digests. I just
> wondering why that method of digest calculation has been chosen. Probably
> nobody should refer to digests in their scripts/
> needed only for internal purposes.
It can lead to issues during merging. If several people make MP with updated tests merge captain should update that test results manually. But I think we can do nothing with it. We can't make rules for test scripts as we work with upstream code.
Vlad Lesin (vlad-lesin) wrote : | # |
Now it is rebased to new code.
Jenkins: http://
Alexey Kopytov (akopytov) wrote : | # |
Vlad,
- do we really need the following change?
-#if !defined(
-#define bool In_C_you_
-#endif
+#include <stdbool.h>
The intention was to allow using C99 'bool' in C code (and break
Windows compatibility), but I don't see any occurrences of such
usage?
- my_os_timer_* to avoid name clash with existing my_timer_init()
- I'm having second thoughts on per-user MAX_STATEMENT_TIME limit
after reviewing the code. It feels like it's going to be a pain to
support and maintain. Let's remove it? It's a "nice to have" thing, but
it was not a requirement for us originally, and would also
unproportio
- was there any specific reason to implement your own set of
regression tests instead of porting them from the Twitter tree? Most
of their tests use the SELECT hint that we chose not to implement,
but those could be converted to SET ...; SELECT ... form.
- include my_global.h and use DBUG_ASSERT() instead of assert()? Also
don't include assert.h, errno.h and string.h?
- unnecessary change:
@@ -4254,6 +4284,7 @@ static int replace_
goto end;
}
}
+
}
/*
- remnant from SELECT hints implementation that is also unnecessary:
--- Percona-
+++ Percona-
@@ -2533,6 +2533,9 @@ struct LEX: public Query_tables_list
class Explain_format *explain_format;
+ /** Maximum execution time for a statement. */
+ ulong max_statement_time;
+
LEX();
virtual ~LEX()
- I would restructure get_max_
a bit for performance reasons. We should first check if we do have
some timeout defined (i.e. thd->variables.
and then check other conditions. So that we do as less work as
possible when timeouts are not used. likely()/unlikely() and
explicit "inline" hints can also make a big difference.
- can you explain changed in ha_innodb.cc? It looks like fixing a
problem in the wrong place, i.e. implementing a workaround of
thread_
- innobase_
Vlad Lesin (vlad-lesin) wrote : | # |
> Vlad,
>
> - do we really need the following change?
>
> -#if !defined(
> -#define bool In_C_you_
> -#endif
> +#include <stdbool.h>
>
> The intention was to allow using C99 'bool' in C code (and break
> Windows compatibility), but I don't see any occurrences of such
> usage?
>
Removed.
> - my_os_timer_* to avoid name clash with existing my_timer_init()
>
Done.
> - I'm having second thoughts on per-user MAX_STATEMENT_TIME limit
> after reviewing the code. It feels like it's going to be a pain to
> support and maintain. Let's remove it? It's a "nice to have" thing, but
> it was not a requirement for us originally, and would also
> unproportionally complicate migrations to/from upstream MySQL.
>
Removed.
> - was there any specific reason to implement your own set of
> regression tests instead of porting them from the Twitter tree? Most
> of their tests use the SELECT hint that we chose not to implement,
> but those could be converted to SET ...; SELECT ... form.
All tests are ported from Twitter tree except these two:
mysql-test/
mysql-test/
The first one is not ported because I did not find randgen grammar files for the test
in the tree. The second one repeats the mysql-test/
but uses statement timeout set instead of set with variable.
>
> - include my_global.h and use DBUG_ASSERT() instead of assert()? Also
> don't include assert.h, errno.h and string.h?
As we do not support BSD-based platforms and do not test code for such platforms with our
regression tests system the BSD-based platform specific files are kept as is.
> - unnecessary change:
>
> @@ -4254,6 +4284,7 @@ static int replace_
> goto end;
> }
> }
> +
> }
>
> /*
>
> - remnant from SELECT hints implementation that is also unnecessary:
>
> --- Percona-
> +++ Percona-
> @@ -2533,6 +2533,9 @@ struct LEX: public Query_tables_list
>
> class Explain_format *explain_format;
>
> + /** Maximum execution time for a statement. */
> + ulong max_statement_time;
> +
> LEX();
>
> virtual ~LEX()
>
As per-user MAX_STATEMENT_TIME limit code is removed the above changes are removed too.
> - I would restructure get_max_
> a bit for performance reasons. We should first check if we do have
> some timeout defined (i.e. thd->variables.
> and then check other conditions. So that we do as less work as
> possible when timeouts are not used. likely()/unlikely() and
> explicit "inline" hints can also make a big difference.
>
Done.
> - can you explain changed in ha_innodb.cc? It looks like fixing a
> problem in the wrong place, i.e. implementing a workaround of
> thread_pool_priv.h defining MYSQL_SERVER unconditionally.
Made conditional #define in thread_pool_priv.h
> - innobase_
Done.
h...
Alexey Kopytov (akopytov) : | # |
Alexey Kopytov (akopytov) wrote : | # |
Preview Diff
1 | === modified file 'Percona-Server/config.h.cmake' | |||
2 | --- Percona-Server/config.h.cmake 2013-06-20 15:16:00 +0000 | |||
3 | +++ Percona-Server/config.h.cmake 2013-09-09 15:30:42 +0000 | |||
4 | @@ -306,6 +306,10 @@ | |||
5 | 306 | #cmakedefine STRUCT_DIRENT_HAS_D_NAMLEN 1 | 306 | #cmakedefine STRUCT_DIRENT_HAS_D_NAMLEN 1 |
6 | 307 | #cmakedefine SPRINTF_RETURNS_INT 1 | 307 | #cmakedefine SPRINTF_RETURNS_INT 1 |
7 | 308 | 308 | ||
8 | 309 | #cmakedefine HAVE_POSIX_TIMERS 1 | ||
9 | 310 | #cmakedefine HAVE_KQUEUE_TIMERS 1 | ||
10 | 311 | #cmakedefine HAVE_MY_TIMER 1 | ||
11 | 312 | |||
12 | 309 | #cmakedefine DNS_USE_CPU_CLOCK_FOR_ID 1 | 313 | #cmakedefine DNS_USE_CPU_CLOCK_FOR_ID 1 |
13 | 310 | #cmakedefine HAVE_EPOLL 1 | 314 | #cmakedefine HAVE_EPOLL 1 |
14 | 311 | #cmakedefine HAVE_EPOLL_CTL 1 | 315 | #cmakedefine HAVE_EPOLL_CTL 1 |
15 | 312 | 316 | ||
16 | === modified file 'Percona-Server/configure.cmake' | |||
17 | --- Percona-Server/configure.cmake 2013-08-14 03:57:21 +0000 | |||
18 | +++ Percona-Server/configure.cmake 2013-09-09 15:30:42 +0000 | |||
19 | @@ -197,6 +197,7 @@ | |||
20 | 197 | IF(NOT LIBRT) | 197 | IF(NOT LIBRT) |
21 | 198 | MY_SEARCH_LIBS(clock_gettime rt LIBRT) | 198 | MY_SEARCH_LIBS(clock_gettime rt LIBRT) |
22 | 199 | ENDIF() | 199 | ENDIF() |
23 | 200 | MY_SEARCH_LIBS(timer_create rt LIBRT) | ||
24 | 200 | FIND_PACKAGE(Threads) | 201 | FIND_PACKAGE(Threads) |
25 | 201 | 202 | ||
26 | 202 | SET(CMAKE_REQUIRED_LIBRARIES | 203 | SET(CMAKE_REQUIRED_LIBRARIES |
27 | @@ -523,6 +524,10 @@ | |||
28 | 523 | CHECK_FUNCTION_EXISTS (nl_langinfo HAVE_NL_LANGINFO) | 524 | CHECK_FUNCTION_EXISTS (nl_langinfo HAVE_NL_LANGINFO) |
29 | 524 | CHECK_FUNCTION_EXISTS (ntohll HAVE_HTONLL) | 525 | CHECK_FUNCTION_EXISTS (ntohll HAVE_HTONLL) |
30 | 525 | 526 | ||
31 | 527 | CHECK_FUNCTION_EXISTS (timer_create HAVE_TIMER_CREATE) | ||
32 | 528 | CHECK_FUNCTION_EXISTS (timer_settime HAVE_TIMER_SETTIME) | ||
33 | 529 | CHECK_FUNCTION_EXISTS (kqueue HAVE_KQUEUE) | ||
34 | 530 | |||
35 | 526 | CHECK_FUNCTION_EXISTS (clock_gettime DNS_USE_CPU_CLOCK_FOR_ID) | 531 | CHECK_FUNCTION_EXISTS (clock_gettime DNS_USE_CPU_CLOCK_FOR_ID) |
36 | 527 | CHECK_FUNCTION_EXISTS (epoll_create HAVE_EPOLL) | 532 | CHECK_FUNCTION_EXISTS (epoll_create HAVE_EPOLL) |
37 | 528 | CHECK_FUNCTION_EXISTS (epoll_ctl HAVE_EPOLL_CTL) | 533 | CHECK_FUNCTION_EXISTS (epoll_ctl HAVE_EPOLL_CTL) |
38 | @@ -579,6 +584,8 @@ | |||
39 | 579 | CHECK_SYMBOL_EXISTS(TIOCSTAT "sys/ioctl.h" TIOCSTAT_IN_SYS_IOCTL) | 584 | CHECK_SYMBOL_EXISTS(TIOCSTAT "sys/ioctl.h" TIOCSTAT_IN_SYS_IOCTL) |
40 | 580 | CHECK_SYMBOL_EXISTS(FIONREAD "sys/filio.h" FIONREAD_IN_SYS_FILIO) | 585 | CHECK_SYMBOL_EXISTS(FIONREAD "sys/filio.h" FIONREAD_IN_SYS_FILIO) |
41 | 581 | CHECK_SYMBOL_EXISTS(gettimeofday "sys/time.h" HAVE_GETTIMEOFDAY) | 586 | CHECK_SYMBOL_EXISTS(gettimeofday "sys/time.h" HAVE_GETTIMEOFDAY) |
42 | 587 | CHECK_SYMBOL_EXISTS(SIGEV_THREAD_ID "signal.h;time.h" HAVE_SIGEV_THREAD_ID) | ||
43 | 588 | CHECK_SYMBOL_EXISTS(EVFILT_TIMER "sys/types.h;sys/event.h;sys/time.h" HAVE_EVFILT_TIMER) | ||
44 | 582 | 589 | ||
45 | 583 | CHECK_SYMBOL_EXISTS(finite "math.h" HAVE_FINITE_IN_MATH_H) | 590 | CHECK_SYMBOL_EXISTS(finite "math.h" HAVE_FINITE_IN_MATH_H) |
46 | 584 | IF(HAVE_FINITE_IN_MATH_H) | 591 | IF(HAVE_FINITE_IN_MATH_H) |
47 | @@ -607,7 +614,18 @@ | |||
48 | 607 | return 0; | 614 | return 0; |
49 | 608 | }" HAVE_FESETROUND) | 615 | }" HAVE_FESETROUND) |
50 | 609 | 616 | ||
52 | 610 | 617 | # Check for the Linux-specific POSIX timers API. | |
53 | 618 | IF(HAVE_TIMER_CREATE AND HAVE_TIMER_SETTIME AND HAVE_SIGEV_THREAD_ID) | ||
54 | 619 | SET(HAVE_POSIX_TIMERS 1 CACHE INTERNAL "Have POSIX timer-related functions") | ||
55 | 620 | ENDIF() | ||
56 | 621 | |||
57 | 622 | IF(HAVE_KQUEUE AND HAVE_EVFILT_TIMER) | ||
58 | 623 | SET(HAVE_KQUEUE_TIMERS 1 CACHE INTERNAL "Have kqueue timer-related filter") | ||
59 | 624 | ENDIF() | ||
60 | 625 | |||
61 | 626 | IF(HAVE_POSIX_TIMERS OR HAVE_KQUEUE_TIMERS) | ||
62 | 627 | SET(HAVE_MY_TIMER 1 CACHE INTERNAL "Have mysys timer-related functions") | ||
63 | 628 | ENDIF() | ||
64 | 611 | 629 | ||
65 | 612 | # | 630 | # |
66 | 613 | # Test for endianess | 631 | # Test for endianess |
67 | 614 | 632 | ||
68 | === modified file 'Percona-Server/include/my_global.h' | |||
69 | --- Percona-Server/include/my_global.h 2013-06-26 14:15:01 +0000 | |||
70 | +++ Percona-Server/include/my_global.h 2013-09-09 15:30:42 +0000 | |||
71 | @@ -363,6 +363,19 @@ | |||
72 | 363 | #include <crypt.h> | 363 | #include <crypt.h> |
73 | 364 | #endif | 364 | #endif |
74 | 365 | 365 | ||
75 | 366 | /** | ||
76 | 367 | Cast a member of a structure to the structure that contains it. | ||
77 | 368 | |||
78 | 369 | @param ptr Pointer to the member. | ||
79 | 370 | @param type Type of the structure that contains the member. | ||
80 | 371 | @param member Name of the member within the structure. | ||
81 | 372 | */ | ||
82 | 373 | #define my_container_of(ptr, type, member) \ | ||
83 | 374 | ({ \ | ||
84 | 375 | const typeof(((type *)0)->member) *__mptr= (ptr); \ | ||
85 | 376 | (type *)((char *)__mptr - offsetof(type, member)); \ | ||
86 | 377 | }) | ||
87 | 378 | |||
88 | 366 | /* | 379 | /* |
89 | 367 | A lot of our programs uses asserts, so better to always include it | 380 | A lot of our programs uses asserts, so better to always include it |
90 | 368 | This also fixes a problem when people uses DBUG_ASSERT without including | 381 | This also fixes a problem when people uses DBUG_ASSERT without including |
91 | 369 | 382 | ||
92 | === added file 'Percona-Server/include/my_timer.h' | |||
93 | --- Percona-Server/include/my_timer.h 1970-01-01 00:00:00 +0000 | |||
94 | +++ Percona-Server/include/my_timer.h 2013-09-09 15:30:42 +0000 | |||
95 | @@ -0,0 +1,69 @@ | |||
96 | 1 | /* Copyright (c) 2012, Twitter, Inc. All rights reserved. | ||
97 | 2 | |||
98 | 3 | This program is free software; you can redistribute it and/or modify | ||
99 | 4 | it under the terms of the GNU General Public License as published by | ||
100 | 5 | the Free Software Foundation; version 2 of the License. | ||
101 | 6 | |||
102 | 7 | This program is distributed in the hope that it will be useful, | ||
103 | 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
104 | 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
105 | 10 | GNU General Public License for more details. | ||
106 | 11 | |||
107 | 12 | You should have received a copy of the GNU General Public License along | ||
108 | 13 | with this program; if not, write to the Free Software Foundation, Inc., | ||
109 | 14 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ | ||
110 | 15 | |||
111 | 16 | #ifndef MY_TIMER_H | ||
112 | 17 | #define MY_TIMER_H | ||
113 | 18 | |||
114 | 19 | #include "my_global.h" /* C_MODE_START, C_MODE_END */ | ||
115 | 20 | #include "my_config.h" /* HAVE_*_TIMERS */ | ||
116 | 21 | |||
117 | 22 | /* POSIX timers API. */ | ||
118 | 23 | #ifdef HAVE_POSIX_TIMERS | ||
119 | 24 | # include <time.h> /* timer_t */ | ||
120 | 25 | typedef timer_t os_timer_t; | ||
121 | 26 | #elif HAVE_KQUEUE_TIMERS | ||
122 | 27 | # include <sys/types.h> /* uintptr_t */ | ||
123 | 28 | typedef uintptr_t os_timer_t; | ||
124 | 29 | #endif | ||
125 | 30 | |||
126 | 31 | /* Whether timer API is implemented. */ | ||
127 | 32 | #ifdef HAVE_MY_TIMER | ||
128 | 33 | |||
129 | 34 | C_MODE_START | ||
130 | 35 | |||
131 | 36 | typedef struct st_my_timer my_timer_t; | ||
132 | 37 | |||
133 | 38 | /** Non-copyable timer object. */ | ||
134 | 39 | struct st_my_timer | ||
135 | 40 | { | ||
136 | 41 | /** Timer ID used to identify the timer in timer requests. */ | ||
137 | 42 | os_timer_t id; | ||
138 | 43 | |||
139 | 44 | /** Timer expiration notification function. */ | ||
140 | 45 | void (*notify_function)(my_timer_t *); | ||
141 | 46 | }; | ||
142 | 47 | |||
143 | 48 | /* Initialize internal components. */ | ||
144 | 49 | int my_os_timer_init_ext(void); | ||
145 | 50 | |||
146 | 51 | /* Release any resources acquired. */ | ||
147 | 52 | void my_os_timer_deinit(void); | ||
148 | 53 | |||
149 | 54 | /* Create a timer object. */ | ||
150 | 55 | int my_os_timer_create(my_timer_t *timer); | ||
151 | 56 | |||
152 | 57 | /* Set the time (in milliseconds) until the next expiration of the timer. */ | ||
153 | 58 | int my_os_timer_set(my_timer_t *timer, unsigned long time); | ||
154 | 59 | |||
155 | 60 | /* Reset the time until the next expiration of the timer. */ | ||
156 | 61 | int my_os_timer_reset(my_timer_t *timer, int *state); | ||
157 | 62 | |||
158 | 63 | /* Delete a timer object. */ | ||
159 | 64 | void my_os_timer_delete(my_timer_t *timer); | ||
160 | 65 | |||
161 | 66 | C_MODE_END | ||
162 | 67 | |||
163 | 68 | #endif /* HAVE_MY_TIMER */ | ||
164 | 69 | #endif /* MY_TIMER_H */ | ||
165 | 0 | 70 | ||
166 | === modified file 'Percona-Server/include/mysql/plugin.h' | |||
167 | --- Percona-Server/include/mysql/plugin.h 2013-08-06 15:16:34 +0000 | |||
168 | +++ Percona-Server/include/mysql/plugin.h 2013-09-09 15:30:42 +0000 | |||
169 | @@ -627,6 +627,13 @@ | |||
170 | 627 | unsigned long long *pos_var); | 627 | unsigned long long *pos_var); |
171 | 628 | 628 | ||
172 | 629 | /** | 629 | /** |
173 | 630 | Set the killed status of the current statement. | ||
174 | 631 | |||
175 | 632 | @param thd user thread connection handle | ||
176 | 633 | */ | ||
177 | 634 | void thd_set_kill_status(const MYSQL_THD thd); | ||
178 | 635 | |||
179 | 636 | /** | ||
180 | 630 | Return the thread id of a user thread | 637 | Return the thread id of a user thread |
181 | 631 | 638 | ||
182 | 632 | @param thd user thread connection handle | 639 | @param thd user thread connection handle |
183 | 633 | 640 | ||
184 | === modified file 'Percona-Server/include/mysql/plugin_audit.h.pp' | |||
185 | --- Percona-Server/include/mysql/plugin_audit.h.pp 2013-05-12 06:24:46 +0000 | |||
186 | +++ Percona-Server/include/mysql/plugin_audit.h.pp 2013-09-09 15:30:42 +0000 | |||
187 | @@ -249,6 +249,7 @@ | |||
188 | 249 | void thd_binlog_pos(const void* thd, | 249 | void thd_binlog_pos(const void* thd, |
189 | 250 | const char **file_var, | 250 | const char **file_var, |
190 | 251 | unsigned long long *pos_var); | 251 | unsigned long long *pos_var); |
191 | 252 | void thd_set_kill_status(const void* thd); | ||
192 | 252 | unsigned long thd_get_thread_id(const void* thd); | 253 | unsigned long thd_get_thread_id(const void* thd); |
193 | 253 | void thd_get_xid(const void* thd, MYSQL_XID *xid); | 254 | void thd_get_xid(const void* thd, MYSQL_XID *xid); |
194 | 254 | void mysql_query_cache_invalidate4(void* thd, | 255 | void mysql_query_cache_invalidate4(void* thd, |
195 | 255 | 256 | ||
196 | === modified file 'Percona-Server/include/mysql/plugin_auth.h.pp' | |||
197 | --- Percona-Server/include/mysql/plugin_auth.h.pp 2013-05-12 06:24:46 +0000 | |||
198 | +++ Percona-Server/include/mysql/plugin_auth.h.pp 2013-09-09 15:30:42 +0000 | |||
199 | @@ -249,6 +249,7 @@ | |||
200 | 249 | void thd_binlog_pos(const void* thd, | 249 | void thd_binlog_pos(const void* thd, |
201 | 250 | const char **file_var, | 250 | const char **file_var, |
202 | 251 | unsigned long long *pos_var); | 251 | unsigned long long *pos_var); |
203 | 252 | void thd_set_kill_status(const void* thd); | ||
204 | 252 | unsigned long thd_get_thread_id(const void* thd); | 253 | unsigned long thd_get_thread_id(const void* thd); |
205 | 253 | void thd_get_xid(const void* thd, MYSQL_XID *xid); | 254 | void thd_get_xid(const void* thd, MYSQL_XID *xid); |
206 | 254 | void mysql_query_cache_invalidate4(void* thd, | 255 | void mysql_query_cache_invalidate4(void* thd, |
207 | 255 | 256 | ||
208 | === modified file 'Percona-Server/include/mysql/plugin_ftparser.h.pp' | |||
209 | --- Percona-Server/include/mysql/plugin_ftparser.h.pp 2013-05-12 06:24:46 +0000 | |||
210 | +++ Percona-Server/include/mysql/plugin_ftparser.h.pp 2013-09-09 15:30:42 +0000 | |||
211 | @@ -202,6 +202,7 @@ | |||
212 | 202 | void thd_binlog_pos(const void* thd, | 202 | void thd_binlog_pos(const void* thd, |
213 | 203 | const char **file_var, | 203 | const char **file_var, |
214 | 204 | unsigned long long *pos_var); | 204 | unsigned long long *pos_var); |
215 | 205 | void thd_set_kill_status(const void* thd); | ||
216 | 205 | unsigned long thd_get_thread_id(const void* thd); | 206 | unsigned long thd_get_thread_id(const void* thd); |
217 | 206 | void thd_get_xid(const void* thd, MYSQL_XID *xid); | 207 | void thd_get_xid(const void* thd, MYSQL_XID *xid); |
218 | 207 | void mysql_query_cache_invalidate4(void* thd, | 208 | void mysql_query_cache_invalidate4(void* thd, |
219 | 208 | 209 | ||
220 | === modified file 'Percona-Server/include/mysql/thread_pool_priv.h' | |||
221 | --- Percona-Server/include/mysql/thread_pool_priv.h 2013-05-12 06:24:46 +0000 | |||
222 | +++ Percona-Server/include/mysql/thread_pool_priv.h 2013-09-09 15:30:42 +0000 | |||
223 | @@ -30,7 +30,13 @@ | |||
224 | 30 | to include sql_profile.h and table.h. | 30 | to include sql_profile.h and table.h. |
225 | 31 | */ | 31 | */ |
226 | 32 | #include <mysqld_error.h> /* To get ER_ERROR_ON_READ */ | 32 | #include <mysqld_error.h> /* To get ER_ERROR_ON_READ */ |
227 | 33 | /* | ||
228 | 34 | MYSQL_SERVER can be defined before including this header, check it to avoid | ||
229 | 35 | compilation error. | ||
230 | 36 | */ | ||
231 | 37 | #ifndef MYSQL_SERVER | ||
232 | 33 | #define MYSQL_SERVER 1 | 38 | #define MYSQL_SERVER 1 |
233 | 39 | #endif //MYSQL_SERVER | ||
234 | 34 | #include <scheduler.h> | 40 | #include <scheduler.h> |
235 | 35 | #include <debug_sync.h> | 41 | #include <debug_sync.h> |
236 | 36 | #include <sql_profile.h> | 42 | #include <sql_profile.h> |
237 | 37 | 43 | ||
238 | === modified file 'Percona-Server/libmysqld/CMakeLists.txt' | |||
239 | --- Percona-Server/libmysqld/CMakeLists.txt 2012-10-16 06:21:51 +0000 | |||
240 | +++ Percona-Server/libmysqld/CMakeLists.txt 2013-09-09 15:30:42 +0000 | |||
241 | @@ -78,6 +78,9 @@ | |||
242 | 78 | ${IMPORTED_SOURCES} | 78 | ${IMPORTED_SOURCES} |
243 | 79 | ) | 79 | ) |
244 | 80 | 80 | ||
245 | 81 | IF(HAVE_MY_TIMER) | ||
246 | 82 | SET(SQL_EMBEDDED_SOURCES ${SQL_EMBEDDED_SOURCES} ../sql/sql_timer.cc) | ||
247 | 83 | ENDIF() | ||
248 | 81 | 84 | ||
249 | 82 | ADD_CONVENIENCE_LIBRARY(sql_embedded ${SQL_EMBEDDED_SOURCES}) | 85 | ADD_CONVENIENCE_LIBRARY(sql_embedded ${SQL_EMBEDDED_SOURCES}) |
250 | 83 | DTRACE_INSTRUMENT(sql_embedded) | 86 | DTRACE_INSTRUMENT(sql_embedded) |
251 | 84 | 87 | ||
252 | === added file 'Percona-Server/mysql-test/include/have_statement_timeout.inc' | |||
253 | --- Percona-Server/mysql-test/include/have_statement_timeout.inc 1970-01-01 00:00:00 +0000 | |||
254 | +++ Percona-Server/mysql-test/include/have_statement_timeout.inc 2013-09-09 15:30:42 +0000 | |||
255 | @@ -0,0 +1,4 @@ | |||
256 | 1 | -- require r/have_statement_timeout.require | ||
257 | 2 | disable_query_log; | ||
258 | 3 | show variables like 'have_statement_timeout'; | ||
259 | 4 | enable_query_log; | ||
260 | 0 | 5 | ||
261 | === added file 'Percona-Server/mysql-test/r/have_statement_timeout.require' | |||
262 | --- Percona-Server/mysql-test/r/have_statement_timeout.require 1970-01-01 00:00:00 +0000 | |||
263 | +++ Percona-Server/mysql-test/r/have_statement_timeout.require 2013-09-09 15:30:42 +0000 | |||
264 | @@ -0,0 +1,2 @@ | |||
265 | 1 | Variable_name Value | ||
266 | 2 | have_statement_timeout YES | ||
267 | 0 | 3 | ||
268 | === added file 'Percona-Server/mysql-test/r/max_statement_time_func.result' | |||
269 | --- Percona-Server/mysql-test/r/max_statement_time_func.result 1970-01-01 00:00:00 +0000 | |||
270 | +++ Percona-Server/mysql-test/r/max_statement_time_func.result 2013-09-09 15:30:42 +0000 | |||
271 | @@ -0,0 +1,116 @@ | |||
272 | 1 | SET @old_session_max_statement_time = @@SESSION.max_statement_time; | ||
273 | 2 | # | ||
274 | 3 | # Test max statement time interruption. | ||
275 | 4 | # Note that if SLEEP() is interrupted, it returns 1. | ||
276 | 5 | # | ||
277 | 6 | SET @@SESSION.max_statement_time = 10; | ||
278 | 7 | SELECT SLEEP(1000); | ||
279 | 8 | SLEEP(1000) | ||
280 | 9 | 1 | ||
281 | 10 | SET @@SESSION.max_statement_time = 0; | ||
282 | 11 | # | ||
283 | 12 | # Apply timeout to the top-level statement. | ||
284 | 13 | # | ||
285 | 14 | CREATE PROCEDURE p1() | ||
286 | 15 | BEGIN | ||
287 | 16 | SELECT SLEEP(1000); | ||
288 | 17 | END| | ||
289 | 18 | SET @@SESSION.max_statement_time = 10; | ||
290 | 19 | CALL p1(); | ||
291 | 20 | SLEEP(1000) | ||
292 | 21 | 1 | ||
293 | 22 | SET @@SESSION.max_statement_time = 0; | ||
294 | 23 | # Apply timeout to prepared statements. | ||
295 | 24 | PREPARE prep_1 FROM 'call p1()'; | ||
296 | 25 | SET @@SESSION.max_statement_time = 10; | ||
297 | 26 | EXECUTE prep_1; | ||
298 | 27 | SLEEP(1000) | ||
299 | 28 | 1 | ||
300 | 29 | SET @@SESSION.max_statement_time = 0; | ||
301 | 30 | DROP PREPARE prep_1; | ||
302 | 31 | DROP PROCEDURE p1; | ||
303 | 32 | # | ||
304 | 33 | # Interrupt a statement that changes data. | ||
305 | 34 | # | ||
306 | 35 | CREATE TABLE t1 (a INT); | ||
307 | 36 | CREATE FUNCTION f1() RETURNS INT | ||
308 | 37 | BEGIN | ||
309 | 38 | WHILE true DO | ||
310 | 39 | INSERT INTO t1 VALUES (1); | ||
311 | 40 | END WHILE; | ||
312 | 41 | RETURN 1; | ||
313 | 42 | END| | ||
314 | 43 | SET @@SESSION.max_statement_time = 500; | ||
315 | 44 | SELECT f1(); | ||
316 | 45 | ERROR 70101: Query execution was interrupted, max_statement_time exceeded | ||
317 | 46 | SET @@SESSION.max_statement_time = 0; | ||
318 | 47 | DROP FUNCTION f1; | ||
319 | 48 | DROP TABLE t1; | ||
320 | 49 | SELECT CONVERT(VARIABLE_VALUE, UNSIGNED) INTO @time_set | ||
321 | 50 | FROM INFORMATION_SCHEMA.GLOBAL_STATUS | ||
322 | 51 | WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_SET'; | ||
323 | 52 | SELECT CONVERT(VARIABLE_VALUE, UNSIGNED) INTO @time_exceeded | ||
324 | 53 | FROM INFORMATION_SCHEMA.GLOBAL_STATUS | ||
325 | 54 | WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_EXCEEDED'; | ||
326 | 55 | SET @@SESSION.max_statement_time = 100; | ||
327 | 56 | SELECT SLEEP(1000); | ||
328 | 57 | SLEEP(1000) | ||
329 | 58 | 1 | ||
330 | 59 | # Ensure that the counters for: | ||
331 | 60 | # - statements that are time limited; and | ||
332 | 61 | # - statements that exceeded their maximum execution time | ||
333 | 62 | # are incremented. | ||
334 | 63 | SELECT 1 AS STATUS FROM INFORMATION_SCHEMA.GLOBAL_STATUS | ||
335 | 64 | WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_SET' | ||
336 | 65 | AND CONVERT(VARIABLE_VALUE, UNSIGNED) > @time_set; | ||
337 | 66 | STATUS | ||
338 | 67 | SELECT 1 AS STATUS FROM INFORMATION_SCHEMA.GLOBAL_STATUS | ||
339 | 68 | WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_EXCEEDED' | ||
340 | 69 | AND CONVERT(VARIABLE_VALUE, UNSIGNED) > @time_exceeded; | ||
341 | 70 | STATUS | ||
342 | 71 | SET @@SESSION.max_statement_time = default; | ||
343 | 72 | |||
344 | 73 | # Check that the appropriate error status is set. | ||
345 | 74 | |||
346 | 75 | CREATE TABLE t1 (a INT) ENGINE=InnoDB; | ||
347 | 76 | INSERT INTO t1 VALUES (1); | ||
348 | 77 | START TRANSACTION; | ||
349 | 78 | SELECT * FROM t1 FOR UPDATE; | ||
350 | 79 | a | ||
351 | 80 | 1 | ||
352 | 81 | SET @@SESSION.max_statement_time = 100; | ||
353 | 82 | UPDATE t1 SET a = 2; | ||
354 | 83 | ERROR 70101: Query execution was interrupted, max_statement_time exceeded | ||
355 | 84 | SHOW WARNINGS; | ||
356 | 85 | Level Code Message | ||
357 | 86 | Error 1877 Query execution was interrupted, max_statement_time exceeded | ||
358 | 87 | ROLLBACK; | ||
359 | 88 | DROP TABLE t1; | ||
360 | 89 | # | ||
361 | 90 | # Test interaction with lock waits. | ||
362 | 91 | # | ||
363 | 92 | CREATE TABLE t1 (a INT) ENGINE=InnoDB; | ||
364 | 93 | INSERT INTO t1 VALUES (1); | ||
365 | 94 | SET @@SESSION.max_statement_time = 500; | ||
366 | 95 | LOCK TABLES t1 WRITE; | ||
367 | 96 | LOCK TABLES t1 READ; | ||
368 | 97 | ERROR 70101: Query execution was interrupted, max_statement_time exceeded | ||
369 | 98 | UNLOCK TABLES; | ||
370 | 99 | BEGIN; | ||
371 | 100 | SELECT * FROM t1; | ||
372 | 101 | a | ||
373 | 102 | 1 | ||
374 | 103 | ALTER TABLE t1 ADD COLUMN b INT; | ||
375 | 104 | ERROR 70101: Query execution was interrupted, max_statement_time exceeded | ||
376 | 105 | ROLLBACK; | ||
377 | 106 | SELECT GET_LOCK('lock', 1); | ||
378 | 107 | GET_LOCK('lock', 1) | ||
379 | 108 | 1 | ||
380 | 109 | SELECT GET_LOCK('lock', 1); | ||
381 | 110 | GET_LOCK('lock', 1) | ||
382 | 111 | NULL | ||
383 | 112 | SELECT RELEASE_LOCK('lock'); | ||
384 | 113 | RELEASE_LOCK('lock') | ||
385 | 114 | 1 | ||
386 | 115 | DROP TABLE t1; | ||
387 | 116 | SET @@SESSION.max_statement_time = @old_session_max_statement_time; | ||
388 | 0 | 117 | ||
389 | === modified file 'Percona-Server/mysql-test/r/mysqld--help-notwin.result' | |||
390 | --- Percona-Server/mysql-test/r/mysqld--help-notwin.result 2013-09-09 07:01:33 +0000 | |||
391 | +++ Percona-Server/mysql-test/r/mysqld--help-notwin.result 2013-09-09 15:30:42 +0000 | |||
392 | @@ -448,6 +448,9 @@ | |||
393 | 448 | value are used; the rest are ignored) | 448 | value are used; the rest are ignored) |
394 | 449 | --max-sp-recursion-depth[=#] | 449 | --max-sp-recursion-depth[=#] |
395 | 450 | Maximum stored procedure recursion depth | 450 | Maximum stored procedure recursion depth |
396 | 451 | --max-statement-time=# | ||
397 | 452 | Kill any statement that takes over the specified number | ||
398 | 453 | of milliseconds | ||
399 | 451 | --max-tmp-tables=# Maximum number of temporary tables a client can keep open | 454 | --max-tmp-tables=# Maximum number of temporary tables a client can keep open |
400 | 452 | at a time | 455 | at a time |
401 | 453 | --max-user-connections=# | 456 | --max-user-connections=# |
402 | @@ -1209,6 +1212,7 @@ | |||
403 | 1209 | max-seeks-for-key 18446744073709551615 | 1212 | max-seeks-for-key 18446744073709551615 |
404 | 1210 | max-sort-length 1024 | 1213 | max-sort-length 1024 |
405 | 1211 | max-sp-recursion-depth 0 | 1214 | max-sp-recursion-depth 0 |
406 | 1215 | max-statement-time 0 | ||
407 | 1212 | max-tmp-tables 32 | 1216 | max-tmp-tables 32 |
408 | 1213 | max-user-connections 0 | 1217 | max-user-connections 0 |
409 | 1214 | max-write-lock-count 18446744073709551615 | 1218 | max-write-lock-count 18446744073709551615 |
410 | 1215 | 1219 | ||
411 | === modified file 'Percona-Server/mysql-test/r/mysqld--help-win.result' | |||
412 | --- Percona-Server/mysql-test/r/mysqld--help-win.result 2013-09-09 07:01:33 +0000 | |||
413 | +++ Percona-Server/mysql-test/r/mysqld--help-win.result 2013-09-09 15:30:42 +0000 | |||
414 | @@ -424,6 +424,9 @@ | |||
415 | 424 | value are used; the rest are ignored) | 424 | value are used; the rest are ignored) |
416 | 425 | --max-sp-recursion-depth[=#] | 425 | --max-sp-recursion-depth[=#] |
417 | 426 | Maximum stored procedure recursion depth | 426 | Maximum stored procedure recursion depth |
418 | 427 | --max-statement-time=# | ||
419 | 428 | Kill any statement that takes over the specified number | ||
420 | 429 | of milliseconds | ||
421 | 427 | --max-tmp-tables=# Maximum number of temporary tables a client can keep open | 430 | --max-tmp-tables=# Maximum number of temporary tables a client can keep open |
422 | 428 | at a time | 431 | at a time |
423 | 429 | --max-user-connections=# | 432 | --max-user-connections=# |
424 | @@ -1155,6 +1158,7 @@ | |||
425 | 1155 | max-seeks-for-key 18446744073709551615 | 1158 | max-seeks-for-key 18446744073709551615 |
426 | 1156 | max-sort-length 1024 | 1159 | max-sort-length 1024 |
427 | 1157 | max-sp-recursion-depth 0 | 1160 | max-sp-recursion-depth 0 |
428 | 1161 | max-statement-time 0 | ||
429 | 1158 | max-tmp-tables 32 | 1162 | max-tmp-tables 32 |
430 | 1159 | max-user-connections 0 | 1163 | max-user-connections 0 |
431 | 1160 | max-write-lock-count 18446744073709551615 | 1164 | max-write-lock-count 18446744073709551615 |
432 | 1161 | 1165 | ||
433 | === added file 'Percona-Server/mysql-test/suite/sys_vars/r/have_statement_timeout_basic.result' | |||
434 | --- Percona-Server/mysql-test/suite/sys_vars/r/have_statement_timeout_basic.result 1970-01-01 00:00:00 +0000 | |||
435 | +++ Percona-Server/mysql-test/suite/sys_vars/r/have_statement_timeout_basic.result 2013-09-09 15:30:42 +0000 | |||
436 | @@ -0,0 +1,53 @@ | |||
437 | 1 | # Displaying default value | ||
438 | 2 | SELECT COUNT(@@GLOBAL.have_statement_timeout); | ||
439 | 3 | COUNT(@@GLOBAL.have_statement_timeout) | ||
440 | 4 | 1 | ||
441 | 5 | 1 Expected | ||
442 | 6 | # Check if Value can set | ||
443 | 7 | SET @@GLOBAL.have_statement_timeout=1; | ||
444 | 8 | ERROR HY000: Variable 'have_statement_timeout' is a read only variable | ||
445 | 9 | Expected error 'Read only variable' | ||
446 | 10 | SELECT COUNT(@@GLOBAL.have_statement_timeout); | ||
447 | 11 | COUNT(@@GLOBAL.have_statement_timeout) | ||
448 | 12 | 1 | ||
449 | 13 | 1 Expected | ||
450 | 14 | # Check if the value in GLOBAL Table matches value in variable | ||
451 | 15 | SELECT @@GLOBAL.have_statement_timeout = VARIABLE_VALUE | ||
452 | 16 | FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES | ||
453 | 17 | WHERE VARIABLE_NAME='have_statement_timeout'; | ||
454 | 18 | @@GLOBAL.have_statement_timeout = VARIABLE_VALUE | ||
455 | 19 | 1 | ||
456 | 20 | 1 Expected | ||
457 | 21 | SELECT COUNT(@@GLOBAL.have_statement_timeout); | ||
458 | 22 | COUNT(@@GLOBAL.have_statement_timeout) | ||
459 | 23 | 1 | ||
460 | 24 | 1 Expected | ||
461 | 25 | SELECT COUNT(VARIABLE_VALUE) | ||
462 | 26 | FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES | ||
463 | 27 | WHERE VARIABLE_NAME='have_statement_timeout'; | ||
464 | 28 | COUNT(VARIABLE_VALUE) | ||
465 | 29 | 1 | ||
466 | 30 | 1 Expected | ||
467 | 31 | # Check if accessing variable with and without GLOBAL point to same variable | ||
468 | 32 | SELECT @@have_statement_timeout = @@GLOBAL.have_statement_timeout; | ||
469 | 33 | @@have_statement_timeout = @@GLOBAL.have_statement_timeout | ||
470 | 34 | 1 | ||
471 | 35 | 1 Expected | ||
472 | 36 | # Check if have_statement_timeout can be accessed with and without @@ sign | ||
473 | 37 | SELECT COUNT(@@have_statement_timeout); | ||
474 | 38 | COUNT(@@have_statement_timeout) | ||
475 | 39 | 1 | ||
476 | 40 | 1 Expected | ||
477 | 41 | SELECT COUNT(@@local.have_statement_timeout); | ||
478 | 42 | ERROR HY000: Variable 'have_statement_timeout' is a GLOBAL variable | ||
479 | 43 | Expected error 'Variable is a GLOBAL variable' | ||
480 | 44 | SELECT COUNT(@@SESSION.have_statement_timeout); | ||
481 | 45 | ERROR HY000: Variable 'have_statement_timeout' is a GLOBAL variable | ||
482 | 46 | Expected error 'Variable is a GLOBAL variable' | ||
483 | 47 | SELECT COUNT(@@GLOBAL.have_statement_timeout); | ||
484 | 48 | COUNT(@@GLOBAL.have_statement_timeout) | ||
485 | 49 | 1 | ||
486 | 50 | 1 Expected | ||
487 | 51 | SELECT have_statement_timeout = @@SESSION.have_statement_timeout; | ||
488 | 52 | ERROR 42S22: Unknown column 'have_statement_timeout' in 'field list' | ||
489 | 53 | Expected error 'Unknown column 'have_statement_timeout' in 'field list'' | ||
490 | 0 | 54 | ||
491 | === added file 'Percona-Server/mysql-test/suite/sys_vars/r/max_statement_time_basic.result' | |||
492 | --- Percona-Server/mysql-test/suite/sys_vars/r/max_statement_time_basic.result 1970-01-01 00:00:00 +0000 | |||
493 | +++ Percona-Server/mysql-test/suite/sys_vars/r/max_statement_time_basic.result 2013-09-09 15:30:42 +0000 | |||
494 | @@ -0,0 +1,89 @@ | |||
495 | 1 | # Save initial value | ||
496 | 2 | SET @start_session_value = @@session.max_statement_time; | ||
497 | 3 | SELECT @start_session_value; | ||
498 | 4 | @start_session_value | ||
499 | 5 | 0 | ||
500 | 6 | # Display the DEFAULT value of max_statement_time | ||
501 | 7 | SET @@session.max_statement_time = 20000; | ||
502 | 8 | SET @@session.max_statement_time = DEFAULT; | ||
503 | 9 | SELECT @@session.max_statement_time; | ||
504 | 10 | @@session.max_statement_time | ||
505 | 11 | 0 | ||
506 | 12 | # Check the DEFAULT value of max_statement_time | ||
507 | 13 | SET @@session.max_statement_time = DEFAULT; | ||
508 | 14 | SELECT @@session.max_statement_time = 28800; | ||
509 | 15 | @@session.max_statement_time = 28800 | ||
510 | 16 | 0 | ||
511 | 17 | # Change the value of max_statement_time to a valid value for SESSION scope | ||
512 | 18 | SET @@session.max_statement_time = 10000; | ||
513 | 19 | SELECT @@session.max_statement_time; | ||
514 | 20 | @@session.max_statement_time | ||
515 | 21 | 10000 | ||
516 | 22 | SET @@session.max_statement_time = 50050; | ||
517 | 23 | SELECT @@session.max_statement_time; | ||
518 | 24 | @@session.max_statement_time | ||
519 | 25 | 50050 | ||
520 | 26 | SET @@session.max_statement_time = 65535; | ||
521 | 27 | SELECT @@session.max_statement_time; | ||
522 | 28 | @@session.max_statement_time | ||
523 | 29 | 65535 | ||
524 | 30 | # Change the value of max_statement_time to an invalid value # | ||
525 | 31 | SET @@session.max_statement_time = 0; | ||
526 | 32 | SELECT @@session.max_statement_time; | ||
527 | 33 | @@session.max_statement_time | ||
528 | 34 | 0 | ||
529 | 35 | SET @@session.max_statement_time = -2; | ||
530 | 36 | Warnings: | ||
531 | 37 | Warning 1292 Truncated incorrect max_statement_time value: '-2' | ||
532 | 38 | SELECT @@session.max_statement_time; | ||
533 | 39 | @@session.max_statement_time | ||
534 | 40 | 0 | ||
535 | 41 | SET @@session.max_statement_time = 65530.34; | ||
536 | 42 | ERROR 42000: Incorrect argument type to variable 'max_statement_time' | ||
537 | 43 | SET @@session.max_statement_time = 100000000; | ||
538 | 44 | SELECT @@session.max_statement_time; | ||
539 | 45 | @@session.max_statement_time | ||
540 | 46 | 100000000 | ||
541 | 47 | SET @@session.max_statement_time = test; | ||
542 | 48 | ERROR 42000: Incorrect argument type to variable 'max_statement_time' | ||
543 | 49 | SELECT @@session.max_statement_time; | ||
544 | 50 | @@session.max_statement_time | ||
545 | 51 | 100000000 | ||
546 | 52 | # Check if the value in SESSION Table matches value in variable | ||
547 | 53 | SELECT @@session.max_statement_time = VARIABLE_VALUE | ||
548 | 54 | FROM INFORMATION_SCHEMA.SESSION_VARIABLES | ||
549 | 55 | WHERE VARIABLE_NAME='max_statement_time'; | ||
550 | 56 | @@session.max_statement_time = VARIABLE_VALUE | ||
551 | 57 | 1 | ||
552 | 58 | # Check if TRUE and FALSE values can be used on variable | ||
553 | 59 | SET @@session.max_statement_time = TRUE; | ||
554 | 60 | SELECT @@session.max_statement_time; | ||
555 | 61 | @@session.max_statement_time | ||
556 | 62 | 1 | ||
557 | 63 | SET @@session.max_statement_time = FALSE; | ||
558 | 64 | SELECT @@session.max_statement_time; | ||
559 | 65 | @@session.max_statement_time | ||
560 | 66 | 0 | ||
561 | 67 | # Check if accessing variable with SESSION,LOCAL and without SCOPE points to same session variable | ||
562 | 68 | SET @@max_statement_time = 10000; | ||
563 | 69 | SELECT @@max_statement_time = @@local.max_statement_time; | ||
564 | 70 | @@max_statement_time = @@local.max_statement_time | ||
565 | 71 | 1 | ||
566 | 72 | SELECT @@local.max_statement_time = @@session.max_statement_time; | ||
567 | 73 | @@local.max_statement_time = @@session.max_statement_time | ||
568 | 74 | 1 | ||
569 | 75 | # Check if max_statement_time can be accessed with and without @@ sign | ||
570 | 76 | SET max_statement_time = 10000; | ||
571 | 77 | SELECT @@max_statement_time; | ||
572 | 78 | @@max_statement_time | ||
573 | 79 | 10000 | ||
574 | 80 | SELECT local.max_statement_time; | ||
575 | 81 | ERROR 42S02: Unknown table 'local' in field list | ||
576 | 82 | SELECT session.max_statement_time; | ||
577 | 83 | ERROR 42S02: Unknown table 'session' in field list | ||
578 | 84 | SET @@global.max_statement_time = 0; | ||
579 | 85 | # Restore initial value | ||
580 | 86 | SET @@session.max_statement_time = @start_session_value; | ||
581 | 87 | SELECT @@session.max_statement_time; | ||
582 | 88 | @@session.max_statement_time | ||
583 | 89 | 0 | ||
584 | 0 | 90 | ||
585 | === added file 'Percona-Server/mysql-test/suite/sys_vars/t/have_statement_timeout_basic.test' | |||
586 | --- Percona-Server/mysql-test/suite/sys_vars/t/have_statement_timeout_basic.test 1970-01-01 00:00:00 +0000 | |||
587 | +++ Percona-Server/mysql-test/suite/sys_vars/t/have_statement_timeout_basic.test 2013-09-09 15:30:42 +0000 | |||
588 | @@ -0,0 +1,55 @@ | |||
589 | 1 | --source include/have_statement_timeout.inc | ||
590 | 2 | |||
591 | 3 | --echo # Displaying default value | ||
592 | 4 | |||
593 | 5 | SELECT COUNT(@@GLOBAL.have_statement_timeout); | ||
594 | 6 | --echo 1 Expected | ||
595 | 7 | |||
596 | 8 | --echo # Check if Value can set | ||
597 | 9 | |||
598 | 10 | --error ER_INCORRECT_GLOBAL_LOCAL_VAR | ||
599 | 11 | SET @@GLOBAL.have_statement_timeout=1; | ||
600 | 12 | --echo Expected error 'Read only variable' | ||
601 | 13 | |||
602 | 14 | SELECT COUNT(@@GLOBAL.have_statement_timeout); | ||
603 | 15 | --echo 1 Expected | ||
604 | 16 | |||
605 | 17 | --echo # Check if the value in GLOBAL Table matches value in variable | ||
606 | 18 | |||
607 | 19 | SELECT @@GLOBAL.have_statement_timeout = VARIABLE_VALUE | ||
608 | 20 | FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES | ||
609 | 21 | WHERE VARIABLE_NAME='have_statement_timeout'; | ||
610 | 22 | --echo 1 Expected | ||
611 | 23 | |||
612 | 24 | SELECT COUNT(@@GLOBAL.have_statement_timeout); | ||
613 | 25 | --echo 1 Expected | ||
614 | 26 | |||
615 | 27 | SELECT COUNT(VARIABLE_VALUE) | ||
616 | 28 | FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES | ||
617 | 29 | WHERE VARIABLE_NAME='have_statement_timeout'; | ||
618 | 30 | --echo 1 Expected | ||
619 | 31 | |||
620 | 32 | --echo # Check if accessing variable with and without GLOBAL point to same variable | ||
621 | 33 | |||
622 | 34 | SELECT @@have_statement_timeout = @@GLOBAL.have_statement_timeout; | ||
623 | 35 | --echo 1 Expected | ||
624 | 36 | |||
625 | 37 | --echo # Check if have_statement_timeout can be accessed with and without @@ sign | ||
626 | 38 | |||
627 | 39 | SELECT COUNT(@@have_statement_timeout); | ||
628 | 40 | --echo 1 Expected | ||
629 | 41 | |||
630 | 42 | --error ER_INCORRECT_GLOBAL_LOCAL_VAR | ||
631 | 43 | SELECT COUNT(@@local.have_statement_timeout); | ||
632 | 44 | --echo Expected error 'Variable is a GLOBAL variable' | ||
633 | 45 | |||
634 | 46 | --error ER_INCORRECT_GLOBAL_LOCAL_VAR | ||
635 | 47 | SELECT COUNT(@@SESSION.have_statement_timeout); | ||
636 | 48 | --echo Expected error 'Variable is a GLOBAL variable' | ||
637 | 49 | |||
638 | 50 | SELECT COUNT(@@GLOBAL.have_statement_timeout); | ||
639 | 51 | --echo 1 Expected | ||
640 | 52 | |||
641 | 53 | --error ER_BAD_FIELD_ERROR | ||
642 | 54 | SELECT have_statement_timeout = @@SESSION.have_statement_timeout; | ||
643 | 55 | --echo Expected error 'Unknown column 'have_statement_timeout' in 'field list'' | ||
644 | 0 | 56 | ||
645 | === added file 'Percona-Server/mysql-test/suite/sys_vars/t/max_statement_time_basic.test' | |||
646 | --- Percona-Server/mysql-test/suite/sys_vars/t/max_statement_time_basic.test 1970-01-01 00:00:00 +0000 | |||
647 | +++ Percona-Server/mysql-test/suite/sys_vars/t/max_statement_time_basic.test 2013-09-09 15:30:42 +0000 | |||
648 | @@ -0,0 +1,78 @@ | |||
649 | 1 | --source include/have_statement_timeout.inc | ||
650 | 2 | |||
651 | 3 | --echo # Save initial value | ||
652 | 4 | |||
653 | 5 | SET @start_session_value = @@session.max_statement_time; | ||
654 | 6 | SELECT @start_session_value; | ||
655 | 7 | |||
656 | 8 | --echo # Display the DEFAULT value of max_statement_time | ||
657 | 9 | |||
658 | 10 | SET @@session.max_statement_time = 20000; | ||
659 | 11 | SET @@session.max_statement_time = DEFAULT; | ||
660 | 12 | SELECT @@session.max_statement_time; | ||
661 | 13 | |||
662 | 14 | --echo # Check the DEFAULT value of max_statement_time | ||
663 | 15 | |||
664 | 16 | SET @@session.max_statement_time = DEFAULT; | ||
665 | 17 | SELECT @@session.max_statement_time = 28800; | ||
666 | 18 | |||
667 | 19 | --echo # Change the value of max_statement_time to a valid value for SESSION scope | ||
668 | 20 | |||
669 | 21 | SET @@session.max_statement_time = 10000; | ||
670 | 22 | SELECT @@session.max_statement_time; | ||
671 | 23 | SET @@session.max_statement_time = 50050; | ||
672 | 24 | SELECT @@session.max_statement_time; | ||
673 | 25 | SET @@session.max_statement_time = 65535; | ||
674 | 26 | SELECT @@session.max_statement_time; | ||
675 | 27 | |||
676 | 28 | --echo # Change the value of max_statement_time to an invalid value # | ||
677 | 29 | |||
678 | 30 | SET @@session.max_statement_time = 0; | ||
679 | 31 | SELECT @@session.max_statement_time; | ||
680 | 32 | SET @@session.max_statement_time = -2; | ||
681 | 33 | SELECT @@session.max_statement_time; | ||
682 | 34 | --error ER_WRONG_TYPE_FOR_VAR | ||
683 | 35 | SET @@session.max_statement_time = 65530.34; | ||
684 | 36 | SET @@session.max_statement_time = 100000000; | ||
685 | 37 | SELECT @@session.max_statement_time; | ||
686 | 38 | |||
687 | 39 | --error ER_WRONG_TYPE_FOR_VAR | ||
688 | 40 | SET @@session.max_statement_time = test; | ||
689 | 41 | SELECT @@session.max_statement_time; | ||
690 | 42 | |||
691 | 43 | --echo # Check if the value in SESSION Table matches value in variable | ||
692 | 44 | |||
693 | 45 | SELECT @@session.max_statement_time = VARIABLE_VALUE | ||
694 | 46 | FROM INFORMATION_SCHEMA.SESSION_VARIABLES | ||
695 | 47 | WHERE VARIABLE_NAME='max_statement_time'; | ||
696 | 48 | |||
697 | 49 | --echo # Check if TRUE and FALSE values can be used on variable | ||
698 | 50 | |||
699 | 51 | SET @@session.max_statement_time = TRUE; | ||
700 | 52 | SELECT @@session.max_statement_time; | ||
701 | 53 | SET @@session.max_statement_time = FALSE; | ||
702 | 54 | SELECT @@session.max_statement_time; | ||
703 | 55 | |||
704 | 56 | --echo # Check if accessing variable with SESSION,LOCAL and without SCOPE points to same session variable | ||
705 | 57 | |||
706 | 58 | SET @@max_statement_time = 10000; | ||
707 | 59 | SELECT @@max_statement_time = @@local.max_statement_time; | ||
708 | 60 | SELECT @@local.max_statement_time = @@session.max_statement_time; | ||
709 | 61 | |||
710 | 62 | --echo # Check if max_statement_time can be accessed with and without @@ sign | ||
711 | 63 | |||
712 | 64 | SET max_statement_time = 10000; | ||
713 | 65 | SELECT @@max_statement_time; | ||
714 | 66 | --error ER_UNKNOWN_TABLE | ||
715 | 67 | SELECT local.max_statement_time; | ||
716 | 68 | --error ER_UNKNOWN_TABLE | ||
717 | 69 | SELECT session.max_statement_time; | ||
718 | 70 | |||
719 | 71 | #--echo # Check that the variable is a SESSION-only variable | ||
720 | 72 | #--error ER_LOCAL_VARIABLE | ||
721 | 73 | SET @@global.max_statement_time = 0; | ||
722 | 74 | |||
723 | 75 | --echo # Restore initial value | ||
724 | 76 | |||
725 | 77 | SET @@session.max_statement_time = @start_session_value; | ||
726 | 78 | SELECT @@session.max_statement_time; | ||
727 | 0 | 79 | ||
728 | === added file 'Percona-Server/mysql-test/t/max_statement_time_func.test' | |||
729 | --- Percona-Server/mysql-test/t/max_statement_time_func.test 1970-01-01 00:00:00 +0000 | |||
730 | +++ Percona-Server/mysql-test/t/max_statement_time_func.test 2013-09-09 15:30:42 +0000 | |||
731 | @@ -0,0 +1,154 @@ | |||
732 | 1 | --source include/have_statement_timeout.inc | ||
733 | 2 | --source include/not_embedded.inc | ||
734 | 3 | --source include/have_innodb.inc | ||
735 | 4 | |||
736 | 5 | SET @old_session_max_statement_time = @@SESSION.max_statement_time; | ||
737 | 6 | |||
738 | 7 | --echo # | ||
739 | 8 | --echo # Test max statement time interruption. | ||
740 | 9 | --echo # Note that if SLEEP() is interrupted, it returns 1. | ||
741 | 10 | --echo # | ||
742 | 11 | |||
743 | 12 | SET @@SESSION.max_statement_time = 10; | ||
744 | 13 | SELECT SLEEP(1000); | ||
745 | 14 | SET @@SESSION.max_statement_time = 0; | ||
746 | 15 | |||
747 | 16 | --echo # | ||
748 | 17 | --echo # Apply timeout to the top-level statement. | ||
749 | 18 | --echo # | ||
750 | 19 | |||
751 | 20 | DELIMITER |; | ||
752 | 21 | |||
753 | 22 | CREATE PROCEDURE p1() | ||
754 | 23 | BEGIN | ||
755 | 24 | SELECT SLEEP(1000); | ||
756 | 25 | END| | ||
757 | 26 | |||
758 | 27 | DELIMITER ;| | ||
759 | 28 | |||
760 | 29 | SET @@SESSION.max_statement_time = 10; | ||
761 | 30 | CALL p1(); | ||
762 | 31 | SET @@SESSION.max_statement_time = 0; | ||
763 | 32 | |||
764 | 33 | --echo # Apply timeout to prepared statements. | ||
765 | 34 | PREPARE prep_1 FROM 'call p1()'; | ||
766 | 35 | SET @@SESSION.max_statement_time = 10; | ||
767 | 36 | EXECUTE prep_1; | ||
768 | 37 | SET @@SESSION.max_statement_time = 0; | ||
769 | 38 | |||
770 | 39 | DROP PREPARE prep_1; | ||
771 | 40 | DROP PROCEDURE p1; | ||
772 | 41 | |||
773 | 42 | --echo # | ||
774 | 43 | --echo # Interrupt a statement that changes data. | ||
775 | 44 | --echo # | ||
776 | 45 | |||
777 | 46 | CREATE TABLE t1 (a INT); | ||
778 | 47 | |||
779 | 48 | DELIMITER |; | ||
780 | 49 | |||
781 | 50 | CREATE FUNCTION f1() RETURNS INT | ||
782 | 51 | BEGIN | ||
783 | 52 | WHILE true DO | ||
784 | 53 | INSERT INTO t1 VALUES (1); | ||
785 | 54 | END WHILE; | ||
786 | 55 | RETURN 1; | ||
787 | 56 | END| | ||
788 | 57 | |||
789 | 58 | DELIMITER ;| | ||
790 | 59 | |||
791 | 60 | SET @@SESSION.max_statement_time = 500; | ||
792 | 61 | --error ER_QUERY_TIMEOUT | ||
793 | 62 | SELECT f1(); | ||
794 | 63 | SET @@SESSION.max_statement_time = 0; | ||
795 | 64 | |||
796 | 65 | DROP FUNCTION f1; | ||
797 | 66 | DROP TABLE t1; | ||
798 | 67 | |||
799 | 68 | SELECT CONVERT(VARIABLE_VALUE, UNSIGNED) INTO @time_set | ||
800 | 69 | FROM INFORMATION_SCHEMA.GLOBAL_STATUS | ||
801 | 70 | WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_SET'; | ||
802 | 71 | |||
803 | 72 | SELECT CONVERT(VARIABLE_VALUE, UNSIGNED) INTO @time_exceeded | ||
804 | 73 | FROM INFORMATION_SCHEMA.GLOBAL_STATUS | ||
805 | 74 | WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_EXCEEDED'; | ||
806 | 75 | |||
807 | 76 | SET @@SESSION.max_statement_time = 100; | ||
808 | 77 | SELECT SLEEP(1000); | ||
809 | 78 | |||
810 | 79 | --echo # Ensure that the counters for: | ||
811 | 80 | --echo # - statements that are time limited; and | ||
812 | 81 | --echo # - statements that exceeded their maximum execution time | ||
813 | 82 | --echo # are incremented. | ||
814 | 83 | |||
815 | 84 | SELECT 1 AS STATUS FROM INFORMATION_SCHEMA.GLOBAL_STATUS | ||
816 | 85 | WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_SET' | ||
817 | 86 | AND CONVERT(VARIABLE_VALUE, UNSIGNED) > @time_set; | ||
818 | 87 | |||
819 | 88 | SELECT 1 AS STATUS FROM INFORMATION_SCHEMA.GLOBAL_STATUS | ||
820 | 89 | WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_EXCEEDED' | ||
821 | 90 | AND CONVERT(VARIABLE_VALUE, UNSIGNED) > @time_exceeded; | ||
822 | 91 | |||
823 | 92 | SET @@SESSION.max_statement_time = default; | ||
824 | 93 | |||
825 | 94 | --echo | ||
826 | 95 | --echo # Check that the appropriate error status is set. | ||
827 | 96 | --echo | ||
828 | 97 | |||
829 | 98 | CREATE TABLE t1 (a INT) ENGINE=InnoDB; | ||
830 | 99 | INSERT INTO t1 VALUES (1); | ||
831 | 100 | |||
832 | 101 | START TRANSACTION; | ||
833 | 102 | SELECT * FROM t1 FOR UPDATE; | ||
834 | 103 | |||
835 | 104 | connect (con1,localhost,root,,test,,); | ||
836 | 105 | SET @@SESSION.max_statement_time = 100; | ||
837 | 106 | --error ER_QUERY_TIMEOUT | ||
838 | 107 | UPDATE t1 SET a = 2; | ||
839 | 108 | SHOW WARNINGS; | ||
840 | 109 | disconnect con1; | ||
841 | 110 | |||
842 | 111 | connection default; | ||
843 | 112 | ROLLBACK; | ||
844 | 113 | |||
845 | 114 | DROP TABLE t1; | ||
846 | 115 | |||
847 | 116 | |||
848 | 117 | --echo # | ||
849 | 118 | --echo # Test interaction with lock waits. | ||
850 | 119 | --echo # | ||
851 | 120 | |||
852 | 121 | CREATE TABLE t1 (a INT) ENGINE=InnoDB; | ||
853 | 122 | INSERT INTO t1 VALUES (1); | ||
854 | 123 | |||
855 | 124 | connect (con1,localhost,root,,test,,); | ||
856 | 125 | SET @@SESSION.max_statement_time = 500; | ||
857 | 126 | |||
858 | 127 | connection default; | ||
859 | 128 | LOCK TABLES t1 WRITE; | ||
860 | 129 | |||
861 | 130 | connection con1; | ||
862 | 131 | --error ER_QUERY_TIMEOUT | ||
863 | 132 | LOCK TABLES t1 READ; | ||
864 | 133 | |||
865 | 134 | connection default; | ||
866 | 135 | UNLOCK TABLES; | ||
867 | 136 | BEGIN; | ||
868 | 137 | SELECT * FROM t1; | ||
869 | 138 | |||
870 | 139 | connection con1; | ||
871 | 140 | --error ER_QUERY_TIMEOUT | ||
872 | 141 | ALTER TABLE t1 ADD COLUMN b INT; | ||
873 | 142 | |||
874 | 143 | connection default; | ||
875 | 144 | ROLLBACK; | ||
876 | 145 | SELECT GET_LOCK('lock', 1); | ||
877 | 146 | |||
878 | 147 | connection con1; | ||
879 | 148 | SELECT GET_LOCK('lock', 1); | ||
880 | 149 | |||
881 | 150 | disconnect con1; | ||
882 | 151 | connection default; | ||
883 | 152 | SELECT RELEASE_LOCK('lock'); | ||
884 | 153 | DROP TABLE t1; | ||
885 | 154 | SET @@SESSION.max_statement_time = @old_session_max_statement_time; | ||
886 | 0 | 155 | ||
887 | === modified file 'Percona-Server/mysys/CMakeLists.txt' | |||
888 | --- Percona-Server/mysys/CMakeLists.txt 2013-08-06 15:16:34 +0000 | |||
889 | +++ Percona-Server/mysys/CMakeLists.txt 2013-09-09 15:30:42 +0000 | |||
890 | @@ -45,6 +45,14 @@ | |||
891 | 45 | SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_alarm.c) | 45 | SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_alarm.c) |
892 | 46 | ENDIF() | 46 | ENDIF() |
893 | 47 | 47 | ||
894 | 48 | IF(HAVE_POSIX_TIMERS) | ||
895 | 49 | SET(MYSYS_SOURCES ${MYSYS_SOURCES} posix_timers.c) | ||
896 | 50 | ENDIF() | ||
897 | 51 | |||
898 | 52 | IF(HAVE_KQUEUE_TIMERS) | ||
899 | 53 | SET(MYSYS_SOURCES ${MYSYS_SOURCES} kqueue_timers.c) | ||
900 | 54 | ENDIF() | ||
901 | 55 | |||
902 | 48 | IF(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND CMAKE_C_COMPILER_ID MATCHES "SunPro") | 56 | IF(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND CMAKE_C_COMPILER_ID MATCHES "SunPro") |
903 | 49 | # Inline assembly template for rdtsc | 57 | # Inline assembly template for rdtsc |
904 | 50 | SET_SOURCE_FILES_PROPERTIES(my_rdtsc.c | 58 | SET_SOURCE_FILES_PROPERTIES(my_rdtsc.c |
905 | 51 | 59 | ||
906 | === added file 'Percona-Server/mysys/kqueue_timers.c' | |||
907 | --- Percona-Server/mysys/kqueue_timers.c 1970-01-01 00:00:00 +0000 | |||
908 | +++ Percona-Server/mysys/kqueue_timers.c 2013-09-09 15:30:42 +0000 | |||
909 | @@ -0,0 +1,219 @@ | |||
910 | 1 | /* Copyright (c) 2012, Twitter, Inc. All rights reserved. | ||
911 | 2 | |||
912 | 3 | This program is free software; you can redistribute it and/or modify | ||
913 | 4 | it under the terms of the GNU General Public License as published by | ||
914 | 5 | the Free Software Foundation; version 2 of the License. | ||
915 | 6 | |||
916 | 7 | This program is distributed in the hope that it will be useful, | ||
917 | 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
918 | 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
919 | 10 | GNU General Public License for more details. | ||
920 | 11 | |||
921 | 12 | You should have received a copy of the GNU General Public License along | ||
922 | 13 | with this program; if not, write to the Free Software Foundation, Inc., | ||
923 | 14 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ | ||
924 | 15 | |||
925 | 16 | #include "my_timer.h" /* my_timer_t */ | ||
926 | 17 | #include "my_pthread.h" /* my_thread_init, my_thread_end */ | ||
927 | 18 | |||
928 | 19 | #include <sys/types.h> | ||
929 | 20 | #include <sys/event.h> | ||
930 | 21 | #include <sys/time.h> | ||
931 | 22 | #include <assert.h> | ||
932 | 23 | #include <errno.h> | ||
933 | 24 | |||
934 | 25 | static int kq_fd= -1; | ||
935 | 26 | static pthread_t thread; | ||
936 | 27 | |||
937 | 28 | /** | ||
938 | 29 | Timer expiration notification thread. | ||
939 | 30 | |||
940 | 31 | @param arg Unused. | ||
941 | 32 | */ | ||
942 | 33 | |||
943 | 34 | static void * | ||
944 | 35 | timer_notify_thread(void *arg __attribute__((unused))) | ||
945 | 36 | { | ||
946 | 37 | my_timer_t *timer; | ||
947 | 38 | struct kevent kev; | ||
948 | 39 | |||
949 | 40 | my_thread_init(); | ||
950 | 41 | |||
951 | 42 | while (1) | ||
952 | 43 | { | ||
953 | 44 | if (kevent(kq_fd, NULL, 0, &kev, 1, NULL) < 0) | ||
954 | 45 | continue; | ||
955 | 46 | |||
956 | 47 | if (kev.filter == EVFILT_TIMER) | ||
957 | 48 | { | ||
958 | 49 | timer= kev.udata; | ||
959 | 50 | assert(timer->id == kev.ident); | ||
960 | 51 | timer->notify_function(timer); | ||
961 | 52 | } | ||
962 | 53 | else if (kev.filter == EVFILT_USER) | ||
963 | 54 | break; | ||
964 | 55 | } | ||
965 | 56 | |||
966 | 57 | my_thread_end(); | ||
967 | 58 | |||
968 | 59 | return NULL; | ||
969 | 60 | } | ||
970 | 61 | |||
971 | 62 | |||
972 | 63 | /** | ||
973 | 64 | Create a helper thread to dispatch timer expiration notifications. | ||
974 | 65 | |||
975 | 66 | @return On success, 0. On error, -1 is returned. | ||
976 | 67 | */ | ||
977 | 68 | |||
978 | 69 | static int | ||
979 | 70 | start_helper_thread(void) | ||
980 | 71 | { | ||
981 | 72 | struct kevent kev; | ||
982 | 73 | |||
983 | 74 | EV_SET(&kev, 0, EVFILT_USER, EV_ADD, 0, 0, 0); | ||
984 | 75 | |||
985 | 76 | if (kevent(kq_fd, &kev, 1, NULL, 0, NULL) < 0) | ||
986 | 77 | return -1; | ||
987 | 78 | |||
988 | 79 | return pthread_create(&thread, NULL, timer_notify_thread, NULL); | ||
989 | 80 | } | ||
990 | 81 | |||
991 | 82 | |||
992 | 83 | /** | ||
993 | 84 | Initialize internal components. | ||
994 | 85 | |||
995 | 86 | @return On success, 0. | ||
996 | 87 | On error, -1 is returned, and errno is set to indicate the error. | ||
997 | 88 | */ | ||
998 | 89 | |||
999 | 90 | int | ||
1000 | 91 | my_os_timer_init_ext(void) | ||
1001 | 92 | { | ||
1002 | 93 | int rc; | ||
1003 | 94 | |||
1004 | 95 | /* Create a file descriptor for event notification. */ | ||
1005 | 96 | if ((kq_fd= kqueue()) < 0) | ||
1006 | 97 | return -1; | ||
1007 | 98 | |||
1008 | 99 | /* Create a helper thread. */ | ||
1009 | 100 | if ((rc= start_helper_thread())) | ||
1010 | 101 | close(kq_fd); | ||
1011 | 102 | |||
1012 | 103 | return rc; | ||
1013 | 104 | } | ||
1014 | 105 | |||
1015 | 106 | |||
1016 | 107 | /** | ||
1017 | 108 | Release any resources that were allocated as part of initialization. | ||
1018 | 109 | */ | ||
1019 | 110 | |||
1020 | 111 | void | ||
1021 | 112 | my_os_timer_deinit(void) | ||
1022 | 113 | { | ||
1023 | 114 | struct kevent kev; | ||
1024 | 115 | |||
1025 | 116 | EV_SET(&kev, 0, EVFILT_USER, 0, NOTE_TRIGGER, 0, 0); | ||
1026 | 117 | |||
1027 | 118 | /* There's not much to do if triggering the event fails. */ | ||
1028 | 119 | if (kevent(kq_fd, &kev, 1, NULL, 0, NULL) > -1) | ||
1029 | 120 | pthread_join(thread, NULL); | ||
1030 | 121 | |||
1031 | 122 | close(kq_fd); | ||
1032 | 123 | } | ||
1033 | 124 | |||
1034 | 125 | |||
1035 | 126 | /** | ||
1036 | 127 | Create a timer object. | ||
1037 | 128 | |||
1038 | 129 | @param timer Timer object. | ||
1039 | 130 | |||
1040 | 131 | @return On success, 0. | ||
1041 | 132 | On error, -1 is returned, and errno is set to indicate the error. | ||
1042 | 133 | */ | ||
1043 | 134 | |||
1044 | 135 | int | ||
1045 | 136 | my_os_timer_create(my_timer_t *timer) | ||
1046 | 137 | { | ||
1047 | 138 | assert(kq_fd >= 0); | ||
1048 | 139 | |||
1049 | 140 | timer->id= (uintptr_t) timer; | ||
1050 | 141 | |||
1051 | 142 | return 0; | ||
1052 | 143 | } | ||
1053 | 144 | |||
1054 | 145 | |||
1055 | 146 | /** | ||
1056 | 147 | Set the time until the next expiration of the timer. | ||
1057 | 148 | |||
1058 | 149 | @param timer Timer object. | ||
1059 | 150 | @param time Amount of time (in milliseconds) before the timer expires. | ||
1060 | 151 | |||
1061 | 152 | @return On success, 0. | ||
1062 | 153 | On error, -1 is returned, and errno is set to indicate the error. | ||
1063 | 154 | */ | ||
1064 | 155 | |||
1065 | 156 | int | ||
1066 | 157 | my_os_timer_set(my_timer_t *timer, unsigned long time) | ||
1067 | 158 | { | ||
1068 | 159 | struct kevent kev; | ||
1069 | 160 | |||
1070 | 161 | EV_SET(&kev, timer->id, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, time, timer); | ||
1071 | 162 | |||
1072 | 163 | return kevent(kq_fd, &kev, 1, NULL, 0, NULL); | ||
1073 | 164 | } | ||
1074 | 165 | |||
1075 | 166 | |||
1076 | 167 | /** | ||
1077 | 168 | Reset the time until the next expiration of the timer. | ||
1078 | 169 | |||
1079 | 170 | @param timer Timer object. | ||
1080 | 171 | @param state The state of the timer at the time of cancellation, either | ||
1081 | 172 | signaled (false) or nonsignaled (true). | ||
1082 | 173 | |||
1083 | 174 | @return On success, 0. | ||
1084 | 175 | On error, -1 is returned, and errno is set to indicate the error. | ||
1085 | 176 | */ | ||
1086 | 177 | |||
1087 | 178 | int | ||
1088 | 179 | my_os_timer_reset(my_timer_t *timer, int *state) | ||
1089 | 180 | { | ||
1090 | 181 | int status; | ||
1091 | 182 | struct kevent kev; | ||
1092 | 183 | |||
1093 | 184 | EV_SET(&kev, timer->id, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); | ||
1094 | 185 | |||
1095 | 186 | status= kevent(kq_fd, &kev, 1, NULL, 0, NULL); | ||
1096 | 187 | |||
1097 | 188 | /* | ||
1098 | 189 | If the event was retrieved from the kqueue (at which point we | ||
1099 | 190 | consider it to be signaled), the timer was automatically deleted. | ||
1100 | 191 | */ | ||
1101 | 192 | if (!status) | ||
1102 | 193 | *state= 1; | ||
1103 | 194 | else if (errno == ENOENT) | ||
1104 | 195 | { | ||
1105 | 196 | *state= 0; | ||
1106 | 197 | status= 0; | ||
1107 | 198 | } | ||
1108 | 199 | |||
1109 | 200 | return status; | ||
1110 | 201 | } | ||
1111 | 202 | |||
1112 | 203 | |||
1113 | 204 | /** | ||
1114 | 205 | Delete a timer object. | ||
1115 | 206 | |||
1116 | 207 | @param timer Timer object. | ||
1117 | 208 | */ | ||
1118 | 209 | |||
1119 | 210 | void | ||
1120 | 211 | my_os_timer_delete(my_timer_t *timer) | ||
1121 | 212 | { | ||
1122 | 213 | struct kevent kev; | ||
1123 | 214 | |||
1124 | 215 | EV_SET(&kev, timer->id, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); | ||
1125 | 216 | |||
1126 | 217 | kevent(kq_fd, &kev, 1, NULL, 0, NULL); | ||
1127 | 218 | } | ||
1128 | 219 | |||
1129 | 0 | 220 | ||
1130 | === added file 'Percona-Server/mysys/posix_timers.c' | |||
1131 | --- Percona-Server/mysys/posix_timers.c 1970-01-01 00:00:00 +0000 | |||
1132 | +++ Percona-Server/mysys/posix_timers.c 2013-09-09 15:30:42 +0000 | |||
1133 | @@ -0,0 +1,256 @@ | |||
1134 | 1 | /* Copyright (c) 2012, Twitter, Inc. All rights reserved. | ||
1135 | 2 | |||
1136 | 3 | This program is free software; you can redistribute it and/or modify | ||
1137 | 4 | it under the terms of the GNU General Public License as published by | ||
1138 | 5 | the Free Software Foundation; version 2 of the License. | ||
1139 | 6 | |||
1140 | 7 | This program is distributed in the hope that it will be useful, | ||
1141 | 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1142 | 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1143 | 10 | GNU General Public License for more details. | ||
1144 | 11 | |||
1145 | 12 | You should have received a copy of the GNU General Public License along | ||
1146 | 13 | with this program; if not, write to the Free Software Foundation, Inc., | ||
1147 | 14 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ | ||
1148 | 15 | |||
1149 | 16 | #include "my_timer.h" /* my_timer_t */ | ||
1150 | 17 | #include "my_pthread.h" /* my_thread_init, my_thread_end */ | ||
1151 | 18 | #include "m_string.h" /* memset */ | ||
1152 | 19 | #include <sys/syscall.h> /* SYS_gettid */ | ||
1153 | 20 | |||
1154 | 21 | #ifndef sigev_notify_thread_id | ||
1155 | 22 | #define sigev_notify_thread_id _sigev_un._tid | ||
1156 | 23 | #endif | ||
1157 | 24 | |||
1158 | 25 | #define MY_TIMER_EVENT_SIGNO (SIGRTMIN) | ||
1159 | 26 | #define MY_TIMER_KILL_SIGNO (SIGRTMIN+1) | ||
1160 | 27 | |||
1161 | 28 | /* Timer thread object. */ | ||
1162 | 29 | static pthread_t thread; | ||
1163 | 30 | |||
1164 | 31 | /* Timer thread ID (TID). */ | ||
1165 | 32 | static pid_t thread_id; | ||
1166 | 33 | |||
1167 | 34 | /** | ||
1168 | 35 | Timer expiration notification function. | ||
1169 | 36 | |||
1170 | 37 | @param sigev_value Signal (notification) value. | ||
1171 | 38 | |||
1172 | 39 | @remark The notification function is usually run in a helper thread | ||
1173 | 40 | and is called each time the timer expires. | ||
1174 | 41 | */ | ||
1175 | 42 | |||
1176 | 43 | static void | ||
1177 | 44 | timer_notify_function(sigval_t sigev_value) | ||
1178 | 45 | { | ||
1179 | 46 | my_timer_t *timer= sigev_value.sival_ptr; | ||
1180 | 47 | timer->notify_function(timer); | ||
1181 | 48 | } | ||
1182 | 49 | |||
1183 | 50 | |||
1184 | 51 | /** | ||
1185 | 52 | Timer expiration notification thread. | ||
1186 | 53 | |||
1187 | 54 | @param arg Barrier object. | ||
1188 | 55 | */ | ||
1189 | 56 | |||
1190 | 57 | static void * | ||
1191 | 58 | timer_notify_thread(void *arg) | ||
1192 | 59 | { | ||
1193 | 60 | sigset_t set; | ||
1194 | 61 | siginfo_t info; | ||
1195 | 62 | pthread_barrier_t *barrier= arg; | ||
1196 | 63 | |||
1197 | 64 | my_thread_init(); | ||
1198 | 65 | |||
1199 | 66 | sigemptyset(&set); | ||
1200 | 67 | sigaddset(&set, MY_TIMER_EVENT_SIGNO); | ||
1201 | 68 | sigaddset(&set, MY_TIMER_KILL_SIGNO); | ||
1202 | 69 | |||
1203 | 70 | /* Get the thread ID of the current thread. */ | ||
1204 | 71 | thread_id= (pid_t) syscall(SYS_gettid); | ||
1205 | 72 | |||
1206 | 73 | /* Wake up parent thread, thread_id is available. */ | ||
1207 | 74 | pthread_barrier_wait(barrier); | ||
1208 | 75 | |||
1209 | 76 | while (1) | ||
1210 | 77 | { | ||
1211 | 78 | if (sigwaitinfo(&set, &info) < 0) | ||
1212 | 79 | continue; | ||
1213 | 80 | |||
1214 | 81 | if (info.si_signo == MY_TIMER_EVENT_SIGNO) | ||
1215 | 82 | timer_notify_function(info.si_value); | ||
1216 | 83 | else if (info.si_signo == MY_TIMER_KILL_SIGNO) | ||
1217 | 84 | break; | ||
1218 | 85 | } | ||
1219 | 86 | |||
1220 | 87 | my_thread_end(); | ||
1221 | 88 | |||
1222 | 89 | return NULL; | ||
1223 | 90 | } | ||
1224 | 91 | |||
1225 | 92 | |||
1226 | 93 | /** | ||
1227 | 94 | Create a helper thread to dispatch timer expiration notifications. | ||
1228 | 95 | |||
1229 | 96 | @return On success, 0. On error, -1 is returned. | ||
1230 | 97 | */ | ||
1231 | 98 | |||
1232 | 99 | static int | ||
1233 | 100 | start_helper_thread(void) | ||
1234 | 101 | { | ||
1235 | 102 | pthread_barrier_t barrier; | ||
1236 | 103 | |||
1237 | 104 | if (pthread_barrier_init(&barrier, NULL, 2)) | ||
1238 | 105 | return -1; | ||
1239 | 106 | |||
1240 | 107 | if (pthread_create(&thread, NULL, timer_notify_thread, &barrier)) | ||
1241 | 108 | return -1; | ||
1242 | 109 | |||
1243 | 110 | pthread_barrier_wait(&barrier); | ||
1244 | 111 | pthread_barrier_destroy(&barrier); | ||
1245 | 112 | |||
1246 | 113 | return 0; | ||
1247 | 114 | } | ||
1248 | 115 | |||
1249 | 116 | |||
1250 | 117 | /** | ||
1251 | 118 | Initialize internal components. | ||
1252 | 119 | |||
1253 | 120 | @return On success, 0. | ||
1254 | 121 | On error, -1 is returned, and errno is set to indicate the error. | ||
1255 | 122 | */ | ||
1256 | 123 | |||
1257 | 124 | int | ||
1258 | 125 | my_os_timer_init_ext(void) | ||
1259 | 126 | { | ||
1260 | 127 | int rc; | ||
1261 | 128 | sigset_t set, old_set; | ||
1262 | 129 | |||
1263 | 130 | if (sigfillset(&set)) | ||
1264 | 131 | return -1; | ||
1265 | 132 | |||
1266 | 133 | /* | ||
1267 | 134 | Temporarily block all signals. New thread will inherit signal | ||
1268 | 135 | mask of the current thread. | ||
1269 | 136 | */ | ||
1270 | 137 | if (pthread_sigmask(SIG_BLOCK, &set, &old_set)) | ||
1271 | 138 | return -1; | ||
1272 | 139 | |||
1273 | 140 | /* Create a helper thread. */ | ||
1274 | 141 | rc= start_helper_thread(); | ||
1275 | 142 | |||
1276 | 143 | /* Restore the signal mask. */ | ||
1277 | 144 | pthread_sigmask(SIG_SETMASK, &old_set, NULL); | ||
1278 | 145 | |||
1279 | 146 | return rc; | ||
1280 | 147 | } | ||
1281 | 148 | |||
1282 | 149 | |||
1283 | 150 | /** | ||
1284 | 151 | Release any resources that were allocated as part of initialization. | ||
1285 | 152 | */ | ||
1286 | 153 | |||
1287 | 154 | void | ||
1288 | 155 | my_os_timer_deinit(void) | ||
1289 | 156 | { | ||
1290 | 157 | /* Kill helper thread. */ | ||
1291 | 158 | pthread_kill(thread, MY_TIMER_KILL_SIGNO); | ||
1292 | 159 | |||
1293 | 160 | /* Wait for helper thread termination. */ | ||
1294 | 161 | pthread_join(thread, NULL); | ||
1295 | 162 | } | ||
1296 | 163 | |||
1297 | 164 | |||
1298 | 165 | /** | ||
1299 | 166 | Create a timer object. | ||
1300 | 167 | |||
1301 | 168 | @param timer Location where the timer ID is returned. | ||
1302 | 169 | |||
1303 | 170 | @return On success, 0. | ||
1304 | 171 | On error, -1 is returned, and errno is set to indicate the error. | ||
1305 | 172 | */ | ||
1306 | 173 | |||
1307 | 174 | int | ||
1308 | 175 | my_os_timer_create(my_timer_t *timer) | ||
1309 | 176 | { | ||
1310 | 177 | struct sigevent sigev; | ||
1311 | 178 | |||
1312 | 179 | memset(&sigev, 0, sizeof(sigev)); | ||
1313 | 180 | |||
1314 | 181 | sigev.sigev_value.sival_ptr= timer; | ||
1315 | 182 | sigev.sigev_signo= MY_TIMER_EVENT_SIGNO; | ||
1316 | 183 | sigev.sigev_notify= SIGEV_SIGNAL | SIGEV_THREAD_ID; | ||
1317 | 184 | sigev.sigev_notify_thread_id= thread_id; | ||
1318 | 185 | |||
1319 | 186 | return timer_create(CLOCK_MONOTONIC, &sigev, &timer->id); | ||
1320 | 187 | } | ||
1321 | 188 | |||
1322 | 189 | |||
1323 | 190 | /** | ||
1324 | 191 | Set the time until the next expiration of the timer. | ||
1325 | 192 | |||
1326 | 193 | @param timer Timer object. | ||
1327 | 194 | @param time Amount of time (in milliseconds) before the timer expires. | ||
1328 | 195 | |||
1329 | 196 | @return On success, 0. | ||
1330 | 197 | On error, -1 is returned, and errno is set to indicate the error. | ||
1331 | 198 | */ | ||
1332 | 199 | |||
1333 | 200 | int | ||
1334 | 201 | my_os_timer_set(my_timer_t *timer, unsigned long time) | ||
1335 | 202 | { | ||
1336 | 203 | const struct itimerspec spec= { | ||
1337 | 204 | .it_interval= {.tv_sec= 0, .tv_nsec= 0}, | ||
1338 | 205 | .it_value= {.tv_sec= time / 1000, | ||
1339 | 206 | .tv_nsec= (time % 1000) * 1000000} | ||
1340 | 207 | }; | ||
1341 | 208 | |||
1342 | 209 | return timer_settime(timer->id, 0, &spec, NULL); | ||
1343 | 210 | } | ||
1344 | 211 | |||
1345 | 212 | |||
1346 | 213 | /** | ||
1347 | 214 | Reset the time until the next expiration of the timer. | ||
1348 | 215 | |||
1349 | 216 | @param timer Timer object. | ||
1350 | 217 | @param state The state of the timer at the time of cancellation, either | ||
1351 | 218 | signaled (false) or nonsignaled (true). | ||
1352 | 219 | |||
1353 | 220 | @return On success, 0. | ||
1354 | 221 | On error, -1 is returned, and errno is set to indicate the error. | ||
1355 | 222 | */ | ||
1356 | 223 | |||
1357 | 224 | int | ||
1358 | 225 | my_os_timer_reset(my_timer_t *timer, int *state) | ||
1359 | 226 | { | ||
1360 | 227 | int status; | ||
1361 | 228 | struct itimerspec old_spec; | ||
1362 | 229 | |||
1363 | 230 | /* A zeroed initial expiration value disarms the timer. */ | ||
1364 | 231 | const struct timespec zero_time= { .tv_sec= 0, .tv_nsec= 0 }; | ||
1365 | 232 | const struct itimerspec zero_spec= { .it_value= zero_time }; | ||
1366 | 233 | |||
1367 | 234 | /* | ||
1368 | 235 | timer_settime returns the amount of time before the timer | ||
1369 | 236 | would have expired or zero if the timer was disarmed. | ||
1370 | 237 | */ | ||
1371 | 238 | if (! (status= timer_settime(timer->id, 0, &zero_spec, &old_spec))) | ||
1372 | 239 | *state= (old_spec.it_value.tv_sec || old_spec.it_value.tv_nsec); | ||
1373 | 240 | |||
1374 | 241 | return status; | ||
1375 | 242 | } | ||
1376 | 243 | |||
1377 | 244 | |||
1378 | 245 | /** | ||
1379 | 246 | Delete a timer object. | ||
1380 | 247 | |||
1381 | 248 | @param timer Timer object. | ||
1382 | 249 | */ | ||
1383 | 250 | |||
1384 | 251 | void | ||
1385 | 252 | my_os_timer_delete(my_timer_t *timer) | ||
1386 | 253 | { | ||
1387 | 254 | timer_delete(timer->id); | ||
1388 | 255 | } | ||
1389 | 256 | |||
1390 | 0 | 257 | ||
1391 | === modified file 'Percona-Server/sql/CMakeLists.txt' | |||
1392 | --- Percona-Server/sql/CMakeLists.txt 2013-06-25 13:13:06 +0000 | |||
1393 | +++ Percona-Server/sql/CMakeLists.txt 2013-09-09 15:30:42 +0000 | |||
1394 | @@ -206,6 +206,10 @@ | |||
1395 | 206 | ) | 206 | ) |
1396 | 207 | ENDIF() | 207 | ENDIF() |
1397 | 208 | 208 | ||
1398 | 209 | IF(HAVE_MY_TIMER) | ||
1399 | 210 | SET(SQL_SOURCE ${SQL_SOURCE} sql_timer.cc) | ||
1400 | 211 | ENDIF() | ||
1401 | 212 | |||
1402 | 209 | MYSQL_ADD_PLUGIN(partition ha_partition.cc STORAGE_ENGINE DEFAULT STATIC_ONLY | 213 | MYSQL_ADD_PLUGIN(partition ha_partition.cc STORAGE_ENGINE DEFAULT STATIC_ONLY |
1403 | 210 | RECOMPILE_FOR_EMBEDDED) | 214 | RECOMPILE_FOR_EMBEDDED) |
1404 | 211 | 215 | ||
1405 | 212 | 216 | ||
1406 | === modified file 'Percona-Server/sql/handler.cc' | |||
1407 | --- Percona-Server/sql/handler.cc 2013-08-22 13:38:28 +0000 | |||
1408 | +++ Percona-Server/sql/handler.cc 2013-09-09 15:30:42 +0000 | |||
1409 | @@ -887,6 +887,24 @@ | |||
1410 | 887 | plugin_foreach(thd, closecon_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0); | 887 | plugin_foreach(thd, closecon_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0); |
1411 | 888 | } | 888 | } |
1412 | 889 | 889 | ||
1413 | 890 | static my_bool kill_handlerton(THD *thd, plugin_ref plugin, void *) | ||
1414 | 891 | { | ||
1415 | 892 | handlerton *hton= plugin_data(plugin, handlerton *); | ||
1416 | 893 | |||
1417 | 894 | if (hton->state == SHOW_OPTION_YES && hton->kill_connection) | ||
1418 | 895 | { | ||
1419 | 896 | if (thd_get_ha_data(thd, hton)) | ||
1420 | 897 | hton->kill_connection(hton, thd); | ||
1421 | 898 | } | ||
1422 | 899 | |||
1423 | 900 | return FALSE; | ||
1424 | 901 | } | ||
1425 | 902 | |||
1426 | 903 | void ha_kill_connection(THD *thd) | ||
1427 | 904 | { | ||
1428 | 905 | plugin_foreach(thd, kill_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0); | ||
1429 | 906 | } | ||
1430 | 907 | |||
1431 | 890 | /* ======================================================================== | 908 | /* ======================================================================== |
1432 | 891 | ======================= TRANSACTIONS ===================================*/ | 909 | ======================= TRANSACTIONS ===================================*/ |
1433 | 892 | 910 | ||
1434 | 893 | 911 | ||
1435 | === modified file 'Percona-Server/sql/handler.h' | |||
1436 | --- Percona-Server/sql/handler.h 2013-08-22 13:38:28 +0000 | |||
1437 | +++ Percona-Server/sql/handler.h 2013-09-09 15:30:42 +0000 | |||
1438 | @@ -908,6 +908,9 @@ | |||
1439 | 908 | const char *db, const char *table_name); | 908 | const char *db, const char *table_name); |
1440 | 909 | int (*release_temporary_latches)(handlerton *hton, THD *thd); | 909 | int (*release_temporary_latches)(handlerton *hton, THD *thd); |
1441 | 910 | 910 | ||
1442 | 911 | /* Terminate connection/statement notification. */ | ||
1443 | 912 | void (*kill_connection)(handlerton *hton, THD *thd); | ||
1444 | 913 | |||
1445 | 911 | /* | 914 | /* |
1446 | 912 | Get log status. | 915 | Get log status. |
1447 | 913 | If log_status is null then the handler do not support transaction | 916 | If log_status is null then the handler do not support transaction |
1448 | @@ -3399,6 +3402,7 @@ | |||
1449 | 3399 | TYPELIB* ha_known_exts(); | 3402 | TYPELIB* ha_known_exts(); |
1450 | 3400 | int ha_panic(enum ha_panic_function flag); | 3403 | int ha_panic(enum ha_panic_function flag); |
1451 | 3401 | void ha_close_connection(THD* thd); | 3404 | void ha_close_connection(THD* thd); |
1452 | 3405 | void ha_kill_connection(THD *thd); | ||
1453 | 3402 | bool ha_flush_logs(handlerton *db_type); | 3406 | bool ha_flush_logs(handlerton *db_type); |
1454 | 3403 | void ha_drop_database(char* path); | 3407 | void ha_drop_database(char* path); |
1455 | 3404 | int ha_create_table(THD *thd, const char *path, | 3408 | int ha_create_table(THD *thd, const char *path, |
1456 | 3405 | 3409 | ||
1457 | === modified file 'Percona-Server/sql/mysqld.cc' | |||
1458 | --- Percona-Server/sql/mysqld.cc 2013-09-09 07:01:33 +0000 | |||
1459 | +++ Percona-Server/sql/mysqld.cc 2013-09-09 15:30:42 +0000 | |||
1460 | @@ -108,6 +108,8 @@ | |||
1461 | 108 | #include "sp_cache.h" | 108 | #include "sp_cache.h" |
1462 | 109 | #include "sql_reload.h" // reload_acl_and_cache | 109 | #include "sql_reload.h" // reload_acl_and_cache |
1463 | 110 | 110 | ||
1464 | 111 | #include "my_timer.h" // my_os_timer_init_ext, my_os_timer_deinit | ||
1465 | 112 | |||
1466 | 111 | #ifdef HAVE_POLL_H | 113 | #ifdef HAVE_POLL_H |
1467 | 112 | #include <poll.h> | 114 | #include <poll.h> |
1468 | 113 | #endif | 115 | #endif |
1469 | @@ -720,6 +722,8 @@ | |||
1470 | 720 | extern TYPELIB utility_user_privileges_typelib; | 722 | extern TYPELIB utility_user_privileges_typelib; |
1471 | 721 | ulonglong utility_user_privileges= 0; | 723 | ulonglong utility_user_privileges= 0; |
1472 | 722 | 724 | ||
1473 | 725 | SHOW_COMP_OPTION have_statement_timeout= SHOW_OPTION_DISABLED; | ||
1474 | 726 | |||
1475 | 723 | /* Thread specific variables */ | 727 | /* Thread specific variables */ |
1476 | 724 | 728 | ||
1477 | 725 | pthread_key(MEM_ROOT**,THR_MALLOC); | 729 | pthread_key(MEM_ROOT**,THR_MALLOC); |
1478 | @@ -1789,6 +1793,12 @@ | |||
1479 | 1789 | 1793 | ||
1480 | 1790 | memcached_shutdown(); | 1794 | memcached_shutdown(); |
1481 | 1791 | 1795 | ||
1482 | 1796 | #ifdef HAVE_MY_TIMER | ||
1483 | 1797 | if (have_statement_timeout == SHOW_OPTION_YES) | ||
1484 | 1798 | my_os_timer_deinit(); | ||
1485 | 1799 | #endif | ||
1486 | 1800 | |||
1487 | 1801 | have_statement_timeout= SHOW_OPTION_DISABLED; | ||
1488 | 1792 | /* | 1802 | /* |
1489 | 1793 | make sure that handlers finish up | 1803 | make sure that handlers finish up |
1490 | 1794 | what they have that is dependent on the binlog | 1804 | what they have that is dependent on the binlog |
1491 | @@ -4584,6 +4594,15 @@ | |||
1492 | 4584 | if (table_def_init() | hostname_cache_init()) | 4594 | if (table_def_init() | hostname_cache_init()) |
1493 | 4585 | unireg_abort(1); | 4595 | unireg_abort(1); |
1494 | 4586 | 4596 | ||
1495 | 4597 | #ifdef HAVE_MY_TIMER | ||
1496 | 4598 | if (my_os_timer_init_ext()) | ||
1497 | 4599 | sql_print_error("Failed to initialize timer component (errno %d).", errno); | ||
1498 | 4600 | else | ||
1499 | 4601 | have_statement_timeout= SHOW_OPTION_YES; | ||
1500 | 4602 | #else | ||
1501 | 4603 | have_statement_timeout= SHOW_OPTION_NO; | ||
1502 | 4604 | #endif | ||
1503 | 4605 | |||
1504 | 4587 | query_cache_set_min_res_unit(query_cache_min_res_unit); | 4606 | query_cache_set_min_res_unit(query_cache_min_res_unit); |
1505 | 4588 | query_cache_init(); | 4607 | query_cache_init(); |
1506 | 4589 | query_cache_resize(query_cache_size); | 4608 | query_cache_resize(query_cache_size); |
1507 | @@ -7991,6 +8010,9 @@ | |||
1508 | 7991 | {"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS}, | 8010 | {"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS}, |
1509 | 7992 | {"Last_query_partial_plans", (char*) offsetof(STATUS_VAR, last_query_partial_plans), SHOW_LONGLONG_STATUS}, | 8011 | {"Last_query_partial_plans", (char*) offsetof(STATUS_VAR, last_query_partial_plans), SHOW_LONGLONG_STATUS}, |
1510 | 7993 | {"Max_used_connections", (char*) &max_used_connections, SHOW_LONG}, | 8012 | {"Max_used_connections", (char*) &max_used_connections, SHOW_LONG}, |
1511 | 8013 | {"Max_statement_time_exceeded", (char*) offsetof(STATUS_VAR, max_statement_time_exceeded), SHOW_LONG_STATUS}, | ||
1512 | 8014 | {"Max_statement_time_set", (char*) offsetof(STATUS_VAR, max_statement_time_set), SHOW_LONG_STATUS}, | ||
1513 | 8015 | {"Max_statement_time_set_failed", (char*) offsetof(STATUS_VAR, max_statement_time_set_failed), SHOW_LONG_STATUS}, | ||
1514 | 7994 | {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_NOFLUSH}, | 8016 | {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_NOFLUSH}, |
1515 | 7995 | {"Open_files", (char*) &my_file_opened, SHOW_LONG_NOFLUSH}, | 8017 | {"Open_files", (char*) &my_file_opened, SHOW_LONG_NOFLUSH}, |
1516 | 7996 | {"Open_streams", (char*) &my_stream_opened, SHOW_LONG_NOFLUSH}, | 8018 | {"Open_streams", (char*) &my_stream_opened, SHOW_LONG_NOFLUSH}, |
1517 | 7997 | 8019 | ||
1518 | === modified file 'Percona-Server/sql/set_var.h' | |||
1519 | --- Percona-Server/sql/set_var.h 2013-08-14 03:57:21 +0000 | |||
1520 | +++ Percona-Server/sql/set_var.h 2013-09-09 15:30:42 +0000 | |||
1521 | @@ -340,6 +340,7 @@ | |||
1522 | 340 | extern SHOW_COMP_OPTION have_geometry, have_rtree_keys; | 340 | extern SHOW_COMP_OPTION have_geometry, have_rtree_keys; |
1523 | 341 | extern SHOW_COMP_OPTION have_crypt; | 341 | extern SHOW_COMP_OPTION have_crypt; |
1524 | 342 | extern SHOW_COMP_OPTION have_compress; | 342 | extern SHOW_COMP_OPTION have_compress; |
1525 | 343 | extern SHOW_COMP_OPTION have_statement_timeout; | ||
1526 | 343 | 344 | ||
1527 | 344 | /* | 345 | /* |
1528 | 345 | Prototypes for helper functions | 346 | Prototypes for helper functions |
1529 | 346 | 347 | ||
1530 | === modified file 'Percona-Server/sql/share/errmsg-utf8.txt' | |||
1531 | --- Percona-Server/sql/share/errmsg-utf8.txt 2013-08-06 15:16:34 +0000 | |||
1532 | +++ Percona-Server/sql/share/errmsg-utf8.txt 2013-09-09 15:30:42 +0000 | |||
1533 | @@ -7082,6 +7082,9 @@ | |||
1534 | 7082 | ER_STOP_SLAVE_IO_THREAD_TIMEOUT | 7082 | ER_STOP_SLAVE_IO_THREAD_TIMEOUT |
1535 | 7083 | eng "STOP SLAVE command execution is incomplete: Slave IO thread got the stop signal, thread is busy, IO thread will stop once the current task is complete." | 7083 | eng "STOP SLAVE command execution is incomplete: Slave IO thread got the stop signal, thread is busy, IO thread will stop once the current task is complete." |
1536 | 7084 | 7084 | ||
1537 | 7085 | ER_QUERY_TIMEOUT 70101 | ||
1538 | 7086 | eng "Query execution was interrupted, max_statement_time exceeded" | ||
1539 | 7087 | |||
1540 | 7085 | # | 7088 | # |
1541 | 7086 | # End of 5.6 error messages. | 7089 | # End of 5.6 error messages. |
1542 | 7087 | # | 7090 | # |
1543 | 7088 | 7091 | ||
1544 | === modified file 'Percona-Server/sql/signal_handler.cc' | |||
1545 | --- Percona-Server/sql/signal_handler.cc 2013-08-14 03:57:21 +0000 | |||
1546 | +++ Percona-Server/sql/signal_handler.cc 2013-09-09 15:30:42 +0000 | |||
1547 | @@ -181,6 +181,9 @@ | |||
1548 | 181 | case THD::KILL_QUERY: | 181 | case THD::KILL_QUERY: |
1549 | 182 | kreason= "KILL_QUERY"; | 182 | kreason= "KILL_QUERY"; |
1550 | 183 | break; | 183 | break; |
1551 | 184 | case THD::KILL_TIMEOUT: | ||
1552 | 185 | kreason= "KILL_TIMEOUT"; | ||
1553 | 186 | break; | ||
1554 | 184 | case THD::KILLED_NO_VALUE: | 187 | case THD::KILLED_NO_VALUE: |
1555 | 185 | kreason= "KILLED_NO_VALUE"; | 188 | kreason= "KILLED_NO_VALUE"; |
1556 | 186 | break; | 189 | break; |
1557 | 187 | 190 | ||
1558 | === modified file 'Percona-Server/sql/sql_class.cc' | |||
1559 | --- Percona-Server/sql/sql_class.cc 2013-08-14 03:57:21 +0000 | |||
1560 | +++ Percona-Server/sql/sql_class.cc 2013-09-09 15:30:42 +0000 | |||
1561 | @@ -66,6 +66,8 @@ | |||
1562 | 66 | using std::min; | 66 | using std::min; |
1563 | 67 | using std::max; | 67 | using std::max; |
1564 | 68 | 68 | ||
1565 | 69 | #include "sql_timer.h" // thd_timer_end | ||
1566 | 70 | |||
1567 | 69 | /* | 71 | /* |
1568 | 70 | The following is used to initialise Table_ident with a internal | 72 | The following is used to initialise Table_ident with a internal |
1569 | 71 | table name | 73 | table name |
1570 | @@ -764,8 +766,11 @@ | |||
1571 | 764 | 766 | ||
1572 | 765 | @note LOCK_thread_count mutex is not necessary when the function is invoked on | 767 | @note LOCK_thread_count mutex is not necessary when the function is invoked on |
1573 | 766 | the currently running thread (current_thd) or if the caller in some other | 768 | the currently running thread (current_thd) or if the caller in some other |
1576 | 767 | way guarantees that access to thd->query is serialized. | 769 | way guarantees that the thread won't be going away. |
1577 | 768 | 770 | ||
1578 | 771 | @note The query string is only printed if the session (thd) to be | ||
1579 | 772 | described belongs to the calling thread. | ||
1580 | 773 | |||
1581 | 769 | @return Pointer to string | 774 | @return Pointer to string |
1582 | 770 | */ | 775 | */ |
1583 | 771 | 776 | ||
1584 | @@ -778,13 +783,11 @@ | |||
1585 | 778 | char header[256]; | 783 | char header[256]; |
1586 | 779 | int len; | 784 | int len; |
1587 | 780 | /* | 785 | /* |
1595 | 781 | The pointers thd->query and thd->proc_info might change since they are | 786 | The thd->proc_info pointer might change since it is being modified |
1596 | 782 | being modified concurrently. This is acceptable for proc_info since its | 787 | concurrently. This is acceptable for proc_info since its value |
1597 | 783 | values doesn't have to very accurate and the memory it points to is static, | 788 | doesn't have to be accurate and the memory it points to is static, |
1598 | 784 | but we need to attempt a snapshot on the pointer values to avoid using NULL | 789 | but we need to attempt a snapshot on the pointer values to avoid |
1599 | 785 | values. The pointer to thd->query however, doesn't point to static memory | 790 | using NULL values. |
1593 | 786 | and has to be protected by LOCK_thread_count or risk pointing to | ||
1594 | 787 | uninitialized memory. | ||
1600 | 788 | */ | 791 | */ |
1601 | 789 | const char *proc_info= thd->proc_info; | 792 | const char *proc_info= thd->proc_info; |
1602 | 790 | 793 | ||
1603 | @@ -818,9 +821,7 @@ | |||
1604 | 818 | str.append(proc_info); | 821 | str.append(proc_info); |
1605 | 819 | } | 822 | } |
1606 | 820 | 823 | ||
1610 | 821 | mysql_mutex_lock(&thd->LOCK_thd_data); | 824 | if (thd == current_thd && thd->query()) |
1608 | 822 | |||
1609 | 823 | if (thd->query()) | ||
1611 | 824 | { | 825 | { |
1612 | 825 | if (max_query_len < 1) | 826 | if (max_query_len < 1) |
1613 | 826 | len= thd->query_length(); | 827 | len= thd->query_length(); |
1614 | @@ -830,8 +831,6 @@ | |||
1615 | 830 | str.append(thd->query(), len); | 831 | str.append(thd->query(), len); |
1616 | 831 | } | 832 | } |
1617 | 832 | 833 | ||
1618 | 833 | mysql_mutex_unlock(&thd->LOCK_thd_data); | ||
1619 | 834 | |||
1620 | 835 | if (str.c_ptr_safe() == buffer) | 834 | if (str.c_ptr_safe() == buffer) |
1621 | 836 | return buffer; | 835 | return buffer; |
1622 | 837 | 836 | ||
1623 | @@ -1129,6 +1128,8 @@ | |||
1624 | 1129 | #ifndef DBUG_OFF | 1128 | #ifndef DBUG_OFF |
1625 | 1130 | gis_debug= 0; | 1129 | gis_debug= 0; |
1626 | 1131 | #endif | 1130 | #endif |
1627 | 1131 | |||
1628 | 1132 | timer= timer_cache= NULL; | ||
1629 | 1132 | } | 1133 | } |
1630 | 1133 | 1134 | ||
1631 | 1134 | 1135 | ||
1632 | @@ -1766,6 +1767,11 @@ | |||
1633 | 1766 | mysql_mutex_lock(&LOCK_thd_data); | 1767 | mysql_mutex_lock(&LOCK_thd_data); |
1634 | 1767 | mysql_mutex_unlock(&LOCK_thd_data); | 1768 | mysql_mutex_unlock(&LOCK_thd_data); |
1635 | 1768 | 1769 | ||
1636 | 1770 | DBUG_ASSERT(timer == NULL); | ||
1637 | 1771 | |||
1638 | 1772 | if (timer_cache) | ||
1639 | 1773 | thd_timer_end(timer_cache); | ||
1640 | 1774 | |||
1641 | 1769 | DBUG_PRINT("info", ("freeing security context")); | 1775 | DBUG_PRINT("info", ("freeing security context")); |
1642 | 1770 | main_security_ctx.destroy(); | 1776 | main_security_ctx.destroy(); |
1643 | 1771 | my_free(db); | 1777 | my_free(db); |
1644 | @@ -1890,7 +1896,8 @@ | |||
1645 | 1890 | /* Set the 'killed' flag of 'this', which is the target THD object. */ | 1896 | /* Set the 'killed' flag of 'this', which is the target THD object. */ |
1646 | 1891 | killed= state_to_set; | 1897 | killed= state_to_set; |
1647 | 1892 | 1898 | ||
1649 | 1893 | if (state_to_set != THD::KILL_QUERY) | 1899 | if (state_to_set != THD::KILL_QUERY && |
1650 | 1900 | state_to_set != THD::KILL_TIMEOUT) | ||
1651 | 1894 | { | 1901 | { |
1652 | 1895 | #ifdef SIGNAL_WITH_VIO_SHUTDOWN | 1902 | #ifdef SIGNAL_WITH_VIO_SHUTDOWN |
1653 | 1896 | if (this != current_thd) | 1903 | if (this != current_thd) |
1654 | @@ -1933,6 +1940,13 @@ | |||
1655 | 1933 | MYSQL_CALLBACK(scheduler, post_kill_notification, (this)); | 1940 | MYSQL_CALLBACK(scheduler, post_kill_notification, (this)); |
1656 | 1934 | } | 1941 | } |
1657 | 1935 | 1942 | ||
1658 | 1943 | /* Interrupt target waiting inside a storage engine. */ | ||
1659 | 1944 | if (state_to_set != THD::NOT_KILLED) | ||
1660 | 1945 | ha_kill_connection(this); | ||
1661 | 1946 | |||
1662 | 1947 | if (state_to_set == THD::KILL_TIMEOUT) | ||
1663 | 1948 | status_var_increment(status_var.max_statement_time_exceeded); | ||
1664 | 1949 | |||
1665 | 1936 | /* Broadcast a condition to kick the target if it is waiting on it. */ | 1950 | /* Broadcast a condition to kick the target if it is waiting on it. */ |
1666 | 1937 | if (mysys_var) | 1951 | if (mysys_var) |
1667 | 1938 | { | 1952 | { |
1668 | @@ -4251,6 +4265,16 @@ | |||
1669 | 4251 | } | 4265 | } |
1670 | 4252 | 4266 | ||
1671 | 4253 | /** | 4267 | /** |
1672 | 4268 | Set the killed status of the current statement. | ||
1673 | 4269 | |||
1674 | 4270 | @param thd user thread connection handle | ||
1675 | 4271 | */ | ||
1676 | 4272 | extern "C" void thd_set_kill_status(const MYSQL_THD thd) | ||
1677 | 4273 | { | ||
1678 | 4274 | thd->send_kill_message(); | ||
1679 | 4275 | } | ||
1680 | 4276 | |||
1681 | 4277 | /** | ||
1682 | 4254 | Return the thread id of a user thread | 4278 | Return the thread id of a user thread |
1683 | 4255 | @param thd user thread | 4279 | @param thd user thread |
1684 | 4256 | @return thread id | 4280 | @return thread id |
1685 | 4257 | 4281 | ||
1686 | === modified file 'Percona-Server/sql/sql_class.h' | |||
1687 | --- Percona-Server/sql/sql_class.h 2013-08-14 03:57:21 +0000 | |||
1688 | +++ Percona-Server/sql/sql_class.h 2013-09-09 15:30:42 +0000 | |||
1689 | @@ -86,6 +86,8 @@ | |||
1690 | 86 | class User_level_lock; | 86 | class User_level_lock; |
1691 | 87 | class user_var_entry; | 87 | class user_var_entry; |
1692 | 88 | 88 | ||
1693 | 89 | struct st_thd_timer; | ||
1694 | 90 | |||
1695 | 89 | enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME }; | 91 | enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME }; |
1696 | 90 | 92 | ||
1697 | 91 | enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON, | 93 | enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON, |
1698 | @@ -600,6 +602,8 @@ | |||
1699 | 600 | 602 | ||
1700 | 601 | my_bool pseudo_slave_mode; | 603 | my_bool pseudo_slave_mode; |
1701 | 602 | 604 | ||
1702 | 605 | ulong max_statement_time; | ||
1703 | 606 | |||
1704 | 603 | Gtid_specification gtid_next; | 607 | Gtid_specification gtid_next; |
1705 | 604 | Gtid_set_or_null gtid_next_list; | 608 | Gtid_set_or_null gtid_next_list; |
1706 | 605 | 609 | ||
1707 | @@ -682,6 +686,11 @@ | |||
1708 | 682 | */ | 686 | */ |
1709 | 683 | double last_query_cost; | 687 | double last_query_cost; |
1710 | 684 | ulonglong last_query_partial_plans; | 688 | ulonglong last_query_partial_plans; |
1711 | 689 | |||
1712 | 690 | ulong max_statement_time_exceeded; | ||
1713 | 691 | ulong max_statement_time_set; | ||
1714 | 692 | ulong max_statement_time_set_failed; | ||
1715 | 693 | |||
1716 | 685 | } STATUS_VAR; | 694 | } STATUS_VAR; |
1717 | 686 | 695 | ||
1718 | 687 | /* | 696 | /* |
1719 | @@ -2387,6 +2396,9 @@ | |||
1720 | 2387 | return m_binlog_filter_state; | 2396 | return m_binlog_filter_state; |
1721 | 2388 | } | 2397 | } |
1722 | 2389 | 2398 | ||
1723 | 2399 | /** Timer object. */ | ||
1724 | 2400 | struct st_thd_timer *timer, *timer_cache; | ||
1725 | 2401 | |||
1726 | 2390 | private: | 2402 | private: |
1727 | 2391 | /** | 2403 | /** |
1728 | 2392 | Indicate if the current statement should be discarded | 2404 | Indicate if the current statement should be discarded |
1729 | @@ -3029,6 +3041,7 @@ | |||
1730 | 3029 | KILL_BAD_DATA=1, | 3041 | KILL_BAD_DATA=1, |
1731 | 3030 | KILL_CONNECTION=ER_SERVER_SHUTDOWN, | 3042 | KILL_CONNECTION=ER_SERVER_SHUTDOWN, |
1732 | 3031 | KILL_QUERY=ER_QUERY_INTERRUPTED, | 3043 | KILL_QUERY=ER_QUERY_INTERRUPTED, |
1733 | 3044 | KILL_TIMEOUT=ER_QUERY_TIMEOUT, | ||
1734 | 3032 | KILLED_NO_VALUE /* means neither of the states */ | 3045 | KILLED_NO_VALUE /* means neither of the states */ |
1735 | 3033 | }; | 3046 | }; |
1736 | 3034 | killed_state volatile killed; | 3047 | killed_state volatile killed; |
1737 | 3035 | 3048 | ||
1738 | === modified file 'Percona-Server/sql/sql_parse.cc' | |||
1739 | --- Percona-Server/sql/sql_parse.cc 2013-09-09 07:01:33 +0000 | |||
1740 | +++ Percona-Server/sql/sql_parse.cc 2013-09-09 15:30:42 +0000 | |||
1741 | @@ -105,6 +105,8 @@ | |||
1742 | 105 | using std::max; | 105 | using std::max; |
1743 | 106 | using std::min; | 106 | using std::min; |
1744 | 107 | 107 | ||
1745 | 108 | #include "sql_timer.h" // thd_timer_set, thd_timer_reset | ||
1746 | 109 | |||
1747 | 108 | #define FLAGSTR(V,F) ((V)&(F)?#F" ":"") | 110 | #define FLAGSTR(V,F) ((V)&(F)?#F" ":"") |
1748 | 109 | 111 | ||
1749 | 110 | /** | 112 | /** |
1750 | @@ -1123,6 +1125,85 @@ | |||
1751 | 1123 | DBUG_RETURN(FALSE); | 1125 | DBUG_RETURN(FALSE); |
1752 | 1124 | } | 1126 | } |
1753 | 1125 | 1127 | ||
1754 | 1128 | |||
1755 | 1129 | /** | ||
1756 | 1130 | Get the maximum execution time for a statement. | ||
1757 | 1131 | |||
1758 | 1132 | @return Length of time in milliseconds. | ||
1759 | 1133 | |||
1760 | 1134 | @remark A zero timeout means that no timeout should be | ||
1761 | 1135 | applied to this particular statement. | ||
1762 | 1136 | */ | ||
1763 | 1137 | |||
1764 | 1138 | static ulong inline get_max_statement_time(THD *thd) | ||
1765 | 1139 | { | ||
1766 | 1140 | |||
1767 | 1141 | /* Assume query execution timeout feature is not used in the most cases */ | ||
1768 | 1142 | if (likely(!thd->variables.max_statement_time)) | ||
1769 | 1143 | return 0; | ||
1770 | 1144 | |||
1771 | 1145 | /* Check if timer support is implemented and was initialized. */ | ||
1772 | 1146 | if (unlikely(have_statement_timeout != SHOW_OPTION_YES)) | ||
1773 | 1147 | return 0; | ||
1774 | 1148 | |||
1775 | 1149 | /* The maximum execution time only applies to top-level statements. */ | ||
1776 | 1150 | if (unlikely(thd->sp_runtime_ctx || thd->in_sub_stmt)) | ||
1777 | 1151 | return 0; | ||
1778 | 1152 | |||
1779 | 1153 | /* Also does not apply to statements made by the slave thread. */ | ||
1780 | 1154 | if (unlikely(thd->slave_thread)) | ||
1781 | 1155 | return 0; | ||
1782 | 1156 | |||
1783 | 1157 | return thd->variables.max_statement_time; | ||
1784 | 1158 | } | ||
1785 | 1159 | |||
1786 | 1160 | |||
1787 | 1161 | /** | ||
1788 | 1162 | Set the time until the currently running statement is aborted. | ||
1789 | 1163 | |||
1790 | 1164 | @param thd Thread (session) context. | ||
1791 | 1165 | |||
1792 | 1166 | @return TRUE if the timer was armed. | ||
1793 | 1167 | */ | ||
1794 | 1168 | |||
1795 | 1169 | static inline bool set_statement_timer(THD *thd) | ||
1796 | 1170 | { | ||
1797 | 1171 | ulong max_statement_time= get_max_statement_time(thd); | ||
1798 | 1172 | |||
1799 | 1173 | /* Assume query execution timeout feature is not used in the most cases */ | ||
1800 | 1174 | if (likely(max_statement_time == 0)) | ||
1801 | 1175 | return false; | ||
1802 | 1176 | |||
1803 | 1177 | if (unlikely(thd->timer != NULL)) | ||
1804 | 1178 | return false; | ||
1805 | 1179 | |||
1806 | 1180 | thd->timer= thd_timer_set(thd, thd->timer_cache, max_statement_time); | ||
1807 | 1181 | thd->timer_cache= NULL; | ||
1808 | 1182 | |||
1809 | 1183 | if (thd->timer) | ||
1810 | 1184 | status_var_increment(thd->status_var.max_statement_time_set); | ||
1811 | 1185 | else | ||
1812 | 1186 | status_var_increment(thd->status_var.max_statement_time_set_failed); | ||
1813 | 1187 | |||
1814 | 1188 | return thd->timer; | ||
1815 | 1189 | } | ||
1816 | 1190 | |||
1817 | 1191 | |||
1818 | 1192 | /** | ||
1819 | 1193 | Deactivate the timer associated with the statement that was executed. | ||
1820 | 1194 | |||
1821 | 1195 | @param thd Thread (session) context. | ||
1822 | 1196 | */ | ||
1823 | 1197 | |||
1824 | 1198 | static void reset_statement_timer(THD *thd) | ||
1825 | 1199 | { | ||
1826 | 1200 | DBUG_ASSERT(thd->timer); | ||
1827 | 1201 | /* Cache the timer object if it can be reused. */ | ||
1828 | 1202 | thd->timer_cache= thd_timer_reset(thd->timer); | ||
1829 | 1203 | thd->timer= NULL; | ||
1830 | 1204 | } | ||
1831 | 1205 | |||
1832 | 1206 | |||
1833 | 1126 | /** | 1207 | /** |
1834 | 1127 | Perform one connection-level (COM_XXXX) command. | 1208 | Perform one connection-level (COM_XXXX) command. |
1835 | 1128 | 1209 | ||
1836 | @@ -2613,6 +2694,8 @@ | |||
1837 | 2613 | } /* endif unlikely slave */ | 2694 | } /* endif unlikely slave */ |
1838 | 2614 | #endif | 2695 | #endif |
1839 | 2615 | 2696 | ||
1840 | 2697 | bool reset_timer= set_statement_timer(thd); | ||
1841 | 2698 | |||
1842 | 2616 | status_var_increment(thd->status_var.com_stat[lex->sql_command]); | 2699 | status_var_increment(thd->status_var.com_stat[lex->sql_command]); |
1843 | 2617 | 2700 | ||
1844 | 2618 | Opt_trace_start ots(thd, all_tables, lex->sql_command, &lex->var_list, | 2701 | Opt_trace_start ots(thd, all_tables, lex->sql_command, &lex->var_list, |
1845 | @@ -5201,12 +5284,17 @@ | |||
1846 | 5201 | DBUG_ASSERT(!thd->in_active_multi_stmt_transaction() || | 5284 | DBUG_ASSERT(!thd->in_active_multi_stmt_transaction() || |
1847 | 5202 | thd->in_multi_stmt_transaction_mode()); | 5285 | thd->in_multi_stmt_transaction_mode()); |
1848 | 5203 | 5286 | ||
1849 | 5287 | if (reset_timer) | ||
1850 | 5288 | reset_statement_timer(thd); | ||
1851 | 5289 | |||
1852 | 5204 | if (! thd->in_sub_stmt) | 5290 | if (! thd->in_sub_stmt) |
1853 | 5205 | { | 5291 | { |
1854 | 5206 | /* report error issued during command execution */ | 5292 | /* report error issued during command execution */ |
1855 | 5207 | if (thd->killed_errno()) | 5293 | if (thd->killed_errno()) |
1856 | 5208 | thd->send_kill_message(); | 5294 | thd->send_kill_message(); |
1858 | 5209 | if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA) | 5295 | if (thd->killed == THD::KILL_QUERY || |
1859 | 5296 | thd->killed == THD::KILL_TIMEOUT || | ||
1860 | 5297 | thd->killed == THD::KILL_BAD_DATA) | ||
1861 | 5210 | { | 5298 | { |
1862 | 5211 | thd->killed= THD::NOT_KILLED; | 5299 | thd->killed= THD::NOT_KILLED; |
1863 | 5212 | thd->mysys_var->abort= 0; | 5300 | thd->mysys_var->abort= 0; |
1864 | 5213 | 5301 | ||
1865 | === added file 'Percona-Server/sql/sql_timer.cc' | |||
1866 | --- Percona-Server/sql/sql_timer.cc 1970-01-01 00:00:00 +0000 | |||
1867 | +++ Percona-Server/sql/sql_timer.cc 2013-09-09 15:30:42 +0000 | |||
1868 | @@ -0,0 +1,253 @@ | |||
1869 | 1 | /* Copyright (c) 2012, Twitter, Inc. All rights reserved. | ||
1870 | 2 | |||
1871 | 3 | This program is free software; you can redistribute it and/or modify | ||
1872 | 4 | it under the terms of the GNU General Public License as published by | ||
1873 | 5 | the Free Software Foundation; version 2 of the License. | ||
1874 | 6 | |||
1875 | 7 | This program is distributed in the hope that it will be useful, | ||
1876 | 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1877 | 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1878 | 10 | GNU General Public License for more details. | ||
1879 | 11 | |||
1880 | 12 | You should have received a copy of the GNU General Public License along | ||
1881 | 13 | with this program; if not, write to the Free Software Foundation, Inc., | ||
1882 | 14 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ | ||
1883 | 15 | |||
1884 | 16 | #include "sql_class.h" /* THD */ | ||
1885 | 17 | #include "sql_timer.h" /* thd_timer_set, etc. */ | ||
1886 | 18 | #include "my_timer.h" /* my_timer_t */ | ||
1887 | 19 | |||
1888 | 20 | struct st_thd_timer | ||
1889 | 21 | { | ||
1890 | 22 | THD *thd; | ||
1891 | 23 | my_timer_t timer; | ||
1892 | 24 | pthread_mutex_t mutex; | ||
1893 | 25 | bool destroy; | ||
1894 | 26 | }; | ||
1895 | 27 | |||
1896 | 28 | C_MODE_START | ||
1897 | 29 | static void timer_callback(my_timer_t *); | ||
1898 | 30 | C_MODE_END | ||
1899 | 31 | |||
1900 | 32 | /** | ||
1901 | 33 | Allocate and initialize a thread timer object. | ||
1902 | 34 | |||
1903 | 35 | @return NULL on failure. | ||
1904 | 36 | */ | ||
1905 | 37 | |||
1906 | 38 | static thd_timer_t * | ||
1907 | 39 | thd_timer_create(void) | ||
1908 | 40 | { | ||
1909 | 41 | thd_timer_t *ttp; | ||
1910 | 42 | DBUG_ENTER("thd_timer_create"); | ||
1911 | 43 | |||
1912 | 44 | ttp= (thd_timer_t *) my_malloc(sizeof(*ttp), MYF(MY_WME | MY_ZEROFILL)); | ||
1913 | 45 | |||
1914 | 46 | if (ttp == NULL) | ||
1915 | 47 | DBUG_RETURN(NULL); | ||
1916 | 48 | |||
1917 | 49 | ttp->timer.notify_function= timer_callback; | ||
1918 | 50 | pthread_mutex_init(&ttp->mutex, MY_MUTEX_INIT_FAST); | ||
1919 | 51 | |||
1920 | 52 | if (! my_os_timer_create(&ttp->timer)) | ||
1921 | 53 | DBUG_RETURN(ttp); | ||
1922 | 54 | |||
1923 | 55 | pthread_mutex_destroy(&ttp->mutex); | ||
1924 | 56 | my_free(ttp); | ||
1925 | 57 | |||
1926 | 58 | DBUG_RETURN(NULL); | ||
1927 | 59 | } | ||
1928 | 60 | |||
1929 | 61 | |||
1930 | 62 | /** | ||
1931 | 63 | Release resources allocated for a thread timer. | ||
1932 | 64 | |||
1933 | 65 | @param ttp Thread timer object. | ||
1934 | 66 | */ | ||
1935 | 67 | |||
1936 | 68 | static void | ||
1937 | 69 | thd_timer_destroy(thd_timer_t *ttp) | ||
1938 | 70 | { | ||
1939 | 71 | DBUG_ENTER("thd_timer_destroy"); | ||
1940 | 72 | |||
1941 | 73 | my_os_timer_delete(&ttp->timer); | ||
1942 | 74 | pthread_mutex_destroy(&ttp->mutex); | ||
1943 | 75 | my_free(ttp); | ||
1944 | 76 | |||
1945 | 77 | DBUG_VOID_RETURN; | ||
1946 | 78 | } | ||
1947 | 79 | |||
1948 | 80 | |||
1949 | 81 | /** | ||
1950 | 82 | Notify a thread (session) that its timer has expired. | ||
1951 | 83 | |||
1952 | 84 | @param ttp Thread timer object. | ||
1953 | 85 | |||
1954 | 86 | @return true if the object should be destroyed. | ||
1955 | 87 | */ | ||
1956 | 88 | |||
1957 | 89 | static bool | ||
1958 | 90 | timer_notify(thd_timer_t *ttp) | ||
1959 | 91 | { | ||
1960 | 92 | THD *thd= ttp->thd; | ||
1961 | 93 | |||
1962 | 94 | DBUG_ASSERT(!ttp->destroy || !thd); | ||
1963 | 95 | |||
1964 | 96 | /* | ||
1965 | 97 | Statement might have finished while the timer notification | ||
1966 | 98 | was being delivered. If this is the case, the timer object | ||
1967 | 99 | was detached (orphaned) and has no associated session (thd). | ||
1968 | 100 | */ | ||
1969 | 101 | if (thd) | ||
1970 | 102 | { | ||
1971 | 103 | mysql_mutex_lock(&thd->LOCK_thd_data); | ||
1972 | 104 | thd->awake(THD::KILL_TIMEOUT); | ||
1973 | 105 | mysql_mutex_unlock(&thd->LOCK_thd_data); | ||
1974 | 106 | } | ||
1975 | 107 | |||
1976 | 108 | /* Mark the object as unreachable. */ | ||
1977 | 109 | ttp->thd= NULL; | ||
1978 | 110 | |||
1979 | 111 | return ttp->destroy; | ||
1980 | 112 | } | ||
1981 | 113 | |||
1982 | 114 | |||
1983 | 115 | /** | ||
1984 | 116 | Timer expiration notification callback. | ||
1985 | 117 | |||
1986 | 118 | @param timer Timer (mysys) object. | ||
1987 | 119 | |||
1988 | 120 | @note Invoked in a separate thread of control. | ||
1989 | 121 | */ | ||
1990 | 122 | |||
1991 | 123 | static void | ||
1992 | 124 | timer_callback(my_timer_t *timer) | ||
1993 | 125 | { | ||
1994 | 126 | bool destroy; | ||
1995 | 127 | thd_timer_t *ttp; | ||
1996 | 128 | |||
1997 | 129 | ttp= my_container_of(timer, thd_timer_t, timer); | ||
1998 | 130 | |||
1999 | 131 | pthread_mutex_lock(&ttp->mutex); | ||
2000 | 132 | destroy= timer_notify(ttp); | ||
2001 | 133 | pthread_mutex_unlock(&ttp->mutex); | ||
2002 | 134 | |||
2003 | 135 | if (destroy) | ||
2004 | 136 | thd_timer_destroy(ttp); | ||
2005 | 137 | } | ||
2006 | 138 | |||
2007 | 139 | |||
2008 | 140 | /** | ||
2009 | 141 | Set the time until the currently running statement is aborted. | ||
2010 | 142 | |||
2011 | 143 | @param thd Thread (session) context. | ||
2012 | 144 | @param ttp Thread timer object. | ||
2013 | 145 | @param time Length of time, in milliseconds, until the currently | ||
2014 | 146 | running statement is aborted. | ||
2015 | 147 | |||
2016 | 148 | @return NULL on failure. | ||
2017 | 149 | */ | ||
2018 | 150 | |||
2019 | 151 | thd_timer_t * | ||
2020 | 152 | thd_timer_set(THD *thd, thd_timer_t *ttp, unsigned long time) | ||
2021 | 153 | { | ||
2022 | 154 | DBUG_ENTER("thd_timer_set"); | ||
2023 | 155 | |||
2024 | 156 | /* Create a new thread timer object if one was not provided. */ | ||
2025 | 157 | if (ttp == NULL && (ttp= thd_timer_create()) == NULL) | ||
2026 | 158 | DBUG_RETURN(NULL); | ||
2027 | 159 | |||
2028 | 160 | DBUG_ASSERT(!ttp->destroy && !ttp->thd); | ||
2029 | 161 | |||
2030 | 162 | /* Mark the notification as pending. */ | ||
2031 | 163 | ttp->thd= thd; | ||
2032 | 164 | |||
2033 | 165 | /* Arm the timer. */ | ||
2034 | 166 | if (! my_os_timer_set(&ttp->timer, time)) | ||
2035 | 167 | DBUG_RETURN(ttp); | ||
2036 | 168 | |||
2037 | 169 | /* Dispose of the (cached) timer object. */ | ||
2038 | 170 | thd_timer_destroy(ttp); | ||
2039 | 171 | |||
2040 | 172 | DBUG_RETURN(NULL); | ||
2041 | 173 | } | ||
2042 | 174 | |||
2043 | 175 | |||
2044 | 176 | /** | ||
2045 | 177 | Reap a (possibly) pending timer object. | ||
2046 | 178 | |||
2047 | 179 | @param ttp Thread timer object. | ||
2048 | 180 | |||
2049 | 181 | @return true if the timer object is unreachable. | ||
2050 | 182 | */ | ||
2051 | 183 | |||
2052 | 184 | static bool | ||
2053 | 185 | reap_timer(thd_timer_t *ttp, bool pending) | ||
2054 | 186 | { | ||
2055 | 187 | bool unreachable; | ||
2056 | 188 | |||
2057 | 189 | /* Cannot be tagged for destruction. */ | ||
2058 | 190 | DBUG_ASSERT(!ttp->destroy); | ||
2059 | 191 | |||
2060 | 192 | /* If not pending, timer hasn't fired. */ | ||
2061 | 193 | DBUG_ASSERT(pending || ttp->thd); | ||
2062 | 194 | |||
2063 | 195 | /* | ||
2064 | 196 | The timer object can be reused if the timer was stopped before | ||
2065 | 197 | expiring. Otherwise, the timer notification function might be | ||
2066 | 198 | executing asynchronously in the context of a separate thread. | ||
2067 | 199 | */ | ||
2068 | 200 | unreachable= pending ? ttp->thd == NULL : true; | ||
2069 | 201 | |||
2070 | 202 | ttp->thd= NULL; | ||
2071 | 203 | |||
2072 | 204 | return unreachable; | ||
2073 | 205 | } | ||
2074 | 206 | |||
2075 | 207 | /** | ||
2076 | 208 | Deactivate the given timer. | ||
2077 | 209 | |||
2078 | 210 | @param ttp Thread timer object. | ||
2079 | 211 | |||
2080 | 212 | @return NULL if the timer object was orphaned. | ||
2081 | 213 | Otherwise, the given timer object is returned. | ||
2082 | 214 | */ | ||
2083 | 215 | |||
2084 | 216 | thd_timer_t * | ||
2085 | 217 | thd_timer_reset(thd_timer_t *ttp) | ||
2086 | 218 | { | ||
2087 | 219 | bool unreachable; | ||
2088 | 220 | int status, state; | ||
2089 | 221 | DBUG_ENTER("thd_timer_reset"); | ||
2090 | 222 | |||
2091 | 223 | status= my_os_timer_reset(&ttp->timer, &state); | ||
2092 | 224 | |||
2093 | 225 | /* | ||
2094 | 226 | If the notification function cannot possibly run anymore, cache | ||
2095 | 227 | the timer object as there are no outstanding references to it. | ||
2096 | 228 | */ | ||
2097 | 229 | pthread_mutex_lock(&ttp->mutex); | ||
2098 | 230 | unreachable= reap_timer(ttp, status ? true : !state); | ||
2099 | 231 | ttp->destroy= unreachable ? false : true; | ||
2100 | 232 | pthread_mutex_unlock(&ttp->mutex); | ||
2101 | 233 | |||
2102 | 234 | DBUG_RETURN(unreachable ? ttp : NULL); | ||
2103 | 235 | } | ||
2104 | 236 | |||
2105 | 237 | |||
2106 | 238 | /** | ||
2107 | 239 | Release resources allocated for a given thread timer. | ||
2108 | 240 | |||
2109 | 241 | @param ttp Thread timer object. | ||
2110 | 242 | */ | ||
2111 | 243 | |||
2112 | 244 | void | ||
2113 | 245 | thd_timer_end(thd_timer_t *ttp) | ||
2114 | 246 | { | ||
2115 | 247 | DBUG_ENTER("thd_timer_end"); | ||
2116 | 248 | |||
2117 | 249 | thd_timer_destroy(ttp); | ||
2118 | 250 | |||
2119 | 251 | DBUG_VOID_RETURN; | ||
2120 | 252 | } | ||
2121 | 253 | |||
2122 | 0 | 254 | ||
2123 | === added file 'Percona-Server/sql/sql_timer.h' | |||
2124 | --- Percona-Server/sql/sql_timer.h 1970-01-01 00:00:00 +0000 | |||
2125 | +++ Percona-Server/sql/sql_timer.h 2013-09-09 15:30:42 +0000 | |||
2126 | @@ -0,0 +1,50 @@ | |||
2127 | 1 | /* Copyright (c) 2012, Twitter, Inc. All rights reserved. | ||
2128 | 2 | |||
2129 | 3 | This program is free software; you can redistribute it and/or modify | ||
2130 | 4 | it under the terms of the GNU General Public License as published by | ||
2131 | 5 | the Free Software Foundation; version 2 of the License. | ||
2132 | 6 | |||
2133 | 7 | This program is distributed in the hope that it will be useful, | ||
2134 | 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2135 | 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2136 | 10 | GNU General Public License for more details. | ||
2137 | 11 | |||
2138 | 12 | You should have received a copy of the GNU General Public License along | ||
2139 | 13 | with this program; if not, write to the Free Software Foundation, Inc., | ||
2140 | 14 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ | ||
2141 | 15 | |||
2142 | 16 | #ifndef SQL_TIMER_INCLUDED | ||
2143 | 17 | #define SQL_TIMER_INCLUDED | ||
2144 | 18 | |||
2145 | 19 | class THD; | ||
2146 | 20 | struct st_thd_timer; | ||
2147 | 21 | typedef struct st_thd_timer thd_timer_t; | ||
2148 | 22 | |||
2149 | 23 | #ifdef HAVE_MY_TIMER | ||
2150 | 24 | |||
2151 | 25 | thd_timer_t *thd_timer_set(THD *, thd_timer_t *, unsigned long); | ||
2152 | 26 | thd_timer_t *thd_timer_reset(thd_timer_t *); | ||
2153 | 27 | void thd_timer_end(thd_timer_t *); | ||
2154 | 28 | |||
2155 | 29 | #else | ||
2156 | 30 | |||
2157 | 31 | static inline thd_timer_t * | ||
2158 | 32 | thd_timer_set(THD *, thd_timer_t *, unsigned long) | ||
2159 | 33 | { | ||
2160 | 34 | return NULL; | ||
2161 | 35 | } | ||
2162 | 36 | |||
2163 | 37 | static inline thd_timer_t * | ||
2164 | 38 | thd_timer_reset(thd_timer_t *) | ||
2165 | 39 | { | ||
2166 | 40 | return NULL; | ||
2167 | 41 | } | ||
2168 | 42 | |||
2169 | 43 | static inline void | ||
2170 | 44 | thd_timer_end(thd_timer_t *) | ||
2171 | 45 | { | ||
2172 | 46 | } | ||
2173 | 47 | |||
2174 | 48 | #endif | ||
2175 | 49 | |||
2176 | 50 | #endif /* SQL_TIMER_INCLUDED */ | ||
2177 | 0 | 51 | ||
2178 | === modified file 'Percona-Server/sql/sys_vars.cc' | |||
2179 | --- Percona-Server/sql/sys_vars.cc 2013-09-09 07:01:33 +0000 | |||
2180 | +++ Percona-Server/sql/sys_vars.cc 2013-09-09 15:30:42 +0000 | |||
2181 | @@ -2928,6 +2928,12 @@ | |||
2182 | 2928 | sql_mode_names, DEFAULT(MODE_NO_ENGINE_SUBSTITUTION), NO_MUTEX_GUARD, | 2928 | sql_mode_names, DEFAULT(MODE_NO_ENGINE_SUBSTITUTION), NO_MUTEX_GUARD, |
2183 | 2929 | NOT_IN_BINLOG, ON_CHECK(check_sql_mode), ON_UPDATE(fix_sql_mode)); | 2929 | NOT_IN_BINLOG, ON_CHECK(check_sql_mode), ON_UPDATE(fix_sql_mode)); |
2184 | 2930 | 2930 | ||
2185 | 2931 | static Sys_var_ulong Sys_max_statement_time( | ||
2186 | 2932 | "max_statement_time", | ||
2187 | 2933 | "Kill any statement that takes over the specified number of milliseconds", | ||
2188 | 2934 | SESSION_VAR(max_statement_time), CMD_LINE(REQUIRED_ARG), | ||
2189 | 2935 | VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1)); | ||
2190 | 2936 | |||
2191 | 2931 | #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) | 2937 | #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) |
2192 | 2932 | #define SSL_OPT(X) CMD_LINE(REQUIRED_ARG,X) | 2938 | #define SSL_OPT(X) CMD_LINE(REQUIRED_ARG,X) |
2193 | 2933 | #else | 2939 | #else |
2194 | @@ -3966,6 +3972,10 @@ | |||
2195 | 3966 | "have_symlink", "have_symlink", | 3972 | "have_symlink", "have_symlink", |
2196 | 3967 | READ_ONLY GLOBAL_VAR(have_symlink), NO_CMD_LINE); | 3973 | READ_ONLY GLOBAL_VAR(have_symlink), NO_CMD_LINE); |
2197 | 3968 | 3974 | ||
2198 | 3975 | static Sys_var_have Sys_have_statement_timeout( | ||
2199 | 3976 | "have_statement_timeout", "have_statement_timeout", | ||
2200 | 3977 | READ_ONLY GLOBAL_VAR(have_statement_timeout), NO_CMD_LINE); | ||
2201 | 3978 | |||
2202 | 3969 | static bool fix_log_state(sys_var *self, THD *thd, enum_var_type type); | 3979 | static bool fix_log_state(sys_var *self, THD *thd, enum_var_type type); |
2203 | 3970 | static Sys_var_mybool Sys_general_log( | 3980 | static Sys_var_mybool Sys_general_log( |
2204 | 3971 | "general_log", "Log connections and queries to a table or log file. " | 3981 | "general_log", "Log connections and queries to a table or log file. " |
2205 | 3972 | 3982 | ||
2206 | === modified file 'Percona-Server/storage/innobase/handler/ha_innodb.cc' | |||
2207 | --- Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-08-30 13:23:53 +0000 | |||
2208 | +++ Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-09-09 15:30:42 +0000 | |||
2209 | @@ -42,6 +42,7 @@ | |||
2210 | 42 | #include <my_base.h> // HA_OPTION_* | 42 | #include <my_base.h> // HA_OPTION_* |
2211 | 43 | #include <mysys_err.h> | 43 | #include <mysys_err.h> |
2212 | 44 | #include <mysql/innodb_priv.h> | 44 | #include <mysql/innodb_priv.h> |
2213 | 45 | #include <mysql/thread_pool_priv.h> | ||
2214 | 45 | 46 | ||
2215 | 46 | /** @file ha_innodb.cc */ | 47 | /** @file ha_innodb.cc */ |
2216 | 47 | 48 | ||
2217 | @@ -809,6 +810,15 @@ | |||
2218 | 809 | which to close the connection */ | 810 | which to close the connection */ |
2219 | 810 | 811 | ||
2220 | 811 | /*****************************************************************//** | 812 | /*****************************************************************//** |
2221 | 813 | Cancel any pending lock request associated with the current THD. */ | ||
2222 | 814 | static | ||
2223 | 815 | void | ||
2224 | 816 | innobase_kill_connection( | ||
2225 | 817 | /*======================*/ | ||
2226 | 818 | handlerton* hton, /*!< in: innobase handlerton */ | ||
2227 | 819 | THD* thd); /*!< in: handle to the MySQL thread being killed */ | ||
2228 | 820 | |||
2229 | 821 | /*****************************************************************//** | ||
2230 | 812 | Commits a transaction in an InnoDB database or marks an SQL statement | 822 | Commits a transaction in an InnoDB database or marks an SQL statement |
2231 | 813 | ended. | 823 | ended. |
2232 | 814 | @return 0 */ | 824 | @return 0 */ |
2233 | @@ -1540,8 +1550,8 @@ | |||
2234 | 1540 | return(0); | 1550 | return(0); |
2235 | 1541 | 1551 | ||
2236 | 1542 | case DB_INTERRUPTED: | 1552 | case DB_INTERRUPTED: |
2239 | 1543 | my_error(ER_QUERY_INTERRUPTED, MYF(0)); | 1553 | thd_set_kill_status(thd ? thd : thd_get_current_thd()); |
2240 | 1544 | /* fall through */ | 1554 | return(-1); |
2241 | 1545 | 1555 | ||
2242 | 1546 | case DB_FOREIGN_EXCEED_MAX_CASCADE: | 1556 | case DB_FOREIGN_EXCEED_MAX_CASCADE: |
2243 | 1547 | ut_ad(thd); | 1557 | ut_ad(thd); |
2244 | @@ -3017,6 +3027,8 @@ | |||
2245 | 3017 | = innobase_purge_changed_page_bitmaps; | 3027 | = innobase_purge_changed_page_bitmaps; |
2246 | 3018 | innobase_hton->is_fake_change = innobase_is_fake_change; | 3028 | innobase_hton->is_fake_change = innobase_is_fake_change; |
2247 | 3019 | 3029 | ||
2248 | 3030 | innobase_hton->kill_connection = innobase_kill_connection; | ||
2249 | 3031 | |||
2250 | 3020 | ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); | 3032 | ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); |
2251 | 3021 | 3033 | ||
2252 | 3022 | #ifndef DBUG_OFF | 3034 | #ifndef DBUG_OFF |
2253 | @@ -4199,6 +4211,40 @@ | |||
2254 | 4199 | return(ROW_TYPE_NOT_USED); | 4211 | return(ROW_TYPE_NOT_USED); |
2255 | 4200 | } | 4212 | } |
2256 | 4201 | 4213 | ||
2257 | 4214 | /*****************************************************************//** | ||
2258 | 4215 | Cancel any pending lock request associated with the current THD. */ | ||
2259 | 4216 | static | ||
2260 | 4217 | void | ||
2261 | 4218 | innobase_kill_connection( | ||
2262 | 4219 | /*======================*/ | ||
2263 | 4220 | handlerton* hton, /*!< in: innobase handlerton */ | ||
2264 | 4221 | THD* thd) /*!< in: handle to the MySQL thread being killed */ | ||
2265 | 4222 | { | ||
2266 | 4223 | trx_t* trx; | ||
2267 | 4224 | |||
2268 | 4225 | DBUG_ENTER("innobase_kill_connection"); | ||
2269 | 4226 | DBUG_ASSERT(hton == innodb_hton_ptr); | ||
2270 | 4227 | |||
2271 | 4228 | lock_mutex_enter(); | ||
2272 | 4229 | |||
2273 | 4230 | trx = thd_to_trx(thd); | ||
2274 | 4231 | |||
2275 | 4232 | if (trx) | ||
2276 | 4233 | { | ||
2277 | 4234 | trx_mutex_enter(trx); | ||
2278 | 4235 | |||
2279 | 4236 | /* Cancel a pending lock request. */ | ||
2280 | 4237 | if (trx->lock.wait_lock) | ||
2281 | 4238 | lock_cancel_waiting_and_release(trx->lock.wait_lock); | ||
2282 | 4239 | |||
2283 | 4240 | trx_mutex_exit(trx); | ||
2284 | 4241 | } | ||
2285 | 4242 | |||
2286 | 4243 | lock_mutex_exit(); | ||
2287 | 4244 | |||
2288 | 4245 | DBUG_VOID_RETURN; | ||
2289 | 4246 | } | ||
2290 | 4247 | |||
2291 | 4202 | 4248 | ||
2292 | 4203 | 4249 | ||
2293 | 4204 | /****************************************************************//** | 4250 | /****************************************************************//** |
2294 | @@ -11874,7 +11920,7 @@ | |||
2295 | 11874 | 11920 | ||
2296 | 11875 | prebuilt->trx->op_info = ""; | 11921 | prebuilt->trx->op_info = ""; |
2297 | 11876 | if (thd_killed(user_thd)) { | 11922 | if (thd_killed(user_thd)) { |
2299 | 11877 | my_error(ER_QUERY_INTERRUPTED, MYF(0)); | 11923 | thd_set_kill_status(user_thd); |
2300 | 11878 | } | 11924 | } |
2301 | 11879 | 11925 | ||
2302 | 11880 | if (UNIV_UNLIKELY(share->ib_table->is_corrupt)) { | 11926 | if (UNIV_UNLIKELY(share->ib_table->is_corrupt)) { |
2303 | 11881 | 11927 | ||
2304 | === modified file 'Percona-Server/storage/innobase/include/lock0lock.h' | |||
2305 | --- Percona-Server/storage/innobase/include/lock0lock.h 2013-08-06 15:16:34 +0000 | |||
2306 | +++ Percona-Server/storage/innobase/include/lock0lock.h 2013-09-09 15:30:42 +0000 | |||
2307 | @@ -498,6 +498,16 @@ | |||
2308 | 498 | lock_trx_release_locks( | 498 | lock_trx_release_locks( |
2309 | 499 | /*===================*/ | 499 | /*===================*/ |
2310 | 500 | trx_t* trx); /*!< in/out: transaction */ | 500 | trx_t* trx); /*!< in/out: transaction */ |
2311 | 501 | |||
2312 | 502 | /*********************************************************************//** | ||
2313 | 503 | Cancels a waiting lock request and releases possible other transactions | ||
2314 | 504 | waiting behind it. */ | ||
2315 | 505 | UNIV_INTERN | ||
2316 | 506 | void | ||
2317 | 507 | lock_cancel_waiting_and_release( | ||
2318 | 508 | /*============================*/ | ||
2319 | 509 | lock_t* lock); /*!< in/out: waiting lock request */ | ||
2320 | 510 | |||
2321 | 501 | /*********************************************************************//** | 511 | /*********************************************************************//** |
2322 | 502 | Removes locks on a table to be dropped or truncated. | 512 | Removes locks on a table to be dropped or truncated. |
2323 | 503 | If remove_also_table_sx_locks is TRUE then table-level S and X locks are | 513 | If remove_also_table_sx_locks is TRUE then table-level S and X locks are |
2324 | 504 | 514 | ||
2325 | === modified file 'Percona-Server/storage/innobase/include/lock0priv.h' | |||
2326 | --- Percona-Server/storage/innobase/include/lock0priv.h 2013-06-10 20:44:22 +0000 | |||
2327 | +++ Percona-Server/storage/innobase/include/lock0priv.h 2013-09-09 15:30:42 +0000 | |||
2328 | @@ -98,15 +98,6 @@ | |||
2329 | 98 | ulint heap_no);/*!< in: heap number of the record */ | 98 | ulint heap_no);/*!< in: heap number of the record */ |
2330 | 99 | 99 | ||
2331 | 100 | /*********************************************************************//** | 100 | /*********************************************************************//** |
2332 | 101 | Cancels a waiting lock request and releases possible other transactions | ||
2333 | 102 | waiting behind it. */ | ||
2334 | 103 | UNIV_INTERN | ||
2335 | 104 | void | ||
2336 | 105 | lock_cancel_waiting_and_release( | ||
2337 | 106 | /*============================*/ | ||
2338 | 107 | lock_t* lock); /*!< in/out: waiting lock request */ | ||
2339 | 108 | |||
2340 | 109 | /*********************************************************************//** | ||
2341 | 110 | Checks if some transaction has an implicit x-lock on a record in a clustered | 101 | Checks if some transaction has an implicit x-lock on a record in a clustered |
2342 | 111 | index. | 102 | index. |
2343 | 112 | @return transaction id of the transaction which has the x-lock, or 0 */ | 103 | @return transaction id of the transaction which has the x-lock, or 0 */ |
2344 | 113 | 104 | ||
2345 | === added directory 'Percona-Server/unittest/mysys' | |||
2346 | === added file 'Percona-Server/unittest/mysys/my_timer-t.c' | |||
2347 | --- Percona-Server/unittest/mysys/my_timer-t.c 1970-01-01 00:00:00 +0000 | |||
2348 | +++ Percona-Server/unittest/mysys/my_timer-t.c 2013-09-09 15:30:42 +0000 | |||
2349 | @@ -0,0 +1,263 @@ | |||
2350 | 1 | /* Copyright (c) 2012, Twitter, Inc. All rights reserved. | ||
2351 | 2 | |||
2352 | 3 | This program is free software; you can redistribute it and/or modify | ||
2353 | 4 | it under the terms of the GNU General Public License as published by | ||
2354 | 5 | the Free Software Foundation; version 2 of the License. | ||
2355 | 6 | |||
2356 | 7 | This program is distributed in the hope that it will be useful, | ||
2357 | 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2358 | 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2359 | 10 | GNU General Public License for more details. | ||
2360 | 11 | |||
2361 | 12 | You should have received a copy of the GNU General Public License along | ||
2362 | 13 | with this program; if not, write to the Free Software Foundation, Inc., | ||
2363 | 14 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ | ||
2364 | 15 | |||
2365 | 16 | #include "m_string.h" | ||
2366 | 17 | #include "my_timer.h" | ||
2367 | 18 | #include "thr_template.c" | ||
2368 | 19 | |||
2369 | 20 | typedef struct | ||
2370 | 21 | { | ||
2371 | 22 | my_timer_t timer; | ||
2372 | 23 | unsigned int fired; | ||
2373 | 24 | pthread_mutex_t mutex; | ||
2374 | 25 | pthread_cond_t cond; | ||
2375 | 26 | } test_timer_t; | ||
2376 | 27 | |||
2377 | 28 | static void timer_notify_function(my_timer_t *timer) | ||
2378 | 29 | { | ||
2379 | 30 | test_timer_t *test= my_container_of(timer, test_timer_t, timer); | ||
2380 | 31 | |||
2381 | 32 | pthread_mutex_lock(&test->mutex); | ||
2382 | 33 | test->fired++; | ||
2383 | 34 | pthread_cond_signal(&test->cond); | ||
2384 | 35 | pthread_mutex_unlock(&test->mutex); | ||
2385 | 36 | } | ||
2386 | 37 | |||
2387 | 38 | static void test_timer_create(test_timer_t *test) | ||
2388 | 39 | { | ||
2389 | 40 | memset(test, 0, sizeof(test_timer_t)); | ||
2390 | 41 | pthread_mutex_init(&test->mutex, NULL); | ||
2391 | 42 | pthread_cond_init(&test->cond, NULL); | ||
2392 | 43 | ok(my_os_timer_create(&test->timer) == 0, "my_os_timer_create"); | ||
2393 | 44 | test->timer.notify_function= timer_notify_function; | ||
2394 | 45 | } | ||
2395 | 46 | |||
2396 | 47 | static void test_timer_destroy(test_timer_t *test) | ||
2397 | 48 | { | ||
2398 | 49 | pthread_mutex_destroy(&test->mutex); | ||
2399 | 50 | pthread_cond_destroy(&test->cond); | ||
2400 | 51 | my_os_timer_delete(&test->timer); | ||
2401 | 52 | } | ||
2402 | 53 | |||
2403 | 54 | static void test_create_and_delete(void) | ||
2404 | 55 | { | ||
2405 | 56 | int rc; | ||
2406 | 57 | my_timer_t timer; | ||
2407 | 58 | |||
2408 | 59 | diag("test_create_and_delete"); | ||
2409 | 60 | |||
2410 | 61 | memset(&timer, 0, sizeof(timer)); | ||
2411 | 62 | |||
2412 | 63 | rc= my_os_timer_create(&timer); | ||
2413 | 64 | ok(rc == 0, "my_os_timer_create"); | ||
2414 | 65 | |||
2415 | 66 | my_os_timer_delete(&timer); | ||
2416 | 67 | } | ||
2417 | 68 | |||
2418 | 69 | static void test_reset(void) | ||
2419 | 70 | { | ||
2420 | 71 | int rc, state; | ||
2421 | 72 | test_timer_t test; | ||
2422 | 73 | |||
2423 | 74 | diag("test_reset"); | ||
2424 | 75 | |||
2425 | 76 | test_timer_create(&test); | ||
2426 | 77 | |||
2427 | 78 | rc= my_os_timer_set(&test.timer, 3600000U); | ||
2428 | 79 | ok(rc == 0, "my_os_timer_set"); | ||
2429 | 80 | |||
2430 | 81 | rc= my_os_timer_reset(&test.timer, &state); | ||
2431 | 82 | ok(rc == 0, "my_os_timer_reset"); | ||
2432 | 83 | |||
2433 | 84 | ok(state == 1, "timer state is nonsignaled"); | ||
2434 | 85 | ok(test.fired == 0, "timer has not fired"); | ||
2435 | 86 | |||
2436 | 87 | test_timer_destroy(&test); | ||
2437 | 88 | } | ||
2438 | 89 | |||
2439 | 90 | static void test_timer(void) | ||
2440 | 91 | { | ||
2441 | 92 | int rc, state; | ||
2442 | 93 | test_timer_t test; | ||
2443 | 94 | |||
2444 | 95 | diag("test_timer"); | ||
2445 | 96 | |||
2446 | 97 | test_timer_create(&test); | ||
2447 | 98 | |||
2448 | 99 | pthread_mutex_lock(&test.mutex); | ||
2449 | 100 | |||
2450 | 101 | rc= my_os_timer_set(&test.timer, 5); | ||
2451 | 102 | ok(rc == 0, "my_os_timer_set"); | ||
2452 | 103 | |||
2453 | 104 | ok(test.fired == 0, "not fired yet"); | ||
2454 | 105 | |||
2455 | 106 | while (!test.fired) | ||
2456 | 107 | pthread_cond_wait(&test.cond, &test.mutex); | ||
2457 | 108 | |||
2458 | 109 | ok(test.fired == 1, "timer fired once"); | ||
2459 | 110 | |||
2460 | 111 | rc= my_os_timer_reset(&test.timer, &state); | ||
2461 | 112 | ok(rc == 0, "my_os_timer_reset"); | ||
2462 | 113 | |||
2463 | 114 | ok(state == 0, "timer state was signaled"); | ||
2464 | 115 | |||
2465 | 116 | pthread_mutex_unlock(&test.mutex); | ||
2466 | 117 | |||
2467 | 118 | test_timer_destroy(&test); | ||
2468 | 119 | } | ||
2469 | 120 | |||
2470 | 121 | static void timer_set_and_wait(test_timer_t *test, unsigned int fired_count) | ||
2471 | 122 | { | ||
2472 | 123 | int rc, state; | ||
2473 | 124 | |||
2474 | 125 | rc= my_os_timer_set(&test->timer, 5); | ||
2475 | 126 | ok(rc == 0, "my_os_timer_set"); | ||
2476 | 127 | |||
2477 | 128 | ok(test->fired != fired_count, "not fired yet"); | ||
2478 | 129 | |||
2479 | 130 | while (test->fired != fired_count) | ||
2480 | 131 | pthread_cond_wait(&test->cond, &test->mutex); | ||
2481 | 132 | |||
2482 | 133 | ok(test->fired == fired_count, "timer fired"); | ||
2483 | 134 | |||
2484 | 135 | rc= my_os_timer_reset(&test->timer, &state); | ||
2485 | 136 | ok(rc == 0, "my_os_timer_reset"); | ||
2486 | 137 | |||
2487 | 138 | ok(state == 0, "timer state was signaled"); | ||
2488 | 139 | } | ||
2489 | 140 | |||
2490 | 141 | static void test_timer_reuse(void) | ||
2491 | 142 | { | ||
2492 | 143 | test_timer_t test; | ||
2493 | 144 | |||
2494 | 145 | diag("test_timer_reuse"); | ||
2495 | 146 | |||
2496 | 147 | test_timer_create(&test); | ||
2497 | 148 | |||
2498 | 149 | pthread_mutex_lock(&test.mutex); | ||
2499 | 150 | |||
2500 | 151 | timer_set_and_wait(&test, 1); | ||
2501 | 152 | timer_set_and_wait(&test, 2); | ||
2502 | 153 | timer_set_and_wait(&test, 3); | ||
2503 | 154 | |||
2504 | 155 | pthread_mutex_unlock(&test.mutex); | ||
2505 | 156 | |||
2506 | 157 | test_timer_destroy(&test); | ||
2507 | 158 | } | ||
2508 | 159 | |||
2509 | 160 | static void test_independent_timers(void) | ||
2510 | 161 | { | ||
2511 | 162 | int rc, state; | ||
2512 | 163 | test_timer_t test; | ||
2513 | 164 | |||
2514 | 165 | diag("test_independent_timers"); | ||
2515 | 166 | |||
2516 | 167 | test_timer_create(&test); | ||
2517 | 168 | |||
2518 | 169 | rc= my_os_timer_set(&test.timer, 3600000U); | ||
2519 | 170 | ok(rc == 0, "my_os_timer_set"); | ||
2520 | 171 | |||
2521 | 172 | test_timer(); | ||
2522 | 173 | |||
2523 | 174 | rc= my_os_timer_reset(&test.timer, &state); | ||
2524 | 175 | ok(rc == 0, "my_os_timer_reset"); | ||
2525 | 176 | |||
2526 | 177 | ok(state == 1, "timer state is nonsignaled"); | ||
2527 | 178 | ok(test.fired == 0, "timer has not fired"); | ||
2528 | 179 | |||
2529 | 180 | test_timer_destroy(&test); | ||
2530 | 181 | } | ||
2531 | 182 | |||
2532 | 183 | static void test_timer_no_tap(void) | ||
2533 | 184 | { | ||
2534 | 185 | int rc, state; | ||
2535 | 186 | test_timer_t test; | ||
2536 | 187 | |||
2537 | 188 | memset(&test, 0, sizeof(test_timer_t)); | ||
2538 | 189 | |||
2539 | 190 | pthread_mutex_init(&test.mutex, NULL); | ||
2540 | 191 | pthread_cond_init(&test.cond, NULL); | ||
2541 | 192 | |||
2542 | 193 | test.timer.notify_function= timer_notify_function; | ||
2543 | 194 | |||
2544 | 195 | rc= my_os_timer_create(&test.timer); | ||
2545 | 196 | assert(rc == 0); | ||
2546 | 197 | |||
2547 | 198 | pthread_mutex_lock(&test.mutex); | ||
2548 | 199 | |||
2549 | 200 | rc= my_os_timer_set(&test.timer, 5); | ||
2550 | 201 | assert(rc == 0); | ||
2551 | 202 | |||
2552 | 203 | assert(test.fired == 0); /* not fired yet */ | ||
2553 | 204 | |||
2554 | 205 | while (!test.fired) | ||
2555 | 206 | pthread_cond_wait(&test.cond, &test.mutex); | ||
2556 | 207 | |||
2557 | 208 | assert(test.fired == 1); /* timer fired once */ | ||
2558 | 209 | |||
2559 | 210 | rc= my_os_timer_reset(&test.timer, &state); | ||
2560 | 211 | assert(rc == 0); | ||
2561 | 212 | |||
2562 | 213 | assert(state == 0); /* timer state was signaled */ | ||
2563 | 214 | |||
2564 | 215 | pthread_mutex_unlock(&test.mutex); | ||
2565 | 216 | |||
2566 | 217 | pthread_mutex_destroy(&test.mutex); | ||
2567 | 218 | pthread_cond_destroy(&test.cond); | ||
2568 | 219 | my_os_timer_delete(&test.timer); | ||
2569 | 220 | } | ||
2570 | 221 | |||
2571 | 222 | static pthread_handler_t test_timer_per_thread(void *arg) | ||
2572 | 223 | { | ||
2573 | 224 | int iter= *(int *) arg; | ||
2574 | 225 | |||
2575 | 226 | while (iter--) | ||
2576 | 227 | test_timer_no_tap(); | ||
2577 | 228 | |||
2578 | 229 | pthread_mutex_lock(&mutex); | ||
2579 | 230 | if (!--running_threads) | ||
2580 | 231 | pthread_cond_signal(&cond); | ||
2581 | 232 | pthread_mutex_unlock(&mutex); | ||
2582 | 233 | |||
2583 | 234 | return NULL; | ||
2584 | 235 | } | ||
2585 | 236 | |||
2586 | 237 | static void test_reinitialization(void) | ||
2587 | 238 | { | ||
2588 | 239 | diag("test_reinitialization"); | ||
2589 | 240 | |||
2590 | 241 | my_os_timer_deinit(); | ||
2591 | 242 | ok(my_os_timer_init_ext() == 0, "my_os_timer_init_ext"); | ||
2592 | 243 | test_timer(); | ||
2593 | 244 | my_os_timer_deinit(); | ||
2594 | 245 | ok(my_os_timer_init_ext() == 0, "my_os_timer_init_ext"); | ||
2595 | 246 | } | ||
2596 | 247 | |||
2597 | 248 | void do_tests() | ||
2598 | 249 | { | ||
2599 | 250 | plan(49); | ||
2600 | 251 | |||
2601 | 252 | ok(my_os_timer_init_ext() == 0, "my_os_timer_init_ext"); | ||
2602 | 253 | |||
2603 | 254 | test_create_and_delete(); | ||
2604 | 255 | test_reset(); | ||
2605 | 256 | test_timer(); | ||
2606 | 257 | test_timer_reuse(); | ||
2607 | 258 | test_independent_timers(); | ||
2608 | 259 | test_concurrently("per-thread", test_timer_per_thread, THREADS, 5); | ||
2609 | 260 | test_reinitialization(); | ||
2610 | 261 | |||
2611 | 262 | my_os_timer_deinit(); | ||
2612 | 263 | } |
Vlad,
I see you encountered same issue as I did also. performance_schema *digest* tables are rely heavily on sql_yacc.yy grammar. So if someone just add new token (or even rule?) many of statement's digests will change.
I very dislike it as
1. There is a need to almost completely rewrite several *.result in perfscehma suite
2. There is no way to merge for example this branch and lp:~sergei.glushchenko/percona-server/ps56-univ-log-archive as both touch sql_yacc.yy. As resulting MD5 hashes will depend on changes made in both branches. The only possible way is once one of the branges been merged, update another one and recalculate digests in test cases.
Do you have any thoughts on how to workaround this?
Thanks,
Sergei