~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2009-01-24 09:43:35 UTC
  • Revision ID: brian@gir-3.local-20090124094335-6qdtvc35gl5fvivz
Adding in an example singe thread scheduler

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (c) 1994, 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., 59 Temple
15
 
Place, Suite 330, Boston, MA 02111-1307 USA
16
 
 
17
 
*****************************************************************************/
18
 
 
19
 
/**************************************************//**
20
 
@file page/page0page.c
 
1
/******************************************************
21
2
Index page routines
22
3
 
 
4
(c) 1994-1996 Innobase Oy
 
5
 
23
6
Created 2/2/1994 Heikki Tuuri
24
7
*******************************************************/
25
8
 
30
13
 
31
14
#include "page0cur.h"
32
15
#include "page0zip.h"
 
16
#include "lock0lock.h"
 
17
#include "fut0lst.h"
 
18
#include "btr0sea.h"
33
19
#include "buf0buf.h"
 
20
#include "srv0srv.h"
34
21
#include "btr0btr.h"
35
 
#ifndef UNIV_HOTBACKUP
36
 
# include "srv0srv.h"
37
 
# include "lock0lock.h"
38
 
# include "fut0lst.h"
39
 
# include "btr0sea.h"
40
 
#endif /* !UNIV_HOTBACKUP */
41
22
 
42
23
/*                      THE INDEX PAGE
43
24
                        ==============
81
62
index contains 300 index entries, and the size of the page directory
82
63
is 50 x 4 bytes = 200 bytes. */
83
64
 
84
 
/***************************************************************//**
85
 
Looks for the directory slot which owns the given record.
86
 
@return the directory slot number */
 
65
/*******************************************************************
 
66
Looks for the directory slot which owns the given record. */
87
67
UNIV_INTERN
88
68
ulint
89
69
page_dir_find_owner_slot(
90
70
/*=====================*/
91
 
        const rec_t*    rec)    /*!< in: the physical record */
 
71
                                /* out: the directory slot number */
 
72
        const rec_t*    rec)    /* in: the physical record */
92
73
{
93
74
        const page_t*                   page;
94
75
        register uint16                 rec_offs_bytes;
157
138
        return(((ulint) (first_slot - slot)) / PAGE_DIR_SLOT_SIZE);
158
139
}
159
140
 
160
 
/**************************************************************//**
161
 
Used to check the consistency of a directory slot.
162
 
@return TRUE if succeed */
 
141
/******************************************************************
 
142
Used to check the consistency of a directory slot. */
163
143
static
164
144
ibool
165
145
page_dir_slot_check(
166
146
/*================*/
167
 
        page_dir_slot_t*        slot)   /*!< in: slot */
 
147
                                        /* out: TRUE if succeed */
 
148
        page_dir_slot_t*        slot)   /* in: slot */
168
149
{
169
150
        page_t* page;
170
151
        ulint   n_slots;
200
181
        return(TRUE);
201
182
}
202
183
 
203
 
/*************************************************************//**
 
184
/*****************************************************************
204
185
Sets the max trx id field value. */
205
186
UNIV_INTERN
206
187
void
207
188
page_set_max_trx_id(
208
189
/*================*/
209
 
        buf_block_t*    block,  /*!< in/out: page */
210
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
211
 
        trx_id_t        trx_id, /*!< in: transaction id */
212
 
        mtr_t*          mtr)    /*!< in/out: mini-transaction, or NULL */
 
190
        buf_block_t*    block,  /* in/out: page */
 
191
        page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
 
192
        dulint          trx_id) /* in: transaction id */
213
193
{
 
194
        const ibool     is_hashed       = block->is_hashed;
214
195
        page_t*         page            = buf_block_get_frame(block);
215
 
#ifndef UNIV_HOTBACKUP
216
 
        const ibool     is_hashed       = block->is_hashed;
217
196
 
218
197
        if (is_hashed) {
219
198
                rw_lock_x_lock(&btr_search_latch);
220
199
        }
221
200
 
222
 
        ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
223
 
#endif /* !UNIV_HOTBACKUP */
224
 
 
225
201
        /* It is not necessary to write this change to the redo log, as
226
202
        during a database recovery we assume that the max trx id of every
227
203
        page is the maximum trx id assigned before the crash. */
228
204
 
 
205
        mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id);
229
206
        if (UNIV_LIKELY_NULL(page_zip)) {
230
 
                mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id);
231
207
                page_zip_write_header(page_zip,
232
208
                                      page + (PAGE_HEADER + PAGE_MAX_TRX_ID),
233
 
                                      8, mtr);
234
 
#ifndef UNIV_HOTBACKUP
235
 
        } else if (mtr) {
236
 
                mlog_write_dulint(page + (PAGE_HEADER + PAGE_MAX_TRX_ID),
237
 
                                  trx_id, mtr);
238
 
#endif /* !UNIV_HOTBACKUP */
239
 
        } else {
240
 
                mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id);
 
209
                                      8, NULL);
241
210
        }
242
211
 
243
 
#ifndef UNIV_HOTBACKUP
244
212
        if (is_hashed) {
245
213
                rw_lock_x_unlock(&btr_search_latch);
246
214
        }
247
 
#endif /* !UNIV_HOTBACKUP */
248
215
}
249
216
 
250
 
/************************************************************//**
251
 
Allocates a block of memory from the heap of an index page.
252
 
@return pointer to start of allocated buffer, or NULL if allocation fails */
 
217
/****************************************************************
 
218
Allocates a block of memory from the heap of an index page. */
253
219
UNIV_INTERN
254
220
byte*
255
221
page_mem_alloc_heap(
256
222
/*================*/
257
 
        page_t*         page,   /*!< in/out: index page */
258
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page with enough
 
223
                                /* out: pointer to start of allocated
 
224
                                buffer, or NULL if allocation fails */
 
225
        page_t*         page,   /* in/out: index page */
 
226
        page_zip_des_t* page_zip,/* in/out: compressed page with enough
259
227
                                space available for inserting the record,
260
228
                                or NULL */
261
 
        ulint           need,   /*!< in: total number of bytes needed */
262
 
        ulint*          heap_no)/*!< out: this contains the heap number
 
229
        ulint           need,   /* in: total number of bytes needed */
 
