~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/lock/lock0lock.cc

  • Committer: Monty Taylor
  • Date: 2011-02-13 17:26:39 UTC
  • mfrom: (2157.2.2 give-in-to-pkg-config)
  • mto: This revision was merged to the branch mainline in revision 2166.
  • Revision ID: mordred@inaugust.com-20110213172639-nhy7i72sfhoq13ms
Merged in pkg-config fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
466
466
        /* A sanity check: the trx_id in rec must be smaller than the global
467
467
        trx id counter */
468
468
 
469
 
        if (ut_dulint_cmp(trx_id, trx_sys->max_trx_id) >= 0) {
 
469
        if (UNIV_UNLIKELY(trx_id >= trx_sys->max_trx_id)) {
470
470
                ut_print_timestamp(stderr);
471
471
                fputs("  InnoDB: Error: transaction id associated"
472
472
                      " with record\n",
479
479
                        " global trx id counter " TRX_ID_FMT "!\n"
480
480
                        "InnoDB: The table is corrupt. You have to do"
481
481
                        " dump + drop + reimport.\n",
482
 
                        TRX_ID_PREP_PRINTF(trx_id),
483
 
                        TRX_ID_PREP_PRINTF(trx_sys->max_trx_id));
 
482
                        trx_id, trx_sys->max_trx_id);
484
483
 
485
484
                is_ok = FALSE;
486
485
        }
554
553
        }
555
554
 
556
555
        max_trx_id = page_get_max_trx_id(page_align(rec));
557
 
        ut_ad(!ut_dulint_is_zero(max_trx_id));
 
556
        ut_ad(max_trx_id);
558
557
 
559
 
        return(ut_dulint_cmp(max_trx_id, view->up_limit_id) < 0);
 
558
        return(max_trx_id < view->up_limit_id);
560
559
}
561
560
 
562
561
/*********************************************************************//**
567
566
/*============*/
568
567
        ulint   n_cells)        /*!< in: number of slots in lock hash table */
