Exemplo n.º 1
0
        private CheckResult _lock_and_check_(KeyValuePair <TableKey, RecordAccessed> e)
        {
            Lockey lockey    = Locks.Instance.Get(e.Key);
            bool   writeLock = e.Value.Dirty;

            lockey.EnterLock(writeLock);
            holdLocks.Add(lockey);
            return(_check_(writeLock, e.Value));
        }
Exemplo n.º 2
0
        private CheckResult _lock_and_check_()
        {
            if (savepoints.Count > 0)
            {
                // 全部 Rollback 时 Count 为 0;最后提交时 Count 必须为 1;其他情况属于Begin,Commit,Rollback不匹配。外面检查。
                foreach (var log in savepoints[savepoints.Count - 1].Logs.Values)
                {
                    if (log.Bean == null)
                    {
                        continue; // 特殊日志。不是 bean 的修改日志,当然也不会修改 Record。现在不会有这种情况,保留给未来扩展需要。
                    }
                    TableKey tkey = log.Bean.TableKey;
                    if (accessedRecords.TryGetValue(tkey, out var record))
                    {
                        record.Dirty = true;
                    }
                    else
                    {
                        logger.Fatal("impossible! record not found."); // 只有测试代码会把非 Managed 的 Bean 的日志加进来。
                    }
                }
            }

            bool conflict = false; // 冲突了,也继续加锁,为重做做准备!!!

            if (holdLocks.Count == 0)
            {
                foreach (var e in accessedRecords)
                {
                    switch (_lock_and_check_(e))
                    {
                    case CheckResult.Success: break;

                    case CheckResult.Redo: conflict = true; break;     // continue lock

                    case CheckResult.RedoAndReleaseLock: return(CheckResult.RedoAndReleaseLock);
                    }
                }
                return(conflict ? CheckResult.Redo : CheckResult.Success);
            }

            int index = 0;
            int n     = holdLocks.Count;

            foreach (var e in accessedRecords)
            {
                // 如果 holdLocks 全部被对比完毕,直接锁定它
                if (index >= n)
                {
                    switch (_lock_and_check_(e))
                    {
                    case CheckResult.Success: break;

                    case CheckResult.Redo: conflict = true; break;     // continue lock

                    case CheckResult.RedoAndReleaseLock: return(CheckResult.RedoAndReleaseLock);
                    }
                    continue;
                }

                Lockey curLock = holdLocks[index];
                int    c       = curLock.TableKey.CompareTo(e.Key);

                // holdlocks a  b  ...
                // needlocks a  b  ...
                if (c == 0)
                {
                    // 这里可能发生读写锁提升
                    if (e.Value.Dirty && false == curLock.isWriteLockHeld())
                    {
                        curLock.EnterLock(true);
                        switch (_check_(true, e.Value))
                        {
                        case CheckResult.Success: break;

                        case CheckResult.Redo: conflict = true; break;     // continue lock

                        case CheckResult.RedoAndReleaseLock: return(CheckResult.RedoAndReleaseLock);
                        }
                    }
                    // else 已经持有读锁,不可能被修改也不可能降级(reduce),所以不做检测了。
                    // 已经锁定了,跳过
                    ++index;
                    continue;
                }
                // holdlocks a  b  ...
                // needlocks a  c  ...
                if (c < 0)
                {
                    // 释放掉 比当前锁序小的锁,因为当前事务中不再需要这些锁
                    int unlockEndIndex = index;
                    for (; unlockEndIndex < n && holdLocks[unlockEndIndex].TableKey.CompareTo(e.Key) < 0; ++unlockEndIndex)
                    {
                        var toUnlockLocker = holdLocks[unlockEndIndex];
                        toUnlockLocker.ExitLock();
                    }
                    holdLocks.RemoveRange(index, unlockEndIndex - index);
                    n = holdLocks.Count;
                    continue;
                }

                // holdlocks a  c  ...
                // needlocks a  b  ...
                // 为了不违背锁序,释放从当前锁开始的所有锁
                for (int i = index; i < n; ++i)
                {
                    var toUnlockLocker = holdLocks[i];
                    toUnlockLocker.ExitLock();
                }
                holdLocks.RemoveRange(index, n - index);
                n = holdLocks.Count;
            }
            return(conflict ? CheckResult.Redo : CheckResult.Success);
        }