230
        ulint*          heap_no)/* out: this contains the heap number
263
231
                                of the allocated record
264
232
                                if allocation succeeds */
265
233
{
285
253
        return(NULL);
286
254
}
287
255
 
288
 
#ifndef UNIV_HOTBACKUP
289
 
/**********************************************************//**
 
256
/**************************************************************
290
257
Writes a log record of page creation. */
291
258
UNIV_INLINE
292
259
void
293
260
page_create_write_log(
294
261
/*==================*/
295
 
        buf_frame_t*    frame,  /*!< in: a buffer frame where the page is
 
262
        buf_frame_t*    frame,  /* in: a buffer frame where the page is
296
263
                                created */
297
 
        mtr_t*          mtr,    /*!< in: mini-transaction handle */
298
 
        ibool           comp)   /*!< in: TRUE=compact page format */
 
264
        mtr_t*          mtr,    /* in: mini-transaction handle */
 
265
        ibool           comp)   /* in: TRUE=compact page format */
299
266
{
300
267
        mlog_write_initial_log_record(frame, comp
301
268
                                      ? MLOG_COMP_PAGE_CREATE
302
269
                                      : MLOG_PAGE_CREATE, mtr);
303
270
}
304
 
#else /* !UNIV_HOTBACKUP */
305
 
# define page_create_write_log(frame,mtr,comp) ((void) 0)
306
 
#endif /* !UNIV_HOTBACKUP */
307
271
 
308
 
/***********************************************************//**
309
 
Parses a redo log record of creating a page.
310
 
@return end of log record or NULL */
 
272
/***************************************************************
 
273
Parses a redo log record of creating a page. */
311
274
UNIV_INTERN
312
275
byte*
313
276
page_parse_create(
314
277
/*==============*/
315
 
        byte*           ptr,    /*!< in: buffer */
316
 
        byte*           end_ptr __attribute__((unused)), /*!< in: buffer end */
317
 
        ulint           comp,   /*!< in: nonzero=compact page format */
318
 
        buf_block_t*    block,  /*!< in: block or NULL */
319
 
        mtr_t*          mtr)    /*!< in: mtr or NULL */
 
278
                                /* out: end of log record or NULL */
 
279
        byte*           ptr,    /* in: buffer */
 
280
        byte*           end_ptr __attribute__((unused)), /* in: buffer end */
 
281
        ulint           comp,   /* in: nonzero=compact page format */
 
282
        buf_block_t*    block,  /* in: block or NULL */
 
283
        mtr_t*          mtr)    /* in: mtr or NULL */
320
284
{
321
285
        ut_ad(ptr && end_ptr);
322
286
 
329
293
        return(ptr);
330
294
}
331
295
 
332
 
/**********************************************************//**
333
 
The index page creation function.
334
 
@return pointer to the page */
 
296
/**************************************************************
 
297
The index page creation function. */
335
298
static
336
299
page_t*
337
300
page_create_low(
338
301
/*============*/
339
 
        buf_block_t*    block,          /*!< in: a buffer block where the
 
302
                                        /* out: pointer to the page */
 
303
        buf_block_t*    block,          /* in: a buffer block where the
340
304
                                        page is created */
341
 
        ulint           comp)           /*!< in: nonzero=compact page format */
 
305
        ulint           comp)           /* in: nonzero=compact page format */
342
306
{
343
307
        page_dir_slot_t* slot;
344
308
        mem_heap_t*     heap;
361
325
 
362
326
        /* The infimum and supremum records use a dummy index. */
363
327
        if (UNIV_LIKELY(comp)) {
364
 
                index = dict_ind_compact;
 
328
                index = srv_sys->dummy_ind2;
365
329
        } else {
366
 
                index = dict_ind_redundant;
 
330
                index = srv_sys->dummy_ind1;
367
331
        }
368
332
 
369
333
        /* 1. INCREMENT MODIFY CLOCK */
455
419
        page_header_set_field(page, NULL, PAGE_DIRECTION, PAGE_NO_DIRECTION);
456
420
        page_header_set_field(page, NULL, PAGE_N_DIRECTION, 0);
457
421
        page_header_set_field(page, NULL, PAGE_N_RECS, 0);
458
 
        page_set_max_trx_id(block, NULL, ut_dulint_zero, NULL);
 
422
        page_set_max_trx_id(block, NULL, ut_dulint_zero);
459
423
        memset(heap_top, 0, UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START
460
424
               - page_offset(heap_top));
461
425
 
482
446
        return(page);
483
447
}
484
448
 
485
 
/**********************************************************//**
486
 
Create an uncompressed B-tree index page.
487
 
@return pointer to the page */
 
449
/**************************************************************
 
450
Create an uncompressed B-tree index page. */
488
451
UNIV_INTERN
489
452
page_t*
490
453
page_create(
491
454
/*========*/
492
 
        buf_block_t*    block,          /*!< in: a buffer block where the
 
455
                                        /* out: pointer to the page */
 
456
        buf_block_t*    block,          /* in: a buffer block where the
493
457
                                        page is created */
494
 
        mtr_t*          mtr,            /*!< in: mini-transaction handle */
495
 
        ulint           comp)           /*!< in: nonzero=compact page format */
 
458
        mtr_t*          mtr,            /* in: mini-transaction handle */
 
459
        ulint           comp)           /* in: nonzero=compact page format */
496
460
{
497
461
        page_create_write_log(buf_block_get_frame(block), mtr, comp);
498
462
        return(page_create_low(block, comp));
499
463
}
500
464
 
