From 2df2238cb86de237c6f57a25adb05dcdce020e8d Mon Sep 17 00:00:00 2001 From: Faustin Lammler Date: Fri, 21 Dec 2018 17:06:08 -0300 Subject: Lintian complains on spelling error The lintian check complains on spelling error: https://salsa.debian.org/mariadb-team/mariadb-10.3/-/jobs/95739 --- storage/innobase/include/fil0fil.h | 2 +- storage/innobase/include/fil0fil.ic | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 0818d3f0ed1..204b199c85a 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -350,7 +350,7 @@ struct fil_node_t { /** Value of fil_node_t::magic_n */ #define FIL_NODE_MAGIC_N 89389 -/** Common InnoDB file extentions */ +/** Common InnoDB file extensions */ enum ib_extention { NO_EXT = 0, IBD = 1, diff --git a/storage/innobase/include/fil0fil.ic b/storage/innobase/include/fil0fil.ic index 457b5e1a03e..31466f38546 100644 --- a/storage/innobase/include/fil0fil.ic +++ b/storage/innobase/include/fil0fil.ic @@ -69,7 +69,7 @@ fil_get_page_type_name( case FIL_PAGE_TYPE_ZBLOB2: return "ZBLOB2"; case FIL_PAGE_TYPE_UNKNOWN: - return "OLD UNKOWN PAGE TYPE"; + return "OLD UNKNOWN PAGE TYPE"; default: return "PAGE TYPE CORRUPTED"; } -- cgit v1.2.1 From 3ff8fb5141850aebcf37578c108bfbea99a5d53e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 3 Dec 2019 07:34:46 +0200 Subject: InnoDB: Remove unused get_wkb_of_default_point() The function get_wkb_of_default_point() should never have been added, and the cleanup in commit 56ff6f1b0b248befb80675ba36a3251c7844f410 should have removed it. The unnecessary code was added in mysql/mysql-server@0a27b72171c4449f506ad4e93df8c29fead1ed72 and mostly disabled in mysql/mysql-server@8f11af7734509821b654f2c330dff5374c89073c. In MariaDB, the types DATA_POINT and DATA_VAR_POINT are never used. Instead, DATA_GEOMETRY continues to be used since 10.2.2, introduced by mysql/mysql-server@673bad7c7e17701b69e29d0fbc4e2d68c1a7b613 in MySQL 5.7.1. --- storage/innobase/include/gis0geo.h | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/gis0geo.h b/storage/innobase/include/gis0geo.h index 3b71815d0fe..dea6d63f4e0 100644 --- a/storage/innobase/include/gis0geo.h +++ b/storage/innobase/include/gis0geo.h @@ -54,19 +54,6 @@ enum wkbByteOrder wkbNDR = 1 /* Little Endian */ }; -/** Get the wkb of default POINT value, which represents POINT(0 0) -if it's of dimension 2, etc. -@param[in] n_dims dimensions -@param[out] wkb wkb buffer for default POINT -@param[in] len length of wkb buffer -@return non-0 indicate the length of wkb of the default POINT, -0 if the buffer is too small */ -uint -get_wkb_of_default_point( - uint n_dims, - uchar* wkb, - uint len); - /*************************************************************//** Calculate minimal bounding rectangle (mbr) of the spatial object stored in "well-known binary representation" (wkb) format. -- cgit v1.2.1 From abbff37eb4f849532a01941c869db3384f772639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 3 Dec 2019 11:58:24 +0200 Subject: MDEV-13564 follow-up: Harden an assertion mlog_write_initial_log_record_low(): Do not allow the MLOG_TRUNCATE record to be written. --- storage/innobase/include/mtr0log.ic | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/mtr0log.ic b/storage/innobase/include/mtr0log.ic index b7ba92ff1a5..23a840d95a6 100644 --- a/storage/innobase/include/mtr0log.ic +++ b/storage/innobase/include/mtr0log.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -187,7 +187,6 @@ mlog_write_initial_log_record_low( || type == MLOG_FILE_CREATE2 || type == MLOG_FILE_RENAME2 || type == MLOG_INDEX_LOAD - || type == MLOG_TRUNCATE || type == MLOG_FILE_WRITE_CRYPT_DATA || mtr->is_named_space(space_id)); -- cgit v1.2.1 From 292015d486aa157422b43d99fabb5f81e6a382f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 9 Dec 2019 10:47:25 +0200 Subject: MDEV-21254 Remove unused keywords from the InnoDB SQL parser The InnoDB internal SQL parser, which is used for updating the InnoDB data dictionary tables (to be removed in MDEV-11655), persistent statistics (to be refactored in MDEV-15020) and fulltext indexes, implements some unused keywords and built-in functions: OUT BINARY BLOB INTEGER FLOAT SUM DISTINCT READ COMPACT BLOCK_SIZE TO_CHAR TO_NUMBER BINARY_TO_NUMBER REPLSTR SYSDATE PRINTF ASSERT RND RND_STR ROW_PRINTF UNSIGNED Also, procedures are never declared with parameters. Only one top-level procedure is declared and invoked at a time, and parameters are being passed via pars_info_t. --- storage/innobase/include/pars0grm.h | 158 ++++++++++++++++------------------- storage/innobase/include/pars0pars.h | 35 +------- 2 files changed, 73 insertions(+), 120 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/pars0grm.h b/storage/innobase/include/pars0grm.h index 90a7468bc9a..58d424abfdc 100644 --- a/storage/innobase/include/pars0grm.h +++ b/storage/innobase/include/pars0grm.h @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.4.2. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,6 +31,9 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + #ifndef YY_YY_PARS0GRM_TAB_H_INCLUDED # define YY_YY_PARS0GRM_TAB_H_INCLUDED /* Debug traces. */ @@ -58,91 +62,71 @@ extern int yydebug; PARS_NE_TOKEN = 268, PARS_PROCEDURE_TOKEN = 269, PARS_IN_TOKEN = 270, - PARS_OUT_TOKEN = 271, - PARS_BINARY_TOKEN = 272, - PARS_BLOB_TOKEN = 273, - PARS_INT_TOKEN = 274, - PARS_FLOAT_TOKEN = 275, - PARS_CHAR_TOKEN = 276, - PARS_IS_TOKEN = 277, - PARS_BEGIN_TOKEN = 278, - PARS_END_TOKEN = 279, - PARS_IF_TOKEN = 280, - PARS_THEN_TOKEN = 281, - PARS_ELSE_TOKEN = 282, - PARS_ELSIF_TOKEN = 283, - PARS_LOOP_TOKEN = 284, - PARS_WHILE_TOKEN = 285, - PARS_RETURN_TOKEN = 286, - PARS_SELECT_TOKEN = 287, - PARS_SUM_TOKEN = 288, - PARS_COUNT_TOKEN = 289, - PARS_DISTINCT_TOKEN = 290, - PARS_FROM_TOKEN = 291, - PARS_WHERE_TOKEN = 292, - PARS_FOR_TOKEN = 293, - PARS_DDOT_TOKEN = 294, - PARS_READ_TOKEN = 295, - PARS_ORDER_TOKEN = 296, - PARS_BY_TOKEN = 297, - PARS_ASC_TOKEN = 298, - PARS_DESC_TOKEN = 299, - PARS_INSERT_TOKEN = 300, - PARS_INTO_TOKEN = 301, - PARS_VALUES_TOKEN = 302, - PARS_UPDATE_TOKEN = 303, - PARS_SET_TOKEN = 304, - PARS_DELETE_TOKEN = 305, - PARS_CURRENT_TOKEN = 306, - PARS_OF_TOKEN = 307, - PARS_CREATE_TOKEN = 308, - PARS_TABLE_TOKEN = 309, - PARS_INDEX_TOKEN = 310, - PARS_UNIQUE_TOKEN = 311, - PARS_CLUSTERED_TOKEN = 312, - PARS_ON_TOKEN = 313, - PARS_ASSIGN_TOKEN = 314, - PARS_DECLARE_TOKEN = 315, - PARS_CURSOR_TOKEN = 316, - PARS_SQL_TOKEN = 317, - PARS_OPEN_TOKEN = 318, - PARS_FETCH_TOKEN = 319, - PARS_CLOSE_TOKEN = 320, - PARS_NOTFOUND_TOKEN = 321, - PARS_TO_CHAR_TOKEN = 322, - PARS_TO_NUMBER_TOKEN = 323, - PARS_TO_BINARY_TOKEN = 324, - PARS_BINARY_TO_NUMBER_TOKEN = 325, - PARS_SUBSTR_TOKEN = 326, - PARS_REPLSTR_TOKEN = 327, - PARS_CONCAT_TOKEN = 328, - PARS_INSTR_TOKEN = 329, - PARS_LENGTH_TOKEN = 330, - PARS_SYSDATE_TOKEN = 331, - PARS_PRINTF_TOKEN = 332, - PARS_ASSERT_TOKEN = 333, - PARS_RND_TOKEN = 334, - PARS_RND_STR_TOKEN = 335, - PARS_ROW_PRINTF_TOKEN = 336, - PARS_COMMIT_TOKEN = 337, - PARS_ROLLBACK_TOKEN = 338, - PARS_WORK_TOKEN = 339, - PARS_UNSIGNED_TOKEN = 340, - PARS_EXIT_TOKEN = 341, - PARS_FUNCTION_TOKEN = 342, - PARS_LOCK_TOKEN = 343, - PARS_SHARE_TOKEN = 344, - PARS_MODE_TOKEN = 345, - PARS_LIKE_TOKEN = 346, - PARS_LIKE_TOKEN_EXACT = 347, - PARS_LIKE_TOKEN_PREFIX = 348, - PARS_LIKE_TOKEN_SUFFIX = 349, - PARS_LIKE_TOKEN_SUBSTR = 350, - PARS_TABLE_NAME_TOKEN = 351, - PARS_COMPACT_TOKEN = 352, - PARS_BLOCK_SIZE_TOKEN = 353, - PARS_BIGINT_TOKEN = 354, - NEG = 355 + PARS_INT_TOKEN = 271, + PARS_CHAR_TOKEN = 272, + PARS_IS_TOKEN = 273, + PARS_BEGIN_TOKEN = 274, + PARS_END_TOKEN = 275, + PARS_IF_TOKEN = 276, + PARS_THEN_TOKEN = 277, + PARS_ELSE_TOKEN = 278, + PARS_ELSIF_TOKEN = 279, + PARS_LOOP_TOKEN = 280, + PARS_WHILE_TOKEN = 281, + PARS_RETURN_TOKEN = 282, + PARS_SELECT_TOKEN = 283, + PARS_COUNT_TOKEN = 284, + PARS_FROM_TOKEN = 285, + PARS_WHERE_TOKEN = 286, + PARS_FOR_TOKEN = 287, + PARS_DDOT_TOKEN = 288, + PARS_ORDER_TOKEN = 289, + PARS_BY_TOKEN = 290, + PARS_ASC_TOKEN = 291, + PARS_DESC_TOKEN = 292, + PARS_INSERT_TOKEN = 293, + PARS_INTO_TOKEN = 294, + PARS_VALUES_TOKEN = 295, + PARS_UPDATE_TOKEN = 296, + PARS_SET_TOKEN = 297, + PARS_DELETE_TOKEN = 298, + PARS_CURRENT_TOKEN = 299, + PARS_OF_TOKEN = 300, + PARS_CREATE_TOKEN = 301, + PARS_TABLE_TOKEN = 302, + PARS_INDEX_TOKEN = 303, + PARS_UNIQUE_TOKEN = 304, + PARS_CLUSTERED_TOKEN = 305, + PARS_ON_TOKEN = 306, + PARS_ASSIGN_TOKEN = 307, + PARS_DECLARE_TOKEN = 308, + PARS_CURSOR_TOKEN = 309, + PARS_SQL_TOKEN = 310, + PARS_OPEN_TOKEN = 311, + PARS_FETCH_TOKEN = 312, + PARS_CLOSE_TOKEN = 313, + PARS_NOTFOUND_TOKEN = 314, + PARS_TO_BINARY_TOKEN = 315, + PARS_SUBSTR_TOKEN = 316, + PARS_CONCAT_TOKEN = 317, + PARS_INSTR_TOKEN = 318, + PARS_LENGTH_TOKEN = 319, + PARS_COMMIT_TOKEN = 320, + PARS_ROLLBACK_TOKEN = 321, + PARS_WORK_TOKEN = 322, + PARS_EXIT_TOKEN = 323, + PARS_FUNCTION_TOKEN = 324, + PARS_LOCK_TOKEN = 325, + PARS_SHARE_TOKEN = 326, + PARS_MODE_TOKEN = 327, + PARS_LIKE_TOKEN = 328, + PARS_LIKE_TOKEN_EXACT = 329, + PARS_LIKE_TOKEN_PREFIX = 330, + PARS_LIKE_TOKEN_SUFFIX = 331, + PARS_LIKE_TOKEN_SUBSTR = 332, + PARS_TABLE_NAME_TOKEN = 333, + PARS_BIGINT_TOKEN = 334, + NEG = 335 }; #endif diff --git a/storage/innobase/include/pars0pars.h b/storage/innobase/include/pars0pars.h index f74d3700eca..f54c50e5b85 100644 --- a/storage/innobase/include/pars0pars.h +++ b/storage/innobase/include/pars0pars.h @@ -48,29 +48,15 @@ extern int yydebug; NOT re-entrant */ extern sym_tab_t* pars_sym_tab_global; -extern pars_res_word_t pars_to_char_token; -extern pars_res_word_t pars_to_number_token; extern pars_res_word_t pars_to_binary_token; -extern pars_res_word_t pars_binary_to_number_token; extern pars_res_word_t pars_substr_token; -extern pars_res_word_t pars_replstr_token; extern pars_res_word_t pars_concat_token; extern pars_res_word_t pars_length_token; extern pars_res_word_t pars_instr_token; -extern pars_res_word_t pars_sysdate_token; -extern pars_res_word_t pars_printf_token; -extern pars_res_word_t pars_assert_token; -extern pars_res_word_t pars_rnd_token; -extern pars_res_word_t pars_rnd_str_token; extern pars_res_word_t pars_count_token; -extern pars_res_word_t pars_sum_token; -extern pars_res_word_t pars_distinct_token; -extern pars_res_word_t pars_binary_token; -extern pars_res_word_t pars_blob_token; extern pars_res_word_t pars_int_token; extern pars_res_word_t pars_bigint_token; extern pars_res_word_t pars_char_token; -extern pars_res_word_t pars_float_token; extern pars_res_word_t pars_update_token; extern pars_res_word_t pars_asc_token; extern pars_res_word_t pars_desc_token; @@ -236,17 +222,6 @@ pars_insert_statement( que_node_t* values_list, /*!< in: value expression list or NULL */ sel_node_t* select); /*!< in: select condition or NULL */ /*********************************************************************//** -Parses a procedure parameter declaration. -@return own: symbol table node of type SYM_VAR */ -sym_node_t* -pars_parameter_declaration( -/*=======================*/ - sym_node_t* node, /*!< in: symbol table node allocated for the - id of the parameter */ - ulint param_type, - /*!< in: PARS_INPUT or PARS_OUTPUT */ - pars_res_word_t* type); /*!< in: pointer to a type token */ -/*********************************************************************//** Parses an elsif element. @return elsif node */ elsif_node_t* @@ -358,8 +333,6 @@ pars_column_def( pars_res_word_t* type, /*!< in: data type */ sym_node_t* len, /*!< in: length of column, or NULL */ - void* is_unsigned, /*!< in: if not NULL, column - is of type UNSIGNED. */ void* is_not_null); /*!< in: if not NULL, column is of type NOT NULL. */ /*********************************************************************//** @@ -370,9 +343,7 @@ pars_create_table( /*==============*/ sym_node_t* table_sym, /*!< in: table name node in the symbol table */ - sym_node_t* column_defs, /*!< in: list of column names */ - sym_node_t* compact, /* in: non-NULL if COMPACT table. */ - sym_node_t* block_size); /* in: block size (can be NULL) */ + sym_node_t* column_defs); /*!< in: list of column names */ /*********************************************************************//** Parses an index creation operation. @return index create subgraph */ @@ -394,7 +365,6 @@ pars_procedure_definition( /*======================*/ sym_node_t* sym_node, /*!< in: procedure id node in the symbol table */ - sym_node_t* param_list, /*!< in: parameter declaration list */ que_node_t* stat_list); /*!< in: statement list */ /*************************************************************//** @@ -672,7 +642,6 @@ struct proc_node_t{ que_common_t common; /*!< type: QUE_NODE_PROC */ sym_node_t* proc_id; /*!< procedure name symbol in the symbol table of this same procedure */ - sym_node_t* param_list; /*!< input and output parameters */ que_node_t* stat_list; /*!< statement list */ sym_tab_t* sym_tab; /*!< symbol table of this procedure */ }; @@ -747,7 +716,7 @@ struct col_assign_node_t{ #define PARS_FUNC_LOGICAL 2 /*!< AND, OR, NOT */ #define PARS_FUNC_CMP 3 /*!< comparison operators */ #define PARS_FUNC_PREDEFINED 4 /*!< TO_NUMBER, SUBSTR, ... */ -#define PARS_FUNC_AGGREGATE 5 /*!< COUNT, DISTINCT, SUM */ +#define PARS_FUNC_AGGREGATE 5 /*!< COUNT */ #define PARS_FUNC_OTHER 6 /*!< these are not real functions, e.g., := */ /* @} */ -- cgit v1.2.1 From 51fc8ab73e3ee9712d1128fefc9831dcf891a3b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 9 Dec 2019 12:17:12 +0200 Subject: MDEV-21256: Reduce the use of ut_rnd_gen_next_ulint() ut_rnd_set_seed(): Unused function; remove. ut_rnd_gen(): Renamed from page_cur_lcg_prng(). ut_rnd_current: The internal state of ut_rnd_gen(). page_cur_open_on_rnd_user_rec(): Replace linear search with page_rec_get_nth(). --- storage/innobase/include/ut0rnd.h | 54 ++++++++++++++++++-------------------- storage/innobase/include/ut0rnd.ic | 13 +-------- 2 files changed, 27 insertions(+), 40 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/ut0rnd.h b/storage/innobase/include/ut0rnd.h index b6d4d4abbd2..56b4a6159c1 100644 --- a/storage/innobase/include/ut0rnd.h +++ b/storage/innobase/include/ut0rnd.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -27,37 +28,34 @@ Created 1/20/1994 Heikki Tuuri #define ut0rnd_h #include "ut0byte.h" +#include #ifndef UNIV_INNOCHECKSUM -/** The 'character code' for end of field or string (used -in folding records */ -#define UT_END_OF_FIELD 257 +/** Seed value of ut_rnd_gen() */ +extern uint64_t ut_rnd_current; + +/** @return a pseudo-random 64-bit number */ +inline uint64_t ut_rnd_gen() +{ + /* + This is a linear congruential pseudo random number generator. + The formula and the constants + being used are: + X[n+1] = (a * X[n] + c) mod m + where: + X[0] = my_interval_timer() + a = 1103515245 (3^5 * 5 * 7 * 129749) + c = 12345 (3 * 5 * 823) + m = 18446744073709551616 (1<<64), implicit */ + + if (UNIV_UNLIKELY(!ut_rnd_current)) { + ut_rnd_current = my_interval_timer(); + } + + ut_rnd_current = 1103515245 * ut_rnd_current + 12345; + return ut_rnd_current; +} -/********************************************************//** -This is used to set the random number seed. */ -UNIV_INLINE -void -ut_rnd_set_seed( -/*============*/ - ulint seed); /*!< in: seed */ -/********************************************************//** -The following function generates a series of 'random' ulint integers. -@return the next 'random' number */ -UNIV_INLINE -ulint -ut_rnd_gen_next_ulint( -/*==================*/ - ulint rnd); /*!< in: the previous random number value */ -/*********************************************************//** -The following function generates 'random' ulint integers which -enumerate the value space (let there be N of them) of ulint integers -in a pseudo-random fashion. Note that the same integer is repeated -always after N calls to the generator. -@return the 'random' number */ -UNIV_INLINE -ulint -ut_rnd_gen_ulint(void); -/*==================*/ /********************************************************//** Generates a random integer from a given interval. @return the 'random' number */ diff --git a/storage/innobase/include/ut0rnd.ic b/storage/innobase/include/ut0rnd.ic index 0003c42baad..8b7ea5fe1e4 100644 --- a/storage/innobase/include/ut0rnd.ic +++ b/storage/innobase/include/ut0rnd.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -42,17 +42,6 @@ Created 5/30/1994 Heikki Tuuri /** Seed value of ut_rnd_gen_ulint() */ extern ulint ut_rnd_ulint_counter; -/********************************************************//** -This is used to set the random number seed. */ -UNIV_INLINE -void -ut_rnd_set_seed( -/*============*/ - ulint seed) /*!< in: seed */ -{ - ut_rnd_ulint_counter = seed; -} - /********************************************************//** The following function generates a series of 'random' ulint integers. @return the next 'random' number */ -- cgit v1.2.1 From d146e3dcfe3d4500eced3e097212b485659ec741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 10 Dec 2019 11:14:57 +0200 Subject: MDEV-21256: Simplify ut_rnd_interval() ut_rnd_interval(): Remove the first parameter, which was mostly passed as 0. Implement as a simple wrapper around ut_rnd_gen(). Trivially return 0 if the size of the interval is smaller than 2. ut_rnd_ulint_counter, ut_rnd_gen_next_ulint(), ut_rnd_gen_ulint(): Remove. --- storage/innobase/include/ib0mutex.h | 6 +-- storage/innobase/include/ut0rnd.h | 14 +++---- storage/innobase/include/ut0rnd.ic | 81 ------------------------------------- 3 files changed, 8 insertions(+), 93 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/ib0mutex.h b/storage/innobase/include/ib0mutex.h index e7f5ca2b44f..6c04563b97a 100644 --- a/storage/innobase/include/ib0mutex.h +++ b/storage/innobase/include/ib0mutex.h @@ -225,7 +225,7 @@ struct TTASFutexMutex { return; } - ut_delay(ut_rnd_interval(0, max_delay)); + ut_delay(ut_rnd_interval(max_delay)); } for (n_waits= 0;; n_waits++) { @@ -362,7 +362,7 @@ struct TTASMutex { uint32_t n_spins = 0; while (!try_lock()) { - ut_delay(ut_rnd_interval(0, max_delay)); + ut_delay(ut_rnd_interval(max_delay)); if (++n_spins == max_spins) { os_thread_yield(); max_spins+= step; @@ -516,7 +516,7 @@ struct TTASEventMutex { sync_array_wait_event(sync_arr, cell); } } else { - ut_delay(ut_rnd_interval(0, max_delay)); + ut_delay(ut_rnd_interval(max_delay)); } } diff --git a/storage/innobase/include/ut0rnd.h b/storage/innobase/include/ut0rnd.h index 56b4a6159c1..fcab293b3b0 100644 --- a/storage/innobase/include/ut0rnd.h +++ b/storage/innobase/include/ut0rnd.h @@ -56,15 +56,11 @@ inline uint64_t ut_rnd_gen() return ut_rnd_current; } -/********************************************************//** -Generates a random integer from a given interval. -@return the 'random' number */ -UNIV_INLINE -ulint -ut_rnd_interval( -/*============*/ - ulint low, /*!< in: low limit; can generate also this value */ - ulint high); /*!< in: high limit; can generate also this value */ +/** @return a random number between 0 and n-1, inclusive */ +inline ulint ut_rnd_interval(ulint n) +{ + return n > 1 ? static_cast(ut_rnd_gen() % n) : 0; +} /*******************************************************//** The following function generates a hash value for a ulint integer diff --git a/storage/innobase/include/ut0rnd.ic b/storage/innobase/include/ut0rnd.ic index 8b7ea5fe1e4..c0105160a42 100644 --- a/storage/innobase/include/ut0rnd.ic +++ b/storage/innobase/include/ut0rnd.ic @@ -29,87 +29,6 @@ Created 5/30/1994 Heikki Tuuri #ifndef UNIV_INNOCHECKSUM -#define UT_RND1 151117737 -#define UT_RND2 119785373 -#define UT_RND3 85689495 -#define UT_RND4 76595339 -#define UT_SUM_RND2 98781234 -#define UT_SUM_RND3 126792457 -#define UT_SUM_RND4 63498502 -#define UT_XOR_RND1 187678878 -#define UT_XOR_RND2 143537923 - -/** Seed value of ut_rnd_gen_ulint() */ -extern ulint ut_rnd_ulint_counter; - -/********************************************************//** -The following function generates a series of 'random' ulint integers. -@return the next 'random' number */ -UNIV_INLINE -ulint -ut_rnd_gen_next_ulint( -/*==================*/ - ulint rnd) /*!< in: the previous random number value */ -{ - ulint n_bits; - - n_bits = 8 * sizeof(ulint); - - rnd = UT_RND2 * rnd + UT_SUM_RND3; - rnd = UT_XOR_RND1 ^ rnd; - rnd = (rnd << 20) + (rnd >> (n_bits - 20)); - rnd = UT_RND3 * rnd + UT_SUM_RND4; - rnd = UT_XOR_RND2 ^ rnd; - rnd = (rnd << 20) + (rnd >> (n_bits - 20)); - rnd = UT_RND1 * rnd + UT_SUM_RND2; - - return(rnd); -} - -/********************************************************//** -The following function generates 'random' ulint integers which -enumerate the value space of ulint integers in a pseudo random -fashion. Note that the same integer is repeated always after -2 to power 32 calls to the generator (if ulint is 32-bit). -@return the 'random' number */ -UNIV_INLINE -ulint -ut_rnd_gen_ulint(void) -/*==================*/ -{ - ulint rnd; - - ut_rnd_ulint_counter = UT_RND1 * ut_rnd_ulint_counter + UT_RND2; - - rnd = ut_rnd_gen_next_ulint(ut_rnd_ulint_counter); - - return(rnd); -} - -/********************************************************//** -Generates a random integer from a given interval. -@return the 'random' number */ -UNIV_INLINE -ulint -ut_rnd_interval( -/*============*/ - ulint low, /*!< in: low limit; can generate also this value */ - ulint high) /*!< in: high limit; can generate also this value */ -{ - ulint rnd; - - ut_ad(high >= low); - - if (low == high) { - - return(low); - } - - rnd = ut_rnd_gen_ulint(); - - return(low + (rnd % (high - low))); -} - /*******************************************************//** The following function generates a hash value for a ulint integer to a hash table of size table_size, which should be a prime -- cgit v1.2.1 From b1f2d3a8c8d9bd10e088111ca966b3f7be35df35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 10 Dec 2019 11:20:26 +0200 Subject: MDEV-21256: Replace the 64-bit LCG with a 32-bit Galois LFSR We should not need anywhere near 32 bits of entropy, so we might just limit ourselves to a 32-bit random number generator. Also, it might be cheaper to use exclusive-or, bit shifting and conditional jumps, instead of multiplication and addition. We use relaxed atomic operations on the global random number generator state in order in an attempt to silence any warnings about race conditions. There is an obvious race condition between the load and store in ut_rnd_gen(), but we do not think that it matters much that the state of the random number generator could 'stutter'. This change seems makes the 'uncompress_ops' nondeterministic in innodb_zip.cmp_per_index after the restart. It looks like there is an inherent race condition in the test, because the table could be opened for InnoDB statistics recalculation already before innodb_cmp_per_index_enabled was set. We might end up having uncompress_ops anywhere between 0 and 9, or perhaps even more. Let us remove that part of the test. --- storage/innobase/include/ut0rnd.h | 49 +++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/ut0rnd.h b/storage/innobase/include/ut0rnd.h index fcab293b3b0..9af8687bfd0 100644 --- a/storage/innobase/include/ut0rnd.h +++ b/storage/innobase/include/ut0rnd.h @@ -32,28 +32,37 @@ Created 1/20/1994 Heikki Tuuri #ifndef UNIV_INNOCHECKSUM /** Seed value of ut_rnd_gen() */ -extern uint64_t ut_rnd_current; +extern int32 ut_rnd_current; -/** @return a pseudo-random 64-bit number */ -inline uint64_t ut_rnd_gen() +/** @return a pseudo-random 32-bit number */ +inline uint32_t ut_rnd_gen() { - /* - This is a linear congruential pseudo random number generator. - The formula and the constants - being used are: - X[n+1] = (a * X[n] + c) mod m - where: - X[0] = my_interval_timer() - a = 1103515245 (3^5 * 5 * 7 * 129749) - c = 12345 (3 * 5 * 823) - m = 18446744073709551616 (1<<64), implicit */ - - if (UNIV_UNLIKELY(!ut_rnd_current)) { - ut_rnd_current = my_interval_timer(); - } - - ut_rnd_current = 1103515245 * ut_rnd_current + 12345; - return ut_rnd_current; + /* This is a Galois linear-feedback shift register. + https://en.wikipedia.org/wiki/Linear-feedback_shift_register#Galois_LFSRs + The generating primitive Galois Field polynomial is the Castagnoli + polynomial that was made popular by CRC-32C: + x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+ + x^19+x^18+x^14+x^13+x^11+x^10+x^9+x^8+x^6+1 */ + const uint32_t crc32c= 0x1edc6f41; + + uint32_t rnd= my_atomic_load32_explicit(&ut_rnd_current, + MY_MEMORY_ORDER_RELAXED); + + if (UNIV_UNLIKELY(rnd == 0)) + { + rnd= static_cast(my_interval_timer()); + if (!rnd) rnd= 1; + } + else + { + bool lsb= rnd & 1; + rnd>>= 1; + if (lsb) + rnd^= crc32c; + } + + my_atomic_store32_explicit(&ut_rnd_current, rnd, MY_MEMORY_ORDER_RELAXED); + return rnd; } /** @return a random number between 0 and n-1, inclusive */ -- cgit v1.2.1 From 41e6a154ece1c7d49becac0ccaa72f507686d298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 10 Dec 2019 11:23:46 +0200 Subject: MDEV-14482 - Cache line contention on ut_rnd_interval() InnoDB RNG maintains global state, causing otherwise unnecessary bus traffic. Even worse, this is cross-mutex traffic. That is, different mutexes suffer from contention. Fixed delay of 4 was verified to give best throughput by OLTP update index and read-write benchmarks on Intel Broadwell (2/20/40) and ARM (1/46/46). This is a backport of ce0479006523bc72ed6abb703bd1f87ff256fd8a from MariaDB Server 10.3. --- storage/innobase/include/ib0mutex.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/ib0mutex.h b/storage/innobase/include/ib0mutex.h index 6c04563b97a..a7289777e00 100644 --- a/storage/innobase/include/ib0mutex.h +++ b/storage/innobase/include/ib0mutex.h @@ -225,7 +225,7 @@ struct TTASFutexMutex { return; } - ut_delay(ut_rnd_interval(max_delay)); + ut_delay(max_delay); } for (n_waits= 0;; n_waits++) { @@ -362,7 +362,7 @@ struct TTASMutex { uint32_t n_spins = 0; while (!try_lock()) { - ut_delay(ut_rnd_interval(max_delay)); + ut_delay(max_delay); if (++n_spins == max_spins) { os_thread_yield(); max_spins+= step; @@ -516,7 +516,7 @@ struct TTASEventMutex { sync_array_wait_event(sync_arr, cell); } } else { - ut_delay(ut_rnd_interval(max_delay)); + ut_delay(max_delay); } } -- cgit v1.2.1 From f0aa073f2bf3d8d85b3d028df89cdb4cdfc4002d Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Mon, 4 Nov 2019 22:30:12 +0300 Subject: MDEV-20950 Reduce size of record offsets offset_t: this is a type which represents one record offset. It's unsigned short int. a lot of functions: replace ulint with offset_t btr_pcur_restore_position_func(), page_validate(), row_ins_scan_sec_index_for_duplicate(), row_upd_clust_rec_by_insert_inherit_func(), row_vers_impl_x_locked_low(), trx_undo_prev_version_build(): allocate record offsets on the stack instead of waiting for rec_get_offsets() to allocate it from mem_heap_t. So, reducing memory allocations. RECORD_OFFSET, INDEX_OFFSET: now it's less convenient to store pointers in offset_t* array. One pointer occupies now several offset_t. And those constant are start indexes into array to places where to store pointer values REC_OFFS_HEADER_SIZE: adjusted for the new reality REC_OFFS_NORMAL_SIZE: increase size from 100 to 300 which means less heap allocations. And sizeof(offset_t[REC_OFFS_NORMAL_SIZE]) now is 600 bytes which is smaller than previous 800 bytes. REC_OFFS_SEC_INDEX_SIZE: adjusted for the new reality rem0rec.h, rem0rec.ic, rem0rec.cc: various arguments, return values and local variables types were changed to fix numerous integer conversions issues. enum field_type_t: offset types concept was introduces which replaces old offset flags stuff. Like in earlier version, 2 upper bits are used to store offset type. And this enum represents those types. REC_OFFS_SQL_NULL, REC_OFFS_MASK: removed get_type(), set_type(), get_value(), combine(): these are convenience functions to work with offsets and it's types rec_offs_base()[0]: still uses an old scheme with flags REC_OFFS_COMPACT and REC_OFFS_EXTERNAL rec_offs_base()[i]: these have type offset_t now. Two upper bits contains type. --- storage/innobase/include/btr0btr.h | 7 +- storage/innobase/include/btr0btr.ic | 2 +- storage/innobase/include/btr0bulk.h | 5 +- storage/innobase/include/btr0cur.h | 25 +++--- storage/innobase/include/dict0mem.h | 4 - storage/innobase/include/gis0rtree.h | 21 ++--- storage/innobase/include/gis0rtree.ic | 2 +- storage/innobase/include/handler0alter.h | 4 +- storage/innobase/include/lock0lock.h | 12 +-- storage/innobase/include/lock0priv.h | 3 +- storage/innobase/include/lock0priv.ic | 2 +- storage/innobase/include/page0cur.h | 15 ++-- storage/innobase/include/page0cur.ic | 4 +- storage/innobase/include/page0page.h | 7 +- storage/innobase/include/page0page.ic | 2 +- storage/innobase/include/page0types.h | 3 +- storage/innobase/include/page0zip.h | 9 +- storage/innobase/include/rem0cmp.h | 24 +++--- storage/innobase/include/rem0cmp.ic | 4 +- storage/innobase/include/rem0rec.h | 137 ++++++++++++++++++++----------- storage/innobase/include/rem0rec.ic | 108 ++++++++++-------------- storage/innobase/include/rem0types.h | 4 + storage/innobase/include/row0ftsort.h | 3 +- storage/innobase/include/row0log.h | 8 +- storage/innobase/include/row0merge.h | 2 +- storage/innobase/include/row0row.h | 18 ++-- storage/innobase/include/row0row.ic | 8 +- storage/innobase/include/row0upd.h | 13 +-- storage/innobase/include/row0upd.ic | 2 +- storage/innobase/include/row0vers.h | 6 +- storage/innobase/include/trx0rec.h | 4 +- 31 files changed, 253 insertions(+), 215 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h index ee4e522cf49..c5ae633016a 100644 --- a/storage/innobase/include/btr0btr.h +++ b/storage/innobase/include/btr0btr.h @@ -30,6 +30,7 @@ Created 6/2/1994 Heikki Tuuri #include "dict0dict.h" #include "data0data.h" +#include "rem0types.h" #include "page0cur.h" #include "btr0types.h" #include "gis0type.h" @@ -305,7 +306,7 @@ ulint btr_node_ptr_get_child_page_no( /*===========================*/ const rec_t* rec, /*!< in: node pointer record */ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((warn_unused_result)); /** Create the root node for a new index tree. @@ -392,7 +393,7 @@ btr_root_raise_and_insert( on the root page; when the function returns, the cursor is positioned on the predecessor of the inserted record */ - ulint** offsets,/*!< out: offsets on inserted record */ + offset_t** offsets,/*!< out: offsets on inserted record */ mem_heap_t** heap, /*!< in/out: pointer to memory heap that can be emptied, or NULL */ const dtuple_t* tuple, /*!< in: tuple to insert */ @@ -475,7 +476,7 @@ btr_page_split_and_insert( btr_cur_t* cursor, /*!< in: cursor at which to insert; when the function returns, the cursor is positioned on the predecessor of the inserted record */ - ulint** offsets,/*!< out: offsets on inserted record */ + offset_t** offsets,/*!< out: offsets on inserted record */ mem_heap_t** heap, /*!< in/out: pointer to memory heap that can be emptied, or NULL */ const dtuple_t* tuple, /*!< in: tuple to insert */ diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic index f4fcd9f4194..e5d0e805bd8 100644 --- a/storage/innobase/include/btr0btr.ic +++ b/storage/innobase/include/btr0btr.ic @@ -218,7 +218,7 @@ ulint btr_node_ptr_get_child_page_no( /*===========================*/ const rec_t* rec, /*!< in: node pointer record */ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ { const byte* field; ulint len; diff --git a/storage/innobase/include/btr0bulk.h b/storage/innobase/include/btr0bulk.h index a65f6901ce9..3dbc85cad6d 100644 --- a/storage/innobase/include/btr0bulk.h +++ b/storage/innobase/include/btr0bulk.h @@ -28,6 +28,7 @@ Created 03/11/2014 Shaohua Wang #define btr0bulk_h #include "dict0dict.h" +#include "rem0types.h" #include "page0cur.h" #include @@ -103,7 +104,7 @@ public: /** Insert a record in the page. @param[in] rec record @param[in] offsets record offsets */ - void insert(const rec_t* rec, ulint* offsets); + void insert(const rec_t* rec, offset_t* offsets); /** Mark end of insertion to the page. Scan all records to set page dirs, and set page header members. */ @@ -127,7 +128,7 @@ public: @param[in] big_rec external recrod @param[in] offsets record offsets @return error code */ - dberr_t storeExt(const big_rec_t* big_rec, ulint* offsets); + dberr_t storeExt(const big_rec_t* big_rec, offset_t* offsets); /** Get node pointer @return node pointer */ diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h index 4d67833db70..0f2fd48004b 100644 --- a/storage/innobase/include/btr0cur.h +++ b/storage/innobase/include/btr0cur.h @@ -30,6 +30,7 @@ Created 10/16/1994 Heikki Tuuri #include "dict0dict.h" #include "page0cur.h" #include "btr0types.h" +#include "rem0types.h" #include "gis0type.h" /** Mode flags for btr_cur operations; these can be ORed */ @@ -242,7 +243,7 @@ btr_cur_optimistic_insert( specified */ btr_cur_t* cursor, /*!< in: cursor on page after which to insert; cursor stays valid */ - ulint** offsets,/*!< out: offsets on *rec */ + offset_t** offsets,/*!< out: offsets on *rec */ mem_heap_t** heap, /*!< in/out: pointer to memory heap */ dtuple_t* entry, /*!< in/out: entry to insert */ rec_t** rec, /*!< out: pointer to inserted record if @@ -278,7 +279,7 @@ btr_cur_pessimistic_insert( insertion will certainly succeed */ btr_cur_t* cursor, /*!< in: cursor after which to insert; cursor stays valid */ - ulint** offsets,/*!< out: offsets on *rec */ + offset_t** offsets,/*!< out: offsets on *rec */ mem_heap_t** heap, /*!< in/out: pointer to memory heap that can be emptied */ dtuple_t* entry, /*!< in/out: entry to insert */ @@ -312,7 +313,7 @@ btr_cur_update_alloc_zip_func( page_cur_t* cursor, /*!< in/out: B-tree page cursor */ dict_index_t* index, /*!< in: the index corresponding to cursor */ #ifdef UNIV_DEBUG - ulint* offsets,/*!< in/out: offsets of the cursor record */ + offset_t* offsets,/*!< in/out: offsets of the cursor record */ #endif /* UNIV_DEBUG */ ulint length, /*!< in: size needed */ bool create, /*!< in: true=delete-and-insert, @@ -339,7 +340,7 @@ btr_cur_update_in_place( btr_cur_t* cursor, /*!< in: cursor on the record to update; cursor stays valid and positioned on the same record */ - ulint* offsets,/*!< in/out: offsets on cursor->page_cur.rec */ + offset_t* offsets,/*!< in/out: offsets on cursor->page_cur.rec */ const upd_t* update, /*!< in: update vector */ ulint cmpl_info,/*!< in: compiler info on secondary index updates */ @@ -381,7 +382,7 @@ btr_cur_optimistic_update( btr_cur_t* cursor, /*!< in: cursor on the record to update; cursor stays valid and positioned on the same record */ - ulint** offsets,/*!< out: offsets on cursor->page_cur.rec */ + offset_t** offsets,/*!< out: offsets on cursor->page_cur.rec */ mem_heap_t** heap, /*!< in/out: pointer to NULL or memory heap */ const upd_t* update, /*!< in: update vector; this must also contain trx id and roll ptr fields */ @@ -408,7 +409,7 @@ btr_cur_pessimistic_update( btr_cur_t* cursor, /*!< in/out: cursor on the record to update; cursor may become invalid if *big_rec == NULL || !(flags & BTR_KEEP_POS_FLAG) */ - ulint** offsets,/*!< out: offsets on cursor->page_cur.rec */ + offset_t** offsets,/*!< out: offsets on cursor->page_cur.rec */ mem_heap_t** offsets_heap, /*!< in/out: pointer to memory heap that can be emptied */ @@ -440,7 +441,7 @@ btr_cur_del_mark_set_clust_rec( buf_block_t* block, /*!< in/out: buffer block of the record */ rec_t* rec, /*!< in/out: record */ dict_index_t* index, /*!< in: clustered index of the record */ - const ulint* offsets,/*!< in: rec_get_offsets(rec) */ + const offset_t* offsets,/*!< in: rec_get_offsets(rec) */ que_thr_t* thr, /*!< in: query thread */ const dtuple_t* entry, /*!< in: dtuple for the deleting record */ mtr_t* mtr) /*!< in/out: mini-transaction */ @@ -607,7 +608,7 @@ btr_estimate_number_of_different_key_vals( ulint btr_rec_get_externally_stored_len( const rec_t* rec, - const ulint* offsets); + const offset_t* offsets); /*******************************************************************//** Marks non-updated off-page fields as disowned by this record. The ownership @@ -621,7 +622,7 @@ btr_cur_disown_inherited_fields( part will be updated, or NULL */ rec_t* rec, /*!< in/out: record in a clustered index */ dict_index_t* index, /*!< in: index of the page */ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets,/*!< in: array returned by rec_get_offsets() */ const upd_t* update, /*!< in: update vector */ mtr_t* mtr) /*!< in/out: mini-transaction */ MY_ATTRIBUTE((nonnull(2,3,4,5,6))); @@ -660,7 +661,7 @@ btr_store_big_rec_extern_fields( btr_pcur_t* pcur, /*!< in/out: a persistent cursor. if btr_mtr is restarted, then this can be repositioned. */ - ulint* offsets, /*!< in/out: rec_get_offsets() on + offset_t* offsets, /*!< in/out: rec_get_offsets() on pcur. the "external storage" flags in offsets will correctly correspond to rec when this function returns */ @@ -691,7 +692,7 @@ btr_free_externally_stored_field( byte* field_ref, /*!< in/out: field reference */ const rec_t* rec, /*!< in: record containing field_ref, for page_zip_write_blob_ptr(), or NULL */ - const ulint* offsets, /*!< in: rec_get_offsets(rec, index), + const offset_t* offsets, /*!< in: rec_get_offsets(rec, index), or NULL */ page_zip_des_t* page_zip, /*!< in: compressed page corresponding to rec, or NULL if rec == NULL */ @@ -748,7 +749,7 @@ protected by a lock or a page latch byte* btr_rec_copy_externally_stored_field( const rec_t* rec, - const ulint* offsets, + const offset_t* offsets, const page_size_t& page_size, ulint no, ulint* len, diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 0f96cd4e3ba..ed4bf073061 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -821,10 +821,6 @@ a certain index.*/ system clustered index when there is no primary key. */ const char innobase_index_reserve_name[] = "GEN_CLUST_INDEX"; -/* Estimated number of offsets in records (based on columns) -to start with. */ -#define OFFS_IN_REC_NORMAL_SIZE 100 - /** Data structure for an index. Most fields will be initialized to 0, NULL or FALSE in dict_mem_index_create(). */ struct dict_index_t{ diff --git a/storage/innobase/include/gis0rtree.h b/storage/innobase/include/gis0rtree.h index e5942b71c64..ffb6beb922b 100644 --- a/storage/innobase/include/gis0rtree.h +++ b/storage/innobase/include/gis0rtree.h @@ -28,6 +28,7 @@ Created 2013/03/27 Jimmy Yang and Allen Lai #define gis0rtree_h #include "btr0cur.h" +#include "rem0types.h" /* Whether MBR 'a' contains 'b' */ #define MBR_CONTAIN_CMP(a, b) \ @@ -90,7 +91,7 @@ rtr_page_split_and_insert( btr_cur_t* cursor, /*!< in/out: cursor at which to insert; when the function returns, the cursor is positioned on the predecessor of the inserted record */ - ulint** offsets,/*!< out: offsets on inserted record */ + offset_t** offsets,/*!< out: offsets on inserted record */ mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ const dtuple_t* tuple, /*!< in: tuple to insert */ ulint n_ext, /*!< in: number of externally stored columns */ @@ -152,7 +153,7 @@ rtr_rec_cal_increase( dtuple in some of the common fields, or which has an equal number or more fields than dtuple */ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets,/*!< in: array returned by rec_get_offsets() */ double* area); /*!< out: increased area */ /****************************************************************//** @@ -276,7 +277,7 @@ void rtr_get_mbr_from_rec( /*=================*/ const rec_t* rec, /*!< in: data tuple */ - const ulint* offsets,/*!< in: offsets array */ + const offset_t* offsets,/*!< in: offsets array */ rtr_mbr_t* mbr); /*!< out MBR */ /****************************************************************//** @@ -308,10 +309,10 @@ rtr_page_get_father( Returns the father block to a page. It is assumed that mtr holds an X or SX latch on the tree. @return rec_get_offsets() of the node pointer record */ -ulint* +offset_t* rtr_page_get_father_block( /*======================*/ - ulint* offsets,/*!< in: work area for the return value */ + offset_t* offsets,/*!< in: work area for the return value */ mem_heap_t* heap, /*!< in: memory heap to use */ dict_index_t* index, /*!< in: b-tree index */ buf_block_t* block, /*!< in: child page in the index */ @@ -418,8 +419,8 @@ rtr_merge_and_update_mbr( /*=====================*/ btr_cur_t* cursor, /*!< in/out: cursor */ btr_cur_t* cursor2, /*!< in: the other cursor */ - ulint* offsets, /*!< in: rec offsets */ - ulint* offsets2, /*!< in: rec offsets */ + offset_t* offsets, /*!< in: rec offsets */ + offset_t* offsets2, /*!< in: rec offsets */ page_t* child_page, /*!< in: the child page. */ buf_block_t* merge_block, /*!< in: page to merge */ buf_block_t* block, /*!< in: page be merged */ @@ -444,8 +445,8 @@ rtr_merge_mbr_changed( /*==================*/ btr_cur_t* cursor, /*!< in: cursor */ btr_cur_t* cursor2, /*!< in: the other cursor */ - ulint* offsets, /*!< in: rec offsets */ - ulint* offsets2, /*!< in: rec offsets */ + offset_t* offsets, /*!< in: rec offsets */ + offset_t* offsets2, /*!< in: rec offsets */ rtr_mbr_t* new_mbr, /*!< out: MBR to update */ buf_block_t* merge_block, /*!< in: page to merge */ buf_block_t* block, /*!< in: page be merged */ @@ -459,7 +460,7 @@ bool rtr_update_mbr_field( /*=================*/ btr_cur_t* cursor, /*!< in: cursor pointed to rec.*/ - ulint* offsets, /*!< in: offsets on rec. */ + offset_t* offsets, /*!< in: offsets on rec. */ btr_cur_t* cursor2, /*!< in/out: cursor pointed to rec that should be deleted. this cursor is for btr_compress to diff --git a/storage/innobase/include/gis0rtree.ic b/storage/innobase/include/gis0rtree.ic index b9ab2ea57e8..525acb7ecf0 100644 --- a/storage/innobase/include/gis0rtree.ic +++ b/storage/innobase/include/gis0rtree.ic @@ -40,7 +40,7 @@ rtr_page_cal_mbr( rec_t* rec; byte* field; ulint len; - ulint* offsets = NULL; + offset_t* offsets = NULL; double bmin, bmax; double* amin; double* amax; diff --git a/storage/innobase/include/handler0alter.h b/storage/innobase/include/handler0alter.h index 16616e3fc9c..2fdcedc5bb6 100644 --- a/storage/innobase/include/handler0alter.h +++ b/storage/innobase/include/handler0alter.h @@ -22,6 +22,8 @@ this program; if not, write to the Free Software Foundation, Inc., Smart ALTER TABLE *******************************************************/ +#include "rem0types.h" + /*************************************************************//** Copies an InnoDB record to table->record[0]. */ void @@ -30,7 +32,7 @@ innobase_rec_to_mysql( struct TABLE* table, /*!< in/out: MySQL table */ const rec_t* rec, /*!< in: record */ const dict_index_t* index, /*!< in: index */ - const ulint* offsets)/*!< in: rec_get_offsets( + const offset_t* offsets)/*!< in: rec_get_offsets( rec, index, ...) */ MY_ATTRIBUTE((nonnull)); diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 8369db8b879..21760d1dca9 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -317,7 +317,7 @@ lock_clust_rec_modify_check_and_lock( const rec_t* rec, /*!< in: record which should be modified */ dict_index_t* index, /*!< in: clustered index */ - const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ + const offset_t* offsets,/*!< in: rec_get_offsets(rec, index) */ que_thr_t* thr) /*!< in: query thread */ MY_ATTRIBUTE((warn_unused_result)); /*********************************************************************//** @@ -355,7 +355,7 @@ lock_sec_rec_read_check_and_lock( be read or passed over by a read cursor */ dict_index_t* index, /*!< in: secondary index */ - const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ + const offset_t* offsets,/*!< in: rec_get_offsets(rec, index) */ lock_mode mode, /*!< in: mode of the lock which the read cursor should set on records: LOCK_S or LOCK_X; the @@ -383,7 +383,7 @@ lock_clust_rec_read_check_and_lock( be read or passed over by a read cursor */ dict_index_t* index, /*!< in: clustered index */ - const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ + const offset_t* offsets,/*!< in: rec_get_offsets(rec, index) */ lock_mode mode, /*!< in: mode of the lock which the read cursor should set on records: LOCK_S or LOCK_X; the @@ -432,7 +432,7 @@ lock_clust_rec_cons_read_sees( const rec_t* rec, /*!< in: user record which should be read or passed over by a read cursor */ dict_index_t* index, /*!< in: clustered index */ - const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ + const offset_t* offsets,/*!< in: rec_get_offsets(rec, index) */ ReadView* view); /*!< in: consistent read view */ /*********************************************************************//** Checks that a non-clustered index record is seen in a consistent read. @@ -577,7 +577,7 @@ lock_report_trx_id_insanity( trx_id_t trx_id, /*!< in: trx id */ const rec_t* rec, /*!< in: user record */ dict_index_t* index, /*!< in: index */ - const ulint* offsets, /*!< in: rec_get_offsets(rec, index) */ + const offset_t* offsets, /*!< in: rec_get_offsets(rec, index) */ trx_id_t max_trx_id); /*!< in: trx_sys_get_max_trx_id() */ /*********************************************************************//** Prints info of locks for all transactions. @@ -803,7 +803,7 @@ lock_check_trx_id_sanity( trx_id_t trx_id, /*!< in: trx id */ const rec_t* rec, /*!< in: user record */ dict_index_t* index, /*!< in: index */ - const ulint* offsets) /*!< in: rec_get_offsets(rec, index) */ + const offset_t* offsets) /*!< in: rec_get_offsets(rec, index) */ MY_ATTRIBUTE((warn_unused_result)); /*******************************************************************//** Check if the transaction holds any locks on the sys tables diff --git a/storage/innobase/include/lock0priv.h b/storage/innobase/include/lock0priv.h index 9b80f593e30..5e00e1bb6f1 100644 --- a/storage/innobase/include/lock0priv.h +++ b/storage/innobase/include/lock0priv.h @@ -35,6 +35,7 @@ those functions in lock/ */ #endif #include "hash0hash.h" +#include "rem0types.h" #include "trx0trx.h" #ifndef UINT32_MAX @@ -468,7 +469,7 @@ lock_clust_rec_some_has_impl( /*=========================*/ const rec_t* rec, /*!< in: user record */ const dict_index_t* index, /*!< in: clustered index */ - const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */ + const offset_t* offsets)/*!< in: rec_get_offsets(rec, index) */ MY_ATTRIBUTE((warn_unused_result)); /*********************************************************************//** diff --git a/storage/innobase/include/lock0priv.ic b/storage/innobase/include/lock0priv.ic index 80a63271256..7062e3f7082 100644 --- a/storage/innobase/include/lock0priv.ic +++ b/storage/innobase/include/lock0priv.ic @@ -59,7 +59,7 @@ lock_clust_rec_some_has_impl( /*=========================*/ const rec_t* rec, /*!< in: user record */ const dict_index_t* index, /*!< in: clustered index */ - const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */ + const offset_t* offsets)/*!< in: rec_get_offsets(rec, index) */ { ut_ad(dict_index_is_clust(index)); ut_ad(page_rec_is_user_rec(rec)); diff --git a/storage/innobase/include/page0cur.h b/storage/innobase/include/page0cur.h index 18cc058ca6d..d91f1bd7ba7 100644 --- a/storage/innobase/include/page0cur.h +++ b/storage/innobase/include/page0cur.h @@ -29,6 +29,7 @@ Created 10/4/1994 Heikki Tuuri #include "buf0types.h" #include "page0page.h" +#include "rem0types.h" #include "rem0rec.h" #include "data0data.h" #include "mtr0mtr.h" @@ -151,7 +152,7 @@ page_cur_tuple_insert( page_cur_t* cursor, /*!< in/out: a page cursor */ const dtuple_t* tuple, /*!< in: pointer to a data tuple */ dict_index_t* index, /*!< in: record descriptor */ - ulint** offsets,/*!< out: offsets on *rec */ + offset_t** offsets,/*!< out: offsets on *rec */ mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ ulint n_ext, /*!< in: number of externally stored columns */ mtr_t* mtr, /*!< in: mini-transaction handle, or NULL */ @@ -178,7 +179,7 @@ page_cur_rec_insert( page_cur_t* cursor, /*!< in/out: a page cursor */ const rec_t* rec, /*!< in: record to insert */ dict_index_t* index, /*!< in: record descriptor */ - ulint* offsets,/*!< in/out: rec_get_offsets(rec, index) */ + offset_t* offsets,/*!< in/out: rec_get_offsets(rec, index) */ mtr_t* mtr); /*!< in: mini-transaction handle, or NULL */ /***********************************************************//** Inserts a record next to page cursor on an uncompressed page. @@ -192,7 +193,7 @@ page_cur_insert_rec_low( which the new record is inserted */ dict_index_t* index, /*!< in: record descriptor */ const rec_t* rec, /*!< in: pointer to a physical record */ - ulint* offsets,/*!< in/out: rec_get_offsets(rec, index) */ + offset_t* offsets,/*!< in/out: rec_get_offsets(rec, index) */ mtr_t* mtr) /*!< in: mini-transaction handle, or NULL */ MY_ATTRIBUTE((nonnull(1,2,3,4), warn_unused_result)); @@ -214,7 +215,7 @@ page_cur_insert_rec_zip( page_cur_t* cursor, /*!< in/out: page cursor */ dict_index_t* index, /*!< in: record descriptor */ const rec_t* rec, /*!< in: pointer to a physical record */ - ulint* offsets,/*!< in/out: rec_get_offsets(rec, index) */ + offset_t* offsets,/*!< in/out: rec_get_offsets(rec, index) */ mtr_t* mtr) /*!< in: mini-transaction handle, or NULL */ MY_ATTRIBUTE((nonnull(1,2,3,4), warn_unused_result)); /*************************************************************//** @@ -240,7 +241,7 @@ page_cur_delete_rec( /*================*/ page_cur_t* cursor, /*!< in/out: a page cursor */ const dict_index_t* index, /*!< in: record descriptor */ - const ulint* offsets,/*!< in: rec_get_offsets( + const offset_t* offsets,/*!< in: rec_get_offsets( cursor->rec, index) */ mtr_t* mtr); /*!< in: mini-transaction handle */ @@ -388,14 +389,14 @@ page_delete_rec( page_cur_t* pcur, /*!< in/out: page cursor on record to delete */ page_zip_des_t* page_zip,/*!< in: compressed page descriptor */ - const ulint* offsets);/*!< in: offsets for record */ + const offset_t* offsets);/*!< in: offsets for record */ /** Index page cursor */ struct page_cur_t{ const dict_index_t* index; rec_t* rec; /*!< pointer to a record on page */ - ulint* offsets; + offset_t* offsets; buf_block_t* block; /*!< pointer to the block containing rec */ }; diff --git a/storage/innobase/include/page0cur.ic b/storage/innobase/include/page0cur.ic index 7c5737613c4..982bda83c32 100644 --- a/storage/innobase/include/page0cur.ic +++ b/storage/innobase/include/page0cur.ic @@ -259,7 +259,7 @@ page_cur_tuple_insert( page_cur_t* cursor, /*!< in/out: a page cursor */ const dtuple_t* tuple, /*!< in: pointer to a data tuple */ dict_index_t* index, /*!< in: record descriptor */ - ulint** offsets,/*!< out: offsets on *rec */ + offset_t** offsets,/*!< out: offsets on *rec */ mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ ulint n_ext, /*!< in: number of externally stored columns */ mtr_t* mtr, /*!< in: mini-transaction handle, or NULL */ @@ -315,7 +315,7 @@ page_cur_rec_insert( page_cur_t* cursor, /*!< in/out: a page cursor */ const rec_t* rec, /*!< in: record to insert */ dict_index_t* index, /*!< in: record descriptor */ - ulint* offsets,/*!< in/out: rec_get_offsets(rec, index) */ + offset_t* offsets,/*!< in/out: rec_get_offsets(rec, index) */ mtr_t* mtr) /*!< in: mini-transaction handle, or NULL */ { if (buf_block_get_page_zip(cursor->block)) { diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index 2e3bae2d7ff..87de16f9abf 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -32,6 +32,7 @@ Created 2/2/1994 Heikki Tuuri #include "buf0buf.h" #include "data0data.h" #include "dict0dict.h" +#include "rem0types.h" #include "rem0rec.h" #endif /* !UNIV_INNOCHECKSUM*/ #include "fsp0fsp.h" @@ -919,7 +920,7 @@ page_mem_free( rec_t* rec, /*!< in: pointer to the (origin of) record */ const dict_index_t* index, /*!< in: index of rec */ - const ulint* offsets);/*!< in: array returned by + const offset_t* offsets);/*!< in: array returned by rec_get_offsets() */ /**********************************************************//** Create an uncompressed B-tree index page. @@ -1140,7 +1141,7 @@ void page_rec_print( /*===========*/ const rec_t* rec, /*!< in: physical record */ - const ulint* offsets);/*!< in: record descriptor */ + const offset_t* offsets);/*!< in: record descriptor */ # ifdef UNIV_BTR_PRINT /***************************************************************//** This is used to print the contents of the directory for @@ -1187,7 +1188,7 @@ ibool page_rec_validate( /*==============*/ const rec_t* rec, /*!< in: physical record */ - const ulint* offsets);/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets);/*!< in: array returned by rec_get_offsets() */ #ifdef UNIV_DEBUG /***************************************************************//** Checks that the first directory slot points to the infimum record and diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic index 6c12c43b237..6369932db1b 100644 --- a/storage/innobase/include/page0page.ic +++ b/storage/innobase/include/page0page.ic @@ -1004,7 +1004,7 @@ page_mem_free( rec_t* rec, /*!< in: pointer to the (origin of) record */ const dict_index_t* index, /*!< in: index of rec */ - const ulint* offsets) /*!< in: array returned by + const offset_t* offsets) /*!< in: array returned by rec_get_offsets() */ { rec_t* free; diff --git a/storage/innobase/include/page0types.h b/storage/innobase/include/page0types.h index 02d0cf29ec5..4debd639fa4 100644 --- a/storage/innobase/include/page0types.h +++ b/storage/innobase/include/page0types.h @@ -28,6 +28,7 @@ Created 2/2/1994 Heikki Tuuri #include "dict0types.h" #include "mtr0types.h" +#include "rem0types.h" #include @@ -184,7 +185,7 @@ page_zip_dir_delete( page_zip_des_t* page_zip,/*!< in/out: compressed page */ byte* rec, /*!< in: deleted record */ dict_index_t* index, /*!< in: index of rec */ - const ulint* offsets,/*!< in: rec_get_offsets(rec) */ + const offset_t* offsets,/*!< in: rec_get_offsets(rec) */ const byte* free) /*!< in: previous start of the free list */ MY_ATTRIBUTE((nonnull(1,2,3,4))); diff --git a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h index b4d4f0e980b..98a1422f496 100644 --- a/storage/innobase/include/page0zip.h +++ b/storage/innobase/include/page0zip.h @@ -47,6 +47,7 @@ Created June 2005 by Marko Makela #endif /* !UNIV_INNOCHECKSUM */ #include "buf0types.h" +#include "rem0types.h" #ifndef UNIV_INNOCHECKSUM #include "dict0types.h" @@ -287,7 +288,7 @@ page_zip_write_rec( page_zip_des_t* page_zip,/*!< in/out: compressed page */ const byte* rec, /*!< in: record being written */ dict_index_t* index, /*!< in: the index the record belongs to */ - const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ + const offset_t* offsets,/*!< in: rec_get_offsets(rec, index) */ ulint create) /*!< in: nonzero=insert, zero=update */ MY_ATTRIBUTE((nonnull)); @@ -312,7 +313,7 @@ page_zip_write_blob_ptr( const byte* rec, /*!< in/out: record whose data is being written */ dict_index_t* index, /*!< in: index of the page */ - const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ + const offset_t* offsets,/*!< in: rec_get_offsets(rec, index) */ ulint n, /*!< in: column index */ mtr_t* mtr); /*!< in: mini-transaction handle, or NULL if no logging is needed */ @@ -346,7 +347,7 @@ page_zip_write_trx_id_and_roll_ptr( /*===============================*/ page_zip_des_t* page_zip,/*!< in/out: compressed page */ byte* rec, /*!< in/out: record */ - const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ + const offset_t* offsets,/*!< in: rec_get_offsets(rec, index) */ ulint trx_id_col,/*!< in: column number of TRX_ID in rec */ trx_id_t trx_id, /*!< in: transaction identifier */ roll_ptr_t roll_ptr)/*!< in: roll_ptr */ @@ -394,7 +395,7 @@ page_zip_dir_delete( page_zip_des_t* page_zip, /*!< in/out: compressed page */ byte* rec, /*!< in: deleted record */ const dict_index_t* index, /*!< in: index of rec */ - const ulint* offsets, /*!< in: rec_get_offsets(rec) */ + const offset_t* offsets, /*!< in: rec_get_offsets(rec) */ const byte* free) /*!< in: previous start of the free list */ MY_ATTRIBUTE((nonnull(1,2,3,4))); diff --git a/storage/innobase/include/rem0cmp.h b/storage/innobase/include/rem0cmp.h index 9582b0df393..0877c7b5b6a 100644 --- a/storage/innobase/include/rem0cmp.h +++ b/storage/innobase/include/rem0cmp.h @@ -89,7 +89,7 @@ cmp_dtuple_rec_with_gis( /*====================*/ const dtuple_t* dtuple, const rec_t* rec, - const ulint* offsets, + const offset_t* offsets, page_cur_mode_t mode) MY_ATTRIBUTE((nonnull)); @@ -105,7 +105,7 @@ int cmp_dtuple_rec_with_gis_internal( const dtuple_t* dtuple, const rec_t* rec, - const ulint* offsets); + const offset_t* offsets); /** Compare a data tuple to a physical record. @param[in] dtuple data tuple @@ -121,7 +121,7 @@ int cmp_dtuple_rec_with_match_low( const dtuple_t* dtuple, const rec_t* rec, - const ulint* offsets, + const offset_t* offsets, ulint n_cmp, ulint* matched_fields) MY_ATTRIBUTE((nonnull)); @@ -145,7 +145,7 @@ cmp_dtuple_rec_with_match_bytes( const dtuple_t* dtuple, const rec_t* rec, const dict_index_t* index, - const ulint* offsets, + const offset_t* offsets, ulint* matched_fields, ulint* matched_bytes) MY_ATTRIBUTE((warn_unused_result)); @@ -162,7 +162,7 @@ int cmp_dtuple_rec( const dtuple_t* dtuple, const rec_t* rec, - const ulint* offsets); + const offset_t* offsets); /**************************************************************//** Checks if a dtuple is a prefix of a record. The last field in dtuple is allowed to be a prefix of the corresponding field in the record. @@ -172,7 +172,7 @@ cmp_dtuple_is_prefix_of_rec( /*========================*/ const dtuple_t* dtuple, /*!< in: data tuple */ const rec_t* rec, /*!< in: physical record */ - const ulint* offsets);/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets);/*!< in: array returned by rec_get_offsets() */ /** Compare two physical records that contain the same number of columns, none of which are stored externally. @retval positive if rec1 (including non-ordering columns) is greater than rec2 @@ -183,8 +183,8 @@ cmp_rec_rec_simple( /*===============*/ const rec_t* rec1, /*!< in: physical record */ const rec_t* rec2, /*!< in: physical record */ - const ulint* offsets1,/*!< in: rec_get_offsets(rec1, ...) */ - const ulint* offsets2,/*!< in: rec_get_offsets(rec2, ...) */ + const offset_t* offsets1,/*!< in: rec_get_offsets(rec1, ...) */ + const offset_t* offsets2,/*!< in: rec_get_offsets(rec2, ...) */ const dict_index_t* index, /*!< in: data dictionary index */ struct TABLE* table) /*!< in: MySQL table, for reporting duplicate key value if applicable, @@ -209,8 +209,8 @@ int cmp_rec_rec_with_match( const rec_t* rec1, const rec_t* rec2, - const ulint* offsets1, - const ulint* offsets2, + const offset_t* offsets1, + const offset_t* offsets2, const dict_index_t* index, bool nulls_unequal, ulint* matched_fields); @@ -231,8 +231,8 @@ int cmp_rec_rec( const rec_t* rec1, const rec_t* rec2, - const ulint* offsets1, - const ulint* offsets2, + const offset_t* offsets1, + const offset_t* offsets2, const dict_index_t* index, ulint* matched_fields = NULL); diff --git a/storage/innobase/include/rem0cmp.ic b/storage/innobase/include/rem0cmp.ic index 2412d22e8fa..5ac3838f244 100644 --- a/storage/innobase/include/rem0cmp.ic +++ b/storage/innobase/include/rem0cmp.ic @@ -68,8 +68,8 @@ int cmp_rec_rec( const rec_t* rec1, const rec_t* rec2, - const ulint* offsets1, - const ulint* offsets2, + const offset_t* offsets1, + const offset_t* offsets2, const dict_index_t* index, ulint* matched_fields) { diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index c81f0479ce6..f38efc660c4 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -71,29 +71,72 @@ The status is stored in the low-order bits. */ /* Length of a B-tree node pointer, in bytes */ #define REC_NODE_PTR_SIZE 4 +#ifndef UNIV_INNOCHECKSUM /** SQL null flag in a 1-byte offset of ROW_FORMAT=REDUNDANT records */ -#define REC_1BYTE_SQL_NULL_MASK 0x80UL +static const offset_t REC_1BYTE_SQL_NULL_MASK= 0x80; /** SQL null flag in a 2-byte offset of ROW_FORMAT=REDUNDANT records */ -#define REC_2BYTE_SQL_NULL_MASK 0x8000UL +static const offset_t REC_2BYTE_SQL_NULL_MASK= 0x8000; /** In a 2-byte offset of ROW_FORMAT=REDUNDANT records, the second most significant bit denotes that the tail of a field is stored off-page. */ -#define REC_2BYTE_EXTERN_MASK 0x4000UL +static const offset_t REC_2BYTE_EXTERN_MASK= 0x4000; + +static const size_t RECORD_OFFSET= 2; +static const size_t INDEX_OFFSET= + RECORD_OFFSET + sizeof(rec_t *) / sizeof(offset_t); -#ifdef UNIV_DEBUG -/* Length of the rec_get_offsets() header */ -# define REC_OFFS_HEADER_SIZE 4 -#else /* UNIV_DEBUG */ /* Length of the rec_get_offsets() header */ -# define REC_OFFS_HEADER_SIZE 2 +static const size_t REC_OFFS_HEADER_SIZE= +#ifdef UNIV_DEBUG + sizeof(rec_t *) / sizeof(offset_t) + + sizeof(dict_index_t *) / sizeof(offset_t) + #endif /* UNIV_DEBUG */ + 2; /* Number of elements that should be initially allocated for the offsets[] array, first passed to rec_get_offsets() */ -#define REC_OFFS_NORMAL_SIZE OFFS_IN_REC_NORMAL_SIZE -#define REC_OFFS_SMALL_SIZE 10 +static const size_t REC_OFFS_NORMAL_SIZE= 300; +static const size_t REC_OFFS_SMALL_SIZE= 18; +static const size_t REC_OFFS_SEC_INDEX_SIZE= + /* PK max key parts */ 16 + /* sec idx max key parts */ 16 + + /* child page number for non-leaf pages */ 1; + +/* Offset consists of two parts: 2 upper bits is type and all other bits is +value */ + +enum field_type_t +{ + /** normal field */ + STORED_IN_RECORD= 0 << 14, + /** this field is stored off-page */ + STORED_OFFPAGE= 1 << 14, + /** just an SQL NULL */ + SQL_NULL= 2 << 14 +}; + +/** without 2 upper bits */ +static const offset_t DATA_MASK= 0x3fff; +/** 2 upper bits */ +static const offset_t TYPE_MASK= ~DATA_MASK; +inline field_type_t get_type(offset_t n) +{ + return static_cast(n & TYPE_MASK); +} +inline void set_type(offset_t &n, field_type_t type) +{ + n= (n & DATA_MASK) | static_cast(type); +} +inline offset_t get_value(offset_t n) { return n & DATA_MASK; } +inline offset_t combine(offset_t value, field_type_t type) +{ + return get_value(value) | static_cast(type); +} + +/** Compact flag ORed to the extra size returned by rec_offs_base()[0] */ +static const offset_t REC_OFFS_COMPACT= 1 << 15; +/** External flag in offsets returned by rec_offs_base()[0] */ +static const offset_t REC_OFFS_EXTERNAL= 1 << 14; -#ifndef UNIV_INNOCHECKSUM /******************************************************//** The following function is used to get the pointer of the next chained record on the same page. @@ -398,7 +441,7 @@ offsets form. If the field is SQL null, the flag is ORed in the returned value. @return offset of the start of the field, SQL null flag ORed */ UNIV_INLINE -ulint +uint8_t rec_1_get_field_end_info( /*=====================*/ const rec_t* rec, /*!< in: record */ @@ -453,11 +496,11 @@ rec_get_n_extern_new( (ULINT_UNDEFINED to compute all offsets) @param[in,out] heap memory heap @return the new offsets */ -ulint* +offset_t* rec_get_offsets_func( const rec_t* rec, const dict_index_t* index, - ulint* offsets, + offset_t* offsets, #ifdef UNIV_DEBUG bool leaf, #endif /* UNIV_DEBUG */ @@ -494,7 +537,7 @@ rec_get_offsets_reverse( const dict_index_t* index, /*!< in: record descriptor */ ulint node_ptr,/*!< in: nonzero=node pointer, 0=leaf node */ - ulint* offsets)/*!< in/out: array consisting of + offset_t* offsets)/*!< in/out: array consisting of offsets[0] allocated elements */ MY_ATTRIBUTE((nonnull)); #ifdef UNIV_DEBUG @@ -507,7 +550,7 @@ rec_offs_validate( /*==============*/ const rec_t* rec, /*!< in: record or NULL */ const dict_index_t* index, /*!< in: record descriptor or NULL */ - const ulint* offsets)/*!< in: array returned by + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((nonnull(3), warn_unused_result)); /************************************************************//** @@ -519,7 +562,7 @@ rec_offs_make_valid( /*================*/ const rec_t* rec, /*!< in: record */ const dict_index_t* index, /*!< in: record descriptor */ - ulint* offsets)/*!< in: array returned by + offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((nonnull)); #else @@ -557,10 +600,10 @@ The following function is used to get an offset to the nth data field in a record. @return offset from the origin of rec */ UNIV_INLINE -ulint +offset_t rec_get_nth_field_offs( /*===================*/ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets,/*!< in: array returned by rec_get_offsets() */ ulint n, /*!< in: index of the field */ ulint* len) /*!< out: length of the field; UNIV_SQL_NULL if SQL null */ @@ -575,7 +618,7 @@ UNIV_INLINE ulint rec_offs_comp( /*==========*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((warn_unused_result)); /******************************************************//** Determine if the offsets are for a record containing @@ -585,7 +628,7 @@ UNIV_INLINE ulint rec_offs_any_extern( /*================*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((warn_unused_result)); /******************************************************//** Determine if the offsets are for a record containing null BLOB pointers. @@ -595,7 +638,7 @@ const byte* rec_offs_any_null_extern( /*=====================*/ const rec_t* rec, /*!< in: record */ - const ulint* offsets) /*!< in: rec_get_offsets(rec) */ + const offset_t* offsets) /*!< in: rec_get_offsets(rec) */ MY_ATTRIBUTE((warn_unused_result)); /******************************************************//** Returns nonzero if the extern bit is set in nth field of rec. @@ -604,7 +647,7 @@ UNIV_INLINE ulint rec_offs_nth_extern( /*================*/ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets,/*!< in: array returned by rec_get_offsets() */ ulint n) /*!< in: nth field */ MY_ATTRIBUTE((warn_unused_result)); @@ -613,7 +656,7 @@ rec_offs_nth_extern( @param[in] n nth field */ void rec_offs_make_nth_extern( - ulint* offsets, + offset_t* offsets, const ulint n); /******************************************************//** Returns nonzero if the SQL NULL bit is set in nth field of rec. @@ -622,7 +665,7 @@ UNIV_INLINE ulint rec_offs_nth_sql_null( /*==================*/ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets,/*!< in: array returned by rec_get_offsets() */ ulint n) /*!< in: nth field */ MY_ATTRIBUTE((warn_unused_result)); /******************************************************//** @@ -632,7 +675,7 @@ UNIV_INLINE ulint rec_offs_nth_size( /*==============*/ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets,/*!< in: array returned by rec_get_offsets() */ ulint n) /*!< in: nth field */ MY_ATTRIBUTE((warn_unused_result)); @@ -643,7 +686,7 @@ UNIV_INLINE ulint rec_offs_n_extern( /*==============*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((warn_unused_result)); /***********************************************************//** This is used to modify the value of an already existing field in a record. @@ -656,7 +699,7 @@ void rec_set_nth_field( /*==============*/ rec_t* rec, /*!< in: record */ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets,/*!< in: array returned by rec_get_offsets() */ ulint n, /*!< in: index number of the field */ const void* data, /*!< in: pointer to the data if not SQL null */ ulint len) /*!< in: length of the data or UNIV_SQL_NULL. @@ -685,7 +728,7 @@ UNIV_INLINE ulint rec_offs_get_n_alloc( /*=================*/ - const ulint* offsets)/*!< in: array for rec_get_offsets() */ + const offset_t* offsets)/*!< in: array for rec_get_offsets() */ MY_ATTRIBUTE((warn_unused_result)); /**********************************************************//** The following function sets the number of allocated elements @@ -694,7 +737,7 @@ UNIV_INLINE void rec_offs_set_n_alloc( /*=================*/ - ulint* offsets, /*!< out: array for rec_get_offsets(), + offset_t*offsets, /*!< out: array for rec_get_offsets(), must be allocated */ ulint n_alloc) /*!< in: number of elements */ MY_ATTRIBUTE((nonnull)); @@ -707,7 +750,7 @@ UNIV_INLINE ulint rec_offs_n_fields( /*==============*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((warn_unused_result)); /**********************************************************//** The following function returns the data size of a physical @@ -719,7 +762,7 @@ UNIV_INLINE ulint rec_offs_data_size( /*===============*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((warn_unused_result)); /**********************************************************//** Returns the total size of record minus data size of record. @@ -730,7 +773,7 @@ UNIV_INLINE ulint rec_offs_extra_size( /*================*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((warn_unused_result)); /**********************************************************//** Returns the total size of a physical record. @@ -739,7 +782,7 @@ UNIV_INLINE ulint rec_offs_size( /*==========*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((warn_unused_result)); #ifdef UNIV_DEBUG /**********************************************************//** @@ -750,7 +793,7 @@ byte* rec_get_start( /*==========*/ const rec_t* rec, /*!< in: pointer to record */ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((warn_unused_result)); /**********************************************************//** Returns a pointer to the end of the record. @@ -760,7 +803,7 @@ byte* rec_get_end( /*========*/ const rec_t* rec, /*!< in: pointer to record */ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((warn_unused_result)); #else /* UNIV_DEBUG */ # define rec_get_start(rec, offsets) ((rec) - rec_offs_extra_size(offsets)) @@ -777,7 +820,7 @@ rec_t* rec_copy( void* buf, const rec_t* rec, - const ulint* offsets); + const offset_t* offsets); /** Determine the size of a data tuple prefix in a temporary file. @param[in] index clustered or secondary index @@ -801,7 +844,7 @@ rec_init_offsets_temp( /*==================*/ const rec_t* rec, /*!< in: temporary file record */ const dict_index_t* index, /*!< in: record descriptor */ - ulint* offsets)/*!< in/out: array of offsets; + offset_t* offsets)/*!< in/out: array of offsets; in: n=rec_offs_n_fields(offsets) */ MY_ATTRIBUTE((nonnull)); @@ -843,7 +886,7 @@ UNIV_INLINE ulint rec_fold( const rec_t* rec, - const ulint* offsets, + const offset_t* offsets, ulint n_fields, ulint n_bytes, index_id_t tree_id) @@ -944,7 +987,7 @@ ibool rec_validate( /*=========*/ const rec_t* rec, /*!< in: physical record */ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((nonnull)); /***************************************************************//** Prints an old-style physical record. */ @@ -961,7 +1004,7 @@ rec_print_mbr_rec( /*==========*/ FILE* file, /*!< in: file where to print */ const rec_t* rec, /*!< in: physical record */ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((nonnull)); /***************************************************************//** Prints a physical record. */ @@ -970,7 +1013,7 @@ rec_print_new( /*==========*/ FILE* file, /*!< in: file where to print */ const rec_t* rec, /*!< in: physical record */ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ MY_ATTRIBUTE((nonnull)); /***************************************************************//** Prints a physical record. */ @@ -992,7 +1035,7 @@ rec_print( std::ostream& o, const rec_t* rec, ulint info, - const ulint* offsets); + const offset_t* offsets); /** Wrapper for pretty-printing a record */ struct rec_index_print @@ -1019,14 +1062,14 @@ operator<<(std::ostream& o, const rec_index_print& r); struct rec_offsets_print { /** Constructor */ - rec_offsets_print(const rec_t* rec, const ulint* offsets) : + rec_offsets_print(const rec_t* rec, const offset_t* offsets) : m_rec(rec), m_offsets(offsets) {} /** Record */ const rec_t* m_rec; /** Offsets to each field */ - const ulint* m_offsets; + const offset_t* m_offsets; }; /** Display a record. @@ -1043,7 +1086,7 @@ public: /** Construct a pretty-printed record. @param rec record with header @param offsets rec_get_offsets(rec, ...) */ - rec_printer(const rec_t* rec, const ulint* offsets) + rec_printer(const rec_t* rec, const offset_t* offsets) : std::ostringstream () { @@ -1056,7 +1099,7 @@ public: @param rec record, possibly lacking header @param info rec_get_info_bits(rec) @param offsets rec_get_offsets(rec, ...) */ - rec_printer(const rec_t* rec, ulint info, const ulint* offsets) + rec_printer(const rec_t* rec, ulint info, const offset_t* offsets) : std::ostringstream () { diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic index 4d2c00de48f..cb62017268c 100644 --- a/storage/innobase/include/rem0rec.ic +++ b/storage/innobase/include/rem0rec.ic @@ -30,15 +30,6 @@ Created 5/30/1994 Heikki Tuuri #include "dict0boot.h" #include "btr0types.h" -/* Compact flag ORed to the extra size returned by rec_get_offsets() */ -#define REC_OFFS_COMPACT ((ulint) 1 << 31) -/* SQL NULL flag in offsets returned by rec_get_offsets() */ -#define REC_OFFS_SQL_NULL ((ulint) 1 << 31) -/* External flag in offsets returned by rec_get_offsets() */ -#define REC_OFFS_EXTERNAL ((ulint) 1 << 30) -/* Mask for offsets returned by rec_get_offsets() */ -#define REC_OFFS_MASK (REC_OFFS_EXTERNAL - 1) - /* Offsets of the bit-fields in an old-style record. NOTE! In the table the most significant bytes and bits are written below less significant. @@ -873,7 +864,7 @@ offsets form. If the field is SQL null, the flag is ORed in the returned value. @return offset of the start of the field, SQL null flag ORed */ UNIV_INLINE -ulint +uint8_t rec_1_get_field_end_info( /*=====================*/ const rec_t* rec, /*!< in: record */ @@ -931,7 +922,7 @@ UNIV_INLINE ulint rec_offs_get_n_alloc( /*=================*/ - const ulint* offsets)/*!< in: array for rec_get_offsets() */ + const offset_t* offsets)/*!< in: array for rec_get_offsets() */ { ulint n_alloc; ut_ad(offsets); @@ -948,13 +939,13 @@ UNIV_INLINE void rec_offs_set_n_alloc( /*=================*/ - ulint* offsets, /*!< out: array for rec_get_offsets(), + offset_t*offsets, /*!< out: array for rec_get_offsets(), must be allocated */ ulint n_alloc) /*!< in: number of elements */ { ut_ad(n_alloc > REC_OFFS_HEADER_SIZE); UNIV_MEM_ALLOC(offsets, n_alloc * sizeof *offsets); - offsets[0] = n_alloc; + offsets[0] = static_cast(n_alloc); } /**********************************************************//** @@ -964,7 +955,7 @@ UNIV_INLINE ulint rec_offs_n_fields( /*==============*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ { ulint n_fields; ut_ad(offsets); @@ -985,22 +976,22 @@ rec_offs_validate( /*==============*/ const rec_t* rec, /*!< in: record or NULL */ const dict_index_t* index, /*!< in: record descriptor or NULL */ - const ulint* offsets)/*!< in: array returned by + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ { ulint i = rec_offs_n_fields(offsets); ulint last = ULINT_MAX; - ulint comp = *rec_offs_base(offsets) & REC_OFFS_COMPACT; + bool comp = rec_offs_base(offsets)[0] & REC_OFFS_COMPACT; if (rec) { - ut_ad((ulint) rec == offsets[2]); + ut_ad(!memcmp(&rec, &offsets[RECORD_OFFSET], sizeof(rec))); if (!comp) { ut_a(rec_get_n_fields_old(rec) >= i); } } if (index) { ulint max_n_fields; - ut_ad((ulint) index == offsets[3]); + ut_ad(!memcmp(&index, &offsets[INDEX_OFFSET], sizeof(index))); max_n_fields = ut_max( dict_index_get_n_fields(index), dict_index_get_n_unique_in_tree(index) + 1); @@ -1025,7 +1016,7 @@ rec_offs_validate( ut_a(!index->n_def || i <= max_n_fields); } while (i--) { - ulint curr = rec_offs_base(offsets)[1 + i] & REC_OFFS_MASK; + offset_t curr = get_value(rec_offs_base(offsets)[1 + i]); ut_a(curr <= last); last = curr; } @@ -1041,15 +1032,15 @@ rec_offs_make_valid( /*================*/ const rec_t* rec, /*!< in: record */ const dict_index_t* index, /*!< in: record descriptor */ - ulint* offsets)/*!< in: array returned by + offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ { ut_ad(rec); ut_ad(index); ut_ad(offsets); ut_ad(rec_get_n_fields(rec, index) >= rec_offs_n_fields(offsets)); - offsets[2] = (ulint) rec; - offsets[3] = (ulint) index; + memcpy(&offsets[RECORD_OFFSET], &rec, sizeof(rec)); + memcpy(&offsets[INDEX_OFFSET], &index, sizeof(index)); } #endif /* UNIV_DEBUG */ @@ -1058,34 +1049,26 @@ The following function is used to get an offset to the nth data field in a record. @return offset from the origin of rec */ UNIV_INLINE -ulint +offset_t rec_get_nth_field_offs( /*===================*/ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets,/*!< in: array returned by rec_get_offsets() */ ulint n, /*!< in: index of the field */ ulint* len) /*!< out: length of the field; UNIV_SQL_NULL if SQL null */ { - ulint offs; - ulint length; ut_ad(n < rec_offs_n_fields(offsets)); - if (n == 0) { - offs = 0; - } else { - offs = rec_offs_base(offsets)[n] & REC_OFFS_MASK; - } - - length = rec_offs_base(offsets)[1 + n]; + offset_t offs = n == 0 ? 0 : get_value(rec_offs_base(offsets)[n]); + offset_t next_offs = rec_offs_base(offsets)[1 + n]; - if (length & REC_OFFS_SQL_NULL) { - length = UNIV_SQL_NULL; + if (get_type(next_offs) == SQL_NULL) { + *len = UNIV_SQL_NULL; } else { - length &= REC_OFFS_MASK; - length -= offs; + + *len = get_value(next_offs) - offs; } - *len = length; return(offs); } @@ -1097,7 +1080,7 @@ UNIV_INLINE ulint rec_offs_comp( /*==========*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ { ut_ad(rec_offs_validate(NULL, NULL, offsets)); return(*rec_offs_base(offsets) & REC_OFFS_COMPACT); @@ -1111,7 +1094,7 @@ UNIV_INLINE ulint rec_offs_any_extern( /*================*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ { ut_ad(rec_offs_validate(NULL, NULL, offsets)); return(*rec_offs_base(offsets) & REC_OFFS_EXTERNAL); @@ -1125,7 +1108,7 @@ const byte* rec_offs_any_null_extern( /*=====================*/ const rec_t* rec, /*!< in: record */ - const ulint* offsets) /*!< in: rec_get_offsets(rec) */ + const offset_t* offsets) /*!< in: rec_get_offsets(rec) */ { ulint i; ut_ad(rec_offs_validate(rec, NULL, offsets)); @@ -1160,12 +1143,12 @@ UNIV_INLINE ulint rec_offs_nth_extern( /*================*/ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets,/*!< in: array returned by rec_get_offsets() */ ulint n) /*!< in: nth field */ { ut_ad(rec_offs_validate(NULL, NULL, offsets)); ut_ad(n < rec_offs_n_fields(offsets)); - return(rec_offs_base(offsets)[1 + n] & REC_OFFS_EXTERNAL); + return get_type(rec_offs_base(offsets)[1 + n]) == STORED_OFFPAGE; } /******************************************************//** @@ -1175,12 +1158,12 @@ UNIV_INLINE ulint rec_offs_nth_sql_null( /*==================*/ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets,/*!< in: array returned by rec_get_offsets() */ ulint n) /*!< in: nth field */ { ut_ad(rec_offs_validate(NULL, NULL, offsets)); ut_ad(n < rec_offs_n_fields(offsets)); - return(rec_offs_base(offsets)[1 + n] & REC_OFFS_SQL_NULL); + return get_type(rec_offs_base(offsets)[1 + n]) == SQL_NULL; } /******************************************************//** @@ -1190,16 +1173,16 @@ UNIV_INLINE ulint rec_offs_nth_size( /*==============*/ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets,/*!< in: array returned by rec_get_offsets() */ ulint n) /*!< in: nth field */ { ut_ad(rec_offs_validate(NULL, NULL, offsets)); ut_ad(n < rec_offs_n_fields(offsets)); if (!n) { - return(rec_offs_base(offsets)[1 + n] & REC_OFFS_MASK); + return get_value(rec_offs_base(offsets)[1 + n]); } - return((rec_offs_base(offsets)[1 + n] - rec_offs_base(offsets)[n]) - & REC_OFFS_MASK); + return get_value((rec_offs_base(offsets)[1 + n])) + - get_value(rec_offs_base(offsets)[n]); } /******************************************************//** @@ -1209,7 +1192,7 @@ UNIV_INLINE ulint rec_offs_n_extern( /*==============*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ { ulint n = 0; @@ -1407,7 +1390,7 @@ void rec_set_nth_field( /*==============*/ rec_t* rec, /*!< in: record */ - const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets,/*!< in: array returned by rec_get_offsets() */ ulint n, /*!< in: index number of the field */ const void* data, /*!< in: pointer to the data if not SQL null */ @@ -1462,16 +1445,16 @@ UNIV_INLINE void rec_offs_set_n_fields( /*==================*/ - ulint* offsets, /*!< in/out: array returned by + offset_t* offsets, /*!< in/out: array returned by rec_get_offsets() */ - ulint n_fields) /*!< in: number of fields */ + ulint n_fields) /*!< in: number of fields */ { ut_ad(offsets); ut_ad(n_fields > 0); ut_ad(n_fields <= REC_MAX_N_FIELDS); ut_ad(n_fields + REC_OFFS_HEADER_SIZE <= rec_offs_get_n_alloc(offsets)); - offsets[1] = n_fields; + offsets[1] = static_cast(n_fields); } /**********************************************************//** @@ -1484,13 +1467,12 @@ UNIV_INLINE ulint rec_offs_data_size( /*===============*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ { ulint size; ut_ad(rec_offs_validate(NULL, NULL, offsets)); - size = rec_offs_base(offsets)[rec_offs_n_fields(offsets)] - & REC_OFFS_MASK; + size = get_value(rec_offs_base(offsets)[rec_offs_n_fields(offsets)]); ut_ad(size < UNIV_PAGE_SIZE); return(size); } @@ -1504,7 +1486,7 @@ UNIV_INLINE ulint rec_offs_extra_size( /*================*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ { ulint size; ut_ad(rec_offs_validate(NULL, NULL, offsets)); @@ -1520,7 +1502,7 @@ UNIV_INLINE ulint rec_offs_size( /*==========*/ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ { return(rec_offs_data_size(offsets) + rec_offs_extra_size(offsets)); } @@ -1534,7 +1516,7 @@ byte* rec_get_end( /*========*/ const rec_t* rec, /*!< in: pointer to record */ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ { ut_ad(rec_offs_validate(rec, NULL, offsets)); return(const_cast(rec + rec_offs_data_size(offsets))); @@ -1548,7 +1530,7 @@ byte* rec_get_start( /*==========*/ const rec_t* rec, /*!< in: pointer to record */ - const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ + const offset_t* offsets)/*!< in: array returned by rec_get_offsets() */ { ut_ad(rec_offs_validate(rec, NULL, offsets)); return(const_cast(rec - rec_offs_extra_size(offsets))); @@ -1565,7 +1547,7 @@ rec_t* rec_copy( void* buf, const rec_t* rec, - const ulint* offsets) + const offset_t* offsets) { ulint extra_len; ulint data_len; @@ -1696,7 +1678,7 @@ UNIV_INLINE ulint rec_fold( const rec_t* rec, - const ulint* offsets, + const offset_t* offsets, ulint n_fields, ulint n_bytes, index_id_t tree_id) diff --git a/storage/innobase/include/rem0types.h b/storage/innobase/include/rem0types.h index cc59bd91076..4482517fc4e 100644 --- a/storage/innobase/include/rem0types.h +++ b/storage/innobase/include/rem0types.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -29,6 +30,9 @@ Created 5/30/1994 Heikki Tuuri /* We define the physical record simply as an array of bytes */ typedef byte rec_t; +/** This type represents a field offset in a rec_t* */ +typedef unsigned short int offset_t; + /* Maximum values for various fields (for non-blob tuples) */ #define REC_MAX_N_FIELDS (1024 - 1) #define REC_MAX_HEAP_NO (2 * 8192 - 1) diff --git a/storage/innobase/include/row0ftsort.h b/storage/innobase/include/row0ftsort.h index 1c1357e330b..73f815604d8 100644 --- a/storage/innobase/include/row0ftsort.h +++ b/storage/innobase/include/row0ftsort.h @@ -30,6 +30,7 @@ Created 10/13/2010 Jimmy Yang #include "data0data.h" #include "fts0fts.h" #include "fts0priv.h" +#include "rem0types.h" #include "row0merge.h" #include "btr0bulk.h" @@ -247,7 +248,7 @@ row_merge_fts_sel_propagate( int* sel_tree, /* Date: Mon, 16 Dec 2019 13:40:00 +0200 Subject: Remove unused mlog_catenate_ulint_compressed() The function was only used by trx_undo_page_init_log() (writing the MLOG_UNDO_INIT record), which was removed in commit ccb3550221497e7e652883b79e4a01451a55c4d7. --- storage/innobase/include/mtr0log.h | 8 -------- storage/innobase/include/mtr0log.ic | 24 ------------------------ 2 files changed, 32 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/mtr0log.h b/storage/innobase/include/mtr0log.h index eaf2fad9e7f..dc76b40a3db 100644 --- a/storage/innobase/include/mtr0log.h +++ b/storage/innobase/include/mtr0log.h @@ -109,14 +109,6 @@ mlog_catenate_string( const byte* str, /*!< in: string to write */ ulint len); /*!< in: string length */ /********************************************************//** -Catenates a compressed ulint to mlog. */ -UNIV_INLINE -void -mlog_catenate_ulint_compressed( -/*===========================*/ - mtr_t* mtr, /*!< in: mtr */ - ulint val); /*!< in: value to write */ -/********************************************************//** Catenates a compressed 64-bit integer to mlog. */ UNIV_INLINE void diff --git a/storage/innobase/include/mtr0log.ic b/storage/innobase/include/mtr0log.ic index 23a840d95a6..70bcaf43b9e 100644 --- a/storage/innobase/include/mtr0log.ic +++ b/storage/innobase/include/mtr0log.ic @@ -117,30 +117,6 @@ mlog_catenate_ulint( mlog_catenate_ulint(mtr->get_log(), val, type); } -/********************************************************//** -Catenates a compressed ulint to mlog. */ -UNIV_INLINE -void -mlog_catenate_ulint_compressed( -/*===========================*/ - mtr_t* mtr, /*!< in: mtr */ - ulint val) /*!< in: value to write */ -{ - byte* log_ptr; - - log_ptr = mlog_open(mtr, 10); - - /* If no logging is requested, we may return now */ - if (log_ptr == NULL) { - - return; - } - - log_ptr += mach_write_compressed(log_ptr, val); - - mlog_close(mtr, log_ptr); -} - /********************************************************//** Catenates a compressed 64-bit integer to mlog. */ UNIV_INLINE -- cgit v1.2.1 From 8174e68895c468a2286688962a65206e677b7c51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 20 Dec 2019 17:55:13 +0200 Subject: MDEV-21371 Assertion failure in page_rec_get_next_low() during innodb_gis.rtree_compress A debug assertion that was added in commit ed0793e096a17955c5a03844b248bcf8303dd335 turns out to be too strict. In the test innodb_gis.rtree_compress,4k the function is sometimes being invoked by purge for a spatial index root page that is not a leaf page (PAGE_LEVEL is 1). --- storage/innobase/include/page0page.ic | 1 + 1 file changed, 1 insertion(+) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic index 6369932db1b..98b518187b5 100644 --- a/storage/innobase/include/page0page.ic +++ b/storage/innobase/include/page0page.ic @@ -660,6 +660,7 @@ page_rec_get_next_low( } ut_ad(page_rec_is_infimum(rec) + || (!page_is_leaf(page) && !page_has_prev(page)) || !(rec_get_info_bits(page + offs, comp) & REC_INFO_MIN_REC_FLAG)); -- cgit v1.2.1 From 496532b5c54d69e012f6fc2417e97d61465588f2 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Sat, 21 Dec 2019 23:29:36 +0800 Subject: MDEV-20950: Fix 32-bit Windows build --- storage/innobase/include/rem0rec.h | 2 +- storage/innobase/include/rem0rec.ic | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index f38efc660c4..72ee96b2887 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -455,7 +455,7 @@ value. @return offset of the start of the field, SQL null flag and extern storage flag ORed */ UNIV_INLINE -ulint +offset_t rec_2_get_field_end_info( /*=====================*/ const rec_t* rec, /*!< in: record */ diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic index cb62017268c..27df29e61d6 100644 --- a/storage/innobase/include/rem0rec.ic +++ b/storage/innobase/include/rem0rec.ic @@ -883,7 +883,7 @@ value. @return offset of the start of the field, SQL null flag and extern storage flag ORed */ UNIV_INLINE -ulint +offset_t rec_2_get_field_end_info( /*=====================*/ const rec_t* rec, /*!< in: record */ -- cgit v1.2.1 From bba59abb039fee1a3ee72a25643ebb7a0b64f3c5 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 23 Dec 2019 12:27:41 +0530 Subject: MDEV-19176 Reduce the memory usage during recovery - Moved the recv_sys->heap memory condition inside recv_parse_log_recs(). So that, InnoDB can mark the status as STORE_NO earlier. - InnoDB uses one third of buffer pool chunk size for reading the redo log records. In that case, we can avoid the scenario where buffer ran out of memory issue during recovery. --- storage/innobase/include/buf0buf.ic | 12 +++++++++++- storage/innobase/include/log0recv.h | 15 ++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic index 98026159b8a..b3fe52a0412 100644 --- a/storage/innobase/include/buf0buf.ic +++ b/storage/innobase/include/buf0buf.ic @@ -113,7 +113,17 @@ ulint buf_pool_get_n_pages(void) /*======================*/ { - return(buf_pool_get_curr_size() / UNIV_PAGE_SIZE); + if (!buf_pool_ptr) + return buf_pool_get_curr_size() >> srv_page_size_shift; + + ulint chunk_size= 0; + for (uint i= 0; i < srv_buf_pool_instances; i++) + { + buf_pool_t* buf_pool = buf_pool_from_array(i); + for (uint j= 0; j < buf_pool->n_chunks; j++) + chunk_size+= buf_pool->chunks[j]->size; + } + return chunk_size; } /********************************************************************//** diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index 74aa4fcb517..d6da4cad9a9 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -133,14 +133,19 @@ bool recv_sys_add_to_parsing_buf(const byte* log_block, lsn_t scanned_lsn); /** Parse log records from a buffer and optionally store them to a hash table to wait merging to file pages. -@param[in] checkpoint_lsn the LSN of the latest checkpoint -@param[in] store whether to store page operations -@param[in] apply whether to apply the records +@param[in] checkpoint_lsn the LSN of the latest checkpoint +@param[in] store whether to store page operations +@param[in] available_memory memory to read the redo logs +@param[in] apply whether to apply the records @return whether MLOG_CHECKPOINT record was seen the first time, or corruption was noticed */ -bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t store, bool apply); +bool recv_parse_log_recs( + lsn_t checkpoint_lsn, + store_t* store, + ulint available_memory, + bool apply); -/** Moves the parsing buffer data left to the buffer start. */ +/** Moves the parsing buffer data left to the buffer start */ void recv_sys_justify_left_parsing_buf(); /** Report optimized DDL operation (without redo log), -- cgit v1.2.1 From 90ba87cb9e3307fff4785cadf2d058e1ce4288a4 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 23 Dec 2019 15:56:57 +0530 Subject: MDEV-19176 Reduce the memory usage during recovery - post-push to fix the compilation issue --- storage/innobase/include/buf0buf.ic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic index b3fe52a0412..e1c8986c2ed 100644 --- a/storage/innobase/include/buf0buf.ic +++ b/storage/innobase/include/buf0buf.ic @@ -121,7 +121,7 @@ buf_pool_get_n_pages(void) { buf_pool_t* buf_pool = buf_pool_from_array(i); for (uint j= 0; j < buf_pool->n_chunks; j++) - chunk_size+= buf_pool->chunks[j]->size; + chunk_size+= buf_pool->chunks[j].size; } return chunk_size; } -- cgit v1.2.1 From 16bce0f6fe6bcad0091dc45a97a8ac7b33fe9d44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 27 Dec 2019 11:23:28 +0200 Subject: Cleanup: Remove dict_delete_tablespace_and_datafiles() The function was only called by innobase_drop_tablespace(), which was removed in commit 494e4b99a4a6c2f933c7e663cbb6ad5b17e8f84a and added in commit 2e814d4702d71a04388386a9f591d14a35980bfe. --- storage/innobase/include/dict0crea.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h index 7d87686e010..359d9f556e5 100644 --- a/storage/innobase/include/dict0crea.h +++ b/storage/innobase/include/dict0crea.h @@ -238,16 +238,6 @@ dict_replace_tablespace_in_dictionary( const char* path, trx_t* trx); -/** Delete records from SYS_TABLESPACES and SYS_DATAFILES associated -with a particular tablespace ID. -@param[in] space Tablespace ID -@param[in,out] trx Current transaction -@return DB_SUCCESS if OK, dberr_t if the operation failed */ -dberr_t -dict_delete_tablespace_and_datafiles( - ulint space, - trx_t* trx); - /********************************************************************//** Add a foreign key definition to the data dictionary tables. @return error code or DB_SUCCESS */ -- cgit v1.2.1 From 4923604ee2fba372f28c856a3f41274f7fc6c1c5 Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Sun, 24 Mar 2019 19:01:54 +1000 Subject: MDEV-18865 Assertion `t->first->versioned_by_id()' failed in innodb_prepare_commit_versioned Cause: * row_start != 0 treated as it exists. Probably, possible row permutations had not been taken in mind. Solution: * Checking both row_start and row_end is correct, so versioned() function is used --- storage/innobase/include/dict0mem.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 8c5314ed39d..1a22470569e 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -1603,10 +1603,14 @@ struct dict_table_t { /** Add the table definition to the data dictionary cache */ void add_to_cache(); + /** @return whether the table is versioned. + It is assumed that both vers_start and vers_end set to 0 + iff table is not versioned. In any other case, + these fields correspond to actual positions in cols[]. */ bool versioned() const { return vers_start || vers_end; } bool versioned_by_id() const { - return vers_start && cols[vers_start].mtype == DATA_INT; + return versioned() && cols[vers_start].mtype == DATA_INT; } void inc_fk_checks() -- cgit v1.2.1 From fd899b3bbd2c7107f708ed46ba3798c48e2cfadd Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Mon, 23 Dec 2019 01:18:39 +0800 Subject: Lets add another intrusive double linked list! Features: * STL-like interface * Fast modification: no branches on insertion or deletion * Fast iteration: one pointer dereference and one pointer comparison * Your class can be a part of several lists Modeled after std::list but currently has fewer methods (not complete yet) For even more performance it's possible to customize list with templates so it won't have size counter variable or won't NULLify unlinked node. How existing lists differ? No existing lists support STL-like interface. I_List: * slower iteration (one more branch on iteration) * element can't be a part of two lists simultaneously I_P_List: * slower modification (branches, except for the fastest push_back() case) * slower iteration (one more branch on iteration) UT_LIST_BASE_NODE_T: * slower modification (branches) Three UT_LISTs were replaced: two in fil_system_t and one in dyn_buf_t. --- storage/innobase/include/dyn0buf.h | 96 +++++++++++++++++--------------------- storage/innobase/include/fil0fil.h | 26 +++++++---- 2 files changed, 58 insertions(+), 64 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/dyn0buf.h b/storage/innobase/include/dyn0buf.h index a7a8e1dea1e..311f6518943 100644 --- a/storage/innobase/include/dyn0buf.h +++ b/storage/innobase/include/dyn0buf.h @@ -29,7 +29,8 @@ Created 2013-03-16 Sunny Bains #include "mem0mem.h" #include "dyn0types.h" -#include "ut0lst.h" +#include "intrusive_list.h" + /** Class that manages dynamic buffers. It uses a UT_LIST of dyn_buf_t::block_t instances. We don't use STL containers in @@ -42,12 +43,7 @@ template class dyn_buf_t { public: - class block_t; - - typedef UT_LIST_NODE_T(block_t) block_node_t; - typedef UT_LIST_BASE_NODE_T(block_t) block_list_t; - - class block_t { + class block_t : public intrusive::list_node<> { public: block_t() @@ -157,16 +153,13 @@ public: /** SIZE - sizeof(m_node) + sizeof(m_used) */ enum { MAX_DATA_SIZE = SIZE - - sizeof(block_node_t) + - sizeof(intrusive::list_node<>) + sizeof(ib_uint32_t) }; /** Storage */ byte m_data[MAX_DATA_SIZE]; - /** Doubly linked list node. */ - block_node_t m_node; - /** number of data bytes used in this block; DYN_BLOCK_FULL_FLAG is set when the block becomes full */ ib_uint32_t m_used; @@ -174,6 +167,8 @@ public: friend class dyn_buf_t; }; + typedef intrusive::list list_t; + enum { MAX_DATA_SIZE = block_t::MAX_DATA_SIZE}; /** Default constructor */ @@ -182,7 +177,6 @@ public: m_heap(), m_size() { - UT_LIST_INIT(m_list, &block_t::m_node); push_back(&m_first_block); } @@ -200,11 +194,11 @@ public: m_heap = NULL; /* Initialise the list and add the first block. */ - UT_LIST_INIT(m_list, &block_t::m_node); - push_back(&m_first_block); + m_list.clear(); + m_list.push_back(m_first_block); } else { m_first_block.init(); - ut_ad(UT_LIST_GET_LEN(m_list) == 1); + ut_ad(m_list.size() == 1); } m_size = 0; @@ -236,7 +230,7 @@ public: @param ptr end of used space */ void close(const byte* ptr) { - ut_ad(UT_LIST_GET_LEN(m_list) > 0); + ut_ad(!m_list.empty()); block_t* block = back(); m_size -= block->used(); @@ -324,11 +318,10 @@ public: #ifdef UNIV_DEBUG ulint total_size = 0; - for (const block_t* block = UT_LIST_GET_FIRST(m_list); - block != NULL; - block = UT_LIST_GET_NEXT(m_node, block)) { - - total_size += block->used(); + for (typename list_t::iterator it = m_list.begin(), + end = m_list.end(); + it != end; ++it) { + total_size += it->used(); } ut_ad(total_size == m_size); @@ -342,12 +335,12 @@ public: template bool for_each_block(Functor& functor) const { - for (const block_t* block = UT_LIST_GET_FIRST(m_list); - block != NULL; - block = UT_LIST_GET_NEXT(m_node, block)) { + for (typename list_t::iterator it = m_list.begin(), + end = m_list.end(); + it != end; ++it) { - if (!functor(block)) { - return(false); + if (!functor(&*it)) { + return false; } } @@ -360,12 +353,12 @@ public: template bool for_each_block_in_reverse(Functor& functor) const { - for (block_t* block = UT_LIST_GET_LAST(m_list); - block != NULL; - block = UT_LIST_GET_PREV(m_node, block)) { + for (typename list_t::reverse_iterator it = m_list.rbegin(), + end = m_list.rend(); + it != end; ++it) { - if (!functor(block)) { - return(false); + if (!functor(&*it)) { + return false; } } @@ -378,12 +371,12 @@ public: template bool for_each_block_in_reverse(const Functor& functor) const { - for (block_t* block = UT_LIST_GET_LAST(m_list); - block != NULL; - block = UT_LIST_GET_PREV(m_node, block)) { + for (typename list_t::reverse_iterator it = m_list.rbegin(), + end = m_list.rend(); + it != end; ++it) { - if (!functor(block)) { - return(false); + if (!functor(&*it)) { + return false; } } @@ -395,8 +388,7 @@ public: block_t* front() MY_ATTRIBUTE((warn_unused_result)) { - ut_ad(UT_LIST_GET_LEN(m_list) > 0); - return(UT_LIST_GET_FIRST(m_list)); + return &m_list.front(); } /** @@ -417,14 +409,13 @@ private: void push_back(block_t* block) { block->init(); - - UT_LIST_ADD_LAST(m_list, block); + m_list.push_back(*block); } /** @return the last block in the list */ block_t* back() { - return(UT_LIST_GET_LAST(m_list)); + return &m_list.back(); } /* @@ -447,25 +438,22 @@ private: @return the block containing the pos. */ block_t* find(ulint& pos) { - block_t* block; + ut_ad(!m_list.empty()); - ut_ad(UT_LIST_GET_LEN(m_list) > 0); + for (typename list_t::iterator it = m_list.begin(), + end = m_list.end(); + it != end; ++it) { - for (block = UT_LIST_GET_FIRST(m_list); - block != NULL; - block = UT_LIST_GET_NEXT(m_node, block)) { + if (pos < it->used()) { + ut_ad(it->used() >= pos); - if (pos < block->used()) { - break; + return &*it; } - pos -= block->used(); + pos -= it->used(); } - ut_ad(block != NULL); - ut_ad(block->used() >= pos); - - return(block); + return NULL; } /** @@ -491,7 +479,7 @@ private: mem_heap_t* m_heap; /** Allocated blocks */ - block_list_t m_list; + list_t m_list; /** Total size used by all blocks */ ulint m_size; diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 386f574a59f..5484477d913 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -33,9 +33,13 @@ Created 10/25/1995 Heikki Tuuri #include "dict0types.h" #include "page0size.h" #include "ibuf0types.h" +#include "intrusive_list.h" #include +struct unflushed_spaces_tag_t; +struct rotation_list_tag_t; + // Forward declaration extern ibool srv_use_doublewrite_buf; extern struct buf_dblwr_t* buf_dblwr; @@ -78,7 +82,9 @@ fil_type_is_data( struct fil_node_t; /** Tablespace or log data space */ -struct fil_space_t { +struct fil_space_t : intrusive::list_node, + intrusive::list_node +{ ulint id; /*!< space id */ hash_node_t hash; /*!< hash chain node */ char* name; /*!< Tablespace name */ @@ -156,9 +162,6 @@ struct fil_space_t { ulint n_pending_ios; rw_lock_t latch; /*!< latch protecting the file space storage allocation */ - UT_LIST_NODE_T(fil_space_t) unflushed_spaces; - /*!< list of spaces with at least one unflushed - file we have written to */ UT_LIST_NODE_T(fil_space_t) named_spaces; /*!< list of spaces for which MLOG_FILE_NAME records have been issued */ @@ -167,8 +170,6 @@ struct fil_space_t { bool is_in_unflushed_spaces() const; UT_LIST_NODE_T(fil_space_t) space_list; /*!< list of all spaces */ - /** other tablespaces needing key rotation */ - UT_LIST_NODE_T(fil_space_t) rotation_list; /** Checks that this tablespace needs key rotation. @return true if in a rotation list */ bool is_in_rotation_list() const; @@ -484,6 +485,11 @@ fil_space_get( data space) is stored here; below we talk about tablespaces, but also the ib_logfiles form a 'space' and it is handled here */ struct fil_system_t { + fil_system_t() + : n_open(0), max_assigned_id(0), space_id_reuse_warned(false) + { + } + ib_mutex_t mutex; /*!< The mutex protecting the cache */ hash_table_t* spaces; /*!< The hash table of spaces in the system; they are hashed on the space @@ -501,8 +507,8 @@ struct fil_system_t { not put to this list: they are opened after the startup, and kept open until shutdown */ - UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces; - /*!< base node for the list of those + intrusive::list unflushed_spaces; + /*!< list of those tablespaces whose files contain unflushed writes; those spaces have at least one file node where @@ -524,11 +530,11 @@ struct fil_system_t { record has been written since the latest redo log checkpoint. Protected only by log_sys->mutex. */ - UT_LIST_BASE_NODE_T(fil_space_t) rotation_list; + intrusive::list rotation_list; /*!< list of all file spaces needing key rotation.*/ - ibool space_id_reuse_warned; + bool space_id_reuse_warned; /* !< TRUE if fil_space_create() has issued a warning about potential space_id reuse */ -- cgit v1.2.1 From 82187a1221467c7d193fca60a11a020ab4228e4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 7 Jan 2020 10:43:22 +0200 Subject: MDEV-21429 TRUNCATE and OPTIMIZE are being refused due to "row size too large" By default (innodb_strict_mode=ON), InnoDB attempts to guarantee at DDL time that any INSERT to the table can succeed. MDEV-19292 recently revised the "row size too large" check in InnoDB. The check still is somewhat inaccurate; that should be addressed in MDEV-20194. Note: If a table contains multiple long string columns so that each column is part of a column prefix index, then an UPDATE that attempts to modify all those columns at once may fail, because the undo log record might not fit in a single undo log page (of innodb_page_size). In the worst case, the undo log record would grow by about 3KiB of for each updated column. The DDL-time check (since the InnoDB Plugin for MySQL 5.1) is optional in the sense that when the maximum B-tree record size or undo log record size would be exceeded, the DML operation will fail and the transaction will be properly rolled back. create_table_info_t::row_size_is_acceptable(): Add the parameter 'bool strict' so that innodb_strict_mode=ON can be overridden during TRUNCATE, OPTIMIZE and ALTER TABLE...FORCE (when the storage format is not changing). create_table_info_t::create_table(): Perform a sloppy check for TRUNCATE TABLE (create_fk=false). prepare_inplace_alter_table_dict(): Perform a sloppy check for simple operations. trx_is_strict(): Remove. The function became unused in commit 98694ab0cbaf623c6ad67dd45d6f90c5c6214fd1 (MDEV-20949). --- storage/innobase/include/trx0trx.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 1d71920d6c5..7e46304b6ee 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2019, MariaDB Corporation. +Copyright (c) 2015, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -432,13 +432,6 @@ ibool trx_is_interrupted( /*===============*/ const trx_t* trx); /*!< in: transaction */ -/**********************************************************************//** -Determines if the currently running transaction is in strict mode. -@return TRUE if strict */ -ibool -trx_is_strict( -/*==========*/ - trx_t* trx); /*!< in: transaction */ /*******************************************************************//** Calculates the "weight" of a transaction. The weight of one transaction -- cgit v1.2.1 From cba9ed12790727c70332f8862684b13ac3f25bbc Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Wed, 8 Jan 2020 00:51:04 +0700 Subject: fix compilation --- storage/innobase/include/dyn0buf.h | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/dyn0buf.h b/storage/innobase/include/dyn0buf.h index b5da367bae1..f66c7e3d405 100644 --- a/storage/innobase/include/dyn0buf.h +++ b/storage/innobase/include/dyn0buf.h @@ -303,8 +303,7 @@ public: #ifdef UNIV_DEBUG ulint total_size = 0; - for (typename list_t::iterator it = m_list.begin(), - end = m_list.end(); + for (list_t::iterator it = m_list.begin(), end = m_list.end(); it != end; ++it) { total_size += it->used(); } @@ -320,8 +319,7 @@ public: template bool for_each_block(Functor& functor) const { - for (typename list_t::iterator it = m_list.begin(), - end = m_list.end(); + for (list_t::iterator it = m_list.begin(), end = m_list.end(); it != end; ++it) { if (!functor(&*it)) { @@ -338,8 +336,8 @@ public: template bool for_each_block_in_reverse(Functor& functor) const { - for (typename list_t::reverse_iterator it = m_list.rbegin(), - end = m_list.rend(); + for (list_t::reverse_iterator it = m_list.rbegin(), + end = m_list.rend(); it != end; ++it) { if (!functor(&*it)) { @@ -356,8 +354,8 @@ public: template bool for_each_block_in_reverse(const Functor& functor) const { - for (typename list_t::reverse_iterator it = m_list.rbegin(), - end = m_list.rend(); + for (list_t::reverse_iterator it = m_list.rbegin(), + end = m_list.rend(); it != end; ++it) { if (!functor(&*it)) { @@ -425,8 +423,7 @@ private: { ut_ad(!m_list.empty()); - for (typename list_t::iterator it = m_list.begin(), - end = m_list.end(); + for (list_t::iterator it = m_list.begin(), end = m_list.end(); it != end; ++it) { if (pos < it->used()) { -- cgit v1.2.1 From 3e38d15585f03e794a83a1d141ead33e8c878f27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 17 Jan 2020 10:37:25 +0200 Subject: MDEV-21509 Possible hang during purge of history, or rollback WL#6326 in MariaDB 10.2.2 introduced a potential hang on purge or rollback when an index tree is being shrunk by multiple levels. This fix is based on mysql/mysql-server@f2c58526300c0d84837effa26d37cbd5d2694967 with the main difference that our version of the test case uses DEBUG_SYNC instrumentation on ROLLBACK, not on purge. btr_cur_will_modify_tree(): Simplify the check further. This is the actual bug fix. row_undo_mod_remove_clust_low(), row_undo_mod_clust(): Add DEBUG_SYNC instrumentation for the test case. --- storage/innobase/include/page0page.h | 20 ++++++++++++++++++-- storage/innobase/include/page0page.ic | 24 ++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index 87de16f9abf..54edf034ac6 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2019, MariaDB Corporation. +Copyright (c) 1994, 2019, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2013, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -813,6 +813,22 @@ page_rec_is_last( const page_t* page) /*!< in: page */ MY_ATTRIBUTE((warn_unused_result)); +/************************************************************//** +true if distance between the records (measured in number of times we have to +move to the next record) is at most the specified value +@param[in] left_rec lefter record +@param[in] right_rec righter record +@param[in] val specified value to compare +@return true if the distance is smaller than the value */ +UNIV_INLINE +bool +page_rec_distance_is_at_most( +/*=========================*/ + const rec_t* left_rec, + const rec_t* right_rec, + ulint val) + MY_ATTRIBUTE((warn_unused_result)); + /************************************************************//** true if the record is the second last user record on a page. @return true if the second last user record */ diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic index 98b518187b5..75bfa56e2a6 100644 --- a/storage/innobase/include/page0page.ic +++ b/storage/innobase/include/page0page.ic @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2019, MariaDB Corporation. +Copyright (c) 1994, 2019, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2016, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -358,6 +358,26 @@ page_rec_is_last( return(page_rec_get_next_const(rec) == page_get_supremum_rec(page)); } +/************************************************************//** +true if distance between the records (measured in number of times we have to +move to the next record) is at most the specified value */ +UNIV_INLINE +bool +page_rec_distance_is_at_most( +/*=========================*/ + const rec_t* left_rec, + const rec_t* right_rec, + ulint val) +{ + for (ulint i = 0; i <= val; i++) { + if (left_rec == right_rec) { + return (true); + } + left_rec = page_rec_get_next_const(left_rec); + } + return (false); +} + /************************************************************//** true if the record is the second last user record on a page. @return true if the second last user record */ -- cgit v1.2.1 From 5838b52743423a2f9cf8d1a80e21c502cd308604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 17 Jan 2020 10:46:33 +0200 Subject: MDEV-21511 Wrong estimate of affected BLOB columns in update During update, rollback, or MVCC read, we may miscalculate the number of off-page columns, and thus the size of the clustered index record. The function btr_push_update_extern_fields() is mostly redundant, because the off-page columns would also be moved by row_upd_index_replace_new_col_val(), which is invoked via row_upd_index_replace_new_col_vals(). btr_push_update_extern_fields(): Remove. This is based on mysql/mysql-server@1fa475b85d24de4b9ce2958c0eed738c221fc82c which refines a fix for a recovery bug fix mysql/mysql-server@ce0a1e85e24e48b8171f767b44330da635a6ea0a in MySQL 5.7.5. No test case was provided by Oracle. Some of the changed code is being covered by the existing test innodb.blob-crash. --- storage/innobase/include/btr0cur.h | 16 ++-------------- storage/innobase/include/rem0rec.ic | 5 +++-- 2 files changed, 5 insertions(+), 16 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h index 0f2fd48004b..63338579064 100644 --- a/storage/innobase/include/btr0cur.h +++ b/storage/innobase/include/btr0cur.h @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 1994, 2019, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -755,18 +755,6 @@ btr_rec_copy_externally_stored_field( ulint* len, mem_heap_t* heap); -/*******************************************************************//** -Flags the data tuple fields that are marked as extern storage in the -update vector. We use this function to remember which fields we must -mark as extern storage in a record inserted for an update. -@return number of flagged external columns */ -ulint -btr_push_update_extern_fields( -/*==========================*/ - dtuple_t* tuple, /*!< in/out: data tuple */ - const upd_t* update, /*!< in: update vector */ - mem_heap_t* heap) /*!< in: memory heap */ - MY_ATTRIBUTE((nonnull)); /***********************************************************//** Sets a secondary index record's delete mark to the given value. This function is only used by the insert buffer merge mechanism. */ diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic index 27df29e61d6..7a9b31648da 100644 --- a/storage/innobase/include/rem0rec.ic +++ b/storage/innobase/include/rem0rec.ic @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 1994, 2019, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1626,6 +1626,7 @@ rec_get_converted_size( data_size = dtuple_get_data_size(dtuple, 0); + ut_ad(n_ext == dtuple_get_n_ext(dtuple)); extra_size = rec_get_converted_extra_size( data_size, dtuple_get_n_fields(dtuple), n_ext); -- cgit v1.2.1 From c3695b4058ea9a8849c22aabeabc76448fe548f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 17 Jan 2020 11:11:19 +0200 Subject: MDEV-21511: Remove unnecessary code Now that we will be invoking dtuple_get_n_ext() instead of letting btr_push_update_extern_fields() update an already calculated value, it is unnecessary to calculate the n_ext upfront. row_rec_to_index_entry(), row_rec_to_index_entry_low(): Remove the output parameter n_ext. --- storage/innobase/include/row0row.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/row0row.h b/storage/innobase/include/row0row.h index a4d3f2cf03d..b7030e91098 100644 --- a/storage/innobase/include/row0row.h +++ b/storage/innobase/include/row0row.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2017, MariaDB Corporation. +Copyright (c) 2016, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -207,8 +207,6 @@ row_rec_to_index_entry_low( const rec_t* rec, /*!< in: record in the index */ const dict_index_t* index, /*!< in: index */ const offset_t* offsets,/*!< in: rec_get_offsets(rec, index) */ - ulint* n_ext, /*!< out: number of externally - stored columns */ mem_heap_t* heap) /*!< in: memory heap from which the memory needed is allocated */ MY_ATTRIBUTE((warn_unused_result)); @@ -222,8 +220,6 @@ row_rec_to_index_entry( const rec_t* rec, /*!< in: record in the index */ const dict_index_t* index, /*!< in: index */ const offset_t* offsets,/*!< in/out: rec_get_offsets(rec) */ - ulint* n_ext, /*!< out: number of externally - stored columns */ mem_heap_t* heap) /*!< in: memory heap from which the memory needed is allocated */ MY_ATTRIBUTE((warn_unused_result)); -- cgit v1.2.1 From 457ce97ef2868c19fc8c9b7d6cd3d12bb78becf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 17 Jan 2020 13:13:03 +0200 Subject: MDEV-21512 InnoDB may hang due to SPATIAL INDEX MySQL 5.7.29 includes the following fix: Bug #30287668 INNODB: A LONG SEMAPHORE WAIT mysql/mysql-server@5cdbb22b51cf2b35dbdf5666a251ffbec2f84dec There is no test case. It seems that the problem could occur when a spatial index is large and peculiar enough so that multiple R-tree leaf pages will have the exactly same maximum bounding rectangle (MBR). The commit message suggests that the hang can occur when R-tree non-leaf pages are being merged, which should only be possible during transaction rollback or the purge of transaction history, when the R-tree index is at least 2 levels high and very many records are being deleted. The message says that a comparison result that two spatial index node pointer records are equal will cause an infinite loop in rtr_page_copy_rec_list_end_no_locks(). Hence, we must include the child page number in the comparison to be consistent with mysql/mysql-server@2e11fe0e152e34d73579e1a9ec19aedc3f6010f6. We fix this bug in a simpler way, involving fewer code changes. cmp_rec_rec(): Renamed from cmp_rec_rec_with_match(). Assert that rec2 always resides in an index page. Treat non-leaf spatial index pages specially. --- storage/innobase/include/rem0cmp.h | 48 ++++++++++++------------------------- storage/innobase/include/rem0cmp.ic | 35 +-------------------------- 2 files changed, 16 insertions(+), 67 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/rem0cmp.h b/storage/innobase/include/rem0cmp.h index 0877c7b5b6a..af1b145b0d9 100644 --- a/storage/innobase/include/rem0cmp.h +++ b/storage/innobase/include/rem0cmp.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -80,7 +80,7 @@ cmp_dfield_dfield( /** Compare a GIS data tuple to a physical record. @param[in] dtuple data tuple -@param[in] rec B-tree record +@param[in] rec R-tree record @param[in] offsets rec_get_offsets(rec) @param[in] mode compare mode @retval negative if dtuple is less than rec */ @@ -190,43 +190,23 @@ cmp_rec_rec_simple( duplicate key value if applicable, or NULL */ MY_ATTRIBUTE((nonnull(1,2,3,4), warn_unused_result)); -/** Compare two B-tree records. -@param[in] rec1 B-tree record -@param[in] rec2 B-tree record -@param[in] offsets1 rec_get_offsets(rec1, index) -@param[in] offsets2 rec_get_offsets(rec2, index) -@param[in] index B-tree index -@param[in] nulls_unequal true if this is for index cardinality -statistics estimation, and innodb_stats_method=nulls_unequal -or innodb_stats_method=nulls_ignored -@param[out] matched_fields number of completely matched fields -within the first field not completely matched -@return the comparison result -@retval 0 if rec1 is equal to rec2 -@retval negative if rec1 is less than rec2 -@retval positive if rec2 is greater than rec2 */ -int -cmp_rec_rec_with_match( - const rec_t* rec1, - const rec_t* rec2, - const offset_t* offsets1, - const offset_t* offsets2, - const dict_index_t* index, - bool nulls_unequal, - ulint* matched_fields); -/** Compare two B-tree records. +/** Compare two B-tree or R-tree records. Only the common first fields are compared, and externally stored field are treated as equal. -@param[in] rec1 B-tree record -@param[in] rec2 B-tree record +@param[in] rec1 record (possibly not on an index page) +@param[in] rec2 B-tree or R-tree record in an index page @param[in] offsets1 rec_get_offsets(rec1, index) @param[in] offsets2 rec_get_offsets(rec2, index) +@param[in] nulls_unequal true if this is for index cardinality + statistics estimation with + innodb_stats_method=nulls_unequal + or innodb_stats_method=nulls_ignored @param[out] matched_fields number of completely matched fields within the first field not completely matched -@return positive, 0, negative if rec1 is greater, equal, less, than rec2, -respectively */ -UNIV_INLINE +@retval 0 if rec1 is equal to rec2 +@retval negative if rec1 is less than rec2 +@retval positive if rec1 is greater than rec2 */ int cmp_rec_rec( const rec_t* rec1, @@ -234,7 +214,9 @@ cmp_rec_rec( const offset_t* offsets1, const offset_t* offsets2, const dict_index_t* index, - ulint* matched_fields = NULL); + bool nulls_unequal = false, + ulint* matched_fields = NULL) + MY_ATTRIBUTE((nonnull(1,2,3,4,5))); /** Compare two data fields. @param[in] dfield1 data field diff --git a/storage/innobase/include/rem0cmp.ic b/storage/innobase/include/rem0cmp.ic index 5ac3838f244..4230543615a 100644 --- a/storage/innobase/include/rem0cmp.ic +++ b/storage/innobase/include/rem0cmp.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -52,40 +53,6 @@ cmp_dfield_dfield( dfield_get_len(dfield2))); } -/** Compare two B-tree records. -Only the common first fields are compared, and externally stored field -are treated as equal. -@param[in] rec1 B-tree record -@param[in] rec2 B-tree record -@param[in] offsets1 rec_get_offsets(rec1, index) -@param[in] offsets2 rec_get_offsets(rec2, index) -@param[out] matched_fields number of completely matched fields - within the first field not completely matched -@return positive, 0, negative if rec1 is greater, equal, less, than rec2, -respectively */ -UNIV_INLINE -int -cmp_rec_rec( - const rec_t* rec1, - const rec_t* rec2, - const offset_t* offsets1, - const offset_t* offsets2, - const dict_index_t* index, - ulint* matched_fields) -{ - ulint match_f; - int ret; - - ret = cmp_rec_rec_with_match( - rec1, rec2, offsets1, offsets2, index, false, &match_f); - - if (matched_fields != NULL) { - *matched_fields = match_f; - } - - return(ret); -} - /** Compare two data fields. @param[in] dfield1 data field @param[in] dfield2 data field -- cgit v1.2.1 From bd36a4ca12159a22ae5512857fa140475fccf22b Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Thu, 30 Jan 2020 13:11:06 +0800 Subject: introduce HASH_REPLACE() for hash_table_t HASH_REPLACE(): allows to not travel through linked list twice when HASH_INSERT() happens right after HASH_DELETE() --- storage/innobase/include/hash0hash.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/hash0hash.h b/storage/innobase/include/hash0hash.h index 5d317a23d4e..4f55b051d80 100644 --- a/storage/innobase/include/hash0hash.h +++ b/storage/innobase/include/hash0hash.h @@ -184,6 +184,18 @@ do {\ HASH_INVALIDATE(DATA, NAME);\ } while (0) +#define HASH_REPLACE(TYPE, NAME, TABLE, FOLD, DATA_OLD, DATA_NEW) \ + do { \ + (DATA_NEW)->NAME = (DATA_OLD)->NAME; \ + \ + hash_cell_t& cell3333 \ + = TABLE->array[hash_calc_hash(FOLD, TABLE)]; \ + TYPE** struct3333 = (TYPE**)&cell3333.node; \ + while (*struct3333 != DATA_OLD) { \ + struct3333 = &((*struct3333)->NAME); \ + } \ + *struct3333 = DATA_NEW; \ + } while (0) /*******************************************************************//** Gets the first struct in a hash chain, NULL if none. */ -- cgit v1.2.1 From a9d1324867075fd3c014d4382a48b5af29e77724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 3 Feb 2020 12:10:59 +0200 Subject: Cleanup: Remove mem_block_t::magic_n and mem_block_validate() Use of freed memory is better caught by AddressSanitizer, especially with ASAN_POISON_MEMORY_REGION that is aliased by MEM_NOACCESS and UNIV_MEM_FREE. --- storage/innobase/include/mem0mem.h | 11 ----------- storage/innobase/include/mem0mem.ic | 28 ++-------------------------- 2 files changed, 2 insertions(+), 37 deletions(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/mem0mem.h b/storage/innobase/include/mem0mem.h index 22c0a04e170..0cd15ebb261 100644 --- a/storage/innobase/include/mem0mem.h +++ b/storage/innobase/include/mem0mem.h @@ -287,13 +287,6 @@ mem_heap_printf( const char* format, /*!< in: format string */ ...) MY_ATTRIBUTE ((format (printf, 2, 3))); -/** Checks that an object is a memory heap (or a block of it) -@param[in] heap Memory heap to check */ -UNIV_INLINE -void -mem_block_validate( - const mem_heap_t* heap); - #ifdef UNIV_DEBUG /** Validates the contents of a memory heap. Asserts that the memory heap is consistent @@ -308,7 +301,6 @@ mem_heap_validate( /** The info structure stored at the beginning of a heap block */ struct mem_block_info_t { - ulint magic_n;/* magic number for debugging */ #ifdef UNIV_DEBUG char file_name[8];/* file name where the mem heap was created */ unsigned line; /*!< line number where the mem heap was created */ @@ -343,9 +335,6 @@ struct mem_block_info_t { otherwise, this is NULL */ }; -#define MEM_BLOCK_MAGIC_N 764741555 -#define MEM_FREED_BLOCK_MAGIC_N 547711122 - /* Header size for a memory heap block */ #define MEM_BLOCK_HEADER_SIZE UT_CALC_ALIGN(sizeof(mem_block_info_t),\ UNIV_MEM_ALIGNMENT) diff --git a/storage/innobase/include/mem0mem.ic b/storage/innobase/include/mem0mem.ic index a44f2ff45fa..9c7ae8c28f8 100644 --- a/storage/innobase/include/mem0mem.ic +++ b/storage/innobase/include/mem0mem.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -144,16 +144,6 @@ mem_block_get_start(mem_block_t* block) return(block->start); } -/** Checks that an object is a memory heap block -@param[in] block Memory block to check. */ -UNIV_INLINE -void -mem_block_validate( - const mem_block_t* block) -{ - ut_a(block->magic_n == MEM_BLOCK_MAGIC_N); -} - /** Allocates and zero-fills n bytes of memory from a memory heap. @param[in] heap memory heap @param[in] n number of bytes; if the heap is allowed to grow into @@ -186,8 +176,6 @@ mem_heap_alloc( byte* buf; ulint free; - ut_d(mem_block_validate(heap)); - block = UT_LIST_GET_LAST(heap->base); n += REDZONE_SIZE; @@ -230,8 +218,6 @@ mem_heap_get_heap_top( mem_block_t* block; byte* buf; - ut_d(mem_block_validate(heap)); - block = UT_LIST_GET_LAST(heap->base); buf = (byte*) block + mem_block_get_free(block); @@ -321,8 +307,6 @@ mem_heap_get_top( mem_block_t* block; byte* buf; - ut_d(mem_block_validate(heap)); - block = UT_LIST_GET_LAST(heap->base); buf = (byte*) block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n); @@ -342,8 +326,6 @@ mem_heap_free_top( { mem_block_t* block; - ut_d(mem_block_validate(heap)); - n += REDZONE_SIZE; block = UT_LIST_GET_LAST(heap->base); @@ -419,8 +401,6 @@ mem_heap_free( mem_block_t* block; mem_block_t* prev_block; - ut_d(mem_block_validate(heap)); - block = UT_LIST_GET_LAST(heap->base); if (heap->free_block) { @@ -447,11 +427,7 @@ mem_heap_get_size( /*==============*/ mem_heap_t* heap) /*!< in: heap */ { - ulint size = 0; - - ut_d(mem_block_validate(heap)); - - size = heap->total_size; + ulint size = heap->total_size; if (heap->free_block) { size += UNIV_PAGE_SIZE; -- cgit v1.2.1 From 3be751d5b9076239baaa07677ab81304fcd92207 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 7 Feb 2020 16:01:31 +0530 Subject: MDEV-21608 Assertion `n_ext == dtuple_get_n_ext(dtuple)' failed during updation of PK - n_ext value may be less than dtuple_get_n_ext(dtuple) when PK is being updated and new record inherits the externally stored fields from delete mark old record. --- storage/innobase/include/rem0rec.ic | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'storage/innobase/include') diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic index 7a9b31648da..eae1c52a2a5 100644 --- a/storage/innobase/include/rem0rec.ic +++ b/storage/innobase/include/rem0rec.ic @@ -1626,7 +1626,11 @@ rec_get_converted_size( data_size = dtuple_get_data_size(dtuple, 0); - ut_ad(n_ext == dtuple_get_n_ext(dtuple)); + /* If primary key is being updated then the new record inherits + externally stored fields from the delete-marked old record. + In that case, n_ext may be less value than + dtuple_get_n_ext(tuple). */ + ut_ad(n_ext <= dtuple_get_n_ext(dtuple)); extra_size = rec_get_converted_extra_size( data_size, dtuple_get_n_fields(dtuple), n_ext); -- cgit v1.2.1