Commit adbd5c3a authored by marko's avatar marko

branches/zip: When retrieving compressed BLOBs, avoid allocating

uncompressed page frames.

buf_page_get_zip(), buf_page_release_zip(): New functions, used
by btr_copy_zblob_prefix().

btr_copy_zblob_prefix(): Do not call inflateEnd().
parent f56b6cf4
......@@ -4312,33 +4312,35 @@ btr_copy_zblob_prefix(
ut_ad(space_id);
for (;;) {
mtr_t mtr;
buf_block_t* block;
page_t* page;
buf_page_t* bpage;
int err;
ulint next_page_no;
mtr_start(&mtr);
bpage = buf_page_get_zip(space_id, zip_size, page_no);
block = buf_page_get(space_id, zip_size, page_no,
RW_S_LATCH, &mtr);
#ifdef UNIV_SYNC_DEBUG
buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE);
#endif /* UNIV_SYNC_DEBUG */
page = buf_block_get_frame(block);
if (UNIV_UNLIKELY(!bpage)) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Cannot load"
" compressed BLOB"
" page %lu space %lu\n",
(ulong) page_no, (ulong) space_id);
return;
}
if (UNIV_UNLIKELY(fil_page_get_type(page)
if (UNIV_UNLIKELY(fil_page_get_type(bpage->zip.data)
!= FIL_PAGE_TYPE_ZBLOB)) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Unknown type %lu of"
" compressed BLOB"
" page %lu space %lu\n",
(ulong) fil_page_get_type(page),
(ulong) fil_page_get_type(bpage->zip.data),
(ulong) page_no, (ulong) space_id);
goto end_of_blob;
}
next_page_no = mach_read_from_4(page + offset);
next_page_no = mach_read_from_4(bpage->zip.data + offset);
if (UNIV_LIKELY(offset == FIL_PAGE_NEXT)) {
/* When the BLOB begins at page header,
......@@ -4349,7 +4351,7 @@ btr_copy_zblob_prefix(
offset += 4;
}
d_stream->next_in = page + offset;
d_stream->next_in = bpage->zip.data + offset;
d_stream->avail_in = zip_size - offset;
err = inflate(d_stream, Z_NO_FLUSH);
......@@ -4388,19 +4390,21 @@ inflate_error:
(ulong) space_id);
} else {
err = inflate(d_stream, Z_FINISH);
if (UNIV_UNLIKELY
(err != Z_STREAM_END)) {
switch (err) {
case Z_STREAM_END:
case Z_BUF_ERROR:
break;
default:
goto inflate_error;
}
}
end_of_blob:
mtr_commit(&mtr);
inflateEnd(d_stream);
buf_page_release_zip(bpage);
return;
}
mtr_commit(&mtr);
buf_page_release_zip(bpage);
/* On other BLOB pages except the first
the BLOB header always is at the page header: */
......@@ -4447,6 +4451,7 @@ btr_copy_externally_stored_field_prefix_low(
btr_copy_zblob_prefix(&d_stream, zip_size,
space_id, page_no, offset);
inflateEnd(&d_stream);
return(d_stream.total_out);
} else {
return(btr_copy_blob_prefix(buf, len, space_id,
......
......@@ -1458,6 +1458,126 @@ buf_page_reset_file_page_was_freed(
}
#endif /* UNIV_DEBUG_FILE_ACCESSES */
/************************************************************************
Get read access to a compressed page (usually FIL_PAGE_TYPE_ZBLOB). */
buf_page_t*
buf_page_get_zip(
/*=============*/
/* out: pointer to the block */
ulint space, /* in: space id */
ulint zip_size,/* in: compressed page size */
ulint offset) /* in: page number */
{
buf_page_t* bpage;
mutex_t* block_mutex;
ibool must_read;
#ifndef UNIV_LOG_DEBUG
ut_ad(!ibuf_inside());
#endif
buf_pool->n_page_gets++;
for (;;) {
mutex_enter_fast(&buf_pool->mutex);
lookup:
bpage = buf_page_hash_get(space, offset);
if (bpage) {
break;
}
/* Page not in buf_pool: needs to be read from file */
mutex_exit(&buf_pool->mutex);
buf_read_page(space, zip_size, offset);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % 37 || buf_validate());
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
}
if (UNIV_UNLIKELY(!bpage->zip.data)) {
/* There is no compressed page. */
mutex_exit(&buf_pool->mutex);
return(NULL);
}
block_mutex = buf_page_get_mutex(bpage);
mutex_enter(block_mutex);
switch (buf_page_get_state(bpage)) {
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_READY_FOR_USE:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
case BUF_BLOCK_ZIP_FREE:
ut_error;
break;
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
bpage->buf_fix_count++;
break;
case BUF_BLOCK_FILE_PAGE:
/* Discard the uncompressed page frame if possible. */
if (buf_LRU_free_block(bpage, FALSE)) {
mutex_exit(block_mutex);
goto lookup;
}
buf_block_buf_fix_inc((buf_block_t*) bpage,
__FILE__, __LINE__);
break;
}
must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
mutex_exit(&buf_pool->mutex);
buf_page_set_accessed(bpage, TRUE);
mutex_exit(block_mutex);
buf_block_make_young(bpage);
#ifdef UNIV_DEBUG_FILE_ACCESSES
ut_a(!bpage->file_page_was_freed);
#endif
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % 5771 || buf_validate());
ut_a(bpage->buf_fix_count > 0);
ut_a(buf_page_in_file(bpage));
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
if (must_read) {
/* Let us wait until the read operation
completes */
for (;;) {
enum buf_io_fix io_fix;
mutex_enter(block_mutex);
io_fix = buf_page_get_io_fix(bpage);
mutex_exit(block_mutex);
if (io_fix == BUF_IO_READ) {
os_thread_sleep(WAIT_FOR_READ);
} else {
break;
}
}
}
#ifdef UNIV_IBUF_DEBUG
ut_a(ibuf_count_get(buf_page_get_space(bpage),
buf_page_get_page_no(bpage)) == 0);
#endif
return(bpage);
}
/************************************************************************
This is the general function used to get access to a database page. */
......
......@@ -223,6 +223,18 @@ buf_page_get_known_nowait(
ulint line, /* in: line where called */
mtr_t* mtr); /* in: mini-transaction */
/************************************************************************
Get read access to a compressed page (usually FIL_PAGE_TYPE_ZBLOB).
The page must be released with buf_page_release_zip(). */
buf_page_t*
buf_page_get_zip(
/*=============*/
/* out: pointer to the block,
or NULL if not compressed */
ulint space, /* in: space id */
ulint zip_size,/* in: compressed page size */
ulint offset);/* in: page number */
/************************************************************************
This is the general function used to get access to a database page. */
buf_block_t*
......@@ -270,6 +282,13 @@ buf_page_init_for_backup_restore(
buf_block_t* block); /* in: block to init */
#endif /* UNIV_HOTBACKUP */
/************************************************************************
Releases a compressed-only page acquired with buf_page_get_zip(). */
UNIV_INLINE
void
buf_page_release_zip(
/*=================*/
buf_page_t* bpage); /* in: buffer block */
/************************************************************************
Decrements the bufferfix count of a buffer control block and releases
a latch, if specified. */
UNIV_INLINE
......
......@@ -954,6 +954,46 @@ buf_page_get_release_on_io(
return(NULL);
}
/************************************************************************
Releases a compressed-only page acquired with buf_page_get_zip(). */
UNIV_INLINE
void
buf_page_release_zip(
/*=================*/
buf_page_t* bpage) /* in: buffer block */
{
buf_block_t* block;
ut_ad(bpage);
ut_a(bpage->buf_fix_count > 0);
switch (buf_page_get_state(bpage)) {
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
mutex_enter(&buf_pool->zip_mutex);
bpage->buf_fix_count--;
mutex_exit(&buf_pool->zip_mutex);
return;
case BUF_BLOCK_FILE_PAGE:
block = (buf_block_t*) bpage;
mutex_enter(&block->mutex);
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&block->debug_latch);
#endif
bpage->buf_fix_count--;
mutex_exit(&block->mutex);
return;
case BUF_BLOCK_ZIP_FREE:
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_READY_FOR_USE:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
break;
}
ut_error;
}
/************************************************************************
Decrements the bufferfix count of a buffer control block and releases
a latch, if specified. */
......
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