501
 
/**********************************************************//**
502
 
Create a compressed B-tree index page.
503
 
@return pointer to the page */
 
465
/**************************************************************
 
466
Create a compressed B-tree index page. */
504
467
UNIV_INTERN
505
468
page_t*
506
469
page_create_zip(
507
470
/*============*/
508
 
        buf_block_t*    block,          /*!< in/out: a buffer frame where the
 
471
                                        /* out: pointer to the page */
 
472
        buf_block_t*    block,          /* in/out: a buffer frame where the
509
473
                                        page is created */
510
 
        dict_index_t*   index,          /*!< in: the index of the page */
511
 
        ulint           level,          /*!< in: the B-tree level of the page */
512
 
        mtr_t*          mtr)            /*!< in: mini-transaction handle */
 
474
        dict_index_t*   index,          /* in: the index of the page */
 
475
        ulint           level,          /* in: the B-tree level of the page */
 
476
        mtr_t*          mtr)            /* in: mini-transaction handle */
513
477
{
514
478
        page_t*         page;
515
479
        page_zip_des_t* page_zip        = buf_block_get_page_zip(block);
531
495
        return(page);
532
496
}
533
497
 
534
 
/*************************************************************//**
 
498
/*****************************************************************
535
499
Differs from page_copy_rec_list_end, because this function does not
536
500
touch the lock table and max trx id on page or compress the page. */
537
501
UNIV_INTERN
538
502
void
539
503
page_copy_rec_list_end_no_locks(
540
504
/*============================*/
541
 
        buf_block_t*    new_block,      /*!< in: index page to copy to */
542
 
        buf_block_t*    block,          /*!< in: index page of rec */
543
 
        rec_t*          rec,            /*!< in: record on page */
544
 
        dict_index_t*   index,          /*!< in: record descriptor */
545
 
        mtr_t*          mtr)            /*!< in: mtr */
 
505
        buf_block_t*    new_block,      /* in: index page to copy to */
 
506
        buf_block_t*    block,          /* in: index page of rec */
 
507
        rec_t*          rec,            /* in: record on page */
 
508
        dict_index_t*   index,          /* in: record descriptor */
 
509
        mtr_t*          mtr)            /* in: mtr */
546
510
{
547
511
        page_t*         new_page        = buf_block_get_frame(new_block);
548
512
        page_cur_t      cur1;
602
566
        }
603
567
}
604
568
 
605
 
#ifndef UNIV_HOTBACKUP
606
 
/*************************************************************//**
 
569
/*****************************************************************
607
570
Copies records from page to new_page, from a given record onward,
608
571
including that record. Infimum and supremum records are not copied.
609
 
The records are copied to the start of the record list on new_page.
610
 
@return pointer to the original successor of the infimum record on
611
 
new_page, or NULL on zip overflow (new_block will be decompressed) */
 
572
The records are copied to the start of the record list on new_page. */
612
573
UNIV_INTERN
613
574
rec_t*
614
575
page_copy_rec_list_end(
615
576
/*===================*/
616
 
        buf_block_t*    new_block,      /*!< in/out: index page to copy to */
617
 
        buf_block_t*    block,          /*!< in: index page containing rec */
618
 
        rec_t*          rec,            /*!< in: record on page */
619
 
        dict_index_t*   index,          /*!< in: record descriptor */
620
 
        mtr_t*          mtr)            /*!< in: mtr */
 
577
                                        /* out: pointer to the original
 
578
                                        successor of the infimum record
 
579
                                        on new_page, or NULL on zip overflow
 
580
                                        (new_block will be decompressed) */
 
581
        buf_block_t*    new_block,      /* in/out: index page to copy to */
 
582
        buf_block_t*    block,          /* in: index page containing rec */
 
583
        rec_t*          rec,            /* in: record on page */
 
584
        dict_index_t*   index,          /* in: record descriptor */
 
585
        mtr_t*          mtr)            /* in: mtr */
621
586
{
622
587
        page_t*         new_page        = buf_block_get_frame(new_block);
623
588
        page_zip_des_t* new_page_zip    = buf_block_get_page_zip(new_block);
698
663
 
699
664
        lock_move_rec_list_end(new_block, block, rec);
700
665
 
701
 
        if (dict_index_is_sec_or_ibuf(index) && page_is_leaf(page)) {
702
 
                page_update_max_trx_id(new_block, new_page_zip,
703
 
                                       page_get_max_trx_id(page), mtr);
704
 
        }
 
666
        page_update_max_trx_id(new_block, new_page_zip,
 
667
                               page_get_max_trx_id(page));
705
668
 
706
669
        btr_search_move_or_delete_hash_entries(new_block, block, index);
707
670
 
708
671
        return(ret);
709
672
}
710
673
 
711
 
/*************************************************************//**
 
674
/*****************************************************************
712
675
Copies records from page to new_page, up to the given record,
713
676
NOT including that record. Infimum and supremum records are not copied.
714
 
The records are copied to the end of the record list on new_page.
715
 
@return pointer to the original predecessor of the supremum record on
716
 
new_page, or NULL on zip overflow (new_block will be decompressed) */
 
677
The records are copied to the end of the record list on new_page. */
717
678
UNIV_INTERN
718
679
rec_t*
719
680
page_copy_rec_list_start(
720
681
/*=====================*/
721
 
        buf_block_t*    new_block,      /*!< in/out: index page to copy to */
722
 
        buf_block_t*    block,          /*!< in: index page containing rec */
723
 
        rec_t*          rec,            /*!< in: record on page */
724
 
        dict_index_t*   index,          /*!< in: record descriptor */
725
 
        mtr_t*          mtr)            /*!< in: mtr */
 
682
                                        /* out: pointer to the original
 
683
                                        predecessor of the supremum record
 
684
                                        on new_page, or NULL on zip overflow
 
685
                                        (new_block will be decompressed) */
 
