~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2008-09-04 19:31:00 UTC
  • Revision ID: brian@tangent.org-20080904193100-l849hgghfy4urj43
Changing default character set from this point on.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
#include "lock0priv.ic"
17
17
#endif
18
18
 
19
 
#include "ha_prototypes.h"
20
19
#include "usr0sess.h"
21
20
#include "trx0purge.h"
22
21
#include "dict0mem.h"
23
22
#include "trx0sys.h"
24
23
 
 
24
 
 
25
/* 2 function prototypes copied from ha_innodb.cc: */
 
26
 
 
27
/*****************************************************************
 
28
If you want to print a thd that is not associated with the current thread,
 
29
you must call this function before reserving the InnoDB kernel_mutex, to
 
30
protect MySQL from setting thd->query NULL. If you print a thd of the current
 
31
thread, we know that MySQL cannot modify thd->query, and it is not necessary
 
32
to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release
 
33
the kernel_mutex.
 
34
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
 
35
function! */
 
36
 
 
37
void
 
38
innobase_mysql_prepare_print_arbitrary_thd(void);
 
39
/*============================================*/
 
40
 
 
41
/*****************************************************************
 
42
Relases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
 
43
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
 
44
function! */
 
45
 
 
46
void
 
47
innobase_mysql_end_print_arbitrary_thd(void);
 
48
/*========================================*/
 
49
 
25
50
/* Restricts the length of search we will do in the waits-for
26
51
graph of transactions */
27
52
#define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000
290
315
 * statement-level MySQL binlog.
291
316
 * See also lock_mode_compatible().
292
317
 */
293
 
#define LK(a,b) (1 << ((a) * LOCK_NUM + (b)))
294
 
#define LKS(a,b) LK(a,b) | LK(b,a)
295
 
 
296
 
/* Define the lock compatibility matrix in a ulint.  The first line below
297
 
defines the diagonal entries.  The following lines define the compatibility
298
 
for LOCK_IX, LOCK_S, and LOCK_AUTO_INC using LKS(), since the matrix
299
 
is symmetric. */
300
 
#define LOCK_MODE_COMPATIBILITY 0                                       \
301
 
 | LK(LOCK_IS, LOCK_IS) | LK(LOCK_IX, LOCK_IX) | LK(LOCK_S, LOCK_S)     \
302
 
 | LKS(LOCK_IX, LOCK_IS) | LKS(LOCK_IS, LOCK_AUTO_INC)                  \
303
 
 | LKS(LOCK_S, LOCK_IS)                                                 \
304
 
 | LKS(LOCK_AUTO_INC, LOCK_IS) | LKS(LOCK_AUTO_INC, LOCK_IX)
305
 
 
306
 
/* STRONGER-OR-EQUAL RELATION (mode1=row, mode2=column)
307
 
 *    IS IX S  X  AI
308
 
 * IS +  -  -  -  -
309
 
 * IX +  +  -  -  -
310
 
 * S  +  -  +  -  -
311
 
 * X  +  +  +  +  +
312
 
 * AI -  -  -  -  +
313
 
 * See lock_mode_stronger_or_eq().
314
 
 */
315
 
 
316
 
/* Define the stronger-or-equal lock relation in a ulint.  This relation
317
 
contains all pairs LK(mode1, mode2) where mode1 is stronger than or
318
 
equal to mode2. */
319
 
#define LOCK_MODE_STRONGER_OR_EQ 0                                      \
320
 
 | LK(LOCK_IS, LOCK_IS)                                                 \
321
 
 | LK(LOCK_IX, LOCK_IS) | LK(LOCK_IX, LOCK_IX)                          \
322
 
 | LK(LOCK_S, LOCK_IS) | LK(LOCK_S, LOCK_S)                             \
323
 
 | LK(LOCK_AUTO_INC, LOCK_AUTO_INC)                                     \
324
 
 | LK(LOCK_X, LOCK_IS) | LK(LOCK_X, LOCK_IX) | LK(LOCK_X, LOCK_S)       \
325
 
 | LK(LOCK_X, LOCK_AUTO_INC) | LK(LOCK_X, LOCK_X)
326
318
 
327
319
#ifdef UNIV_DEBUG
328
 
UNIV_INTERN ibool       lock_print_waits        = FALSE;
329
 
 
330
 
/*************************************************************************
331
 
Validates the lock system. */
332
 
static
333
 
ibool
334
 
lock_validate(void);
335
 
/*===============*/
336
 
                        /* out: TRUE if ok */
337
 
 
338
 
/*************************************************************************
339
 
Validates the record lock queues on a page. */
340
 
static
341
 
ibool
342
 
lock_rec_validate_page(
343
 
/*===================*/
344
 
                        /* out: TRUE if ok */
345
 
        ulint   space,  /* in: space id */
346
 
        ulint   page_no);/* in: page number */
347
 
 
348
 
/* Define the following in order to enable lock_rec_validate_page() checks. */
349
 
# undef UNIV_DEBUG_LOCK_VALIDATE
 
320
ibool   lock_print_waits        = FALSE;
350
321
#endif /* UNIV_DEBUG */
351
322
 
352
323
/* The lock system */
353
 
UNIV_INTERN lock_sys_t* lock_sys        = NULL;
 
324
lock_sys_t*     lock_sys        = NULL;
354
325
 
355
326
/* We store info on the latest deadlock error to this buffer. InnoDB
356
327
Monitor will then fetch it and print */
357
 
UNIV_INTERN ibool       lock_deadlock_found = FALSE;
358
 
UNIV_INTERN FILE*       lock_latest_err_file;
 
328
ibool   lock_deadlock_found = FALSE;
 
329
FILE*   lock_latest_err_file;
359
330
 
360
331
/* Flags for recursive deadlock search */
361
332
#define LOCK_VICTIM_IS_START    1
403
374
ibool
404
375
lock_rec_get_nth_bit(
405
376
/*=================*/
406
 
                                /* out: TRUE if bit set */
407
 
        const lock_t*   lock,   /* in: record lock */
408
 
        ulint           i)      /* in: index of the bit */
 
377
                        /* out: TRUE if bit set */
 
378
        lock_t* lock,   /* in: record lock */
 
379
        ulint   i)      /* in: index of the bit */
