diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2017-04-21 17:32:02 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2017-04-21 17:47:23 +0300 |
commit | 996c7d5cb5e369de178da3482f3dfc36d57fd6a9 (patch) | |
tree | 499e295f2815eeb5e4222db6093f37046bc58f83 /storage | |
parent | 555e52f3bc8d67d0cfe176d25e2fe0c73fdb2fd2 (diff) | |
download | mariadb-git-996c7d5cb5e369de178da3482f3dfc36d57fd6a9.tar.gz |
MDEV-12545 Reduce the amount of fil_space_t lookups
buf_flush_write_block_low(): Acquire the tablespace reference once,
and pass it to lower-level functions. This is only a start; further
calls may be removed later.
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/buf/buf0buf.cc | 98 | ||||
-rw-r--r-- | storage/innobase/buf/buf0dblwr.cc | 4 | ||||
-rw-r--r-- | storage/innobase/buf/buf0flu.cc | 16 | ||||
-rw-r--r-- | storage/innobase/fil/fil0fil.cc | 76 | ||||
-rw-r--r-- | storage/innobase/fil/fil0pagecompress.cc | 63 | ||||
-rw-r--r-- | storage/innobase/include/buf0buf.h | 18 | ||||
-rw-r--r-- | storage/innobase/include/fil0fil.h | 29 | ||||
-rw-r--r-- | storage/innobase/include/fil0pagecompress.h | 30 | ||||
-rw-r--r-- | storage/innobase/include/fsp0pagecompress.ic | 63 | ||||
-rw-r--r-- | storage/xtradb/buf/buf0buf.cc | 99 | ||||
-rw-r--r-- | storage/xtradb/buf/buf0dblwr.cc | 4 | ||||
-rw-r--r-- | storage/xtradb/buf/buf0flu.cc | 16 | ||||
-rw-r--r-- | storage/xtradb/fil/fil0fil.cc | 76 | ||||
-rw-r--r-- | storage/xtradb/fil/fil0pagecompress.cc | 62 | ||||
-rw-r--r-- | storage/xtradb/include/buf0buf.h | 18 | ||||
-rw-r--r-- | storage/xtradb/include/fil0fil.h | 27 | ||||
-rw-r--r-- | storage/xtradb/include/fil0pagecompress.h | 30 | ||||
-rw-r--r-- | storage/xtradb/include/fsp0pagecompress.ic | 63 |
18 files changed, 309 insertions, 483 deletions
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 2133457fcbb..bb567119a13 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -6080,71 +6080,54 @@ buf_pool_reserve_tmp_slot( return (free_slot); } -/********************************************************************//** -Encrypts a buffer page right before it's flushed to disk -@param[in,out] bpage Page control block -@param[in,out] src_frame Source page -@param[in] space_id Tablespace id -@return either unencrypted source page or decrypted page. -*/ +/** Encryption and page_compression hook that is called just before +a page is written to disk. +@param[in,out] space tablespace +@param[in,out] bpage buffer page +@param[in] src_frame physical page frame that is being encrypted +@return page frame to be written to file +(may be src_frame or an encrypted/compressed copy of it) */ UNIV_INTERN byte* buf_page_encrypt_before_write( + fil_space_t* space, buf_page_t* bpage, - byte* src_frame, - ulint space_id) + byte* src_frame) { + ut_ad(space->id == bpage->space); bpage->real_size = UNIV_PAGE_SIZE; fil_page_type_validate(src_frame); - if (bpage->offset == 0) { + switch (bpage->offset) { + case 0: /* Page 0 of a tablespace is not encrypted/compressed */ ut_ad(bpage->key_version == 0); return src_frame; - } - - if (bpage->space == TRX_SYS_SPACE && bpage->offset == TRX_SYS_PAGE_NO) { - /* don't encrypt/compress page as it contains address to dblwr buffer */ - bpage->key_version = 0; - return src_frame; - } - - fil_space_t* space = fil_space_acquire_silent(space_id); - - /* Tablespace must exist during write operation */ - if (!space) { - /* This could be true on discard if we have injected a error - case e.g. in innodb.innodb-wl5522-debug-zip so that space - is already marked as stop_new_ops = true. */ - return src_frame; + case TRX_SYS_PAGE_NO: + if (bpage->space == TRX_SYS_SPACE) { + /* don't encrypt/compress page as it contains + address to dblwr buffer */ + bpage->key_version = 0; + return src_frame; + } } fil_space_crypt_t* crypt_data = space->crypt_data; - bool encrypted = true; - - if (space->crypt_data != NULL && space->crypt_data->not_encrypted()) { - /* Encryption is disabled */ - encrypted = false; - } + const bool encrypted = crypt_data + && !crypt_data->not_encrypted() + && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED + && (!crypt_data->is_default_encryption() + || srv_encrypt_tables); - if (!srv_encrypt_tables && (crypt_data == NULL || crypt_data->is_default_encryption())) { - /* Encryption is disabled */ - encrypted = false; - } - - /* Is encryption needed? */ - if (crypt_data == NULL || crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) { - /* An unencrypted table */ + if (!encrypted) { bpage->key_version = 0; - encrypted = false; } - bool page_compressed = fil_space_is_page_compressed(bpage->space); + bool page_compressed = FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags); if (!encrypted && !page_compressed) { /* No need to encrypt or page compress the page */ - fil_space_release(space); return src_frame; } @@ -6172,25 +6155,21 @@ buf_page_encrypt_before_write( bpage->real_size = page_size; slot->out_buf = dst_frame = tmp; -#ifdef UNIV_DEBUG - fil_page_type_validate(tmp); -#endif - + ut_d(fil_page_type_validate(tmp)); } else { /* First we compress the page content */ ulint out_len = 0; - ulint block_size = fil_space_get_block_size(bpage->space, bpage->offset, page_size); - - byte *tmp = fil_compress_page(bpage->space, - (byte *)src_frame, - slot->comp_buf, - page_size, - fil_space_get_page_compression_level(bpage->space), - block_size, - encrypted, - &out_len, - IF_LZO(slot->lzo_mem, NULL) - ); + + byte *tmp = fil_compress_page( + space, + (byte *)src_frame, + slot->comp_buf, + page_size, + fsp_flags_get_page_compression_level(space->flags), + fil_space_get_block_size(space, bpage->offset), + encrypted, + &out_len, + IF_LZO(slot->lzo_mem, NULL)); bpage->real_size = out_len; @@ -6215,7 +6194,6 @@ buf_page_encrypt_before_write( fil_page_type_validate(dst_frame); #endif - fil_space_release(space); // return dst_frame which will be written return dst_frame; } diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index f99679f6fec..cedbff96a67 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -986,7 +986,7 @@ flush: srv_stats.dblwr_writes.inc(); /* Now flush the doublewrite buffer data to disk */ - fil_flush(TRX_SYS_SPACE); + fil_flush(ulint(TRX_SYS_SPACE)); /* We know that the writes have been flushed to disk now and in recovery we will find them in the doublewrite buffer @@ -1231,7 +1231,7 @@ retry: } /* Now flush the doublewrite buffer data to disk */ - fil_flush(TRX_SYS_SPACE); + fil_flush(ulint(TRX_SYS_SPACE)); /* We know that the write has been flushed to disk now and during recovery we will find it in the doublewrite buffer diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 3f03ee8256f..87a5386ce25 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -831,11 +831,12 @@ buf_flush_write_block_low( buf_flush_t flush_type, /*!< in: type of flush */ bool sync) /*!< in: true if sync IO request */ { + fil_space_t* space = fil_space_acquire(bpage->space, true); + if (!space) { + return; + } ulint zip_size = buf_page_get_zip_size(bpage); page_t* frame = NULL; - ulint space_id = buf_page_get_space(bpage); - atomic_writes_t awrites = fil_space_get_atomic_writes(space_id); - #ifdef UNIV_DEBUG buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); ut_ad(!buf_pool_mutex_own(buf_pool)); @@ -906,7 +907,7 @@ buf_flush_write_block_low( break; } - frame = buf_page_encrypt_before_write(bpage, frame, space_id); + frame = buf_page_encrypt_before_write(space, bpage, frame); if (!srv_use_doublewrite_buf || !buf_dblwr) { fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, @@ -928,7 +929,8 @@ buf_flush_write_block_low( atomic writes should be used, no doublewrite buffer is used. */ - if (awrites == ATOMIC_WRITES_ON) { + if (fsp_flags_get_atomic_writes(space->flags) + == ATOMIC_WRITES_ON) { fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, FALSE, buf_page_get_space(bpage), @@ -952,13 +954,15 @@ buf_flush_write_block_low( are working on. */ if (sync) { ut_ad(flush_type == BUF_FLUSH_SINGLE_PAGE); - fil_flush(buf_page_get_space(bpage)); + fil_flush(space); /* true means we want to evict this page from the LRU list as well. */ buf_page_io_complete(bpage, true); } + fil_space_release(space); + /* Increment the counter of I/O operations used for selecting LRU policy. */ buf_LRU_stat_inc_io(); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index ceda86e16b6..2a812fa8a9f 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -5956,31 +5956,34 @@ fil_space_get_node( return (node); } -/********************************************************************//** -Return block size of node in file space -@return file block size */ + +/** Determine the block size of the data file. +@param[in] space tablespace +@param[in] offset page number +@return block size */ UNIV_INTERN ulint -fil_space_get_block_size( -/*=====================*/ - ulint space_id, - ulint block_offset, - ulint len) +fil_space_get_block_size(const fil_space_t* space, unsigned offset) { - ulint block_size = 512; - ut_ad(!mutex_own(&fil_system->mutex)); - - mutex_enter(&fil_system->mutex); - fil_space_t* space = fil_space_get_space(space_id); + ut_ad(space->n_pending_ops > 0); - if (space) { - fil_node_t* node = fil_space_get_node(space, space_id, &block_offset, 0, len); + ulint block_size = 512; - if (node) { - block_size = node->file_block_size; + for (fil_node_t* node = UT_LIST_GET_FIRST(space->chain); + node != NULL; + node = UT_LIST_GET_NEXT(chain, node)) { + block_size = node->file_block_size; + if (node->size > offset) { + break; } + offset -= node->size; + } + + /* Currently supporting block size up to 4K, + fall back to default if bigger requested. */ + if (block_size > 4096) { + block_size = 512; } - mutex_exit(&fil_system->mutex); return block_size; } @@ -6334,14 +6337,29 @@ fil_flush( mutex_exit(&fil_system->mutex); } -/**********************************************************************//** -Flushes to disk the writes in file spaces of the given type possibly cached by -the OS. */ +/** Flush a tablespace. +@param[in,out] space tablespace to flush */ UNIV_INTERN void -fil_flush_file_spaces( -/*==================*/ - ulint purpose) /*!< in: FIL_TABLESPACE, FIL_LOG */ +fil_flush(fil_space_t* space) +{ + ut_ad(space->n_pending_ops > 0); + + if (!space->is_stopping()) { + mutex_enter(&fil_system->mutex); + if (!space->is_stopping()) { + fil_flush_low(space); + } + mutex_exit(&fil_system->mutex); + } +} + +/** Flush to disk the writes in file spaces of the given type +possibly cached by the OS. +@param[in] purpose FIL_TYPE_TABLESPACE or FIL_TYPE_LOG */ +UNIV_INTERN +void +fil_flush_file_spaces(ulint purpose) { fil_space_t* space; ulint* space_ids; @@ -6769,12 +6787,14 @@ fil_iterate( if (page_compressed) { ulint len = 0; - fil_compress_page(space_id, + + fil_compress_page( + NULL, src, NULL, size, - fil_space_get_page_compression_level(space_id), - fil_space_get_block_size(space_id, offset, size), + 0,/* FIXME: compression level */ + 512,/* FIXME: use proper block size */ encrypted, &len, NULL); @@ -6785,6 +6805,8 @@ fil_iterate( /* If tablespace is encrypted, encrypt page before we write it back. Note that we should not encrypt the buffer that is in buffer pool. */ + /* NOTE: At this stage of IMPORT the + buffer pool is not being used at all! */ if (decrypted && encrypted) { byte *dest = writeptr + (i * size); ulint space = mach_read_from_4( diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc index 42f894f08d7..73df69beb90 100644 --- a/storage/innobase/fil/fil0pagecompress.cc +++ b/storage/innobase/fil/fil0pagecompress.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved. 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 @@ -91,8 +91,7 @@ UNIV_INTERN byte* fil_compress_page( /*==============*/ - ulint space_id, /*!< in: tablespace id of the - table. */ + fil_space_t* space, /*!< in,out: tablespace (NULL during IMPORT) */ byte* buf, /*!< in: buffer from which to write; in aio this must be appropriately aligned */ byte* out_buf, /*!< out: compressed buffer */ @@ -110,9 +109,12 @@ fil_compress_page( ulint write_size=0; /* Cache to avoid change during function execution */ ulint comp_method = innodb_compression_algorithm; - ulint orig_page_type; bool allocated=false; + /* page_compression does not apply to tables or tablespaces + that use ROW_FORMAT=COMPRESSED */ + ut_ad(!space || !FSP_FLAGS_GET_ZIP_SSIZE(space->flags)); + if (encrypted) { header_len += FIL_PAGE_COMPRESSION_METHOD_SIZE; } @@ -133,21 +135,14 @@ fil_compress_page( ut_ad(len); ut_ad(out_len); - /* read original page type */ - orig_page_type = mach_read_from_2(buf + FIL_PAGE_TYPE); - - fil_system_enter(); - fil_space_t* space = fil_space_get_by_id(space_id); - fil_system_exit(); - /* Let's not compress file space header or extent descriptor */ - if (orig_page_type == 0 || - orig_page_type == FIL_PAGE_TYPE_FSP_HDR || - orig_page_type == FIL_PAGE_TYPE_XDES || - orig_page_type == FIL_PAGE_PAGE_COMPRESSED) { + switch (fil_page_get_type(buf)) { + case 0: + case FIL_PAGE_TYPE_FSP_HDR: + case FIL_PAGE_TYPE_XDES: + case FIL_PAGE_PAGE_COMPRESSED: *out_len = len; - goto err_exit; } @@ -157,11 +152,11 @@ fil_compress_page( comp_level = page_zip_level; } -#ifdef UNIV_PAGECOMPRESS_DEBUG - ib_logf(IB_LOG_LEVEL_INFO, - "Preparing for compress for space %lu name %s len %lu.", - space_id, fil_space_name(space), len); -#endif /* UNIV_PAGECOMPRESS_DEBUG */ + DBUG_PRINT("compress", + ("Preparing for space " ULINTPF " '%s' len " ULINTPF, + space ? space->id : 0, + space ? space->name : "(import)", + len)); write_size = UNIV_PAGE_SIZE - header_len; @@ -306,10 +301,13 @@ fil_compress_page( if (err != Z_OK) { /* If error we leave the actual page as it was */ - if (space->printed_compression_failure == false) { + if (space && !space->printed_compression_failure) { ib_logf(IB_LOG_LEVEL_WARN, - "Compression failed for space %lu name %s len %lu rt %d write %lu.", - space_id, fil_space_name(space), len, err, write_size); + "Compression failed for space " + ULINTPF " name %s len " ULINTPF + " rt %d write " ULINTPF ".", + space->id, space->name, len, err, + write_size); space->printed_compression_failure = true; } @@ -367,9 +365,8 @@ fil_compress_page( fil_decompress_page(uncomp_page, comp_page, ulong(len), NULL); - if(buf_page_is_corrupted(false, uncomp_page, 0, space)) { - buf_page_print(uncomp_page, 0, BUF_PAGE_PRINT_NO_CRASH); - ut_error; + if (buf_page_is_corrupted(false, uncomp_page, 0, space)) { + buf_page_print(uncomp_page, 0, 0); } ut_free(comp_page); @@ -388,7 +385,6 @@ fil_compress_page( /* Actual write needs to be alligned on block size */ if (write_size % block_size) { size_t tmp = write_size; - write_size = (size_t)ut_uint64_align_up((ib_uint64_t)write_size, block_size); /* Clean up the end of buffer */ memset(out_buf+tmp, 0, write_size - tmp); @@ -398,11 +394,12 @@ fil_compress_page( #endif } -#ifdef UNIV_PAGECOMPRESS_DEBUG - ib_logf(IB_LOG_LEVEL_INFO, - "Compression succeeded for space %lu name %s len %lu out_len %lu.", - space_id, fil_space_name(space), len, write_size); -#endif /* UNIV_PAGECOMPRESS_DEBUG */ + DBUG_PRINT("compress", + ("Succeeded for space " ULINTPF + " '%s' len " ULINTPF " out_len " ULINTPF, + space ? space->id : 0, + space ? space->name : "(import)", + len, write_size)); srv_stats.page_compression_saved.add((len - write_size)); srv_stats.pages_page_compressed.inc(); diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 643e8c731e5..b4d39351370 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -1502,17 +1502,19 @@ buf_flush_update_zip_checksum( #endif /* !UNIV_HOTBACKUP */ -/********************************************************************//** -The hook that is called just before a page is written to disk. -The function encrypts the content of the page and returns a pointer -to a frame that will be written instead of the real frame. */ +/** Encryption and page_compression hook that is called just before +a page is written to disk. +@param[in,out] space tablespace +@param[in,out] bpage buffer page +@param[in] src_frame physical page frame that is being encrypted +@return page frame to be written to file +(may be src_frame or an encrypted/compressed copy of it) */ UNIV_INTERN byte* buf_page_encrypt_before_write( -/*==========================*/ - buf_page_t* page, /*!< in/out: buffer page to be flushed */ - byte* frame, /*!< in: src frame */ - ulint space_id); /*!< in: space id */ + fil_space_t* space, + buf_page_t* bpage, + byte* src_frame); /********************************************************************** The hook that is called after page is written to disk. diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 3d7ae49f8ae..ba9e5029c6d 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1135,14 +1135,18 @@ fil_flush( /*======*/ ulint space_id); /*!< in: file space id (this can be a group of log files or a tablespace of the database) */ -/**********************************************************************//** -Flushes to disk writes in file spaces of the given type possibly cached by -the OS. */ +/** Flush a tablespace. +@param[in,out] space tablespace to flush */ UNIV_INTERN void -fil_flush_file_spaces( -/*==================*/ - ulint purpose); /*!< in: FIL_TABLESPACE, FIL_LOG */ +fil_flush(fil_space_t* space); + +/** Flush to disk the writes in file spaces of the given type +possibly cached by the OS. +@param[in] purpose FIL_TYPE_TABLESPACE or FIL_TYPE_LOG */ +UNIV_INTERN +void +fil_flush_file_spaces(ulint purpose); /******************************************************************//** Checks the consistency of the tablespace cache. @return TRUE if ok */ @@ -1430,18 +1434,13 @@ fil_get_next_space_safe( /*====================*/ ulint id); /*!< in: previous space id */ - -/*******************************************************************//** -Returns the block size of the file space +/** Determine the block size of the data file. +@param[in] space tablespace +@param[in] offset page number @return block size */ UNIV_INTERN ulint -fil_space_get_block_size( -/*=====================*/ - ulint id, /*!< in: space id */ - ulint offset, /*!< in: page offset */ - ulint len); /*!< in: page len */ - +fil_space_get_block_size(const fil_space_t* space, unsigned offset); #endif /* UNIV_INNOCHECKSUM */ #ifndef UNIV_INNOCHECKSUM diff --git a/storage/innobase/include/fil0pagecompress.h b/storage/innobase/include/fil0pagecompress.h index 1fe5cb66bf6..73667c5420e 100644 --- a/storage/innobase/include/fil0pagecompress.h +++ b/storage/innobase/include/fil0pagecompress.h @@ -31,33 +31,6 @@ Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com ***********************************************************************/ /*******************************************************************//** -Returns the page compression level flag of the space, or 0 if the space -is not compressed. The tablespace must be cached in the memory cache. -@return page compression level if page compressed, ULINT_UNDEFINED if space not found */ -UNIV_INLINE -ulint -fil_space_get_page_compression_level( -/*=================================*/ - ulint id); /*!< in: space id */ -/*******************************************************************//** -Returns the page compression flag of the space, or false if the space -is not compressed. The tablespace must be cached in the memory cache. -@return true if page compressed, false if not or space not found */ -UNIV_INLINE -bool -fil_space_is_page_compressed( -/*=========================*/ - ulint id); /*!< in: space id */ -/*******************************************************************//** -Returns the atomic writes flag of the space, or false if the space -is not using atomic writes. The tablespace must be cached in the memory cache. -@return atomic write table option value */ -UNIV_INLINE -atomic_writes_t -fil_space_get_atomic_writes( -/*=========================*/ - ulint id); /*!< in: space id */ -/*******************************************************************//** Find out wheather the page is index page or not @return true if page type index page, false if not */ UNIV_INLINE @@ -84,8 +57,7 @@ UNIV_INTERN byte* fil_compress_page( /*==============*/ - ulint space_id, /*!< in: tablespace id of the - table. */ + fil_space_t* space, /*!< in,out: tablespace (NULL during IMPORT) */ byte* buf, /*!< in: buffer from which to write; in aio this must be appropriately aligned */ byte* out_buf, /*!< out: compressed buffer */ diff --git a/storage/innobase/include/fsp0pagecompress.ic b/storage/innobase/include/fsp0pagecompress.ic index 48163277feb..14f968e319e 100644 --- a/storage/innobase/include/fsp0pagecompress.ic +++ b/storage/innobase/include/fsp0pagecompress.ic @@ -85,47 +85,6 @@ fil_page_is_compressed_encrypted( return(mach_read_from_2(buf+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED); } -#ifndef UNIV_INNOCHECKSUM -/*******************************************************************//** -Returns the page compression level of the space, or 0 if the space -is not compressed. The tablespace must be cached in the memory cache. -@return page compression level, 0 if space not found */ -UNIV_INLINE -ulint -fil_space_get_page_compression_level( -/*=================================*/ - ulint id) /*!< in: space id */ -{ - ulint flags; - - flags = fil_space_get_flags(id); - - if (flags && flags != ULINT_UNDEFINED) { - - return(fsp_flags_get_page_compression_level(flags)); - } - - return(0); -} - -/*******************************************************************//** -Extract the page compression from space. -@return true if space is page compressed, false if space is not found -or space is not page compressed. */ -UNIV_INLINE -bool -fil_space_is_page_compressed( -/*=========================*/ - ulint id) /*!< in: space id */ -{ - ulint flags = fil_space_get_flags(id); - - return(flags != ULINT_UNDEFINED - && FSP_FLAGS_HAS_PAGE_COMPRESSION(flags)); -} - -#endif /* UNIV_INNOCHECKSUM */ - /****************************************************************//** Get the name of the compression algorithm used for page compression. @@ -166,28 +125,6 @@ fil_get_compression_alg_name( #ifndef UNIV_INNOCHECKSUM /*******************************************************************//** -Returns the atomic writes flag of the space, or false if the space -is not using atomic writes. The tablespace must be cached in the memory cache. -@return atomic writes table option value */ -UNIV_INLINE -atomic_writes_t -fil_space_get_atomic_writes( -/*========================*/ - ulint id) /*!< in: space id */ -{ - ulint flags; - - flags = fil_space_get_flags(id); - - if (flags && flags != ULINT_UNDEFINED) { - - return((atomic_writes_t)fsp_flags_get_atomic_writes(flags)); - } - - return((atomic_writes_t)0); -} - -/*******************************************************************//** Find out wheather the page is page compressed with lzo method @return true if page is page compressed with lzo method, false if not */ UNIV_INLINE diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc index 7f77f96c2fe..394d2be6838 100644 --- a/storage/xtradb/buf/buf0buf.cc +++ b/storage/xtradb/buf/buf0buf.cc @@ -6241,70 +6241,54 @@ buf_pool_reserve_tmp_slot( return (free_slot); } -/********************************************************************//** -Encrypts a buffer page right before it's flushed to disk -@param[in,out] bpage Page control block -@param[in,out] src_frame Source page -@param[in] space_id Tablespace id -@return either unencrypted source page or decrypted page. -*/ +/** Encryption and page_compression hook that is called just before +a page is written to disk. +@param[in,out] space tablespace +@param[in,out] bpage buffer page +@param[in] src_frame physical page frame that is being encrypted +@return page frame to be written to file +(may be src_frame or an encrypted/compressed copy of it) */ +UNIV_INTERN byte* buf_page_encrypt_before_write( + fil_space_t* space, buf_page_t* bpage, - byte* src_frame, - ulint space_id) + byte* src_frame) { + ut_ad(space->id == bpage->space); bpage->real_size = UNIV_PAGE_SIZE; fil_page_type_validate(src_frame); - if (bpage->offset == 0) { + switch (bpage->offset) { + case 0: /* Page 0 of a tablespace is not encrypted/compressed */ ut_ad(bpage->key_version == 0); return src_frame; - } - - if (bpage->space == TRX_SYS_SPACE && bpage->offset == TRX_SYS_PAGE_NO) { - /* don't encrypt/compress page as it contains address to dblwr buffer */ - bpage->key_version = 0; - return src_frame; - } - - fil_space_t* space = fil_space_acquire_silent(space_id); - - /* Tablespace must exist during write operation */ - if (!space) { - /* This could be true on discard if we have injected a error - case e.g. in innodb.innodb-wl5522-debug-zip so that space - is already marked as stop_new_ops = true. */ - return src_frame; + case TRX_SYS_PAGE_NO: + if (bpage->space == TRX_SYS_SPACE) { + /* don't encrypt/compress page as it contains + address to dblwr buffer */ + bpage->key_version = 0; + return src_frame; + } } fil_space_crypt_t* crypt_data = space->crypt_data; - bool encrypted = true; - - if (space->crypt_data != NULL && space->crypt_data->not_encrypted()) { - /* Encryption is disabled */ - encrypted = false; - } + const bool encrypted = crypt_data + && !crypt_data->not_encrypted() + && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED + && (!crypt_data->is_default_encryption() + || srv_encrypt_tables); - if (!srv_encrypt_tables && (crypt_data == NULL || crypt_data->is_default_encryption())) { - /* Encryption is disabled */ - encrypted = false; - } - - /* Is encryption needed? */ - if (crypt_data == NULL || crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) { - /* An unencrypted table */ + if (!encrypted) { bpage->key_version = 0; - encrypted = false; } - bool page_compressed = fil_space_is_page_compressed(bpage->space); + bool page_compressed = FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags); if (!encrypted && !page_compressed) { /* No need to encrypt or page compress the page */ - fil_space_release(space); return src_frame; } @@ -6332,25 +6316,21 @@ buf_page_encrypt_before_write( bpage->real_size = page_size; slot->out_buf = dst_frame = tmp; -#ifdef UNIV_DEBUG - fil_page_type_validate(tmp); -#endif - + ut_d(fil_page_type_validate(tmp)); } else { /* First we compress the page content */ ulint out_len = 0; - ulint block_size = fil_space_get_block_size(bpage->space, bpage->offset, page_size); - - byte *tmp = fil_compress_page(bpage->space, - (byte *)src_frame, - slot->comp_buf, - page_size, - fil_space_get_page_compression_level(bpage->space), - block_size, - encrypted, - &out_len, - IF_LZO(slot->lzo_mem, NULL) - ); + + byte *tmp = fil_compress_page( + space, + (byte *)src_frame, + slot->comp_buf, + page_size, + fsp_flags_get_page_compression_level(space->flags), + fil_space_get_block_size(space, bpage->offset), + encrypted, + &out_len, + IF_LZO(slot->lzo_mem, NULL)); bpage->real_size = out_len; @@ -6375,7 +6355,6 @@ buf_page_encrypt_before_write( fil_page_type_validate(dst_frame); #endif - fil_space_release(space); // return dst_frame which will be written return dst_frame; } diff --git a/storage/xtradb/buf/buf0dblwr.cc b/storage/xtradb/buf/buf0dblwr.cc index ddef13ef8ea..55c5e4d543a 100644 --- a/storage/xtradb/buf/buf0dblwr.cc +++ b/storage/xtradb/buf/buf0dblwr.cc @@ -1001,7 +1001,7 @@ flush: srv_stats.dblwr_writes.inc(); /* Now flush the doublewrite buffer data to disk */ - fil_flush(TRX_SYS_SPACE); + fil_flush(ulint(TRX_SYS_SPACE)); /* We know that the writes have been flushed to disk now and in recovery we will find them in the doublewrite buffer @@ -1249,7 +1249,7 @@ retry: } /* Now flush the doublewrite buffer data to disk */ - fil_flush(TRX_SYS_SPACE); + fil_flush(ulint(TRX_SYS_SPACE)); /* We know that the write has been flushed to disk now and during recovery we will find it in the doublewrite buffer diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc index 4804d71a51f..f71bdb9f69a 100644 --- a/storage/xtradb/buf/buf0flu.cc +++ b/storage/xtradb/buf/buf0flu.cc @@ -873,11 +873,12 @@ buf_flush_write_block_low( buf_flush_t flush_type, /*!< in: type of flush */ bool sync) /*!< in: true if sync IO request */ { + fil_space_t* space = fil_space_acquire(bpage->space, true); + if (!space) { + return; + } ulint zip_size = buf_page_get_zip_size(bpage); page_t* frame = NULL; - ulint space_id = buf_page_get_space(bpage); - atomic_writes_t awrites = fil_space_get_atomic_writes(space_id); - #ifdef UNIV_DEBUG buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); ut_ad(!mutex_own(&buf_pool->LRU_list_mutex)); @@ -947,7 +948,7 @@ buf_flush_write_block_low( break; } - frame = buf_page_encrypt_before_write(bpage, frame, space_id); + frame = buf_page_encrypt_before_write(space, bpage, frame); if (!srv_use_doublewrite_buf || !buf_dblwr) { fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, @@ -968,7 +969,8 @@ buf_flush_write_block_low( atomic writes should be used, no doublewrite buffer is used. */ - if (awrites == ATOMIC_WRITES_ON) { + if (fsp_flags_get_atomic_writes(space->flags) + == ATOMIC_WRITES_ON) { fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, FALSE, buf_page_get_space(bpage), @@ -991,10 +993,12 @@ buf_flush_write_block_low( are working on. */ if (sync) { ut_ad(flush_type == BUF_FLUSH_SINGLE_PAGE); - fil_flush(buf_page_get_space(bpage)); + fil_flush(space); buf_page_io_complete(bpage); } + fil_space_release(space); + /* Increment the counter of I/O operations used for selecting LRU policy. */ buf_LRU_stat_inc_io(); diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index fba7d5d8e38..e504ab3947e 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -5993,31 +5993,34 @@ fil_space_get_node( return (node); } -/********************************************************************//** -Return block size of node in file space -@return file block size */ + +/** Determine the block size of the data file. +@param[in] space tablespace +@param[in] offset page number +@return block size */ UNIV_INTERN ulint -fil_space_get_block_size( -/*=====================*/ - ulint space_id, - ulint block_offset, - ulint len) +fil_space_get_block_size(const fil_space_t* space, unsigned offset) { - ulint block_size = 512; - ut_ad(!mutex_own(&fil_system->mutex)); - - mutex_enter(&fil_system->mutex); - fil_space_t* space = fil_space_get_space(space_id); + ut_ad(space->n_pending_ops > 0); - if (space) { - fil_node_t* node = fil_space_get_node(space, space_id, &block_offset, 0, len); + ulint block_size = 512; - if (node) { - block_size = node->file_block_size; + for (fil_node_t* node = UT_LIST_GET_FIRST(space->chain); + node != NULL; + node = UT_LIST_GET_NEXT(chain, node)) { + block_size = node->file_block_size; + if (node->size > offset) { + break; } + offset -= node->size; + } + + /* Currently supporting block size up to 4K, + fall back to default if bigger requested. */ + if (block_size > 4096) { + block_size = 512; } - mutex_exit(&fil_system->mutex); return block_size; } @@ -6398,14 +6401,29 @@ fil_flush( mutex_exit(&fil_system->mutex); } -/**********************************************************************//** -Flushes to disk the writes in file spaces of the given type possibly cached by -the OS. */ +/** Flush a tablespace. +@param[in,out] space tablespace to flush */ UNIV_INTERN void -fil_flush_file_spaces( -/*==================*/ - ulint purpose) /*!< in: FIL_TABLESPACE, FIL_LOG */ +fil_flush(fil_space_t* space) +{ + ut_ad(space->n_pending_ops > 0); + + if (!space->is_stopping()) { + mutex_enter(&fil_system->mutex); + if (!space->is_stopping()) { + fil_flush_low(space); + } + mutex_exit(&fil_system->mutex); + } +} + +/** Flush to disk the writes in file spaces of the given type +possibly cached by the OS. +@param[in] purpose FIL_TYPE_TABLESPACE or FIL_TYPE_LOG */ +UNIV_INTERN +void +fil_flush_file_spaces(ulint purpose) { fil_space_t* space; ulint* space_ids; @@ -6833,12 +6851,14 @@ fil_iterate( if (page_compressed) { ulint len = 0; - fil_compress_page(space_id, + + fil_compress_page( + NULL, src, NULL, size, - fil_space_get_page_compression_level(space_id), - fil_space_get_block_size(space_id, offset, size), + 0,/* FIXME: compression level */ + 512,/* FIXME: use proper block size */ encrypted, &len, NULL); @@ -6849,6 +6869,8 @@ fil_iterate( /* If tablespace is encrypted, encrypt page before we write it back. Note that we should not encrypt the buffer that is in buffer pool. */ + /* NOTE: At this stage of IMPORT the + buffer pool is not being used at all! */ if (decrypted && encrypted) { byte *dest = writeptr + (i * size); ulint space = mach_read_from_4( diff --git a/storage/xtradb/fil/fil0pagecompress.cc b/storage/xtradb/fil/fil0pagecompress.cc index 655460c57ac..73df69beb90 100644 --- a/storage/xtradb/fil/fil0pagecompress.cc +++ b/storage/xtradb/fil/fil0pagecompress.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved. 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 @@ -91,8 +91,7 @@ UNIV_INTERN byte* fil_compress_page( /*==============*/ - ulint space_id, /*!< in: tablespace id of the - table. */ + fil_space_t* space, /*!< in,out: tablespace (NULL during IMPORT) */ byte* buf, /*!< in: buffer from which to write; in aio this must be appropriately aligned */ byte* out_buf, /*!< out: compressed buffer */ @@ -110,9 +109,12 @@ fil_compress_page( ulint write_size=0; /* Cache to avoid change during function execution */ ulint comp_method = innodb_compression_algorithm; - ulint orig_page_type; bool allocated=false; + /* page_compression does not apply to tables or tablespaces + that use ROW_FORMAT=COMPRESSED */ + ut_ad(!space || !FSP_FLAGS_GET_ZIP_SSIZE(space->flags)); + if (encrypted) { header_len += FIL_PAGE_COMPRESSION_METHOD_SIZE; } @@ -133,21 +135,14 @@ fil_compress_page( ut_ad(len); ut_ad(out_len); - /* read original page type */ - orig_page_type = mach_read_from_2(buf + FIL_PAGE_TYPE); - - fil_system_enter(); - fil_space_t* space = fil_space_get_by_id(space_id); - fil_system_exit(); - /* Let's not compress file space header or extent descriptor */ - if (orig_page_type == 0 || - orig_page_type == FIL_PAGE_TYPE_FSP_HDR || - orig_page_type == FIL_PAGE_TYPE_XDES || - orig_page_type == FIL_PAGE_PAGE_COMPRESSED) { + switch (fil_page_get_type(buf)) { + case 0: + case FIL_PAGE_TYPE_FSP_HDR: + case FIL_PAGE_TYPE_XDES: + case FIL_PAGE_PAGE_COMPRESSED: *out_len = len; - goto err_exit; } @@ -157,11 +152,11 @@ fil_compress_page( comp_level = page_zip_level; } -#ifdef UNIV_PAGECOMPRESS_DEBUG - ib_logf(IB_LOG_LEVEL_INFO, - "Preparing for compress for space %lu name %s len %lu.", - space_id, fil_space_name(space), len); -#endif /* UNIV_PAGECOMPRESS_DEBUG */ + DBUG_PRINT("compress", + ("Preparing for space " ULINTPF " '%s' len " ULINTPF, + space ? space->id : 0, + space ? space->name : "(import)", + len)); write_size = UNIV_PAGE_SIZE - header_len; @@ -306,10 +301,13 @@ fil_compress_page( if (err != Z_OK) { /* If error we leave the actual page as it was */ - if (space->printed_compression_failure == false) { + if (space && !space->printed_compression_failure) { ib_logf(IB_LOG_LEVEL_WARN, - "Compression failed for space %lu name %s len %lu rt %d write %lu.", - space_id, fil_space_name(space), len, err, write_size); + "Compression failed for space " + ULINTPF " name %s len " ULINTPF + " rt %d write " ULINTPF ".", + space->id, space->name, len, err, + write_size); space->printed_compression_failure = true; } @@ -367,9 +365,8 @@ fil_compress_page( fil_decompress_page(uncomp_page, comp_page, ulong(len), NULL); - if(buf_page_is_corrupted(false, uncomp_page, 0, space)) { - buf_page_print(uncomp_page, 0, BUF_PAGE_PRINT_NO_CRASH); - ut_error; + if (buf_page_is_corrupted(false, uncomp_page, 0, space)) { + buf_page_print(uncomp_page, 0, 0); } ut_free(comp_page); @@ -397,11 +394,12 @@ fil_compress_page( #endif } -#ifdef UNIV_PAGECOMPRESS_DEBUG - ib_logf(IB_LOG_LEVEL_INFO, - "Compression succeeded for space %lu name %s len %lu out_len %lu.", - space_id, fil_space_name(space), len, write_size); -#endif /* UNIV_PAGECOMPRESS_DEBUG */ + DBUG_PRINT("compress", + ("Succeeded for space " ULINTPF + " '%s' len " ULINTPF " out_len " ULINTPF, + space ? space->id : 0, + space ? space->name : "(import)", + len, write_size)); srv_stats.page_compression_saved.add((len - write_size)); srv_stats.pages_page_compressed.inc(); diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h index 1774d9445ff..4a632e2345f 100644 --- a/storage/xtradb/include/buf0buf.h +++ b/storage/xtradb/include/buf0buf.h @@ -1534,17 +1534,19 @@ buf_own_zip_mutex_for_page( MY_ATTRIBUTE((nonnull,warn_unused_result)); #endif /* UNIV_DEBUG */ -/********************************************************************//** -The hook that is called just before a page is written to disk. -The function encrypts the content of the page and returns a pointer -to a frame that will be written instead of the real frame. */ +/** Encryption and page_compression hook that is called just before +a page is written to disk. +@param[in,out] space tablespace +@param[in,out] bpage buffer page +@param[in] src_frame physical page frame that is being encrypted +@return page frame to be written to file +(may be src_frame or an encrypted/compressed copy of it) */ UNIV_INTERN byte* buf_page_encrypt_before_write( -/*==========================*/ - buf_page_t* page, /*!< in/out: buffer page to be flushed */ - byte* frame, /*!< in: src frame */ - ulint space_id); /*!< in: space id */ + fil_space_t* space, + buf_page_t* bpage, + byte* src_frame); /********************************************************************** The hook that is called after page is written to disk. diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h index 698039afede..fe7cc60d1e4 100644 --- a/storage/xtradb/include/fil0fil.h +++ b/storage/xtradb/include/fil0fil.h @@ -1120,16 +1120,13 @@ _fil_io( #define fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message, write_size) \ _fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message, write_size, NULL) -/*******************************************************************//** -Returns the block size of the file space +/** Determine the block size of the data file. +@param[in] space tablespace +@param[in] offset page number @return block size */ UNIV_INTERN ulint -fil_space_get_block_size( -/*=====================*/ - ulint id, /*!< in: space id */ - ulint offset, /*!< in: page offset */ - ulint len); /*!< in: page len */ +fil_space_get_block_size(const fil_space_t* space, unsigned offset); /**********************************************************************//** Waits for an aio operation to complete. This function is used to write the @@ -1151,14 +1148,18 @@ fil_flush( /*======*/ ulint space_id); /*!< in: file space id (this can be a group of log files or a tablespace of the database) */ -/**********************************************************************//** -Flushes to disk writes in file spaces of the given type possibly cached by -the OS. */ +/** Flush a tablespace. +@param[in,out] space tablespace to flush */ UNIV_INTERN void -fil_flush_file_spaces( -/*==================*/ - ulint purpose); /*!< in: FIL_TABLESPACE, FIL_LOG */ +fil_flush(fil_space_t* space); + +/** Flush to disk the writes in file spaces of the given type +possibly cached by the OS. +@param[in] purpose FIL_TYPE_TABLESPACE or FIL_TYPE_LOG */ +UNIV_INTERN +void +fil_flush_file_spaces(ulint purpose); /******************************************************************//** Checks the consistency of the tablespace cache. @return TRUE if ok */ diff --git a/storage/xtradb/include/fil0pagecompress.h b/storage/xtradb/include/fil0pagecompress.h index 1fe5cb66bf6..73667c5420e 100644 --- a/storage/xtradb/include/fil0pagecompress.h +++ b/storage/xtradb/include/fil0pagecompress.h @@ -31,33 +31,6 @@ Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com ***********************************************************************/ /*******************************************************************//** -Returns the page compression level flag of the space, or 0 if the space -is not compressed. The tablespace must be cached in the memory cache. -@return page compression level if page compressed, ULINT_UNDEFINED if space not found */ -UNIV_INLINE -ulint -fil_space_get_page_compression_level( -/*=================================*/ - ulint id); /*!< in: space id */ -/*******************************************************************//** -Returns the page compression flag of the space, or false if the space -is not compressed. The tablespace must be cached in the memory cache. -@return true if page compressed, false if not or space not found */ -UNIV_INLINE -bool -fil_space_is_page_compressed( -/*=========================*/ - ulint id); /*!< in: space id */ -/*******************************************************************//** -Returns the atomic writes flag of the space, or false if the space -is not using atomic writes. The tablespace must be cached in the memory cache. -@return atomic write table option value */ -UNIV_INLINE -atomic_writes_t -fil_space_get_atomic_writes( -/*=========================*/ - ulint id); /*!< in: space id */ -/*******************************************************************//** Find out wheather the page is index page or not @return true if page type index page, false if not */ UNIV_INLINE @@ -84,8 +57,7 @@ UNIV_INTERN byte* fil_compress_page( /*==============*/ - ulint space_id, /*!< in: tablespace id of the - table. */ + fil_space_t* space, /*!< in,out: tablespace (NULL during IMPORT) */ byte* buf, /*!< in: buffer from which to write; in aio this must be appropriately aligned */ byte* out_buf, /*!< out: compressed buffer */ diff --git a/storage/xtradb/include/fsp0pagecompress.ic b/storage/xtradb/include/fsp0pagecompress.ic index 48163277feb..14f968e319e 100644 --- a/storage/xtradb/include/fsp0pagecompress.ic +++ b/storage/xtradb/include/fsp0pagecompress.ic @@ -85,47 +85,6 @@ fil_page_is_compressed_encrypted( return(mach_read_from_2(buf+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED); } -#ifndef UNIV_INNOCHECKSUM -/*******************************************************************//** -Returns the page compression level of the space, or 0 if the space -is not compressed. The tablespace must be cached in the memory cache. -@return page compression level, 0 if space not found */ -UNIV_INLINE -ulint -fil_space_get_page_compression_level( -/*=================================*/ - ulint id) /*!< in: space id */ -{ - ulint flags; - - flags = fil_space_get_flags(id); - - if (flags && flags != ULINT_UNDEFINED) { - - return(fsp_flags_get_page_compression_level(flags)); - } - - return(0); -} - -/*******************************************************************//** -Extract the page compression from space. -@return true if space is page compressed, false if space is not found -or space is not page compressed. */ -UNIV_INLINE -bool -fil_space_is_page_compressed( -/*=========================*/ - ulint id) /*!< in: space id */ -{ - ulint flags = fil_space_get_flags(id); - - return(flags != ULINT_UNDEFINED - && FSP_FLAGS_HAS_PAGE_COMPRESSION(flags)); -} - -#endif /* UNIV_INNOCHECKSUM */ - /****************************************************************//** Get the name of the compression algorithm used for page compression. @@ -166,28 +125,6 @@ fil_get_compression_alg_name( #ifndef UNIV_INNOCHECKSUM /*******************************************************************//** -Returns the atomic writes flag of the space, or false if the space -is not using atomic writes. The tablespace must be cached in the memory cache. -@return atomic writes table option value */ -UNIV_INLINE -atomic_writes_t -fil_space_get_atomic_writes( -/*========================*/ - ulint id) /*!< in: space id */ -{ - ulint flags; - - flags = fil_space_get_flags(id); - - if (flags && flags != ULINT_UNDEFINED) { - - return((atomic_writes_t)fsp_flags_get_atomic_writes(flags)); - } - - return((atomic_writes_t)0); -} - -/*******************************************************************//** Find out wheather the page is page compressed with lzo method @return true if page is page compressed with lzo method, false if not */ UNIV_INLINE |