686
        buf_block_t*    new_block,      /* in/out: index page to copy to */
 
687
        buf_block_t*    block,          /* in: index page containing rec */
 
688
        rec_t*          rec,            /* in: record on page */
 
689
        dict_index_t*   index,          /* in: record descriptor */
 
690
        mtr_t*          mtr)            /* in: mtr */
726
691
{
727
692
        page_t*         new_page        = buf_block_get_frame(new_block);
728
693
        page_zip_des_t* new_page_zip    = buf_block_get_page_zip(new_block);
809
774
 
810
775
        /* Update MAX_TRX_ID, the lock table, and possible hash index */
811
776
 
812
 
        if (dict_index_is_sec_or_ibuf(index)
813
 
            && page_is_leaf(page_align(rec))) {
814
 
                page_update_max_trx_id(new_block, new_page_zip,
815
 
                                       page_get_max_trx_id(page_align(rec)),
816
 
                                       mtr);
817
 
        }
 
777
        page_update_max_trx_id(new_block, new_page_zip,
 
778
                               page_get_max_trx_id(page_align(rec)));
818
779
 
819
780
        lock_move_rec_list_start(new_block, block, rec, ret);
820
781
 
823
784
        return(ret);
824
785
}
825
786
 
826
 
/**********************************************************//**
 
787
/**************************************************************
827
788
Writes a log record of a record list end or start deletion. */
828
789
UNIV_INLINE
829
790
void
830
791
page_delete_rec_list_write_log(
831
792
/*===========================*/
832
 
        rec_t*          rec,    /*!< in: record on page */
833
 
        dict_index_t*   index,  /*!< in: record descriptor */
834
 
        byte            type,   /*!< in: operation type:
 
793
        rec_t*          rec,    /* in: record on page */
 
794
        dict_index_t*   index,  /* in: record descriptor */
 
795
        byte            type,   /* in: operation type:
835
796
                                MLOG_LIST_END_DELETE, ... */
836
 
        mtr_t*          mtr)    /*!< in: mtr */
 
797
        mtr_t*          mtr)    /* in: mtr */
837
798
{
838
799
        byte*   log_ptr;
839
800
        ut_ad(type == MLOG_LIST_END_DELETE
848
809
                mlog_close(mtr, log_ptr + 2);
849
810
        }
850
811
}
851
 
#else /* !UNIV_HOTBACKUP */
852
 
# define page_delete_rec_list_write_log(rec,index,type,mtr) ((void) 0)
853
 
#endif /* !UNIV_HOTBACKUP */
854
812
 
855
 
/**********************************************************//**
856
 
Parses a log record of a record list end or start deletion.
857
 
@return end of log record or NULL */
 
813
/**************************************************************
 
814
Parses a log record of a record list end or start deletion. */
858
815
UNIV_INTERN
859
816
byte*
860
817
page_parse_delete_rec_list(
861
818
/*=======================*/
862
 
        byte            type,   /*!< in: MLOG_LIST_END_DELETE,
 
819
                                /* out: end of log record or NULL */
 
820
        byte            type,   /* in: MLOG_LIST_END_DELETE,
863
821
                                MLOG_LIST_START_DELETE,
864
822
                                MLOG_COMP_LIST_END_DELETE or
865
823
                                MLOG_COMP_LIST_START_DELETE */
866
 
        byte*           ptr,    /*!< in: buffer */
867
 
        byte*           end_ptr,/*!< in: buffer end */
868
 
        buf_block_t*    block,  /*!< in/out: buffer block or NULL */
869
 
        dict_index_t*   index,  /*!< in: record descriptor */
870
 
        mtr_t*          mtr)    /*!< in: mtr or NULL */
 
824
        byte*           ptr,    /* in: buffer */
 
825
        byte*           end_ptr,/* in: buffer end */
 
826
        buf_block_t*    block,  /* in/out: buffer block or NULL */
 
827
        dict_index_t*   index,  /* in: record descriptor */
 
828
        mtr_t*          mtr)    /* in: mtr or NULL */
871
829
{
872
830
        page_t* page;
873
831
        ulint   offset;
908
866
        return(ptr);
909
867
}
910
868
 
911
 
/*************************************************************//**
 
869
/*****************************************************************
912
870
Deletes records from a page from a given record onward, including that record.
913
871
The infimum and supremum records are not deleted. */
914
872
UNIV_INTERN
915
873
void
916
874
page_delete_rec_list_end(
917
875
/*=====================*/
918
 
        rec_t*          rec,    /*!< in: pointer to record on page */
919
 
        buf_block_t*    block,  /*!< in: buffer block of the page */
920
 
        dict_index_t*   index,  /*!< in: record descriptor */
921
 
        ulint           n_recs, /*!< in: number of records to delete,
 
876
        rec_t*          rec,    /* in: pointer to record on page */
 
877
        buf_block_t*    block,  /* in: buffer block of the page */
 
878
        dict_index_t*   index,  /* in: record descriptor */
 
879
        ulint           n_recs, /* in: number of records to delete,
922
880
                                or ULINT_UNDEFINED if not known */
923
 
        ulint           size,   /*!< in: the sum of the sizes of the
 
881
        ulint           size,   /* in: the sum of the sizes of the
924
882
                                records in the end of the chain to
925
883
                                delete, or ULINT_UNDEFINED if not known */
926
 
        mtr_t*          mtr)    /*!< in: mtr */
 
884
        mtr_t*          mtr)    /* in: mtr */
927
885
{
928
886
        page_dir_slot_t*slot;
929
887
        ulint           slot_index;
1084
1042
                              (ulint)(page_get_n_recs(page) - n_recs));
1085
1043
}
1086
1044
 
1087
 