569
568
{
570
 
        lock_sys = mem_alloc(sizeof(lock_sys_t));
 
569
        lock_sys = static_cast<lock_sys_t *>(mem_alloc(sizeof(lock_sys_t)));
571
570
 
572
571
        lock_sys->rec_hash = hash_create(n_cells);
573
572
 
616
615
{
617
616
        ut_ad(lock);
618
617
 
619
 
        return(lock->type_mode & LOCK_MODE_MASK);
 
618
        return static_cast<lock_mode>(lock->type_mode & LOCK_MODE_MASK);
620
619
}
621
620
 
622
621
/*********************************************************************//**
919
918
        ut_ad(lock_get_type_low(lock2) == LOCK_REC);
920
919
 
921
920
        if (trx != lock2->trx
922
 
            && !lock_mode_compatible(LOCK_MODE_MASK & type_mode,
 
921
            && !lock_mode_compatible(static_cast<lock_mode>(LOCK_MODE_MASK & type_mode),
923
922
                                     lock_get_mode(lock2))) {
924
923
 
925
924
                /* We have somewhat complex rules when gap type record locks
1114
1113
        page_no = lock->un_member.rec_lock.page_no;
1115
1114
 
1116
1115
        for (;;) {
1117
 
                lock = HASH_GET_NEXT(hash, lock);
 
1116
                lock = static_cast<lock_t *>(HASH_GET_NEXT(hash, lock));
1118
1117
 
1119
1118
                if (!lock) {
1120
1119
 
1146
1145
 
1147
1146
        ut_ad(mutex_own(&kernel_mutex));
1148
1147
 
1149
 
        lock = HASH_GET_FIRST(lock_sys->rec_hash,
1150
 
                              lock_rec_hash(space, page_no));
 
1148
        lock = static_cast<lock_t *>(HASH_GET_FIRST(lock_sys->rec_hash,
 
1149
                              lock_rec_hash(space, page_no)));
1151
1150
        while (lock) {
1152
1151
                if ((lock->un_member.rec_lock.space == space)
1153
1152
                    && (lock->un_member.rec_lock.page_no == page_no)) {
1155
1154
                        break;
1156
1155
                }
1157
1156
 
1158
 
                lock = HASH_GET_NEXT(hash, lock);
 
1157
                lock = static_cast<lock_t *>(HASH_GET_NEXT(hash, lock));
1159
1158
        }
1160
1159
 
1161
1160
        return(lock);
1205
1204
 
1206
1205
        hash = buf_block_get_lock_hash_val(block);
1207
1206
 
1208
 
        lock = HASH_GET_FIRST(lock_sys->rec_hash, hash);
 
1207
        lock = static_cast<lock_t *>(HASH_GET_FIRST(lock_sys->rec_hash, hash));
1209
1208
 
1210
1209
        while (lock) {
1211
1210
                if ((lock->un_member.rec_lock.space == space)
1214
1213
                        break;
1215
1214
                }
1216
1215
 
1217
 
                lock = HASH_GET_NEXT(hash, lock);
 
1216
                lock = static_cast<lock_t *>(HASH_GET_NEXT(hash, lock));
1218
1217
        }
1219
1218
 
1220
1219
        return(lock);
1304
1303
 
1305
1304
        size = sizeof(lock_t) + lock_rec_get_n_bits(lock) / 8;
1306
1305
 
1307
 
        return(mem_heap_dup(heap, lock, size));
 
1306
        return static_cast<lock_t *>(mem_heap_dup(heap, lock, size));
1308
1307
}
1309
1308
 
1310
1309
/*********************************************************************//**
1419
1418
        while (lock) {
1420
1419
                if (lock->trx == trx
1421
1420
                    && lock_mode_stronger_or_eq(lock_get_mode(lock),
1422
 
                                                precise_mode & LOCK_MODE_MASK)
 
1421
                                                static_cast<lock_mode>(precise_mode & LOCK_MODE_MASK))
1423
1422
                    && !lock_get_wait(lock)
1424
1423
                    && (!lock_rec_get_rec_not_gap(lock)
1425
1424
                        || (precise_mode & LOCK_REC_NOT_GAP)
1592
1591
        max trx id to the log, and therefore during recovery, this value
1593
1592
        for a page may be incorrect. */
1594
1593
 
1595
 
        if (!(ut_dulint_cmp(page_get_max_trx_id(page),
1596
 
                            trx_list_get_min_trx_id()) >= 0)
 
1594
        if (page_get_max_trx_id(page) < trx_list_get_min_trx_id()
1597
1595
            && !recv_recovery_is_on()) {
1598
1596
 
1599
1597
                return(NULL);
1622
1620
ulint
1623
1621
lock_number_of_rows_locked(
1624
1622
/*=======================*/
1625
 
        trx_t*  trx)    /*!< in: transaction */
 
1623
        const trx_t*    trx)    /*!< in: transaction */
1626
1624
{
1627
1625
        lock_t* lock;
1628
1626
        ulint   n_records = 0;
1696
1694
        n_bits = page_dir_get_n_heap(page) + LOCK_PAGE_BITMAP_MARGIN;
1697
1695
        n_bytes = 1 + n_bits / 8;
1698
1696
 
1699
 
        lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t) + n_bytes);
 
1697
        lock = static_cast<lock_t *>(mem_heap_alloc(trx->lock_heap, sizeof(lock_t) + n_bytes));
1700
1698
 
1701
1699
        UT_LIST_ADD_LAST(trx_locks, trx->trx_locks, lock);
1702
1700
 
1731
1729
Enqueues a waiting request for a lock which cannot be granted immediately.
1732
1730
Checks for deadlocks.
1733
1731
@return DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED, or
1734
 
DB_SUCCESS; DB_SUCCESS means that there was a deadlock, but another
1735
 
transaction was chosen as a victim, and we got the lock immediately:
1736
 
no need to wait then */
 
1732
DB_SUCCESS_LOCKED_REC; DB_SUCCESS_LOCKED_REC means that
 
1733
there was a deadlock, but another transaction was chosen as a victim,
 
1734
and we got the lock immediately: no need to wait then */
1737
1735
static
1738
 
ulint
 
1736
enum db_err
1739
1737
lock_rec_enqueue_waiting(
1740
1738
/*=====================*/
1741
1739
        ulint                   type_mode,/*!< in: lock mode this
1807
1805
 
1808
1806
        if (trx->wait_lock == NULL) {
1809
1807
 
1810
 
                return(DB_SUCCESS);
 
1808
                return(DB_SUCCESS_LOCKED_REC);
1811
1809
        }
1812
1810
 
1813
1811
        trx->que_state = TRX_QUE_LOCK_WAIT;
1818
1816
 
1819
1817
#ifdef UNIV_DEBUG
1820
1818
        if (lock_print_waits) {
1821
 
                fprintf(stderr, "Lock wait for trx %lu in index ",
1822
 
                        (ulong) ut_dulint_get_low(trx->id));
 
1819
                fprintf(stderr, "Lock wait for trx " TRX_ID_FMT " in index ",
 
1820
                        trx->id);
1823
1821
                ut_print_name(stderr, trx, FALSE, index->name);
1824
1822
        }
1825
1823
#endif /* UNIV_DEBUG */
1923
1921
        return(lock_rec_create(type_mode, block, heap_no, index, trx));
1924
1922
}
1925
1923
 
 
1924
/** Record locking request status */
 
1925
enum lock_rec_req_status {
 
1926
        /** Failed to acquire a lock */
 
1927
        LOCK_REC_FAIL,
 
1928
        /** Succeeded in acquiring a lock (implicit or already acquired) */
 
1929
        LOCK_REC_SUCCESS,
 
1930
        /** Explicitly created a new lock */
 
1931
        LOCK_REC_SUCCESS_CREATED
 
1932
};
 
1933
 
1926
1934
/*********************************************************************//**
1927
1935
This is a fast routine for locking a record in the most common cases:
1928
1936
there are no explicit locks on the page, or there is just one lock, owned
1930
1938
which does NOT look at implicit locks! Checks lock compatibility within
1931
1939
explicit locks. This function sets a normal next-key lock, or in the case of
1932
1940
a page supremum record, a gap type lock.
1933
 
@return TRUE if locking succeeded */
 
1941
@return whether the locking succeeded */
1934
1942
UNIV_INLINE
1935
 
ibool
 
1943
enum lock_rec_req_status
1936
1944
lock_rec_lock_fast(
1937
1945
/*===============*/
1938
1946
        ibool                   impl,   /*!< in: if TRUE, no lock is set
1971
1979
                        lock_rec_create(mode, block, heap_no, index, trx);
1972
1980
                }
1973
1981
 
1974
 
                return(TRUE);
 
1982
                return(LOCK_REC_SUCCESS_CREATED);
1975
1983
        }
1976
1984
 
1977
1985
        if (lock_rec_get_next_on_page(lock)) {
1978
1986
 
1979
 
                return(FALSE);
 
1987
                return(LOCK_REC_FAIL);
1980
1988
        }
1981
1989
 
1982
1990
        if (lock->trx != trx
1983
1991
            || lock->type_mode != (mode | LOCK_REC)
1984
1992
            || lock_rec_get_n_bits(lock) <= heap_no) {
1985
1993
 
1986
 
                return(FALSE);
 
1994
                return(LOCK_REC_FAIL);
1987
1995
        }
1988
1996
 
1989
1997
        if (!impl) {
1992
2000
 
1993
2001
                if (!lock_rec_get_nth_bit(lock, heap_no)) {
1994
2002
                        lock_rec_set_nth_bit(lock, heap_no);
 
2003
                        return(LOCK_REC_SUCCESS_CREATED);
1995
2004
                }
1996
2005
        }
1997
2006
 
1998
 
        return(TRUE);
 
2007
        return(LOCK_REC_SUCCESS);
1999
2008
}
2000
2009
 
2001
2010
/*********************************************************************//**
2003
2012
low-level function which does NOT look at implicit locks! Checks lock
2004
2013
compatibility within explicit locks. This function sets a normal next-key
2005
2014
lock, or in the case of a page supremum record, a gap type lock.
2006
 
@return DB_SUCCESS, DB_LOCK_WAIT, or error code */
 
2015
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
 
2016
or DB_QUE_THR_SUSPENDED */
2007
2017
static
2008
 
ulint
 
2018
enum db_err
2009
2019
lock_rec_lock_slow(
2010
2020
/*===============*/
2011
2021
        ibool                   impl,   /*!< in: if TRUE, no lock is set
2022
2032
        que_thr_t*              thr)    /*!< in: query thread */
2023
2033
{
2024
2034
        trx_t*  trx;
2025
 
        ulint   err;
2026
2035
 
2027
2036
        ut_ad(mutex_own(&kernel_mutex));
2028
2037
        ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
2041
2050
                /* The trx already has a strong enough lock on rec: do
2042
2051
                nothing */
2043
2052
 
2044
 
                err = DB_SUCCESS;
2045
 
        } else if (lock_rec_other_has_conflicting(mode, block, heap_no, trx)) {
 
2053
        } else if (lock_rec_other_has_conflicting(static_cast<lock_mode>(mode), block, heap_no, trx)) {
2046
2054
 
2047
2055
                /* If another transaction has a non-gap conflicting request in
2048
2056
                the queue, as this transaction does not have a lock strong
2049
2057
                enough already granted on the record, we have to wait. */
2050
2058
 
2051
 
                err = lock_rec_enqueue_waiting(mode, block, heap_no,
2052
 
                                               index, thr);
2053
 
        } else {
2054
 
                if (!impl) {
2055
 
                        /* Set the requested lock on the record */
2056
 
 
2057
 
                        lock_rec_add_to_queue(LOCK_REC | mode, block,
2058
 
                                              heap_no, index, trx);
2059
 
                }
2060
 
 
2061
 
                err = DB_SUCCESS;
 
2059
                return(lock_rec_enqueue_waiting(mode, block, heap_no,
 
2060
                                                index, thr));
 
2061
        } else if (!impl) {
 
2062
                /* Set the requested lock on the record */
 
2063
 
 
2064
                lock_rec_add_to_queue(LOCK_REC | mode, block,
 
2065
                                      heap_no, index, trx);
 
2066
                return(DB_SUCCESS_LOCKED_REC);
2062
2067
        }
2063
2068
 
2064
 
        return(err);
 
2069
        return(DB_SUCCESS);
2065
2070
}
2066
2071
 
2067
2072
/*********************************************************************//**
2070
2075
which does NOT look at implicit locks! Checks lock compatibility within
2071
2076
explicit locks. This function sets a normal next-key lock, or in the case
2072
2077
of a page supremum record, a gap type lock.
2073
 
@return DB_SUCCESS, DB_LOCK_WAIT, or error code */
 
2078
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
 
2079
or DB_QUE_THR_SUSPENDED */
2074
2080
static
2075
 
ulint
 
2081
enum db_err
2076
2082
lock_rec_lock(
2077
2083
/*==========*/
2078
2084
        ibool                   impl,   /*!< in: if TRUE, no lock is set
2088
2094
        dict_index_t*           index,  /*!< in: index of record */
2089
2095
        que_thr_t*              thr)    /*!< in: query thread */
2090
2096
{
2091
 
        ulint   err;
2092
 
 
2093
2097
        ut_ad(mutex_own(&kernel_mutex));
2094
2098
        ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
2095
2099
              || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
2101
2105
              || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
2102
2106
              || mode - (LOCK_MODE_MASK & mode) == 0);
2103
2107
 
2104
 
        if (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) {
2105
 
 
2106
 
                /* We try a simplified and faster subroutine for the most
2107
 
                common cases */
2108
 
 
2109
 
                err = DB_SUCCESS;
2110
 
        } else {
2111
 
                err = lock_rec_lock_slow(impl, mode, block,
2112
 
                                         heap_no, index, thr);
 
2108
        /* We try a simplified and faster subroutine for the most
 
2109
        common cases */
 
2110
        switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) {
 
2111
        case LOCK_REC_SUCCESS:
 
2112
                return(DB_SUCCESS);
 
2113
        case LOCK_REC_SUCCESS_CREATED:
 
2114
                return(DB_SUCCESS_LOCKED_REC);
 
2115
        case LOCK_REC_FAIL:
 
2116
                return(lock_rec_lock_slow(impl, mode, block,
 
2117
                                          heap_no, index, thr));
2113
2118
        }
2114
2119
 
2115
 
        return(err);
 
2120
        ut_error;
 
2121
        return(DB_ERROR);
2116
2122
}
2117
2123
 
2118
2124
/*********************************************************************//**
2183
2189
 
2184
2190
#ifdef UNIV_DEBUG
2185
2191
        if (lock_print_waits) {
2186
 
                fprintf(stderr, "Lock wait for trx %lu ends\n",
2187
 
                        (ulong) ut_dulint_get_low(lock->trx->id));
 
2192
                fprintf(stderr, "Lock wait for trx " TRX_ID_FMT " ends\n",
 
2193
                        lock->trx->id);
2188
2194
        }
2189
2195
#endif /* UNIV_DEBUG */
2190
2196
 
3472
3478
                                }
