1
/*****************************************************************************
3
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
4
Copyright (c) 2008, Google Inc.
6
Portions of this file contain modifications contributed and copyrighted by
7
Google, Inc. Those modifications are gratefully acknowledged and are described
8
briefly in the InnoDB documentation. The contributions by Google are
9
incorporated with their permission, and subject to the conditions contained in
10
the file COPYING.Google.
12
This program is free software; you can redistribute it and/or modify it under
13
the terms of the GNU General Public License as published by the Free Software
14
Foundation; version 2 of the License.
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 for more details.
20
You should have received a copy of the GNU General Public License along with
21
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22
Place, Suite 330, Boston, MA 02111-1307 USA
24
*****************************************************************************/
1
26
/******************************************************
2
27
The index tree cursor
12
37
if leaf splitting has been started, it is difficult to undo, except
13
38
by crashing the database and doing a roll-forward.
15
(c) 1994-2001 Innobase Oy
17
40
Created 10/16/1994 Heikki Tuuri
18
41
*******************************************************/
368
389
#ifdef UNIV_SEARCH_PERF_STAT
369
390
info->n_searches++;
371
if (btr_search_latch.writer == RW_LOCK_NOT_LOCKED
392
if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_NOT_LOCKED
372
393
&& latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ
374
395
#ifdef PAGE_CUR_LE_OR_EXTENDS
375
396
&& mode != PAGE_CUR_LE_OR_EXTENDS
376
397
#endif /* PAGE_CUR_LE_OR_EXTENDS */
377
&& !UNIV_UNLIKELY(btr_search_disabled)
398
/* If !has_search_latch, we do a dirty read of
399
btr_search_enabled below, and btr_search_guess_on_hash()
400
will have to check it again. */
401
&& UNIV_LIKELY(btr_search_enabled)
378
402
&& btr_search_guess_on_hash(index, info, tuple, mode,
379
403
latch_mode, cursor,
380
404
has_search_latch, mtr)) {
462
484
buf_block_t* block;
488
zip_size = dict_table_zip_size(index->table);
489
rw_latch = RW_NO_LATCH;
492
if (height == 0 && latch_mode <= BTR_MODIFY_LEAF) {
494
rw_latch = latch_mode;
497
&& ibuf_should_try(index, ignore_sec_unique)) {
499
/* Try insert to the insert buffer if the
500
page is not in the buffer pool */
502
buf_mode = BUF_GET_IF_IN_POOL;
464
zip_size = dict_table_zip_size(index->table);
466
507
block = buf_page_get_gen(space, zip_size, page_no,
467
508
rw_latch, guess, buf_mode,
468
509
__FILE__, __LINE__, mtr);
474
515
ut_ad(insert_planned);
475
516
ut_ad(cursor->thr);
477
if (ibuf_should_try(index, ignore_sec_unique)
478
&& ibuf_insert(tuple, index, space, zip_size,
479
page_no, cursor->thr)) {
518
if (ibuf_insert(tuple, index, space, zip_size,
519
page_no, cursor->thr)) {
480
520
/* Insertion to the insert buffer succeeded */
481
521
cursor->flag = BTR_CUR_INSERT_TO_IBUF;
482
522
if (UNIV_LIKELY_NULL(heap)) {
496
536
page = buf_block_get_frame(block);
538
block->check_index_page_at_flush = TRUE;
540
if (rw_latch != RW_NO_LATCH) {
497
541
#ifdef UNIV_ZIP_DEBUG
498
if (rw_latch != RW_NO_LATCH) {
499
542
const page_zip_des_t* page_zip
500
543
= buf_block_get_page_zip(block);
501
544
ut_a(!page_zip || page_zip_validate(page_zip, page));
503
545
#endif /* UNIV_ZIP_DEBUG */
505
block->check_index_page_at_flush = TRUE;
507
if (rw_latch != RW_NO_LATCH) {
508
547
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
579
if ((height == 0) && (latch_mode <= BTR_MODIFY_LEAF)) {
581
rw_latch = latch_mode;
584
&& ibuf_should_try(index, ignore_sec_unique)) {
586
/* Try insert to the insert buffer if the
587
page is not in the buffer pool */
589
buf_mode = BUF_GET_IF_IN_POOL;
595
620
node_ptr = page_cur_get_rec(page_cursor);
610
635
cursor->up_bytes = up_bytes;
612
637
#ifdef BTR_CUR_ADAPT
613
if (!UNIV_UNLIKELY(btr_search_disabled)) {
638
/* We do a dirty read of btr_search_enabled here. We
639
will properly check btr_search_enabled again in
640
btr_search_build_page_hash_index() before building a
641
page hash index, while holding btr_search_latch. */
642
if (UNIV_LIKELY(btr_search_enabled)) {
615
644
btr_search_info_update(index, cursor);
1219
1248
buf_block_get_page_no(block), max_size,
1220
1249
rec_size + PAGE_DIR_SLOT_SIZE, index->type);
1222
if (!dict_index_is_clust(index) && leaf) {
1252
&& !dict_index_is_clust(index)
1253
&& !dict_index_is_ibuf(index)) {
1223
1254
/* Update the free bits of the B-tree page in the
1224
1255
insert buffer bitmap. */
1676
1708
rec = btr_cur_get_rec(cursor);
1677
1709
index = cursor->index;
1678
1710
ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
1711
/* The insert buffer tree should never be updated in place. */
1712
ut_ad(!dict_index_is_ibuf(index));
1679
1714
trx = thr_get_trx(thr);
1680
1715
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
1681
1716
#ifdef UNIV_DEBUG
1812
1847
index = cursor->index;
1813
1848
ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
1814
1849
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
1850
/* The insert buffer tree should never be updated in place. */
1851
ut_ad(!dict_index_is_ibuf(index));
1816
1853
heap = mem_heap_create(1024);
1817
1854
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
2075
2112
#ifdef UNIV_ZIP_DEBUG
2076
2113
ut_a(!page_zip || page_zip_validate(page_zip, page));
2077
2114
#endif /* UNIV_ZIP_DEBUG */
2115
/* The insert buffer tree should never be updated in place. */
2116
ut_ad(!dict_index_is_ibuf(index));
2079
2118
optim_err = btr_cur_optimistic_update(flags, cursor, update,
2080
2119
cmpl_info, thr, mtr);
2724
2763
delete; cursor stays valid: if deletion
2725
2764
succeeds, on function exit it points to the
2726
2765
successor of the deleted record */
2727
mtr_t* mtr) /* in: mtr */
2766
mtr_t* mtr) /* in: mtr; if this function returns
2767
TRUE on a leaf page of a secondary
2768
index, the mtr must be committed
2769
before latching any further pages */
2729
2771
buf_block_t* block;
2774
2816
#endif /* UNIV_ZIP_DEBUG */
2776
2818
if (dict_index_is_clust(cursor->index)
2819
|| dict_index_is_ibuf(cursor->index)
2777
2820
|| !page_is_leaf(page)) {
2778
2821
/* The insert buffer does not handle
2779
inserts to clustered indexes or to non-leaf
2780
pages of secondary index B-trees. */
2822
inserts to clustered indexes, to
2823
non-leaf pages of secondary index B-trees,
2824
or to the insert buffer. */
2781
2825
} else if (page_zip) {
2782
2826
ibuf_update_free_bits_zip(block, mtr);
4075
4119
/***********************************************************************
4120
Check the FIL_PAGE_TYPE on an uncompressed BLOB page. */
4123
btr_check_blob_fil_page_type(
4124
/*=========================*/
4125
ulint space_id, /* in: space id */
4126
ulint page_no, /* in: page number */
4127
const page_t* page, /* in: page */
4128
ibool read) /* in: TRUE=read, FALSE=purge */
4130
ulint type = fil_page_get_type(page);
4132
ut_a(space_id == page_get_space_id(page));
4133
ut_a(page_no == page_get_page_no(page));
4135
if (UNIV_UNLIKELY(type != FIL_PAGE_TYPE_BLOB)) {
4136
ulint flags = fil_space_get_flags(space_id);
4139
((flags & DICT_TF_FORMAT_MASK) == DICT_TF_FORMAT_51)) {
4140
/* Old versions of InnoDB did not initialize
4141
FIL_PAGE_TYPE on BLOB pages. Do not print
4142
anything about the type mismatch when reading
4143
a BLOB page that is in Antelope format.*/
4147
ut_print_timestamp(stderr);
4149
" InnoDB: FIL_PAGE_TYPE=%lu"
4150
" on BLOB %s space %lu page %lu flags %lx\n",
4151
(ulong) type, read ? "read" : "purge",
4152
(ulong) space_id, (ulong) page_no, (ulong) flags);
4157
/***********************************************************************
4076
4158
Frees the space in an externally stored field to the file space
4077
4159
management if the field in data is owned by the externally stored field,
4078
4160
in a rollback we may have the additional condition that the field must
4225
4307
MLOG_4BYTES, &mtr);
4228
ut_a(fil_page_get_type(page) == FIL_PAGE_TYPE_BLOB);
4229
4310
ut_a(!page_zip);
4311
btr_check_blob_fil_page_type(space_id, page_no, page,
4231
4314
next_page_no = mach_read_from_4(
4232
4315
page + FIL_PAGE_DATA
4236
4319
because we did not store it on the page (we save the
4237
4320
space overhead from an index page header. */
4239
ut_a(space_id == page_get_space_id(page));
4240
ut_a(page_no == page_get_page_no(page));
4242
4322
btr_page_free_low(index, ext_block, 0, &mtr);
4244
4324
mlog_write_ulint(field_ref + BTR_EXTERN_PAGE_NO,
4376
4456
buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE);
4377
4457
page = buf_block_get_frame(block);
4379
/* Unfortunately, FIL_PAGE_TYPE was uninitialized for
4380
many pages until MySQL/InnoDB 5.1.7. */
4381
/* ut_ad(fil_page_get_type(page) == FIL_PAGE_TYPE_BLOB); */
4459
btr_check_blob_fil_page_type(space_id, page_no, page, TRUE);
4382
4461
blob_header = page + offset;
4383
4462
part_len = btr_blob_get_part_len(blob_header);
4384
4463
copy_len = ut_min(part_len, len - copied_len);