/*************************************************************//**
 
1045
/*****************************************************************
1088
1046
Deletes records from page, up to the given record, NOT including
1089
1047
that record. Infimum and supremum records are not deleted. */
1090
1048
UNIV_INTERN
1091
1049
void
1092
1050
page_delete_rec_list_start(
1093
1051
/*=======================*/
1094
 
        rec_t*          rec,    /*!< in: record on page */
1095
 
        buf_block_t*    block,  /*!< in: buffer block of the page */
1096
 
        dict_index_t*   index,  /*!< in: record descriptor */
1097
 
        mtr_t*          mtr)    /*!< in: mtr */
 
1052
        rec_t*          rec,    /* in: record on page */
 
1053
        buf_block_t*    block,  /* in: buffer block of the page */
 
1054
        dict_index_t*   index,  /* in: record descriptor */
 
1055
        mtr_t*          mtr)    /* in: mtr */
1098
1056
{
1099
1057
        page_cur_t      cur1;
1100
1058
        ulint           log_mode;
1156
1114
        mtr_set_log_mode(mtr, log_mode);
1157
1115
}
1158
1116
 
1159
 
#ifndef UNIV_HOTBACKUP
1160
 
/*************************************************************//**
 
1117
/*****************************************************************
1161
1118
Moves record list end to another page. Moved records include
1162
 
split_rec.
1163
 
@return TRUE on success; FALSE on compression failure (new_block will
1164
 
be decompressed) */
 
1119
split_rec. */
1165
1120
UNIV_INTERN
1166
1121
ibool
1167
1122
page_move_rec_list_end(
1168
1123
/*===================*/
1169
 
        buf_block_t*    new_block,      /*!< in/out: index page where to move */
1170
 
        buf_block_t*    block,          /*!< in: index page from where to move */
1171
 
        rec_t*          split_rec,      /*!< in: first record to move */
1172
 
        dict_index_t*   index,          /*!< in: record descriptor */
1173
 
        mtr_t*          mtr)            /*!< in: mtr */
 
1124
                                        /* out: TRUE on success; FALSE on
 
1125
                                        compression failure
 
1126
                                        (new_block will be decompressed) */
 
1127
        buf_block_t*    new_block,      /* in/out: index page where to move */
 
1128
        buf_block_t*    block,          /* in: index page from where to move */
 
1129
        rec_t*          split_rec,      /* in: first record to move */
 
1130
        dict_index_t*   index,          /* in: record descriptor */
 
1131
        mtr_t*          mtr)            /* in: mtr */
1174
1132
{
1175
1133
        page_t*         new_page        = buf_block_get_frame(new_block);
1176
1134
        ulint           old_data_size;
1211
1169
        return(TRUE);
1212
1170
}
1213
1171
 
1214
 
/*************************************************************//**
 
1172
/*****************************************************************
1215
1173
Moves record list start to another page. Moved records do not include
1216
 
split_rec.
1217
 
@return TRUE on success; FALSE on compression failure */
 
1174
split_rec. */
1218
1175
UNIV_INTERN
1219
1176
ibool
1220
1177
page_move_rec_list_start(
1221
1178
/*=====================*/
1222
 
        buf_block_t*    new_block,      /*!< in/out: index page where to move */
1223
 
        buf_block_t*    block,          /*!< in/out: page containing split_rec */
1224
 
        rec_t*          split_rec,      /*!< in: first record not to move */
1225
 
        dict_index_t*   index,          /*!< in: record descriptor */
1226
 
        mtr_t*          mtr)            /*!< in: mtr */
 
1179
                                        /* out: TRUE on success; FALSE on
 
1180
                                        compression failure */
 
1181
        buf_block_t*    new_block,      /* in/out: index page where to move */
 
1182
        buf_block_t*    block,          /* in/out: page containing split_rec */
 
1183
        rec_t*          split_rec,      /* in: first record not to move */
 
1184
        dict_index_t*   index,          /* in: record descriptor */
 
1185
        mtr_t*          mtr)            /* in: mtr */
1227
1186
{
1228
1187
        if (UNIV_UNLIKELY(!page_copy_rec_list_start(new_block, block,
1229
1188
                                                    split_rec, index, mtr))) {
1235
1194
        return(TRUE);
1236
1195
}
1237
1196
 
1238
 
/***********************************************************************//**
 
1197
/***************************************************************************
1239
1198
This is a low-level operation which is used in a database index creation
1240
1199
to update the page number of a created B-tree to a data dictionary record. */
1241
1200
UNIV_INTERN
1242
1201
void
1243
1202
page_rec_write_index_page_no(
1244
1203
/*=========================*/
1245
 
        rec_t*  rec,    /*!< in: record to update */
1246
 
        ulint   i,      /*!< in: index of the field to update */
1247
 
        ulint   page_no,/*!< in: value to write */
1248
 
        mtr_t*  mtr)    /*!< in: mtr */
 
1204
        rec_t*  rec,    /* in: record to update */
 
1205
        ulint   i,      /* in: index of the field to update */
 
1206
        ulint   page_no,/* in: value to write */
 
1207
        mtr_t*  mtr)    /* in: mtr */
1249
1208
{
1250
1209
        byte*   data;
1251
1210
        ulint   len;
1256
1215
 
1257
1216
        mlog_write_ulint(data, page_no, MLOG_4BYTES, mtr);
1258
1217
}
1259
 
#endif /* !UNIV_HOTBACKUP */
1260
1218
 
1261
 
/**************************************************************//**
 
1219
/******************************************************************
1262
1220
Used to delete n slots from the directory. This function updates
1263
1221
also n_owned fields in the records, so that the first slot after
1264
1222
the deleted ones inherits the records of the deleted slots. */
1266
1224
void
1267
1225
page_dir_delete_slot(
1268
1226
/*=================*/
1269
 
        page_t*         page,   /*!< in/out: the index page */
1270
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
1271
 
        ulint           slot_no)/*!< in: slot to be deleted */
 
1227
        page_t*         page,   /* in/out: the index page */
 
1228
        page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
 
