Example #1
0
 public bool Contains(Lockey key)
 {
     // 需要sync,get不是线程安全的
     lock (this)
     {
         return(locks.get(key) != null);
     }
 }
Example #2
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));
        }
Example #3
0
            public Lockey Get(Lockey key)
            {
                lock (this)
                {
                    Lockey exist = locks.get(key);
                    if (null != exist)
                    {
                        return(exist);
                    }

                    locks.add(key);
                    return(key.Alloc());
                }
            }
Example #4
0
        // 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();
            }
        }
Example #5
0
        /* ---------------- 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]);
        }
Example #6
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);
        }
Example #7
0
 public Lockey Get(Lockey lockey)
 {
     return(this.segmentFor(lockey).Get(lockey));
 }
Example #8
0
 public bool Contains(Lockey lockey)
 {
     return(this.segmentFor(lockey).Contains(lockey));
 }