#include "lock0lock.h"#include "usr0sess.h"#include "trx0purge.h"#include "dict0mem.h"#include "trx0sys.h"Include dependency graph for lock0lock.c:

Go to the source code of this file.
| #define LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK 200 |
| #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000 |
| #define lock_mutex_enter_kernel | ( | ) | mutex_enter(&kernel_mutex) |
Definition at line 449 of file lock0lock.c.
Referenced by lock_clust_rec_modify_check_and_lock(), lock_clust_rec_read_check_and_lock(), lock_is_on_table(), lock_move_rec_list_end(), lock_move_rec_list_start(), lock_move_reorganize_page(), lock_print_info_all_transactions(), lock_print_info_summary(), lock_rec_insert_check_and_lock(), lock_rec_queue_validate(), lock_rec_restore_from_page_infimum(), lock_rec_store_on_page_infimum(), lock_rec_validate_page(), lock_release_off_kernel(), lock_sec_rec_modify_check_and_lock(), lock_sec_rec_read_check_and_lock(), lock_table(), lock_update_copy_and_discard(), lock_update_delete(), lock_update_discard(), lock_update_insert(), lock_update_merge_left(), lock_update_merge_right(), lock_update_root_raise(), lock_update_split_left(), lock_update_split_right(), and lock_validate().
| #define lock_mutex_exit_kernel | ( | ) | mutex_exit(&kernel_mutex) |
Definition at line 450 of file lock0lock.c.
Referenced by lock_clust_rec_modify_check_and_lock(), lock_clust_rec_read_check_and_lock(), lock_is_on_table(), lock_move_rec_list_end(), lock_move_rec_list_start(), lock_move_reorganize_page(), lock_print_info_all_transactions(), lock_rec_insert_check_and_lock(), lock_rec_queue_validate(), lock_rec_restore_from_page_infimum(), lock_rec_store_on_page_infimum(), lock_rec_validate_page(), lock_release_off_kernel(), lock_sec_rec_modify_check_and_lock(), lock_sec_rec_read_check_and_lock(), lock_table(), lock_update_copy_and_discard(), lock_update_delete(), lock_update_discard(), lock_update_insert(), lock_update_merge_left(), lock_update_merge_right(), lock_update_root_raise(), lock_update_split_left(), lock_update_split_right(), and lock_validate().
| #define LOCK_PAGE_BITMAP_MARGIN 64 |
| #define LOCK_RELEASE_KERNEL_INTERVAL 1000 |
| #define LOCK_VICTIM_IS_OTHER 2 |
Definition at line 365 of file lock0lock.c.
Referenced by lock_deadlock_occurs(), and lock_deadlock_recursive().
| #define LOCK_VICTIM_IS_START 1 |
Definition at line 364 of file lock0lock.c.
Referenced by lock_deadlock_occurs(), and lock_deadlock_recursive().
| typedef struct lock_rec_struct lock_rec_t |
Definition at line 331 of file lock0lock.c.
| typedef struct lock_table_struct lock_table_t |
Definition at line 323 of file lock0lock.c.
| void innobase_mysql_end_print_arbitrary_thd | ( | void | ) |
| void innobase_mysql_prepare_print_arbitrary_thd | ( | void | ) |
Referenced by lock_print_info_all_transactions(), and lock_print_info_summary().
Here is the caller graph for this function:

| void lock_cancel_waiting_and_release | ( | lock_t * | lock | ) |
Definition at line 3969 of file lock0lock.c.
References kernel_mutex, lock, lock_get_type(), LOCK_REC, lock_rec_dequeue_from_page(), lock_reset_lock_and_trx_wait(), LOCK_TABLE, lock_table_dequeue(), trx_end_lock_wait(), and ut_ad.
Referenced by lock_deadlock_recursive(), row_search_for_mysql(), and srv_lock_timeout_and_monitor_thread().
03971 : waiting lock request */ 03972 { 03973 #ifdef UNIV_SYNC_DEBUG 03974 ut_ad(mutex_own(&kernel_mutex)); 03975 #endif /* UNIV_SYNC_DEBUG */ 03976 03977 if (lock_get_type(lock) == LOCK_REC) { 03978 03979 lock_rec_dequeue_from_page(lock); 03980 } else { 03981 ut_ad(lock_get_type(lock) & LOCK_TABLE); 03982 03983 lock_table_dequeue(lock); 03984 } 03985 03986 /* Reset the wait flag and the back pointer to lock in trx */ 03987 03988 lock_reset_lock_and_trx_wait(lock); 03989 03990 /* The following function releases the trx from lock wait */ 03991 03992 trx_end_lock_wait(lock->trx); 03993 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool lock_check_trx_id_sanity | ( | dulint | trx_id, | |
| rec_t * | rec, | |||
| dict_index_t * | index, | |||
| const ulint * | offsets, | |||
| ibool | has_kernel_mutex | |||
| ) |
Definition at line 456 of file lock0lock.c.
References dict_index_name_print(), FALSE, index(), kernel_mutex, trx_sys_struct::max_trx_id, mutex_enter, mutex_exit(), NULL, rec_offs_validate(), rec_print_new(), TRUE, trx_sys, ut_ad, ut_dulint_cmp(), ut_dulint_get_high(), ut_dulint_get_low(), and ut_print_timestamp().
Referenced by lock_sec_rec_some_has_impl_off_kernel(), and row_vers_impl_x_locked_off_kernel().
00458 : TRUE if ok */ 00459 dulint trx_id, /* in: trx id */ 00460 rec_t* rec, /* in: user record */ 00461 dict_index_t* index, /* in: index */ 00462 const ulint* offsets, /* in: rec_get_offsets(rec, index) */ 00463 ibool has_kernel_mutex)/* in: TRUE if the caller owns the 00464 kernel mutex */ 00465 { 00466 ibool is_ok = TRUE; 00467 00468 ut_ad(rec_offs_validate(rec, index, offsets)); 00469 00470 if (!has_kernel_mutex) { 00471 mutex_enter(&kernel_mutex); 00472 } 00473 00474 /* A sanity check: the trx_id in rec must be smaller than the global 00475 trx id counter */ 00476 00477 if (ut_dulint_cmp(trx_id, trx_sys->max_trx_id) >= 0) { 00478 ut_print_timestamp(stderr); 00479 fputs(" InnoDB: Error: transaction id associated" 00480 " with record\n", 00481 stderr); 00482 rec_print_new(stderr, rec, offsets); 00483 fputs("InnoDB: in ", stderr); 00484 dict_index_name_print(stderr, NULL, index); 00485 fprintf(stderr, "\n" 00486 "InnoDB: is %lu %lu which is higher than the global trx id counter %lu %lu!\n" 00487 "InnoDB: The table is corrupt. You have to do dump + drop + reimport.\n", 00488 (ulong) ut_dulint_get_high(trx_id), 00489 (ulong) ut_dulint_get_low(trx_id), 00490 (ulong) ut_dulint_get_high(trx_sys->max_trx_id), 00491 (ulong) ut_dulint_get_low(trx_sys->max_trx_id)); 00492 00493 is_ok = FALSE; 00494 } 00495 00496 if (!has_kernel_mutex) { 00497 mutex_exit(&kernel_mutex); 00498 } 00499 00500 return(is_ok); 00501 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool lock_clust_rec_cons_read_sees | ( | rec_t * | rec, | |
| dict_index_t * | index, | |||
| const ulint * | offsets, | |||
| read_view_t * | view | |||
| ) |
Definition at line 507 of file lock0lock.c.
References DICT_CLUSTERED, index(), page_rec_is_user_rec(), read_view_sees_trx_id(), rec_offs_validate(), row_get_rec_trx_id(), and ut_ad.
Referenced by row_search_for_mysql(), row_sel(), row_sel_get_clust_rec(), row_sel_get_clust_rec_for_mysql(), row_sel_try_search_shortcut(), and row_sel_try_search_shortcut_for_mysql().
00509 : TRUE if sees, or FALSE if an earlier 00510 version of the record should be retrieved */ 00511 rec_t* rec, /* in: user record which should be read or 00512 passed over by a read cursor */ 00513 dict_index_t* index, /* in: clustered index */ 00514 const ulint* offsets,/* in: rec_get_offsets(rec, index) */ 00515 read_view_t* view) /* in: consistent read view */ 00516 { 00517 dulint trx_id; 00518 00519 ut_ad(index->type & DICT_CLUSTERED); 00520 ut_ad(page_rec_is_user_rec(rec)); 00521 ut_ad(rec_offs_validate(rec, index, offsets)); 00522 00523 /* NOTE that we call this function while holding the search 00524 system latch. To obey the latching order we must NOT reserve the 00525 kernel mutex here! */ 00526 00527 trx_id = row_get_rec_trx_id(rec, index, offsets); 00528 00529 return(read_view_sees_trx_id(view, trx_id)); 00530 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint lock_clust_rec_modify_check_and_lock | ( | ulint | flags, | |
| rec_t * | rec, | |||
| dict_index_t * | index, | |||
| const ulint * | offsets, | |||
| que_thr_t * | thr | |||
| ) |
Definition at line 4946 of file lock0lock.c.
References BTR_NO_LOCKING_FLAG, DB_SUCCESS, DICT_CLUSTERED, err, index(), LOCK_IX, lock_mutex_enter_kernel, lock_mutex_exit_kernel, lock_rec_convert_impl_to_expl(), lock_rec_lock(), LOCK_REC_NOT_GAP, lock_rec_queue_validate(), lock_table_has(), LOCK_X, rec_offs_validate(), thr_get_trx(), TRUE, and ut_ad.
Referenced by btr_cur_del_mark_set_clust_rec(), btr_cur_upd_lock_and_undo(), and row_upd_clust_step().
04948 : DB_SUCCESS, DB_LOCK_WAIT, 04949 DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ 04950 ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, 04951 does nothing */ 04952 rec_t* rec, /* in: record which should be modified */ 04953 dict_index_t* index, /* in: clustered index */ 04954 const ulint* offsets,/* in: rec_get_offsets(rec, index) */ 04955 que_thr_t* thr) /* in: query thread */ 04956 { 04957 ulint err; 04958 04959 ut_ad(rec_offs_validate(rec, index, offsets)); 04960 ut_ad(index->type & DICT_CLUSTERED); 04961 04962 if (flags & BTR_NO_LOCKING_FLAG) { 04963 04964 return(DB_SUCCESS); 04965 } 04966 04967 lock_mutex_enter_kernel(); 04968 04969 ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX)); 04970 04971 /* If a transaction has no explicit x-lock set on the record, set one 04972 for it */ 04973 04974 lock_rec_convert_impl_to_expl(rec, index, offsets); 04975 04976 err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP, rec, index, thr); 04977 04978 lock_mutex_exit_kernel(); 04979 04980 ut_ad(lock_rec_queue_validate(rec, index, offsets)); 04981 04982 return(err); 04983 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint lock_clust_rec_read_check_and_lock | ( | ulint | flags, | |
| rec_t * | rec, | |||
| dict_index_t * | index, | |||
| const ulint * | offsets, | |||
| ulint | mode, | |||
| ulint | gap_mode, | |||
| que_thr_t * | thr | |||
| ) |
Definition at line 5122 of file lock0lock.c.
References BTR_NO_LOCKING_FLAG, DB_SUCCESS, DICT_CLUSTERED, err, FALSE, index(), LOCK_GAP, LOCK_IS, LOCK_IX, lock_mutex_enter_kernel, lock_mutex_exit_kernel, LOCK_ORDINARY, lock_rec_convert_impl_to_expl(), lock_rec_lock(), LOCK_REC_NOT_GAP, lock_rec_queue_validate(), LOCK_S, lock_table_has(), LOCK_X, page_rec_is_supremum(), page_rec_is_user_rec(), rec_offs_validate(), thr_get_trx(), and ut_ad.
Referenced by lock_clust_rec_read_check_and_lock_alt(), row_ins_set_exclusive_rec_lock(), row_ins_set_shared_rec_lock(), row_sel_get_clust_rec(), row_sel_get_clust_rec_for_mysql(), and sel_set_rec_lock().
05124 : DB_SUCCESS, DB_LOCK_WAIT, 05125 DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ 05126 ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, 05127 does nothing */ 05128 rec_t* rec, /* in: user record or page supremum record 05129 which should be read or passed over by a read 05130 cursor */ 05131 dict_index_t* index, /* in: clustered index */ 05132 const ulint* offsets,/* in: rec_get_offsets(rec, index) */ 05133 ulint mode, /* in: mode of the lock which the read cursor 05134 should set on records: LOCK_S or LOCK_X; the 05135 latter is possible in SELECT FOR UPDATE */ 05136 ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or 05137 LOCK_REC_NOT_GAP */ 05138 que_thr_t* thr) /* in: query thread */ 05139 { 05140 ulint err; 05141 05142 ut_ad(index->type & DICT_CLUSTERED); 05143 ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec)); 05144 ut_ad(gap_mode == LOCK_ORDINARY || gap_mode == LOCK_GAP 05145 || gap_mode == LOCK_REC_NOT_GAP); 05146 ut_ad(rec_offs_validate(rec, index, offsets)); 05147 05148 if (flags & BTR_NO_LOCKING_FLAG) { 05149 05150 return(DB_SUCCESS); 05151 } 05152 05153 lock_mutex_enter_kernel(); 05154 05155 ut_ad(mode != LOCK_X 05156 || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX)); 05157 ut_ad(mode != LOCK_S 05158 || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS)); 05159 05160 if (!page_rec_is_supremum(rec)) { 05161 05162 lock_rec_convert_impl_to_expl(rec, index, offsets); 05163 } 05164 05165 err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr); 05166 05167 lock_mutex_exit_kernel(); 05168 05169 ut_ad(lock_rec_queue_validate(rec, index, offsets)); 05170 05171 return(err); 05172 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint lock_clust_rec_read_check_and_lock_alt | ( | ulint | flags, | |
| rec_t * | rec, | |||
| dict_index_t * | index, | |||
| ulint | mode, | |||
| ulint | gap_mode, | |||
| que_thr_t * | thr | |||
| ) |
Definition at line 5184 of file lock0lock.c.
References index(), lock_clust_rec_read_check_and_lock(), mem_heap_free, NULL, rec_get_offsets, and REC_OFFS_NORMAL_SIZE.
Referenced by row_ins_foreign_check_on_constraint().
05186 : DB_SUCCESS, DB_LOCK_WAIT, 05187 DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ 05188 ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, 05189 does nothing */ 05190 rec_t* rec, /* in: user record or page supremum record 05191 which should be read or passed over by a read 05192 cursor */ 05193 dict_index_t* index, /* in: clustered index */ 05194 ulint mode, /* in: mode of the lock which the read cursor 05195 should set on records: LOCK_S or LOCK_X; the 05196 latter is possible in SELECT FOR UPDATE */ 05197 ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or 05198 LOCK_REC_NOT_GAP */ 05199 que_thr_t* thr) /* in: query thread */ 05200 { 05201 mem_heap_t* tmp_heap = NULL; 05202 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 05203 ulint* offsets = offsets_; 05204 ulint ret; 05205 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 05206 05207 offsets = rec_get_offsets(rec, index, offsets, 05208 ULINT_UNDEFINED, &tmp_heap); 05209 ret = lock_clust_rec_read_check_and_lock(flags, rec, index, 05210 offsets, mode, gap_mode, thr); 05211 if (tmp_heap) { 05212 mem_heap_free(tmp_heap); 05213 } 05214 return(ret); 05215 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3196 of file lock0lock.c.
References trx_struct::deadlock_mark, FALSE, index(), kernel_mutex, lock, lock_deadlock_found, lock_deadlock_recursive(), lock_get_type(), lock_latest_err_file, LOCK_TABLE, LOCK_VICTIM_IS_OTHER, LOCK_VICTIM_IS_START, NULL, TRUE, trx_sys, ut_ad, UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by lock_rec_enqueue_waiting(), and lock_table_enqueue_waiting().
03198 : TRUE if a deadlock was detected and we 03199 chose trx as a victim; FALSE if no deadlock, or 03200 there was a deadlock, but we chose other 03201 transaction(s) as victim(s) */ 03202 lock_t* lock, /* in: lock the transaction is requesting */ 03203 trx_t* trx) /* in: transaction */ 03204 { 03205 dict_table_t* table; 03206 dict_index_t* index; 03207 trx_t* mark_trx; 03208 ulint ret; 03209 ulint cost = 0; 03210 03211 ut_ad(trx && lock); 03212 #ifdef UNIV_SYNC_DEBUG 03213 ut_ad(mutex_own(&kernel_mutex)); 03214 #endif /* UNIV_SYNC_DEBUG */ 03215 retry: 03216 /* We check that adding this trx to the waits-for graph 03217 does not produce a cycle. First mark all active transactions 03218 with 0: */ 03219 03220 mark_trx = UT_LIST_GET_FIRST(trx_sys->trx_list); 03221 03222 while (mark_trx) { 03223 mark_trx->deadlock_mark = 0; 03224 mark_trx = UT_LIST_GET_NEXT(trx_list, mark_trx); 03225 } 03226 03227 ret = lock_deadlock_recursive(trx, trx, lock, &cost, 0); 03228 03229 if (ret == LOCK_VICTIM_IS_OTHER) { 03230 /* We chose some other trx as a victim: retry if there still 03231 is a deadlock */ 03232 03233 goto retry; 03234 } 03235 03236 if (ret == LOCK_VICTIM_IS_START) { 03237 if (lock_get_type(lock) & LOCK_TABLE) { 03238 table = lock->un_member.tab_lock.table; 03239 index = NULL; 03240 } else { 03241 index = lock->index; 03242 table = index->table; 03243 } 03244 03245 lock_deadlock_found = TRUE; 03246 03247 fputs("*** WE ROLL BACK TRANSACTION (2)\n", 03248 lock_latest_err_file); 03249 03250 return(TRUE); 03251 } 03252 03253 return(FALSE); 03254 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint lock_deadlock_recursive | ( | trx_t * | start, | |
| trx_t * | trx, | |||
| lock_t * | wait_lock, | |||
| ulint * | cost, | |||
| ulint | depth | |||
| ) | [static] |
Definition at line 3260 of file lock0lock.c.
References trx_struct::deadlock_mark, FALSE, kernel_mutex, lock, lock_cancel_waiting_and_release(), lock_deadlock_found, lock_get_type(), lock_has_to_wait(), lock_latest_err_file, LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK, LOCK_REC, lock_rec_find_set_bit(), lock_rec_get_prev(), lock_rec_print(), LOCK_TABLE, lock_table_print(), LOCK_VICTIM_IS_OTHER, LOCK_VICTIM_IS_START, NULL, trx_struct::que_state, start(), TRUE, lock_struct::trx, trx_print(), TRX_QUE_LOCK_WAIT, trx_struct::undo_no, ut_a, ut_ad, ut_dulint_cmp(), UT_LIST_GET_PREV, ut_print_timestamp(), trx_struct::wait_lock, and trx_struct::was_chosen_as_deadlock_victim.
Referenced by lock_deadlock_occurs().
03262 : 0 if no deadlock found, 03263 LOCK_VICTIM_IS_START if there was a deadlock 03264 and we chose 'start' as the victim, 03265 LOCK_VICTIM_IS_OTHER if a deadlock 03266 was found and we chose some other trx as a 03267 victim: we must do the search again in this 03268 last case because there may be another 03269 deadlock! */ 03270 trx_t* start, /* in: recursion starting point */ 03271 trx_t* trx, /* in: a transaction waiting for a lock */ 03272 lock_t* wait_lock, /* in: the lock trx is waiting to be granted */ 03273 ulint* cost, /* in/out: number of calculation steps thus 03274 far: if this exceeds LOCK_MAX_N_STEPS_... 03275 we return LOCK_VICTIM_IS_START */ 03276 ulint depth) /* in: recursion depth: if this exceeds 03277 LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we 03278 return LOCK_VICTIM_IS_START */ 03279 { 03280 lock_t* lock; 03281 ulint bit_no = ULINT_UNDEFINED; 03282 trx_t* lock_trx; 03283 ulint ret; 03284 03285 ut_a(trx && start && wait_lock); 03286 #ifdef UNIV_SYNC_DEBUG 03287 ut_ad(mutex_own(&kernel_mutex)); 03288 #endif /* UNIV_SYNC_DEBUG */ 03289 03290 if (trx->deadlock_mark == 1) { 03291 /* We have already exhaustively searched the subtree starting 03292 from this trx */ 03293 03294 return(0); 03295 } 03296 03297 *cost = *cost + 1; 03298 03299 if ((depth > LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK) 03300 || (*cost > LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK)) { 03301 03302 return(LOCK_VICTIM_IS_START); 03303 } 03304 03305 lock = wait_lock; 03306 03307 if (lock_get_type(wait_lock) == LOCK_REC) { 03308 03309 bit_no = lock_rec_find_set_bit(wait_lock); 03310 03311 ut_a(bit_no != ULINT_UNDEFINED); 03312 } 03313 03314 /* Look at the locks ahead of wait_lock in the lock queue */ 03315 03316 for (;;) { 03317 if (lock_get_type(lock) & LOCK_TABLE) { 03318 03319 lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock); 03320 } else { 03321 ut_ad(lock_get_type(lock) == LOCK_REC); 03322 ut_a(bit_no != ULINT_UNDEFINED); 03323 03324 lock = lock_rec_get_prev(lock, bit_no); 03325 } 03326 03327 if (lock == NULL) { 03328 /* We can mark this subtree as searched */ 03329 trx->deadlock_mark = 1; 03330 03331 return(FALSE); 03332 } 03333 03334 if (lock_has_to_wait(wait_lock, lock)) { 03335 03336 lock_trx = lock->trx; 03337 03338 if (lock_trx == start) { 03339 /* We came back to the recursion starting 03340 point: a deadlock detected */ 03341 FILE* ef = lock_latest_err_file; 03342 03343 rewind(ef); 03344 ut_print_timestamp(ef); 03345 03346 fputs("\n*** (1) TRANSACTION:\n", ef); 03347 03348 trx_print(ef, wait_lock->trx, 3000); 03349 03350 fputs( 03351 "*** (1) WAITING FOR THIS LOCK TO BE GRANTED:\n", ef); 03352 03353 if (lock_get_type(wait_lock) == LOCK_REC) { 03354 lock_rec_print(ef, wait_lock); 03355 } else { 03356 lock_table_print(ef, wait_lock); 03357 } 03358 03359 fputs("*** (2) TRANSACTION:\n", ef); 03360 03361 trx_print(ef, lock->trx, 3000); 03362 03363 fputs("*** (2) HOLDS THE LOCK(S):\n", ef); 03364 03365 if (lock_get_type(lock) == LOCK_REC) { 03366 lock_rec_print(ef, lock); 03367 } else { 03368 lock_table_print(ef, lock); 03369 } 03370 03371 fputs( 03372 "*** (2) WAITING FOR THIS LOCK TO BE GRANTED:\n", ef); 03373 03374 if (lock_get_type(start->wait_lock) 03375 == LOCK_REC) { 03376 lock_rec_print(ef, start->wait_lock); 03377 } else { 03378 lock_table_print(ef, start->wait_lock); 03379 } 03380 #ifdef UNIV_DEBUG 03381 if (lock_print_waits) { 03382 fputs("Deadlock detected\n", stderr); 03383 } 03384 #endif /* UNIV_DEBUG */ 03385 if (ut_dulint_cmp(wait_lock->trx->undo_no, 03386 start->undo_no) >= 0) { 03387 /* Our recursion starting point 03388 transaction is 'smaller', let us 03389 choose 'start' as the victim and roll 03390 back it */ 03391 03392 return(LOCK_VICTIM_IS_START); 03393 } 03394 03395 lock_deadlock_found = TRUE; 03396 03397 /* Let us choose the transaction of wait_lock 03398 as a victim to try to avoid deadlocking our 03399 recursion starting point transaction */ 03400 03401 fputs("*** WE ROLL BACK TRANSACTION (1)\n", 03402 ef); 03403 03404 wait_lock->trx->was_chosen_as_deadlock_victim 03405 = TRUE; 03406 03407 lock_cancel_waiting_and_release(wait_lock); 03408 03409 /* Since trx and wait_lock are no longer 03410 in the waits-for graph, we can return FALSE; 03411 note that our selective algorithm can choose 03412 several transactions as victims, but still 03413 we may end up rolling back also the recursion 03414 starting point transaction! */ 03415 03416 return(LOCK_VICTIM_IS_OTHER); 03417 } 03418 03419 if (lock_trx->que_state == TRX_QUE_LOCK_WAIT) { 03420 03421 /* Another trx ahead has requested lock in an 03422 incompatible mode, and is itself waiting for 03423 a lock */ 03424 03425 ret = lock_deadlock_recursive(start, lock_trx, 03426 lock_trx->wait_lock, cost, depth + 1); 03427 if (ret != 0) { 03428 03429 return(ret); 03430 } 03431 } 03432 } 03433 }/* end of the 'for (;;)'-loop */ 03434 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 610 of file lock0lock.c.
References lock, LOCK_MODE_MASK, and ut_ad.
Referenced by lock_get_src_table(), lock_grant(), lock_has_to_wait(), lock_is_table_exclusive(), lock_rec_has_expl(), lock_rec_has_to_wait(), lock_rec_inherit_to_gap(), lock_rec_inherit_to_gap_if_gap_lock(), lock_rec_other_has_expl_req(), lock_rec_print(), lock_rec_queue_validate(), lock_rec_unlock(), lock_release_off_kernel(), lock_table_has(), lock_table_other_has_incompatible(), lock_table_print(), and lock_table_queue_validate().
00612 : mode */ 00613 lock_t* lock) /* in: lock */ 00614 { 00615 ut_ad(lock); 00616 00617 return(lock->type_mode & LOCK_MODE_MASK); 00618 }
Here is the caller graph for this function:

