~ubuntu-branches/ubuntu/maverick/mysql-5.1/maverick-proposed

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-02-22 14:16:05 UTC
  • mto: This revision was merged to the branch mainline in revision 20.
  • Revision ID: package-import@ubuntu.com-20120222141605-nxlu9yzc6attylc2
Tags: upstream-5.1.61
ImportĀ upstreamĀ versionĀ 5.1.61

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 2005, 2011, Oracle and/or its affiliates. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
151
151
#endif /* !UNIV_HOTBACKUP */
152
152
 
153
153
/*************************************************************//**
 
154
Gets the number of elements in the dense page directory,
 
155
including deleted records (the free list).
 
156
@return number of elements in the dense page directory */
 
157
UNIV_INLINE
 
158
ulint
 
159
page_zip_dir_elems(
 
160
/*===============*/
 
161
        const page_zip_des_t*   page_zip)       /*!< in: compressed page */
 
162
{
 
163
        /* Exclude the page infimum and supremum from the record count. */
 
164
        return(page_dir_get_n_heap(page_zip->data) - PAGE_HEAP_NO_USER_LOW);
 
165
}
 
166
 
 
167
/*************************************************************//**
154
168
Gets the size of the compressed page trailer (the dense page directory),
155
169
including deleted records (the free list).
156
170
@return length of dense page directory, in bytes */
160
174
/*==============*/
161
175
        const page_zip_des_t*   page_zip)       /*!< in: compressed page */
162
176
{
163
 
        /* Exclude the page infimum and supremum from the record count. */
164
 
        ulint   size = PAGE_ZIP_DIR_SLOT_SIZE
165
 
                * (page_dir_get_n_heap(page_zip->data)
166
 
                   - PAGE_HEAP_NO_USER_LOW);
167
 
        return(size);
168
 
}
 
177
        return(PAGE_ZIP_DIR_SLOT_SIZE * page_zip_dir_elems(page_zip));
 
178
}
 
179
 
 
180
/*************************************************************//**
 
181
Gets an offset to the compressed page trailer (the dense page directory),
 
182
including deleted records (the free list).
 
183
@return offset of the dense page directory */
 
184
UNIV_INLINE
 
185
ulint
 
186
page_zip_dir_start_offs(
 
187
/*====================*/
 
188
        const page_zip_des_t*   page_zip,       /*!< in: compressed page */
 
189
        ulint                   n_dense)        /*!< in: directory size */
 
190
{
 
191
        ut_ad(n_dense * PAGE_ZIP_DIR_SLOT_SIZE < page_zip_get_size(page_zip));
 
192
 
 
193
        return(page_zip_get_size(page_zip) - n_dense * PAGE_ZIP_DIR_SLOT_SIZE);
 
194
}
 
195
 
 
196
/*************************************************************//**
 
197
Gets a pointer to the compressed page trailer (the dense page directory),
 
198
including deleted records (the free list).
 
199
@param[in] page_zip     compressed page
 
200
@param[in] n_dense      number of entries in the directory
 
201
@return pointer to the dense page directory */
 
202
#define page_zip_dir_start_low(page_zip, n_dense)                       \
 
203
        ((page_zip)->data + page_zip_dir_start_offs(page_zip, n_dense))
 
204
/*************************************************************//**
 
205
Gets a pointer to the compressed page trailer (the dense page directory),
 
206
including deleted records (the free list).
 
207
@param[in] page_zip     compressed page
 
208
@return pointer to the dense page directory */
 
209
#define page_zip_dir_start(page_zip)                                    \
 
210
        page_zip_dir_start_low(page_zip, page_zip_dir_elems(page_zip))
169
211
 
170
212
/*************************************************************//**
171
213
Gets the size of the compressed page trailer (the dense page directory),
653
695
Allocate memory for zlib. */
654
696
static
655
697
void*
656
 
