Commit ccbb93c0 authored by marko's avatar marko

branches/zip: btr_copy_externally_stored_field_prefix_low():

Split the code to subroutines.

btr_copy_blob_prefix(): New function: copy the prefix of the externally
stored part of an uncompressed BLOB.

btr_copy_zblob_prefix(): New function: copy the prefix of the externally
stored part of a compressed BLOB.

btr_blob_get_part_len(), btr_blob_get_next_page_no(): Add const qualifier
to the parameter.
parent d3d72895
...@@ -3548,8 +3548,8 @@ static ...@@ -3548,8 +3548,8 @@ static
ulint ulint
btr_blob_get_part_len( btr_blob_get_part_len(
/*==================*/ /*==================*/
/* out: part length */ /* out: part length */
byte* blob_header) /* in: blob header */ const byte* blob_header) /* in: blob header */
{ {
return(mach_read_from_4(blob_header + BTR_BLOB_HDR_PART_LEN)); return(mach_read_from_4(blob_header + BTR_BLOB_HDR_PART_LEN));
} }
...@@ -3560,9 +3560,9 @@ static ...@@ -3560,9 +3560,9 @@ static
ulint ulint
btr_blob_get_next_page_no( btr_blob_get_next_page_no(
/*======================*/ /*======================*/
/* out: page number or FIL_NULL if /* out: page number or FIL_NULL if
no more pages */ no more pages */
byte* blob_header) /* in: blob header */ const byte* blob_header) /* in: blob header */
{ {
return(mach_read_from_4(blob_header + BTR_BLOB_HDR_NEXT_PAGE_NO)); return(mach_read_from_4(blob_header + BTR_BLOB_HDR_NEXT_PAGE_NO));
} }
...@@ -4170,46 +4170,88 @@ btr_rec_free_updated_extern_fields( ...@@ -4170,46 +4170,88 @@ btr_rec_free_updated_extern_fields(
} }
/*********************************************************************** /***********************************************************************
Copies the prefix of an externally stored field of a record. */ Copies the prefix of an uncompressed BLOB. */
static static
ulint ulint
btr_copy_externally_stored_field_prefix_low( btr_copy_blob_prefix(
/*========================================*/ /*=================*/
/* out: bytes written to buf */ /* out: bytes written to buf */
byte* buf, /* out: the externally stored part of byte* buf, /* out: the externally stored part of
the field, or a prefix of it */ the field, or a prefix of it */
ulint len, /* in: length of buf, in bytes */ ulint len, /* in: length of buf, in bytes */
ulint zip_size,/* in: nonzero=compressed BLOB page size,
zero for uncompressed BLOBs */
ulint space_id,/* in: space id of the first BLOB page */ ulint space_id,/* in: space id of the first BLOB page */
ulint page_no,/* in: page number of the first BLOB page */ ulint page_no,/* in: page number of the first BLOB page */
ulint offset) /* in: offset on the first BLOB page */ ulint offset) /* in: offset on the first BLOB page */
{ {
ulint copied_len = 0; ulint copied_len = 0;
mtr_t mtr;
z_stream d_stream;
if (UNIV_UNLIKELY(len == 0)) { for (;;) {
return(0); mtr_t mtr;
} buf_block_t* block;
const page_t* page;
const byte* blob_header;
ulint part_len;
ulint copy_len;
if (UNIV_UNLIKELY(zip_size)) { mtr_start(&mtr);
int err;
d_stream.zalloc = (alloc_func) 0;
d_stream.zfree = (free_func) 0;
d_stream.opaque = (voidpf) 0;
err = inflateInit(&d_stream); block = buf_page_get(space_id, page_no, RW_S_LATCH, &mtr);
ut_a(err == Z_OK); #ifdef UNIV_SYNC_DEBUG
buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE);
#endif /* UNIV_SYNC_DEBUG */
page = buf_block_get_frame(block);
d_stream.next_out = buf; /* Unfortunately, FIL_PAGE_TYPE was uninitialized for
d_stream.avail_out = len; many pages until MySQL/InnoDB 5.1.7. */
d_stream.avail_in = 0; /* ut_ad(fil_page_get_type(page) == FIL_PAGE_TYPE_BLOB); */
blob_header = page + offset;
part_len = btr_blob_get_part_len(blob_header);
copy_len = ut_min(part_len, len - copied_len);
memcpy(buf + copied_len,
blob_header + BTR_BLOB_HDR_SIZE, copy_len);
copied_len += copy_len;
page_no = btr_blob_get_next_page_no(blob_header);
mtr_commit(&mtr);
if (page_no == FIL_NULL || copy_len != part_len) {
return(copied_len);
}
/* On other BLOB pages except the first the BLOB header
always is at the page data start: */
offset = FIL_PAGE_DATA;
ut_ad(copied_len <= len);
} }
}
/***********************************************************************
Copies the prefix of a compressed BLOB. */
static
void
btr_copy_zblob_prefix(
/*==================*/
z_stream* d_stream,/* in/out: the decompressing stream */
ulint zip_size,/* in: compressed BLOB page size */
ulint space_id,/* in: space id of the first BLOB page */
ulint page_no,/* in: page number of the first BLOB page */
ulint offset) /* in: offset on the first BLOB page */
{
ut_ad(ut_is_2pow(zip_size));
ut_ad(zip_size >= PAGE_ZIP_MIN_SIZE);
ut_ad(zip_size <= UNIV_PAGE_SIZE);
ut_ad(space_id);
for (;;) { for (;;) {
mtr_t mtr;
buf_block_t* block; buf_block_t* block;
page_t* page; page_t* page;
int err;
ulint next_page_no;
mtr_start(&mtr); mtr_start(&mtr);
...@@ -4219,117 +4261,130 @@ btr_copy_externally_stored_field_prefix_low( ...@@ -4219,117 +4261,130 @@ btr_copy_externally_stored_field_prefix_low(
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
page = buf_block_get_frame(block); page = buf_block_get_frame(block);
if (UNIV_UNLIKELY(zip_size)) { if (UNIV_UNLIKELY(fil_page_get_type(page)
int err; != FIL_PAGE_TYPE_ZBLOB)) {
ulint next_page_no; ut_print_timestamp(stderr);
fprintf(stderr,
if (UNIV_UNLIKELY(fil_page_get_type(page) " InnoDB: Unknown type %lu of"
!= FIL_PAGE_TYPE_ZBLOB)) { " compressed BLOB"
ut_print_timestamp(stderr); " page %lu space %lu\n",
fprintf(stderr, (ulong) fil_page_get_type(page),
" InnoDB: Unknown type %lu of" (ulong) page_no, (ulong) space_id);
" compressed BLOB" }
" page %lu space %lu\n",
(ulong) fil_page_get_type(page),
(ulong) page_no, (ulong) space_id);
}
next_page_no = mach_read_from_4(page + offset); next_page_no = mach_read_from_4(page + offset);
if (UNIV_LIKELY(offset == FIL_PAGE_NEXT)) { if (UNIV_LIKELY(offset == FIL_PAGE_NEXT)) {
/* When the BLOB begins at page header, /* When the BLOB begins at page header,
the compressed data payload does not the compressed data payload does not
immediately follow the next page pointer. */ immediately follow the next page pointer. */
offset = FIL_PAGE_DATA; offset = FIL_PAGE_DATA;
} else { } else {
offset += 4; offset += 4;
} }
d_stream.next_in = page + offset; d_stream->next_in = page + offset;
d_stream.avail_in = zip_size - offset; d_stream->avail_in = zip_size - offset;
err = inflate(&d_stream, Z_NO_FLUSH); err = inflate(d_stream, Z_NO_FLUSH);
switch (err) { switch (err) {
case Z_OK: case Z_OK:
if (!d_stream.avail_out) { if (!d_stream->avail_out) {
goto end_of_blob; goto end_of_blob;
} }
break; break;
case Z_STREAM_END: case Z_STREAM_END:
if (next_page_no == FIL_NULL) { if (next_page_no == FIL_NULL) {
goto end_of_blob; goto end_of_blob;
} }
/* fall through */ /* fall through */
default: default:
inflate_error: inflate_error:
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: inflate() of"
" compressed BLOB"
" page %lu space %lu returned %d\n",
(ulong) page_no, (ulong) space_id,
err);
case Z_BUF_ERROR:
goto end_of_blob;
}
if (next_page_no == FIL_NULL) {
if (!d_stream->avail_in) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
" InnoDB: inflate() of" " InnoDB: unexpected end of"
" compressed BLOB" " compressed BLOB"
" page %lu space %lu returned %d\n", " page %lu space %lu\n",
(ulong) page_no, (ulong) space_id, (ulong) page_no,
err); (ulong) space_id);
case Z_BUF_ERROR: } else {
goto end_of_blob; err = inflate(d_stream, Z_FINISH);
} if (UNIV_UNLIKELY
(err != Z_STREAM_END)) {
if (next_page_no == FIL_NULL) { goto inflate_error;
if (!d_stream.avail_in) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: unexpected end of"
" compressed BLOB"
" page %lu space %lu\n",
(ulong) page_no,
(ulong) space_id);
} else {
err = inflate(&d_stream, Z_FINISH);
if (UNIV_UNLIKELY
(err != Z_STREAM_END)) {
goto inflate_error;
}
} }
end_of_blob:
mtr_commit(&mtr);
inflateEnd(&d_stream);
return(d_stream.total_out);
} }
end_of_blob:
mtr_commit(&mtr); mtr_commit(&mtr);
inflateEnd(d_stream);
return;
}
/* On other BLOB pages except the first mtr_commit(&mtr);
the BLOB header always is at the page header: */
page_no = next_page_no; /* On other BLOB pages except the first
offset = FIL_PAGE_NEXT; the BLOB header always is at the page header: */
} else {
byte* blob_header
= page + offset;
ulint part_len
= btr_blob_get_part_len(blob_header);
ulint copy_len
= ut_min(part_len, len - copied_len);
memcpy(buf + copied_len, page_no = next_page_no;
blob_header + BTR_BLOB_HDR_SIZE, copy_len); offset = FIL_PAGE_NEXT;
copied_len += copy_len; }
}
page_no = btr_blob_get_next_page_no(blob_header); /***********************************************************************
Copies the prefix of an externally stored field of a record. */
static
ulint
btr_copy_externally_stored_field_prefix_low(
/*========================================*/
/* out: bytes written to buf */
byte* buf, /* out: the externally stored part of
the field, or a prefix of it */
ulint len, /* in: length of buf, in bytes */
ulint zip_size,/* in: nonzero=compressed BLOB page size,
zero for uncompressed BLOBs */
ulint space_id,/* in: space id of the first BLOB page */
ulint page_no,/* in: page number of the first BLOB page */
ulint offset) /* in: offset on the first BLOB page */
{
if (UNIV_UNLIKELY(len == 0)) {
return(0);
}
mtr_commit(&mtr); if (UNIV_UNLIKELY(zip_size)) {
int err;
z_stream d_stream;
if (page_no == FIL_NULL || copy_len != part_len) { d_stream.zalloc = (alloc_func) 0;
return(copied_len); d_stream.zfree = (free_func) 0;
} d_stream.opaque = (voidpf) 0;
/* On other BLOB pages except the first the BLOB header err = inflateInit(&d_stream);
always is at the page data start: */ ut_a(err == Z_OK);
offset = FIL_PAGE_DATA; d_stream.next_out = buf;
d_stream.avail_out = len;
d_stream.avail_in = 0;
ut_ad(copied_len <= len); btr_copy_zblob_prefix(&d_stream, zip_size,
} space_id, page_no, offset);
return(d_stream.total_out);
} else {
return(btr_copy_blob_prefix(buf, len, space_id,
page_no, offset));
} }
} }
......
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