| static ulint lock_get_n_rec_locks | ( | void | ) | [static] |
Definition at line 4221 of file lock0lock.c.
References hash(), HASH_GET_FIRST, hash_get_n_cells(), HASH_GET_NEXT, kernel_mutex, lock, lock_sys, lock_sys_struct::rec_hash, and ut_ad.
Referenced by lock_print_info_summary().
04223 { 04224 lock_t* lock; 04225 ulint n_locks = 0; 04226 ulint i; 04227 04228 #ifdef UNIV_SYNC_DEBUG 04229 ut_ad(mutex_own(&kernel_mutex)); 04230 #endif /* UNIV_SYNC_DEBUG */ 04231 04232 for (i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) { 04233 04234 lock = HASH_GET_FIRST(lock_sys->rec_hash, i); 04235 04236 while (lock) { 04237 n_locks++; 04238 04239 lock = HASH_GET_NEXT(hash, lock); 04240 } 04241 } 04242 04243 return(n_locks); 04244 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint lock_get_size | ( | void | ) |
Definition at line 599 of file lock0lock.c.
Referenced by dict_mem_table_create().
Here is the caller graph for this function:

| dict_table_t* lock_get_src_table | ( | trx_t * | trx, | |
| dict_table_t * | dest, | |||
| ulint * | mode | |||
| ) |
Definition at line 644 of file lock0lock.c.
References lock, lock_get_mode(), lock_get_type(), LOCK_IS, LOCK_IX, LOCK_NONE, LOCK_TABLE, dict_table_struct::locks, NULL, lock_table_struct::table, trx_struct::trx_locks, UT_LIST_GET_FIRST, UT_LIST_GET_LEN, and UT_LIST_GET_NEXT.
00646 : the source table of transaction, 00647 if it is covered by an IX or IS table lock; 00648 dest if there is no source table, and 00649 NULL if the transaction is locking more than 00650 two tables or an inconsistency is found */ 00651 trx_t* trx, /* in: transaction */ 00652 dict_table_t* dest, /* in: destination of ALTER TABLE */ 00653 ulint* mode) /* out: lock mode of the source table */ 00654 { 00655 dict_table_t* src; 00656 lock_t* lock; 00657 00658 src = NULL; 00659 *mode = LOCK_NONE; 00660 00661 for (lock = UT_LIST_GET_FIRST(trx->trx_locks); 00662 lock; 00663 lock = UT_LIST_GET_NEXT(trx_locks, lock)) { 00664 lock_table_t* tab_lock; 00665 ulint lock_mode; 00666 if (!(lock_get_type(lock) & LOCK_TABLE)) { 00667 /* We are only interested in table locks. */ 00668 continue; 00669 } 00670 tab_lock = &lock->un_member.tab_lock; 00671 if (dest == tab_lock->table) { 00672 /* We are not interested in the destination table. */ 00673 continue; 00674 } else if (!src) { 00675 /* This presumably is the source table. */ 00676 src = tab_lock->table; 00677 if (UT_LIST_GET_LEN(src->locks) != 1 || 00678 UT_LIST_GET_FIRST(src->locks) != lock) { 00679 /* We only support the case when 00680 there is only one lock on this table. */ 00681 return(NULL); 00682 } 00683 } else if (src != tab_lock->table) { 00684 /* The transaction is locking more than 00685 two tables (src and dest): abort */ 00686 return(NULL); 00687 } 00688 00689 /* Check that the source table is locked by 00690 LOCK_IX or LOCK_IS. */ 00691 lock_mode = lock_get_mode(lock); 00692 switch (lock_mode) { 00693 case LOCK_IX: 00694 case LOCK_IS: 00695 if (*mode != LOCK_NONE && *mode != lock_mode) { 00696 /* There are multiple locks on src. */ 00697 return(NULL); 00698 } 00699 *mode = lock_mode; 00700 break; 00701 } 00702 } 00703 00704 if (!src) { 00705 /* No source table lock found: flag the situation to caller */ 00706 src = dest; 00707 } 00708 00709 return(src); 00710 }
Here is the call graph for this function:

Definition at line 407 of file lock0lock.c.
References lock, LOCK_TYPE_MASK, and ut_ad.
Referenced by lock_cancel_waiting_and_release(), lock_deadlock_occurs(), lock_deadlock_recursive(), lock_get_src_table(), lock_has_to_wait(), lock_is_table_exclusive(), lock_number_of_rows_locked(), lock_print_info_all_transactions(), lock_rec_bitmap_reset(), lock_rec_cancel(), lock_rec_copy(), lock_rec_dequeue_from_page(), lock_rec_discard(), lock_rec_get_gap(), lock_rec_get_insert_intention(), lock_rec_get_next(), lock_rec_get_next_on_page(), lock_rec_get_nth_bit(), lock_rec_get_prev(), lock_rec_get_rec_not_gap(), lock_rec_has_to_wait(), lock_rec_has_to_wait_in_queue(), lock_rec_print(), lock_rec_reset_nth_bit(), lock_rec_set_nth_bit(), lock_release_off_kernel(), lock_reset_all_on_table_for_trx(), lock_table_dequeue(), lock_table_print(), and lock_validate().
00409 : LOCK_TABLE or LOCK_REC */ 00410 lock_t* lock) /* in: lock */ 00411 { 00412 ut_ad(lock); 00413 00414 return(lock->type_mode & LOCK_TYPE_MASK); 00415 }
Here is the caller graph for this function:

| UNIV_INLINE ibool lock_get_wait | ( | lock_t * | lock | ) |
Definition at line 624 of file lock0lock.c.
References FALSE, lock, LOCK_WAIT, TRUE, and ut_ad.
Referenced by lock_move_rec_list_end(), lock_move_rec_list_start(), lock_move_reorganize_page(), lock_rec_add_to_queue(), lock_rec_dequeue_from_page(), lock_rec_free_all_from_discard_page(), lock_rec_has_expl(), lock_rec_has_to_wait_in_queue(), lock_rec_move(), lock_rec_other_has_expl_req(), lock_rec_print(), lock_rec_queue_validate(), lock_rec_reset_and_release_wait(), lock_rec_unlock(), lock_reset_all_on_table(), lock_reset_all_on_table_for_trx(), lock_reset_lock_and_trx_wait(), lock_table_dequeue(), lock_table_has(), lock_table_has_to_wait_in_queue(), lock_table_other_has_incompatible(), lock_table_print(), and lock_table_queue_validate().
00626 : TRUE if waiting */ 00627 lock_t* lock) /* in: lock */ 00628 { 00629 ut_ad(lock); 00630 00631 if (lock->type_mode & LOCK_WAIT) { 00632 00633 return(TRUE); 00634 } 00635 00636 return(FALSE); 00637 }
Here is the caller graph for this function:

| static void lock_grant | ( | lock_t * | lock | ) | [static] |
Definition at line 2242 of file lock0lock.c.
References kernel_mutex, lock, LOCK_AUTO_INC, lock_get_mode(), lock_reset_lock_and_trx_wait(), NULL, trx_end_lock_wait(), TRX_QUE_LOCK_WAIT, ut_ad, and ut_dulint_get_low().
Referenced by lock_rec_dequeue_from_page(), lock_rec_unlock(), and lock_table_dequeue().
02244 : waiting lock request */ 02245 { 02246 #ifdef UNIV_SYNC_DEBUG 02247 ut_ad(mutex_own(&kernel_mutex)); 02248 #endif /* UNIV_SYNC_DEBUG */ 02249 02250 lock_reset_lock_and_trx_wait(lock); 02251 02252 if (lock_get_mode(lock) == LOCK_AUTO_INC) { 02253 02254 if (lock->trx->auto_inc_lock != NULL) { 02255 fprintf(stderr, 02256 "InnoDB: Error: trx already had an AUTO-INC lock!\n"); 02257 } 02258 02259 /* Store pointer to lock to trx so that we know to 02260 release it at the end of the SQL statement */ 02261 02262 lock->trx->auto_inc_lock = lock; 02263 } 02264 02265 #ifdef UNIV_DEBUG 02266 if (lock_print_waits) { 02267 fprintf(stderr, "Lock wait for trx %lu ends\n", 02268 (ulong) ut_dulint_get_low(lock->trx->id)); 02269 } 02270 #endif /* UNIV_DEBUG */ 02271 02272 /* If we are resolving a deadlock by choosing another transaction 02273 as a victim, then our original transaction may not be in the 02274 TRX_QUE_LOCK_WAIT state, and there is no need to end the lock wait 02275 for it */ 02276 02277 if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) { 02278 trx_end_lock_wait(lock->trx); 02279 } 02280 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1020 of file lock0lock.c.
References FALSE, lock_get_mode(), lock_get_type(), lock_mode_compatible(), LOCK_REC, lock_rec_get_nth_bit(), lock_rec_has_to_wait(), TRUE, lock_struct::trx, and ut_ad.
Referenced by lock_deadlock_recursive(), lock_rec_has_to_wait_in_queue(), and lock_table_has_to_wait_in_queue().
01022 : TRUE if lock1 has to wait for lock2 to be 01023 removed */ 01024 lock_t* lock1, /* in: waiting lock */ 01025 lock_t* lock2) /* in: another lock; NOTE that it is assumed that this 01026 has a lock bit set on the same record as in lock1 if 01027 the locks are record locks */ 01028 { 01029 ut_ad(lock1 && lock2); 01030 01031 if (lock1->trx != lock2->trx 01032 && !lock_mode_compatible(lock_get_mode(lock1), 01033 lock_get_mode(lock2))) { 01034 if (lock_get_type(lock1) == LOCK_REC) { 01035 ut_ad(lock_get_type(lock2) == LOCK_REC); 01036 01037 /* If this lock request is for a supremum record 01038 then the second bit on the lock bitmap is set */ 01039 01040 return(lock_rec_has_to_wait(lock1->trx, 01041 lock1->type_mode, lock2, 01042 lock_rec_get_nth_bit(lock1,1))); 01043 } 01044 01045 return(TRUE); 01046 } 01047 01048 return(FALSE); 01049 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool lock_is_on_table | ( | dict_table_t * | table | ) |
Definition at line 3700 of file lock0lock.c.
References FALSE, lock_mutex_enter_kernel, lock_mutex_exit_kernel, dict_table_struct::locks, TRUE, ut_ad, and UT_LIST_GET_LAST.
03702 : TRUE if there are lock(s) */ 03703 dict_table_t* table) /* in: database table in dictionary cache */ 03704 { 03705 ibool ret; 03706 03707 ut_ad(table); 03708 03709 lock_mutex_enter_kernel(); 03710 03711 if (UT_LIST_GET_LAST(table->locks)) { 03712 ret = TRUE; 03713 } else { 03714 ret = FALSE; 03715 } 03716 03717 lock_mutex_exit_kernel(); 03718 03719 return(ret); 03720 }
| ibool lock_is_table_exclusive | ( | dict_table_t * | table, | |
| trx_t * | trx | |||
| ) |
Definition at line 718 of file lock0lock.c.
References FALSE, lock, LOCK_AUTO_INC, lock_get_mode(), lock_get_type(), LOCK_IX, LOCK_TABLE, lock_table_struct::locks, dict_table_struct::locks, ok(), lock_table_struct::table, TRUE, ut_ad, UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
00720 : TRUE if table is only locked by trx, 00721 with LOCK_IX, and possibly LOCK_AUTO_INC */ 00722 dict_table_t* table, /* in: table */ 00723 trx_t* trx) /* in: transaction */ 00724 { 00725 lock_t* lock; 00726 ibool ok = FALSE; 00727 00728 ut_ad(table && trx); 00729 00730 for (lock = UT_LIST_GET_FIRST(table->locks); 00731 lock; 00732 lock = UT_LIST_GET_NEXT(locks, &lock->un_member.tab_lock)) { 00733 if (lock->trx != trx) { 00734 /* A lock on the table is held 00735 by some other transaction. */ 00736 return(FALSE); 00737 } 00738 00739 if (!(lock_get_type(lock) & LOCK_TABLE)) { 00740 /* We are interested in table locks only. */ 00741 continue; 00742 } 00743 00744 switch (lock_get_mode(lock)) { 00745 case LOCK_IX: 00746 ok = TRUE; 00747 break; 00748 case LOCK_AUTO_INC: 00749 /* It is allowed for trx to hold an 00750 auto_increment lock. */ 00751 break; 00752 default: 00753 /* Other table locks than LOCK_IX are not allowed. */ 00754 return(FALSE); 00755 } 00756 } 00757 00758 return(ok); 00759 }
Here is the call graph for this function:

Definition at line 897 of file lock0lock.c.
References FALSE, LOCK_AUTO_INC, LOCK_IS, LOCK_IX, LOCK_S, LOCK_X, TRUE, and ut_ad.
Referenced by lock_has_to_wait(), lock_rec_has_to_wait(), and lock_table_other_has_incompatible().
00899 : TRUE if mode1 compatible with mode2 */ 00900 ulint mode1, /* in: lock mode */ 00901 ulint mode2) /* in: lock mode */ 00902 { 00903 ut_ad(mode1 == LOCK_X || mode1 == LOCK_S || mode1 == LOCK_IX 00904 || mode1 == LOCK_IS || mode1 == LOCK_AUTO_INC); 00905 ut_ad(mode2 == LOCK_X || mode2 == LOCK_S || mode2 == LOCK_IX 00906 || mode2 == LOCK_IS || mode2 == LOCK_AUTO_INC); 00907 00908 if (mode1 == LOCK_S && (mode2 == LOCK_IS || mode2 == LOCK_S)) { 00909 00910 return(TRUE); 00911 00912 } else if (mode1 == LOCK_X) { 00913 00914 return(FALSE); 00915 00916 } else if (mode1 == LOCK_AUTO_INC && (mode2 == LOCK_IS 00917 || mode2 == LOCK_IX)) { 00918 return(TRUE); 00919 00920 } else if (mode1 == LOCK_IS && (mode2 == LOCK_IS 00921 || mode2 == LOCK_IX 00922 || mode2 == LOCK_AUTO_INC 00923 || mode2 == LOCK_S)) { 00924 return(TRUE); 00925 00926 } else if (mode1 == LOCK_IX && (mode2 == LOCK_IS 00927 || mode2 == LOCK_AUTO_INC 00928 || mode2 == LOCK_IX)) { 00929 return(TRUE); 00930 } 00931 00932 return(FALSE); 00933 }
Here is the caller graph for this function:

Definition at line 859 of file lock0lock.c.
References FALSE, LOCK_AUTO_INC, LOCK_IS, LOCK_IX, LOCK_S, LOCK_X, TRUE, and ut_ad.
Referenced by lock_rec_has_expl(), lock_rec_other_has_expl_req(), and lock_table_has().
00861 : TRUE if mode1 stronger or equal to mode2 */ 00862 ulint mode1, /* in: lock mode */ 00863 ulint mode2) /* in: lock mode */ 00864 { 00865 ut_ad(mode1 == LOCK_X || mode1 == LOCK_S || mode1 == LOCK_IX 00866 || mode1 == LOCK_IS || mode1 == LOCK_AUTO_INC); 00867 ut_ad(mode2 == LOCK_X || mode2 == LOCK_S || mode2 == LOCK_IX 00868 || mode2 == LOCK_IS || mode2 == LOCK_AUTO_INC); 00869 if (mode1 == LOCK_X) { 00870 00871 return(TRUE); 00872 00873 } else if (mode1 == LOCK_AUTO_INC && mode2 == LOCK_AUTO_INC) { 00874 00875 return(TRUE); 00876 00877 } else if (mode1 == LOCK_S 00878 && (mode2 == LOCK_S || mode2 == LOCK_IS)) { 00879 return(TRUE); 00880 00881 } else if (mode1 == LOCK_IS && mode2 == LOCK_IS) { 00882 00883 return(TRUE); 00884 00885 } else if (mode1 == LOCK_IX && (mode2 == LOCK_IX 00886 || mode2 == LOCK_IS)) { 00887 return(TRUE); 00888 } 00889 00890 return(FALSE); 00891 }
Here is the caller graph for this function:

Definition at line 2704 of file lock0lock.c.
References buf_frame_align(), lock, lock_get_wait(), lock_mutex_enter_kernel, lock_mutex_exit_kernel, lock_rec_add_to_queue(), lock_rec_get_first_on_page(), lock_rec_get_next_on_page(), lock_rec_get_nth_bit(), lock_rec_reset_nth_bit(), lock_reset_lock_and_trx_wait(), NULL, page_cur_get_rec(), page_cur_is_before_first(), page_cur_move_to_next(), page_cur_position(), page_cur_set_before_first(), page_get_supremum_rec(), page_is_comp(), rec_get_data_size_old(), rec_get_heap_no(), ut_ad, and ut_memcmp().
Referenced by page_copy_rec_list_end().
02706 : index page to move to */ 02707 page_t* page, /* in: index page */ 02708 rec_t* rec) /* in: record on page: this is the 02709 first record moved */ 02710 { 02711 lock_t* lock; 02712 page_cur_t cur1; 02713 page_cur_t cur2; 02714 ulint heap_no; 02715 rec_t* sup; 02716 ulint type_mode; 02717 ulint comp; 02718 ut_ad(page == buf_frame_align(rec)); 02719 02720 lock_mutex_enter_kernel(); 02721 02722 /* Note: when we move locks from record to record, waiting locks 02723 and possible granted gap type locks behind them are enqueued in 02724 the original order, because new elements are inserted to a hash 02725 table to the end of the hash chain, and lock_rec_add_to_queue 02726 does not reuse locks if there are waiters in the queue. */ 02727 02728 sup = page_get_supremum_rec(page); 02729 02730 lock = lock_rec_get_first_on_page(page); 02731 02732 comp = page_is_comp(page); 02733 02734 while (lock != NULL) { 02735 02736 page_cur_position(rec, &cur1); 02737 02738 if (page_cur_is_before_first(&cur1)) { 02739 page_cur_move_to_next(&cur1); 02740 } 02741 02742 page_cur_set_before_first(new_page, &cur2); 02743 page_cur_move_to_next(&cur2); 02744 02745 /* Copy lock requests on user records to new page and 02746 reset the lock bits on the old */ 02747 02748 while (page_cur_get_rec(&cur1) != sup) { 02749 ut_ad(comp || 0 == ut_memcmp(page_cur_get_rec(&cur1), 02750 page_cur_get_rec(&cur2), 02751 rec_get_data_size_old( 02752 page_cur_get_rec(&cur2)))); 02753 heap_no = rec_get_heap_no(page_cur_get_rec(&cur1), 02754 comp); 02755 02756 if (lock_rec_get_nth_bit(lock, heap_no)) { 02757 type_mode = lock->type_mode; 02758 02759 lock_rec_reset_nth_bit(lock, heap_no); 02760 02761 if (lock_get_wait(lock)) { 02762 lock_reset_lock_and_trx_wait(lock); 02763 } 02764 02765 lock_rec_add_to_queue(type_mode, 02766 page_cur_get_rec(&cur2), 02767 lock->index, lock->trx); 02768 } 02769 02770 page_cur_move_to_next(&cur1); 02771 page_cur_move_to_next(&cur2); 02772 } 02773 02774 lock = lock_rec_get_next_on_page(lock); 02775 } 02776 02777 lock_mutex_exit_kernel(); 02778 02779 /* ut_ad(lock_rec_validate_page(buf_frame_get_space_id(page), 02780 buf_frame_get_page_no(page))); 02781 ut_ad(lock_rec_validate_page(buf_frame_get_space_id(new_page), 02782 buf_frame_get_page_no(new_page))); */ 02783 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2790 of file lock0lock.c.
References buf_frame_align(), lock, lock_get_wait(), lock_mutex_enter_kernel, lock_mutex_exit_kernel, lock_rec_add_to_queue(), lock_rec_get_first_on_page(), lock_rec_get_next_on_page(), lock_rec_get_nth_bit(), lock_rec_reset_nth_bit(), lock_reset_lock_and_trx_wait(), NULL, page_cur_get_rec(), page_cur_move_to_next(), page_cur_position(), page_cur_set_before_first(), page_is_comp(), rec_get_data_size_old(), rec_get_heap_no(), ut_a, ut_ad, and ut_memcmp().
Referenced by page_copy_rec_list_start().
02792 : index page to move to */ 02793 page_t* page, /* in: index page */ 02794 rec_t* rec, /* in: record on page: this is the 02795 first record NOT copied */ 02796 rec_t* old_end) /* in: old previous-to-last record on 02797 new_page before the records were copied */ 02798 { 02799 lock_t* lock; 02800 page_cur_t cur1; 02801 page_cur_t cur2; 02802 ulint heap_no; 02803 ulint type_mode; 02804 ulint comp; 02805 02806 ut_a(new_page); 02807 02808 lock_mutex_enter_kernel(); 02809 02810 lock = lock_rec_get_first_on_page(page); 02811 comp = page_is_comp(page); 02812 ut_ad(comp == page_is_comp(new_page)); 02813 ut_ad(page == buf_frame_align(rec)); 02814 02815 while (lock != NULL) { 02816 02817 page_cur_set_before_first(page, &cur1); 02818 page_cur_move_to_next(&cur1); 02819 02820 page_cur_position(old_end, &cur2); 02821 page_cur_move_to_next(&cur2); 02822 02823 /* Copy lock requests on user records to new page and 02824 reset the lock bits on the old */ 02825 02826 while (page_cur_get_rec(&cur1) != rec) { 02827 ut_ad(comp || 0 == ut_memcmp(page_cur_get_rec(&cur1), 02828 page_cur_get_rec(&cur2), 02829 rec_get_data_size_old( 02830 page_cur_get_rec(&cur2)))); 02831 heap_no = rec_get_heap_no(page_cur_get_rec(&cur1), 02832 comp); 02833 02834 if (lock_rec_get_nth_bit(lock, heap_no)) { 02835 type_mode = lock->type_mode; 02836 02837 lock_rec_reset_nth_bit(lock, heap_no); 02838 02839 if (lock_get_wait(lock)) { 02840 lock_reset_lock_and_trx_wait(lock); 02841 } 02842 02843 lock_rec_add_to_queue(type_mode, 02844 page_cur_get_rec(&cur2), 02845 lock->index, lock->trx); 02846 } 02847 02848 page_cur_move_to_next(&cur1); 02849 page_cur_move_to_next(&cur2); 02850 } 02851 02852 lock = lock_rec_get_next_on_page(lock); 02853 } 02854 02855 lock_mutex_exit_kernel(); 02856 02857 /* ut_ad(lock_rec_validate_page(buf_frame_get_space_id(page), 02858 buf_frame_get_page_no(page))); 02859 ut_ad(lock_rec_validate_page(buf_frame_get_space_id(new_page), 02860 buf_frame_get_page_no(new_page))); */ 02861 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2585 of file lock0lock.c.
References lock, lock_get_wait(), lock_mutex_enter_kernel, lock_mutex_exit_kernel, lock_rec_add_to_queue(), lock_rec_bitmap_reset(), lock_rec_copy(), lock_rec_get_first_on_page(), lock_rec_get_next_on_page(), lock_rec_get_nth_bit(), lock_reset_lock_and_trx_wait(), mem_heap_create, mem_heap_free, NULL, page_cur_get_rec(), page_cur_move_to_next(), page_cur_set_before_first(), page_get_supremum_rec(), page_is_comp(), rec_get_data_size_old(), rec_get_heap_no(), ut_ad, UT_LIST_ADD_LAST, UT_LIST_BASE_NODE_T, UT_LIST_GET_FIRST, UT_LIST_GET_NEXT, UT_LIST_INIT, and ut_memcmp().
Referenced by btr_page_reorganize_low().
02587 : old index page, now reorganized */ 02588 page_t* old_page) /* in: copy of the old, not reorganized page */ 02589 { 02590 lock_t* lock; 02591 lock_t* old_lock; 02592 page_cur_t cur1; 02593 page_cur_t cur2; 02594 ulint old_heap_no; 02595 UT_LIST_BASE_NODE_T(lock_t) old_locks; 02596 mem_heap_t* heap = NULL; 02597 rec_t* sup; 02598 ulint comp; 02599 02600 lock_mutex_enter_kernel(); 02601 02602 lock = lock_rec_get_first_on_page(page); 02603 02604 if (lock == NULL) { 02605 lock_mutex_exit_kernel(); 02606 02607 return; 02608 } 02609 02610 heap = mem_heap_create(256); 02611 02612 /* Copy first all the locks on the page to heap and reset the 02613 bitmaps in the original locks; chain the copies of the locks 02614 using the trx_locks field in them. */ 02615 02616 UT_LIST_INIT(old_locks); 02617 02618 while (lock != NULL) { 02619 02620 /* Make a copy of the lock */ 02621 old_lock = lock_rec_copy(lock, heap); 02622 02623 UT_LIST_ADD_LAST(trx_locks, old_locks, old_lock); 02624 02625 /* Reset bitmap of lock */ 02626 lock_rec_bitmap_reset(lock); 02627 02628 if (lock_get_wait(lock)) { 02629 lock_reset_lock_and_trx_wait(lock); 02630 } 02631 02632 lock = lock_rec_get_next_on_page(lock); 02633 } 02634 02635 sup = page_get_supremum_rec(page); 02636 02637 lock = UT_LIST_GET_FIRST(old_locks); 02638 02639 comp = page_is_comp(page); 02640 ut_ad(comp == page_is_comp(old_page)); 02641 02642 while (lock) { 02643 /* NOTE: we copy also the locks set on the infimum and 02644 supremum of the page; the infimum may carry locks if an 02645 update of a record is occurring on the page, and its locks 02646 were temporarily stored on the infimum */ 02647 02648 page_cur_set_before_first(page, &cur1); 02649 page_cur_set_before_first(old_page, &cur2); 02650 02651 /* Set locks according to old locks */ 02652 for (;;) { 02653 ut_ad(comp || 0 == ut_memcmp(page_cur_get_rec(&cur1), 02654 page_cur_get_rec(&cur2), 02655 rec_get_data_size_old( 02656 page_cur_get_rec(&cur2)))); 02657 old_heap_no = rec_get_heap_no(page_cur_get_rec(&cur2), 02658 comp); 02659 02660 if (lock_rec_get_nth_bit(lock, old_heap_no)) { 02661 02662 /* NOTE that the old lock bitmap could be too 02663 small for the new heap number! */ 02664 02665 lock_rec_add_to_queue(lock->type_mode, 02666 page_cur_get_rec(&cur1), 02667 lock->index, lock->trx); 02668 02669 /* if ((page_cur_get_rec(&cur1) == sup) 02670 && lock_get_wait(lock)) { 02671 fprintf(stderr, 02672 "---\n--\n!!!Lock reorg: supr type %lu\n", 02673 lock->type_mode); 02674 } */ 02675 } 02676 02677 if (page_cur_get_rec(&cur1) == sup) { 02678 02679 break; 02680 } 02681 02682 page_cur_move_to_next(&cur1); 02683 page_cur_move_to_next(&cur2); 02684 } 02685 02686 /* Remember that we chained old locks on the trx_locks field: */ 02687 02688 lock = UT_LIST_GET_NEXT(trx_locks, lock); 02689 } 02690 02691 lock_mutex_exit_kernel(); 02692 02693 mem_heap_free(heap); 02694 02695 /* ut_ad(lock_rec_validate_page(buf_frame_get_space_id(page), 02696 buf_frame_get_page_no(page))); */ 02697 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1707 of file lock0lock.c.
References lock, lock_get_type(), LOCK_REC, lock_rec_get_n_bits(), lock_rec_get_nth_bit(), trx_struct::trx_locks, UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by lock_print_info_all_transactions(), and trx_print().
01709 : transaction */ 01710 { 01711 lock_t* lock; 01712 ulint n_records = 0; 01713 ulint n_bits; 01714 ulint n_bit; 01715 01716 lock = UT_LIST_GET_FIRST(trx->trx_locks); 01717 01718 while (lock) { 01719 if (lock_get_type(lock) == LOCK_REC) { 01720 n_bits = lock_rec_get_n_bits(lock); 01721 01722 for (n_bit = 0; n_bit < n_bits; n_bit++) { 01723 if (lock_rec_get_nth_bit(lock, n_bit)) { 01724 n_records++; 01725 } 01726 } 01727 } 01728 01729 lock = UT_LIST_GET_NEXT(trx_locks, lock); 01730 } 01731 01732 return (n_records); 01733 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void lock_print_info_all_transactions | ( | FILE * | file | ) |
Definition at line 4298 of file lock0lock.c.
References buf_page_get_with_no_latch, trx_struct::conc_state, FALSE, innobase_mysql_end_print_arbitrary_thd(), innobase_mysql_prepare_print_arbitrary_thd(), lock, lock_get_type(), lock_mutex_enter_kernel, lock_mutex_exit_kernel, lock_number_of_rows_locked(), LOCK_REC, lock_rec_print(), LOCK_TABLE, lock_table_print(), lock_validate(), read_view_struct::low_limit_id, mtr_commit(), mtr_start(), NULL, page, page_t, trx_struct::read_view, srv_print_innodb_lock_monitor, TRUE, trx_struct::trx_locks, TRX_NOT_STARTED, trx_print(), TRX_QUE_LOCK_WAIT, trx_sys, read_view_struct::up_limit_id, ut_ad, ut_dulint_get_high(), ut_dulint_get_low(), UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by srv_printf_innodb_monitor().
04300 : file where to print */ 04301 { 04302 lock_t* lock; 04303 ulint space; 04304 ulint page_no; 04305 page_t* page; 04306 ibool load_page_first = TRUE; 04307 ulint nth_trx = 0; 04308 ulint nth_lock = 0; 04309 ulint i; 04310 mtr_t mtr; 04311 trx_t* trx; 04312 04313 fprintf(file, "LIST OF TRANSACTIONS FOR EACH SESSION:\n"); 04314 04315 /* First print info on non-active transactions */ 04316 04317 trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list); 04318 04319 while (trx) { 04320 if (trx->conc_state == TRX_NOT_STARTED) { 04321 fputs("---", file); 04322 trx_print(file, trx, 600); 04323 } 04324 04325 trx = UT_LIST_GET_NEXT(mysql_trx_list, trx); 04326 } 04327 04328 loop: 04329 trx = UT_LIST_GET_FIRST(trx_sys->trx_list); 04330 04331 i = 0; 04332 04333 /* Since we temporarily release the kernel mutex when 04334 reading a database page in below, variable trx may be 04335 obsolete now and we must loop through the trx list to 04336 get probably the same trx, or some other trx. */ 04337 04338 while (trx && (i < nth_trx)) { 04339 trx = UT_LIST_GET_NEXT(trx_list, trx); 04340 i++; 04341 } 04342 04343 if (trx == NULL) { 04344 lock_mutex_exit_kernel(); 04345 innobase_mysql_end_print_arbitrary_thd(); 04346 04347 ut_ad(lock_validate()); 04348 04349 return; 04350 } 04351 04352 if (nth_lock == 0) { 04353 fputs("---", file); 04354 trx_print(file, trx, 600); 04355 04356 if (trx->read_view) { 04357 fprintf(file, 04358 "Trx read view will not see trx with id >= %lu %lu, sees < %lu %lu\n", 04359 (ulong) ut_dulint_get_high(trx->read_view->low_limit_id), 04360 (ulong) ut_dulint_get_low(trx->read_view->low_limit_id), 04361 (ulong) ut_dulint_get_high(trx->read_view->up_limit_id), 04362 (ulong) ut_dulint_get_low(trx->read_view->up_limit_id)); 04363 } 04364 04365 fprintf(file, 04366 "Trx has approximately %lu row locks\n", 04367 (ulong) lock_number_of_rows_locked(trx)); 04368 04369 if (trx->que_state == TRX_QUE_LOCK_WAIT) { 04370 fprintf(file, 04371 "------- TRX HAS BEEN WAITING %lu SEC FOR THIS LOCK TO BE GRANTED:\n", 04372 (ulong)difftime(time(NULL), trx->wait_started)); 04373 04374 if (lock_get_type(trx->wait_lock) == LOCK_REC) { 04375 lock_rec_print(file, trx->wait_lock); 04376 } else { 04377 lock_table_print(file, trx->wait_lock); 04378 } 04379 04380 fputs("------------------\n", file); 04381 } 04382 } 04383 04384 if (!srv_print_innodb_lock_monitor) { 04385 nth_trx++; 04386 goto loop; 04387 } 04388 04389 i = 0; 04390 04391 /* Look at the note about the trx loop above why we loop here: 04392 lock may be an obsolete pointer now. */ 04393 04394 lock = UT_LIST_GET_FIRST(trx->trx_locks); 04395 04396 while (lock && (i < nth_lock)) { 04397 lock = UT_LIST_GET_NEXT(trx_locks, lock); 04398 i++; 04399 } 04400 04401 if (lock == NULL) { 04402 nth_trx++; 04403 nth_lock = 0; 04404 04405 goto loop; 04406 } 04407 04408 if (lock_get_type(lock) == LOCK_REC) { 04409 space = lock->un_member.rec_lock.space; 04410 page_no = lock->un_member.rec_lock.page_no; 04411 04412 if (load_page_first) { 04413 lock_mutex_exit_kernel(); 04414 innobase_mysql_end_print_arbitrary_thd(); 04415 04416 mtr_start(&mtr); 04417 04418 page = buf_page_get_with_no_latch(space, page_no, &mtr); 04419 04420 mtr_commit(&mtr); 04421 04422 load_page_first = FALSE; 04423 04424 innobase_mysql_prepare_print_arbitrary_thd(); 04425 lock_mutex_enter_kernel(); 04426 04427 goto loop; 04428 } 04429 04430 lock_rec_print(file, lock); 04431 } else { 04432 ut_ad(lock_get_type(lock) & LOCK_TABLE); 04433 04434 lock_table_print(file, lock); 04435 } 04436 04437 load_page_first = TRUE; 04438 04439 nth_lock++; 04440 04441 if (nth_lock >= 10) { 04442 fputs( 04443 "10 LOCKS PRINTED FOR THIS TRX: SUPPRESSING FURTHER PRINTS\n", 04444 file); 04445 04446 nth_trx++; 04447 nth_lock = 0; 04448 04449 goto loop; 04450 } 04451 04452 goto loop; 04453 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void lock_print_info_summary | ( | FILE * | file | ) |
Definition at line 4250 of file lock0lock.c.
References innobase_mysql_prepare_print_arbitrary_thd(), lock_deadlock_found, lock_get_n_rec_locks(), lock_latest_err_file, lock_mutex_enter_kernel, trx_sys_struct::max_trx_id, purge_sys, trx_purge_struct::purge_trx_no, trx_purge_struct::purge_undo_no, trx_sys_struct::rseg_history_len, trx_sys, ut_copy_file(), ut_dulint_get_high(), and ut_dulint_get_low().
Referenced by srv_printf_innodb_monitor().
04252 : file where to print */ 04253 { 04254 /* We must protect the MySQL thd->query field with a MySQL mutex, and 04255 because the MySQL mutex must be reserved before the kernel_mutex of 04256 InnoDB, we call innobase_mysql_prepare_print_arbitrary_thd() here. */ 04257 04258 innobase_mysql_prepare_print_arbitrary_thd(); 04259 lock_mutex_enter_kernel(); 04260 04261 if (lock_deadlock_found) { 04262 fputs( 04263 "------------------------\n" 04264 "LATEST DETECTED DEADLOCK\n" 04265 "------------------------\n", file); 04266 04267 ut_copy_file(file, lock_latest_err_file); 04268 } 04269 04270 fputs( 04271 "------------\n" 04272 "TRANSACTIONS\n" 04273 "------------\n", file); 04274 04275 fprintf(file, "Trx id counter %lu %lu\n", 04276 (ulong) ut_dulint_get_high(trx_sys->max_trx_id), 04277 (ulong) ut_dulint_get_low(trx_sys->max_trx_id)); 04278 04279 fprintf(file, 04280 "Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu\n", 04281 (ulong) ut_dulint_get_high(purge_sys->purge_trx_no), 04282 (ulong) ut_dulint_get_low(purge_sys->purge_trx_no), 04283 (ulong) ut_dulint_get_high(purge_sys->purge_undo_no), 04284 (ulong) ut_dulint_get_low(purge_sys->purge_undo_no)); 04285 04286 fprintf(file, 04287 "History list length %lu\n", (ulong) trx_sys->rseg_history_len); 04288 04289 fprintf(file, 04290 "Total number of lock structs in row lock hash table %lu\n", 04291 (ulong) lock_get_n_rec_locks()); 04292 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static lock_t* lock_rec_add_to_queue | ( | ulint | type_mode, | |
| rec_t * | rec, | |||
| dict_index_t * | index, | |||
| trx_t * | trx | |||
| ) | [static] |
Definition at line 1918 of file lock0lock.c.
References FALSE, index(), kernel_mutex, lock, LOCK_GAP, lock_get_wait(), LOCK_MODE_MASK, LOCK_REC, lock_rec_create(), lock_rec_find_similar_on_page(), lock_rec_get_first_on_page(), lock_rec_get_next_on_page(), lock_rec_get_nth_bit(), LOCK_REC_NOT_GAP, lock_rec_other_has_expl_req(), lock_rec_set_nth_bit(), LOCK_S, LOCK_WAIT, LOCK_X, NULL, page_rec_is_comp(), page_rec_is_supremum(), rec_get_heap_no(), TRUE, and ut_ad.
Referenced by lock_move_rec_list_end(), lock_move_rec_list_start(), lock_move_reorganize_page(), lock_rec_convert_impl_to_expl(), lock_rec_inherit_to_gap(), lock_rec_inherit_to_gap_if_gap_lock(), lock_rec_lock_slow(), and lock_rec_move().
01920 : lock where the bit was set */ 01921 ulint type_mode,/* in: lock mode, wait, gap etc. flags; 01922 type is ignored and replaced by LOCK_REC */ 01923 rec_t* rec, /* in: record on page */ 01924 dict_index_t* index, /* in: index of record */ 01925 trx_t* trx) /* in: transaction */ 01926 { 01927 lock_t* lock; 01928 lock_t* similar_lock = NULL; 01929 ulint heap_no; 01930 ibool somebody_waits = FALSE; 01931 01932 #ifdef UNIV_SYNC_DEBUG 01933 ut_ad(mutex_own(&kernel_mutex)); 01934 #endif /* UNIV_SYNC_DEBUG */ 01935 ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP)) 01936 || ((type_mode & LOCK_MODE_MASK) != LOCK_S) 01937 || !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT, 01938 rec, trx)); 01939 ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP)) 01940 || ((type_mode & LOCK_MODE_MASK) != LOCK_X) 01941 || !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT, 01942 rec, trx)); 01943 01944 type_mode = type_mode | LOCK_REC; 01945 01946 /* If rec is the supremum record, then we can reset the gap bit, as 01947 all locks on the supremum are automatically of the gap type, and we 01948 try to avoid unnecessary memory consumption of a new record lock 01949 struct for a gap type lock */ 01950 01951 if (page_rec_is_supremum(rec)) { 01952 ut_ad(!(type_mode & LOCK_REC_NOT_GAP)); 01953 01954 /* There should never be LOCK_REC_NOT_GAP on a supremum 01955 record, but let us play safe */ 01956 01957 type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP); 01958 } 01959 01960 /* Look for a waiting lock request on the same record or on a gap */ 01961 01962 heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec)); 01963 lock = lock_rec_get_first_on_page(rec); 01964 01965 while (lock != NULL) { 01966 if (lock_get_wait(lock) 01967 && (lock_rec_get_nth_bit(lock, heap_no))) { 01968 01969 somebody_waits = TRUE; 01970 } 01971 01972 lock = lock_rec_get_next_on_page(lock); 01973 } 01974 01975 /* Look for a similar record lock on the same page: if one is found 01976 and there are no waiting lock requests, we can just set the bit */ 01977 01978 similar_lock = lock_rec_find_similar_on_page(type_mode, rec, trx); 01979 01980 if (similar_lock && !somebody_waits && !(type_mode & LOCK_WAIT)) { 01981 01982 lock_rec_set_nth_bit(similar_lock, heap_no); 01983 01984 return(similar_lock); 01985 } 01986 01987 return(lock_rec_create(type_mode, rec, index, trx)); 01988 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void lock_rec_bitmap_reset | ( | lock_t * | lock | ) | [static] |
Definition at line 1348 of file lock0lock.c.
References lock, lock_get_type(), LOCK_REC, lock_rec_get_n_bits(), and ut_ad.
Referenced by lock_move_reorganize_page(), and lock_rec_create().
01350 : record lock */ 01351 { 01352 byte* ptr; 01353 ulint n_bytes; 01354 ulint i; 01355 01356 ut_ad(lock_get_type(lock) == LOCK_REC); 01357 01358 /* Reset to zero the bitmap which resides immediately after the lock 01359 struct */ 01360 01361 ptr = (byte*)lock + sizeof(lock_t); 01362 01363 n_bytes = lock_rec_get_n_bits(lock) / 8; 01364 01365 ut_ad((lock_rec_get_n_bits(lock) % 8) == 0); 01366 01367 for (i = 0; i < n_bytes; i++) { 01368 01369 *ptr = 0; 01370 ptr++; 01371 } 01372 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void lock_rec_cancel | ( | lock_t * | lock | ) | [static] |
Definition at line 2288 of file lock0lock.c.
References kernel_mutex, lock, lock_get_type(), LOCK_REC, lock_rec_find_set_bit(), lock_rec_reset_nth_bit(), lock_reset_lock_and_trx_wait(), trx_end_lock_wait(), and ut_ad.
Referenced by lock_rec_reset_and_release_wait().
02290 : waiting record lock request */ 02291 { 02292 #ifdef UNIV_SYNC_DEBUG 02293 ut_ad(mutex_own(&kernel_mutex)); 02294 #endif /* UNIV_SYNC_DEBUG */ 02295 ut_ad(lock_get_type(lock) == LOCK_REC); 02296 02297 /* Reset the bit (there can be only one set bit) in the lock bitmap */ 02298 lock_rec_reset_nth_bit(lock, lock_rec_find_set_bit(lock)); 02299 02300 /* Reset the wait flag and the back pointer to lock in trx */ 02301 02302 lock_reset_lock_and_trx_wait(lock); 02303 02304 /* The following function releases the trx from lock wait */ 02305 02306 trx_end_lock_wait(lock->trx); 02307 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void lock_rec_convert_impl_to_expl | ( | rec_t * | rec, | |
| dict_index_t * | index, | |||
| const ulint * | offsets | |||
| ) | [static] |
Definition at line 4902 of file lock0lock.c.
References DICT_CLUSTERED, index(), kernel_mutex, lock_clust_rec_some_has_impl(), LOCK_REC, lock_rec_add_to_queue(), lock_rec_has_expl(), LOCK_REC_NOT_GAP, lock_sec_rec_some_has_impl_off_kernel(), LOCK_X, page_rec_is_comp(), page_rec_is_user_rec(), rec_offs_comp(), rec_offs_validate(), and ut_ad.
Referenced by lock_clust_rec_modify_check_and_lock(), lock_clust_rec_read_check_and_lock(), and lock_sec_rec_read_check_and_lock().
04904 : user record on page */ 04905 dict_index_t* index, /* in: index of record */ 04906 const ulint* offsets)/* in: rec_get_offsets(rec, index) */ 04907 { 04908 trx_t* impl_trx; 04909 04910 #ifdef UNIV_SYNC_DEBUG 04911 ut_ad(mutex_own(&kernel_mutex)); 04912 #endif /* UNIV_SYNC_DEBUG */ 04913 ut_ad(page_rec_is_user_rec(rec)); 04914 ut_ad(rec_offs_validate(rec, index, offsets)); 04915 ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets)); 04916 04917 if (index->type & DICT_CLUSTERED) { 04918 impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets); 04919 } else { 04920 impl_trx = lock_sec_rec_some_has_impl_off_kernel( 04921 rec, index, offsets); 04922 } 04923 04924 if (impl_trx) { 04925 /* If the transaction has no explicit x-lock set on the 04926 record, set one for it */ 04927 04928 if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec, 04929 impl_trx)) { 04930 04931 lock_rec_add_to_queue(LOCK_REC | LOCK_X 04932 | LOCK_REC_NOT_GAP, rec, index, impl_trx); 04933 } 04934 } 04935 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static lock_t* lock_rec_copy | ( | lock_t * | lock, | |
| mem_heap_t * | heap | |||
| ) | [static] |
Definition at line 1378 of file lock0lock.c.
References lock, lock_get_type(), LOCK_REC, lock_rec_get_n_bits(), mem_heap_alloc(), ut_ad, and ut_memcpy().
Referenced by lock_move_reorganize_page().
01380 : copy of lock */ 01381 lock_t* lock, /* in: record lock */ 01382 mem_heap_t* heap) /* in: memory heap */ 01383 { 01384 lock_t* dupl_lock; 01385 ulint size; 01386 01387 ut_ad(lock_get_type(lock) == LOCK_REC); 01388 01389 size = sizeof(lock_t) + lock_rec_get_n_bits(lock) / 8; 01390 01391 dupl_lock = mem_heap_alloc(heap, size); 01392 01393 ut_memcpy(dupl_lock, lock, size); 01394 01395 return(dupl_lock); 01396 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static lock_t* lock_rec_create | ( | ulint | type_mode, | |
| rec_t * | rec, | |||
| dict_index_t * | index, | |||
| trx_t * | trx | |||
| ) | [static] |
Definition at line 1742 of file lock0lock.c.
References buf_frame_align(), buf_frame_get_page_no(), buf_frame_get_space_id(), dict_table_is_comp(), hash(), HASH_INSERT, index(), kernel_mutex, lock, LOCK_GAP, trx_struct::lock_heap, LOCK_PAGE_BITMAP_MARGIN, LOCK_REC, lock_rec_bitmap_reset(), lock_rec_fold(), LOCK_REC_NOT_GAP, lock_rec_set_nth_bit(), lock_set_lock_and_trx_wait(), lock_sys, LOCK_TYPE_MASK, LOCK_WAIT, mem_heap_alloc(), page, page_dir_get_n_heap(), page_get_supremum_rec(), page_is_comp(), page_t, rec_get_heap_no(), lock_sys_struct::rec_hash, trx_struct::trx_locks, ut_ad, and UT_LIST_ADD_LAST.
Referenced by lock_rec_add_to_queue(), lock_rec_enqueue_waiting(), and lock_rec_lock_fast().
01744 : created lock */ 01745 ulint type_mode,/* in: lock mode and wait flag, type is 01746 ignored and replaced by LOCK_REC */ 01747 rec_t* rec, /* in: record on page */ 01748 dict_index_t* index, /* in: index of record */ 01749 trx_t* trx) /* in: transaction */ 01750 { 01751 page_t* page; 01752 lock_t* lock; 01753 ulint page_no; 01754 ulint heap_no; 01755 ulint space; 01756 ulint n_bits; 01757 ulint n_bytes; 01758 01759 #ifdef UNIV_SYNC_DEBUG 01760 ut_ad(mutex_own(&kernel_mutex)); 01761 #endif /* UNIV_SYNC_DEBUG */ 01762 01763 page = buf_frame_align(rec); 01764 space = buf_frame_get_space_id(page); 01765 page_no = buf_frame_get_page_no(page); 01766 heap_no = rec_get_heap_no(rec, page_is_comp(page)); 01767 01768 ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table)); 01769 01770 /* If rec is the supremum record, then we reset the gap and 01771 LOCK_REC_NOT_GAP bits, as all locks on the supremum are 01772 automatically of the gap type */ 01773 01774 if (rec == page_get_supremum_rec(page)) { 01775 ut_ad(!(type_mode & LOCK_REC_NOT_GAP)); 01776 01777 type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP); 01778 } 01779 01780 /* Make lock bitmap bigger by a safety margin */ 01781 n_bits = page_dir_get_n_heap(page) + LOCK_PAGE_BITMAP_MARGIN; 01782 n_bytes = 1 + n_bits / 8; 01783 01784 lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t) + n_bytes); 01785 01786 UT_LIST_ADD_LAST(trx_locks, trx->trx_locks, lock); 01787 01788 lock->trx = trx; 01789 01790 lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC; 01791 lock->index = index; 01792 01793 lock->un_member.rec_lock.space = space; 01794 lock->un_member.rec_lock.page_no = page_no; 01795 lock->un_member.rec_lock.n_bits = n_bytes * 8; 01796 01797 /* Reset to zero the bitmap which resides immediately after the 01798 lock struct */ 01799 01800 lock_rec_bitmap_reset(lock); 01801 01802 /* Set the bit corresponding to rec */ 01803 lock_rec_set_nth_bit(lock, heap_no); 01804 01805 HASH_INSERT(lock_t, hash, lock_sys->rec_hash, 01806 lock_rec_fold(space, page_no), lock); 01807 if (type_mode & LOCK_WAIT) { 01808 01809 lock_set_lock_and_trx_wait(lock, trx); 01810 } 01811 01812 return(lock); 01813 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void lock_rec_dequeue_from_page | ( | lock_t * | in_lock | ) | [static] |
Definition at line 2315 of file lock0lock.c.
References hash(), HASH_DELETE, kernel_mutex, lock, lock_get_type(), lock_get_wait(), lock_grant(), LOCK_REC, lock_rec_fold(), lock_rec_get_first_on_page_addr(), lock_rec_get_next_on_page(), lock_rec_has_to_wait_in_queue(), lock_sys, NULL, lock_rec_struct::page_no, lock_sys_struct::rec_hash, lock_struct::rec_lock, lock_rec_struct::space, lock_struct::trx, trx_struct::trx_locks, lock_struct::un_member, ut_ad, and UT_LIST_REMOVE.
Referenced by lock_cancel_waiting_and_release(), and lock_release_off_kernel().
02317 : record lock object: all record locks which 02318 are contained in this lock object are removed; 02319 transactions waiting behind will get their lock 02320 requests granted, if they are now qualified to it */ 02321 { 02322 ulint space; 02323 ulint page_no; 02324 lock_t* lock; 02325 trx_t* trx; 02326 02327 #ifdef UNIV_SYNC_DEBUG 02328 ut_ad(mutex_own(&kernel_mutex)); 02329 #endif /* UNIV_SYNC_DEBUG */ 02330 ut_ad(lock_get_type(in_lock) == LOCK_REC); 02331 02332 trx = in_lock->trx; 02333 02334 space = in_lock->un_member.rec_lock.space; 02335 page_no = in_lock->un_member.rec_lock.page_no; 02336 02337 HASH_DELETE(lock_t, hash, lock_sys->rec_hash, 02338 lock_rec_fold(space, page_no), in_lock); 02339 02340 UT_LIST_REMOVE(trx_locks, trx->trx_locks, in_lock); 02341 02342 /* Check if waiting locks in the queue can now be granted: grant 02343 locks if there are no conflicting locks ahead. */ 02344 02345 lock = lock_rec_get_first_on_page_addr(space, page_no); 02346 02347 while (lock != NULL) { 02348 if (lock_get_wait(lock) 02349 && !lock_rec_has_to_wait_in_queue(lock)) { 02350 02351 /* Grant the lock */ 02352 lock_grant(lock); 02353 } 02354 02355 lock = lock_rec_get_next_on_page(lock); 02356 } 02357 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void lock_rec_discard | ( | lock_t * | in_lock | ) | [static] |
Definition at line 2363 of file lock0lock.c.
References hash(), HASH_DELETE, kernel_mutex, lock_get_type(), LOCK_REC, lock_rec_fold(), lock_sys, lock_rec_struct::page_no, lock_sys_struct::rec_hash, lock_struct::rec_lock, lock_rec_struct::space, lock_struct::trx, trx_struct::trx_locks, lock_struct::un_member, ut_ad, and UT_LIST_REMOVE.
Referenced by lock_rec_free_all_from_discard_page(), and lock_reset_all_on_table_for_trx().
02365 : record lock object: all record locks which 02366 are contained in this lock object are removed */ 02367 { 02368 ulint space; 02369 ulint page_no; 02370 trx_t* trx; 02371 02372 #ifdef UNIV_SYNC_DEBUG 02373 ut_ad(mutex_own(&kernel_mutex)); 02374 #endif /* UNIV_SYNC_DEBUG */ 02375 ut_ad(lock_get_type(in_lock) == LOCK_REC); 02376 02377 trx = in_lock->trx; 02378 02379 space = in_lock->un_member.rec_lock.space; 02380 page_no = in_lock->un_member.rec_lock.page_no; 02381 02382 HASH_DELETE(lock_t, hash, lock_sys->rec_hash, 02383 lock_rec_fold(space, page_no), in_lock); 02384 02385 UT_LIST_REMOVE(trx_locks, trx->trx_locks, in_lock); 02386 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint lock_rec_enqueue_waiting | ( | ulint | type_mode, | |
| rec_t * | rec, | |||
| dict_index_t * | index, | |||
| que_thr_t * | thr | |||
| ) | [static] |
Definition at line 1820 of file lock0lock.c.
References DB_DEADLOCK, DB_LOCK_WAIT, DB_QUE_THR_SUSPENDED, DB_SUCCESS, trx_struct::dict_operation, FALSE, trx_struct::id, index(), kernel_mutex, lock, lock_deadlock_occurs(), lock_rec_create(), lock_rec_reset_nth_bit(), lock_reset_lock_and_trx_wait(), LOCK_WAIT, NULL, page_rec_is_comp(), trx_struct::que_state, que_thr_stop(), rec_get_heap_no(), thr_get_trx(), TRUE, TRX_QUE_LOCK_WAIT, ut_a, ut_ad, ut_dulint_get_low(), ut_error, ut_print_name(), ut_print_timestamp(), trx_struct::wait_lock, trx_struct::wait_started, and trx_struct::was_chosen_as_deadlock_victim.
Referenced by lock_rec_insert_check_and_lock(), and lock_rec_lock_slow().
01822 : DB_LOCK_WAIT, DB_DEADLOCK, or 01823 DB_QUE_THR_SUSPENDED, or DB_SUCCESS; 01824 DB_SUCCESS means that there was a deadlock, 01825 but another transaction was chosen as a 01826 victim, and we got the lock immediately: 01827 no need to wait then */ 01828 ulint type_mode,/* in: lock mode this transaction is 01829 requesting: LOCK_S or LOCK_X, possibly ORed 01830 with LOCK_GAP or LOCK_REC_NOT_GAP, ORed 01831 with LOCK_INSERT_INTENTION if this waiting 01832 lock request is set when performing an 01833 insert of an index record */ 01834 rec_t* rec, /* in: record */ 01835 dict_index_t* index, /* in: index of record */ 01836 que_thr_t* thr) /* in: query thread */ 01837 { 01838 lock_t* lock; 01839 trx_t* trx; 01840 01841 #ifdef UNIV_SYNC_DEBUG 01842 ut_ad(mutex_own(&kernel_mutex)); 01843 #endif /* UNIV_SYNC_DEBUG */ 01844 01845 /* Test if there already is some other reason to suspend thread: 01846 we do not enqueue a lock request if the query thread should be 01847 stopped anyway */ 01848 01849 if (que_thr_stop(thr)) { 01850 01851 ut_error; 01852 01853 return(DB_QUE_THR_SUSPENDED); 01854 } 01855 01856 trx = thr_get_trx(thr); 01857 01858 if (trx->dict_operation) { 01859 ut_print_timestamp(stderr); 01860 fputs( 01861 " InnoDB: Error: a record lock wait happens in a dictionary operation!\n" 01862 "InnoDB: Table name ", stderr); 01863 ut_print_name(stderr, trx, TRUE, index->table_name); 01864 fputs(".\n" 01865 "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", 01866 stderr); 01867 } 01868 01869 /* Enqueue the lock request that will wait to be granted */ 01870 lock = lock_rec_create(type_mode | LOCK_WAIT, rec, index, trx); 01871 01872 /* Check if a deadlock occurs: if yes, remove the lock request and 01873 return an error code */ 01874 01875 if (lock_deadlock_occurs(lock, trx)) { 01876 01877 lock_reset_lock_and_trx_wait(lock); 01878 lock_rec_reset_nth_bit(lock, rec_get_heap_no(rec, 01879 page_rec_is_comp(rec))); 01880 01881 return(DB_DEADLOCK); 01882 } 01883 01884 /* If there was a deadlock but we chose another transaction as a 01885 victim, it is possible that we already have the lock now granted! */ 01886 01887 if (trx->wait_lock == NULL) { 01888 01889 return(DB_SUCCESS); 01890 } 01891 01892 trx->que_state = TRX_QUE_LOCK_WAIT; 01893 trx->was_chosen_as_deadlock_victim = FALSE; 01894 trx->wait_started = time(NULL); 01895 01896 ut_a(que_thr_stop(thr)); 01897 01898 #ifdef UNIV_DEBUG 01899 if (lock_print_waits) { 01900 fprintf(stderr, "Lock wait for trx %lu in index ", 01901 (ulong) ut_dulint_get_low(trx->id)); 01902 ut_print_name(stderr, trx, FALSE, index->name); 01903 } 01904 #endif /* UNIV_DEBUG */ 01905 01906 return(DB_LOCK_WAIT); 01907 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1224 of file lock0lock.c.
References FALSE, kernel_mutex, lock_rec_get_first_on_page_addr(), mutex_enter, mutex_exit(), and TRUE.
Referenced by ibuf_insert_low().
01226 : TRUE if there are explicit record locks on 01227 the page */ 01228 ulint space, /* in: space id */ 01229 ulint page_no)/* in: page number */ 01230 { 01231 ibool ret; 01232 01233 mutex_enter(&kernel_mutex); 01234 01235 if (lock_rec_get_first_on_page_addr(space, page_no)) { 01236 ret = TRUE; 01237 } else { 01238 ret = FALSE; 01239 } 01240 01241 mutex_exit(&kernel_mutex); 01242 01243 return(ret); 01244 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1100 of file lock0lock.c.
References lock, lock_rec_get_n_bits(), and lock_rec_get_nth_bit().
Referenced by lock_deadlock_recursive(), lock_rec_cancel(), lock_rec_free_all_from_discard_page(), and lock_rec_has_to_wait_in_queue().
01102 : bit index == heap number of the record, or 01103 ULINT_UNDEFINED if none found */ 01104 lock_t* lock) /* in: record lock with at least one bit set */ 01105 { 01106 ulint i; 01107 01108 for (i = 0; i < lock_rec_get_n_bits(lock); i++) { 01109 01110 if (lock_rec_get_nth_bit(lock, i)) { 01111 01112 return(i); 01113 } 01114 } 01115 01116 return(ULINT_UNDEFINED); 01117 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1618 of file lock0lock.c.
References kernel_mutex, lock, lock_rec_get_first_on_page(), lock_rec_get_n_bits(), lock_rec_get_next_on_page(), NULL, page_rec_is_comp(), rec_get_heap_no(), and ut_ad.
Referenced by lock_rec_add_to_queue().
01620 : lock or NULL */ 01621 ulint type_mode, /* in: lock type_mode field */ 01622 rec_t* rec, /* in: record */ 01623 trx_t* trx) /* in: transaction */ 01624 { 01625 lock_t* lock; 01626 ulint heap_no; 01627 01628 #ifdef UNIV_SYNC_DEBUG 01629 ut_ad(mutex_own(&kernel_mutex)); 01630 #endif /* UNIV_SYNC_DEBUG */ 01631 01632 heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec)); 01633 lock = lock_rec_get_first_on_page(rec); 01634 01635 while (lock != NULL) { 01636 if (lock->trx == trx 01637 && lock->type_mode == type_mode 01638 && lock_rec_get_n_bits(lock) > heap_no) { 01639 01640 return(lock); 01641 } 01642 01643 lock = lock_rec_get_next_on_page(lock); 01644 } 01645 01646 return(NULL); 01647 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void lock_rec_free_all_from_discard_page | ( | page_t * | page | ) | [static] |
Definition at line 2394 of file lock0lock.c.
References buf_frame_get_page_no(), buf_frame_get_space_id(), kernel_mutex, lock, lock_get_wait(), lock_rec_discard(), lock_rec_find_set_bit(), lock_rec_get_first_on_page_addr(), lock_rec_get_next_on_page(), NULL, and ut_ad.
Referenced by lock_update_copy_and_discard(), lock_update_discard(), lock_update_merge_left(), and lock_update_merge_right().
02396 : page to be discarded */ 02397 { 02398 ulint space; 02399 ulint page_no; 02400 lock_t* lock; 02401 lock_t* next_lock; 02402 02403 #ifdef UNIV_SYNC_DEBUG 02404 ut_ad(mutex_own(&kernel_mutex)); 02405 #endif /* UNIV_SYNC_DEBUG */ 02406 02407 space = buf_frame_get_space_id(page); 02408 page_no = buf_frame_get_page_no(page); 02409 02410 lock = lock_rec_get_first_on_page_addr(space, page_no); 02411 02412 while (lock != NULL) { 02413 ut_ad(lock_rec_find_set_bit(lock) == ULINT_UNDEFINED); 02414 ut_ad(!lock_get_wait(lock)); 02415 02416 next_lock = lock_rec_get_next_on_page(lock); 02417 02418 lock_rec_discard(lock); 02419 02420 lock = next_lock; 02421 } 02422 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1319 of file lock0lock.c.
References kernel_mutex, lock, lock_rec_get_first_on_page(), lock_rec_get_next_on_page(), lock_rec_get_nth_bit(), page_rec_is_comp(), rec_get_heap_no(), and ut_ad.
Referenced by lock_rec_has_expl(), lock_rec_inherit_to_gap(), lock_rec_inherit_to_gap_if_gap_lock(), lock_rec_insert_check_and_lock(), lock_rec_move(), lock_rec_other_has_conflicting(), lock_rec_other_has_expl_req(), lock_rec_queue_validate(), lock_rec_reset_and_release_wait(), and lock_rec_unlock().
01321 : first lock, NULL if none exists */ 01322 rec_t* rec) /* in: record on a page */ 01323 { 01324 lock_t* lock; 01325 01326 #ifdef UNIV_SYNC_DEBUG 01327 ut_ad(mutex_own(&kernel_mutex)); 01328 #endif /* UNIV_SYNC_DEBUG */ 01329 01330 lock = lock_rec_get_first_on_page(rec); 01331 if (UNIV_LIKELY_NULL(lock)) { 01332 ulint heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec)); 01333 01334 while (lock && !lock_rec_get_nth_bit(lock, heap_no)) { 01335 lock = lock_rec_get_next_on_page(lock); 01336 } 01337 } 01338 01339 return(lock); 01340 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1251 of file lock0lock.c.
References buf_frame_get_lock_hash_val(), buf_frame_get_page_no(), buf_frame_get_space_id(), hash(), HASH_GET_FIRST, HASH_GET_NEXT, kernel_mutex, lock, lock_sys, lock_sys_struct::rec_hash, and ut_ad.
Referenced by lock_move_rec_list_end(), lock_move_rec_list_start(), lock_move_reorganize_page(), lock_rec_add_to_queue(), lock_rec_find_similar_on_page(), lock_rec_get_first(), lock_rec_lock_fast(), and lock_update_discard().
01253 : first lock, NULL if none exists */ 01254 byte* ptr) /* in: pointer to somewhere on the page */ 01255 { 01256 ulint hash; 01257 lock_t* lock; 01258 ulint space; 01259 ulint page_no; 01260 01261 #ifdef UNIV_SYNC_DEBUG 01262 ut_ad(mutex_own(&kernel_mutex)); 01263 #endif /* UNIV_SYNC_DEBUG */ 01264 01265 hash = buf_frame_get_lock_hash_val(ptr); 01266 01267 lock = HASH_GET_FIRST(lock_sys->rec_hash, hash); 01268 01269 while (lock) { 01270 space = buf_frame_get_space_id(ptr); 01271 page_no = buf_frame_get_page_no(ptr); 01272 01273 if ((lock->un_member.rec_lock.space == space) 01274 && (lock->un_member.rec_lock.page_no == page_no)) { 01275 01276 break; 01277 } 01278 01279 lock = HASH_GET_NEXT(hash, lock); 01280 } 01281 01282 return(lock); 01283 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1193 of file lock0lock.c.
References hash(), HASH_GET_FIRST, HASH_GET_NEXT, kernel_mutex, lock, lock_rec_hash(), lock_sys, lock_sys_struct::rec_hash, and ut_ad.
Referenced by lock_rec_dequeue_from_page(), lock_rec_expl_exist_on_page(), lock_rec_free_all_from_discard_page(), lock_rec_get_prev(), lock_rec_has_to_wait_in_queue(), and lock_rec_validate_page().
01195 : first lock, NULL if none exists */ 01196 ulint space, /* in: space */ 01197 ulint page_no)/* in: page number */ 01198 { 01199 lock_t* lock; 01200 01201 #ifdef UNIV_SYNC_DEBUG 01202 ut_ad(mutex_own(&kernel_mutex)); 01203 #endif /* UNIV_SYNC_DEBUG */ 01204 01205 lock = HASH_GET_FIRST(lock_sys->rec_hash, 01206 lock_rec_hash(space, page_no)); 01207 while (lock) { 01208 if ((lock->un_member.rec_lock.space == space) 01209 && (lock->un_member.rec_lock.page_no == page_no)) { 01210 01211 break; 01212 } 01213 01214 lock = HASH_GET_NEXT(hash, lock); 01215 } 01216 01217 return(lock); 01218 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE ibool lock_rec_get_gap | ( | lock_t * | lock | ) |
Definition at line 799 of file lock0lock.c.
References FALSE, lock, LOCK_GAP, lock_get_type(), LOCK_REC, TRUE, and ut_ad.
Referenced by lock_rec_has_expl(), lock_rec_has_to_wait(), lock_rec_other_has_expl_req(), lock_rec_print(), and lock_rec_queue_validate().
00801 : TRUE if gap flag set */ 00802 lock_t* lock) /* in: record lock */ 00803 { 00804 ut_ad(lock); 00805 ut_ad(lock_get_type(lock) == LOCK_REC); 00806 00807 if (lock->type_mode & LOCK_GAP) { 00808 00809 return(TRUE); 00810 } 00811 00812 return(FALSE); 00813 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE ibool lock_rec_get_insert_intention | ( | lock_t * | lock | ) |
Definition at line 839 of file lock0lock.c.
References FALSE, lock, lock_get_type(), LOCK_INSERT_INTENTION, LOCK_REC, TRUE, and ut_ad.
Referenced by lock_rec_has_expl(), lock_rec_has_to_wait(), lock_rec_inherit_to_gap(), lock_rec_inherit_to_gap_if_gap_lock(), and lock_rec_print().
00841 : TRUE if gap flag set */ 00842 lock_t* lock) /* in: record lock */ 00843 { 00844 ut_ad(lock); 00845 ut_ad(lock_get_type(lock) == LOCK_REC); 00846 00847 if (lock->type_mode & LOCK_INSERT_INTENTION) { 00848 00849 return(TRUE); 00850 } 00851 00852 return(FALSE); 00853 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1057 of file lock0lock.c.
References lock.
Referenced by lock_number_of_rows_locked(), lock_rec_bitmap_reset(), lock_rec_copy(), lock_rec_find_set_bit(), lock_rec_find_similar_on_page(), lock_rec_lock_fast(), lock_rec_print(), and lock_rec_validate_page().
01059 : number of bits */ 01060 lock_t* lock) /* in: record lock */ 01061 { 01062 return(lock->un_member.rec_lock.n_bits); 01063 }
Here is the caller graph for this function:

Definition at line 1289 of file lock0lock.c.
References FALSE, kernel_mutex, lock, lock_get_type(), LOCK_REC, lock_rec_get_next_on_page(), lock_rec_get_nth_bit(), page_rec_is_comp(), rec_get_heap_no(), TRUE, and ut_ad.
Referenced by lock_rec_has_expl(), lock_rec_inherit_to_gap(), lock_rec_inherit_to_gap_if_gap_lock(), lock_rec_move(), lock_rec_other_has_conflicting(), lock_rec_other_has_expl_req(), lock_rec_queue_validate(), lock_rec_reset_and_release_wait(), and lock_rec_unlock().
01291 : next lock, NULL if none exists */ 01292 rec_t* rec, /* in: record on a page */ 01293 lock_t* lock) /* in: lock */ 01294 { 01295 #ifdef UNIV_SYNC_DEBUG 01296 ut_ad(mutex_own(&kernel_mutex)); 01297 #endif /* UNIV_SYNC_DEBUG */ 01298 ut_ad(lock_get_type(lock) == LOCK_REC); 01299 01300 if (page_rec_is_comp(rec)) { 01301 do { 01302 lock = lock_rec_get_next_on_page(lock); 01303 } while (lock && !lock_rec_get_nth_bit(lock, 01304 rec_get_heap_no(rec, TRUE))); 01305 } else { 01306 do { 01307 lock = lock_rec_get_next_on_page(lock); 01308 } while (lock && !lock_rec_get_nth_bit(lock, 01309 rec_get_heap_no(rec, FALSE))); 01310 } 01311 01312 return(lock); 01313 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1154 of file lock0lock.c.
References hash(), HASH_GET_NEXT, kernel_mutex, lock, lock_get_type(), LOCK_REC, and ut_ad.
Referenced by lock_move_rec_list_end(), lock_move_rec_list_start(), lock_move_reorganize_page(), lock_rec_add_to_queue(), lock_rec_dequeue_from_page(), lock_rec_find_similar_on_page(), lock_rec_free_all_from_discard_page(), lock_rec_get_first(), lock_rec_get_next(), lock_rec_get_prev(), lock_rec_has_to_wait_in_queue(), lock_rec_lock_fast(), and lock_rec_validate_page().
01156 : next lock, NULL if none exists */ 01157 lock_t* lock) /* in: a record lock */ 01158 { 01159 ulint space; 01160 ulint page_no; 01161 01162 #ifdef UNIV_SYNC_DEBUG 01163 ut_ad(mutex_own(&kernel_mutex)); 01164 #endif /* UNIV_SYNC_DEBUG */ 01165 ut_ad(lock_get_type(lock) == LOCK_REC); 01166 01167 space = lock->un_member.rec_lock.space; 01168 page_no = lock->un_member.rec_lock.page_no; 01169 01170 for (;;) { 01171 lock = HASH_GET_NEXT(hash, lock); 01172 01173 if (!lock) { 01174 01175 break; 01176 } 01177 01178 if ((lock->un_member.rec_lock.space == space) 01179 && (lock->un_member.rec_lock.page_no == page_no)) { 01180 01181 break; 01182 } 01183 } 01184 01185 return(lock); 01186 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 421 of file lock0lock.c.
References FALSE, lock, lock_get_type(), LOCK_REC, ut_ad, and ut_bit_get_nth().
Referenced by lock_has_to_wait(), lock_move_rec_list_end(), lock_move_rec_list_start(), lock_move_reorganize_page(), lock_number_of_rows_locked(), lock_rec_add_to_queue(), lock_rec_find_set_bit(), lock_rec_get_first(), lock_rec_get_next(), lock_rec_get_prev(), lock_rec_has_to_wait_in_queue(), lock_rec_lock_fast(), lock_rec_print(), and lock_rec_validate_page().
00423 : TRUE if bit set */ 00424 lock_t* lock, /* in: record lock */ 00425 ulint i) /* in: index of the bit */ 00426 { 00427 ulint byte_index; 00428 ulint bit_index; 00429 ulint b; 00430 00431 ut_ad(lock); 00432 ut_ad(lock_get_type(lock) == LOCK_REC); 00433 00434 if (i >= lock->un_member.rec_lock.n_bits) { 00435 00436 return(FALSE); 00437 } 00438 00439 byte_index = i / 8; 00440 bit_index = i % 8; 00441 00442 b = (ulint)*((byte*)lock + sizeof(lock_t) + byte_index); 00443 00444 return(ut_bit_get_nth(b, bit_index)); 00445 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1402 of file lock0lock.c.
References kernel_mutex, lock, lock_get_type(), LOCK_REC, lock_rec_get_first_on_page_addr(), lock_rec_get_next_on_page(), lock_rec_get_nth_bit(), NULL, lock_rec_struct::page_no, lock_struct::rec_lock, lock_rec_struct::space, lock_struct::un_member, and ut_ad.
Referenced by lock_deadlock_recursive().
01404 : previous lock on the same record, NULL if 01405 none exists */ 01406 lock_t* in_lock,/* in: record lock */ 01407 ulint heap_no)/* in: heap number of the record */ 01408 { 01409 lock_t* lock; 01410 ulint space; 01411 ulint page_no; 01412 lock_t* found_lock = NULL; 01413 01414 #ifdef UNIV_SYNC_DEBUG 01415 ut_ad(mutex_own(&kernel_mutex)); 01416 #endif /* UNIV_SYNC_DEBUG */ 01417 ut_ad(lock_get_type(in_lock) == LOCK_REC); 01418 01419 space = in_lock->un_member.rec_lock.space; 01420 page_no = in_lock->un_member.rec_lock.page_no; 01421 01422 lock = lock_rec_get_first_on_page_addr(space, page_no); 01423 01424 for (;;) { 01425 ut_ad(lock); 01426 01427 if (lock == in_lock) { 01428 01429 return(found_lock); 01430 } 01431 01432 if (lock_rec_get_nth_bit(lock, heap_no)) { 01433 01434 found_lock = lock; 01435 } 01436 01437 lock = lock_rec_get_next_on_page(lock); 01438 } 01439 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE ibool lock_rec_get_rec_not_gap | ( | lock_t * | lock | ) |
Definition at line 819 of file lock0lock.c.
References FALSE, lock, lock_get_type(), LOCK_REC, LOCK_REC_NOT_GAP, TRUE, and ut_ad.
Referenced by lock_rec_has_expl(), lock_rec_has_to_wait(), lock_rec_inherit_to_gap_if_gap_lock(), and lock_rec_print().
00821 : TRUE if LOCK_REC_NOT_GAP flag set */ 00822 lock_t* lock) /* in: record lock */ 00823 { 00824 ut_ad(lock); 00825 ut_ad(lock_get_type(lock) == LOCK_REC); 00826 00827 if (lock->type_mode & LOCK_REC_NOT_GAP) { 00828 00829 return(TRUE); 00830 } 00831 00832 return(FALSE); 00833 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1490 of file lock0lock.c.
References kernel_mutex, lock, LOCK_GAP, lock_get_mode(), lock_get_wait(), LOCK_INSERT_INTENTION, LOCK_MODE_MASK, lock_mode_stronger_or_eq(), lock_rec_get_first(), lock_rec_get_gap(), lock_rec_get_insert_intention(), lock_rec_get_next(), lock_rec_get_rec_not_gap(), LOCK_REC_NOT_GAP, LOCK_S, LOCK_X, NULL, page_rec_is_supremum(), and ut_ad.
Referenced by lock_rec_convert_impl_to_expl(), lock_rec_lock_slow(), and lock_rec_queue_validate().
01492 : lock or NULL */ 01493 ulint precise_mode,/* in: LOCK_S or LOCK_X possibly ORed to 01494 LOCK_GAP or LOCK_REC_NOT_GAP, 01495 for a supremum record we regard this always a gap 01496 type request */ 01497 rec_t* rec, /* in: record */ 01498 trx_t* trx) /* in: transaction */ 01499 { 01500 lock_t* lock; 01501 01502 #ifdef UNIV_SYNC_DEBUG 01503 ut_ad(mutex_own(&kernel_mutex)); 01504 #endif /* UNIV_SYNC_DEBUG */ 01505 ut_ad((precise_mode & LOCK_MODE_MASK) == LOCK_S 01506 || (precise_mode & LOCK_MODE_MASK) == LOCK_X); 01507 ut_ad(!(precise_mode & LOCK_INSERT_INTENTION)); 01508 01509 lock = lock_rec_get_first(rec); 01510 01511 while (lock) { 01512 if (lock->trx == trx 01513 && lock_mode_stronger_or_eq(lock_get_mode(lock), 01514 precise_mode & LOCK_MODE_MASK) 01515 && !lock_get_wait(lock) 01516 && (!lock_rec_get_rec_not_gap(lock) 01517 || (precise_mode & LOCK_REC_NOT_GAP) 01518 || page_rec_is_supremum(rec)) 01519 && (!lock_rec_get_gap(lock) 01520 || (precise_mode & LOCK_GAP) 01521 || page_rec_is_supremum(rec)) 01522 && (!lock_rec_get_insert_intention(lock))) { 01523 01524 return(lock); 01525 } 01526 01527 lock = lock_rec_get_next(rec, lock); 01528 } 01529 01530 return(NULL); 01531 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE ibool lock_rec_has_to_wait | ( | trx_t * | trx, | |
| ulint | type_mode, | |||
| lock_t * | lock2, | |||
| ibool | lock_is_on_supremum | |||
| ) |
Definition at line 939 of file lock0lock.c.
References FALSE, LOCK_GAP, lock_get_mode(), lock_get_type(), LOCK_INSERT_INTENTION, lock_mode_compatible(), LOCK_MODE_MASK, LOCK_REC, lock_rec_get_gap(), lock_rec_get_insert_intention(), lock_rec_get_rec_not_gap(), TRUE, lock_struct::trx, and ut_ad.
Referenced by lock_has_to_wait(), and lock_rec_other_has_conflicting().
00941 : TRUE if new lock has to wait for lock2 to be 00942 removed */ 00943 trx_t* trx, /* in: trx of new lock */ 00944 ulint type_mode,/* in: precise mode of the new lock to set: 00945 LOCK_S or LOCK_X, possibly ORed to 00946 LOCK_GAP or LOCK_REC_NOT_GAP, LOCK_INSERT_INTENTION */ 00947 lock_t* lock2, /* in: another record lock; NOTE that it is assumed 00948 that this has a lock bit set on the same record as 00949 in the new lock we are setting */ 00950 ibool lock_is_on_supremum) /* in: TRUE if we are setting the lock 00951 on the 'supremum' record of an index 00952 page: we know then that the lock request 00953 is really for a 'gap' type lock */ 00954 { 00955 ut_ad(trx && lock2); 00956 ut_ad(lock_get_type(lock2) == LOCK_REC); 00957 00958 if (trx != lock2->trx 00959 && !lock_mode_compatible(LOCK_MODE_MASK & type_mode, 00960 lock_get_mode(lock2))) { 00961 00962 /* We have somewhat complex rules when gap type record locks 00963 cause waits */ 00964 00965 if ((lock_is_on_supremum || (type_mode & LOCK_GAP)) 00966 && !(type_mode & LOCK_INSERT_INTENTION)) { 00967 00968 /* Gap type locks without LOCK_INSERT_INTENTION flag 00969 do not need to wait for anything. This is because 00970 different users can have conflicting lock types 00971 on gaps. */ 00972 00973 return(FALSE); 00974 } 00975 00976 if (!(type_mode & LOCK_INSERT_INTENTION) 00977 && lock_rec_get_gap(lock2)) { 00978 00979 /* Record lock (LOCK_ORDINARY or LOCK_REC_NOT_GAP 00980 does not need to wait for a gap type lock */ 00981 00982 return(FALSE); 00983 } 00984 00985 if ((type_mode & LOCK_GAP) 00986 && lock_rec_get_rec_not_gap(lock2)) { 00987 00988 /* Lock on gap does not need to wait for 00989 a LOCK_REC_NOT_GAP type lock */ 00990 00991 return(FALSE); 00992 } 00993 00994 if (lock_rec_get_insert_intention(lock2)) { 00995 00996 /* No lock request needs to wait for an insert 00997 intention lock to be removed. This is ok since our 00998 rules allow conflicting locks on gaps. This eliminates 00999 a spurious deadlock caused by a next-key lock waiting 01000 for an insert intention lock; when the insert 01001 intention lock was granted, the insert deadlocked on 01002 the waiting next-key lock. 01003 01004 Also, insert intention locks do not disturb each 01005 other. */ 01006 01007 return(FALSE); 01008 } 01009 01010 return(TRUE); 01011 } 01012 01013 return(FALSE); 01014 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ibool lock_rec_has_to_wait_in_queue | ( | lock_t * | wait_lock | ) | [static] |
Definition at line 2201 of file lock0lock.c.
References FALSE, kernel_mutex, lock, lock_get_type(), lock_get_wait(), lock_has_to_wait(), LOCK_REC, lock_rec_find_set_bit(), lock_rec_get_first_on_page_addr(), lock_rec_get_next_on_page(), lock_rec_get_nth_bit(), lock_rec_struct::page_no, lock_struct::rec_lock, lock_rec_struct::space, TRUE, lock_struct::un_member, and ut_ad.
Referenced by lock_rec_dequeue_from_page(), lock_rec_queue_validate(), and lock_rec_unlock().
02203 : TRUE if still has to wait */ 02204 lock_t* wait_lock) /* in: waiting record lock */ 02205 { 02206 lock_t* lock; 02207 ulint space; 02208 ulint page_no; 02209 ulint heap_no; 02210 02211 #ifdef UNIV_SYNC_DEBUG 02212 ut_ad(mutex_own(&kernel_mutex)); 02213 #endif /* UNIV_SYNC_DEBUG */ 02214 ut_ad(lock_get_wait(wait_lock)); 02215 ut_ad(lock_get_type(wait_lock) == LOCK_REC); 02216 02217 space = wait_lock->un_member.rec_lock.space; 02218 page_no = wait_lock->un_member.rec_lock.page_no; 02219 heap_no = lock_rec_find_set_bit(wait_lock); 02220 02221 lock = lock_rec_get_first_on_page_addr(space, page_no); 02222 02223 while (lock != wait_lock) { 02224 02225 if (lock_rec_get_nth_bit(lock, heap_no) 02226 && lock_has_to_wait(wait_lock, lock)) { 02227 02228 return(TRUE); 02229 } 02230 02231 lock = lock_rec_get_next_on_page(lock); 02232 } 02233 02234 return(FALSE); 02235 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2464 of file lock0lock.c.
References kernel_mutex, lock, LOCK_GAP, lock_get_mode(), LOCK_REC, lock_rec_add_to_queue(), lock_rec_get_first(), lock_rec_get_insert_intention(), lock_rec_get_next(), LOCK_X, NULL, srv_locks_unsafe_for_binlog, TRX_ISO_READ_COMMITTED, and ut_ad.
Referenced by lock_rec_reset_and_inherit_gap_locks(), lock_update_delete(), lock_update_discard(), lock_update_merge_left(), lock_update_merge_right(), lock_update_split_left(), and lock_update_split_right().
02466 : record which inherits */ 02467 rec_t* rec) /* in: record from which inherited; does NOT reset 02468 the locks on this record */ 02469 { 02470 lock_t* lock; 02471 #ifdef UNIV_SYNC_DEBUG 02472 ut_ad(mutex_own(&kernel_mutex)); 02473 #endif /* UNIV_SYNC_DEBUG */ 02474 02475 lock = lock_rec_get_first(rec); 02476 02477 /* If srv_locks_unsafe_for_binlog is TRUE or session is using 02478 READ COMMITTED isolation level, we do not want locks set 02479 by an UPDATE or a DELETE to be inherited as gap type locks. But we 02480 DO want S-locks set by a consistency constraint to be inherited also 02481 then. */ 02482 02483 while (lock != NULL) { 02484 if (!lock_rec_get_insert_intention(lock) 02485 && !((srv_locks_unsafe_for_binlog 02486 || lock->trx->isolation_level == 02487 TRX_ISO_READ_COMMITTED) 02488 && lock_get_mode(lock) == LOCK_X)) { 02489 02490 lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock) 02491 | LOCK_GAP, 02492 heir, lock->index, lock->trx); 02493 } 02494 02495 lock = lock_rec_get_next(rec, lock); 02496 } 02497 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2505 of file lock0lock.c.
References kernel_mutex, lock, LOCK_GAP, lock_get_mode(), LOCK_REC, lock_rec_add_to_queue(), lock_rec_get_first(), lock_rec_get_insert_intention(), lock_rec_get_next(), lock_rec_get_rec_not_gap(), NULL, page_rec_is_supremum(), and ut_ad.
Referenced by lock_update_insert().
02507 : record which inherits */ 02508 rec_t* rec) /* in: record from which inherited; does NOT reset 02509 the locks on this record */ 02510 { 02511 lock_t* lock; 02512 #ifdef UNIV_SYNC_DEBUG 02513 ut_ad(mutex_own(&kernel_mutex)); 02514 #endif /* UNIV_SYNC_DEBUG */ 02515 02516 lock = lock_rec_get_first(rec); 02517 02518 while (lock != NULL) { 02519 if (!lock_rec_get_insert_intention(lock) 02520 && (page_rec_is_supremum(rec) 02521 || !lock_rec_get_rec_not_gap(lock))) { 02522 02523 lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock) 02524 | LOCK_GAP, 02525 heir, lock->index, lock->trx); 02526 } 02527 02528 lock = lock_rec_get_next(rec, lock); 02529 } 02530 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint lock_rec_insert_check_and_lock | ( | ulint | flags, | |
| rec_t * | rec, | |||
| dict_index_t * | index, | |||
| que_thr_t * | thr, | |||
| ibool * | inherit | |||
| ) |
Definition at line 4794 of file lock0lock.c.
References BTR_NO_LOCKING_FLAG, buf_frame_align(), DB_SUCCESS, DICT_CLUSTERED, err, FALSE, index(), lock, LOCK_GAP, LOCK_INSERT_INTENTION, LOCK_IX, lock_mutex_enter_kernel, lock_mutex_exit_kernel, lock_rec_enqueue_waiting(), lock_rec_get_first(), lock_rec_other_has_conflicting(), lock_rec_queue_validate(), lock_table_has(), LOCK_X, mem_heap_free, NULL, page_rec_get_next(), page_update_max_trx_id(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, thr_get_trx(), TRUE, and ut_ad.
Referenced by btr_cur_ins_lock_and_undo().
04796 : DB_SUCCESS, DB_LOCK_WAIT, 04797 DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ 04798 ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, 04799 does nothing */ 04800 rec_t* rec, /* in: record after which to insert */ 04801 dict_index_t* index, /* in: index */ 04802 que_thr_t* thr, /* in: query thread */ 04803 ibool* inherit)/* out: set to TRUE if the new inserted 04804 record maybe should inherit LOCK_GAP type 04805 locks from the successor record */ 04806 { 04807 rec_t* next_rec; 04808 trx_t* trx; 04809 lock_t* lock; 04810 ulint err; 04811 04812 if (flags & BTR_NO_LOCKING_FLAG) { 04813 04814 return(DB_SUCCESS); 04815 } 04816 04817 ut_ad(rec); 04818 04819 trx = thr_get_trx(thr); 04820 next_rec = page_rec_get_next(rec); 04821 04822 *inherit = FALSE; 04823 04824 lock_mutex_enter_kernel(); 04825 04826 ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX)); 04827 04828 lock = lock_rec_get_first(next_rec); 04829 04830 if (lock == NULL) { 04831 /* We optimize CPU time usage in the simplest case */ 04832 04833 lock_mutex_exit_kernel(); 04834 04835 if (!(index->type & DICT_CLUSTERED)) { 04836 04837 /* Update the page max trx id field */ 04838 page_update_max_trx_id(buf_frame_align(rec), 04839 thr_get_trx(thr)->id); 04840 } 04841 04842 return(DB_SUCCESS); 04843 } 04844 04845 *inherit = TRUE; 04846 04847 /* If another transaction has an explicit lock request which locks 04848 the gap, waiting or granted, on the successor, the insert has to wait. 04849 04850 An exception is the case where the lock by the another transaction 04851 is a gap type lock which it placed to wait for its turn to insert. We 04852 do not consider that kind of a lock conflicting with our insert. This 04853 eliminates an unnecessary deadlock which resulted when 2 transactions 04854 had to wait for their insert. Both had waiting gap type lock requests 04855 on the successor, which produced an unnecessary deadlock. */ 04856 04857 if (lock_rec_other_has_conflicting(LOCK_X | LOCK_GAP 04858 | LOCK_INSERT_INTENTION, next_rec, trx)) { 04859 04860 /* Note that we may get DB_SUCCESS also here! */ 04861 err = lock_rec_enqueue_waiting(LOCK_X | LOCK_GAP 04862 | LOCK_INSERT_INTENTION, 04863 next_rec, index, thr); 04864 } else { 04865 err = DB_SUCCESS; 04866 } 04867 04868 lock_mutex_exit_kernel(); 04869 04870 if (!(index->type & DICT_CLUSTERED) && (err == DB_SUCCESS)) { 04871 04872 /* Update the page max trx id field */ 04873 page_update_max_trx_id(buf_frame_align(rec), 04874 thr_get_trx(thr)->id); 04875 } 04876 04877 #ifdef UNIV_DEBUG 04878 { 04879 mem_heap_t* heap = NULL; 04880 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 04881 const ulint* offsets; 04882 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 04883 04884 offsets = rec_get_offsets(next_rec, index, offsets_, 04885 ULINT_UNDEFINED, &heap); 04886 ut_ad(lock_rec_queue_validate(next_rec, index, offsets)); 04887 if (UNIV_LIKELY_NULL(heap)) { 04888 mem_heap_free(heap); 04889 } 04890 } 04891 #endif /* UNIV_DEBUG */ 04892 04893 return(err); 04894 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint lock_rec_lock | ( | ibool | impl, | |
| ulint | mode, | |||
| rec_t * | rec, | |||
| dict_index_t * | index, | |||
| que_thr_t * | thr | |||
| ) | [static] |
Definition at line 2156 of file lock0lock.c.
References DB_SUCCESS, err, index(), kernel_mutex, LOCK_GAP, LOCK_IS, LOCK_IX, LOCK_MODE_MASK, lock_rec_lock_fast(), lock_rec_lock_slow(), LOCK_REC_NOT_GAP, LOCK_S, lock_table_has(), LOCK_X, thr_get_trx(), and ut_ad.
Referenced by lock_clust_rec_modify_check_and_lock(), lock_clust_rec_read_check_and_lock(), lock_sec_rec_modify_check_and_lock(), and lock_sec_rec_read_check_and_lock().
02158 : DB_SUCCESS, DB_LOCK_WAIT, or error 02159 code */ 02160 ibool impl, /* in: if TRUE, no lock is set if no wait is 02161 necessary: we assume that the caller will set 02162 an implicit lock */ 02163 ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly 02164 ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */ 02165 rec_t* rec, /* in: record */ 02166 dict_index_t* index, /* in: index of record */ 02167 que_thr_t* thr) /* in: query thread */ 02168 { 02169 ulint err; 02170 02171 #ifdef UNIV_SYNC_DEBUG 02172 ut_ad(mutex_own(&kernel_mutex)); 02173 #endif /* UNIV_SYNC_DEBUG */ 02174 ut_ad((LOCK_MODE_MASK & mode) != LOCK_S 02175 || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS)); 02176 ut_ad((LOCK_MODE_MASK & mode) != LOCK_X 02177 || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX)); 02178 ut_ad((LOCK_MODE_MASK & mode) == LOCK_S 02179 || (LOCK_MODE_MASK & mode) == LOCK_X); 02180 ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP 02181 || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP 02182 || mode - (LOCK_MODE_MASK & mode) == 0); 02183 02184 if (lock_rec_lock_fast(impl, mode, rec, index, thr)) { 02185 02186 /* We try a simplified and faster subroutine for the most 02187 common cases */ 02188 02189 err = DB_SUCCESS; 02190 } else { 02191 err = lock_rec_lock_slow(impl, mode, rec, index, thr); 02192 } 02193 02194 return(err); 02195 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE ibool lock_rec_lock_fast | ( | ibool | impl, | |
| ulint | mode, | |||
| rec_t * | rec, | |||
| dict_index_t * | index, | |||
| que_thr_t * | thr | |||
| ) |
Definition at line 1999 of file lock0lock.c.
References FALSE, index(), trx_struct::isolation_level, kernel_mutex, lock, LOCK_GAP, LOCK_IS, LOCK_IX, LOCK_MODE_MASK, LOCK_REC, lock_rec_create(), lock_rec_get_first_on_page(), lock_rec_get_n_bits(), lock_rec_get_next_on_page(), lock_rec_get_nth_bit(), LOCK_REC_NOT_GAP, lock_rec_set_nth_bit(), LOCK_S, lock_table_has(), LOCK_X, NULL, page_rec_is_comp(), rec_get_heap_no(), srv_locks_unsafe_for_binlog, thr_get_trx(), TRUE, TRX_ISO_READ_COMMITTED, trx_register_new_rec_lock(), and ut_ad.
Referenced by lock_rec_lock().
02001 : TRUE if locking succeeded */ 02002 ibool impl, /* in: if TRUE, no lock is set if no wait 02003 is necessary: we assume that the caller will 02004 set an implicit lock */ 02005 ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly 02006 ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */ 02007 rec_t* rec, /* in: record */ 02008 dict_index_t* index, /* in: index of record */ 02009 que_thr_t* thr) /* in: query thread */ 02010 { 02011 lock_t* lock; 02012 ulint heap_no; 02013 trx_t* trx; 02014 02015 #ifdef UNIV_SYNC_DEBUG 02016 ut_ad(mutex_own(&kernel_mutex)); 02017 #endif /* UNIV_SYNC_DEBUG */ 02018 ut_ad((LOCK_MODE_MASK & mode) != LOCK_S 02019 || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS)); 02020 ut_ad((LOCK_MODE_MASK & mode) != LOCK_X 02021 || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX)); 02022 ut_ad((LOCK_MODE_MASK & mode) == LOCK_S 02023 || (LOCK_MODE_MASK & mode) == LOCK_X); 02024 ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP 02025 || mode - (LOCK_MODE_MASK & mode) == 0 02026 || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); 02027 02028 heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec)); 02029 02030 lock = lock_rec_get_first_on_page(rec); 02031 02032 trx = thr_get_trx(thr); 02033 02034 if (lock == NULL) { 02035 if (!impl) { 02036 lock_rec_create(mode, rec, index, trx); 02037 02038 if (srv_locks_unsafe_for_binlog 02039 || trx->isolation_level == TRX_ISO_READ_COMMITTED) { 02040 trx_register_new_rec_lock(trx, index); 02041 } 02042 } 02043 02044 return(TRUE); 02045 } 02046 02047 if (lock_rec_get_next_on_page(lock)) { 02048 02049 return(FALSE); 02050 } 02051 02052 if (lock->trx != trx 02053 || lock->type_mode != (mode | LOCK_REC) 02054 || lock_rec_get_n_bits(lock) <= heap_no) { 02055 02056 return(FALSE); 02057 } 02058 02059 if (!impl) { 02060 /* If the nth bit of the record lock is already set then we 02061 do not set a new lock bit, otherwise we do set */ 02062 02063 if (!lock_rec_get_nth_bit(lock, heap_no)) { 02064 lock_rec_set_nth_bit(lock, heap_no); 02065 if (srv_locks_unsafe_for_binlog 02066 || trx->isolation_level == TRX_ISO_READ_COMMITTED) { 02067 trx_register_new_rec_lock(trx, index); 02068 } 02069 } 02070 } 02071 02072 return(TRUE); 02073 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint lock_rec_lock_slow | ( | ibool | impl, | |
| ulint | mode, | |||
| rec_t * | rec, | |||
| dict_index_t * | index, | |||
| que_thr_t * | thr | |||
| ) | [static] |
Definition at line 2082 of file lock0lock.c.
References DB_SUCCESS, err, index(), trx_struct::isolation_level, kernel_mutex, LOCK_GAP, LOCK_IS, LOCK_IX, LOCK_MODE_MASK, LOCK_REC, lock_rec_add_to_queue(), lock_rec_enqueue_waiting(), lock_rec_has_expl(), LOCK_REC_NOT_GAP, lock_rec_other_has_conflicting(), LOCK_S, lock_table_has(), LOCK_X, srv_locks_unsafe_for_binlog, thr_get_trx(), TRX_ISO_READ_COMMITTED, trx_register_new_rec_lock(), and ut_ad.
Referenced by lock_rec_lock().
02084 : DB_SUCCESS, DB_LOCK_WAIT, or error 02085 code */ 02086 ibool impl, /* in: if TRUE, no lock is set if no wait is 02087 necessary: we assume that the caller will set 02088 an implicit lock */ 02089 ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly 02090 ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */ 02091 rec_t* rec, /* in: record */ 02092 dict_index_t* index, /* in: index of record */ 02093 que_thr_t* thr) /* in: query thread */ 02094 { 02095 trx_t* trx; 02096 ulint err; 02097 02098 #ifdef UNIV_SYNC_DEBUG 02099 ut_ad(mutex_own(&kernel_mutex)); 02100 #endif /* UNIV_SYNC_DEBUG */ 02101 ut_ad((LOCK_MODE_MASK & mode) != LOCK_S 02102 || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS)); 02103 ut_ad((LOCK_MODE_MASK & mode) != LOCK_X 02104 || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX)); 02105 ut_ad((LOCK_MODE_MASK & mode) == LOCK_S 02106 || (LOCK_MODE_MASK & mode) == LOCK_X); 02107 ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP 02108 || mode - (LOCK_MODE_MASK & mode) == 0 02109 || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); 02110 02111 trx = thr_get_trx(thr); 02112 02113 if (lock_rec_has_expl(mode, rec, trx)) { 02114 /* The trx already has a strong enough lock on rec: do 02115 nothing */ 02116 02117 err = DB_SUCCESS; 02118 } else if (lock_rec_other_has_conflicting(mode, rec, trx)) { 02119 02120 /* If another transaction has a non-gap conflicting request in 02121 the queue, as this transaction does not have a lock strong 02122 enough already granted on the record, we have to wait. */ 02123 02124 err = lock_rec_enqueue_waiting(mode, rec, index, thr); 02125 02126 if (srv_locks_unsafe_for_binlog 02127 || trx->isolation_level == TRX_ISO_READ_COMMITTED) { 02128 trx_register_new_rec_lock(trx, index); 02129 } 02130 } else { 02131 if (!impl) { 02132 /* Set the requested lock on the record */ 02133 02134 lock_rec_add_to_queue(LOCK_REC | mode, rec, index, 02135 trx); 02136 if (srv_locks_unsafe_for_binlog 02137 || trx->isolation_level == TRX_ISO_READ_COMMITTED) { 02138 trx_register_new_rec_lock(trx, index); 02139 } 02140 } 02141 02142 err = DB_SUCCESS; 02143 } 02144 02145 return(err); 02146 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2537 of file lock0lock.c.
References kernel_mutex, lock, lock_get_wait(), lock_rec_add_to_queue(), lock_rec_get_first(), lock_rec_get_next(), lock_rec_reset_nth_bit(), lock_reset_lock_and_trx_wait(), NULL, rec_get_heap_no(), and ut_ad.
Referenced by lock_rec_restore_from_page_infimum(), lock_rec_store_on_page_infimum(), lock_update_copy_and_discard(), lock_update_merge_left(), lock_update_root_raise(), and lock_update_split_right().
02539 : record which gets locks; this record 02540 must have no lock requests on it! */ 02541 rec_t* donator, /* in: record which gives locks */ 02542 ulint comp) /* in: nonzero=compact page format */ 02543 { 02544 lock_t* lock; 02545 ulint heap_no; 02546 ulint type_mode; 02547 02548 #ifdef UNIV_SYNC_DEBUG 02549 ut_ad(mutex_own(&kernel_mutex)); 02550 #endif /* UNIV_SYNC_DEBUG */ 02551 02552 heap_no = rec_get_heap_no(donator, comp); 02553 02554 lock = lock_rec_get_first(donator); 02555 02556 ut_ad(lock_rec_get_first(receiver) == NULL); 02557 02558 while (lock != NULL) { 02559 type_mode = lock->type_mode; 02560 02561 lock_rec_reset_nth_bit(lock, heap_no); 02562 02563 if (lock_get_wait(lock)) { 02564 lock_reset_lock_and_trx_wait(lock); 02565 } 02566 02567 /* Note that we FIRST reset the bit, and then set the lock: 02568 the function works also if donator == receiver */ 02569 02570 lock_rec_add_to_queue(type_mode, receiver, lock->index, 02571 lock->trx); 02572 lock = lock_rec_get_next(donator, lock); 02573 } 02574 02575 ut_ad(lock_rec_get_first(donator) == NULL); 02576 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1583 of file lock0lock.c.
References kernel_mutex, lock, lock_rec_get_first(), lock_rec_get_next(), lock_rec_has_to_wait(), NULL, page_rec_is_supremum(), and ut_ad.
Referenced by lock_rec_insert_check_and_lock(), and lock_rec_lock_slow().
01585 : lock or NULL */ 01586 ulint mode, /* in: LOCK_S or LOCK_X, 01587 possibly ORed to LOCK_GAP or LOC_REC_NOT_GAP, 01588 LOCK_INSERT_INTENTION */ 01589 rec_t* rec, /* in: record to look at */ 01590 trx_t* trx) /* in: our transaction */ 01591 { 01592 lock_t* lock; 01593 #ifdef UNIV_SYNC_DEBUG 01594 ut_ad(mutex_own(&kernel_mutex)); 01595 #endif /* UNIV_SYNC_DEBUG */ 01596 01597 lock = lock_rec_get_first(rec); 01598 01599 while (lock) { 01600 if (lock_rec_has_to_wait(trx, mode, lock, 01601 page_rec_is_supremum(rec))) { 01602 01603 return(lock); 01604 } 01605 01606 lock = lock_rec_get_next(rec, lock); 01607 } 01608 01609 return(NULL); 01610 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static lock_t* lock_rec_other_has_expl_req | ( | ulint | mode, | |
| ulint | gap, | |||
| ulint | wait, | |||
| rec_t * | rec, | |||
| trx_t * | trx | |||
| ) | [static] |
Definition at line 1538 of file lock0lock.c.
References kernel_mutex, lock, LOCK_GAP, lock_get_mode(), lock_get_wait(), lock_mode_stronger_or_eq(), lock_rec_get_first(), lock_rec_get_gap(), lock_rec_get_next(), LOCK_S, LOCK_WAIT, LOCK_X, NULL, page_rec_is_supremum(), and ut_ad.
Referenced by lock_rec_add_to_queue(), and lock_rec_queue_validate().
01540 : lock or NULL */ 01541 ulint mode, /* in: LOCK_S or LOCK_X */ 01542 ulint gap, /* in: LOCK_GAP if also gap locks are taken 01543 into account, or 0 if not */ 01544 ulint wait, /* in: LOCK_WAIT if also waiting locks are 01545 taken into account, or 0 if not */ 01546 rec_t* rec, /* in: record to look at */ 01547 trx_t* trx) /* in: transaction, or NULL if requests by all 01548 transactions are taken into account */ 01549 { 01550 lock_t* lock; 01551 01552 #ifdef UNIV_SYNC_DEBUG 01553 ut_ad(mutex_own(&kernel_mutex)); 01554 #endif /* UNIV_SYNC_DEBUG */ 01555 ut_ad(mode == LOCK_X || mode == LOCK_S); 01556 ut_ad(gap == 0 || gap == LOCK_GAP); 01557 ut_ad(wait == 0 || wait == LOCK_WAIT); 01558 01559 lock = lock_rec_get_first(rec); 01560 01561 while (lock) { 01562 if (lock->trx != trx 01563 && (gap || 01564 !(lock_rec_get_gap(lock) || page_rec_is_supremum(rec))) 01565 && (wait || !lock_get_wait(lock)) 01566 && lock_mode_stronger_or_eq(lock_get_mode(lock), mode)) { 01567 01568 return(lock); 01569 } 01570 01571 lock = lock_rec_get_next(rec, lock); 01572 } 01573 01574 return(NULL); 01575 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void lock_rec_print | ( | FILE * | file, | |
| lock_t * | lock | |||
| ) |
Definition at line 4107 of file lock0lock.c.
References BUF_GET_IF_IN_POOL, buf_page_get_gen(), buf_page_get_nowait, dict_index_name_print(), kernel_mutex, lock, lock_get_mode(), lock_get_type(), lock_get_wait(), LOCK_REC, lock_rec_get_gap(), lock_rec_get_insert_intention(), lock_rec_get_n_bits(), lock_rec_get_nth_bit(), lock_rec_get_rec_not_gap(), LOCK_S, LOCK_X, mem_heap_free, mtr_commit(), mtr_start(), NULL, page, page_find_rec_with_heap_no(), page_t, rec_get_offsets, REC_OFFS_NORMAL_SIZE, rec_print_new(), RW_NO_LATCH, RW_S_LATCH, RW_X_LATCH, SYNC_NO_ORDER_CHECK, ut_a, ut_ad, and ut_error.
Referenced by lock_deadlock_recursive(), and lock_print_info_all_transactions().
04109 : file where to print */ 04110 lock_t* lock) /* in: record type lock */ 04111 { 04112 page_t* page; 04113 ulint space; 04114 ulint page_no; 04115 ulint i; 04116 mtr_t mtr; 04117 mem_heap_t* heap = NULL; 04118 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 04119 ulint* offsets = offsets_; 04120 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 04121 04122 #ifdef UNIV_SYNC_DEBUG 04123 ut_ad(mutex_own(&kernel_mutex)); 04124 #endif /* UNIV_SYNC_DEBUG */ 04125 ut_a(lock_get_type(lock) == LOCK_REC); 04126 04127 space = lock->un_member.rec_lock.space; 04128 page_no = lock->un_member.rec_lock.page_no; 04129 04130 fprintf(file, "RECORD LOCKS space id %lu page no %lu n bits %lu ", 04131 (ulong) space, (ulong) page_no, 04132 (ulong) lock_rec_get_n_bits(lock)); 04133 dict_index_name_print(file, lock->trx, lock->index); 04134 fprintf(file, " trx id %lu %lu", 04135 (ulong) (lock->trx)->id.high, 04136 (ulong) (lock->trx)->id.low); 04137 04138 if (lock_get_mode(lock) == LOCK_S) { 04139 fputs(" lock mode S", file); 04140 } else if (lock_get_mode(lock) == LOCK_X) { 04141 fputs(" lock_mode X", file); 04142 } else { 04143 ut_error; 04144 } 04145 04146 if (lock_rec_get_gap(lock)) { 04147 fputs(" locks gap before rec", file); 04148 } 04149 04150 if (lock_rec_get_rec_not_gap(lock)) { 04151 fputs(" locks rec but not gap", file); 04152 } 04153 04154 if (lock_rec_get_insert_intention(lock)) { 04155 fputs(" insert intention", file); 04156 } 04157 04158 if (lock_get_wait(lock)) { 04159 fputs(" waiting", file); 04160 } 04161 04162 mtr_start(&mtr); 04163 04164 putc('\n', file); 04165 04166 /* If the page is not in the buffer pool, we cannot load it 04167 because we have the kernel mutex and ibuf operations would 04168 break the latching order */ 04169 04170 page = buf_page_get_gen(space, page_no, RW_NO_LATCH, 04171 NULL, BUF_GET_IF_IN_POOL, 04172 __FILE__, __LINE__, &mtr); 04173 if (page) { 04174 page = buf_page_get_nowait(space, page_no, RW_S_LATCH, &mtr); 04175 04176 if (!page) { 04177 /* Let us try to get an X-latch. If the current thread 04178 is holding an X-latch on the page, we cannot get an 04179 S-latch. */ 04180 04181 page = buf_page_get_nowait(space, page_no, RW_X_LATCH, 04182 &mtr); 04183 } 04184 } 04185 04186 if (page) { 04187 #ifdef UNIV_SYNC_DEBUG 04188 buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK); 04189 #endif /* UNIV_SYNC_DEBUG */ 04190 } 04191 04192 for (i = 0; i < lock_rec_get_n_bits(lock); i++) { 04193 04194 if (lock_rec_get_nth_bit(lock, i)) { 04195 04196 fprintf(file, "Record lock, heap no %lu ", (ulong) i); 04197 04198 if (page) { 04199 rec_t* rec 04200 = page_find_rec_with_heap_no(page, i); 04201 offsets = rec_get_offsets(rec, lock->index, 04202 offsets, ULINT_UNDEFINED, &heap); 04203 rec_print_new(file, rec, offsets); 04204 } 04205 04206 putc('\n', file); 04207 } 04208 } 04209 04210 mtr_commit(&mtr); 04211 if (UNIV_LIKELY_NULL(heap)) { 04212 mem_heap_free(heap); 04213 } 04214 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool lock_rec_queue_validate | ( | rec_t * | rec, | |
| dict_index_t * | index, | |||
| const ulint * | offsets | |||
| ) |
Definition at line 4502 of file lock0lock.c.
References DICT_CLUSTERED, index(), lock, lock_clust_rec_some_has_impl(), lock_get_mode(), lock_get_wait(), lock_mutex_enter_kernel, lock_mutex_exit_kernel, lock_rec_get_first(), lock_rec_get_gap(), lock_rec_get_next(), lock_rec_has_expl(), lock_rec_has_to_wait_in_queue(), LOCK_REC_NOT_GAP, lock_rec_other_has_expl_req(), LOCK_S, lock_sec_rec_some_has_impl_off_kernel(), LOCK_WAIT, LOCK_X, page_rec_is_comp(), page_rec_is_user_rec(), rec_offs_comp(), rec_offs_validate(), TRUE, TRX_ACTIVE, TRX_COMMITTED_IN_MEMORY, trx_in_trx_list(), TRX_PREPARED, ut_a, and ut_ad.
Referenced by lock_clust_rec_modify_check_and_lock(), lock_clust_rec_read_check_and_lock(), lock_rec_insert_check_and_lock(), lock_rec_validate_page(), lock_sec_rec_modify_check_and_lock(), and lock_sec_rec_read_check_and_lock().
04504 : TRUE if ok */ 04505 rec_t* rec, /* in: record to look at */ 04506 dict_index_t* index, /* in: index, or NULL if not known */ 04507 const ulint* offsets)/* in: rec_get_offsets(rec, index) */ 04508 { 04509 trx_t* impl_trx; 04510 lock_t* lock; 04511 04512 ut_a(rec); 04513 ut_ad(rec_offs_validate(rec, index, offsets)); 04514 ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets)); 04515 04516 lock_mutex_enter_kernel(); 04517 04518 if (!page_rec_is_user_rec(rec)) { 04519 04520 lock = lock_rec_get_first(rec); 04521 04522 while (lock) { 04523 ut_a(lock->trx->conc_state == TRX_ACTIVE 04524 || lock->trx->conc_state == TRX_PREPARED 04525 || lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY); 04526 04527 ut_a(trx_in_trx_list(lock->trx)); 04528 04529 if (lock_get_wait(lock)) { 04530 ut_a(lock_rec_has_to_wait_in_queue(lock)); 04531 } 04532 04533 if (index) { 04534 ut_a(lock->index == index); 04535 } 04536 04537 lock = lock_rec_get_next(rec, lock); 04538 } 04539 04540 lock_mutex_exit_kernel(); 04541 04542 return(TRUE); 04543 } 04544 04545 if (index && (index->type & DICT_CLUSTERED)) { 04546 04547 impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets); 04548 04549 if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0, 04550 LOCK_WAIT, rec, impl_trx)) { 04551 04552 ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec, 04553 impl_trx)); 04554 } 04555 } 04556 04557 if (index && !(index->type & DICT_CLUSTERED)) { 04558 04559 /* The kernel mutex may get released temporarily in the 04560 next function call: we have to release lock table mutex 04561 to obey the latching order */ 04562 04563 impl_trx = lock_sec_rec_some_has_impl_off_kernel( 04564 rec, index, offsets); 04565 04566 if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0, 04567 LOCK_WAIT, rec, impl_trx)) { 04568 04569 ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, 04570 rec, impl_trx)); 04571 } 04572 } 04573 04574 lock = lock_rec_get_first(rec); 04575 04576 while (lock) { 04577 ut_a(lock->trx->conc_state == TRX_ACTIVE 04578 || lock->trx->conc_state == TRX_PREPARED 04579 || lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY); 04580 ut_a(trx_in_trx_list(lock->trx)); 04581 04582 if (index) { 04583 ut_a(lock->index == index); 04584 } 04585 04586 if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) { 04587 04588 ulint mode; 04589 04590 if (lock_get_mode(lock) == LOCK_S) { 04591 mode = LOCK_X; 04592 } else { 04593 mode = LOCK_S; 04594 } 04595 ut_a(!lock_rec_other_has_expl_req(mode, 04596 0, 0, rec, lock->trx)); 04597 04598 } else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) { 04599 04600 ut_a(lock_rec_has_to_wait_in_queue(lock)); 04601 } 04602 04603 lock = lock_rec_get_next(rec, lock); 04604 } 04605 04606 lock_mutex_exit_kernel(); 04607 04608 return(TRUE); 04609 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3044 of file lock0lock.c.
References kernel_mutex, lock_rec_inherit_to_gap(), lock_rec_reset_and_release_wait(), mutex_enter, and mutex_exit().
Referenced by btr_cur_pess_upd_restore_supremum().
03046 : heir record */ 03047 rec_t* rec) /* in: record */ 03048 { 03049 mutex_enter(&kernel_mutex); 03050 03051 lock_rec_reset_and_release_wait(heir); 03052 03053 lock_rec_inherit_to_gap(heir, rec); 03054 03055 mutex_exit(&kernel_mutex); 03056 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void lock_rec_reset_and_release_wait | ( | rec_t * | rec | ) | [static] |
Definition at line 2431 of file lock0lock.c.
References kernel_mutex, lock, lock_get_wait(), lock_rec_cancel(), lock_rec_get_first(), lock_rec_get_next(), lock_rec_reset_nth_bit(), NULL, page_rec_is_comp(), rec_get_heap_no(), and ut_ad.
Referenced by lock_rec_reset_and_inherit_gap_locks(), lock_update_delete(), lock_update_discard(), lock_update_merge_left(), and lock_update_merge_right().
02433 : record whose locks bits should be reset */ 02434 { 02435 lock_t* lock; 02436 ulint heap_no; 02437 02438 #ifdef UNIV_SYNC_DEBUG 02439 ut_ad(mutex_own(&kernel_mutex)); 02440 #endif /* UNIV_SYNC_DEBUG */ 02441 02442 heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec)); 02443 02444 lock = lock_rec_get_first(rec); 02445 02446 while (lock != NULL) { 02447 if (lock_get_wait(lock)) { 02448 lock_rec_cancel(lock); 02449 } else { 02450 lock_rec_reset_nth_bit(lock, heap_no); 02451 } 02452 02453 lock = lock_rec_get_next(rec, lock); 02454 } 02455 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1123 of file lock0lock.c.
References FALSE, lock, lock_get_type(), LOCK_REC, ut_ad, and ut_bit_set_nth().
Referenced by lock_move_rec_list_end(), lock_move_rec_list_start(), lock_rec_cancel(), lock_rec_enqueue_waiting(), lock_rec_move(), lock_rec_reset_and_release_wait(), and lock_rec_unlock().
01125 : record lock */ 01126 ulint i) /* in: index of the bit which must be set to TRUE 01127 when this function is called */ 01128 { 01129 ulint byte_index; 01130 ulint bit_index; 01131 byte* ptr; 01132 ulint b; 01133 01134 ut_ad(lock); 01135 ut_ad(lock_get_type(lock) == LOCK_REC); 01136 ut_ad(i < lock->un_member.rec_lock.n_bits); 01137 01138 byte_index = i / 8; 01139 bit_index = i % 8; 01140 01141 ptr = (byte*)lock + sizeof(lock_t) + byte_index; 01142 01143 b = (ulint)*ptr; 01144 01145 b = ut_bit_set_nth(b, bit_index, FALSE); 01146 01147 *ptr = (byte)b; 01148 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3173 of file lock0lock.c.
References lock_mutex_enter_kernel, lock_mutex_exit_kernel, lock_rec_move(), page_get_infimum_rec(), page_is_comp(), page_rec_is_comp(), and ut_ad.
Referenced by btr_cur_optimistic_update(), and btr_cur_pessimistic_update().
03175 : record whose lock state is restored */ 03176 page_t* page) /* in: page (rec is not necessarily on this page) 03177 whose infimum stored the lock state; lock bits are 03178 reset on the infimum */ 03179 { 03180 ulint comp; 03181 lock_mutex_enter_kernel(); 03182 comp = page_is_comp(page); 03183 ut_ad(!comp == !page_rec_is_comp(rec)); 03184 03185 lock_rec_move(rec, page_get_infimum_rec(page), comp); 03186 03187 lock_mutex_exit_kernel(); 03188 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1069 of file lock0lock.c.
References lock, lock_get_type(), LOCK_REC, TRUE, ut_ad, and ut_bit_set_nth().
Referenced by lock_rec_add_to_queue(), lock_rec_create(), and lock_rec_lock_fast().
01071 : record lock */ 01072 ulint i) /* in: index of the bit */ 01073 { 01074 ulint byte_index; 01075 ulint bit_index; 01076 byte* ptr; 01077 ulint b; 01078 01079 ut_ad(lock); 01080 ut_ad(lock_get_type(lock) == LOCK_REC); 01081 ut_ad(i < lock->un_member.rec_lock.n_bits); 01082 01083 byte_index = i / 8; 01084 bit_index = i % 8; 01085 01086 ptr = (byte*)lock + sizeof(lock_t) + byte_index; 01087 01088 b = (ulint)*ptr; 01089 01090 b = ut_bit_set_nth(b, bit_index, TRUE); 01091 01092 *ptr = (byte)b; 01093 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3152 of file lock0lock.c.
References buf_frame_align(), lock_mutex_enter_kernel, lock_mutex_exit_kernel, lock_rec_move(), page_get_infimum_rec(), page_is_comp(), and ut_ad.
Referenced by btr_cur_optimistic_update(), and btr_cur_pessimistic_update().
03154 : page containing the record */ 03155 rec_t* rec) /* in: record whose lock state is stored 03156 on the infimum record of the same page; lock 03157 bits are reset on the record */ 03158 { 03159 ut_ad(page == buf_frame_align(rec)); 03160 03161 lock_mutex_enter_kernel(); 03162 03163 lock_rec_move(page_get_infimum_rec(page), rec, page_is_comp(page)); 03164 03165 lock_mutex_exit_kernel(); 03166 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3800 of file lock0lock.c.
References kernel_mutex, lock, lock_get_mode(), lock_get_wait(), lock_grant(), lock_rec_get_first(), lock_rec_get_next(), lock_rec_has_to_wait_in_queue(), lock_rec_reset_nth_bit(), mutex_enter, mutex_exit(), NULL, page_rec_is_comp(), rec_get_heap_no(), ut_a, ut_ad, and ut_print_timestamp().
Referenced by row_unlock_for_mysql().
03802 : transaction that has set a record 03803 lock */ 03804 rec_t* rec, /* in: record */ 03805 ulint lock_mode) /* in: LOCK_S or LOCK_X */ 03806 { 03807 lock_t* lock; 03808 lock_t* release_lock = NULL; 03809 ulint heap_no; 03810 03811 ut_ad(trx && rec); 03812 03813 mutex_enter(&kernel_mutex); 03814 03815 heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec)); 03816 03817 lock = lock_rec_get_first(rec); 03818 03819 /* Find the last lock with the same lock_mode and transaction 03820 from the record. */ 03821 03822 while (lock != NULL) { 03823 if (lock->trx == trx && lock_get_mode(lock) == lock_mode) { 03824 release_lock = lock; 03825 ut_a(!lock_get_wait(lock)); 03826 } 03827 03828 lock = lock_rec_get_next(rec, lock); 03829 } 03830 03831 /* If a record lock is found, release the record lock */ 03832 03833 if (UNIV_LIKELY(release_lock != NULL)) { 03834 lock_rec_reset_nth_bit(release_lock, heap_no); 03835 } else { 03836 mutex_exit(&kernel_mutex); 03837 ut_print_timestamp(stderr); 03838 fprintf(stderr, 03839 " InnoDB: Error: unlock row could not find a %lu mode lock on the record\n", 03840 (ulong)lock_mode); 03841 03842 return; 03843 } 03844 03845 /* Check if we can now grant waiting lock requests */ 03846 03847 lock = lock_rec_get_first(rec); 03848 03849 while (lock != NULL) { 03850 if (lock_get_wait(lock) 03851 && !lock_rec_has_to_wait_in_queue(lock)) { 03852 03853 /* Grant the lock */ 03854 lock_grant(lock); 03855 } 03856 03857 lock = lock_rec_get_next(rec, lock); 03858 } 03859 03860 mutex_exit(&kernel_mutex); 03861 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 4615 of file lock0lock.c.
References buf_page_get, index(), kernel_mutex, lock, lock_mutex_enter_kernel, lock_mutex_exit_kernel, lock_rec_get_first_on_page_addr(), lock_rec_get_n_bits(), lock_rec_get_next_on_page(), lock_rec_get_nth_bit(), lock_rec_queue_validate(), mem_heap_free, mtr_commit(), mtr_start(), NULL, page, page_find_rec_with_heap_no(), page_t, rec_get_offsets, REC_OFFS_NORMAL_SIZE, RW_X_LATCH, SYNC_NO_ORDER_CHECK, TRUE, TRX_ACTIVE, TRX_COMMITTED_IN_MEMORY, trx_in_trx_list(), TRX_PREPARED, ut_a, and ut_ad.
Referenced by lock_validate().
04617 : TRUE if ok */ 04618 ulint space, /* in: space id */ 04619 ulint page_no)/* in: page number */ 04620 { 04621 dict_index_t* index; 04622 page_t* page; 04623 lock_t* lock; 04624 rec_t* rec; 04625 ulint nth_lock = 0; 04626 ulint nth_bit = 0; 04627 ulint i; 04628 mtr_t mtr; 04629 mem_heap_t* heap = NULL; 04630 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 04631 ulint* offsets = offsets_; 04632 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 04633 04634 #ifdef UNIV_SYNC_DEBUG 04635 ut_ad(!mutex_own(&kernel_mutex)); 04636 #endif /* UNIV_SYNC_DEBUG */ 04637 04638 mtr_start(&mtr); 04639 04640 page = buf_page_get(space, page_no, RW_X_LATCH, &mtr); 04641 #ifdef UNIV_SYNC_DEBUG 04642 buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK); 04643 #endif /* UNIV_SYNC_DEBUG */ 04644 04645 lock_mutex_enter_kernel(); 04646 loop: 04647 lock = lock_rec_get_first_on_page_addr(space, page_no); 04648 04649 if (!lock) { 04650 goto function_exit; 04651 } 04652 04653 for (i = 0; i < nth_lock; i++) { 04654 04655 lock = lock_rec_get_next_on_page(lock); 04656 04657 if (!lock) { 04658 goto function_exit; 04659 } 04660 } 04661 04662 ut_a(trx_in_trx_list(lock->trx)); 04663 ut_a(lock->trx->conc_state == TRX_ACTIVE 04664 || lock->trx->conc_state == TRX_PREPARED 04665 || lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY); 04666 04667 for (i = nth_bit; i < lock_rec_get_n_bits(lock); i++) { 04668 04669 if (i == 1 || lock_rec_get_nth_bit(lock, i)) { 04670 04671 index = lock->index; 04672 rec = page_find_rec_with_heap_no(page, i); 04673 offsets = rec_get_offsets(rec, index, offsets, 04674 ULINT_UNDEFINED, &heap); 04675 04676 fprintf(stderr, 04677 "Validating %lu %lu\n", (ulong) space, (ulong) page_no); 04678 04679 lock_mutex_exit_kernel(); 04680 04681 lock_rec_queue_validate(rec, index, offsets); 04682 04683 lock_mutex_enter_kernel(); 04684 04685 nth_bit = i + 1; 04686 04687 goto loop; 04688 } 04689 } 04690 04691 nth_bit = 0; 04692 nth_lock++; 04693 04694 goto loop; 04695 04696 function_exit: 04697 lock_mutex_exit_kernel(); 04698 04699 mtr_commit(&mtr); 04700 04701 if (UNIV_LIKELY_NULL(heap)) { 04702 mem_heap_free(heap); 04703 } 04704 return(TRUE); 04705 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void lock_release_off_kernel | ( | trx_t * | trx | ) |
Definition at line 3902 of file lock0lock.c.
References trx_struct::auto_inc_lock, count, kernel_mutex, lock, lock_get_mode(), lock_get_type(), trx_struct::lock_heap, LOCK_IS, lock_mutex_enter_kernel, lock_mutex_exit_kernel, LOCK_REC, lock_rec_dequeue_from_page(), LOCK_RELEASE_KERNEL_INTERVAL, LOCK_TABLE, lock_table_dequeue(), trx_sys_struct::max_trx_id, mem_heap_empty(), NULL, dict_table_struct::query_cache_inv_trx_id, trx_struct::trx_locks, trx_sys, trx_struct::undo_no, ut_a, ut_ad, ut_dulint_cmp(), ut_dulint_zero, and UT_LIST_GET_LAST.
Referenced by trx_commit_off_kernel().
03904 : transaction */ 03905 { 03906 dict_table_t* table; 03907 ulint count; 03908 lock_t* lock; 03909 03910 #ifdef UNIV_SYNC_DEBUG 03911 ut_ad(mutex_own(&kernel_mutex)); 03912 #endif /* UNIV_SYNC_DEBUG */ 03913 03914 lock = UT_LIST_GET_LAST(trx->trx_locks); 03915 03916 count = 0; 03917 03918 while (lock != NULL) { 03919 03920 count++; 03921 03922 if (lock_get_type(lock) == LOCK_REC) { 03923 03924 lock_rec_dequeue_from_page(lock); 03925 } else { 03926 ut_ad(lock_get_type(lock) & LOCK_TABLE); 03927 03928 if (lock_get_mode(lock) != LOCK_IS 03929 && 0 != ut_dulint_cmp(trx->undo_no, 03930 ut_dulint_zero)) { 03931 03932 /* The trx may have modified the table. We 03933 block the use of the MySQL query cache for 03934 all currently active transactions. */ 03935 03936 table = lock->un_member.tab_lock.table; 03937 03938 table->query_cache_inv_trx_id = 03939 trx_sys->max_trx_id; 03940 } 03941 03942 lock_table_dequeue(lock); 03943 } 03944 03945 if (count == LOCK_RELEASE_KERNEL_INTERVAL) { 03946 /* Release the kernel mutex for a while, so that we 03947 do not monopolize it */ 03948 03949 lock_mutex_exit_kernel(); 03950 03951 lock_mutex_enter_kernel(); 03952 03953 count = 0; 03954 } 03955 03956 lock = UT_LIST_GET_LAST(trx->trx_locks); 03957 } 03958 03959 mem_heap_empty(trx->lock_heap); 03960 03961 ut_a(trx->auto_inc_lock == NULL); 03962 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void lock_reset_all_on_table | ( | dict_table_t * | table | ) |
Definition at line 4039 of file lock0lock.c.
References kernel_mutex, lock, lock_get_wait(), lock_reset_all_on_table_for_trx(), dict_table_struct::locks, mutex_enter, mutex_exit(), ut_a, and UT_LIST_GET_FIRST.
Referenced by row_discard_tablespace_for_mysql(), row_drop_table_for_mysql(), and row_truncate_table_for_mysql().
04041 : table to be dropped */ 04042 { 04043 lock_t* lock; 04044 04045 mutex_enter(&kernel_mutex); 04046 04047 lock = UT_LIST_GET_FIRST(table->locks); 04048 04049 while (lock) { 04050 ut_a(!lock_get_wait(lock)); 04051 04052 lock_reset_all_on_table_for_trx(table, lock->trx); 04053 04054 lock = UT_LIST_GET_FIRST(table->locks); 04055 } 04056 04057 mutex_exit(&kernel_mutex); 04058 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void lock_reset_all_on_table_for_trx | ( | dict_table_t * | table, | |
| trx_t * | trx | |||
| ) | [static] |
Definition at line 4000 of file lock0lock.c.
References kernel_mutex, lock, lock_get_type(), lock_get_wait(), LOCK_REC, lock_rec_discard(), LOCK_TABLE, lock_table_remove_low(), NULL, trx_struct::trx_locks, ut_a, ut_ad, UT_LIST_GET_LAST, and UT_LIST_GET_PREV.
Referenced by lock_reset_all_on_table().
04002 : table to be dropped */ 04003 trx_t* trx) /* in: a transaction */ 04004 { 04005 lock_t* lock; 04006 lock_t* prev_lock; 04007 04008 #ifdef UNIV_SYNC_DEBUG 04009 ut_ad(mutex_own(&kernel_mutex)); 04010 #endif /* UNIV_SYNC_DEBUG */ 04011 04012 lock = UT_LIST_GET_LAST(trx->trx_locks); 04013 04014 while (lock != NULL) { 04015 prev_lock = UT_LIST_GET_PREV(trx_locks, lock); 04016 04017 if (lock_get_type(lock) == LOCK_REC 04018 && lock->index->table == table) { 04019 ut_a(!lock_get_wait(lock)); 04020 04021 lock_rec_discard(lock); 04022 } else if (lock_get_type(lock) & LOCK_TABLE 04023 && lock->un_member.tab_lock.table == table) { 04024 04025 ut_a(!lock_get_wait(lock)); 04026 04027 lock_table_remove_low(lock); 04028 } 04029 04030 lock = prev_lock; 04031 } 04032 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE void lock_reset_lock_and_trx_wait | ( | lock_t * | lock | ) |
Definition at line 782 of file lock0lock.c.
References lock, lock_get_wait(), LOCK_WAIT, NULL, and ut_ad.
Referenced by lock_cancel_waiting_and_release(), lock_grant(), lock_move_rec_list_end(), lock_move_rec_list_start(), lock_move_reorganize_page(), lock_rec_cancel(), lock_rec_enqueue_waiting(), lock_rec_move(), and lock_table_enqueue_waiting().
00784 : record lock */ 00785 { 00786 ut_ad((lock->trx)->wait_lock == lock); 00787 ut_ad(lock_get_wait(lock)); 00788 00789 /* Reset the back pointer in trx to this waiting lock request */ 00790 00791 (lock->trx)->wait_lock = NULL; 00792 lock->type_mode = lock->type_mode & ~LOCK_WAIT; 00793 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint lock_sec_rec_cons_read_sees | ( | rec_t * | rec, | |
| dict_index_t * | index, | |||
| read_view_t * | view | |||
| ) |
Definition at line 536 of file lock0lock.c.
References buf_frame_align(), DICT_CLUSTERED, FALSE, index(), page_get_max_trx_id(), page_rec_is_user_rec(), recv_recovery_is_on(), TRUE, read_view_struct::up_limit_id, ut_ad, ut_dulint_cmp(), and UT_NOT_USED.
Referenced by row_search_for_mysql(), row_sel(), and row_sel_try_search_shortcut().
00538 : TRUE if certainly sees, or FALSE if an 00539 earlier version of the clustered index record 00540 might be needed: NOTE that a non-clustered 00541 index page contains so little information on 00542 its modifications that also in the case FALSE, 00543 the present version of rec may be the right, 00544 but we must check this from the clustered 00545 index record */ 00546 rec_t* rec, /* in: user record which should be read or 00547 passed over by a read cursor */ 00548 dict_index_t* index, /* in: non-clustered index */ 00549 read_view_t* view) /* in: consistent read view */ 00550 { 00551 dulint max_trx_id; 00552 00553 UT_NOT_USED(index); 00554 00555 ut_ad(!(index->type & DICT_CLUSTERED)); 00556 ut_ad(page_rec_is_user_rec(rec)); 00557 00558 /* NOTE that we might call this function while holding the search 00559 system latch. To obey the latching order we must NOT reserve the 00560 kernel mutex here! */ 00561 00562 if (recv_recovery_is_on()) { 00563 00564 return(FALSE); 00565 } 00566 00567 max_trx_id = page_get_max_trx_id(buf_frame_align(rec)); 00568 00569 if (ut_dulint_cmp(max_trx_id, view->up_limit_id) >= 0) { 00570 00571 return(FALSE); 00572 } 00573 00574 return(TRUE); 00575 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint lock_sec_rec_modify_check_and_lock | ( | ulint | flags, | |
| rec_t * | rec, | |||
| dict_index_t * | index, | |||
| que_thr_t * | thr | |||
| ) |
Definition at line 4990 of file lock0lock.c.
References BTR_NO_LOCKING_FLAG, buf_frame_align(), DB_SUCCESS, DICT_CLUSTERED, err, index(), LOCK_IX, lock_mutex_enter_kernel, lock_mutex_exit_kernel, lock_rec_lock(), LOCK_REC_NOT_GAP, lock_rec_queue_validate(), lock_table_has(), LOCK_X, mem_heap_free, NULL, page_update_max_trx_id(), rec_get_offsets, REC_OFFS_NORMAL_SIZE, thr_get_trx(), TRUE, and ut_ad.
Referenced by btr_cur_del_mark_set_sec_rec(), and btr_cur_upd_lock_and_undo().
04992 : DB_SUCCESS, DB_LOCK_WAIT, 04993 DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ 04994 ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, 04995 does nothing */ 04996 rec_t* rec, /* in: record which should be modified; 04997 NOTE: as this is a secondary index, we 04998 always have to modify the clustered index 04999 record first: see the comment below */ 05000 dict_index_t* index, /* in: secondary index */ 05001 que_thr_t* thr) /* in: query thread */ 05002 { 05003 ulint err; 05004 05005 if (flags & BTR_NO_LOCKING_FLAG) { 05006 05007 return(DB_SUCCESS); 05008 } 05009 05010 ut_ad(!(index->type & DICT_CLUSTERED)); 05011 05012 /* Another transaction cannot have an implicit lock on the record, 05013 because when we come here, we already have modified the clustered 05014 index record, and this would not have been possible if another active 05015 transaction had modified this secondary index record. */ 05016 05017 lock_mutex_enter_kernel(); 05018 05019 ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX)); 05020 05021 err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP, rec, index, thr); 05022 05023 lock_mutex_exit_kernel(); 05024 05025 #ifdef UNIV_DEBUG 05026 { 05027 mem_heap_t* heap = NULL; 05028 ulint offsets_[REC_OFFS_NORMAL_SIZE]; 05029 const ulint* offsets; 05030 *offsets_ = (sizeof offsets_) / sizeof *offsets_; 05031 05032 offsets = rec_get_offsets(rec, index, offsets_, 05033 ULINT_UNDEFINED, &heap); 05034 ut_ad(lock_rec_queue_validate(rec, index, offsets)); 05035 if (UNIV_LIKELY_NULL(heap)) { 05036 mem_heap_free(heap); 05037 } 05038 } 05039 #endif /* UNIV_DEBUG */ 05040 05041 if (err == DB_SUCCESS) { 05042 /* Update the page max trx id field */ 05043 05044 page_update_max_trx_id(buf_frame_align(rec), 05045 thr_get_trx(thr)->id); 05046 } 05047 05048 return(err); 05049 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint lock_sec_rec_read_check_and_lock | ( | ulint | flags, | |
| rec_t * | rec, | |||
| dict_index_t * | index, | |||
| const ulint * | offsets, | |||
| ulint | mode, | |||
| ulint | gap_mode, | |||
| que_thr_t * | thr | |||
| ) |
Definition at line 5056 of file lock0lock.c.
References BTR_NO_LOCKING_FLAG, buf_frame_align(), DB_SUCCESS, DICT_CLUSTERED, err, FALSE, index(), LOCK_IS, LOCK_IX, lock_mutex_enter_kernel, lock_mutex_exit_kernel, lock_rec_convert_impl_to_expl(), lock_rec_lock(), lock_rec_queue_validate(), LOCK_S, lock_table_has(), LOCK_X, page_get_max_trx_id(), page_rec_is_supremum(), page_rec_is_user_rec(), rec_offs_validate(), recv_recovery_is_on(), thr_get_trx(), trx_list_get_min_trx_id(), ut_ad, and ut_dulint_cmp().
Referenced by row_ins_set_exclusive_rec_lock(), row_ins_set_shared_rec_lock(), and sel_set_rec_lock().
05058 : DB_SUCCESS, DB_LOCK_WAIT, 05059 DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ 05060 ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, 05061 does nothing */ 05062 rec_t* rec, /* in: user record or page supremum record 05063 which should be read or passed over by a read 05064 cursor */ 05065 dict_index_t* index, /* in: secondary index */ 05066 const ulint* offsets,/* in: rec_get_offsets(rec, index) */ 05067 ulint mode, /* in: mode of the lock which the read cursor 05068 should set on records: LOCK_S or LOCK_X; the 05069 latter is possible in SELECT FOR UPDATE */ 05070 ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or 05071 LOCK_REC_NOT_GAP */ 05072 que_thr_t* thr) /* in: query thread */ 05073 { 05074 ulint err; 05075 05076 ut_ad(!(index->type & DICT_CLUSTERED)); 05077 ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec)); 05078 ut_ad(rec_offs_validate(rec, index, offsets)); 05079 05080 if (flags & BTR_NO_LOCKING_FLAG) { 05081 05082 return(DB_SUCCESS); 05083 } 05084 05085 lock_mutex_enter_kernel(); 05086 05087 ut_ad(mode != LOCK_X 05088 || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX)); 05089 ut_ad(mode != LOCK_S 05090 || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS)); 05091 05092 /* Some transaction may have an implicit x-lock on the record only 05093 if the max trx id for the page >= min trx id for the trx list or a 05094 database recovery is running. */ 05095 05096 if (((ut_dulint_cmp(page_get_max_trx_id(buf_frame_align(rec)), 05097 trx_list_get_min_trx_id()) >= 0) 05098 || recv_recovery_is_on()) 05099 && !page_rec_is_supremum(rec)) { 05100 05101 lock_rec_convert_impl_to_expl(rec, index, offsets); 05102 } 05103 05104 err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr); 05105 05106 lock_mutex_exit_kernel(); 05107 05108 ut_ad(lock_rec_queue_validate(rec, index, offsets)); 05109 05110 return(err); 05111 }
Here is the call graph for this function:

