1
1
/*****************************************************************************
3
Copyright (C) 1994, 2010, Innobase Oy. All Rights Reserved.
3
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
592
592
@return rec_get_offsets() of the node pointer record */
595
btr_page_get_father_node_ptr_func(
596
/*==============================*/
595
btr_page_get_father_node_ptr(
596
/*=========================*/
597
597
ulint* offsets,/*!< in: work area for the return value */
598
598
mem_heap_t* heap, /*!< in: memory heap to use */
599
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
const char* file, /*!< in: file name */
603
ulint line, /*!< in: line where called */
604
602
mtr_t* mtr) /*!< in: mtr */
619
617
ut_ad(dict_index_get_page(index) != page_no);
621
619
level = btr_page_get_level(btr_cur_get_page(cursor), mtr);
623
620
user_rec = btr_cur_get_rec(cursor);
624
621
ut_a(page_rec_is_user_rec(user_rec));
625
622
tuple = dict_index_build_node_ptr(index, user_rec, 0, heap, level);
627
624
btr_cur_search_to_nth_level(index, level + 1, tuple, PAGE_CUR_LE,
628
BTR_CONT_MODIFY_TREE, cursor, 0,
625
BTR_CONT_MODIFY_TREE, cursor, 0, mtr);
631
627
node_ptr = btr_cur_get_rec(cursor);
632
628
ut_ad(!page_rec_is_comp(node_ptr)
677
#define btr_page_get_father_node_ptr(of,heap,cur,mtr) \
678
btr_page_get_father_node_ptr_func(of,heap,cur,__FILE__,__LINE__,mtr)
680
673
/************************************************************//**
681
674
Returns the upper level node pointer to a page. It is assumed that mtr holds
682
675
an x-latch on the tree.
735
728
ulint space, /*!< in: space where created */
736
729
ulint zip_size,/*!< in: compressed page size in bytes
737
730
or 0 for uncompressed pages */
738
index_id_t index_id,/*!< in: index id */
731
dulint index_id,/*!< in: index id */
739
732
dict_index_t* index, /*!< in: index */
740
733
mtr_t* mtr) /*!< in: mini-transaction handle */
981
973
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
983
975
#ifndef UNIV_HOTBACKUP
984
temp_block = buf_block_alloc(buf_pool, 0);
976
temp_block = buf_block_alloc(0);
985
977
#else /* !UNIV_HOTBACKUP */
986
978
ut_ad(block == back_block1);
987
979
temp_block = back_block2;
1018
1010
/* In crash recovery, dict_index_is_sec_or_ibuf() always
1019
1011
returns TRUE, even for clustered indexes. max_trx_id is
1020
1012
unused in clustered index pages. */
1021
ut_ad(max_trx_id != 0 || recovery);
1013
ut_ad(!ut_dulint_is_zero(max_trx_id) || recovery);
1024
1016
if (UNIV_LIKELY_NULL(page_zip)
1120
1112
btr_parse_page_reorganize(
1121
1113
/*======================*/
1122
1114
byte* ptr, /*!< in: buffer */
1123
byte* /*end_ptr __attribute__((unused))*/,
1115
byte* end_ptr __attribute__((unused)),
1124
1116
/*!< in: buffer end */
1125
1117
dict_index_t* index, /*!< in: record descriptor */
1126
1118
buf_block_t* block, /*!< in: page to be reorganized, or NULL */
1453
1445
its half-page when the split is performed. We assume in this function
1454
1446
only that the cursor page has at least one user record.
1455
1447
@return split record, or NULL if tuple will be the first record on
1456
the lower or upper half-page (determined by btr_page_tuple_smaller()) */
1459
btr_page_get_split_rec(
1460
/*===================*/
1451
btr_page_get_sure_split_rec(
1452
/*========================*/
1461
1453
btr_cur_t* cursor, /*!< in: cursor at which insert should be made */
1462
1454
const dtuple_t* tuple, /*!< in: tuple to insert */
1463
1455
ulint n_ext) /*!< in: number of externally stored columns */
1670
1662
that mtr holds an x-latch on the tree. */
1673
btr_insert_on_non_leaf_level_func(
1674
/*==============================*/
1665
btr_insert_on_non_leaf_level(
1666
/*=========================*/
1675
1667
dict_index_t* index, /*!< in: index */
1676
1668
ulint level, /*!< in: level, must be > 0 */
1677
1669
dtuple_t* tuple, /*!< in: the record to be inserted */
1678
const char* file, /*!< in: file name */
1679
ulint line, /*!< in: line where called */
1680
1670
mtr_t* mtr) /*!< in: mtr */
1682
1672
big_rec_t* dummy_big_rec;
1689
1679
btr_cur_search_to_nth_level(index, level, tuple, PAGE_CUR_LE,
1690
1680
BTR_CONT_MODIFY_TREE,
1691
&cursor, 0, file, line, mtr);
1693
1683
err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG
1694
1684
| BTR_KEEP_SYS_FLAG
1836
1826
/*************************************************************//**
1837
Determine if a tuple is smaller than any record on the page.
1838
@return TRUE if smaller */
1841
btr_page_tuple_smaller(
1842
/*===================*/
1843
btr_cur_t* cursor, /*!< in: b-tree cursor */
1844
const dtuple_t* tuple, /*!< in: tuple to consider */
1845
ulint* offsets,/*!< in/out: temporary storage */
1846
ulint n_uniq, /*!< in: number of unique fields
1847
in the index page records */
1848
mem_heap_t** heap) /*!< in/out: heap for offsets */
1851
const rec_t* first_rec;
1854
/* Read the first user record in the page. */
1855
block = btr_cur_get_block(cursor);
1856
page_cur_set_before_first(block, &pcur);
1857
page_cur_move_to_next(&pcur);
1858
first_rec = page_cur_get_rec(&pcur);
1860
offsets = rec_get_offsets(
1861
first_rec, cursor->index, offsets,
1864
return(cmp_dtuple_rec(tuple, first_rec, offsets) < 0);
1867
/*************************************************************//**
1868
1827
Splits an index page to halves and inserts the tuple. It is assumed
1869
1828
that mtr holds an x-latch to the index tree. NOTE: the tree x-latch is
1870
1829
released within this function! NOTE that the operation of this
1933
1893
/* 1. Decide the split record; split_rec == NULL means that the
1934
1894
tuple to be inserted should be the first record on the upper
1936
insert_left = FALSE;
1938
1897
if (n_iterations > 0) {
1939
1898
direction = FSP_UP;
1940
1899
hint_page_no = page_no + 1;
1941
split_rec = btr_page_get_split_rec(cursor, tuple, n_ext);
1900
split_rec = btr_page_get_sure_split_rec(cursor, tuple, n_ext);
1943
if (UNIV_UNLIKELY(split_rec == NULL)) {
1944
insert_left = btr_page_tuple_smaller(
1945
cursor, tuple, offsets, n_uniq, &heap);
1947
1902
} else if (btr_page_get_split_rec_to_right(cursor, &split_rec)) {
1948
1903
direction = FSP_UP;
1949
1904
hint_page_no = page_no + 1;
1950
1906
} else if (btr_page_get_split_rec_to_left(cursor, &split_rec)) {
1951
1907
direction = FSP_DOWN;
1952
1908
hint_page_no = page_no - 1;
1955
1910
direction = FSP_UP;
1956
1911
hint_page_no = page_no + 1;
1957
/* If there is only one record in the index page, we
1958
can't split the node in the middle by default. We need
1959
to determine whether the new record will be inserted
1960
to the left or right. */
1962
if (page_get_n_recs(page) > 1) {
1963
split_rec = page_get_middle_rec(page);
1964
} else if (btr_page_tuple_smaller(cursor, tuple,
1965
offsets, n_uniq, &heap)) {
1966
split_rec = page_rec_get_next(
1967
page_get_infimum_rec(page));
1913
if (page_get_n_recs(page) == 1) {
1916
/* There is only one record in the index page
1917
therefore we can't split the node in the middle
1918
by default. We need to determine whether the
1919
new record will be inserted to the left or right. */
1921
/* Read the first (and only) record in the page. */
1922
page_cur_set_before_first(block, &pcur);
1923
page_cur_move_to_next(&pcur);
1924
first_rec = page_cur_get_rec(&pcur);
1926
offsets = rec_get_offsets(
1927
first_rec, cursor->index, offsets,
1930
/* If the new record is less than the existing record
1931
the the split in the middle will copy the existing
1932
record to the new node. */
1933
if (cmp_dtuple_rec(tuple, first_rec, offsets) < 0) {
1934
split_rec = page_get_middle_rec(page);
1939
split_rec = page_get_middle_rec(page);
1996
1966
avoid further splits by inserting the record
1997
1967
to an empty page. */
1998
1968
split_rec = NULL;
2001
} else if (UNIV_UNLIKELY(insert_left)) {
2002
ut_a(n_iterations > 0);
2003
first_rec = page_rec_get_next(page_get_infimum_rec(page));
2004
move_limit = page_rec_get_next(btr_cur_get_rec(cursor));
2008
ut_ad(!insert_left);
2009
buf = (unsigned char *)mem_alloc(rec_get_converted_size(cursor->index,
1973
insert_left = FALSE;
1974
buf = mem_alloc(rec_get_converted_size(cursor->index,
2012
1977
first_rec = rec_convert_dtuple_to_rec(buf, cursor->index,
2029
1994
&& btr_page_insert_fits(cursor, split_rec,
2030
1995
offsets, tuple, n_ext, heap);
2037
1998
insert_will_fit = !new_page_zip
2038
1999
&& btr_page_insert_fits(cursor, NULL,
2039
2000
NULL, tuple, n_ext, heap);
2502
2461
/* Go upward to root page, decrementing levels by one. */
2503
2462
for (i = 0; i < n_blocks; i++, page_level++) {
2504
page_t* inner_page = buf_block_get_frame(blocks[i]);
2463
page_t* page = buf_block_get_frame(blocks[i]);
2505
2464
page_zip_des_t* page_zip= buf_block_get_page_zip(blocks[i]);
2507
2466
ut_ad(btr_page_get_level(page, mtr) == page_level + 1);
2509
btr_page_set_level(inner_page, page_zip, page_level, mtr);
2468
btr_page_set_level(page, page_zip, page_level, mtr);
2510
2469
#ifdef UNIV_ZIP_DEBUG
2511
ut_a(!page_zip || page_zip_validate(page_zip, inner_page));
2470
ut_a(!page_zip || page_zip_validate(page_zip, page));
2512
2471
#endif /* UNIV_ZIP_DEBUG */
2570
2530
ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
2571
2531
MTR_MEMO_X_LOCK));
2572
2532
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
2533
level = btr_page_get_level(page, mtr);
2573
2534
space = dict_index_get_space(index);
2574
2535
zip_size = dict_table_zip_size(index->table);