Project

General

Profile

h2_synchronization_fix_20160816a.patch

Eric Faulhaber, 02/06/2017 09:49 AM

Download (5.76 KB)

View differences:

h2/src/main/org/h2/table/RegularTable.java
533 533
    }
534 534

  
535 535
    private boolean doLock2(Session session, int lockMode, boolean exclusive) {
536
        if (exclusive) {
537
            if (lockExclusiveSession == null) {
538
                if (lockSharedSessions.isEmpty()) {
539
                    traceLock(session, exclusive, "added for");
540
                    session.addLock(this);
541
                    lockExclusiveSession = session;
542
                    return true;
543
                } else if (lockSharedSessions.size() == 1 &&
544
                        lockSharedSessions.contains(session)) {
545
                    traceLock(session, exclusive, "add (upgraded) for ");
546
                    lockExclusiveSession = session;
547
                    return true;
548
                }
549
            }
550
        } else {
551
            if (lockExclusiveSession == null) {
552
                if (lockMode == Constants.LOCK_MODE_READ_COMMITTED) {
553
                    if (!database.isMultiThreaded() && !database.isMultiVersion()) {
554
                        // READ_COMMITTED: a read lock is acquired,
555
                        // but released immediately after the operation
556
                        // is complete.
557
                        // When allowing only one thread, no lock is
558
                        // required.
559
                        // Row level locks work like read committed.
536
        synchronized (this)
537
        {
538
            if (exclusive) {
539
                if (lockExclusiveSession == null) {
540
                    if (lockSharedSessions.isEmpty()) {
541
                        traceLock(session, exclusive, "added for");
542
                        session.addLock(this);
543
                        lockExclusiveSession = session;
544
                        return true;
545
                    } else if (lockSharedSessions.size() == 1 &&
546
                            lockSharedSessions.contains(session)) {
547
                        traceLock(session, exclusive, "add (upgraded) for ");
548
                        lockExclusiveSession = session;
560 549
                        return true;
561 550
                    }
562 551
                }
563
                if (!lockSharedSessions.contains(session)) {
564
                    traceLock(session, exclusive, "ok");
565
                    session.addLock(this);
566
                    lockSharedSessions.add(session);
552
            } else {
553
                if (lockExclusiveSession == null) {
554
                    if (lockMode == Constants.LOCK_MODE_READ_COMMITTED) {
555
                        if (!database.isMultiThreaded() && !database.isMultiVersion()) {
556
                            // READ_COMMITTED: a read lock is acquired,
557
                            // but released immediately after the operation
558
                            // is complete.
559
                            // When allowing only one thread, no lock is
560
                            // required.
561
                            // Row level locks work like read committed.
562
                            return true;
563
                        }
564
                    }
565
                    if (!lockSharedSessions.contains(session)) {
566
                        traceLock(session, exclusive, "ok");
567
                        session.addLock(this);
568
                        lockSharedSessions.add(session);
569
                    }
570
                    return true;
567 571
                }
568
                return true;
569 572
            }
570 573
        }
571 574
        return false;
......
638 641
                    }
639 642
                }
640 643
            }
641
            if (error == null && lockExclusiveSession != null) {
642
                Table t = lockExclusiveSession.getWaitForLock();
643
                if (t != null) {
644
                    error = t.checkDeadlock(lockExclusiveSession, clash, visited);
645
                    if (error != null) {
646
                        error.add(session);
644
            synchronized (this)
645
            {
646
                if (error == null && lockExclusiveSession != null) {
647
                    Table t = lockExclusiveSession.getWaitForLock();
648
                    if (t != null) {
649
                        error = t.checkDeadlock(lockExclusiveSession, clash, visited);
650
                        if (error != null) {
651
                            error.add(session);
652
                        }
647 653
                    }
648 654
                }
649 655
            }
......
666 672
    @Override
667 673
    public void unlock(Session s) {
668 674
        if (database != null) {
669
            traceLock(s, lockExclusiveSession == s, "unlock");
670
            if (lockExclusiveSession == s) {
671
                lockExclusiveSession = null;
672
            }
673
            if (lockSharedSessions.size() > 0) {
674
                lockSharedSessions.remove(s);
675
            synchronized (this)
676
            {
677
                traceLock(s, lockExclusiveSession == s, "unlock");
678
                if (lockExclusiveSession == s) {
679
                    lockExclusiveSession = null;
680
                }
681
                if (lockSharedSessions.size() > 0) {
682
                    lockSharedSessions.remove(s);
683
                }
675 684
            }
676 685
            synchronized (database) {
677 686
                if (!waitingSessions.isEmpty()) {
......
719 728
        scanIndex.remove(session);
720 729
        database.removeMeta(session, getId());
721 730
        scanIndex = null;
722
        lockExclusiveSession = null;
731
        synchronized (this)
732
        {
733
            lockExclusiveSession = null;
734
        }
723 735
        lockSharedSessions = null;
724 736
        invalidate();
725 737
    }