Here is the caller graph for this function:

| trx_t* lock_sec_rec_some_has_impl_off_kernel | ( | rec_t * | rec, | |
| dict_index_t * | index, | |||
| const ulint * | offsets | |||
| ) |
Definition at line 1654 of file lock0lock.c.
References buf_frame_align(), buf_page_print(), DICT_CLUSTERED, index(), kernel_mutex, lock_check_trx_id_sanity(), NULL, page, page_get_max_trx_id(), page_rec_is_user_rec(), page_t, rec_offs_validate(), recv_recovery_is_on(), row_vers_impl_x_locked_off_kernel(), TRUE, trx_list_get_min_trx_id(), ut_ad, and ut_dulint_cmp().
Referenced by lock_rec_convert_impl_to_expl(), and lock_rec_queue_validate().
01656 : transaction which has the x-lock, or 01657 NULL */ 01658 rec_t* rec, /* in: user record */ 01659 dict_index_t* index, /* in: secondary index */ 01660 const ulint* offsets)/* in: rec_get_offsets(rec, index) */ 01661 { 01662 page_t* page; 01663 01664 #ifdef UNIV_SYNC_DEBUG 01665 ut_ad(mutex_own(&kernel_mutex)); 01666 #endif /* UNIV_SYNC_DEBUG */ 01667 ut_ad(!(index->type & DICT_CLUSTERED)); 01668 ut_ad(page_rec_is_user_rec(rec)); 01669 ut_ad(rec_offs_validate(rec, index, offsets)); 01670 01671 page = buf_frame_align(rec); 01672 01673 /* Some transaction may have an implicit x-lock on the record only 01674 if the max trx id for the page >= min trx id for the trx list, or 01675 database recovery is running. We do not write the changes of a page 01676 max trx id to the log, and therefore during recovery, this value 01677 for a page may be incorrect. */ 01678 01679 if (!(ut_dulint_cmp(page_get_max_trx_id(page), 01680 trx_list_get_min_trx_id()) >= 0) 01681 && !recv_recovery_is_on()) { 01682 01683 return(NULL); 01684 } 01685 01686 /* Ok, in this case it is possible that some transaction has an 01687 implicit x-lock. We have to look in the clustered index. */ 01688 01689 if (!lock_check_trx_id_sanity(page_get_max_trx_id(page), 01690 rec, index, offsets, TRUE)) { 01691 buf_page_print(page); 01692 01693 /* The page is corrupt: try to avoid a crash by returning 01694 NULL */ 01695 return(NULL); 01696 } 01697 01698 return(row_vers_impl_x_locked_off_kernel(rec, index, offsets)); 01699 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 765 of file lock0lock.c.
References lock, LOCK_WAIT, NULL, ut_ad, and trx_struct::wait_lock.
Referenced by lock_rec_create(), and lock_table_create().
00767 : lock */ 00768 trx_t* trx) /* in: trx */ 00769 { 00770 ut_ad(lock); 00771 ut_ad(trx->wait_lock == NULL); 00772 00773 trx->wait_lock = lock; 00774 lock->type_mode = lock->type_mode | LOCK_WAIT; 00775 }
Here is the caller graph for this function:

| void lock_sys_create | ( | ulint | n_cells | ) |
Definition at line 581 of file lock0lock.c.
References hash_create(), lock_latest_err_file, lock_sys, mem_alloc, os_file_create_tmpfile(), lock_sys_struct::rec_hash, and ut_a.
Referenced by innobase_start_or_create_for_mysql().
00583 : number of slots in lock hash table */ 00584 { 00585 lock_sys = mem_alloc(sizeof(lock_sys_t)); 00586 00587 lock_sys->rec_hash = hash_create(n_cells); 00588 00589 /* hash_create_mutexes(lock_sys->rec_hash, 2, SYNC_REC_LOCK); */ 00590 00591 lock_latest_err_file = os_file_create_tmpfile(); 00592 ut_a(lock_latest_err_file); 00593 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ulint lock_table | ( | ulint | flags, | |
| dict_table_t * | table, | |||
| ulint | mode, | |||
| que_thr_t * | thr | |||
| ) |
Definition at line 3637 of file lock0lock.c.
References BTR_NO_LOCKING_FLAG, DB_SUCCESS, err, lock_mutex_enter_kernel, lock_mutex_exit_kernel, LOCK_S, lock_table_create(), lock_table_enqueue_waiting(), lock_table_has(), lock_table_other_has_incompatible(), LOCK_WAIT, LOCK_X, thr_get_trx(), ut_a, and ut_ad.
03639 : DB_SUCCESS, DB_LOCK_WAIT, 03640 DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ 03641 ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, 03642 does nothing */ 03643 dict_table_t* table, /* in: database table in dictionary cache */ 03644 ulint mode, /* in: lock mode */ 03645 que_thr_t* thr) /* in: query thread */ 03646 { 03647 trx_t* trx; 03648 ulint err; 03649 03650 ut_ad(table && thr); 03651 03652 if (flags & BTR_NO_LOCKING_FLAG) { 03653 03654 return(DB_SUCCESS); 03655 } 03656 03657 ut_a(flags == 0); 03658 03659 trx = thr_get_trx(thr); 03660 03661 lock_mutex_enter_kernel(); 03662 03663 /* Look for stronger locks the same trx already has on the table */ 03664 03665 if (lock_table_has(trx, table, mode)) { 03666 03667 lock_mutex_exit_kernel(); 03668 03669 return(DB_SUCCESS); 03670 } 03671 03672 /* We have to check if the new lock is compatible with any locks 03673 other transactions have in the table lock queue. */ 03674 03675 if (lock_table_other_has_incompatible(trx, LOCK_WAIT, table, mode)) { 03676 03677 /* Another trx has a request on the table in an incompatible 03678 mode: this trx may have to wait */ 03679 03680 err = lock_table_enqueue_waiting(mode | flags, table, thr); 03681 03682 lock_mutex_exit_kernel(); 03683 03684 return(err); 03685 } 03686 03687 lock_table_create(table, mode | flags, trx); 03688 03689 ut_a(!flags || mode == LOCK_S || mode == LOCK_X); 03690 03691 lock_mutex_exit_kernel(); 03692 03693 return(DB_SUCCESS); 03694 }
Here is the call graph for this function:

| UNIV_INLINE lock_t* lock_table_create | ( | dict_table_t * | table, | |
| ulint | type_mode, | |||
| trx_t * | trx | |||
| ) |
Definition at line 3443 of file lock0lock.c.
References trx_struct::auto_inc_lock, dict_table_struct::auto_inc_lock, kernel_mutex, lock, LOCK_AUTO_INC, trx_struct::lock_heap, lock_set_lock_and_trx_wait(), LOCK_TABLE, LOCK_WAIT, dict_table_struct::locks, mem_heap_alloc(), NULL, trx_struct::trx_locks, ut_a, ut_ad, and UT_LIST_ADD_LAST.
Referenced by lock_table(), and lock_table_enqueue_waiting().
03445 : new lock object */ 03446 dict_table_t* table, /* in: database table in dictionary cache */ 03447 ulint type_mode,/* in: lock mode possibly ORed with 03448 LOCK_WAIT */ 03449 trx_t* trx) /* in: trx */ 03450 { 03451 lock_t* lock; 03452 03453 ut_ad(table && trx); 03454 #ifdef UNIV_SYNC_DEBUG 03455 ut_ad(mutex_own(&kernel_mutex)); 03456 #endif /* UNIV_SYNC_DEBUG */ 03457 03458 if (type_mode == LOCK_AUTO_INC) { 03459 /* Only one trx can have the lock on the table 03460 at a time: we may use the memory preallocated 03461 to the table object */ 03462 03463 lock = table->auto_inc_lock; 03464 03465 ut_a(trx->auto_inc_lock == NULL); 03466 trx->auto_inc_lock = lock; 03467 } else { 03468 lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t)); 03469 } 03470 03471 UT_LIST_ADD_LAST(trx_locks, trx->trx_locks, lock); 03472 03473 lock->type_mode = type_mode | LOCK_TABLE; 03474 lock->trx = trx; 03475 03476 lock->un_member.tab_lock.table = table; 03477 03478 UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); 03479 03480 if (type_mode & LOCK_WAIT) { 03481 03482 lock_set_lock_and_trx_wait(lock, trx); 03483 } 03484 03485 return(lock); 03486 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void lock_table_dequeue | ( | lock_t * | in_lock | ) | [static] |
Definition at line 3759 of file lock0lock.c.
References kernel_mutex, lock, lock_get_type(), lock_get_wait(), lock_grant(), LOCK_TABLE, lock_table_has_to_wait_in_queue(), lock_table_remove_low(), NULL, ut_a, ut_ad, and UT_LIST_GET_NEXT.
Referenced by lock_cancel_waiting_and_release(), lock_release_off_kernel(), lock_table_unlock(), and lock_table_unlock_auto_inc().
03761 : table lock object; transactions waiting 03762 behind will get their lock requests granted, if 03763 they are now qualified to it */ 03764 { 03765 lock_t* lock; 03766 03767 #ifdef UNIV_SYNC_DEBUG 03768 ut_ad(mutex_own(&kernel_mutex)); 03769 #endif /* UNIV_SYNC_DEBUG */ 03770 ut_a(lock_get_type(in_lock) == LOCK_TABLE); 03771 03772 lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock); 03773 03774 lock_table_remove_low(in_lock); 03775 03776 /* Check if waiting locks in the queue can now be granted: grant 03777 locks if there are no conflicting locks ahead. */ 03778 03779 while (lock != NULL) { 03780 03781 if (lock_get_wait(lock) 03782 && !lock_table_has_to_wait_in_queue(lock)) { 03783 03784 /* Grant the lock */ 03785 lock_grant(lock); 03786 } 03787 03788 lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock); 03789 } 03790 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulint lock_table_enqueue_waiting | ( | ulint | mode, | |
| dict_table_t * | table, | |||
| que_thr_t * | thr | |||
| ) | [static] |
Definition at line 3521 of file lock0lock.c.
References DB_DEADLOCK, DB_LOCK_WAIT, DB_QUE_THR_SUSPENDED, DB_SUCCESS, trx_struct::dict_operation, FALSE, kernel_mutex, lock, lock_deadlock_occurs(), lock_reset_lock_and_trx_wait(), lock_table_create(), lock_table_remove_low(), LOCK_WAIT, dict_table_struct::name, NULL, trx_struct::que_state, que_thr_stop(), thr_get_trx(), TRUE, TRX_QUE_LOCK_WAIT, ut_a, ut_ad, ut_error, ut_print_name(), ut_print_timestamp(), trx_struct::wait_lock, trx_struct::wait_started, and trx_struct::was_chosen_as_deadlock_victim.
Referenced by lock_table().
03523 : DB_LOCK_WAIT, DB_DEADLOCK, or 03524 DB_QUE_THR_SUSPENDED, or DB_SUCCESS; 03525 DB_SUCCESS means that there was a deadlock, 03526 but another transaction was chosen as a 03527 victim, and we got the lock immediately: 03528 no need to wait then */ 03529 ulint mode, /* in: lock mode this transaction is 03530 requesting */ 03531 dict_table_t* table, /* in: table */ 03532 que_thr_t* thr) /* in: query thread */ 03533 { 03534 lock_t* lock; 03535 trx_t* trx; 03536 03537 #ifdef UNIV_SYNC_DEBUG 03538 ut_ad(mutex_own(&kernel_mutex)); 03539 #endif /* UNIV_SYNC_DEBUG */ 03540 03541 /* Test if there already is some other reason to suspend thread: 03542 we do not enqueue a lock request if the query thread should be 03543 stopped anyway */ 03544 03545 if (que_thr_stop(thr)) { 03546 ut_error; 03547 03548 return(DB_QUE_THR_SUSPENDED); 03549 } 03550 03551 trx = thr_get_trx(thr); 03552 03553 if (trx->dict_operation) { 03554 ut_print_timestamp(stderr); 03555 fputs( 03556 " InnoDB: Error: a table lock wait happens in a dictionary operation!\n" 03557 "InnoDB: Table name ", stderr); 03558 ut_print_name(stderr, trx, TRUE, table->name); 03559 fputs(".\n" 03560 "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", 03561 stderr); 03562 } 03563 03564 /* Enqueue the lock request that will wait to be granted */ 03565 03566 lock = lock_table_create(table, mode | LOCK_WAIT, trx); 03567 03568 /* Check if a deadlock occurs: if yes, remove the lock request and 03569 return an error code */ 03570 03571 if (lock_deadlock_occurs(lock, trx)) { 03572 03573 lock_reset_lock_and_trx_wait(lock); 03574 lock_table_remove_low(lock); 03575 03576 return(DB_DEADLOCK); 03577 } 03578 03579 if (trx->wait_lock == NULL) { 03580 /* Deadlock resolution chose another transaction as a victim, 03581 and we accidentally got our lock granted! */ 03582 03583 return(DB_SUCCESS); 03584 } 03585 03586 trx->que_state = TRX_QUE_LOCK_WAIT; 03587 trx->was_chosen_as_deadlock_victim = FALSE; 03588 trx->wait_started = time(NULL); 03589 03590 ut_a(que_thr_stop(thr)); 03591 03592 return(DB_LOCK_WAIT); 03593 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE lock_t* lock_table_has | ( | trx_t * | trx, | |
| dict_table_t * | table, | |||
| ulint | mode | |||
| ) |
Definition at line 1447 of file lock0lock.c.
References kernel_mutex, lock, lock_get_mode(), lock_get_wait(), lock_mode_stronger_or_eq(), dict_table_struct::locks, NULL, ut_ad, UT_LIST_GET_LAST, and UT_LIST_GET_PREV.
Referenced by lock_clust_rec_modify_check_and_lock(), lock_clust_rec_read_check_and_lock(), lock_rec_insert_check_and_lock(), lock_rec_lock(), lock_rec_lock_fast(), lock_rec_lock_slow(), lock_sec_rec_modify_check_and_lock(), lock_sec_rec_read_check_and_lock(), and lock_table().
01449 : lock or NULL */ 01450 trx_t* trx, /* in: transaction */ 01451 dict_table_t* table, /* in: table */ 01452 ulint mode) /* in: lock mode */ 01453 { 01454 lock_t* lock; 01455 01456 #ifdef UNIV_SYNC_DEBUG 01457 ut_ad(mutex_own(&kernel_mutex)); 01458 #endif /* UNIV_SYNC_DEBUG */ 01459 01460 /* Look for stronger locks the same trx already has on the table */ 01461 01462 lock = UT_LIST_GET_LAST(table->locks); 01463 01464 while (lock != NULL) { 01465 01466 if (lock->trx == trx 01467 && lock_mode_stronger_or_eq(lock_get_mode(lock), mode)) { 01468 01469 /* The same trx already has locked the table in 01470 a mode stronger or equal to the mode given */ 01471 01472 ut_ad(!lock_get_wait(lock)); 01473 01474 return(lock); 01475 } 01476 01477 lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock); 01478 } 01479 01480 return(NULL); 01481 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ibool lock_table_has_to_wait_in_queue | ( | lock_t * | wait_lock | ) | [static] |
Definition at line 3726 of file lock0lock.c.
References FALSE, lock, lock_get_wait(), lock_has_to_wait(), dict_table_struct::locks, lock_struct::tab_lock, lock_table_struct::table, TRUE, lock_struct::un_member, ut_ad, UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by lock_table_dequeue(), and lock_table_queue_validate().
03728 : TRUE if still has to wait */ 03729 lock_t* wait_lock) /* in: waiting table lock */ 03730 { 03731 dict_table_t* table; 03732 lock_t* lock; 03733 03734 ut_ad(lock_get_wait(wait_lock)); 03735 03736 table = wait_lock->un_member.tab_lock.table; 03737 03738 lock = UT_LIST_GET_FIRST(table->locks); 03739 03740 while (lock != wait_lock) { 03741 03742 if (lock_has_to_wait(wait_lock, lock)) { 03743 03744 return(TRUE); 03745 } 03746 03747 lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock); 03748 } 03749 03750 return(FALSE); 03751 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE ibool lock_table_other_has_incompatible | ( | trx_t * | trx, | |
| ulint | wait, | |||
| dict_table_t * | table, | |||
| ulint | mode | |||
| ) |
Definition at line 3600 of file lock0lock.c.
References FALSE, kernel_mutex, lock, lock_get_mode(), lock_get_wait(), lock_mode_compatible(), dict_table_struct::locks, NULL, TRUE, ut_ad, UT_LIST_GET_LAST, and UT_LIST_GET_PREV.
Referenced by lock_table(), and lock_table_queue_validate().
03602 : transaction, or NULL if all 03603 transactions should be included */ 03604 ulint wait, /* in: LOCK_WAIT if also waiting locks are 03605 taken into account, or 0 if not */ 03606 dict_table_t* table, /* in: table */ 03607 ulint mode) /* in: lock mode */ 03608 { 03609 lock_t* lock; 03610 03611 #ifdef UNIV_SYNC_DEBUG 03612 ut_ad(mutex_own(&kernel_mutex)); 03613 #endif /* UNIV_SYNC_DEBUG */ 03614 03615 lock = UT_LIST_GET_LAST(table->locks); 03616 03617 while (lock != NULL) { 03618 03619 if ((lock->trx != trx) 03620 && (!lock_mode_compatible(lock_get_mode(lock), mode)) 03621 && (wait || !(lock_get_wait(lock)))) { 03622 03623 return(TRUE); 03624 } 03625 03626 lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock); 03627 } 03628 03629 return(FALSE); 03630 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void lock_table_print | ( | FILE * | file, | |
| lock_t * | lock | |||
| ) |
Definition at line 4066 of file lock0lock.c.
References kernel_mutex, lock, LOCK_AUTO_INC, lock_get_mode(), lock_get_type(), lock_get_wait(), LOCK_IS, LOCK_IX, LOCK_S, LOCK_TABLE, LOCK_X, TRUE, ut_a, ut_ad, and ut_print_name().
Referenced by lock_deadlock_recursive(), and lock_print_info_all_transactions().
04068 : file where to print */ 04069 lock_t* lock) /* in: table type lock */ 04070 { 04071 #ifdef UNIV_SYNC_DEBUG 04072 ut_ad(mutex_own(&kernel_mutex)); 04073 #endif /* UNIV_SYNC_DEBUG */ 04074 ut_a(lock_get_type(lock) == LOCK_TABLE); 04075 04076 fputs("TABLE LOCK table ", file); 04077 ut_print_name(file, lock->trx, TRUE, 04078 lock->un_member.tab_lock.table->name); 04079 fprintf(file, " trx id %lu %lu", 04080 (ulong) (lock->trx)->id.high, (ulong) (lock->trx)->id.low); 04081 04082 if (lock_get_mode(lock) == LOCK_S) { 04083 fputs(" lock mode S", file); 04084 } else if (lock_get_mode(lock) == LOCK_X) { 04085 fputs(" lock mode X", file); 04086 } else if (lock_get_mode(lock) == LOCK_IS) { 04087 fputs(" lock mode IS", file); 04088 } else if (lock_get_mode(lock) == LOCK_IX) { 04089 fputs(" lock mode IX", file); 04090 } else if (lock_get_mode(lock) == LOCK_AUTO_INC) { 04091 fputs(" lock mode AUTO-INC", file); 04092 } else { 04093 fprintf(file, " unknown lock mode %lu", (ulong) lock_get_mode(lock)); 04094 } 04095 04096 if (lock_get_wait(lock)) { 04097 fputs(" waiting", file); 04098 } 04099 04100 putc('\n', file); 04101 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool lock_table_queue_validate | ( | dict_table_t * | table | ) |
Definition at line 4459 of file lock0lock.c.
References FALSE, kernel_mutex, lock, lock_get_mode(), lock_get_wait(), lock_table_has_to_wait_in_queue(), lock_table_other_has_incompatible(), dict_table_struct::locks, TRUE, TRX_ACTIVE, TRX_COMMITTED_IN_MEMORY, TRX_PREPARED, ut_a, ut_ad, UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by lock_validate().
04461 : TRUE if ok */ 04462 dict_table_t* table) /* in: table */ 04463 { 04464 lock_t* lock; 04465 ibool is_waiting; 04466 04467 #ifdef UNIV_SYNC_DEBUG 04468 ut_ad(mutex_own(&kernel_mutex)); 04469 #endif /* UNIV_SYNC_DEBUG */ 04470 04471 is_waiting = FALSE; 04472 04473 lock = UT_LIST_GET_FIRST(table->locks); 04474 04475 while (lock) { 04476 ut_a(((lock->trx)->conc_state == TRX_ACTIVE) 04477 || ((lock->trx)->conc_state == TRX_PREPARED) 04478 || ((lock->trx)->conc_state == TRX_COMMITTED_IN_MEMORY)); 04479 04480 if (!lock_get_wait(lock)) { 04481 04482 ut_a(!is_waiting); 04483 04484 ut_a(!lock_table_other_has_incompatible(lock->trx, 0, 04485 table, lock_get_mode(lock))); 04486 } else { 04487 is_waiting = TRUE; 04488 04489 ut_a(lock_table_has_to_wait_in_queue(lock)); 04490 } 04491 04492 lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock); 04493 } 04494 04495 return(TRUE); 04496 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE void lock_table_remove_low | ( | lock_t * | lock | ) |
Definition at line 3494 of file lock0lock.c.
References trx_struct::auto_inc_lock, kernel_mutex, lock, dict_table_struct::locks, NULL, trx_struct::trx_locks, ut_ad, and UT_LIST_REMOVE.
Referenced by lock_reset_all_on_table_for_trx(), lock_table_dequeue(), and lock_table_enqueue_waiting().
03496 : table lock */ 03497 { 03498 dict_table_t* table; 03499 trx_t* trx; 03500 03501 #ifdef UNIV_SYNC_DEBUG 03502 ut_ad(mutex_own(&kernel_mutex)); 03503 #endif /* UNIV_SYNC_DEBUG */ 03504 03505 table = lock->un_member.tab_lock.table; 03506 trx = lock->trx; 03507 03508 if (lock == trx->auto_inc_lock) { 03509 trx->auto_inc_lock = NULL; 03510 } 03511 03512 UT_LIST_REMOVE(trx_locks, trx->trx_locks, lock); 03513 UT_LIST_REMOVE(un_member.tab_lock.locks, table->locks, lock); 03514 }
Here is the caller graph for this function:

| void lock_table_unlock | ( | lock_t * | lock | ) |
Definition at line 3868 of file lock0lock.c.
References kernel_mutex, lock, lock_table_dequeue(), mutex_enter, and mutex_exit().
03870 : lock */ 03871 { 03872 mutex_enter(&kernel_mutex); 03873 03874 lock_table_dequeue(lock); 03875 03876 mutex_exit(&kernel_mutex); 03877 }
Here is the call graph for this function:

| void lock_table_unlock_auto_inc | ( | trx_t * | trx | ) |
Definition at line 3884 of file lock0lock.c.
References trx_struct::auto_inc_lock, kernel_mutex, lock_table_dequeue(), mutex_enter, and mutex_exit().
Referenced by row_unlock_table_autoinc_for_mysql().