409
380
{
410
381
        ulint   byte_index;
411
382
        ulint   bit_index;
 
383
        ulint   b;
412
384
 
413
385
        ut_ad(lock);
414
 
        ut_ad(lock_get_type_low(lock) == LOCK_REC);
 
386
        ut_ad(lock_get_type(lock) == LOCK_REC);
415
387
 
416
388
        if (i >= lock->un_member.rec_lock.n_bits) {
417
389
 
421
393
        byte_index = i / 8;
422
394
        bit_index = i % 8;
423
395
 
424
 
        return(1 & ((const byte*) &lock[1])[byte_index] >> bit_index);
 
396
        b = (ulint)*((byte*)lock + sizeof(lock_t) + byte_index);
 
397
 
 
398
        return(ut_bit_get_nth(b, bit_index));
425
399
}
426
400
 
427
401
/*************************************************************************/
431
405
 
432
406
/*************************************************************************
433
407
Checks that a transaction id is sensible, i.e., not in the future. */
434
 
UNIV_INTERN
 
408
 
435
409
ibool
436
410
lock_check_trx_id_sanity(
437
411
/*=====================*/
438
412
                                        /* out: TRUE if ok */
439
413
        dulint          trx_id,         /* in: trx id */
440
 
        const rec_t*    rec,            /* in: user record */
 
414
        rec_t*          rec,            /* in: user record */
441
415
        dict_index_t*   index,          /* in: index */
442
416
        const ulint*    offsets,        /* in: rec_get_offsets(rec, index) */
443
417
        ibool           has_kernel_mutex)/* in: TRUE if the caller owns the
463
437
                fputs("InnoDB: in ", stderr);
464
438
                dict_index_name_print(stderr, NULL, index);
465
439
                fprintf(stderr, "\n"
466
 
                        "InnoDB: is " TRX_ID_FMT " which is higher than the"
467
 
                        " global trx id counter " TRX_ID_FMT "!\n"
 
440
                        "InnoDB: is %lu %lu which is higher than the"
 
441
                        " global trx id counter %lu %lu!\n"
468
442
                        "InnoDB: The table is corrupt. You have to do"
469
443
                        " dump + drop + reimport.\n",
470
 
                        TRX_ID_PREP_PRINTF(trx_id),
471
 
                        TRX_ID_PREP_PRINTF(trx_sys->max_trx_id));
 
444
                        (ulong) ut_dulint_get_high(trx_id),
 
445
                        (ulong) ut_dulint_get_low(trx_id),
 
446
                        (ulong) ut_dulint_get_high(trx_sys->max_trx_id),
 
447
                        (ulong) ut_dulint_get_low(trx_sys->max_trx_id));
472
448
 
473
449
                is_ok = FALSE;
474
450
        }
482
458
 
483
459
/*************************************************************************
484
460
Checks that a record is seen in a consistent read. */
485
 
UNIV_INTERN
 
461
 
486
462
ibool
487
463
lock_clust_rec_cons_read_sees(
488
464
/*==========================*/
489
465
                                /* out: TRUE if sees, or FALSE if an earlier
490
466
                                version of the record should be retrieved */
491
 
        const rec_t*    rec,    /* in: user record which should be read or
 
467
        rec_t*          rec,    /* in: user record which should be read or
492
468
                                passed over by a read cursor */
493
469
        dict_index_t*   index,  /* in: clustered index */
494
470
        const ulint*    offsets,/* in: rec_get_offsets(rec, index) */
496
472
{
497
473
        dulint  trx_id;
498
474
 
499
 
        ut_ad(dict_index_is_clust(index));
 
475
        ut_ad(index->type & DICT_CLUSTERED);
500
476
        ut_ad(page_rec_is_user_rec(rec));
501
477
        ut_ad(rec_offs_validate(rec, index, offsets));
502
478
 
511
487
 
512
488
/*************************************************************************
513
489
Checks that a non-clustered index record is seen in a consistent read. */
514
 
UNIV_INTERN
 
490
 
515
491
ulint
516
492
lock_sec_rec_cons_read_sees(
517
493
/*========================*/
518
 
                                        /* out: TRUE if certainly
519
 
                                        sees, or FALSE if an earlier
520
 
                                        version of the clustered index
521
 
                                        record might be needed: NOTE
522
 
                                        that a non-clustered index
523
 
                                        page contains so little
524
 
                                        information on its
525
 
                                        modifications that also in the
526
 
                                        case FALSE, the present
527
 
                                        version of rec may be the
528
 
                                        right, but we must check this
529
 
                                        from the clustered index
530
 
                                        record */
531
 
        const rec_t*            rec,    /* in: user record which
532
 
                                        should be read or passed over
533
 
                                        by a read cursor */
534
 
        const read_view_t*      view)   /* in: consistent read view */
 
494
                                /* out: TRUE if certainly sees, or FALSE if an
 
495
                                earlier version of the clustered index record
 
496
                                might be needed: NOTE that a non-clustered
 
497
                                index page contains so little information on
 
498
                                its modifications that also in the case FALSE,
 
499
                                the present version of rec may be the right,
 
500
                                but we must check this from the clustered
 
501
                                index record */
 
502
        rec_t*          rec,    /* in: user record which should be read or
 
503
                                passed over by a read cursor */
 
504
        dict_index_t*   index,  /* in: non-clustered index */
 
505
        read_view_t*    view)   /* in: consistent read view */
535
506
{
536
507
        dulint  max_trx_id;
537
508
 
 
509
        UT_NOT_USED(index);
 
510
 
 
511
        ut_ad(!(index->type & DICT_CLUSTERED));
538
512
        ut_ad(page_rec_is_user_rec(rec));
539
513
 
540
514
        /* NOTE that we might call this function while holding the search
546
520
                return(FALSE);
547
521
        }
548
522
 
549
 
        max_trx_id = page_get_max_trx_id(page_align(rec));
550
 
 
551
 
        return(ut_dulint_cmp(max_trx_id, view->up_limit_id) < 0);
 
523
        max_trx_id = page_get_max_trx_id(buf_frame_align(rec));
 
524
 
 
525
        if (ut_dulint_cmp(max_trx_id, view->up_limit_id) >= 0) {
 
526
 
 
527
                return(FALSE);
 
528
        }
 
529
 
 
530
        return(TRUE);
552
531
}
553
532
 
554
533
/*************************************************************************
555
534
Creates the lock system at database start. */
556
 
UNIV_INTERN
 
535
 
557
536
void
558
537
lock_sys_create(
559
538
/*============*/
571
550
 
572
551
/*************************************************************************
573
552
Gets the size of a lock struct. */
574
 
UNIV_INTERN
 
553
 
575
554
ulint
576
555
lock_get_size(void)
577
556
/*===============*/
583
562
/*************************************************************************
584
563
Gets the mode of a lock. */
585
564
UNIV_INLINE
586
 
enum lock_mode
 
565
ulint
587
566
lock_get_mode(
588
567
/*==========*/
589
568
                                /* out: mode */
600
579
ibool
601
580
lock_get_wait(
602
581
/*==========*/
603
 
                                /* out: TRUE if waiting */
604
 
        const lock_t*   lock)   /* in: lock */
 
582
                        /* out: TRUE if waiting */
 
583
        lock_t* lock)   /* in: lock */
605
584
{
606
585
        ut_ad(lock);
607
586
 
608
 
        if (UNIV_UNLIKELY(lock->type_mode & LOCK_WAIT)) {
 
587
        if (lock->type_mode & LOCK_WAIT) {
609
588
 
610
589
                return(TRUE);
611
590
        }
616
595
/*************************************************************************
617
596
Gets the source table of an ALTER TABLE transaction.  The table must be
618
597
covered by an IX or IS table lock. */
619
 
UNIV_INTERN
 
598
 
620
599
dict_table_t*
621
600
lock_get_src_table(
622
601
/*===============*/
627
606
                                two tables or an inconsistency is found */
628
607
        trx_t*          trx,    /* in: transaction */
629
608
        dict_table_t*   dest,   /* in: destination of ALTER TABLE */
630
 
        enum lock_mode* mode)   /* out: lock mode of the source table */
 
609
        ulint*          mode)   /* out: lock mode of the source table */
631
610
{
632
611
        dict_table_t*   src;
633
612
        lock_t*         lock;
639
618
             lock;
640
619
             lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
641
620
                lock_table_t*   tab_lock;
642
 
                enum lock_mode  lock_mode;
643
 
                if (!(lock_get_type_low(lock) & LOCK_TABLE)) {
 
621
                ulint           lock_mode;
 
622
                if (!(lock_get_type(lock) & LOCK_TABLE)) {
644
623
                        /* We are only interested in table locks. */
645
624
                        continue;
646
625
                }
666
645
                /* Check that the source table is locked by
667
646
                LOCK_IX or LOCK_IS. */
668
647
                lock_mode = lock_get_mode(lock);
669
 
                if (lock_mode == LOCK_IX || lock_mode == LOCK_IS) {
 
648
                switch (lock_mode) {
 
649
                case LOCK_IX:
 
650
                case LOCK_IS:
670
651
                        if (*mode != LOCK_NONE && *mode != lock_mode) {
671
652
                                /* There are multiple locks on src. */
672
653
                                return(NULL);
673
654
                        }
674
655
                        *mode = lock_mode;
 
656
                        break;
675
657
                }
676
658
        }
677
659
 
687
669
Determine if the given table is exclusively "owned" by the given
688
670
transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
689
671
on the table. */
690
 
UNIV_INTERN
 
672
 
691
673
ibool
692
674
lock_is_table_exclusive(
693
675
/*====================*/
696
678
        dict_table_t*   table,  /* in: table */
697
679
        trx_t*          trx)    /* in: transaction */
698
680
{
699
 
        const lock_t*   lock;
700
 
        ibool           ok      = FALSE;
 
681
        lock_t* lock;
 
682
        ibool   ok      = FALSE;
701
683
 
702
684
        ut_ad(table && trx);
703
685
 
710
692
                        return(FALSE);
711
693
                }
712
694
 
713
 
                if (!(lock_get_type_low(lock) & LOCK_TABLE)) {
 
695
                if (!(lock_get_type(lock) & LOCK_TABLE)) {
714
696
                        /* We are interested in table locks only. */
715
697
                        continue;
716
698
                }
745
727
        ut_ad(trx->wait_lock == NULL);
746
728
 
747
729
        trx->wait_lock = lock;
748
 
        lock->type_mode |= LOCK_WAIT;
 
730
        lock->type_mode = lock->type_mode | LOCK_WAIT;
749
731
}
750
732
 
751
733
/**************************************************************************
763
745
        /* Reset the back pointer in trx to this waiting lock request */
764
746
 
765
747
        (lock->trx)->wait_lock = NULL;
766
 
        lock->type_mode &= ~LOCK_WAIT;
 
748
        lock->type_mode = lock->type_mode & ~LOCK_WAIT;
767
749
}
768
750
 
769
751
/*************************************************************************
772
754
ibool
773
755
lock_rec_get_gap(
774
756
/*=============*/
775
 
                                /* out: TRUE if gap flag set */
776
 
        const lock_t*   lock)   /* in: record lock */
 
757
                        /* out: TRUE if gap flag set */
 
758
        lock_t* lock)   /* in: record lock */
777
759
{
778
760
        ut_ad(lock);
779
 
        ut_ad(lock_get_type_low(lock) == LOCK_REC);
 
761
        ut_ad(lock_get_type(lock) == LOCK_REC);
780
762
 
781
763
        if (lock->type_mode & LOCK_GAP) {
782
764
 
792
774
ibool
793
775
lock_rec_get_rec_not_gap(
794
776
/*=====================*/
795
 
                                /* out: TRUE if LOCK_REC_NOT_GAP flag set */
796
 
        const lock_t*   lock)   /* in: record lock */
 
777
                        /* out: TRUE if LOCK_REC_NOT_GAP flag set */
 
778
        lock_t* lock)   /* in: record lock */
797
779
{
798
780
        ut_ad(lock);
799
 
        ut_ad(lock_get_type_low(lock) == LOCK_REC);
 
781
        ut_ad(lock_get_type(lock) == LOCK_REC);
800
782
 
801
783
        if (lock->type_mode & LOCK_REC_NOT_GAP) {
802
784
 
812
794
ibool
813
795
lock_rec_get_insert_intention(
814
796
/*==========================*/
815
 
                                /* out: TRUE if gap flag set */
816
 
        const lock_t*   lock)   /* in: record lock */
 
797
                        /* out: TRUE if gap flag set */
 
798
        lock_t* lock)   /* in: record lock */
817
799
{
818
800
        ut_ad(lock);
819
 
        ut_ad(lock_get_type_low(lock) == LOCK_REC);
 
801
        ut_ad(lock_get_type(lock) == LOCK_REC);
820
802
 
821
803
        if (lock->type_mode & LOCK_INSERT_INTENTION) {
822
804
 
829
811
/*************************************************************************
830
812
Calculates if lock mode 1 is stronger or equal to lock mode 2. */
831
813
UNIV_INLINE
832
 
ulint
 
814
ibool
833
815
lock_mode_stronger_or_eq(
834
816
/*=====================*/
835
 
                                /* out: nonzero
836
 
                                if mode1 stronger or equal to mode2 */
837
 
        enum lock_mode  mode1,  /* in: lock mode */
838
 
        enum lock_mode  mode2)  /* in: lock mode */
 
817
                        /* out: TRUE if mode1 stronger or equal to mode2 */
 
818
        ulint   mode1,  /* in: lock mode */
 
819
        ulint   mode2)  /* in: lock mode */
839
820
{
840
821
        ut_ad(mode1 == LOCK_X || mode1 == LOCK_S || mode1 == LOCK_IX
841
822
              || mode1 == LOCK_IS || mode1 == LOCK_AUTO_INC);
842
823
        ut_ad(mode2 == LOCK_X || mode2 == LOCK_S || mode2 == LOCK_IX
843
824
              || mode2 == LOCK_IS || mode2 == LOCK_AUTO_INC);
844
 
 
845
 
        return((LOCK_MODE_STRONGER_OR_EQ) & LK(mode1, mode2));
 
825
        if (mode1 == LOCK_X) {
 
826
 
 
827
                return(TRUE);
 
828
 
 
829
        } else if (mode1 == LOCK_AUTO_INC && mode2 == LOCK_AUTO_INC) {
 
830
 
 
831
                return(TRUE);
 
832
 
 
833
        } else if (mode1 == LOCK_S
 
834
                   && (mode2 == LOCK_S || mode2 == LOCK_IS)) {
 
835
                return(TRUE);
 
836
 
 
837
        } else if (mode1 == LOCK_IS && mode2 == LOCK_IS) {
 
838
 
 
839
                return(TRUE);
 
840
 
 
841
        } else if (mode1 == LOCK_IX && (mode2 == LOCK_IX
 
842
                                        || mode2 == LOCK_IS)) {
 
843
                return(TRUE);
 
844
        }
 
845
 
 
846
        return(FALSE);
846
847
}
847
848
 
848
849
/*************************************************************************
849
850
Calculates if lock mode 1 is compatible with lock mode 2. */
850
851
UNIV_INLINE
851
 
ulint
 
852
ibool
852
853
lock_mode_compatible(
853
854
/*=================*/
854
 
                        /* out: nonzero if mode1 compatible with mode2 */
855
 
        enum lock_mode  mode1,  /* in: lock mode */
856
 
        enum lock_mode  mode2)  /* in: lock mode */
 
855
                        /* out: TRUE if mode1 compatible with mode2 */
 
856
        ulint   mode1,  /* in: lock mode */
 
857
        ulint   mode2)  /* in: lock mode */
857
858
{
858
859
        ut_ad(mode1 == LOCK_X || mode1 == LOCK_S || mode1 == LOCK_IX
859
860
              || mode1 == LOCK_IS || mode1 == LOCK_AUTO_INC);
860
861
        ut_ad(mode2 == LOCK_X || mode2 == LOCK_S || mode2 == LOCK_IX
861
862
              || mode2 == LOCK_IS || mode2 == LOCK_AUTO_INC);
862
863
 
863
 
        return((LOCK_MODE_COMPATIBILITY) & LK(mode1, mode2));
 
864
        if (mode1 == LOCK_S && (mode2 == LOCK_IS || mode2 == LOCK_S)) {
 
865
 
 
866
                return(TRUE);
 
867
 
 
868
        } else if (mode1 == LOCK_X) {
 
869
 
 
870
                return(FALSE);
 
871
 
 
872
        } else if (mode1 == LOCK_AUTO_INC && (mode2 == LOCK_IS
 
873
                                              || mode2 == LOCK_IX)) {
 
874
                return(TRUE);
 
875
 
 
876
        } else if (mode1 == LOCK_IS && (mode2 == LOCK_IS
 
877
                                        || mode2 == LOCK_IX
 
878
                                        || mode2 == LOCK_AUTO_INC
 
879
                                        || mode2 == LOCK_S)) {
 
880
                return(TRUE);
 
881
 
 
882
        } else if (mode1 == LOCK_IX && (mode2 == LOCK_IS
 
883
                                        || mode2 == LOCK_AUTO_INC
 
884
                                        || mode2 == LOCK_IX)) {
 
885
                return(TRUE);
 
886
        }
 
887
 
 
888
        return(FALSE);
864
889
}
865
890
 
866
891
/*************************************************************************
869
894
ibool
870
895
lock_rec_has_to_wait(
871
896
/*=================*/
872
 
                                /* out: TRUE if new lock has to wait
873
 
                                for lock2 to be removed */
874
 
        const trx_t*    trx,    /* in: trx of new lock */
875
 
        ulint           type_mode,/* in: precise mode of the new lock
876
 
                                to set: LOCK_S or LOCK_X, possibly
877
 
                                ORed to LOCK_GAP or LOCK_REC_NOT_GAP,
878
 
                                LOCK_INSERT_INTENTION */
879
 
        const lock_t*   lock2,  /* in: another record lock; NOTE that
880
 
                                it is assumed that this has a lock bit
881
 
                                set on the same record as in the new
882
 
                                lock we are setting */
883
 
        ibool lock_is_on_supremum)  /* in: TRUE if we are setting the
884
 
                                lock on the 'supremum' record of an
885
 
                                index page: we know then that the lock
886
 
                                request is really for a 'gap' type lock */
 
897
                        /* out: TRUE if new lock has to wait for lock2 to be
 
898
                        removed */
 
899
        trx_t*  trx,    /* in: trx of new lock */
 
900
        ulint   type_mode,/* in: precise mode of the new lock to set:
 
901
                        LOCK_S or LOCK_X, possibly ORed to
 
902
                        LOCK_GAP or LOCK_REC_NOT_GAP, LOCK_INSERT_INTENTION */
 
903
        lock_t* lock2,  /* in: another record lock; NOTE that it is assumed
 
904
                        that this has a lock bit set on the same record as
 
905
                        in the new lock we are setting */
 
906
        ibool lock_is_on_supremum)  /* in: TRUE if we are setting the lock
 
907
                        on the 'supremum' record of an index
 
908
                        page: we know then that the lock request
 
909
                        is really for a 'gap' type lock */
887
910
{
888
911
        ut_ad(trx && lock2);
889
 
        ut_ad(lock_get_type_low(lock2) == LOCK_REC);
 
912
        ut_ad(lock_get_type(lock2) == LOCK_REC);
890
913
 
891
914
        if (trx != lock2->trx
892
915
            && !lock_mode_compatible(LOCK_MODE_MASK & type_mode,
948
971
 
949
972
/*************************************************************************
950
973
Checks if a lock request lock1 has to wait for request lock2. */
951
 
UNIV_INTERN
 
974
 
952
975
ibool
953
976
lock_has_to_wait(
954
977
/*=============*/
955
 
                                /* out: TRUE if lock1 has to wait for
956
 
                                lock2 to be removed */
957
 
        const lock_t*   lock1,  /* in: waiting lock */
958
 
        const lock_t*   lock2)  /* in: another lock; NOTE that it is
959
 
                                assumed that this has a lock bit set
960
 
                                on the same record as in lock1 if the
961
 
                                locks are record locks */
 
978
                        /* out: TRUE if lock1 has to wait for lock2 to be
 
979
                        removed */
 
980
        lock_t* lock1,  /* in: waiting lock */
 
981
        lock_t* lock2)  /* in: another lock; NOTE that it is assumed that this
 
982
                        has a lock bit set on the same record as in lock1 if
 
983
                        the locks are record locks */
962
984
{
963
985
        ut_ad(lock1 && lock2);
964
986
 
965
987
        if (lock1->trx != lock2->trx
966
988
            && !lock_mode_compatible(lock_get_mode(lock1),
967
989
                                     lock_get_mode(lock2))) {
968
 
                if (lock_get_type_low(lock1) == LOCK_REC) {
969
 
                        ut_ad(lock_get_type_low(lock2) == LOCK_REC);
 
990
                if (lock_get_type(lock1) == LOCK_REC) {
 
991
                        ut_ad(lock_get_type(lock2) == LOCK_REC);
970
992
 
971
993
                        /* If this lock request is for a supremum record
972
994
                        then the second bit on the lock bitmap is set */
991
1013
ulint
992
1014
lock_rec_get_n_bits(
993
1015
/*================*/
994
 
                                /* out: number of bits */
995
 
        const lock_t*   lock)   /* in: record lock */
 
1016
                        /* out: number of bits */
 
1017
        lock_t* lock)   /* in: record lock */
996
1018
{
997
1019
        return(lock->un_member.rec_lock.n_bits);
998
1020
}
1008
1030
{
1009
1031
        ulint   byte_index;
1010
1032
        ulint   bit_index;
 
1033
        byte*   ptr;
 
1034
        ulint   b;
1011
1035
 
1012
1036
        ut_ad(lock);
1013
 
        ut_ad(lock_get_type_low(lock) == LOCK_REC);
 
1037
        ut_ad(lock_get_type(lock) == LOCK_REC);
1014
1038
        ut_ad(i < lock->un_member.rec_lock.n_bits);
1015
1039
 
1016
1040
        byte_index = i / 8;
1017
1041
        bit_index = i % 8;
1018
1042
 
1019
 
        ((byte*) &lock[1])[byte_index] |= 1 << bit_index;
 
1043
        ptr = (byte*)lock + sizeof(lock_t) + byte_index;
 
1044
 
 
1045
        b = (ulint)*ptr;
 
1046
 
 
1047
        b = ut_bit_set_nth(b, bit_index, TRUE);
 
1048
 
 
1049
        *ptr = (byte)b;
1020
1050
}
1021
1051
 
1022
1052
/**************************************************************************
1023
1053
Looks for a set bit in a record lock bitmap. Returns ULINT_UNDEFINED,
1024
1054
if none found. */
1025
 
UNIV_INTERN
 
1055
 
1026
1056
ulint
1027
1057
lock_rec_find_set_bit(
1028
1058
/*==================*/
1029
 
                                /* out: bit index == heap number of
1030
 
                                the record, or ULINT_UNDEFINED if none found */
1031
 
        const lock_t*   lock)   /* in: record lock with at least one bit set */
 
1059
                        /* out: bit index == heap number of the record, or
 
1060
                        ULINT_UNDEFINED if none found */
 
1061
        lock_t* lock)   /* in: record lock with at least one bit set */
1032
1062
{
1033
1063
        ulint   i;
1034
1064
 
1055
1085
{
1056
1086
        ulint   byte_index;
1057
1087
        ulint   bit_index;
 
1088
        byte*   ptr;
 
1089
        ulint   b;
1058
1090
 
1059
1091
        ut_ad(lock);
1060
 
        ut_ad(lock_get_type_low(lock) == LOCK_REC);
 
1092
        ut_ad(lock_get_type(lock) == LOCK_REC);
1061
1093
        ut_ad(i < lock->un_member.rec_lock.n_bits);
1062
1094
 
1063
1095
        byte_index = i / 8;
1064
1096
        bit_index = i % 8;
1065
1097
 
1066
 
        ((byte*) &lock[1])[byte_index] &= ~(1 << bit_index);
 
1098
        ptr = (byte*)lock + sizeof(lock_t) + byte_index;
 
1099
 
 
1100
        b = (ulint)*ptr;
 
1101
 
 
1102
        b = ut_bit_set_nth(b, bit_index, FALSE);
 
1103
 
 
1104
        *ptr = (byte)b;
1067
1105
}
1068
1106
 
1069
1107
/*************************************************************************
1079
1117
        ulint   page_no;
1080
1118
 
1081
1119
        ut_ad(mutex_own(&kernel_mutex));
1082
 
        ut_ad(lock_get_type_low(lock) == LOCK_REC);
 
1120
        ut_ad(lock_get_type(lock) == LOCK_REC);
1083
1121
 
1084
1122
        space = lock->un_member.rec_lock.space;
1085
1123
        page_no = lock->un_member.rec_lock.page_no;
1134
1172
 
1135
1173
/*************************************************************************
1136
1174
Returns TRUE if there are explicit record locks on a page. */
1137
 
UNIV_INTERN
 
1175
 
1138
1176
ibool
1139
1177
lock_rec_expl_exist_on_page(
1140
1178
/*========================*/
1165
1203
lock_t*
1166
1204
lock_rec_get_first_on_page(
1167
1205
/*=======================*/
1168
 
                                        /* out: first lock, NULL if
1169
 
                                        none exists */
1170
 
        const buf_block_t*      block)  /* in: buffer block */
 
1206
                        /* out: first lock, NULL if none exists */
 
1207
        byte*   ptr)    /* in: pointer to somewhere on the page */
1171
1208
{
1172
1209
        ulint   hash;
1173
1210
        lock_t* lock;
1174
 
        ulint   space   = buf_block_get_space(block);
1175
 
        ulint   page_no = buf_block_get_page_no(block);
 
1211
        ulint   space;
 
1212
        ulint   page_no;
1176
1213
 
1177
1214
        ut_ad(mutex_own(&kernel_mutex));
1178
1215
 
1179
 
        hash = buf_block_get_lock_hash_val(block);
 
1216
        hash = buf_frame_get_lock_hash_val(ptr);
1180
1217
 
1181
1218
        lock = HASH_GET_FIRST(lock_sys->rec_hash, hash);
1182
1219
 
1183
1220
        while (lock) {
 
1221
                space = buf_frame_get_space_id(ptr);
 
1222
                page_no = buf_frame_get_page_no(ptr);
 
1223
 
1184
1224
                if ((lock->un_member.rec_lock.space == space)
1185
1225
                    && (lock->un_member.rec_lock.page_no == page_no)) {
1186
1226
 
1200
1240
lock_rec_get_next(
1201
1241
/*==============*/
1202
1242
                        /* out: next lock, NULL if none exists */
1203
 
        ulint   heap_no,/* in: heap number of the record */
 
1243
        rec_t*  rec,    /* in: record on a page */
1204
1244
        lock_t* lock)   /* in: lock */
1205
1245
{
1206
1246
        ut_ad(mutex_own(&kernel_mutex));
 
1247
        ut_ad(lock_get_type(lock) == LOCK_REC);
1207
1248
 
1208
 
        do {
1209
 
                ut_ad(lock_get_type_low(lock) == LOCK_REC);
1210
 
                lock = lock_rec_get_next_on_page(lock);
1211
 
        } while (lock && !lock_rec_get_nth_bit(lock, heap_no));
 
1249
        if (page_rec_is_comp(rec)) {
 
1250
                do {
 
1251
                        lock = lock_rec_get_next_on_page(lock);
 
1252
                } while (lock && !lock_rec_get_nth_bit(
 
1253
                                 lock, rec_get_heap_no(rec, TRUE)));
 
1254
        } else {
 
1255
                do {
 
1256
                        lock = lock_rec_get_next_on_page(lock);
 
1257
                } while (lock && !lock_rec_get_nth_bit(
 
1258
                                 lock, rec_get_heap_no(rec, FALSE)));
 
1259
        }
1212
1260
 
1213
1261
        return(lock);
1214
1262
}
1219
1267
lock_t*
1220
1268
lock_rec_get_first(
1221
1269
/*===============*/
1222
 
                                        /* out: first lock, NULL if
1223
 
                                        none exists */
1224
 
        const buf_block_t*      block,  /* in: block containing the record */
1225
 
        ulint                   heap_no)/* in: heap number of the record */
 
1270
                        /* out: first lock, NULL if none exists */
 
1271
        rec_t*  rec)    /* in: record on a page */
1226
1272
{
1227
1273
        lock_t* lock;
1228
1274
 
1229
1275
        ut_ad(mutex_own(&kernel_mutex));
1230
1276
 
1231
 
        for (lock = lock_rec_get_first_on_page(block); lock;
1232
 
             lock = lock_rec_get_next_on_page(lock)) {
1233
 
                if (lock_rec_get_nth_bit(lock, heap_no)) {
1234
 
                        break;
 
1277
        lock = lock_rec_get_first_on_page(rec);
 
1278
        if (UNIV_LIKELY_NULL(lock)) {
 
1279
                ulint   heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
 
1280
 
 
1281
                while (lock && !lock_rec_get_nth_bit(lock, heap_no)) {
 
1282
                        lock = lock_rec_get_next_on_page(lock);
1235
1283
                }
1236
1284
        }
1237
1285
 
1248
1296
/*==================*/
1249
1297
        lock_t* lock)   /* in: record lock */
1250
1298
{
 
1299
        byte*   ptr;
1251
1300
        ulint   n_bytes;
 
1301
        ulint   i;
1252
1302
 
1253
 
        ut_ad(lock_get_type_low(lock) == LOCK_REC);
 
1303
        ut_ad(lock_get_type(lock) == LOCK_REC);
1254
1304
 
1255
1305
        /* Reset to zero the bitmap which resides immediately after the lock
1256
1306
        struct */
1257
1307
 
 
1308
        ptr = (byte*)lock + sizeof(lock_t);
 
1309
 
1258
1310
        n_bytes = lock_rec_get_n_bits(lock) / 8;
1259
1311
 
1260
1312
        ut_ad((lock_rec_get_n_bits(lock) % 8) == 0);
1261
1313
 
1262
 
        memset(&lock[1], 0, n_bytes);
 
1314
        for (i = 0; i < n_bytes; i++) {
 
1315
 
 
1316
                *ptr = 0;
 
1317
                ptr++;
 
1318
        }
1263
1319
}
1264
1320
 
1265
1321
/*************************************************************************
1269
1325
lock_rec_copy(
1270
1326
/*==========*/
1271
1327
                                /* out: copy of lock */
1272
 
        const lock_t*   lock,   /* in: record lock */
 
1328
        lock_t*         lock,   /* in: record lock */
1273
1329
        mem_heap_t*     heap)   /* in: memory heap */
1274
1330
{
 
1331
        lock_t* dupl_lock;
1275
1332
        ulint   size;
1276
1333
 
1277
 
        ut_ad(lock_get_type_low(lock) == LOCK_REC);
 
1334
        ut_ad(lock_get_type(lock) == LOCK_REC);
1278
1335
 
1279
1336
        size = sizeof(lock_t) + lock_rec_get_n_bits(lock) / 8;
1280
1337
 
1281
 
        return(mem_heap_dup(heap, lock, size));
 
1338
        dupl_lock = mem_heap_alloc(heap, size);
 
1339
 
 
1340
        ut_memcpy(dupl_lock, lock, size);
 
1341
 
 
1342
        return(dupl_lock);
1282
1343
}
1283
1344
 
1284
1345
/*************************************************************************
1285
1346
Gets the previous record lock set on a record. */
1286
 
UNIV_INTERN
1287
 
const lock_t*
 
1347
 
 
1348
lock_t*
1288
1349
lock_rec_get_prev(
1289
1350
/*==============*/
1290
 
                                /* out: previous lock on the same
1291
 
                                record, NULL if none exists */
1292
 
        const lock_t*   in_lock,/* in: record lock */
1293
 
        ulint           heap_no)/* in: heap number of the record */
 
1351
                        /* out: previous lock on the same record, NULL if
 
1352
                        none exists */
 
1353
        lock_t* in_lock,/* in: record lock */
 
1354
        ulint   heap_no)/* in: heap number of the record */
1294
1355
{
1295
1356
        lock_t* lock;
1296
1357
        ulint   space;
1298
1359
        lock_t* found_lock      = NULL;
1299
1360
 
1300
1361
        ut_ad(mutex_own(&kernel_mutex));
1301
 
        ut_ad(lock_get_type_low(in_lock) == LOCK_REC);
 
1362
        ut_ad(lock_get_type(in_lock) == LOCK_REC);
1302
1363
 
1303
1364
        space = in_lock->un_member.rec_lock.space;
1304
1365
        page_no = in_lock->un_member.rec_lock.page_no;
1333
1394
                                /* out: lock or NULL */
1334
1395
        trx_t*          trx,    /* in: transaction */
1335
1396
        dict_table_t*   table,  /* in: table */
1336
 
        enum lock_mode  mode)   /* in: lock mode */
 
1397
        ulint           mode)   /* in: lock mode */
1337
1398
{
1338
1399
        lock_t* lock;
1339
1400
 
1371
1432
lock_t*
1372
1433
lock_rec_has_expl(
1373
1434
/*==============*/
1374
 
                                        /* out: lock or NULL */
1375
 
        ulint                   precise_mode,/* in: LOCK_S or LOCK_X
1376
 
                                        possibly ORed to LOCK_GAP or
1377
 
                                        LOCK_REC_NOT_GAP, for a
1378
 
                                        supremum record we regard this
1379
 
                                        always a gap type request */
1380
 
        const buf_block_t*      block,  /* in: buffer block containing
1381
 
                                        the record */
1382
 
        ulint                   heap_no,/* in: heap number of the record */
1383
 
        trx_t*                  trx)    /* in: transaction */
 
1435
                        /* out: lock or NULL */
 
1436
        ulint   precise_mode,/* in: LOCK_S or LOCK_X possibly ORed to
 
1437
                        LOCK_GAP or LOCK_REC_NOT_GAP,
 
1438
                        for a supremum record we regard this always a gap
 
1439
                        type request */
 
1440
        rec_t*  rec,    /* in: record */
 
1441
        trx_t*  trx)    /* in: transaction */
1384
1442
{
1385
1443
        lock_t* lock;
1386
1444
 
1389
1447
              || (precise_mode & LOCK_MODE_MASK) == LOCK_X);
1390
1448
        ut_ad(!(precise_mode & LOCK_INSERT_INTENTION));
1391
1449
 
1392
 
        lock = lock_rec_get_first(block, heap_no);
 
1450
        lock = lock_rec_get_first(rec);
1393
1451
 
1394
1452
        while (lock) {
1395
1453
                if (lock->trx == trx
1398
1456
                    && !lock_get_wait(lock)
1399
1457
                    && (!lock_rec_get_rec_not_gap(lock)
1400
1458
                        || (precise_mode & LOCK_REC_NOT_GAP)
1401
 
                        || heap_no == PAGE_HEAP_NO_SUPREMUM)
 
1459
                        || page_rec_is_supremum(rec))
1402
1460
                    && (!lock_rec_get_gap(lock)
1403
1461
                        || (precise_mode & LOCK_GAP)
1404
 
                        || heap_no == PAGE_HEAP_NO_SUPREMUM)
 
1462
                        || page_rec_is_supremum(rec))
1405
1463
                    && (!lock_rec_get_insert_intention(lock))) {
1406
1464
 
1407
1465
                        return(lock);
1408
1466
                }
1409
1467
 
1410
 
                lock = lock_rec_get_next(heap_no, lock);
 
1468
                lock = lock_rec_get_next(rec, lock);
1411
1469
        }
1412
1470
 
1413
1471
        return(NULL);
1414
1472
}
1415
1473
 
1416
 
#ifdef UNIV_DEBUG
1417
 
# ifndef UNIV_HOTBACKUP
 
1474
#ifndef UNIV_HOTBACKUP
1418
1475
/*************************************************************************
1419
1476
Checks if some other transaction has a lock request in the queue. */
1420
1477
static
1421
1478
lock_t*
1422
1479
lock_rec_other_has_expl_req(
1423
1480
/*========================*/
1424
 
                                        /* out: lock or NULL */
1425
 
        enum lock_mode          mode,   /* in: LOCK_S or LOCK_X */
1426
 
        ulint                   gap,    /* in: LOCK_GAP if also gap
1427
 
                                        locks are taken into account,
1428
 
                                        or 0 if not */
1429
 
        ulint                   wait,   /* in: LOCK_WAIT if also
1430
 
                                        waiting locks are taken into
1431
 
                                        account, or 0 if not */
1432
 
        const buf_block_t*      block,  /* in: buffer block containing
1433
 
                                        the record */
1434
 
        ulint                   heap_no,/* in: heap number of the record */
1435
 
        const trx_t*            trx)    /* in: transaction, or NULL if
1436
 
                                        requests by all transactions
1437
 
                                        are taken into account */
 
1481
                        /* out: lock or NULL */
 
1482
        ulint   mode,   /* in: LOCK_S or LOCK_X */
 
1483
        ulint   gap,    /* in: LOCK_GAP if also gap locks are taken
 
1484
                        into account, or 0 if not */
 
1485
        ulint   wait,   /* in: LOCK_WAIT if also waiting locks are
 
1486
                        taken into account, or 0 if not */
 
1487
        rec_t*  rec,    /* in: record to look at */
 
1488
        trx_t*  trx)    /* in: transaction, or NULL if requests by all
 
1489
                        transactions are taken into account */
1438
1490
{
1439
1491
        lock_t* lock;
1440
1492
 
1443
1495
        ut_ad(gap == 0 || gap == LOCK_GAP);
1444
1496
        ut_ad(wait == 0 || wait == LOCK_WAIT);
1445
1497
 
1446
 
        lock = lock_rec_get_first(block, heap_no);
 
1498
        lock = lock_rec_get_first(rec);
1447
1499
 
1448
1500
        while (lock) {
1449
1501
                if (lock->trx != trx
1450
1502
                    && (gap
1451
1503
                        || !(lock_rec_get_gap(lock)
1452
 
                             || heap_no == PAGE_HEAP_NO_SUPREMUM))
 
1504
                             || page_rec_is_supremum(rec)))
1453
1505
                    && (wait || !lock_get_wait(lock))
1454
1506
                    && lock_mode_stronger_or_eq(lock_get_mode(lock), mode)) {
1455
1507
 
1456
1508
                        return(lock);
1457
1509
                }
1458
1510
 
1459
 
                lock = lock_rec_get_next(heap_no, lock);
 
1511
                lock = lock_rec_get_next(rec, lock);
1460
1512
        }
1461
1513
 
1462
1514
        return(NULL);
1463
1515
}
1464
 
# endif /* !UNIV_HOTBACKUP */
1465
 
#endif /* UNIV_DEBUG */
 
1516
#endif /* !UNIV_HOTBACKUP */
1466
1517
 
1467
1518
/*************************************************************************
1468
1519
Checks if some other transaction has a conflicting explicit lock request
1471
1522
lock_t*
1472
1523
lock_rec_other_has_conflicting(
1473
1524
/*===========================*/
1474
 
                                        /* out: lock or NULL */
1475
 
        enum lock_mode          mode,   /* in: LOCK_S or LOCK_X,
1476
 
                                        possibly ORed to LOCK_GAP or
1477
 
                                        LOC_REC_NOT_GAP,
1478
 
                                        LOCK_INSERT_INTENTION */
1479
 
        const buf_block_t*      block,  /* in: buffer block containing
1480
 
                                        the record */
1481
 
        ulint                   heap_no,/* in: heap number of the record */
1482
 
        trx_t*                  trx)    /* in: our transaction */
 
1525
                        /* out: lock or NULL */
 
1526
        ulint   mode,   /* in: LOCK_S or LOCK_X,
 
1527
                        possibly ORed to LOCK_GAP or LOC_REC_NOT_GAP,
 
1528
                        LOCK_INSERT_INTENTION */
 
1529
        rec_t*  rec,    /* in: record to look at */
 
1530
        trx_t*  trx)    /* in: our transaction */
1483
1531
{
1484
1532
        lock_t* lock;
1485
1533
 
1486
1534
        ut_ad(mutex_own(&kernel_mutex));
1487
1535
 
1488
 
        lock = lock_rec_get_first(block, heap_no);
1489
 
 
1490
 
        if (UNIV_LIKELY_NULL(lock)) {
1491
 
                if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
1492
 
 
1493
 
                        do {
1494
 
                                if (lock_rec_has_to_wait(trx, mode, lock,
1495
 
                                                         TRUE)) {
1496
 
                                        return(lock);
1497
 
                                }
1498
 
 
1499
 
                                lock = lock_rec_get_next(heap_no, lock);
1500
 
                        } while (lock);
1501
 
                } else {
1502
 
 
1503
 
                        do {
1504
 
                                if (lock_rec_has_to_wait(trx, mode, lock,
1505
 
                                                         FALSE)) {
1506
 
                                        return(lock);
1507
 
                                }
1508
 
 
1509
 
                                lock = lock_rec_get_next(heap_no, lock);
1510
 
                        } while (lock);
 
1536
        lock = lock_rec_get_first(rec);
 
1537
 
 
1538
        while (lock) {
 
1539
                if (lock_rec_has_to_wait(trx, mode, lock,
 
1540
                                         page_rec_is_supremum(rec))) {
 
1541
 
 
1542
                        return(lock);
1511
1543
                }
 
1544
 
 
1545
                lock = lock_rec_get_next(rec, lock);
1512
1546
        }
1513
1547
 
1514
1548
        return(NULL);
1522
1556
lock_t*
1523
1557
lock_rec_find_similar_on_page(
1524
1558
/*==========================*/
1525
 
                                        /* out: lock or NULL */
1526
 
        ulint           type_mode,      /* in: lock type_mode field */
1527
 
        ulint           heap_no,        /* in: heap number of the record */
1528
 
        lock_t*         lock,           /* in: lock_rec_get_first_on_page() */
1529
 
        const trx_t*    trx)            /* in: transaction */
 
1559
                                /* out: lock or NULL */
 
1560
        ulint   type_mode,      /* in: lock type_mode field */
 
1561
        rec_t*  rec,            /* in: record */
 
1562
        trx_t*  trx)            /* in: transaction */
1530
1563
{
 
1564
        lock_t* lock;
 
1565
        ulint   heap_no;
 
1566
 
1531
1567
        ut_ad(mutex_own(&kernel_mutex));
1532
1568
 
 
1569
        heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
 
1570
        lock = lock_rec_get_first_on_page(rec);
 
1571
 
1533
1572
        while (lock != NULL) {
1534
1573
                if (lock->trx == trx
1535
1574
                    && lock->type_mode == type_mode
1547
1586
/*************************************************************************
1548
1587
Checks if some transaction has an implicit x-lock on a record in a secondary
1549
1588
index. */
1550
 
static
 
1589
 
1551
1590
trx_t*
1552
1591
lock_sec_rec_some_has_impl_off_kernel(
1553
1592
/*==================================*/
1554
1593
                                /* out: transaction which has the x-lock, or
1555
1594
                                NULL */
1556
 
        const rec_t*    rec,    /* in: user record */
 
1595
        rec_t*          rec,    /* in: user record */
1557
1596
        dict_index_t*   index,  /* in: secondary index */
1558
1597
        const ulint*    offsets)/* in: rec_get_offsets(rec, index) */
1559
1598
{
1560
 
        const page_t*   page = page_align(rec);
 
1599
        page_t* page;
1561
1600
 
1562
1601
        ut_ad(mutex_own(&kernel_mutex));
1563
 
        ut_ad(!dict_index_is_clust(index));
 
1602
        ut_ad(!(index->type & DICT_CLUSTERED));
1564
1603
        ut_ad(page_rec_is_user_rec(rec));
1565
1604
        ut_ad(rec_offs_validate(rec, index, offsets));
1566
1605
 
 
1606
        page = buf_frame_align(rec);
 
1607
 
1567
1608
        /* Some transaction may have an implicit x-lock on the record only
1568
1609
        if the max trx id for the page >= min trx id for the trx list, or
1569
1610
        database recovery is running. We do not write the changes of a page
1582
1623
 
1583
1624
        if (!lock_check_trx_id_sanity(page_get_max_trx_id(page),
1584
1625
                                      rec, index, offsets, TRUE)) {
1585
 
                buf_page_print(page, 0);
 
1626
                buf_page_print(page);
1586
1627
 
1587
1628
                /* The page is corrupt: try to avoid a crash by returning
1588
1629
                NULL */
1596
1637
Return approximate number or record locks (bits set in the bitmap) for
1597
1638
this transaction. Since delete-marked records may be removed, the
1598
1639
record count will not be precise. */
1599
 
UNIV_INTERN
 
1640
 
1600
1641
ulint
1601
1642
lock_number_of_rows_locked(
1602
1643
/*=======================*/
1610
1651
        lock = UT_LIST_GET_FIRST(trx->trx_locks);
1611
1652
 
1612
1653
        while (lock) {
1613
 
                if (lock_get_type_low(lock) == LOCK_REC) {
 
1654
                if (lock_get_type(lock) == LOCK_REC) {
1614
1655
                        n_bits = lock_rec_get_n_bits(lock);
1615
1656
 
1616
1657
                        for (n_bit = 0; n_bit < n_bits; n_bit++) {
1635
1676
lock_t*
1636
1677
lock_rec_create(
1637
1678
/*============*/
1638
 
                                        /* out: created lock */
1639
 
        ulint                   type_mode,/* in: lock mode and wait
1640
 
                                        flag, type is ignored and
1641
 
                                        replaced by LOCK_REC */
1642
 
        const buf_block_t*      block,  /* in: buffer block containing
1643
 
                                        the record */
1644
 
        ulint                   heap_no,/* in: heap number of the record */
1645
 
        dict_index_t*           index,  /* in: index of record */
1646
 
        trx_t*                  trx)    /* in: transaction */
 
1679
                                /* out: created lock */
 
1680
        ulint           type_mode,/* in: lock mode and wait flag, type is
 
1681
                                ignored and replaced by LOCK_REC */
 
1682
        rec_t*          rec,    /* in: record on page */
 
1683
        dict_index_t*   index,  /* in: index of record */
 
1684
        trx_t*          trx)    /* in: transaction */
1647
1685
{
1648
 
        lock_t*         lock;
1649
 
        ulint           page_no;
1650
 
        ulint           space;
1651
 
        ulint           n_bits;
1652
 
        ulint           n_bytes;
1653
 
        const page_t*   page;
 
1686
        page_t* page;
 
1687
        lock_t* lock;
 
1688
        ulint   page_no;
 
1689
        ulint   heap_no;
 
1690
        ulint   space;
 
1691
        ulint   n_bits;
 
1692
        ulint   n_bytes;
1654
1693
 
1655
1694
        ut_ad(mutex_own(&kernel_mutex));
1656
1695
 
1657
 
        space = buf_block_get_space(block);
1658
 
        page_no = buf_block_get_page_no(block);
1659
 
        page = block->frame;
 
1696
        page = buf_frame_align(rec);
 
1697
        space = buf_frame_get_space_id(page);
 
1698
        page_no = buf_frame_get_page_no(page);
 
1699
        heap_no = rec_get_heap_no(rec, page_is_comp(page));
1660
1700
 
1661
1701
        ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table));
1662
1702
 
1664
1704
        LOCK_REC_NOT_GAP bits, as all locks on the supremum are
1665
1705
        automatically of the gap type */
1666
1706
 
1667
 
        if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
 
1707
        if (rec == page_get_supremum_rec(page)) {
1668
1708
                ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
1669
1709
 
1670
1710
                type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP);
1697
1737
 
1698
1738
        HASH_INSERT(lock_t, hash, lock_sys->rec_hash,
1699
1739
                    lock_rec_fold(space, page_no), lock);
1700
 
        if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
 
1740
        if (type_mode & LOCK_WAIT) {
1701
1741
 
1702
1742
                lock_set_lock_and_trx_wait(lock, trx);
1703
1743
        }
1712
1752
ulint
1713
1753
lock_rec_enqueue_waiting(
1714
1754
/*=====================*/
1715
 
                                        /* out: DB_LOCK_WAIT,
1716
 
                                        DB_DEADLOCK, or
1717
 
                                        DB_QUE_THR_SUSPENDED, or
1718
 
                                        DB_SUCCESS; DB_SUCCESS means
1719
 
                                        that there was a deadlock, but
1720
 
                                        another transaction was chosen
1721
 
                                        as a victim, and we got the
1722
 
                                        lock immediately: no need to
1723
 
                                        wait then */
1724
 
        ulint                   type_mode,/* in: lock mode this
1725
 
                                        transaction is requesting:
1726
 
                                        LOCK_S or LOCK_X, possibly
1727
 
                                        ORed with LOCK_GAP or
1728
 
                                        LOCK_REC_NOT_GAP, ORed with
1729
 
                                        LOCK_INSERT_INTENTION if this
1730
 
                                        waiting lock request is set
1731
 
                                        when performing an insert of
1732
 
                                        an index record */
1733
 
        const buf_block_t*      block,  /* in: buffer block containing
1734
 
                                        the record */
1735
 
        ulint                   heap_no,/* in: heap number of the record */
1736
 
        dict_index_t*           index,  /* in: index of record */
1737
 
        que_thr_t*              thr)    /* in: query thread */
 
1755
                                /* out: DB_LOCK_WAIT, DB_DEADLOCK, or
 
1756
                                DB_QUE_THR_SUSPENDED, or DB_SUCCESS;
 
1757
                                DB_SUCCESS means that there was a deadlock,
 
1758
                                but another transaction was chosen as a
 
1759
                                victim, and we got the lock immediately:
 
1760
                                no need to wait then */
 
1761
        ulint           type_mode,/* in: lock mode this transaction is
 
1762
                                requesting: LOCK_S or LOCK_X, possibly ORed
 
1763
                                with LOCK_GAP or LOCK_REC_NOT_GAP, ORed
 
1764
                                with LOCK_INSERT_INTENTION if this waiting
 
1765
                                lock request is set when performing an
 
1766
                                insert of an index record */
 
1767
        rec_t*          rec,    /* in: record */
 
1768
        dict_index_t*   index,  /* in: index of record */
 
1769
        que_thr_t*      thr)    /* in: query thread */
1738
1770
{
1739
1771
        lock_t* lock;
1740
1772
        trx_t*  trx;
1745
1777
        we do not enqueue a lock request if the query thread should be
1746
1778
        stopped anyway */
1747
1779
 
1748
 
        if (UNIV_UNLIKELY(que_thr_stop(thr))) {
 
1780
        if (que_thr_stop(thr)) {
1749
1781
 
1750
1782
                ut_error;
1751
1783
 
1754
1786
 
1755
1787
        trx = thr_get_trx(thr);
1756
1788
 
1757
 
        switch (trx_get_dict_operation(trx)) {
1758
 
        case TRX_DICT_OP_NONE:
1759
 
                break;
1760
 
        case TRX_DICT_OP_TABLE:
1761
 
        case TRX_DICT_OP_INDEX:
 
1789
        if (trx->dict_operation) {
1762
1790
                ut_print_timestamp(stderr);
1763
1791
                fputs("  InnoDB: Error: a record lock wait happens"
1764
1792
                      " in a dictionary operation!\n"
1765
 
                      "InnoDB: ", stderr);
1766
 
                dict_index_name_print(stderr, trx, index);
 
1793
                      "InnoDB: Table name ", stderr);
 
1794
                ut_print_name(stderr, trx, TRUE, index->table_name);
1767
1795
                fputs(".\n"
1768
1796
                      "InnoDB: Submit a detailed bug report"
1769
1797
                      " to http://bugs.mysql.com\n",
1771
1799
        }
1772
1800
 
1773
1801
        /* Enqueue the lock request that will wait to be granted */
1774
 
        lock = lock_rec_create(type_mode | LOCK_WAIT,
1775
 
                               block, heap_no, index, trx);
 
1802
        lock = lock_rec_create(type_mode | LOCK_WAIT, rec, index, trx);
1776
1803
 
1777
1804
        /* Check if a deadlock occurs: if yes, remove the lock request and
1778
1805
        return an error code */
1779
1806
 
1780
 
        if (UNIV_UNLIKELY(lock_deadlock_occurs(lock, trx))) {
 
1807
        if (lock_deadlock_occurs(lock, trx)) {
1781
1808
 
1782
1809
                lock_reset_lock_and_trx_wait(lock);
1783
 
                lock_rec_reset_nth_bit(lock, heap_no);
 
1810
                lock_rec_reset_nth_bit(lock, rec_get_heap_no(
 
1811
                                               rec, page_rec_is_comp(rec)));
1784
1812
 
1785
1813
                return(DB_DEADLOCK);
1786
1814
        }
1821
1849
lock_t*
1822
1850
lock_rec_add_to_queue(
1823
1851
/*==================*/
1824
 
                                        /* out: lock where the bit was set */
1825
 
        ulint                   type_mode,/* in: lock mode, wait, gap
1826
 
                                        etc. flags; type is ignored
1827
 
                                        and replaced by LOCK_REC */
1828
 
        const buf_block_t*      block,  /* in: buffer block containing
1829
 
                                        the record */
1830
 
        ulint                   heap_no,/* in: heap number of the record */
1831
 
        dict_index_t*           index,  /* in: index of record */
1832
 
        trx_t*                  trx)    /* in: transaction */
 
1852
                                /* out: lock where the bit was set */
 
1853
        ulint           type_mode,/* in: lock mode, wait, gap etc. flags;
 
1854
                                type is ignored and replaced by LOCK_REC */
 
1855
        rec_t*          rec,    /* in: record on page */
 
1856
        dict_index_t*   index,  /* in: index of record */
 
1857
        trx_t*          trx)    /* in: transaction */
1833
1858
{
1834
1859
        lock_t* lock;
 
1860
        lock_t* similar_lock    = NULL;
 
1861
        ulint   heap_no;
 
1862
        ibool   somebody_waits  = FALSE;
1835
1863
 
1836
1864
        ut_ad(mutex_own(&kernel_mutex));
1837
 
#ifdef UNIV_DEBUG
1838
 
        switch (type_mode & LOCK_MODE_MASK) {
1839
 
        case LOCK_X:
1840
 
        case LOCK_S:
1841
 
                break;
1842
 
        default:
1843
 
                ut_error;
1844
 
        }
1845
 
 
1846
 
        if (!(type_mode & (LOCK_WAIT | LOCK_GAP))) {
1847
 
                enum lock_mode  mode = (type_mode & LOCK_MODE_MASK) == LOCK_S
1848
 
                        ? LOCK_X
1849
 
                        : LOCK_S;
1850
 
                lock_t*         other_lock
1851
 
                        = lock_rec_other_has_expl_req(mode, 0, LOCK_WAIT,
1852
 
                                                      block, heap_no, trx);
1853
 
                ut_a(!other_lock);
1854
 
        }
1855
 
#endif /* UNIV_DEBUG */
1856
 
 
1857
 
        type_mode |= LOCK_REC;
 
1865
        ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
 
1866
              || ((type_mode & LOCK_MODE_MASK) != LOCK_S)
 
1867
              || !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT,
 
1868
                                              rec, trx));
 
1869
        ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
 
1870
              || ((type_mode & LOCK_MODE_MASK) != LOCK_X)
 
1871
              || !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
 
1872
                                              rec, trx));
 
1873
 
 
1874
        type_mode = type_mode | LOCK_REC;
1858
1875
 
1859
1876
        /* If rec is the supremum record, then we can reset the gap bit, as
1860
1877
        all locks on the supremum are automatically of the gap type, and we
1861
1878
        try to avoid unnecessary memory consumption of a new record lock
1862
1879
        struct for a gap type lock */
1863
1880
 
1864
 
        if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
 
1881
        if (page_rec_is_supremum(rec)) {
1865
1882
                ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
1866
1883
 
1867
1884
                /* There should never be LOCK_REC_NOT_GAP on a supremum
1872
1889
 
1873
1890
        /* Look for a waiting lock request on the same record or on a gap */
1874
1891
 
1875
 
        lock = lock_rec_get_first_on_page(block);
 
1892
        heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
 
1893
        lock = lock_rec_get_first_on_page(rec);
1876
1894
 
1877
1895
        while (lock != NULL) {
1878
1896
                if (lock_get_wait(lock)
1879
1897
                    && (lock_rec_get_nth_bit(lock, heap_no))) {
1880
1898
 
1881
 
                        goto somebody_waits;
 
1899
                        somebody_waits = TRUE;
1882
1900
                }
1883
1901
 
1884
1902
                lock = lock_rec_get_next_on_page(lock);
1885
1903
        }
1886
1904
 
1887
 
        if (UNIV_LIKELY(!(type_mode & LOCK_WAIT))) {
1888
 
 
1889
 
                /* Look for a similar record lock on the same page:
1890
 
                if one is found and there are no waiting lock requests,
1891
 
                we can just set the bit */
1892
 
 
1893
 
                lock = lock_rec_find_similar_on_page(
1894
 
                        type_mode, heap_no,
1895
 
                        lock_rec_get_first_on_page(block), trx);
1896
 
 
1897
 
                if (lock) {
1898
 
 
1899
 
                        lock_rec_set_nth_bit(lock, heap_no);
1900
 
 
1901
 
                        return(lock);
1902
 
                }
 
1905
        /* Look for a similar record lock on the same page: if one is found
 
1906
        and there are no waiting lock requests, we can just set the bit */
 
1907
 
 
1908
        similar_lock = lock_rec_find_similar_on_page(type_mode, rec, trx);
 
1909
 
 
1910
        if (similar_lock && !somebody_waits && !(type_mode & LOCK_WAIT)) {
 
1911
 
 
1912
                lock_rec_set_nth_bit(similar_lock, heap_no);
 
1913
 
 
1914
                return(similar_lock);
1903
1915
        }
1904
1916
 
1905
 
somebody_waits:
1906
 
        return(lock_rec_create(type_mode, block, heap_no, index, trx));
 
1917
        return(lock_rec_create(type_mode, rec, index, trx));
1907
1918
}
1908
1919
 
1909
1920
/*************************************************************************
1917
1928
ibool
1918
1929
lock_rec_lock_fast(
1919
1930
/*===============*/
1920
 
                                        /* out: TRUE if locking succeeded */
1921
 
        ibool                   impl,   /* in: if TRUE, no lock is set
1922
 
                                        if no wait is necessary: we
1923
 
                                        assume that the caller will
1924
 
                                        set an implicit lock */
1925
 
        ulint                   mode,   /* in: lock mode: LOCK_X or
1926
 
                                        LOCK_S possibly ORed to either
1927
 
                                        LOCK_GAP or LOCK_REC_NOT_GAP */
1928
 
        const buf_block_t*      block,  /* in: buffer block containing
1929
 
                                        the record */
1930
 
        ulint                   heap_no,/* in: heap number of record */
1931
 
        dict_index_t*           index,  /* in: index of record */
1932
 
        que_thr_t*              thr)    /* in: query thread */
 
1931
                                /* out: TRUE if locking succeeded */
 
1932
        ibool           impl,   /* in: if TRUE, no lock is set if no wait
 
1933
                                is necessary: we assume that the caller will
 
1934
                                set an implicit lock */
 
1935
        ulint           mode,   /* in: lock mode: LOCK_X or LOCK_S possibly
 
1936
                                ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
 
1937
        rec_t*          rec,    /* in: record */
 
1938
        dict_index_t*   index,  /* in: index of record */
 
1939
        que_thr_t*      thr)    /* in: query thread */
1933
1940
{
1934
1941
        lock_t* lock;
 
1942
        ulint   heap_no;
1935
1943
        trx_t*  trx;
1936
1944
 
1937
1945
        ut_ad(mutex_own(&kernel_mutex));
1945
1953
              || mode - (LOCK_MODE_MASK & mode) == 0
1946
1954
              || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
1947
1955
 
1948
 
        lock = lock_rec_get_first_on_page(block);
 
1956
        heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
 
1957
 
 
1958
        lock = lock_rec_get_first_on_page(rec);
1949
1959
 
1950
1960
        trx = thr_get_trx(thr);
1951
1961
 
1952
1962
        if (lock == NULL) {
1953
1963
                if (!impl) {
1954
 
                        lock_rec_create(mode, block, heap_no, index, trx);
 
1964
                        lock_rec_create(mode, rec, index, trx);
1955
1965
 
1956
1966
                        if (srv_locks_unsafe_for_binlog
1957
1967
                            || trx->isolation_level
2001
2011
ulint
2002
2012
lock_rec_lock_slow(
2003
2013
/*===============*/
2004
 
                                        /* out: DB_SUCCESS,
2005
 
                                        DB_LOCK_WAIT, or error code */
2006
 
        ibool                   impl,   /* in: if TRUE, no lock is set
2007
 
                                        if no wait is necessary: we
2008
 
                                        assume that the caller will
2009
 
                                        set an implicit lock */
2010
 
        ulint                   mode,   /* in: lock mode: LOCK_X or
2011
 
                                        LOCK_S possibly ORed to either
2012
 
                                        LOCK_GAP or LOCK_REC_NOT_GAP */
2013
 
        const buf_block_t*      block,  /* in: buffer block containing
2014
 
                                        the record */
2015
 
        ulint                   heap_no,/* in: heap number of record */
2016
 
        dict_index_t*           index,  /* in: index of record */
2017
 
        que_thr_t*              thr)    /* in: query thread */
 
2014
                                /* out: DB_SUCCESS, DB_LOCK_WAIT, or error
 
2015
                                code */
 
2016
        ibool           impl,   /* in: if TRUE, no lock is set if no wait is
 
2017
                                necessary: we assume that the caller will set
 
2018
                                an implicit lock */
 
2019
        ulint           mode,   /* in: lock mode: LOCK_X or LOCK_S possibly
 
2020
                                ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
 
2021
        rec_t*          rec,    /* in: record */
 
2022
        dict_index_t*   index,  /* in: index of record */
 
2023
        que_thr_t*      thr)    /* in: query thread */
2018
2024
{
2019
2025
        trx_t*  trx;
2020
2026
        ulint   err;
2032
2038
 
2033
2039
        trx = thr_get_trx(thr);
2034
2040
 
2035
 
        if (lock_rec_has_expl(mode, block, heap_no, trx)) {
 
2041
        if (lock_rec_has_expl(mode, rec, trx)) {
2036
2042
                /* The trx already has a strong enough lock on rec: do
2037
2043
                nothing */
2038
2044
 
2039
2045
                err = DB_SUCCESS;
2040
 
        } else if (lock_rec_other_has_conflicting(mode, block, heap_no, trx)) {
 
2046
        } else if (lock_rec_other_has_conflicting(mode, rec, trx)) {
2041
2047
 
2042
2048
                /* If another transaction has a non-gap conflicting request in
2043
2049
                the queue, as this transaction does not have a lock strong
2044
2050
                enough already granted on the record, we have to wait. */
2045
2051
 
2046
 
                err = lock_rec_enqueue_waiting(mode, block, heap_no,
2047
 
                                               index, thr);
 
2052
                err = lock_rec_enqueue_waiting(mode, rec, index, thr);
2048
2053
 
2049
2054
                if (srv_locks_unsafe_for_binlog
2050
2055
                    || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
2054
2059
                if (!impl) {
2055
2060
                        /* Set the requested lock on the record */
2056
2061
 
2057
 
                        lock_rec_add_to_queue(LOCK_REC | mode, block,
2058
 
                                              heap_no, index, trx);
 
2062
                        lock_rec_add_to_queue(LOCK_REC | mode, rec, index,
 
2063
                                              trx);
2059
2064
                        if (srv_locks_unsafe_for_binlog
2060
2065
                            || trx->isolation_level
2061
2066
                            == TRX_ISO_READ_COMMITTED) {
2079
2084
ulint
2080
2085
lock_rec_lock(
2081
2086
/*==========*/
2082
 
                                        /* out: DB_SUCCESS,
2083
 
                                        DB_LOCK_WAIT, or error code */
2084
 
        ibool                   impl,   /* in: if TRUE, no lock is set
2085
 
                                        if no wait is necessary: we
2086
 
                                        assume that the caller will
2087
 
                                        set an implicit lock */
2088
 
        ulint                   mode,   /* in: lock mode: LOCK_X or
2089
 
                                        LOCK_S possibly ORed to either
2090
 
                                        LOCK_GAP or LOCK_REC_NOT_GAP */
2091
 
        const buf_block_t*      block,  /* in: buffer block containing
2092
 
                                        the record */
2093
 
        ulint                   heap_no,/* in: heap number of record */
2094
 
        dict_index_t*           index,  /* in: index of record */
2095
 
        que_thr_t*              thr)    /* in: query thread */
 
2087
                                /* out: DB_SUCCESS, DB_LOCK_WAIT, or error
 
2088
                                code */
 
2089
        ibool           impl,   /* in: if TRUE, no lock is set if no wait is
 
2090
                                necessary: we assume that the caller will set
 
2091
                                an implicit lock */
 
2092
        ulint           mode,   /* in: lock mode: LOCK_X or LOCK_S possibly
 
2093
                                ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
 
2094
        rec_t*          rec,    /* in: record */
 
2095
        dict_index_t*   index,  /* in: index of record */
 
2096
        que_thr_t*      thr)    /* in: query thread */
2096
2097
{
2097
2098
        ulint   err;
2098
2099
 
2107
2108
              || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
2108
2109
              || mode - (LOCK_MODE_MASK & mode) == 0);
2109
2110
 
2110
 
        if (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) {
 
2111
        if (lock_rec_lock_fast(impl, mode, rec, index, thr)) {
2111
2112
 
2112
2113
                /* We try a simplified and faster subroutine for the most
2113
2114
                common cases */
2114
2115
 
2115
2116
                err = DB_SUCCESS;
2116
2117
        } else {
2117
 
                err = lock_rec_lock_slow(impl, mode, block,
2118
 
                                         heap_no, index, thr);
 
2118
                err = lock_rec_lock_slow(impl, mode, rec, index, thr);
2119
2119
        }
2120
2120
 
2121
2121
        return(err);
2137
2137
 
2138
2138
        ut_ad(mutex_own(&kernel_mutex));
2139
2139
        ut_ad(lock_get_wait(wait_lock));
2140
 
        ut_ad(lock_get_type_low(wait_lock) == LOCK_REC);
 
2140
        ut_ad(lock_get_type(wait_lock) == LOCK_REC);
2141
2141
 
2142
2142
        space = wait_lock->un_member.rec_lock.space;
2143
2143
        page_no = wait_lock->un_member.rec_lock.page_no;
2214
2214
        lock_t* lock)   /* in: waiting record lock request */
2215
2215
{
2216
2216
        ut_ad(mutex_own(&kernel_mutex));
2217
 
        ut_ad(lock_get_type_low(lock) == LOCK_REC);
 
2217
        ut_ad(lock_get_type(lock) == LOCK_REC);
2218
2218
 
2219
2219
        /* Reset the bit (there can be only one set bit) in the lock bitmap */
2220
2220
        lock_rec_reset_nth_bit(lock, lock_rec_find_set_bit(lock));
2247
2247
        trx_t*  trx;
2248
2248
 
2249
2249
        ut_ad(mutex_own(&kernel_mutex));
2250
 
        ut_ad(lock_get_type_low(in_lock) == LOCK_REC);
 
2250
        ut_ad(lock_get_type(in_lock) == LOCK_REC);
2251
2251
 
2252
2252
        trx = in_lock->trx;
2253
2253
 
2290
2290
        trx_t*  trx;
2291
2291
 
2292
2292
        ut_ad(mutex_own(&kernel_mutex));
2293
 
        ut_ad(lock_get_type_low(in_lock) == LOCK_REC);
 
2293
        ut_ad(lock_get_type(in_lock) == LOCK_REC);
2294
2294
 
2295
2295
        trx = in_lock->trx;
2296
2296
 
2311
2311
void
2312
2312
lock_rec_free_all_from_discard_page(
2313
2313
/*================================*/
2314
 
        const buf_block_t*      block)  /* in: page to be discarded */
 
2314
        page_t* page)   /* in: page to be discarded */
2315
2315
{
2316
2316
        ulint   space;
2317
2317
        ulint   page_no;
2320
2320
 
2321
2321
        ut_ad(mutex_own(&kernel_mutex));
2322
2322
 
2323
 
        space = buf_block_get_space(block);
2324
 
        page_no = buf_block_get_page_no(block);
 
2323
        space = buf_frame_get_space_id(page);
 
2324
        page_no = buf_frame_get_page_no(page);
2325
2325
 
2326
2326
        lock = lock_rec_get_first_on_page_addr(space, page_no);
2327
2327
 
2346
2346
void
2347
2347
lock_rec_reset_and_release_wait(
2348
2348
/*============================*/
2349
 
        const buf_block_t*      block,  /* in: buffer block containing
2350
 
                                        the record */
2351
 
        ulint                   heap_no)/* in: heap number of record */
 
2349
        rec_t*  rec)    /* in: record whose locks bits should be reset */
2352
2350
{
2353
2351
        lock_t* lock;
 
2352
        ulint   heap_no;
2354
2353
 
2355
2354
        ut_ad(mutex_own(&kernel_mutex));
2356
2355
 
2357
 
        lock = lock_rec_get_first(block, heap_no);
 
2356
        heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
 
2357
 
 
2358
        lock = lock_rec_get_first(rec);
2358
2359
 
2359
2360
        while (lock != NULL) {
2360
2361
                if (lock_get_wait(lock)) {
2363
2364
                        lock_rec_reset_nth_bit(lock, heap_no);
2364
2365
                }
2365
2366
 
2366
 
                lock = lock_rec_get_next(heap_no, lock);
 
2367
                lock = lock_rec_get_next(rec, lock);
2367
2368
        }
2368
2369
}
2369
2370
 
2372
2373
of another record as gap type locks, but does not reset the lock bits of
2373
2374
the other record. Also waiting lock requests on rec are inherited as
2374
2375
GRANTED gap locks. */
2375
 
static
 
2376
 
2376
2377
void
2377
2378
lock_rec_inherit_to_gap(
2378
2379
/*====================*/
2379
 
        const buf_block_t*      heir_block,     /* in: block containing the
2380
 
                                                record which inherits */
2381
 
        const buf_block_t*      block,          /* in: block containing the
2382
 
                                                record from which inherited;
2383
 
                                                does NOT reset the locks on
2384
 
                                                this record */
2385
 
        ulint                   heir_heap_no,   /* in: heap_no of the
2386
 
                                                inheriting record */
2387
 
        ulint                   heap_no)        /* in: heap_no of the
2388
 
                                                donating record */
 
2380
        rec_t*  heir,   /* in: record which inherits */
 
2381
        rec_t*  rec)    /* in: record from which inherited; does NOT reset
 
2382
                        the locks on this record */
2389
2383
{
2390
2384
        lock_t* lock;
2391
2385
 
2392
2386
        ut_ad(mutex_own(&kernel_mutex));
2393
2387
 
2394
 
        lock = lock_rec_get_first(block, heap_no);
 
2388
        lock = lock_rec_get_first(rec);
2395
2389
 
2396
2390
        /* If srv_locks_unsafe_for_binlog is TRUE or session is using
2397
2391
        READ COMMITTED isolation level, we do not want locks set
2406
2400
                          == TRX_ISO_READ_COMMITTED)
2407
2401
                         && lock_get_mode(lock) == LOCK_X)) {
2408
2402
 
2409
 
                        lock_rec_add_to_queue(LOCK_REC | LOCK_GAP
2410
 
                                              | lock_get_mode(lock),
2411
 
                                              heir_block, heir_heap_no,
2412
 
                                              lock->index, lock->trx);
 
2403
                        lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock)
 
2404
                                              | LOCK_GAP,
 
2405
                                              heir, lock->index, lock->trx);
2413
2406
                }
2414
2407
 
2415
 
                lock = lock_rec_get_next(heap_no, lock);
 
2408
                lock = lock_rec_get_next(rec, lock);
2416
2409
        }
2417
2410
}
2418
2411
 
2424
2417
void
2425
2418
lock_rec_inherit_to_gap_if_gap_lock(
2426
2419
/*================================*/
2427
 
        const buf_block_t*      block,          /* in: buffer block */
2428
 
        ulint                   heir_heap_no,   /* in: heap_no of
2429
 
                                                record which inherits */
2430
 
        ulint                   heap_no)        /* in: heap_no of record
2431
 
                                                from which inherited;
2432
 
                                                does NOT reset the locks
2433
 
                                                on this record */
 
2420
        rec_t*  heir,   /* in: record which inherits */
 
2421
        rec_t*  rec)    /* in: record from which inherited; does NOT reset
 
2422
                        the locks on this record */
2434
2423
{
2435
2424
        lock_t* lock;
2436
2425
 
2437
2426
        ut_ad(mutex_own(&kernel_mutex));
2438
2427
 
2439
 
        lock = lock_rec_get_first(block, heap_no);
 
2428
        lock = lock_rec_get_first(rec);
2440
2429
 
2441
2430
        while (lock != NULL) {
2442
2431
                if (!lock_rec_get_insert_intention(lock)
2443
 
                    && (heap_no == PAGE_HEAP_NO_SUPREMUM
 
2432
                    && (page_rec_is_supremum(rec)
2444
2433
                        || !lock_rec_get_rec_not_gap(lock))) {
2445
2434
 
2446
 
                        lock_rec_add_to_queue(LOCK_REC | LOCK_GAP
2447
 
                                              | lock_get_mode(lock),
2448
 
                                              block, heir_heap_no,
2449
 
                                              lock->index, lock->trx);
 
2435
                        lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock)
 
2436
                                              | LOCK_GAP,
 
2437
                                              heir, lock->index, lock->trx);
2450
2438
                }
2451
2439
 
2452
 
                lock = lock_rec_get_next(heap_no, lock);
 
2440
                lock = lock_rec_get_next(rec, lock);
2453
2441
        }
2454
2442
}
2455
2443
 
2460
2448
void
2461
2449
lock_rec_move(
2462
2450
/*==========*/
2463
 
        const buf_block_t*      receiver,       /* in: buffer block containing
2464
 
                                                the receiving record */
2465
 
        const buf_block_t*      donator,        /* in: buffer block containing
2466
 
                                                the donating record */
2467
 
        ulint                   receiver_heap_no,/* in: heap_no of the record
2468
 
                                                which gets the locks; there
2469
 
                                                must be no lock requests
2470
 
                                                on it! */
2471
 
        ulint                   donator_heap_no)/* in: heap_no of the record
2472
 
                                                which gives the locks */
 
2451
        rec_t*  receiver,       /* in: record which gets locks; this record
 
2452
                                must have no lock requests on it! */
 
2453
        rec_t*  donator,        /* in: record which gives locks */
 
2454
        ulint   comp)           /* in: nonzero=compact page format */
2473
2455
{
2474
2456
        lock_t* lock;
 
2457
        ulint   heap_no;
 
2458
        ulint   type_mode;
2475
2459
 
2476
2460
        ut_ad(mutex_own(&kernel_mutex));
2477
2461
 
2478
 
        lock = lock_rec_get_first(donator, donator_heap_no);
2479
 
 
2480
 
        ut_ad(lock_rec_get_first(receiver, receiver_heap_no) == NULL);
 
2462
        heap_no = rec_get_heap_no(donator, comp);
 
2463
 
 
2464
        lock = lock_rec_get_first(donator);
 
2465
 
 
2466
        ut_ad(lock_rec_get_first(receiver) == NULL);
2481
2467
 
2482
2468
        while (lock != NULL) {
2483
 
                const ulint     type_mode = lock->type_mode;
2484
 
 
2485
 
                lock_rec_reset_nth_bit(lock, donator_heap_no);
2486
 
 
2487
 
                if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
 
2469
                type_mode = lock->type_mode;
 
2470
 
 
2471
                lock_rec_reset_nth_bit(lock, heap_no);
 
2472
 
 
2473
                if (lock_get_wait(lock)) {
2488
2474
                        lock_reset_lock_and_trx_wait(lock);
2489
2475
                }
2490
2476
 
2491
2477
                /* Note that we FIRST reset the bit, and then set the lock:
2492
2478
                the function works also if donator == receiver */
2493
2479
 
2494
 
                lock_rec_add_to_queue(type_mode, receiver, receiver_heap_no,
2495
 
                                      lock->index, lock->trx);
2496
 
                lock = lock_rec_get_next(donator_heap_no, lock);
 
2480
                lock_rec_add_to_queue(type_mode, receiver, lock->index,
 
2481
                                      lock->trx);
 
2482
                lock = lock_rec_get_next(donator, lock);
2497
2483
        }
2498
2484
 
2499
 
        ut_ad(lock_rec_get_first(donator, donator_heap_no) == NULL);
 
2485
        ut_ad(lock_rec_get_first(donator) == NULL);
2500
2486
}
2501
2487
 
2502
2488
/*****************************************************************
2504
2490
also the locks set on the infimum of the page; the infimum may carry
2505
2491
locks if an update of a record is occurring on the page, and its locks
2506
2492
were temporarily stored on the infimum. */
2507
 
UNIV_INTERN
 
2493
 
2508
2494
void
2509
2495
lock_move_reorganize_page(
2510
2496
/*======================*/
2511
 
        const buf_block_t*      block,  /* in: old index page, now
2512
 
                                        reorganized */
2513
 
        const buf_block_t*      oblock) /* in: copy of the old, not
2514
 
                                        reorganized page */
 
2497
        page_t* page,           /* in: old index page, now reorganized */
 
2498
        page_t* old_page)       /* in: copy of the old, not reorganized page */
2515
2499
{
2516
2500
        lock_t*         lock;
 
2501
        lock_t*         old_lock;
 
2502
        page_cur_t      cur1;
 
2503
        page_cur_t      cur2;
 
2504
        ulint           old_heap_no;
2517
2505
        UT_LIST_BASE_NODE_T(lock_t)     old_locks;
2518
2506
        mem_heap_t*     heap            = NULL;
 
2507
        rec_t*          sup;
2519
2508
        ulint           comp;
2520
2509
 
2521
2510
        lock_mutex_enter_kernel();
2522
2511
 
2523
 
        lock = lock_rec_get_first_on_page(block);
 
2512
        lock = lock_rec_get_first_on_page(page);
2524
2513
 
2525
2514
        if (lock == NULL) {
2526
2515
                lock_mutex_exit_kernel();
2536
2525
 
2537
2526
        UT_LIST_INIT(old_locks);
2538
2527
 
2539
 
        do {
 
2528
        while (lock != NULL) {
 
2529
 
2540
2530
                /* Make a copy of the lock */
2541
 
                lock_t* old_lock = lock_rec_copy(lock, heap);
 
2531
                old_lock = lock_rec_copy(lock, heap);
2542
2532
 
2543
2533
                UT_LIST_ADD_LAST(trx_locks, old_locks, old_lock);
2544
2534
 
2550
2540
                }
2551
2541
 
2552
2542
                lock = lock_rec_get_next_on_page(lock);
2553
 
        } while (lock != NULL);
2554
 
 
2555
 
        comp = page_is_comp(block->frame);
2556
 
        ut_ad(comp == page_is_comp(oblock->frame));
2557
 
 
2558
 
        for (lock = UT_LIST_GET_FIRST(old_locks); lock;
2559
 
             lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
 
2543
        }
 
2544
 
 
2545
        sup = page_get_supremum_rec(page);
 
2546
 
 
2547
        lock = UT_LIST_GET_FIRST(old_locks);
 
2548
 
 
2549
        comp = page_is_comp(page);
 
2550
        ut_ad(comp == page_is_comp(old_page));
 
2551
 
 
2552
        while (lock) {
2560
2553
                /* NOTE: we copy also the locks set on the infimum and
2561
2554
                supremum of the page; the infimum may carry locks if an
2562
2555
                update of a record is occurring on the page, and its locks
2563
2556
                were temporarily stored on the infimum */
2564
 
                page_cur_t      cur1;
2565
 
                page_cur_t      cur2;
2566
2557
 
2567
 
                page_cur_set_before_first(block, &cur1);
2568
 
                page_cur_set_before_first(oblock, &cur2);
 
2558
                page_cur_set_before_first(page, &cur1);
 
2559
                page_cur_set_before_first(old_page, &cur2);
2569
2560
 
2570
2561
                /* Set locks according to old locks */
2571
2562
                for (;;) {
2572
 
                        ulint   old_heap_no;
2573
 
                        ulint   new_heap_no;
2574
 
 
2575
2563
                        ut_ad(comp || !memcmp(page_cur_get_rec(&cur1),
2576
2564
                                              page_cur_get_rec(&cur2),
2577
2565
                                              rec_get_data_size_old(
2578
2566
                                                      page_cur_get_rec(
2579
2567
                                                              &cur2))));
2580
 
                        if (UNIV_LIKELY(comp)) {
2581
 
                                old_heap_no = rec_get_heap_no_new(
2582
 
                                        page_cur_get_rec(&cur2));
2583
 
                                new_heap_no = rec_get_heap_no_new(
2584
 
                                        page_cur_get_rec(&cur1));
2585
 
                        } else {
2586
 
                                old_heap_no = rec_get_heap_no_old(
2587
 
                                        page_cur_get_rec(&cur2));
2588
 
                                new_heap_no = rec_get_heap_no_old(
2589
 
                                        page_cur_get_rec(&cur1));
2590
 
                        }
 
2568
                        old_heap_no = rec_get_heap_no(page_cur_get_rec(&cur2),
 
2569
                                                      comp);
2591
2570
 
2592
2571
                        if (lock_rec_get_nth_bit(lock, old_heap_no)) {
2593
2572
 
2594
 
                                /* Clear the bit in old_lock. */
2595
 
                                ut_d(lock_rec_reset_nth_bit(lock,
2596
 
                                                            old_heap_no));
2597
 
 
2598
2573
                                /* NOTE that the old lock bitmap could be too
2599
2574
                                small for the new heap number! */
2600
2575
 
2601
 
                                lock_rec_add_to_queue(lock->type_mode, block,
2602
 
                                                      new_heap_no,
 
2576
                                lock_rec_add_to_queue(lock->type_mode,
 
2577
                                                      page_cur_get_rec(&cur1),
2603
2578
                                                      lock->index, lock->trx);
2604
2579
 
2605
 
                                /* if (new_heap_no == PAGE_HEAP_NO_SUPREMUM
 
2580
                                /* if ((page_cur_get_rec(&cur1) == sup)
2606
2581
                                && lock_get_wait(lock)) {
2607
2582
                                fprintf(stderr,
2608
2583
                                "---\n--\n!!!Lock reorg: supr type %lu\n",
2610
2585
                                } */
2611
2586
                        }
2612
2587
 
2613
 
                        if (UNIV_UNLIKELY
2614
 
                            (new_heap_no == PAGE_HEAP_NO_SUPREMUM)) {
 
2588
                        if (page_cur_get_rec(&cur1) == sup) {
2615
2589
 
2616
 
                                ut_ad(old_heap_no == PAGE_HEAP_NO_SUPREMUM);
2617
2590
                                break;
2618
2591
                        }
2619
2592
 
2621
2594
                        page_cur_move_to_next(&cur2);
2622
2595
                }
2623
2596
 
2624
 
#ifdef UNIV_DEBUG
2625
 
                {
2626
 
                        ulint   i = lock_rec_find_set_bit(lock);
 
2597
                /* Remember that we chained old locks on the trx_locks field */
2627
2598
 
2628
 
                        /* Check that all locks were moved. */
2629
 
                        if (UNIV_UNLIKELY(i != ULINT_UNDEFINED)) {
2630
 
                                fprintf(stderr,
2631
 
                                        "lock_move_reorganize_page():"
2632
 
                                        " %lu not moved in %p\n",
2633
 
                                        (ulong) i, (void*) lock);
2634
 
                                ut_error;
2635
 
                        }
2636
 
                }
2637
 
#endif /* UNIV_DEBUG */
 
2599
                lock = UT_LIST_GET_NEXT(trx_locks, lock);
2638
2600
        }
2639
2601
 
2640
2602
        lock_mutex_exit_kernel();
2641
2603
 
2642
2604
        mem_heap_free(heap);
2643
2605
 
2644
 
#ifdef UNIV_DEBUG_LOCK_VALIDATE
2645
 
        ut_ad(lock_rec_validate_page(buf_block_get_space(block),
2646
 
                                     buf_block_get_page_no(block)));
 
2606
#if 0
 
2607
        ut_ad(lock_rec_validate_page(buf_frame_get_space_id(page),
 
2608
                                     buf_frame_get_page_no(page)));
2647
2609
#endif
2648
2610
}
2649
2611
 
2650
2612
/*****************************************************************
2651
2613
Moves the explicit locks on user records to another page if a record
2652
2614
list end is moved to another page. */
2653
 
UNIV_INTERN
 
2615
 
2654
2616
void
2655
2617
lock_move_rec_list_end(
2656
2618
/*===================*/
2657
 
        const buf_block_t*      new_block,      /* in: index page to move to */
2658
 
        const buf_block_t*      block,          /* in: index page */
2659
 
        const rec_t*            rec)            /* in: record on page: this
2660
 
                                                is the first record moved */
 
2619
        page_t* new_page,       /* in: index page to move to */
 
2620
        page_t* page,           /* in: index page */
 
2621
        rec_t*  rec)            /* in: record on page: this is the
 
2622
                                first record moved */
2661
2623
{
2662
2624
        lock_t*         lock;
2663
 
        const ulint     comp    = page_rec_is_comp(rec);
 
2625
        page_cur_t      cur1;
 
2626
        page_cur_t      cur2;
 
2627
        ulint           heap_no;
 
2628
        rec_t*          sup;
 
2629
        ulint           type_mode;
 
2630
        ulint           comp;
 
2631
        ut_ad(page == buf_frame_align(rec));
2664
2632
 
2665
2633
        lock_mutex_enter_kernel();
2666
2634
 
2670
2638
        table to the end of the hash chain, and lock_rec_add_to_queue
2671
2639
        does not reuse locks if there are waiters in the queue. */
2672
2640
 
2673
 
        for (lock = lock_rec_get_first_on_page(block); lock;
2674
 
             lock = lock_rec_get_next_on_page(lock)) {
2675
 
                page_cur_t      cur1;
2676
 
                page_cur_t      cur2;
2677
 
                const ulint     type_mode = lock->type_mode;
2678
 
 
2679
 
                page_cur_position(rec, block, &cur1);
 
2641
        sup = page_get_supremum_rec(page);
 
2642
 
 
2643
        lock = lock_rec_get_first_on_page(page);
 
2644
 
 
2645
        comp = page_is_comp(page);
 
2646
 
 
2647
        while (lock != NULL) {
 
2648
 
 
2649
                page_cur_position(rec, &cur1);
2680
2650
 
2681
2651
                if (page_cur_is_before_first(&cur1)) {
2682
2652
                        page_cur_move_to_next(&cur1);
2683
2653
                }
2684
2654
 
2685
 
                page_cur_set_before_first(new_block, &cur2);
 
2655
                page_cur_set_before_first(new_page, &cur2);
2686
2656
                page_cur_move_to_next(&cur2);
2687
2657
 
2688
2658
                /* Copy lock requests on user records to new page and
2689
2659
                reset the lock bits on the old */
2690
2660
 
2691
 
                while (!page_cur_is_after_last(&cur1)) {
2692
 
                        ulint   heap_no;
2693
 
 
2694
 
                        if (comp) {
2695
 
                                heap_no = rec_get_heap_no_new(
2696
 
                                        page_cur_get_rec(&cur1));
2697
 
                        } else {
2698
 
                                heap_no = rec_get_heap_no_old(
2699
 
                                        page_cur_get_rec(&cur1));
2700
 
                                ut_ad(!memcmp(page_cur_get_rec(&cur1),
2701
 
                                         page_cur_get_rec(&cur2),
2702
 
                                         rec_get_data_size_old(
2703
 
                                                 page_cur_get_rec(&cur2))));
2704
 
                        }
 
2661
                while (page_cur_get_rec(&cur1) != sup) {
 
2662
                        ut_ad(comp || !memcmp(page_cur_get_rec(&cur1),
 
2663
                                              page_cur_get_rec(&cur2),
 
2664
                                              rec_get_data_size_old(
 
2665
                                                      page_cur_get_rec(
 
2666
                                                              &cur2))));
 
2667
                        heap_no = rec_get_heap_no(page_cur_get_rec(&cur1),
 
2668
                                                  comp);
2705
2669
 
2706
2670
                        if (lock_rec_get_nth_bit(lock, heap_no)) {
 
2671
                                type_mode = lock->type_mode;
 
2672
 
2707
2673
                                lock_rec_reset_nth_bit(lock, heap_no);
2708
2674
 
2709
 
                                if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
 
2675
                                if (lock_get_wait(lock)) {
2710
2676
                                        lock_reset_lock_and_trx_wait(lock);
2711
2677
                                }
2712
2678
 
2713
 
                                if (comp) {
2714
 
                                        heap_no = rec_get_heap_no_new(
2715
 
                                                page_cur_get_rec(&cur2));
2716
 
                                } else {
2717
 
                                        heap_no = rec_get_heap_no_old(
2718
 
                                                page_cur_get_rec(&cur2));
2719
 
                                }
2720
 
 
2721
2679
                                lock_rec_add_to_queue(type_mode,
2722
 
                                                      new_block, heap_no,
 
2680
                                                      page_cur_get_rec(&cur2),
2723
2681
                                                      lock->index, lock->trx);
2724
2682
                        }
2725
2683
 
2726
2684
                        page_cur_move_to_next(&cur1);
2727
2685
                        page_cur_move_to_next(&cur2);
2728
2686
                }
 
2687
 
 
2688
                lock = lock_rec_get_next_on_page(lock);
2729
2689
        }
2730
2690
 
2731
2691
        lock_mutex_exit_kernel();
2732
2692
 
2733
 
#ifdef UNIV_DEBUG_LOCK_VALIDATE
2734
 
        ut_ad(lock_rec_validate_page(buf_block_get_space(block),
2735
 
                                     buf_block_get_page_no(block)));
2736
 
        ut_ad(lock_rec_validate_page(buf_block_get_space(new_block),
2737
 
                                     buf_block_get_page_no(new_block)));
 
2693
#if 0
 
2694
        ut_ad(lock_rec_validate_page(buf_frame_get_space_id(page),
 
2695
                                     buf_frame_get_page_no(page)));
 
2696
        ut_ad(lock_rec_validate_page(buf_frame_get_space_id(new_page),
 
2697
                                     buf_frame_get_page_no(new_page)));
2738
2698
#endif
2739
2699
}
2740
2700
 
2741
2701
/*****************************************************************
2742
2702
Moves the explicit locks on user records to another page if a record
2743
2703
list start is moved to another page. */
2744
 
UNIV_INTERN
 
2704
 
2745
2705
void
2746
2706
lock_move_rec_list_start(
2747
2707
/*=====================*/
2748
 
        const buf_block_t*      new_block,      /* in: index page to move to */
2749
 
        const buf_block_t*      block,          /* in: index page */
2750
 
        const rec_t*            rec,            /* in: record on page:
2751
 
                                                this is the first
2752
 
                                                record NOT copied */
2753
 
        const rec_t*            old_end)        /* in: old
2754
 
                                                previous-to-last
2755
 
                                                record on new_page
2756
 
                                                before the records
2757
 
                                                were copied */
 
2708
        page_t* new_page,       /* in: index page to move to */
 
2709
        page_t* page,           /* in: index page */
 
2710
        rec_t*  rec,            /* in: record on page: this is the
 
2711
                                first record NOT copied */
 
2712
        rec_t*  old_end)        /* in: old previous-to-last record on
 
2713
                                new_page before the records were copied */
2758
2714
{
2759
2715
        lock_t*         lock;
2760
 
        const ulint     comp    = page_rec_is_comp(rec);
 
2716
        page_cur_t      cur1;
 
2717
        page_cur_t      cur2;
 
2718
        ulint           heap_no;
 
2719
        ulint           type_mode;
 
2720
        ulint           comp;
2761
2721
 
2762
 
        ut_ad(block->frame == page_align(rec));
2763
 
        ut_ad(new_block->frame == page_align(old_end));
 
2722
        ut_a(new_page);
2764
2723
 
2765
2724
        lock_mutex_enter_kernel();
2766
2725
 
2767
 
        for (lock = lock_rec_get_first_on_page(block); lock;
2768
 
             lock = lock_rec_get_next_on_page(lock)) {
2769
 
                page_cur_t      cur1;
2770
 
                page_cur_t      cur2;
2771
 
                const ulint     type_mode = lock->type_mode;
2772
 
 
2773
 
                page_cur_set_before_first(block, &cur1);
 
2726
        lock = lock_rec_get_first_on_page(page);
 
2727
        comp = page_is_comp(page);
 
2728
        ut_ad(comp == page_is_comp(new_page));
 
2729
        ut_ad(page == buf_frame_align(rec));
 
2730
 
 
2731
        while (lock != NULL) {
 
2732
 
 
2733
                page_cur_set_before_first(page, &cur1);
2774
2734
                page_cur_move_to_next(&cur1);
2775
2735
 
2776
 
                page_cur_position(old_end, new_block, &cur2);
 
2736
                page_cur_position(old_end, &cur2);
2777
2737
                page_cur_move_to_next(&cur2);
2778
2738
 
2779
2739
                /* Copy lock requests on user records to new page and
2780
2740
                reset the lock bits on the old */
2781
2741
 
2782
2742
                while (page_cur_get_rec(&cur1) != rec) {
2783
 
                        ulint   heap_no;
2784
 
 
2785
 
                        if (comp) {
2786
 
                                heap_no = rec_get_heap_no_new(
2787
 
                                        page_cur_get_rec(&cur1));
2788
 
                        } else {
2789
 
                                heap_no = rec_get_heap_no_old(
2790
 
                                        page_cur_get_rec(&cur1));
2791
 
                                ut_ad(!memcmp(page_cur_get_rec(&cur1),
 
2743
                        ut_ad(comp || !memcmp(page_cur_get_rec(&cur1),
2792
2744
                                              page_cur_get_rec(&cur2),
2793
2745
                                              rec_get_data_size_old(
2794
2746
                                                      page_cur_get_rec(
2795
2747
                                                              &cur2))));
2796
 
                        }
 
2748
                        heap_no = rec_get_heap_no(page_cur_get_rec(&cur1),
 
2749
                                                  comp);
2797
2750
 
2798
2751
                        if (lock_rec_get_nth_bit(lock, heap_no)) {
 
2752
                                type_mode = lock->type_mode;
 
2753
 
2799
2754
                                lock_rec_reset_nth_bit(lock, heap_no);
2800
2755
 
2801
 
                                if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
 
2756
                                if (lock_get_wait(lock)) {
2802
2757
                                        lock_reset_lock_and_trx_wait(lock);
2803
2758
                                }
2804
2759
 
2805
 
                                if (comp) {
2806
 
                                        heap_no = rec_get_heap_no_new(
2807
 
                                                page_cur_get_rec(&cur2));
2808
 
                                } else {
2809
 
                                        heap_no = rec_get_heap_no_old(
2810
 
                                                page_cur_get_rec(&cur2));
2811
 
                                }
2812
 
 
2813
2760
                                lock_rec_add_to_queue(type_mode,
2814
 
                                                      new_block, heap_no,
 
2761
                                                      page_cur_get_rec(&cur2),
2815
2762
                                                      lock->index, lock->trx);
2816
2763
                        }
2817
2764
 
2819
2766
                        page_cur_move_to_next(&cur2);
2820
2767
                }
2821
2768
 
2822
 
#ifdef UNIV_DEBUG
2823
 
                if (page_rec_is_supremum(rec)) {
2824
 
                        ulint   i;
2825
 
 
2826
 
                        for (i = PAGE_HEAP_NO_USER_LOW;
2827
 
                             i < lock_rec_get_n_bits(lock); i++) {
2828
 
                                if (UNIV_UNLIKELY
2829
 
                                    (lock_rec_get_nth_bit(lock, i))) {
2830
 
 
2831
 
                                        fprintf(stderr,
2832
 
                                                "lock_move_rec_list_start():"
2833
 
                                                " %lu not moved in %p\n",
2834
 
                                                (ulong) i, (void*) lock);
2835
 
                                        ut_error;
2836
 
                                }
2837
 
                        }
2838
 
                }
2839
 
#endif /* UNIV_DEBUG */
 
2769
                lock = lock_rec_get_next_on_page(lock);
2840
2770
        }
2841
2771
 
2842
2772
        lock_mutex_exit_kernel();
2843
 
 
2844
 
#ifdef UNIV_DEBUG_LOCK_VALIDATE
2845
 
        ut_ad(lock_rec_validate_page(buf_block_get_space(block),
2846
 
                                     buf_block_get_page_no(block)));
 
2773
#if 0
 
2774
        ut_ad(lock_rec_validate_page(buf_frame_get_space_id(page),
 
2775
                                     buf_frame_get_page_no(page)));
 
2776
        ut_ad(lock_rec_validate_page(buf_frame_get_space_id(new_page),
 
2777
                                     buf_frame_get_page_no(new_page)));
2847
2778
#endif
2848
2779
}
2849
2780
 
2850
2781
/*****************************************************************
2851
2782
Updates the lock table when a page is split to the right. */
2852
 
UNIV_INTERN
 
2783
 
2853
2784
void
2854
2785
lock_update_split_right(
2855
2786
/*====================*/
2856
 
        const buf_block_t*      right_block,    /* in: right page */
2857
 
        const buf_block_t*      left_block)     /* in: left page */
 
2787
        page_t* right_page,     /* in: right page */
 
2788
        page_t* left_page)      /* in: left page */
2858
2789
{
2859
 
        ulint   heap_no = lock_get_min_heap_no(right_block);
2860
 
 
 
2790
        ulint   comp;
2861
2791
        lock_mutex_enter_kernel();
 
2792
        comp = page_is_comp(left_page);
 
2793
        ut_ad(comp == page_is_comp(right_page));
2862
2794
 
2863
2795
        /* Move the locks on the supremum of the left page to the supremum
2864
2796
        of the right page */
2865
2797
 
2866
 
        lock_rec_move(right_block, left_block,
2867
 
                      PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
 
2798
        lock_rec_move(page_get_supremum_rec(right_page),
 
2799
                      page_get_supremum_rec(left_page), comp);
2868
2800
 
2869
2801
        /* Inherit the locks to the supremum of left page from the successor
2870
2802
        of the infimum on right page */
2871
2803
 
2872
 
        lock_rec_inherit_to_gap(left_block, right_block,
2873
 
                                PAGE_HEAP_NO_SUPREMUM, heap_no);
 
2804
        lock_rec_inherit_to_gap(page_get_supremum_rec(left_page),
 
2805
                                page_rec_get_next(
 
2806
                                        page_get_infimum_rec(right_page)));
2874
2807
 
2875
2808
        lock_mutex_exit_kernel();
2876
2809
}
2877
2810
 
2878
2811
/*****************************************************************
2879
2812
Updates the lock table when a page is merged to the right. */
2880
 
UNIV_INTERN
 
2813
 
2881
2814
void
2882
2815
lock_update_merge_right(
2883
2816
/*====================*/
2884
 
        const buf_block_t*      right_block,    /* in: right page to
2885
 
                                                which merged */
2886
 
        const rec_t*            orig_succ,      /* in: original
2887
 
                                                successor of infimum
2888
 
                                                on the right page
2889
 
                                                before merge */
2890
 
        const buf_block_t*      left_block)     /* in: merged index
2891
 
                                                page which will be
2892
 
                                                discarded */
 
2817
        rec_t*  orig_succ,      /* in: original successor of infimum
 
2818
                                on the right page before merge */
 
2819
        page_t* left_page)      /* in: merged index page which will be
 
2820
                                discarded */
2893
2821
{
2894
2822
        lock_mutex_enter_kernel();
2895
2823
 
2897
2825
        original successor of infimum on the right page, to which the left
2898
2826
        page was merged */
2899
2827
 
2900
 
        lock_rec_inherit_to_gap(right_block, left_block,
2901
 
                                page_rec_get_heap_no(orig_succ),
2902
 
                                PAGE_HEAP_NO_SUPREMUM);
 
2828
        lock_rec_inherit_to_gap(orig_succ, page_get_supremum_rec(left_page));
2903
2829
 
2904
2830
        /* Reset the locks on the supremum of the left page, releasing
2905
2831
        waiting transactions */
2906
2832
 
2907
 
        lock_rec_reset_and_release_wait(left_block,
2908
 
                                        PAGE_HEAP_NO_SUPREMUM);
 
2833
        lock_rec_reset_and_release_wait(page_get_supremum_rec(left_page));
2909
2834
 
2910
 
        lock_rec_free_all_from_discard_page(left_block);
 
2835
        lock_rec_free_all_from_discard_page(left_page);
2911
2836
 
2912
2837
        lock_mutex_exit_kernel();
2913
2838
}
2919
2844
pages: the reason is that in a pessimistic update the infimum record
2920
2845
of the root page will act as a dummy carrier of the locks of the record
2921
2846
to be updated. */
2922
 
UNIV_INTERN
 
2847
 
2923
2848
void
2924
2849
lock_update_root_raise(
2925
2850
/*===================*/
2926
 
        const buf_block_t*      block,  /* in: index page to which copied */
2927
 
        const buf_block_t*      root)   /* in: root page */
 
2851
        page_t* new_page,       /* in: index page to which copied */
 
2852
        page_t* root)           /* in: root page */
2928
2853
{
 
2854
        ulint   comp;
2929
2855
        lock_mutex_enter_kernel();
 
2856
        comp = page_is_comp(root);
 
2857
        ut_ad(comp == page_is_comp(new_page));
2930
2858
 
2931
2859
        /* Move the locks on the supremum of the root to the supremum
2932
 
        of block */
 
2860
        of new_page */
2933
2861
 
2934
 
        lock_rec_move(block, root,
2935
 
                      PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
 
2862
        lock_rec_move(page_get_supremum_rec(new_page),
 
2863
                      page_get_supremum_rec(root), comp);
2936
2864
        lock_mutex_exit_kernel();
2937
2865
}
2938
2866
 
2939
2867
/*****************************************************************
2940
2868
Updates the lock table when a page is copied to another and the original page
2941
2869
is removed from the chain of leaf pages, except if page is the root! */
2942
 
UNIV_INTERN
 
2870
 
2943
2871
void
2944
2872
lock_update_copy_and_discard(
2945
2873
/*=========================*/
2946
 
        const buf_block_t*      new_block,      /* in: index page to
2947
 
                                                which copied */
2948
 
        const buf_block_t*      block)          /* in: index page;
2949
 
                                                NOT the root! */
 
2874
        page_t* new_page,       /* in: index page to which copied */
 
2875
        page_t* page)           /* in: index page; NOT the root! */
2950
2876
{
 
2877
        ulint   comp;
2951
2878
        lock_mutex_enter_kernel();
 
2879
        comp = page_is_comp(page);
 
2880
        ut_ad(comp == page_is_comp(new_page));
2952
2881
 
2953
2882
        /* Move the locks on the supremum of the old page to the supremum
2954
2883
        of new_page */
2955
2884
 
2956
 
        lock_rec_move(new_block, block,
2957
 
                      PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
2958
 
        lock_rec_free_all_from_discard_page(block);
 
2885
        lock_rec_move(page_get_supremum_rec(new_page),
 
2886
                      page_get_supremum_rec(page), comp);
 
2887
        lock_rec_free_all_from_discard_page(page);
2959
2888
 
2960
2889
        lock_mutex_exit_kernel();
2961
2890
}
2962
2891
 
2963
2892
/*****************************************************************
2964
2893
Updates the lock table when a page is split to the left. */
2965
 
UNIV_INTERN
 
2894
 
2966
2895
void
2967
2896
lock_update_split_left(
2968
2897
/*===================*/
2969
 
        const buf_block_t*      right_block,    /* in: right page */
2970
 
        const buf_block_t*      left_block)     /* in: left page */
 
2898
        page_t* right_page,     /* in: right page */
 
2899
        page_t* left_page)      /* in: left page */
2971
2900
{
2972
 
        ulint   heap_no = lock_get_min_heap_no(right_block);
2973
 
 
2974
2901
        lock_mutex_enter_kernel();
2975
2902
 
2976
2903
        /* Inherit the locks to the supremum of the left page from the
2977
2904
        successor of the infimum on the right page */
2978
2905
 
2979
 
        lock_rec_inherit_to_gap(left_block, right_block,
2980
 
                                PAGE_HEAP_NO_SUPREMUM, heap_no);
 
2906
        lock_rec_inherit_to_gap(page_get_supremum_rec(left_page),
 
2907
                                page_rec_get_next(
 
2908
                                        page_get_infimum_rec(right_page)));
2981
2909
 
2982
2910
        lock_mutex_exit_kernel();
2983
2911
}
2984
2912
 
2985
2913
/*****************************************************************
2986
2914
Updates the lock table when a page is merged to the left. */
2987
 
UNIV_INTERN
 
2915
 
2988
2916
void
2989
2917
lock_update_merge_left(
2990
2918
/*===================*/
2991
 
        const buf_block_t*      left_block,     /* in: left page to
2992
 
                                                which merged */
2993
 
        const rec_t*            orig_pred,      /* in: original predecessor
2994
 
                                                of supremum on the left page
2995
 
                                                before merge */
2996
 
        const buf_block_t*      right_block)    /* in: merged index page
2997
 
                                                which will be discarded */
 
2919
        page_t* left_page,      /* in: left page to which merged */
 
2920
        rec_t*  orig_pred,      /* in: original predecessor of supremum
 
2921
                                on the left page before merge */
 
2922
        page_t* right_page)     /* in: merged index page which will be
 
2923
                                discarded */
2998
2924
{
2999
 
        const rec_t*    left_next_rec;
3000
 
 
3001
 
        ut_ad(left_block->frame == page_align(orig_pred));
3002
 
 
 
2925
        rec_t*  left_next_rec;
 
2926
        rec_t*  left_supremum;
 
2927
        ulint   comp;
3003
2928
        lock_mutex_enter_kernel();
3004
 
 
3005
 
        left_next_rec = page_rec_get_next_const(orig_pred);
3006
 
 
3007
 
        if (!page_rec_is_supremum(left_next_rec)) {
 
2929
        comp = page_is_comp(left_page);
 
2930
        ut_ad(comp == page_is_comp(right_page));
 
2931
        ut_ad(left_page == buf_frame_align(orig_pred));
 
2932
 
 
2933
        left_next_rec = page_rec_get_next(orig_pred);
 
2934
        left_supremum = page_get_supremum_rec(left_page);
 
2935
 
 
2936
        if (UNIV_LIKELY(left_next_rec != left_supremum)) {
3008
2937
 
3009
2938
                /* Inherit the locks on the supremum of the left page to the
3010
2939
                first record which was moved from the right page */
3011
2940
 
3012
 
                lock_rec_inherit_to_gap(left_block, left_block,
3013
 
                                        page_rec_get_heap_no(left_next_rec),
3014
 
                                        PAGE_HEAP_NO_SUPREMUM);
 
2941
                lock_rec_inherit_to_gap(left_next_rec, left_supremum);
3015
2942
 
3016
2943
                /* Reset the locks on the supremum of the left page,
3017
2944
                releasing waiting transactions */
3018
2945
 
3019
 
                lock_rec_reset_and_release_wait(left_block,
3020
 
                                                PAGE_HEAP_NO_SUPREMUM);
 
2946
                lock_rec_reset_and_release_wait(left_supremum);
3021
2947
        }
3022
2948
 
3023
2949
        /* Move the locks from the supremum of right page to the supremum
3024
2950
        of the left page */
3025
2951
 
3026
 
        lock_rec_move(left_block, right_block,
3027
 
                      PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
 
2952
        lock_rec_move(left_supremum, page_get_supremum_rec(right_page), comp);
3028
2953
 
3029
 
        lock_rec_free_all_from_discard_page(right_block);
 
2954
        lock_rec_free_all_from_discard_page(right_page);
3030
2955
 
3031
2956
        lock_mutex_exit_kernel();
3032
2957
}
3034
2959
/*****************************************************************
3035
2960
Resets the original locks on heir and replaces them with gap type locks
3036
2961
inherited from rec. */
3037
 
UNIV_INTERN
 
2962
 
3038
2963
void
3039
2964
lock_rec_reset_and_inherit_gap_locks(
3040
2965
/*=================================*/
3041
 
        const buf_block_t*      heir_block,     /* in: block containing the
3042
 
                                                record which inherits */
3043
 
        const buf_block_t*      block,          /* in: block containing the
3044
 
                                                record from which inherited;
3045
 
                                                does NOT reset the locks on
3046
 
                                                this record */
3047
 
        ulint                   heir_heap_no,   /* in: heap_no of the
3048
 
                                                inheriting record */
3049
 
        ulint                   heap_no)        /* in: heap_no of the
3050
 
                                                donating record */
 
2966
        rec_t*  heir,   /* in: heir record */
 
2967
        rec_t*  rec)    /* in: record */
3051
2968
{
3052
2969
        mutex_enter(&kernel_mutex);
3053
2970
 
3054
 
        lock_rec_reset_and_release_wait(heir_block, heir_heap_no);
 
2971
        lock_rec_reset_and_release_wait(heir);
3055
2972
 
3056
 
        lock_rec_inherit_to_gap(heir_block, block, heir_heap_no, heap_no);
 
2973
        lock_rec_inherit_to_gap(heir, rec);
3057
2974
 
3058
2975
        mutex_exit(&kernel_mutex);
3059
2976
}
3060
2977
 
3061
2978
/*****************************************************************
3062
2979
Updates the lock table when a page is discarded. */
3063
 
UNIV_INTERN
 
2980
 
3064
2981
void
3065
2982
lock_update_discard(
3066
2983
/*================*/
3067
 
        const buf_block_t*      heir_block,     /* in: index page
3068
 
                                                which will inherit the locks */
3069
 
        ulint                   heir_heap_no,   /* in: heap_no of the record
3070
 
                                                which will inherit the locks */
3071
 
        const buf_block_t*      block)          /* in: index page
3072
 
                                                which will be discarded */
 
2984
        rec_t*  heir,   /* in: record which will inherit the locks */
 
2985
        page_t* page)   /* in: index page which will be discarded */
3073
2986
{
3074
 
        const page_t*   page = block->frame;
3075
 
        const rec_t*    rec;
3076
 
        ulint           heap_no;
 
2987
        rec_t*  rec;
3077
2988
 
3078
2989
        lock_mutex_enter_kernel();
3079
2990
 
3080
 
        if (!lock_rec_get_first_on_page(block)) {
 
2991
        if (NULL == lock_rec_get_first_on_page(page)) {
3081
2992
                /* No locks exist on page, nothing to do */
3082
2993
 
3083
2994
                lock_mutex_exit_kernel();
3088
2999
        /* Inherit all the locks on the page to the record and reset all
3089
3000
        the locks on the page */
3090
3001
 
3091
 
        if (page_is_comp(page)) {
3092
 
                rec = page + PAGE_NEW_INFIMUM;
3093
 
 
3094
 
                do {
3095
 
                        heap_no = rec_get_heap_no_new(rec);
3096
 
 
3097
 
                        lock_rec_inherit_to_gap(heir_block, block,
3098
 
                                                heir_heap_no, heap_no);
3099
 
 
3100
 
                        lock_rec_reset_and_release_wait(block, heap_no);
3101
 
 
3102
 
                        rec = page + rec_get_next_offs(rec, TRUE);
3103
 
                } while (heap_no != PAGE_HEAP_NO_SUPREMUM);
3104
 
        } else {
3105
 
                rec = page + PAGE_OLD_INFIMUM;
3106
 
 
3107
 
                do {
3108
 
                        heap_no = rec_get_heap_no_old(rec);
3109
 
 
3110
 
                        lock_rec_inherit_to_gap(heir_block, block,
3111
 
                                                heir_heap_no, heap_no);
3112
 
 
3113
 
                        lock_rec_reset_and_release_wait(block, heap_no);
3114
 
 
3115
 
                        rec = page + rec_get_next_offs(rec, FALSE);
3116
 
                } while (heap_no != PAGE_HEAP_NO_SUPREMUM);
 
3002
        rec = page_get_infimum_rec(page);
 
3003
 
 
3004
        for (;;) {
 
3005
                lock_rec_inherit_to_gap(heir, rec);
 
3006
 
 
3007
                /* Reset the locks on rec, releasing waiting transactions */
 
3008
 
 
3009
                lock_rec_reset_and_release_wait(rec);
 
3010
 
 
3011
                if (page_rec_is_supremum(rec)) {
 
3012
 
 
3013
                        break;
 
3014
                }
 
3015
 
 
3016
                rec = page_rec_get_next(rec);
3117
3017
        }
3118
3018
 
3119
 
        lock_rec_free_all_from_discard_page(block);
 
3019
        lock_rec_free_all_from_discard_page(page);
3120
3020
 
3121
3021
        lock_mutex_exit_kernel();
3122
3022
}
3123
3023
 
3124
3024
/*****************************************************************
3125
3025
Updates the lock table when a new user record is inserted. */
3126
 
UNIV_INTERN
 
3026
 
3127
3027
void
3128
3028
lock_update_insert(
3129
3029
/*===============*/
3130
 
        const buf_block_t*      block,  /* in: buffer block containing rec */
3131
 
        const rec_t*            rec)    /* in: the inserted record */
 
3030
        rec_t*  rec)    /* in: the inserted record */
3132
3031
{
3133
 
        ulint   receiver_heap_no;
3134
 
        ulint   donator_heap_no;
3135
 
 
3136
 
        ut_ad(block->frame == page_align(rec));
 
3032
        lock_mutex_enter_kernel();
3137
3033
 
3138
3034
        /* Inherit the gap-locking locks for rec, in gap mode, from the next
3139
3035
        record */
3140
3036
 
3141
 
        if (page_rec_is_comp(rec)) {
3142
 
                receiver_heap_no = rec_get_heap_no_new(rec);
3143
 
                donator_heap_no = rec_get_heap_no_new(
3144
 
                        page_rec_get_next_low(rec, TRUE));
3145
 
        } else {
3146
 
                receiver_heap_no = rec_get_heap_no_old(rec);
3147
 
                donator_heap_no = rec_get_heap_no_old(
3148
 
                        page_rec_get_next_low(rec, FALSE));
3149
 
        }
 
3037
        lock_rec_inherit_to_gap_if_gap_lock(rec, page_rec_get_next(rec));
3150
3038
 
3151
 
        lock_mutex_enter_kernel();
3152
 
        lock_rec_inherit_to_gap_if_gap_lock(block,
3153
 
                                            receiver_heap_no, donator_heap_no);
3154
3039
        lock_mutex_exit_kernel();
3155
3040
}
3156
3041
 
3157
3042
/*****************************************************************
3158
3043
Updates the lock table when a record is removed. */
3159
 
UNIV_INTERN
 
3044
 
3160
3045
void
3161
3046
lock_update_delete(
3162
3047
/*===============*/
3163
 
        const buf_block_t*      block,  /* in: buffer block containing rec */
3164
 
        const rec_t*            rec)    /* in: the record to be removed */
 
3048
        rec_t*  rec)    /* in: the record to be removed */
3165
3049
{
3166
 
        const page_t*   page = block->frame;
3167
 
        ulint           heap_no;
3168
 
        ulint           next_heap_no;
3169
 
 
3170
 
        ut_ad(page == page_align(rec));
3171
 
 
3172
 
        if (page_is_comp(page)) {
3173
 
                heap_no = rec_get_heap_no_new(rec);
3174
 
                next_heap_no = rec_get_heap_no_new(page
3175
 
                                                   + rec_get_next_offs(rec,
3176
 
                                                                       TRUE));
3177
 
        } else {
3178
 
                heap_no = rec_get_heap_no_old(rec);
3179
 
                next_heap_no = rec_get_heap_no_old(page
3180
 
                                                   + rec_get_next_offs(rec,
3181
 
                                                                       FALSE));
3182
 
        }
3183
 
 
3184
3050
        lock_mutex_enter_kernel();
3185
3051
 
3186
3052
        /* Let the next record inherit the locks from rec, in gap mode */
3187
3053
 
3188
 
        lock_rec_inherit_to_gap(block, block, next_heap_no, heap_no);
 
3054
        lock_rec_inherit_to_gap(page_rec_get_next(rec), rec);
3189
3055
 
3190
3056
        /* Reset the lock bits on rec and release waiting transactions */
3191
3057
 
3192
 
        lock_rec_reset_and_release_wait(block, heap_no);
 
3058
        lock_rec_reset_and_release_wait(rec);
3193
3059
 
3194
3060
        lock_mutex_exit_kernel();
3195
3061
}
3201
3067
is moved in such an update, perhaps to another page. The infimum record
3202
3068
acts as a dummy carrier record, taking care of lock releases while the
3203
3069
actual record is being moved. */
3204
 
UNIV_INTERN
 
3070
 
3205
3071
void
3206
3072
lock_rec_store_on_page_infimum(
3207
3073
/*===========================*/
3208
 
        const buf_block_t*      block,  /* in: buffer block containing rec */
3209
 
        const rec_t*            rec)    /* in: record whose lock state
3210
 
                                        is stored on the infimum
3211
 
                                        record of the same page; lock
3212
 
                                        bits are reset on the
3213
 
                                        record */
 
3074
        page_t* page,   /* in: page containing the record */
 
3075
        rec_t*  rec)    /* in: record whose lock state is stored
 
3076
                        on the infimum record of the same page; lock
 
3077
                        bits are reset on the record */
3214
3078
{
3215
 
        ulint   heap_no = page_rec_get_heap_no(rec);
3216
 
 
3217
 
        ut_ad(block->frame == page_align(rec));
 
3079
        ut_ad(page == buf_frame_align(rec));
3218
3080
 
3219
3081
        lock_mutex_enter_kernel();
3220
3082
 
3221
 
        lock_rec_move(block, block, PAGE_HEAP_NO_INFIMUM, heap_no);
 
3083
        lock_rec_move(page_get_infimum_rec(page), rec, page_is_comp(page));
3222
3084
 
3223
3085
        lock_mutex_exit_kernel();
3224
3086
}
3226
3088
/*************************************************************************
3227
3089
Restores the state of explicit lock requests on a single record, where the
3228
3090
state was stored on the infimum of the page. */
3229
 
UNIV_INTERN
 
3091
 
3230
3092
void
3231
3093
lock_rec_restore_from_page_infimum(
3232
3094
/*===============================*/
3233
 
        const buf_block_t*      block,  /* in: buffer block containing rec */
3234
 
        const rec_t*            rec,    /* in: record whose lock state
3235
 
                                        is restored */
3236
 
        const buf_block_t*      donator)/* in: page (rec is not
3237
 
                                        necessarily on this page)
3238
 
                                        whose infimum stored the lock
3239
 
                                        state; lock bits are reset on
3240
 
                                        the infimum */
 
3095
        rec_t*  rec,    /* in: record whose lock state is restored */
 
3096
        page_t* page)   /* in: page (rec is not necessarily on this page)
 
3097
                        whose infimum stored the lock state; lock bits are
 
3098
                        reset on the infimum */
3241
3099
{
3242
 
        ulint   heap_no = page_rec_get_heap_no(rec);
3243
 
 
 
3100
        ulint   comp;
3244
3101
        lock_mutex_enter_kernel();
 
3102
        comp = page_is_comp(page);
 
3103
        ut_ad(!comp == !page_rec_is_comp(rec));
3245
3104
 
3246
 
        lock_rec_move(block, donator, heap_no, PAGE_HEAP_NO_INFIMUM);
 
3105
        lock_rec_move(rec, page_get_infimum_rec(page), comp);
3247
3106
 
3248
3107
        lock_mutex_exit_kernel();
3249
3108
}
3293
3152
                goto retry;
3294
3153
        }
3295
3154
 
3296
 
        if (UNIV_UNLIKELY(ret == LOCK_VICTIM_IS_START)) {
3297
 
                if (lock_get_type_low(lock) & LOCK_TABLE) {
 
3155
        if (ret == LOCK_VICTIM_IS_START) {
 
3156
                if (lock_get_type(lock) & LOCK_TABLE) {
3298
3157
                        table = lock->un_member.tab_lock.table;
3299
3158
                        index = NULL;
3300
3159
                } else {
3358
3217
 
3359
3218
        lock = wait_lock;
3360
3219
 
3361
 
        if (lock_get_type_low(wait_lock) == LOCK_REC) {
 
3220
        if (lock_get_type(wait_lock) == LOCK_REC) {
3362
3221
 
3363
3222
                bit_no = lock_rec_find_set_bit(wait_lock);
3364
3223
 
3368
3227
        /* Look at the locks ahead of wait_lock in the lock queue */
3369
3228
 
3370
3229
        for (;;) {
3371
 
                if (lock_get_type_low(lock) & LOCK_TABLE) {
 
3230
                if (lock_get_type(lock) & LOCK_TABLE) {
3372
3231
 
3373
3232
                        lock = UT_LIST_GET_PREV(un_member.tab_lock.locks,
3374
3233
                                                lock);
3375
3234
                } else {
3376
 
                        ut_ad(lock_get_type_low(lock) == LOCK_REC);
 
3235
                        ut_ad(lock_get_type(lock) == LOCK_REC);
3377
3236
                        ut_a(bit_no != ULINT_UNDEFINED);
3378
3237
 
3379
 
                        lock = (lock_t*) lock_rec_get_prev(lock, bit_no);
 
3238
                        lock = lock_rec_get_prev(lock, bit_no);
3380
3239
                }
3381
3240
 
3382
3241
                if (lock == NULL) {
3412
3271
                                fputs("*** (1) WAITING FOR THIS LOCK"
3413
3272
                                      " TO BE GRANTED:\n", ef);
3414
3273
 
3415
 
                                if (lock_get_type_low(wait_lock) == LOCK_REC) {
 
3274
                                if (lock_get_type(wait_lock) == LOCK_REC) {
3416
3275
                                        lock_rec_print(ef, wait_lock);
3417
3276
                                } else {
3418
3277
                                        lock_table_print(ef, wait_lock);
3424
3283
 
3425
3284
                                fputs("*** (2) HOLDS THE LOCK(S):\n", ef);
3426
3285
 
3427
 
                                if (lock_get_type_low(lock) == LOCK_REC) {
 
3286
                                if (lock_get_type(lock) == LOCK_REC) {
3428
3287
                                        lock_rec_print(ef, lock);
3429
3288
                                } else {
3430
3289
                                        lock_table_print(ef, lock);
3433
3292
                                fputs("*** (2) WAITING FOR THIS LOCK"
3434
3293
                                      " TO BE GRANTED:\n", ef);
3435
3294
 
3436
 
                                if (lock_get_type_low(start->wait_lock)
 
3295
                                if (lock_get_type(start->wait_lock)
3437
3296
                                    == LOCK_REC) {
3438
3297
                                        lock_rec_print(ef, start->wait_lock);
3439
3298
                                } else {
3553
3412
 
3554
3413
        UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
3555
3414
 
3556
 
        if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
 
3415
        if (type_mode & LOCK_WAIT) {
3557
3416
 
3558
3417
                lock_set_lock_and_trx_wait(lock, trx);
3559
3418
        }
3625
3484
 
3626
3485
        trx = thr_get_trx(thr);
3627
3486
 
3628
 
        switch (trx_get_dict_operation(trx)) {
3629
 
        case TRX_DICT_OP_NONE:
3630
 
                break;
3631
 
        case TRX_DICT_OP_TABLE:
3632
 
        case TRX_DICT_OP_INDEX:
 
3487
        if (trx->dict_operation) {
3633
3488
                ut_print_timestamp(stderr);
3634
3489
                fputs("  InnoDB: Error: a table lock wait happens"
3635
3490
                      " in a dictionary operation!\n"
3684
3539
        ulint           wait,   /* in: LOCK_WAIT if also waiting locks are
3685
3540
                                taken into account, or 0 if not */
3686
3541
        dict_table_t*   table,  /* in: table */
3687
 
        enum lock_mode  mode)   /* in: lock mode */
 
3542
        ulint           mode)   /* in: lock mode */
3688
3543
{
3689
3544
        lock_t* lock;
3690
3545
 
3710
3565
/*************************************************************************
3711
3566
Locks the specified database table in the mode given. If the lock cannot
3712
3567
be granted immediately, the query thread is put to wait. */
3713
 
UNIV_INTERN
 
3568
 
3714
3569
ulint
3715
3570
lock_table(
3716
3571
/*=======*/
3719
3574
        ulint           flags,  /* in: if BTR_NO_LOCKING_FLAG bit is set,
3720
3575
                                does nothing */
3721
3576
        dict_table_t*   table,  /* in: database table in dictionary cache */
3722
 
        enum lock_mode  mode,   /* in: lock mode */
 
3577
        ulint           mode,   /* in: lock mode */
3723
3578
        que_thr_t*      thr)    /* in: query thread */
3724
3579
{
3725
3580
        trx_t*  trx;
3773
3628
 
3774
3629
/*************************************************************************
3775
3630
Checks if there are any locks set on the table. */
3776
 
UNIV_INTERN
 
3631
 
3777
3632
ibool
3778
3633
lock_is_on_table(
3779
3634
/*=============*/
3843
3698
        lock_t* lock;
3844
3699
 
3845
3700
        ut_ad(mutex_own(&kernel_mutex));
3846
 
        ut_a(lock_get_type_low(in_lock) == LOCK_TABLE);
 
3701
        ut_a(lock_get_type(in_lock) == LOCK_TABLE);
3847
3702
 
3848
3703
        lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock);
3849
3704
 
3871
3726
Removes a granted record lock of a transaction from the queue and grants
3872
3727
locks to other transactions waiting in the queue if they now are entitled
3873
3728
to a lock. */
3874
 
UNIV_INTERN
 
3729
 
3875
3730
void
3876
3731
lock_rec_unlock(
3877
3732
/*============*/
3878
 
        trx_t*                  trx,    /* in: transaction that has
3879
 
                                        set a record lock */
3880
 
        const buf_block_t*      block,  /* in: buffer block containing rec */
3881
 
        const rec_t*            rec,    /* in: record */
3882
 
        enum lock_mode          lock_mode)/* in: LOCK_S or LOCK_X */
 
3733
        trx_t*  trx,            /* in: transaction that has set a record
 
3734
                                lock */
 
3735
        rec_t*  rec,            /* in: record */
 
3736
        ulint   lock_mode)      /* in: LOCK_S or LOCK_X */
3883
3737
{
3884
3738
        lock_t* lock;
3885
3739
        lock_t* release_lock    = NULL;
3886
3740
        ulint   heap_no;
3887
3741
 
3888
3742
        ut_ad(trx && rec);
3889
 
        ut_ad(block->frame == page_align(rec));
3890
 
 
3891
 
        heap_no = page_rec_get_heap_no(rec);
3892
3743
 
3893
3744
        mutex_enter(&kernel_mutex);
3894
3745
 
3895
 
        lock = lock_rec_get_first(block, heap_no);
 
3746
        heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
 
3747
 
 
3748
        lock = lock_rec_get_first(rec);
3896
3749
 
3897
3750
        /* Find the last lock with the same lock_mode and transaction
3898
3751
        from the record. */
3903
3756
                        ut_a(!lock_get_wait(lock));
3904
3757
                }
3905
3758
 
3906
 
                lock = lock_rec_get_next(heap_no, lock);
 
3759
                lock = lock_rec_get_next(rec, lock);
3907
3760
        }
3908
3761
 
3909
3762
        /* If a record lock is found, release the record lock */
3923
3776
 
3924
3777
        /* Check if we can now grant waiting lock requests */
3925
3778
 
3926
 
        lock = lock_rec_get_first(block, heap_no);
 
3779
        lock = lock_rec_get_first(rec);
3927
3780
 
3928
3781
        while (lock != NULL) {
3929
3782
                if (lock_get_wait(lock)
3933
3786
                        lock_grant(lock);
3934
3787
                }
3935
3788
 
3936
 
                lock = lock_rec_get_next(heap_no, lock);
 
3789
                lock = lock_rec_get_next(rec, lock);
3937
3790
        }
3938
3791
 
3939
3792
        mutex_exit(&kernel_mutex);
3942
3795
/*************************************************************************
3943
3796
Releases a table lock.
3944
3797
Releases possible other transactions waiting for this lock. */
3945
 
UNIV_INTERN
 
3798
 
3946
3799
void
3947
3800
lock_table_unlock(
3948
3801
/*==============*/
3958
3811
/*************************************************************************
3959
3812
Releases an auto-inc lock a transaction possibly has on a table.
3960
3813
Releases possible other transactions waiting for this lock. */
3961
 
UNIV_INTERN
 
3814
 
3962
3815
void
3963
3816
lock_table_unlock_auto_inc(
3964
3817
/*=======================*/
3976
3829
/*************************************************************************
3977
3830
Releases transaction locks, and releases possible other transactions waiting
3978
3831
because of these locks. */
3979
 
UNIV_INTERN
 
3832
 
3980
3833
void
3981
3834
lock_release_off_kernel(
3982
3835
/*====================*/
3996
3849
 
3997
3850
                count++;
3998
3851
 
3999
 
                if (lock_get_type_low(lock) == LOCK_REC) {
 
3852
                if (lock_get_type(lock) == LOCK_REC) {
4000
3853
 
4001
3854
                        lock_rec_dequeue_from_page(lock);
4002
3855
                } else {
4003
 
                        ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
 
3856
                        ut_ad(lock_get_type(lock) & LOCK_TABLE);
4004
3857
 
4005
3858
                        if (lock_get_mode(lock) != LOCK_IS
4006
 
                            && !ut_dulint_is_zero(trx->undo_no)) {
 
3859
                            && 0 != ut_dulint_cmp(trx->undo_no,
 
3860
                                                  ut_dulint_zero)) {
4007
3861
 
4008
3862
                                /* The trx may have modified the table. We
4009
3863
                                block the use of the MySQL query cache for
4040
3894
/*************************************************************************
4041
3895
Cancels a waiting lock request and releases possible other transactions
4042
3896
waiting behind it. */
4043
 
UNIV_INTERN
 
3897
 
4044
3898
void
4045
3899
lock_cancel_waiting_and_release(
4046
3900
/*============================*/
4048
3902
{
4049
3903
        ut_ad(mutex_own(&kernel_mutex));
4050
3904
 
4051
 
        if (lock_get_type_low(lock) == LOCK_REC) {
 
3905
        if (lock_get_type(lock) == LOCK_REC) {
4052
3906
 
4053
3907
                lock_rec_dequeue_from_page(lock);
4054
3908
        } else {
4055
 
                ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
 
3909
                ut_ad(lock_get_type(lock) & LOCK_TABLE);
4056
3910
 
4057
3911
                lock_table_dequeue(lock);
4058
3912
        }
4086
3940
        while (lock != NULL) {
4087
3941
                prev_lock = UT_LIST_GET_PREV(trx_locks, lock);
4088
3942
 
4089
 
                if (lock_get_type_low(lock) == LOCK_REC
 
3943
                if (lock_get_type(lock) == LOCK_REC
4090
3944
                    && lock->index->table == table) {
4091
3945
                        ut_a(!lock_get_wait(lock));
4092
3946
 
4093
3947
                        lock_rec_discard(lock);
4094
 
                } else if (lock_get_type_low(lock) & LOCK_TABLE
 
3948
                } else if (lock_get_type(lock) & LOCK_TABLE
4095
3949
                           && lock->un_member.tab_lock.table == table) {
4096
3950
 
4097
3951
                        ut_a(!lock_get_wait(lock));
4106
3960
/*************************************************************************
4107
3961
Resets all locks, both table and record locks, on a table to be dropped.
4108
3962
No lock is allowed to be a wait lock. */
4109
 
UNIV_INTERN
 
3963
 
4110
3964
void
4111
3965
lock_reset_all_on_table(
4112
3966
/*====================*/
4133
3987
 
4134
3988
/*************************************************************************
4135
3989
Prints info of a table lock. */
4136
 
UNIV_INTERN
 
3990
 
4137
3991
void
4138
3992
lock_table_print(
4139
3993
/*=============*/
4140
 
        FILE*           file,   /* in: file where to print */
4141
 
        const lock_t*   lock)   /* in: table type lock */
 
3994
        FILE*   file,   /* in: file where to print */
 
3995
        lock_t* lock)   /* in: table type lock */
4142
3996
{
4143
3997
        ut_ad(mutex_own(&kernel_mutex));
4144
 
        ut_a(lock_get_type_low(lock) == LOCK_TABLE);
 
3998
        ut_a(lock_get_type(lock) == LOCK_TABLE);
4145
3999
 
4146
4000
        fputs("TABLE LOCK table ", file);
4147
4001
        ut_print_name(file, lock->trx, TRUE,
4148
4002
                      lock->un_member.tab_lock.table->name);
4149
 
        fprintf(file, " trx id " TRX_ID_FMT,
4150
 
                TRX_ID_PREP_PRINTF(lock->trx->id));
 
4003
        fprintf(file, " trx id %lu %lu",
 
4004
                (ulong) (lock->trx)->id.high, (ulong) (lock->trx)->id.low);
4151
4005
 
4152
4006
        if (lock_get_mode(lock) == LOCK_S) {
4153
4007
                fputs(" lock mode S", file);
4173
4027
 
4174
4028
/*************************************************************************
4175
4029
Prints info of a record lock. */
4176
 
UNIV_INTERN
 
4030
 
4177
4031
void
4178
4032
lock_rec_print(
4179
4033
/*===========*/
4180
 
        FILE*           file,   /* in: file where to print */
4181
 
        const lock_t*   lock)   /* in: record type lock */
 
4034
        FILE*   file,   /* in: file where to print */
 
4035
        lock_t* lock)   /* in: record type lock */
4182
4036
{
4183
 
        const buf_block_t*      block;
4184
 
        ulint                   space;
4185
 
        ulint                   page_no;
4186
 
        ulint                   i;
4187
 
        mtr_t                   mtr;
4188
 
        mem_heap_t*             heap            = NULL;
4189
 
        ulint                   offsets_[REC_OFFS_NORMAL_SIZE];
4190
 
        ulint*                  offsets         = offsets_;
4191
 
        rec_offs_init(offsets_);
 
4037
        page_t*         page;
 
4038
        ulint           space;
 
4039
        ulint           page_no;
 
4040
        ulint           i;
 
4041
        mtr_t           mtr;
 
4042
        mem_heap_t*     heap            = NULL;
 
4043
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
 
4044
        ulint*          offsets         = offsets_;
 
4045
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
4192
4046
 
4193
4047
        ut_ad(mutex_own(&kernel_mutex));
4194
 
        ut_a(lock_get_type_low(lock) == LOCK_REC);
 
4048
        ut_a(lock_get_type(lock) == LOCK_REC);
4195
4049
 
4196
4050
        space = lock->un_member.rec_lock.space;
4197
4051
        page_no = lock->un_member.rec_lock.page_no;
4200
4054
                (ulong) space, (ulong) page_no,
4201
4055
                (ulong) lock_rec_get_n_bits(lock));
4202
4056
        dict_index_name_print(file, lock->trx, lock->index);
4203
 
        fprintf(file, " trx id " TRX_ID_FMT,
4204
 
                TRX_ID_PREP_PRINTF(lock->trx->id));
 
4057
        fprintf(file, " trx id %lu %lu",
 
4058
                (ulong) (lock->trx)->id.high,
 
4059
                (ulong) (lock->trx)->id.low);
4205
4060
 
4206
4061
        if (lock_get_mode(lock) == LOCK_S) {
4207
4062
                fputs(" lock mode S", file);
4231
4086
 
4232
4087
        putc('\n', file);
4233
4088
 
4234
 
        block = buf_page_try_get(space, page_no, &mtr);
4235
 
 
4236
 
        if (block) {
4237
 
                for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
4238
 
 
4239
 
                        if (lock_rec_get_nth_bit(lock, i)) {
4240
 
 
4241
 
                                const rec_t*    rec
4242
 
                                        = page_find_rec_with_heap_no(
4243
 
                                                buf_block_get_frame(block), i);
 
4089
        /* If the page is not in the buffer pool, we cannot load it
 
4090
        because we have the kernel mutex and ibuf operations would
 
4091
        break the latching order */
 
4092
 
 
4093
        page = buf_page_get_gen(space, page_no, RW_NO_LATCH,
 
4094
                                NULL, BUF_GET_IF_IN_POOL,
 
4095
                                __FILE__, __LINE__, &mtr);
 
4096
        if (page) {
 
4097
                page = buf_page_get_nowait(space, page_no, RW_S_LATCH, &mtr);
 
4098
 
 
4099
                if (!page) {
 
4100
                        /* Let us try to get an X-latch. If the current thread
 
4101
                        is holding an X-latch on the page, we cannot get an
 
4102
                        S-latch. */
 
4103
 
 
4104
                        page = buf_page_get_nowait(space, page_no, RW_X_LATCH,
 
4105
                                                   &mtr);
 
4106
                }
 
4107
        }
 
4108
 
 
4109
        if (page) {
 
4110
#ifdef UNIV_SYNC_DEBUG
 
4111
                buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK);
 
4112
#endif /* UNIV_SYNC_DEBUG */
 
4113
        }
 
4114
 
 
4115
        for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
 
4116
 
 
4117
                if (lock_rec_get_nth_bit(lock, i)) {
 
4118
 
 
4119
                        fprintf(file, "Record lock, heap no %lu ", (ulong) i);
 
4120
 
 
4121
                        if (page) {
 
4122
                                rec_t*  rec
 
4123
                                        = page_find_rec_with_heap_no(page, i);
4244
4124
                                offsets = rec_get_offsets(
4245
4125
                                        rec, lock->index, offsets,
4246
4126
                                        ULINT_UNDEFINED, &heap);
4247
 
 
4248
 
                                fprintf(file, "Record lock, heap no %lu ",
4249
 
                                        (ulong) i);
4250
4127
                                rec_print_new(file, rec, offsets);
4251
 
                                putc('\n', file);
4252
4128
                        }
4253
 
                }
4254
 
        } else {
4255
 
                for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
4256
 
                        fprintf(file, "Record lock, heap no %lu\n", (ulong) i);
 
4129
 
 
4130
                        putc('\n', file);
4257
4131
                }
4258
4132
        }
4259
4133
 
4293
4167
 
4294
4168
/*************************************************************************
4295
4169
Prints info of locks for all transactions. */
4296
 
UNIV_INTERN
 
4170
 
4297
4171
void
4298
4172
lock_print_info_summary(
4299
4173
/*====================*/
4318
4192
              "TRANSACTIONS\n"
4319
4193
              "------------\n", file);
4320
4194
 
4321
 
        fprintf(file, "Trx id counter " TRX_ID_FMT "\n",
4322
 
                TRX_ID_PREP_PRINTF(trx_sys->max_trx_id));
 
4195
        fprintf(file, "Trx id counter %lu %lu\n",
 
4196
                (ulong) ut_dulint_get_high(trx_sys->max_trx_id),
 
4197
                (ulong) ut_dulint_get_low(trx_sys->max_trx_id));
4323
4198
 
4324
4199
        fprintf(file,
4325
 
                "Purge done for trx's n:o < " TRX_ID_FMT
4326
 
                " undo n:o < " TRX_ID_FMT "\n",
4327
 
                TRX_ID_PREP_PRINTF(purge_sys->purge_trx_no),
4328
 
                TRX_ID_PREP_PRINTF(purge_sys->purge_undo_no));
 
4200
                "Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu\n",
 
4201
                (ulong) ut_dulint_get_high(purge_sys->purge_trx_no),
 
4202
                (ulong) ut_dulint_get_low(purge_sys->purge_trx_no),
 
4203
                (ulong) ut_dulint_get_high(purge_sys->purge_undo_no),
 
4204
                (ulong) ut_dulint_get_low(purge_sys->purge_undo_no));
4329
4205
 
4330
4206
        fprintf(file,
4331
4207
                "History list length %lu\n",
4338
4214
 
4339
4215
/*************************************************************************
4340
4216
Prints info of locks for each transaction. */
4341
 
UNIV_INTERN
 
4217
 
4342
4218
void
4343
4219
lock_print_info_all_transactions(
4344
4220
/*=============================*/
4345
4221
        FILE*   file)   /* in: file where to print */
4346
4222
{
4347
4223
        lock_t* lock;
 
4224
        ulint   space;
 
4225
        ulint   page_no;
 
4226
        page_t* page;
4348
4227
        ibool   load_page_first = TRUE;
4349
4228
        ulint   nth_trx         = 0;
4350
4229
        ulint   nth_lock        = 0;
4398
4277
                if (trx->read_view) {
4399
4278
                        fprintf(file,
4400
4279
                                "Trx read view will not see trx with"
4401
 
                                " id >= " TRX_ID_FMT
4402
 
                                ", sees < " TRX_ID_FMT "\n",
4403
 
                                TRX_ID_PREP_PRINTF(
4404
 
                                        trx->read_view->low_limit_id),
4405
 
                                TRX_ID_PREP_PRINTF(
 
4280
                                " id >= %lu %lu, sees < %lu %lu\n",
 
4281
                                (ulong) ut_dulint_get_high(
 
4282
                                        trx->read_view->low_limit_id),
 
4283
                                (ulong) ut_dulint_get_low(
 
4284
                                        trx->read_view->low_limit_id),
 
4285
                                (ulong) ut_dulint_get_high(
 
4286
                                        trx->read_view->up_limit_id),
 
4287
                                (ulong) ut_dulint_get_low(
4406
4288
                                        trx->read_view->up_limit_id));
4407
4289
                }
4408
4290
 
4413
4295
                                (ulong) difftime(time(NULL),
4414
4296
                                                 trx->wait_started));
4415
4297
 
4416
 
                        if (lock_get_type_low(trx->wait_lock) == LOCK_REC) {
 
4298
                        if (lock_get_type(trx->wait_lock) == LOCK_REC) {
4417
4299
                                lock_rec_print(file, trx->wait_lock);
4418
4300
                        } else {
4419
4301
                                lock_table_print(file, trx->wait_lock);
4447
4329
                goto loop;
4448
4330
        }
4449
4331
 
4450
 
        if (lock_get_type_low(lock) == LOCK_REC) {
 
4332
        if (lock_get_type(lock) == LOCK_REC) {
 
4333
                space = lock->un_member.rec_lock.space;
 
4334
                page_no = lock->un_member.rec_lock.page_no;
 
4335
 
4451
4336
                if (load_page_first) {
4452
 
                        ulint   space   = lock->un_member.rec_lock.space;
4453
 
                        ulint   zip_size= fil_space_get_zip_size(space);
4454
 
                        ulint   page_no = lock->un_member.rec_lock.page_no;
4455
 
 
4456
4337
                        lock_mutex_exit_kernel();
4457
4338
                        innobase_mysql_end_print_arbitrary_thd();
4458
4339
 
4459
4340
                        mtr_start(&mtr);
4460
4341
 
4461
 
                        buf_page_get_with_no_latch(space, zip_size,
4462
 
                                                   page_no, &mtr);
 
4342
                        page = buf_page_get_with_no_latch(
 
4343
                                space, page_no, &mtr);
4463
4344
 
4464
4345
                        mtr_commit(&mtr);
4465
4346
 
4473
4354
 
4474
4355
                lock_rec_print(file, lock);
4475
4356
        } else {
4476
 
                ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
 
4357
                ut_ad(lock_get_type(lock) & LOCK_TABLE);
4477
4358
 
4478
4359
                lock_table_print(file, lock);
4479
4360
        }
4496
4377
        goto loop;
4497
4378
}
4498
4379
 
4499
 
# ifdef UNIV_DEBUG
4500
4380
/*************************************************************************
4501
4381
Validates the lock queue on a table. */
4502
 
static
 
4382
 
4503
4383
ibool
4504
4384
lock_table_queue_validate(
4505
4385
/*======================*/
4535
4415
 
4536
4416
/*************************************************************************
4537
4417
Validates the lock queue on a single record. */
4538
 
static
 
4418
 
4539
4419
ibool
4540
4420
lock_rec_queue_validate(
4541
4421
/*====================*/
4542
 
                                        /* out: TRUE if ok */
4543
 
        const buf_block_t*      block,  /* in: buffer block containing rec */
4544
 
        const rec_t*            rec,    /* in: record to look at */
4545
 
        dict_index_t*           index,  /* in: index, or NULL if not known */
4546
 
        const ulint*            offsets)/* in: rec_get_offsets(rec, index) */
 
4422
                                /* out: TRUE if ok */
 
4423
        rec_t*          rec,    /* in: record to look at */
 
4424
        dict_index_t*   index,  /* in: index, or NULL if not known */
 
4425
        const ulint*    offsets)/* in: rec_get_offsets(rec, index) */
4547
4426
{
4548
4427
        trx_t*  impl_trx;
4549
4428
        lock_t* lock;
4550
 
        ulint   heap_no;
4551
4429
 
4552
4430
        ut_a(rec);
4553
 
        ut_a(block->frame == page_align(rec));
4554
4431
        ut_ad(rec_offs_validate(rec, index, offsets));
4555
4432
        ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
4556
4433
 
4557
 
        heap_no = page_rec_get_heap_no(rec);
4558
 
 
4559
4434
        lock_mutex_enter_kernel();
4560
4435
 
4561
4436
        if (!page_rec_is_user_rec(rec)) {
4562
4437
 
4563
 
                lock = lock_rec_get_first(block, heap_no);
 
4438
                lock = lock_rec_get_first(rec);
4564
4439
 
4565
4440
                while (lock) {
4566
4441
                        switch(lock->trx->conc_state) {
4582
4457
                                ut_a(lock->index == index);
4583
4458
                        }
4584
4459
 
4585
 
                        lock = lock_rec_get_next(heap_no, lock);
 
4460
                        lock = lock_rec_get_next(rec, lock);
4586
4461
                }
4587
4462
 
4588
4463
                lock_mutex_exit_kernel();
4590
4465
                return(TRUE);
4591
4466
        }
4592
4467
 
4593
 
        if (!index);
4594
 
        else if (dict_index_is_clust(index)) {
 
4468
        if (index && (index->type & DICT_CLUSTERED)) {
4595
4469
 
4596
4470
                impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets);
4597
4471
 
4598
 
                if (impl_trx
4599
 
                    && lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
4600
 
                                                   block, heap_no, impl_trx)) {
 
4472
                if (impl_trx && lock_rec_other_has_expl_req(
 
4473
                            LOCK_S, 0, LOCK_WAIT, rec, impl_trx)) {
4601
4474
 
4602
4475
                        ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
4603
 
                                               block, heap_no, impl_trx));
 
4476
                                               rec, impl_trx));
4604
4477
                }
4605
 
        } else {
 
4478
        }
 
4479
 
 
4480
        if (index && !(index->type & DICT_CLUSTERED)) {
4606
4481
 
4607
4482
                /* The kernel mutex may get released temporarily in the
4608
4483
                next function call: we have to release lock table mutex
4611
4486
                impl_trx = lock_sec_rec_some_has_impl_off_kernel(
4612
4487
                        rec, index, offsets);
4613
4488
 
4614
 
                if (impl_trx
4615
 
                    && lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
4616
 
                                                   block, heap_no, impl_trx)) {
 
4489
                if (impl_trx && lock_rec_other_has_expl_req(
 
4490
                            LOCK_S, 0, LOCK_WAIT, rec, impl_trx)) {
4617
4491
 
4618
4492
                        ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
4619
 
                                               block, heap_no, impl_trx));
 
4493
                                               rec, impl_trx));
4620
4494
                }
4621
4495
        }
4622
4496
 
4623
 
        lock = lock_rec_get_first(block, heap_no);
 
4497
        lock = lock_rec_get_first(rec);
4624
4498
 
4625
4499
        while (lock) {
4626
4500
                ut_a(lock->trx->conc_state == TRX_ACTIVE
4634
4508
 
4635
4509
                if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
4636
4510
 
4637
 
                        enum lock_mode  mode;
 
4511
                        ulint   mode;
4638
4512
 
4639
4513
                        if (lock_get_mode(lock) == LOCK_S) {
4640
4514
                                mode = LOCK_X;
4642
4516
                                mode = LOCK_S;
4643
4517
                        }
4644
4518
                        ut_a(!lock_rec_other_has_expl_req(
4645
 
                                     mode, 0, 0, block, heap_no, lock->trx));
 
4519
                                     mode, 0, 0, rec, lock->trx));
4646
4520
 
4647
4521
                } else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) {
4648
4522
 
4649
4523
                        ut_a(lock_rec_has_to_wait_in_queue(lock));
4650
4524
                }
4651
4525
 
4652
 
                lock = lock_rec_get_next(heap_no, lock);
 
4526
                lock = lock_rec_get_next(rec, lock);
4653
4527
        }
4654
4528
 
4655
4529
        lock_mutex_exit_kernel();
4659
4533
 
4660
4534
/*************************************************************************
4661
4535
Validates the record lock queues on a page. */
4662
 
static
 
4536
 
4663
4537
ibool
4664
4538
lock_rec_validate_page(
4665
4539
/*===================*/
4668
4542
        ulint   page_no)/* in: page number */
4669
4543
{
4670
4544
        dict_index_t*   index;
4671
 
        buf_block_t*    block;
4672
 
        const page_t*   page;
4673
 
        lock_t*         lock;
4674
 
        const rec_t*    rec;
4675
 
        ulint           nth_lock        = 0;
4676
 
        ulint           nth_bit         = 0;
4677
 
        ulint           i;
4678
 
        mtr_t           mtr;
 
4545
        page_t* page;
 
4546
        lock_t* lock;
 
4547
        rec_t*  rec;
 
4548
        ulint   nth_lock                = 0;
 
4549
        ulint   nth_bit                 = 0;
 
4550
        ulint   i;
 
4551
        mtr_t   mtr;
4679
4552
        mem_heap_t*     heap            = NULL;
4680
4553
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
4681
4554
        ulint*          offsets         = offsets_;
4682
 
        rec_offs_init(offsets_);
 
4555
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
4683
4556
 
4684
4557
        ut_ad(!mutex_own(&kernel_mutex));
4685
4558
 
4686
4559
        mtr_start(&mtr);
4687
4560
 
4688
 
        block = buf_page_get(space, fil_space_get_zip_size(space),
4689
 
                             page_no, RW_X_LATCH, &mtr);
 
4561
        page = buf_page_get(space, page_no, RW_X_LATCH, &mtr);
4690
4562
#ifdef UNIV_SYNC_DEBUG
4691
 
        buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
 
4563
        buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK);
4692
4564
#endif /* UNIV_SYNC_DEBUG */
4693
 
        page = block->frame;
4694
4565
 
4695
4566
        lock_mutex_enter_kernel();
4696
4567
loop:
4720
4591
 
4721
4592
                        index = lock->index;
4722
4593
                        rec = page_find_rec_with_heap_no(page, i);
4723
 
                        ut_a(rec);
4724
4594
                        offsets = rec_get_offsets(rec, index, offsets,
4725
4595
                                                  ULINT_UNDEFINED, &heap);
4726
4596
 
4730
4600
 
4731
4601
                        lock_mutex_exit_kernel();
4732
4602
 
4733
 
                        lock_rec_queue_validate(block, rec, index, offsets);
 
4603
                        lock_rec_queue_validate(rec, index, offsets);
4734
4604
 
4735
4605
                        lock_mutex_enter_kernel();
4736
4606
 
4758
4628
 
4759
4629
/*************************************************************************
4760
4630
Validates the lock system. */
4761
 
static
 
4631
 
4762
4632
ibool
4763
4633
lock_validate(void)
4764
4634
/*===============*/
4779
4649
                lock = UT_LIST_GET_FIRST(trx->trx_locks);
4780
4650
 
4781
4651
                while (lock) {
4782
 
                        if (lock_get_type_low(lock) & LOCK_TABLE) {
 
4652
                        if (lock_get_type(lock) & LOCK_TABLE) {
4783
4653
 
4784
4654
                                lock_table_queue_validate(
4785
4655
                                        lock->un_member.tab_lock.table);
4832
4702
 
4833
4703
        return(TRUE);
4834
4704
}
4835
 
# endif /* UNIV_DEBUG */
4836
4705
#endif /* !UNIV_HOTBACKUP */
4837
4706
/*============ RECORD LOCK CHECKS FOR ROW OPERATIONS ====================*/
4838
4707
 
4842
4711
be suspended for some reason; if not, then puts the transaction and
4843
4712
the query thread to the lock wait state and inserts a waiting request
4844
4713
for a gap x-lock to the lock queue. */
4845
 
UNIV_INTERN
 
4714
 
4846
4715
ulint
4847
4716
lock_rec_insert_check_and_lock(
4848
4717
/*===========================*/
4849
4718
                                /* out: DB_SUCCESS, DB_LOCK_WAIT,
4850
4719
                                DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
4851
 
        ulint           flags,  /* in: if BTR_NO_LOCKING_FLAG bit is
4852
 
                                set, does nothing */
 
4720
        ulint           flags,  /* in: if BTR_NO_LOCKING_FLAG bit is set,
 
4721
                                does nothing */
4853
4722
        rec_t*          rec,    /* in: record after which to insert */
4854
 
        buf_block_t*    block,  /* in/out: buffer block of rec */
4855
4723
        dict_index_t*   index,  /* in: index */
4856
4724
        que_thr_t*      thr,    /* in: query thread */
4857
 
        ibool*          inherit)/* out: set to TRUE if the new
4858
 
                                inserted record maybe should inherit
4859
 
                                LOCK_GAP type locks from the successor
4860
 
                                record */
 
4725
        ibool*          inherit)/* out: set to TRUE if the new inserted
 
4726
                                record maybe should inherit LOCK_GAP type
 
4727
                                locks from the successor record */
4861
4728
{
4862
 
        const rec_t*    next_rec;
4863
 
        trx_t*          trx;
4864
 
        lock_t*         lock;
4865
 
        ulint           err;
4866
 
        ulint           next_rec_heap_no;
4867
 
 
4868
 
        ut_ad(block->frame == page_align(rec));
 
4729
        rec_t*  next_rec;
 
4730
        trx_t*  trx;
 
4731
        lock_t* lock;
 
4732
        ulint   err;
4869
4733
 
4870
4734
        if (flags & BTR_NO_LOCKING_FLAG) {
4871
4735
 
4872
4736
                return(DB_SUCCESS);
4873
4737
        }
4874
4738
 
 
4739
        ut_ad(rec);
 
4740
 
4875
4741
        trx = thr_get_trx(thr);
4876
4742
        next_rec = page_rec_get_next(rec);
4877
 
        next_rec_heap_no = page_rec_get_heap_no(next_rec);
 
4743
 
 
4744
        *inherit = FALSE;
4878
4745
 
4879
4746
        lock_mutex_enter_kernel();
4880
4747
 
4881
 
        /* When inserting a record into an index, the table must be at
4882
 
        least IX-locked or we must be building an index, in which case
4883
 
        the table must be at least S-locked. */
4884
 
        ut_ad(lock_table_has(trx, index->table, LOCK_IX)
4885
 
              || (*index->name == TEMP_INDEX_PREFIX
4886
 
                  && lock_table_has(trx, index->table, LOCK_S)));
4887
 
 
4888
 
        lock = lock_rec_get_first(block, next_rec_heap_no);
4889
 
 
4890
 
        if (UNIV_LIKELY(lock == NULL)) {
 
4748
        ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
 
4749
 
 
4750
        lock = lock_rec_get_first(next_rec);
 
4751
 
 
4752
        if (lock == NULL) {
4891
4753
                /* We optimize CPU time usage in the simplest case */
4892
4754
 
4893
4755
                lock_mutex_exit_kernel();
4894
4756
 
4895
 
                if (!dict_index_is_clust(index)) {
 
4757
                if (!(index->type & DICT_CLUSTERED)) {
 
4758
 
4896
4759
                        /* Update the page max trx id field */
4897
 
                        page_update_max_trx_id(block,
4898
 
                                               buf_block_get_page_zip(block),
4899
 
                                               trx->id);
 
4760
                        page_update_max_trx_id(buf_frame_align(rec),
 
4761
                                               thr_get_trx(thr)->id);
4900
4762
                }
4901
4763
 
4902
 
                *inherit = FALSE;
4903
 
 
4904
4764
                return(DB_SUCCESS);
4905
4765
        }
4906
4766
 
4917
4777
        on the successor, which produced an unnecessary deadlock. */
4918
4778
 
4919
4779
        if (lock_rec_other_has_conflicting(
4920
 
                    LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,
4921
 
                    block, next_rec_heap_no, trx)) {
 
4780
                    LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION, next_rec,
 
4781
                    trx)) {
4922
4782
 
4923
4783
                /* Note that we may get DB_SUCCESS also here! */
4924
4784
                err = lock_rec_enqueue_waiting(LOCK_X | LOCK_GAP
4925
4785
                                               | LOCK_INSERT_INTENTION,
4926
 
                                               block, next_rec_heap_no,
4927
 
                                               index, thr);
 
4786
                                               next_rec, index, thr);
4928
4787
        } else {
4929
4788
                err = DB_SUCCESS;
4930
4789
        }
4931
4790
 
4932
4791
        lock_mutex_exit_kernel();
4933
4792
 
4934
 
        if ((err == DB_SUCCESS) && !dict_index_is_clust(index)) {
 
4793
        if (!(index->type & DICT_CLUSTERED) && (err == DB_SUCCESS)) {
 
4794
 
4935
4795
                /* Update the page max trx id field */
4936
 
                page_update_max_trx_id(block,
4937
 
                                       buf_block_get_page_zip(block),
4938
 
                                       trx->id);
 
4796
                page_update_max_trx_id(buf_frame_align(rec),
 
4797
                                       thr_get_trx(thr)->id);
4939
4798
        }
4940
4799
 
4941
4800
#ifdef UNIV_DEBUG
4943
4802
                mem_heap_t*     heap            = NULL;
4944
4803
                ulint           offsets_[REC_OFFS_NORMAL_SIZE];
4945
4804
                const ulint*    offsets;
4946
 
                rec_offs_init(offsets_);
 
4805
                *offsets_ = (sizeof offsets_) / sizeof *offsets_;
4947
4806
 
4948
4807
                offsets = rec_get_offsets(next_rec, index, offsets_,
4949
4808
                                          ULINT_UNDEFINED, &heap);
4950
 
                ut_ad(lock_rec_queue_validate(block,
4951
 
                                              next_rec, index, offsets));
 
4809
                ut_ad(lock_rec_queue_validate(next_rec, index, offsets));
4952
4810
                if (UNIV_LIKELY_NULL(heap)) {
4953
4811
                        mem_heap_free(heap);
4954
4812
                }
4966
4824
void
4967
4825
lock_rec_convert_impl_to_expl(
4968
4826
/*==========================*/
4969
 
        const buf_block_t*      block,  /* in: buffer block of rec */
4970
 
        const rec_t*            rec,    /* in: user record on page */
4971
 
        dict_index_t*           index,  /* in: index of record */
4972
 
        const ulint*            offsets)/* in: rec_get_offsets(rec, index) */
 
4827
        rec_t*          rec,    /* in: user record on page */
 
4828
        dict_index_t*   index,  /* in: index of record */
 
4829
        const ulint*    offsets)/* in: rec_get_offsets(rec, index) */
4973
4830
{
4974
4831
        trx_t*  impl_trx;
4975
4832
 
4978
4835
        ut_ad(rec_offs_validate(rec, index, offsets));
4979
4836
        ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
4980
4837
 
4981
 
        if (dict_index_is_clust(index)) {
 
4838
        if (index->type & DICT_CLUSTERED) {
4982
4839
                impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets);
4983
4840
        } else {
4984
4841
                impl_trx = lock_sec_rec_some_has_impl_off_kernel(
4986
4843
        }
4987
4844
 
4988
4845
        if (impl_trx) {
4989
 
                ulint   heap_no = page_rec_get_heap_no(rec);
4990
 
 
4991
4846
                /* If the transaction has no explicit x-lock set on the
4992
4847
                record, set one for it */
4993
4848
 
4994
 
                if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, block,
4995
 
                                       heap_no, impl_trx)) {
 
4849
                if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
 
4850
                                       impl_trx)) {
4996
4851
 
4997
4852
                        lock_rec_add_to_queue(
4998
4853
                                LOCK_REC | LOCK_X | LOCK_REC_NOT_GAP,
4999
 
                                block, heap_no, index, impl_trx);
 
4854
                                rec, index, impl_trx);
5000
4855
                }
5001
4856
        }
5002
4857
}
5008
4863
reason; if not, then puts the transaction and the query thread to the
5009
4864
lock wait state and inserts a waiting request for a record x-lock to the
5010
4865
lock queue. */
5011
 
UNIV_INTERN
 
4866
 
5012
4867
ulint
5013
4868
lock_clust_rec_modify_check_and_lock(
5014
4869
/*=================================*/
5015
 
                                        /* out: DB_SUCCESS,
5016
 
                                        DB_LOCK_WAIT, DB_DEADLOCK, or
5017
 
                                        DB_QUE_THR_SUSPENDED */
5018
 
        ulint                   flags,  /* in: if BTR_NO_LOCKING_FLAG
5019
 
                                        bit is set, does nothing */
5020
 
        const buf_block_t*      block,  /* in: buffer block of rec */
5021
 
        const rec_t*            rec,    /* in: record which should be
5022
 
                                        modified */
5023
 
        dict_index_t*           index,  /* in: clustered index */
5024
 
        const ulint*            offsets,/* in: rec_get_offsets(rec, index) */
5025
 
        que_thr_t*              thr)    /* in: query thread */
 
4870
                                /* out: DB_SUCCESS, DB_LOCK_WAIT,
 
4871
                                DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
 
4872
        ulint           flags,  /* in: if BTR_NO_LOCKING_FLAG bit is set,
 
4873
                                does nothing */
 
4874
        rec_t*          rec,    /* in: record which should be modified */
 
4875
        dict_index_t*   index,  /* in: clustered index */
 
4876
        const ulint*    offsets,/* in: rec_get_offsets(rec, index) */
 
4877
        que_thr_t*      thr)    /* in: query thread */
5026
4878
{
5027
4879
        ulint   err;
5028
 
        ulint   heap_no;
5029
4880
 
5030
4881
        ut_ad(rec_offs_validate(rec, index, offsets));
5031
 
        ut_ad(dict_index_is_clust(index));
5032
 
        ut_ad(block->frame == page_align(rec));
 
4882
        ut_ad(index->type & DICT_CLUSTERED);
5033
4883
 
5034
4884
        if (flags & BTR_NO_LOCKING_FLAG) {
5035
4885
 
5036
4886
                return(DB_SUCCESS);
5037
4887
        }
5038
4888
 
5039
 
        heap_no = rec_offs_comp(offsets)
5040
 
                ? rec_get_heap_no_new(rec)
5041
 
                : rec_get_heap_no_old(rec);
5042
 
 
5043
4889
        lock_mutex_enter_kernel();
5044
4890
 
5045
4891
        ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
5047
4893
        /* If a transaction has no explicit x-lock set on the record, set one
5048
4894
        for it */
5049
4895
 
5050
 
        lock_rec_convert_impl_to_expl(block, rec, index, offsets);
 
4896
        lock_rec_convert_impl_to_expl(rec, index, offsets);
5051
4897
 
5052
 
        err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP,
5053
 
                            block, heap_no, index, thr);
 
4898
        err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP, rec, index, thr);
5054
4899
 
5055
4900
        lock_mutex_exit_kernel();
5056
4901
 
5057
 
        ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
 
4902
        ut_ad(lock_rec_queue_validate(rec, index, offsets));
5058
4903
 
5059
4904
        return(err);
5060
4905
}
5062
4907
/*************************************************************************
5063
4908
Checks if locks of other transactions prevent an immediate modify (delete
5064
4909
mark or delete unmark) of a secondary index record. */
5065
 
UNIV_INTERN
 
4910
 
5066
4911
ulint
5067
4912
lock_sec_rec_modify_check_and_lock(
5068
4913
/*===============================*/
5069
4914
                                /* out: DB_SUCCESS, DB_LOCK_WAIT,
5070
4915
                                DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
5071
 
        ulint           flags,  /* in: if BTR_NO_LOCKING_FLAG
5072
 
                                bit is set, does nothing */
5073
 
        buf_block_t*    block,  /* in/out: buffer block of rec */
5074
 
        rec_t*          rec,    /* in: record which should be
5075
 
                                modified; NOTE: as this is a secondary
5076
 
                                index, we always have to modify the
5077
 
                                clustered index record first: see the
5078
 
                                comment below */
 
4916
        ulint           flags,  /* in: if BTR_NO_LOCKING_FLAG bit is set,
 
4917
                                does nothing */
 
4918
        rec_t*          rec,    /* in: record which should be modified;
 
4919
                                NOTE: as this is a secondary index, we
 
4920
                                always have to modify the clustered index
 
4921
                                record first: see the comment below */
5079
4922
        dict_index_t*   index,  /* in: secondary index */
5080
4923
        que_thr_t*      thr)    /* in: query thread */
5081
4924
{
5082
4925
        ulint   err;
5083
 
        ulint   heap_no;
5084
 
 
5085
 
        ut_ad(!dict_index_is_clust(index));
5086
 
        ut_ad(block->frame == page_align(rec));
5087
4926
 
5088
4927
        if (flags & BTR_NO_LOCKING_FLAG) {
5089
4928
 
5090
4929
                return(DB_SUCCESS);
5091
4930
        }
5092
4931
 
5093
 
        heap_no = page_rec_get_heap_no(rec);
 
4932
        ut_ad(!(index->type & DICT_CLUSTERED));
5094
4933
 
5095
4934
        /* Another transaction cannot have an implicit lock on the record,
5096
4935
        because when we come here, we already have modified the clustered
5101
4940
 
5102
4941
        ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
5103
4942
 
5104
 
        err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP,
5105
 
                            block, heap_no, index, thr);
 
4943
        err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP, rec, index, thr);
5106
4944
 
5107
4945
        lock_mutex_exit_kernel();
5108
4946
 
5111
4949
                mem_heap_t*     heap            = NULL;
5112
4950
                ulint           offsets_[REC_OFFS_NORMAL_SIZE];
5113
4951
                const ulint*    offsets;
5114
 
                rec_offs_init(offsets_);
 
4952
                *offsets_ = (sizeof offsets_) / sizeof *offsets_;
5115
4953
 
5116
4954
                offsets = rec_get_offsets(rec, index, offsets_,
5117
4955
                                          ULINT_UNDEFINED, &heap);
5118
 
                ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
 
4956
                ut_ad(lock_rec_queue_validate(rec, index, offsets));
5119
4957
                if (UNIV_LIKELY_NULL(heap)) {
5120
4958
                        mem_heap_free(heap);
5121
4959
                }
5124
4962
 
5125
4963
        if (err == DB_SUCCESS) {
5126
4964
                /* Update the page max trx id field */
5127
 
                page_update_max_trx_id(block,
5128
 
                                       buf_block_get_page_zip(block),
 
4965
 
 
4966
                page_update_max_trx_id(buf_frame_align(rec),
5129
4967
                                       thr_get_trx(thr)->id);
5130
4968
        }
5131
4969
 
5135
4973
/*************************************************************************
5136
4974
Like the counterpart for a clustered index below, but now we read a
5137
4975
secondary index record. */
5138
 
UNIV_INTERN
 
4976
 
5139
4977
ulint
5140
4978
lock_sec_rec_read_check_and_lock(
5141
4979
/*=============================*/
5142
 
                                        /* out: DB_SUCCESS,
5143
 
                                        DB_LOCK_WAIT, DB_DEADLOCK, or
5144
 
                                        DB_QUE_THR_SUSPENDED */
5145
 
        ulint                   flags,  /* in: if BTR_NO_LOCKING_FLAG
5146
 
                                        bit is set, does nothing */
5147
 
        const buf_block_t*      block,  /* in: buffer block of rec */
5148
 
        const rec_t*            rec,    /* in: user record or page
5149
 
                                        supremum record which should
5150
 
                                        be read or passed over by a
5151
 
                                        read cursor */
5152
 
        dict_index_t*           index,  /* in: secondary index */
5153
 
        const ulint*            offsets,/* in: rec_get_offsets(rec, index) */
5154
 
        enum lock_mode          mode,   /* in: mode of the lock which
5155
 
                                        the read cursor should set on
5156
 
                                        records: LOCK_S or LOCK_X; the
5157
 
                                        latter is possible in
5158
 
                                        SELECT FOR UPDATE */
5159
 
        ulint                   gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
5160
 
                                        LOCK_REC_NOT_GAP */
5161
 
        que_thr_t*              thr)    /* in: query thread */
 
4980
                                /* out: DB_SUCCESS, DB_LOCK_WAIT,
 
4981
                                DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
 
4982
        ulint           flags,  /* in: if BTR_NO_LOCKING_FLAG bit is set,
 
4983
                                does nothing */
 
4984
        rec_t*          rec,    /* in: user record or page supremum record
 
4985
                                which should be read or passed over by a read
 
4986
                                cursor */
 
4987
        dict_index_t*   index,  /* in: secondary index */
 
4988
        const ulint*    offsets,/* in: rec_get_offsets(rec, index) */
 
4989
        ulint           mode,   /* in: mode of the lock which the read cursor
 
4990
                                should set on records: LOCK_S or LOCK_X; the
 
4991
                                latter is possible in SELECT FOR UPDATE */
 
4992
        ulint           gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
 
4993
                                LOCK_REC_NOT_GAP */
 
4994
        que_thr_t*      thr)    /* in: query thread */
5162
4995
{
5163
4996
        ulint   err;
5164
 
        ulint   heap_no;
5165
4997
 
5166
 
        ut_ad(!dict_index_is_clust(index));
5167
 
        ut_ad(block->frame == page_align(rec));
 
4998
        ut_ad(!(index->type & DICT_CLUSTERED));
5168
4999
        ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
5169
5000
        ut_ad(rec_offs_validate(rec, index, offsets));
5170
 
        ut_ad(mode == LOCK_X || mode == LOCK_S);
5171
5001
 
5172
5002
        if (flags & BTR_NO_LOCKING_FLAG) {
5173
5003
 
5174
5004
                return(DB_SUCCESS);
5175
5005
        }
5176
5006
 
5177
 
        heap_no = page_rec_get_heap_no(rec);
5178
 
 
5179
5007
        lock_mutex_enter_kernel();
5180
5008
 
5181
5009
        ut_ad(mode != LOCK_X
5187
5015
        if the max trx id for the page >= min trx id for the trx list or a
5188
5016
        database recovery is running. */
5189
5017
 
5190
 
        if (((ut_dulint_cmp(page_get_max_trx_id(block->frame),
 
5018
        if (((ut_dulint_cmp(page_get_max_trx_id(buf_frame_align(rec)),
5191
5019
                            trx_list_get_min_trx_id()) >= 0)
5192
5020
             || recv_recovery_is_on())
5193
5021
            && !page_rec_is_supremum(rec)) {
5194
5022
 
5195
 
                lock_rec_convert_impl_to_expl(block, rec, index, offsets);
 
5023
                lock_rec_convert_impl_to_expl(rec, index, offsets);
5196
5024
        }
5197
5025
 
5198
 
        err = lock_rec_lock(FALSE, mode | gap_mode,
5199
 
                            block, heap_no, index, thr);
 
5026
        err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr);
5200
5027
 
5201
5028
        lock_mutex_exit_kernel();
5202
5029
 
5203
 
        ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
 
5030
        ut_ad(lock_rec_queue_validate(rec, index, offsets));
5204
5031
 
5205
5032
        return(err);
5206
5033
}
5212
5039
puts the transaction and the query thread to the lock wait state and inserts a
5213
5040
waiting request for a record lock to the lock queue. Sets the requested mode
5214
5041
lock on the record. */
5215
 
UNIV_INTERN
 
5042
 
5216
5043
ulint
5217
5044
lock_clust_rec_read_check_and_lock(
5218
5045
/*===============================*/
5219
 
                                        /* out: DB_SUCCESS,
5220
 
                                        DB_LOCK_WAIT, DB_DEADLOCK, or
5221
 
                                        DB_QUE_THR_SUSPENDED */
5222
 
        ulint                   flags,  /* in: if BTR_NO_LOCKING_FLAG
5223
 
                                        bit is set, does nothing */
5224
 
        const buf_block_t*      block,  /* in: buffer block of rec */
5225
 
        const rec_t*            rec,    /* in: user record or page
5226
 
                                        supremum record which should
5227
 
                                        be read or passed over by a
5228
 
                                        read cursor */
5229
 
        dict_index_t*           index,  /* in: clustered index */
5230
 
        const ulint*            offsets,/* in: rec_get_offsets(rec, index) */
5231
 
        enum lock_mode          mode,   /* in: mode of the lock which
5232
 
                                        the read cursor should set on
5233
 
                                        records: LOCK_S or LOCK_X; the
5234
 
                                        latter is possible in
5235
 
                                        SELECT FOR UPDATE */
5236
 
        ulint                   gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
5237
 
                                        LOCK_REC_NOT_GAP */
5238
 
        que_thr_t*              thr)    /* in: query thread */
 
5046
                                /* out: DB_SUCCESS, DB_LOCK_WAIT,
 
5047
                                DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
 
5048
        ulint           flags,  /* in: if BTR_NO_LOCKING_FLAG bit is set,
 
5049
                                does nothing */
 
5050
        rec_t*          rec,    /* in: user record or page supremum record
 
5051
                                which should be read or passed over by a read
 
5052
                                cursor */
 
5053
        dict_index_t*   index,  /* in: clustered index */
 
5054
        const ulint*    offsets,/* in: rec_get_offsets(rec, index) */
 
5055
        ulint           mode,   /* in: mode of the lock which the read cursor
 
5056
                                should set on records: LOCK_S or LOCK_X; the
 
5057
                                latter is possible in SELECT FOR UPDATE */
 
5058
        ulint           gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
 
5059
                                LOCK_REC_NOT_GAP */
 
5060
        que_thr_t*      thr)    /* in: query thread */
5239
5061
{
5240
5062
        ulint   err;
5241
 
        ulint   heap_no;
5242
5063
 
5243
 
        ut_ad(dict_index_is_clust(index));
5244
 
        ut_ad(block->frame == page_align(rec));
 
5064
        ut_ad(index->type & DICT_CLUSTERED);
5245
5065
        ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
5246
5066
        ut_ad(gap_mode == LOCK_ORDINARY || gap_mode == LOCK_GAP
5247
5067
              || gap_mode == LOCK_REC_NOT_GAP);
5252
5072
                return(DB_SUCCESS);
5253
5073
        }
5254
5074
 
5255
 
        heap_no = page_rec_get_heap_no(rec);
5256
 
 
5257
5075
        lock_mutex_enter_kernel();
5258
5076
 
5259
5077
        ut_ad(mode != LOCK_X
5261
5079
        ut_ad(mode != LOCK_S
5262
5080
              || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
5263
5081
 
5264
 
        if (UNIV_LIKELY(heap_no != PAGE_HEAP_NO_SUPREMUM)) {
 
5082
        if (!page_rec_is_supremum(rec)) {
5265
5083
 
5266
 
                lock_rec_convert_impl_to_expl(block, rec, index, offsets);
 
5084
                lock_rec_convert_impl_to_expl(rec, index, offsets);
5267
5085
        }
5268
5086
 
5269
 
        err = lock_rec_lock(FALSE, mode | gap_mode,
5270
 
                            block, heap_no, index, thr);
 
5087
        err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr);
5271
5088
 
5272
5089
        lock_mutex_exit_kernel();
5273
5090
 
5274
 
        ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
 
5091
        ut_ad(lock_rec_queue_validate(rec, index, offsets));
5275
5092
 
5276
5093
        return(err);
5277
5094
}
5284
5101
lock on the record. This is an alternative version of
5285
5102
lock_clust_rec_read_check_and_lock() that does not require the parameter
5286
5103
"offsets". */
5287
 
UNIV_INTERN
 
5104
 
5288
5105
ulint
5289
5106
lock_clust_rec_read_check_and_lock_alt(
5290
5107
/*===================================*/
5291
 
                                        /* out: DB_SUCCESS,
5292
 
                                        DB_LOCK_WAIT, DB_DEADLOCK, or
5293
 
                                        DB_QUE_THR_SUSPENDED */
5294
 
        ulint                   flags,  /* in: if BTR_NO_LOCKING_FLAG
5295
 
                                        bit is set, does nothing */
5296
 
        const buf_block_t*      block,  /* in: buffer block of rec */
5297
 
        const rec_t*            rec,    /* in: user record or page
5298
 
                                        supremum record which should
5299
 
                                        be read or passed over by a
5300
 
                                        read cursor */
5301
 
        dict_index_t*           index,  /* in: clustered index */
5302
 
        enum lock_mode          mode,   /* in: mode of the lock which
5303
 
                                        the read cursor should set on
5304
 
                                        records: LOCK_S or LOCK_X; the
5305
 
                                        latter is possible in
5306
 
                                        SELECT FOR UPDATE */
5307
 
        ulint                   gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
5308
 
                                        LOCK_REC_NOT_GAP */
5309
 
        que_thr_t*              thr)    /* in: query thread */
 
5108
                                /* out: DB_SUCCESS, DB_LOCK_WAIT,
 
5109
                                DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
 
5110
        ulint           flags,  /* in: if BTR_NO_LOCKING_FLAG bit is set,
 
5111
                                does nothing */
 
5112
        rec_t*          rec,    /* in: user record or page supremum record
 
5113
                                which should be read or passed over by a read
 
5114
                                cursor */
 
5115
        dict_index_t*   index,  /* in: clustered index */
 
5116
        ulint           mode,   /* in: mode of the lock which the read cursor
 
5117
                                should set on records: LOCK_S or LOCK_X; the
 
5118
                                latter is possible in SELECT FOR UPDATE */
 
5119
        ulint           gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
 
5120
                                LOCK_REC_NOT_GAP */
 
5121
        que_thr_t*      thr)    /* in: query thread */
5310
5122
{
5311
5123
        mem_heap_t*     tmp_heap        = NULL;
5312
5124
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
5313
5125
        ulint*          offsets         = offsets_;
5314
5126
        ulint           ret;
5315
 
        rec_offs_init(offsets_);
 
5127
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
5316
5128
 
5317
5129
        offsets = rec_get_offsets(rec, index, offsets,
5318
5130
                                  ULINT_UNDEFINED, &tmp_heap);
5319
 
        ret = lock_clust_rec_read_check_and_lock(flags, block, rec, index,
 
5131
        ret = lock_clust_rec_read_check_and_lock(flags, rec, index,
5320
5132
                                                 offsets, mode, gap_mode, thr);
5321
5133
        if (tmp_heap) {
5322
5134
                mem_heap_free(tmp_heap);
5324
5136
        return(ret);
5325
5137
}
5326
5138
 
5327
 
/***********************************************************************
5328
 
Gets the type of a lock. Non-inline version for using outside of the
5329
 
lock module. */
5330
 
UNIV_INTERN
5331
 
ulint
5332
 
lock_get_type(
5333
 
/*==========*/
5334
 
                                /* out: LOCK_TABLE or LOCK_REC */
5335
 
        const lock_t*   lock)   /* in: lock */
5336
 
{
5337
 
        return(lock_get_type_low(lock));
5338
 
}
5339
 
 
5340
 
/***********************************************************************
5341
 
Gets the id of the transaction owning a lock. */
5342
 
UNIV_INTERN
5343
 
ullint
5344
 
lock_get_trx_id(
5345
 
/*============*/
5346
 
                                /* out: transaction id */
5347
 
        const lock_t*   lock)   /* in: lock */
5348
 
{
5349
 
        return(trx_get_id(lock->trx));
5350
 
}
5351
 
 
5352
 
/***********************************************************************
5353
 
Gets the mode of a lock in a human readable string.
5354
 
The string should not be free()'d or modified. */
5355
 
UNIV_INTERN
5356
 
const char*
5357
 
lock_get_mode_str(
5358
 
/*==============*/
5359
 
                                /* out: lock mode */
5360
 
        const lock_t*   lock)   /* in: lock */
5361
 
{
5362
 
        ibool   is_gap_lock;
5363
 
 
5364
 
        is_gap_lock = lock_get_type_low(lock) == LOCK_REC
5365
 
                && lock_rec_get_gap(lock);
5366
 
 
5367
 
        switch (lock_get_mode(lock)) {
5368
 
        case LOCK_S:
5369
 
                if (is_gap_lock) {
5370
 
                        return("S,GAP");
5371
 
                } else {
5372
 
                        return("S");
5373
 
                }
5374
 
        case LOCK_X:
5375
 
                if (is_gap_lock) {
5376
 
                        return("X,GAP");
5377
 
                } else {
5378
 
                        return("X");
5379
 
                }
5380
 
        case LOCK_IS:
5381
 
                if (is_gap_lock) {
5382
 
                        return("IS,GAP");
5383
 
                } else {
5384
 
                        return("IS");
5385
 
                }
5386
 
        case LOCK_IX:
5387
 
                if (is_gap_lock) {
5388
 
                        return("IX,GAP");
5389
 
                } else {
5390
 
                        return("IX");
5391
 
                }
5392
 
        case LOCK_AUTO_INC:
5393
 
                return("AUTO_INC");
5394
 
        default:
5395
 
                return("UNKNOWN");
5396
 
        }
5397
 
}
5398
 
 
5399
 
/***********************************************************************
5400
 
Gets the type of a lock in a human readable string.
5401
 
The string should not be free()'d or modified. */
5402
 
UNIV_INTERN
5403
 
const char*
5404
 
lock_get_type_str(
5405
 
/*==============*/
5406
 
                                /* out: lock type */
5407
 
        const lock_t*   lock)   /* in: lock */
5408
 
{
5409
 
        switch (lock_get_type_low(lock)) {
5410
 
        case LOCK_REC:
5411
 
                return("RECORD");
5412
 
        case LOCK_TABLE:
5413
 
                return("TABLE");
5414
 
        default:
5415
 
                return("UNKNOWN");
5416
 
        }
5417
 
}
5418
 
 
5419
 
/***********************************************************************
5420
 
Gets the table on which the lock is. */
5421
 
UNIV_INLINE
5422
 
dict_table_t*
5423
 
lock_get_table(
5424
 
/*===========*/
5425
 
                                /* out: table */
5426
 
        const lock_t*   lock)   /* in: lock */
5427
 
{
5428
 
        switch (lock_get_type_low(lock)) {
5429
 
        case LOCK_REC:
5430
 
                return(lock->index->table);
5431
 
        case LOCK_TABLE:
5432
 
                return(lock->un_member.tab_lock.table);
5433
 
        default:
5434
 
                ut_error;
5435
 
                return(NULL);
5436
 
        }
5437
 
}
5438
 
 
5439
 
/***********************************************************************
5440
 
Gets the id of the table on which the lock is. */
5441
 
UNIV_INTERN
5442
 
ullint
5443
 
lock_get_table_id(
5444
 
/*==============*/
5445
 
                                /* out: id of the table */
5446
 
        const lock_t*   lock)   /* in: lock */
5447
 
{
5448
 
        dict_table_t*   table;
5449
 
 
5450
 
        table = lock_get_table(lock);
5451
 
 
5452
 
        return((ullint)ut_conv_dulint_to_longlong(table->id));
5453
 
}
5454
 
 
5455
 
/***********************************************************************
5456
 
Gets the name of the table on which the lock is.
5457
 
The string should not be free()'d or modified. */
5458
 
UNIV_INTERN
5459
 
const char*
5460
 
lock_get_table_name(
5461
 
/*================*/
5462
 
                                /* out: name of the table */
5463
 
        const lock_t*   lock)   /* in: lock */
5464
 
{
5465
 
        dict_table_t*   table;
5466
 
 
5467
 
        table = lock_get_table(lock);
5468
 
 
5469
 
        return(table->name);
5470
 
}
5471
 
 
5472
 
/***********************************************************************
5473
 
For a record lock, gets the index on which the lock is. */
5474
 
UNIV_INTERN
5475
 
const dict_index_t*
5476
 
lock_rec_get_index(
5477
 
/*===============*/
5478
 
                                /* out: index */
5479
 
        const lock_t*   lock)   /* in: lock */
5480
 
{
5481
 
        ut_a(lock_get_type_low(lock) == LOCK_REC);
5482
 
 
5483
 
        return(lock->index);
5484
 
}
5485
 
 
5486
 
/***********************************************************************
5487
 
For a record lock, gets the name of the index on which the lock is.
5488
 
The string should not be free()'d or modified. */
5489
 
UNIV_INTERN
5490
 
const char*
5491
 
lock_rec_get_index_name(
5492
 
/*====================*/
5493
 
                                /* out: name of the index */
5494
 
        const lock_t*   lock)   /* in: lock */
5495
 
{
5496
 
        ut_a(lock_get_type_low(lock) == LOCK_REC);
5497
 
 
5498
 
        return(lock->index->name);
5499
 
}
5500
 
 
5501
 
/***********************************************************************
5502
 
For a record lock, gets the tablespace number on which the lock is. */
5503
 
UNIV_INTERN
5504
 
ulint
5505
 
lock_rec_get_space_id(
5506
 
/*==================*/
5507
 
                                /* out: tablespace number */
5508
 
        const lock_t*   lock)   /* in: lock */
5509
 
{
5510
 
        ut_a(lock_get_type_low(lock) == LOCK_REC);
5511
 
 
5512
 
        return(lock->un_member.rec_lock.space);
5513
 
}
5514
 
 
5515
 
/***********************************************************************
5516
 
For a record lock, gets the page number on which the lock is. */
5517
 
UNIV_INTERN
5518
 
ulint
5519
 
lock_rec_get_page_no(
5520
 
/*=================*/
5521
 
                                /* out: page number */
5522
 
        const lock_t*   lock)   /* in: lock */
5523
 
{
5524
 
        ut_a(lock_get_type_low(lock) == LOCK_REC);
5525
 
 
5526
 
        return(lock->un_member.rec_lock.page_no);
5527
 
}