~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/page/page0zip.c

  • Committer: Jay Pipes
  • Date: 2009-03-13 23:35:46 UTC
  • mto: This revision was merged to the branch mainline in revision 937.
  • Revision ID: jpipes@serialcoder-20090313233546-n12t6xpf71um75fo
Split index hints out into their own file, removal from sql_lex.h and sql_select.cc

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
4
 
 
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.
8
 
 
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.
12
 
 
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
16
 
 
17
 
*****************************************************************************/
18
 
 
19
 
/**************************************************//**
20
 
@file page/page0zip.c
 
1
/******************************************************
21
2
Compressed page interface
22
3
 
 
4
(c) 2005 Innobase Oy
 
5
 
23
6
Created June 2005 by Marko Makela
24
7
*******************************************************/
25
8
 
32
15
#include "page0page.h"
33
16
#include "mtr0log.h"
34
17
#include "ut0sort.h"
 
18
#include "dict0boot.h"
35
19
#include "dict0dict.h"
 
20
#include "btr0sea.h"
36
21
#include "btr0cur.h"
37
22
#include "page0types.h"
 
23
#include "lock0lock.h"
38
24
#include "log0recv.h"
39
25
#include "zlib.h"
40
 
#ifndef UNIV_HOTBACKUP
41
 
# include "buf0lru.h"
42
 
# include "btr0sea.h"
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 */
 
26
#include "buf0lru.h"
49
27
 
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 */
54
30
 
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) */
66
41
};
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" */
71
45
};
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 */
79
52
};
80
53
 
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))
91
61
 
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. */
100
69
static
101
70
int
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 */
106
76
{
107
77
        int     res;
108
78
        va_list ap;
115
85
 
116
86
        return(res);
117
87
}
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 */
126
92
 
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. */
131
95
UNIV_INTERN
132
96
ulint
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 */
137
102
{
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);
150
115
}
151
 
#endif /* !UNIV_HOTBACKUP */
152
116
 
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). */
157
120
UNIV_INLINE
158
121
ulint
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 */
162
127
{
163
128
        /* Exclude the page infimum and supremum from the record count. */
164
129
        ulint   size = PAGE_ZIP_DIR_SLOT_SIZE
167
132
        return(size);
168
133
}
169
134
 
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). */
174
138
UNIV_INLINE
175
139
ulint
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
 
144
                                                records, in bytes */
 
145
        const page_zip_des_t*   page_zip)       /* in: compressed page */
179
146
{
180
147
        ulint   size = PAGE_ZIP_DIR_SLOT_SIZE
181
148
                * page_get_n_recs(page_zip->data);
183
150
        return(size);
184
151
}
185
152
 
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. */
189
155
UNIV_INLINE
190
156
byte*
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 */
196
164
{
197
165
        ut_ad(slot <= end);
198
166
 
206
174
        return(NULL);
207
175
}
208
176
 
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. */
212
179
UNIV_INLINE
213
180
byte*
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 */
218
187
{
219
188
        byte*   end     = page_zip->data + page_zip_get_size(page_zip);
220
189
 
225
194
                                     offset));
226
195
}
227
196
 
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. */
231
199
UNIV_INLINE
232
200
byte*
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 */
237
207
{
238
208
        byte*   end     = page_zip->data + page_zip_get_size(page_zip);
239
209
 
244
214
                                     offset));
245
215
}
246
216
 
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. */
251
219
UNIV_INLINE
252
220
ulint
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,
 
225
                                                possibly ORed with
 
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) */
258
231
{
259
232
        ut_ad(page_zip_simple_validate(page_zip));
262
235
                                - PAGE_ZIP_DIR_SLOT_SIZE * (slot + 1)));
263
236
}
264
237
 
265
 
#ifndef UNIV_HOTBACKUP
266
 
