Commit ec06cfdb authored by marko's avatar marko

branches/zip: Introduce separate functions for handling records containing

externally stored columns.

page_zip_compress_clust_ext(), page_zip_apply_log_ext():
New functions.

page_zip_compress_clust(), page_zip_apply_log(): Check rec_offs_any_extern()
and avoid invoking the costly loop in most cases.

Similar optimizations can be made in page_zip_decompress_clust() and
page_zip_write_rec().
parent 8ef30756
...@@ -748,64 +748,29 @@ page_zip_compress_sec( ...@@ -748,64 +748,29 @@ page_zip_compress_sec(
} }
/************************************************************************** /**************************************************************************
Compress the records of a leaf node of a clustered index. */ Compress a record of a leaf node of a clustered index that contains
externally stored columns. */
static static
int int
page_zip_compress_clust( page_zip_compress_clust_ext(
/*====================*/ /*========================*/
/* out: Z_OK, or a zlib error code */ /* out: Z_OK, or a zlib error code */
z_stream* c_stream, /* in/out: compressed page stream */ z_stream* c_stream, /* in/out: compressed page stream */
const rec_t** recs, /* in: dense page directory const rec_t* rec, /* in: record */
sorted by address */ const ulint* offsets, /* in: rec_get_offsets(rec) */
ulint n_dense, /* in: size of recs[] */ ulint trx_id_col, /* in: position of of DB_TRX_ID */
dict_index_t* index, /* in: the index of the page */
ulint* n_blobs_out, /* out: number of
externally stored columns */
ulint trx_id_col, /* index of the trx_id column */
byte* deleted, /* in: dense directory entry pointing byte* deleted, /* in: dense directory entry pointing
to the head of the free list */ to the head of the free list */
byte* storage, /* in: end of dense page directory */ byte* storage, /* in: end of dense page directory */
mem_heap_t* heap) /* in: temporary memory heap */ byte** externs, /* in/out: pointer to the next
available BLOB pointer */
ulint* n_blobs) /* in/out: number of
externally stored columns */
{ {
int err = Z_OK; int err;
ulint* offsets = NULL;
/* BTR_EXTERN_FIELD_REF storage */
byte* externs = storage - n_dense
* (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
ulint n_blobs = 0;
ulint n_fields = dict_index_get_n_fields(index);
do {
ulint i; ulint i;
const rec_t* rec = *recs++;
offsets = rec_get_offsets(rec, index, offsets, for (i = 0; i < rec_offs_n_fields(offsets); i++) {
ULINT_UNDEFINED, &heap);
ut_ad(rec_offs_n_fields(offsets) == n_fields);
/* Compress the extra bytes. */
c_stream->avail_in = rec - REC_N_NEW_EXTRA_BYTES
- c_stream->next_in;
if (c_stream->avail_in) {
err = deflate(c_stream, Z_NO_FLUSH);
if (UNIV_UNLIKELY(err != Z_OK)) {
goto func_exit;
}
}
ut_ad(!c_stream->avail_in);
ut_ad(c_stream->next_in == rec - REC_N_NEW_EXTRA_BYTES);
/* Compress the data bytes. */
c_stream->next_in = (byte*) rec;
/* Check if there are any externally stored columns.
For each externally stored column, store the
BTR_EXTERN_FIELD_REF separately. */
for (i = 0; i < n_fields; i++) {
ulint len; ulint len;
const byte* src; const byte* src;
...@@ -827,7 +792,7 @@ page_zip_compress_clust( ...@@ -827,7 +792,7 @@ page_zip_compress_clust(
err = deflate(c_stream, Z_NO_FLUSH); err = deflate(c_stream, Z_NO_FLUSH);
if (UNIV_UNLIKELY(err != Z_OK)) { if (UNIV_UNLIKELY(err != Z_OK)) {
goto func_exit; return(err);
} }
} }
...@@ -847,7 +812,6 @@ page_zip_compress_clust( ...@@ -847,7 +812,6 @@ page_zip_compress_clust(
i++; i++;
} else if (rec_offs_nth_extern(offsets, i)) { } else if (rec_offs_nth_extern(offsets, i)) {
src = rec_get_nth_field(rec, offsets, i, &len); src = rec_get_nth_field(rec, offsets, i, &len);
ut_ad(dict_index_is_clust(index));
ut_ad(len >= BTR_EXTERN_FIELD_REF_SIZE); ut_ad(len >= BTR_EXTERN_FIELD_REF_SIZE);
src += len - BTR_EXTERN_FIELD_REF_SIZE; src += len - BTR_EXTERN_FIELD_REF_SIZE;
...@@ -857,7 +821,7 @@ page_zip_compress_clust( ...@@ -857,7 +821,7 @@ page_zip_compress_clust(
err = deflate(c_stream, Z_NO_FLUSH); err = deflate(c_stream, Z_NO_FLUSH);
if (UNIV_UNLIKELY(err != Z_OK)) { if (UNIV_UNLIKELY(err != Z_OK)) {
goto func_exit; return(err);
} }
} }
...@@ -873,10 +837,10 @@ page_zip_compress_clust( ...@@ -873,10 +837,10 @@ page_zip_compress_clust(
(c_stream->avail_out (c_stream->avail_out
<= BTR_EXTERN_FIELD_REF_SIZE)) { <= BTR_EXTERN_FIELD_REF_SIZE)) {
/* out of space */ /* out of space */
goto func_exit; return(Z_BUF_ERROR);
} }
ut_ad(externs == c_stream->next_out ut_ad(*externs == c_stream->next_out
+ c_stream->avail_out + c_stream->avail_out
+ 1/* end of modif. log */); + 1/* end of modif. log */);
...@@ -891,18 +855,128 @@ page_zip_compress_clust( ...@@ -891,18 +855,128 @@ page_zip_compress_clust(
continue; continue;
} }
n_blobs++; (*n_blobs)++;
c_stream->avail_out c_stream->avail_out
-= BTR_EXTERN_FIELD_REF_SIZE; -= BTR_EXTERN_FIELD_REF_SIZE;
externs -= BTR_EXTERN_FIELD_REF_SIZE; *externs -= BTR_EXTERN_FIELD_REF_SIZE;
/* Copy the BLOB pointer */ /* Copy the BLOB pointer */
memcpy(externs, c_stream->next_in memcpy(*externs, c_stream->next_in
- BTR_EXTERN_FIELD_REF_SIZE, - BTR_EXTERN_FIELD_REF_SIZE,
BTR_EXTERN_FIELD_REF_SIZE); BTR_EXTERN_FIELD_REF_SIZE);
} }
} }
return(Z_OK);
}
/**************************************************************************
Compress the records of a leaf node of a clustered index. */
static
int
page_zip_compress_clust(
/*====================*/
/* out: Z_OK, or a zlib error code */
z_stream* c_stream, /* in/out: compressed page stream */
const rec_t** recs, /* in: dense page directory
sorted by address */
ulint n_dense, /* in: size of recs[] */
dict_index_t* index, /* in: the index of the page */
ulint* n_blobs, /* in: 0; out: number of
externally stored columns */
ulint trx_id_col, /* index of the trx_id column */
byte* deleted, /* in: dense directory entry pointing
to the head of the free list */
byte* storage, /* in: end of dense page directory */
mem_heap_t* heap) /* in: temporary memory heap */
{
int err = Z_OK;
ulint* offsets = NULL;
/* BTR_EXTERN_FIELD_REF storage */
byte* externs = storage - n_dense
* (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
ut_ad(*n_blobs == 0);
do {
const rec_t* rec = *recs++;
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
ut_ad(rec_offs_n_fields(offsets)
== dict_index_get_n_fields(index));
/* Compress the extra bytes. */
c_stream->avail_in = rec - REC_N_NEW_EXTRA_BYTES
- c_stream->next_in;
if (c_stream->avail_in) {
err = deflate(c_stream, Z_NO_FLUSH);
if (UNIV_UNLIKELY(err != Z_OK)) {
goto func_exit;
}
}
ut_ad(!c_stream->avail_in);
ut_ad(c_stream->next_in == rec - REC_N_NEW_EXTRA_BYTES);
/* Compress the data bytes. */
c_stream->next_in = (byte*) rec;
/* Check if there are any externally stored columns.
For each externally stored column, store the
BTR_EXTERN_FIELD_REF separately. */
if (UNIV_UNLIKELY(rec_offs_any_extern(offsets))) {
ut_ad(dict_index_is_clust(index));
err = page_zip_compress_clust_ext(
c_stream, rec, offsets, trx_id_col,
deleted, storage, &externs, n_blobs);
if (UNIV_UNLIKELY(err != Z_OK)) {
goto func_exit;
}
} else {
ulint len;
const byte* src;
/* Store trx_id and roll_ptr in uncompressed form. */
src = rec_get_nth_field(rec, offsets,
trx_id_col, &len);
ut_ad(src + DATA_TRX_ID_LEN
== rec_get_nth_field(rec, offsets,
trx_id_col + 1, &len));
ut_ad(len == DATA_ROLL_PTR_LEN);
/* Compress any preceding bytes. */
c_stream->avail_in = src - c_stream->next_in;
if (c_stream->avail_in) {
err = deflate(c_stream, Z_NO_FLUSH);
if (UNIV_UNLIKELY(err != Z_OK)) {
return(err);
}
}
ut_ad(!c_stream->avail_in);
ut_ad(c_stream->next_in == src);
memcpy(storage
- (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN)
* (rec_get_heap_no_new(rec) - 1),
c_stream->next_in,
DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
c_stream->next_in
+= DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN;
/* Skip also roll_ptr */
ut_ad(trx_id_col + 1 < rec_offs_n_fields(offsets));
}
/* Compress the last bytes of the record. */ /* Compress the last bytes of the record. */
c_stream->avail_in = rec + rec_offs_data_size(offsets) c_stream->avail_in = rec + rec_offs_data_size(offsets)
- c_stream->next_in; - c_stream->next_in;
...@@ -918,7 +992,6 @@ page_zip_compress_clust( ...@@ -918,7 +992,6 @@ page_zip_compress_clust(
} while (--n_dense); } while (--n_dense);
func_exit: func_exit:
*n_blobs_out = n_blobs;
return(err); return(err);
} }
...@@ -1476,6 +1549,81 @@ page_zip_set_extra_bytes( ...@@ -1476,6 +1549,81 @@ page_zip_set_extra_bytes(
return(TRUE); return(TRUE);
} }
/**************************************************************************
Apply the modification log to a record containing externally stored
columns. Do not copy the fields that are stored separately. */
static
const byte*
page_zip_apply_log_ext(
/*===================*/
/* out: pointer to modification log,
or NULL on failure */
rec_t* rec, /* in/out: record */
const ulint* offsets, /* in: rec_get_offsets(rec) */
ulint trx_id_col, /* in: position of of DB_TRX_ID */
const byte* data, /* in: modification log */
const byte* end) /* in: end of modification log */
{
ulint i;
ulint len;
byte* next_out = rec;
/* Check if there are any externally stored columns.
For each externally stored column, skip the
BTR_EXTERN_FIELD_REF. */
for (i = 0; i < rec_offs_n_fields(offsets); i++) {
byte* dst;
if (UNIV_UNLIKELY(i == trx_id_col)) {
/* Skip trx_id and roll_ptr */
dst = rec_get_nth_field(rec, offsets,
i, &len);
if (UNIV_UNLIKELY(dst - next_out
>= end - data)
|| UNIV_UNLIKELY
(len < (DATA_TRX_ID_LEN
+ DATA_ROLL_PTR_LEN))
|| rec_offs_nth_extern(offsets,
i)) {
return(NULL);
}
memcpy(next_out, data, dst - next_out);
data += dst - next_out;
next_out = dst + (DATA_TRX_ID_LEN
+ DATA_ROLL_PTR_LEN);
} else if (rec_offs_nth_extern(offsets, i)) {
dst = rec_get_nth_field(rec, offsets,
i, &len);
ut_ad(len
>= BTR_EXTERN_FIELD_REF_SIZE);
len += dst - next_out
- BTR_EXTERN_FIELD_REF_SIZE;
if (UNIV_UNLIKELY(data + len >= end)) {
return(NULL);
}
memcpy(next_out, data, len);
data += len;
next_out += len
+ BTR_EXTERN_FIELD_REF_SIZE;
}
}
/* Copy the last bytes of the record. */
len = rec_get_end(rec, offsets) - next_out;
if (UNIV_UNLIKELY(data + len >= end)) {
return(NULL);
}
memcpy(next_out, data, len);
data += len;
return(data);
}
/************************************************************************** /**************************************************************************
Apply the modification log to an uncompressed page. Apply the modification log to an uncompressed page.
Do not copy the fields that are stored separately. */ Do not copy the fields that are stored separately. */
...@@ -1575,13 +1723,20 @@ page_zip_apply_log( ...@@ -1575,13 +1723,20 @@ page_zip_apply_log(
} }
/* Copy the data bytes. */ /* Copy the data bytes. */
if (UNIV_UNLIKELY(hs & REC_STATUS_NODE_PTR)) { if (UNIV_UNLIKELY(rec_offs_any_extern(offsets))) {
/* Non-leaf nodes should not contain any /* Non-leaf nodes should not contain any
externally stored columns. */ externally stored columns. */
if (UNIV_UNLIKELY(rec_offs_any_extern(offsets))) { if (UNIV_UNLIKELY(hs & REC_STATUS_NODE_PTR)) {
return(NULL); return(NULL);
} }
data = page_zip_apply_log_ext(
rec, offsets, trx_id_col, data, end);
if (UNIV_UNLIKELY(!data)) {
return(NULL);
}
} else if (UNIV_UNLIKELY(hs & REC_STATUS_NODE_PTR)) {
len = rec_offs_data_size(offsets) len = rec_offs_data_size(offsets)
- REC_NODE_PTR_SIZE; - REC_NODE_PTR_SIZE;
/* Copy the data bytes, except node_ptr. */ /* Copy the data bytes, except node_ptr. */
...@@ -1590,61 +1745,40 @@ page_zip_apply_log( ...@@ -1590,61 +1745,40 @@ page_zip_apply_log(
} }
memcpy(rec, data, len); memcpy(rec, data, len);
data += len; data += len;
} else { } else if (UNIV_LIKELY(trx_id_col == ULINT_UNDEFINED)) {
ulint i; len = rec_offs_data_size(offsets);
byte* next_out = rec;
/* Check if there are any externally stored columns.
For each externally stored column, skip the
BTR_EXTERN_FIELD_REF. */
for (i = 0; i < rec_offs_n_fields(offsets); i++) {
byte* dst;
if (UNIV_UNLIKELY(i == trx_id_col)) { /* Copy all data bytes of
/* Skip trx_id and roll_ptr */ a record in a secondary index. */
dst = rec_get_nth_field(rec, offsets, if (UNIV_UNLIKELY(data + len >= end)) {
i, &len);
if (UNIV_UNLIKELY(dst - next_out
>= end - data)
|| UNIV_UNLIKELY
(len < (DATA_TRX_ID_LEN
+ DATA_ROLL_PTR_LEN))
|| rec_offs_nth_extern(offsets,
i)) {
return(NULL); return(NULL);
} }
memcpy(next_out, data, dst - next_out); memcpy(rec, data, len);
data += dst - next_out; data += len;
next_out = dst + (DATA_TRX_ID_LEN } else {
+ DATA_ROLL_PTR_LEN); /* Skip DB_TRX_ID and DB_ROLL_PTR. */
} else if (rec_offs_nth_extern(offsets, i)) { ulint l = rec_get_nth_field_offs(offsets,
dst = rec_get_nth_field(rec, offsets, trx_id_col, &len);
i, &len); byte* b;
ut_ad(len
>= BTR_EXTERN_FIELD_REF_SIZE);
len += dst - next_out
- BTR_EXTERN_FIELD_REF_SIZE;
if (UNIV_UNLIKELY(data + len >= end)) { if (UNIV_UNLIKELY(data + l >= end)
|| UNIV_UNLIKELY(len < (DATA_TRX_ID_LEN
+ DATA_ROLL_PTR_LEN))) {
return(NULL); return(NULL);
} }
memcpy(next_out, data, len); /* Copy any preceding data bytes. */
data += len; memcpy(rec, data, l);
next_out += len data += l;
+ BTR_EXTERN_FIELD_REF_SIZE;
}
}
/* Copy the last bytes of the record. */ /* Copy any bytes following DB_TRX_ID, DB_ROLL_PTR. */
len = rec_get_end(rec, offsets) - next_out; b = rec + l + (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
len = rec_get_end(rec, offsets) - b;
if (UNIV_UNLIKELY(data + len >= end)) { if (UNIV_UNLIKELY(data + len >= end)) {
return(NULL); return(NULL);
} }
memcpy(next_out, data, len); memcpy(b, data, len);
data += len; data += len;
} }
} }
...@@ -2831,6 +2965,7 @@ page_zip_write_blob_ptr( ...@@ -2831,6 +2965,7 @@ page_zip_write_blob_ptr(
> PAGE_DATA + page_zip_dir_size(page_zip)); > PAGE_DATA + page_zip_dir_size(page_zip));
ut_ad(rec_offs_comp(offsets)); ut_ad(rec_offs_comp(offsets));
ut_ad(rec_offs_validate(rec, NULL, offsets)); ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_ad(rec_offs_any_extern(offsets));
ut_ad(rec_offs_nth_extern(offsets, n)); ut_ad(rec_offs_nth_extern(offsets, n));
ut_ad(page_zip->m_start >= PAGE_DATA); ut_ad(page_zip->m_start >= PAGE_DATA);
......
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