~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/lock/lock0lock.c

Tags: innodb-plugin-1.0.2
InnoDB Plugin 1.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
2166
2166
void
2167
2167
lock_grant(
2168
2168
/*=======*/
2169
 
        lock_t* lock)   /* in: waiting lock request */
 
2169
        lock_t* lock)   /* in/out: waiting lock request */
2170
2170
{
2171
2171
        ut_ad(mutex_own(&kernel_mutex));
2172
2172
 
2173
2173
        lock_reset_lock_and_trx_wait(lock);
2174
2174
 
2175
2175
        if (lock_get_mode(lock) == LOCK_AUTO_INC) {
 
2176
                trx_t*          trx = lock->trx;
 
2177
                dict_table_t*   table = lock->un_member.tab_lock.table;
2176
2178
 
2177
 
                if (lock->trx->auto_inc_lock != NULL) {
 
2179
                if (table->autoinc_trx == trx) {
2178
2180
                        fprintf(stderr,
2179
2181
                                "InnoDB: Error: trx already had"
2180
2182
                                " an AUTO-INC lock!\n");
 
2183
                } else {
 
2184
                        table->autoinc_trx = trx;
 
2185
 
 
2186
                        ib_vector_push(trx->autoinc_locks, lock);
2181
2187
                }
2182
 
 
2183
 
                /* Store pointer to lock to trx so that we know to
2184
 
                release it at the end of the SQL statement */
2185
 
 
2186
 
                lock->trx->auto_inc_lock = lock;
2187
2188
        }
2188
2189
 
2189
2190
#ifdef UNIV_DEBUG
3531
3532
                ++table->n_waiting_or_granted_auto_inc_locks;
3532
3533
        }
3533
3534
 
 
3535
        /* For AUTOINC locking we reuse the lock instance only if
 
3536
        there is no wait involved else we allocate the waiting lock
 
3537
        from the transaction lock heap. */
3534
3538
        if (type_mode == LOCK_AUTO_INC) {
3535
 
                /* Only one trx can have the lock on the table
3536
 
                at a time: we may use the memory preallocated
3537
 
                to the table object */
3538
 
 
3539
 
                lock = table->auto_inc_lock;
3540
 
 
3541
 
                ut_a(trx->auto_inc_lock == NULL);
3542
 
                trx->auto_inc_lock = lock;
 
3539
 
 
3540
                lock = table->autoinc_lock;
 
3541
 
 
3542
                table->autoinc_trx = trx;
 
3543
 
 
3544
                ib_vector_push(trx->autoinc_locks, lock);
3543
3545
        } else {
3544
3546
                lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t));
3545
3547
        }
3571
3573
/*==================*/
3572
3574
        lock_t* lock)   /* in: table lock */