/**********************************************************************//**
 
238
/**************************************************************************
267
239
Write a log record of compressing an index page. */
268
240
static
269
241
void
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 */
276
248
{
277
249
        byte*   log_ptr;
278
250
        ulint   trailer_size;
279
251
 
280
 
        ut_ad(!dict_index_is_ibuf(index));
281
 
 
282
252
        log_ptr = mlog_open(mtr, 11 + 2 + 2);
283
253
 
284
254
        if (!log_ptr) {
326
296
        mlog_catenate_string(mtr, page_zip->data + page_zip_get_size(page_zip)
327
297
                             - trailer_size, trailer_size);
328
298
}
329
 
#endif /* !UNIV_HOTBACKUP */
330
299
 
331
 
/******************************************************//**
 
300
/**********************************************************
332
301
Determine how many externally stored columns are contained
333
302
in existing records with smaller heap_no than rec. */
334
303
static
335
304
ulint
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 */
343
312
{
344
313
        const page_t*   page    = page_align(rec);
345
314
        ulint           n_ext   = 0;
352
321
        ut_ad(page_is_comp(page));
353
322
        ut_ad(dict_table_is_comp(index->table));
354
323
        ut_ad(dict_index_is_clust(index));
355
 
        ut_ad(!dict_index_is_ibuf(index));
356
324
 
357
325
        heap_no = rec_get_heap_no_new(rec);
358
326
        ut_ad(heap_no >= PAGE_HEAP_NO_USER_LOW);
377
345
        return(n_ext);
378
346
}
379
347
 
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. */
383
350
static
384
351
byte*
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 */
389
357
{
390
358
        ut_ad(val >= 2);
391
359
 
405
373
        return(buf);
406
374
}
407
375
 
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. */
411
378
static
412
379
ulint
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 */
421
389
{
422
390
        const byte*     buf_start       = buf;
423
391
        ulint           i;
533
501
        return((ulint) (buf - buf_start));
534
502
}
535
503
 
536
 
/**********************************************************************//**
 
504
/**************************************************************************
537
505
Populate the dense page directory from the sparse directory. */
538
506
static
539
507
void
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) */
548
516
{
571
539
        /* Traverse the list of stored records in the collation order,
572
540
        starting from the first user record. */
573
541
 
574
 
        rec = page + PAGE_NEW_INFIMUM;
 
542
        rec = page + PAGE_NEW_INFIMUM, TRUE;
575
543
 
576
544
        i = 0;
577
545
 
649
617
        ut_a(i + PAGE_HEAP_NO_USER_LOW == n_heap);
650
618
}
651
619
 
652
 
/**********************************************************************//**
 
620
/**************************************************************************
653
621
Allocate memory for zlib. */
654
622
static
655
623
void*
656
624
page_zip_malloc(
657
625
/*============*/
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 */
 
626
        void*   opaque,
 
627
        uInt    items,
 
628
        uInt    size)
661
629
{
662
630
        return(mem_heap_alloc(opaque, items * size));
663
631
}
664
632
 
665
 
/**********************************************************************//**
 
633
/**************************************************************************
666
634
Deallocate memory for zlib. */
667
635
static
668
636
void
669
637
page_zip_free(
670
638
/*==========*/
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)))
673
641
{
674
642
}
675
643
 
676
 
/**********************************************************************//**
 
644
/**************************************************************************
677
645
Configure the zlib allocator to use the given memory heap. */
678
646
UNIV_INTERN
679
647
void
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 */
684
652
{
685
653
        z_stream*       strm = stream;
686
654
 
690
658
}
691
659
 
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
695
662
#endif
696
663
 
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;
706
673
 
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. */
710
676
static
711
 
int
 