1229
        ulint           slot_no)/* in: slot to be deleted */
1272
1230
{
1273
1231
        page_dir_slot_t*        slot;
1274
1232
        ulint                   n_owned;
1307
1265
        page_header_set_field(page, page_zip, PAGE_N_DIR_SLOTS, n_slots - 1);
1308
1266
}
1309
1267
 
1310
 
/**************************************************************//**
 
1268
/******************************************************************
1311
1269
Used to add n slots to the directory. Does not set the record pointers
1312
1270
in the added slots or update n_owned values: this is the responsibility
1313
1271
of the caller. */
1315
1273
void
1316
1274
page_dir_add_slot(
1317
1275
/*==============*/
1318
 
        page_t*         page,   /*!< in/out: the index page */
1319
 
        page_zip_des_t* page_zip,/*!< in/out: comprssed page, or NULL */
1320
 
        ulint           start)  /*!< in: the slot above which the new slots
 
1276
        page_t*         page,   /* in/out: the index page */
 
1277
        page_zip_des_t* page_zip,/* in/out: comprssed page, or NULL */
 
1278
        ulint           start)  /* in: the slot above which the new slots
1321
1279
                                are added */
1322
1280
{
1323
1281
        page_dir_slot_t*        slot;
1336
1294
                (n_slots - 1 - start) * PAGE_DIR_SLOT_SIZE);
1337
1295
}
1338
1296
 
1339
 
/****************************************************************//**
 
1297
/********************************************************************
1340
1298
Splits a directory slot which owns too many records. */
1341
1299
UNIV_INTERN
1342
1300
void
1343
1301
page_dir_split_slot(
1344
1302
/*================*/
1345
 
        page_t*         page,   /*!< in/out: index page */
1346
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page whose
 
1303
        page_t*         page,   /* in/out: index page */
 
1304
        page_zip_des_t* page_zip,/* in/out: compressed page whose
1347
1305
                                uncompressed part will be written, or NULL */
1348
 
        ulint           slot_no)/*!< in: the directory slot */
 
1306
        ulint           slot_no)/* in: the directory slot */
1349
1307
{
1350
1308
        rec_t*                  rec;
1351
1309
        page_dir_slot_t*        new_slot;
1397
1355
        page_dir_slot_set_n_owned(slot, page_zip, n_owned - (n_owned / 2));
1398
1356
}
1399
1357
 
1400
 
/*************************************************************//**
 
1358
/*****************************************************************
1401
1359
Tries to balance the given directory slot with too few records with the upper
1402
1360
neighbor, so that there are at least the minimum number of records owned by
1403
1361
the slot; this may result in the merging of two slots. */
1405
1363
void
1406
1364
page_dir_balance_slot(
1407
1365
/*==================*/
1408
 
        page_t*         page,   /*!< in/out: index page */
1409
 
        page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
1410
 
        ulint           slot_no)/*!< in: the directory slot */
 
1366
        page_t*         page,   /* in/out: index page */
 
1367
        page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
 
1368
        ulint           slot_no)/* in: the directory slot */
1411
1369
{
1412
1370
        page_dir_slot_t*        slot;
1413
1371
        page_dir_slot_t*        up_slot;
1468
1426
        }
1469
1427
}
1470
1428
 
1471
 
#ifndef UNIV_HOTBACKUP
1472
 
/************************************************************//**
 
1429
/****************************************************************
1473
1430
Returns the middle record of the record list. If there are an even number
1474
 
of records in the list, returns the first record of the upper half-list.
1475
 
@return middle record */
 
1431
of records in the list, returns the first record of the upper half-list. */
1476
1432
UNIV_INTERN
1477
1433
rec_t*
1478
1434
page_get_middle_rec(
1479
1435
/*================*/
1480
 
        page_t* page)   /*!< in: page */
 
1436
                        /* out: middle record */
 
1437
        page_t* page)   /* in: page */
1481
1438
{
1482
1439
        page_dir_slot_t*        slot;
1483
1440
        ulint                   middle;
1516
1473
 
1517
1474
        return(rec);
1518
1475
}
1519
 
#endif /* !UNIV_HOTBACKUP */
1520
1476
 
1521
 
/***************************************************************//**
 
1477
/*******************************************************************
1522
1478
Returns the number of records before the given record in chain.
1523
 
The number includes infimum and supremum records.
1524
 
@return number of records */
 
1479
The number includes infimum and supremum records. */
1525
1480
UNIV_INTERN
1526
1481
ulint
1527
1482
page_rec_get_n_recs_before(
1528
1483
/*=======================*/
1529
 
        const rec_t*    rec)    /*!< in: the physical record */
 
1484
                                /* out: number of records */
 
1485
        const rec_t*    rec)    /* in: the physical record */
1530
1486
{
1531
1487
        const page_dir_slot_t*  slot;
1532
1488
        const rec_t*            slot_rec;
1582
1538
        return((ulint) n);
1583
1539
}
1584
1540
 
1585
 
#ifndef UNIV_HOTBACKUP
1586
 
/************************************************************//**
 
1541
/****************************************************************
1587
1542
Prints record contents including the data relevant only in
1588
1543
the index page context. */
1589
1544
UNIV_INTERN
1590
1545
void
1591
1546
page_rec_print(
1592
1547
/*===========*/
1593
 
        const rec_t*    rec,    /*!< in: physical record */
1594
 
        const ulint*    offsets)/*!< in: record descriptor */
 
1548
        const rec_t*    rec,    /* in: physical record */
 
1549
        const ulint*    offsets)/* in: record descriptor */
