1
/*****************************************************************************
3
Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/**************************************************//**
1
/******************************************************
21
2
Compressed page interface
23
6
Created June 2005 by Marko Makela
24
7
*******************************************************/
32
15
#include "page0page.h"
33
16
#include "mtr0log.h"
34
17
#include "ut0sort.h"
18
#include "dict0boot.h"
35
19
#include "dict0dict.h"
36
21
#include "btr0cur.h"
37
22
#include "page0types.h"
23
#include "lock0lock.h"
38
24
#include "log0recv.h"
40
#ifndef UNIV_HOTBACKUP
43
# include "dict0boot.h"
44
# include "lock0lock.h"
45
#else /* !UNIV_HOTBACKUP */
46
# define lock_move_reorganize_page(block, temp_block) ((void) 0)
47
# define buf_LRU_stat_inc_unzip() ((void) 0)
48
#endif /* !UNIV_HOTBACKUP */
50
#ifndef UNIV_HOTBACKUP
51
28
/** Statistics on compression, indexed by page_zip_des_t::ssize - 1 */
52
29
UNIV_INTERN page_zip_stat_t page_zip_stat[PAGE_ZIP_NUM_SSIZE - 1];
53
#endif /* !UNIV_HOTBACKUP */
55
31
/* Please refer to ../include/page0zip.ic for a description of the
56
32
compressed page format. */
58
34
/* The infimum and supremum records are omitted from the compressed page.
59
35
On compress, we compare that the records are there, and on uncompress we
60
36
restore the records. */
61
/** Extra bytes of an infimum record */
62
37
static const byte infimum_extra[] = {
63
38
0x01, /* info_bits=0, n_owned=1 */
64
39
0x00, 0x02 /* heap_no=0, status=2 */
65
40
/* ?, ? */ /* next=(first user rec, or supremum) */
67
/** Data bytes of an infimum record */
68
42
static const byte infimum_data[] = {
69
43
0x69, 0x6e, 0x66, 0x69,
70
44
0x6d, 0x75, 0x6d, 0x00 /* "infimum\0" */
72
/** Extra bytes and data bytes of a supremum record */
73
46
static const byte supremum_extra_data[] = {
74
47
/* 0x0?, */ /* info_bits=0, n_owned=1..8 */
75
48
0x00, 0x0b, /* heap_no=1, status=3 */
81
54
/** Assert that a block of memory is filled with zero bytes.
82
Compare at most sizeof(field_ref_zero) bytes.
83
@param b in: memory block
84
@param s in: size of the memory block, in bytes */
55
Compare at most sizeof(field_ref_zero) bytes. */
85
56
#define ASSERT_ZERO(b, s) \
86
57
ut_ad(!memcmp(b, field_ref_zero, ut_min(s, sizeof field_ref_zero)))
87
/** Assert that a BLOB pointer is filled with zero bytes.
88
@param b in: BLOB pointer */
58
/** Assert that a BLOB pointer is filled with zero bytes. */
89
59
#define ASSERT_ZERO_BLOB(b) \
90
60
ut_ad(!memcmp(b, field_ref_zero, sizeof field_ref_zero))
94
64
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
95
65
# include <stdarg.h>
96
66
__attribute__((format (printf, 1, 2)))
97
/**********************************************************************//**
98
Report a failure to decompress or compress.
99
@return number of characters printed */
67
/**************************************************************************
68
Report a failure to decompress or compress. */
102
71
page_zip_fail_func(
103
72
/*===============*/
104
const char* fmt, /*!< in: printf(3) format string */
105
...) /*!< in: arguments corresponding to fmt */
73
/* out: number of characters printed */
74
const char* fmt, /* in: printf(3) format string */
75
...) /* in: arguments corresponding to fmt */
118
/** Wrapper for page_zip_fail_func()
119
@param fmt_args in: printf(3) format string and arguments */
120
88
# define page_zip_fail(fmt_args) page_zip_fail_func fmt_args
121
89
#else /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
122
/** Dummy wrapper for page_zip_fail_func()
123
@param fmt_args ignored: printf(3) format string and arguments */
124
90
# define page_zip_fail(fmt_args) /* empty */
125
91
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
127
#ifndef UNIV_HOTBACKUP
128
/**********************************************************************//**
129
Determine the guaranteed free space on an empty page.
130
@return minimum payload size on the page */
93
/**************************************************************************
94
Determine the guaranteed free space on an empty page. */
133
97
page_zip_empty_size(
134
98
/*================*/
135
ulint n_fields, /*!< in: number of columns in the index */
136
ulint zip_size) /*!< in: compressed page size in bytes */
99
/* out: minimum payload size on the page */
100
ulint n_fields, /* in: number of columns in the index */
101
ulint zip_size) /* in: compressed page size in bytes */
138
103
lint size = zip_size
139
104
/* subtract the page header and the longest
148
113
- compressBound(2 * (n_fields + 1));
149
114
return(size > 0 ? (ulint) size : 0);
151
#endif /* !UNIV_HOTBACKUP */
153
/*************************************************************//**
117
/*****************************************************************
154
118
Gets the size of the compressed page trailer (the dense page directory),
155
including deleted records (the free list).
156
@return length of dense page directory, in bytes */
119
including deleted records (the free list). */
159
122
page_zip_dir_size(
160
123
/*==============*/
161
const page_zip_des_t* page_zip) /*!< in: compressed page */
124
/* out: length of dense page
125
directory, in bytes */
126
const page_zip_des_t* page_zip) /* in: compressed page */
163
128
/* Exclude the page infimum and supremum from the record count. */
164
129
ulint size = PAGE_ZIP_DIR_SLOT_SIZE
170
/*************************************************************//**
135
/*****************************************************************
171
136
Gets the size of the compressed page trailer (the dense page directory),
172
only including user records (excluding the free list).
173
@return length of dense page directory comprising existing records, in bytes */
137
only including user records (excluding the free list). */
176
140
page_zip_dir_user_size(
177
141
/*===================*/
178
const page_zip_des_t* page_zip) /*!< in: compressed page */
142
/* out: length of dense page
143
directory comprising existing
145
const page_zip_des_t* page_zip) /* in: compressed page */
180
147
ulint size = PAGE_ZIP_DIR_SLOT_SIZE
181
148
* page_get_n_recs(page_zip->data);
186
/*************************************************************//**
187
Find the slot of the given record in the dense page directory.
188
@return dense directory slot, or NULL if record not found */
153
/*****************************************************************
154
Find the slot of the given record in the dense page directory. */
191
157
page_zip_dir_find_low(
192
158
/*==================*/
193
byte* slot, /*!< in: start of records */
194
byte* end, /*!< in: end of records */
195
ulint offset) /*!< in: offset of user record */
159
/* out: dense directory slot,
160
or NULL if record not found */
161
byte* slot, /* in: start of records */
162
byte* end, /* in: end of records */
163
ulint offset) /* in: offset of user record */
197
165
ut_ad(slot <= end);
209
/*************************************************************//**
210
Find the slot of the given non-free record in the dense page directory.
211
@return dense directory slot, or NULL if record not found */
177
/*****************************************************************
178
Find the slot of the given non-free record in the dense page directory. */
214
181
page_zip_dir_find(
215
182
/*==============*/
216
page_zip_des_t* page_zip, /*!< in: compressed page */
217
ulint offset) /*!< in: offset of user record */
183
/* out: dense directory slot,
184
or NULL if record not found */
185
page_zip_des_t* page_zip, /* in: compressed page */
186
ulint offset) /* in: offset of user record */
219
188
byte* end = page_zip->data + page_zip_get_size(page_zip);
228
/*************************************************************//**
229
Find the slot of the given free record in the dense page directory.
230
@return dense directory slot, or NULL if record not found */
197
/*****************************************************************
198
Find the slot of the given free record in the dense page directory. */
233
201
page_zip_dir_find_free(
234
202
/*===================*/
235
page_zip_des_t* page_zip, /*!< in: compressed page */
236
ulint offset) /*!< in: offset of user record */
203
/* out: dense directory slot,
204
or NULL if record not found */
205
page_zip_des_t* page_zip, /* in: compressed page */
206
ulint offset) /* in: offset of user record */
238
208
byte* end = page_zip->data + page_zip_get_size(page_zip);
247
/*************************************************************//**
248
Read a given slot in the dense page directory.
249
@return record offset on the uncompressed page, possibly ORed with
250
PAGE_ZIP_DIR_SLOT_DEL or PAGE_ZIP_DIR_SLOT_OWNED */
217
/*****************************************************************
218
Read a given slot in the dense page directory. */
253
221
page_zip_dir_get(
254
222
/*=============*/
255
const page_zip_des_t* page_zip, /*!< in: compressed page */
256
ulint slot) /*!< in: slot
223
/* out: record offset
224
on the uncompressed page,
226
PAGE_ZIP_DIR_SLOT_DEL or
227
PAGE_ZIP_DIR_SLOT_OWNED */
228
const page_zip_des_t* page_zip, /* in: compressed page */
229
ulint slot) /* in: slot
257
230
(0=first user record) */
259
232
ut_ad(page_zip_simple_validate(page_zip));
262
235
- PAGE_ZIP_DIR_SLOT_SIZE * (slot + 1)));
265
#ifndef UNIV_HOTBACKUP
266
/**********************************************************************//**
238
/**************************************************************************
267
239
Write a log record of compressing an index page. */
270
242
page_zip_compress_write_log(
271
243
/*========================*/
272
const page_zip_des_t* page_zip,/*!< in: compressed page */
273
const page_t* page, /*!< in: uncompressed page */
274
dict_index_t* index, /*!< in: index of the B-tree node */
275
mtr_t* mtr) /*!< in: mini-transaction */
244
const page_zip_des_t* page_zip,/* in: compressed page */
245
const page_t* page, /* in: uncompressed page */
246
dict_index_t* index, /* in: index of the B-tree node */
247
mtr_t* mtr) /* in: mini-transaction */
278
250
ulint trailer_size;
280
ut_ad(!dict_index_is_ibuf(index));
282
252
log_ptr = mlog_open(mtr, 11 + 2 + 2);
326
296
mlog_catenate_string(mtr, page_zip->data + page_zip_get_size(page_zip)
327
297
- trailer_size, trailer_size);
329
#endif /* !UNIV_HOTBACKUP */
331
/******************************************************//**
300
/**********************************************************
332
301
Determine how many externally stored columns are contained
333
302
in existing records with smaller heap_no than rec. */
336
305
page_zip_get_n_prev_extern(
337
306
/*=======================*/
338
const page_zip_des_t* page_zip,/*!< in: dense page directory on
307
const page_zip_des_t* page_zip,/* in: dense page directory on
339
308
compressed page */
340
const rec_t* rec, /*!< in: compact physical record
309
const rec_t* rec, /* in: compact physical record
341
310
on a B-tree leaf page */
342
dict_index_t* index) /*!< in: record descriptor */
311
dict_index_t* index) /* in: record descriptor */
344
313
const page_t* page = page_align(rec);
380
/**********************************************************************//**
381
Encode the length of a fixed-length column.
382
@return buf + length of encoded val */
348
/**************************************************************************
349
Encode the length of a fixed-length column. */
385
352
page_zip_fixed_field_encode(
386
353
/*========================*/
387
byte* buf, /*!< in: pointer to buffer where to write */
388
ulint val) /*!< in: value to write */
354
/* out: buf + length of encoded val */
355
byte* buf, /* in: pointer to buffer where to write */
356
ulint val) /* in: value to write */
408
/**********************************************************************//**
409
Write the index information for the compressed page.
410
@return used size of buf */
376
/**************************************************************************
377
Write the index information for the compressed page. */
413
380
page_zip_fields_encode(
414
381
/*===================*/
415
ulint n, /*!< in: number of fields to compress */
416
dict_index_t* index, /*!< in: index comprising at least n fields */
417
ulint trx_id_pos,/*!< in: position of the trx_id column
382
/* out: used size of buf */
383
ulint n, /* in: number of fields to compress */
384
dict_index_t* index, /* in: index comprising at least n fields */
385
ulint trx_id_pos,/* in: position of the trx_id column
418
386
in the index, or ULINT_UNDEFINED if
419
387
this is a non-leaf page */
420
byte* buf) /*!< out: buffer of (n + 1) * 2 bytes */
388
byte* buf) /* out: buffer of (n + 1) * 2 bytes */
422
390
const byte* buf_start = buf;
533
501
return((ulint) (buf - buf_start));
536
/**********************************************************************//**
504
/**************************************************************************
537
505
Populate the dense page directory from the sparse directory. */
540
508
page_zip_dir_encode(
541
509
/*================*/
542
const page_t* page, /*!< in: compact page */
543
byte* buf, /*!< in: pointer to dense page directory[-1];
510
const page_t* page, /* in: compact page */
511
byte* buf, /* in: pointer to dense page directory[-1];
544
512
out: dense directory on compressed page */
545
const rec_t** recs) /*!< in: pointer to an array of 0, or NULL;
513
const rec_t** recs) /* in: pointer to an array of 0, or NULL;
546
514
out: dense page directory sorted by ascending
547
515
address (and heap_no) */
649
617
ut_a(i + PAGE_HEAP_NO_USER_LOW == n_heap);
652
/**********************************************************************//**
620
/**************************************************************************
653
621
Allocate memory for zlib. */
658
void* opaque, /*!< in/out: memory heap */
659
uInt items, /*!< in: number of items to allocate */
660
uInt size) /*!< in: size of an item in bytes */
662
630
return(mem_heap_alloc(opaque, items * size));
665
/**********************************************************************//**
633
/**************************************************************************
666
634
Deallocate memory for zlib. */
671
void* opaque __attribute__((unused)), /*!< in: memory heap */
672
void* address __attribute__((unused)))/*!< in: object to free */
639
void* opaque __attribute__((unused)),
640
void* address __attribute__((unused)))
676
/**********************************************************************//**
644
/**************************************************************************
677
645
Configure the zlib allocator to use the given memory heap. */
680
648
page_zip_set_alloc(
681
649
/*===============*/
682
void* stream, /*!< in/out: zlib stream */
683
mem_heap_t* heap) /*!< in: memory heap to use */
650
void* stream, /* in/out: zlib stream */
651
mem_heap_t* heap) /* in: memory heap to use */
685
653
z_stream* strm = stream;
692
660
#if 0 || defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
693
/** Symbol for enabling compression and decompression diagnostics */
694
661
# define PAGE_ZIP_COMPRESS_DBG
697
664
#ifdef PAGE_ZIP_COMPRESS_DBG
698
/** Set this variable in a debugger to enable
665
/* Set this variable in a debugger to enable
699
666
excessive logging in page_zip_compress(). */
700
667
UNIV_INTERN ibool page_zip_compress_dbg;
701
/** Set this variable in a debugger to enable
668
/* Set this variable in a debugger to enable
702
669
binary logging of the data passed to deflate().
703
670
When this variable is nonzero, it will act
704
671
as a log file name generator. */
705
672
UNIV_INTERN unsigned page_zip_compress_log;
707
/**********************************************************************//**
708
Wrapper for deflate(). Log the operation if page_zip_compress_dbg is set.
709
@return deflate() status: Z_OK, Z_BUF_ERROR, ... */
674
/**************************************************************************
675
Wrapper for deflate(). Log the operation if page_zip_compress_dbg is set. */
712
678
page_zip_compress_deflate(
713
679
/*======================*/
714
FILE* logfile,/*!< in: log file, or NULL */
715
z_streamp strm, /*!< in/out: compressed stream for deflate() */
716
int flush) /*!< in: deflate() flushing method */
680
FILE* logfile,/* in: log file, or NULL */
681
z_streamp strm, /* in/out: compressed stream for deflate() */
682
int flush) /* in: deflate() flushing method */
719
685
if (UNIV_UNLIKELY(page_zip_compress_dbg)) {
732
698
/* Redefine deflate(). */
734
/** Debug wrapper for the zlib compression routine deflate().
735
Log the operation if page_zip_compress_dbg is set.
736
@param strm in/out: compressed stream
737
@param flush in: flushing method
738
@return deflate() status: Z_OK, Z_BUF_ERROR, ... */
739
700
# define deflate(strm, flush) page_zip_compress_deflate(logfile, strm, flush)
740
/** Declaration of the logfile parameter */
741
701
# define FILE_LOGFILE FILE* logfile,
742
/** The logfile parameter */
743
702
# define LOGFILE logfile,
744
703
#else /* PAGE_ZIP_COMPRESS_DBG */
745
/** Empty declaration of the logfile parameter */
746
704
# define FILE_LOGFILE
747
/** Missing logfile parameter */
749
706
#endif /* PAGE_ZIP_COMPRESS_DBG */
751
/**********************************************************************//**
752
Compress the records of a node pointer page.
753
@return Z_OK, or a zlib error code */
708
/**************************************************************************
709
Compress the records of a node pointer page. */
756
712
page_zip_compress_node_ptrs(
757
713
/*========================*/
714
/* out: Z_OK, or a zlib error code */
759
z_stream* c_stream, /*!< in/out: compressed page stream */
760
const rec_t** recs, /*!< in: dense page directory
716
z_stream* c_stream, /* in/out: compressed page stream */
717
const rec_t** recs, /* in: dense page directory
761
718
sorted by address */
762
ulint n_dense, /*!< in: size of recs[] */
763
dict_index_t* index, /*!< in: the index of the page */
764
byte* storage, /*!< in: end of dense page directory */
765
mem_heap_t* heap) /*!< in: temporary memory heap */
719
ulint n_dense, /* in: size of recs[] */
720
dict_index_t* index, /* in: the index of the page */
721
byte* storage, /* in: end of dense page directory */
722
mem_heap_t* heap) /* in: temporary memory heap */
768
725
ulint* offsets = NULL;
816
/**********************************************************************//**
817
Compress the records of a leaf node of a secondary index.
818
@return Z_OK, or a zlib error code */
773
/**************************************************************************
774
Compress the records of a leaf node of a secondary index. */
821
777
page_zip_compress_sec(
822
778
/*==================*/
779
/* out: Z_OK, or a zlib error code */
824
z_stream* c_stream, /*!< in/out: compressed page stream */
825
const rec_t** recs, /*!< in: dense page directory
781
z_stream* c_stream, /* in/out: compressed page stream */
782
const rec_t** recs, /* in: dense page directory
826
783
sorted by address */
827
ulint n_dense) /*!< in: size of recs[] */
784
ulint n_dense) /* in: size of recs[] */
860
/**********************************************************************//**
817
/**************************************************************************
861
818
Compress a record of a leaf node of a clustered index that contains
862
externally stored columns.
863
@return Z_OK, or a zlib error code */
819
externally stored columns. */
866
822
page_zip_compress_clust_ext(
867
823
/*========================*/
824
/* out: Z_OK, or a zlib error code */
869
z_stream* c_stream, /*!< in/out: compressed page stream */
870
const rec_t* rec, /*!< in: record */
871
const ulint* offsets, /*!< in: rec_get_offsets(rec) */
872
ulint trx_id_col, /*!< in: position of of DB_TRX_ID */
873
byte* deleted, /*!< in: dense directory entry pointing
826
z_stream* c_stream, /* in/out: compressed page stream */
827
const rec_t* rec, /* in: record */
828
const ulint* offsets, /* in: rec_get_offsets(rec) */
829
ulint trx_id_col, /* in: position of of DB_TRX_ID */
830
byte* deleted, /* in: dense directory entry pointing
874
831
to the head of the free list */
875
byte* storage, /*!< in: end of dense page directory */
876
byte** externs, /*!< in/out: pointer to the next
832
byte* storage, /* in: end of dense page directory */
833
byte** externs, /* in/out: pointer to the next
877
834
available BLOB pointer */
878
ulint* n_blobs) /*!< in/out: number of
835
ulint* n_blobs) /* in/out: number of
879
836
externally stored columns */
988
/**********************************************************************//**
989
Compress the records of a leaf node of a clustered index.
990
@return Z_OK, or a zlib error code */
945
/**************************************************************************
946
Compress the records of a leaf node of a clustered index. */
993
949
page_zip_compress_clust(
994
950
/*====================*/
951
/* out: Z_OK, or a zlib error code */
996
z_stream* c_stream, /*!< in/out: compressed page stream */
997
const rec_t** recs, /*!< in: dense page directory
953
z_stream* c_stream, /* in/out: compressed page stream */
954
const rec_t** recs, /* in: dense page directory
998
955
sorted by address */
999
ulint n_dense, /*!< in: size of recs[] */
1000
dict_index_t* index, /*!< in: the index of the page */
1001
ulint* n_blobs, /*!< in: 0; out: number of
956
ulint n_dense, /* in: size of recs[] */
957
dict_index_t* index, /* in: the index of the page */
958
ulint* n_blobs, /* in: 0; out: number of
1002
959
externally stored columns */
1003
ulint trx_id_col, /*!< index of the trx_id column */
1004
byte* deleted, /*!< in: dense directory entry pointing
960
ulint trx_id_col, /* index of the trx_id column */
961
byte* deleted, /* in: dense directory entry pointing
1005
962
to the head of the free list */
1006
byte* storage, /*!< in: end of dense page directory */
1007
mem_heap_t* heap) /*!< in: temporary memory heap */
963
byte* storage, /* in: end of dense page directory */
964
mem_heap_t* heap) /* in: temporary memory heap */
1010
967
ulint* offsets = NULL;
1121
/**********************************************************************//**
1123
@return TRUE on success, FALSE on failure; page_zip will be left
1124
intact on failure. */
1078
/**************************************************************************
1127
1082
page_zip_compress(
1128
1083
/*==============*/
1129
page_zip_des_t* page_zip,/*!< in: size; out: data, n_blobs,
1084
/* out: TRUE on success, FALSE on failure;
1085
page_zip will be left intact on failure. */
1086
page_zip_des_t* page_zip,/* in: size; out: data, n_blobs,
1130
1087
m_start, m_end, m_nonempty */
1131
const page_t* page, /*!< in: uncompressed page */
1132
dict_index_t* index, /*!< in: index of the B-tree node */
1133
mtr_t* mtr) /*!< in: mini-transaction, or NULL */
1088
const page_t* page, /* in: uncompressed page */
1089
dict_index_t* index, /* in: index of the B-tree node */
1090
mtr_t* mtr) /* in: mini-transaction, or NULL */
1135
1092
z_stream c_stream;
1137
1094
ulint n_fields;/* number of index fields needed */
1138
byte* fields; /*!< index field information */
1139
byte* buf; /*!< compressed payload of the page */
1095
byte* fields; /* index field information */
1096
byte* buf; /* compressed payload of the page */
1140
1097
byte* buf_end;/* end of buf */
1142
1099
ulint slot_size;/* amount of uncompressed bytes per record */
1143
const rec_t** recs; /*!< dense page directory, sorted by address */
1100
const rec_t** recs; /* dense page directory, sorted by address */
1144
1101
mem_heap_t* heap;
1145
1102
ulint trx_id_col;
1146
1103
ulint* offsets = NULL;
1147
1104
ulint n_blobs = 0;
1148
1105
byte* storage;/* storage of uncompressed columns */
1149
#ifndef UNIV_HOTBACKUP
1150
1106
ullint usec = ut_time_us(NULL);
1151
#endif /* !UNIV_HOTBACKUP */
1152
1107
#ifdef PAGE_ZIP_COMPRESS_DBG
1153
1108
FILE* logfile = NULL;
1412
1359
fclose(logfile);
1414
1361
#endif /* PAGE_ZIP_COMPRESS_DBG */
1415
#ifndef UNIV_HOTBACKUP
1417
1363
page_zip_stat_t* zip_stat
1418
1364
= &page_zip_stat[page_zip->ssize - 1];
1419
1365
zip_stat->compressed_ok++;
1420
1366
zip_stat->compressed_usec += ut_time_us(NULL) - usec;
1422
#endif /* !UNIV_HOTBACKUP */
1427
/**********************************************************************//**
1428
Compare two page directory entries.
1429
@return positive if rec1 > rec2 */
1372
/**************************************************************************
1373
Compare two page directory entries. */
1432
1376
page_zip_dir_cmp(
1433
1377
/*=============*/
1434
const rec_t* rec1, /*!< in: rec1 */
1435
const rec_t* rec2) /*!< in: rec2 */
1378
/* out: positive if rec1 > rec2 */
1379
const rec_t* rec1, /* in: rec1 */
1380
const rec_t* rec2) /* in: rec2 */
1437
1382
return(rec1 > rec2);
1440
/**********************************************************************//**
1385
/**************************************************************************
1441
1386
Sort the dense page directory by address (heap_no). */
1444
1389
page_zip_dir_sort(
1445
1390
/*==============*/
1446
rec_t** arr, /*!< in/out: dense page directory */
1447
rec_t** aux_arr,/*!< in/out: work area */
1448
ulint low, /*!< in: lower bound of the sorting area, inclusive */
1449
ulint high) /*!< in: upper bound of the sorting area, exclusive */
1391
rec_t** arr, /* in/out: dense page directory */
1392
rec_t** aux_arr,/* in/out: work area */
1393
ulint low, /* in: lower bound of the sorting area, inclusive */
1394
ulint high) /* in: upper bound of the sorting area, exclusive */
1451
1396
UT_SORT_FUNCTION_BODY(page_zip_dir_sort, arr, aux_arr, low, high,
1452
1397
page_zip_dir_cmp);
1455
/**********************************************************************//**
1400
/**************************************************************************
1456
1401
Deallocate the index information initialized by page_zip_fields_decode(). */
1459
1404
page_zip_fields_free(
1460
1405
/*=================*/
1461
dict_index_t* index) /*!< in: dummy index to be freed */
1406
dict_index_t* index) /* in: dummy index to be freed */
1464
1409
dict_table_t* table = index->table;
1465
1410
mem_heap_free(index->heap);
1466
1411
mutex_free(&(table->autoinc_mutex));
1467
ut_free(table->name);
1468
1412
mem_heap_free(table->heap);
1472
/**********************************************************************//**
1473
Read the index information for the compressed page.
1474
@return own: dummy index describing the page, or NULL on error */
1416
/**************************************************************************
1417
Read the index information for the compressed page. */
1477
1420
page_zip_fields_decode(
1478
1421
/*===================*/
1479
const byte* buf, /*!< in: index information */
1480
const byte* end, /*!< in: end of buf */
1481
ulint* trx_id_col)/*!< in: NULL for non-leaf pages;
1422
/* out,own: dummy index describing the page,
1424
const byte* buf, /* in: index information */
1425
const byte* end, /* in: end of buf */
1426
ulint* trx_id_col)/* in: NULL for non-leaf pages;
1482
1427
for leaf pages, pointer to where to store
1483
1428
the position of the trx_id column */
1588
/**********************************************************************//**
1589
Populate the sparse page directory from the dense directory.
1590
@return TRUE on success, FALSE on failure */
1533
/**************************************************************************
1534
Populate the sparse page directory from the dense directory. */
1593
1537
page_zip_dir_decode(
1594
1538
/*================*/
1595
const page_zip_des_t* page_zip,/*!< in: dense page directory on
1539
/* out: TRUE on success,
1541
const page_zip_des_t* page_zip,/* in: dense page directory on
1596
1542
compressed page */
1597
page_t* page, /*!< in: compact page with valid header;
1543
page_t* page, /* in: compact page with valid header;
1598
1544
out: trailer and sparse page directory
1600
rec_t** recs, /*!< out: dense page directory sorted by
1546
rec_t** recs, /* out: dense page directory sorted by
1601
1547
ascending address (and heap_no) */
1602
rec_t** recs_aux,/*!< in/out: scratch area */
1603
ulint n_dense)/*!< in: number of user records, and
1548
rec_t** recs_aux,/* in/out: scratch area */
1549
ulint n_dense)/* in: number of user records, and
1604
1550
size of recs[] and recs_aux[] */
1685
/**********************************************************************//**
1686
Initialize the REC_N_NEW_EXTRA_BYTES of each record.
1687
@return TRUE on success, FALSE on failure */
1631
/**************************************************************************
1632
Initialize the REC_N_NEW_EXTRA_BYTES of each record. */
1690
1635
page_zip_set_extra_bytes(
1691
1636
/*=====================*/
1692
const page_zip_des_t* page_zip,/*!< in: compressed page */
1693
page_t* page, /*!< in/out: uncompressed page */
1694
ulint info_bits)/*!< in: REC_INFO_MIN_REC_FLAG or 0 */
1637
/* out: TRUE on success,
1639
const page_zip_des_t* page_zip,/* in: compressed page */
1640
page_t* page, /* in/out: uncompressed page */
1641
ulint info_bits)/* in: REC_INFO_MIN_REC_FLAG or 0 */
1782
/**********************************************************************//**
1729
/**************************************************************************
1783
1730
Apply the modification log to a record containing externally stored
1784
columns. Do not copy the fields that are stored separately.
1785
@return pointer to modification log, or NULL on failure */
1731
columns. Do not copy the fields that are stored separately. */
1788
1734
page_zip_apply_log_ext(
1789
1735
/*===================*/
1790
rec_t* rec, /*!< in/out: record */
1791
const ulint* offsets, /*!< in: rec_get_offsets(rec) */
1792
ulint trx_id_col, /*!< in: position of of DB_TRX_ID */
1793
const byte* data, /*!< in: modification log */
1794
const byte* end) /*!< in: end of modification log */
1736
/* out: pointer to modification log,
1737
or NULL on failure */
1738
rec_t* rec, /* in/out: record */
1739
const ulint* offsets, /* in: rec_get_offsets(rec) */
1740
ulint trx_id_col, /* in: position of of DB_TRX_ID */
1741
const byte* data, /* in: modification log */
1742
const byte* end) /* in: end of modification log */
1871
/**********************************************************************//**
1819
/**************************************************************************
1872
1820
Apply the modification log to an uncompressed page.
1873
Do not copy the fields that are stored separately.
1874
@return pointer to end of modification log, or NULL on failure */
1821
Do not copy the fields that are stored separately. */
1877
1824
page_zip_apply_log(
1878
1825
/*===============*/
1879
const byte* data, /*!< in: modification log */
1880
ulint size, /*!< in: maximum length of the log, in bytes */
1881
rec_t** recs, /*!< in: dense page directory,
1826
/* out: pointer to end of modification log,
1827
or NULL on failure */
1828
const byte* data, /* in: modification log */
1829
ulint size, /* in: maximum length of the log, in bytes */
1830
rec_t** recs, /* in: dense page directory,
1882
1831
sorted by address (indexed by
1883
1832
heap_no - PAGE_HEAP_NO_USER_LOW) */
1884
ulint n_dense,/*!< in: size of recs[] */
1885
ulint trx_id_col,/*!< in: column number of trx_id in the index,
1833
ulint n_dense,/* in: size of recs[] */
1834
ulint trx_id_col,/* in: column number of trx_id in the index,
1886
1835
or ULINT_UNDEFINED if none */
1887
1836
ulint heap_status,
1888
/*!< in: heap_no and status bits for
1837
/* in: heap_no and status bits for
1889
1838
the next record to uncompress */
1890
dict_index_t* index, /*!< in: index of the page */
1891
ulint* offsets)/*!< in/out: work area for
1839
dict_index_t* index, /* in: index of the page */
1840
ulint* offsets)/* in/out: work area for
1892
1841
rec_get_offsets_reverse() */
1894
1843
const byte* const end = data + size;
2072
/**********************************************************************//**
2073
Decompress the records of a node pointer page.
2074
@return TRUE on success, FALSE on failure */
2021
/**************************************************************************
2022
Decompress the records of a node pointer page. */
2077
2025
page_zip_decompress_node_ptrs(
2078
2026
/*==========================*/
2079
page_zip_des_t* page_zip, /*!< in/out: compressed page */
2080
z_stream* d_stream, /*!< in/out: compressed page stream */
2081
rec_t** recs, /*!< in: dense page directory
2027
/* out: TRUE on success,
2029
page_zip_des_t* page_zip, /* in/out: compressed page */
2030
z_stream* d_stream, /* in/out: compressed page stream */
2031
rec_t** recs, /* in: dense page directory
2082
2032
sorted by address */
2083
ulint n_dense, /*!< in: size of recs[] */
2084
dict_index_t* index, /*!< in: the index of the page */
2085
ulint* offsets, /*!< in/out: temporary offsets */
2086
mem_heap_t* heap) /*!< in: temporary memory heap */
2033
ulint n_dense, /* in: size of recs[] */
2034
dict_index_t* index, /* in: the index of the page */
2035
ulint* offsets, /* in/out: temporary offsets */
2036
mem_heap_t* heap) /* in: temporary memory heap */
2088
2038
ulint heap_status = REC_STATUS_NODE_PTR
2089
2039
| PAGE_HEAP_NO_USER_LOW << REC_HEAP_NO_SHIFT;
2265
/**********************************************************************//**
2266
Decompress the records of a leaf node of a secondary index.
2267
@return TRUE on success, FALSE on failure */
2215
/**************************************************************************
2216
Decompress the records of a leaf node of a secondary index. */
2270
2219
page_zip_decompress_sec(
2271
2220
/*====================*/
2272
page_zip_des_t* page_zip, /*!< in/out: compressed page */
2273
z_stream* d_stream, /*!< in/out: compressed page stream */
2274
rec_t** recs, /*!< in: dense page directory
2221
/* out: TRUE on success,
2223
page_zip_des_t* page_zip, /* in/out: compressed page */
2224
z_stream* d_stream, /* in/out: compressed page stream */
2225
rec_t** recs, /* in: dense page directory
2275
2226
sorted by address */
2276
ulint n_dense, /*!< in: size of recs[] */
2277
dict_index_t* index, /*!< in: the index of the page */
2278
ulint* offsets) /*!< in/out: temporary offsets */
2227
ulint n_dense, /* in: size of recs[] */
2228
dict_index_t* index, /* in: the index of the page */
2229
ulint* offsets) /* in/out: temporary offsets */
2280
2231
ulint heap_status = REC_STATUS_ORDINARY
2281
2232
| PAGE_HEAP_NO_USER_LOW << REC_HEAP_NO_SHIFT;
2406
/**********************************************************************//**
2357
/**************************************************************************
2407
2358
Decompress a record of a leaf node of a clustered index that contains
2408
externally stored columns.
2409
@return TRUE on success */
2359
externally stored columns. */
2412
2362
page_zip_decompress_clust_ext(
2413
2363
/*==========================*/
2414
z_stream* d_stream, /*!< in/out: compressed page stream */
2415
rec_t* rec, /*!< in/out: record */
2416
const ulint* offsets, /*!< in: rec_get_offsets(rec) */
2417
ulint trx_id_col) /*!< in: position of of DB_TRX_ID */
2364
/* out: TRUE on success */
2365
z_stream* d_stream, /* in/out: compressed page stream */
2366
rec_t* rec, /* in/out: record */
2367
const ulint* offsets, /* in: rec_get_offsets(rec) */
2368
ulint trx_id_col) /* in: position of of DB_TRX_ID */
2515
/**********************************************************************//**
2516
Compress the records of a leaf node of a clustered index.
2517
@return TRUE on success, FALSE on failure */
2466
/**************************************************************************
2467
Compress the records of a leaf node of a clustered index. */
2520
2470
page_zip_decompress_clust(
2521
2471
/*======================*/
2522
page_zip_des_t* page_zip, /*!< in/out: compressed page */
2523
z_stream* d_stream, /*!< in/out: compressed page stream */
2524
rec_t** recs, /*!< in: dense page directory
2472
/* out: TRUE on success,
2474
page_zip_des_t* page_zip, /* in/out: compressed page */
2475
z_stream* d_stream, /* in/out: compressed page stream */
2476
rec_t** recs, /* in: dense page directory
2525
2477
sorted by address */
2526
ulint n_dense, /*!< in: size of recs[] */
2527
dict_index_t* index, /*!< in: the index of the page */
2528
ulint trx_id_col, /*!< index of the trx_id column */
2529
ulint* offsets, /*!< in/out: temporary offsets */
2530
mem_heap_t* heap) /*!< in: temporary memory heap */
2478
ulint n_dense, /* in: size of recs[] */
2479
dict_index_t* index, /* in: the index of the page */
2480
ulint trx_id_col, /* index of the trx_id column */
2481
ulint* offsets, /* in/out: temporary offsets */
2482
mem_heap_t* heap) /* in: temporary memory heap */
2814
/**********************************************************************//**
2766
/**************************************************************************
2815
2767
Decompress a page. This function should tolerate errors on the compressed
2816
2768
page. Instead of letting assertions fail, it will return FALSE if an
2817
inconsistency is detected.
2818
@return TRUE on success, FALSE on failure */
2769
inconsistency is detected. */
2821
2772
page_zip_decompress(
2822
2773
/*================*/
2823
page_zip_des_t* page_zip,/*!< in: data, ssize;
2774
/* out: TRUE on success, FALSE on failure */
2775
page_zip_des_t* page_zip,/* in: data, ssize;
2824
2776
out: m_start, m_end, m_nonempty, n_blobs */
2825
page_t* page, /*!< out: uncompressed page, may be trashed */
2826
ibool all) /*!< in: TRUE=decompress the whole page;
2827
FALSE=verify but do not copy some
2828
page header fields that should not change
2829
after page creation */
2777
page_t* page) /* out: uncompressed page, may be trashed */
2831
2779
z_stream d_stream;
2832
2780
dict_index_t* index = NULL;
2833
rec_t** recs; /*!< dense page directory, sorted by address */
2781
rec_t** recs; /* dense page directory, sorted by address */
2834
2782
ulint n_dense;/* number of user records on the page */
2835
2783
ulint trx_id_col = ULINT_UNDEFINED;
2836
2784
mem_heap_t* heap;
2837
2785
ulint* offsets;
2838
#ifndef UNIV_HOTBACKUP
2839
2786
ullint usec = ut_time_us(NULL);
2840
#endif /* !UNIV_HOTBACKUP */
2842
2788
ut_ad(page_zip_simple_validate(page_zip));
2843
2789
UNIV_MEM_ASSERT_W(page, UNIV_PAGE_SIZE);
2856
2802
heap = mem_heap_create(n_dense * (3 * sizeof *recs) + UNIV_PAGE_SIZE);
2857
2803
recs = mem_heap_alloc(heap, n_dense * (2 * sizeof *recs));
2860
/* Copy the page header. */
2861
memcpy(page, page_zip->data, PAGE_DATA);
2863
/* Check that the bytes that we skip are identical. */
2864
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
2865
ut_a(!memcmp(FIL_PAGE_TYPE + page,
2866
FIL_PAGE_TYPE + page_zip->data,
2867
PAGE_HEADER - FIL_PAGE_TYPE));
2868
ut_a(!memcmp(PAGE_HEADER + PAGE_LEVEL + page,
2869
PAGE_HEADER + PAGE_LEVEL + page_zip->data,
2870
PAGE_DATA - (PAGE_HEADER + PAGE_LEVEL)));
2871
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
2873
/* Copy the mutable parts of the page header. */
2874
memcpy(page, page_zip->data, FIL_PAGE_TYPE);
2875
memcpy(PAGE_HEADER + page, PAGE_HEADER + page_zip->data,
2876
PAGE_LEVEL - PAGE_N_DIR_SLOTS);
2878
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
2879
/* Check that the page headers match after copying. */
2880
ut_a(!memcmp(page, page_zip->data, PAGE_DATA));
2881
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
2884
2805
#ifdef UNIV_ZIP_DEBUG
2885
/* Clear the uncompressed page, except the header. */
2886
memset(PAGE_DATA + page, 0x55, UNIV_PAGE_SIZE - PAGE_DATA);
2806
/* Clear the page. */
2807
memset(page, 0x55, UNIV_PAGE_SIZE);
2887
2808
#endif /* UNIV_ZIP_DEBUG */
2888
UNIV_MEM_INVALID(PAGE_DATA + page, UNIV_PAGE_SIZE - PAGE_DATA);
2809
UNIV_MEM_INVALID(page, UNIV_PAGE_SIZE);
2810
/* Copy the page header. */
2811
memcpy(page, page_zip->data, PAGE_DATA);
2890
2813
/* Copy the page directory. */
2891
2814
if (UNIV_UNLIKELY(!page_zip_dir_decode(page_zip, page, recs,
3034
2955
#ifdef UNIV_ZIP_DEBUG
3035
/**********************************************************************//**
2956
/**************************************************************************
3036
2957
Dump a block of memory on the standard error stream. */
3039
2960
page_zip_hexdump_func(
3040
2961
/*==================*/
3041
const char* name, /*!< in: name of the data structure */
3042
const void* buf, /*!< in: data */
3043
ulint size) /*!< in: length of the data, in bytes */
2962
const char* name, /* in: name of the data structure */
2963
const void* buf, /* in: data */
2964
ulint size) /* in: length of the data, in bytes */
3045
2966
const byte* s = buf;
3066
/** Dump a block of memory on the standard error stream.
3068
@param size in: length of the data, in bytes */
3069
2987
#define page_zip_hexdump(buf, size) page_zip_hexdump_func(#buf, buf, size)
3071
/** Flag: make page_zip_validate() compare page headers only */
2989
/* Flag: make page_zip_validate() compare page headers only */
3072
2990
UNIV_INTERN ibool page_zip_validate_header_only = FALSE;
3074
/**********************************************************************//**
3075
Check that the compressed and decompressed pages match.
3076
@return TRUE if valid, FALSE if not */
2992
/**************************************************************************
2993
Check that the compressed and decompressed pages match. */
3079
2996
page_zip_validate_low(
3080
2997
/*==================*/
3081
const page_zip_des_t* page_zip,/*!< in: compressed page */
3082
const page_t* page, /*!< in: uncompressed page */
3083
ibool sloppy) /*!< in: FALSE=strict,
2998
/* out: TRUE if valid, FALSE if not */
2999
const page_zip_des_t* page_zip,/* in: compressed page */
3000
const page_t* page, /* in: uncompressed page */
3001
ibool sloppy) /* in: FALSE=strict,
3084
3002
TRUE=ignore the MIN_REC_FLAG */
3086
3004
page_zip_des_t temp_page_zip;
3118
3036
temp_page_zip in a debugger when running valgrind --db-attach. */
3119
3037
VALGRIND_GET_VBITS(page, temp_page, UNIV_PAGE_SIZE);
3120
3038
UNIV_MEM_ASSERT_RW(page, UNIV_PAGE_SIZE);
3121
# if UNIV_WORD_SIZE == 4
3122
3039
VALGRIND_GET_VBITS(page_zip, &temp_page_zip, sizeof temp_page_zip);
3123
/* On 32-bit systems, there is no padding in page_zip_des_t.
3124
On other systems, Valgrind could complain about uninitialized
3126
3040
UNIV_MEM_ASSERT_RW(page_zip, sizeof *page_zip);
3128
3041
VALGRIND_GET_VBITS(page_zip->data, temp_page,
3129
3042
page_zip_get_size(page_zip));
3130
3043
UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
3131
3044
#endif /* UNIV_DEBUG_VALGRIND */
3133
3046
temp_page_zip = *page_zip;
3134
valid = page_zip_decompress(&temp_page_zip, temp_page, TRUE);
3047
valid = page_zip_decompress(&temp_page_zip, temp_page);
3136
3049
fputs("page_zip_validate(): failed to decompress\n", stderr);
3137
3050
goto func_exit;
3216
/**********************************************************************//**
3217
Check that the compressed and decompressed pages match.
3218
@return TRUE if valid, FALSE if not */
3129
/**************************************************************************
3130
Check that the compressed and decompressed pages match. */
3221
3133
page_zip_validate(
3222
3134
/*==============*/
3223
const page_zip_des_t* page_zip,/*!< in: compressed page */
3224
const page_t* page) /*!< in: uncompressed page */
3135
/* out: TRUE if valid, FALSE if not */
3136
const page_zip_des_t* page_zip,/* in: compressed page */
3137
const page_t* page) /* in: uncompressed page */
3226
3139
return(page_zip_validate_low(page_zip, page,
3227
3140
recv_recovery_is_on()));
3229
3142
#endif /* UNIV_ZIP_DEBUG */
3231
3144
#ifdef UNIV_DEBUG
3232
/**********************************************************************//**
3233
Assert that the compressed and decompressed page headers match.
3237
3147
page_zip_header_cmp(
3238
3148
/*================*/
3239
const page_zip_des_t* page_zip,/*!< in: compressed page */
3240
const byte* page) /*!< in: uncompressed page */
3150
const page_zip_des_t* page_zip,/* in: compressed page */
3151
const byte* page) /* in: uncompressed page */
3242
3153
ut_ad(!memcmp(page_zip->data + FIL_PAGE_PREV, page + FIL_PAGE_PREV,
3243
3154
FIL_PAGE_LSN - FIL_PAGE_PREV));
3251
3162
#endif /* UNIV_DEBUG */
3253
/**********************************************************************//**
3164
/**************************************************************************
3254
3165
Write a record on the compressed page that contains externally stored
3255
columns. The data must already have been written to the uncompressed page.
3256
@return end of modification log */
3166
columns. The data must already have been written to the uncompressed page. */
3259
3169
page_zip_write_rec_ext(
3260
3170
/*===================*/
3261
page_zip_des_t* page_zip, /*!< in/out: compressed page */
3262
const page_t* page, /*!< in: page containing rec */
3263
const byte* rec, /*!< in: record being written */
3264
dict_index_t* index, /*!< in: record descriptor */
3265
const ulint* offsets, /*!< in: rec_get_offsets(rec, index) */
3266
ulint create, /*!< in: nonzero=insert, zero=update */
3267
ulint trx_id_col, /*!< in: position of DB_TRX_ID */
3268
ulint heap_no, /*!< in: heap number of rec */
3269
byte* storage, /*!< in: end of dense page directory */
3270
byte* data) /*!< in: end of modification log */
3171
/* out: end of modification log */
3172
page_zip_des_t* page_zip, /* in/out: compressed page */
3173
const page_t* page, /* in: page containing rec */
3174
const byte* rec, /* in: record being written */
3175
dict_index_t* index, /* in: record descriptor */
3176
const ulint* offsets, /* in: rec_get_offsets(rec, index) */
3177
ulint create, /* in: nonzero=insert, zero=update */
3178
ulint trx_id_col, /* in: position of DB_TRX_ID */
3179
ulint heap_no, /* in: heap number of rec */
3180
byte* storage, /* in: end of dense page directory */
3181
byte* data) /* in: end of modification log */
3272
3183
const byte* start = rec;
3375
/**********************************************************************//**
3286
/**************************************************************************
3376
3287
Write an entire record on the compressed page. The data must already
3377
3288
have been written to the uncompressed page. */
3380
3291
page_zip_write_rec(
3381
3292
/*===============*/
3382
page_zip_des_t* page_zip,/*!< in/out: compressed page */
3383
const byte* rec, /*!< in: record being written */
3384
dict_index_t* index, /*!< in: the index the record belongs to */
3385
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
3386
ulint create) /*!< in: nonzero=insert, zero=update */
3293
page_zip_des_t* page_zip,/* in/out: compressed page */
3294
const byte* rec, /* in: record being written */
3295
dict_index_t* index, /* in: the index the record belongs to */
3296
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
3297
ulint create) /* in: nonzero=insert, zero=update */
3388
3299
const page_t* page;
3560
3471
#endif /* UNIV_ZIP_DEBUG */
3563
/***********************************************************//**
3564
Parses a log record of writing a BLOB pointer of a record.
3565
@return end of log record or NULL */
3474
/***************************************************************
3475
Parses a log record of writing a BLOB pointer of a record. */
3568
3478
page_zip_parse_write_blob_ptr(
3569
3479
/*==========================*/
3570
byte* ptr, /*!< in: redo log buffer */
3571
byte* end_ptr,/*!< in: redo log buffer end */
3572
page_t* page, /*!< in/out: uncompressed page */
3573
page_zip_des_t* page_zip)/*!< in/out: compressed page */
3480
/* out: end of log record or NULL */
3481
byte* ptr, /* in: redo log buffer */
3482
byte* end_ptr,/* in: redo log buffer end */
3483
page_t* page, /* in/out: uncompressed page */
3484
page_zip_des_t* page_zip)/* in/out: compressed page */
3576
3487
ulint z_offset;
3619
3530
return(ptr + (2 + 2 + BTR_EXTERN_FIELD_REF_SIZE));
3622
/**********************************************************************//**
3533
/**************************************************************************
3623
3534
Write a BLOB pointer of a record on the leaf page of a clustered index.
3624
3535
The information must already have been updated on the uncompressed page. */
3627
3538
page_zip_write_blob_ptr(
3628
3539
/*====================*/
3629
page_zip_des_t* page_zip,/*!< in/out: compressed page */
3630
const byte* rec, /*!< in/out: record whose data is being
3540
page_zip_des_t* page_zip,/* in/out: compressed page */
3541
const byte* rec, /* in/out: record whose data is being
3632
dict_index_t* index, /*!< in: index of the page */
3633
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
3634
ulint n, /*!< in: column index */
3635
mtr_t* mtr) /*!< in: mini-transaction handle,
3543
dict_index_t* index, /* in: index of the page */
3544
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
3545
ulint n, /* in: column index */
3546
mtr_t* mtr) /* in: mini-transaction handle,
3636
3547
or NULL if no logging is needed */
3638
3549
const byte* field;
3699
3609
memcpy(log_ptr, externs, BTR_EXTERN_FIELD_REF_SIZE);
3700
3610
log_ptr += BTR_EXTERN_FIELD_REF_SIZE;
3701
3611
mlog_close(mtr, log_ptr);
3702
#endif /* !UNIV_HOTBACKUP */
3706
/***********************************************************//**
3707
Parses a log record of writing the node pointer of a record.
3708
@return end of log record or NULL */
3615
/***************************************************************
3616
Parses a log record of writing the node pointer of a record. */
3711
3619
page_zip_parse_write_node_ptr(
3712
3620
/*==========================*/
3713
byte* ptr, /*!< in: redo log buffer */
3714
byte* end_ptr,/*!< in: redo log buffer end */
3715
page_t* page, /*!< in/out: uncompressed page */
3716
page_zip_des_t* page_zip)/*!< in/out: compressed page */
3621
/* out: end of log record or NULL */
3622
byte* ptr, /* in: redo log buffer */
3623
byte* end_ptr,/* in: redo log buffer end */
3624
page_t* page, /* in/out: uncompressed page */
3625
page_zip_des_t* page_zip)/* in/out: compressed page */
3719
3628
ulint z_offset;
3780
3689
return(ptr + (2 + 2 + REC_NODE_PTR_SIZE));
3783
/**********************************************************************//**
3692
/**************************************************************************
3784
3693
Write the node pointer of a record on a non-leaf compressed page. */
3787
3696
page_zip_write_node_ptr(
3788
3697
/*====================*/
3789
page_zip_des_t* page_zip,/*!< in/out: compressed page */
3790
byte* rec, /*!< in/out: record */
3791
ulint size, /*!< in: data size of rec */
3792
ulint ptr, /*!< in: node pointer */
3793
mtr_t* mtr) /*!< in: mini-transaction, or NULL */
3698
page_zip_des_t* page_zip,/* in/out: compressed page */
3699
byte* rec, /* in/out: record */
3700
ulint size, /* in: data size of rec */
3701
ulint ptr, /* in: node pointer */
3702
mtr_t* mtr) /* in: mini-transaction, or NULL */
3797
3706
page_t* page = page_align(rec);
3799
ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
3708
ut_ad(buf_frame_get_page_zip(rec) == page_zip);
3800
3709
ut_ad(page_simple_validate_new(page));
3801
3710
ut_ad(page_zip_simple_validate(page_zip));
3802
3711
ut_ad(page_zip_get_size(page_zip)
3843
3751
memcpy(log_ptr, field, REC_NODE_PTR_SIZE);
3844
3752
log_ptr += REC_NODE_PTR_SIZE;
3845
3753
mlog_close(mtr, log_ptr);
3846
#endif /* !UNIV_HOTBACKUP */
3850
/**********************************************************************//**
3757
/**************************************************************************
3851
3758
Write the trx_id and roll_ptr of a record on a B-tree leaf node page. */
3854
3761
page_zip_write_trx_id_and_roll_ptr(
3855
3762
/*===============================*/
3856
page_zip_des_t* page_zip,/*!< in/out: compressed page */
3857
byte* rec, /*!< in/out: record */
3858
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
3859
ulint trx_id_col,/*!< in: column number of TRX_ID in rec */
3860
trx_id_t trx_id, /*!< in: transaction identifier */
3861
roll_ptr_t roll_ptr)/*!< in: roll_ptr */
3763
page_zip_des_t* page_zip,/* in/out: compressed page */
3764
byte* rec, /* in/out: record */
3765
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
3766
ulint trx_id_col,/* in: column number of TRX_ID in rec */
3767
dulint trx_id, /* in: transaction identifier */
3768
dulint roll_ptr)/* in: roll_ptr */
3865
3772
page_t* page = page_align(rec);
3868
ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
3775
ut_ad(buf_frame_get_page_zip(rec) == page_zip);
3869
3776
ut_ad(page_simple_validate_new(page));
3870
3777
ut_ad(page_zip_simple_validate(page_zip));
3871
3778
ut_ad(page_zip_get_size(page_zip)
3922
3829
UNIV_INTERN ibool page_zip_clear_rec_disable;
3923
3830
#endif /* UNIV_ZIP_DEBUG */
3925
/**********************************************************************//**
3832
/**************************************************************************
3926
3833
Clear an area on the uncompressed and compressed page, if possible. */
3929
3836
page_zip_clear_rec(
3930
3837
/*===============*/
3931
page_zip_des_t* page_zip,/*!< in/out: compressed page */
3932
byte* rec, /*!< in: record to clear */
3933
dict_index_t* index, /*!< in: index of rec */
3934
const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
3838
page_zip_des_t* page_zip,/* in/out: compressed page */
3839
byte* rec, /* in: record to clear */
3840
dict_index_t* index, /* in: index of rec */
3841
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
3937
3844
page_t* page = page_align(rec);
4028
3935
#endif /* UNIV_ZIP_DEBUG */
4031
/**********************************************************************//**
3938
/**************************************************************************
4032
3939
Write the "deleted" flag of a record on a compressed page. The flag must
4033
3940
already have been written on the uncompressed page. */
4036
3943
page_zip_rec_set_deleted(
4037
3944
/*=====================*/
4038
page_zip_des_t* page_zip,/*!< in/out: compressed page */
4039
const byte* rec, /*!< in: record on the uncompressed page */
4040
ulint flag) /*!< in: the deleted flag (nonzero=TRUE) */
3945
page_zip_des_t* page_zip,/* in/out: compressed page */
3946
const byte* rec, /* in: record on the uncompressed page */
3947
ulint flag) /* in: the deleted flag (nonzero=TRUE) */
4042
3949
byte* slot = page_zip_dir_find(page_zip, page_offset(rec));
4052
3959
#endif /* UNIV_ZIP_DEBUG */
4055
/**********************************************************************//**
3962
/**************************************************************************
4056
3963
Write the "owned" flag of a record on a compressed page. The n_owned field
4057
3964
must already have been written on the uncompressed page. */
4060
3967
page_zip_rec_set_owned(
4061
3968
/*===================*/
4062
page_zip_des_t* page_zip,/*!< in/out: compressed page */
4063
const byte* rec, /*!< in: record on the uncompressed page */
4064
ulint flag) /*!< in: the owned flag (nonzero=TRUE) */
3969
page_zip_des_t* page_zip,/* in/out: compressed page */
3970
const byte* rec, /* in: record on the uncompressed page */
3971
ulint flag) /* in: the owned flag (nonzero=TRUE) */
4066
3973
byte* slot = page_zip_dir_find(page_zip, page_offset(rec));
4076
/**********************************************************************//**
3983
/**************************************************************************
4077
3984
Insert a record to the dense page directory. */
4080
3987
page_zip_dir_insert(
4081
3988
/*================*/
4082
page_zip_des_t* page_zip,/*!< in/out: compressed page */
4083
const byte* prev_rec,/*!< in: record after which to insert */
4084
const byte* free_rec,/*!< in: record from which rec was
3989
page_zip_des_t* page_zip,/* in/out: compressed page */
3990
const byte* prev_rec,/* in: record after which to insert */
3991
const byte* free_rec,/* in: record from which rec was
4085
3992
allocated, or NULL */
4086
byte* rec) /*!< in: record to insert */
3993
byte* rec) /* in: record to insert */
4089
3996
byte* slot_rec;
4151
4058
mach_write_to_2(slot_rec - PAGE_ZIP_DIR_SLOT_SIZE, page_offset(rec));
4154
/**********************************************************************//**
4061
/**************************************************************************
4155
4062
Shift the dense page directory and the array of BLOB pointers
4156
4063
when a record is deleted. */
4159
4066
page_zip_dir_delete(
4160
4067
/*================*/
4161
page_zip_des_t* page_zip,/*!< in/out: compressed page */
4162
byte* rec, /*!< in: record to delete */
4163
dict_index_t* index, /*!< in: index of rec */
4164
const ulint* offsets,/*!< in: rec_get_offsets(rec) */
4165
const byte* free) /*!< in: previous start of the free list */
4068
page_zip_des_t* page_zip,/* in/out: compressed page */
4069
byte* rec, /* in: record to delete */
4070
dict_index_t* index, /* in: index of rec */
4071
const ulint* offsets,/* in: rec_get_offsets(rec) */
4072
const byte* free) /* in: previous start of the free list */
4167
4074
byte* slot_rec;
4168
4075
byte* slot_free;
4249
4156
page_zip_clear_rec(page_zip, rec, index, offsets);
4252
/**********************************************************************//**
4159
/**************************************************************************
4253
4160
Add a slot to the dense page directory. */
4256
4163
page_zip_dir_add_slot(
4257
4164
/*==================*/
4258
page_zip_des_t* page_zip, /*!< in/out: compressed page */
4259
ulint is_clustered) /*!< in: nonzero for clustered index,
4165
page_zip_des_t* page_zip, /* in/out: compressed page */
4166
ulint is_clustered) /* in: nonzero for clustered index,
4260
4167
zero for others */
4305
4212
memmove(stored - PAGE_ZIP_DIR_SLOT_SIZE, stored, dir - stored);
4308
/***********************************************************//**
4309
Parses a log record of writing to the header of a page.
4310
@return end of log record or NULL */
4215
/***************************************************************
4216
Parses a log record of writing to the header of a page. */
4313
4219
page_zip_parse_write_header(
4314
4220
/*========================*/
4315
byte* ptr, /*!< in: redo log buffer */
4316
byte* end_ptr,/*!< in: redo log buffer end */
4317
page_t* page, /*!< in/out: uncompressed page */
4318
page_zip_des_t* page_zip)/*!< in/out: compressed page */
4221
/* out: end of log record or NULL */
4222
byte* ptr, /* in: redo log buffer */
4223
byte* end_ptr,/* in: redo log buffer end */
4224
page_t* page, /* in/out: uncompressed page */
4225
page_zip_des_t* page_zip)/* in/out: compressed page */
4363
4270
return(ptr + len);
4366
#ifndef UNIV_HOTBACKUP
4367
/**********************************************************************//**
4273
/**************************************************************************
4368
4274
Write a log record of writing to the uncompressed header portion of a page. */
4371
4277
page_zip_write_header_log(
4372
4278
/*======================*/
4373
const byte* data, /*!< in: data on the uncompressed page */
4374
ulint length, /*!< in: length of the data */
4375
mtr_t* mtr) /*!< in: mini-transaction */
4279
const byte* data, /* in: data on the uncompressed page */
4280
ulint length, /* in: length of the data */
4281
mtr_t* mtr) /* in: mini-transaction */
4377
4283
byte* log_ptr = mlog_open(mtr, 11 + 1 + 1);
4378
4284
ulint offset = page_offset(data);
4408
4313
IMPORTANT: if page_zip_reorganize() is invoked on a leaf page of a
4409
4314
non-clustered index, the caller must update the insert buffer free
4410
4315
bits in the same mini-transaction in such a way that the modification
4411
will be redo-logged.
4412
@return TRUE on success, FALSE on failure; page_zip will be left
4413
intact on failure, but page will be overwritten. */
4316
will be redo-logged. */
4416
4319
page_zip_reorganize(
4417
4320
/*================*/
4418
buf_block_t* block, /*!< in/out: page with compressed page;
4321
/* out: TRUE on success, FALSE on failure;
4322
page and page_zip will be left intact
4324
buf_block_t* block, /* in/out: page with compressed page;
4419
4325
on the compressed page, in: size;
4420
4326
out: data, n_blobs,
4421
4327
m_start, m_end, m_nonempty */
4422
dict_index_t* index, /*!< in: index of the B-tree node */
4423
mtr_t* mtr) /*!< in: mini-transaction */
4328
dict_index_t* index, /* in: index of the B-tree node */
4329
mtr_t* mtr) /* in: mini-transaction */
4425
buf_pool_t* buf_pool = buf_pool_from_block(block);
4426
4331
page_zip_des_t* page_zip = buf_block_get_page_zip(block);
4427
4332
page_t* page = buf_block_get_frame(block);
4428
4333
buf_block_t* temp_block;
4439
4343
/* Disable logging */
4440
4344
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
4442
#ifndef UNIV_HOTBACKUP
4443
temp_block = buf_block_alloc(buf_pool, 0);
4346
temp_block = buf_block_alloc(0);
4347
temp_page = temp_block->frame;
4444
4349
btr_search_drop_page_hash_index(block);
4445
block->check_index_page_at_flush = TRUE;
4446
#else /* !UNIV_HOTBACKUP */
4447
ut_ad(block == back_block1);
4448
temp_block = back_block2;
4449
#endif /* !UNIV_HOTBACKUP */
4450
temp_page = temp_block->frame;
4452
4351
/* Copy the old page to temporary space */
4453
4352
buf_frame_copy(temp_page, page);
4463
4363
page_copy_rec_list_end_no_locks(block, temp_block,
4464
4364
page_get_infimum_rec(temp_page),
4467
if (!dict_index_is_clust(index) && page_is_leaf(temp_page)) {
4468
/* Copy max trx id to recreated page */
4469
trx_id_t max_trx_id = page_get_max_trx_id(temp_page);
4470
page_set_max_trx_id(block, NULL, max_trx_id, NULL);
4471
ut_ad(max_trx_id != 0);
4366
/* Copy max trx id to recreated page */
4367
page_set_max_trx_id(block, NULL, page_get_max_trx_id(temp_page));
4474
4369
/* Restore logging. */
4475
4370
mtr_set_log_mode(mtr, log_mode);
4477
4372
if (UNIV_UNLIKELY(!page_zip_compress(page_zip, page, index, mtr))) {
4479
#ifndef UNIV_HOTBACKUP
4374
/* Restore the old page and exit. */
4375
buf_frame_copy(page, temp_page);
4480
4377
buf_block_free(temp_block);
4481
#endif /* !UNIV_HOTBACKUP */
4485
4381
lock_move_reorganize_page(block, temp_block);
4487
#ifndef UNIV_HOTBACKUP
4488
4383
buf_block_free(temp_block);
4489
#endif /* !UNIV_HOTBACKUP */
4493
#ifndef UNIV_HOTBACKUP
4494
/**********************************************************************//**
4387
/**************************************************************************
4495
4388
Copy the records of a page byte for byte. Do not copy the page header
4496
4389
or trailer, except those B-tree header fields that are directly
4497
4390
related to the storage of records. Also copy PAGE_MAX_TRX_ID.
4501
4394
page_zip_copy_recs(
4502
4395
/*===============*/
4503
page_zip_des_t* page_zip, /*!< out: copy of src_zip
4396
page_zip_des_t* page_zip, /* out: copy of src_zip
4504
4397
(n_blobs, m_start, m_end,
4505
4398
m_nonempty, data[0..size-1]) */
4506
page_t* page, /*!< out: copy of src */
4507
const page_zip_des_t* src_zip, /*!< in: compressed page */
4508
const page_t* src, /*!< in: page */
4509
dict_index_t* index, /*!< in: index of the B-tree */
4510
mtr_t* mtr) /*!< in: mini-transaction */
4399
page_t* page, /* out: copy of src */
4400
const page_zip_des_t* src_zip, /* in: compressed page */
4401
const page_t* src, /* in: page */
4402
dict_index_t* index, /* in: index of the B-tree */
4403
mtr_t* mtr) /* in: mini-transaction */
4512
4405
ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
4513
4406
ut_ad(mtr_memo_contains_page(mtr, (page_t*) src, MTR_MEMO_PAGE_X_FIX));
4514
ut_ad(!dict_index_is_ibuf(index));
4515
4407
#ifdef UNIV_ZIP_DEBUG
4516
4408
/* The B-tree operations that call this function may set
4517
4409
FIL_PAGE_PREV or PAGE_LEVEL, causing a temporary min_rec_flag
4525
4417
ut_a(dict_index_is_clust(index));
4528
/* The PAGE_MAX_TRX_ID must be set on leaf pages of secondary
4529
indexes. It does not matter on other pages. */
4530
ut_a(dict_index_is_clust(index) || !page_is_leaf(src)
4531
|| page_get_max_trx_id(src));
4533
4420
UNIV_MEM_ASSERT_W(page, UNIV_PAGE_SIZE);
4534
4421
UNIV_MEM_ASSERT_W(page_zip->data, page_zip_get_size(page_zip));
4535
4422
UNIV_MEM_ASSERT_RW(src, UNIV_PAGE_SIZE);
4584
4471
page_zip_compress_write_log(page_zip, page, index, mtr);
4586
#endif /* !UNIV_HOTBACKUP */
4588
/**********************************************************************//**
4589
Parses a log record of compressing an index page.
4590
@return end of log record or NULL */
4474
/**************************************************************************
4475
Parses a log record of compressing an index page. */
4593
4478
page_zip_parse_compress(
4594
4479
/*====================*/
4595
byte* ptr, /*!< in: buffer */
4596
byte* end_ptr,/*!< in: buffer end */
4597
page_t* page, /*!< out: uncompressed page */
4598
page_zip_des_t* page_zip)/*!< out: compressed page */
4480
/* out: end of log record or NULL */
4481
byte* ptr, /* in: buffer */
4482
byte* end_ptr,/* in: buffer end */
4483
page_t* page, /* out: uncompressed page */
4484
page_zip_des_t* page_zip)/* out: compressed page */
4601
4487
ulint trailer_size;
4646
4531
return(ptr + 8 + size + trailer_size);
4649
/**********************************************************************//**
4650
Calculate the compressed page checksum.
4651
@return page checksum */
4534
/**************************************************************************
4535
Calculate the compressed page checksum. */
4654
4538
page_zip_calc_checksum(
4655
4539
/*===================*/
4656
const void* data, /*!< in: compressed page */
4657
ulint size) /*!< in: size of compressed page */
4540
/* out: page checksum */
4541
const void* data, /* in: compressed page */
4542
ulint size) /* in: size of compressed page */
4659
4544
/* Exclude FIL_PAGE_SPACE_OR_CHKSUM, FIL_PAGE_LSN,
4660
4545
and FIL_PAGE_FILE_FLUSH_LSN from the checksum. */