677
ibool
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 */
717
683
{
718
684
        int     status;
719
685
        if (UNIV_UNLIKELY(page_zip_compress_dbg)) {
731
697
 
732
698
/* Redefine deflate(). */
733
699
# undef 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 */
748
705
# define LOGFILE
749
706
#endif /* PAGE_ZIP_COMPRESS_DBG */
750
707
 
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. */
754
710
static
755
711
int
756
712
page_zip_compress_node_ptrs(
757
713
/*========================*/
 
714
                                        /* out: Z_OK, or a zlib error code */
758
715
        FILE_LOGFILE
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 */
766
723
{
767
724
        int     err     = Z_OK;
768
725
        ulint*  offsets = NULL;
813
770
        return(err);
814
771
}
815
772
 
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. */
819
775
static
820
776
int
821
777
page_zip_compress_sec(
822
778
/*==================*/
 
779
                                        /* out: Z_OK, or a zlib error code */
823
780
        FILE_LOGFILE
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[] */
828
785
{
829
786
        int             err     = Z_OK;
830
787
 
857
814
        return(err);
858
815
}
859
816
 
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. */
864
820
static
865
821
int
866
822
page_zip_compress_clust_ext(
867
823
/*========================*/
 
824
                                        /* out: Z_OK, or a zlib error code */
868
825
        FILE_LOGFILE
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 */
880
837
{
881
838
        int     err;
985
942
        return(Z_OK);
986
943
}
987
944
 
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. */
991
947
static
992
948
int
993
949
page_zip_compress_clust(
994
950
/*====================*/
 
951
                                        /* out: Z_OK, or a zlib error code */
995
952
        FILE_LOGFILE
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 */
1008
965
{
1009
966
        int     err             = Z_OK;
1010
967
        ulint*  offsets         = NULL;
1118
1075
        return(err);
1119
1076
}
1120
1077
 
1121
 
/**********************************************************************//**
1122
 
Compress a page.
1123
 
@return TRUE on success, FALSE on failure; page_zip will be left
1124
 
intact on failure. */
 
1078
/**************************************************************************
 
1079
Compress a page. */
1125
1080
UNIV_INTERN
1126
1081
ibool
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 */
1134
1091
{
1135
1092
        z_stream        c_stream;
1136
1093
        int             err;
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 */
1141
1098
        ulint           n_dense;
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;
1154
1109
#endif
1157
1112
        ut_a(fil_page_get_type(page) == FIL_PAGE_INDEX);
1158
1113
        ut_ad(page_simple_validate_new((page_t*) page));
1159
1114
        ut_ad(page_zip_simple_validate(page_zip));
1160
 
        ut_ad(dict_table_is_comp(index->table));
1161
 
        ut_ad(!dict_index_is_ibuf(index));
1162
1115
 
1163
1116
        UNIV_MEM_ASSERT_RW(page, UNIV_PAGE_SIZE);
1164
1117
 
1212
1165
                }
1213
1166
        }
1214
1167
#endif /* PAGE_ZIP_COMPRESS_DBG */
1215
 
#ifndef UNIV_HOTBACKUP
1216
1168
        page_zip_stat[page_zip->ssize - 1].compressed++;
1217
 
#endif /* !UNIV_HOTBACKUP */
1218
1169
 
1219
1170
        if (UNIV_UNLIKELY(n_dense * PAGE_ZIP_DIR_SLOT_SIZE
1220
1171
                          >= page_zip_get_size(page_zip))) {
1351
1302
                        fclose(logfile);
1352
1303
                }
1353
1304
#endif /* PAGE_ZIP_COMPRESS_DBG */
1354
 
#ifndef UNIV_HOTBACKUP
1355
1305
                page_zip_stat[page_zip->ssize - 1].compressed_usec
1356
1306
                        += ut_time_us(NULL) - usec;
1357
 
#endif /* !UNIV_HOTBACKUP */
1358
1307
                return(FALSE);
1359
1308
        }
1360
1309
 
1395
1344
#endif /* UNIV_ZIP_DEBUG */
1396
1345
 
1397
1346
        if (mtr) {
1398
 
#ifndef UNIV_HOTBACKUP
1399
1347
                page_zip_compress_write_log(page_zip, page, index, mtr);
1400
 
#endif /* !UNIV_HOTBACKUP */
1401
1348
        }
1402
1349
 
1403
1350
        UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
1412
1359
                fclose(logfile);
1413
1360
        }
1414
1361
#endif /* PAGE_ZIP_COMPRESS_DBG */
1415
 
#ifndef UNIV_HOTBACKUP
1416
1362
        {
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;
1421
1367
        }
1422
 
#endif /* !UNIV_HOTBACKUP */
1423
1368
 
1424
1369
        return(TRUE);
1425
1370
}
1426
1371
 
1427
 
/**********************************************************************//**
1428
 
Compare two page directory entries.
1429
 
@return positive if rec1 > rec2 */
 
1372
/**************************************************************************
 
1373
Compare two page directory entries. */
1430
1374
UNIV_INLINE
1431
1375
ibool
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 */
1436
1381
{
1437
1382
        return(rec1 > rec2);
1438
1383
}
1439
1384
 
1440
 
/**********************************************************************//**
 
1385
/**************************************************************************
1441
1386
Sort the dense page directory by address (heap_no). */
1442
1387
static
1443
1388
void
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 */
1450
1395
{
1451
1396
        UT_SORT_FUNCTION_BODY(page_zip_dir_sort, arr, aux_arr, low, high,
1452
1397
                              page_zip_dir_cmp);
1453
1398
}
1454
1399
 
1455
 
/**********************************************************************//**
 
1400
/**************************************************************************
1456
1401
Deallocate the index information initialized by page_zip_fields_decode(). */
1457
1402
static
1458
1403
void
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 */
1462
1407
{
1463
1408
        if (index) {
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);
1469
1413
        }
1470
1414
}
1471
1415
 
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. */
1475
1418
static
1476
1419
dict_index_t*
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,
 
1423
                                or NULL on error */
 
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 */
1484
1429
{
1585
1530
        return(index);
1586
1531
}
1587
1532
 
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. */
1591
1535
static
1592
1536
ibool
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,
 
1540
                                        FALSE on failure */
 
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
1599
1545
                                        filled in */
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[] */
1605
1551
{
1606
1552
        ulint   i;
1682
1628
        return(TRUE);
1683
1629
}
1684
1630
 
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. */
1688
1633
static
1689
1634
ibool
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,
 
1638
                                        FALSE on failure */
 
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 */
1695
1642
{
1696
1643
        ulint   n;
1697
1644
        ulint   i;
1779
1726
        return(TRUE);
1780
1727
}
1781
1728
 
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. */
1786
1732
static
1787
1733
const byte*
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 */
1795
1743
{
1796
1744
        ulint   i;
1797
1745
        ulint   len;
1868
1816
        return(data);
1869
1817
}
1870
1818
 
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. */
1875
1822
static
1876
1823
const byte*
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() */
1893
1842
{
1894
1843
        const byte* const end = data + size;
2069
2018
        }
2070
2019
}
2071
2020
 
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. */
2075
2023
static
2076
2024
ibool
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,
 
