Exemple #1
0
 public void BuildCollect(TableKey tableKey, Transaction.RecordAccessed recordAccessed)
 {
     if (tableHasListener)
     {
         ChangeRecordCollector recordCollector = new ChangeRecordCollector(tableKey, table, recordAccessed);
         records.Add(tableKey.Key, recordCollector);
     }
 }
Exemple #2
0
 public void CollectChanged(TableKey tableKey, Collect collect)
 {
     if (tables.TryGetValue(tableKey.TableId, out var ctc))
     {
         ctc.CollectChanged(tableKey, collect);
     }
     // else skip error 只有测试代码可能会走到这个分支。
 }
Exemple #3
0
 public void BuildCollect(TableKey tableKey, Transaction.RecordAccessed recordAccessed)
 {
     if (false == tables.TryGetValue(tableKey.TableId, out var tableCollector))
     {
         tableCollector = new ChangeTableCollector(tableKey);
         tables.Add(tableKey.TableId, tableCollector);
     }
     tableCollector.BuildCollect(tableKey, recordAccessed);
 }
Exemple #4
0
        public RootInfo CreateRootInfoIfNeed(TableKey tkey)
        {
            var cur = Value?.RootInfo;

            if (null == cur)
            {
                cur = new RootInfo(this, tkey);
            }
            return(cur);
        }
Exemple #5
0
        internal RecordAccessed GetRecordAccessed(TableKey key)
        {
            // 允许读取事务内访问过的记录。
            //if (IsCompleted)
            //    throw new Exception("Transaction Is Completed");

            if (accessedRecords.TryGetValue(key, out var record))
            {
                return(record);
            }
            return(null);
        }
Exemple #6
0
 public void CollectChanged(TableKey tableKey, ChangeCollector.Collect collect)
 {
     if (false == this.tableHasListener)
     {
         return;                 // 优化,表格没有监听者时,不收集改变。
     }
     if (records.TryGetValue(tableKey.Key, out var crc))
     {
         crc.CollectChanged(collect);
     }
     // else skip error . 只有测试代码可能会走到这个分支。
 }
Exemple #7
0
        public ChangeRecordCollector(TableKey tableKey, Table table, Transaction.RecordAccessed recordAccessed)
        {
            this.recordAccessed = recordAccessed;
            key = tableKey.Key;

            // 记录发生了覆盖或者删除,也需要把listener建立好,以便后面Notify。但是就不需要收集log和note了。参见下面的 CollectChanged.
            Dictionary <int, HashSet <ChangeListener> > tmp = table.ChangeListenerMap.mapCopy;

            foreach (var e in tmp)
            {
                ChangeVariableCollector cvc = table.CreateChangeVariableCollector(e.Key);
                if (null != cvc)                 // 忽略掉不正确的 variableId,也许注册的时候加个检查更好,先这样了。
                {
                    variables.Add(e.Key, cvc);
                    cvc.listeners = e.Value;
                }
            }
        }
Exemple #8
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();
            }
        }
Exemple #9
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);
        }
Exemple #10
0
 public bool Contains(TableKey tkey)
 {
     return(Contains(new Lockey(tkey)));
 }
Exemple #11
0
 public Lockey Get(TableKey tkey)
 {
     return(Get(new Lockey(tkey)));
 }
Exemple #12
0
 /// <summary>
 /// 相同值的 TableKey 要得到同一个 Lock 引用,必须使用 Locks 查询。
 /// 不要自己构造这个对象。开放出去仅仅为了测试。
 /// </summary>
 /// <param name="key"></param>
 public Lockey(TableKey key)
 {
     TableKey = key;
 }
Exemple #13
0
 public RootInfo(Record record, TableKey tableKey)
 {
     Record   = record;
     TableKey = tableKey;
 }
Exemple #14
0
 public ChangeTableCollector(TableKey tableKey)
 {
     table            = Table.GetTable(tableKey.TableId);
     tableHasListener = table.ChangeListenerMap.HasListener();
 }