page_zip_malloc(
 
698
page_zip_zalloc(
657
699
/*============*/
658
700
        void*   opaque, /*!< in/out: memory heap */
659
701
        uInt    items,  /*!< in: number of items to allocate */
660
702
        uInt    size)   /*!< in: size of an item in bytes */
661
703
{
662
 
        return(mem_heap_alloc(opaque, items * size));
 
704
        return(mem_heap_zalloc(opaque, items * size));
663
705
}
664
706
 
665
707
/**********************************************************************//**
684
726
{
685
727
        z_stream*       strm = stream;
686
728
 
687
 
        strm->zalloc = page_zip_malloc;
 
729
        strm->zalloc = page_zip_zalloc;
688
730
        strm->zfree = page_zip_free;
689
731
        strm->opaque = heap;
690
732
}
2242
2284
        }
2243
2285
 
2244
2286
        /* Restore the uncompressed columns in heap_no order. */
2245
 
        storage = page_zip->data + page_zip_get_size(page_zip)
2246
 
                - n_dense * PAGE_ZIP_DIR_SLOT_SIZE;
 
2287
        storage = page_zip_dir_start_low(page_zip, n_dense);
2247
2288
 
2248
2289
        for (slot = 0; slot < n_dense; slot++) {
2249
2290
                rec_t*          rec     = recs[slot];
2728
2769
                return(FALSE);
2729
2770
        }
2730
2771
 
2731
 
        storage = page_zip->data + page_zip_get_size(page_zip)
2732
 
                - n_dense * PAGE_ZIP_DIR_SLOT_SIZE;
 
2772
        storage = page_zip_dir_start_low(page_zip, n_dense);
2733
2773
 
2734
2774
        externs = storage - n_dense
2735
2775
                * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
2912
2952
 
2913
2953
        page_zip_set_alloc(&d_stream, heap);
2914
2954
 
2915
 
        if (UNIV_UNLIKELY(inflateInit2(&d_stream, UNIV_PAGE_SIZE_SHIFT)
2916
 
                          != Z_OK)) {
2917
 
                ut_error;
2918
 
        }
2919
 
 
2920
2955
        d_stream.next_in = page_zip->data + PAGE_DATA;
2921
2956
        /* Subtract the space reserved for
2922
2957
        the page header and the end marker of the modification log. */
2923
2958
        d_stream.avail_in = page_zip_get_size(page_zip) - (PAGE_DATA + 1);
2924
 
 
2925
2959
        d_stream.next_out = page + PAGE_ZIP_START;
2926
2960
        d_stream.avail_out = UNIV_PAGE_SIZE - PAGE_ZIP_START;
2927
2961
 
 
2962
        if (UNIV_UNLIKELY(inflateInit2(&d_stream, UNIV_PAGE_SIZE_SHIFT)
 
2963
                          != Z_OK)) {
 
2964
                ut_error;
 
2965
        }
 
2966
 
2928
2967
        /* Decode the zlib header and the index information. */
2929
2968
        if (UNIV_UNLIKELY(inflate(&d_stream, Z_BLOCK) != Z_OK)) {
2930
2969
 
3458
3497
        }
3459
3498
 
3460
3499
        /* Write the data bytes.  Store the uncompressed bytes separately. */
3461
 
        storage = page_zip->data + page_zip_get_size(page_zip)
3462
 
                - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
3463
 
                * PAGE_ZIP_DIR_SLOT_SIZE;
 
3500
        storage = page_zip_dir_start(page_zip);
3464
3501
 
3465
3502
        if (page_is_leaf(page)) {
3466
3503
                ulint           len;
3756
3793
                field = page + offset;
3757
3794
                storage = page_zip->data + z_offset;
3758
3795
 
3759
 
                storage_end = page_zip->data + page_zip_get_size(page_zip)
3760
 
                        - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
3761
 
                        * PAGE_ZIP_DIR_SLOT_SIZE;
 
3796
                storage_end = page_zip_dir_start(page_zip);
3762
3797
 
3763
3798
                heap_no = 1 + (storage_end - storage) / REC_NODE_PTR_SIZE;
3764
3799
 
3794
3829
{
3795
3830
        byte*   field;
3796
3831
        byte*   storage;
 
3832
#ifdef UNIV_DEBUG
3797
3833
        page_t* page    = page_align(rec);
 
3834
#endif /* UNIV_DEBUG */
3798
3835
 
3799
3836
        ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
3800
3837
        ut_ad(page_simple_validate_new(page));
3811
3848
        UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
3812
3849
        UNIV_MEM_ASSERT_RW(rec, size);
3813
3850
 
3814
 
        storage = page_zip->data + page_zip_get_size(page_zip)
3815
 
                - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
3816
 
                * PAGE_ZIP_DIR_SLOT_SIZE
 
3851
        storage = page_zip_dir_start(page_zip)
3817
3852
                - (rec_get_heap_no_new(rec) - 1) * REC_NODE_PTR_SIZE;
3818
3853
        field = rec + size - REC_NODE_PTR_SIZE;
3819
3854
 
3862
3897
{
3863
3898
        byte*   field;
3864
3899
        byte*   storage;
 
3900
#ifdef UNIV_DEBUG
3865
3901
        page_t* page    = page_align(rec);
 
3902
#endif /* UNIV_DEBUG */
3866
3903
        ulint   len;
3867
3904
 
3868
3905
        ut_ad(PAGE_ZIP_MATCH(rec, page_zip));
3880
3917
 
3881
3918
        UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
3882
3919
 
3883
 
        storage = page_zip->data + page_zip_get_size(page_zip)
3884
 
                - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW)
3885
 
                * PAGE_ZIP_DIR_SLOT_SIZE
 
3920
        storage = page_zip_dir_start(page_zip)
3886
3921
                - (rec_get_heap_no_new(rec) - 1)
3887
3922
                * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
3888
3923
 
3913
3948
        UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
3914
3949
}
3915
3950
 
3916
 
#ifdef UNIV_ZIP_DEBUG
3917
 
/** Set this variable in a debugger to disable page_zip_clear_rec().
3918
 
The only observable effect should be the compression ratio due to
3919
 
deleted records not being zeroed out.  In rare cases, there can be
3920
 
page_zip_validate() failures on the node_ptr, trx_id and roll_ptr
3921
 
columns if the space is reallocated for a smaller record. */
3922
 
UNIV_INTERN ibool       page_zip_clear_rec_disable;
3923
 
#endif /* UNIV_ZIP_DEBUG */
3924
 
 
3925
3951
/**********************************************************************//**
3926
 
Clear an area on the uncompressed and compressed page, if possible. */
 
3952
Clear an area on the uncompressed and compressed page.
 
3953
Do not clear the data payload, as that would grow the modification log. */
3927
3954
static
3928
3955
void
3929
3956
page_zip_clear_rec(
3935
3962
{
3936
3963
        ulint   heap_no;
3937
3964
        page_t* page    = page_align(rec);
 
3965
        byte*   storage;
 
3966
        byte*   field;
 
3967
        ulint   len;
3938
3968
        /* page_zip_validate() would fail here if a record
3939
3969
        containing externally stored columns is being deleted. */
3940
3970
        ut_ad(rec_offs_validate(rec, index, offsets));
3950
3980
        UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
3951
3981
                           rec_offs_extra_size(offsets));
3952
3982
 
3953
 
        if (
3954
 
#ifdef UNIV_ZIP_DEBUG
3955
 
            !page_zip_clear_rec_disable &&
3956
 
#endif /* UNIV_ZIP_DEBUG */
3957
 
            page_zip->m_end
3958
 
            + 1 + ((heap_no - 1) >= 64)/* size of the log entry */
3959
 
            + page_zip_get_trailer_len(page_zip,
3960
 
                                       dict_index_is_clust(index), NULL)
3961
 
            < page_zip_get_size(page_zip)) {
3962
 
                byte*   data;
3963
 
 
3964
 
                /* Clear only the data bytes, because the allocator and
3965
 
                the decompressor depend on the extra bytes. */
3966
 
                memset(rec, 0, rec_offs_data_size(offsets));
3967
 
 
3968
 
                if (!page_is_leaf(page)) {
3969
 
                        /* Clear node_ptr on the compressed page. */
3970
 
                        byte*   storage = page_zip->data
3971
 
                                + page_zip_get_size(page_zip)
3972
 
                                - (page_dir_get_n_heap(page)
3973
 
                                   - PAGE_HEAP_NO_USER_LOW)
3974
 
                                * PAGE_ZIP_DIR_SLOT_SIZE;
3975
 
 
3976
 
                        memset(storage - (heap_no - 1) * REC_NODE_PTR_SIZE,
3977
 
                               0, REC_NODE_PTR_SIZE);
3978
 
                } else if (dict_index_is_clust(index)) {
3979
 
                        /* Clear trx_id and roll_ptr on the compressed page. */
3980
 
                        byte*   storage = page_zip->data
3981
 
                                + page_zip_get_size(page_zip)
3982
 
                                - (page_dir_get_n_heap(page)
3983
 
                                   - PAGE_HEAP_NO_USER_LOW)
3984
 
                                * PAGE_ZIP_DIR_SLOT_SIZE;
3985
 
 
3986
 
                        memset(storage - (heap_no - 1)
3987
 
                               * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN),
3988
 
                               0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
3989
 
                }
3990
 
 
3991
 
                /* Log that the data was zeroed out. */
3992
 
                data = page_zip->data + page_zip->m_end;
3993
 
                ut_ad(!*data);
3994
 
                if (UNIV_UNLIKELY(heap_no - 1 >= 64)) {
3995
 
                        *data++ = (byte) (0x80 | (heap_no - 1) >> 7);
3996
 
                        ut_ad(!*data);
3997
 
                }
3998
 
                *data++ = (byte) ((heap_no - 1) << 1 | 1);
3999
 
                ut_ad(!*data);
4000
 
                ut_ad((ulint) (data - page_zip->data)
4001
 
                      < page_zip_get_size(page_zip));
4002
 
                page_zip->m_end = data - page_zip->data;
4003
 
                page_zip->m_nonempty = TRUE;
4004
 
        } else if (page_is_leaf(page) && dict_index_is_clust(index)) {
4005
 
                /* Do not clear the record, because there is not enough space
4006
 
                to log the operation. */
 
3983
        if (!page_is_leaf(page)) {
 
3984
                /* Clear node_ptr. On the compressed page,
 
3985
                there is an array of node_ptr immediately before the
 
3986
                dense page directory, at the very end of the page. */
 
3987
                storage = page_zip_dir_start(page_zip);
 
3988
                ut_ad(dict_index_get_n_unique_in_tree(index) ==
 
3989
                      rec_offs_n_fields(offsets) - 1);
 
3990
                field   = rec_get_nth_field(rec, offsets,
 
3991
                                            rec_offs_n_fields(offsets) - 1,
 
3992
                                            &len);
 
3993
                ut_ad(len == REC_NODE_PTR_SIZE);
 
3994
 
 
3995
                ut_ad(!rec_offs_any_extern(offsets));
 
3996
                memset(field, 0, REC_NODE_PTR_SIZE);
 
3997
                memset(storage - (heap_no - 1) * REC_NODE_PTR_SIZE,
 
3998
                       0, REC_NODE_PTR_SIZE);
 
3999
        } else if (dict_index_is_clust(index)) {
 
4000
                /* Clear trx_id and roll_ptr. On the compressed page,
 
4001
                there is an array of these fields immediately before the
 
4002
                dense page directory, at the very end of the page. */
 
4003
                const ulint     trx_id_pos
 
4004
                        = dict_col_get_clust_pos(
 
4005
                        dict_table_get_sys_col(
 
4006
                                index->table, DATA_TRX_ID), index);
 
4007
                storage = page_zip_dir_start(page_zip);
 
4008
                field   = rec_get_nth_field(rec, offsets, trx_id_pos, &len);
 
4009
                ut_ad(len == DATA_TRX_ID_LEN);
 
4010
 
 
4011
                memset(field, 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
 
4012
                memset(storage - (heap_no - 1)
 
4013
                       * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN),
 
4014
                       0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
4007
4015
 
4008
4016
                if (rec_offs_any_extern(offsets)) {
4009
4017
                        ulint   i;
4012
4020
                                /* Clear all BLOB pointers in order to make
4013
4021
                                page_zip_validate() pass. */
4014
4022
                                if (rec_offs_nth_extern(offsets, i)) {
4015
 
                                        ulint   len;
4016
 
                                        byte*   field = rec_get_nth_field(
 
4023
                                        field = rec_get_nth_field(
4017
4024
                                                rec, offsets, i, &len);
 
4025
                                        ut_ad(len
 
4026
                                              == BTR_EXTERN_FIELD_REF_SIZE);
4018
4027
                                        memset(field + len
4019
4028
                                               - BTR_EXTERN_FIELD_REF_SIZE,
4020
4029
                                               0, BTR_EXTERN_FIELD_REF_SIZE);
4021
4030
                                }
4022
4031
                        }
4023
4032
                }
 
4033
        } else {
 
4034
                ut_ad(!rec_offs_any_extern(offsets));
4024
4035
        }
4025
4036
 
4026
4037
#ifdef UNIV_ZIP_DEBUG
4439
4450
        log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
4440
4451
 
4441
4452
#ifndef UNIV_HOTBACKUP
4442
 
        temp_block = buf_block_alloc(0);
 
4453
        temp_block = buf_block_alloc();
4443
4454
        btr_search_drop_page_hash_index(block);
4444
4455
        block->check_index_page_at_flush = TRUE;
4445
4456
#else /* !UNIV_HOTBACKUP */
4451
4462
        /* Copy the old page to temporary space */
4452
4463
        buf_frame_copy(temp_page, page);
4453
4464
 
 
4465
        btr_blob_dbg_remove(page, index, "zip_reorg");
 
4466
 
4454
4467
        /* Recreate the page: note that global data on page (possible
4455
4468
        segment headers, next page-field, etc.) is preserved intact */
4456
4469
 
4509
4522
        mtr_t*                  mtr)            /*!< in: mini-transaction */
4510
4523
{
4511
4524
        ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
4512
 
        ut_ad(mtr_memo_contains_page(mtr, (page_t*) src, MTR_MEMO_PAGE_X_FIX));
 
4525
        ut_ad(mtr_memo_contains_page(mtr, src, MTR_MEMO_PAGE_X_FIX));
4513
4526
        ut_ad(!dict_index_is_ibuf(index));
4514
4527
#ifdef UNIV_ZIP_DEBUG
4515
4528
        /* The B-tree operations that call this function may set
4579
4592
#ifdef UNIV_ZIP_DEBUG
4580
4593
        ut_a(page_zip_validate(page_zip, page));
4581
4594
#endif /* UNIV_ZIP_DEBUG */
 
4595
        btr_blob_dbg_add(page, index, "page_zip_copy_recs");
4582
4596
 
4583
4597
        page_zip_compress_write_log(page_zip, page, index, mtr);
4584
4598
}