2028
                                        FALSE on failure */
 
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 */
2087
2037
{
2088
2038
        ulint           heap_status = REC_STATUS_NODE_PTR
2089
2039
                | PAGE_HEAP_NO_USER_LOW << REC_HEAP_NO_SHIFT;
2262
2212
        return(TRUE);
2263
2213
}
2264
2214
 
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. */
2268
2217
static
2269
2218
ibool
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,
 
2222
                                        FALSE on failure */
 
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 */
2279
2230
{
2280
2231
        ulint   heap_status     = REC_STATUS_ORDINARY
2281
2232
                | PAGE_HEAP_NO_USER_LOW << REC_HEAP_NO_SHIFT;
2403
2354
        return(TRUE);
2404
2355
}
2405
2356
 
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. */
2410
2360
static
2411
2361
ibool
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 */
2418
2369
{
2419
2370
        ulint   i;
2420
2371
 
2512
2463
        return(TRUE);
2513
2464
}
2514
2465
 
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. */
2518
2468
static
2519
2469
ibool
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,
 
2473
                                        FALSE on failure */
 
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 */
2531
2483
{
2532
2484
        int             err;
2533
2485
        ulint           slot;
2811
2763
        return(TRUE);
2812
2764
}
2813
2765
 
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. */
2819
2770
UNIV_INTERN
2820
2771
ibool
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 */
2830
2778
{
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 */
2841
2787
 
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));
2858
2804
 
