00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "btr0pcur.h"
00027
00028 #ifdef UNIV_NONINL
00029 #include "btr0pcur.ic"
00030 #endif
00031
00032 #include "ut0byte.h"
00033 #include "rem0cmp.h"
00034 #include "trx0trx.h"
00035
00036
00039 UNIV_INTERN
00040 btr_pcur_t*
00041 btr_pcur_create_for_mysql(void)
00042
00043 {
00044 btr_pcur_t* pcur;
00045
00046 pcur = (btr_pcur_t *)mem_alloc(sizeof(btr_pcur_t));
00047
00048 pcur->btr_cur.index = NULL;
00049 btr_pcur_init(pcur);
00050
00051 return(pcur);
00052 }
00053
00054
00056 UNIV_INTERN
00057 void
00058 btr_pcur_free_for_mysql(
00059
00060 btr_pcur_t* cursor)
00061 {
00062 if (cursor->old_rec_buf != NULL) {
00063
00064 mem_free(cursor->old_rec_buf);
00065
00066 cursor->old_rec_buf = NULL;
00067 }
00068
00069 cursor->btr_cur.page_cur.rec = NULL;
00070 cursor->old_rec = NULL;
00071 cursor->old_n_fields = 0;
00072 cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
00073
00074 cursor->latch_mode = BTR_NO_LATCHES;
00075 cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
00076
00077 mem_free(cursor);
00078 }
00079
00080
00087 UNIV_INTERN
00088 void
00089 btr_pcur_store_position(
00090
00091 btr_pcur_t* cursor,
00092 mtr_t* mtr)
00093 {
00094 page_cur_t* page_cursor;
00095 buf_block_t* block;
00096 rec_t* rec;
00097 dict_index_t* index;
00098 page_t* page;
00099 ulint offs;
00100
00101 ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
00102 ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
00103
00104 block = btr_pcur_get_block(cursor);
00105 index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));
00106
00107 page_cursor = btr_pcur_get_page_cur(cursor);
00108
00109 rec = page_cur_get_rec(page_cursor);
00110 page = page_align(rec);
00111 offs = page_offset(rec);
00112
00113 ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_S_FIX)
00114 || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
00115 ut_a(cursor->latch_mode != BTR_NO_LATCHES);
00116
00117 if (UNIV_UNLIKELY(page_get_n_recs(page) == 0)) {
00118
00119
00120
00121
00122 ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
00123 ut_a(btr_page_get_prev(page, mtr) == FIL_NULL);
00124
00125 cursor->old_stored = BTR_PCUR_OLD_STORED;
00126
00127 if (page_rec_is_supremum_low(offs)) {
00128
00129 cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE;
00130 } else {
00131 cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE;
00132 }
00133
00134 return;
00135 }
00136
00137 if (page_rec_is_supremum_low(offs)) {
00138
00139 rec = page_rec_get_prev(rec);
00140
00141 cursor->rel_pos = BTR_PCUR_AFTER;
00142
00143 } else if (page_rec_is_infimum_low(offs)) {
00144
00145 rec = page_rec_get_next(rec);
00146
00147 cursor->rel_pos = BTR_PCUR_BEFORE;
00148 } else {
00149 cursor->rel_pos = BTR_PCUR_ON;
00150 }
00151
00152 cursor->old_stored = BTR_PCUR_OLD_STORED;
00153 cursor->old_rec = dict_index_copy_rec_order_prefix(
00154 index, rec, &cursor->old_n_fields,
00155 &cursor->old_rec_buf, &cursor->buf_size);
00156
00157 cursor->block_when_stored = block;
00158 cursor->modify_clock = buf_block_get_modify_clock(block);
00159 }
00160
00161
00163 UNIV_INTERN
00164 void
00165 btr_pcur_copy_stored_position(
00166
00167 btr_pcur_t* pcur_receive,
00169 btr_pcur_t* pcur_donate)
00171 {
00172 if (pcur_receive->old_rec_buf) {
00173 mem_free(pcur_receive->old_rec_buf);
00174 }
00175
00176 ut_memcpy(pcur_receive, pcur_donate, sizeof(btr_pcur_t));
00177
00178 if (pcur_donate->old_rec_buf) {
00179
00180 pcur_receive->old_rec_buf = (unsigned char *)mem_alloc(pcur_donate->buf_size);
00181
00182 ut_memcpy(pcur_receive->old_rec_buf, pcur_donate->old_rec_buf,
00183 pcur_donate->buf_size);
00184 pcur_receive->old_rec = pcur_receive->old_rec_buf
00185 + (pcur_donate->old_rec - pcur_donate->old_rec_buf);
00186 }
00187
00188 pcur_receive->old_n_fields = pcur_donate->old_n_fields;
00189 }
00190
00191
00206 UNIV_INTERN
00207 ibool
00208 btr_pcur_restore_position_func(
00209
00210 ulint latch_mode,
00211 btr_pcur_t* cursor,
00212 const char* file,
00213 ulint line,
00214 mtr_t* mtr)
00215 {
00216 dict_index_t* index;
00217 dtuple_t* tuple;
00218 ulint mode;
00219 ulint old_mode;
00220 mem_heap_t* heap;
00221
00222 ut_ad(mtr);
00223 ut_ad(mtr->state == MTR_ACTIVE);
00224
00225 index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));
00226
00227 if (UNIV_UNLIKELY(cursor->old_stored != BTR_PCUR_OLD_STORED)
00228 || UNIV_UNLIKELY(cursor->pos_state != BTR_PCUR_WAS_POSITIONED
00229 && cursor->pos_state != BTR_PCUR_IS_POSITIONED)) {
00230 ut_print_buf(stderr, cursor, sizeof(btr_pcur_t));
00231 putc('\n', stderr);
00232 if (cursor->trx_if_known) {
00233 trx_print(stderr, cursor->trx_if_known, 0);
00234 }
00235
00236 ut_error;
00237 }
00238
00239 if (UNIV_UNLIKELY
00240 (cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
00241 || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) {
00242
00243
00244
00245
00246 btr_cur_open_at_index_side(
00247 cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
00248 index, latch_mode, btr_pcur_get_btr_cur(cursor), mtr);
00249
00250 cursor->latch_mode = latch_mode;
00251 cursor->pos_state = BTR_PCUR_IS_POSITIONED;
00252 cursor->block_when_stored = btr_pcur_get_block(cursor);
00253
00254 return(FALSE);
00255 }
00256
00257 ut_a(cursor->old_rec);
00258 ut_a(cursor->old_n_fields);
00259
00260 if (UNIV_LIKELY(latch_mode == BTR_SEARCH_LEAF)
00261 || UNIV_LIKELY(latch_mode == BTR_MODIFY_LEAF)) {
00262
00263
00264 if (UNIV_LIKELY(buf_page_optimistic_get(
00265 latch_mode,
00266 cursor->block_when_stored,
00267 cursor->modify_clock,
00268 file, line, mtr))) {
00269 cursor->pos_state = BTR_PCUR_IS_POSITIONED;
00270
00271 buf_block_dbg_add_level(btr_pcur_get_block(cursor),
00272 SYNC_TREE_NODE);
00273
00274 if (cursor->rel_pos == BTR_PCUR_ON) {
00275 #ifdef UNIV_DEBUG
00276 const rec_t* rec;
00277 const ulint* offsets1;
00278 const ulint* offsets2;
00279 #endif
00280 cursor->latch_mode = latch_mode;
00281 #ifdef UNIV_DEBUG
00282 rec = btr_pcur_get_rec(cursor);
00283
00284 heap = mem_heap_create(256);
00285 offsets1 = rec_get_offsets(
00286 cursor->old_rec, index, NULL,
00287 cursor->old_n_fields, &heap);
00288 offsets2 = rec_get_offsets(
00289 rec, index, NULL,
00290 cursor->old_n_fields, &heap);
00291
00292 ut_ad(!cmp_rec_rec(cursor->old_rec,
00293 rec, offsets1, offsets2,
00294 index));
00295 mem_heap_free(heap);
00296 #endif
00297 return(TRUE);
00298 }
00299
00300 return(FALSE);
00301 }
00302 }
00303
00304
00305
00306 heap = mem_heap_create(256);
00307
00308 tuple = dict_index_build_data_tuple(index, cursor->old_rec,
00309 cursor->old_n_fields, heap);
00310
00311
00312 old_mode = cursor->search_mode;
00313
00314 if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) {
00315 mode = PAGE_CUR_LE;
00316 } else if (cursor->rel_pos == BTR_PCUR_AFTER) {
00317 mode = PAGE_CUR_G;
00318 } else {
00319 ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE);
00320 mode = PAGE_CUR_L;
00321 }
00322
00323 btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode,
00324 cursor, 0, file, line, mtr);
00325
00326
00327 cursor->search_mode = old_mode;
00328
00329 if (cursor->rel_pos == BTR_PCUR_ON
00330 && btr_pcur_is_on_user_rec(cursor)
00331 && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor),
00332 rec_get_offsets(
00333 btr_pcur_get_rec(cursor), index,
00334 NULL, ULINT_UNDEFINED, &heap))) {
00335
00336
00337
00338
00339
00340 cursor->block_when_stored = btr_pcur_get_block(cursor);
00341 cursor->modify_clock = buf_block_get_modify_clock(
00342 cursor->block_when_stored);
00343 cursor->old_stored = BTR_PCUR_OLD_STORED;
00344
00345 mem_heap_free(heap);
00346
00347 return(TRUE);
00348 }
00349
00350 mem_heap_free(heap);
00351
00352
00353
00354
00355
00356 btr_pcur_store_position(cursor, mtr);
00357
00358 return(FALSE);
00359 }
00360
00361
00367 UNIV_INTERN
00368 void
00369 btr_pcur_release_leaf(
00370
00371 btr_pcur_t* cursor,
00372 mtr_t* mtr)
00373 {
00374 buf_block_t* block;
00375
00376 ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
00377 ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
00378
00379 block = btr_pcur_get_block(cursor);
00380
00381 btr_leaf_page_release(block, cursor->latch_mode, mtr);
00382
00383 cursor->latch_mode = BTR_NO_LATCHES;
00384
00385 cursor->pos_state = BTR_PCUR_WAS_POSITIONED;
00386 }
00387
00388
00393 UNIV_INTERN
00394 void
00395 btr_pcur_move_to_next_page(
00396
00397 btr_pcur_t* cursor,
00399 mtr_t* mtr)
00400 {
00401 ulint next_page_no;
00402 ulint space;
00403 ulint zip_size;
00404 page_t* page;
00405 buf_block_t* next_block;
00406 page_t* next_page;
00407
00408 ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
00409 ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
00410 ut_ad(btr_pcur_is_after_last_on_page(cursor));
00411
00412 cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
00413
00414 page = btr_pcur_get_page(cursor);
00415 next_page_no = btr_page_get_next(page, mtr);
00416 space = buf_block_get_space(btr_pcur_get_block(cursor));
00417 zip_size = buf_block_get_zip_size(btr_pcur_get_block(cursor));
00418
00419 ut_ad(next_page_no != FIL_NULL);
00420
00421 next_block = btr_block_get(space, zip_size, next_page_no,
00422 cursor->latch_mode, mtr);
00423 next_page = buf_block_get_frame(next_block);
00424 #ifdef UNIV_BTR_DEBUG
00425 ut_a(page_is_comp(next_page) == page_is_comp(page));
00426 ut_a(btr_page_get_prev(next_page, mtr)
00427 == buf_block_get_page_no(btr_pcur_get_block(cursor)));
00428 #endif
00429 next_block->check_index_page_at_flush = TRUE;
00430
00431 btr_leaf_page_release(btr_pcur_get_block(cursor),
00432 cursor->latch_mode, mtr);
00433
00434 page_cur_set_before_first(next_block, btr_pcur_get_page_cur(cursor));
00435
00436 page_check_dir(next_page);
00437 }
00438
00439
00448 UNIV_INTERN
00449 void
00450 btr_pcur_move_backward_from_page(
00451
00452 btr_pcur_t* cursor,
00454 mtr_t* mtr)
00455 {
00456 ulint prev_page_no;
00457 page_t* page;
00458 buf_block_t* prev_block;
00459 ulint latch_mode;
00460 ulint latch_mode2;
00461
00462 ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
00463 ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
00464 ut_ad(btr_pcur_is_before_first_on_page(cursor));
00465 ut_ad(!btr_pcur_is_before_first_in_tree(cursor, mtr));
00466
00467 latch_mode = cursor->latch_mode;
00468
00469 if (latch_mode == BTR_SEARCH_LEAF) {
00470
00471 latch_mode2 = BTR_SEARCH_PREV;
00472
00473 } else if (latch_mode == BTR_MODIFY_LEAF) {
00474
00475 latch_mode2 = BTR_MODIFY_PREV;
00476 } else {
00477 latch_mode2 = 0;
00478 ut_error;
00479 }
00480
00481 btr_pcur_store_position(cursor, mtr);
00482
00483 mtr_commit(mtr);
00484
00485 mtr_start(mtr);
00486
00487 btr_pcur_restore_position(latch_mode2, cursor, mtr);
00488
00489 page = btr_pcur_get_page(cursor);
00490
00491 prev_page_no = btr_page_get_prev(page, mtr);
00492
00493 if (prev_page_no == FIL_NULL) {
00494 } else if (btr_pcur_is_before_first_on_page(cursor)) {
00495
00496 prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
00497
00498 btr_leaf_page_release(btr_pcur_get_block(cursor),
00499 latch_mode, mtr);
00500
00501 page_cur_set_after_last(prev_block,
00502 btr_pcur_get_page_cur(cursor));
00503 } else {
00504
00505
00506
00507
00508
00509 prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
00510
00511 btr_leaf_page_release(prev_block, latch_mode, mtr);
00512 }
00513
00514 cursor->latch_mode = latch_mode;
00515
00516 cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
00517 }
00518
00519
00523 UNIV_INTERN
00524 ibool
00525 btr_pcur_move_to_prev(
00526
00527 btr_pcur_t* cursor,
00529 mtr_t* mtr)
00530 {
00531 ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
00532 ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
00533
00534 cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
00535
00536 if (btr_pcur_is_before_first_on_page(cursor)) {
00537
00538 if (btr_pcur_is_before_first_in_tree(cursor, mtr)) {
00539
00540 return(FALSE);
00541 }
00542
00543 btr_pcur_move_backward_from_page(cursor, mtr);
00544
00545 return(TRUE);
00546 }
00547
00548 btr_pcur_move_to_prev_on_page(cursor);
00549
00550 return(TRUE);
00551 }
00552
00553
00560 UNIV_INTERN
00561 void
00562 btr_pcur_open_on_user_rec_func(
00563
00564 dict_index_t* index,
00565 const dtuple_t* tuple,
00566 ulint mode,
00567 ulint latch_mode,
00569 btr_pcur_t* cursor,
00571 const char* file,
00572 ulint line,
00573 mtr_t* mtr)
00574 {
00575 btr_pcur_open_func(index, tuple, mode, latch_mode, cursor,
00576 file, line, mtr);
00577
00578 if ((mode == PAGE_CUR_GE) || (mode == PAGE_CUR_G)) {
00579
00580 if (btr_pcur_is_after_last_on_page(cursor)) {
00581
00582 btr_pcur_move_to_next_user_rec(cursor, mtr);
00583 }
00584 } else {
00585 ut_ad((mode == PAGE_CUR_LE) || (mode == PAGE_CUR_L));
00586
00587
00588
00589 ut_error;
00590 }
00591 }