diff options
Diffstat (limited to 'storage/innobase')
43 files changed, 498 insertions, 722 deletions
diff --git a/storage/innobase/buf/buf0buddy.cc b/storage/innobase/buf/buf0buddy.cc index 3b784494fda..a41345b43ab 100644 --- a/storage/innobase/buf/buf0buddy.cc +++ b/storage/innobase/buf/buf0buddy.cc @@ -171,13 +171,13 @@ buf_buddy_get( struct CheckZipFree { CheckZipFree(ulint i) : m_i(i) {} - void operator()(const buf_buddy_free_t* elem) const + void operator()(const buf_buddy_free_t* elem) const { - ut_a(buf_buddy_stamp_is_free(elem)); - ut_a(elem->stamp.size <= m_i); + ut_ad(buf_buddy_stamp_is_free(elem)); + ut_ad(elem->stamp.size <= m_i); } - ulint m_i; + const ulint m_i; }; /** Validate a buddy list. @@ -189,8 +189,7 @@ buf_buddy_list_validate( const buf_pool_t* buf_pool, ulint i) { - CheckZipFree check(i); - ut_list_validate(buf_pool->zip_free[i], check); + ut_list_validate(buf_pool->zip_free[i], CheckZipFree(i)); } /**********************************************************************//** diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 744b0cb5060..fb3d4d96003 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -325,7 +325,7 @@ too_small: mtr_commit(&mtr); /* Flush the modified pages to disk and make a checkpoint */ - log_make_checkpoint_at(LSN_MAX, TRUE); + log_make_checkpoint_at(LSN_MAX); /* Remove doublewrite pages from LRU */ buf_pool_invalidate(); diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 9631102f455..6e3d1fa7356 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -3528,7 +3528,7 @@ buf_flush_request_force( /** Functor to validate the flush list. */ struct Check { - void operator()(const buf_page_t* elem) + void operator()(const buf_page_t* elem) const { ut_a(elem->in_flush_list); } @@ -3545,11 +3545,10 @@ buf_flush_validate_low( { buf_page_t* bpage; const ib_rbt_node_t* rnode = NULL; - Check check; ut_ad(buf_flush_list_mutex_own(buf_pool)); - ut_list_validate(buf_pool->flush_list, check); + ut_list_validate(buf_pool->flush_list, Check()); bpage = UT_LIST_GET_FIRST(buf_pool->flush_list); diff --git a/storage/innobase/data/data0data.cc b/storage/innobase/data/data0data.cc index 2629e753b5c..8b1966443c9 100644 --- a/storage/innobase/data/data0data.cc +++ b/storage/innobase/data/data0data.cc @@ -37,7 +37,7 @@ Created 5/30/1994 Heikki Tuuri /** Dummy variable to catch access to uninitialized fields. In the debug version, dtuple_create() will make all fields of dtuple_t point to data_error. */ -byte data_error; +ut_d(byte data_error); #endif /* UNIV_DEBUG */ /** Trim the tail of an index tuple before insert or update. @@ -455,7 +455,7 @@ dfield_print_also_hex( break; } - data = static_cast<byte*>(dfield_get_data(dfield)); + data = static_cast<const byte*>(dfield_get_data(dfield)); /* fall through */ case DATA_BINARY: diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 7a6d21dba13..b242b57714f 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -417,45 +417,6 @@ fil_space_crypt_t::write_page0( } /****************************************************************** -Set crypt data for a tablespace -@param[in,out] space Tablespace -@param[in,out] crypt_data Crypt data to be set -@return crypt_data in tablespace */ -static -fil_space_crypt_t* -fil_space_set_crypt_data( - fil_space_t* space, - fil_space_crypt_t* crypt_data) -{ - fil_space_crypt_t* free_crypt_data = NULL; - fil_space_crypt_t* ret_crypt_data = NULL; - - /* Provided space is protected using fil_space_acquire() - from concurrent operations. */ - if (space->crypt_data != NULL) { - /* There is already crypt data present, - merge new crypt_data */ - fil_space_merge_crypt_data(space->crypt_data, - crypt_data); - ret_crypt_data = space->crypt_data; - free_crypt_data = crypt_data; - } else { - space->crypt_data = crypt_data; - ret_crypt_data = space->crypt_data; - } - - if (free_crypt_data != NULL) { - /* there was already crypt data present and the new crypt - * data provided as argument to this function has been merged - * into that => free new crypt data - */ - fil_space_destroy_crypt_data(&free_crypt_data); - } - - return ret_crypt_data; -} - -/****************************************************************** Parse a MLOG_FILE_WRITE_CRYPT_DATA log entry @param[in] ptr Log entry start @param[in] end_ptr Log entry end @@ -512,26 +473,36 @@ fil_parse_write_crypt_data( return NULL; } - fil_space_crypt_t* crypt_data = fil_space_create_crypt_data(encryption, key_id); - /* Need to overwrite these as above will initialize fields. */ + mutex_enter(&fil_system.mutex); + + fil_space_t* space = fil_space_get_by_id(space_id); + + if (!space) { + mutex_exit(&fil_system.mutex); + return ptr + len; + } + + fil_space_crypt_t* crypt_data = fil_space_create_crypt_data( + encryption, key_id); + crypt_data->page0_offset = offset; crypt_data->min_key_version = min_key_version; - crypt_data->encryption = encryption; crypt_data->type = type; memcpy(crypt_data->iv, ptr, len); ptr += len; - /* update fil_space memory cache with crypt_data */ - if (fil_space_t* space = fil_space_acquire_silent(space_id)) { - crypt_data = fil_space_set_crypt_data(space, crypt_data); - space->release(); - /* Check is used key found from encryption plugin */ - if (crypt_data->should_encrypt() - && !crypt_data->is_key_found()) { - *err = DB_DECRYPTION_FAILED; - } - } else { + if (space->crypt_data) { + fil_space_merge_crypt_data(space->crypt_data, crypt_data); fil_space_destroy_crypt_data(&crypt_data); + crypt_data = space->crypt_data; + } else { + space->crypt_data = crypt_data; + } + + mutex_exit(&fil_system.mutex); + + if (crypt_data->should_encrypt() && !crypt_data->is_key_found()) { + *err = DB_DECRYPTION_FAILED; } return ptr; @@ -1138,11 +1109,15 @@ fil_crypt_needs_rotation( if (crypt_data->encryption == FIL_ENCRYPTION_DEFAULT && crypt_data->type == CRYPT_SCHEME_1 - && srv_encrypt_tables == 0 ) { + && !srv_encrypt_tables) { /* This is rotation encrypted => unencrypted */ return true; } + if (rotate_key_age == 0) { + return false; + } + /* this is rotation encrypted => encrypted, * only reencrypt if key is sufficiently old */ if (key_version + rotate_key_age < latest_key_version) { @@ -1225,7 +1200,8 @@ fil_crypt_start_encrypting_space( * crypt data in page 0 */ /* 1 - create crypt data */ - crypt_data = fil_space_create_crypt_data(FIL_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY); + crypt_data = fil_space_create_crypt_data( + FIL_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY); if (crypt_data == NULL) { mutex_exit(&fil_crypt_threads_mutex); @@ -1238,9 +1214,9 @@ fil_crypt_start_encrypting_space( crypt_data->rotate_state.starting = true; crypt_data->rotate_state.active_threads = 1; - mutex_enter(&crypt_data->mutex); - crypt_data = fil_space_set_crypt_data(space, crypt_data); - mutex_exit(&crypt_data->mutex); + mutex_enter(&fil_system.mutex); + space->crypt_data = crypt_data; + mutex_exit(&fil_system.mutex); fil_crypt_start_converting = true; mutex_exit(&fil_crypt_threads_mutex); @@ -2505,6 +2481,64 @@ fil_crypt_set_thread_cnt( } } +/** Initialize the tablespace rotation_list +if innodb_encryption_rotate_key_age=0. */ +static void fil_crypt_rotation_list_fill() +{ + ut_ad(mutex_own(&fil_system.mutex)); + + for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list); + space != NULL; + space = UT_LIST_GET_NEXT(space_list, space)) { + if (space->purpose != FIL_TYPE_TABLESPACE + || space->is_in_rotation_list() + || space->is_stopping() + || UT_LIST_GET_LEN(space->chain) == 0) { + continue; + } + + /* Ensure that crypt_data has been initialized. */ + if (!space->size) { + /* Protect the tablespace while we may + release fil_system.mutex. */ + space->n_pending_ops++; + fil_space_t* s= fil_system.read_page0( + space->id); + ut_ad(!s || s == space); + space->n_pending_ops--; + if (!space->size) { + /* Page 0 was not loaded. + Skip this tablespace. */ + continue; + } + } + + /* Skip ENCRYPTION!=DEFAULT tablespaces. */ + if (space->crypt_data + && !space->crypt_data->is_default_encryption()) { + continue; + } + + if (srv_encrypt_tables) { + /* Skip encrypted tablespaces if + innodb_encrypt_tables!=OFF */ + if (space->crypt_data + && space->crypt_data->min_key_version) { + continue; + } + } else { + /* Skip unencrypted tablespaces if + innodb_encrypt_tables=OFF */ + if (!space->crypt_data + || !space->crypt_data->min_key_version) { + continue; + } + } + + UT_LIST_ADD_LAST(fil_system.rotation_list, space); + } +} + /********************************************************************* Adjust max key age @param[in] val New max key age */ @@ -2513,7 +2547,12 @@ void fil_crypt_set_rotate_key_age( uint val) { + mutex_enter(&fil_system.mutex); srv_fil_crypt_rotate_key_age = val; + if (val == 0) { + fil_crypt_rotation_list_fill(); + } + mutex_exit(&fil_system.mutex); os_event_set(fil_crypt_threads_event); } @@ -2537,7 +2576,16 @@ void fil_crypt_set_encrypt_tables( uint val) { + mutex_enter(&fil_system.mutex); + srv_encrypt_tables = val; + + if (srv_fil_crypt_rotate_key_age == 0) { + fil_crypt_rotation_list_fill(); + } + + mutex_exit(&fil_system.mutex); + os_event_set(fil_crypt_threads_event); } diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 1f13e2abfcc..f02f304a858 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -327,6 +327,7 @@ fil_space_get_by_id( { fil_space_t* space; + ut_ad(fil_system.is_initialised()); ut_ad(mutex_own(&fil_system.mutex)); HASH_SEARCH(hash, fil_system.spaces, id, @@ -1358,6 +1359,47 @@ fil_assign_new_space_id( return(success); } +/** Trigger a call to fil_node_t::read_page0() +@param[in] id tablespace identifier +@return tablespace +@retval NULL if the tablespace does not exist or cannot be read */ +fil_space_t* fil_system_t::read_page0(ulint id) +{ + mutex_exit(&mutex); + + ut_ad(id != 0); + + /* It is possible that the tablespace is dropped while we are + not holding the mutex. */ + fil_mutex_enter_and_prepare_for_io(id); + + fil_space_t* space = fil_space_get_by_id(id); + + if (space == NULL || UT_LIST_GET_LEN(space->chain) == 0) { + return(NULL); + } + + /* The following code must change when InnoDB supports + multiple datafiles per tablespace. */ + ut_a(1 == UT_LIST_GET_LEN(space->chain)); + + fil_node_t* node = UT_LIST_GET_FIRST(space->chain); + + /* It must be a single-table tablespace and we have not opened + the file yet; the following calls will open it and update the + size fields */ + + if (!fil_node_prepare_for_io(node, space)) { + /* The single-table tablespace can't be opened, + because the ibd file is missing. */ + return(NULL); + } + + fil_node_complete_io(node, IORequestRead); + + return space; +} + /*******************************************************************//** Returns a pointer to the fil_space_t that is in the memory cache associated with a space id. The caller must lock fil_system.mutex. @@ -1368,12 +1410,7 @@ fil_space_get_space( /*================*/ ulint id) /*!< in: space id */ { - fil_space_t* space; - fil_node_t* node; - - ut_ad(fil_system.is_initialised()); - - space = fil_space_get_by_id(id); + fil_space_t* space = fil_space_get_by_id(id); if (space == NULL || space->size != 0) { return(space); } @@ -1384,41 +1421,7 @@ fil_space_get_space( case FIL_TYPE_TEMPORARY: case FIL_TYPE_TABLESPACE: case FIL_TYPE_IMPORT: - ut_a(id != 0); - - mutex_exit(&fil_system.mutex); - - /* It is possible that the space gets evicted at this point - before the fil_mutex_enter_and_prepare_for_io() acquires - the fil_system.mutex. Check for this after completing the - call to fil_mutex_enter_and_prepare_for_io(). */ - fil_mutex_enter_and_prepare_for_io(id); - - /* We are still holding the fil_system.mutex. Check if - the space is still in memory cache. */ - space = fil_space_get_by_id(id); - - if (space == NULL || UT_LIST_GET_LEN(space->chain) == 0) { - return(NULL); - } - - /* The following code must change when InnoDB supports - multiple datafiles per tablespace. */ - ut_a(1 == UT_LIST_GET_LEN(space->chain)); - - node = UT_LIST_GET_FIRST(space->chain); - - /* It must be a single-table tablespace and we have not opened - the file yet; the following calls will open it and update the - size fields */ - - if (!fil_node_prepare_for_io(node, space)) { - /* The single-table tablespace can't be opened, - because the ibd file is missing. */ - return(NULL); - } - - fil_node_complete_io(node, IORequestRead); + space = fil_system.read_page0(id); } return(space); @@ -4587,7 +4590,7 @@ fil_validate(void) ut_a(fil_system.n_open == n_open); - UT_LIST_CHECK(fil_system.LRU); + ut_list_validate(fil_system.LRU); for (fil_node = UT_LIST_GET_FIRST(fil_system.LRU); fil_node != 0; diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index d55cafa8ff2..128518d7433 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -3331,12 +3331,11 @@ fts_fetch_doc_from_tuple( const dict_field_t* ifield; const dict_col_t* col; ulint pos; - dfield_t* field; ifield = dict_index_get_nth_field(index, i); col = dict_field_get_col(ifield); pos = dict_col_get_no(col); - field = dtuple_get_nth_field(tuple, pos); + const dfield_t* field = dtuple_get_nth_field(tuple, pos); if (!get_doc->index_cache->charset) { get_doc->index_cache->charset = fts_get_charset( diff --git a/storage/innobase/gis/gis0geo.cc b/storage/innobase/gis/gis0geo.cc index 71d637d62d5..fabe39834f7 100644 --- a/storage/innobase/gis/gis0geo.cc +++ b/storage/innobase/gis/gis0geo.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2015, 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 @@ -69,9 +70,9 @@ static int rtree_add_point_to_mbr( /*===================*/ - uchar** wkb, /*!< in: pointer to wkb, + const uchar** wkb, /*!< in: pointer to wkb, where point is stored */ - uchar* end, /*!< in: end of wkb. */ + const uchar* end, /*!< in: end of wkb. */ uint n_dims, /*!< in: dimensions. */ double* mbr) /*!< in/out: mbr, which must be of length n_dims * 2. */ @@ -108,9 +109,9 @@ static int rtree_get_point_mbr( /*================*/ - uchar** wkb, /*!< in: pointer to wkb, + const uchar** wkb, /*!< in: pointer to wkb, where point is stored. */ - uchar* end, /*!< in: end of wkb. */ + const uchar* end, /*!< in: end of wkb. */ uint n_dims, /*!< in: dimensions. */ double* mbr) /*!< in/out: mbr, must be of length n_dims * 2. */ @@ -126,9 +127,9 @@ static int rtree_get_linestring_mbr( /*=====================*/ - uchar** wkb, /*!< in: pointer to wkb, + const uchar** wkb, /*!< in: pointer to wkb, where point is stored. */ - uchar* end, /*!< in: end of wkb. */ + const uchar* end, /*!< in: end of wkb. */ uint n_dims, /*!< in: dimensions. */ double* mbr) /*!< in/out: mbr, must be of length n_dims * 2. */ @@ -155,9 +156,9 @@ static int rtree_get_polygon_mbr( /*==================*/ - uchar** wkb, /*!< in: pointer to wkb, + const uchar** wkb, /*!< in: pointer to wkb, where point is stored. */ - uchar* end, /*!< in: end of wkb. */ + const uchar* end, /*!< in: end of wkb. */ uint n_dims, /*!< in: dimensions. */ double* mbr) /*!< in/out: mbr, must be of length n_dims * 2. */ @@ -190,9 +191,9 @@ static int rtree_get_geometry_mbr( /*===================*/ - uchar** wkb, /*!< in: pointer to wkb, + const uchar** wkb, /*!< in: pointer to wkb, where point is stored. */ - uchar* end, /*!< in: end of wkb. */ + const uchar* end, /*!< in: end of wkb. */ uint n_dims, /*!< in: dimensions. */ double* mbr, /*!< in/out: mbr. */ int top) /*!< in: if it is the top, @@ -287,7 +288,7 @@ stored in "well-known binary representation" (wkb) format. int rtree_mbr_from_wkb( /*===============*/ - uchar* wkb, /*!< in: wkb */ + const uchar* wkb, /*!< in: wkb */ uint size, /*!< in: size of wkb. */ uint n_dims, /*!< in: dimensions. */ double* mbr) /*!< in/out: mbr, which must diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc index d77e29d308e..3f9812928a4 100644 --- a/storage/innobase/gis/gis0rtree.cc +++ b/storage/innobase/gis/gis0rtree.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, MariaDB Corporation. +Copyright (c) 2018, 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 @@ -66,7 +66,7 @@ rtr_page_split_initialize_nodes( page_t* page; ulint n_uniq; ulint len; - byte* source_cur; + const byte* source_cur; block = btr_cur_get_block(cursor); page = buf_block_get_frame(block); @@ -106,7 +106,7 @@ rtr_page_split_initialize_nodes( } /* Put the insert key to node list */ - source_cur = static_cast<byte*>(dfield_get_data( + source_cur = static_cast<const byte*>(dfield_get_data( dtuple_get_nth_field(tuple, 0))); cur->coords = reserve_coords(buf_pos, SPDIMS); rec = (byte*) mem_heap_alloc( @@ -1855,11 +1855,10 @@ rtr_estimate_n_rows_in_range( /* Read mbr from tuple. */ rtr_mbr_t range_mbr; double range_area; - const byte* range_mbr_ptr; const dfield_t* dtuple_field = dtuple_get_nth_field(tuple, 0); ut_ad(dfield_get_len(dtuple_field) >= DATA_MBR_LEN); - range_mbr_ptr = reinterpret_cast<const byte*>( + const byte* range_mbr_ptr = reinterpret_cast<const byte*>( dfield_get_data(dtuple_field)); rtr_read_mbr(range_mbr_ptr, &range_mbr); diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index 84d07b5ac52..913a299c118 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -1627,15 +1627,13 @@ rtr_get_mbr_from_tuple( { const dfield_t* dtuple_field; ulint dtuple_f_len; - byte* data; dtuple_field = dtuple_get_nth_field(dtuple, 0); dtuple_f_len = dfield_get_len(dtuple_field); ut_a(dtuple_f_len >= 4 * sizeof(double)); - data = static_cast<byte*>(dfield_get_data(dtuple_field)); - - rtr_read_mbr(data, mbr); + rtr_read_mbr(static_cast<const byte*>(dfield_get_data(dtuple_field)), + mbr); } /****************************************************************//** diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index dd79dceed0b..04fdb0ff3b2 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6159,9 +6159,9 @@ no_such_table: << n_cols << " user" " defined columns in InnoDB, but " << n_fields << " columns in MariaDB. Please check" - " INFORMATION_SCHEMA.INNODB_SYS_COLUMNS and " REFMAN - "innodb-troubleshooting.html for how to resolve the" - " issue."; + " INFORMATION_SCHEMA.INNODB_SYS_COLUMNS and" + " https://mariadb.com/kb/en/innodb-data-dictionary-troubleshooting/" + " for how to resolve the issue."; /* Mark this table as corrupted, so the drop table or force recovery can still use it, but not others. */ @@ -18348,7 +18348,7 @@ checkpoint_now_set(THD*, st_mysql_sys_var*, void*, const void* save) + (log_sys.append_on_checkpoint != NULL ? log_sys.append_on_checkpoint->size() : 0) < log_sys.lsn) { - log_make_checkpoint_at(LSN_MAX, TRUE); + log_make_checkpoint_at(LSN_MAX); fil_flush_file_spaces(FIL_TYPE_LOG); } @@ -20683,7 +20683,7 @@ void innobase_free_row_for_vcol(VCOL_STORAGE *storage) to store the value in passed in "my_rec" */ dfield_t* innobase_get_computed_value( - const dtuple_t* row, + dtuple_t* row, const dict_v_col_t* col, const dict_index_t* index, mem_heap_t** local_heap, @@ -21013,11 +21013,11 @@ ib_errf( /* Keep the first 16 characters as-is, since the url is sometimes used as an offset from this.*/ const char* TROUBLESHOOTING_MSG = - "Please refer to " REFMAN "innodb-troubleshooting.html" + "Please refer to https://mariadb.com/kb/en/innodb-troubleshooting/" " for how to resolve the issue."; const char* TROUBLESHOOT_DATADICT_MSG = - "Please refer to " REFMAN "innodb-troubleshooting-datadict.html" + "Please refer to https://mariadb.com/kb/en/innodb-data-dictionary-troubleshooting/" " for how to resolve the issue."; const char* BUG_REPORT_MSG = @@ -21028,9 +21028,6 @@ const char* FORCE_RECOVERY_MSG = "https://mariadb.com/kb/en/library/innodb-recovery-modes/" " for information about forcing recovery."; -const char* ERROR_CREATING_MSG = - "Please refer to " REFMAN "error-creating-innodb.html"; - const char* OPERATING_SYSTEM_ERROR_MSG = "Some operating system error numbers are described at" " https://mariadb.com/kb/en/library/operating-system-error-codes/"; @@ -21314,16 +21311,6 @@ innodb_encrypt_tables_validate( return 1; } - if (!srv_fil_crypt_rotate_key_age) { - const char *msg = (encrypt_tables ? "enable" : "disable"); - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - HA_ERR_UNSUPPORTED, - "InnoDB: cannot %s encryption, " - "innodb_encryption_rotate_key_age=0" - " i.e. key rotation disabled", msg); - return 1; - } - return 0; } @@ -21418,8 +21405,7 @@ ib_push_frm_error( " Have you mixed up " ".frm files from different " "installations? See " - REFMAN - "innodb-troubleshooting.html\n", + "https://mariadb.com/kb/en/innodb-troubleshooting/\n", ib_table->name.m_name); if (push_warning) { @@ -21462,8 +21448,7 @@ ib_push_frm_error( " Have you mixed up " ".frm files from different " "installations? See " - REFMAN - "innodb-troubleshooting.html\n", + "https://mariadb.com/kb/en/innodb-troubleshooting/\n", ib_table->name.m_name, n_keys, table->s->keys); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 729208dd04c..403dae8334d 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -10989,7 +10989,6 @@ ha_innobase::commit_inplace_alter_table( and the .frm files must be swapped manually by the administrator. No loss of data. */ DBUG_EXECUTE_IF("innodb_alter_commit_crash_after_commit", - log_make_checkpoint_at(LSN_MAX, TRUE); log_buffer_flush_to_disk(); DBUG_SUICIDE();); } diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index db9aa9d66fb..c6f693b1dc2 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -2500,8 +2500,7 @@ struct CheckInLRUList { static void validate(const buf_pool_t* buf_pool) { - CheckInLRUList check; - ut_list_validate(buf_pool->LRU, check); + ut_list_validate(buf_pool->LRU, CheckInLRUList()); } }; @@ -2514,8 +2513,7 @@ struct CheckInFreeList { static void validate(const buf_pool_t* buf_pool) { - CheckInFreeList check; - ut_list_validate(buf_pool->free, check); + ut_list_validate(buf_pool->free, CheckInFreeList()); } }; @@ -2528,8 +2526,8 @@ struct CheckUnzipLRUAndLRUList { static void validate(const buf_pool_t* buf_pool) { - CheckUnzipLRUAndLRUList check; - ut_list_validate(buf_pool->unzip_LRU, check); + ut_list_validate(buf_pool->unzip_LRU, + CheckUnzipLRUAndLRUList()); } }; #endif /* UNIV_DEBUG || defined UNIV_BUF_DEBUG */ diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h index 8505505270b..f4f3b3622c5 100644 --- a/storage/innobase/include/data0data.h +++ b/storage/innobase/include/data0data.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, 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 @@ -31,6 +31,7 @@ Created 5/30/1994 Heikki Tuuri #include "data0type.h" #include "mem0mem.h" #include "dict0types.h" +#include "btr0types.h" #include <ostream> @@ -39,29 +40,11 @@ index record which needs external storage of data fields */ struct big_rec_t; struct upd_t; -#ifdef UNIV_DEBUG -/*********************************************************************//** -Gets pointer to the type struct of SQL data field. -@return pointer to the type struct */ -UNIV_INLINE -dtype_t* -dfield_get_type( -/*============*/ - const dfield_t* field) /*!< in: SQL data field */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); -/*********************************************************************//** -Gets pointer to the data in a field. -@return pointer to data */ -UNIV_INLINE -void* -dfield_get_data( -/*============*/ - const dfield_t* field) /*!< in: field */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); -#else /* UNIV_DEBUG */ -# define dfield_get_type(field) (&(field)->type) -# define dfield_get_data(field) ((field)->data) -#endif /* UNIV_DEBUG */ +/** Dummy variable to catch access to uninitialized fields. In the +debug version, dtuple_create() will make all fields of dtuple_t point +to data_error. */ +ut_d(extern byte data_error); + /*********************************************************************//** Sets the type struct of SQL data field. */ UNIV_INLINE @@ -72,15 +55,6 @@ dfield_set_type( const dtype_t* type); /*!< in: pointer to data type struct */ /*********************************************************************//** -Gets length of field data. -@return length of data; UNIV_SQL_NULL if SQL null data */ -UNIV_INLINE -ulint -dfield_get_len( -/*===========*/ - const dfield_t* field) /*!< in: field */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); -/*********************************************************************//** Sets length in a field. */ UNIV_INLINE void @@ -89,32 +63,6 @@ dfield_set_len( dfield_t* field, /*!< in: field */ ulint len) /*!< in: length or UNIV_SQL_NULL */ MY_ATTRIBUTE((nonnull)); -/*********************************************************************//** -Determines if a field is SQL NULL -@return nonzero if SQL null data */ -UNIV_INLINE -ulint -dfield_is_null( -/*===========*/ - const dfield_t* field) /*!< in: field */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); -/*********************************************************************//** -Determines if a field is externally stored -@return nonzero if externally stored */ -UNIV_INLINE -ulint -dfield_is_ext( -/*==========*/ - const dfield_t* field) /*!< in: field */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); -/*********************************************************************//** -Sets the "external storage" flag */ -UNIV_INLINE -void -dfield_set_ext( -/*===========*/ - dfield_t* field) /*!< in/out: field */ - MY_ATTRIBUTE((nonnull)); /** Gets spatial status for "external storage" @param[in,out] field field */ @@ -221,46 +169,7 @@ dfield_data_is_binary_equal( ulint len, /*!< in: data length or UNIV_SQL_NULL */ const byte* data) /*!< in: data */ MY_ATTRIBUTE((nonnull, warn_unused_result)); -/*********************************************************************//** -Gets number of fields in a data tuple. -@return number of fields */ -UNIV_INLINE -ulint -dtuple_get_n_fields( -/*================*/ - const dtuple_t* tuple) /*!< in: tuple */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); -/** Gets number of virtual fields in a data tuple. -@param[in] tuple dtuple to check -@return number of fields */ -UNIV_INLINE -ulint -dtuple_get_n_v_fields( - const dtuple_t* tuple); -#ifdef UNIV_DEBUG -/** Gets nth field of a tuple. -@param[in] tuple tuple -@param[in] n index of field -@return nth field */ -UNIV_INLINE -dfield_t* -dtuple_get_nth_field( - const dtuple_t* tuple, - ulint n); -/** Gets nth virtual field of a tuple. -@param[in] tuple tuple -@oaran[in] n the nth field to get -@return nth field */ -UNIV_INLINE -dfield_t* -dtuple_get_nth_v_field( - const dtuple_t* tuple, - ulint n); -#else /* UNIV_DEBUG */ -# define dtuple_get_nth_field(tuple, n) ((tuple)->fields + (n)) -# define dtuple_get_nth_v_field(tuple, n) ((tuple)->fields + (tuple)->n_fields + (n)) -#endif /* UNIV_DEBUG */ /*********************************************************************//** Gets info bits in a data tuple. @return info bits */ @@ -338,19 +247,12 @@ dtuple_create( /** Initialize the virtual field data in a dtuple_t @param[in,out] vrow dtuple contains the virtual fields */ -UNIV_INLINE -void -dtuple_init_v_fld( - const dtuple_t* vrow); +UNIV_INLINE void dtuple_init_v_fld(dtuple_t* vrow); /** Duplicate the virtual field data in a dtuple_t @param[in,out] vrow dtuple contains the virtual fields @param[in] heap heap memory to use */ -UNIV_INLINE -void -dtuple_dup_v_fld( - const dtuple_t* vrow, - mem_heap_t* heap); +UNIV_INLINE void dtuple_dup_v_fld(dtuple_t* vrow, mem_heap_t* heap); /** Creates a data tuple with possible virtual columns to a memory heap. @param[in] heap memory heap where the tuple is created @@ -672,6 +574,73 @@ struct dtuple_t { bool is_metadata() const { return is_metadata(info_bits); } }; +inline ulint dtuple_get_n_fields(const dtuple_t* tuple) +{ return tuple->n_fields; } +inline dtype_t* dfield_get_type(dfield_t* field) { return &field->type; } +inline const dtype_t* dfield_get_type(const dfield_t* field) +{ return &field->type; } +inline void* dfield_get_data(dfield_t* field) +{ + ut_ad(field->len == UNIV_SQL_NULL || field->data != &data_error); + return field->data; +} +inline const void* dfield_get_data(const dfield_t* field) +{ + ut_ad(field->len == UNIV_SQL_NULL || field->data != &data_error); + return field->data; +} +inline ulint dfield_get_len(const dfield_t* field) { + ut_ad(field->len == UNIV_SQL_NULL || field->data != &data_error); + ut_ad(field->len != UNIV_SQL_DEFAULT); + return field->len; +} +inline bool dfield_is_null(const dfield_t* field) +{ return field->len == UNIV_SQL_NULL; } +/** @return whether a column is to be stored off-page */ +inline bool dfield_is_ext(const dfield_t* field) +{ + ut_ad(!field->ext || field->len >= BTR_EXTERN_FIELD_REF_SIZE); + return static_cast<bool>(field->ext); +} +/** Set the "external storage" flag */ +inline void dfield_set_ext(dfield_t* field) { field->ext = 1; } + +/** Gets number of virtual fields in a data tuple. +@param[in] tuple dtuple to check +@return number of fields */ +inline ulint +dtuple_get_n_v_fields(const dtuple_t* tuple) { return tuple->n_v_fields; } + +inline const dfield_t* dtuple_get_nth_field(const dtuple_t* tuple, ulint n) +{ + ut_ad(n < tuple->n_fields); + return &tuple->fields[n]; +} +inline dfield_t* dtuple_get_nth_field(dtuple_t* tuple, ulint n) +{ + ut_ad(n < tuple->n_fields); + return &tuple->fields[n]; +} + +/** Get a virtual column in a table row or an extended clustered index record. +@param[in] tuple tuple +@oaran[in] n the nth virtual field to get +@return nth virtual field */ +inline const dfield_t* dtuple_get_nth_v_field(const dtuple_t* tuple, ulint n) +{ + ut_ad(n < tuple->n_v_fields); + return &tuple->v_fields[n]; +} +/** Get a virtual column in a table row or an extended clustered index record. +@param[in] tuple tuple +@oaran[in] n the nth virtual field to get +@return nth virtual field */ +inline dfield_t* dtuple_get_nth_v_field(dtuple_t* tuple, ulint n) +{ + ut_ad(n < tuple->n_v_fields); + return &tuple->v_fields[n]; +} + /** A slot for a field in a big rec vector */ struct big_rec_field_t { diff --git a/storage/innobase/include/data0data.ic b/storage/innobase/include/data0data.ic index 2d5a9810025..0f13c9398c9 100644 --- a/storage/innobase/include/data0data.ic +++ b/storage/innobase/include/data0data.ic @@ -24,28 +24,7 @@ SQL data field and tuple Created 5/30/1994 Heikki Tuuri *************************************************************************/ -#include "mem0mem.h" #include "ut0rnd.h" -#include "btr0types.h" - -#ifdef UNIV_DEBUG -/** Dummy variable to catch access to uninitialized fields. In the -debug version, dtuple_create() will make all fields of dtuple_t point -to data_error. */ -extern byte data_error; - -/*********************************************************************//** -Gets pointer to the type struct of SQL data field. -@return pointer to the type struct */ -UNIV_INLINE -dtype_t* -dfield_get_type( -/*============*/ - const dfield_t* field) /*!< in: SQL data field */ -{ - return((dtype_t*) &(field->type)); -} -#endif /* UNIV_DEBUG */ /*********************************************************************//** Sets the type struct of SQL data field. */ @@ -62,39 +41,6 @@ dfield_set_type( field->type = *type; } -#ifdef UNIV_DEBUG -/*********************************************************************//** -Gets pointer to the data in a field. -@return pointer to data */ -UNIV_INLINE -void* -dfield_get_data( -/*============*/ - const dfield_t* field) /*!< in: field */ -{ - ut_ad((field->len == UNIV_SQL_NULL) - || (field->data != &data_error)); - - return((void*) field->data); -} -#endif /* UNIV_DEBUG */ - -/*********************************************************************//** -Gets length of field data. -@return length of data; UNIV_SQL_NULL if SQL null data */ -UNIV_INLINE -ulint -dfield_get_len( -/*===========*/ - const dfield_t* field) /*!< in: field */ -{ - ut_ad((field->len == UNIV_SQL_NULL) - || (field->data != &data_error)); - ut_ad(field->len != UNIV_SQL_DEFAULT); - - return(field->len); -} - /*********************************************************************//** Sets length in a field. */ UNIV_INLINE @@ -113,42 +59,6 @@ dfield_set_len( field->len = static_cast<unsigned int>(len); } -/*********************************************************************//** -Determines if a field is SQL NULL -@return nonzero if SQL null data */ -UNIV_INLINE -ulint -dfield_is_null( -/*===========*/ - const dfield_t* field) /*!< in: field */ -{ - return(field->len == UNIV_SQL_NULL); -} - -/*********************************************************************//** -Determines if a field is externally stored -@return nonzero if externally stored */ -UNIV_INLINE -ulint -dfield_is_ext( -/*==========*/ - const dfield_t* field) /*!< in: field */ -{ - ut_ad(!field->ext || field->len >= BTR_EXTERN_FIELD_REF_SIZE); - return(field->ext); -} - -/*********************************************************************//** -Sets the "external storage" flag */ -UNIV_INLINE -void -dfield_set_ext( -/*===========*/ - dfield_t* field) /*!< in/out: field */ -{ - field->ext = 1; -} - /** Gets spatial status for "external storage" @param[in,out] field field */ UNIV_INLINE @@ -369,63 +279,6 @@ dtuple_set_n_fields_cmp( tuple->n_fields_cmp = n_fields_cmp; } -/*********************************************************************//** -Gets number of fields in a data tuple. -@return number of fields */ -UNIV_INLINE -ulint -dtuple_get_n_fields( -/*================*/ - const dtuple_t* tuple) /*!< in: tuple */ -{ - return(tuple->n_fields); -} - -/** Gets the number of virtual fields in a data tuple. -@param[in] tuple dtuple to check -@return number of fields */ -UNIV_INLINE -ulint -dtuple_get_n_v_fields( - const dtuple_t* tuple) -{ - ut_ad(tuple); - - return(tuple->n_v_fields); -} -#ifdef UNIV_DEBUG -/** Gets nth field of a tuple. -@param[in] tuple tuple -@param[in] n index of field -@return nth field */ -UNIV_INLINE -dfield_t* -dtuple_get_nth_field( - const dtuple_t* tuple, - ulint n) -{ - ut_ad(tuple); - ut_ad(n < tuple->n_fields); - - return((dfield_t*) tuple->fields + n); -} -/** Gets nth virtual field of a tuple. -@param[in] tuple tuple -@oaran[in] n the nth field to get -@return nth field */ -UNIV_INLINE -dfield_t* -dtuple_get_nth_v_field( - const dtuple_t* tuple, - ulint n) -{ - ut_ad(tuple); - ut_ad(n < tuple->n_v_fields); - - return(static_cast<dfield_t*>(tuple->v_fields + n)); -} -#endif /* UNIV_DEBUG */ - /** Creates a data tuple from an already allocated chunk of memory. The size of the chunk must be at least DTUPLE_EST_ALLOC(n_fields). The default value for number of fields used in record comparisons @@ -490,12 +343,10 @@ dtuple_create_from_mem( /** Duplicate the virtual field data in a dtuple_t @param[in,out] vrow dtuple contains the virtual fields -@param[in] heap heap memory to use */ +@param[in,out] heap heap memory to use */ UNIV_INLINE void -dtuple_dup_v_fld( - const dtuple_t* vrow, - mem_heap_t* heap) +dtuple_dup_v_fld(dtuple_t* vrow, mem_heap_t* heap) { for (ulint i = 0; i < vrow->n_v_fields; i++) { dfield_t* dfield = dtuple_get_nth_v_field(vrow, i); @@ -507,8 +358,7 @@ dtuple_dup_v_fld( @param[in,out] vrow dtuple contains the virtual fields */ UNIV_INLINE void -dtuple_init_v_fld( - const dtuple_t* vrow) +dtuple_init_v_fld(dtuple_t* vrow) { for (ulint i = 0; i < vrow->n_v_fields; i++) { dfield_t* dfield = dtuple_get_nth_v_field(vrow, i); diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index b06cb15e64a..bfbe3a3578f 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -959,6 +959,12 @@ public: /*!< whether fil_space_create() has issued a warning about potential space_id reuse */ + + /** Trigger a call to fil_node_t::read_page0() + @param[in] id tablespace identifier + @return tablespace + @retval NULL if the tablespace does not exist or cannot be read */ + fil_space_t* read_page0(ulint id); }; /** The tablespace memory cache. */ diff --git a/storage/innobase/include/gis0geo.h b/storage/innobase/include/gis0geo.h index 08895af545e..9a5d426cd7c 100644 --- a/storage/innobase/include/gis0geo.h +++ b/storage/innobase/include/gis0geo.h @@ -1,5 +1,6 @@ /***************************************************************************** Copyright (c) 2014, 2015, 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 @@ -73,7 +74,7 @@ stored in "well-known binary representation" (wkb) format. int rtree_mbr_from_wkb( /*===============*/ - uchar* wkb, /*!< in: pointer to wkb. */ + const uchar* wkb, /*!< in: pointer to wkb. */ uint size, /*!< in: size of wkb. */ uint n_dims, /*!< in: dimensions. */ double* mbr); /*!< in/out: mbr. */ diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index ee60bdbf597..96c30c7f757 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -431,7 +431,6 @@ extern const char* TROUBLESHOOTING_MSG; extern const char* TROUBLESHOOT_DATADICT_MSG; extern const char* BUG_REPORT_MSG; extern const char* FORCE_RECOVERY_MSG; -extern const char* ERROR_CREATING_MSG; extern const char* OPERATING_SYSTEM_ERROR_MSG; extern const char* FOREIGN_KEY_CONSTRAINTS_MSG; extern const char* SET_TRANSACTION_MSG; diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index e088f248681..2fb026849c1 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -190,23 +190,13 @@ blocks from the buffer pool: it only checks what is lsn of the oldest modification in the pool, and writes information about the lsn in log files. Use log_make_checkpoint_at() to flush also the pool. @param[in] sync whether to wait for the write to complete -@param[in] write_always force a write even if no log -has been generated since the latest checkpoint @return true if success, false if a checkpoint write was already running */ -bool -log_checkpoint( - bool sync, - bool write_always); +bool log_checkpoint(bool sync); /** Make a checkpoint at or after a specified LSN. @param[in] lsn the log sequence number, or LSN_MAX -for the latest LSN -@param[in] write_always force a write even if no log -has been generated since the latest checkpoint */ -void -log_make_checkpoint_at( - lsn_t lsn, - bool write_always); +for the latest LSN */ +void log_make_checkpoint_at(lsn_t lsn); /****************************************************************//** Makes a checkpoint at the latest lsn and writes it to first page of each diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index 5d5ccac885a..9c1c6a3c38b 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -69,16 +69,6 @@ Initiates the rollback of active transactions. */ void recv_recovery_rollback_active(void); /*===============================*/ -/******************************************************//** -Resets the logs. The contents of log files will be lost! */ -void -recv_reset_logs( -/*============*/ - lsn_t lsn); /*!< in: reset to this lsn - rounded up to be divisible by - OS_FILE_LOG_BLOCK_SIZE, after - which we add - LOG_BLOCK_HDR_SIZE */ /** Clean up after recv_sys_init() */ void recv_sys_close(); diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic index 641323e7d41..49d127499f7 100644 --- a/storage/innobase/include/page0page.ic +++ b/storage/innobase/include/page0page.ic @@ -165,7 +165,9 @@ page_header_set_field( { ut_ad(page); ut_ad(field <= PAGE_N_RECS); +#if 0 /* FIXME: MDEV-19344 hits this */ ut_ad(field != PAGE_N_RECS || val); +#endif ut_ad(field == PAGE_N_HEAP || val < srv_page_size); ut_ad(field != PAGE_N_HEAP || (val & 0x7fff) < srv_page_size); diff --git a/storage/innobase/include/rem0cmp.ic b/storage/innobase/include/rem0cmp.ic index 290c1455f27..9ba61ca1f94 100644 --- a/storage/innobase/include/rem0cmp.ic +++ b/storage/innobase/include/rem0cmp.ic @@ -127,10 +127,10 @@ cmp_dfield_dfield_like_prefix( if (CHARSET_INFO* cs = get_charset(cs_num, MYF(MY_WME))) { return(cs->coll->strnncoll( cs, - static_cast<uchar*>( + static_cast<const uchar*>( dfield_get_data(dfield1)), dfield_get_len(dfield1), - static_cast<uchar*>( + static_cast<const uchar*>( dfield_get_data(dfield2)), dfield_get_len(dfield2), 1)); diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index 9d8b425fbba..94307146e9e 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -892,7 +892,7 @@ void innobase_free_row_for_vcol(VCOL_STORAGE *storage); @return the field filled with computed value */ dfield_t* innobase_get_computed_value( - const dtuple_t* row, + dtuple_t* row, const dict_v_col_t* col, const dict_index_t* index, mem_heap_t** local_heap, diff --git a/storage/innobase/include/row0vers.h b/storage/innobase/include/row0vers.h index dd438c366a8..6e3dd394d76 100644 --- a/storage/innobase/include/row0vers.h +++ b/storage/innobase/include/row0vers.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, 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 @@ -110,7 +110,7 @@ row_vers_build_for_consistent_read( if the history is missing or the record does not exist in the view, that is, it was freshly inserted afterwards */ - const dtuple_t**vrow); /*!< out: reports virtual column info if any */ + dtuple_t** vrow); /*!< out: reports virtual column info if any */ /*****************************************************************//** Constructs the last committed version of a clustered index record, @@ -136,7 +136,7 @@ row_vers_build_for_semi_consistent_read( const rec_t** old_vers,/*!< out: rec, old version, or NULL if the record does not exist in the view, that is, it was freshly inserted afterwards */ - const dtuple_t**vrow); /*!< out: holds virtual column info if any + dtuple_t** vrow); /*!< out: holds virtual column info if any is updated in the view */ #endif diff --git a/storage/innobase/include/trx0rec.h b/storage/innobase/include/trx0rec.h index bf8835f189f..dd164b7f973 100644 --- a/storage/innobase/include/trx0rec.h +++ b/storage/innobase/include/trx0rec.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, 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 @@ -234,7 +234,7 @@ trx_undo_prev_version_build( dtuple if it is not yet created. This heap diffs from "heap" above in that it could be prebuilt->old_vers_heap for selection */ - const dtuple_t**vrow, /*!< out: virtual column info, if any */ + dtuple_t** vrow, /*!< out: virtual column info, if any */ ulint v_status); /*!< in: status determine if it is going into this function by purge thread or not. @@ -280,7 +280,7 @@ void trx_undo_read_v_cols( const dict_table_t* table, const byte* ptr, - const dtuple_t* row, + dtuple_t* row, bool in_purge); /** Read virtual column index from undo log if the undo log contains such diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index 277e5842ff6..149d0122576 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -53,8 +53,6 @@ component, i.e. we show M.N.P as M.N */ IB_TO_STR(MYSQL_VERSION_MINOR) "." \ IB_TO_STR(MYSQL_VERSION_PATCH) -#define REFMAN "http://dev.mysql.com/doc/refman/5.7/en/" - /** How far ahead should we tell the service manager the timeout (time in seconds) */ #define INNODB_EXTEND_TIMEOUT_INTERVAL 30 diff --git a/storage/innobase/include/ut0lst.h b/storage/innobase/include/ut0lst.h index f62d3744b96..986f73ea17c 100644 --- a/storage/innobase/include/ut0lst.h +++ b/storage/innobase/include/ut0lst.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2015, 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 @@ -426,24 +427,19 @@ Gets the last node in a two-way list. @return last node, or NULL if the list is empty */ #define UT_LIST_GET_LAST(BASE) (BASE).end -struct NullValidate { void operator()(const void*) { } }; +struct NullValidate { void operator()(const void*) const {} }; -/********************************************************************//** -Iterate over all the elements and call the functor for each element. +/** Iterate over all the elements and call the functor for each element. @param[in] list base node (not a pointer to it) @param[in,out] functor Functor that is called for each element in the list */ template <typename List, class Functor> -void -ut_list_map( - const List& list, - Functor& functor) +inline void ut_list_map(const List& list, Functor& functor) { - ulint count = 0; + ulint count = 0; UT_LIST_IS_INITIALISED(list); - for (typename List::elem_type* elem = list.start; - elem != 0; + for (typename List::elem_type* elem = list.start; elem; elem = (elem->*list.node).next, ++count) { functor(elem); @@ -452,32 +448,50 @@ ut_list_map( ut_a(count == list.count); } -template <typename List> -void -ut_list_reverse(List& list) +/** Iterate over all the elements and call the functor for each element. +@param[in] list base node (not a pointer to it) +@param[in] functor Functor that is called for each element in the list */ +template <typename List, class Functor> +inline void ut_list_map(const List& list, const Functor& functor) { + ulint count = 0; + UT_LIST_IS_INITIALISED(list); - for (typename List::elem_type* elem = list.start; + for (typename List::elem_type* elem = list.start; elem; + elem = (elem->*list.node).next, ++count) { + + functor(elem); + } + + ut_a(count == list.count); +} + +/** Check the consistency of a doubly linked list. +@param[in] list base node (not a pointer to it) +@param[in,out] functor Functor that is called for each element in the list */ +template <typename List, class Functor> +void ut_list_validate(const List& list, Functor& functor) +{ + ut_list_map(list, functor); + + /* Validate the list backwards. */ + ulint count = 0; + + for (typename List::elem_type* elem = list.end; elem != 0; elem = (elem->*list.node).prev) { - (elem->*list.node).reverse(); + ++count; } - list.reverse(); + ut_a(count == list.count); } -#define UT_LIST_REVERSE(LIST) ut_list_reverse(LIST) - -/********************************************************************//** -Checks the consistency of a two-way list. -@param[in] list base node (not a pointer to it) -@param[in,out] functor Functor that is called for each element in the list */ +/** Check the consistency of a doubly linked list. +@param[in] list base node (not a pointer to it) +@param[in] functor Functor that is called for each element in the list */ template <typename List, class Functor> -void -ut_list_validate( - const List& list, - Functor& functor) +inline void ut_list_validate(const List& list, const Functor& functor) { ut_list_map(list, functor); @@ -493,12 +507,42 @@ ut_list_validate( ut_a(count == list.count); } -/** Check the consistency of a two-way list. -@param[in] LIST base node reference */ -#define UT_LIST_CHECK(LIST) do { \ - NullValidate nullV; \ - ut_list_validate(LIST, nullV); \ -} while (0) +template <typename List> +inline void ut_list_validate(const List& list) +{ + ut_list_validate(list, NullValidate()); +} + +#ifdef UNIV_DEBUG +template <typename List> +inline void ut_list_reverse(List& list) +{ + UT_LIST_IS_INITIALISED(list); + + for (typename List::elem_type* elem = list.start; + elem != 0; + elem = (elem->*list.node).prev) { + (elem->*list.node).reverse(); + } + + list.reverse(); +} + +/** Check if the given element exists in the list. +@param[in,out] list the list object +@param[in] elem the element of the list which will be checked */ +template <typename List> +inline bool ut_list_exists(const List& list, typename List::elem_type* elem) +{ + for (typename List::elem_type* e1 = UT_LIST_GET_FIRST(list); e1; + e1 = (e1->*list.node).next) { + if (elem == e1) { + return true; + } + } + return false; +} +#endif /** Move the given element to the beginning of the list. @param[in,out] list the list object @@ -519,28 +563,6 @@ ut_list_move_to_front( } #ifdef UNIV_DEBUG -/** Check if the given element exists in the list. -@param[in,out] list the list object -@param[in] elem the element of the list which will be checked */ -template <typename List> -bool -ut_list_exists( - List& list, - typename List::elem_type* elem) -{ - typename List::elem_type* e1; - - for (e1 = UT_LIST_GET_FIRST(list); e1 != NULL; - e1 = (e1->*list.node).next) { - if (elem == e1) { - return(true); - } - } - return(false); -} #endif -#define UT_LIST_MOVE_TO_FRONT(LIST, ELEM) \ - ut_list_move_to_front(LIST, ELEM) - #endif /* ut0lst.h */ diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 2d6a643c4ea..0c232878c3c 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -2581,7 +2581,7 @@ lock_move_granted_locks_to_front( if (!lock->is_waiting()) { lock_t* prev = UT_LIST_GET_PREV(trx_locks, lock); ut_a(prev); - UT_LIST_MOVE_TO_FRONT(lock_list, lock); + ut_list_move_to_front(lock_list, lock); lock = prev; } } @@ -2669,7 +2669,7 @@ lock_move_reorganize_page( lock_move_granted_locks_to_front(old_locks); DBUG_EXECUTE_IF("do_lock_reverse_page_reorganize", - UT_LIST_REVERSE(old_locks);); + ut_list_reverse(old_locks);); for (lock = UT_LIST_GET_FIRST(old_locks); lock; lock = UT_LIST_GET_NEXT(trx_locks, lock)) { @@ -4620,29 +4620,6 @@ lock_print_info_summary( return(TRUE); } -/** Functor to print not-started transaction from the trx_list. */ - -struct PrintNotStarted { - - PrintNotStarted(FILE* file) : m_file(file) { } - - void operator()(const trx_t* trx) - { - ut_ad(mutex_own(&trx_sys.mutex)); - - /* See state transitions and locking rules in trx0trx.h */ - - if (trx->mysql_thd - && trx_state_eq(trx, TRX_STATE_NOT_STARTED)) { - - fputs("---", m_file); - trx_print_latched(m_file, trx, 600); - } - } - - FILE* m_file; -}; - /** Prints transaction lock wait and MVCC state. @param[in,out] file file where to print @param[in] trx transaction */ @@ -4715,29 +4692,24 @@ lock_trx_print_locks( } } - -static my_bool lock_print_info_all_transactions_callback( - rw_trx_hash_element_t *element, FILE *file) +/** Functor to display all transactions */ +struct lock_print_info { - mutex_enter(&element->mutex); - if (trx_t *trx= element->trx) + lock_print_info(FILE* file) : file(file) {} + + void operator()(const trx_t* trx) const { - check_trx_state(trx); + ut_ad(mutex_own(&trx_sys.mutex)); + if (trx == purge_sys.query->trx) + return; lock_trx_print_wait_and_mvcc_state(file, trx); - if (srv_print_innodb_lock_monitor) - { - trx->reference(); - mutex_exit(&element->mutex); + if (trx->will_lock && srv_print_innodb_lock_monitor) lock_trx_print_locks(file, trx); - trx->release_reference(); - return 0; - } } - mutex_exit(&element->mutex); - return 0; -} + FILE* const file; +}; /*********************************************************************//** Prints info of locks for each transaction. This function assumes that the @@ -4752,20 +4724,9 @@ lock_print_info_all_transactions( fprintf(file, "LIST OF TRANSACTIONS FOR EACH SESSION:\n"); - /* First print info on non-active transactions */ - - /* NOTE: information of auto-commit non-locking read-only - transactions will be omitted here. The information will be - available from INFORMATION_SCHEMA.INNODB_TRX. */ - - PrintNotStarted print_not_started(file); mutex_enter(&trx_sys.mutex); - ut_list_map(trx_sys.trx_list, print_not_started); + ut_list_map(trx_sys.trx_list, lock_print_info(file)); mutex_exit(&trx_sys.mutex); - - trx_sys.rw_trx_hash.iterate_no_dups( - reinterpret_cast<my_hash_walk_action> - (lock_print_info_all_transactions_callback), file); lock_mutex_exit(); ut_ad(lock_validate()); diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index a6f8ea99dcf..3a8bd63fcdd 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -326,7 +326,7 @@ log_margin_checkpoint_age( if (!flushed_enough) { os_thread_sleep(100000); } - log_checkpoint(true, false); + log_checkpoint(true); log_mutex_enter(); } @@ -1405,13 +1405,8 @@ blocks from the buffer pool: it only checks what is lsn of the oldest modification in the pool, and writes information about the lsn in log files. Use log_make_checkpoint_at() to flush also the pool. @param[in] sync whether to wait for the write to complete -@param[in] write_always force a write even if no log -has been generated since the latest checkpoint @return true if success, false if a checkpoint write was already running */ -bool -log_checkpoint( - bool sync, - bool write_always) +bool log_checkpoint(bool sync) { lsn_t oldest_lsn; @@ -1454,9 +1449,15 @@ log_checkpoint( flushed up to oldest_lsn. */ ut_ad(oldest_lsn >= log_sys.last_checkpoint_lsn); - if (!write_always - && oldest_lsn - <= log_sys.last_checkpoint_lsn + SIZE_OF_MLOG_CHECKPOINT) { + if (oldest_lsn + > log_sys.last_checkpoint_lsn + SIZE_OF_MLOG_CHECKPOINT) { + /* Some log has been written since the previous checkpoint. */ + } else if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + /* MariaDB 10.3 startup expects the redo log file to be + logically empty (not even containing a MLOG_CHECKPOINT record) + after a clean shutdown. Perform an extra checkpoint at + shutdown. */ + } else { /* Do nothing, because nothing was logged (other than a MLOG_CHECKPOINT marker) since the previous checkpoint. */ log_mutex_exit(); @@ -1488,20 +1489,6 @@ log_checkpoint( log_write_up_to(flush_lsn, true, true); - DBUG_EXECUTE_IF( - "using_wa_checkpoint_middle", - if (write_always) { - DEBUG_SYNC_C("wa_checkpoint_middle"); - - const my_bool b = TRUE; - buf_flush_page_cleaner_disabled_debug_update( - NULL, NULL, NULL, &b); - dict_stats_disabled_debug_update( - NULL, NULL, NULL, &b); - srv_master_thread_disabled_debug_update( - NULL, NULL, NULL, &b); - }); - log_mutex_enter(); ut_ad(log_sys.flushed_to_disk_lsn >= flush_lsn); @@ -1534,13 +1521,8 @@ log_checkpoint( /** Make a checkpoint at or after a specified LSN. @param[in] lsn the log sequence number, or LSN_MAX -for the latest LSN -@param[in] write_always force a write even if no log -has been generated since the latest checkpoint */ -void -log_make_checkpoint_at( - lsn_t lsn, - bool write_always) +for the latest LSN */ +void log_make_checkpoint_at(lsn_t lsn) { /* Preflush pages synchronously */ @@ -1548,7 +1530,7 @@ log_make_checkpoint_at( /* Flush as much as we can */ } - while (!log_checkpoint(true, write_always)) { + while (!log_checkpoint(true)) { /* Force a checkpoint */ } } @@ -1628,7 +1610,7 @@ loop: } if (do_checkpoint) { - log_checkpoint(checkpoint_sync, FALSE); + log_checkpoint(checkpoint_sync); if (checkpoint_sync) { @@ -1877,7 +1859,7 @@ wait_suspend_loop: if (!srv_read_only_mode) { service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, "ensuring dirty buffer pool are written to log"); - log_make_checkpoint_at(LSN_MAX, TRUE); + log_make_checkpoint_at(LSN_MAX); log_mutex_enter(); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 32c63546e5d..420f186b5fb 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2739,11 +2739,6 @@ loop: if (lsn == checkpoint_lsn) { if (recv_sys->mlog_checkpoint_lsn) { - /* At recv_reset_logs() we may - write a duplicate MLOG_CHECKPOINT - for the same checkpoint LSN. Thus - recv_sys->mlog_checkpoint_lsn - can differ from the current LSN. */ ut_ad(recv_sys->mlog_checkpoint_lsn <= recv_sys->recovered_lsn); break; @@ -3872,49 +3867,6 @@ recv_recovery_rollback_active(void) } } -/******************************************************//** -Resets the logs. The contents of log files will be lost! */ -void -recv_reset_logs( -/*============*/ - lsn_t lsn) /*!< in: reset to this lsn - rounded up to be divisible by - OS_FILE_LOG_BLOCK_SIZE, after - which we add - LOG_BLOCK_HDR_SIZE */ -{ - ut_ad(log_mutex_own()); - - log_sys.lsn = ut_uint64_align_up(lsn, OS_FILE_LOG_BLOCK_SIZE); - - log_sys.log.set_lsn(log_sys.lsn); - log_sys.log.set_lsn_offset(LOG_FILE_HDR_SIZE); - - log_sys.buf_next_to_write = 0; - log_sys.write_lsn = log_sys.lsn; - - log_sys.next_checkpoint_no = 0; - log_sys.last_checkpoint_lsn = 0; - - memset(log_sys.buf, 0, srv_log_buffer_size); - log_block_init(log_sys.buf, log_sys.lsn); - log_block_set_first_rec_group(log_sys.buf, LOG_BLOCK_HDR_SIZE); - - log_sys.buf_free = LOG_BLOCK_HDR_SIZE; - log_sys.lsn += LOG_BLOCK_HDR_SIZE; - - MONITOR_SET(MONITOR_LSN_CHECKPOINT_AGE, - (log_sys.lsn - log_sys.last_checkpoint_lsn)); - - log_mutex_exit(); - - /* Reset the checkpoint fields in logs */ - - log_make_checkpoint_at(LSN_MAX, TRUE); - - log_mutex_enter(); -} - /** Find a doublewrite copy of a page. @param[in] space_id tablespace identifier @param[in] page_no page number diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index ded109138dc..77f5ba7c113 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -7743,13 +7743,8 @@ invalid: return false; } - ut_ad(space->free_limit == 0 || space->free_limit == free_limit); - ut_ad(space->free_len == 0 || space->free_len == free_len); - space->size_in_header = size; - space->free_limit = free_limit; - space->free_len = free_len; - if (first) { + ut_ad(space->id != TRX_SYS_SPACE); #ifdef UNIV_LINUX find_metadata(handle, &statbuf); #else @@ -7770,8 +7765,19 @@ invalid: this->size = ulint(size_bytes / psize); space->size += this->size; + } else if (space->id != TRX_SYS_SPACE || space->size_in_header) { + /* If this is not the first-time open, do nothing. + For the system tablespace, we always get invoked as + first=false, so we detect the true first-time-open based + on size_in_header and proceed to initiailze the data. */ + return true; } + ut_ad(space->free_limit == 0 || space->free_limit == free_limit); + ut_ad(space->free_len == 0 || space->free_len == free_len); + space->size_in_header = size; + space->free_limit = free_limit; + space->free_len = free_len; return true; } diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index fdd352390da..9ef737828a0 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -2140,7 +2140,7 @@ row_import_cleanup( DBUG_EXECUTE_IF("ib_import_before_checkpoint_crash", DBUG_SUICIDE();); - log_make_checkpoint_at(LSN_MAX, TRUE); + log_make_checkpoint_at(LSN_MAX); return(err); } diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index cc30de70798..adb154c8446 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -2782,8 +2782,7 @@ do_insert: DBUG_EXECUTE_IF( "row_ins_extern_checkpoint", - log_make_checkpoint_at( - LSN_MAX, TRUE);); + log_write_up_to(mtr.commit_lsn(), true);); err = row_ins_index_entry_big_rec( entry, big_rec, offsets, &offsets_heap, index, thr_get_trx(thr)->mysql_thd); @@ -3413,14 +3412,14 @@ row_ins_spatial_index_entry_set_mbr_field( dfield_t* field, /*!< in/out: mbr field */ const dfield_t* row_field) /*!< in: row field */ { - uchar* dptr = NULL; ulint dlen = 0; double mbr[SPDIMS * 2]; /* This must be a GEOMETRY datatype */ ut_ad(DATA_GEOMETRY_MTYPE(field->type.mtype)); - dptr = static_cast<uchar*>(dfield_get_data(row_field)); + const byte* dptr = static_cast<const byte*>( + dfield_get_data(row_field)); dlen = dfield_get_len(row_field); /* obtain the MBR */ diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 989f242cf6c..469a25e6836 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -453,7 +453,7 @@ row_merge_buf_redundant_convert( ut_ad(field_len <= len); if (row_field->ext) { - const byte* field_data = static_cast<byte*>( + const byte* field_data = static_cast<const byte*>( dfield_get_data(row_field)); ulint ext_len; @@ -483,7 +483,7 @@ row_merge_buf_redundant_convert( @param[in] old_table original table @param[in] new_table new table @param[in,out] psort_info parallel sort info -@param[in] row table row +@param[in,out] row table row @param[in] ext cache of externally stored column prefixes, or NULL @param[in,out] doc_id Doc ID if we are creating @@ -505,7 +505,7 @@ row_merge_buf_add( const dict_table_t* old_table, const dict_table_t* new_table, fts_psort_t* psort_info, - const dtuple_t* row, + dtuple_t* row, const row_ext_t* ext, doc_id_t* doc_id, mem_heap_t* conv_heap, @@ -642,7 +642,7 @@ row_merge_buf_add( row, index->table->fts->doc_col); *doc_id = (doc_id_t) mach_read_from_8( - static_cast<byte*>( + static_cast<const byte*>( dfield_get_data(doc_field))); if (*doc_id == 0) { @@ -1935,7 +1935,7 @@ row_merge_read_clustered_index( const rec_t* rec; trx_id_t rec_trx_id; ulint* offsets; - const dtuple_t* row; + dtuple_t* row; row_ext_t* ext; page_cur_t* cur = btr_pcur_get_page_cur(&pcur); @@ -2244,9 +2244,8 @@ end_of_index: history_row = dfield->vers_history_row(); } - dfield_t* dfield; - - dfield = dtuple_get_nth_field(row, add_autoinc); + dfield_t* dfield = dtuple_get_nth_field(row, + add_autoinc); if (new_table->versioned()) { if (history_row) { diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 1225c7f35f4..afbcdfe4423 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2979,13 +2979,13 @@ row_discard_tablespace_end( } DBUG_EXECUTE_IF("ib_discard_before_commit_crash", - log_make_checkpoint_at(LSN_MAX, TRUE); + log_write_up_to(LSN_MAX, true); DBUG_SUICIDE();); trx_commit_for_mysql(trx); DBUG_EXECUTE_IF("ib_discard_after_commit_crash", - log_make_checkpoint_at(LSN_MAX, TRUE); + log_write_up_to(LSN_MAX, true); DBUG_SUICIDE();); row_mysql_unlock_data_dictionary(trx); diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc index d7191a5971d..c200e6fb15c 100644 --- a/storage/innobase/row/row0row.cc +++ b/storage/innobase/row/row0row.cc @@ -83,20 +83,21 @@ static bool row_build_spatial_index_key( return true; } - uchar* dptr = NULL; + const byte* dptr = NULL; ulint dlen = 0; ulint flen = 0; double tmp_mbr[SPDIMS * 2]; mem_heap_t* temp_heap = NULL; if (!dfield_is_ext(dfield2)) { - dptr = static_cast<uchar*>(dfield_get_data(dfield2)); + dptr = static_cast<const byte*>(dfield_get_data(dfield2)); dlen = dfield_get_len(dfield2); goto write_mbr; } if (flag == ROW_BUILD_FOR_PURGE) { - byte* ptr = static_cast<byte*>(dfield_get_data(dfield2)); + const byte* ptr = static_cast<const byte*>( + dfield_get_data(dfield2)); switch (dfield_get_spatial_status(dfield2)) { case SPATIAL_ONLY: @@ -140,12 +141,12 @@ static bool row_build_spatial_index_key( log record, and avoid recomputing it here! */ flen = BTR_EXTERN_FIELD_REF_SIZE; ut_ad(dfield_get_len(dfield2) >= BTR_EXTERN_FIELD_REF_SIZE); - dptr = static_cast<byte*>(dfield_get_data(dfield2)) + dptr = static_cast<const byte*>(dfield_get_data(dfield2)) + dfield_get_len(dfield2) - BTR_EXTERN_FIELD_REF_SIZE; } else { flen = dfield_get_len(dfield2); - dptr = static_cast<byte*>(dfield_get_data(dfield2)); + dptr = static_cast<const byte*>(dfield_get_data(dfield2)); } temp_heap = mem_heap_create(1000); diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 9a3f3bb9be7..20df64d599f 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -224,7 +224,6 @@ row_sel_sec_rec_is_for_clust_rec( reconstructed from base column in cluster index */ if (is_virtual) { const dict_v_col_t* v_col; - const dtuple_t* row; dfield_t* vfield; row_ext_t* ext; @@ -241,10 +240,11 @@ row_sel_sec_rec_is_for_clust_rec( v_col = reinterpret_cast<const dict_v_col_t*>(col); - row = row_build(ROW_COPY_POINTERS, - clust_index, clust_rec, - clust_offs, - NULL, NULL, NULL, &ext, heap); + dtuple_t* row = row_build( + ROW_COPY_POINTERS, + clust_index, clust_rec, + clust_offs, + NULL, NULL, NULL, &ext, heap); vfield = innobase_get_computed_value( row, v_col, clust_index, @@ -804,7 +804,7 @@ row_sel_build_committed_vers_for_mysql( record does not exist in the view: i.e., it was freshly inserted afterwards */ - const dtuple_t**vrow, /*!< out: to be filled with old virtual + dtuple_t** vrow, /*!< out: to be filled with old virtual column version if any */ mtr_t* mtr) /*!< in: mtr */ { @@ -3181,7 +3181,7 @@ row_sel_build_prev_vers_for_mysql( record does not exist in the view: i.e., it was freshly inserted afterwards */ - const dtuple_t**vrow, /*!< out: dtuple to hold old virtual + dtuple_t** vrow, /*!< out: dtuple to hold old virtual column data */ mtr_t* mtr) /*!< in: mtr */ { @@ -3225,7 +3225,7 @@ row_sel_get_clust_rec_for_mysql( rec_get_offsets(out_rec, clust_index) */ mem_heap_t** offset_heap,/*!< in/out: memory heap from which the offsets are allocated */ - const dtuple_t**vrow, /*!< out: virtual column to fill */ + dtuple_t** vrow, /*!< out: virtual column to fill */ mtr_t* mtr) /*!< in: mtr used to get access to the non-clustered record; the same mtr is used to access the clustered index */ @@ -3947,7 +3947,7 @@ void row_sel_fill_vrow( const rec_t* rec, dict_index_t* index, - const dtuple_t** vrow, + dtuple_t** vrow, mem_heap_t* heap) { ulint offsets_[REC_OFFS_NORMAL_SIZE]; @@ -4143,7 +4143,7 @@ row_search_mvcc( dict_index_t* clust_index; que_thr_t* thr; const rec_t* UNINIT_VAR(rec); - const dtuple_t* vrow = NULL; + dtuple_t* vrow = NULL; const rec_t* result_rec = NULL; const rec_t* clust_rec; dberr_t err = DB_SUCCESS; diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 88a0bce52a6..e1403eea93b 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -791,7 +791,7 @@ row_upd_index_write_log( mlog_catenate_string( mtr, - static_cast<byte*>( + static_cast<const byte*>( dfield_get_data(new_val)), len); @@ -988,8 +988,6 @@ row_upd_build_difference_binary( dberr_t* error) { upd_field_t* upd_field; - dfield_t* dfield; - const byte* data; ulint len; upd_t* update; ulint n_diff; @@ -1015,9 +1013,9 @@ row_upd_build_difference_binary( } for (i = 0; i < n_fld; i++) { - data = rec_get_nth_cfield(rec, index, offsets, i, &len); - - dfield = dtuple_get_nth_field(entry, i); + const byte* data = rec_get_nth_cfield(rec, index, offsets, i, + &len); + const dfield_t* dfield = dtuple_get_nth_field(entry, i); /* NOTE: we compare the fields as binary strings! (No collation) */ @@ -1078,8 +1076,6 @@ row_upd_build_difference_binary( index->table, NULL, NULL, &ext, heap); } - dfield = dtuple_get_nth_v_field(entry, i); - dfield_t* vfield = innobase_get_computed_value( update->old_vrow, col, index, &v_heap, heap, NULL, thd, mysql_table, record, @@ -1090,6 +1086,9 @@ row_upd_build_difference_binary( return(NULL); } + const dfield_t* dfield = dtuple_get_nth_v_field( + entry, i); + if (!dfield_data_is_binary_equal( dfield, vfield->len, static_cast<byte*>(vfield->data))) { @@ -1734,7 +1733,7 @@ row_upd_changes_ord_field_binary_func( double mbr2[SPDIMS * 2]; rtr_mbr_t* old_mbr; rtr_mbr_t* new_mbr; - uchar* dptr = NULL; + const uchar* dptr = NULL; ulint flen = 0; ulint dlen = 0; mem_heap_t* temp_heap = NULL; @@ -1753,7 +1752,7 @@ row_upd_changes_ord_field_binary_func( /* For off-page stored data, we need to read the whole field data. */ flen = dfield_get_len(dfield); - dptr = static_cast<byte*>( + dptr = static_cast<const byte*>( dfield_get_data(dfield)); temp_heap = mem_heap_create(1000); @@ -1763,7 +1762,7 @@ row_upd_changes_ord_field_binary_func( flen, temp_heap); } else { - dptr = static_cast<uchar*>(dfield->data); + dptr = static_cast<const uchar*>(dfield->data); dlen = dfield->len; } @@ -1806,13 +1805,13 @@ row_upd_changes_ord_field_binary_func( flen = BTR_EXTERN_FIELD_REF_SIZE; ut_ad(dfield_get_len(new_field) >= BTR_EXTERN_FIELD_REF_SIZE); - dptr = static_cast<byte*>( + dptr = static_cast<const byte*>( dfield_get_data(new_field)) + dfield_get_len(new_field) - BTR_EXTERN_FIELD_REF_SIZE; } else { flen = dfield_get_len(new_field); - dptr = static_cast<byte*>( + dptr = static_cast<const byte*>( dfield_get_data(new_field)); } @@ -1826,7 +1825,8 @@ row_upd_changes_ord_field_binary_func( flen, temp_heap); } else { - dptr = static_cast<uchar*>(upd_field->new_val.data); + dptr = static_cast<const byte*>( + upd_field->new_val.data); dlen = upd_field->new_val.len; } rtree_mbr_from_wkb(dptr + GEO_DATA_HEADER_SIZE, @@ -1884,7 +1884,7 @@ row_upd_changes_ord_field_binary_func( ut_a(dict_index_is_clust(index) || ind_field->prefix_len <= dfield_len); - buf = static_cast<byte*>(dfield_get_data(dfield)); + buf= static_cast<const byte*>(dfield_get_data(dfield)); copy_dfield: ut_a(dfield_len > 0); dfield_copy(&dfield_ext, dfield); diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index f31ae1573cf..bc84348384e 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, 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 @@ -98,7 +98,7 @@ row_vers_impl_x_locked_low( mem_heap_t* heap; dtuple_t* ientry = NULL; mem_heap_t* v_heap = NULL; - const dtuple_t* cur_vrow = NULL; + dtuple_t* cur_vrow = NULL; DBUG_ENTER("row_vers_impl_x_locked_low"); @@ -181,7 +181,7 @@ row_vers_impl_x_locked_low( ulint vers_del; trx_id_t prev_trx_id; mem_heap_t* old_heap = heap; - const dtuple_t* vrow = NULL; + dtuple_t* vrow = NULL; /* We keep the semaphore in mtr on the clust_rec page, so that no other transaction can update it and get an @@ -515,7 +515,7 @@ row_vers_build_cur_vrow_low( roll_ptr_t roll_ptr, trx_id_t trx_id, mem_heap_t* v_heap, - const dtuple_t** vrow, + dtuple_t** vrow, mtr_t* mtr) { const rec_t* version; @@ -632,7 +632,7 @@ row_vers_vc_matches_cluster( roll_ptr_t roll_ptr, trx_id_t trx_id, mem_heap_t* v_heap, - const dtuple_t**vrow, + dtuple_t** vrow, mtr_t* mtr) { const rec_t* version; @@ -796,7 +796,7 @@ func_exit: @param[in,out] vcol_info virtual column information for purge thread @return dtuple contains virtual column data */ static -const dtuple_t* +dtuple_t* row_vers_build_cur_vrow( bool in_purge, const rec_t* rec, @@ -810,7 +810,7 @@ row_vers_build_cur_vrow( mtr_t* mtr, purge_vcol_info_t* vcol_info) { - const dtuple_t* cur_vrow = NULL; + dtuple_t* cur_vrow = NULL; roll_ptr_t t_roll_ptr = row_get_rec_roll_ptr( rec, clust_index, *clust_offsets); @@ -891,9 +891,9 @@ row_vers_old_has_index_entry( dtuple_t* row; const dtuple_t* entry; ulint comp; - const dtuple_t* vrow = NULL; + dtuple_t* vrow = NULL; mem_heap_t* v_heap = NULL; - const dtuple_t* cur_vrow = NULL; + dtuple_t* cur_vrow = NULL; ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_S_FIX)); @@ -1155,7 +1155,7 @@ row_vers_build_for_consistent_read( if the history is missing or the record does not exist in the view, that is, it was freshly inserted afterwards */ - const dtuple_t**vrow) /*!< out: virtual row */ + dtuple_t** vrow) /*!< out: virtual row */ { const rec_t* version; rec_t* prev_version; @@ -1269,7 +1269,7 @@ row_vers_build_for_semi_consistent_read( const rec_t** old_vers,/*!< out: rec, old version, or NULL if the record does not exist in the view, that is, it was freshly inserted afterwards */ - const dtuple_t** vrow) /*!< out: virtual row, old version, or NULL + dtuple_t** vrow) /*!< out: virtual row, old version, or NULL if it is not updated in the view */ { const rec_t* version; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 528384eaa3f..8501ffbf672 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -2185,7 +2185,7 @@ srv_master_do_active_tasks(void) /* Make a new checkpoint */ if (cur_time % SRV_MASTER_CHECKPOINT_INTERVAL == 0) { srv_main_thread_op_info = "making checkpoint"; - log_checkpoint(TRUE, FALSE); + log_checkpoint(true); MONITOR_INC_TIME_IN_MICRO_SECS( MONITOR_SRV_CHECKPOINT_MICROSECOND, counter_time); } @@ -2273,7 +2273,7 @@ srv_master_do_idle_tasks(void) /* Make a new checkpoint */ srv_main_thread_op_info = "making checkpoint"; - log_checkpoint(TRUE, FALSE); + log_checkpoint(true); MONITOR_INC_TIME_IN_MICRO_SECS(MONITOR_SRV_CHECKPOINT_MICROSECOND, counter_time); } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index b1c0748a52e..2337dfaada2 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -487,9 +487,30 @@ create_log_files( return(DB_ERROR); } ut_d(recv_no_log_write = false); - recv_reset_logs(lsn); + log_sys.lsn = ut_uint64_align_up(lsn, OS_FILE_LOG_BLOCK_SIZE); + + log_sys.log.set_lsn(log_sys.lsn); + log_sys.log.set_lsn_offset(LOG_FILE_HDR_SIZE); + + log_sys.buf_next_to_write = 0; + log_sys.write_lsn = log_sys.lsn; + + log_sys.next_checkpoint_no = 0; + log_sys.last_checkpoint_lsn = 0; + + memset(log_sys.buf, 0, srv_log_buffer_size); + log_block_init(log_sys.buf, log_sys.lsn); + log_block_set_first_rec_group(log_sys.buf, LOG_BLOCK_HDR_SIZE); + + log_sys.buf_free = LOG_BLOCK_HDR_SIZE; + log_sys.lsn += LOG_BLOCK_HDR_SIZE; + + MONITOR_SET(MONITOR_LSN_CHECKPOINT_AGE, + (log_sys.lsn - log_sys.last_checkpoint_lsn)); log_mutex_exit(); + log_make_checkpoint_at(LSN_MAX); + return(DB_SUCCESS); } diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index f56691bd4ec..9fdbe0a7aeb 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -400,8 +400,6 @@ trx_undo_report_insert_virtual( for (ulint col_no = 0; col_no < dict_table_get_n_v_cols(table); col_no++) { - dfield_t* vfield = NULL; - const dict_v_col_t* col = dict_table_get_nth_v_col(table, col_no); @@ -424,7 +422,8 @@ trx_undo_report_insert_virtual( return(false); } - vfield = dtuple_get_nth_v_field(row, col->v_pos); + const dfield_t* vfield = dtuple_get_nth_v_field( + row, col->v_pos); ulint flen = vfield->len; if (flen != UNIV_SQL_NULL) { @@ -1394,8 +1393,6 @@ already_logged: for (col_no = 0; col_no < dict_table_get_n_v_cols(table); col_no++) { - dfield_t* vfield = NULL; - const dict_v_col_t* col = dict_table_get_nth_v_col(table, col_no); @@ -1424,6 +1421,8 @@ already_logged: return(0); } + const dfield_t* vfield = NULL; + if (update) { ut_ad(!row); if (update->old_vrow == NULL) { @@ -2338,7 +2337,7 @@ trx_undo_prev_version_build( dtuple if it is not yet created. This heap diffs from "heap" above in that it could be prebuilt->old_vers_heap for selection */ - const dtuple_t**vrow, /*!< out: virtual column info, if any */ + dtuple_t** vrow, /*!< out: virtual column info, if any */ ulint v_status) /*!< in: status determine if it is going into this function by purge thread or not. @@ -2539,7 +2538,7 @@ void trx_undo_read_v_cols( const dict_table_t* table, const byte* ptr, - const dtuple_t* row, + dtuple_t* row, bool in_purge) { const byte* end_ptr; diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index a420ac1d0d8..7ef6b88a9a9 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1529,7 +1529,8 @@ void trx_commit_low(trx_t* trx, mtr_t* mtr) DBUG_EXECUTE_IF("ib_crash_during_trx_commit_in_mem", if (trx->has_logged()) { - log_make_checkpoint_at(LSN_MAX, TRUE); + log_write_up_to(mtr->commit_lsn(), + true); DBUG_SUICIDE(); }); /*--------------*/ |