diff options
Diffstat (limited to 'storage/innobase/include')
26 files changed, 239 insertions, 225 deletions
diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic index 308fcfe9b03..bd4f2a40267 100644 --- a/storage/innobase/include/btr0btr.ic +++ b/storage/innobase/include/btr0btr.ic @@ -63,7 +63,7 @@ btr_block_get_func( if (err == DB_DECRYPTION_FAILED) { if (index && index->table) { - index->table->is_encrypted = true; + index->table->file_unreadable = true; } } diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h index e00af130479..fab934ca0ee 100644 --- a/storage/innobase/include/btr0pcur.h +++ b/storage/innobase/include/btr0pcur.h @@ -99,7 +99,7 @@ btr_pcur_free( Initializes and opens a persistent cursor to an index tree. It should be closed with btr_pcur_close. */ UNIV_INLINE -void +dberr_t btr_pcur_open_low( /*==============*/ dict_index_t* index, /*!< in: index */ diff --git a/storage/innobase/include/btr0pcur.ic b/storage/innobase/include/btr0pcur.ic index 425593631d3..4490942a2bb 100644 --- a/storage/innobase/include/btr0pcur.ic +++ b/storage/innobase/include/btr0pcur.ic @@ -418,7 +418,7 @@ btr_pcur_free( Initializes and opens a persistent cursor to an index tree. It should be closed with btr_pcur_close. */ UNIV_INLINE -void +dberr_t btr_pcur_open_low( /*==============*/ dict_index_t* index, /*!< in: index */ @@ -471,6 +471,8 @@ btr_pcur_open_low( cursor->pos_state = BTR_PCUR_IS_POSITIONED; cursor->trx_if_known = NULL; + + return(err); } /**************************************************************//** diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 7dee52d8f74..928521e789e 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -812,9 +812,8 @@ buf_page_is_zeroes( const byte* read_buf, const page_size_t& page_size); -/** Checks if a page is corrupt. -@param[in] check_lsn true if we need to check and complain about -the LSN +/** Check if a page is corrupt. +@param[in] check_lsn whether the LSN should be checked @param[in] read_buf database page @param[in] page_size page size @param[in] space tablespace @@ -824,8 +823,8 @@ buf_page_is_corrupted( bool check_lsn, const byte* read_buf, const page_size_t& page_size, - const fil_space_t* space = NULL -) MY_ATTRIBUTE((warn_unused_result)); + const fil_space_t* space = NULL) + MY_ATTRIBUTE((warn_unused_result)); #ifndef UNIV_INNOCHECKSUM /**********************************************************************//** Gets the space id, page offset, and byte offset within page of a @@ -1249,7 +1248,7 @@ buf_pointer_is_block_field( #define buf_pool_is_block_lock(l) \ buf_pointer_is_block_field((const void*)(l)) -/** Inits a page for read to the buffer buf_pool. If the page is +/** Initialize a page for read to the buffer buf_pool. If the page is (1) already in buf_pool, or (2) if we specify to read only ibuf pages and the page is not an ibuf page, or (3) if the space is deleted or being deleted, @@ -1260,27 +1259,34 @@ and the lock released later. @param[out] err DB_SUCCESS or DB_TABLESPACE_DELETED @param[in] mode BUF_READ_IBUF_PAGES_ONLY, ... @param[in] page_id page id -@param[in] unzip TRUE=request uncompressed page -@return pointer to the block or NULL */ +@param[in] unzip whether the uncompressed page is + requested (for ROW_FORMAT=COMPRESSED) +@return pointer to the block +@retval NULL in case of an error */ buf_page_t* buf_page_init_for_read( dberr_t* err, ulint mode, const page_id_t& page_id, const page_size_t& page_size, - ibool unzip); + bool unzip); + +/** Complete a read or write request of a file page to or from the buffer pool. +@param[in,out] bpage Page to complete +@param[in] evict whether or not to evict the page + from LRU list. +@return whether the operation succeeded +@retval DB_SUCCESS always when writing, or if a read page was OK +@retval DB_PAGE_CORRUPTED if the checksum fails on a page read +@retval DB_DECRYPTION_FAILED if page post encryption checksum matches but + after decryption normal page checksum does + not match */ +UNIV_INTERN +dberr_t +buf_page_io_complete(buf_page_t* bpage, bool evict = false) + MY_ATTRIBUTE((nonnull)); /********************************************************************//** -Completes an asynchronous read or write request of a file page to or from -the buffer pool. -@return true if successful */ -bool -buf_page_io_complete( -/*=================*/ - buf_page_t* bpage, /*!< in: pointer to the block in question */ - bool evict = false);/*!< in: whether or not to evict - the page from LRU list. */ -/********************************************************************//** Calculates the index of a buffer pool to the buf_pool[] array. @return the position of the buffer pool in buf_pool[] */ UNIV_INLINE @@ -1586,7 +1592,6 @@ public: if written again we check is TRIM operation needed. */ - unsigned key_version; /*!< key version for this block */ bool encrypted; /*!< page is still encrypted */ ulint real_size; /*!< Real size of the page diff --git a/storage/innobase/include/buf0checksum.h b/storage/innobase/include/buf0checksum.h index 9405251dc74..20955a5b2e6 100644 --- a/storage/innobase/include/buf0checksum.h +++ b/storage/innobase/include/buf0checksum.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 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 @@ -30,7 +31,7 @@ Created Aug 11, 2011 Vasil Dimov #include "buf0types.h" -/** Calculates the CRC32 checksum of a page. The value is stored to the page +/** Calculate the CRC32 checksum of a page. The value is stored to the page when it is written to a file and also checked for a match when reading from the file. When reading we allow both normal CRC32 and CRC-legacy-big-endian variants. Note that we must be careful to calculate the same value on 32-bit @@ -44,37 +45,30 @@ buf_calc_page_crc32( const byte* page, bool use_legacy_big_endian = false); -/********************************************************************//** -Calculates a page checksum which is stored to the page when it is written +/** Calculate a checksum which is stored to the page when it is written to a file. Note that we must be careful to calculate the same value on 32-bit and 64-bit architectures. +@param[in] page file page (srv_page_size bytes) @return checksum */ -ulint -buf_calc_page_new_checksum( -/*=======================*/ - const byte* page); /*!< in: buffer page */ - -/********************************************************************//** -In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only -looked at the first few bytes of the page. This calculates that old -checksum. +uint32_t +buf_calc_page_new_checksum(const byte* page); + +/** In MySQL before 4.0.14 or 4.1.1 there was an InnoDB bug that +the checksum only looked at the first few bytes of the page. +This calculates that old checksum. NOTE: we must first store the new formula checksum to FIL_PAGE_SPACE_OR_CHKSUM before calculating and storing this old checksum because this takes that field as an input! +@param[in] page file page (srv_page_size bytes) @return checksum */ -ulint -buf_calc_page_old_checksum( -/*=======================*/ - const byte* page); /*!< in: buffer page */ - +uint32_t +buf_calc_page_old_checksum(const byte* page); -/********************************************************************//** -Return a printable string describing the checksum algorithm. +/** Return a printable string describing the checksum algorithm. +@param[in] algo algorithm @return algorithm name */ const char* -buf_checksum_algorithm_name( -/*========================*/ - srv_checksum_algorithm_t algo); /*!< in: algorithm */ +buf_checksum_algorithm_name(srv_checksum_algorithm_t algo); extern ulong srv_checksum_algorithm; extern bool legacy_big_endian_checksum; diff --git a/storage/innobase/include/buf0rea.h b/storage/innobase/include/buf0rea.h index 9c97a5147c1..5c766b9412a 100644 --- a/storage/innobase/include/buf0rea.h +++ b/storage/innobase/include/buf0rea.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, MariaDB Corporation. +Copyright (c) 2015, 2017, 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 @@ -37,12 +37,15 @@ an exclusive lock on the buffer frame. The flag is cleared and the x-lock released by the i/o-handler thread. @param[in] page_id page id @param[in] page_size page size -@return TRUE if page has been read in, FALSE in case of failure */ -ibool +@retval DB_SUCCESS if the page was read and is not corrupted, +@retval DB_PAGE_CORRUPTED if page based on checksum check is corrupted, +@retval DB_DECRYPTION_FAILED if page post encryption checksum matches but +after decryption normal page checksum does not match. +@retval DB_TABLESPACE_DELETED if tablespace .ibd file is missing */ +dberr_t buf_read_page( const page_id_t& page_id, - const page_size_t& page_size, - buf_page_t** bpage); + const page_size_t& page_size); /********************************************************************//** High-level function which reads a page asynchronously from a file to the @@ -51,9 +54,8 @@ an exclusive lock on the buffer frame. The flag is cleared and the x-lock released by the i/o-handler thread. @param[in] page_id page id @param[in] page_size page size -@param[in] sync true if synchronous aio is desired -@return TRUE if page has been read in, FALSE in case of failure */ -ibool +@param[in] sync true if synchronous aio is desired */ +void buf_read_page_background( const page_id_t& page_id, const page_size_t& page_size, diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h index b0609991f61..ef6f8b39abb 100644 --- a/storage/innobase/include/db0err.h +++ b/storage/innobase/include/db0err.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, MariaDB Corporation. +Copyright (c) 2015, 2017, 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 @@ -163,6 +163,8 @@ enum dberr_t { DB_IO_NO_PUNCH_HOLE, /*!< Punch hole not supported by file system. */ + DB_PAGE_CORRUPTED, /* Page read from tablespace is + corrupted. */ /* The following are partial failure codes */ DB_FAIL = 1000, DB_OVERFLOW, diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h index f53ea74717d..76eb48d1e7e 100644 --- a/storage/innobase/include/dict0crea.h +++ b/storage/innobase/include/dict0crea.h @@ -45,7 +45,7 @@ tab_create_graph_create( a memory data structure */ mem_heap_t* heap, /*!< in: heap where created */ fil_encryption_t mode, /*!< in: encryption mode */ - ulint key_id); /*!< in: encryption key_id */ + uint32_t key_id); /*!< in: encryption key_id */ /** Creates an index create graph. @param[in] index index to create, built as a memory data structure @@ -305,7 +305,7 @@ struct tab_node_t{ /* Local storage for this graph node */ ulint state; /*!< node execution state */ ulint col_no; /*!< next column definition to insert */ - ulint key_id; /*!< encryption key_id */ + uint key_id; /*!< encryption key_id */ fil_encryption_t mode; /*!< encryption mode */ ulint base_col_no; /*!< next base column to insert */ mem_heap_t* heap; /*!< memory heap used as auxiliary diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 18578388723..f80047f29a9 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1889,6 +1889,14 @@ dict_set_corrupted_by_space( /*========================*/ ulint space_id); /*!< in: space ID */ +/** Flag a table with specified space_id encrypted in the data dictionary +cache +@param[in] space_id Tablespace id */ +UNIV_INTERN +void +dict_set_encrypted_by_space( + ulint space_id); + /** Sets merge_threshold in the SYS_INDEXES @param[in,out] index index @param[in] merge_threshold value to set */ diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index 8849be1206d..e9507302e66 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -1680,7 +1680,7 @@ dict_index_is_corrupted( ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); return((index->type & DICT_CORRUPT) - || (index->table && index->table->corrupted)); + || (index->table && index->table->corrupted)); } /********************************************************************//** diff --git a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict0load.h index fb443caf770..22fd27c2484 100644 --- a/storage/innobase/include/dict0load.h +++ b/storage/innobase/include/dict0load.h @@ -119,7 +119,7 @@ a foreign key references columns in this table. @param[in] ignore_err Error to be ignored when loading table and its index definition @return table, NULL if does not exist; if the table is stored in an -.ibd file, but the file does not exist, then we set the ibd_file_missing +.ibd file, but the file does not exist, then we set the file_unreadable flag in the table object we return. */ dict_table_t* dict_load_table( diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 9b87e654b21..f35a7810736 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -1018,6 +1018,13 @@ struct dict_index_t{ ut_ad(committed || !(type & DICT_CLUSTERED)); uncommitted = !committed; } + + /** @return whether this index is readable + @retval true normally + @retval false if this is a single-table tablespace + and the .ibd file is missing, or a + page cannot be read or decrypted */ + inline bool is_readable() const; }; /** The status of online index creation */ @@ -1367,6 +1374,15 @@ struct dict_table_t { bool no_rollback() const { return flags & (1U << DICT_TF_POS_NO_ROLLBACK); + } + /** @return whether this table is readable + @retval true normally + @retval false if this is a single-table tablespace + and the .ibd file is missing, or a + page cannot be read or decrypted */ + bool is_readable() const + { + return(UNIV_LIKELY(!file_unreadable)); } /** Id of the table. */ @@ -1415,10 +1431,9 @@ struct dict_table_t { Use DICT_TF2_FLAG_IS_SET() to parse this flag. */ unsigned flags2:DICT_TF2_BITS; - /** TRUE if this is in a single-table tablespace and the .ibd file is - missing. Then we must return in ha_innodb.cc an error if the user - tries to query such an orphaned table. */ - unsigned ibd_file_missing:1; + /*!< whether this is in a single-table tablespace and the .ibd + file is missing or page decryption failed and page is corrupted */ + unsigned file_unreadable:1; /** TRUE if the table object has been added to the dictionary cache. */ unsigned cached:1; @@ -1739,8 +1754,6 @@ public: /** Timestamp of the last modification of this table. */ time_t update_time; - bool is_encrypted; - #ifdef UNIV_DEBUG /** Value of 'magic_n'. */ #define DICT_TABLE_MAGIC_N 76333786 @@ -1753,6 +1766,11 @@ public: dict_vcol_templ_t* vc_templ; }; +inline bool dict_index_t::is_readable() const +{ + return(UNIV_LIKELY(!table->file_unreadable)); +} + /*******************************************************************//** Initialise the table lock list. */ void diff --git a/storage/innobase/include/dict0stats.h b/storage/innobase/include/dict0stats.h index f02b8eb8eed..752c197f8c3 100644 --- a/storage/innobase/include/dict0stats.h +++ b/storage/innobase/include/dict0stats.h @@ -252,6 +252,17 @@ dict_stats_save_index_stat( const char* stat_description, trx_t* trx); +/** Report an error if updating table statistics failed because +.ibd file is missing, table decryption failed or table is corrupted. +@param[in,out] table Table +@param[in] defragment true if statistics is for defragment +@retval DB_DECRYPTION_FAILED if decryption of the table failed +@retval DB_TABLESPACE_DELETED if .ibd file is missing +@retval DB_CORRUPTION if table is marked as corrupted */ +dberr_t +dict_stats_report_error(dict_table_t* table, bool defragment = false) + MY_ATTRIBUTE((nonnull, warn_unused_result)); + #include "dict0stats.ic" #ifdef UNIV_ENABLE_UNIT_TEST_DICT_STATS diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h index ca65df21402..06785430c25 100644 --- a/storage/innobase/include/fil0crypt.h +++ b/storage/innobase/include/fil0crypt.h @@ -116,8 +116,7 @@ struct fil_space_crypt_t : st_encryption_scheme min_key_version(new_min_key_version), page0_offset(0), encryption(new_encryption), - mutex(), - key_found(new_min_key_version), + key_found(0), rotate_state() { key_id = new_key_id; @@ -134,6 +133,8 @@ struct fil_space_crypt_t : st_encryption_scheme type = CRYPT_SCHEME_1; min_key_version = key_get_latest_version(); } + + key_found = min_key_version; } /** Destructor */ @@ -205,7 +206,7 @@ struct fil_space_crypt_status_t { uint min_key_version; /*!< min key version */ uint current_key_version;/*!< current key version */ uint keyserver_requests;/*!< no of key requests to key server */ - ulint key_id; /*!< current key_id */ + uint key_id; /*!< current key_id */ bool rotating; /*!< is key rotation ongoing */ bool flushing; /*!< is flush at end of rotation ongoing */ ulint rotate_next_page_number; /*!< next page if key rotating */ @@ -293,13 +294,15 @@ Parse a MLOG_FILE_WRITE_CRYPT_DATA log entry @param[in] ptr Log entry start @param[in] end_ptr Log entry end @param[in] block buffer block +@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED @return position on log buffer */ UNIV_INTERN -const byte* +byte* fil_parse_write_crypt_data( - const byte* ptr, + byte* ptr, const byte* end_ptr, - const buf_block_t* block) + const buf_block_t* block, + dberr_t* err) MY_ATTRIBUTE((warn_unused_result)); /** Encrypt a buffer. @@ -382,7 +385,7 @@ Calculate post encryption checksum @return page checksum or BUF_NO_CHECKSUM_MAGIC not needed. */ UNIV_INTERN -ulint +uint32_t fil_crypt_calculate_checksum( const page_size_t& page_size, const byte* dst_frame) diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index cef5b578a4a..d8b6cf33675 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -733,21 +733,39 @@ MY_ATTRIBUTE((warn_unused_result)); Used by background threads that do not necessarily hold proper locks for concurrency control. @param[in] id tablespace ID +@param[in] silent whether to silently ignore missing tablespaces @return the tablespace @retval NULL if missing or being deleted or truncated */ +UNIV_INTERN fil_space_t* -fil_space_acquire(ulint id) +fil_space_acquire_low(ulint id, bool silent) MY_ATTRIBUTE((warn_unused_result)); +/** Acquire a tablespace when it could be dropped concurrently. +Used by background threads that do not necessarily hold proper locks +for concurrency control. +@param[in] id tablespace ID +@return the tablespace +@retval NULL if missing or being deleted or truncated */ +inline +fil_space_t* +fil_space_acquire(ulint id) +{ + return (fil_space_acquire_low(id, false)); +} + /** Acquire a tablespace that may not exist. Used by background threads that do not necessarily hold proper locks for concurrency control. @param[in] id tablespace ID @return the tablespace @retval NULL if missing or being deleted */ +inline fil_space_t* fil_space_acquire_silent(ulint id) - MY_ATTRIBUTE((warn_unused_result)); +{ + return (fil_space_acquire_low(id, true)); +} /** Release a tablespace acquired with fil_space_acquire(). @param[in,out] space tablespace to release */ @@ -803,9 +821,10 @@ public: /** Constructor: Look up the tablespace and increment the reference count if found. - @param[in] space_id tablespace ID */ - explicit FilSpace(ulint space_id) - : m_space(fil_space_acquire(space_id)) {} + @param[in] space_id tablespace ID + @param[in] silent whether not to display errors */ + explicit FilSpace(ulint space_id, bool silent = false) + : m_space(fil_space_acquire_low(space_id, silent)) {} /** Assignment operator: This assumes that fil_space_acquire() has already been done for the fil_space_t. The caller must @@ -1044,7 +1063,7 @@ fil_ibd_create( ulint flags, ulint size, fil_encryption_t mode, - ulint key_id) + uint32_t key_id) MY_ATTRIBUTE((warn_unused_result)); /** Try to adjust FSP_SPACE_FLAGS if they differ from the expectations. @@ -1510,13 +1529,6 @@ fil_mtr_rename_log( /*******************************************************************//** Returns the table space by a given id, NULL if not found. */ fil_space_t* -fil_space_found_by_id( -/*==================*/ - ulint id); /*!< in: space id */ - -/*******************************************************************//** -Returns the table space by a given id, NULL if not found. */ -fil_space_t* fil_space_get_by_id( /*================*/ ulint id); /*!< in: space id */ diff --git a/storage/innobase/include/fil0fil.ic b/storage/innobase/include/fil0fil.ic index e3d4fd4d88b..9505cc0bd69 100644 --- a/storage/innobase/include/fil0fil.ic +++ b/storage/innobase/include/fil0fil.ic @@ -75,19 +75,6 @@ fil_get_page_type_name( } /****************************************************************//** -Get block size from fil node -@return block size*/ -UNIV_INLINE -ulint -fil_node_get_block_size( -/*====================*/ - fil_node_t* node) /*!< in: Node where to get block - size */ -{ - return (node->block_size); -} - -/****************************************************************//** Validate page type. @return true if valid, false if not */ UNIV_INLINE diff --git a/storage/innobase/include/fil0pagecompress.h b/storage/innobase/include/fil0pagecompress.h index cd754151d80..67ff7895b02 100644 --- a/storage/innobase/include/fil0pagecompress.h +++ b/storage/innobase/include/fil0pagecompress.h @@ -67,23 +67,4 @@ fil_decompress_page( /*!< in: true if only an error should be produced when decompression fails. By default this parameter is false. */ - -/****************************************************************//** -Get space id from fil node -@return space id*/ -UNIV_INTERN -ulint -fil_node_get_space_id( -/*==================*/ - fil_node_t* node); /*!< in: Node where to get space id*/ - -/****************************************************************//** -Get block size from fil node -@return block size*/ -UNIV_INLINE -ulint -fil_node_get_block_size( -/*====================*/ - fil_node_t* node); /*!< in: Node where to get block - size */ #endif diff --git a/storage/innobase/include/fsp0space.h b/storage/innobase/include/fsp0space.h index 0b66827ab49..3928f8362b9 100644 --- a/storage/innobase/include/fsp0space.h +++ b/storage/innobase/include/fsp0space.h @@ -140,7 +140,7 @@ public: /** Get the tablespace encryption key_id @return m_key_id tablespace encryption key_id */ - ulint key_id() const + uint32_t key_id() const { return (m_key_id); } @@ -226,7 +226,7 @@ private: /** Encryption mode and key_id */ fil_encryption_t m_mode; - ulint m_key_id; + uint32_t m_key_id; protected: /** Ignore server read only configuration for this tablespace. */ diff --git a/storage/innobase/include/mtr0log.ic b/storage/innobase/include/mtr0log.ic index 972fdc81518..dd68ea25613 100644 --- a/storage/innobase/include/mtr0log.ic +++ b/storage/innobase/include/mtr0log.ic @@ -76,10 +76,10 @@ mlog_catenate_ulint( ulint val, /*!< in: value to write */ mlog_id_t type) /*!< in: type of value to write */ { - ut_ad(MLOG_1BYTE == 1); - ut_ad(MLOG_2BYTES == 2); - ut_ad(MLOG_4BYTES == 4); - ut_ad(MLOG_8BYTES == 8); + compile_time_assert(MLOG_1BYTE == 1); + compile_time_assert(MLOG_2BYTES == 2); + compile_time_assert(MLOG_4BYTES == 4); + compile_time_assert(MLOG_8BYTES == 8); byte* ptr = mtr_buf->push<byte*>(type); @@ -182,6 +182,14 @@ mlog_write_initial_log_record_low( mtr_t* mtr) { ut_ad(type <= MLOG_BIGGEST_TYPE || EXTRA_CHECK_MLOG_NUMBER(type)); + ut_ad(type == MLOG_FILE_NAME + || type == MLOG_FILE_DELETE + || 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)); mach_write_to_1(log_ptr, type); log_ptr++; diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index 0557b585ae1..7507c96ea5f 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -365,7 +365,7 @@ row_create_table_for_mysql( trx_t* trx, /*!< in/out: transaction */ bool commit, /*!< in: if true, commit the transaction */ fil_encryption_t mode, /*!< in: encryption mode */ - ulint key_id) /*!< in: encryption key_id */ + uint32_t key_id) /*!< in: encryption key_id */ MY_ATTRIBUTE((warn_unused_result)); /*********************************************************************//** @@ -474,7 +474,7 @@ row_drop_table_for_mysql( /*********************************************************************//** Discards the tablespace of a table which stored in an .ibd file. Discarding means that this function deletes the .ibd file and assigns a new table id for -the table. Also the flag table->ibd_file_missing is set TRUE. +the table. Also the file_unreadable flag is set. @return error code or DB_SUCCESS */ dberr_t row_discard_tablespace_for_mysql( diff --git a/storage/innobase/include/row0trunc.h b/storage/innobase/include/row0trunc.h index b6c7810d522..56302a0e570 100644 --- a/storage/innobase/include/row0trunc.h +++ b/storage/innobase/include/row0trunc.h @@ -359,7 +359,7 @@ private: /** Encryption information of the table */ fil_encryption_t m_encryption; - uint m_key_id; + uint32_t m_key_id; /** Vector of tables to truncate. */ typedef std::vector<truncate_t*, ut_allocator<truncate_t*> > diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 230d7b7effe..9d8e736beb1 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -57,15 +57,13 @@ Created 10/10/1995 Heikki Tuuri #include "ut0counter.h" #include "fil0fil.h" -struct fil_space_t; - -/* Global counters used inside InnoDB. */ -struct srv_stats_t { +/** Global counters used inside InnoDB. */ +struct srv_stats_t +{ typedef ib_counter_t<ulint, 64> ulint_ctr_64_t; - typedef ib_counter_t<lsn_t, 1, single_indexer_t> lsn_ctr_1_t; - typedef ib_counter_t<ulint, 1, single_indexer_t> ulint_ctr_1_t; - typedef ib_counter_t<lint, 1, single_indexer_t> lint_ctr_1_t; - typedef ib_counter_t<int64_t, 1, single_indexer_t> int64_ctr_1_t; + typedef simple_counter<lsn_t> lsn_ctr_1_t; + typedef simple_counter<ulint> ulint_ctr_1_t; + typedef simple_counter<int64_t> int64_ctr_1_t; /** Count the amount of data written in total (in bytes) */ ulint_ctr_1_t data_written; @@ -82,8 +80,9 @@ struct srv_stats_t { /** Amount of data written to the log files in bytes */ lsn_ctr_1_t os_log_written; - /** Number of writes being done to the log files */ - lint_ctr_1_t os_log_pending_writes; + /** Number of writes being done to the log files. + Protected by log_sys->write_mutex. */ + ulint_ctr_1_t os_log_pending_writes; /** We increase this counter, when we don't have enough space in the log buffer and have to flush it */ @@ -141,7 +140,7 @@ struct srv_stats_t { ulint_ctr_1_t n_lock_wait_count; /** Number of threads currently waiting on database locks */ - lint_ctr_1_t n_lock_wait_current_count; + simple_counter<ulint, true> n_lock_wait_current_count; /** Number of rows read. */ ulint_ctr_64_t n_rows_read; diff --git a/storage/innobase/include/sync0types.h b/storage/innobase/include/sync0types.h index 1d11bfa7811..c3d413e71df 100644 --- a/storage/innobase/include/sync0types.h +++ b/storage/innobase/include/sync0types.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2017, 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 @@ -1266,4 +1266,48 @@ enum rw_lock_flag_t { #define my_atomic_caslint my_atomic_caslong #endif +/** Simple counter aligned to CACHE_LINE_SIZE +@tparam Type the integer type of the counter +@tparam atomic whether to use atomic memory access */ +template <typename Type = ulint, bool atomic = false> +struct MY_ALIGNED(CPU_LEVEL1_DCACHE_LINESIZE) simple_counter +{ + /** Increment the counter */ + Type inc() { return add(1); } + /** Decrement the counter */ + Type dec() { return sub(1); } + + /** Add to the counter + @param[in] i amount to be added + @return the value of the counter after adding */ + Type add(Type i) + { + compile_time_assert(!atomic || sizeof(Type) == sizeof(lint)); + if (atomic) { + return Type(my_atomic_addlint(&m_counter, i)); + } else { + return m_counter += i; + } + } + /** Subtract from the counter + @param[in] i amount to be subtracted + @return the value of the counter after adding */ + Type sub(Type i) + { + compile_time_assert(!atomic || sizeof(Type) == sizeof(lint)); + if (atomic) { + return Type(my_atomic_addlint(&m_counter, -lint(i))); + } else { + return m_counter -= i; + } + } + + /** @return the value of the counter (non-atomic access)! */ + operator Type() const { return m_counter; } + +private: + /** The counter */ + Type m_counter; +}; + #endif /* sync0types_h */ diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 446e619abb9..75753b53467 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -1508,17 +1508,15 @@ private: } /* Avoid excessive mutex acquire/release */ - ++trx->in_depth; - - /* If trx->in_depth is greater than 1 then - transaction is already in InnoDB. */ - if (trx->in_depth > 1) { - + if (++trx->in_depth > 1) { + /* The transaction is already inside InnoDB. */ + ut_ad(trx->in_depth > 1); return; } /* Only the owning thread should release the latch. */ + ut_ad(trx->in_depth == 1); trx_assert_no_search_latch(trx); trx_mutex_enter(trx); @@ -1545,15 +1543,14 @@ private: ut_ad(trx->in_depth > 0); - --trx->in_depth; - - if (trx->in_depth > 0) { - + if (--trx->in_depth > 0) { + ut_ad(trx->in_depth); return; } /* Only the owning thread should release the latch. */ + ut_ad(trx->in_depth == 0); trx_assert_no_search_latch(trx); trx_mutex_enter(trx); diff --git a/storage/innobase/include/ut0counter.h b/storage/innobase/include/ut0counter.h index 70381f26a84..f1a9384667e 100644 --- a/storage/innobase/include/ut0counter.h +++ b/storage/innobase/include/ut0counter.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 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 @@ -44,8 +45,6 @@ Created 2012/04/12 by Sunny Bains /** Get the offset into the counter array. */ template <typename Type, int N> struct generic_indexer_t { - /** Default constructor/destructor should be OK. */ - /** @return offset within m_counter */ static size_t offset(size_t index) UNIV_NOTHROW { @@ -57,11 +56,6 @@ struct generic_indexer_t { to index into the counter array. See the comments for my_timer_cycles() */ template <typename Type=ulint, int N=1> struct counter_indexer_t : public generic_indexer_t<Type, N> { - - /** Default constructor/destructor should be OK. */ - - enum { fast = 1 }; - /** @return result from RDTSC or similar functions. */ static size_t get_rnd_index() UNIV_NOTHROW { @@ -82,27 +76,11 @@ struct counter_indexer_t : public generic_indexer_t<Type, N> { #endif /* !_WIN32 */ } } -}; -/** For counters where N=1 */ -template <typename Type=ulint, int N=1> -struct single_indexer_t { - /** Default constructor/destructor should are OK. */ - - enum { fast = 0 }; - - /** @return offset within m_counter */ - static size_t offset(size_t index) UNIV_NOTHROW + /** @return a random offset to the array */ + static size_t get_rnd_offset() UNIV_NOTHROW { - ut_ad(N == 1); - return((CACHE_LINE_SIZE / sizeof(Type))); - } - - /** @return 1 */ - static size_t get_rnd_index() UNIV_NOTHROW - { - ut_ad(N == 1); - return(1); + return(generic_indexer_t<Type, N>::offset(get_rnd_index())); } }; @@ -116,19 +94,11 @@ template < typename Type, int N = IB_N_SLOTS, template<typename, int> class Indexer = default_indexer_t> -class ib_counter_t { -public: - ib_counter_t() { memset(m_counter, 0x0, sizeof(m_counter)); } - +struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t +{ +#ifdef UNIV_DEBUG ~ib_counter_t() { - ut_ad(validate()); - } - - static bool is_fast() { return(Indexer<Type, N>::fast); } - - bool validate() UNIV_NOTHROW { -#ifdef UNIV_DEBUG size_t n = (CACHE_LINE_SIZE / sizeof(Type)); /* Check that we aren't writing outside our defined bounds. */ @@ -137,27 +107,23 @@ public: ut_ad(m_counter[i + j] == 0); } } -#endif /* UNIV_DEBUG */ - return(true); } +#endif /* UNIV_DEBUG */ - /** If you can't use a good index id. Increment by 1. */ + /** Increment the counter by 1. */ void inc() UNIV_NOTHROW { add(1); } - /** If you can't use a good index id. - @param n is the amount to increment */ - void add(Type n) UNIV_NOTHROW { - size_t i = m_policy.offset(m_policy.get_rnd_index()); - - ut_ad(i < UT_ARR_SIZE(m_counter)); + /** Increment the counter by 1. + @param[in] index a reasonably thread-unique identifier */ + void inc(size_t index) UNIV_NOTHROW { add(index, 1); } - m_counter[i] += n; - } + /** Add to the counter. + @param[in] n amount to be added */ + void add(Type n) UNIV_NOTHROW { add(m_policy.get_rnd_offset(), n); } - /** Use this if you can use a unique identifier, saves a - call to get_rnd_index(). - @param i index into a slot - @param n amount to increment */ + /** Add to the counter. + @param[in] index a reasonably thread-unique identifier + @param[in] n amount to be added */ void add(size_t index, Type n) UNIV_NOTHROW { size_t i = m_policy.offset(index); @@ -166,31 +132,6 @@ public: m_counter[i] += n; } - /** If you can't use a good index id. Decrement by 1. */ - void dec() UNIV_NOTHROW { sub(1); } - - /** If you can't use a good index id. - @param n the amount to decrement */ - void sub(Type n) UNIV_NOTHROW { - size_t i = m_policy.offset(m_policy.get_rnd_index()); - - ut_ad(i < UT_ARR_SIZE(m_counter)); - - m_counter[i] -= n; - } - - /** Use this if you can use a unique identifier, saves a - call to get_rnd_index(). - @param i index into a slot - @param n amount to decrement */ - void sub(size_t index, Type n) UNIV_NOTHROW { - size_t i = m_policy.offset(index); - - ut_ad(i < UT_ARR_SIZE(m_counter)); - - m_counter[i] -= n; - } - /* @return total value - not 100% accurate, since it is not atomic. */ operator Type() const UNIV_NOTHROW { Type total = 0; diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h index 3027004dbaf..7082d18da53 100644 --- a/storage/innobase/include/ut0ut.h +++ b/storage/innobase/include/ut0ut.h @@ -313,7 +313,7 @@ ut_sprintf_timestamp( Runs an idle loop on CPU. The argument gives the desired delay in microseconds on 100 MHz Pentium + Visual C++. @return dummy value */ -ulint +void ut_delay( /*=====*/ ulint delay); /*!< in: delay in microseconds on 100 MHz Pentium */ |