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->block_when_stored = btr_pcur_get_block(cursor);
00251
00252 return(FALSE);
00253 }
00254
00255 ut_a(cursor->old_rec);
00256 ut_a(cursor->old_n_fields);
00257
00258 if (UNIV_LIKELY(latch_mode == BTR_SEARCH_LEAF)
00259 || UNIV_LIKELY(latch_mode == BTR_MODIFY_LEAF)) {
00260
00261
00262 if (UNIV_LIKELY(buf_page_optimistic_get(
00263 latch_mode,
00264 cursor->block_when_stored,
00265 cursor->modify_clock,
00266 file, line, mtr))) {
00267 cursor->pos_state = BTR_PCUR_IS_POSITIONED;
00268
00269 buf_block_dbg_add_level(btr_pcur_get_block(cursor),
00270 SYNC_TREE_NODE);
00271
00272 if (cursor->rel_pos == BTR_PCUR_ON) {
00273 #ifdef UNIV_DEBUG
00274 const rec_t* rec;
00275 const ulint* offsets1;
00276 const ulint* offsets2;
00277 #endif
00278 cursor->latch_mode = latch_mode;
00279 #ifdef UNIV_DEBUG
00280 rec = btr_pcur_get_rec(cursor);
00281
00282 heap = mem_heap_create(256);
00283 offsets1 = rec_get_offsets(
00284 cursor->old_rec, index, NULL,
00285 cursor->old_n_fields, &heap);
00286 offsets2 = rec_get_offsets(
00287 rec, index, NULL,
00288 cursor->old_n_fields, &heap);
00289
00290 ut_ad(!cmp_rec_rec(cursor->old_rec,
00291 rec, offsets1, offsets2,
00292 index));
00293 mem_heap_free(heap);
00294 #endif
00295 return(TRUE);
00296 }
00297
00298 return(FALSE);
00299 }
00300 }
00301
00302
00303
00304 heap = mem_heap_create(256);
00305
00306 tuple = dict_index_build_data_tuple(index, cursor->old_rec,
00307 cursor->old_n_fields, heap);
00308
00309
00310 old_mode = cursor->search_mode;
00311
00312 if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) {
00313 mode = PAGE_CUR_LE;
00314 } else if (cursor->rel_pos == BTR_PCUR_AFTER) {
00315 mode = PAGE_CUR_G;
00316 } else {
00317 ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE);
00318 mode = PAGE_CUR_L;
00319 }
00320
00321 btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode,
00322 cursor, 0, file, line, mtr);
00323
00324
00325 cursor->search_mode = old_mode;
00326
00327 if (cursor->rel_pos == BTR_PCUR_ON
00328 && btr_pcur_is_on_user_rec(cursor)
00329 && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor),
00330 rec_get_offsets(
00331 btr_pcur_get_rec(cursor), index,
00332 NULL, ULINT_UNDEFINED, &heap))) {
00333
00334
00335
00336
00337
00338 cursor->block_when_stored = btr_pcur_get_block(cursor);
00339 cursor->modify_clock = buf_block_get_modify_clock(
00340 cursor->block_when_stored);
00341 cursor->old_stored = BTR_PCUR_OLD_STORED;
00342
00343 mem_heap_free(heap);
00344
00345 return(TRUE);
00346 }
00347
00348 mem_heap_free(heap);
00349
00350
00351
00352
00353
00354 btr_pcur_store_position(cursor, mtr);
00355
00356 return(FALSE);
00357 }
00358
00359
00365 UNIV_INTERN
00366 void
00367 btr_pcur_release_leaf(
00368
00369 btr_pcur_t* cursor,
00370 mtr_t* mtr)
00371 {
00372 buf_block_t* block;
00373
00374 ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
00375 ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
00376
00377 block = btr_pcur_get_block(cursor);
00378
00379 btr_leaf_page_release(block, cursor->latch_mode, mtr);
00380
00381 cursor->latch_mode = BTR_NO_LATCHES;
00382
00383 cursor->pos_state = BTR_PCUR_WAS_POSITIONED;
00384 }
00385
00386
00391 UNIV_INTERN
00392 void
00393 btr_pcur_move_to_next_page(
00394
00395 btr_pcur_t* cursor,
00397 mtr_t* mtr)
00398 {
00399 ulint next_page_no;
00400 ulint space;
00401 ulint zip_size;
00402 page_t* page;
00403 buf_block_t* next_block;
00404 page_t* next_page;
00405
00406 ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
00407 ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
00408 ut_ad(btr_pcur_is_after_last_on_page(cursor));
00409
00410 cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
00411
00412 page = btr_pcur_get_page(cursor);
00413 next_page_no = btr_page_get_next(page, mtr);
00414 space = buf_block_get_space(btr_pcur_get_block(cursor));
00415 zip_size = buf_block_get_zip_size(btr_pcur_get_block(cursor));
00416
00417 ut_ad(next_page_no != FIL_NULL);
00418
00419 next_block = btr_block_get(space, zip_size, next_page_no,
00420 cursor->latch_mode, mtr);
00421 next_page = buf_block_get_frame(next_block);
00422 #ifdef UNIV_BTR_DEBUG
00423 ut_a(page_is_comp(next_page) == page_is_comp(page));
00424 ut_a(btr_page_get_prev(next_page, mtr)
00425 == buf_block_get_page_no(btr_pcur_get_block(cursor)));
00426 #endif
00427 next_block->check_index_page_at_flush = TRUE;
00428
00429 btr_leaf_page_release(btr_pcur_get_block(cursor),
00430 cursor->latch_mode, mtr);
00431
00432 page_cur_set_before_first(next_block, btr_pcur_get_page_cur(cursor));
00433
00434 page_check_dir(next_page);
00435 }
00436
00437
00446 UNIV_INTERN
00447 void
00448 btr_pcur_move_backward_from_page(
00449
00450 btr_pcur_t* cursor,
00452 mtr_t* mtr)
00453 {
00454 ulint prev_page_no;
00455 page_t* page;
00456 buf_block_t* prev_block;
00457 ulint latch_mode;
00458 ulint latch_mode2;
00459
00460 ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
00461 ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
00462 ut_ad(btr_pcur_is_before_first_on_page(cursor));
00463 ut_ad(!btr_pcur_is_before_first_in_tree(cursor, mtr));
00464
00465 latch_mode = cursor->latch_mode;
00466
00467 if (latch_mode == BTR_SEARCH_LEAF) {
00468
00469 latch_mode2 = BTR_SEARCH_PREV;
00470
00471 } else if (latch_mode == BTR_MODIFY_LEAF) {
00472
00473 latch_mode2 = BTR_MODIFY_PREV;
00474 } else {
00475 latch_mode2 = 0;
00476 ut_error;
00477 }
00478
00479 btr_pcur_store_position(cursor, mtr);
00480
00481 mtr_commit(mtr);
00482
00483 mtr_start(mtr);
00484
00485 btr_pcur_restore_position(latch_mode2, cursor, mtr);
00486
00487 page = btr_pcur_get_page(cursor);
00488
00489 prev_page_no = btr_page_get_prev(page, mtr);
00490
00491 if (prev_page_no == FIL_NULL) {
00492 } else if (btr_pcur_is_before_first_on_page(cursor)) {
00493
00494 prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
00495
00496 btr_leaf_page_release(btr_pcur_get_block(cursor),
00497 latch_mode, mtr);
00498
00499 page_cur_set_after_last(prev_block,
00500 btr_pcur_get_page_cur(cursor));
00501 } else {
00502
00503
00504
00505
00506
00507 prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
00508
00509 btr_leaf_page_release(prev_block, latch_mode, mtr);
00510 }
00511
00512 cursor->latch_mode = latch_mode;
00513
00514 cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
00515 }
00516
00517
00521 UNIV_INTERN
00522 ibool
00523 btr_pcur_move_to_prev(
00524
00525 btr_pcur_t* cursor,
00527 mtr_t* mtr)
00528 {
00529 ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
00530 ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
00531
00532 cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
00533
00534 if (btr_pcur_is_before_first_on_page(cursor)) {
00535
00536 if (btr_pcur_is_before_first_in_tree(cursor, mtr)) {
00537
00538 return(FALSE);
00539 }
00540
00541 btr_pcur_move_backward_from_page(cursor, mtr);
00542
00543 return(TRUE);
00544 }
00545
00546 btr_pcur_move_to_prev_on_page(cursor);
00547
00548 return(TRUE);
00549 }
00550
00551
00558 UNIV_INTERN
00559 void
00560 btr_pcur_open_on_user_rec_func(
00561
00562 dict_index_t* index,
00563 const dtuple_t* tuple,
00564 ulint mode,
00565 ulint latch_mode,
00567 btr_pcur_t* cursor,
00569 const char* file,
00570 ulint line,
00571 mtr_t* mtr)
00572 {
00573 btr_pcur_open_func(index, tuple, mode, latch_mode, cursor,
00574 file, line, mtr);
00575
00576 if ((mode == PAGE_CUR_GE) || (mode == PAGE_CUR_G)) {
00577
00578 if (btr_pcur_is_after_last_on_page(cursor)) {
00579
00580 btr_pcur_move_to_next_user_rec(cursor, mtr);
00581 }
00582 } else {
00583 ut_ad((mode == PAGE_CUR_LE) || (mode == PAGE_CUR_L));
00584
00585
00586
00587 ut_error;
00588 }
00589 }