public bool Contains(Lockey key) { // 需要sync,get不是线程安全的 lock (this) { return(locks.get(key) != null); } }
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)); }
public Lockey Get(Lockey key) { lock (this) { Lockey exist = locks.get(key); if (null != exist) { return(exist); } locks.add(key); return(key.Alloc()); } }
// under lockey.writelock /* * internal bool RemoeIfNotDirty(K key) * { * var storage = Table.Storage; * if (null == storage) * return false; // 内存表不该发生Reduce. * * if (storage.IsRecordChanged(key)) // 在记录里面维持一个 Dirty 标志是可行的,但是由于 Cache.CleanNow 执行的不频繁,无所谓了。 * return false; * * return map.TryRemove(key, out var _); * } */ private bool TryRemoveRecord(KeyValuePair <K, Record <K, V> > p) { TableKey tkey = new TableKey(this.Table.Id, p.Key); Lockey lockey = Locks.Instance.Get(tkey); if (false == lockey.TryEnterWriteLock(0)) { return(false); } try { var storage = Table.Storage; if (null == storage) { /* 不支持内存表cache同步。 * if (p.Value.Acquire(GlobalCacheManager.StateInvalid) != GlobalCacheManager.StateInvalid) * return false; */ return(Remove(p)); } if (storage.IsRecordChanged(p.Key)) // 在记录里面维持一个 Dirty 标志是可行的,但是由于 Cache.CleanNow 执行的不频繁,无所谓了。 { return(false); } if (p.Value.State != GlobalCacheManager.StateInvalid) { if (p.Value.Acquire(GlobalCacheManager.StateInvalid) != GlobalCacheManager.StateInvalid) { return(false); } } return(Remove(p)); } finally { lockey.ExitWriteLock(); } }
/* ---------------- hash算法和映射规则都是来自 ConcurrentHashMap. -------------- */ /** * Returns the segment that should be used for key with given hash. * * @param lockey the Lockey * @return the segment */ private Segment segmentFor(Lockey lockey) { /** * Applies a supplemental hash function to a given hashCode, which defends * against poor quality hash functions. This is critical because * ConcurrentHashMap uses power-of-two length hash tables, that otherwise * encounter collisions for hashCodes that do not differ in lower or upper bits. */ // Spread bits to regularize both segment and index locations, // using variant of single-word Wang/Jenkins hash. uint h = (uint)lockey.GetHashCode(); h += (h << 15) ^ 0xffffcd7d; h ^= (h >> 10); h += (h << 3); h ^= (h >> 6); h += (h << 2) + (h << 14); uint hash = h ^ (h >> 16); uint index = (hash >> segmentShift) & segmentMask; return(segments[index]); }
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); }
public Lockey Get(Lockey lockey) { return(this.segmentFor(lockey).Get(lockey)); }
public bool Contains(Lockey lockey) { return(this.segmentFor(lockey).Contains(lockey)); }