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