Commit 996c7d5c authored by Marko Mäkelä's avatar Marko Mäkelä

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.
parent 555e52f3
......@@ -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;
}
......
......@@ -986,7 +986,7 @@ buf_dblwr_flush_buffered_writes(void)
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 @@ buf_dblwr_write_single_page(
}
/* 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
......
......@@ -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();
......
......@@ -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(
......
/*****************************************************************************
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();
......
......@@ -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.
......
......@@ -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
......
......@@ -30,33 +30,6 @@ atomic writes information to table space.
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 */
......@@ -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 */
......
......@@ -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.
......@@ -165,28 +124,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 */
......
......@@ -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;
}
......
......@@ -1001,7 +1001,7 @@ buf_dblwr_flush_buffered_writes(void)
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 @@ buf_dblwr_write_single_page(
}
/* 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
......
......@@ -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();
......
......@@ -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(
......
/*****************************************************************************
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();
......
......@@ -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.
......
......@@ -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 */
......
......@@ -30,33 +30,6 @@ atomic writes information to table space.
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 */
......@@ -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 */
......
......@@ -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.
......@@ -165,28 +124,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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment