1
/*****************************************************************************
3
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/**************************************************//**
20
@file page/page0page.c
1
/******************************************************
4
(c) 1994-1996 Innobase Oy
23
6
Created 2/2/1994 Heikki Tuuri
24
7
*******************************************************/
81
62
index contains 300 index entries, and the size of the page directory
82
63
is 50 x 4 bytes = 200 bytes. */
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. */
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 */
93
74
const page_t* page;
94
75
register uint16 rec_offs_bytes;
157
138
return(((ulint) (first_slot - slot)) / PAGE_DIR_SLOT_SIZE);
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. */
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 */
203
/*************************************************************//**
184
/*****************************************************************
204
185
Sets the max trx id field value. */
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 */
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;
219
198
rw_lock_x_lock(&btr_search_latch);
222
ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
223
#endif /* !UNIV_HOTBACKUP */
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. */
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),
234
#ifndef UNIV_HOTBACKUP
236
mlog_write_ull(page + (PAGE_HEADER + PAGE_MAX_TRX_ID),
238
#endif /* !UNIV_HOTBACKUP */
240
mach_write_to_8(page + (PAGE_HEADER + PAGE_MAX_TRX_ID), trx_id);
243
#ifndef UNIV_HOTBACKUP
245
213
rw_lock_x_unlock(&btr_search_latch);
247
#endif /* !UNIV_HOTBACKUP */
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. */
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,
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 */
288
#ifndef UNIV_HOTBACKUP
289
/**********************************************************//**
256
/**************************************************************
290
257
Writes a log record of page creation. */
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
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 */
300
267
mlog_write_initial_log_record(frame, comp
301
268
? MLOG_COMP_PAGE_CREATE
302
269
: MLOG_PAGE_CREATE, mtr);
304
#else /* !UNIV_HOTBACKUP */
305
# define page_create_write_log(frame,mtr,comp) ((void) 0)
306
#endif /* !UNIV_HOTBACKUP */
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. */
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 */
321
285
ut_ad(ptr && end_ptr);
332
/**********************************************************//**
333
The index page creation function.
334
@return pointer to the page */
296
/**************************************************************
297
The index page creation function. */
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 */
343
307
page_dir_slot_t* slot;
344
308
mem_heap_t* heap;
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, 0, 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));
485
/**********************************************************//**
486
Create an uncompressed B-tree index page.
487
@return pointer to the page */
449
/**************************************************************
450
Create an uncompressed B-tree index page. */
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 */
497
461
page_create_write_log(buf_block_get_frame(block), mtr, comp);
498
462
return(page_create_low(block, comp));
501
/**********************************************************//**
502
Create a compressed B-tree index page.
503
@return pointer to the page */
465
/**************************************************************
466
Create a compressed B-tree index page. */
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 */
515
479
page_zip_des_t* page_zip = buf_block_get_page_zip(block);
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. */
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 */
547
511
page_t* new_page = buf_block_get_frame(new_block);
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. */
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 */
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);
659
/* Update PAGE_MAX_TRX_ID on the uncompressed page.
660
Modifications will be redo logged and copied to the compressed
661
page in page_zip_compress() or page_zip_reorganize() below. */
662
if (dict_index_is_sec_or_ibuf(index) && page_is_leaf(page)) {
663
page_update_max_trx_id(new_block, NULL,
664
page_get_max_trx_id(page), mtr);
667
624
if (UNIV_LIKELY_NULL(new_page_zip)) {
668
625
mtr_set_log_mode(mtr, log_mode);
705
/* Update the lock table and possible hash index */
662
/* Update the lock table, MAX_TRX_ID, and possible hash index */
707
664
lock_move_rec_list_end(new_block, block, rec);
666
page_update_max_trx_id(new_block, new_page_zip,
667
page_get_max_trx_id(page));
709
669
btr_search_move_or_delete_hash_entries(new_block, block, index);
714
/*************************************************************//**
674
/*****************************************************************
715
675
Copies records from page to new_page, up to the given record,
716
676
NOT including that record. Infimum and supremum records are not copied.
717
The records are copied to the end of the record list on new_page.
718
@return pointer to the original predecessor of the supremum record on
719
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. */
722
680
page_copy_rec_list_start(
723
681
/*=====================*/
724
buf_block_t* new_block, /*!< in/out: index page to copy to */
725
buf_block_t* block, /*!< in: index page containing rec */
726
rec_t* rec, /*!< in: record on page */
727
dict_index_t* index, /*!< in: record descriptor */
728
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 */
730
692
page_t* new_page = buf_block_get_frame(new_block);
731
693
page_zip_des_t* new_page_zip = buf_block_get_page_zip(new_block);
773
735
mem_heap_free(heap);
776
/* Update PAGE_MAX_TRX_ID on the uncompressed page.
777
Modifications will be redo logged and copied to the compressed
778
page in page_zip_compress() or page_zip_reorganize() below. */
779
if (dict_index_is_sec_or_ibuf(index)
780
&& page_is_leaf(page_align(rec))) {
781
page_update_max_trx_id(new_block, NULL,
782
page_get_max_trx_id(page_align(rec)),
786
738
if (UNIV_LIKELY_NULL(new_page_zip)) {
787
739
mtr_set_log_mode(mtr, log_mode);
832
/**********************************************************//**
787
/**************************************************************
833
788
Writes a log record of a record list end or start deletion. */
836
791
page_delete_rec_list_write_log(
837
792
/*===========================*/
838
rec_t* rec, /*!< in: record on page */
839
dict_index_t* index, /*!< in: record descriptor */
840
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:
841
796
MLOG_LIST_END_DELETE, ... */
842
mtr_t* mtr) /*!< in: mtr */
797
mtr_t* mtr) /* in: mtr */
845
800
ut_ad(type == MLOG_LIST_END_DELETE
854
809
mlog_close(mtr, log_ptr + 2);
857
#else /* !UNIV_HOTBACKUP */
858
# define page_delete_rec_list_write_log(rec,index,type,mtr) ((void) 0)
859
#endif /* !UNIV_HOTBACKUP */
861
/**********************************************************//**
862
Parses a log record of a record list end or start deletion.
863
@return end of log record or NULL */
813
/**************************************************************
814
Parses a log record of a record list end or start deletion. */
866
817
page_parse_delete_rec_list(
867
818
/*=======================*/
868
byte type, /*!< in: MLOG_LIST_END_DELETE,
819
/* out: end of log record or NULL */
820
byte type, /* in: MLOG_LIST_END_DELETE,
869
821
MLOG_LIST_START_DELETE,
870
822
MLOG_COMP_LIST_END_DELETE or
871
823
MLOG_COMP_LIST_START_DELETE */
872
byte* ptr, /*!< in: buffer */
873
byte* end_ptr,/*!< in: buffer end */
874
buf_block_t* block, /*!< in/out: buffer block or NULL */
875
dict_index_t* index, /*!< in: record descriptor */
876
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 */
917
/*************************************************************//**
869
/*****************************************************************
918
870
Deletes records from a page from a given record onward, including that record.
919
871
The infimum and supremum records are not deleted. */
922
874
page_delete_rec_list_end(
923
875
/*=====================*/
924
rec_t* rec, /*!< in: pointer to record on page */
925
buf_block_t* block, /*!< in: buffer block of the page */
926
dict_index_t* index, /*!< in: record descriptor */
927
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,
928
880
or ULINT_UNDEFINED if not known */
929
ulint size, /*!< in: the sum of the sizes of the
881
ulint size, /* in: the sum of the sizes of the
930
882
records in the end of the chain to
931
883
delete, or ULINT_UNDEFINED if not known */
932
mtr_t* mtr) /*!< in: mtr */
884
mtr_t* mtr) /* in: mtr */
934
886
page_dir_slot_t*slot;
935
887
ulint slot_index;
1090
1042
(ulint)(page_get_n_recs(page) - n_recs));
1093
/*************************************************************//**
1045
/*****************************************************************
1094
1046
Deletes records from page, up to the given record, NOT including
1095
1047
that record. Infimum and supremum records are not deleted. */
1098
1050
page_delete_rec_list_start(
1099
1051
/*=======================*/
1100
rec_t* rec, /*!< in: record on page */
1101
buf_block_t* block, /*!< in: buffer block of the page */
1102
dict_index_t* index, /*!< in: record descriptor */
1103
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 */
1105
1057
page_cur_t cur1;
1106
1058
ulint log_mode;
1162
1114
mtr_set_log_mode(mtr, log_mode);
1165
#ifndef UNIV_HOTBACKUP
1166
/*************************************************************//**
1117
/*****************************************************************
1167
1118
Moves record list end to another page. Moved records include
1169
@return TRUE on success; FALSE on compression failure (new_block will
1173
1122
page_move_rec_list_end(
1174
1123
/*===================*/
1175
buf_block_t* new_block, /*!< in/out: index page where to move */
1176
buf_block_t* block, /*!< in: index page from where to move */
1177
rec_t* split_rec, /*!< in: first record to move */
1178
dict_index_t* index, /*!< in: record descriptor */
1179
mtr_t* mtr) /*!< in: mtr */
1124
/* out: TRUE on success; FALSE on
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 */
1181
1133
page_t* new_page = buf_block_get_frame(new_block);
1182
1134
ulint old_data_size;
1220
/*************************************************************//**
1172
/*****************************************************************
1221
1173
Moves record list start to another page. Moved records do not include
1223
@return TRUE on success; FALSE on compression failure */
1226
1177
page_move_rec_list_start(
1227
1178
/*=====================*/
1228
buf_block_t* new_block, /*!< in/out: index page where to move */
1229
buf_block_t* block, /*!< in/out: page containing split_rec */
1230
rec_t* split_rec, /*!< in: first record not to move */
1231
dict_index_t* index, /*!< in: record descriptor */
1232
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 */
1234
1187
if (UNIV_UNLIKELY(!page_copy_rec_list_start(new_block, block,
1235
1188
split_rec, index, mtr))) {
1244
/***********************************************************************//**
1197
/***************************************************************************
1245
1198
This is a low-level operation which is used in a database index creation
1246
1199
to update the page number of a created B-tree to a data dictionary record. */
1249
1202
page_rec_write_index_page_no(
1250
1203
/*=========================*/
1251
rec_t* rec, /*!< in: record to update */
1252
ulint i, /*!< in: index of the field to update */
1253
ulint page_no,/*!< in: value to write */
1254
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 */
1263
1216
mlog_write_ulint(data, page_no, MLOG_4BYTES, mtr);
1265
#endif /* !UNIV_HOTBACKUP */
1267
/**************************************************************//**
1219
/******************************************************************
1268
1220
Used to delete n slots from the directory. This function updates
1269
1221
also n_owned fields in the records, so that the first slot after
1270
1222
the deleted ones inherits the records of the deleted slots. */
1273
1225
page_dir_delete_slot(
1274
1226
/*=================*/
1275
page_t* page, /*!< in/out: the index page */
1276
page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
1277
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 */
1279
1231
page_dir_slot_t* slot;
1322
1274
page_dir_add_slot(
1323
1275
/*==============*/
1324
page_t* page, /*!< in/out: the index page */
1325
page_zip_des_t* page_zip,/*!< in/out: comprssed page, or NULL */
1326
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
1329
1281
page_dir_slot_t* slot;
1342
1294
(n_slots - 1 - start) * PAGE_DIR_SLOT_SIZE);
1345
/****************************************************************//**
1297
/********************************************************************
1346
1298
Splits a directory slot which owns too many records. */
1349
1301
page_dir_split_slot(
1350
1302
/*================*/
1351
page_t* page, /*!< in/out: index page */
1352
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
1353
1305
uncompressed part will be written, or NULL */
1354
ulint slot_no)/*!< in: the directory slot */
1306
ulint slot_no)/* in: the directory slot */
1357
1309
page_dir_slot_t* new_slot;
1412
1364
page_dir_balance_slot(
1413
1365
/*==================*/
1414
page_t* page, /*!< in/out: index page */
1415
page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
1416
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 */
1418
1370
page_dir_slot_t* slot;
1419
1371
page_dir_slot_t* up_slot;
1525
#endif /* !UNIV_HOTBACKUP */
1527
/***************************************************************//**
1477
/*******************************************************************
1528
1478
Returns the number of records before the given record in chain.
1529
The number includes infimum and supremum records.
1530
@return number of records */
1479
The number includes infimum and supremum records. */
1533
1482
page_rec_get_n_recs_before(
1534
1483
/*=======================*/
1535
const rec_t* rec) /*!< in: the physical record */
1484
/* out: number of records */
1485
const rec_t* rec) /* in: the physical record */
1537
1487
const page_dir_slot_t* slot;
1538
1488
const rec_t* slot_rec;
1588
1538
return((ulint) n);
1591
#ifndef UNIV_HOTBACKUP
1592
/************************************************************//**
1541
/****************************************************************
1593
1542
Prints record contents including the data relevant only in
1594
1543
the index page context. */
1597
1546
page_rec_print(
1598
1547
/*===========*/
1599
const rec_t* rec, /*!< in: physical record */
1600
const ulint* offsets)/*!< in: record descriptor */
1548
const rec_t* rec, /* in: physical record */
1549
const ulint* offsets)/* in: record descriptor */
1602
1551
ut_a(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
1603
1552
rec_print_new(stderr, rec, offsets);
1619
1568
rec_validate(rec, offsets);
1622
/***************************************************************//**
1571
/*******************************************************************
1623
1572
This is used to print the contents of the directory for
1624
1573
debugging purposes. */
1627
1576
page_dir_print(
1628
1577
/*===========*/
1629
page_t* page, /*!< in: index page */
1630
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 */
1661
1610
(ulong) (PAGE_HEAP_NO_USER_LOW + page_get_n_recs(page)));
1664
/***************************************************************//**
1613
/*******************************************************************
1665
1614
This is used to print the contents of the page record list for
1666
1615
debugging purposes. */
1669
1618
page_print_list(
1670
1619
/*============*/
1671
buf_block_t* block, /*!< in: index page */
1672
dict_index_t* index, /*!< in: dictionary index of the page */
1673
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 */
1675
1624
page_t* page = block->frame;
1676
1625
page_cur_t cur;
1759
1708
(ulong) page_header_get_field(page, PAGE_N_DIRECTION));
1762
/***************************************************************//**
1711
/*******************************************************************
1763
1712
This is used to print the contents of the page for
1764
1713
debugging purposes. */
1769
buf_block_t* block, /*!< in: index page */
1770
dict_index_t* index, /*!< in: dictionary index of the page */
1771
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
1772
1721
in directory */
1773
ulint rn) /*!< in: print rn first and last records
1722
ulint rn) /* in: print rn first and last records
1774
1723
in directory */
1776
1725
page_t* page = block->frame;
1779
1728
page_dir_print(page, dn);
1780
1729
page_print_list(block, index, rn);
1782
#endif /* !UNIV_HOTBACKUP */
1784
/***************************************************************//**
1732
/*******************************************************************
1785
1733
The following is used to validate a record on a page. This function
1786
1734
differs from rec_validate as it can also check the n_owned field and
1788
@return TRUE if ok */
1735
the heap_no field. */
1791
1738
page_rec_validate(
1792
1739
/*==============*/
1793
rec_t* rec, /*!< in: physical record */
1794
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() */
1865
1812
buf_page_print(page, 0);
1868
#endif /* !UNIV_HOTBACKUP */
1870
/***************************************************************//**
1816
/*******************************************************************
1871
1817
This function checks the consistency of an index page when we do not
1872
1818
know the index. This is also resilient so that this should never crash
1873
even if the page is total garbage.
1874
@return TRUE if ok */
1819
even if the page is total garbage. */
1877
1822
page_simple_validate_old(
1878
1823
/*=====================*/
1879
page_t* page) /*!< in: old-style index page */
1824
/* out: TRUE if ok */
1825
page_t* page) /* in: old-style index page */
1881
1827
page_dir_slot_t* slot;
2080
/***************************************************************//**
2026
/*******************************************************************
2081
2027
This function checks the consistency of an index page when we do not
2082
2028
know the index. This is also resilient so that this should never crash
2083
even if the page is total garbage.
2084
@return TRUE if ok */
2029
even if the page is total garbage. */
2087
2032
page_simple_validate_new(
2088
2033
/*=====================*/
2089
page_t* page) /*!< in: new-style index page */
2034
/* out: TRUE if ok */
2035
page_t* page) /* in: new-style index page */
2091
2037
page_dir_slot_t* slot;
2291
/***************************************************************//**
2292
This function checks the consistency of an index page.
2293
@return TRUE if ok */
2237
/*******************************************************************
2238
This function checks the consistency of an index page. */
2298
page_t* page, /*!< in: index page */
2299
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
2300
2246
the page record type definition */
2302
2248
page_dir_slot_t*slot;
2346
2292
if (UNIV_UNLIKELY(!(page_header_get_ptr(page, PAGE_HEAP_TOP)
2347
2293
<= page_dir_get_nth_slot(page, n_slots - 1)))) {
2350
"InnoDB: Record heap and dir overlap"
2351
" on space %lu page %lu index %s, %p, %p\n",
2352
(ulong) page_get_space_id(page),
2353
(ulong) page_get_page_no(page), index->name,
2295
fputs("InnoDB: Record heap and dir overlap on a page ",
2297
dict_index_name_print(stderr, NULL, index);
2298
fprintf(stderr, ", %p, %p\n",
2354
2299
page_header_get_ptr(page, PAGE_HEAP_TOP),
2355
2300
page_dir_get_nth_slot(page, n_slots - 1));
2382
2327
goto func_exit;
2385
#ifndef UNIV_HOTBACKUP
2386
2330
/* Check that the records are in the ascending order */
2387
2331
if (UNIV_LIKELY(count >= PAGE_HEAP_NO_USER_LOW)
2388
2332
&& !page_rec_is_supremum(rec)) {
2389
2333
if (UNIV_UNLIKELY
2390
2334
(1 != cmp_rec_rec(rec, old_rec,
2391
2335
offsets, old_offsets, index))) {
2393
2337
"InnoDB: Records in wrong order"
2394
" on space %lu page %lu index %s\n",
2395
(ulong) page_get_space_id(page),
2396
(ulong) page_get_page_no(page),
2339
(ulong) page_get_page_no(page));
2340
dict_index_name_print(stderr, NULL, index);
2398
2341
fputs("\nInnoDB: previous record ", stderr);
2399
2342
rec_print_new(stderr, old_rec, old_offsets);
2400
2343
fputs("\nInnoDB: record ", stderr);
2561
2493
if (UNIV_UNLIKELY(ret == FALSE)) {
2564
"InnoDB: Apparent corruption"
2565
" in space %lu page %lu index %s\n",
2566
(ulong) page_get_space_id(page),
2567
(ulong) page_get_page_no(page),
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);
2569
2499
buf_page_print(page, 0);
2575
#ifndef UNIV_HOTBACKUP
2576
/***************************************************************//**
2577
Looks in the page record list for a record with the given heap number.
2578
@return record, NULL if not found */
2505
/*******************************************************************
2506
Looks in the page record list for a record with the given heap number. */
2581
2509
page_find_rec_with_heap_no(
2582
2510
/*=======================*/
2583
const page_t* page, /*!< in: index page */
2584
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 */
2586
2515
const rec_t* rec;