Commit 3b6dadb5 authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.1 into 10.2

parents 0460d42b 7f67ef14
......@@ -101,18 +101,7 @@
sort-buffer-size 2097152
sql-mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
stack-trace TRUE
@@ -1516,14 +1532,16 @@
sync-relay-log 10000
sync-relay-log-info 10000
sysdate-is-now FALSE
-table-cache 421
+table-cache 2000
table-definition-cache 400
-table-open-cache 421
-table-open-cache-instances 1
+table-open-cache 2000
+table-open-cache-instances 8
tc-heuristic-recover OFF
@@ -1516,6 +1532,8 @@
thread-cache-size 151
thread-pool-idle-timeout 60
thread-pool-max-threads 65536
......
......@@ -1343,7 +1343,6 @@ max-binlog-cache-size 18446744073709547520
max-binlog-size 1073741824
max-binlog-stmt-cache-size 18446744073709547520
max-connect-errors 100
max-connections 151
max-delayed-threads 20
max-digest-length 1024
max-error-count 64
......@@ -1516,10 +1515,7 @@ sync-master-info 10000
sync-relay-log 10000
sync-relay-log-info 10000
sysdate-is-now FALSE
table-cache 421
table-definition-cache 400
table-open-cache 421
table-open-cache-instances 1
tc-heuristic-recover OFF
thread-cache-size 151
thread-pool-idle-timeout 60
......
......@@ -2609,6 +2609,47 @@ Central America and the Caribbean 442 66422
SET @@optimizer_switch= @save_optimizer_switch;
DROP TABLE t1;
#
# MDEV-9513: Assertion `join->group_list || !join->is_in_subquery()' failed in create_sort_index
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2 (a INT);
INSERT INTO t2 VALUES (2),(3);
EXPLAIN
SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY A ALL NULL NULL NULL NULL 2 Using where
3 DEPENDENT UNION B ALL NULL NULL NULL NULL 2 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1);
a
1
2
EXPLAIN
SELECT t1.a FROM t1 WHERE EXISTS (SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
2 SUBQUERY A ALL NULL NULL NULL NULL 2
3 UNION B ALL NULL NULL NULL NULL 2
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
SELECT t1.a FROM t1 WHERE EXISTS (SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1);
a
1
2
EXPLAIN
SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION ALL SELECT B.a FROM t2 B ORDER BY 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY A ALL NULL NULL NULL NULL 2 Using where
3 DEPENDENT UNION B ALL NULL NULL NULL NULL 2 Using where
SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION ALL SELECT B.a FROM t2 B ORDER BY 1);
a
1
2
DROP TABLE t1,t2;
# end of 10.1 tests
#
# MDEV-22852: SIGSEGV in sortlength (optimized builds)
#
SET @save_optimizer_switch=@@optimizer_switch;
......
......@@ -2340,6 +2340,53 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# MDEV-23105 Cast number string with many leading zeros to decimal gives unexpected result
#
SELECT CAST(0000000000000000000000000000000000000000000000000000000000000000000000000000000020.01 AS DECIMAL(15,2)) as val;
val
20.01
SET sql_mode='';
CREATE TABLE t1 (a TEXT);
INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1));
INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.0'));
INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.9'));
INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.99'));
INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.994'));
INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.995'));
INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.999'));
CREATE TABLE t2 (a TEXT, d DECIMAL(15,2));
INSERT IGNORE INTO t2 (a,d) SELECT a, a FROM t1;
Warnings:
Note 1265 Data truncated for column 'd' at row 5
Note 1265 Data truncated for column 'd' at row 6
Note 1265 Data truncated for column 'd' at row 7
INSERT IGNORE INTO t2 (a,d) SELECT CONCAT('-',a), CONCAT('-',a) FROM t1;
Warnings:
Note 1265 Data truncated for column 'd' at row 5
Note 1265 Data truncated for column 'd' at row 6
Note 1265 Data truncated for column 'd' at row 7
SELECT d, a FROM t2 ORDER BY d,a;
d a
-2.00 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.995
-2.00 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.999
-1.99 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.99
-1.99 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.994
-1.90 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.9
-1.00 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-1.00 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.0
1.00 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
1.00 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.0
1.90 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.9
1.99 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.99
1.99 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.994
2.00 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.995
2.00 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.999
DROP TABLE t1, t2;
SET sql_mode=DEFAULT;
#
# End of 10.1 tests
#
#
# Bug#18408499 UNSIGNED BIGINT HIGH VALUES
# WRONG NUMERICAL COMPARISON RESULTS
#
......
......@@ -23,7 +23,9 @@ perl;
log-slow-queries pid-file slow-query-log-file log-basename
datadir slave-load-tmpdir tmpdir socket thread-pool-size
large-files-support lower-case-file-system system-time-zone
collation-server character-set-server log-tc-size version.*/;
collation-server character-set-server log-tc-size table-cache
table-open-cache table-open-cache-instances max-connections
version.*/;
# Plugins which may or may not be there:
@plugins=qw/innodb archive blackhole federated partition
......
......@@ -2143,6 +2143,31 @@ SET @@optimizer_switch= @save_optimizer_switch;
DROP TABLE t1;
--echo #
--echo # MDEV-9513: Assertion `join->group_list || !join->is_in_subquery()' failed in create_sort_index
--echo #
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2 (a INT);
INSERT INTO t2 VALUES (2),(3);
EXPLAIN
SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1);
SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1);
EXPLAIN
SELECT t1.a FROM t1 WHERE EXISTS (SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1);
SELECT t1.a FROM t1 WHERE EXISTS (SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1);
EXPLAIN
SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION ALL SELECT B.a FROM t2 B ORDER BY 1);
SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION ALL SELECT B.a FROM t2 B ORDER BY 1);
DROP TABLE t1,t2;
--echo # end of 10.1 tests
--echo #
--echo # MDEV-22852: SIGSEGV in sortlength (optimized builds)
--echo #
......
......@@ -1824,6 +1824,32 @@ CREATE TABLE t1 (a DECIMAL(2,1) DEFAULT 0.10001e0);
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # MDEV-23105 Cast number string with many leading zeros to decimal gives unexpected result
--echo #
SELECT CAST(0000000000000000000000000000000000000000000000000000000000000000000000000000000020.01 AS DECIMAL(15,2)) as val;
SET sql_mode='';
CREATE TABLE t1 (a TEXT);
INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1));
INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.0'));
INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.9'));
INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.99'));
INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.994'));
INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.995'));
INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.999'));
CREATE TABLE t2 (a TEXT, d DECIMAL(15,2));
INSERT IGNORE INTO t2 (a,d) SELECT a, a FROM t1;
INSERT IGNORE INTO t2 (a,d) SELECT CONCAT('-',a), CONCAT('-',a) FROM t1;
SELECT d, a FROM t2 ORDER BY d,a;
DROP TABLE t1, t2;
SET sql_mode=DEFAULT;
--echo #
--echo # End of 10.1 tests
--echo #
--echo #
--echo # Bug#18408499 UNSIGNED BIGINT HIGH VALUES
--echo # WRONG NUMERICAL COMPARISON RESULTS
......
......@@ -145,6 +145,10 @@ class Item_subselect :public Item_result_field,
Item_subselect(THD *thd);
virtual subs_type substype() { return UNKNOWN_SUBS; }
bool is_exists_predicate()
{
return substype() == Item_subselect::EXISTS_SUBS;
}
bool is_in_predicate()
{
return (substype() == Item_subselect::IN_SUBS ||
......
......@@ -514,6 +514,25 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
is_union_select= is_union() || fake_select_lex;
/*
If we are reading UNION output and the UNION is in the
IN/ANY/ALL/EXISTS subquery, then ORDER BY is redundant and hence should
be removed.
Example:
select ... col IN (select col2 FROM t1 union select col3 from t2 ORDER BY 1)
(as for ORDER BY ... LIMIT, it currently not supported inside
IN/ALL/ANY subqueries)
(For non-UNION this removal of ORDER BY clause is done in
check_and_do_in_subquery_rewrites())
*/
if (is_union() && item &&
(item->is_in_predicate() || item->is_exists_predicate()))
{
global_parameters()->order_list.first= NULL;
global_parameters()->order_list.elements= 0;
}
/* Global option */
if (is_union_select || is_recursive)
......
......@@ -1281,9 +1281,16 @@ struct TABLE
/* number of select if it is derived table */
uint derived_select_number;
/*
0 or JOIN_TYPE_{LEFT|RIGHT}. Currently this is only compared to 0.
If maybe_null !=0, this table is inner w.r.t. some outer join operation,
and null_row may be true.
Possible values:
- 0 by default
- JOIN_TYPE_{LEFT|RIGHT} if the table is inner w.r.t an outer join
operation
- 1 if the SELECT has mixed_implicit_grouping=1. example:
select max(col1), col2 from t1. In this case, the query produces
one row with all columns having NULL values.
Interpetation: If maybe_null!=0, all fields of the table are considered
NULLable (and have NULL values when null_row=true)
*/
uint maybe_null;
int current_lock; /* Type of lock on table */
......
......@@ -41,9 +41,6 @@ Modified Jan Lindström jan.lindstrom@mariadb.com
#include "fil0pagecompress.h"
#include <my_crypt.h>
/** Mutex for keys */
static ib_mutex_t fil_crypt_key_mutex;
static bool fil_crypt_threads_inited = false;
/** Is encryption enabled/disabled */
......@@ -113,8 +110,6 @@ UNIV_INTERN
void
fil_space_crypt_init()
{
mutex_create(LATCH_ID_FIL_CRYPT_MUTEX, &fil_crypt_key_mutex);
fil_crypt_throttle_sleep_event = os_event_create(0);
mutex_create(LATCH_ID_FIL_CRYPT_STAT_MUTEX, &crypt_stat_mutex);
......@@ -128,7 +123,6 @@ void
fil_space_crypt_cleanup()
{
os_event_destroy(fil_crypt_throttle_sleep_event);
mutex_free(&fil_crypt_key_mutex);
mutex_free(&crypt_stat_mutex);
}
......@@ -1384,6 +1378,94 @@ fil_crypt_return_iops(
fil_crypt_update_total_stat(state);
}
/** Return the next tablespace from rotation_list.
@param space previous tablespace (NULL to start from the start)
@param recheck whether the removal condition needs to be rechecked after
the encryption parameters were changed
@param encrypt expected state of innodb_encrypt_tables
@return the next tablespace to process (n_pending_ops incremented)
@retval NULL if this was the last */
inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space,
bool recheck, bool encrypt)
{
ut_ad(mutex_own(&fil_system->mutex));
sized_ilist<fil_space_t, rotation_list_tag_t>::iterator it=
space ? space : fil_system->rotation_list.begin();
const sized_ilist<fil_space_t, rotation_list_tag_t>::iterator end=
fil_system->rotation_list.end();
if (space)
{
while (++it != end && (!UT_LIST_GET_LEN(it->chain) || it->is_stopping()));
/* If one of the encryption threads already started the encryption
of the table then don't remove the unencrypted spaces from rotation list
If there is a change in innodb_encrypt_tables variables value then
don't remove the last processed tablespace from the rotation list. */
if (!--space->n_pending_ops &&
(!recheck || space->crypt_data) && !encrypt == !srv_encrypt_tables &&
space->is_in_rotation_list)
{
ut_a(!fil_system->rotation_list.empty());
fil_system->rotation_list.remove(*space);
space->is_in_rotation_list= false;
}
}
if (it == end)
return NULL;
space= &*it;
space->n_pending_ops++;
return space;
}
/** Return the next tablespace.
@param space previous tablespace (NULL to start from the beginning)
@param recheck whether the removal condition needs to be rechecked after
the encryption parameters were changed
@param encrypt expected state of innodb_encrypt_tables
@return pointer to the next tablespace (with n_pending_ops incremented)
@retval NULL if this was the last */
static fil_space_t *fil_space_next(fil_space_t *space, bool recheck,
bool encrypt)
{
mutex_enter(&fil_system->mutex);
ut_ad(!space || space->n_pending_ops);
if (!srv_fil_crypt_rotate_key_age)
space= fil_system->keyrotate_next(space, recheck, encrypt);
else if (!space)
{
space= UT_LIST_GET_FIRST(fil_system->space_list);
/* We can trust that space is not NULL because at least the
system tablespace is always present and loaded first. */
space->n_pending_ops++;
}
else
{
ut_ad(space->n_pending_ops > 0);
/* Move on to the next fil_space_t */
space->n_pending_ops--;
space= UT_LIST_GET_NEXT(space_list, space);
/* Skip abnormal tablespaces or those that are being created by
fil_ibd_create(), or being dropped. */
while (space &&
(UT_LIST_GET_LEN(space->chain) == 0 ||
space->is_stopping() || space->purpose != FIL_TYPE_TABLESPACE))
space= UT_LIST_GET_NEXT(space_list, space);
if (space)
space->n_pending_ops++;
}
mutex_exit(&fil_system->mutex);
return space;
}
/** Search for a space needing rotation
@param[in,out] key_state Key state
@param[in,out] state Rotation state
......@@ -1416,16 +1498,8 @@ static bool fil_crypt_find_space_to_rotate(
state->space = NULL;
}
/* If key rotation is enabled (default) we iterate all tablespaces.
If key rotation is not enabled we iterate only the tablespaces
added to keyrotation list. */
if (srv_fil_crypt_rotate_key_age) {
state->space = fil_space_next(state->space);
} else {
state->space = fil_system->keyrotate_next(
state->space, *recheck,
key_state->key_version);
}
state->space = fil_space_next(state->space, *recheck,
key_state->key_version != 0);
while (!state->should_shutdown() && state->space) {
/* If there is no crypt data and we have not yet read
......@@ -1443,16 +1517,16 @@ static bool fil_crypt_find_space_to_rotate(
return true;
}
if (srv_fil_crypt_rotate_key_age) {
state->space = fil_space_next(state->space);
} else {
state->space = fil_system->keyrotate_next(
state->space, *recheck,
key_state->key_version);
}
state->space = fil_space_next(state->space, *recheck,
key_state->key_version != 0);
}
if (state->space) {
fil_space_release(state->space);
state->space = NULL;
}
/* if we didn't find any space return iops */
/* no work to do; release our allocation of I/O capacity */
fil_crypt_return_iops(state);
return false;
......
......@@ -5892,136 +5892,6 @@ fil_space_t::release_free_extents(ulint n_reserved)
n_reserved_extents -= n_reserved;
}
/** Return the next fil_space_t.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in] prev_space Pointer to the previous fil_space_t.
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last*/
fil_space_t*
fil_space_next(fil_space_t* prev_space)
{
fil_space_t* space=prev_space;
mutex_enter(&fil_system->mutex);
if (prev_space == NULL) {
space = UT_LIST_GET_FIRST(fil_system->space_list);
/* We can trust that space is not NULL because at least the
system tablespace is always present and loaded first. */
space->n_pending_ops++;
} else {
ut_ad(space->n_pending_ops > 0);
/* Move on to the next fil_space_t */
space->n_pending_ops--;
space = UT_LIST_GET_NEXT(space_list, space);
/* Skip spaces that are being created by
fil_ibd_create(), or dropped, or !tablespace. */
while (space != NULL
&& (UT_LIST_GET_LEN(space->chain) == 0
|| space->is_stopping()
|| space->purpose != FIL_TYPE_TABLESPACE)) {
space = UT_LIST_GET_NEXT(space_list, space);
}
if (space != NULL) {
space->n_pending_ops++;
}
}
mutex_exit(&fil_system->mutex);
return(space);
}
/**
Remove space from key rotation list if there are no more
pending operations.
@param[in,out] space Tablespace */
static
void
fil_space_remove_from_keyrotation(fil_space_t* space)
{
ut_ad(mutex_own(&fil_system->mutex));
ut_ad(space);
if (space->n_pending_ops == 0 && space->is_in_rotation_list) {
ut_a(!fil_system->rotation_list.empty());
fil_system->rotation_list.remove(*space);
space->is_in_rotation_list = false;
}
}
/** Return the next fil_space_t from key rotation list.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in] prev_space Previous tablespace or NULL to start
from beginning of fil_system->rotation list
@param[in] recheck recheck of the tablespace is needed or
still encryption thread does write page0 for it
@param[in] key_version key version of the key state thread
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last */
fil_space_t *fil_system_t::keyrotate_next(fil_space_t *prev_space,
bool recheck, uint key_version)
{
mutex_enter(&fil_system->mutex);
/* If one of the encryption threads already started the encryption
of the table then don't remove the unencrypted spaces from rotation list
If there is a change in innodb_encrypt_tables variables value then
don't remove the last processed tablespace from the rotation list. */
const bool remove= (!recheck || prev_space->crypt_data) &&
!key_version == !srv_encrypt_tables;
sized_ilist<fil_space_t, rotation_list_tag_t>::iterator it=
prev_space == NULL ? fil_system->rotation_list.end() : prev_space;
if (it == fil_system->rotation_list.end())
{
it= fil_system->rotation_list.begin();
}
else
{
ut_ad(prev_space->n_pending_ops > 0);
/* Move on to the next fil_space_t */
prev_space->n_pending_ops--;
++it;
while (it != fil_system->rotation_list.end() &&
(UT_LIST_GET_LEN(it->chain) == 0 || it->is_stopping()))
{
++it;
}
if (remove)
{
fil_space_remove_from_keyrotation(prev_space);
}
}
fil_space_t *space= it == fil_system->rotation_list.end() ? NULL : &*it;
if (space)
{
space->n_pending_ops++;
}
mutex_exit(&fil_system->mutex);
return space;
}
/** Determine the block size of the data file.
@param[in] space tablespace
@param[in] offset page number
......
......@@ -556,24 +556,15 @@ struct fil_system_t {
@retval NULL if the tablespace does not exist or cannot be read */
fil_space_t* read_page0(ulint id);
/** Return the next fil_space_t from key rotation list.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in] prev_space Previous tablespace or NULL to start
from beginning of fil_system->rotation
list
@param[in] recheck recheck of the tablespace is needed or
still encryption thread does write page0
for it
@param[in] key_version key version of the key state thread
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last */
fil_space_t* keyrotate_next(
fil_space_t* prev_space,
bool remove,
uint key_version);
/** Return the next tablespace from rotation_list.
@param space previous tablespace (NULL to start from the start)
@param recheck whether the removal condition needs to be rechecked after
the encryption parameters were changed
@param encrypt expected state of innodb_encrypt_tables
@return the next tablespace to process (n_pending_ops incremented)
@retval NULL if this was the last */
inline fil_space_t* keyrotate_next(fil_space_t *space, bool recheck,
bool encrypt);
};
/** The tablespace memory cache. This variable is NULL before the module is
......@@ -803,34 +794,6 @@ fil_space_acquire_for_io(ulint id);
void
fil_space_release_for_io(fil_space_t* space);
/** Return the next fil_space_t.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in,out] prev_space Pointer to the previous fil_space_t.
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last */
fil_space_t*
fil_space_next(
fil_space_t* prev_space)
MY_ATTRIBUTE((warn_unused_result));
/** Return the next fil_space_t from key rotation list.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in] prev_space Previous tablespace or NULL to start
from beginning of fil_system->rotation list
@param[in] remove Whether to remove the previous tablespace from
the rotation list
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last*/
fil_space_t*
fil_space_keyrotate_next(fil_space_t* prev_space, bool remove)
MY_ATTRIBUTE((warn_unused_result));
/** Wrapper with reference-counting for a fil_space_t. */
class FilSpace
{
......
......@@ -379,7 +379,6 @@ enum latch_id_t {
LATCH_ID_BTR_DEFRAGMENT_MUTEX,
LATCH_ID_MTFLUSH_THREAD_MUTEX,
LATCH_ID_MTFLUSH_MUTEX,
LATCH_ID_FIL_CRYPT_MUTEX,
LATCH_ID_FIL_CRYPT_STAT_MUTEX,
LATCH_ID_FIL_CRYPT_DATA_MUTEX,
LATCH_ID_FIL_CRYPT_THREADS_MUTEX,
......
......@@ -1511,8 +1511,6 @@ sync_latch_meta_init()
PFS_NOT_INSTRUMENTED);
LATCH_ADD_MUTEX(MTFLUSH_MUTEX, SYNC_NO_ORDER_CHECK,
PFS_NOT_INSTRUMENTED);
LATCH_ADD_MUTEX(FIL_CRYPT_MUTEX, SYNC_NO_ORDER_CHECK,
PFS_NOT_INSTRUMENTED);
LATCH_ADD_MUTEX(FIL_CRYPT_STAT_MUTEX, SYNC_NO_ORDER_CHECK,
PFS_NOT_INSTRUMENTED);
LATCH_ADD_MUTEX(FIL_CRYPT_DATA_MUTEX, SYNC_NO_ORDER_CHECK,
......
......@@ -44,15 +44,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com
#include "ha_prototypes.h" // IB_LOG_
#include <my_crypt.h>
/** Mutex for keys */
static ib_mutex_t fil_crypt_key_mutex;
static bool fil_crypt_threads_inited = false;
#ifdef UNIV_PFS_MUTEX
static mysql_pfs_key_t fil_crypt_key_mutex_key;
#endif
/** Is encryption enabled/disabled */
UNIV_INTERN ulong srv_encrypt_tables = 0;
......@@ -133,9 +126,6 @@ UNIV_INTERN
void
fil_space_crypt_init()
{
mutex_create(fil_crypt_key_mutex_key,
&fil_crypt_key_mutex, SYNC_NO_ORDER_CHECK);
fil_crypt_throttle_sleep_event = os_event_create();
mutex_create(fil_crypt_stat_mutex_key,
......@@ -152,7 +142,6 @@ fil_space_crypt_cleanup()
{
os_event_free(fil_crypt_throttle_sleep_event);
fil_crypt_throttle_sleep_event = NULL;
mutex_free(&fil_crypt_key_mutex);
mutex_free(&crypt_stat_mutex);
}
......@@ -1451,6 +1440,109 @@ fil_crypt_return_iops(
fil_crypt_update_total_stat(state);
}
/** Remove space from key rotation list if there are no pending operations. */
static void fil_space_remove_from_keyrotation(fil_space_t *space)
{
ut_ad(mutex_own(&fil_system->mutex));
if (space->n_pending_ops == 0 && space->is_in_rotation_list)
{
space->is_in_rotation_list= false;
ut_a(UT_LIST_GET_LEN(fil_system->rotation_list) > 0);
UT_LIST_REMOVE(rotation_list, fil_system->rotation_list, space);
}
}
/** Return the next tablespace from key rotation list.
@param space previous tablespace (NULL to start from the beginning)
@return pointer to the next tablespace (with n_pending_ops incremented)
@retval NULL if this was the last */
static fil_space_t *fil_space_keyrotate_next(fil_space_t *space)
{
ut_ad(mutex_own(&fil_system->mutex));
if (UT_LIST_GET_LEN(fil_system->rotation_list) == 0)
{
if (space)
{
space->n_pending_ops--;
fil_space_remove_from_keyrotation(space);
}
return NULL;
}
if (!space)
{
space= UT_LIST_GET_FIRST(fil_system->rotation_list);
/* We can trust that space is not NULL because we
checked list length above */
}
else
{
space->n_pending_ops--;
fil_space_t *old = space;
space= UT_LIST_GET_NEXT(rotation_list, space);
fil_space_remove_from_keyrotation(old);
}
/* Skip spaces that are being created by fil_ibd_create(),
or dropped. Note that rotation_list contains only
space->purpose == FIL_TABLESPACE. */
while (space && (!UT_LIST_GET_LEN(space->chain) || space->is_stopping()))
{
fil_space_t *old = space;
space= UT_LIST_GET_NEXT(rotation_list, space);
fil_space_remove_from_keyrotation(old);
}
if (space)
space->n_pending_ops++;
return space;
}
/** Return the next tablespace.
@param space previous tablespace (NULL to start from the beginning)
@return pointer to the next tablespace (with n_pending_ops incremented)
@retval NULL if this was the last */
static fil_space_t *fil_space_next(fil_space_t *space)
{
mutex_enter(&fil_system->mutex);
ut_ad(!space || space->n_pending_ops);
if (!srv_fil_crypt_rotate_key_age)
space= fil_space_keyrotate_next(space);
else if (!space)
{
space= UT_LIST_GET_FIRST(fil_system->space_list);
/* We can trust that space is not NULL because at least the
system tablespace is always present and loaded first. */
space->n_pending_ops++;
}
else
{
ut_ad(space->n_pending_ops > 0);
/* Move on to the next fil_space_t */
space->n_pending_ops--;
space= UT_LIST_GET_NEXT(space_list, space);
/* Skip abnormal tablespaces or those that are being created by
fil_ibd_create(), or being dropped. */
while (space &&
(UT_LIST_GET_LEN(space->chain) == 0 ||
space->is_stopping() || space->purpose != FIL_TABLESPACE))
space= UT_LIST_GET_NEXT(space_list, space);
if (space)
space->n_pending_ops++;
}
mutex_exit(&fil_system->mutex);
return space;
}
/***********************************************************************
Search for a space needing rotation
@param[in,out] key_state Key state
......@@ -1485,14 +1577,7 @@ fil_crypt_find_space_to_rotate(
state->space = NULL;
}
/* If key rotation is enabled (default) we iterate all tablespaces.
If key rotation is not enabled we iterate only the tablespaces
added to keyrotation list. */
if (srv_fil_crypt_rotate_key_age) {
state->space = fil_space_next(state->space);
} else {
state->space = fil_space_keyrotate_next(state->space);
}
state->space = fil_space_next(state->space);
while (!state->should_shutdown() && state->space) {
fil_crypt_read_crypt_data(state->space);
......@@ -1505,14 +1590,15 @@ fil_crypt_find_space_to_rotate(
return true;
}
if (srv_fil_crypt_rotate_key_age) {
state->space = fil_space_next(state->space);
} else {
state->space = fil_space_keyrotate_next(state->space);
}
state->space = fil_space_next(state->space);
}
if (state->space) {
fil_space_release(state->space);
state->space = NULL;
}
/* if we didn't find any space return iops */
/* no work to do; release our allocation of I/O capacity */
fil_crypt_return_iops(state);
return false;
......
......@@ -6863,137 +6863,3 @@ fil_space_release(fil_space_t* space)
space->n_pending_ops--;
mutex_exit(&fil_system->mutex);
}
/** Return the next fil_space_t.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in] prev_space Pointer to the previous fil_space_t.
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last*/
UNIV_INTERN
fil_space_t*
fil_space_next(fil_space_t* prev_space)
{
fil_space_t* space=prev_space;
mutex_enter(&fil_system->mutex);
if (prev_space == NULL) {
space = UT_LIST_GET_FIRST(fil_system->space_list);
/* We can trust that space is not NULL because at least the
system tablespace is always present and loaded first. */
space->n_pending_ops++;
} else {
ut_ad(space->n_pending_ops > 0);
/* Move on to the next fil_space_t */
space->n_pending_ops--;
space = UT_LIST_GET_NEXT(space_list, space);
/* Skip spaces that are being created by
fil_ibd_create(), or dropped, or !tablespace. */
while (space != NULL
&& (UT_LIST_GET_LEN(space->chain) == 0
|| space->is_stopping()
|| space->purpose != FIL_TABLESPACE)) {
space = UT_LIST_GET_NEXT(space_list, space);
}
if (space != NULL) {
space->n_pending_ops++;
}
}
mutex_exit(&fil_system->mutex);
return(space);
}
/**
Remove space from key rotation list if there are no more
pending operations.
@param[in] space Tablespace */
static
void
fil_space_remove_from_keyrotation(
fil_space_t* space)
{
ut_ad(mutex_own(&fil_system->mutex));
ut_ad(space);
if (space->n_pending_ops == 0 && space->is_in_rotation_list) {
space->is_in_rotation_list = false;
ut_a(UT_LIST_GET_LEN(fil_system->rotation_list) > 0);
UT_LIST_REMOVE(rotation_list, fil_system->rotation_list, space);
}
}
/** Return the next fil_space_t from key rotation list.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in] prev_space Pointer to the previous fil_space_t.
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last*/
UNIV_INTERN
fil_space_t*
fil_space_keyrotate_next(
fil_space_t* prev_space)
{
fil_space_t* space = prev_space;
fil_space_t* old = NULL;
mutex_enter(&fil_system->mutex);
if (UT_LIST_GET_LEN(fil_system->rotation_list) == 0) {
if (space) {
ut_ad(space->n_pending_ops > 0);
space->n_pending_ops--;
fil_space_remove_from_keyrotation(space);
}
mutex_exit(&fil_system->mutex);
return(NULL);
}
if (prev_space == NULL) {
space = UT_LIST_GET_FIRST(fil_system->rotation_list);
/* We can trust that space is not NULL because we
checked list length above */
} else {
ut_ad(space->n_pending_ops > 0);
/* Move on to the next fil_space_t */
space->n_pending_ops--;
old = space;
space = UT_LIST_GET_NEXT(rotation_list, space);
fil_space_remove_from_keyrotation(old);
}
/* Skip spaces that are being created by fil_ibd_create(),
or dropped. Note that rotation_list contains only
space->purpose == FIL_TABLESPACE. */
while (space != NULL
&& (UT_LIST_GET_LEN(space->chain) == 0
|| space->is_stopping())) {
old = space;
space = UT_LIST_GET_NEXT(rotation_list, space);
fil_space_remove_from_keyrotation(old);
}
if (space != NULL) {
space->n_pending_ops++;
}
mutex_exit(&fil_system->mutex);
return(space);
}
......@@ -705,34 +705,6 @@ UNIV_INTERN
void
fil_space_release_for_io(fil_space_t* space);
/** Return the next fil_space_t.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in,out] prev_space Pointer to the previous fil_space_t.
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last */
UNIV_INTERN
fil_space_t*
fil_space_next(
fil_space_t* prev_space)
MY_ATTRIBUTE((warn_unused_result));
/** Return the next fil_space_t from key rotation list.
Once started, the caller must keep calling this until it returns NULL.
fil_space_acquire() and fil_space_release() are invoked here which
blocks a concurrent operation from dropping the tablespace.
@param[in,out] prev_space Pointer to the previous fil_space_t.
If NULL, use the first fil_space_t on fil_system->space_list.
@return pointer to the next fil_space_t.
@retval NULL if this was the last*/
UNIV_INTERN
fil_space_t*
fil_space_keyrotate_next(
fil_space_t* prev_space)
MY_ATTRIBUTE((warn_unused_result));
/** Wrapper with reference-counting for a fil_space_t. */
class FilSpace
{
......
......@@ -812,6 +812,24 @@ internal_str2dec(const char *from, decimal_t *to, char **end, my_bool fixed)
while (s < end_of_string && my_isdigit(&my_charset_latin1, *s))
s++;
intg= (int) (s-s1);
/*
If the integer part is long enough and it has multiple leading zeros,
let's trim them, so this expression can return 1 without overflowing:
CAST(CONCAT(REPEAT('0',90),'1') AS DECIMAL(10))
*/
if (intg > DIG_PER_DEC1 && s1[0] == '0' && s1[1] == '0')
{
/*
Keep at least one digit, to avoid an empty string.
So we trim '0000' to '0' rather than to ''.
Otherwise the below code (converting digits to to->buf)
would fail on a fatal error.
*/
const char *iend= s - 1;
for ( ; s1 < iend && *s1 == '0'; s1++)
{ }
intg= (int) (s-s1);
}
if (s < end_of_string && *s=='.')
{
endp= s+1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment