1 /***************************************************************************** 2 3 Copyright (c) 1994, 2020, Oracle and/or its affiliates. All Rights Reserved. 4 5 This program is free software; you can redistribute it and/or modify it under 6 the terms of the GNU General Public License, version 2.0, as published by the 7 Free Software Foundation. 8 9 This program is also distributed with certain software (including but not 10 limited to OpenSSL) that is licensed under separate terms, as designated in a 11 particular file or component or in included license documentation. The authors 12 of MySQL hereby grant you an additional permission to link the program and 13 your derivative works with the separately licensed software that they have 14 included with MySQL. 15 16 This program is distributed in the hope that it will be useful, but WITHOUT 17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 18 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, 19 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 St, Fifth Floor, Boston, MA 02110-1301 USA 24 25 *****************************************************************************/ 26 27 #include <stddef.h> 28 #include <sys/types.h> 29 30 /** @file include/page0page.h 31 Index page routines 32 33 Created 2/2/1994 Heikki Tuuri 34 *******************************************************/ 35 36 #ifndef page0page_h 37 #define page0page_h 38 39 #include "univ.i" 40 41 #include "buf0buf.h" 42 #include "data0data.h" 43 #include "dict0dict.h" 44 #include "fil0fil.h" 45 #include "fsp0fsp.h" 46 #include "mtr0mtr.h" 47 #include "page0types.h" 48 #include "rem0rec.h" 49 50 #ifdef UNIV_MATERIALIZE 51 #undef UNIV_INLINE 52 #define UNIV_INLINE 53 #endif 54 55 /* PAGE DIRECTORY 56 ============== 57 */ 58 59 typedef byte page_dir_slot_t; 60 typedef page_dir_slot_t page_dir_t; 61 62 /* Offset of the directory start down from the page end. We call the 63 slot with the highest file address directory start, as it points to 64 the first record in the list of records. */ 65 #define PAGE_DIR FIL_PAGE_DATA_END 66 67 /* We define a slot in the page directory as two bytes */ 68 #define PAGE_DIR_SLOT_SIZE 2 69 70 /* The offset of the physically lower end of the directory, counted from 71 page end, when the page is empty */ 72 #define PAGE_EMPTY_DIR_START (PAGE_DIR + 2 * PAGE_DIR_SLOT_SIZE) 73 74 /* The maximum and minimum number of records owned by a directory slot. The 75 number may drop below the minimum in the first and the last slot in the 76 directory. */ 77 #define PAGE_DIR_SLOT_MAX_N_OWNED 8 78 #define PAGE_DIR_SLOT_MIN_N_OWNED 4 79 80 /* The infimum and supremum records are omitted from the compressed page. 81 On compress, we compare that the records are there, and on uncompress we 82 restore the records. */ 83 /** Extra bytes of an infimum record */ 84 static const byte infimum_extra[] = { 85 0x01, /* info_bits=0, n_owned=1 */ 86 0x00, 0x02 /* heap_no=0, status=2 */ 87 /* ?, ? */ /* next=(first user rec, or supremum) */ 88 }; 89 /** Data bytes of an infimum record */ 90 static const byte infimum_data[] = { 91 0x69, 0x6e, 0x66, 0x69, 0x6d, 0x75, 0x6d, 0x00 /* "infimum\0" */ 92 }; 93 /** Extra bytes and data bytes of a supremum record */ 94 static const byte supremum_extra_data[] = { 95 /* 0x0?, */ /* info_bits=0, n_owned=1..8 */ 96 0x00, 97 0x0b, /* heap_no=1, status=3 */ 98 0x00, 99 0x00, /* next=0 */ 100 0x73, 101 0x75, 102 0x70, 103 0x72, 104 0x65, 105 0x6d, 106 0x75, 107 0x6d /* "supremum" */ 108 }; 109 110 /** Gets the start of a page. 111 @param[in] ptr pointer to page frame 112 @return start of the page */ 113 UNIV_INLINE 114 page_t *page_align(const void *ptr); 115 116 /** Gets the offset within a page. 117 @param[in] ptr pointer to page frame 118 @return offset from the start of the page */ 119 UNIV_INLINE 120 ulint page_offset(const void *ptr); 121 122 /** Returns the max trx id field value. */ 123 UNIV_INLINE 124 trx_id_t page_get_max_trx_id(const page_t *page); /*!< in: page */ 125 /** Sets the max trx id field value. */ 126 void page_set_max_trx_id( 127 buf_block_t *block, /*!< in/out: page */ 128 page_zip_des_t *page_zip, /*!< in/out: compressed page, or NULL */ 129 trx_id_t trx_id, /*!< in: transaction id */ 130 mtr_t *mtr); /*!< in/out: mini-transaction, or NULL */ 131 132 /** Sets the max trx id field value if trx_id is bigger than the previous 133 value. 134 @param[in,out] block page 135 @param[in,out] page_zip compressed page whose uncompressed part will 136 be updated, or NULL 137 @param[in] trx_id transaction id 138 @param[in,out] mtr mini-transaction */ 139 UNIV_INLINE 140 void page_update_max_trx_id(buf_block_t *block, page_zip_des_t *page_zip, 141 trx_id_t trx_id, mtr_t *mtr); 142 143 /** Returns the RTREE SPLIT SEQUENCE NUMBER (FIL_RTREE_SPLIT_SEQ_NUM). 144 @param[in] page page 145 @return SPLIT SEQUENCE NUMBER */ 146 UNIV_INLINE 147 node_seq_t page_get_ssn_id(const page_t *page); 148 149 /** Sets the RTREE SPLIT SEQUENCE NUMBER field value 150 @param[in,out] block page 151 @param[in,out] page_zip compressed page whose uncompressed part will 152 be updated, or NULL 153 @param[in] ssn_id split sequence id 154 @param[in,out] mtr mini-transaction */ 155 UNIV_INLINE 156 void page_set_ssn_id(buf_block_t *block, page_zip_des_t *page_zip, 157 node_seq_t ssn_id, mtr_t *mtr); 158 159 /** Reads the given header field. 160 @param[in] page page 161 @param[in] field PAGE_N_DIR_SLOTS, ... */ 162 UNIV_INLINE 163 ulint page_header_get_field(const page_t *page, ulint field); 164 165 /** Sets the given header field. 166 @param[in,out] page page 167 @param[in,out] page_zip compressed page whose uncompressed part will 168 be updated, or NULL 169 @param[in] field PAGE_N_DIR_SLOTS, ... 170 @param[in] val value */ 171 UNIV_INLINE 172 void page_header_set_field(page_t *page, page_zip_des_t *page_zip, ulint field, 173 ulint val); 174 175 /** Returns the offset stored in the given header field. 176 @return offset from the start of the page, or 0 */ 177 UNIV_INLINE 178 ulint page_header_get_offs(const page_t *page, /*!< in: page */ 179 ulint field) /*!< in: PAGE_FREE, ... */ 180 MY_ATTRIBUTE((warn_unused_result)); 181 182 /** Returns the pointer stored in the given header field, or NULL. */ 183 #define page_header_get_ptr(page, field) \ 184 (page_header_get_offs(page, field) \ 185 ? page + page_header_get_offs(page, field) \ 186 : NULL) 187 188 /** Sets the pointer stored in the given header field. 189 @param[in,out] page page 190 @param[in,out] page_zip compressed page whose uncompressed part will 191 be updated, or NULL 192 @param[in,out] field PAGE_FREE, ... 193 @param[in] ptr pointer or NULL */ 194 UNIV_INLINE 195 void page_header_set_ptr(page_t *page, page_zip_des_t *page_zip, ulint field, 196 const byte *ptr); 197 #ifndef UNIV_HOTBACKUP 198 199 /** Resets the last insert info field in the page header. Writes to mlog about 200 this operation. 201 @param[in] page page 202 @param[in,out] page_zip compressed page whose uncompressed part will 203 be updated, or NULL 204 @param[in] mtr mtr */ 205 UNIV_INLINE 206 void page_header_reset_last_insert(page_t *page, page_zip_des_t *page_zip, 207 mtr_t *mtr); 208 #endif /* !UNIV_HOTBACKUP */ 209 210 /** Gets the offset of the first record on the page. 211 @return offset of the first record in record list, relative from page */ 212 UNIV_INLINE 213 ulint page_get_infimum_offset( 214 const page_t *page); /*!< in: page which must have record(s) */ 215 /** Gets the offset of the last record on the page. 216 @return offset of the last record in record list, relative from page */ 217 UNIV_INLINE 218 ulint page_get_supremum_offset( 219 const page_t *page); /*!< in: page which must have record(s) */ 220 #define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page)) 221 #define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page)) 222 223 /** Returns the nth record of the record list. 224 This is the inverse function of page_rec_get_n_recs_before(). 225 @return nth record */ 226 const rec_t *page_rec_get_nth_const(const page_t *page, /*!< in: page */ 227 ulint nth) /*!< in: nth record */ 228 MY_ATTRIBUTE((warn_unused_result)); 229 230 /** Returns the nth record of the record list. 231 This is the inverse function of page_rec_get_n_recs_before(). 232 @param[in] page page 233 @param[in] nth nth record 234 @return nth record */ 235 UNIV_INLINE 236 rec_t *page_rec_get_nth(page_t *page, ulint nth) 237 MY_ATTRIBUTE((warn_unused_result)); 238 239 #ifndef UNIV_HOTBACKUP 240 /** Returns the middle record of the records on the page. If there is an 241 even number of records in the list, returns the first record of the 242 upper half-list. 243 @return middle record */ 244 UNIV_INLINE 245 rec_t *page_get_middle_rec(page_t *page) /*!< in: page */ 246 MY_ATTRIBUTE((warn_unused_result)); 247 #endif /* !UNIV_HOTBACKUP */ 248 /** Gets the page number. 249 @return page number */ 250 UNIV_INLINE 251 page_no_t page_get_page_no(const page_t *page); /*!< in: page */ 252 /** Gets the tablespace identifier. 253 @return space id */ 254 UNIV_INLINE 255 space_id_t page_get_space_id(const page_t *page); /*!< in: page */ 256 257 /** Gets the space id and page number identifying the page. 258 @return page number */ 259 UNIV_INLINE 260 page_id_t page_get_page_id(const page_t *page); 261 262 /** Gets the number of user records on page (the infimum and supremum records 263 are not user records). 264 @return number of user records */ 265 UNIV_INLINE 266 ulint page_get_n_recs(const page_t *page); /*!< in: index page */ 267 /** Returns the number of records before the given record in chain. 268 The number includes infimum and supremum records. 269 This is the inverse function of page_rec_get_nth(). 270 @return number of records */ 271 ulint page_rec_get_n_recs_before( 272 const rec_t *rec); /*!< in: the physical record */ 273 /** Gets the number of records in the heap. 274 @return number of user records */ 275 UNIV_INLINE 276 ulint page_dir_get_n_heap(const page_t *page); /*!< in: index page */ 277 278 /** Sets the number of records in the heap. 279 @param[in,out] page index page 280 @param[in,out] page_zip compressed page whose uncompressed part will 281 be updated, or NULL. Note that the size of the 282 dense page directory in the compressed page 283 trailer is n_heap * PAGE_ZIP_DIR_SLOT_SIZE. 284 @param[in] n_heap number of records*/ 285 UNIV_INLINE 286 void page_dir_set_n_heap(page_t *page, page_zip_des_t *page_zip, ulint n_heap); 287 288 /** Gets the number of dir slots in directory. 289 @return number of slots */ 290 UNIV_INLINE 291 ulint page_dir_get_n_slots(const page_t *page); /*!< in: index page */ 292 293 /** Sets the number of dir slots in directory. 294 @param[in,out] page page 295 @param[in,out] page_zip compressed page whose uncompressed part will 296 be updated, or NULL 297 @param[in] n_slots number of slots */ 298 UNIV_INLINE 299 void page_dir_set_n_slots(page_t *page, page_zip_des_t *page_zip, 300 ulint n_slots); 301 302 #ifdef UNIV_DEBUG 303 /** Gets pointer to nth directory slot. 304 @param[in] page index page 305 @param[in] n position 306 @return pointer to dir slot */ 307 UNIV_INLINE 308 page_dir_slot_t *page_dir_get_nth_slot(const page_t *page, ulint n); 309 #else /* UNIV_DEBUG */ 310 #define page_dir_get_nth_slot(page, n) \ 311 ((page) + (UNIV_PAGE_SIZE - PAGE_DIR - (n + 1) * PAGE_DIR_SLOT_SIZE)) 312 #endif /* UNIV_DEBUG */ 313 314 /** Used to check the consistency of a record on a page. 315 @return true if succeed */ 316 UNIV_INLINE 317 ibool page_rec_check(const rec_t *rec); /*!< in: record */ 318 /** Gets the record pointed to by a directory slot. 319 @return pointer to record */ 320 UNIV_INLINE 321 const rec_t *page_dir_slot_get_rec( 322 const page_dir_slot_t *slot); /*!< in: directory slot */ 323 324 /** This is used to set the record offset in a directory slot. 325 @param[in] rec record on the page 326 @param[in] slot directory slot */ 327 UNIV_INLINE 328 void page_dir_slot_set_rec(page_dir_slot_t *slot, rec_t *rec); 329 330 /** Gets the number of records owned by a directory slot. 331 @return number of records */ 332 UNIV_INLINE 333 ulint page_dir_slot_get_n_owned( 334 const page_dir_slot_t *slot); /*!< in: page directory slot */ 335 336 /** This is used to set the owned records field of a directory slot. 337 @param[in,out] slot directory slot 338 @param[in,out] page_zip compressed page, or NULL 339 @param[in] n number of records owned by the slot */ 340 UNIV_INLINE 341 void page_dir_slot_set_n_owned(page_dir_slot_t *slot, page_zip_des_t *page_zip, 342 ulint n); 343 344 /** Calculates the space reserved for directory slots of a given 345 number of records. The exact value is a fraction number 346 n * PAGE_DIR_SLOT_SIZE / PAGE_DIR_SLOT_MIN_N_OWNED, and it is 347 rounded upwards to an integer. */ 348 UNIV_INLINE 349 ulint page_dir_calc_reserved_space(ulint n_recs); /*!< in: number of records */ 350 /** Looks for the directory slot which owns the given record. 351 @return the directory slot number */ 352 ulint page_dir_find_owner_slot( 353 const rec_t *rec); /*!< in: the physical record */ 354 /** Determine whether the page is in new-style compact format. 355 @return nonzero if the page is in compact format, zero if it is in 356 old-style format */ 357 UNIV_INLINE 358 ulint page_is_comp(const page_t *page); /*!< in: index page */ 359 /** TRUE if the record is on a page in compact format. 360 @return nonzero if in compact format */ 361 UNIV_INLINE 362 ulint page_rec_is_comp(const rec_t *rec); /*!< in: record */ 363 /** Returns the heap number of a record. 364 @return heap number */ 365 UNIV_INLINE 366 ulint page_rec_get_heap_no(const rec_t *rec); /*!< in: the physical record */ 367 /** Determine whether the page is a B-tree leaf. 368 @return true if the page is a B-tree leaf (PAGE_LEVEL = 0) */ 369 UNIV_INLINE 370 bool page_is_leaf(const page_t *page) /*!< in: page */ 371 MY_ATTRIBUTE((warn_unused_result)); 372 /** Determine whether the page is empty. 373 @return true if the page is empty (PAGE_N_RECS = 0) */ 374 UNIV_INLINE 375 bool page_is_empty(const page_t *page) /*!< in: page */ 376 MY_ATTRIBUTE((warn_unused_result)); 377 /** Determine whether a page is an index root page. 378 @param[in] page page frame 379 @return true if the page is a root page of an index */ 380 UNIV_INLINE 381 bool page_is_root(const page_t *page) MY_ATTRIBUTE((warn_unused_result)); 382 /** Determine whether the page contains garbage. 383 @return true if the page contains garbage (PAGE_GARBAGE is not 0) */ 384 UNIV_INLINE 385 bool page_has_garbage(const page_t *page) /*!< in: page */ 386 MY_ATTRIBUTE((warn_unused_result)); 387 388 /** Gets the pointer to the next record on the page. 389 @param[in] rec pointer to record 390 @param[in] comp nonzero=compact page layout 391 @return pointer to next record */ 392 UNIV_INLINE 393 const rec_t *page_rec_get_next_low(const rec_t *rec, ulint comp); 394 395 /** Gets the pointer to the next record on the page. 396 @return pointer to next record */ 397 UNIV_INLINE 398 rec_t *page_rec_get_next(rec_t *rec); /*!< in: pointer to record */ 399 /** Gets the pointer to the next record on the page. 400 @return pointer to next record */ 401 UNIV_INLINE 402 const rec_t *page_rec_get_next_const( 403 const rec_t *rec); /*!< in: pointer to record */ 404 /** Gets the pointer to the next non delete-marked record on the page. 405 If all subsequent records are delete-marked, then this function 406 will return the supremum record. 407 @return pointer to next non delete-marked record or pointer to supremum */ 408 UNIV_INLINE 409 const rec_t *page_rec_get_next_non_del_marked( 410 const rec_t *rec); /*!< in: pointer to record */ 411 412 /** Sets the pointer to the next record on the page. 413 @param[in] rec pointer to record, must not be page supremum 414 @param[in] next pointer to next record, must not be page infimum */ 415 UNIV_INLINE 416 void page_rec_set_next(rec_t *rec, const rec_t *next); 417 418 /** Gets the pointer to the previous record. 419 @return pointer to previous record */ 420 UNIV_INLINE 421 const rec_t *page_rec_get_prev_const( 422 const rec_t *rec); /*!< in: pointer to record, must not be page 423 infimum */ 424 /** Gets the pointer to the previous record. 425 @return pointer to previous record */ 426 UNIV_INLINE 427 rec_t *page_rec_get_prev(rec_t *rec); /*!< in: pointer to record, 428 must not be page infimum */ 429 /** TRUE if the record is a user record on the page. 430 @param[in] offset record offset on page 431 @return true if a user record */ 432 UNIV_INLINE 433 ibool page_rec_is_user_rec_low(ulint offset); 434 435 /** TRUE if the record is the supremum record on a page. 436 @param[in] offset record offset on page 437 @return true if the supremum record */ 438 UNIV_INLINE 439 ibool page_rec_is_supremum_low(ulint offset); 440 441 /** TRUE if the record is the infimum record on a page. 442 @param[in] offset record offset on page 443 @return true if the infimum record */ 444 UNIV_INLINE 445 ibool page_rec_is_infimum_low(ulint offset); 446 447 /** TRUE if the record is a user record on the page. 448 @return true if a user record */ 449 UNIV_INLINE 450 ibool page_rec_is_user_rec(const rec_t *rec) /*!< in: record */ 451 MY_ATTRIBUTE((warn_unused_result)); 452 /** TRUE if the record is the supremum record on a page. 453 @return true if the supremum record */ 454 UNIV_INLINE 455 ibool page_rec_is_supremum(const rec_t *rec) /*!< in: record */ 456 MY_ATTRIBUTE((warn_unused_result)); 457 458 /** TRUE if the record is the infimum record on a page. 459 @return true if the infimum record */ 460 UNIV_INLINE 461 ibool page_rec_is_infimum(const rec_t *rec) /*!< in: record */ 462 MY_ATTRIBUTE((warn_unused_result)); 463 464 /** true if the record is the first user record on a page. 465 @return true if the first user record */ 466 UNIV_INLINE 467 bool page_rec_is_first(const rec_t *rec, /*!< in: record */ 468 const page_t *page) /*!< in: page */ 469 MY_ATTRIBUTE((warn_unused_result)); 470 471 /** true if the record is the second user record on a page. 472 @return true if the second user record */ 473 UNIV_INLINE 474 bool page_rec_is_second(const rec_t *rec, /*!< in: record */ 475 const page_t *page) /*!< in: page */ 476 MY_ATTRIBUTE((warn_unused_result)); 477 478 /** true if the record is the last user record on a page. 479 @return true if the last user record */ 480 UNIV_INLINE 481 bool page_rec_is_last(const rec_t *rec, /*!< in: record */ 482 const page_t *page) /*!< in: page */ 483 MY_ATTRIBUTE((warn_unused_result)); 484 485 /** true if distance between the records (measured in number of times we have to 486 move to the next record) is at most the specified value 487 @param[in] left_rec lefter record 488 @param[in] right_rec righter record 489 @param[in] val specified value to compare 490 @return true if the distance is smaller than the value */ 491 UNIV_INLINE 492 bool page_rec_distance_is_at_most(const rec_t *left_rec, const rec_t *right_rec, 493 ulint val) MY_ATTRIBUTE((warn_unused_result)); 494 495 /** true if the record is the second last user record on a page. 496 @return true if the second last user record */ 497 UNIV_INLINE 498 bool page_rec_is_second_last(const rec_t *rec, /*!< in: record */ 499 const page_t *page) /*!< in: page */ 500 MY_ATTRIBUTE((warn_unused_result)); 501 502 /** Looks for the record which owns the given record. 503 @return the owner record */ 504 UNIV_INLINE 505 rec_t *page_rec_find_owner_rec(rec_t *rec); /*!< in: the physical record */ 506 #ifndef UNIV_HOTBACKUP 507 508 /** Write a 32-bit field in a data dictionary record. 509 @param[in,out] rec record to update 510 @param[in] i index of the field to update 511 @param[in] val value to write 512 @param[in,out] mtr mini-transaction */ 513 UNIV_INLINE 514 void page_rec_write_field(rec_t *rec, ulint i, ulint val, mtr_t *mtr); 515 #endif /* !UNIV_HOTBACKUP */ 516 517 /** Returns the maximum combined size of records which can be inserted on top 518 of record heap. 519 @param[in] page index page 520 @param[in] n_recs number of records 521 @return maximum combined size for inserted records */ 522 UNIV_INLINE 523 ulint page_get_max_insert_size(const page_t *page, ulint n_recs); 524 525 /** Returns the maximum combined size of records which can be inserted on top 526 of record heap if page is first reorganized. 527 @param[in] page index page 528 @param[in] n_recs number of records 529 @return maximum combined size for inserted records */ 530 UNIV_INLINE 531 ulint page_get_max_insert_size_after_reorganize(const page_t *page, 532 ulint n_recs); 533 534 /** Calculates free space if a page is emptied. 535 @param[in] comp nonzero=compact page format 536 @return free space */ 537 UNIV_INLINE 538 ulint page_get_free_space_of_empty(ulint comp); 539 540 /** Returns the base extra size of a physical record. This is the 541 size of the fixed header, independent of the record size. 542 @return REC_N_NEW_EXTRA_BYTES or REC_N_OLD_EXTRA_BYTES */ 543 UNIV_INLINE 544 ulint page_rec_get_base_extra_size( 545 const rec_t *rec); /*!< in: physical record */ 546 /** Returns the sum of the sizes of the records in the record list 547 excluding the infimum and supremum records. 548 @return data in bytes */ 549 UNIV_INLINE 550 ulint page_get_data_size(const page_t *page); /*!< in: index page */ 551 552 /** Allocates a block of memory from the head of the free list of an index 553 page. 554 @param[in,out] page index page 555 @param[in,out] page_zip compressed page with enough space available 556 for inserting the record, or NULL 557 @param[in] next_rec pointer to the new head of the free record 558 list 559 @param[in] need number of bytes allocated */ 560 UNIV_INLINE 561 void page_mem_alloc_free(page_t *page, page_zip_des_t *page_zip, 562 rec_t *next_rec, ulint need); 563 564 /** Allocates a block of memory from the heap of an index page. 565 @return pointer to start of allocated buffer, or NULL if allocation fails */ 566 byte *page_mem_alloc_heap( 567 page_t *page, /*!< in/out: index page */ 568 page_zip_des_t *page_zip, /*!< in/out: compressed page with enough 569 space available for inserting the record, 570 or NULL */ 571 ulint need, /*!< in: total number of bytes needed */ 572 ulint *heap_no); /*!< out: this contains the heap number 573 of the allocated record 574 if allocation succeeds */ 575 576 /** Puts a record to free list. 577 @param[in,out] page index page 578 @param[in,out] page_zip compressed page, or NULL 579 @param[in] rec pointer to the (origin of) record 580 @param[in] index index of rec 581 @param[in] offsets array returned by rec_get_offsets() */ 582 UNIV_INLINE 583 void page_mem_free(page_t *page, page_zip_des_t *page_zip, rec_t *rec, 584 const dict_index_t *index, const ulint *offsets); 585 586 /** Create an uncompressed B-tree or R-tree or SDI index page. 587 @param[in] block a buffer block where the page is created 588 @param[in] mtr mini-transaction handle 589 @param[in] comp nonzero=compact page format 590 @param[in] page_type page type 591 @return pointer to the page */ 592 page_t *page_create(buf_block_t *block, mtr_t *mtr, ulint comp, 593 page_type_t page_type); 594 595 /** Create a compressed B-tree index page. 596 @param[in,out] block buffer frame where the page is created 597 @param[in] index index of the page, or NULL when applying 598 TRUNCATE log record during recovery 599 @param[in] level the B-tree level of the page 600 @param[in] max_trx_id PAGE_MAX_TRX_ID 601 @param[in] mtr mini-transaction handle 602 @param[in] page_type page_type to be created. Only FIL_PAGE_INDEX, 603 FIL_PAGE_RTREE, FIL_PAGE_SDI allowed */ 604 page_t *page_create_zip(buf_block_t *block, dict_index_t *index, ulint level, 605 trx_id_t max_trx_id, mtr_t *mtr, page_type_t page_type); 606 607 /** Empty a previously created B-tree index page. */ 608 void page_create_empty(buf_block_t *block, /*!< in/out: B-tree block */ 609 dict_index_t *index, /*!< in: the index of the page */ 610 mtr_t *mtr); /*!< in/out: mini-transaction */ 611 /** Differs from page_copy_rec_list_end, because this function does not 612 touch the lock table and max trx id on page or compress the page. 613 614 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE 615 if new_block is a compressed leaf page in a secondary index. 616 This has to be done either within the same mini-transaction, 617 or by invoking ibuf_reset_free_bits() before mtr_commit(). */ 618 void page_copy_rec_list_end_no_locks( 619 buf_block_t *new_block, /*!< in: index page to copy to */ 620 buf_block_t *block, /*!< in: index page of rec */ 621 rec_t *rec, /*!< in: record on page */ 622 dict_index_t *index, /*!< in: record descriptor */ 623 mtr_t *mtr); /*!< in: mtr */ 624 /** Copies records from page to new_page, from the given record onward, 625 including that record. Infimum and supremum records are not copied. 626 The records are copied to the start of the record list on new_page. 627 628 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE 629 if new_block is a compressed leaf page in a secondary index. 630 This has to be done either within the same mini-transaction, 631 or by invoking ibuf_reset_free_bits() before mtr_commit(). 632 633 @return pointer to the original successor of the infimum record on 634 new_page, or NULL on zip overflow (new_block will be decompressed) */ 635 rec_t *page_copy_rec_list_end( 636 buf_block_t *new_block, /*!< in/out: index page to copy to */ 637 buf_block_t *block, /*!< in: index page containing rec */ 638 rec_t *rec, /*!< in: record on page */ 639 dict_index_t *index, /*!< in: record descriptor */ 640 mtr_t *mtr); /*!< in: mtr */ 641 /** Copies records from page to new_page, up to the given record, NOT 642 including that record. Infimum and supremum records are not copied. 643 The records are copied to the end of the record list on new_page. 644 645 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE 646 if new_block is a compressed leaf page in a secondary index. 647 This has to be done either within the same mini-transaction, 648 or by invoking ibuf_reset_free_bits() before mtr_commit(). 649 650 @return pointer to the original predecessor of the supremum record on 651 new_page, or NULL on zip overflow (new_block will be decompressed) */ 652 rec_t *page_copy_rec_list_start( 653 buf_block_t *new_block, /*!< in/out: index page to copy to */ 654 buf_block_t *block, /*!< in: index page containing rec */ 655 rec_t *rec, /*!< in: record on page */ 656 dict_index_t *index, /*!< in: record descriptor */ 657 mtr_t *mtr); /*!< in: mtr */ 658 /** Deletes records from a page from a given record onward, including that 659 record. The infimum and supremum records are not deleted. */ 660 void page_delete_rec_list_end( 661 rec_t *rec, /*!< in: pointer to record on page */ 662 buf_block_t *block, /*!< in: buffer block of the page */ 663 dict_index_t *index, /*!< in: record descriptor */ 664 ulint n_recs, /*!< in: number of records to delete, 665 or ULINT_UNDEFINED if not known */ 666 ulint size, /*!< in: the sum of the sizes of the 667 records in the end of the chain to 668 delete, or ULINT_UNDEFINED if not known */ 669 mtr_t *mtr); /*!< in: mtr */ 670 /** Deletes records from page, up to the given record, NOT including 671 that record. Infimum and supremum records are not deleted. */ 672 void page_delete_rec_list_start( 673 rec_t *rec, /*!< in: record on page */ 674 buf_block_t *block, /*!< in: buffer block of the page */ 675 dict_index_t *index, /*!< in: record descriptor */ 676 mtr_t *mtr); /*!< in: mtr */ 677 /** Moves record list end to another page. Moved records include 678 split_rec. 679 680 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE 681 if new_block is a compressed leaf page in a secondary index. 682 This has to be done either within the same mini-transaction, 683 or by invoking ibuf_reset_free_bits() before mtr_commit(). 684 685 @return true on success; false on compression failure (new_block will 686 be decompressed) */ 687 ibool page_move_rec_list_end( 688 buf_block_t *new_block, /*!< in/out: index page where to move */ 689 buf_block_t *block, /*!< in: index page from where to move */ 690 rec_t *split_rec, /*!< in: first record to move */ 691 dict_index_t *index, /*!< in: record descriptor */ 692 mtr_t *mtr); /*!< in: mtr */ 693 /** Moves record list start to another page. Moved records do not include 694 split_rec. 695 696 IMPORTANT: The caller will have to update IBUF_BITMAP_FREE 697 if new_block is a compressed leaf page in a secondary index. 698 This has to be done either within the same mini-transaction, 699 or by invoking ibuf_reset_free_bits() before mtr_commit(). 700 701 @return true on success; false on compression failure */ 702 ibool page_move_rec_list_start( 703 buf_block_t *new_block, /*!< in/out: index page where to move */ 704 buf_block_t *block, /*!< in/out: page containing split_rec */ 705 rec_t *split_rec, /*!< in: first record not to move */ 706 dict_index_t *index, /*!< in: record descriptor */ 707 mtr_t *mtr); /*!< in: mtr */ 708 /** Splits a directory slot which owns too many records. */ 709 void page_dir_split_slot( 710 page_t *page, /*!< in: index page */ 711 page_zip_des_t *page_zip, /*!< in/out: compressed page whose 712 uncompressed part will be written, or NULL */ 713 ulint slot_no); /*!< in: the directory slot */ 714 /** Tries to balance the given directory slot with too few records 715 with the upper neighbor, so that there are at least the minimum number 716 of records owned by the slot; this may result in the merging of 717 two slots. */ 718 void page_dir_balance_slot( 719 page_t *page, /*!< in/out: index page */ 720 page_zip_des_t *page_zip, /*!< in/out: compressed page, or NULL */ 721 ulint slot_no); /*!< in: the directory slot */ 722 /** Parses a log record of a record list end or start deletion. 723 @return end of log record or NULL */ 724 byte *page_parse_delete_rec_list( 725 mlog_id_t type, /*!< in: MLOG_LIST_END_DELETE, 726 MLOG_LIST_START_DELETE, 727 MLOG_COMP_LIST_END_DELETE or 728 MLOG_COMP_LIST_START_DELETE */ 729 byte *ptr, /*!< in: buffer */ 730 byte *end_ptr, /*!< in: buffer end */ 731 buf_block_t *block, /*!< in/out: buffer block or NULL */ 732 dict_index_t *index, /*!< in: record descriptor */ 733 mtr_t *mtr); /*!< in: mtr or NULL */ 734 735 /** Parses a redo log record of creating a page. 736 @param[in,out] block buffer block, or NULL 737 @param[in] comp nonzero=compact page format 738 @param[in] page_type page type */ 739 void page_parse_create(buf_block_t *block, ulint comp, page_type_t page_type); 740 #ifndef UNIV_HOTBACKUP 741 /** Prints record contents including the data relevant only in 742 the index page context. */ 743 void page_rec_print(const rec_t *rec, /*!< in: physical record */ 744 const ulint *offsets); /*!< in: record descriptor */ 745 #ifdef UNIV_BTR_PRINT 746 /** This is used to print the contents of the directory for 747 debugging purposes. */ 748 void page_dir_print(page_t *page, /*!< in: index page */ 749 ulint pr_n); /*!< in: print n first and n last entries */ 750 /** This is used to print the contents of the page record list for 751 debugging purposes. */ 752 void page_print_list( 753 buf_block_t *block, /*!< in: index page */ 754 dict_index_t *index, /*!< in: dictionary index of the page */ 755 ulint pr_n); /*!< in: print n first and n last entries */ 756 /** Prints the info in a page header. */ 757 void page_header_print(const page_t *page); /*!< in: index page */ 758 /** This is used to print the contents of the page for 759 debugging purposes. */ 760 void page_print(buf_block_t *block, /*!< in: index page */ 761 dict_index_t *index, /*!< in: dictionary index of the page */ 762 ulint dn, /*!< in: print dn first and last entries 763 in directory */ 764 ulint rn); /*!< in: print rn first and last records 765 in directory */ 766 #endif /* UNIV_BTR_PRINT */ 767 #endif /* !UNIV_HOTBACKUP */ 768 /** The following is used to validate a record on a page. This function 769 differs from rec_validate as it can also check the n_owned field and 770 the heap_no field. 771 @return true if ok */ 772 ibool page_rec_validate( 773 const rec_t *rec, /*!< in: physical record */ 774 const ulint *offsets); /*!< in: array returned by rec_get_offsets() */ 775 #ifdef UNIV_DEBUG 776 /** Checks that the first directory slot points to the infimum record and 777 the last to the supremum. This function is intended to track if the 778 bug fixed in 4.0.14 has caused corruption to users' databases. */ 779 void page_check_dir(const page_t *page); /*!< in: index page */ 780 #endif /* UNIV_DEBUG */ 781 /** This function checks the consistency of an index page when we do not 782 know the index. This is also resilient so that this should never crash 783 even if the page is total garbage. 784 @return true if ok */ 785 ibool page_simple_validate_old( 786 const page_t *page); /*!< in: index page in ROW_FORMAT=REDUNDANT */ 787 /** This function checks the consistency of an index page when we do not 788 know the index. This is also resilient so that this should never crash 789 even if the page is total garbage. 790 @return true if ok */ 791 ibool page_simple_validate_new( 792 const page_t *page); /*!< in: index page in ROW_FORMAT!=REDUNDANT */ 793 /** This function checks the consistency of an index page. 794 @return true if ok */ 795 ibool page_validate( 796 const page_t *page, /*!< in: index page */ 797 dict_index_t *index); /*!< in: data dictionary index containing 798 the page record type definition */ 799 /** Looks in the page record list for a record with the given heap number. 800 @return record, NULL if not found */ 801 const rec_t *page_find_rec_with_heap_no( 802 const page_t *page, /*!< in: index page */ 803 ulint heap_no); /*!< in: heap number */ 804 /** Get the last non-delete-marked record on a page. 805 @param[in] page index tree leaf page 806 @return the last record, not delete-marked 807 @retval infimum record if all records are delete-marked */ 808 const rec_t *page_find_rec_last_not_deleted(const page_t *page); 809 810 /** Issue a warning when the checksum that is stored in the page is valid, 811 but different than the global setting innodb_checksum_algorithm. 812 @param[in] curr_algo current checksum algorithm 813 @param[in] page_checksum page valid checksum 814 @param[in] page_id page identifier */ 815 void page_warn_strict_checksum(srv_checksum_algorithm_t curr_algo, 816 srv_checksum_algorithm_t page_checksum, 817 const page_id_t &page_id); 818 819 /** Check that a page_size is correct for InnoDB. 820 If correct, set the associated page_size_shift which is the power of 2 821 for this page size. 822 @param[in] page_size Page Size to evaluate 823 @return an associated page_size_shift if valid, 0 if invalid. */ 824 inline ulong page_size_validate(ulong page_size); 825 826 /** This function checks if the page in which record is present is a 827 non-leaf node of a spatial index. 828 param[in] rec Btree record 829 param[in] index index 830 @return TRUE if ok */ 831 bool page_is_spatial_non_leaf(const rec_t *rec, dict_index_t *index); 832 833 #ifdef UNIV_MATERIALIZE 834 #undef UNIV_INLINE 835 #define UNIV_INLINE UNIV_INLINE_ORIGINAL 836 #endif 837 838 #include "page0page.ic" 839 840 #endif 841