3473
3479
#endif /* UNIV_DEBUG */
3474
3480
 
3475
 
                                if (trx_weight_cmp(wait_lock->trx,
3476
 
                                                   start) >= 0) {
 
3481
                                if (trx_weight_ge(wait_lock->trx, start)) {
3477
3482
                                        /* Our recursion starting point
3478
3483
                                        transaction is 'smaller', let us
3479
3484
                                        choose 'start' as the victim and roll
3590
3595
 
3591
3596
                ib_vector_push(trx->autoinc_locks, lock);
3592
3597
        } else {
3593
 
                lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t));
 
3598
                lock = static_cast<lock_t *>(mem_heap_alloc(trx->lock_heap, sizeof(lock_t)));
3594
3599
        }
3595
3600
 
3596
3601
        UT_LIST_ADD_LAST(trx_locks, trx->trx_locks, lock);
3651
3656
                    && !ib_vector_is_empty(trx->autoinc_locks)) {
3652
3657
                        lock_t* autoinc_lock;
3653
3658
 
3654
 
                        autoinc_lock = ib_vector_pop(trx->autoinc_locks);
 
3659
                        autoinc_lock = static_cast<lock_t *>(ib_vector_pop(trx->autoinc_locks));
3655
3660
                        ut_a(autoinc_lock == lock);
3656
3661
                }
3657
3662
 
3733
3738
                /* Deadlock resolution chose another transaction as a victim,
3734
3739
                and we accidentally got our lock granted! */
3735
3740
 
3736
 
                return(DB_SUCCESS);
 
3741
                return(DB_SUCCESS_LOCKED_REC);
3737
3742
        }
3738
3743
 
3739
3744
        trx->que_state = TRX_QUE_LOCK_WAIT;
3802
3807
 
3803
3808
        if (flags & BTR_NO_LOCKING_FLAG) {
3804
3809
 
3805
 
                return(DB_SUCCESS);
 
3810
                return(DB_SUCCESS_LOCKED_REC);
3806
3811
        }
3807
3812
 
3808
3813
        ut_a(flags == 0);
3929
3934
        const rec_t*            rec,    /*!< in: record */
3930
3935
        enum lock_mode          lock_mode)/*!< in: LOCK_S or LOCK_X */