3573
3575
{
 
3576
        trx_t*          trx;
3574
3577
        dict_table_t*   table;
3575
 
        trx_t*          trx;
3576
3578
 
3577
3579
        ut_ad(mutex_own(&kernel_mutex));
3578
3580
 
 
3581
        trx = lock->trx;
3579
3582
        table = lock->un_member.tab_lock.table;
3580
 
        trx = lock->trx;
3581
 
 
3582
 
        if (lock == trx->auto_inc_lock) {
3583
 
                trx->auto_inc_lock = NULL;
 
3583
 
 
3584
        /* Remove the table from the transaction's AUTOINC vector, if
 
3585
        the lock that is being release is an AUTOINC lock. */
 
3586
        if (lock_get_mode(lock) == LOCK_AUTO_INC) {
 
3587
 
 
3588
                /* The table's AUTOINC lock can get transferred to
 
3589
                another transaction before we get here. */
 
3590
                if (table->autoinc_trx == trx) {
 
3591
                        table->autoinc_trx = NULL;
 
3592
                }
 
3593
 
 
3594
                /* The locks must be freed in the reverse order from
 
3595
                the one in which they were acquired. This is to avoid
 
3596
                traversing the AUTOINC lock vector unnecessarily. 
 
3597
 
 
3598
                We only store locks that were granted in the
 
3599
                trx->autoinc_locks vector (see lock_table_create()
 
3600
                and lock_grant()). Therefore it can be empty and we
 
3601
                need to check for that. */
 
3602
 
 
3603
                if (!ib_vector_is_empty(trx->autoinc_locks)) {
 
3604
                        lock_t* autoinc_lock;
 
3605
 
 
3606
                        autoinc_lock = ib_vector_pop(trx->autoinc_locks);
 
3607
                        ut_a(autoinc_lock == lock);
 
3608
                }
3584
3609
 
3585
3610
                ut_a(table->n_waiting_or_granted_auto_inc_locks > 0);
3586
3611
                --table->n_waiting_or_granted_auto_inc_locks;
3956
3981
}
3957
3982
 
3958
3983
/*************************************************************************
3959
 
Releases an auto-inc lock a transaction possibly has on a table.
3960
 
Releases possible other transactions waiting for this lock. */
3961
 
UNIV_INTERN
3962
 
void
3963
 
lock_table_unlock_auto_inc(
3964
 
/*=======================*/
3965
 
        trx_t*  trx)    /* in: transaction */
3966
 
{
3967
 
        if (trx->auto_inc_lock) {
3968
 
                mutex_enter(&kernel_mutex);
3969
 
 
3970
 
                lock_table_dequeue(trx->auto_inc_lock);
3971
 
 
3972
 
                mutex_exit(&kernel_mutex);
3973
 
        }
3974
 
}
3975
 
 
3976
 
/*************************************************************************
3977
3984
Releases transaction locks, and releases possible other transactions waiting
3978
3985
because of these locks. */
3979
3986
UNIV_INTERN
4032
4039
                lock = UT_LIST_GET_LAST(trx->trx_locks);
4033
4040
        }
4034
4041
 
 
4042
        ut_a(ib_vector_size(trx->autoinc_locks) == 0);
 
4043
 
4035
4044
        mem_heap_empty(trx->lock_heap);
4036
 
 
4037
 
        ut_a(trx->auto_inc_lock == NULL);
4038
4045
}
4039
4046
 
4040
4047
/*************************************************************************
4054
4061
        } else {
4055
4062
                ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
4056
4063
 
 
4064
                if (lock->trx->autoinc_locks != NULL) {
 
4065
                        /* Release the transaction's AUTOINC locks/ */
 
4066
                        lock_release_autoinc_locks(lock->trx);
 
4067
                }
 
4068
 
4057
4069
                lock_table_dequeue(lock);
4058
4070
        }
4059
4071
 
4066
4078
        trx_end_lock_wait(lock->trx);
4067
4079
}
4068
4080
 
 
4081
/* True if a lock mode is S or X */
 
4082
#define IS_LOCK_S_OR_X(lock) \
 
4083
        (lock_get_mode(lock) == LOCK_S \
 
4084
         || lock_get_mode(lock) == LOCK_X)
 
4085
 
 
4086
 
4069
4087
/*************************************************************************
4070
 
Resets all record and table locks of a transaction on a table to be dropped.
4071
 
No lock is allowed to be a wait lock. */
 
4088
Removes locks of a transaction on a table to be dropped.
 
4089
If remove_also_table_sx_locks is TRUE then table-level S and X locks are
 
4090
also removed in addition to other table-level and record-level locks.
 
4091
No lock, that is going to be removed, is allowed to be a wait lock. */
4072
4092
static
4073
4093
void
4074
 
lock_reset_all_on_table_for_trx(
4075
 
/*============================*/
4076
 
        dict_table_t*   table,  /* in: table to be dropped */
4077
 
        trx_t*          trx)    /* in: a transaction */
 
4094
lock_remove_all_on_table_for_trx(
 
4095
/*=============================*/
 
4096
        dict_table_t*   table,                  /* in: table to be dropped */
 
4097
        trx_t*          trx,                    /* in: a transaction */
 
4098
        ibool           remove_also_table_sx_locks)/* in: also removes
 
4099
                                                table S and X locks */
4078
4100
{
4079
4101
        lock_t* lock;
4080
4102
        lock_t* prev_lock;
4092
4114
 
4093
4115
                        lock_rec_discard(lock);
4094
4116
                } else if (lock_get_type_low(lock) & LOCK_TABLE
4095
 
                           && lock->un_member.tab_lock.table == table) {
 
4117
                           && lock->un_member.tab_lock.table == table
 
4118
                           && (remove_also_table_sx_locks
 
4119
                               || !IS_LOCK_S_OR_X(lock))) {
4096
4120
 
4097
4121
                        ut_a(!lock_get_wait(lock));
4098
4122
 
4104
4128
}
4105
4129
 