1595
1550
{
1596
1551
        ut_a(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
1597
1552
        rec_print_new(stderr, rec, offsets);
1613
1568
        rec_validate(rec, offsets);
1614
1569
}
1615
1570
 
1616
 
/***************************************************************//**
 
1571
/*******************************************************************
1617
1572
This is used to print the contents of the directory for
1618
1573
debugging purposes. */
1619
1574
UNIV_INTERN
1620
1575
void
1621
1576
page_dir_print(
1622
1577
/*===========*/
1623
 
        page_t* page,   /*!< in: index page */
1624
 
        ulint   pr_n)   /*!< in: print n first and n last entries */
 
1578
        page_t* page,   /* in: index page */
 
1579
        ulint   pr_n)   /* in: print n first and n last entries */
1625
1580
{
1626
1581
        ulint                   n;
1627
1582
        ulint                   i;
1655
1610
                (ulong) (PAGE_HEAP_NO_USER_LOW + page_get_n_recs(page)));
1656
1611
}
1657
1612
 
1658
 
/***************************************************************//**
 
1613
/*******************************************************************
1659
1614
This is used to print the contents of the page record list for
1660
1615
debugging purposes. */
1661
1616
UNIV_INTERN
1662
1617
void
1663
1618
page_print_list(
1664
1619
/*============*/
1665
 
        buf_block_t*    block,  /*!< in: index page */
1666
 
        dict_index_t*   index,  /*!< in: dictionary index of the page */
1667
 
        ulint           pr_n)   /*!< in: print n first and n last entries */
 
1620
        buf_block_t*    block,  /* in: index page */
 
1621
        dict_index_t*   index,  /* in: dictionary index of the page */
 
1622
        ulint           pr_n)   /* in: print n first and n last entries */
1668
1623
{
1669
1624
        page_t*         page            = block->frame;
1670
1625
        page_cur_t      cur;
1726
1681
        }
1727
1682
}
1728
1683
 
1729
 
/***************************************************************//**
 
1684
/*******************************************************************
1730
1685
Prints the info in a page header. */
1731
1686
UNIV_INTERN
1732
1687
void
1753
1708
                (ulong) page_header_get_field(page, PAGE_N_DIRECTION));
1754
1709
}
1755
1710
 
1756
 
/***************************************************************//**
 
1711
/*******************************************************************
1757
1712
This is used to print the contents of the page for
1758
1713
debugging purposes. */
1759
1714
UNIV_INTERN
1760
1715
void
1761
1716
page_print(
1762
1717
/*=======*/
1763
 
        buf_block_t*    block,  /*!< in: index page */
1764
 
        dict_index_t*   index,  /*!< in: dictionary index of the page */
1765
 
        ulint           dn,     /*!< in: print dn first and last entries
 
1718
        buf_block_t*    block,  /* in: index page */
 
1719
        dict_index_t*   index,  /* in: dictionary index of the page */
 
1720
        ulint           dn,     /* in: print dn first and last entries
1766
1721
                                in directory */
1767
 
        ulint           rn)     /*!< in: print rn first and last records
 
1722
        ulint           rn)     /* in: print rn first and last records
1768
1723
                                in directory */
1769
1724
{
1770
1725
        page_t* page = block->frame;
1773
1728
        page_dir_print(page, dn);
1774
1729
        page_print_list(block, index, rn);
1775
1730
}
1776
 
#endif /* !UNIV_HOTBACKUP */
1777
1731
 
1778
 
/***************************************************************//**
 
1732
/*******************************************************************
1779
1733
The following is used to validate a record on a page. This function
1780
1734
differs from rec_validate as it can also check the n_owned field and
1781
 
the heap_no field.
1782
 
@return TRUE if ok */
 
1735
the heap_no field. */
1783
1736
UNIV_INTERN
1784
1737
ibool
1785
1738
page_rec_validate(
1786
1739
/*==============*/
1787
 
        rec_t*          rec,    /*!< in: physical record */
1788
 
        const ulint*    offsets)/*!< in: array returned by rec_get_offsets() */
 
1740
                                /* out: TRUE if ok */
 
1741
        rec_t*          rec,    /* in: physical record */
 
1742
        const ulint*    offsets)/* in: array returned by rec_get_offsets() */
1789
1743
{
1790
1744
        ulint   n_owned;
1791
1745
        ulint   heap_no;
1823
1777
        return(TRUE);
1824
1778
}
1825
1779
 
1826
 
#ifndef UNIV_HOTBACKUP
1827
 
/***************************************************************//**
 
1780
/*******************************************************************
1828
1781
Checks that the first directory slot points to the infimum record and
1829
1782
the last to the supremum. This function is intended to track if the
1830
1783
bug fixed in 4.0.14 has caused corruption to users' databases. */
1832
1785
void
1833
1786
page_check_dir(
1834
1787
/*===========*/
1835
 
        const page_t*   page)   /*!< in: index page */
 
1788
        const page_t*   page)   /* in: index page */
1836
1789
{
1837
1790
        ulint   n_slots;
1838
1791
        ulint   infimum_offs;
1859
1812
                buf_page_print(page, 0);
1860
1813
        }
1861
1814
}
1862
 
#endif /* !UNIV_HOTBACKUP */
1863
1815
 
1864
 
/***************************************************************//**
 
1816
/*******************************************************************
1865
1817
This function checks the consistency of an index page when we do not
1866
1818
know the index. This is also resilient so that this should never crash
1867
 
even if the page is total garbage.
1868
 
@return TRUE if ok */
 
1819
even if the page is total garbage. */
1869
1820
UNIV_INTERN
1870
1821
ibool
1871
1822
page_simple_validate_old(
1872
1823
/*=====================*/
1873
 
        page_t* page)   /*!< in: old-style index page */
 
1824
                        /* out: TRUE if ok */
 
1825
        page_t* page)   /* in: old-style index page */
1874
1826
{
1875
1827
        page_dir_slot_t* slot;
1876
1828
        ulint           slot_no;
2071
2023
        return(ret);
2072
2024
}
2073
2025
 
2074
 