3931
3936
{
 
3937
        lock_t* first_lock;
3932
3938
        lock_t* lock;
3933
 
        lock_t* release_lock    = NULL;
3934
3939
        ulint   heap_no;
3935
3940
 
3936
3941
        ut_ad(trx && rec);
3940
3945
 
3941
3946
        mutex_enter(&kernel_mutex);
3942
3947
 
3943
 
        lock = lock_rec_get_first(block, heap_no);
 
3948
        first_lock = lock_rec_get_first(block, heap_no);
3944
3949
 
3945
3950
        /* Find the last lock with the same lock_mode and transaction
3946
3951
        from the record. */
3947
3952
 
3948
 
        while (lock != NULL) {
 
3953
        for (lock = first_lock; lock != NULL;
 
3954
             lock = lock_rec_get_next(heap_no, lock)) {
3949
3955
                if (lock->trx == trx && lock_get_mode(lock) == lock_mode) {
3950
 
                        release_lock = lock;
3951
3956
                        ut_a(!lock_get_wait(lock));
 
3957
                        lock_rec_reset_nth_bit(lock, heap_no);
 
3958
                        goto released;
3952
3959
                }
3953
 
 
3954
 
                lock = lock_rec_get_next(heap_no, lock);
3955
 
        }
3956
 
 
3957
 
        /* If a record lock is found, release the record lock */
3958
 
 
3959
 
        if (UNIV_LIKELY(release_lock != NULL)) {
3960
 
                lock_rec_reset_nth_bit(release_lock, heap_no);
3961
 
        } else {
3962
 
                mutex_exit(&kernel_mutex);
3963
 
                ut_print_timestamp(stderr);
3964
 
                fprintf(stderr,
3965
 
                        "  InnoDB: Error: unlock row could not"
3966
 
                        " find a %lu mode lock on the record\n",
3967
 
                        (ulong) lock_mode);
3968
 
 
3969
 
                return;
3970
 
        }
3971
 
 
 
3960
        }
 
3961
 
 
3962
        mutex_exit(&kernel_mutex);
 
3963
        ut_print_timestamp(stderr);
 
3964
        fprintf(stderr,
 
3965
                "  InnoDB: Error: unlock row could not"
 
3966
                " find a %lu mode lock on the record\n",
 
3967
                (ulong) lock_mode);
 
3968
 
 
3969
        return;
 
3970
 
 
3971
released:
3972
3972
        /* Check if we can now grant waiting lock requests */
3973
3973
 
3974
 
        lock = lock_rec_get_first(block, heap_no);
3975
 
 
3976
 
        while (lock != NULL) {
 
3974
        for (lock = first_lock; lock != NULL;
 
3975
             lock = lock_rec_get_next(heap_no, lock)) {
3977
3976
                if (lock_get_wait(lock)
3978
3977
                    && !lock_rec_has_to_wait_in_queue(lock)) {
3979
3978
 
3980
3979
                        /* Grant the lock */
3981
3980
                        lock_grant(lock);
3982
3981
                }
3983
 
 
3984
 
                lock = lock_rec_get_next(heap_no, lock);
3985
3982
        }
3986
3983
 
3987
3984
        mutex_exit(&kernel_mutex);
4017
4014
                        ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
4018
4015
 
4019
4016
                        if (lock_get_mode(lock) != LOCK_IS
4020
 
                            && !ut_dulint_is_zero(trx->undo_no)) {
 
4017
                            && trx->undo_no != 0) {
4021
4018
 
4022
4019
                                /* The trx may have modified the table. We
4023
4020
                                block the use of the MySQL query cache for
4216
4213
        fputs("TABLE LOCK table ", file);
4217
4214
        ut_print_name(file, lock->trx, TRUE,
4218
4215
                      lock->un_member.tab_lock.table->name);
4219
 
        fprintf(file, " trx id " TRX_ID_FMT,
4220
 
                TRX_ID_PREP_PRINTF(lock->trx->id));
 
4216
        fprintf(file, " trx id " TRX_ID_FMT, lock->trx->id);
4221
4217
 
4222
4218
        if (lock_get_mode(lock) == LOCK_S) {
4223
4219
                fputs(" lock mode S", file);
4270
4266
                (ulong) space, (ulong) page_no,
4271
4267
                (ulong) lock_rec_get_n_bits(lock));
4272
4268
        dict_index_name_print(file, lock->trx, lock->index);
4273
 
        fprintf(file, " trx id " TRX_ID_FMT,
4274
 
                TRX_ID_PREP_PRINTF(lock->trx->id));
 
4269
        fprintf(file, " trx id " TRX_ID_FMT, lock->trx->id);
4275
4270
 
4276
4271
        if (lock_get_mode(lock) == LOCK_S) {
4277
4272
                fputs(" lock mode S", file);
4406
4401
              "------------\n", file);
4407
4402
 
4408
4403
        fprintf(file, "Trx id counter " TRX_ID_FMT "\n",
4409
 
                TRX_ID_PREP_PRINTF(trx_sys->max_trx_id));
 
4404
                trx_sys->max_trx_id);
4410
4405
 
4411
4406
        fprintf(file,
4412
4407
                "Purge done for trx's n:o < " TRX_ID_FMT
4413
4408
                " undo n:o < " TRX_ID_FMT "\n",
4414
 
                TRX_ID_PREP_PRINTF(purge_sys->purge_trx_no),
4415
 
                TRX_ID_PREP_PRINTF(purge_sys->purge_undo_no));
 
4409
                purge_sys->purge_trx_no,
 
4410
                purge_sys->purge_undo_no);
4416
4411
 
4417
4412
        fprintf(file,
4418
4413
                "History list length %lu\n",
4489
4484
                                "Trx read view will not see trx with"
4490
4485
                                " id >= " TRX_ID_FMT
4491
4486
                                ", sees < " TRX_ID_FMT "\n",
4492
 
                                TRX_ID_PREP_PRINTF(
4493
 
                                        trx->read_view->low_limit_id),
4494
 
                                TRX_ID_PREP_PRINTF(
4495
 
                                        trx->read_view->up_limit_id));
 
4487
                                trx->read_view->low_limit_id,
 
4488
                                trx->read_view->up_limit_id);
4496
4489
                }
4497
4490
 
4498
4491
                if (trx->que_state == TRX_QUE_LOCK_WAIT) {
4860
4853
                        ut_a(rec);
4861
4854
                        offsets = rec_get_offsets(rec, index, offsets,
4862
4855
                                                  ULINT_UNDEFINED, &heap);
4863
 
 
 
4856
#if 0
4864
4857
                        fprintf(stderr,
4865
4858
                                "Validating %lu %lu\n",
4866
4859
                                (ulong) space, (ulong) page_no);
4867
 
 
 
4860
#endif
4868
4861
                        lock_mutex_exit_kernel();
4869
4862
 
4870
4863
                        /* If this thread is holding the file space
4906
4899
lock_validate(void)
4907
4900
/*===============*/
4908
4901
{
4909
 
        lock_t* lock;
4910
 
        trx_t*  trx;
4911
 
        dulint  limit;
4912
 
        ulint   space;
4913
 
        ulint   page_no;
4914
 
        ulint   i;
 
4902
        lock_t*         lock;
 
4903
        trx_t*          trx;
 
4904
        ib_uint64_t     limit;
 
4905
        ulint           space;
 
4906
        ulint           page_no;
 
4907
        ulint           i;
4915
4908
 
4916
4909
        lock_mutex_enter_kernel();
4917
4910
 
4935
4928
 
4936
4929
        for (i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) {
4937
4930
 
4938
 
                limit = ut_dulint_zero;
 
4931
                limit = 0;
4939
4932
 
4940
4933
                for (;;) {
4941
4934
                        lock = HASH_GET_FIRST(lock_sys->rec_hash, i);
4942
4935
 
4943
4936
                        while (lock) {
 
4937
                                ib_uint64_t     space_page;
4944
4938
                                ut_a(trx_in_trx_list(lock->trx));
4945
4939
 
4946
4940
                                space = lock->un_member.rec_lock.space;
4947
4941
                                page_no = lock->un_member.rec_lock.page_no;
4948
4942
 
4949
 
                                if (ut_dulint_cmp(
4950
 
                                            ut_dulint_create(space, page_no),
4951
 
                                            limit) >= 0) {
 
4943
                                space_page = ut_ull_create(space, page_no);
 
4944
 
 
4945
                                if (space_page >= limit) {
4952
4946
                                        break;
4953
4947
                                }
4954
4948
 
4966
4960
 
4967
4961
                        lock_mutex_enter_kernel();
4968
4962
 
4969
 
                        limit = ut_dulint_create(space, page_no + 1);
 
4963
                        limit = ut_ull_create(space, page_no + 1);
4970
4964
                }
4971
4965
        }
4972
4966
 
5058
5052
        on the successor, which produced an unnecessary deadlock. */
5059
5053
 
5060
5054
        if (lock_rec_other_has_conflicting(
5061
 
                    LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,
 
5055
                    static_cast<lock_mode>(LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION),
5062
5056
                    block, next_rec_heap_no, trx)) {
5063
5057
 
5064
5058
                /* Note that we may get DB_SUCCESS also here! */
5072
5066
 
5073
5067
        lock_mutex_exit_kernel();
5074
5068
 
5075
 
        if ((err == DB_SUCCESS) && !dict_index_is_clust(index)) {
 
5069
        switch (err) {
 
5070
        case DB_SUCCESS_LOCKED_REC:
 
5071
                err = DB_SUCCESS;
 
5072
                /* fall through */
 
5073
        case DB_SUCCESS:
 
5074
                if (dict_index_is_clust(index)) {
 
5075
                        break;
 
5076
                }
5076
5077
                /* Update the page max trx id field */
5077
5078
                page_update_max_trx_id(block,
5078
5079
                                       buf_block_get_page_zip(block),
5195
5196
 
5196
5197
        ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
5197
5198
 
 
5199
        if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
 
5200
                err = DB_SUCCESS;
 
5201
        }
 
5202
 
5198
5203
        return(err);
5199
5204
}
5200
5205
 
5261
5266
        }
5262
5267
#endif /* UNIV_DEBUG */
5263
5268
 
5264
 
        if (err == DB_SUCCESS) {
 
5269
        if (err == DB_SUCCESS || err == DB_SUCCESS_LOCKED_REC) {
5265
5270
                /* Update the page max trx id field */
 
5271
                /* It might not be necessary to do this if
 
5272
                err == DB_SUCCESS (no new lock created),
 
5273
                but it should not cost too much performance. */
5266
5274
                page_update_max_trx_id(block,
5267
5275
                                       buf_block_get_page_zip(block),
5268
5276
                                       thr_get_trx(thr)->id, mtr);
 
5277
                err = DB_SUCCESS;
5269
5278
        }
5270
5279
 
5271
5280
        return(err);
5272
5281
}
5273
5282
 
5274
5283
/*********************************************************************//**
5275
 
Like the counterpart for a clustered index below, but now we read a
 
5284
Like lock_clust_rec_read_check_and_lock(), but reads a
5276
5285
secondary index record.
5277
 
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
 
5286
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
 
5287
or DB_QUE_THR_SUSPENDED */
5278
5288
UNIV_INTERN
5279
 
ulint
 
5289
enum db_err
5280
5290
lock_sec_rec_read_check_and_lock(
5281
5291
/*=============================*/
5282
5292
        ulint                   flags,  /*!< in: if BTR_NO_LOCKING_FLAG
5297
5307
                                        LOCK_REC_NOT_GAP */
5298
5308
        que_thr_t*              thr)    /*!< in: query thread */
5299
5309
{
5300
 
        ulint   err;
5301
 
        ulint   heap_no;
 
5310
        enum db_err     err;
 
5311
        ulint           heap_no;
5302
5312
 
5303
5313
        ut_ad(!dict_index_is_clust(index));
5304
5314
        ut_ad(block->frame == page_align(rec));
5324
5334
        if the max trx id for the page >= min trx id for the trx list or a
5325
5335
        database recovery is running. */
5326
5336
 
5327
 
        if (((ut_dulint_cmp(page_get_max_trx_id(block->frame),
5328
 
                            trx_list_get_min_trx_id()) >= 0)
 
5337
        if ((page_get_max_trx_id(block->frame) >= trx_list_get_min_trx_id()
5329
5338
             || recv_recovery_is_on())
5330
5339
            && !page_rec_is_supremum(rec)) {
5331
5340
 
5339
5348
 
5340
5349
        ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
5341
5350
 
 
5351
        if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
 
5352
                err = DB_SUCCESS;
 
5353
        }
 
5354
 
5342
5355
        return(err);
5343
5356
}
5344
5357
 
5349
5362
puts the transaction and the query thread to the lock wait state and inserts a
5350
5363
waiting request for a record lock to the lock queue. Sets the requested mode
5351
5364
lock on the record.
5352
 
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
 
5365
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
 
5366
or DB_QUE_THR_SUSPENDED */
5353
5367
UNIV_INTERN
5354
 
ulint
 
5368
enum db_err
5355
5369
lock_clust_rec_read_check_and_lock(
5356
5370
/*===============================*/
5357
5371
        ulint                   flags,  /*!< in: if BTR_NO_LOCKING_FLAG
5372
5386
                                        LOCK_REC_NOT_GAP */
5373
5387
        que_thr_t*              thr)    /*!< in: query thread */
5374
5388
{
5375
 
        ulint   err;
5376
 
        ulint   heap_no;
 
5389
        enum db_err     err;
 
5390
        ulint           heap_no;
5377
5391
 
5378
5392
        ut_ad(dict_index_is_clust(index));
5379
5393
        ut_ad(block->frame == page_align(rec));
5444
5458
        mem_heap_t*     tmp_heap        = NULL;
5445
5459
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
5446
5460
        ulint*          offsets         = offsets_;
5447
 
        ulint           ret;
 
5461
        ulint           err;
5448
5462
        rec_offs_init(offsets_);
5449
5463
 
5450
5464
        offsets = rec_get_offsets(rec, index, offsets,
5451
5465
                                  ULINT_UNDEFINED, &tmp_heap);
5452
 
        ret = lock_clust_rec_read_check_and_lock(flags, block, rec, index,
 
5466
        err = lock_clust_rec_read_check_and_lock(flags, block, rec, index,
5453
5467
                                                 offsets, mode, gap_mode, thr);
5454
5468
        if (tmp_heap) {
5455
5469
                mem_heap_free(tmp_heap);
5456
5470
        }
5457
 
        return(ret);
 
5471
 
 
5472
        if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
 
5473
                err = DB_SUCCESS;
 
5474
        }
 
5475
 
 
5476
        return(err);
5458
5477
}
5459
5478
 
5460
5479
/*******************************************************************//**
5473
5492
 
5474
5493
        /* The lock to be release must be the last lock acquired. */
5475
5494
        last = ib_vector_size(autoinc_locks) - 1;
5476
 
        lock = ib_vector_get(autoinc_locks, last);
 
5495
        lock = static_cast<lock_t *>(ib_vector_get(autoinc_locks, last));
5477
5496
 
5478
5497
        /* Should have only AUTOINC locks in the vector. */
5479
5498
        ut_a(lock_get_mode(lock) == LOCK_AUTO_INC);
5542
5561
Gets the id of the transaction owning a lock.
5543
5562
@return transaction id */
5544
5563
UNIV_INTERN
5545
 
ullint
 
5564
trx_id_t
5546
5565
lock_get_trx_id(
5547
5566
/*============*/
5548
5567
        const lock_t*   lock)   /*!< in: lock */
5549
5568
{
5550
 
        return(trx_get_id(lock->trx));
 
5569
        return(lock->trx->id);
5551
5570
}
5552
5571
 
5553
5572
/*******************************************************************//**
5641
5660
Gets the id of the table on which the lock is.
5642
5661
@return id of the table */
5643
5662
UNIV_INTERN
5644
 
ullint
 
5663
table_id_t
5645
5664
lock_get_table_id(
5646
5665
/*==============*/
5647
5666
        const lock_t*   lock)   /*!< in: lock */
5650
5669
 
5651
5670
        table = lock_get_table(lock);
5652
5671
 
5653
 
        return((ullint)ut_conv_dulint_to_longlong(table->id));
 
5672
        return(table->id);
5654
5673
}
5655
5674
 
5656
5675
/*******************************************************************//**