1
/*****************************************************************************
3
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 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_dulint(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, 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));
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);
699
664
lock_move_rec_list_end(new_block, block, rec);
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);
666
page_update_max_trx_id(new_block, new_page_zip,
667
page_get_max_trx_id(page));
706
669
btr_search_move_or_delete_hash_entries(new_block, block, index);
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. */
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 */
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);
810
775
/* Update MAX_TRX_ID, the lock table, and possible hash index */
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)),
777
page_update_max_trx_id(new_block, new_page_zip,
778
page_get_max_trx_id(page_align(rec)));
819
780
lock_move_rec_list_start(new_block, block, rec, ret);
826
/**********************************************************//**
787
/**************************************************************
827
788
Writes a log record of a record list end or start deletion. */
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 */
839
800
ut_ad(type == MLOG_LIST_END_DELETE
848
809
mlog_close(mtr, log_ptr + 2);
851
#else /* !UNIV_HOTBACKUP */
852
# define page_delete_rec_list_write_log(rec,index,type,mtr) ((void) 0)
853
#endif /* !UNIV_HOTBACKUP */
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. */
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 */
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. */
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 */
928
886
page_dir_slot_t*slot;
929
887
ulint slot_index;
1084
1042
(ulint)(page_get_n_recs(page) - n_recs));
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. */
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 */
1099
1057
page_cur_t cur1;
1100
1058
ulint log_mode;
1156
1114
mtr_set_log_mode(mtr, log_mode);
1159
#ifndef UNIV_HOTBACKUP
1160
/*************************************************************//**
1117
/*****************************************************************
1161
1118
Moves record list end to another page. Moved records include
1163
@return TRUE on success; FALSE on compression failure (new_block will
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
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 */
1175
1133
page_t* new_page = buf_block_get_frame(new_block);
1176
1134
ulint old_data_size;
1214
/*************************************************************//**
1172
/*****************************************************************
1215
1173
Moves record list start to another page. Moved records do not include
1217
@return TRUE on success; FALSE on compression failure */
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 */
1228
1187
if (UNIV_UNLIKELY(!page_copy_rec_list_start(new_block, block,
1229
1188
split_rec, index, mtr))) {
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. */
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 */
1257
1216
mlog_write_ulint(data, page_no, MLOG_4BYTES, mtr);
1259
#endif /* !UNIV_HOTBACKUP */
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. */
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 */
1273
1231
page_dir_slot_t* slot;
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
1323
1281
page_dir_slot_t* slot;
1336
1294
(n_slots - 1 - start) * PAGE_DIR_SLOT_SIZE);
1339
/****************************************************************//**
1297
/********************************************************************
1340
1298
Splits a directory slot which owns too many records. */
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 */
1351
1309
page_dir_slot_t* new_slot;
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 */
1412
1370
page_dir_slot_t* slot;
1413
1371
page_dir_slot_t* up_slot;
1519
#endif /* !UNIV_HOTBACKUP */
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. */
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 */
1531
1487
const page_dir_slot_t* slot;
1532
1488
const rec_t* slot_rec;
1582
1538
return((ulint) n);
1585
#ifndef UNIV_HOTBACKUP
1586
/************************************************************//**
1541
/****************************************************************
1587
1542
Prints record contents including the data relevant only in
1588
1543
the index page context. */
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 */
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);
1616
/***************************************************************//**
1571
/*******************************************************************
1617
1572
This is used to print the contents of the directory for
1618
1573
debugging purposes. */
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 */
1655
1610
(ulong) (PAGE_HEAP_NO_USER_LOW + page_get_n_recs(page)));
1658
/***************************************************************//**
1613
/*******************************************************************
1659
1614
This is used to print the contents of the page record list for
1660
1615
debugging purposes. */
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 */
1669
1624
page_t* page = block->frame;
1670
1625
page_cur_t cur;
1753
1708
(ulong) page_header_get_field(page, PAGE_N_DIRECTION));
1756
/***************************************************************//**
1711
/*******************************************************************
1757
1712
This is used to print the contents of the page for
1758
1713
debugging purposes. */
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 */
1770
1725
page_t* page = block->frame;
1773
1728
page_dir_print(page, dn);
1774
1729
page_print_list(block, index, rn);
1776
#endif /* !UNIV_HOTBACKUP */
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
1782
@return TRUE if ok */
1735
the heap_no field. */
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() */
1859
1812
buf_page_print(page, 0);
1862
#endif /* !UNIV_HOTBACKUP */
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. */
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 */
1875
1827
page_dir_slot_t* slot;
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. */
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 */
2085
2037
page_dir_slot_t* slot;
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. */
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 */
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)))) {
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 ",
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));
2376
2327
goto func_exit;
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))) {
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),
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);
2545
2493
if (UNIV_UNLIKELY(ret == FALSE)) {
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),
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);
2553
2499
buf_page_print(page, 0);
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. */
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 */
2570
2515
const rec_t* rec;