98
100
#ifdef UNIV_BTR_DEBUG
99
/******************************************************************
100
Checks a file segment header within a B-tree root page. */
101
/**************************************************************//**
102
Checks a file segment header within a B-tree root page.
103
@return TRUE if valid */
103
106
btr_root_fseg_validate(
104
107
/*===================*/
105
/* out: TRUE if valid */
106
const fseg_header_t* seg_header, /* in: segment header */
107
ulint space) /* in: tablespace identifier */
108
const fseg_header_t* seg_header, /*!< in: segment header */
109
ulint space) /*!< in: tablespace identifier */
109
111
ulint offset = mach_read_from_2(seg_header + FSEG_HDR_OFFSET);
116
118
#endif /* UNIV_BTR_DEBUG */
118
/******************************************************************
119
Gets the root node of a tree and x-latches it. */
120
/**************************************************************//**
121
Gets the root node of a tree and x-latches it.
122
@return root page, x-latched */
122
125
btr_root_block_get(
123
126
/*===============*/
124
/* out: root page, x-latched */
125
dict_index_t* index, /* in: index tree */
126
mtr_t* mtr) /* in: mtr */
127
dict_index_t* index, /*!< in: index tree */
128
mtr_t* mtr) /*!< in: mtr */
154
/******************************************************************
155
Gets the root node of a tree and x-latches it. */
156
/**************************************************************//**
157
Gets the root node of a tree and x-latches it.
158
@return root page, x-latched */
160
/* out: root page, x-latched */
161
dict_index_t* index, /* in: index tree */
162
mtr_t* mtr) /* in: mtr */
163
dict_index_t* index, /*!< in: index tree */
164
mtr_t* mtr) /*!< in: mtr */
164
166
return(buf_block_get_frame(btr_root_block_get(index, mtr)));
167
/*****************************************************************
169
/*************************************************************//**
168
170
Gets pointer to the previous user record in the tree. It is assumed that
169
the caller has appropriate latches on the page and its neighbor. */
171
the caller has appropriate latches on the page and its neighbor.
172
@return previous user record, NULL if there is none */
172
175
btr_get_prev_user_rec(
173
176
/*==================*/
174
/* out: previous user record, NULL if there is none */
175
rec_t* rec, /* in: record on leaf level */
176
mtr_t* mtr) /* in: mtr holding a latch on the page, and if
177
rec_t* rec, /*!< in: record on leaf level */
178
mtr_t* mtr) /*!< in: mtr holding a latch on the page, and if
177
179
needed, also to the previous page */
225
/*****************************************************************
227
/*************************************************************//**
226
228
Gets pointer to the next user record in the tree. It is assumed that the
227
caller has appropriate latches on the page and its neighbor. */
229
caller has appropriate latches on the page and its neighbor.
230
@return next user record, NULL if there is none */
230
233
btr_get_next_user_rec(
231
234
/*==================*/
232
/* out: next user record, NULL if there is none */
233
rec_t* rec, /* in: record on leaf level */
234
mtr_t* mtr) /* in: mtr holding a latch on the page, and if
235
rec_t* rec, /*!< in: record on leaf level */
236
mtr_t* mtr) /*!< in: mtr holding a latch on the page, and if
235
237
needed, also to the next page */
281
/******************************************************************
283
/**************************************************************//**
282
284
Creates a new index page (not the root, and also not
283
285
used in page reorganization). @see btr_page_empty(). */
288
buf_block_t* block, /* in/out: page to be created */
289
page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
290
dict_index_t* index, /* in: index */
291
ulint level, /* in: the B-tree level of the page */
292
mtr_t* mtr) /* in: mtr */
290
buf_block_t* block, /*!< in/out: page to be created */
291
page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
292
dict_index_t* index, /*!< in: index */
293
ulint level, /*!< in: the B-tree level of the page */
294
mtr_t* mtr) /*!< in: mtr */
294
296
page_t* page = buf_block_get_frame(block);
308
310
btr_page_set_index_id(page, page_zip, index->id, mtr);
311
/******************************************************************
313
/**************************************************************//**
312
314
Allocates a new file page to be used in an ibuf tree. Takes the page from
313
the free list of the tree, which must contain pages! */
315
the free list of the tree, which must contain pages!
316
@return new allocated block, x-latched */
316
319
btr_page_alloc_for_ibuf(
317
320
/*====================*/
318
/* out: new allocated block, x-latched */
319
dict_index_t* index, /* in: index tree */
320
mtr_t* mtr) /* in: mtr */
321
dict_index_t* index, /*!< in: index tree */
322
mtr_t* mtr) /*!< in: mtr */
322
324
fil_addr_t node_addr;
345
347
return(new_block);
348
/******************************************************************
350
/**************************************************************//**
349
351
Allocates a new file page to be used in an index tree. NOTE: we assume
350
that the caller has made the reservation for free extents! */
352
that the caller has made the reservation for free extents!
353
@return new allocated block, x-latched; NULL if out of space */
355
/* out: new allocated block, x-latched;
356
NULL if out of space */
357
dict_index_t* index, /* in: index */
358
ulint hint_page_no, /* in: hint of a good page */
359
byte file_direction, /* in: direction where a possible
358
dict_index_t* index, /*!< in: index */
359
ulint hint_page_no, /*!< in: hint of a good page */
360
byte file_direction, /*!< in: direction where a possible
360
361
page split is made */
361
ulint level, /* in: level where the page is placed
362
ulint level, /*!< in: level where the page is placed
363
mtr_t* mtr) /* in: mtr */
364
mtr_t* mtr) /*!< in: mtr */
365
366
fseg_header_t* seg_header;
399
400
return(new_block);
402
/******************************************************************
403
Gets the number of pages in a B-tree. */
403
/**************************************************************//**
404
Gets the number of pages in a B-tree.
405
@return number of pages */
408
/* out: number of pages */
409
dict_index_t* index, /* in: index */
410
ulint flag) /* in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
410
dict_index_t* index, /*!< in: index */
411
ulint flag) /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
412
413
fseg_header_t* seg_header;
446
/******************************************************************
447
/**************************************************************//**
447
448
Frees a page used in an ibuf tree. Puts the page to the free list of the
451
452
btr_page_free_for_ibuf(
452
453
/*===================*/
453
dict_index_t* index, /* in: index tree */
454
buf_block_t* block, /* in: block to be freed, x-latched */
455
mtr_t* mtr) /* in: mtr */
454
dict_index_t* index, /*!< in: index tree */
455
buf_block_t* block, /*!< in: block to be freed, x-latched */
456
mtr_t* mtr) /*!< in: mtr */
476
477
btr_page_free_low(
477
478
/*==============*/
478
dict_index_t* index, /* in: index tree */
479
buf_block_t* block, /* in: block to be freed, x-latched */
480
ulint level, /* in: page level */
481
mtr_t* mtr) /* in: mtr */
479
dict_index_t* index, /*!< in: index tree */
480
buf_block_t* block, /*!< in: block to be freed, x-latched */
481
ulint level, /*!< in: page level */
482
mtr_t* mtr) /*!< in: mtr */
483
484
fseg_header_t* seg_header;
509
510
buf_block_get_page_no(block), mtr);
512
/******************************************************************
513
/**************************************************************//**
513
514
Frees a file page used in an index tree. NOTE: cannot free field external
514
515
storage pages because the page must contain info on its level. */
519
dict_index_t* index, /* in: index tree */
520
buf_block_t* block, /* in: block to be freed, x-latched */
521
mtr_t* mtr) /* in: mtr */
520
dict_index_t* index, /*!< in: index tree */
521
buf_block_t* block, /*!< in: block to be freed, x-latched */
522
mtr_t* mtr) /*!< in: mtr */
527
528
btr_page_free_low(index, block, level, mtr);
530
/******************************************************************
531
/**************************************************************//**
531
532
Sets the child node file address in a node pointer. */
534
535
btr_node_ptr_set_child_page_no(
535
536
/*===========================*/
536
rec_t* rec, /* in: node pointer record */
537
page_zip_des_t* page_zip,/* in/out: compressed page whose uncompressed
537
rec_t* rec, /*!< in: node pointer record */
538
page_zip_des_t* page_zip,/*!< in/out: compressed page whose uncompressed
538
539
part will be updated, or NULL */
539
const ulint* offsets,/* in: array returned by rec_get_offsets() */
540
ulint page_no,/* in: child node address */
541
mtr_t* mtr) /* in: mtr */
540
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
541
ulint page_no,/*!< in: child node address */
542
mtr_t* mtr) /*!< in: mtr */
565
/****************************************************************
566
Returns the child page of a node pointer and x-latches it. */
566
/************************************************************//**
567
Returns the child page of a node pointer and x-latches it.
568
@return child page, x-latched */
569
571
btr_node_ptr_get_child(
570
572
/*===================*/
571
/* out: child page, x-latched */
572
const rec_t* node_ptr,/* in: node pointer */
573
dict_index_t* index, /* in: index */
574
const ulint* offsets,/* in: array returned by rec_get_offsets() */
575
mtr_t* mtr) /* in: mtr */
573
const rec_t* node_ptr,/*!< in: node pointer */
574
dict_index_t* index, /*!< in: index */
575
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
576
mtr_t* mtr) /*!< in: mtr */
585
586
page_no, RW_X_LATCH, mtr));
588
/****************************************************************
589
/************************************************************//**
589
590
Returns the upper level node pointer to a page. It is assumed that mtr holds
590
an x-latch on the tree. */
591
an x-latch on the tree.
592
@return rec_get_offsets() of the node pointer record */
593
595
btr_page_get_father_node_ptr(
594
596
/*=========================*/
595
/* out: rec_get_offsets() of the
596
node pointer record */
597
ulint* offsets,/* in: work area for the return value */
598
mem_heap_t* heap, /* in: memory heap to use */
599
btr_cur_t* cursor, /* in: cursor pointing to user record,
597
ulint* offsets,/*!< in: work area for the return value */
598
mem_heap_t* heap, /*!< in: memory heap to use */
599
btr_cur_t* cursor, /*!< in: cursor pointing to user record,
600
600
out: cursor on node pointer record,
601
601
its page x-latched */
602
mtr_t* mtr) /* in: mtr */
602
mtr_t* mtr) /*!< in: mtr */
661
661
"InnoDB: corruption. If the crash happens at "
662
662
"the database startup, see\n"
663
"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
664
"forcing-recovery.html about\n"
663
"InnoDB: " REFMAN "forcing-recovery.html about\n"
665
664
"InnoDB: forcing recovery. "
666
665
"Then dump + drop + reimport.\n", stderr);
674
/****************************************************************
673
/************************************************************//**
675
674
Returns the upper level node pointer to a page. It is assumed that mtr holds
676
an x-latch on the tree. */
675
an x-latch on the tree.
676
@return rec_get_offsets() of the node pointer record */
679
679
btr_page_get_father_block(
680
680
/*======================*/
681
/* out: rec_get_offsets() of the
682
node pointer record */
683
ulint* offsets,/* in: work area for the return value */
684
mem_heap_t* heap, /* in: memory heap to use */
685
dict_index_t* index, /* in: b-tree index */
686
buf_block_t* block, /* in: child page in the index */
687
mtr_t* mtr, /* in: mtr */
688
btr_cur_t* cursor) /* out: cursor on node pointer record,
681
ulint* offsets,/*!< in: work area for the return value */
682
mem_heap_t* heap, /*!< in: memory heap to use */
683
dict_index_t* index, /*!< in: b-tree index */
684
buf_block_t* block, /*!< in: child page in the index */
685
mtr_t* mtr, /*!< in: mtr */
686
btr_cur_t* cursor) /*!< out: cursor on node pointer record,
689
687
its page x-latched */
695
693
return(btr_page_get_father_node_ptr(offsets, heap, cursor, mtr));
698
/****************************************************************
696
/************************************************************//**
699
697
Seeks to the upper level node pointer to a page.
700
698
It is assumed that mtr holds an x-latch on the tree. */
703
701
btr_page_get_father(
704
702
/*================*/
705
dict_index_t* index, /* in: b-tree index */
706
buf_block_t* block, /* in: child page in the index */
707
mtr_t* mtr, /* in: mtr */
708
btr_cur_t* cursor) /* out: cursor on node pointer record,
703
dict_index_t* index, /*!< in: b-tree index */
704
buf_block_t* block, /*!< in: child page in the index */
705
mtr_t* mtr, /*!< in: mtr */
706
btr_cur_t* cursor) /*!< out: cursor on node pointer record,
709
707
its page x-latched */
711
709
mem_heap_t* heap;
719
717
mem_heap_free(heap);
722
/****************************************************************
723
Creates the root node for a new index tree. */
720
/************************************************************//**
721
Creates the root node for a new index tree.
722
@return page number of the created root, FIL_NULL if did not succeed */
728
/* out: page number of the created root,
729
FIL_NULL if did not succeed */
730
ulint type, /* in: type of the index */
731
ulint space, /* in: space where created */
732
ulint zip_size,/* in: compressed page size in bytes
727
ulint type, /*!< in: type of the index */
728
ulint space, /*!< in: space where created */
729
ulint zip_size,/*!< in: compressed page size in bytes
733
730
or 0 for uncompressed pages */
734
dulint index_id,/* in: index id */
735
dict_index_t* index, /* in: index */
736
mtr_t* mtr) /* in: mini-transaction handle */
731
dulint index_id,/*!< in: index id */
732
dict_index_t* index, /*!< in: index */
733
mtr_t* mtr) /*!< in: mini-transaction handle */
739
736
buf_block_t* block;
841
/****************************************************************
838
/************************************************************//**
842
839
Frees a B-tree except the root page, which MUST be freed after this
843
840
by calling btr_free_root. */
846
843
btr_free_but_not_root(
847
844
/*==================*/
848
ulint space, /* in: space where created */
849
ulint zip_size, /* in: compressed page size in bytes
845
ulint space, /*!< in: space where created */
846
ulint zip_size, /*!< in: compressed page size in bytes
850
847
or 0 for uncompressed pages */
851
ulint root_page_no) /* in: root page number */
848
ulint root_page_no) /*!< in: root page number */
898
/****************************************************************
895
/************************************************************//**
899
896
Frees the B-tree root page. Other tree MUST already have been freed. */
904
ulint space, /* in: space where created */
905
ulint zip_size, /* in: compressed page size in bytes
901
ulint space, /*!< in: space where created */
902
ulint zip_size, /*!< in: compressed page size in bytes
906
903
or 0 for uncompressed pages */
907
ulint root_page_no, /* in: root page number */
908
mtr_t* mtr) /* in: a mini-transaction which has already
904
ulint root_page_no, /*!< in: root page number */
905
mtr_t* mtr) /*!< in: a mini-transaction which has already
911
908
buf_block_t* block;
923
920
while (!fseg_free_step(header, mtr));
922
#endif /* !UNIV_HOTBACKUP */
926
/*****************************************************************
924
/*************************************************************//**
927
925
Reorganizes an index page. */
930
928
btr_page_reorganize_low(
931
929
/*====================*/
932
ibool recovery,/* in: TRUE if called in recovery:
930
ibool recovery,/*!< in: TRUE if called in recovery:
933
931
locks should not be updated, i.e.,
934
932
there cannot exist locks on the
935
933
page, and a hash index should not be
936
934
dropped: it cannot exist */
937
buf_block_t* block, /* in: page to be reorganized */
938
dict_index_t* index, /* in: record descriptor */
939
mtr_t* mtr) /* in: mtr */
935
buf_block_t* block, /*!< in: page to be reorganized */
936
dict_index_t* index, /*!< in: record descriptor */
937
mtr_t* mtr) /*!< in: mtr */
941
939
page_t* page = buf_block_get_frame(block);
942
940
page_zip_des_t* page_zip = buf_block_get_page_zip(block);
957
955
data_size1 = page_get_data_size(page);
958
956
max_ins_size1 = page_get_max_insert_size_after_reorganize(page, 1);
958
#ifndef UNIV_HOTBACKUP
960
959
/* Write the log record */
961
960
mlog_open_and_write_index(mtr, page, index, page_is_comp(page)
962
961
? MLOG_COMP_PAGE_REORGANIZE
963
962
: MLOG_PAGE_REORGANIZE, 0);
963
#endif /* !UNIV_HOTBACKUP */
965
965
/* Turn logging off */
966
966
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
968
#ifndef UNIV_HOTBACKUP
968
969
temp_block = buf_block_alloc(0);
970
#else /* !UNIV_HOTBACKUP */
971
ut_ad(block == back_block1);
972
temp_block = back_block2;
973
#endif /* !UNIV_HOTBACKUP */
969
974
temp_page = temp_block->frame;
971
976
/* Copy the old page to temporary space */
972
977
buf_frame_copy(temp_page, page);
979
#ifndef UNIV_HOTBACKUP
974
980
if (UNIV_LIKELY(!recovery)) {
975
981
btr_search_drop_page_hash_index(block);
984
block->check_index_page_at_flush = TRUE;
985
#endif /* !UNIV_HOTBACKUP */
978
987
/* Recreate the page: note that global data on page (possible
979
988
segment headers, next page-field, etc.) is preserved intact */
981
990
page_create(block, mtr, dict_table_is_comp(index->table));
982
block->check_index_page_at_flush = TRUE;
984
992
/* Copy the records from the temporary space to the recreated page;
985
993
do not copy the lock bits yet */
987
995
page_copy_rec_list_end_no_locks(block, temp_block,
988
996
page_get_infimum_rec(temp_page),
990
/* Copy max trx id to recreated page */
991
page_set_max_trx_id(block, NULL, page_get_max_trx_id(temp_page));
999
if (dict_index_is_sec_or_ibuf(index) && page_is_leaf(page)) {
1000
/* Copy max trx id to recreated page */
1001
trx_id_t max_trx_id = page_get_max_trx_id(temp_page);
1002
page_set_max_trx_id(block, NULL, max_trx_id, mtr);
1003
/* In crash recovery, dict_index_is_sec_or_ibuf() always
1004
returns TRUE, even for clustered indexes. max_trx_id is
1005
unused in clustered index pages. */
1006
ut_ad(!ut_dulint_is_zero(max_trx_id) || recovery);
993
1009
if (UNIV_LIKELY_NULL(page_zip)
994
1010
&& UNIV_UNLIKELY
1000
1016
goto func_exit;
1019
#ifndef UNIV_HOTBACKUP
1003
1020
if (UNIV_LIKELY(!recovery)) {
1004
1021
/* Update the record lock bitmaps */
1005
1022
lock_move_reorganize_page(block, temp_block);
1024
#endif /* !UNIV_HOTBACKUP */
1008
1026
data_size2 = page_get_data_size(page);
1009
1027
max_ins_size2 = page_get_max_insert_size_after_reorganize(page, 1);
1030
1048
#ifdef UNIV_ZIP_DEBUG
1031
1049
ut_a(!page_zip || page_zip_validate(page_zip, page));
1032
1050
#endif /* UNIV_ZIP_DEBUG */
1051
#ifndef UNIV_HOTBACKUP
1033
1052
buf_block_free(temp_block);
1053
#endif /* !UNIV_HOTBACKUP */
1035
1055
/* Restore logging mode */
1036
1056
mtr_set_log_mode(mtr, log_mode);
1038
1058
return(success);
1041
/*****************************************************************
1061
#ifndef UNIV_HOTBACKUP
1062
/*************************************************************//**
1042
1063
Reorganizes an index page.
1043
1064
IMPORTANT: if btr_page_reorganize() is invoked on a compressed leaf
1044
1065
page of a non-clustered index, the caller must update the insert
1045
1066
buffer free bits in the same mini-transaction in such a way that the
1046
modification will be redo-logged. */
1067
modification will be redo-logged.
1068
@return TRUE on success, FALSE on failure */
1049
1071
btr_page_reorganize(
1050
1072
/*================*/
1051
/* out: TRUE on success, FALSE on failure */
1052
buf_block_t* block, /* in: page to be reorganized */
1053
dict_index_t* index, /* in: record descriptor */
1054
mtr_t* mtr) /* in: mtr */
1073
buf_block_t* block, /*!< in: page to be reorganized */
1074
dict_index_t* index, /*!< in: record descriptor */
1075
mtr_t* mtr) /*!< in: mtr */
1056
1077
return(btr_page_reorganize_low(FALSE, block, index, mtr));
1079
#endif /* !UNIV_HOTBACKUP */
1059
/***************************************************************
1060
Parses a redo log record of reorganizing a page. */
1081
/***********************************************************//**
1082
Parses a redo log record of reorganizing a page.
1083
@return end of log record or NULL */
1063
1086
btr_parse_page_reorganize(
1064
1087
/*======================*/
1065
/* out: end of log record or NULL */
1066
byte* ptr, /* in: buffer */
1088
byte* ptr, /*!< in: buffer */
1067
1089
byte* end_ptr __attribute__((unused)),
1068
/* in: buffer end */
1069
dict_index_t* index, /* in: record descriptor */
1070
buf_block_t* block, /* in: page to be reorganized, or NULL */
1071
mtr_t* mtr) /* in: mtr or NULL */
1090
/*!< in: buffer end */
1091
dict_index_t* index, /*!< in: record descriptor */
1092
buf_block_t* block, /*!< in: page to be reorganized, or NULL */
1093
mtr_t* mtr) /*!< in: mtr or NULL */
1073
1095
ut_ad(ptr && end_ptr);
1084
/*****************************************************************
1085
Empties an index page. @see btr_page_create().*/
1106
#ifndef UNIV_HOTBACKUP
1107
/*************************************************************//**
1108
Empties an index page. @see btr_page_create(). */
1088
1111
btr_page_empty(
1089
1112
/*===========*/
1090
buf_block_t* block, /* in: page to be emptied */
1091
page_zip_des_t* page_zip,/* out: compressed page, or NULL */
1092
dict_index_t* index, /* in: index of the page */
1093
ulint level, /* in: the B-tree level of the page */
1094
mtr_t* mtr) /* in: mtr */
1113
buf_block_t* block, /*!< in: page to be emptied */
1114
page_zip_des_t* page_zip,/*!< out: compressed page, or NULL */
1115
dict_index_t* index, /*!< in: index of the page */
1116
ulint level, /*!< in: the B-tree level of the page */
1117
mtr_t* mtr) /*!< in: mtr */
1096
1119
page_t* page = buf_block_get_frame(block);
1116
1139
block->check_index_page_at_flush = TRUE;
1119
/*****************************************************************
1142
/*************************************************************//**
1120
1143
Makes tree one level higher by splitting the root, and inserts
1121
1144
the tuple. It is assumed that mtr contains an x-latch on the tree.
1122
1145
NOTE that the operation of this function must always succeed,
1123
1146
we cannot reverse it: therefore enough free disk space must be
1124
guaranteed to be available before this function is called. */
1147
guaranteed to be available before this function is called.
1148
@return inserted record */
1127
1151
btr_root_raise_and_insert(
1128
1152
/*======================*/
1129
/* out: inserted record */
1130
btr_cur_t* cursor, /* in: cursor at which to insert: must be
1153
btr_cur_t* cursor, /*!< in: cursor at which to insert: must be
1131
1154
on the root page; when the function returns,
1132
1155
the cursor is positioned on the predecessor
1133
1156
of the inserted record */
1134
const dtuple_t* tuple, /* in: tuple to insert */
1135
ulint n_ext, /* in: number of externally stored columns */
1136
mtr_t* mtr) /* in: mtr */
1157
const dtuple_t* tuple, /*!< in: tuple to insert */
1158
ulint n_ext, /*!< in: number of externally stored columns */
1159
mtr_t* mtr) /*!< in: mtr */
1138
1161
dict_index_t* index;
1288
1311
return(btr_page_split_and_insert(cursor, tuple, n_ext, mtr));
1291
/*****************************************************************
1314
/*************************************************************//**
1292
1315
Decides if the page should be split at the convergence point of inserts
1293
converging to the left. */
1316
converging to the left.
1317
@return TRUE if split recommended */
1296
1320
btr_page_get_split_rec_to_left(
1297
1321
/*===========================*/
1298
/* out: TRUE if split recommended */
1299
btr_cur_t* cursor, /* in: cursor at which to insert */
1300
rec_t** split_rec) /* out: if split recommended,
1322
btr_cur_t* cursor, /*!< in: cursor at which to insert */
1323
rec_t** split_rec) /*!< out: if split recommended,
1301
1324
the first record on upper half page,
1302
1325
or NULL if tuple to be inserted should
1336
/*****************************************************************
1359
/*************************************************************//**
1337
1360
Decides if the page should be split at the convergence point of inserts
1338
converging to the right. */
1361
converging to the right.
1362
@return TRUE if split recommended */
1341
1365
btr_page_get_split_rec_to_right(
1342
1366
/*============================*/
1343
/* out: TRUE if split recommended */
1344
btr_cur_t* cursor, /* in: cursor at which to insert */
1345
rec_t** split_rec) /* out: if split recommended,
1367
btr_cur_t* cursor, /*!< in: cursor at which to insert */
1368
rec_t** split_rec) /*!< out: if split recommended,
1346
1369
the first record on upper half page,
1347
1370
or NULL if tuple to be inserted should
1394
/*****************************************************************
1417
/*************************************************************//**
1395
1418
Calculates a split record such that the tuple will certainly fit on
1396
1419
its half-page when the split is performed. We assume in this function
1397
only that the cursor page has at least one user record. */
1420
only that the cursor page has at least one user record.
1421
@return split record, or NULL if tuple will be the first record on
1400
1425
btr_page_get_sure_split_rec(
1401
1426
/*========================*/
1402
/* out: split record, or NULL if tuple
1403
will be the first record on upper half-page */
1404
btr_cur_t* cursor, /* in: cursor at which insert should be made */
1405
const dtuple_t* tuple, /* in: tuple to insert */
1406
ulint n_ext) /* in: number of externally stored columns */
1427
btr_cur_t* cursor, /*!< in: cursor at which insert should be made */
1428
const dtuple_t* tuple, /*!< in: tuple to insert */
1429
ulint n_ext) /*!< in: number of externally stored columns */
1409
1432
page_zip_des_t* page_zip;
1514
/*****************************************************************
1537
/*************************************************************//**
1515
1538
Returns TRUE if the insert fits on the appropriate half-page with the
1516
chosen split_rec. */
1540
@return TRUE if fits */
1519
1543
btr_page_insert_fits(
1520
1544
/*=================*/
1521
/* out: TRUE if fits */
1522
btr_cur_t* cursor, /* in: cursor at which insert
1545
btr_cur_t* cursor, /*!< in: cursor at which insert
1523
1546
should be made */
1524
const rec_t* split_rec,/* in: suggestion for first record
1547
const rec_t* split_rec,/*!< in: suggestion for first record
1525
1548
on upper half-page, or NULL if
1526
1549
tuple to be inserted should be first */
1527
const ulint* offsets,/* in: rec_get_offsets(
1550
const ulint* offsets,/*!< in: rec_get_offsets(
1528
1551
split_rec, cursor->index) */
1529
const dtuple_t* tuple, /* in: tuple to insert */
1530
ulint n_ext, /* in: number of externally stored columns */
1531
mem_heap_t* heap) /* in: temporary memory heap */
1552
const dtuple_t* tuple, /*!< in: tuple to insert */
1553
ulint n_ext, /*!< in: number of externally stored columns */
1554
mem_heap_t* heap) /*!< in: temporary memory heap */
1534
1557
ulint insert_size;
1611
/***********************************************************
1634
/*******************************************************//**
1612
1635
Inserts a data tuple to a tree on a non-leaf level. It is assumed
1613
1636
that mtr holds an x-latch on the tree. */
1616
1639
btr_insert_on_non_leaf_level(
1617
1640
/*=========================*/
1618
dict_index_t* index, /* in: index */
1619
ulint level, /* in: level, must be > 0 */
1620
dtuple_t* tuple, /* in: the record to be inserted */
1621
mtr_t* mtr) /* in: mtr */
1641
dict_index_t* index, /*!< in: index */
1642
ulint level, /*!< in: level, must be > 0 */
1643
dtuple_t* tuple, /*!< in: the record to be inserted */
1644
mtr_t* mtr) /*!< in: mtr */
1623
1646
big_rec_t* dummy_big_rec;
1624
1647
btr_cur_t cursor;
1639
1662
ut_a(err == DB_SUCCESS);
1642
/******************************************************************
1665
/**************************************************************//**
1643
1666
Attaches the halves of an index page on the appropriate level in an
1647
1670
btr_attach_half_pages(
1648
1671
/*==================*/
1649
dict_index_t* index, /* in: the index tree */
1650
buf_block_t* block, /* in/out: page to be split */
1651
rec_t* split_rec, /* in: first record on upper
1672
dict_index_t* index, /*!< in: the index tree */
1673
buf_block_t* block, /*!< in/out: page to be split */
1674
rec_t* split_rec, /*!< in: first record on upper
1653
buf_block_t* new_block, /* in/out: the new half page */
1654
ulint direction, /* in: FSP_UP or FSP_DOWN */
1655
mtr_t* mtr) /* in: mtr */
1676
buf_block_t* new_block, /*!< in/out: the new half page */
1677
ulint direction, /*!< in: FSP_UP or FSP_DOWN */
1678
mtr_t* mtr) /*!< in: mtr */
1658
1681
ulint zip_size;
1774
1797
btr_page_set_next(upper_page, upper_page_zip, next_page_no, mtr);
1777
/*****************************************************************
1800
/*************************************************************//**
1778
1801
Splits an index page to halves and inserts the tuple. It is assumed
1779
that mtr holds an x-latch to the index tree. NOTE: the tree x-latch
1780
is released within this function! NOTE that the operation of this
1781
function must always succeed, we cannot reverse it: therefore
1782
enough free disk space must be guaranteed to be available before
1783
this function is called. */
1802
that mtr holds an x-latch to the index tree. NOTE: the tree x-latch is
1803
released within this function! NOTE that the operation of this
1804
function must always succeed, we cannot reverse it: therefore enough
1805
free disk space (2 pages) must be guaranteed to be available before
1806
this function is called.
1808
@return inserted record */
1786
1811
btr_page_split_and_insert(
1787
1812
/*======================*/
1788
/* out: inserted record; NOTE: the tree
1789
x-latch is released! NOTE: 2 free disk
1790
pages must be available! */
1791
btr_cur_t* cursor, /* in: cursor at which to insert; when the
1813
btr_cur_t* cursor, /*!< in: cursor at which to insert; when the
1792
1814
function returns, the cursor is positioned
1793
1815
on the predecessor of the inserted record */
1794
const dtuple_t* tuple, /* in: tuple to insert */
1795
ulint n_ext, /* in: number of externally stored columns */
1796
mtr_t* mtr) /* in: mtr */
1816
const dtuple_t* tuple, /*!< in: tuple to insert */
1817
ulint n_ext, /*!< in: number of externally stored columns */
1818
mtr_t* mtr) /*!< in: mtr */
1798
1820
buf_block_t* block;
2148
/*****************************************************************
2170
/*************************************************************//**
2149
2171
Removes a page from the level list of pages. */
2152
2174
btr_level_list_remove(
2153
2175
/*==================*/
2154
ulint space, /* in: space where removed */
2155
ulint zip_size,/* in: compressed page size in bytes
2176
ulint space, /*!< in: space where removed */
2177
ulint zip_size,/*!< in: compressed page size in bytes
2156
2178
or 0 for uncompressed pages */
2157
page_t* page, /* in: page to remove */
2158
mtr_t* mtr) /* in: mtr */
2179
page_t* page, /*!< in: page to remove */
2180
mtr_t* mtr) /*!< in: mtr */
2160
2182
ulint prev_page_no;
2161
2183
ulint next_page_no;
2208
/********************************************************************
2230
/****************************************************************//**
2209
2231
Writes the redo log record for setting an index record as the predefined
2210
2232
minimum record. */
2213
2235
btr_set_min_rec_mark_log(
2214
2236
/*=====================*/
2215
rec_t* rec, /* in: record */
2216
byte type, /* in: MLOG_COMP_REC_MIN_MARK or MLOG_REC_MIN_MARK */
2217
mtr_t* mtr) /* in: mtr */
2237
rec_t* rec, /*!< in: record */
2238
byte type, /*!< in: MLOG_COMP_REC_MIN_MARK or MLOG_REC_MIN_MARK */
2239
mtr_t* mtr) /*!< in: mtr */
2219
2241
mlog_write_initial_log_record(rec, type, mtr);
2221
2243
/* Write rec offset as a 2-byte ulint */
2222
2244
mlog_catenate_ulint(mtr, page_offset(rec), MLOG_2BYTES);
2246
#else /* !UNIV_HOTBACKUP */
2247
# define btr_set_min_rec_mark_log(rec,comp,mtr) ((void) 0)
2248
#endif /* !UNIV_HOTBACKUP */
2225
/********************************************************************
2250
/****************************************************************//**
2226
2251
Parses the redo log record for setting an index record as the predefined
2253
@return end of log record or NULL */
2230
2256
btr_parse_set_min_rec_mark(
2231
2257
/*=======================*/
2232
/* out: end of log record or NULL */
2233
byte* ptr, /* in: buffer */
2234
byte* end_ptr,/* in: buffer end */
2235
ulint comp, /* in: nonzero=compact page format */
2236
page_t* page, /* in: page or NULL */
2237
mtr_t* mtr) /* in: mtr or NULL */
2258
byte* ptr, /*!< in: buffer */
2259
byte* end_ptr,/*!< in: buffer end */
2260
ulint comp, /*!< in: nonzero=compact page format */
2261
page_t* page, /*!< in: page or NULL */
2262
mtr_t* mtr) /*!< in: mtr or NULL */
2254
2279
return(ptr + 2);
2257
/********************************************************************
2282
/****************************************************************//**
2258
2283
Sets a record as the predefined minimum record. */
2261
2286
btr_set_min_rec_mark(
2262
2287
/*=================*/
2263
rec_t* rec, /* in: record */
2264
mtr_t* mtr) /* in: mtr */
2288
rec_t* rec, /*!< in: record */
2289
mtr_t* mtr) /*!< in: mtr */
2266
2291
ulint info_bits;
2283
/*****************************************************************
2308
#ifndef UNIV_HOTBACKUP
2309
/*************************************************************//**
2284
2310
Deletes on the upper level the node pointer to a page. */
2287
2313
btr_node_ptr_delete(
2288
2314
/*================*/
2289
dict_index_t* index, /* in: index tree */
2290
buf_block_t* block, /* in: page whose node pointer is deleted */
2291
mtr_t* mtr) /* in: mtr */
2315
dict_index_t* index, /*!< in: index tree */
2316
buf_block_t* block, /*!< in: page whose node pointer is deleted */
2317
mtr_t* mtr) /*!< in: mtr */
2293
2319
btr_cur_t cursor;
2294
2320
ibool compressed;
2311
/*****************************************************************
2337
/*************************************************************//**
2312
2338
If page is the only on its level, this function moves its records to the
2313
2339
father page, thus reducing the tree height. */
2316
2342
btr_lift_page_up(
2317
2343
/*=============*/
2318
dict_index_t* index, /* in: index tree */
2319
buf_block_t* block, /* in: page which is the only on its level;
2344
dict_index_t* index, /*!< in: index tree */
2345
buf_block_t* block, /*!< in: page which is the only on its level;
2320
2346
must not be empty: use
2321
2347
btr_discard_only_page_on_level if the last
2322
2348
record from the page should be removed */
2323
mtr_t* mtr) /* in: mtr */
2349
mtr_t* mtr) /*!< in: mtr */
2325
2351
buf_block_t* father_block;
2326
2352
page_t* father_page;
2329
2355
page_t* page = buf_block_get_frame(block);
2330
2356
ulint root_page_no;
2331
2357
buf_block_t* blocks[BTR_MAX_LEVELS];
2332
ulint n_blocks; /* last used index in blocks[] */
2358
ulint n_blocks; /*!< last used index in blocks[] */
2335
2361
ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL);
2430
2456
ut_ad(btr_check_node_ptr(index, father_block, mtr));
2433
/*****************************************************************
2459
/*************************************************************//**
2434
2460
Tries to merge the page first to the left immediate brother if such a
2435
2461
brother exists, and the node pointers to the current page and to the brother
2436
2462
reside on the same page. If the left brother does not satisfy these
2438
2464
level lifts the records of the page to the father page, thus reducing the
2439
2465
tree height. It is assumed that mtr holds an x-latch on the tree and on the
2440
2466
page. If cursor is on the leaf level, mtr must also hold x-latches to the
2441
brothers, if they exist. */
2467
brothers, if they exist.
2468
@return TRUE on success */
2446
/* out: TRUE on success */
2447
btr_cur_t* cursor, /* in: cursor on the page to merge or lift;
2473
btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift;
2448
2474
the page must not be empty: in record delete
2449
2475
use btr_discard_page if the page would become
2451
mtr_t* mtr) /* in: mtr */
2477
mtr_t* mtr) /*!< in: mtr */
2453
2479
dict_index_t* index;
2725
/*****************************************************************
2751
/*************************************************************//**
2726
2752
Discards a page that is the only page on its level. This will empty
2727
2753
the whole B-tree, leaving just an empty root page. This function
2728
2754
should never be reached, because btr_compress(), which is invoked in
2732
2758
btr_discard_only_page_on_level(
2733
2759
/*===========================*/
2734
dict_index_t* index, /* in: index tree */
2735
buf_block_t* block, /* in: page which is the only on its level */
2736
mtr_t* mtr) /* in: mtr */
2760
dict_index_t* index, /*!< in: index tree */
2761
buf_block_t* block, /*!< in: page which is the only on its level */
2762
mtr_t* mtr) /*!< in: mtr */
2738
ulint page_level = 0;
2764
ulint page_level = 0;
2765
trx_id_t max_trx_id;
2767
/* Save the PAGE_MAX_TRX_ID from the leaf page. */
2768
max_trx_id = page_get_max_trx_id(buf_block_get_frame(block));
2740
2770
while (buf_block_get_page_no(block) != dict_index_get_page(index)) {
2741
2771
btr_cur_t cursor;
2779
2809
btr_page_empty(block, buf_block_get_page_zip(block), index, 0, mtr);
2781
/* We play it safe and reset the free bits for the root */
2782
2811
if (!dict_index_is_clust(index)) {
2812
/* We play it safe and reset the free bits for the root */
2783
2813
ibuf_reset_free_bits(block);
2815
if (page_is_leaf(buf_block_get_frame(block))) {
2816
ut_a(!ut_dulint_is_zero(max_trx_id));
2817
page_set_max_trx_id(block,
2818
buf_block_get_page_zip(block),
2787
/*****************************************************************
2824
/*************************************************************//**
2788
2825
Discards a page from a B-tree. This is used to remove the last record from
2789
2826
a B-tree page: the whole page must be removed at the same time. This cannot
2790
2827
be used for the root page, which is allowed to be empty. */
2932
2969
mtr_commit(&mtr);
2935
/****************************************************************
2972
/************************************************************//**
2936
2973
Prints recursively index tree pages. */
2939
2976
btr_print_recursive(
2940
2977
/*================*/
2941
dict_index_t* index, /* in: index tree */
2942
buf_block_t* block, /* in: index page */
2943
ulint width, /* in: print this many entries from start
2978
dict_index_t* index, /*!< in: index tree */
2979
buf_block_t* block, /*!< in: index page */
2980
ulint width, /*!< in: print this many entries from start
2945
mem_heap_t** heap, /* in/out: heap for rec_get_offsets() */
2946
ulint** offsets,/* in/out: buffer for rec_get_offsets() */
2947
mtr_t* mtr) /* in: mtr */
2982
mem_heap_t** heap, /*!< in/out: heap for rec_get_offsets() */
2983
ulint** offsets,/*!< in/out: buffer for rec_get_offsets() */
2984
mtr_t* mtr) /*!< in: mtr */
2949
2986
const page_t* page = buf_block_get_frame(block);
2950
2987
page_cur_t cursor;
2997
/******************************************************************
3034
/**************************************************************//**
2998
3035
Prints directories and other info of all nodes in the tree. */
3001
3038
btr_print_index(
3002
3039
/*============*/
3003
dict_index_t* index, /* in: index */
3004
ulint width) /* in: print this many entries from start
3040
dict_index_t* index, /*!< in: index */
3041
ulint width) /*!< in: print this many entries from start
3030
3067
#endif /* UNIV_BTR_PRINT */
3032
3069
#ifdef UNIV_DEBUG
3033
/****************************************************************
3034
Checks that the node pointer to a page is appropriate. */
3070
/************************************************************//**
3071
Checks that the node pointer to a page is appropriate.
3037
3075
btr_check_node_ptr(
3038
3076
/*===============*/
3040
dict_index_t* index, /* in: index tree */
3041
buf_block_t* block, /* in: index page */
3042
mtr_t* mtr) /* in: mtr */
3077
dict_index_t* index, /*!< in: index tree */
3078
buf_block_t* block, /*!< in: index page */
3079
mtr_t* mtr) /*!< in: mtr */
3044
3081
mem_heap_t* heap;
3045
3082
dtuple_t* tuple;
3075
3112
#endif /* UNIV_DEBUG */
3077
/****************************************************************
3114
/************************************************************//**
3078
3115
Display identification information for a record. */
3081
3118
btr_index_rec_validate_report(
3082
3119
/*==========================*/
3083
const page_t* page, /* in: index page */
3084
const rec_t* rec, /* in: index record */
3085
const dict_index_t* index) /* in: index */
3120
const page_t* page, /*!< in: index page */
3121
const rec_t* rec, /*!< in: index record */
3122
const dict_index_t* index) /*!< in: index */
3087
3124
fputs("InnoDB: Record in ", stderr);
3088
3125
dict_index_name_print(stderr, NULL, index);
3090
3127
page_get_page_no(page), (ulint) page_offset(rec));
3093
/****************************************************************
3130
/************************************************************//**
3094
3131
Checks the size and number of fields in a record based on the definition of
3133
@return TRUE if ok */
3098
3136
btr_index_rec_validate(
3099
3137
/*===================*/
3100
/* out: TRUE if ok */
3101
const rec_t* rec, /* in: index record */
3102
const dict_index_t* index, /* in: index */
3103
ibool dump_on_error) /* in: TRUE if the function
3138
const rec_t* rec, /*!< in: index record */
3139
const dict_index_t* index, /*!< in: index */
3140
ibool dump_on_error) /*!< in: TRUE if the function
3104
3141
should print hex dump of record
3105
3142
and page on error */
3156
3193
for (i = 0; i < n; i++) {
3157
3194
ulint fixed_size = dict_col_get_fixed_size(
3158
dict_index_get_nth_col(index, i));
3195
dict_index_get_nth_col(index, i), page_is_comp(page));
3160
3197
rec_get_nth_field_offs(offsets, i, &len);
3202
/****************************************************************
3239
/************************************************************//**
3203
3240
Checks the size and number of fields in records based on the definition of
3242
@return TRUE if ok */
3207
3245
btr_index_page_validate(
3208
3246
/*====================*/
3209
/* out: TRUE if ok */
3210
buf_block_t* block, /* in: index page */
3211
dict_index_t* index) /* in: index */
3247
buf_block_t* block, /*!< in: index page */
3248
dict_index_t* index) /*!< in: index */
3213
3250
page_cur_t cur;
3214
3251
ibool ret = TRUE;
3236
/****************************************************************
3273
/************************************************************//**
3237
3274
Report an error on one page of an index tree. */
3240
3277
btr_validate_report1(
3241
3278
/*=================*/
3242
/* out: TRUE if ok */
3243
dict_index_t* index, /* in: index */
3244
ulint level, /* in: B-tree level */
3245
const buf_block_t* block) /* in: index page */
3279
dict_index_t* index, /*!< in: index */
3280
ulint level, /*!< in: B-tree level */
3281
const buf_block_t* block) /*!< in: index page */
3247
3283
fprintf(stderr, "InnoDB: Error in page %lu of ",
3248
3284
buf_block_get_page_no(block));
3253
3289
putc('\n', stderr);
3256
/****************************************************************
3292
/************************************************************//**
3257
3293
Report an error on two pages of an index tree. */
3260
3296
btr_validate_report2(
3261
3297
/*=================*/
3262
/* out: TRUE if ok */
3263
const dict_index_t* index, /* in: index */
3264
ulint level, /* in: B-tree level */
3265
const buf_block_t* block1, /* in: first index page */
3266
const buf_block_t* block2) /* in: second index page */
3298
const dict_index_t* index, /*!< in: index */
3299
ulint level, /*!< in: B-tree level */
3300
const buf_block_t* block1, /*!< in: first index page */
3301
const buf_block_t* block2) /*!< in: second index page */
3268
3303
fprintf(stderr, "InnoDB: Error in pages %lu and %lu of ",
3269
3304
buf_block_get_page_no(block1),
3275
3310
putc('\n', stderr);
3278
/****************************************************************
3279
Validates index tree level. */
3313
/************************************************************//**
3314
Validates index tree level.
3315
@return TRUE if ok */
3282
3318
btr_validate_level(
3283
3319
/*===============*/
3284
/* out: TRUE if ok */
3285
dict_index_t* index, /* in: index tree */
3286
trx_t* trx, /* in: transaction or NULL */
3287
ulint level) /* in: level number */
3320
dict_index_t* index, /*!< in: index tree */
3321
trx_t* trx, /*!< in: transaction or NULL */
3322
ulint level) /*!< in: level number */
3290
3325
ulint zip_size;
3624
/******************************************************************
3625
Checks the consistency of an index tree. */
3659
/**************************************************************//**
3660
Checks the consistency of an index tree.
3661
@return TRUE if ok */
3628
3664
btr_validate_index(
3629
3665
/*===============*/
3630
/* out: TRUE if ok */
3631
dict_index_t* index, /* in: index */
3632
trx_t* trx) /* in: transaction or NULL */
3666
dict_index_t* index, /*!< in: index */
3667
trx_t* trx) /*!< in: transaction or NULL */