2859
 
        if (all) {
2860
 
                /* Copy the page header. */
2861
 
                memcpy(page, page_zip->data, PAGE_DATA);
2862
 
        } else {
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 */
2872
 
 
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);
2877
 
 
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 */
2882
 
        }
2883
 
 
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);
2889
2812
 
2890
2813
        /* Copy the page directory. */
2891
2814
        if (UNIV_UNLIKELY(!page_zip_dir_decode(page_zip, page, recs,
3016
2939
 
3017
2940
        page_zip_fields_free(index);
3018
2941
        mem_heap_free(heap);
3019
 
#ifndef UNIV_HOTBACKUP
3020
2942
        {
3021
2943
                page_zip_stat_t*        zip_stat
3022
2944
                        = &page_zip_stat[page_zip->ssize - 1];
3023
2945
                zip_stat->decompressed++;
3024
2946
                zip_stat->decompressed_usec += ut_time_us(NULL) - usec;
3025
2947
        }
3026
 
#endif /* !UNIV_HOTBACKUP */
3027
2948
 
3028
2949
        /* Update the stat counter for LRU policy. */
3029
2950
        buf_LRU_stat_inc_unzip();
3032
2953
}
3033
2954
 
3034
2955
#ifdef UNIV_ZIP_DEBUG
3035
 
/**********************************************************************//**
 
2956
/**************************************************************************
3036
2957
Dump a block of memory on the standard error stream. */
3037
2958
static
3038
2959
void
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 */
3044
2965
{
3045
2966
        const byte*     s       = buf;
3046
2967
        ulint           addr;
3063
2984
        }
3064
2985
}
3065
2986
 
3066
 
/** Dump a block of memory on the standard error stream.
3067
 
@param buf      in: data
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)
3070
2988
 
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;
3073
2991
 
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. */
3077
2994
UNIV_INTERN
3078
2995
ibool
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 */
3085
3003
{
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
3125
 
        pad bytes. */
3126
3040
        UNIV_MEM_ASSERT_RW(page_zip, sizeof *page_zip);
3127
 
# endif
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 */
3132
3045
 
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);
3135
3048
        if (!valid) {
3136
3049
                fputs("page_zip_validate(): failed to decompress\n", stderr);
3137
3050
                goto func_exit;
3213
3126
        return(valid);
3214
3127
}
3215
3128
 
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. */
3219
3131
UNIV_INTERN
3220
3132
ibool
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 */
3225
3138
{
3226
3139
        return(page_zip_validate_low(page_zip, page,
3227
3140
                                     recv_recovery_is_on()));
3229
3142
#endif /* UNIV_ZIP_DEBUG */
3230
3143
 
3231
3144
#ifdef UNIV_DEBUG
3232
 
/**********************************************************************//**
3233
 
Assert that the compressed and decompressed page headers match.
3234
 
@return TRUE */
3235
3145
static
3236
3146
ibool
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 */
 
3149
                                        /* out: TRUE */
 
3150
        const page_zip_des_t*   page_zip,/* in: compressed page */
 
3151
        const byte*             page)   /* in: uncompressed page */
3241
3152
{
3242
3153
        ut_ad(!memcmp(page_zip->data + FIL_PAGE_PREV, page + FIL_PAGE_PREV,
3243
3154
                      FIL_PAGE_LSN - FIL_PAGE_PREV));
3250
3161
}
3251
3162
#endif /* UNIV_DEBUG */
3252
3163
 
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. */
3257
3167
static
3258
3168
byte*
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 */
3271
3182
{
3272
3183
        const byte*     start   = rec;
3273
3184
        ulint           i;
3372
3283
        return(data);
3373
3284
}
3374
3285
 
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. */
3378
3289
UNIV_INTERN
3379
3290
void
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 */
3387
3298
{
3388
3299
        const page_t*   page;
3389
3300
        byte*           data;
3391
3302
        ulint           heap_no;
3392
3303
        byte*           slot;
3393
3304
 
3394
 
        ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
 
3305
        ut_ad(buf_frame_get_page_zip(rec) == page_zip);
3395
3306
        ut_ad(page_zip_simple_validate(page_zip));
3396
3307
        ut_ad(page_zip_get_size(page_zip)
3397
3308
              > PAGE_DATA + page_zip_dir_size(page_zip));
3560
3471
#endif /* UNIV_ZIP_DEBUG */
3561
3472
}
3562
3473
 
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. */
3566
3476
UNIV_INTERN
3567
3477
byte*
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 */
3574
3485
{
3575
3486
        ulint   offset;
3576
3487
        ulint   z_offset;
3619
3530
        return(ptr + (2 + 2 + BTR_EXTERN_FIELD_REF_SIZE));
3620
3531
}
3621
3532
 
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. */
3625
3536
UNIV_INTERN
3626
3537
void
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
3631
3542
                                written */
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 */
3637
3548
{
3638
3549
        const byte*     field;
3641
3552
        ulint           blob_no;
3642
3553
        ulint           len;
3643
3554
 
3644
 
        ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
 
3555
        ut_ad(buf_frame_get_page_zip(rec) == page_zip);
3645
3556
        ut_ad(page_simple_validate_new((page_t*) page));
3646
3557
        ut_ad(page_zip_simple_validate(page_zip));
3647
3558
        ut_ad(page_zip_get_size(page_zip)
3683
3594
#endif /* UNIV_ZIP_DEBUG */
3684
3595
 
3685
3596
        if (mtr) {
3686
 
#ifndef UNIV_HOTBACKUP
3687
3597
                byte*   log_ptr = mlog_open(
3688
3598
                        mtr, 11 + 2 + 2 + BTR_EXTERN_FIELD_REF_SIZE);
3689
3599
                if (UNIV_UNLIKELY(!log_ptr)) {
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 */
3703
3612
        }
3704
3613
}
3705
3614
 
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. */
3709
3617
UNIV_INTERN
3710
3618
byte*
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 */
3717
3626
{
3718
3627
        ulint   offset;
3719
3628
        ulint   z_offset;
3780
3689
        return(ptr + (2 + 2 + REC_NODE_PTR_SIZE));
3781
3690
}
3782
3691
 
3783
 
/**********************************************************************//**
 
3692
/**************************************************************************
3784
3693
Write the node pointer of a record on a non-leaf compressed page. */
3785
3694
UNIV_INTERN
3786
3695
void
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 */
3794
3703
{
3795
3704
        byte*   field;
3796
3705
        byte*   storage;
3797
3706
        page_t* page    = page_align(rec);
3798
3707
 
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)
3827
3736
        memcpy(storage, field, REC_NODE_PTR_SIZE);
3828
3737
 
3829
3738
        if (mtr) {
3830
 
#ifndef UNIV_HOTBACKUP
3831
3739
                byte*   log_ptr = mlog_open(mtr,
3832
3740
                                            11 + 2 + 2 + REC_NODE_PTR_SIZE);
3833
3741
                if (UNIV_UNLIKELY(!log_ptr)) {
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 */
3847
3754
        }
3848
3755
}
3849
3756
 
3850
 
/**********************************************************************//**
 
3757
/**************************************************************************
3851
3758
Write the trx_id and roll_ptr of a record on a B-tree leaf node page. */
3852
3759
UNIV_INTERN
3853
3760
void
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 */
3862
3769
{
3863
3770
        byte*   field;
3864
3771
        byte*   storage;
3865
3772
        page_t* page    = page_align(rec);
3866
3773
        ulint   len;
3867
3774
 
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)
3914
3821
}
3915
3822
 
3916
3823
#ifdef UNIV_ZIP_DEBUG
3917
 
/** Set this variable in a debugger to disable page_zip_clear_rec().
 
3824
/* Set this variable in a debugger to disable page_zip_clear_rec().
3918
3825
The only observable effect should be the compression ratio due to
3919
3826
deleted records not being zeroed out.  In rare cases, there can be
3920
3827
page_zip_validate() failures on the node_ptr, trx_id and roll_ptr
3922
3829
UNIV_INTERN ibool       page_zip_clear_rec_disable;
3923
3830
#endif /* UNIV_ZIP_DEBUG */
3924
3831
 
3925
 
/**********************************************************************//**
 
3832
/**************************************************************************
3926
3833
Clear an area on the uncompressed and compressed page, if possible. */
3927
3834
static
3928
3835
void
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) */
3935
3842
{
3936
3843
        ulint   heap_no;
3937
3844
        page_t* page    = page_align(rec);
4028
3935
#endif /* UNIV_ZIP_DEBUG */
4029
3936
}
4030
3937
 
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. */
4034
3941
UNIV_INTERN
4035
3942
void
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) */
4041
3948
{
4042
3949
        byte*   slot = page_zip_dir_find(page_zip, page_offset(rec));
4043
3950
        ut_a(slot);
4052
3959
#endif /* UNIV_ZIP_DEBUG */
4053
3960
}
4054
3961
 
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. */
4058
3965
UNIV_INTERN
4059
3966
void
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) */
4065
3972
{
4066
3973
        byte*   slot = page_zip_dir_find(page_zip, page_offset(rec));
4067
3974
        ut_a(slot);
4073
3980
        }
