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
...@@ -747,6 +747,129 @@ page_zip_compress_sec( ...@@ -747,6 +747,129 @@ page_zip_compress_sec(
return(err); return(err);
} }
/**************************************************************************
Compress a record of a leaf node of a clustered index that contains
externally stored columns. */
static
int
page_zip_compress_clust_ext(
/*========================*/
/* out: Z_OK, or a zlib error code */
z_stream* c_stream, /* in/out: compressed page stream */
const rec_t* rec, /* in: record */
const ulint* offsets, /* in: rec_get_offsets(rec) */
ulint trx_id_col, /* in: position of of DB_TRX_ID */
byte* deleted, /* in: dense directory entry pointing
to the head of the free list */
byte* storage, /* in: end of dense page directory */
byte** externs, /* in/out: pointer to the next
available BLOB pointer */
ulint* n_blobs) /* in/out: number of
externally stored columns */
{
int err;
ulint i;
for (i = 0; i < rec_offs_n_fields(offsets); i++) {
ulint len;
const byte* src;
if (UNIV_UNLIKELY(i == trx_id_col)) {
ut_ad(!rec_offs_nth_extern(offsets, i));
/* Store trx_id and roll_ptr
in uncompressed form. */
src = rec_get_nth_field(rec, offsets, i, &len);
ut_ad(src + DATA_TRX_ID_LEN
== rec_get_nth_field(rec, offsets,
i + 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 */
i++;
} else if (rec_offs_nth_extern(offsets, i)) {
src = rec_get_nth_field(rec, offsets, i, &len);
ut_ad(len >= BTR_EXTERN_FIELD_REF_SIZE);
src += len - BTR_EXTERN_FIELD_REF_SIZE;
c_stream->avail_in = src
- c_stream->next_in;
if (UNIV_LIKELY(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);
/* Reserve space for the data at
the end of the space reserved for
the compressed data and the page
modification log. */
if (UNIV_UNLIKELY
(c_stream->avail_out
<= BTR_EXTERN_FIELD_REF_SIZE)) {
/* out of space */
return(Z_BUF_ERROR);
}
ut_ad(*externs == c_stream->next_out
+ c_stream->avail_out
+ 1/* end of modif. log */);
c_stream->next_in
+= BTR_EXTERN_FIELD_REF_SIZE;
/* Skip deleted records. */
if (UNIV_LIKELY_NULL
(page_zip_dir_find_low(
storage, deleted,
page_offset(rec)))) {
continue;
}
(*n_blobs)++;
c_stream->avail_out
-= BTR_EXTERN_FIELD_REF_SIZE;
*externs -= BTR_EXTERN_FIELD_REF_SIZE;
/* Copy the BLOB pointer */
memcpy(*externs, c_stream->next_in
- BTR_EXTERN_FIELD_REF_SIZE,
BTR_EXTERN_FIELD_REF_SIZE);
}
}
return(Z_OK);
}
/************************************************************************** /**************************************************************************
Compress the records of a leaf node of a clustered index. */ Compress the records of a leaf node of a clustered index. */
static static
...@@ -759,7 +882,7 @@ page_zip_compress_clust( ...@@ -759,7 +882,7 @@ page_zip_compress_clust(
sorted by address */ sorted by address */
ulint n_dense, /* in: size of recs[] */ ulint n_dense, /* in: size of recs[] */
dict_index_t* index, /* in: the index of the page */ dict_index_t* index, /* in: the index of the page */
ulint* n_blobs_out, /* out: number of ulint* n_blobs, /* in: 0; out: number of
externally stored columns */ externally stored columns */
ulint trx_id_col, /* index of the trx_id column */ ulint trx_id_col, /* index of the trx_id column */
byte* deleted, /* in: dense directory entry pointing byte* deleted, /* in: dense directory entry pointing
...@@ -772,16 +895,16 @@ page_zip_compress_clust( ...@@ -772,16 +895,16 @@ page_zip_compress_clust(
/* BTR_EXTERN_FIELD_REF storage */ /* BTR_EXTERN_FIELD_REF storage */
byte* externs = storage - n_dense byte* externs = storage - n_dense
* (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN); * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
ulint n_blobs = 0;
ulint n_fields = dict_index_get_n_fields(index); ut_ad(*n_blobs == 0);
do { do {
ulint i;
const rec_t* rec = *recs++; const rec_t* rec = *recs++;
offsets = rec_get_offsets(rec, index, offsets, offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
ut_ad(rec_offs_n_fields(offsets) == n_fields); ut_ad(rec_offs_n_fields(offsets)
== dict_index_get_n_fields(index));
/* Compress the extra bytes. */ /* Compress the extra bytes. */
c_stream->avail_in = rec - REC_N_NEW_EXTRA_BYTES c_stream->avail_in = rec - REC_N_NEW_EXTRA_BYTES
...@@ -804,103 +927,54 @@ page_zip_compress_clust( ...@@ -804,103 +927,54 @@ page_zip_compress_clust(
/* Check if there are any externally stored columns. /* Check if there are any externally stored columns.
For each externally stored column, store the For each externally stored column, store the
BTR_EXTERN_FIELD_REF separately. */ BTR_EXTERN_FIELD_REF separately. */
if (UNIV_UNLIKELY(rec_offs_any_extern(offsets))) {
ut_ad(dict_index_is_clust(index));
for (i = 0; i < n_fields; i++) { err = page_zip_compress_clust_ext(
ulint len; c_stream, rec, offsets, trx_id_col,
const byte* src; deleted, storage, &externs, n_blobs);
if (UNIV_UNLIKELY(i == trx_id_col)) {
ut_ad(!rec_offs_nth_extern(offsets, i));
/* Store trx_id and roll_ptr
in uncompressed form. */
src = rec_get_nth_field(rec, offsets, i, &len);
ut_ad(src + DATA_TRX_ID_LEN
== rec_get_nth_field(rec, offsets,
i + 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)) {
goto func_exit;
}
}
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 */ if (UNIV_UNLIKELY(err != Z_OK)) {
i++;
} else if (rec_offs_nth_extern(offsets, i)) {
src = rec_get_nth_field(rec, offsets, i, &len);
ut_ad(dict_index_is_clust(index));
ut_ad(len >= BTR_EXTERN_FIELD_REF_SIZE);
src += len - BTR_EXTERN_FIELD_REF_SIZE;
c_stream->avail_in = src goto func_exit;
- c_stream->next_in; }
if (UNIV_LIKELY(c_stream->avail_in)) { } else {
err = deflate(c_stream, Z_NO_FLUSH); ulint len;
if (UNIV_UNLIKELY(err != Z_OK)) { const byte* src;
goto func_exit; /* 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);
ut_ad(!c_stream->avail_in); /* Compress any preceding bytes. */
ut_ad(c_stream->next_in == src); c_stream->avail_in = src - c_stream->next_in;
/* Reserve space for the data at if (c_stream->avail_in) {
the end of the space reserved for err = deflate(c_stream, Z_NO_FLUSH);
the compressed data and the page if (UNIV_UNLIKELY(err != Z_OK)) {
modification log. */
if (UNIV_UNLIKELY return(err);
(c_stream->avail_out
<= BTR_EXTERN_FIELD_REF_SIZE)) {
/* out of space */
goto func_exit;
} }
}
ut_ad(externs == c_stream->next_out ut_ad(!c_stream->avail_in);
+ c_stream->avail_out ut_ad(c_stream->next_in == src);
+ 1/* end of modif. log */);
c_stream->next_in
+= BTR_EXTERN_FIELD_REF_SIZE;
/* Skip deleted records. */ memcpy(storage
if (UNIV_LIKELY_NULL - (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN)
(page_zip_dir_find_low( * (rec_get_heap_no_new(rec) - 1),
storage, deleted, c_stream->next_in,
page_offset(rec)))) { DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
continue;
}
n_blobs++; c_stream->next_in
c_stream->avail_out += DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN;
-= BTR_EXTERN_FIELD_REF_SIZE;
externs -= BTR_EXTERN_FIELD_REF_SIZE;
/* Copy the BLOB pointer */ /* Skip also roll_ptr */
memcpy(externs, c_stream->next_in ut_ad(trx_id_col + 1 < rec_offs_n_fields(offsets));
- BTR_EXTERN_FIELD_REF_SIZE,
BTR_EXTERN_FIELD_REF_SIZE);
}
} }
/* Compress the last bytes of the record. */ /* Compress the last bytes of the record. */
...@@ -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++) { /* Copy all data bytes of
byte* dst; a record in a secondary index. */
if (UNIV_UNLIKELY(data + len >= end)) {
if (UNIV_UNLIKELY(i == trx_id_col)) { return(NULL);
/* 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); memcpy(rec, data, len);
data += len; data += len;
next_out += len } else {
+ BTR_EXTERN_FIELD_REF_SIZE; /* Skip DB_TRX_ID and DB_ROLL_PTR. */
} ulint l = rec_get_nth_field_offs(offsets,
trx_id_col, &len);
byte* b;
if (UNIV_UNLIKELY(data + l >= end)
|| UNIV_UNLIKELY(len < (DATA_TRX_ID_LEN
+ DATA_ROLL_PTR_LEN))) {
return(NULL);
} }
/* Copy the last bytes of the record. */ /* Copy any preceding data bytes. */
len = rec_get_end(rec, offsets) - next_out; memcpy(rec, data, l);
data += l;
/* Copy any bytes following DB_TRX_ID, DB_ROLL_PTR. */
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