/***************************************************************//**
 
2026
/*******************************************************************
2075
2027
This function checks the consistency of an index page when we do not
2076
2028
know the index. This is also resilient so that this should never crash
2077
 
even if the page is total garbage.
2078
 
@return TRUE if ok */
 
2029
even if the page is total garbage. */
2079
2030
UNIV_INTERN
2080
2031
ibool
2081
2032
page_simple_validate_new(
2082
2033
/*=====================*/
2083
 
        page_t* page)   /*!< in: new-style index page */
 
2034
                        /* out: TRUE if ok */
 
2035
        page_t* page)   /* in: new-style index page */
2084
2036
{
2085
2037
        page_dir_slot_t* slot;
2086
2038
        ulint           slot_no;
2282
2234
        return(ret);
2283
2235
}
2284
2236
 
2285
 
/***************************************************************//**
2286
 
This function checks the consistency of an index page.
2287
 
@return TRUE if ok */
 
2237
/*******************************************************************
 
2238
This function checks the consistency of an index page. */
2288
2239
UNIV_INTERN
2289
2240
ibool
2290
2241
page_validate(
2291
2242
/*==========*/
2292
 
        page_t*         page,   /*!< in: index page */
2293
 
        dict_index_t*   index)  /*!< in: data dictionary index containing
 
2243
                                /* out: TRUE if ok */
 
2244
        page_t*         page,   /* in: index page */
 
2245
        dict_index_t*   index)  /* in: data dictionary index containing
2294
2246
                                the page record type definition */
2295
2247
{
2296
2248
        page_dir_slot_t*slot;
2340
2292
        if (UNIV_UNLIKELY(!(page_header_get_ptr(page, PAGE_HEAP_TOP)
2341
2293
                            <= page_dir_get_nth_slot(page, n_slots - 1)))) {
2342
2294
 
2343
 
                fprintf(stderr, 
2344
 
                        "InnoDB: Record heap and dir overlap"
2345
 
                        " on space %lu page %lu index %s, %p, %p\n",
2346
 
                        (ulong) page_get_space_id(page),
2347
 
                        (ulong) page_get_page_no(page), index->name,
 
2295
                fputs("InnoDB: Record heap and dir overlap on a page ",
 
2296
                      stderr);
 
2297
                dict_index_name_print(stderr, NULL, index);
 
2298
                fprintf(stderr, ", %p, %p\n",
2348
2299
                        page_header_get_ptr(page, PAGE_HEAP_TOP),
2349
2300
                        page_dir_get_nth_slot(page, n_slots - 1));
2350
2301
 
2376
2327
                        goto func_exit;
2377
2328
                }
2378
2329
 
2379
 
#ifndef UNIV_HOTBACKUP
2380
2330
                /* Check that the records are in the ascending order */
2381
2331
                if (UNIV_LIKELY(count >= PAGE_HEAP_NO_USER_LOW)
2382
2332
                    && !page_rec_is_supremum(rec)) {
2383
2333
                        if (UNIV_UNLIKELY
2384
2334
                            (1 != cmp_rec_rec(rec, old_rec,
2385
2335
                                              offsets, old_offsets, index))) {
2386
 
                                fprintf(stderr, 
 
2336
                                fprintf(stderr,
2387
2337
                                        "InnoDB: Records in wrong order"
2388
 
                                        " on space %lu page %lu index %s\n",
2389
 
                                        (ulong) page_get_space_id(page),
2390
 
                                        (ulong) page_get_page_no(page),
2391
 
                                        index->name);
 
2338
                                        " on page %lu ",
 
2339
                                        (ulong) page_get_page_no(page));
 
2340
                                dict_index_name_print(stderr, NULL, index);
2392
2341
                                fputs("\nInnoDB: previous record ", stderr);
2393
2342
                                rec_print_new(stderr, old_rec, old_offsets);
2394
2343
                                fputs("\nInnoDB: record ", stderr);
2398
2347
                                goto func_exit;
2399
2348
                        }
2400
2349
                }
2401
 
#endif /* !UNIV_HOTBACKUP */
2402
2350
 
2403
2351
                if (page_rec_is_user_rec(rec)) {
2404
2352
 
2544
2492
 
2545
2493
        if (UNIV_UNLIKELY(ret == FALSE)) {
2546
2494
func_exit2:
2547
 
                fprintf(stderr, 
2548
 
                        "InnoDB: Apparent corruption"
2549
 
                        " in space %lu page %lu index %s\n",
2550
 
                        (ulong) page_get_space_id(page),
2551
 
                        (ulong) page_get_page_no(page),
2552
 
                        index->name);
 
2495
                fprintf(stderr, "InnoDB: Apparent corruption in page %lu in ",
 
2496
                        (ulong) page_get_page_no(page));
 
2497
                dict_index_name_print(stderr, NULL, index);
 
2498
                putc('\n', stderr);
2553
2499
                buf_page_print(page, 0);
2554
2500
        }
2555
2501
 
2556
2502
        return(ret);
2557
2503
}
2558
2504
 
2559
 
#ifndef UNIV_HOTBACKUP
2560
 
/***************************************************************//**
2561
 
Looks in the page record list for a record with the given heap number.
2562
 
@return record, NULL if not found */
 
2505
/*******************************************************************
 
2506
Looks in the page record list for a record with the given heap number. */
2563
2507
UNIV_INTERN
2564
2508
const rec_t*
2565
2509
page_find_rec_with_heap_no(
2566
2510
/*=======================*/
2567
 
        const page_t*   page,   /*!< in: index page */
2568
 
        ulint           heap_no)/*!< in: heap number */
 
2511
                                /* out: record, NULL if not found */
 
2512
        const page_t*   page,   /* in: index page */
 
2513
        ulint           heap_no)/* in: heap number */
2569
2514
{
2570
2515
        const rec_t*    rec;
2571
2516
 
2603
2548
                }
2604
2549
        }
2605
2550
}
2606
 
#endif /* !UNIV_HOTBACKUP */