4106
4130
/*************************************************************************
4107
 
Resets all locks, both table and record locks, on a table to be dropped.
4108
 
No lock is allowed to be a wait lock. */
 
4131
Removes locks on a table to be dropped or truncated.
 
4132
If remove_also_table_sx_locks is TRUE then table-level S and X locks are
 
4133
also removed in addition to other table-level and record-level locks.
 
4134
No lock, that is going to be removed, is allowed to be a wait lock. */
4109
4135
UNIV_INTERN
4110
4136
void
4111
 
lock_reset_all_on_table(
4112
 
/*====================*/
4113
 
        dict_table_t*   table)  /* in: table to be dropped */
 
4137
lock_remove_all_on_table(
 
4138
/*=====================*/
 
4139
        dict_table_t*   table,                  /* in: table to be dropped
 
4140
                                                or truncated */
 
4141
        ibool           remove_also_table_sx_locks)/* in: also removes
 
4142
                                                table S and X locks */
4114
4143
{
4115
4144
        lock_t* lock;
 
4145
        lock_t* prev_lock;
4116
4146
 
4117
4147
        mutex_enter(&kernel_mutex);
4118
4148
 
4119
4149
        lock = UT_LIST_GET_FIRST(table->locks);
4120
4150
 
4121
 
        while (lock) {
4122
 
                ut_a(!lock_get_wait(lock));
4123
 
 
4124
 
                lock_reset_all_on_table_for_trx(table, lock->trx);
4125
 
 
4126
 
                lock = UT_LIST_GET_FIRST(table->locks);
 
4151
        while (lock != NULL) {
 
4152
 
 
4153
                prev_lock = UT_LIST_GET_PREV(un_member.tab_lock.locks,
 
4154
                                             lock);
 
4155
 
 
4156
                /* If we should remove all locks (remove_also_table_sx_locks
 
4157
                is TRUE), or if the lock is not table-level S or X lock,
 
4158
                then check we are not going to remove a wait lock. */
 
4159
                if (remove_also_table_sx_locks
 
4160
                    || !(lock_get_type(lock) == LOCK_TABLE
 
4161
                         && IS_LOCK_S_OR_X(lock))) {
 
4162
 
 
4163
                        ut_a(!lock_get_wait(lock));
 
4164
                }
 
4165
 
 
4166
                lock_remove_all_on_table_for_trx(table, lock->trx,
 
4167
                                                 remove_also_table_sx_locks);
 
4168
 
 
4169
                if (prev_lock == NULL) {
 
4170
                        if (lock == UT_LIST_GET_FIRST(table->locks)) {
 
4171
                                /* lock was not removed, pick its successor */
 
4172
                                lock = UT_LIST_GET_NEXT(
 
4173
                                        un_member.tab_lock.locks, lock);
 
4174
                        } else {
 
4175
                                /* lock was removed, pick the first one */
 
4176
                                lock = UT_LIST_GET_FIRST(table->locks);
 
4177
                        }
 
4178
                } else if (UT_LIST_GET_NEXT(un_member.tab_lock.locks,
 
4179
                                            prev_lock) != lock) {
 
4180
                        /* If lock was removed by
 
4181
                        lock_remove_all_on_table_for_trx() then pick the
 
4182
                        successor of prev_lock ... */
 
4183
                        lock = UT_LIST_GET_NEXT(
 
4184
                                un_member.tab_lock.locks, prev_lock);
 
4185
                } else {
 
4186
                        /* ... otherwise pick the successor of lock. */
 
4187
                        lock = UT_LIST_GET_NEXT(
 
4188
                                un_member.tab_lock.locks, lock);
 
4189
                }
4127
4190
        }
4128
4191
 
4129
4192
        mutex_exit(&kernel_mutex);
4264
4327
}
4265
4328
 
4266
4329
#ifndef UNIV_HOTBACKUP
 
4330
 
 
4331
#ifdef UNIV_DEBUG
 
4332
/* Print the number of lock structs from lock_print_info_summary() only
 
4333
in non-production builds for performance reasons, see
 
4334
http://bugs.mysql.com/36942 */
 
4335
#define PRINT_NUM_OF_LOCK_STRUCTS
 
4336
#endif /* UNIV_DEBUG */
 
4337
 
 
4338
#ifdef PRINT_NUM_OF_LOCK_STRUCTS
4267
4339
/*************************************************************************
4268
4340
Calculates the number of record lock structs in the record lock hash table. */
4269
4341
static
4290
4362
 
4291
4363
        return(n_locks);
4292
4364
}
 
