1 /***************************************************************************** 2 3 Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License, version 2.0, 7 as published by the Free Software Foundation. 8 9 This program is also distributed with certain software (including 10 but not limited to OpenSSL) that is licensed under separate terms, 11 as designated in a particular file or component or in included license 12 documentation. The authors of MySQL hereby grant you an additional 13 permission to link the program and your derivative works with the 14 separately licensed software that they have included with MySQL. 15 16 This program is distributed in the hope that it will be useful, 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 GNU General Public License, version 2.0, for more details. 20 21 You should have received a copy of the GNU General Public License along with 22 this program; if not, write to the Free Software Foundation, Inc., 23 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA 24 25 *****************************************************************************/ 26 27 /**************************************************//** 28 @file include/page0page.h 29 Index page routines 30 31 Created 2/2/1994 Heikki Tuuri 32 *******************************************************/ 33 34 #ifndef page0page_h 35 #define page0page_h 36 37 #include "univ.i" 38 39 #include "page0types.h" 40 #include "fil0fil.h" 41 #include "buf0buf.h" 42 #include "data0data.h" 43 #include "dict0dict.h" 44 #include "rem0rec.h" 45 #include "fsp0fsp.h" 46 #include "mtr0mtr.h" 47 48 #ifdef UNIV_MATERIALIZE 49 #undef UNIV_INLINE 50 #define UNIV_INLINE 51 #endif 52 53 /* PAGE HEADER 54 =========== 55 56 Index page header starts at the first offset left free by the FIL-module */ 57 58 typedef byte page_header_t; 59 60 #define PAGE_HEADER FSEG_PAGE_DATA /* index page header starts at this 61 offset */ 62 /*-----------------------------*/ 63 #define PAGE_N_DIR_SLOTS 0 /* number of slots in page directory */ 64 #define PAGE_HEAP_TOP 2 /* pointer to record heap top */ 65 #define PAGE_N_HEAP 4 /* number of records in the heap, 66 bit 15=flag: new-style compact page format */ 67 #define PAGE_FREE 6 /* pointer to start of page free record list */ 68 #define PAGE_GARBAGE 8 /* number of bytes in deleted records */ 69 #define PAGE_LAST_INSERT 10 /* pointer to the last inserted record, or 70 NULL if this info has been reset by a delete, 71 for example */ 72 #define PAGE_DIRECTION 12 /* last insert direction: PAGE_LEFT, ... */ 73 #define PAGE_N_DIRECTION 14 /* number of consecutive inserts to the same 74 direction */ 75 #define PAGE_N_RECS 16 /* number of user records on the page */ 76 #define PAGE_MAX_TRX_ID 18 /* highest id of a trx which may have modified 77 a record on the page; trx_id_t; defined only 78 in secondary indexes and in the insert buffer 79 tree */ 80 #define PAGE_HEADER_PRIV_END 26 /* end of private data structure of the page 81 header which are set in a page create */ 82 /*----*/ 83 #define PAGE_LEVEL 26 /* level of the node in an index tree; the 84 leaf level is the level 0. This field should 85 not be written to after page creation. */ 86 #define PAGE_INDEX_ID 28 /* index id where the page belongs. 87 This field should not be written to after 88 page creation. */ 89 #define PAGE_BTR_SEG_LEAF 36 /* file segment header for the leaf pages in 90 a B-tree: defined only on the root page of a 91 B-tree, but not in the root of an ibuf tree */ 92 #define PAGE_BTR_IBUF_FREE_LIST PAGE_BTR_SEG_LEAF 93 #define PAGE_BTR_IBUF_FREE_LIST_NODE PAGE_BTR_SEG_LEAF 94 /* in the place of PAGE_BTR_SEG_LEAF and _TOP 95 there is a free list base node if the page is 96 the root page of an ibuf tree, and at the same 97 place is the free list node if the page is in 98 a free list */ 99 #define PAGE_BTR_SEG_TOP (36 + FSEG_HEADER_SIZE) 100 /* file segment header for the non-leaf pages 101 in a B-tree: defined only on the root page of 102 a B-tree, but not in the root of an ibuf 103 tree */ 104 /*----*/ 105 #define PAGE_DATA (PAGE_HEADER + 36 + 2 * FSEG_HEADER_SIZE) 106 /* start of data on the page */ 107 108 #define PAGE_OLD_INFIMUM (PAGE_DATA + 1 + REC_N_OLD_EXTRA_BYTES) 109 /* offset of the page infimum record on an 110 old-style page */ 111 #define PAGE_OLD_SUPREMUM (PAGE_DATA + 2 + 2 * REC_N_OLD_EXTRA_BYTES + 8) 112 /* offset of the page supremum record on an 113 old-style page */ 114 #define PAGE_OLD_SUPREMUM_END (PAGE_OLD_SUPREMUM + 9) 115 /* offset of the page supremum record end on 116 an old-style page */ 117 #define PAGE_NEW_INFIMUM (PAGE_DATA + REC_N_NEW_EXTRA_BYTES) 118 /* offset of the page infimum record on a 119 new-style compact page */ 120 #define PAGE_NEW_SUPREMUM (PAGE_DATA + 2 * REC_N_NEW_EXTRA_BYTES + 8) 121 /* offset of the page supremum record on a 122 new-style compact page */ 123 #define PAGE_NEW_SUPREMUM_END (PAGE_NEW_SUPREMUM + 8) 124 /* offset of the page supremum record end on 125 a new-style compact page */ 126 /*-----------------------------*/ 127 128 /* Heap numbers */ 129 #define PAGE_HEAP_NO_INFIMUM 0 /* page infimum */ 130 #define PAGE_HEAP_NO_SUPREMUM 1 /* page supremum */ 131 #define PAGE_HEAP_NO_USER_LOW 2 /* first user record in 132 creation (insertion) order, 133 not necessarily collation order; 134 this record may have been deleted */ 135 136 /* Directions of cursor movement */ 137 #define PAGE_LEFT 1 138 #define PAGE_RIGHT 2 139 #define PAGE_SAME_REC 3 140 #define PAGE_SAME_PAGE 4 141 #define PAGE_NO_DIRECTION 5 142 143 /* PAGE DIRECTORY 144 ============== 145 */ 146 147 typedef byte page_dir_slot_t; 148 typedef page_dir_slot_t page_dir_t; 149 150 /* Offset of the directory start down from the page end. We call the 151 slot with the highest file address directory start, as it points to 152 the first record in the list of records. */ 153 #define PAGE_DIR FIL_PAGE_DATA_END 154 155 /* We define a slot in the page directory as two bytes */ 156 #define PAGE_DIR_SLOT_SIZE 2 157 158 /* The offset of the physically lower end of the directory, counted from 159 page end, when the page is empty */ 160 #define PAGE_EMPTY_DIR_START (PAGE_DIR + 2 * PAGE_DIR_SLOT_SIZE) 161 162 /* The maximum and minimum number of records owned by a directory slot. The 163 number may drop below the minimum in the first and the last slot in the 164 directory. */ 165 #define PAGE_DIR_SLOT_MAX_N_OWNED 8 166 #define PAGE_DIR_SLOT_MIN_N_OWNED 4 167 168 /************************************************************//** 169 Gets the start of a page. 170 @return start of the page */ 171 UNIV_INLINE 172 page_t* 173 page_align( 174 /*=======*/ 175 const void* ptr) /*!< in: pointer to page frame */ 176 MY_ATTRIBUTE((const)); 177 /************************************************************//** 178 Gets the offset within a page. 179 @return offset from the start of the page */ 180 UNIV_INLINE 181 ulint 182 page_offset( 183 /*========*/ 184 const void* ptr) /*!< in: pointer to page frame */ 185 MY_ATTRIBUTE((const)); 186 /*************************************************************//** 187 Returns the max trx id field value. */ 188 UNIV_INLINE 189 trx_id_t 190 page_get_max_trx_id( 191 /*================*/ 192 const page_t* page); /*!< in: page */ 193 /*************************************************************//** 194 Sets the max trx id field value. */ 195 UNIV_INTERN 196 void 197 page_set_max_trx_id( 198 /*================*/ 199 buf_block_t* block, /*!< in/out: page */ 200 page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ 201 trx_id_t trx_id, /*!< in: transaction id */ 202 mtr_t* mtr); /*!< in/out: mini-transaction, or NULL */ 203 /*************************************************************//** 204 Sets the max trx id field value if trx_id is bigger than the previous 205 value. */ 206 UNIV_INLINE 207 void 208 page_update_max_trx_id( 209 /*===================*/ 210 buf_block_t* block, /*!< in/out: page */ 211 page_zip_des_t* page_zip,/*!< in/out: compressed page whose 212 uncompressed part will be updated, or NULL */ 213 trx_id_t trx_id, /*!< in: transaction id */ 214 mtr_t* mtr); /*!< in/out: mini-transaction */ 215 /*************************************************************//** 216 Reads the given header field. */ 217 UNIV_INLINE 218 ulint 219 page_header_get_field( 220 /*==================*/ 221 const page_t* page, /*!< in: page */ 222 ulint field); /*!< in: PAGE_N_DIR_SLOTS, ... */ 223 /*************************************************************//** 224 Sets the given header field. */ 225 UNIV_INLINE 226 void 227 page_header_set_field( 228 /*==================*/ 229 page_t* page, /*!< in/out: page */ 230 page_zip_des_t* page_zip,/*!< in/out: compressed page whose 231 uncompressed part will be updated, or NULL */ 232 ulint field, /*!< in: PAGE_N_DIR_SLOTS, ... */ 233 ulint val); /*!< in: value */ 234 /*************************************************************//** 235 Returns the offset stored in the given header field. 236 @return offset from the start of the page, or 0 */ 237 UNIV_INLINE 238 ulint 239 page_header_get_offs( 240 /*=================*/ 241 const page_t* page, /*!< in: page */ 242 ulint field) /*!< in: PAGE_FREE, ... */ 243 MY_ATTRIBUTE((nonnull, pure)); 244 245 /*************************************************************//** 246 Returns the pointer stored in the given header field, or NULL. */ 247 #define page_header_get_ptr(page, field) \ 248 (page_header_get_offs(page, field) \ 249 ? page + page_header_get_offs(page, field) : NULL) 250 /*************************************************************//** 251 Sets the pointer stored in the given header field. */ 252 UNIV_INLINE 253 void 254 page_header_set_ptr( 255 /*================*/ 256 page_t* page, /*!< in/out: page */ 257 page_zip_des_t* page_zip,/*!< in/out: compressed page whose 258 uncompressed part will be updated, or NULL */ 259 ulint field, /*!< in/out: PAGE_FREE, ... */ 260 const byte* ptr); /*!< in: pointer or NULL*/ 261 #ifndef UNIV_HOTBACKUP 262 /*************************************************************//** 263 Resets the last insert info field in the page header. Writes to mlog 264 about this operation. */ 265 UNIV_INLINE 266 void 267 page_header_reset_last_insert( 268 /*==========================*/ 269 page_t* page, /*!< in: page */ 270 page_zip_des_t* page_zip,/*!< in/out: compressed page whose 271 uncompressed part will be updated, or NULL */ 272 mtr_t* mtr); /*!< in: mtr */ 273 #endif /* !UNIV_HOTBACKUP */ 274 /************************************************************//** 275 Gets the offset of the first record on the page. 276 @return offset of the first record in record list, relative from page */ 277 UNIV_INLINE 278 ulint 279 page_get_infimum_offset( 280 /*====================*/ 281 const page_t* page); /*!< in: page which must have record(s) */ 282 /************************************************************//** 283 Gets the offset of the last record on the page. 284 @return offset of the last record in record list, relative from page */ 285 UNIV_INLINE 286 ulint 287 page_get_supremum_offset( 288 /*=====================*/ 289 const page_t* page); /*!< in: page which must have record(s) */ 290 #define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page)) 291 #define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page)) 292 293 /************************************************************//** 294 Returns the nth record of the record list. 295 This is the inverse function of page_rec_get_n_recs_before(). 296 @return nth record */ 297 UNIV_INTERN 298 const rec_t* 299 page_rec_get_nth_const( 300 /*===================*/ 301 const page_t* page, /*!< in: page */ 302 ulint nth) /*!< in: nth record */ 303 MY_ATTRIBUTE((nonnull, warn_unused_result)); 304 /************************************************************//** 305 Returns the nth record of the record list. 306 This is the inverse function of page_rec_get_n_recs_before(). 307 @return nth record */ 308 UNIV_INLINE 309 rec_t* 310 page_rec_get_nth( 311 /*=============*/ 312 page_t* page, /*< in: page */ 313 ulint nth) /*!< in: nth record */ 314 MY_ATTRIBUTE((nonnull, warn_unused_result)); 315 316 #ifndef UNIV_HOTBACKUP 317 /************************************************************//** 318 Returns the middle record of the records on the page. If there is an 319 even number of records in the list, returns the first record of the 320 upper half-list. 321 @return middle record */ 322 UNIV_INLINE 323 rec_t* 324 page_get_middle_rec( 325 /*================*/ 326 page_t* page) /*!< in: page */ 327 MY_ATTRIBUTE((nonnull, warn_unused_result)); 328 /*************************************************************//** 329 Compares a data tuple to a physical record. Differs from the function 330 cmp_dtuple_rec_with_match in the way that the record must reside on an 331 index page, and also page infimum and supremum records can be given in 332 the parameter rec. These are considered as the negative infinity and 333 the positive infinity in the alphabetical order. 334 @return 1, 0, -1, if dtuple is greater, equal, less than rec, 335 respectively, when only the common first fields are compared */ 336 UNIV_INLINE 337 int 338 page_cmp_dtuple_rec_with_match( 339 /*===========================*/ 340 const dtuple_t* dtuple, /*!< in: data tuple */ 341 const rec_t* rec, /*!< in: physical record on a page; may also 342 be page infimum or supremum, in which case 343 matched-parameter values below are not 344 affected */ 345 const ulint* offsets,/*!< in: array returned by rec_get_offsets() */ 346 ulint* matched_fields, /*!< in/out: number of already completely 347 matched fields; when function returns 348 contains the value for current comparison */ 349 ulint* matched_bytes); /*!< in/out: number of already matched 350 bytes within the first field not completely 351 matched; when function returns contains the 352 value for current comparison */ 353 #endif /* !UNIV_HOTBACKUP */ 354 /*************************************************************//** 355 Gets the page number. 356 @return page number */ 357 UNIV_INLINE 358 ulint 359 page_get_page_no( 360 /*=============*/ 361 const page_t* page); /*!< in: page */ 362 /*************************************************************//** 363 Gets the tablespace identifier. 364 @return space id */ 365 UNIV_INLINE 366 ulint 367 page_get_space_id( 368 /*==============*/ 369 const page_t* page); /*!< in: page */ 370 /*************************************************************//** 371 Gets the number of user records on page (the infimum and supremum records 372 are not user records). 373 @return number of user records */ 374 UNIV_INLINE 375 ulint 376 page_get_n_recs( 377 /*============*/ 378 const page_t* page); /*!< in: index page */ 379 /***************************************************************//** 380 Returns the number of records before the given record in chain. 381 The number includes infimum and supremum records. 382 This is the inverse function of page_rec_get_nth(). 383 @return number of records */ 384 UNIV_INTERN 385 ulint 386 page_rec_get_n_recs_before( 387 /*=======================*/ 388 const rec_t* rec); /*!< in: the physical record */ 389 /*************************************************************//** 390 Gets the number of records in the heap. 391 @return number of user records */ 392 UNIV_INLINE 393 ulint 394 page_dir_get_n_heap( 395 /*================*/ 396 const page_t* page); /*!< in: index page */ 397 /*************************************************************//** 398 Sets the number of records in the heap. */ 399 UNIV_INLINE 400 void 401 page_dir_set_n_heap( 402 /*================*/ 403 page_t* page, /*!< in/out: index page */ 404 page_zip_des_t* page_zip,/*!< in/out: compressed page whose 405 uncompressed part will be updated, or NULL. 406 Note that the size of the dense page directory 407 in the compressed page trailer is 408 n_heap * PAGE_ZIP_DIR_SLOT_SIZE. */ 409 ulint n_heap);/*!< in: number of records */ 410 /*************************************************************//** 411 Gets the number of dir slots in directory. 412 @return number of slots */ 413 UNIV_INLINE 414 ulint 415 page_dir_get_n_slots( 416 /*=================*/ 417 const page_t* page); /*!< in: index page */ 418 /*************************************************************//** 419 Sets the number of dir slots in directory. */ 420 UNIV_INLINE 421 void 422 page_dir_set_n_slots( 423 /*=================*/ 424 page_t* page, /*!< in/out: page */ 425 page_zip_des_t* page_zip,/*!< in/out: compressed page whose 426 uncompressed part will be updated, or NULL */ 427 ulint n_slots);/*!< in: number of slots */ 428 #ifdef UNIV_DEBUG 429 /*************************************************************//** 430 Gets pointer to nth directory slot. 431 @return pointer to dir slot */ 432 UNIV_INLINE 433 page_dir_slot_t* 434 page_dir_get_nth_slot( 435 /*==================*/ 436 const page_t* page, /*!< in: index page */ 437 ulint n); /*!< in: position */ 438 #else /* UNIV_DEBUG */ 439 # define page_dir_get_nth_slot(page, n) \ 440 ((page) + UNIV_PAGE_SIZE - PAGE_DIR \ 441 - (n + 1) * PAGE_DIR_SLOT_SIZE) 442 #endif /* UNIV_DEBUG */ 443 /**************************************************************//** 444 Used to check the consistency of a record on a page. 445 @return TRUE if succeed */ 446 UNIV_INLINE 447 ibool 448 page_rec_check( 449 /*===========*/ 450 const rec_t* rec); /*!< in: record */ 451 /***************************************************************//** 452 Gets the record pointed to by a directory slot. 453 @return pointer to record */ 454 UNIV_INLINE 455 const rec_t* 456 page_dir_slot_get_rec( 457 /*==================*/ 458 const page_dir_slot_t* slot); /*!< in: directory slot */ 459 /***************************************************************//** 460 This is used to set the record offset in a directory slot. */ 461 UNIV_INLINE 462 void 463 page_dir_slot_set_rec( 464 /*==================*/ 465 page_dir_slot_t* slot, /*!< in: directory slot */ 466 rec_t* rec); /*!< in: record on the page */ 467 /***************************************************************//** 468 Gets the number of records owned by a directory slot. 469 @return number of records */ 470 UNIV_INLINE 471 ulint 472 page_dir_slot_get_n_owned( 473 /*======================*/ 474 const page_dir_slot_t* slot); /*!< in: page directory slot */ 475 /***************************************************************//** 476 This is used to set the owned records field of a directory slot. */ 477 UNIV_INLINE 478 void 479 page_dir_slot_set_n_owned( 480 /*======================*/ 481 page_dir_slot_t*slot, /*!< in/out: directory slot */ 482 page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ 483 ulint n); /*!< in: number of records owned by the slot */ 484 /************************************************************//** 485 Calculates the space reserved for directory slots of a given 486 number of records. The exact value is a fraction number 487 n * PAGE_DIR_SLOT_SIZE / PAGE_DIR_SLOT_MIN_N_OWNED, and it is 488 rounded upwards to an integer. */ 489 UNIV_INLINE 490 ulint 491 page_dir_calc_reserved_space( 492 /*=========================*/ 493 ulint n_recs); /*!< in: number of records */ 494 /***************************************************************//** 495 Looks for the directory slot which owns the given record. 496 @return the directory slot number */ 497 UNIV_INTERN 498 ulint 499 page_dir_find_owner_slot( 500 /*=====================*/ 501 const rec_t* rec); /*!< in: the physical record */ 502 /************************************************************//** 503 Determine whether the page is in new-style compact format. 504 @return nonzero if the page is in compact format, zero if it is in 505 old-style format */ 506 UNIV_INLINE 507 ulint 508 page_is_comp( 509 /*=========*/ 510 const page_t* page); /*!< in: index page */ 511 /************************************************************//** 512 TRUE if the record is on a page in compact format. 513 @return nonzero if in compact format */ 514 UNIV_INLINE 515 ulint 516 page_rec_is_comp( 517 /*=============*/ 518 const rec_t* rec); /*!< in: record */ 519 /***************************************************************//** 520 Returns the heap number of a record. 521 @return heap number */ 522 UNIV_INLINE 523 ulint 524 page_rec_get_heap_no( 525 /*=================*/ 526 const rec_t* rec); /*!< in: the physical record */ 527 /************************************************************//** 528 Determine whether the page is a B-tree leaf. 529 @return true if the page is a B-tree leaf (PAGE_LEVEL = 0) */ 530 UNIV_INLINE 531 bool 532 page_is_leaf( 533 /*=========*/ 534 const page_t* page) /*!< in: page */ 535 MY_ATTRIBUTE((nonnull, pure)); 536 /************************************************************//** 537 Determine whether the page is empty. 538 @return true if the page is empty (PAGE_N_RECS = 0) */ 539 UNIV_INLINE 540 bool 541 page_is_empty( 542 /*==========*/ 543 const page_t* page) /*!< in: page */ 544 MY_ATTRIBUTE((nonnull, pure)); 545 /************************************************************//** 546 Determine whether the page contains garbage. 547 @return true if the page contains garbage (PAGE_GARBAGE is not 0) */ 548 UNIV_INLINE 549 bool 550 page_has_garbage( 551 /*=============*/ 552 const page_t* page) /*!< in: page */ 553 MY_ATTRIBUTE((nonnull, pure)); 554 /************************************************************//** 555 Gets the pointer to the next record on the page. 556 @return pointer to next record */ 557 UNIV_INLINE 558 const rec_t* 559 page_rec_get_next_low( 560 /*==================*/ 561 const rec_t* rec, /*!< in: pointer to record */ 562 ulint comp); /*!< in: nonzero=compact page layout */ 563 /************************************************************//** 564 Gets the pointer to the next record on the page. 565 @return pointer to next record */ 566 UNIV_INLINE 567 rec_t* 568 page_rec_get_next( 569 /*==============*/ 570 rec_t* rec); /*!< in: pointer to record */ 571 /************************************************************//** 572 Gets the pointer to the next record on the page. 573 @return pointer to next record */ 574 UNIV_INLINE 575 const rec_t* 576 page_rec_get_next_const( 577 /*====================*/ 578 const rec_t* rec); /*!< in: pointer to record */ 579 /************************************************************//** 580 Gets the pointer to the next non delete-marked record on the page. 581 If all subsequent records are delete-marked, then this function 582 will return the supremum record. 583 @return pointer to next non delete-marked record or pointer to supremum */ 584 UNIV_INLINE 585 const rec_t* 586 page_rec_get_next_non_del_marked( 587 /*=============================*/ 588 const rec_t* rec); /*!< in: pointer to record */ 589 /************************************************************//** 590 Sets the pointer to the next record on the page. */ 591 UNIV_INLINE 592 void 593 page_rec_set_next( 594 /*==============*/ 595 rec_t* rec, /*!< in: pointer to record, 596 must not be page supremum */ 597 const rec_t* next); /*!< in: pointer to next record, 598 must not be page infimum */ 599 /************************************************************//** 600 Gets the pointer to the previous record. 601 @return pointer to previous record */ 602 UNIV_INLINE 603 const rec_t* 604 page_rec_get_prev_const( 605 /*====================*/ 606 const rec_t* rec); /*!< in: pointer to record, must not be page 607 infimum */ 608 /************************************************************//** 609 Gets the pointer to the previous record. 610 @return pointer to previous record */ 611 UNIV_INLINE 612 rec_t* 613 page_rec_get_prev( 614 /*==============*/ 615 rec_t* rec); /*!< in: pointer to record, 616 must not be page infimum */ 617 /************************************************************//** 618 TRUE if the record is a user record on the page. 619 @return TRUE if a user record */ 620 UNIV_INLINE 621 ibool 622 page_rec_is_user_rec_low( 623 /*=====================*/ 624 ulint offset) /*!< in: record offset on page */ 625 MY_ATTRIBUTE((const)); 626 /************************************************************//** 627 TRUE if the record is the supremum record on a page. 628 @return TRUE if the supremum record */ 629 UNIV_INLINE 630 ibool 631 page_rec_is_supremum_low( 632 /*=====================*/ 633 ulint offset) /*!< in: record offset on page */ 634 MY_ATTRIBUTE((const)); 635 /************************************************************//** 636 TRUE if the record is the infimum record on a page. 637 @return TRUE if the infimum record */ 638 UNIV_INLINE 639 ibool 640 page_rec_is_infimum_low( 641 /*====================*/ 642 ulint offset) /*!< in: record offset on page */ 643 MY_ATTRIBUTE((const)); 644 645 /************************************************************//** 646 TRUE if the record is a user record on the page. 647 @return TRUE if a user record */ 648 UNIV_INLINE 649 ibool 650 page_rec_is_user_rec( 651 /*=================*/ 652 const rec_t* rec) /*!< in: record */ 653 MY_ATTRIBUTE((const)); 654 /************************************************************//** 655 TRUE if the record is the supremum record on a page. 656 @return TRUE if the supremum record */ 657 UNIV_INLINE 658 ibool 659 page_rec_is_supremum( 660 /*=================*/ 661 const rec_t* rec) /*!< in: record */ 662 MY_ATTRIBUTE((const)); 663 664 /************************************************************//** 665 TRUE if the record is the infimum record on a page. 666 @return TRUE if the infimum record */ 667 UNIV_INLINE 668 ibool 669 page_rec_is_infimum( 670 /*================*/ 671 const rec_t* rec) /*!< in: record */ 672 MY_ATTRIBUTE((const)); 673 /***************************************************************//** 674 Looks for the record which owns the given record. 675 @return the owner record */ 676 UNIV_INLINE 677 rec_t* 678 page_rec_find_owner_rec( 679 /*====================*/ 680 rec_t* rec); /*!< in: the physical record */ 681 #ifndef UNIV_HOTBACKUP 682 /***********************************************************************//** 683 Write a 32-bit field in a data dictionary record. */ 684 UNIV_INLINE 685 void 686 page_rec_write_field( 687 /*=================*/ 688 rec_t* rec, /*!< in/out: record to update */ 689 ulint i, /*!< in: index of the field to update */ 690 ulint val, /*!< in: value to write */ 691 mtr_t* mtr) /*!< in/out: mini-transaction */ 692 MY_ATTRIBUTE((nonnull)); 693 #endif /* !UNIV_HOTBACKUP */ 694 /************************************************************//** 695 Returns the maximum combined size of records which can be inserted on top 696 of record heap. 697 @return maximum combined size for inserted records */ 698 UNIV_INLINE 699 ulint 700 page_get_max_insert_size( 701 /*=====================*/ 702 const page_t* page, /*!< in: index page */ 703 ulint n_recs);/*!< in: number of records */ 704 /************************************************************//** 705 Returns the maximum combined size of records which can be inserted on top 706 of record heap if page is first reorganized. 707 @return maximum combined size for inserted records */ 708 UNIV_INLINE 709 ulint 710 page_get_max_insert_size_after_reorganize( 711 /*======================================*/ 712 const page_t* page, /*!< in: index page */ 713 ulint n_recs);/*!< in: number of records */ 714 /*************************************************************//** 715 Calculates free space if a page is emptied. 716 @return free space */ 717 UNIV_INLINE 718 ulint 719 page_get_free_space_of_empty( 720 /*=========================*/ 721 ulint comp) /*!< in: nonzero=compact page format */ 722 MY_ATTRIBUTE((const)); 723 /**********************************************************//** 724 Returns the base extra size of a physical record. This is the 725 size of the fixed header, independent of the record size. 726 @return REC_N_NEW_EXTRA_BYTES or REC_N_OLD_EXTRA_BYTES */ 727 UNIV_INLINE 728 ulint 729 page_rec_get_base_extra_size( 730 /*=========================*/ 731 const rec_t* rec); /*!< in: physical record */ 732 /************************************************************//** 733 Returns the sum of the sizes of the records in the record list 734 excluding the infimum and supremum records. 735 @return data in bytes */ 736 UNIV_INLINE 737 ulint 738 page_get_data_size( 739 /*===============*/ 740 const page_t* page); /*!< in: index page */ 741 /************************************************************//** 742 Allocates a block of memory from the head of the free list 743 of an index page. */ 744 UNIV_INLINE 745 void 746 page_mem_alloc_free( 747 /*================*/ 748 page_t* page, /*!< in/out: index page */ 749 page_zip_des_t* page_zip,/*!< in/out: compressed page with enough 750 space available for inserting the record, 751 or NULL */ 752 rec_t* next_rec,/*!< in: pointer to the new head of the 753 free record list */ 754 ulint need); /*!< in: number of bytes allocated */ 755 /************************************************************//** 756 Allocates a block of memory from the heap of an index page. 757 @return pointer to start of allocated buffer, or NULL if allocation fails */ 758 UNIV_INTERN 759 byte* 760 page_mem_alloc_heap( 761 /*================*/ 762 page_t* page, /*!< in/out: index page */ 763 page_zip_des_t* page_zip,/*!< in/out: compressed page with enough 764 space available for inserting the record, 765 or NULL */ 766 ulint need, /*!< in: total number of bytes needed */ 767 ulint* heap_no);/*!< out: this contains the heap number 768 of the allocated record 769 if allocation succeeds */ 770 /************************************************************//** 771 Puts a record to free list. */ 772 UNIV_INLINE 773 void 774 page_mem_free( 775 /*==========*/ 776 page_t* page, /*!< in/out: index page */ 777 page_zip_des_t* page_zip,/*!< in/out: compressed page, 778 or NULL */ 779 rec_t* rec, /*!< in: pointer to the (origin of) 780 record */ 781 const dict_index_t* index, /*!< in: index of rec */ 782 const ulint* offsets);/*!< in: array returned by 783 rec_get_offsets() */ 784 /**********************************************************//** 785 Create an uncompressed B-tree index page. 786 @return pointer to the page */ 787 UNIV_INTERN 788 page_t* 789 page_create( 790 /*========*/ 791 buf_block_t* block, /*!< in: a buffer block where the 792 page is created */ 793 mtr_t* mtr, /*!< in: mini-transaction handle */ 794 ulint comp); /*!< in: nonzero=compact page format */ 795 /**********************************************************//** 796 Create a compressed B-tree index page. 797 @return pointer to the page */ 798 UNIV_INTERN 799 page_t* 800 page_create_zip( 801 /*============*/ 802 buf_block_t* block, /*!< in/out: a buffer frame where the 803 page is created */ 804 dict_index_t* index, /*!< in: the index of the page */ 805 ulint level, /*!< in: the B-tree level of the page */ 806 trx_id_t max_trx_id, /*!< in: PAGE_MAX_TRX_ID */ 807 mtr_t* mtr) /*!< in/out: mini-transaction */ 808 MY_ATTRIBUTE((nonnull)); 809 /**********************************************************//** 810 Empty a previously created B-tree index page. */ 811 UNIV_INTERN 812 void 813 page_create_empty( 814 /*==============*/ 815 buf_block_t* block, /*!< in/out: B-tree block */ 816 dict_index_t* index, /*!< in: the index of the page */ 817 mtr_t* mtr) /*!< in/out: mini-transaction */ 818 MY_ATTRIBUTE((nonnull(1,2))); 819 /*************************************************************//** 820 Differs from page_copy_rec_list_end, because this function does not 821 touch the lock table and max trx id on page or compress the page. 822 823 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE 824 if new_block is a compressed leaf page in a secondary index. 825 This has to be done either within the same mini-transaction, 826 or by invoking ibuf_reset_free_bits() before mtr_commit(). */ 827 UNIV_INTERN 828 void 829 page_copy_rec_list_end_no_locks( 830 /*============================*/ 831 buf_block_t* new_block, /*!< in: index page to copy to */ 832 buf_block_t* block, /*!< in: index page of rec */ 833 rec_t* rec, /*!< in: record on page */ 834 dict_index_t* index, /*!< in: record descriptor */ 835 mtr_t* mtr); /*!< in: mtr */ 836 /*************************************************************//** 837 Copies records from page to new_page, from the given record onward, 838 including that record. Infimum and supremum records are not copied. 839 The records are copied to the start of the record list on new_page. 840 841 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE 842 if new_block is a compressed leaf page in a secondary index. 843 This has to be done either within the same mini-transaction, 844 or by invoking ibuf_reset_free_bits() before mtr_commit(). 845 846 @return pointer to the original successor of the infimum record on 847 new_page, or NULL on zip overflow (new_block will be decompressed) */ 848 UNIV_INTERN 849 rec_t* 850 page_copy_rec_list_end( 851 /*===================*/ 852 buf_block_t* new_block, /*!< in/out: index page to copy to */ 853 buf_block_t* block, /*!< in: index page containing rec */ 854 rec_t* rec, /*!< in: record on page */ 855 dict_index_t* index, /*!< in: record descriptor */ 856 mtr_t* mtr) /*!< in: mtr */ 857 MY_ATTRIBUTE((nonnull)); 858 /*************************************************************//** 859 Copies records from page to new_page, up to the given record, NOT 860 including that record. Infimum and supremum records are not copied. 861 The records are copied to the end of the record list on new_page. 862 863 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE 864 if new_block is a compressed leaf page in a secondary index. 865 This has to be done either within the same mini-transaction, 866 or by invoking ibuf_reset_free_bits() before mtr_commit(). 867 868 @return pointer to the original predecessor of the supremum record on 869 new_page, or NULL on zip overflow (new_block will be decompressed) */ 870 UNIV_INTERN 871 rec_t* 872 page_copy_rec_list_start( 873 /*=====================*/ 874 buf_block_t* new_block, /*!< in/out: index page to copy to */ 875 buf_block_t* block, /*!< in: index page containing rec */ 876 rec_t* rec, /*!< in: record on page */ 877 dict_index_t* index, /*!< in: record descriptor */ 878 mtr_t* mtr) /*!< in: mtr */ 879 MY_ATTRIBUTE((nonnull)); 880 /*************************************************************//** 881 Deletes records from a page from a given record onward, including that record. 882 The infimum and supremum records are not deleted. */ 883 UNIV_INTERN 884 void 885 page_delete_rec_list_end( 886 /*=====================*/ 887 rec_t* rec, /*!< in: pointer to record on page */ 888 buf_block_t* block, /*!< in: buffer block of the page */ 889 dict_index_t* index, /*!< in: record descriptor */ 890 ulint n_recs, /*!< in: number of records to delete, 891 or ULINT_UNDEFINED if not known */ 892 ulint size, /*!< in: the sum of the sizes of the 893 records in the end of the chain to 894 delete, or ULINT_UNDEFINED if not known */ 895 mtr_t* mtr) /*!< in: mtr */ 896 MY_ATTRIBUTE((nonnull)); 897 /*************************************************************//** 898 Deletes records from page, up to the given record, NOT including 899 that record. Infimum and supremum records are not deleted. */ 900 UNIV_INTERN 901 void 902 page_delete_rec_list_start( 903 /*=======================*/ 904 rec_t* rec, /*!< in: record on page */ 905 buf_block_t* block, /*!< in: buffer block of the page */ 906 dict_index_t* index, /*!< in: record descriptor */ 907 mtr_t* mtr) /*!< in: mtr */ 908 MY_ATTRIBUTE((nonnull)); 909 /*************************************************************//** 910 Moves record list end to another page. Moved records include 911 split_rec. 912 913 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE 914 if new_block is a compressed leaf page in a secondary index. 915 This has to be done either within the same mini-transaction, 916 or by invoking ibuf_reset_free_bits() before mtr_commit(). 917 918 @return TRUE on success; FALSE on compression failure (new_block will 919 be decompressed) */ 920 UNIV_INTERN 921 ibool 922 page_move_rec_list_end( 923 /*===================*/ 924 buf_block_t* new_block, /*!< in/out: index page where to move */ 925 buf_block_t* block, /*!< in: index page from where to move */ 926 rec_t* split_rec, /*!< in: first record to move */ 927 dict_index_t* index, /*!< in: record descriptor */ 928 mtr_t* mtr) /*!< in: mtr */ 929 MY_ATTRIBUTE((nonnull(1, 2, 4, 5))); 930 /*************************************************************//** 931 Moves record list start to another page. Moved records do not include 932 split_rec. 933 934 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE 935 if new_block is a compressed leaf page in a secondary index. 936 This has to be done either within the same mini-transaction, 937 or by invoking ibuf_reset_free_bits() before mtr_commit(). 938 939 @return TRUE on success; FALSE on compression failure */ 940 UNIV_INTERN 941 ibool 942 page_move_rec_list_start( 943 /*=====================*/ 944 buf_block_t* new_block, /*!< in/out: index page where to move */ 945 buf_block_t* block, /*!< in/out: page containing split_rec */ 946 rec_t* split_rec, /*!< in: first record not to move */ 947 dict_index_t* index, /*!< in: record descriptor */ 948 mtr_t* mtr) /*!< in: mtr */ 949 MY_ATTRIBUTE((nonnull(1, 2, 4, 5))); 950 /****************************************************************//** 951 Splits a directory slot which owns too many records. */ 952 UNIV_INTERN 953 void 954 page_dir_split_slot( 955 /*================*/ 956 page_t* page, /*!< in: index page */ 957 page_zip_des_t* page_zip,/*!< in/out: compressed page whose 958 uncompressed part will be written, or NULL */ 959 ulint slot_no)/*!< in: the directory slot */ 960 MY_ATTRIBUTE((nonnull(1))); 961 /*************************************************************//** 962 Tries to balance the given directory slot with too few records 963 with the upper neighbor, so that there are at least the minimum number 964 of records owned by the slot; this may result in the merging of 965 two slots. */ 966 UNIV_INTERN 967 void 968 page_dir_balance_slot( 969 /*==================*/ 970 page_t* page, /*!< in/out: index page */ 971 page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */ 972 ulint slot_no)/*!< in: the directory slot */ 973 MY_ATTRIBUTE((nonnull(1))); 974 /**********************************************************//** 975 Parses a log record of a record list end or start deletion. 976 @return end of log record or NULL */ 977 UNIV_INTERN 978 byte* 979 page_parse_delete_rec_list( 980 /*=======================*/ 981 byte type, /*!< in: MLOG_LIST_END_DELETE, 982 MLOG_LIST_START_DELETE, 983 MLOG_COMP_LIST_END_DELETE or 984 MLOG_COMP_LIST_START_DELETE */ 985 byte* ptr, /*!< in: buffer */ 986 byte* end_ptr,/*!< in: buffer end */ 987 buf_block_t* block, /*!< in/out: buffer block or NULL */ 988 dict_index_t* index, /*!< in: record descriptor */ 989 mtr_t* mtr); /*!< in: mtr or NULL */ 990 /***********************************************************//** 991 Parses a redo log record of creating a page. 992 @return end of log record or NULL */ 993 UNIV_INTERN 994 byte* 995 page_parse_create( 996 /*==============*/ 997 byte* ptr, /*!< in: buffer */ 998 byte* end_ptr,/*!< in: buffer end */ 999 ulint comp, /*!< in: nonzero=compact page format */ 1000 buf_block_t* block, /*!< in: block or NULL */ 1001 mtr_t* mtr); /*!< in: mtr or NULL */ 1002 #ifndef UNIV_HOTBACKUP 1003 /************************************************************//** 1004 Prints record contents including the data relevant only in 1005 the index page context. */ 1006 UNIV_INTERN 1007 void 1008 page_rec_print( 1009 /*===========*/ 1010 const rec_t* rec, /*!< in: physical record */ 1011 const ulint* offsets);/*!< in: record descriptor */ 1012 # ifdef UNIV_BTR_PRINT 1013 /***************************************************************//** 1014 This is used to print the contents of the directory for 1015 debugging purposes. */ 1016 UNIV_INTERN 1017 void 1018 page_dir_print( 1019 /*===========*/ 1020 page_t* page, /*!< in: index page */ 1021 ulint pr_n); /*!< in: print n first and n last entries */ 1022 /***************************************************************//** 1023 This is used to print the contents of the page record list for 1024 debugging purposes. */ 1025 UNIV_INTERN 1026 void 1027 page_print_list( 1028 /*============*/ 1029 buf_block_t* block, /*!< in: index page */ 1030 dict_index_t* index, /*!< in: dictionary index of the page */ 1031 ulint pr_n); /*!< in: print n first and n last entries */ 1032 /***************************************************************//** 1033 Prints the info in a page header. */ 1034 UNIV_INTERN 1035 void 1036 page_header_print( 1037 /*==============*/ 1038 const page_t* page); /*!< in: index page */ 1039 /***************************************************************//** 1040 This is used to print the contents of the page for 1041 debugging purposes. */ 1042 UNIV_INTERN 1043 void 1044 page_print( 1045 /*=======*/ 1046 buf_block_t* block, /*!< in: index page */ 1047 dict_index_t* index, /*!< in: dictionary index of the page */ 1048 ulint dn, /*!< in: print dn first and last entries 1049 in directory */ 1050 ulint rn); /*!< in: print rn first and last records 1051 in directory */ 1052 # endif /* UNIV_BTR_PRINT */ 1053 #endif /* !UNIV_HOTBACKUP */ 1054 /***************************************************************//** 1055 The following is used to validate a record on a page. This function 1056 differs from rec_validate as it can also check the n_owned field and 1057 the heap_no field. 1058 @return TRUE if ok */ 1059 UNIV_INTERN 1060 ibool 1061 page_rec_validate( 1062 /*==============*/ 1063 const rec_t* rec, /*!< in: physical record */ 1064 const ulint* offsets);/*!< in: array returned by rec_get_offsets() */ 1065 /***************************************************************//** 1066 Checks that the first directory slot points to the infimum record and 1067 the last to the supremum. This function is intended to track if the 1068 bug fixed in 4.0.14 has caused corruption to users' databases. */ 1069 UNIV_INTERN 1070 void 1071 page_check_dir( 1072 /*===========*/ 1073 const page_t* page); /*!< in: index page */ 1074 /***************************************************************//** 1075 This function checks the consistency of an index page when we do not 1076 know the index. This is also resilient so that this should never crash 1077 even if the page is total garbage. 1078 @return TRUE if ok */ 1079 UNIV_INTERN 1080 ibool 1081 page_simple_validate_old( 1082 /*=====================*/ 1083 const page_t* page); /*!< in: index page in ROW_FORMAT=REDUNDANT */ 1084 /***************************************************************//** 1085 This function checks the consistency of an index page when we do not 1086 know the index. This is also resilient so that this should never crash 1087 even if the page is total garbage. 1088 @return TRUE if ok */ 1089 UNIV_INTERN 1090 ibool 1091 page_simple_validate_new( 1092 /*=====================*/ 1093 const page_t* page); /*!< in: index page in ROW_FORMAT!=REDUNDANT */ 1094 /***************************************************************//** 1095 This function checks the consistency of an index page. 1096 @return TRUE if ok */ 1097 UNIV_INTERN 1098 ibool 1099 page_validate( 1100 /*==========*/ 1101 const page_t* page, /*!< in: index page */ 1102 dict_index_t* index); /*!< in: data dictionary index containing 1103 the page record type definition */ 1104 /***************************************************************//** 1105 Looks in the page record list for a record with the given heap number. 1106 @return record, NULL if not found */ 1107 1108 const rec_t* 1109 page_find_rec_with_heap_no( 1110 /*=======================*/ 1111 const page_t* page, /*!< in: index page */ 1112 ulint heap_no);/*!< in: heap number */ 1113 /** Get the last non-delete-marked record on a page. 1114 @param[in] page index tree leaf page 1115 @return the last record, not delete-marked 1116 @retval infimum record if all records are delete-marked */ 1117 1118 const rec_t* 1119 page_find_rec_max_not_deleted( 1120 const page_t* page); 1121 1122 /** Issue a warning when the checksum that is stored in the page is valid, 1123 but different than the global setting innodb_checksum_algorithm. 1124 @param[in] current_algo current checksum algorithm 1125 @param[in] page_checksum page valid checksum 1126 @param[in] space_id tablespace id 1127 @param[in] page_no page number */ 1128 void 1129 page_warn_strict_checksum( 1130 srv_checksum_algorithm_t curr_algo, 1131 srv_checksum_algorithm_t page_checksum, 1132 ulint space_id, 1133 ulint page_no); 1134 1135 #ifdef UNIV_MATERIALIZE 1136 #undef UNIV_INLINE 1137 #define UNIV_INLINE UNIV_INLINE_ORIGINAL 1138 #endif 1139 1140 #ifndef UNIV_NONINL 1141 #include "page0page.ic" 1142 #endif 1143 1144 #endif 1145