4074
3981
}
4075
3982
 
4076
 
/**********************************************************************//**
 
3983
/**************************************************************************
4077
3984
Insert a record to the dense page directory. */
4078
3985
UNIV_INTERN
4079
3986
void
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 */
4087
3994
{
4088
3995
        ulint   n_dense;
4089
3996
        byte*   slot_rec;
4151
4058
        mach_write_to_2(slot_rec - PAGE_ZIP_DIR_SLOT_SIZE, page_offset(rec));
4152
4059
}
4153
4060
 
4154
 
/**********************************************************************//**
 
4061
/**************************************************************************
4155
4062
Shift the dense page directory and the array of BLOB pointers
4156
4063
when a record is deleted. */
4157
4064
UNIV_INTERN
4158
4065
void
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 */
4166
4073
{
4167
4074
        byte*   slot_rec;
4168
4075
        byte*   slot_free;
4249
4156
        page_zip_clear_rec(page_zip, rec, index, offsets);
4250
4157
}
4251
4158
 
4252
 
/**********************************************************************//**
 
4159
/**************************************************************************
4253
4160
Add a slot to the dense page directory. */
4254
4161
UNIV_INTERN
4255
4162
void
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 */
4261
4168
{
4262
4169
        ulint   n_dense;
4305
4212
        memmove(stored - PAGE_ZIP_DIR_SLOT_SIZE, stored, dir - stored);
4306
4213
}
4307
4214
 
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. */
4311
4217
UNIV_INTERN
4312
4218
byte*
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 */
4319
4226
{
4320
4227
        ulint   offset;
4321
4228
        ulint   len;
4363
4270
        return(ptr + len);
4364
4271
}
4365
4272
 
