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)); }
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); }