00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #define THIS_MODULE
00027 #include "page0zip.h"
00028 #ifdef UNIV_NONINL
00029 # include "page0zip.ic"
00030 #endif
00031 #undef THIS_MODULE
00032 #include "page0page.h"
00033 #include "mtr0log.h"
00034 #include "ut0sort.h"
00035 #include "dict0dict.h"
00036 #include "btr0cur.h"
00037 #include "page0types.h"
00038 #include "log0recv.h"
00039 #include "zlib.h"
00040 #ifndef UNIV_HOTBACKUP
00041 # include "buf0lru.h"
00042 # include "btr0sea.h"
00043 # include "dict0boot.h"
00044 # include "lock0lock.h"
00045 #else
00046 # define lock_move_reorganize_page(block, temp_block) ((void) 0)
00047 # define buf_LRU_stat_inc_unzip() ((void) 0)
00048 #endif
00049
00050 #ifndef UNIV_HOTBACKUP
00051
00052 UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE - 1];
00053 #endif
00054
00055
00056
00057
00058
00059
00060
00062 static const byte infimum_extra[] = {
00063 0x01,
00064 0x00, 0x02
00065
00066 };
00068 static const byte infimum_data[] = {
00069 0x69, 0x6e, 0x66, 0x69,
00070 0x6d, 0x75, 0x6d, 0x00
00071 };
00073 static const byte supremum_extra_data[] = {
00074
00075 0x00, 0x0b,
00076 0x00, 0x00,
00077 0x73, 0x75, 0x70, 0x72,
00078 0x65, 0x6d, 0x75, 0x6d
00079 };
00080
00085 #define ASSERT_ZERO(b, s) \
00086 ut_ad(!memcmp(b, field_ref_zero, ut_min(s, sizeof field_ref_zero)))
00087
00089 #define ASSERT_ZERO_BLOB(b) \
00090 ut_ad(!memcmp(b, field_ref_zero, sizeof field_ref_zero))
00091
00092
00093
00094 #if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
00095 # include <stdarg.h>
00096 __attribute__((format (printf, 1, 2)))
00097
00100 static
00101 int
00102 page_zip_fail_func(
00103
00104 const char* fmt,
00105 ...)
00106 {
00107 int res;
00108 va_list ap;
00109
00110 ut_print_timestamp(stderr);
00111 fputs(" InnoDB: ", stderr);
00112 va_start(ap, fmt);
00113 res = vfprintf(stderr, fmt, ap);
00114 va_end(ap);
00115
00116 return(res);
00117 }
00120 # define page_zip_fail(fmt_args) page_zip_fail_func fmt_args
00121 #else
00122
00124 # define page_zip_fail(fmt_args)
00125 #endif
00126
00127 #ifndef UNIV_HOTBACKUP
00128
00131 UNIV_INTERN
00132 ulint
00133 page_zip_empty_size(
00134
00135 ulint n_fields,
00136 ulint zip_size)
00137 {
00138 lint size = zip_size
00139
00140
00141 - (PAGE_DATA
00142 + PAGE_ZIP_DIR_SLOT_SIZE
00143 + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN
00144 + 1
00145 + 1
00146 - REC_N_NEW_EXTRA_BYTES)
00147
00148 - compressBound(2 * (n_fields + 1));
00149 return(size > 0 ? (ulint) size : 0);
00150 }
00151 #endif
00152
00153
00157 UNIV_INLINE
00158 ulint
00159 page_zip_dir_size(
00160
00161 const page_zip_des_t* page_zip)
00162 {
00163
00164 ulint size = PAGE_ZIP_DIR_SLOT_SIZE
00165 * (page_dir_get_n_heap(page_zip->data)
00166 - PAGE_HEAP_NO_USER_LOW);
00167 return(size);
00168 }
00169
00170
00174 UNIV_INLINE
00175 ulint
00176 page_zip_dir_user_size(
00177
00178 const page_zip_des_t* page_zip)
00179 {
00180 ulint size = PAGE_ZIP_DIR_SLOT_SIZE
00181 * page_get_n_recs(page_zip->data);
00182 ut_ad(size <= page_zip_dir_size(page_zip));
00183 return(size);
00184 }
00185
00186
00189 UNIV_INLINE
00190 byte*
00191 page_zip_dir_find_low(
00192
00193 byte* slot,
00194 byte* end,
00195 ulint offset)
00196 {
00197 ut_ad(slot <= end);
00198
00199 for (; slot < end; slot += PAGE_ZIP_DIR_SLOT_SIZE) {
00200 if ((mach_read_from_2(slot) & PAGE_ZIP_DIR_SLOT_MASK)
00201 == offset) {
00202 return(slot);
00203 }
00204 }
00205
00206 return(NULL);
00207 }
00208
00209
00212 UNIV_INLINE
00213 byte*
00214 page_zip_dir_find(
00215
00216 page_zip_des_t* page_zip,
00217 ulint offset)
00218 {
00219 byte* end = page_zip->data + page_zip_get_size(page_zip);
00220
00221 ut_ad(page_zip_simple_validate(page_zip));
00222
00223 return(page_zip_dir_find_low(end - page_zip_dir_user_size(page_zip),
00224 end,
00225 offset));
00226 }
00227
00228
00231 UNIV_INLINE
00232 byte*
00233 page_zip_dir_find_free(
00234
00235 page_zip_des_t* page_zip,
00236 ulint offset)
00237 {
00238 byte* end = page_zip->data + page_zip_get_size(page_zip);
00239
00240 ut_ad(page_zip_simple_validate(page_zip));
00241
00242 return(page_zip_dir_find_low(end - page_zip_dir_size(page_zip),
00243 end - page_zip_dir_user_size(page_zip),
00244 offset));
00245 }
00246
00247
00251 UNIV_INLINE
00252 ulint
00253 page_zip_dir_get(
00254
00255 const page_zip_des_t* page_zip,
00256 ulint slot)
00258 {
00259 ut_ad(page_zip_simple_validate(page_zip));
00260 ut_ad(slot < page_zip_dir_size(page_zip) / PAGE_ZIP_DIR_SLOT_SIZE);
00261 return(mach_read_from_2(page_zip->data + page_zip_get_size(page_zip)
00262 - PAGE_ZIP_DIR_SLOT_SIZE * (slot + 1)));
00263 }
00264
00265 #ifndef UNIV_HOTBACKUP
00266
00268 static
00269 void
00270 page_zip_compress_write_log(
00271
00272 const page_zip_des_t* page_zip,
00273 const page_t* page,
00274 dict_index_t* index,
00275 mtr_t* mtr)
00276 {
00277 byte* log_ptr;
00278 ulint trailer_size;
00279
00280 ut_ad(!dict_index_is_ibuf(index));
00281
00282 log_ptr = mlog_open(mtr, 11 + 2 + 2);
00283
00284 if (!log_ptr) {
00285
00286 return;
00287 }
00288
00289
00290 trailer_size = page_dir_get_n_heap(page_zip->data)
00291 - PAGE_HEAP_NO_USER_LOW;
00292
00293 if (!page_is_leaf(page)) {
00294 trailer_size *= PAGE_ZIP_DIR_SLOT_SIZE + REC_NODE_PTR_SIZE;
00295 } else if (dict_index_is_clust(index)) {
00296 trailer_size *= PAGE_ZIP_DIR_SLOT_SIZE
00297 + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN;
00298 } else {
00299 trailer_size *= PAGE_ZIP_DIR_SLOT_SIZE;
00300 }
00301
00302 trailer_size += page_zip->n_blobs * BTR_EXTERN_FIELD_REF_SIZE;
00303 ut_a(page_zip->m_end > PAGE_DATA);
00304 #if FIL_PAGE_DATA > PAGE_DATA
00305 # error "FIL_PAGE_DATA > PAGE_DATA"
00306 #endif
00307 ut_a(page_zip->m_end + trailer_size <= page_zip_get_size(page_zip));
00308
00309 log_ptr = mlog_write_initial_log_record_fast((page_t*) page,
00310 MLOG_ZIP_PAGE_COMPRESS,
00311 log_ptr, mtr);
00312 mach_write_to_2(log_ptr, page_zip->m_end - FIL_PAGE_TYPE);
00313 log_ptr += 2;
00314 mach_write_to_2(log_ptr, trailer_size);
00315 log_ptr += 2;
00316 mlog_close(mtr, log_ptr);
00317
00318
00319 mlog_catenate_string(mtr, page_zip->data + FIL_PAGE_PREV, 4);
00320 mlog_catenate_string(mtr, page_zip->data + FIL_PAGE_NEXT, 4);
00321
00322
00323 mlog_catenate_string(mtr, page_zip->data + FIL_PAGE_TYPE,
00324 page_zip->m_end - FIL_PAGE_TYPE);
00325
00326 mlog_catenate_string(mtr, page_zip->data + page_zip_get_size(page_zip)
00327 - trailer_size, trailer_size);
00328 }
00329 #endif
00330
00331
00334 static
00335 ulint
00336 page_zip_get_n_prev_extern(
00337
00338 const page_zip_des_t* page_zip,
00340 const rec_t* rec,
00342 dict_index_t* index)
00343 {
00344 const page_t* page = page_align(rec);
00345 ulint n_ext = 0;
00346 ulint i;
00347 ulint left;
00348 ulint heap_no;
00349 ulint n_recs = page_get_n_recs(page_zip->data);
00350
00351 ut_ad(page_is_leaf(page));
00352 ut_ad(page_is_comp(page));
00353 ut_ad(dict_table_is_comp(index->table));
00354 ut_ad(dict_index_is_clust(index));
00355 ut_ad(!dict_index_is_ibuf(index));
00356
00357 heap_no = rec_get_heap_no_new(rec);
00358 ut_ad(heap_no >= PAGE_HEAP_NO_USER_LOW);
00359 left = heap_no - PAGE_HEAP_NO_USER_LOW;
00360 if (UNIV_UNLIKELY(!left)) {
00361 return(0);
00362 }
00363
00364 for (i = 0; i < n_recs; i++) {
00365 const rec_t* r = page + (page_zip_dir_get(page_zip, i)
00366 & PAGE_ZIP_DIR_SLOT_MASK);
00367
00368 if (rec_get_heap_no_new(r) < heap_no) {
00369 n_ext += rec_get_n_extern_new(r, index,
00370 ULINT_UNDEFINED);
00371 if (!--left) {
00372 break;
00373 }
00374 }
00375 }
00376
00377 return(n_ext);
00378 }
00379
00380
00383 static
00384 byte*
00385 page_zip_fixed_field_encode(
00386
00387 byte* buf,
00388 ulint val)
00389 {
00390 ut_ad(val >= 2);
00391
00392 if (UNIV_LIKELY(val < 126)) {
00393
00394
00395
00396
00397
00398
00399 *buf++ = (byte) val;
00400 } else {
00401 *buf++ = (byte) (0x80 | val >> 8);
00402 *buf++ = (byte) val;
00403 }
00404
00405 return(buf);
00406 }
00407
00408
00411 static
00412 ulint
00413 page_zip_fields_encode(
00414
00415 ulint n,
00416 dict_index_t* index,
00417 ulint trx_id_pos,
00420 byte* buf)
00421 {
00422 const byte* buf_start = buf;
00423 ulint i;
00424 ulint col;
00425 ulint trx_id_col = 0;
00426
00427 ulint fixed_sum = 0;
00428
00429 ut_ad(trx_id_pos == ULINT_UNDEFINED || trx_id_pos < n);
00430
00431 for (i = col = 0; i < n; i++) {
00432 dict_field_t* field = dict_index_get_nth_field(index, i);
00433 ulint val;
00434
00435 if (dict_field_get_col(field)->prtype & DATA_NOT_NULL) {
00436 val = 1;
00437 } else {
00438 val = 0;
00439 }
00440
00441 if (!field->fixed_len) {
00442
00443 const dict_col_t* column
00444 = dict_field_get_col(field);
00445
00446 if (UNIV_UNLIKELY(column->len > 255)
00447 || UNIV_UNLIKELY(column->mtype == DATA_BLOB)) {
00448 val |= 0x7e;
00449 }
00450
00451 if (fixed_sum) {
00452
00453
00454 buf = page_zip_fixed_field_encode(
00455 buf, fixed_sum << 1 | 1);
00456 fixed_sum = 0;
00457 col++;
00458 }
00459
00460 *buf++ = (byte) val;
00461 col++;
00462 } else if (val) {
00463
00464
00465 if (fixed_sum && UNIV_UNLIKELY
00466 (fixed_sum + field->fixed_len
00467 > DICT_MAX_INDEX_COL_LEN)) {
00468
00469
00470
00471
00472 buf = page_zip_fixed_field_encode(
00473 buf, fixed_sum << 1 | 1);
00474 fixed_sum = 0;
00475 col++;
00476 }
00477
00478 if (i && UNIV_UNLIKELY(i == trx_id_pos)) {
00479 if (fixed_sum) {
00480
00481
00482
00483 buf = page_zip_fixed_field_encode(
00484 buf, fixed_sum << 1 | 1);
00485 col++;
00486 }
00487
00488 trx_id_col = col;
00489 fixed_sum = field->fixed_len;
00490 } else {
00491
00492 fixed_sum += field->fixed_len;
00493 }
00494 } else {
00495
00496
00497 if (fixed_sum) {
00498
00499
00500 buf = page_zip_fixed_field_encode(
00501 buf, fixed_sum << 1 | 1);
00502 fixed_sum = 0;
00503 col++;
00504 }
00505
00506 buf = page_zip_fixed_field_encode(
00507 buf, field->fixed_len << 1);
00508 col++;
00509 }
00510 }
00511
00512 if (fixed_sum) {
00513
00514 buf = page_zip_fixed_field_encode(buf, fixed_sum << 1 | 1);
00515 }
00516
00517 if (trx_id_pos != ULINT_UNDEFINED) {
00518
00519 i = trx_id_col;
00520 } else {
00521
00522 i = index->n_nullable;
00523 }
00524
00525 if (i < 128) {
00526 *buf++ = (byte) i;
00527 } else {
00528 *buf++ = (byte) (0x80 | i >> 8);
00529 *buf++ = (byte) i;
00530 }
00531
00532 ut_ad((ulint) (buf - buf_start) <= (n + 2) * 2);
00533 return((ulint) (buf - buf_start));
00534 }
00535
00536
00538 static
00539 void
00540 page_zip_dir_encode(
00541
00542 const page_t* page,
00543 byte* buf,
00545 const rec_t** recs)
00548 {
00549 const byte* rec;
00550 ulint status;
00551 ulint min_mark;
00552 ulint heap_no;
00553 ulint i;
00554 ulint n_heap;
00555 ulint offs;
00556
00557 min_mark = 0;
00558
00559 if (page_is_leaf(page)) {
00560 status = REC_STATUS_ORDINARY;
00561 } else {
00562 status = REC_STATUS_NODE_PTR;
00563 if (UNIV_UNLIKELY
00564 (mach_read_from_4(page + FIL_PAGE_PREV) == FIL_NULL)) {
00565 min_mark = REC_INFO_MIN_REC_FLAG;
00566 }
00567 }
00568
00569 n_heap = page_dir_get_n_heap(page);
00570
00571
00572
00573
00574 rec = page + PAGE_NEW_INFIMUM;
00575
00576 i = 0;
00577
00578 for (;;) {
00579 ulint info_bits;
00580 offs = rec_get_next_offs(rec, TRUE);
00581 if (UNIV_UNLIKELY(offs == PAGE_NEW_SUPREMUM)) {
00582 break;
00583 }
00584 rec = page + offs;
00585 heap_no = rec_get_heap_no_new(rec);
00586 ut_a(heap_no >= PAGE_HEAP_NO_USER_LOW);
00587 ut_a(heap_no < n_heap);
00588 ut_a(offs < UNIV_PAGE_SIZE - PAGE_DIR);
00589 ut_a(offs >= PAGE_ZIP_START);
00590 #if PAGE_ZIP_DIR_SLOT_MASK & (PAGE_ZIP_DIR_SLOT_MASK + 1)
00591 # error "PAGE_ZIP_DIR_SLOT_MASK is not 1 less than a power of 2"
00592 #endif
00593 #if PAGE_ZIP_DIR_SLOT_MASK < UNIV_PAGE_SIZE - 1
00594 # error "PAGE_ZIP_DIR_SLOT_MASK < UNIV_PAGE_SIZE - 1"
00595 #endif
00596 if (UNIV_UNLIKELY(rec_get_n_owned_new(rec))) {
00597 offs |= PAGE_ZIP_DIR_SLOT_OWNED;
00598 }
00599
00600 info_bits = rec_get_info_bits(rec, TRUE);
00601 if (UNIV_UNLIKELY(info_bits & REC_INFO_DELETED_FLAG)) {
00602 info_bits &= ~REC_INFO_DELETED_FLAG;
00603 offs |= PAGE_ZIP_DIR_SLOT_DEL;
00604 }
00605 ut_a(info_bits == min_mark);
00606
00607
00608 min_mark = 0;
00609
00610 mach_write_to_2(buf - PAGE_ZIP_DIR_SLOT_SIZE * ++i, offs);
00611
00612 if (UNIV_LIKELY_NULL(recs)) {
00613
00614 ut_a(!recs[heap_no - PAGE_HEAP_NO_USER_LOW]);
00615
00616 recs[heap_no - PAGE_HEAP_NO_USER_LOW] = rec;
00617 }
00618
00619 ut_a(rec_get_status(rec) == status);
00620 }
00621
00622 offs = page_header_get_field(page, PAGE_FREE);
00623
00624
00625 while (offs) {
00626 ut_ad(!(offs & ~PAGE_ZIP_DIR_SLOT_MASK));
00627 rec = page + offs;
00628
00629 heap_no = rec_get_heap_no_new(rec);
00630 ut_a(heap_no >= PAGE_HEAP_NO_USER_LOW);
00631 ut_a(heap_no < n_heap);
00632
00633 ut_a(!rec[-REC_N_NEW_EXTRA_BYTES]);
00634 ut_a(rec_get_status(rec) == status);
00635
00636 mach_write_to_2(buf - PAGE_ZIP_DIR_SLOT_SIZE * ++i, offs);
00637
00638 if (UNIV_LIKELY_NULL(recs)) {
00639
00640 ut_a(!recs[heap_no - PAGE_HEAP_NO_USER_LOW]);
00641
00642 recs[heap_no - PAGE_HEAP_NO_USER_LOW] = rec;
00643 }
00644
00645 offs = rec_get_next_offs(rec, TRUE);
00646 }
00647
00648
00649 ut_a(i + PAGE_HEAP_NO_USER_LOW == n_heap);
00650 }
00651
00652
00654 extern "C" void* page_zip_malloc(void* opaque, uInt items, uInt size);
00655
00656 extern "C" void* page_zip_malloc
00657 (
00658
00659 void* opaque,
00660 uInt items,
00661 uInt size)
00662 {
00663 return(mem_heap_alloc(static_cast<mem_block_info_t *>(opaque), items * size));
00664 }
00665
00666
00668 extern "C" void page_zip_free(void *opaque, void *address);
00669
00670 extern "C" void page_zip_free(void *, void *)
00671 { }
00672
00673
00675 UNIV_INTERN
00676 void
00677 page_zip_set_alloc(
00678
00679 void* stream,
00680 mem_heap_t* heap)
00681 {
00682 z_stream* strm = static_cast<z_stream *>(stream);
00683
00684 strm->zalloc = page_zip_malloc;
00685 strm->zfree = page_zip_free;
00686 strm->opaque = heap;
00687 }
00688
00689 #if 0 || defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
00690
00691 # define PAGE_ZIP_COMPRESS_DBG
00692 #endif
00693
00694 #ifdef PAGE_ZIP_COMPRESS_DBG
00695
00697 UNIV_INTERN ibool page_zip_compress_dbg;
00702 UNIV_INTERN unsigned page_zip_compress_log;
00703
00704
00707 static
00708 int
00709 page_zip_compress_deflate(
00710
00711 FILE* logfile,
00712 z_streamp strm,
00713 int flush)
00714 {
00715 int status;
00716 if (UNIV_UNLIKELY(page_zip_compress_dbg)) {
00717 ut_print_buf(stderr, strm->next_in, strm->avail_in);
00718 }
00719 if (UNIV_LIKELY_NULL(logfile)) {
00720 fwrite(strm->next_in, 1, strm->avail_in, logfile);
00721 }
00722 status = deflate(strm, flush);
00723 if (UNIV_UNLIKELY(page_zip_compress_dbg)) {
00724 fprintf(stderr, " -> %d\n", status);
00725 }
00726 return(status);
00727 }
00728
00729
00730 # undef deflate
00731
00736 # define deflate(strm, flush) page_zip_compress_deflate(logfile, strm, flush)
00737
00738 # define FILE_LOGFILE FILE* logfile,
00739
00740 # define LOGFILE logfile,
00741 #else
00742
00743 # define FILE_LOGFILE
00744
00745 # define LOGFILE
00746 #endif
00747
00748
00751 static
00752 int
00753 page_zip_compress_node_ptrs(
00754
00755 FILE_LOGFILE
00756 z_stream* c_stream,
00757 const rec_t** recs,
00759 ulint n_dense,
00760 dict_index_t* index,
00761 byte* storage,
00762 mem_heap_t* heap)
00763 {
00764 int err = Z_OK;
00765 ulint* offsets = NULL;
00766
00767 do {
00768 const rec_t* rec = *recs++;
00769
00770 offsets = rec_get_offsets(rec, index, offsets,
00771 ULINT_UNDEFINED, &heap);
00772
00773 ut_ad(!rec_offs_any_extern(offsets));
00774
00775 UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets));
00776 UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
00777 rec_offs_extra_size(offsets));
00778
00779
00780 c_stream->avail_in = rec - REC_N_NEW_EXTRA_BYTES
00781 - c_stream->next_in;
00782
00783 if (c_stream->avail_in) {
00784 err = deflate(c_stream, Z_NO_FLUSH);
00785 if (UNIV_UNLIKELY(err != Z_OK)) {
00786 break;
00787 }
00788 }
00789 ut_ad(!c_stream->avail_in);
00790
00791
00792 c_stream->next_in = (byte*) rec;
00793 c_stream->avail_in = rec_offs_data_size(offsets)
00794 - REC_NODE_PTR_SIZE;
00795 ut_ad(c_stream->avail_in);
00796
00797 err = deflate(c_stream, Z_NO_FLUSH);
00798 if (UNIV_UNLIKELY(err != Z_OK)) {
00799 break;
00800 }
00801
00802 ut_ad(!c_stream->avail_in);
00803
00804 memcpy(storage - REC_NODE_PTR_SIZE
00805 * (rec_get_heap_no_new(rec) - 1),
00806 c_stream->next_in, REC_NODE_PTR_SIZE);
00807 c_stream->next_in += REC_NODE_PTR_SIZE;
00808 } while (--n_dense);
00809
00810 return(err);
00811 }
00812
00813
00816 static
00817 int
00818 page_zip_compress_sec(
00819
00820 FILE_LOGFILE
00821 z_stream* c_stream,
00822 const rec_t** recs,
00824 ulint n_dense)
00825 {
00826 int err = Z_OK;
00827
00828 ut_ad(n_dense > 0);
00829
00830 do {
00831 const rec_t* rec = *recs++;
00832
00833
00834 c_stream->avail_in = rec - REC_N_NEW_EXTRA_BYTES
00835 - c_stream->next_in;
00836
00837 if (UNIV_LIKELY(c_stream->avail_in)) {
00838 UNIV_MEM_ASSERT_RW(c_stream->next_in,
00839 c_stream->avail_in);
00840 err = deflate(c_stream, Z_NO_FLUSH);
00841 if (UNIV_UNLIKELY(err != Z_OK)) {
00842 break;
00843 }
00844 }
00845
00846 ut_ad(!c_stream->avail_in);
00847 ut_ad(c_stream->next_in == rec - REC_N_NEW_EXTRA_BYTES);
00848
00849
00850
00851 c_stream->next_in = (byte*) rec;
00852 } while (--n_dense);
00853
00854 return(err);
00855 }
00856
00857
00861 static
00862 int
00863 page_zip_compress_clust_ext(
00864
00865 FILE_LOGFILE
00866 z_stream* c_stream,
00867 const rec_t* rec,
00868 const ulint* offsets,
00869 ulint trx_id_col,
00870 byte* deleted,
00872 byte* storage,
00873 byte** externs,
00875 ulint* n_blobs)
00877 {
00878 int err;
00879 ulint i;
00880
00881 UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets));
00882 UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
00883 rec_offs_extra_size(offsets));
00884
00885 for (i = 0; i < rec_offs_n_fields(offsets); i++) {
00886 ulint len;
00887 const byte* src;
00888
00889 if (UNIV_UNLIKELY(i == trx_id_col)) {
00890 ut_ad(!rec_offs_nth_extern(offsets, i));
00891
00892
00893 src = rec_get_nth_field(rec, offsets, i, &len);
00894 ut_ad(src + DATA_TRX_ID_LEN
00895 == rec_get_nth_field(rec, offsets,
00896 i + 1, &len));
00897 ut_ad(len == DATA_ROLL_PTR_LEN);
00898
00899
00900 c_stream->avail_in
00901 = src - c_stream->next_in;
00902
00903 if (c_stream->avail_in) {
00904 err = deflate(c_stream, Z_NO_FLUSH);
00905 if (UNIV_UNLIKELY(err != Z_OK)) {
00906
00907 return(err);
00908 }
00909 }
00910
00911 ut_ad(!c_stream->avail_in);
00912 ut_ad(c_stream->next_in == src);
00913
00914 memcpy(storage
00915 - (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN)
00916 * (rec_get_heap_no_new(rec) - 1),
00917 c_stream->next_in,
00918 DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
00919
00920 c_stream->next_in
00921 += DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN;
00922
00923
00924 i++;
00925 } else if (rec_offs_nth_extern(offsets, i)) {
00926 src = rec_get_nth_field(rec, offsets, i, &len);
00927 ut_ad(len >= BTR_EXTERN_FIELD_REF_SIZE);
00928 src += len - BTR_EXTERN_FIELD_REF_SIZE;
00929
00930 c_stream->avail_in = src
00931 - c_stream->next_in;
00932 if (UNIV_LIKELY(c_stream->avail_in)) {
00933 err = deflate(c_stream, Z_NO_FLUSH);
00934 if (UNIV_UNLIKELY(err != Z_OK)) {
00935
00936 return(err);
00937 }
00938 }
00939
00940 ut_ad(!c_stream->avail_in);
00941 ut_ad(c_stream->next_in == src);
00942
00943
00944
00945
00946
00947
00948 if (UNIV_UNLIKELY
00949 (c_stream->avail_out
00950 <= BTR_EXTERN_FIELD_REF_SIZE)) {
00951
00952 return(Z_BUF_ERROR);
00953 }
00954
00955 ut_ad(*externs == c_stream->next_out
00956 + c_stream->avail_out
00957 + 1);
00958
00959 c_stream->next_in
00960 += BTR_EXTERN_FIELD_REF_SIZE;
00961
00962
00963 if (UNIV_LIKELY_NULL
00964 (page_zip_dir_find_low(
00965 storage, deleted,
00966 page_offset(rec)))) {
00967 continue;
00968 }
00969
00970 (*n_blobs)++;
00971 c_stream->avail_out
00972 -= BTR_EXTERN_FIELD_REF_SIZE;
00973 *externs -= BTR_EXTERN_FIELD_REF_SIZE;
00974
00975
00976 memcpy(*externs, c_stream->next_in
00977 - BTR_EXTERN_FIELD_REF_SIZE,
00978 BTR_EXTERN_FIELD_REF_SIZE);
00979 }
00980 }
00981
00982 return(Z_OK);
00983 }
00984
00985
00988 static
00989 int
00990 page_zip_compress_clust(
00991
00992 FILE_LOGFILE
00993 z_stream* c_stream,
00994 const rec_t** recs,
00996 ulint n_dense,
00997 dict_index_t* index,
00998 ulint* n_blobs,
01000 ulint trx_id_col,
01001 byte* deleted,
01003 byte* storage,
01004 mem_heap_t* heap)
01005 {
01006 int err = Z_OK;
01007 ulint* offsets = NULL;
01008
01009 byte* externs = storage - n_dense
01010 * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
01011
01012 ut_ad(*n_blobs == 0);
01013
01014 do {
01015 const rec_t* rec = *recs++;
01016
01017 offsets = rec_get_offsets(rec, index, offsets,
01018 ULINT_UNDEFINED, &heap);
01019 ut_ad(rec_offs_n_fields(offsets)
01020 == dict_index_get_n_fields(index));
01021 UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets));
01022 UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
01023 rec_offs_extra_size(offsets));
01024
01025
01026 c_stream->avail_in = rec - REC_N_NEW_EXTRA_BYTES
01027 - c_stream->next_in;
01028
01029 if (c_stream->avail_in) {
01030 err = deflate(c_stream, Z_NO_FLUSH);
01031 if (UNIV_UNLIKELY(err != Z_OK)) {
01032
01033 goto func_exit;
01034 }
01035 }
01036 ut_ad(!c_stream->avail_in);
01037 ut_ad(c_stream->next_in == rec - REC_N_NEW_EXTRA_BYTES);
01038
01039
01040
01041 c_stream->next_in = (byte*) rec;
01042
01043
01044
01045
01046 if (UNIV_UNLIKELY(rec_offs_any_extern(offsets))) {
01047 ut_ad(dict_index_is_clust(index));
01048
01049 err = page_zip_compress_clust_ext(
01050 LOGFILE
01051 c_stream, rec, offsets, trx_id_col,
01052 deleted, storage, &externs, n_blobs);
01053
01054 if (UNIV_UNLIKELY(err != Z_OK)) {
01055
01056 goto func_exit;
01057 }
01058 } else {
01059 ulint len;
01060 const byte* src;
01061
01062
01063 src = rec_get_nth_field(rec, offsets,
01064 trx_id_col, &len);
01065 ut_ad(src + DATA_TRX_ID_LEN
01066 == rec_get_nth_field(rec, offsets,
01067 trx_id_col + 1, &len));
01068 ut_ad(len == DATA_ROLL_PTR_LEN);
01069 UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets));
01070 UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
01071 rec_offs_extra_size(offsets));
01072
01073
01074 c_stream->avail_in = src - c_stream->next_in;
01075
01076 if (c_stream->avail_in) {
01077 err = deflate(c_stream, Z_NO_FLUSH);
01078 if (UNIV_UNLIKELY(err != Z_OK)) {
01079
01080 return(err);
01081 }
01082 }
01083
01084 ut_ad(!c_stream->avail_in);
01085 ut_ad(c_stream->next_in == src);
01086
01087 memcpy(storage
01088 - (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN)
01089 * (rec_get_heap_no_new(rec) - 1),
01090 c_stream->next_in,
01091 DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
01092
01093 c_stream->next_in
01094 += DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN;
01095
01096
01097 ut_ad(trx_id_col + 1 < rec_offs_n_fields(offsets));
01098 }
01099
01100
01101 c_stream->avail_in = rec + rec_offs_data_size(offsets)
01102 - c_stream->next_in;
01103
01104 if (c_stream->avail_in) {
01105 err = deflate(c_stream, Z_NO_FLUSH);
01106 if (UNIV_UNLIKELY(err != Z_OK)) {
01107
01108 goto func_exit;
01109 }
01110 }
01111 ut_ad(!c_stream->avail_in);
01112 } while (--n_dense);
01113
01114 func_exit:
01115 return(err);
01116 }
01117
01118
01122 UNIV_INTERN
01123 ibool
01124 page_zip_compress(
01125
01126 page_zip_des_t* page_zip,
01128 const page_t* page,
01129 dict_index_t* index,
01130 mtr_t* mtr)
01131 {
01132 z_stream c_stream;
01133 int err;
01134 ulint n_fields;
01135 byte* fields;
01136 byte* buf;
01137 byte* buf_end;
01138 ulint n_dense;
01139 ulint slot_size;
01140 const rec_t** recs;
01141 mem_heap_t* heap;
01142 ulint trx_id_col;
01143 ulint* offsets = NULL;
01144 ulint n_blobs = 0;
01145 byte* storage;
01146 #ifndef UNIV_HOTBACKUP
01147 ullint usec = ut_time_us(NULL);
01148 #endif
01149 #ifdef PAGE_ZIP_COMPRESS_DBG
01150 FILE* logfile = NULL;
01151 #endif
01152
01153 ut_a(page_is_comp(page));
01154 ut_a(fil_page_get_type(page) == FIL_PAGE_INDEX);
01155 ut_ad(page_simple_validate_new((page_t*) page));
01156 ut_ad(page_zip_simple_validate(page_zip));
01157 ut_ad(dict_table_is_comp(index->table));
01158 ut_ad(!dict_index_is_ibuf(index));
01159
01160 UNIV_MEM_ASSERT_RW(page, UNIV_PAGE_SIZE);
01161
01162
01163 ut_a(!memcmp(page + (PAGE_NEW_INFIMUM - REC_N_NEW_EXTRA_BYTES),
01164 infimum_extra, sizeof infimum_extra));
01165 ut_a(!memcmp(page + PAGE_NEW_INFIMUM,
01166 infimum_data, sizeof infimum_data));
01167 ut_a(page[PAGE_NEW_SUPREMUM - REC_N_NEW_EXTRA_BYTES]
01168
01169 <= PAGE_DIR_SLOT_MAX_N_OWNED);
01170 ut_a(!memcmp(page + (PAGE_NEW_SUPREMUM - REC_N_NEW_EXTRA_BYTES + 1),
01171 supremum_extra_data, sizeof supremum_extra_data));
01172
01173 if (UNIV_UNLIKELY(!page_get_n_recs(page))) {
01174 ut_a(rec_get_next_offs(page + PAGE_NEW_INFIMUM, TRUE)
01175 == PAGE_NEW_SUPREMUM);
01176 }
01177
01178 if (page_is_leaf(page)) {
01179 n_fields = dict_index_get_n_fields(index);
01180 } else {
01181 n_fields = dict_index_get_n_unique_in_tree(index);
01182 }
01183
01184
01185 n_dense = page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW;
01186 #ifdef PAGE_ZIP_COMPRESS_DBG
01187 if (UNIV_UNLIKELY(page_zip_compress_dbg)) {
01188 fprintf(stderr, "compress %p %p %lu %lu %lu\n",
01189 (void*) page_zip, (void*) page,
01190 page_is_leaf(page),
01191 n_fields, n_dense);
01192 }
01193 if (UNIV_UNLIKELY(page_zip_compress_log)) {
01194
01195 char logfilename[9];
01196 ut_snprintf(logfilename, sizeof logfilename,
01197 "%08x", page_zip_compress_log++);
01198 logfile = fopen(logfilename, "wb");
01199
01200 if (logfile) {
01201
01202 fwrite(page, 1, UNIV_PAGE_SIZE, logfile);
01203
01204
01205 putc(0, logfile);
01206 putc(0, logfile);
01207 putc(0, logfile);
01208 putc(0, logfile);
01209 }
01210 }
01211 #endif
01212 #ifndef UNIV_HOTBACKUP
01213 page_zip_stat[page_zip->ssize - 1].compressed++;
01214 #endif
01215
01216 if (UNIV_UNLIKELY(n_dense * PAGE_ZIP_DIR_SLOT_SIZE
01217 >= page_zip_get_size(page_zip))) {
01218
01219 goto err_exit;
01220 }
01221
01222 heap = mem_heap_create(page_zip_get_size(page_zip)
01223 + n_fields * (2 + sizeof *offsets)
01224 + n_dense * ((sizeof *recs)
01225 - PAGE_ZIP_DIR_SLOT_SIZE)
01226 + UNIV_PAGE_SIZE * 4
01227 + (512 << MAX_MEM_LEVEL));
01228
01229 recs = static_cast<const unsigned char **>(mem_heap_zalloc(heap, n_dense * sizeof *recs));
01230
01231 fields = static_cast<byte *>(mem_heap_alloc(heap, (n_fields + 1) * 2));
01232
01233 buf = static_cast<byte *>(mem_heap_alloc(heap, page_zip_get_size(page_zip) - PAGE_DATA));
01234 buf_end = buf + page_zip_get_size(page_zip) - PAGE_DATA;
01235
01236
01237 page_zip_set_alloc(&c_stream, heap);
01238
01239 err = deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION,
01240 Z_DEFLATED, UNIV_PAGE_SIZE_SHIFT,
01241 MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
01242 ut_a(err == Z_OK);
01243
01244 c_stream.next_out = buf;
01245
01246
01247 c_stream.avail_out = buf_end - buf - 1;
01248
01249 if (page_is_leaf(page)) {
01250 if (dict_index_is_clust(index)) {
01251 trx_id_col = dict_index_get_sys_col_pos(
01252 index, DATA_TRX_ID);
01253 ut_ad(trx_id_col > 0);
01254 ut_ad(trx_id_col != ULINT_UNDEFINED);
01255
01256 slot_size = PAGE_ZIP_DIR_SLOT_SIZE
01257 + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN;
01258 } else {
01259
01260
01261 ut_ad(dict_index_get_sys_col_pos(index, DATA_TRX_ID)
01262 == ULINT_UNDEFINED);
01263 trx_id_col = 0;
01264 slot_size = PAGE_ZIP_DIR_SLOT_SIZE;
01265 }
01266 } else {
01267 slot_size = PAGE_ZIP_DIR_SLOT_SIZE + REC_NODE_PTR_SIZE;
01268 trx_id_col = ULINT_UNDEFINED;
01269 }
01270
01271 if (UNIV_UNLIKELY(c_stream.avail_out <= n_dense * slot_size
01272 + 6)) {
01273 goto zlib_error;
01274 }
01275
01276 c_stream.avail_out -= n_dense * slot_size;
01277 c_stream.avail_in = page_zip_fields_encode(n_fields, index,
01278 trx_id_col, fields);
01279 c_stream.next_in = fields;
01280 if (UNIV_LIKELY(!trx_id_col)) {
01281 trx_id_col = ULINT_UNDEFINED;
01282 }
01283
01284 UNIV_MEM_ASSERT_RW(c_stream.next_in, c_stream.avail_in);
01285 err = deflate(&c_stream, Z_FULL_FLUSH);
01286 if (err != Z_OK) {
01287 goto zlib_error;
01288 }
01289
01290 ut_ad(!c_stream.avail_in);
01291
01292 page_zip_dir_encode(page, buf_end, recs);
01293
01294 c_stream.next_in = (byte*) page + PAGE_ZIP_START;
01295
01296 storage = buf_end - n_dense * PAGE_ZIP_DIR_SLOT_SIZE;
01297
01298
01299 if (UNIV_UNLIKELY(!n_dense)) {
01300 } else if (!page_is_leaf(page)) {
01301
01302 err = page_zip_compress_node_ptrs(LOGFILE
01303 &c_stream, recs, n_dense,
01304 index, storage, heap);
01305 if (UNIV_UNLIKELY(err != Z_OK)) {
01306 goto zlib_error;
01307 }
01308 } else if (UNIV_LIKELY(trx_id_col == ULINT_UNDEFINED)) {
01309
01310 err = page_zip_compress_sec(LOGFILE
01311 &c_stream, recs, n_dense);
01312 if (UNIV_UNLIKELY(err != Z_OK)) {
01313 goto zlib_error;
01314 }
01315 } else {
01316
01317 err = page_zip_compress_clust(LOGFILE
01318 &c_stream, recs, n_dense,
01319 index, &n_blobs, trx_id_col,
01320 buf_end - PAGE_ZIP_DIR_SLOT_SIZE
01321 * page_get_n_recs(page),
01322 storage, heap);
01323 if (UNIV_UNLIKELY(err != Z_OK)) {
01324 goto zlib_error;
01325 }
01326 }
01327
01328
01329 ut_ad(!c_stream.avail_in);
01330
01331
01332
01333 c_stream.avail_in
01334 = page_header_get_field(page, PAGE_HEAP_TOP)
01335 - (c_stream.next_in - page);
01336 ut_a(c_stream.avail_in <= UNIV_PAGE_SIZE - PAGE_ZIP_START - PAGE_DIR);
01337
01338 UNIV_MEM_ASSERT_RW(c_stream.next_in, c_stream.avail_in);
01339 err = deflate(&c_stream, Z_FINISH);
01340
01341 if (UNIV_UNLIKELY(err != Z_STREAM_END)) {
01342 zlib_error:
01343 deflateEnd(&c_stream);
01344 mem_heap_free(heap);
01345 err_exit:
01346 #ifdef PAGE_ZIP_COMPRESS_DBG
01347 if (logfile) {
01348 fclose(logfile);
01349 }
01350 #endif
01351 #ifndef UNIV_HOTBACKUP
01352 page_zip_stat[page_zip->ssize - 1].compressed_usec
01353 += ut_time_us(NULL) - usec;
01354 #endif
01355 return(FALSE);
01356 }
01357
01358 err = deflateEnd(&c_stream);
01359 ut_a(err == Z_OK);
01360
01361 ut_ad(buf + c_stream.total_out == c_stream.next_out);
01362 ut_ad((ulint) (storage - c_stream.next_out) >= c_stream.avail_out);
01363
01364
01365
01366 UNIV_MEM_VALID(buf, c_stream.total_out);
01367
01368
01369
01370
01371 memset(c_stream.next_out, 0, c_stream.avail_out + 1);
01372
01373 #ifdef UNIV_DEBUG
01374 page_zip->m_start =
01375 #endif
01376 page_zip->m_end = PAGE_DATA + c_stream.total_out;
01377 page_zip->m_nonempty = FALSE;
01378 page_zip->n_blobs = n_blobs;
01379
01380
01381 memcpy(page_zip->data + FIL_PAGE_PREV, page + FIL_PAGE_PREV,
01382 FIL_PAGE_LSN - FIL_PAGE_PREV);
01383 memcpy(page_zip->data + FIL_PAGE_TYPE, page + FIL_PAGE_TYPE, 2);
01384 memcpy(page_zip->data + FIL_PAGE_DATA, page + FIL_PAGE_DATA,
01385 PAGE_DATA - FIL_PAGE_DATA);
01386
01387 memcpy(page_zip->data + PAGE_DATA, buf,
01388 page_zip_get_size(page_zip) - PAGE_DATA);
01389 mem_heap_free(heap);
01390 #ifdef UNIV_ZIP_DEBUG
01391 ut_a(page_zip_validate(page_zip, page));
01392 #endif
01393
01394 if (mtr) {
01395 #ifndef UNIV_HOTBACKUP
01396 page_zip_compress_write_log(page_zip, page, index, mtr);
01397 #endif
01398 }
01399
01400 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
01401
01402 #ifdef PAGE_ZIP_COMPRESS_DBG
01403 if (logfile) {
01404
01405 byte sz[4];
01406 mach_write_to_4(sz, c_stream.total_out);
01407 fseek(logfile, UNIV_PAGE_SIZE, SEEK_SET);
01408 fwrite(sz, 1, sizeof sz, logfile);
01409 fclose(logfile);
01410 }
01411 #endif
01412 #ifndef UNIV_HOTBACKUP
01413 {
01414 page_zip_stat_t* zip_stat
01415 = &page_zip_stat[page_zip->ssize - 1];
01416 zip_stat->compressed_ok++;
01417 zip_stat->compressed_usec += ut_time_us(NULL) - usec;
01418 }
01419 #endif
01420
01421 return(TRUE);
01422 }
01423
01424
01427 UNIV_INLINE
01428 ibool
01429 page_zip_dir_cmp(
01430
01431 const rec_t* rec1,
01432 const rec_t* rec2)
01433 {
01434 return(rec1 > rec2);
01435 }
01436
01437
01439 static
01440 void
01441 page_zip_dir_sort(
01442
01443 rec_t** arr,
01444 rec_t** aux_arr,
01445 ulint low,
01446 ulint high)
01447 {
01448 UT_SORT_FUNCTION_BODY(page_zip_dir_sort, arr, aux_arr, low, high,
01449 page_zip_dir_cmp);
01450 }
01451
01452
01454 static
01455 void
01456 page_zip_fields_free(
01457
01458 dict_index_t* index)
01459 {
01460 if (index) {
01461 dict_table_t* table = index->table;
01462 mem_heap_free(index->heap);
01463 mutex_free(&(table->autoinc_mutex));
01464 ut_free(table->name);
01465 mem_heap_free(table->heap);
01466 }
01467 }
01468
01469
01472 static
01473 dict_index_t*
01474 page_zip_fields_decode(
01475
01476 const byte* buf,
01477 const byte* end,
01478 ulint* trx_id_col)
01481 {
01482 const byte* b;
01483 ulint n;
01484 ulint i;
01485 ulint val;
01486 dict_table_t* table;
01487 dict_index_t* index;
01488
01489
01490 for (b = buf, n = 0; b < end; n++) {
01491 if (*b++ & 0x80) {
01492 b++;
01493 }
01494 }
01495
01496 n--;
01497
01498 if (UNIV_UNLIKELY(n > REC_MAX_N_FIELDS)) {
01499
01500 page_zip_fail(("page_zip_fields_decode: n = %lu\n",
01501 (ulong) n));
01502 return(NULL);
01503 }
01504
01505 if (UNIV_UNLIKELY(b > end)) {
01506
01507 page_zip_fail(("page_zip_fields_decode: %p > %p\n",
01508 (const void*) b, (const void*) end));
01509 return(NULL);
01510 }
01511
01512 table = dict_mem_table_create("ZIP_DUMMY", DICT_HDR_SPACE, n,
01513 DICT_TF_COMPACT);
01514 index = dict_mem_index_create("ZIP_DUMMY", "ZIP_DUMMY",
01515 DICT_HDR_SPACE, 0, n);
01516 index->table = table;
01517 index->n_uniq = n;
01518
01519 index->cached = TRUE;
01520
01521
01522 for (b = buf, i = 0; i < n; i++) {
01523 ulint mtype;
01524 ulint len;
01525
01526 val = *b++;
01527
01528 if (UNIV_UNLIKELY(val & 0x80)) {
01529
01530 val = (val & 0x7f) << 8 | *b++;
01531 len = val >> 1;
01532 mtype = DATA_FIXBINARY;
01533 } else if (UNIV_UNLIKELY(val >= 126)) {
01534
01535 len = 0x7fff;
01536 mtype = DATA_BINARY;
01537 } else if (val <= 1) {
01538
01539 len = 0;
01540 mtype = DATA_BINARY;
01541 } else {
01542
01543 len = val >> 1;
01544 mtype = DATA_FIXBINARY;
01545 }
01546
01547 dict_mem_table_add_col(table, NULL, NULL, mtype,
01548 val & 1 ? DATA_NOT_NULL : 0, len);
01549 dict_index_add_col(index, table,
01550 dict_table_get_nth_col(table, i), 0);
01551 }
01552
01553 val = *b++;
01554 if (UNIV_UNLIKELY(val & 0x80)) {
01555 val = (val & 0x7f) << 8 | *b++;
01556 }
01557
01558
01559 if (trx_id_col) {
01560 if (!val) {
01561 val = ULINT_UNDEFINED;
01562 } else if (UNIV_UNLIKELY(val >= n)) {
01563 page_zip_fields_free(index);
01564 index = NULL;
01565 } else {
01566 index->type = DICT_CLUSTERED;
01567 }
01568
01569 *trx_id_col = val;
01570 } else {
01571
01572 if (UNIV_UNLIKELY(index->n_nullable > val)) {
01573 page_zip_fields_free(index);
01574 index = NULL;
01575 } else {
01576 index->n_nullable = val;
01577 }
01578 }
01579
01580 ut_ad(b == end);
01581
01582 return(index);
01583 }
01584
01585
01588 static
01589 ibool
01590 page_zip_dir_decode(
01591
01592 const page_zip_des_t* page_zip,
01594 page_t* page,
01597 rec_t** recs,
01599 rec_t** recs_aux,
01600 ulint n_dense)
01602 {
01603 ulint i;
01604 ulint n_recs;
01605 byte* slot;
01606
01607 n_recs = page_get_n_recs(page);
01608
01609 if (UNIV_UNLIKELY(n_recs > n_dense)) {
01610 page_zip_fail(("page_zip_dir_decode 1: %lu > %lu\n",
01611 (ulong) n_recs, (ulong) n_dense));
01612 return(FALSE);
01613 }
01614
01615
01616
01617
01618 slot = page + (UNIV_PAGE_SIZE - PAGE_DIR - PAGE_DIR_SLOT_SIZE);
01619 UNIV_PREFETCH_RW(slot);
01620
01621
01622 memset(slot + PAGE_DIR_SLOT_SIZE, 0, PAGE_DIR);
01623
01624 mach_write_to_2(slot, PAGE_NEW_INFIMUM);
01625 slot -= PAGE_DIR_SLOT_SIZE;
01626 UNIV_PREFETCH_RW(slot);
01627
01628
01629 for (i = 0; i < n_recs; i++) {
01630 ulint offs = page_zip_dir_get(page_zip, i);
01631
01632 if (offs & PAGE_ZIP_DIR_SLOT_OWNED) {
01633 mach_write_to_2(slot, offs & PAGE_ZIP_DIR_SLOT_MASK);
01634 slot -= PAGE_DIR_SLOT_SIZE;
01635 UNIV_PREFETCH_RW(slot);
01636 }
01637
01638 if (UNIV_UNLIKELY((offs & PAGE_ZIP_DIR_SLOT_MASK)
01639 < PAGE_ZIP_START + REC_N_NEW_EXTRA_BYTES)) {
01640 page_zip_fail(("page_zip_dir_decode 2: %u %u %lx\n",
01641 (unsigned) i, (unsigned) n_recs,
01642 (ulong) offs));
01643 return(FALSE);
01644 }
01645
01646 recs[i] = page + (offs & PAGE_ZIP_DIR_SLOT_MASK);
01647 }
01648
01649 mach_write_to_2(slot, PAGE_NEW_SUPREMUM);
01650 {
01651 const page_dir_slot_t* last_slot = page_dir_get_nth_slot(
01652 page, page_dir_get_n_slots(page) - 1);
01653
01654 if (UNIV_UNLIKELY(slot != last_slot)) {
01655 page_zip_fail(("page_zip_dir_decode 3: %p != %p\n",
01656 (const void*) slot,
01657 (const void*) last_slot));
01658 return(FALSE);
01659 }
01660 }
01661
01662
01663 for (; i < n_dense; i++) {
01664 ulint offs = page_zip_dir_get(page_zip, i);
01665
01666 if (UNIV_UNLIKELY(offs & ~PAGE_ZIP_DIR_SLOT_MASK)) {
01667 page_zip_fail(("page_zip_dir_decode 4: %u %u %lx\n",
01668 (unsigned) i, (unsigned) n_dense,
01669 (ulong) offs));
01670 return(FALSE);
01671 }
01672
01673 recs[i] = page + offs;
01674 }
01675
01676 if (UNIV_LIKELY(n_dense > 1)) {
01677 page_zip_dir_sort(recs, recs_aux, 0, n_dense);
01678 }
01679 return(TRUE);
01680 }
01681
01682
01685 static
01686 ibool
01687 page_zip_set_extra_bytes(
01688
01689 const page_zip_des_t* page_zip,
01690 page_t* page,
01691 ulint info_bits)
01692 {
01693 ulint n;
01694 ulint i;
01695 ulint n_owned = 1;
01696 ulint offs;
01697 rec_t* rec;
01698
01699 n = page_get_n_recs(page);
01700 rec = page + PAGE_NEW_INFIMUM;
01701
01702 for (i = 0; i < n; i++) {
01703 offs = page_zip_dir_get(page_zip, i);
01704
01705 if (UNIV_UNLIKELY(offs & PAGE_ZIP_DIR_SLOT_DEL)) {
01706 info_bits |= REC_INFO_DELETED_FLAG;
01707 }
01708 if (UNIV_UNLIKELY(offs & PAGE_ZIP_DIR_SLOT_OWNED)) {
01709 info_bits |= n_owned;
01710 n_owned = 1;
01711 } else {
01712 n_owned++;
01713 }
01714 offs &= PAGE_ZIP_DIR_SLOT_MASK;
01715 if (UNIV_UNLIKELY(offs < PAGE_ZIP_START
01716 + REC_N_NEW_EXTRA_BYTES)) {
01717 page_zip_fail(("page_zip_set_extra_bytes 1:"
01718 " %u %u %lx\n",
01719 (unsigned) i, (unsigned) n,
01720 (ulong) offs));
01721 return(FALSE);
01722 }
01723
01724 rec_set_next_offs_new(rec, offs);
01725 rec = page + offs;
01726 rec[-REC_N_NEW_EXTRA_BYTES] = (byte) info_bits;
01727 info_bits = 0;
01728 }
01729
01730
01731 rec_set_next_offs_new(rec, PAGE_NEW_SUPREMUM);
01732
01733
01734 page[PAGE_NEW_SUPREMUM - REC_N_NEW_EXTRA_BYTES] = (byte) n_owned;
01735
01736
01737 n = page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW;
01738
01739 if (i >= n) {
01740 if (UNIV_LIKELY(i == n)) {
01741 return(TRUE);
01742 }
01743
01744 page_zip_fail(("page_zip_set_extra_bytes 2: %u != %u\n",
01745 (unsigned) i, (unsigned) n));
01746 return(FALSE);
01747 }
01748
01749 offs = page_zip_dir_get(page_zip, i);
01750
01751
01752 for (;;) {
01753 if (UNIV_UNLIKELY(!offs)
01754 || UNIV_UNLIKELY(offs & ~PAGE_ZIP_DIR_SLOT_MASK)) {
01755
01756 page_zip_fail(("page_zip_set_extra_bytes 3: %lx\n",
01757 (ulong) offs));
01758 return(FALSE);
01759 }
01760
01761 rec = page + offs;
01762 rec[-REC_N_NEW_EXTRA_BYTES] = 0;
01763
01764 if (++i == n) {
01765 break;
01766 }
01767
01768 offs = page_zip_dir_get(page_zip, i);
01769 rec_set_next_offs_new(rec, offs);
01770 }
01771
01772
01773 rec[-REC_N_NEW_EXTRA_BYTES] = 0;
01774 rec_set_next_offs_new(rec, 0);
01775
01776 return(TRUE);
01777 }
01778
01779
01783 static
01784 const byte*
01785 page_zip_apply_log_ext(
01786
01787 rec_t* rec,
01788 const ulint* offsets,
01789 ulint trx_id_col,
01790 const byte* data,
01791 const byte* end)
01792 {
01793 ulint i;
01794 ulint len;
01795 byte* next_out = rec;
01796
01797
01798
01799
01800
01801 for (i = 0; i < rec_offs_n_fields(offsets); i++) {
01802 byte* dst;
01803
01804 if (UNIV_UNLIKELY(i == trx_id_col)) {
01805
01806 dst = rec_get_nth_field(rec, offsets,
01807 i, &len);
01808 if (UNIV_UNLIKELY(dst - next_out >= end - data)
01809 || UNIV_UNLIKELY
01810 (len < (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN))
01811 || rec_offs_nth_extern(offsets, i)) {
01812 page_zip_fail(("page_zip_apply_log_ext:"
01813 " trx_id len %lu,"
01814 " %p - %p >= %p - %p\n",
01815 (ulong) len,
01816 (const void*) dst,
01817 (const void*) next_out,
01818 (const void*) end,
01819 (const void*) data));
01820 return(NULL);
01821 }
01822
01823 memcpy(next_out, data, dst - next_out);
01824 data += dst - next_out;
01825 next_out = dst + (DATA_TRX_ID_LEN
01826 + DATA_ROLL_PTR_LEN);
01827 } else if (rec_offs_nth_extern(offsets, i)) {
01828 dst = rec_get_nth_field(rec, offsets,
01829 i, &len);
01830 ut_ad(len
01831 >= BTR_EXTERN_FIELD_REF_SIZE);
01832
01833 len += dst - next_out
01834 - BTR_EXTERN_FIELD_REF_SIZE;
01835
01836 if (UNIV_UNLIKELY(data + len >= end)) {
01837 page_zip_fail(("page_zip_apply_log_ext: "
01838 "ext %p+%lu >= %p\n",
01839 (const void*) data,
01840 (ulong) len,
01841 (const void*) end));
01842 return(NULL);
01843 }
01844
01845 memcpy(next_out, data, len);
01846 data += len;
01847 next_out += len
01848 + BTR_EXTERN_FIELD_REF_SIZE;
01849 }
01850 }
01851
01852
01853 len = rec_get_end(rec, offsets) - next_out;
01854 if (UNIV_UNLIKELY(data + len >= end)) {
01855 page_zip_fail(("page_zip_apply_log_ext: "
01856 "last %p+%lu >= %p\n",
01857 (const void*) data,
01858 (ulong) len,
01859 (const void*) end));
01860 return(NULL);
01861 }
01862 memcpy(next_out, data, len);
01863 data += len;
01864
01865 return(data);
01866 }
01867
01868
01872 static
01873 const byte*
01874 page_zip_apply_log(
01875
01876 const byte* data,
01877 ulint size,
01878 rec_t** recs,
01881 ulint n_dense,
01882 ulint trx_id_col,
01884 ulint heap_status,
01887 dict_index_t* index,
01888 ulint* offsets)
01890 {
01891 const byte* const end = data + size;
01892
01893 for (;;) {
01894 ulint val;
01895 rec_t* rec;
01896 ulint len;
01897 ulint hs;
01898
01899 val = *data++;
01900 if (UNIV_UNLIKELY(!val)) {
01901 return(data - 1);
01902 }
01903 if (val & 0x80) {
01904 val = (val & 0x7f) << 8 | *data++;
01905 if (UNIV_UNLIKELY(!val)) {
01906 page_zip_fail(("page_zip_apply_log:"
01907 " invalid val %x%x\n",
01908 data[-2], data[-1]));
01909 return(NULL);
01910 }
01911 }
01912 if (UNIV_UNLIKELY(data >= end)) {
01913 page_zip_fail(("page_zip_apply_log: %p >= %p\n",
01914 (const void*) data,
01915 (const void*) end));
01916 return(NULL);
01917 }
01918 if (UNIV_UNLIKELY((val >> 1) > n_dense)) {
01919 page_zip_fail(("page_zip_apply_log: %lu>>1 > %lu\n",
01920 (ulong) val, (ulong) n_dense));
01921 return(NULL);
01922 }
01923
01924
01925 rec = recs[(val >> 1) - 1];
01926
01927 hs = ((val >> 1) + 1) << REC_HEAP_NO_SHIFT;
01928 hs |= heap_status & ((1 << REC_HEAP_NO_SHIFT) - 1);
01929
01930
01931
01932
01933
01934 if (UNIV_UNLIKELY(hs > heap_status)) {
01935 page_zip_fail(("page_zip_apply_log: %lu > %lu\n",
01936 (ulong) hs, (ulong) heap_status));
01937 return(NULL);
01938 } else if (hs == heap_status) {
01939
01940 if (UNIV_UNLIKELY(val & 1)) {
01941
01942 page_zip_fail(("page_zip_apply_log:"
01943 " attempting to create"
01944 " deleted rec %lu\n",
01945 (ulong) hs));
01946 return(NULL);
01947 }
01948 heap_status += 1 << REC_HEAP_NO_SHIFT;
01949 }
01950
01951 mach_write_to_2(rec - REC_NEW_HEAP_NO, hs);
01952
01953 if (val & 1) {
01954
01955 mem_heap_t* heap = NULL;
01956 ulint* offs;
01957 offs = rec_get_offsets(rec, index, offsets,
01958 ULINT_UNDEFINED, &heap);
01959 memset(rec, 0, rec_offs_data_size(offs));
01960
01961 if (UNIV_LIKELY_NULL(heap)) {
01962 mem_heap_free(heap);
01963 }
01964 continue;
01965 }
01966
01967 #if REC_STATUS_NODE_PTR != TRUE
01968 # error "REC_STATUS_NODE_PTR != TRUE"
01969 #endif
01970 rec_get_offsets_reverse(data, index,
01971 hs & REC_STATUS_NODE_PTR,
01972 offsets);
01973 rec_offs_make_valid(rec, index, offsets);
01974
01975
01976 {
01977 byte* start = rec_get_start(rec, offsets);
01978 byte* b = rec - REC_N_NEW_EXTRA_BYTES;
01979 while (b != start) {
01980 *--b = *data++;
01981 }
01982 }
01983
01984
01985 if (UNIV_UNLIKELY(rec_offs_any_extern(offsets))) {
01986
01987
01988 if (UNIV_UNLIKELY(hs & REC_STATUS_NODE_PTR)) {
01989 page_zip_fail(("page_zip_apply_log: "
01990 "%lu&REC_STATUS_NODE_PTR\n",
01991 (ulong) hs));
01992 return(NULL);
01993 }
01994
01995 data = page_zip_apply_log_ext(
01996 rec, offsets, trx_id_col, data, end);
01997
01998 if (UNIV_UNLIKELY(!data)) {
01999 return(NULL);
02000 }
02001 } else if (UNIV_UNLIKELY(hs & REC_STATUS_NODE_PTR)) {
02002 len = rec_offs_data_size(offsets)
02003 - REC_NODE_PTR_SIZE;
02004
02005 if (UNIV_UNLIKELY(data + len >= end)) {
02006 page_zip_fail(("page_zip_apply_log: "
02007 "node_ptr %p+%lu >= %p\n",
02008 (const void*) data,
02009 (ulong) len,
02010 (const void*) end));
02011 return(NULL);
02012 }
02013 memcpy(rec, data, len);
02014 data += len;
02015 } else if (UNIV_LIKELY(trx_id_col == ULINT_UNDEFINED)) {
02016 len = rec_offs_data_size(offsets);
02017
02018
02019
02020 if (UNIV_UNLIKELY(data + len >= end)) {
02021 page_zip_fail(("page_zip_apply_log: "
02022 "sec %p+%lu >= %p\n",
02023 (const void*) data,
02024 (ulong) len,
02025 (const void*) end));
02026 return(NULL);
02027 }
02028
02029 memcpy(rec, data, len);
02030 data += len;
02031 } else {
02032
02033 ulint l = rec_get_nth_field_offs(offsets,
02034 trx_id_col, &len);
02035 byte* b;
02036
02037 if (UNIV_UNLIKELY(data + l >= end)
02038 || UNIV_UNLIKELY(len < (DATA_TRX_ID_LEN
02039 + DATA_ROLL_PTR_LEN))) {
02040 page_zip_fail(("page_zip_apply_log: "
02041 "trx_id %p+%lu >= %p\n",
02042 (const void*) data,
02043 (ulong) l,
02044 (const void*) end));
02045 return(NULL);
02046 }
02047
02048
02049 memcpy(rec, data, l);
02050 data += l;
02051
02052
02053 b = rec + l + (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
02054 len = rec_get_end(rec, offsets) - b;
02055 if (UNIV_UNLIKELY(data + len >= end)) {
02056 page_zip_fail(("page_zip_apply_log: "
02057 "clust %p+%lu >= %p\n",
02058 (const void*) data,
02059 (ulong) len,
02060 (const void*) end));
02061 return(NULL);
02062 }
02063 memcpy(b, data, len);
02064 data += len;
02065 }
02066 }
02067 }
02068
02069
02072 static
02073 ibool
02074 page_zip_decompress_node_ptrs(
02075
02076 page_zip_des_t* page_zip,
02077 z_stream* d_stream,
02078 rec_t** recs,
02080 ulint n_dense,
02081 dict_index_t* index,
02082 ulint* offsets,
02083 mem_heap_t* heap)
02084 {
02085 ulint heap_status = REC_STATUS_NODE_PTR
02086 | PAGE_HEAP_NO_USER_LOW << REC_HEAP_NO_SHIFT;
02087 ulint slot;
02088 const byte* storage;
02089
02090
02091 d_stream->avail_in -= n_dense
02092 * (PAGE_ZIP_DIR_SLOT_SIZE + REC_NODE_PTR_SIZE);
02093
02094
02095 for (slot = 0; slot < n_dense; slot++) {
02096 rec_t* rec = recs[slot];
02097
02098 d_stream->avail_out = rec - REC_N_NEW_EXTRA_BYTES
02099 - d_stream->next_out;
02100
02101 ut_ad(d_stream->avail_out < UNIV_PAGE_SIZE
02102 - PAGE_ZIP_START - PAGE_DIR);
02103 switch (inflate(d_stream, Z_SYNC_FLUSH)) {
02104 case Z_STREAM_END:
02105
02106
02107 goto zlib_done;
02108 case Z_OK:
02109 case Z_BUF_ERROR:
02110 if (!d_stream->avail_out) {
02111 break;
02112 }
02113
02114 default:
02115 page_zip_fail(("page_zip_decompress_node_ptrs:"
02116 " 1 inflate(Z_SYNC_FLUSH)=%s\n",
02117 d_stream->msg));
02118 goto zlib_error;
02119 }
02120
02121 ut_ad(d_stream->next_out == rec - REC_N_NEW_EXTRA_BYTES);
02122
02123 d_stream->next_out = rec;
02124
02125 mach_write_to_2(rec - REC_NEW_HEAP_NO, heap_status);
02126 heap_status += 1 << REC_HEAP_NO_SHIFT;
02127
02128
02129 offsets = rec_get_offsets(rec, index, offsets,
02130 ULINT_UNDEFINED, &heap);
02131
02132
02133
02134 ut_ad(!rec_offs_any_extern(offsets));
02135
02136
02137 d_stream->avail_out = rec_offs_data_size(offsets)
02138 - REC_NODE_PTR_SIZE;
02139
02140 switch (inflate(d_stream, Z_SYNC_FLUSH)) {
02141 case Z_STREAM_END:
02142 goto zlib_done;
02143 case Z_OK:
02144 case Z_BUF_ERROR:
02145 if (!d_stream->avail_out) {
02146 break;
02147 }
02148
02149 default:
02150 page_zip_fail(("page_zip_decompress_node_ptrs:"
02151 " 2 inflate(Z_SYNC_FLUSH)=%s\n",
02152 d_stream->msg));
02153 goto zlib_error;
02154 }
02155
02156
02157
02158
02159 memset(d_stream->next_out, 0, REC_NODE_PTR_SIZE);
02160 d_stream->next_out += REC_NODE_PTR_SIZE;
02161
02162 ut_ad(d_stream->next_out == rec_get_end(rec, offsets));
02163 }
02164
02165
02166
02167 d_stream->avail_out = page_header_get_field(page_zip->data,
02168 PAGE_HEAP_TOP)
02169 - page_offset(d_stream->next_out);
02170 if (UNIV_UNLIKELY(d_stream->avail_out > UNIV_PAGE_SIZE
02171 - PAGE_ZIP_START - PAGE_DIR)) {
02172
02173 page_zip_fail(("page_zip_decompress_node_ptrs:"
02174 " avail_out = %u\n",
02175 d_stream->avail_out));
02176 goto zlib_error;
02177 }
02178
02179 if (UNIV_UNLIKELY(inflate(d_stream, Z_FINISH) != Z_STREAM_END)) {
02180 page_zip_fail(("page_zip_decompress_node_ptrs:"
02181 " inflate(Z_FINISH)=%s\n",
02182 d_stream->msg));
02183 zlib_error:
02184 inflateEnd(d_stream);
02185 return(FALSE);
02186 }
02187
02188
02189
02190
02191 zlib_done:
02192 if (UNIV_UNLIKELY(inflateEnd(d_stream) != Z_OK)) {
02193 ut_error;
02194 }
02195
02196 {
02197 page_t* page = page_align(d_stream->next_out);
02198
02199
02200 memset(d_stream->next_out, 0,
02201 page_dir_get_nth_slot(page,
02202 page_dir_get_n_slots(page) - 1)
02203 - d_stream->next_out);
02204 }
02205
02206 #ifdef UNIV_DEBUG
02207 page_zip->m_start = PAGE_DATA + d_stream->total_in;
02208 #endif
02209
02210
02211 {
02212 const byte* mod_log_ptr;
02213 mod_log_ptr = page_zip_apply_log(d_stream->next_in,
02214 d_stream->avail_in + 1,
02215 recs, n_dense,
02216 ULINT_UNDEFINED, heap_status,
02217 index, offsets);
02218
02219 if (UNIV_UNLIKELY(!mod_log_ptr)) {
02220 return(FALSE);
02221 }
02222 page_zip->m_end = mod_log_ptr - page_zip->data;
02223 page_zip->m_nonempty = mod_log_ptr != d_stream->next_in;
02224 }
02225
02226 if (UNIV_UNLIKELY
02227 (page_zip_get_trailer_len(page_zip,
02228 dict_index_is_clust(index), NULL)
02229 + page_zip->m_end >= page_zip_get_size(page_zip))) {
02230 page_zip_fail(("page_zip_decompress_node_ptrs:"
02231 " %lu + %lu >= %lu, %lu\n",
02232 (ulong) page_zip_get_trailer_len(
02233 page_zip, dict_index_is_clust(index),
02234 NULL),
02235 (ulong) page_zip->m_end,
02236 (ulong) page_zip_get_size(page_zip),
02237 (ulong) dict_index_is_clust(index)));
02238 return(FALSE);
02239 }
02240
02241
02242 storage = page_zip->data + page_zip_get_size(page_zip)
02243 - n_dense * PAGE_ZIP_DIR_SLOT_SIZE;
02244
02245 for (slot = 0; slot < n_dense; slot++) {
02246 rec_t* rec = recs[slot];
02247
02248 offsets = rec_get_offsets(rec, index, offsets,
02249 ULINT_UNDEFINED, &heap);
02250
02251
02252 ut_ad(!rec_offs_any_extern(offsets));
02253 storage -= REC_NODE_PTR_SIZE;
02254
02255 memcpy(rec_get_end(rec, offsets) - REC_NODE_PTR_SIZE,
02256 storage, REC_NODE_PTR_SIZE);
02257 }
02258
02259 return(TRUE);
02260 }
02261
02262
02265 static
02266 ibool
02267 page_zip_decompress_sec(
02268
02269 page_zip_des_t* page_zip,
02270 z_stream* d_stream,
02271 rec_t** recs,
02273 ulint n_dense,
02274 dict_index_t* index,
02275 ulint* offsets)
02276 {
02277 ulint heap_status = REC_STATUS_ORDINARY
02278 | PAGE_HEAP_NO_USER_LOW << REC_HEAP_NO_SHIFT;
02279 ulint slot;
02280
02281 ut_a(!dict_index_is_clust(index));
02282
02283
02284 d_stream->avail_in -= n_dense * PAGE_ZIP_DIR_SLOT_SIZE;
02285
02286 for (slot = 0; slot < n_dense; slot++) {
02287 rec_t* rec = recs[slot];
02288
02289
02290 d_stream->avail_out = rec - REC_N_NEW_EXTRA_BYTES
02291 - d_stream->next_out;
02292
02293 if (UNIV_LIKELY(d_stream->avail_out)) {
02294 switch (inflate(d_stream, Z_SYNC_FLUSH)) {
02295 case Z_STREAM_END:
02296
02297
02298 goto zlib_done;
02299 case Z_OK:
02300 case Z_BUF_ERROR:
02301 if (!d_stream->avail_out) {
02302 break;
02303 }
02304
02305 default:
02306 page_zip_fail(("page_zip_decompress_sec:"
02307 " inflate(Z_SYNC_FLUSH)=%s\n",
02308 d_stream->msg));
02309 goto zlib_error;
02310 }
02311 }
02312
02313 ut_ad(d_stream->next_out == rec - REC_N_NEW_EXTRA_BYTES);
02314
02315
02316
02317 d_stream->next_out = rec;
02318
02319
02320 mach_write_to_2(rec - REC_NEW_HEAP_NO, heap_status);
02321 heap_status += 1 << REC_HEAP_NO_SHIFT;
02322 }
02323
02324
02325
02326
02327 d_stream->avail_out = page_header_get_field(page_zip->data,
02328 PAGE_HEAP_TOP)
02329 - page_offset(d_stream->next_out);
02330 if (UNIV_UNLIKELY(d_stream->avail_out > UNIV_PAGE_SIZE
02331 - PAGE_ZIP_START - PAGE_DIR)) {
02332
02333 page_zip_fail(("page_zip_decompress_sec:"
02334 " avail_out = %u\n",
02335 d_stream->avail_out));
02336 goto zlib_error;
02337 }
02338
02339 if (UNIV_UNLIKELY(inflate(d_stream, Z_FINISH) != Z_STREAM_END)) {
02340 page_zip_fail(("page_zip_decompress_sec:"
02341 " inflate(Z_FINISH)=%s\n",
02342 d_stream->msg));
02343 zlib_error:
02344 inflateEnd(d_stream);
02345 return(FALSE);
02346 }
02347
02348
02349
02350
02351 zlib_done:
02352 if (UNIV_UNLIKELY(inflateEnd(d_stream) != Z_OK)) {
02353 ut_error;
02354 }
02355
02356 {
02357 page_t* page = page_align(d_stream->next_out);
02358
02359
02360 memset(d_stream->next_out, 0,
02361 page_dir_get_nth_slot(page,
02362 page_dir_get_n_slots(page) - 1)
02363 - d_stream->next_out);
02364 }
02365
02366 #ifdef UNIV_DEBUG
02367 page_zip->m_start = PAGE_DATA + d_stream->total_in;
02368 #endif
02369
02370
02371 {
02372 const byte* mod_log_ptr;
02373 mod_log_ptr = page_zip_apply_log(d_stream->next_in,
02374 d_stream->avail_in + 1,
02375 recs, n_dense,
02376 ULINT_UNDEFINED, heap_status,
02377 index, offsets);
02378
02379 if (UNIV_UNLIKELY(!mod_log_ptr)) {
02380 return(FALSE);
02381 }
02382 page_zip->m_end = mod_log_ptr - page_zip->data;
02383 page_zip->m_nonempty = mod_log_ptr != d_stream->next_in;
02384 }
02385
02386 if (UNIV_UNLIKELY(page_zip_get_trailer_len(page_zip, FALSE, NULL)
02387 + page_zip->m_end >= page_zip_get_size(page_zip))) {
02388
02389 page_zip_fail(("page_zip_decompress_sec: %lu + %lu >= %lu\n",
02390 (ulong) page_zip_get_trailer_len(
02391 page_zip, FALSE, NULL),
02392 (ulong) page_zip->m_end,
02393 (ulong) page_zip_get_size(page_zip)));
02394 return(FALSE);
02395 }
02396
02397
02398
02399
02400 return(TRUE);
02401 }
02402
02403
02407 static
02408 ibool
02409 page_zip_decompress_clust_ext(
02410
02411 z_stream* d_stream,
02412 rec_t* rec,
02413 const ulint* offsets,
02414 ulint trx_id_col)
02415 {
02416 ulint i;
02417
02418 for (i = 0; i < rec_offs_n_fields(offsets); i++) {
02419 ulint len;
02420 byte* dst;
02421
02422 if (UNIV_UNLIKELY(i == trx_id_col)) {
02423
02424 dst = rec_get_nth_field(rec, offsets, i, &len);
02425 if (UNIV_UNLIKELY(len < DATA_TRX_ID_LEN
02426 + DATA_ROLL_PTR_LEN)) {
02427
02428 page_zip_fail(("page_zip_decompress_clust_ext:"
02429 " len[%lu] = %lu\n",
02430 (ulong) i, (ulong) len));
02431 return(FALSE);
02432 }
02433
02434 if (rec_offs_nth_extern(offsets, i)) {
02435
02436 page_zip_fail(("page_zip_decompress_clust_ext:"
02437 " DB_TRX_ID at %lu is ext\n",
02438 (ulong) i));
02439 return(FALSE);
02440 }
02441
02442 d_stream->avail_out = dst - d_stream->next_out;
02443
02444 switch (inflate(d_stream, Z_SYNC_FLUSH)) {
02445 case Z_STREAM_END:
02446 case Z_OK:
02447 case Z_BUF_ERROR:
02448 if (!d_stream->avail_out) {
02449 break;
02450 }
02451
02452 default:
02453 page_zip_fail(("page_zip_decompress_clust_ext:"
02454 " 1 inflate(Z_SYNC_FLUSH)=%s\n",
02455 d_stream->msg));
02456 return(FALSE);
02457 }
02458
02459 ut_ad(d_stream->next_out == dst);
02460
02461
02462
02463
02464 memset(dst, 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
02465
02466 d_stream->next_out += DATA_TRX_ID_LEN
02467 + DATA_ROLL_PTR_LEN;
02468 } else if (rec_offs_nth_extern(offsets, i)) {
02469 dst = rec_get_nth_field(rec, offsets, i, &len);
02470 ut_ad(len >= BTR_EXTERN_FIELD_REF_SIZE);
02471 dst += len - BTR_EXTERN_FIELD_REF_SIZE;
02472
02473 d_stream->avail_out = dst - d_stream->next_out;
02474 switch (inflate(d_stream, Z_SYNC_FLUSH)) {
02475 case Z_STREAM_END:
02476 case Z_OK:
02477 case Z_BUF_ERROR:
02478 if (!d_stream->avail_out) {
02479 break;
02480 }
02481
02482 default:
02483 page_zip_fail(("page_zip_decompress_clust_ext:"
02484 " 2 inflate(Z_SYNC_FLUSH)=%s\n",
02485 d_stream->msg));
02486 return(FALSE);
02487 }
02488
02489 ut_ad(d_stream->next_out == dst);
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502 memset(d_stream->next_out, 0,
02503 BTR_EXTERN_FIELD_REF_SIZE);
02504 d_stream->next_out
02505 += BTR_EXTERN_FIELD_REF_SIZE;
02506 }
02507 }
02508
02509 return(TRUE);
02510 }
02511
02512
02515 static
02516 ibool
02517 page_zip_decompress_clust(
02518
02519 page_zip_des_t* page_zip,
02520 z_stream* d_stream,
02521 rec_t** recs,
02523 ulint n_dense,
02524 dict_index_t* index,
02525 ulint trx_id_col,
02526 ulint* offsets,
02527 mem_heap_t* heap)
02528 {
02529 int err;
02530 ulint slot;
02531 ulint heap_status = REC_STATUS_ORDINARY
02532 | PAGE_HEAP_NO_USER_LOW << REC_HEAP_NO_SHIFT;
02533 const byte* storage;
02534 const byte* externs;
02535
02536 ut_a(dict_index_is_clust(index));
02537
02538
02539 d_stream->avail_in -= n_dense * (PAGE_ZIP_DIR_SLOT_SIZE
02540 + DATA_TRX_ID_LEN
02541 + DATA_ROLL_PTR_LEN);
02542
02543
02544 for (slot = 0; slot < n_dense; slot++) {
02545 rec_t* rec = recs[slot];
02546
02547 d_stream->avail_out = rec - REC_N_NEW_EXTRA_BYTES
02548 - d_stream->next_out;
02549
02550 ut_ad(d_stream->avail_out < UNIV_PAGE_SIZE
02551 - PAGE_ZIP_START - PAGE_DIR);
02552 err = inflate(d_stream, Z_SYNC_FLUSH);
02553 switch (err) {
02554 case Z_STREAM_END:
02555
02556
02557 goto zlib_done;
02558 case Z_OK:
02559 case Z_BUF_ERROR:
02560 if (UNIV_LIKELY(!d_stream->avail_out)) {
02561 break;
02562 }
02563
02564 default:
02565 page_zip_fail(("page_zip_decompress_clust:"
02566 " 1 inflate(Z_SYNC_FLUSH)=%s\n",
02567 d_stream->msg));
02568 goto zlib_error;
02569 }
02570
02571 ut_ad(d_stream->next_out == rec - REC_N_NEW_EXTRA_BYTES);
02572
02573 d_stream->next_out = rec;
02574
02575 mach_write_to_2(rec - REC_NEW_HEAP_NO, heap_status);
02576 heap_status += 1 << REC_HEAP_NO_SHIFT;
02577
02578
02579 offsets = rec_get_offsets(rec, index, offsets,
02580 ULINT_UNDEFINED, &heap);
02581
02582
02583
02584
02585
02586
02587
02588 if (UNIV_UNLIKELY(rec_offs_any_extern(offsets))) {
02589 if (UNIV_UNLIKELY
02590 (!page_zip_decompress_clust_ext(
02591 d_stream, rec, offsets, trx_id_col))) {
02592
02593 goto zlib_error;
02594 }
02595 } else {
02596
02597 ulint len;
02598 byte* dst = rec_get_nth_field(rec, offsets,
02599 trx_id_col, &len);
02600 if (UNIV_UNLIKELY(len < DATA_TRX_ID_LEN
02601 + DATA_ROLL_PTR_LEN)) {
02602
02603 page_zip_fail(("page_zip_decompress_clust:"
02604 " len = %lu\n", (ulong) len));
02605 goto zlib_error;
02606 }
02607
02608 d_stream->avail_out = dst - d_stream->next_out;
02609
02610 switch (inflate(d_stream, Z_SYNC_FLUSH)) {
02611 case Z_STREAM_END:
02612 case Z_OK:
02613 case Z_BUF_ERROR:
02614 if (!d_stream->avail_out) {
02615 break;
02616 }
02617
02618 default:
02619 page_zip_fail(("page_zip_decompress_clust:"
02620 " 2 inflate(Z_SYNC_FLUSH)=%s\n",
02621 d_stream->msg));
02622 goto zlib_error;
02623 }
02624
02625 ut_ad(d_stream->next_out == dst);
02626
02627
02628
02629
02630 memset(dst, 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
02631
02632 d_stream->next_out += DATA_TRX_ID_LEN
02633 + DATA_ROLL_PTR_LEN;
02634 }
02635
02636
02637 d_stream->avail_out = rec_get_end(rec, offsets)
02638 - d_stream->next_out;
02639
02640 switch (inflate(d_stream, Z_SYNC_FLUSH)) {
02641 case Z_STREAM_END:
02642 case Z_OK:
02643 case Z_BUF_ERROR:
02644 if (!d_stream->avail_out) {
02645 break;
02646 }
02647
02648 default:
02649 page_zip_fail(("page_zip_decompress_clust:"
02650 " 3 inflate(Z_SYNC_FLUSH)=%s\n",
02651 d_stream->msg));
02652 goto zlib_error;
02653 }
02654 }
02655
02656
02657
02658 d_stream->avail_out = page_header_get_field(page_zip->data,
02659 PAGE_HEAP_TOP)
02660 - page_offset(d_stream->next_out);
02661 if (UNIV_UNLIKELY(d_stream->avail_out > UNIV_PAGE_SIZE
02662 - PAGE_ZIP_START - PAGE_DIR)) {
02663
02664 page_zip_fail(("page_zip_decompress_clust:"
02665 " avail_out = %u\n",
02666 d_stream->avail_out));
02667 goto zlib_error;
02668 }
02669
02670 if (UNIV_UNLIKELY(inflate(d_stream, Z_FINISH) != Z_STREAM_END)) {
02671 page_zip_fail(("page_zip_decompress_clust:"
02672 " inflate(Z_FINISH)=%s\n",
02673 d_stream->msg));
02674 zlib_error:
02675 inflateEnd(d_stream);
02676 return(FALSE);
02677 }
02678
02679
02680
02681
02682 zlib_done:
02683 if (UNIV_UNLIKELY(inflateEnd(d_stream) != Z_OK)) {
02684 ut_error;
02685 }
02686
02687 {
02688 page_t* page = page_align(d_stream->next_out);
02689
02690
02691 memset(d_stream->next_out, 0,
02692 page_dir_get_nth_slot(page,
02693 page_dir_get_n_slots(page) - 1)
02694 - d_stream->next_out);
02695 }
02696
02697 #ifdef UNIV_DEBUG
02698 page_zip->m_start = PAGE_DATA + d_stream->total_in;
02699 #endif
02700
02701
02702 {
02703 const byte* mod_log_ptr;
02704 mod_log_ptr = page_zip_apply_log(d_stream->next_in,
02705 d_stream->avail_in + 1,
02706 recs, n_dense,
02707 trx_id_col, heap_status,
02708 index, offsets);
02709
02710 if (UNIV_UNLIKELY(!mod_log_ptr)) {
02711 return(FALSE);
02712 }
02713 page_zip->m_end = mod_log_ptr - page_zip->data;
02714 page_zip->m_nonempty = mod_log_ptr != d_stream->next_in;
02715 }
02716
02717 if (UNIV_UNLIKELY(page_zip_get_trailer_len(page_zip, TRUE, NULL)
02718 + page_zip->m_end >= page_zip_get_size(page_zip))) {
02719
02720 page_zip_fail(("page_zip_decompress_clust: %lu + %lu >= %lu\n",
02721 (ulong) page_zip_get_trailer_len(
02722 page_zip, TRUE, NULL),
02723 (ulong) page_zip->m_end,
02724 (ulong) page_zip_get_size(page_zip)));
02725 return(FALSE);
02726 }
02727
02728 storage = page_zip->data + page_zip_get_size(page_zip)
02729 - n_dense * PAGE_ZIP_DIR_SLOT_SIZE;
02730
02731 externs = storage - n_dense
02732 * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
02733
02734
02735
02736 for (slot = 0; slot < n_dense; slot++) {
02737 ulint i;
02738 ulint len;
02739 byte* dst;
02740 rec_t* rec = recs[slot];
02741 ibool exists = !page_zip_dir_find_free(
02742 page_zip, page_offset(rec));
02743 offsets = rec_get_offsets(rec, index, offsets,
02744 ULINT_UNDEFINED, &heap);
02745
02746 dst = rec_get_nth_field(rec, offsets,
02747 trx_id_col, &len);
02748 ut_ad(len >= DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
02749 storage -= DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN;
02750 memcpy(dst, storage,
02751 DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
02752
02753
02754
02755
02756
02757 if (!rec_offs_any_extern(offsets)) {
02758 continue;
02759 }
02760
02761 for (i = 0; i < rec_offs_n_fields(offsets); i++) {
02762 if (!rec_offs_nth_extern(offsets, i)) {
02763 continue;
02764 }
02765 dst = rec_get_nth_field(rec, offsets, i, &len);
02766
02767 if (UNIV_UNLIKELY(len < BTR_EXTERN_FIELD_REF_SIZE)) {
02768 page_zip_fail(("page_zip_decompress_clust:"
02769 " %lu < 20\n",
02770 (ulong) len));
02771 return(FALSE);
02772 }
02773
02774 dst += len - BTR_EXTERN_FIELD_REF_SIZE;
02775
02776 if (UNIV_LIKELY(exists)) {
02777
02778
02779 externs -= BTR_EXTERN_FIELD_REF_SIZE;
02780
02781 if (UNIV_UNLIKELY
02782 (externs < page_zip->data
02783 + page_zip->m_end)) {
02784 page_zip_fail(("page_zip_"
02785 "decompress_clust: "
02786 "%p < %p + %lu\n",
02787 (const void*) externs,
02788 (const void*)
02789 page_zip->data,
02790 (ulong)
02791 page_zip->m_end));
02792 return(FALSE);
02793 }
02794
02795 memcpy(dst, externs,
02796 BTR_EXTERN_FIELD_REF_SIZE);
02797
02798 page_zip->n_blobs++;
02799 } else {
02800
02801
02802 memset(dst, 0,
02803 BTR_EXTERN_FIELD_REF_SIZE);
02804 }
02805 }
02806 }
02807
02808 return(TRUE);
02809 }
02810
02811
02816 UNIV_INTERN
02817 ibool
02818 page_zip_decompress(
02819
02820 page_zip_des_t* page_zip,
02822 page_t* page,
02823 ibool all)
02827 {
02828 z_stream d_stream;
02829 dict_index_t* index = NULL;
02830 rec_t** recs;
02831 ulint n_dense;
02832 ulint trx_id_col = ULINT_UNDEFINED;
02833 mem_heap_t* heap;
02834 ulint* offsets;
02835 #ifndef UNIV_HOTBACKUP
02836 ullint usec = ut_time_us(NULL);
02837 #endif
02838
02839 ut_ad(page_zip_simple_validate(page_zip));
02840 UNIV_MEM_ASSERT_W(page, UNIV_PAGE_SIZE);
02841 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
02842
02843
02844 n_dense = page_dir_get_n_heap(page_zip->data) - PAGE_HEAP_NO_USER_LOW;
02845 if (UNIV_UNLIKELY(n_dense * PAGE_ZIP_DIR_SLOT_SIZE
02846 >= page_zip_get_size(page_zip))) {
02847 page_zip_fail(("page_zip_decompress 1: %lu %lu\n",
02848 (ulong) n_dense,
02849 (ulong) page_zip_get_size(page_zip)));
02850 return(FALSE);
02851 }
02852
02853 heap = mem_heap_create(n_dense * (3 * sizeof *recs) + UNIV_PAGE_SIZE);
02854 recs = static_cast<byte **>(mem_heap_alloc(heap, n_dense * (2 * sizeof *recs)));
02855
02856 if (all) {
02857
02858 memcpy(page, page_zip->data, PAGE_DATA);
02859 } else {
02860
02861 #if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
02862 ut_a(!memcmp(FIL_PAGE_TYPE + page,
02863 FIL_PAGE_TYPE + page_zip->data,
02864 PAGE_HEADER - FIL_PAGE_TYPE));
02865 ut_a(!memcmp(PAGE_HEADER + PAGE_LEVEL + page,
02866 PAGE_HEADER + PAGE_LEVEL + page_zip->data,
02867 PAGE_DATA - (PAGE_HEADER + PAGE_LEVEL)));
02868 #endif
02869
02870
02871 memcpy(page, page_zip->data, FIL_PAGE_TYPE);
02872 memcpy(PAGE_HEADER + page, PAGE_HEADER + page_zip->data,
02873 PAGE_LEVEL - PAGE_N_DIR_SLOTS);
02874
02875 #if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
02876
02877 ut_a(!memcmp(page, page_zip->data, PAGE_DATA));
02878 #endif
02879 }
02880
02881 #ifdef UNIV_ZIP_DEBUG
02882
02883 memset(PAGE_DATA + page, 0x55, UNIV_PAGE_SIZE - PAGE_DATA);
02884 #endif
02885 UNIV_MEM_INVALID(PAGE_DATA + page, UNIV_PAGE_SIZE - PAGE_DATA);
02886
02887
02888 if (UNIV_UNLIKELY(!page_zip_dir_decode(page_zip, page, recs,
02889 recs + n_dense, n_dense))) {
02890 zlib_error:
02891 mem_heap_free(heap);
02892 return(FALSE);
02893 }
02894
02895
02896 memcpy(page + (PAGE_NEW_INFIMUM - REC_N_NEW_EXTRA_BYTES),
02897 infimum_extra, sizeof infimum_extra);
02898 if (UNIV_UNLIKELY(!page_get_n_recs(page))) {
02899 rec_set_next_offs_new(page + PAGE_NEW_INFIMUM,
02900 PAGE_NEW_SUPREMUM);
02901 } else {
02902 rec_set_next_offs_new(page + PAGE_NEW_INFIMUM,
02903 page_zip_dir_get(page_zip, 0)
02904 & PAGE_ZIP_DIR_SLOT_MASK);
02905 }
02906 memcpy(page + PAGE_NEW_INFIMUM, infimum_data, sizeof infimum_data);
02907 memcpy(page + (PAGE_NEW_SUPREMUM - REC_N_NEW_EXTRA_BYTES + 1),
02908 supremum_extra_data, sizeof supremum_extra_data);
02909
02910 page_zip_set_alloc(&d_stream, heap);
02911
02912 if (UNIV_UNLIKELY(inflateInit2(&d_stream, UNIV_PAGE_SIZE_SHIFT)
02913 != Z_OK)) {
02914 ut_error;
02915 }
02916
02917 d_stream.next_in = page_zip->data + PAGE_DATA;
02918
02919
02920 d_stream.avail_in = page_zip_get_size(page_zip) - (PAGE_DATA + 1);
02921
02922 d_stream.next_out = page + PAGE_ZIP_START;
02923 d_stream.avail_out = UNIV_PAGE_SIZE - PAGE_ZIP_START;
02924
02925
02926 if (UNIV_UNLIKELY(inflate(&d_stream, Z_BLOCK) != Z_OK)) {
02927
02928 page_zip_fail(("page_zip_decompress:"
02929 " 1 inflate(Z_BLOCK)=%s\n", d_stream.msg));
02930 goto zlib_error;
02931 }
02932
02933 if (UNIV_UNLIKELY(inflate(&d_stream, Z_BLOCK) != Z_OK)) {
02934
02935 page_zip_fail(("page_zip_decompress:"
02936 " 2 inflate(Z_BLOCK)=%s\n", d_stream.msg));
02937 goto zlib_error;
02938 }
02939
02940 index = page_zip_fields_decode(
02941 page + PAGE_ZIP_START, d_stream.next_out,
02942 page_is_leaf(page) ? &trx_id_col : NULL);
02943
02944 if (UNIV_UNLIKELY(!index)) {
02945
02946 goto zlib_error;
02947 }
02948
02949
02950 page_zip->n_blobs = 0;
02951 d_stream.next_out = page + PAGE_ZIP_START;
02952
02953 {
02954
02955 ulint n = 1 + 1 + REC_OFFS_HEADER_SIZE
02956 + dict_index_get_n_fields(index);
02957 offsets = static_cast<unsigned long *>(mem_heap_alloc(heap, n * sizeof(ulint)));
02958 *offsets = n;
02959 }
02960
02961
02962 if (!page_is_leaf(page)) {
02963
02964 ulint info_bits;
02965
02966 if (UNIV_UNLIKELY
02967 (!page_zip_decompress_node_ptrs(page_zip, &d_stream,
02968 recs, n_dense, index,
02969 offsets, heap))) {
02970 goto err_exit;
02971 }
02972
02973 info_bits = mach_read_from_4(page + FIL_PAGE_PREV) == FIL_NULL
02974 ? REC_INFO_MIN_REC_FLAG : 0;
02975
02976 if (UNIV_UNLIKELY(!page_zip_set_extra_bytes(page_zip, page,
02977 info_bits))) {
02978 goto err_exit;
02979 }
02980 } else if (UNIV_LIKELY(trx_id_col == ULINT_UNDEFINED)) {
02981
02982 if (UNIV_UNLIKELY(!page_zip_decompress_sec(page_zip, &d_stream,
02983 recs, n_dense,
02984 index, offsets))) {
02985 goto err_exit;
02986 }
02987
02988 if (UNIV_UNLIKELY(!page_zip_set_extra_bytes(page_zip,
02989 page, 0))) {
02990 err_exit:
02991 page_zip_fields_free(index);
02992 mem_heap_free(heap);
02993 return(FALSE);
02994 }
02995 } else {
02996
02997 if (UNIV_UNLIKELY(!page_zip_decompress_clust(page_zip,
02998 &d_stream, recs,
02999 n_dense, index,
03000 trx_id_col,
03001 offsets, heap))) {
03002 goto err_exit;
03003 }
03004
03005 if (UNIV_UNLIKELY(!page_zip_set_extra_bytes(page_zip,
03006 page, 0))) {
03007 goto err_exit;
03008 }
03009 }
03010
03011 ut_a(page_is_comp(page));
03012 UNIV_MEM_ASSERT_RW(page, UNIV_PAGE_SIZE);
03013
03014 page_zip_fields_free(index);
03015 mem_heap_free(heap);
03016 #ifndef UNIV_HOTBACKUP
03017 {
03018 page_zip_stat_t* zip_stat
03019 = &page_zip_stat[page_zip->ssize - 1];
03020 zip_stat->decompressed++;
03021 zip_stat->decompressed_usec += ut_time_us(NULL) - usec;
03022 }
03023 #endif
03024
03025
03026 buf_LRU_stat_inc_unzip();
03027
03028 return(TRUE);
03029 }
03030
03031 #ifdef UNIV_ZIP_DEBUG
03032
03034 static
03035 void
03036 page_zip_hexdump_func(
03037
03038 const char* name,
03039 const void* buf,
03040 ulint size)
03041 {
03042 const byte* s = buf;
03043 ulint addr;
03044 const ulint width = 32;
03045
03046 fprintf(stderr, "%s:\n", name);
03047
03048 for (addr = 0; addr < size; addr += width) {
03049 ulint i;
03050
03051 fprintf(stderr, "%04lx ", (ulong) addr);
03052
03053 i = ut_min(width, size - addr);
03054
03055 while (i--) {
03056 fprintf(stderr, "%02x", *s++);
03057 }
03058
03059 putc('\n', stderr);
03060 }
03061 }
03062
03066 #define page_zip_hexdump(buf, size) page_zip_hexdump_func(#buf, buf, size)
03067
03069 UNIV_INTERN ibool page_zip_validate_header_only = FALSE;
03070
03071
03074 UNIV_INTERN
03075 ibool
03076 page_zip_validate_low(
03077
03078 const page_zip_des_t* page_zip,
03079 const page_t* page,
03080 ibool sloppy)
03082 {
03083 page_zip_des_t temp_page_zip;
03084 byte* temp_page_buf;
03085 page_t* temp_page;
03086 ibool valid;
03087
03088 if (memcmp(page_zip->data + FIL_PAGE_PREV, page + FIL_PAGE_PREV,
03089 FIL_PAGE_LSN - FIL_PAGE_PREV)
03090 || memcmp(page_zip->data + FIL_PAGE_TYPE, page + FIL_PAGE_TYPE, 2)
03091 || memcmp(page_zip->data + FIL_PAGE_DATA, page + FIL_PAGE_DATA,
03092 PAGE_DATA - FIL_PAGE_DATA)) {
03093 page_zip_fail(("page_zip_validate: page header\n"));
03094 page_zip_hexdump(page_zip, sizeof *page_zip);
03095 page_zip_hexdump(page_zip->data, page_zip_get_size(page_zip));
03096 page_zip_hexdump(page, UNIV_PAGE_SIZE);
03097 return(FALSE);
03098 }
03099
03100 ut_a(page_is_comp(page));
03101
03102 if (page_zip_validate_header_only) {
03103 return(TRUE);
03104 }
03105
03106
03107
03108 temp_page_buf = ut_malloc(2 * UNIV_PAGE_SIZE);
03109 temp_page = ut_align(temp_page_buf, UNIV_PAGE_SIZE);
03110
03111 #ifdef UNIV_DEBUG_VALGRIND
03112
03113
03114
03115
03116 VALGRIND_GET_VBITS(page, temp_page, UNIV_PAGE_SIZE);
03117 UNIV_MEM_ASSERT_RW(page, UNIV_PAGE_SIZE);
03118 # if UNIV_WORD_SIZE == 4
03119 VALGRIND_GET_VBITS(page_zip, &temp_page_zip, sizeof temp_page_zip);
03120
03121
03122
03123 UNIV_MEM_ASSERT_RW(page_zip, sizeof *page_zip);
03124 # endif
03125 VALGRIND_GET_VBITS(page_zip->data, temp_page,
03126 page_zip_get_size(page_zip));
03127 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
03128 #endif
03129
03130 temp_page_zip = *page_zip;
03131 valid = page_zip_decompress(&temp_page_zip, temp_page, TRUE);
03132 if (!valid) {
03133 fputs("page_zip_validate(): failed to decompress\n", stderr);
03134 goto func_exit;
03135 }
03136 if (page_zip->n_blobs != temp_page_zip.n_blobs) {
03137 page_zip_fail(("page_zip_validate: n_blobs: %u!=%u\n",
03138 page_zip->n_blobs, temp_page_zip.n_blobs));
03139 valid = FALSE;
03140 }
03141 #ifdef UNIV_DEBUG
03142 if (page_zip->m_start != temp_page_zip.m_start) {
03143 page_zip_fail(("page_zip_validate: m_start: %u!=%u\n",
03144 page_zip->m_start, temp_page_zip.m_start));
03145 valid = FALSE;
03146 }
03147 #endif
03148 if (page_zip->m_end != temp_page_zip.m_end) {
03149 page_zip_fail(("page_zip_validate: m_end: %u!=%u\n",
03150 page_zip->m_end, temp_page_zip.m_end));
03151 valid = FALSE;
03152 }
03153 if (page_zip->m_nonempty != temp_page_zip.m_nonempty) {
03154 page_zip_fail(("page_zip_validate(): m_nonempty: %u!=%u\n",
03155 page_zip->m_nonempty,
03156 temp_page_zip.m_nonempty));
03157 valid = FALSE;
03158 }
03159 if (memcmp(page + PAGE_HEADER, temp_page + PAGE_HEADER,
03160 UNIV_PAGE_SIZE - PAGE_HEADER - FIL_PAGE_DATA_END)) {
03161
03162
03163
03164
03165
03166
03167 if (sloppy) {
03168 byte info_bits_diff;
03169 ulint offset
03170 = rec_get_next_offs(page + PAGE_NEW_INFIMUM,
03171 TRUE);
03172 ut_a(offset >= PAGE_NEW_SUPREMUM);
03173 offset -= 5 ;
03174
03175 info_bits_diff = page[offset] ^ temp_page[offset];
03176
03177 if (info_bits_diff == REC_INFO_MIN_REC_FLAG) {
03178 temp_page[offset] = page[offset];
03179
03180 if (!memcmp(page + PAGE_HEADER,
03181 temp_page + PAGE_HEADER,
03182 UNIV_PAGE_SIZE - PAGE_HEADER
03183 - FIL_PAGE_DATA_END)) {
03184
03185
03186
03187 page_zip_fail(("page_zip_validate: "
03188 "min_rec_flag "
03189 "(ignored, "
03190 "%lu,%lu,0x%02lx)\n",
03191 page_get_space_id(page),
03192 page_get_page_no(page),
03193 (ulong) page[offset]));
03194 goto func_exit;
03195 }
03196 }
03197 }
03198 page_zip_fail(("page_zip_validate: content\n"));
03199 valid = FALSE;
03200 }
03201
03202 func_exit:
03203 if (!valid) {
03204 page_zip_hexdump(page_zip, sizeof *page_zip);
03205 page_zip_hexdump(page_zip->data, page_zip_get_size(page_zip));
03206 page_zip_hexdump(page, UNIV_PAGE_SIZE);
03207 page_zip_hexdump(temp_page, UNIV_PAGE_SIZE);
03208 }
03209 ut_free(temp_page_buf);
03210 return(valid);
03211 }
03212
03213
03216 UNIV_INTERN
03217 ibool
03218 page_zip_validate(
03219
03220 const page_zip_des_t* page_zip,
03221 const page_t* page)
03222 {
03223 return(page_zip_validate_low(page_zip, page,
03224 recv_recovery_is_on()));
03225 }
03226 #endif
03227
03228 #ifdef UNIV_DEBUG
03229
03232 static
03233 ibool
03234 page_zip_header_cmp(
03235
03236 const page_zip_des_t* page_zip,
03237 const byte* page)
03238 {
03239 ut_ad(!memcmp(page_zip->data + FIL_PAGE_PREV, page + FIL_PAGE_PREV,
03240 FIL_PAGE_LSN - FIL_PAGE_PREV));
03241 ut_ad(!memcmp(page_zip->data + FIL_PAGE_TYPE, page + FIL_PAGE_TYPE,
03242 2));
03243 ut_ad(!memcmp(page_zip->data + FIL_PAGE_DATA, page + FIL_PAGE_DATA,
03244 PAGE_DATA - FIL_PAGE_DATA));
03245
03246 return(TRUE);
03247 }
03248 #endif
03249
03250
03254 static
03255 byte*
03256 page_zip_write_rec_ext(
03257
03258 page_zip_des_t* page_zip,
03259 const page_t* page,
03260 const byte* rec,
03261 dict_index_t* index,
03262 const ulint* offsets,
03263 ulint create,
03264 ulint trx_id_col,
03265 ulint heap_no,
03266 byte* storage,
03267 byte* data)
03268 {
03269 const byte* start = rec;
03270 ulint i;
03271 ulint len;
03272 byte* externs = storage;
03273 ulint n_ext = rec_offs_n_extern(offsets);
03274
03275 ut_ad(rec_offs_validate(rec, index, offsets));
03276 UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets));
03277 UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
03278 rec_offs_extra_size(offsets));
03279
03280 externs -= (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN)
03281 * (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW);
03282
03283
03284
03285 ut_ad(data + rec_offs_data_size(offsets)
03286 - (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN)
03287 - n_ext * BTR_EXTERN_FIELD_REF_SIZE
03288 < externs - BTR_EXTERN_FIELD_REF_SIZE * page_zip->n_blobs);
03289
03290 {
03291 ulint blob_no = page_zip_get_n_prev_extern(
03292 page_zip, rec, index);
03293 byte* ext_end = externs - page_zip->n_blobs
03294 * BTR_EXTERN_FIELD_REF_SIZE;
03295 ut_ad(blob_no <= page_zip->n_blobs);
03296 externs -= blob_no * BTR_EXTERN_FIELD_REF_SIZE;
03297
03298 if (create) {
03299 page_zip->n_blobs += n_ext;
03300 ASSERT_ZERO_BLOB(ext_end - n_ext
03301 * BTR_EXTERN_FIELD_REF_SIZE);
03302 memmove(ext_end - n_ext
03303 * BTR_EXTERN_FIELD_REF_SIZE,
03304 ext_end,
03305 externs - ext_end);
03306 }
03307
03308 ut_a(blob_no + n_ext <= page_zip->n_blobs);
03309 }
03310
03311 for (i = 0; i < rec_offs_n_fields(offsets); i++) {
03312 const byte* src;
03313
03314 if (UNIV_UNLIKELY(i == trx_id_col)) {
03315 ut_ad(!rec_offs_nth_extern(offsets,
03316 i));
03317 ut_ad(!rec_offs_nth_extern(offsets,
03318 i + 1));
03319
03320 src = rec_get_nth_field(rec, offsets,
03321 i, &len);
03322 ut_ad(len == DATA_TRX_ID_LEN);
03323 ut_ad(src + DATA_TRX_ID_LEN
03324 == rec_get_nth_field(
03325 rec, offsets,
03326 i + 1, &len));
03327 ut_ad(len == DATA_ROLL_PTR_LEN);
03328
03329
03330 ASSERT_ZERO(data, src - start);
03331 memcpy(data, start, src - start);
03332 data += src - start;
03333 start = src + (DATA_TRX_ID_LEN
03334 + DATA_ROLL_PTR_LEN);
03335
03336
03337 memcpy(storage - (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN)
03338 * (heap_no - 1),
03339 src, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
03340 i++;
03341 } else if (rec_offs_nth_extern(offsets, i)) {
03342 src = rec_get_nth_field(rec, offsets,
03343 i, &len);
03344
03345 ut_ad(dict_index_is_clust(index));
03346 ut_ad(len
03347 >= BTR_EXTERN_FIELD_REF_SIZE);
03348 src += len - BTR_EXTERN_FIELD_REF_SIZE;
03349
03350 ASSERT_ZERO(data, src - start);
03351 memcpy(data, start, src - start);
03352 data += src - start;
03353 start = src + BTR_EXTERN_FIELD_REF_SIZE;
03354
03355
03356 externs -= BTR_EXTERN_FIELD_REF_SIZE;
03357 ut_ad(data < externs);
03358 memcpy(externs, src, BTR_EXTERN_FIELD_REF_SIZE);
03359 }
03360 }
03361
03362
03363 len = rec_offs_data_size(offsets) - (start - rec);
03364
03365 ASSERT_ZERO(data, len);
03366 memcpy(data, start, len);
03367 data += len;
03368
03369 return(data);
03370 }
03371
03372
03375 UNIV_INTERN
03376 void
03377 page_zip_write_rec(
03378
03379 page_zip_des_t* page_zip,
03380 const byte* rec,
03381 dict_index_t* index,
03382 const ulint* offsets,
03383 ulint create)
03384 {
03385 const page_t* page;
03386 byte* data;
03387 byte* storage;
03388 ulint heap_no;
03389 byte* slot;
03390
03391 ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
03392 ut_ad(page_zip_simple_validate(page_zip));
03393 ut_ad(page_zip_get_size(page_zip)
03394 > PAGE_DATA + page_zip_dir_size(page_zip));
03395 ut_ad(rec_offs_comp(offsets));
03396 ut_ad(rec_offs_validate(rec, index, offsets));
03397
03398 ut_ad(page_zip->m_start >= PAGE_DATA);
03399
03400 page = page_align(rec);
03401
03402 ut_ad(page_zip_header_cmp(page_zip, page));
03403 ut_ad(page_simple_validate_new((page_t*) page));
03404
03405 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
03406 UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets));
03407 UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
03408 rec_offs_extra_size(offsets));
03409
03410 slot = page_zip_dir_find(page_zip, page_offset(rec));
03411 ut_a(slot);
03412
03413 if (rec_get_deleted_flag(rec, TRUE)) {
03414 *slot |= PAGE_ZIP_DIR_SLOT_DEL >> 8;
03415 } else {
03416 *slot &= ~(PAGE_ZIP_DIR_SLOT_DEL >> 8);
03417 }
03418
03419 ut_ad(rec_get_start((rec_t*) rec, offsets) >= page + PAGE_ZIP_START);
03420 ut_ad(rec_get_end((rec_t*) rec, offsets) <= page + UNIV_PAGE_SIZE
03421 - PAGE_DIR - PAGE_DIR_SLOT_SIZE
03422 * page_dir_get_n_slots(page));
03423
03424 heap_no = rec_get_heap_no_new(rec);
03425 ut_ad(heap_no >= PAGE_HEAP_NO_USER_LOW);
03426 ut_ad(heap_no < page_dir_get_n_heap(page));
03427
03428
03429 data = page_zip->data + page_zip->m_end;
03430 ut_ad(!*data);
03431
03432
03433
03434
03435 if (UNIV_UNLIKELY(heap_no - 1 >= 64)) {
03436 *data++ = (byte) (0x80 | (heap_no - 1) >> 7);
03437 ut_ad(!*data);
03438 }
03439 *data++ = (byte) ((heap_no - 1) << 1);
03440 ut_ad(!*data);
03441
03442 {
03443 const byte* start = rec - rec_offs_extra_size(offsets);
03444 const byte* b = rec - REC_N_NEW_EXTRA_BYTES;
03445
03446
03447
03448
03449
03450
03451 while (b != start) {
03452 *data++ = *--b;
03453 ut_ad(!*data);
03454 }
03455 }
03456
03457
03458 storage = page_zip->data + page_zip_get_size(page_zip)
03459 - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
03460 * PAGE_ZIP_DIR_SLOT_SIZE;
03461
03462 if (page_is_leaf(page)) {
03463 ulint len;
03464
03465 if (dict_index_is_clust(index)) {
03466 ulint trx_id_col;
03467
03468 trx_id_col = dict_index_get_sys_col_pos(index,
03469 DATA_TRX_ID);
03470 ut_ad(trx_id_col != ULINT_UNDEFINED);
03471
03472
03473
03474 if (rec_offs_any_extern(offsets)) {
03475 data = page_zip_write_rec_ext(
03476 page_zip, page,
03477 rec, index, offsets, create,
03478 trx_id_col, heap_no, storage, data);
03479 } else {
03480
03481 const byte* src
03482 = rec_get_nth_field(rec, offsets,
03483 trx_id_col, &len);
03484 ut_ad(len == DATA_TRX_ID_LEN);
03485 ut_ad(src + DATA_TRX_ID_LEN
03486 == rec_get_nth_field(
03487 rec, offsets,
03488 trx_id_col + 1, &len));
03489 ut_ad(len == DATA_ROLL_PTR_LEN);
03490
03491
03492 ASSERT_ZERO(data, src - rec);
03493 memcpy(data, rec, src - rec);
03494 data += src - rec;
03495
03496
03497 memcpy(storage
03498 - (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN)
03499 * (heap_no - 1),
03500 src,
03501 DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
03502
03503 src += DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN;
03504
03505
03506 len = rec_offs_data_size(offsets)
03507 - (src - rec);
03508
03509 ASSERT_ZERO(data, len);
03510 memcpy(data, src, len);
03511 data += len;
03512 }
03513 } else {
03514
03515
03516 ut_ad(dict_index_get_sys_col_pos(index, DATA_TRX_ID)
03517 == ULINT_UNDEFINED);
03518 ut_ad(!rec_offs_any_extern(offsets));
03519
03520
03521 len = rec_offs_data_size(offsets);
03522
03523 ASSERT_ZERO(data, len);
03524 memcpy(data, rec, len);
03525 data += len;
03526 }
03527 } else {
03528
03529 ulint len;
03530
03531
03532
03533 ut_ad(!rec_offs_any_extern(offsets));
03534
03535
03536 len = rec_offs_data_size(offsets) - REC_NODE_PTR_SIZE;
03537 ut_ad(data + len < storage - REC_NODE_PTR_SIZE
03538 * (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW));
03539 ASSERT_ZERO(data, len);
03540 memcpy(data, rec, len);
03541 data += len;
03542
03543
03544 memcpy(storage - REC_NODE_PTR_SIZE
03545 * (heap_no - 1),
03546 rec + len,
03547 REC_NODE_PTR_SIZE);
03548 }
03549
03550 ut_a(!*data);
03551 ut_ad((ulint) (data - page_zip->data) < page_zip_get_size(page_zip));
03552 page_zip->m_end = data - page_zip->data;
03553 page_zip->m_nonempty = TRUE;
03554
03555 #ifdef UNIV_ZIP_DEBUG
03556 ut_a(page_zip_validate(page_zip, page_align(rec)));
03557 #endif
03558 }
03559
03560
03563 UNIV_INTERN
03564 byte*
03565 page_zip_parse_write_blob_ptr(
03566
03567 byte* ptr,
03568 byte* end_ptr,
03569 page_t* page,
03570 page_zip_des_t* page_zip)
03571 {
03572 ulint offset;
03573 ulint z_offset;
03574
03575 ut_ad(!page == !page_zip);
03576
03577 if (UNIV_UNLIKELY
03578 (end_ptr < ptr + (2 + 2 + BTR_EXTERN_FIELD_REF_SIZE))) {
03579
03580 return(NULL);
03581 }
03582
03583 offset = mach_read_from_2(ptr);
03584 z_offset = mach_read_from_2(ptr + 2);
03585
03586 if (UNIV_UNLIKELY(offset < PAGE_ZIP_START)
03587 || UNIV_UNLIKELY(offset >= UNIV_PAGE_SIZE)
03588 || UNIV_UNLIKELY(z_offset >= UNIV_PAGE_SIZE)) {
03589 corrupt:
03590 recv_sys->found_corrupt_log = TRUE;
03591
03592 return(NULL);
03593 }
03594
03595 if (page) {
03596 if (UNIV_UNLIKELY(!page_zip)
03597 || UNIV_UNLIKELY(!page_is_leaf(page))) {
03598
03599 goto corrupt;
03600 }
03601
03602 #ifdef UNIV_ZIP_DEBUG
03603 ut_a(page_zip_validate(page_zip, page));
03604 #endif
03605
03606 memcpy(page + offset,
03607 ptr + 4, BTR_EXTERN_FIELD_REF_SIZE);
03608 memcpy(page_zip->data + z_offset,
03609 ptr + 4, BTR_EXTERN_FIELD_REF_SIZE);
03610
03611 #ifdef UNIV_ZIP_DEBUG
03612 ut_a(page_zip_validate(page_zip, page));
03613 #endif
03614 }
03615
03616 return(ptr + (2 + 2 + BTR_EXTERN_FIELD_REF_SIZE));
03617 }
03618
03619
03622 UNIV_INTERN
03623 void
03624 page_zip_write_blob_ptr(
03625
03626 page_zip_des_t* page_zip,
03627 const byte* rec,
03629 dict_index_t* index,
03630 const ulint* offsets,
03631 ulint n,
03632 mtr_t* mtr)
03634 {
03635 const byte* field;
03636 byte* externs;
03637 const page_t* page = page_align(rec);
03638 ulint blob_no;
03639 ulint len;
03640
03641 ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
03642 ut_ad(page_simple_validate_new((page_t*) page));
03643 ut_ad(page_zip_simple_validate(page_zip));
03644 ut_ad(page_zip_get_size(page_zip)
03645 > PAGE_DATA + page_zip_dir_size(page_zip));
03646 ut_ad(rec_offs_comp(offsets));
03647 ut_ad(rec_offs_validate(rec, NULL, offsets));
03648 ut_ad(rec_offs_any_extern(offsets));
03649 ut_ad(rec_offs_nth_extern(offsets, n));
03650
03651 ut_ad(page_zip->m_start >= PAGE_DATA);
03652 ut_ad(page_zip_header_cmp(page_zip, page));
03653
03654 ut_ad(page_is_leaf(page));
03655 ut_ad(dict_index_is_clust(index));
03656
03657 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
03658 UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets));
03659 UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
03660 rec_offs_extra_size(offsets));
03661
03662 blob_no = page_zip_get_n_prev_extern(page_zip, rec, index)
03663 + rec_get_n_extern_new(rec, index, n);
03664 ut_a(blob_no < page_zip->n_blobs);
03665
03666 externs = page_zip->data + page_zip_get_size(page_zip)
03667 - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
03668 * (PAGE_ZIP_DIR_SLOT_SIZE
03669 + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
03670
03671 field = rec_get_nth_field(rec, offsets, n, &len);
03672
03673 externs -= (blob_no + 1) * BTR_EXTERN_FIELD_REF_SIZE;
03674 field += len - BTR_EXTERN_FIELD_REF_SIZE;
03675
03676 memcpy(externs, field, BTR_EXTERN_FIELD_REF_SIZE);
03677
03678 #ifdef UNIV_ZIP_DEBUG
03679 ut_a(page_zip_validate(page_zip, page));
03680 #endif
03681
03682 if (mtr) {
03683 #ifndef UNIV_HOTBACKUP
03684 byte* log_ptr = mlog_open(
03685 mtr, 11 + 2 + 2 + BTR_EXTERN_FIELD_REF_SIZE);
03686 if (UNIV_UNLIKELY(!log_ptr)) {
03687 return;
03688 }
03689
03690 log_ptr = mlog_write_initial_log_record_fast(
03691 (byte*) field, MLOG_ZIP_WRITE_BLOB_PTR, log_ptr, mtr);
03692 mach_write_to_2(log_ptr, page_offset(field));
03693 log_ptr += 2;
03694 mach_write_to_2(log_ptr, externs - page_zip->data);
03695 log_ptr += 2;
03696 memcpy(log_ptr, externs, BTR_EXTERN_FIELD_REF_SIZE);
03697 log_ptr += BTR_EXTERN_FIELD_REF_SIZE;
03698 mlog_close(mtr, log_ptr);
03699 #endif
03700 }
03701 }
03702
03703
03706 UNIV_INTERN
03707 byte*
03708 page_zip_parse_write_node_ptr(
03709
03710 byte* ptr,
03711 byte* end_ptr,
03712 page_t* page,
03713 page_zip_des_t* page_zip)
03714 {
03715 ulint offset;
03716 ulint z_offset;
03717
03718 ut_ad(!page == !page_zip);
03719
03720 if (UNIV_UNLIKELY(end_ptr < ptr + (2 + 2 + REC_NODE_PTR_SIZE))) {
03721
03722 return(NULL);
03723 }
03724
03725 offset = mach_read_from_2(ptr);
03726 z_offset = mach_read_from_2(ptr + 2);
03727
03728 if (UNIV_UNLIKELY(offset < PAGE_ZIP_START)
03729 || UNIV_UNLIKELY(offset >= UNIV_PAGE_SIZE)
03730 || UNIV_UNLIKELY(z_offset >= UNIV_PAGE_SIZE)) {
03731 corrupt:
03732 recv_sys->found_corrupt_log = TRUE;
03733
03734 return(NULL);
03735 }
03736
03737 if (page) {
03738 byte* storage_end;
03739 byte* field;
03740 byte* storage;
03741 ulint heap_no;
03742
03743 if (UNIV_UNLIKELY(!page_zip)
03744 || UNIV_UNLIKELY(page_is_leaf(page))) {
03745
03746 goto corrupt;
03747 }
03748
03749 #ifdef UNIV_ZIP_DEBUG
03750 ut_a(page_zip_validate(page_zip, page));
03751 #endif
03752
03753 field = page + offset;
03754 storage = page_zip->data + z_offset;
03755
03756 storage_end = page_zip->data + page_zip_get_size(page_zip)
03757 - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
03758 * PAGE_ZIP_DIR_SLOT_SIZE;
03759
03760 heap_no = 1 + (storage_end - storage) / REC_NODE_PTR_SIZE;
03761
03762 if (UNIV_UNLIKELY((storage_end - storage) % REC_NODE_PTR_SIZE)
03763 || UNIV_UNLIKELY(heap_no < PAGE_HEAP_NO_USER_LOW)
03764 || UNIV_UNLIKELY(heap_no >= page_dir_get_n_heap(page))) {
03765
03766 goto corrupt;
03767 }
03768
03769 memcpy(field, ptr + 4, REC_NODE_PTR_SIZE);
03770 memcpy(storage, ptr + 4, REC_NODE_PTR_SIZE);
03771
03772 #ifdef UNIV_ZIP_DEBUG
03773 ut_a(page_zip_validate(page_zip, page));
03774 #endif
03775 }
03776
03777 return(ptr + (2 + 2 + REC_NODE_PTR_SIZE));
03778 }
03779
03780
03782 UNIV_INTERN
03783 void
03784 page_zip_write_node_ptr(
03785
03786 page_zip_des_t* page_zip,
03787 byte* rec,
03788 ulint size,
03789 ulint ptr,
03790 mtr_t* mtr)
03791 {
03792 byte* field;
03793 byte* storage;
03794 page_t* page = page_align(rec);
03795
03796 ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
03797 ut_ad(page_simple_validate_new(page));
03798 ut_ad(page_zip_simple_validate(page_zip));
03799 ut_ad(page_zip_get_size(page_zip)
03800 > PAGE_DATA + page_zip_dir_size(page_zip));
03801 ut_ad(page_rec_is_comp(rec));
03802
03803 ut_ad(page_zip->m_start >= PAGE_DATA);
03804 ut_ad(page_zip_header_cmp(page_zip, page));
03805
03806 ut_ad(!page_is_leaf(page));
03807
03808 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
03809 UNIV_MEM_ASSERT_RW(rec, size);
03810
03811 storage = page_zip->data + page_zip_get_size(page_zip)
03812 - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
03813 * PAGE_ZIP_DIR_SLOT_SIZE
03814 - (rec_get_heap_no_new(rec) - 1) * REC_NODE_PTR_SIZE;
03815 field = rec + size - REC_NODE_PTR_SIZE;
03816
03817 #if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
03818 ut_a(!memcmp(storage, field, REC_NODE_PTR_SIZE));
03819 #endif
03820 #if REC_NODE_PTR_SIZE != 4
03821 # error "REC_NODE_PTR_SIZE != 4"
03822 #endif
03823 mach_write_to_4(field, ptr);
03824 memcpy(storage, field, REC_NODE_PTR_SIZE);
03825
03826 if (mtr) {
03827 #ifndef UNIV_HOTBACKUP
03828 byte* log_ptr = mlog_open(mtr,
03829 11 + 2 + 2 + REC_NODE_PTR_SIZE);
03830 if (UNIV_UNLIKELY(!log_ptr)) {
03831 return;
03832 }
03833
03834 log_ptr = mlog_write_initial_log_record_fast(
03835 field, MLOG_ZIP_WRITE_NODE_PTR, log_ptr, mtr);
03836 mach_write_to_2(log_ptr, page_offset(field));
03837 log_ptr += 2;
03838 mach_write_to_2(log_ptr, storage - page_zip->data);
03839 log_ptr += 2;
03840 memcpy(log_ptr, field, REC_NODE_PTR_SIZE);
03841 log_ptr += REC_NODE_PTR_SIZE;
03842 mlog_close(mtr, log_ptr);
03843 #endif
03844 }
03845 }
03846
03847
03849 UNIV_INTERN
03850 void
03851 page_zip_write_trx_id_and_roll_ptr(
03852
03853 page_zip_des_t* page_zip,
03854 byte* rec,
03855 const ulint* offsets,
03856 ulint trx_id_col,
03857 trx_id_t trx_id,
03858 roll_ptr_t roll_ptr)
03859 {
03860 byte* field;
03861 byte* storage;
03862 page_t* page = page_align(rec);
03863 ulint len;
03864
03865 ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
03866 ut_ad(page_simple_validate_new(page));
03867 ut_ad(page_zip_simple_validate(page_zip));
03868 ut_ad(page_zip_get_size(page_zip)
03869 > PAGE_DATA + page_zip_dir_size(page_zip));
03870 ut_ad(rec_offs_validate(rec, NULL, offsets));
03871 ut_ad(rec_offs_comp(offsets));
03872
03873 ut_ad(page_zip->m_start >= PAGE_DATA);
03874 ut_ad(page_zip_header_cmp(page_zip, page));
03875
03876 ut_ad(page_is_leaf(page));
03877
03878 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
03879
03880 storage = page_zip->data + page_zip_get_size(page_zip)
03881 - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
03882 * PAGE_ZIP_DIR_SLOT_SIZE
03883 - (rec_get_heap_no_new(rec) - 1)
03884 * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
03885
03886 #if DATA_TRX_ID + 1 != DATA_ROLL_PTR
03887 # error "DATA_TRX_ID + 1 != DATA_ROLL_PTR"
03888 #endif
03889 field = rec_get_nth_field(rec, offsets, trx_id_col, &len);
03890 ut_ad(len == DATA_TRX_ID_LEN);
03891 ut_ad(field + DATA_TRX_ID_LEN
03892 == rec_get_nth_field(rec, offsets, trx_id_col + 1, &len));
03893 ut_ad(len == DATA_ROLL_PTR_LEN);
03894 #if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
03895 ut_a(!memcmp(storage, field, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN));
03896 #endif
03897 #if DATA_TRX_ID_LEN != 6
03898 # error "DATA_TRX_ID_LEN != 6"
03899 #endif
03900 mach_write_to_6(field, trx_id);
03901 #if DATA_ROLL_PTR_LEN != 7
03902 # error "DATA_ROLL_PTR_LEN != 7"
03903 #endif
03904 mach_write_to_7(field + DATA_TRX_ID_LEN, roll_ptr);
03905 memcpy(storage, field, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
03906
03907 UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets));
03908 UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
03909 rec_offs_extra_size(offsets));
03910 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
03911 }
03912
03913 #ifdef UNIV_ZIP_DEBUG
03914
03919 UNIV_INTERN ibool page_zip_clear_rec_disable;
03920 #endif
03921
03922
03924 static
03925 void
03926 page_zip_clear_rec(
03927
03928 page_zip_des_t* page_zip,
03929 byte* rec,
03930 dict_index_t* index,
03931 const ulint* offsets)
03932 {
03933 ulint heap_no;
03934 page_t* page = page_align(rec);
03935
03936
03937 ut_ad(rec_offs_validate(rec, index, offsets));
03938 ut_ad(!page_zip_dir_find(page_zip, page_offset(rec)));
03939 ut_ad(page_zip_dir_find_free(page_zip, page_offset(rec)));
03940 ut_ad(page_zip_header_cmp(page_zip, page));
03941
03942 heap_no = rec_get_heap_no_new(rec);
03943 ut_ad(heap_no >= PAGE_HEAP_NO_USER_LOW);
03944
03945 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
03946 UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets));
03947 UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
03948 rec_offs_extra_size(offsets));
03949
03950 if (
03951 #ifdef UNIV_ZIP_DEBUG
03952 !page_zip_clear_rec_disable &&
03953 #endif
03954 page_zip->m_end
03955 + 1 + ((heap_no - 1) >= 64)
03956 + page_zip_get_trailer_len(page_zip,
03957 dict_index_is_clust(index), NULL)
03958 < page_zip_get_size(page_zip)) {
03959 byte* data;
03960
03961
03962
03963 memset(rec, 0, rec_offs_data_size(offsets));
03964
03965 if (!page_is_leaf(page)) {
03966
03967 byte* storage = page_zip->data
03968 + page_zip_get_size(page_zip)
03969 - (page_dir_get_n_heap(page)
03970 - PAGE_HEAP_NO_USER_LOW)
03971 * PAGE_ZIP_DIR_SLOT_SIZE;
03972
03973 memset(storage - (heap_no - 1) * REC_NODE_PTR_SIZE,
03974 0, REC_NODE_PTR_SIZE);
03975 } else if (dict_index_is_clust(index)) {
03976
03977 byte* storage = page_zip->data
03978 + page_zip_get_size(page_zip)
03979 - (page_dir_get_n_heap(page)
03980 - PAGE_HEAP_NO_USER_LOW)
03981 * PAGE_ZIP_DIR_SLOT_SIZE;
03982
03983 memset(storage - (heap_no - 1)
03984 * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN),
03985 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
03986 }
03987
03988
03989 data = page_zip->data + page_zip->m_end;
03990 ut_ad(!*data);
03991 if (UNIV_UNLIKELY(heap_no - 1 >= 64)) {
03992 *data++ = (byte) (0x80 | (heap_no - 1) >> 7);
03993 ut_ad(!*data);
03994 }
03995 *data++ = (byte) ((heap_no - 1) << 1 | 1);
03996 ut_ad(!*data);
03997 ut_ad((ulint) (data - page_zip->data)
03998 < page_zip_get_size(page_zip));
03999 page_zip->m_end = data - page_zip->data;
04000 page_zip->m_nonempty = TRUE;
04001 } else if (page_is_leaf(page) && dict_index_is_clust(index)) {
04002
04003
04004
04005 if (rec_offs_any_extern(offsets)) {
04006 ulint i;
04007
04008 for (i = rec_offs_n_fields(offsets); i--; ) {
04009
04010
04011 if (rec_offs_nth_extern(offsets, i)) {
04012 ulint len;
04013 byte* field = rec_get_nth_field(
04014 rec, offsets, i, &len);
04015 memset(field + len
04016 - BTR_EXTERN_FIELD_REF_SIZE,
04017 0, BTR_EXTERN_FIELD_REF_SIZE);
04018 }
04019 }
04020 }
04021 }
04022
04023 #ifdef UNIV_ZIP_DEBUG
04024 ut_a(page_zip_validate(page_zip, page));
04025 #endif
04026 }
04027
04028
04031 UNIV_INTERN
04032 void
04033 page_zip_rec_set_deleted(
04034
04035 page_zip_des_t* page_zip,
04036 const byte* rec,
04037 ulint flag)
04038 {
04039 byte* slot = page_zip_dir_find(page_zip, page_offset(rec));
04040 ut_a(slot);
04041 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
04042 if (flag) {
04043 *slot |= (PAGE_ZIP_DIR_SLOT_DEL >> 8);
04044 } else {
04045 *slot &= ~(PAGE_ZIP_DIR_SLOT_DEL >> 8);
04046 }
04047 #ifdef UNIV_ZIP_DEBUG
04048 ut_a(page_zip_validate(page_zip, page_align(rec)));
04049 #endif
04050 }
04051
04052
04055 UNIV_INTERN
04056 void
04057 page_zip_rec_set_owned(
04058
04059 page_zip_des_t* page_zip,
04060 const byte* rec,
04061 ulint flag)
04062 {
04063 byte* slot = page_zip_dir_find(page_zip, page_offset(rec));
04064 ut_a(slot);
04065 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
04066 if (flag) {
04067 *slot |= (PAGE_ZIP_DIR_SLOT_OWNED >> 8);
04068 } else {
04069 *slot &= ~(PAGE_ZIP_DIR_SLOT_OWNED >> 8);
04070 }
04071 }
04072
04073
04075 UNIV_INTERN
04076 void
04077 page_zip_dir_insert(
04078
04079 page_zip_des_t* page_zip,
04080 const byte* prev_rec,
04081 const byte* free_rec,
04083 byte* rec)
04084 {
04085 ulint n_dense;
04086 byte* slot_rec;
04087 byte* slot_free;
04088
04089 ut_ad(prev_rec != rec);
04090 ut_ad(page_rec_get_next((rec_t*) prev_rec) == rec);
04091 ut_ad(page_zip_simple_validate(page_zip));
04092
04093 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
04094
04095 if (page_rec_is_infimum(prev_rec)) {
04096
04097 slot_rec = page_zip->data + page_zip_get_size(page_zip);
04098 } else {
04099 byte* end = page_zip->data + page_zip_get_size(page_zip);
04100 byte* start = end - page_zip_dir_user_size(page_zip);
04101
04102 if (UNIV_LIKELY(!free_rec)) {
04103
04104
04105
04106
04107 start += PAGE_ZIP_DIR_SLOT_SIZE;
04108 }
04109
04110 slot_rec = page_zip_dir_find_low(start, end,
04111 page_offset(prev_rec));
04112 ut_a(slot_rec);
04113 }
04114
04115
04116 n_dense = page_dir_get_n_heap(page_zip->data)
04117 - (PAGE_HEAP_NO_USER_LOW + 1);
04118
04119 if (UNIV_LIKELY_NULL(free_rec)) {
04120
04121
04122
04123
04124
04125 ut_ad(rec_get_heap_no_new(rec) < n_dense + 1
04126 + PAGE_HEAP_NO_USER_LOW);
04127 ut_ad(rec >= free_rec);
04128 slot_free = page_zip_dir_find(page_zip, page_offset(free_rec));
04129 ut_ad(slot_free);
04130 slot_free += PAGE_ZIP_DIR_SLOT_SIZE;
04131 } else {
04132
04133
04134 ut_ad(rec_get_heap_no_new(rec) == n_dense
04135 + PAGE_HEAP_NO_USER_LOW);
04136
04137
04138 slot_free = page_zip->data + page_zip_get_size(page_zip)
04139 - PAGE_ZIP_DIR_SLOT_SIZE * n_dense;
04140 }
04141
04142
04143 memmove(slot_free - PAGE_ZIP_DIR_SLOT_SIZE, slot_free,
04144 slot_rec - slot_free);
04145
04146
04147
04148 mach_write_to_2(slot_rec - PAGE_ZIP_DIR_SLOT_SIZE, page_offset(rec));
04149 }
04150
04151
04154 UNIV_INTERN
04155 void
04156 page_zip_dir_delete(
04157
04158 page_zip_des_t* page_zip,
04159 byte* rec,
04160 dict_index_t* index,
04161 const ulint* offsets,
04162 const byte* free)
04163 {
04164 byte* slot_rec;
04165 byte* slot_free;
04166 ulint n_ext;
04167 page_t* page = page_align(rec);
04168
04169 ut_ad(rec_offs_validate(rec, index, offsets));
04170 ut_ad(rec_offs_comp(offsets));
04171
04172 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
04173 UNIV_MEM_ASSERT_RW(rec, rec_offs_data_size(offsets));
04174 UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
04175 rec_offs_extra_size(offsets));
04176
04177 slot_rec = page_zip_dir_find(page_zip, page_offset(rec));
04178
04179 ut_a(slot_rec);
04180
04181
04182 page_header_set_field(page, page_zip, PAGE_N_RECS,
04183 (ulint)(page_get_n_recs(page) - 1));
04184
04185 if (UNIV_UNLIKELY(!free)) {
04186
04187 slot_free = page_zip->data + page_zip_get_size(page_zip)
04188 - PAGE_ZIP_DIR_SLOT_SIZE
04189 * (page_dir_get_n_heap(page_zip->data)
04190 - PAGE_HEAP_NO_USER_LOW);
04191 } else {
04192 slot_free = page_zip_dir_find_free(page_zip,
04193 page_offset(free));
04194 ut_a(slot_free < slot_rec);
04195
04196 slot_free += PAGE_ZIP_DIR_SLOT_SIZE;
04197 }
04198
04199 if (UNIV_LIKELY(slot_rec > slot_free)) {
04200 memmove(slot_free + PAGE_ZIP_DIR_SLOT_SIZE,
04201 slot_free,
04202 slot_rec - slot_free);
04203 }
04204
04205
04206
04207 mach_write_to_2(slot_free, page_offset(rec));
04208
04209 if (!page_is_leaf(page) || !dict_index_is_clust(index)) {
04210 ut_ad(!rec_offs_any_extern(offsets));
04211 goto skip_blobs;
04212 }
04213
04214 n_ext = rec_offs_n_extern(offsets);
04215 if (UNIV_UNLIKELY(n_ext)) {
04216
04217 ulint blob_no;
04218 byte* externs;
04219 byte* ext_end;
04220
04221 blob_no = page_zip_get_n_prev_extern(page_zip, rec, index);
04222 ut_a(blob_no + n_ext <= page_zip->n_blobs);
04223
04224 externs = page_zip->data + page_zip_get_size(page_zip)
04225 - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
04226 * (PAGE_ZIP_DIR_SLOT_SIZE
04227 + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
04228
04229 ext_end = externs - page_zip->n_blobs
04230 * BTR_EXTERN_FIELD_REF_SIZE;
04231 externs -= blob_no * BTR_EXTERN_FIELD_REF_SIZE;
04232
04233 page_zip->n_blobs -= n_ext;
04234
04235 memmove(ext_end + n_ext * BTR_EXTERN_FIELD_REF_SIZE, ext_end,
04236 (page_zip->n_blobs - blob_no)
04237 * BTR_EXTERN_FIELD_REF_SIZE);
04238 memset(ext_end, 0, n_ext * BTR_EXTERN_FIELD_REF_SIZE);
04239 }
04240
04241 skip_blobs:
04242
04243
04244 rec[-REC_N_NEW_EXTRA_BYTES] = 0;
04245
04246 page_zip_clear_rec(page_zip, rec, index, offsets);
04247 }
04248
04249
04251 UNIV_INTERN
04252 void
04253 page_zip_dir_add_slot(
04254
04255 page_zip_des_t* page_zip,
04256 ulint is_clustered)
04258 {
04259 ulint n_dense;
04260 byte* dir;
04261 byte* stored;
04262
04263 ut_ad(page_is_comp(page_zip->data));
04264 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
04265
04266
04267 n_dense = page_dir_get_n_heap(page_zip->data)
04268 - (PAGE_HEAP_NO_USER_LOW + 1);
04269
04270 dir = page_zip->data + page_zip_get_size(page_zip)
04271 - PAGE_ZIP_DIR_SLOT_SIZE * n_dense;
04272
04273 if (!page_is_leaf(page_zip->data)) {
04274 ut_ad(!page_zip->n_blobs);
04275 stored = dir - n_dense * REC_NODE_PTR_SIZE;
04276 } else if (UNIV_UNLIKELY(is_clustered)) {
04277
04278
04279 byte* externs;
04280
04281 stored = dir - n_dense
04282 * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
04283 externs = stored
04284 - page_zip->n_blobs * BTR_EXTERN_FIELD_REF_SIZE;
04285 ASSERT_ZERO(externs
04286 - (PAGE_ZIP_DIR_SLOT_SIZE
04287 + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN),
04288 PAGE_ZIP_DIR_SLOT_SIZE
04289 + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
04290 memmove(externs - (PAGE_ZIP_DIR_SLOT_SIZE
04291 + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN),
04292 externs, stored - externs);
04293 } else {
04294 stored = dir
04295 - page_zip->n_blobs * BTR_EXTERN_FIELD_REF_SIZE;
04296 ASSERT_ZERO(stored - PAGE_ZIP_DIR_SLOT_SIZE,
04297 PAGE_ZIP_DIR_SLOT_SIZE);
04298 }
04299
04300
04301
04302 memmove(stored - PAGE_ZIP_DIR_SLOT_SIZE, stored, dir - stored);
04303 }
04304
04305
04308 UNIV_INTERN
04309 byte*
04310 page_zip_parse_write_header(
04311
04312 byte* ptr,
04313 byte* end_ptr,
04314 page_t* page,
04315 page_zip_des_t* page_zip)
04316 {
04317 ulint offset;
04318 ulint len;
04319
04320 ut_ad(ptr && end_ptr);
04321 ut_ad(!page == !page_zip);
04322
04323 if (UNIV_UNLIKELY(end_ptr < ptr + (1 + 1))) {
04324
04325 return(NULL);
04326 }
04327
04328 offset = (ulint) *ptr++;
04329 len = (ulint) *ptr++;
04330
04331 if (UNIV_UNLIKELY(!len) || UNIV_UNLIKELY(offset + len >= PAGE_DATA)) {
04332 corrupt:
04333 recv_sys->found_corrupt_log = TRUE;
04334
04335 return(NULL);
04336 }
04337
04338 if (UNIV_UNLIKELY(end_ptr < ptr + len)) {
04339
04340 return(NULL);
04341 }
04342
04343 if (page) {
04344 if (UNIV_UNLIKELY(!page_zip)) {
04345
04346 goto corrupt;
04347 }
04348 #ifdef UNIV_ZIP_DEBUG
04349 ut_a(page_zip_validate(page_zip, page));
04350 #endif
04351
04352 memcpy(page + offset, ptr, len);
04353 memcpy(page_zip->data + offset, ptr, len);
04354
04355 #ifdef UNIV_ZIP_DEBUG
04356 ut_a(page_zip_validate(page_zip, page));
04357 #endif
04358 }
04359
04360 return(ptr + len);
04361 }
04362
04363 #ifndef UNIV_HOTBACKUP
04364
04366 UNIV_INTERN
04367 void
04368 page_zip_write_header_log(
04369
04370 const byte* data,
04371 ulint length,
04372 mtr_t* mtr)
04373 {
04374 byte* log_ptr = mlog_open(mtr, 11 + 1 + 1);
04375 ulint offset = page_offset(data);
04376
04377 ut_ad(offset < PAGE_DATA);
04378 ut_ad(offset + length < PAGE_DATA);
04379 #if PAGE_DATA > 255
04380 # error "PAGE_DATA > 255"
04381 #endif
04382 ut_ad(length < 256);
04383
04384
04385 if (UNIV_UNLIKELY(!log_ptr)) {
04386
04387 return;
04388 }
04389
04390 log_ptr = mlog_write_initial_log_record_fast(
04391 (byte*) data, MLOG_ZIP_WRITE_HEADER, log_ptr, mtr);
04392 *log_ptr++ = (byte) offset;
04393 *log_ptr++ = (byte) length;
04394 mlog_close(mtr, log_ptr);
04395
04396 mlog_catenate_string(mtr, data, length);
04397 }
04398 #endif
04399
04400
04411 UNIV_INTERN
04412 ibool
04413 page_zip_reorganize(
04414
04415 buf_block_t* block,
04419 dict_index_t* index,
04420 mtr_t* mtr)
04421 {
04422 buf_pool_t* buf_pool = buf_pool_from_block(block);
04423 page_zip_des_t* page_zip = buf_block_get_page_zip(block);
04424 page_t* page = buf_block_get_frame(block);
04425 buf_block_t* temp_block;
04426 page_t* temp_page;
04427 ulint log_mode;
04428
04429 ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
04430 ut_ad(page_is_comp(page));
04431 ut_ad(!dict_index_is_ibuf(index));
04432
04433 UNIV_MEM_ASSERT_RW(page, UNIV_PAGE_SIZE);
04434 UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
04435
04436
04437 log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
04438
04439 #ifndef UNIV_HOTBACKUP
04440 temp_block = buf_block_alloc(buf_pool, 0);
04441 btr_search_drop_page_hash_index(block);
04442 block->check_index_page_at_flush = TRUE;
04443 #else
04444 ut_ad(block == back_block1);
04445 temp_block = back_block2;
04446 #endif
04447 temp_page = temp_block->frame;
04448
04449
04450 buf_frame_copy(temp_page, page);
04451
04452
04453
04454
04455 page_create(block, mtr, TRUE);
04456
04457
04458
04459
04460 page_copy_rec_list_end_no_locks(block, temp_block,
04461 page_get_infimum_rec(temp_page),
04462 index, mtr);
04463
04464 if (!dict_index_is_clust(index) && page_is_leaf(temp_page)) {
04465
04466 trx_id_t max_trx_id = page_get_max_trx_id(temp_page);
04467 page_set_max_trx_id(block, NULL, max_trx_id, NULL);
04468 ut_ad(max_trx_id != 0);
04469 }
04470
04471
04472 mtr_set_log_mode(mtr, log_mode);
04473
04474 if (UNIV_UNLIKELY(!page_zip_compress(page_zip, page, index, mtr))) {
04475
04476 #ifndef UNIV_HOTBACKUP
04477 buf_block_free(temp_block);
04478 #endif
04479 return(FALSE);
04480 }
04481
04482 lock_move_reorganize_page(block, temp_block);
04483
04484 #ifndef UNIV_HOTBACKUP
04485 buf_block_free(temp_block);
04486 #endif
04487 return(TRUE);
04488 }
04489
04490 #ifndef UNIV_HOTBACKUP
04491
04496 UNIV_INTERN
04497 void
04498 page_zip_copy_recs(
04499
04500 page_zip_des_t* page_zip,
04503 page_t* page,
04504 const page_zip_des_t* src_zip,
04505 const page_t* src,
04506 dict_index_t* index,
04507 mtr_t* mtr)
04508 {
04509 ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
04510 ut_ad(mtr_memo_contains_page(mtr, (page_t*) src, MTR_MEMO_PAGE_X_FIX));
04511 ut_ad(!dict_index_is_ibuf(index));
04512 #ifdef UNIV_ZIP_DEBUG
04513
04514
04515
04516
04517 ut_a(page_zip_validate_low(src_zip, src, TRUE));
04518 #endif
04519 ut_a(page_zip_get_size(page_zip) == page_zip_get_size(src_zip));
04520 if (UNIV_UNLIKELY(src_zip->n_blobs)) {
04521 ut_a(page_is_leaf(src));
04522 ut_a(dict_index_is_clust(index));
04523 }
04524
04525
04526
04527 ut_a(dict_index_is_clust(index) || !page_is_leaf(src)
04528 || page_get_max_trx_id(src));
04529
04530 UNIV_MEM_ASSERT_W(page, UNIV_PAGE_SIZE);
04531 UNIV_MEM_ASSERT_W(page_zip->data, page_zip_get_size(page_zip));
04532 UNIV_MEM_ASSERT_RW(src, UNIV_PAGE_SIZE);
04533 UNIV_MEM_ASSERT_RW(src_zip->data, page_zip_get_size(page_zip));
04534
04535
04536
04537
04538
04539 #if PAGE_MAX_TRX_ID + 8 != PAGE_HEADER_PRIV_END
04540 # error "PAGE_MAX_TRX_ID + 8 != PAGE_HEADER_PRIV_END"
04541 #endif
04542 memcpy(PAGE_HEADER + page, PAGE_HEADER + src,
04543 PAGE_HEADER_PRIV_END);
04544 memcpy(PAGE_DATA + page, PAGE_DATA + src,
04545 UNIV_PAGE_SIZE - PAGE_DATA - FIL_PAGE_DATA_END);
04546 memcpy(PAGE_HEADER + page_zip->data, PAGE_HEADER + src_zip->data,
04547 PAGE_HEADER_PRIV_END);
04548 memcpy(PAGE_DATA + page_zip->data, PAGE_DATA + src_zip->data,
04549 page_zip_get_size(page_zip) - PAGE_DATA);
04550
04551
04552
04553 {
04554 page_zip_t* data = page_zip->data;
04555 memcpy(page_zip, src_zip, sizeof *page_zip);
04556 page_zip->data = data;
04557 }
04558 ut_ad(page_zip_get_trailer_len(page_zip,
04559 dict_index_is_clust(index), NULL)
04560 + page_zip->m_end < page_zip_get_size(page_zip));
04561
04562 if (!page_is_leaf(src)
04563 && UNIV_UNLIKELY(mach_read_from_4(src + FIL_PAGE_PREV) == FIL_NULL)
04564 && UNIV_LIKELY(mach_read_from_4(page
04565 + FIL_PAGE_PREV) != FIL_NULL)) {
04566
04567 ulint offs = rec_get_next_offs(page + PAGE_NEW_INFIMUM,
04568 TRUE);
04569 if (UNIV_LIKELY(offs != PAGE_NEW_SUPREMUM)) {
04570 rec_t* rec = page + offs;
04571 ut_a(rec[-REC_N_NEW_EXTRA_BYTES]
04572 & REC_INFO_MIN_REC_FLAG);
04573 rec[-REC_N_NEW_EXTRA_BYTES] &= ~ REC_INFO_MIN_REC_FLAG;
04574 }
04575 }
04576
04577 #ifdef UNIV_ZIP_DEBUG
04578 ut_a(page_zip_validate(page_zip, page));
04579 #endif
04580
04581 page_zip_compress_write_log(page_zip, page, index, mtr);
04582 }
04583 #endif
04584
04585
04588 UNIV_INTERN
04589 byte*
04590 page_zip_parse_compress(
04591
04592 byte* ptr,
04593 byte* end_ptr,
04594 page_t* page,
04595 page_zip_des_t* page_zip)
04596 {
04597 ulint size;
04598 ulint trailer_size;
04599
04600 ut_ad(ptr && end_ptr);
04601 ut_ad(!page == !page_zip);
04602
04603 if (UNIV_UNLIKELY(ptr + (2 + 2) > end_ptr)) {
04604
04605 return(NULL);
04606 }
04607
04608 size = mach_read_from_2(ptr);
04609 ptr += 2;
04610 trailer_size = mach_read_from_2(ptr);
04611 ptr += 2;
04612
04613 if (UNIV_UNLIKELY(ptr + 8 + size + trailer_size > end_ptr)) {
04614
04615 return(NULL);
04616 }
04617
04618 if (page) {
04619 if (UNIV_UNLIKELY(!page_zip)
04620 || UNIV_UNLIKELY(page_zip_get_size(page_zip) < size)) {
04621 corrupt:
04622 recv_sys->found_corrupt_log = TRUE;
04623
04624 return(NULL);
04625 }
04626
04627 memcpy(page_zip->data + FIL_PAGE_PREV, ptr, 4);
04628 memcpy(page_zip->data + FIL_PAGE_NEXT, ptr + 4, 4);
04629 memcpy(page_zip->data + FIL_PAGE_TYPE, ptr + 8, size);
04630 memset(page_zip->data + FIL_PAGE_TYPE + size, 0,
04631 page_zip_get_size(page_zip) - trailer_size
04632 - (FIL_PAGE_TYPE + size));
04633 memcpy(page_zip->data + page_zip_get_size(page_zip)
04634 - trailer_size, ptr + 8 + size, trailer_size);
04635
04636 if (UNIV_UNLIKELY(!page_zip_decompress(page_zip, page,
04637 TRUE))) {
04638
04639 goto corrupt;
04640 }
04641 }
04642
04643 return(ptr + 8 + size + trailer_size);
04644 }
04645
04646
04649 UNIV_INTERN
04650 ulint
04651 page_zip_calc_checksum(
04652
04653 const void* data,
04654 ulint size)
04655 {
04656
04657
04658
04659 const Bytef* s = static_cast<const Bytef *>(data);
04660 uLong adler;
04661
04662 ut_ad(size > FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
04663
04664 adler = adler32(0L, s + FIL_PAGE_OFFSET,
04665 FIL_PAGE_LSN - FIL_PAGE_OFFSET);
04666 adler = adler32(adler, s + FIL_PAGE_TYPE, 2);
04667 adler = adler32(adler, s + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
04668 size - FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
04669
04670 return((ulint) adler);
04671 }