4366
 
#ifndef UNIV_HOTBACKUP
4367
 
/**********************************************************************//**
 
4273
/**************************************************************************
4368
4274
Write a log record of writing to the uncompressed header portion of a page. */
4369
4275
UNIV_INTERN
4370
4276
void
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 */
4376
4282
{
4377
4283
        byte*   log_ptr = mlog_open(mtr, 11 + 1 + 1);
4378
4284
        ulint   offset  = page_offset(data);
4398
4304
 
4399
4305
        mlog_catenate_string(mtr, data, length);
4400
4306
}
4401
 
#endif /* !UNIV_HOTBACKUP */
4402
4307
 
4403
 
/**********************************************************************//**
 
4308
/**************************************************************************
4404
4309
Reorganize and compress a page.  This is a low-level operation for
4405
4310
compressed pages, to be used when page_zip_compress() fails.
4406
4311
On success, a redo log entry MLOG_ZIP_PAGE_COMPRESS will be written.
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. */
4414
4317
UNIV_INTERN
4415
4318
ibool
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
 
4323
                                on failure. */
 
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 */
4424
4330
{
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;
4431
4336
 
4432
4337
        ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
4433
4338
        ut_ad(page_is_comp(page));
4434
 
        ut_ad(!dict_index_is_ibuf(index));
4435
4339
        /* Note that page_zip_validate(page_zip, page) may fail here. */
4436
4340
        UNIV_MEM_ASSERT_RW(page, UNIV_PAGE_SIZE);
4437
4341
        UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
4439
4343
        /* Disable logging */
4440
4344
        log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
4441
4345
 
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;
 
4348
 
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;
4451
4350
 
4452
4351
        /* Copy the old page to temporary space */
4453
4352
        buf_frame_copy(temp_page, page);
4456
4355
        segment headers, next page-field, etc.) is preserved intact */