4365
#endif /* PRINT_NUM_OF_LOCK_STRUCTS */
4293
4366
 
4294
4367
/*************************************************************************
4295
4368
Prints info of locks for all transactions. */
4331
4404
                "History list length %lu\n",
4332
4405
                (ulong) trx_sys->rseg_history_len);
4333
4406
 
 
4407
#ifdef PRINT_NUM_OF_LOCK_STRUCTS
4334
4408
        fprintf(file,
4335
4409
                "Total number of lock structs in row lock hash table %lu\n",
4336
4410
                (ulong) lock_get_n_rec_locks());
 
4411
#endif /* PRINT_NUM_OF_LOCK_STRUCTS */
4337
4412
}
4338
4413
 
4339
4414
/*************************************************************************
4687
4762
 
4688
4763
        block = buf_page_get(space, fil_space_get_zip_size(space),
4689
4764
                             page_no, RW_X_LATCH, &mtr);
4690
 
#ifdef UNIV_SYNC_DEBUG
4691
4765
        buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
4692
 
#endif /* UNIV_SYNC_DEBUG */
 
4766
 
4693
4767
        page = block->frame;
4694
4768
 
4695
4769
        lock_mutex_enter_kernel();
5325
5399
}
5326
5400
 
5327
5401
/***********************************************************************
 
5402
Release the last lock from the transaction's autoinc locks. */
 
5403
UNIV_INLINE
 
5404
void
 
5405
lock_release_autoinc_last_lock(
 
5406
/*===========================*/
 
5407
        ib_vector_t*    autoinc_locks)  /* in/out: vector of AUTOINC locks */
 
5408
{
 
5409
        ulint           last;
 
5410
        lock_t*         lock;
 
5411
 
 
5412
        ut_ad(mutex_own(&kernel_mutex));
 
5413
        ut_a(!ib_vector_is_empty(autoinc_locks));
 
5414
 
 
5415
        /* The lock to be release must be the last lock acquired. */
 
5416
        last = ib_vector_size(autoinc_locks) - 1;
 
5417
        lock = ib_vector_get(autoinc_locks, last);
 
5418
 
 
5419
        /* Should have only AUTOINC locks in the vector. */
 
5420
        ut_a(lock_get_mode(lock) == LOCK_AUTO_INC);
 
5421
        ut_a(lock_get_type(lock) == LOCK_TABLE);
 
5422
 
 
5423
        ut_a(lock->un_member.tab_lock.table != NULL);
 
5424
 
 
5425
        /* This will remove the lock from the trx autoinc_locks too. */
 
5426
        lock_table_dequeue(lock);
 
5427
}
 
5428
 
 
5429
/***********************************************************************
 
5430
Release all the transaction's autoinc locks. */
 
5431
UNIV_INTERN
 
5432
void
 
5433
lock_release_autoinc_locks(
 
5434
/*=======================*/
 
5435
        trx_t*          trx)            /* in/out: transaction */
 
5436
{
 
5437
        ut_ad(mutex_own(&kernel_mutex));
 
5438
 
 
5439
        ut_a(trx->autoinc_locks != NULL);
 
5440
 
 
5441
        /* We release the locks in the reverse order. This is to
 
5442
        avoid searching the vector for the element to delete at
 
5443
        the lower level. See (lock_table_remove_low()) for details. */
 
5444
        while (!ib_vector_is_empty(trx->autoinc_locks)) {
 
5445
 
 
5446
                /* lock_table_remove_low() will also remove the lock from
 
5447
                the transaction's autoinc_locks vector. */
 
5448
                lock_release_autoinc_last_lock(trx->autoinc_locks);
 
5449
        }
 
5450
 
 
5451
        /* Should release all locks. */
 
5452
        ut_a(ib_vector_is_empty(trx->autoinc_locks));
 
5453
}
 
5454
 
 
5455
/***********************************************************************
5328
5456
Gets the type of a lock. Non-inline version for using outside of the
5329
5457
lock module. */
5330
5458
UNIV_INTERN