4457
4356
 
4458
4357
        page_create(block, mtr, TRUE);
 
4358
        block->check_index_page_at_flush = TRUE;
4459
4359
 
4460
4360
        /* Copy the records from the temporary space to the recreated page;
4461
4361
        do not copy the lock bits yet */
4463
4363
        page_copy_rec_list_end_no_locks(block, temp_block,
4464
4364
                                        page_get_infimum_rec(temp_page),
4465
4365
                                        index, mtr);
4466
 
 
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);
4472
 
        }
 
4366
        /* Copy max trx id to recreated page */
 
4367
        page_set_max_trx_id(block, NULL, page_get_max_trx_id(temp_page));
4473
4368
 
4474
4369
        /* Restore logging. */
4475
4370
        mtr_set_log_mode(mtr, log_mode);
4476
4371
 
4477
4372
        if (UNIV_UNLIKELY(!page_zip_compress(page_zip, page, index, mtr))) {
4478
4373
 
4479
 
#ifndef UNIV_HOTBACKUP
 
4374
                /* Restore the old page and exit. */
 
4375
                buf_frame_copy(page, temp_page);
 
4376
 
4480
4377
                buf_block_free(temp_block);
4481
 
#endif /* !UNIV_HOTBACKUP */
4482
4378
                return(FALSE);
4483
4379
        }
4484
4380
 
4485
4381
        lock_move_reorganize_page(block, temp_block);
4486
4382
 
4487
 
#ifndef UNIV_HOTBACKUP
4488
4383
        buf_block_free(temp_block);
4489
 
#endif /* !UNIV_HOTBACKUP */
4490
4384
        return(TRUE);
4491
4385
}
4492
4386
 
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.
4500
4393
void
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 */
4511
4404
{
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));
4526
4418
        }
4527
4419
 
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));
4532
 
 
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);
4583
4470
 
4584
4471
        page_zip_compress_write_log(page_zip, page, index, mtr);
4585
4472
}
4586
 
#endif /* !UNIV_HOTBACKUP */
4587
4473
 
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. */
4591
4476
UNIV_INTERN
4592
4477
byte*
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 */
4599
4485
{
4600
4486
        ulint   size;
4601
4487
        ulint   trailer_size;
4636
4522
                memcpy(page_zip->data + page_zip_get_size(page_zip)
4637
4523
                       - trailer_size, ptr + 8 + size, trailer_size);
4638
4524
 
4639
 
                if (UNIV_UNLIKELY(!page_zip_decompress(page_zip, page,
4640
 
                                                       TRUE))) {
 
4525
                if (UNIV_UNLIKELY(!page_zip_decompress(page_zip, page))) {
4641
4526
 
4642
4527
                        goto corrupt;
4643
4528
                }
4646
4531
        return(ptr + 8 + size + trailer_size);
4647
4532
}
4648
4533
 
4649
 
/**********************************************************************//**
4650
 
Calculate the compressed page checksum.
4651
 
@return page checksum */
 
4534
/**************************************************************************
 
4535
Calculate the compressed page checksum. */
4652
4536
UNIV_INTERN
4653
4537
ulint
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 */
4658
4543
{
4659
4544
        /* Exclude FIL_PAGE_SPACE_OR_CHKSUM, FIL_PAGE_LSN,
4660
4545
        and FIL_PAGE_FILE_FLUSH_LSN from the checksum. */