Пример #1
0
        public void Rollback()
        {
            int       lastIndex = savepoints.Count - 1;
            Savepoint last      = savepoints[lastIndex];

            savepoints.RemoveAt(lastIndex);
            last.Rollback();
        }
Пример #2
0
        public Savepoint Duplicate()
        {
            Savepoint sp = new Savepoint();

            foreach (var e in Logs)
            {
                sp.Logs[e.Key] = e.Value;
            }
            return(sp);
        }
Пример #3
0
        public void Commit()
        {
            if (savepoints.Count > 1)
            {
                // 嵌套事务,把日志合并到上一层。
                int       lastIndex = savepoints.Count - 1;
                Savepoint last      = savepoints[lastIndex];
                savepoints.RemoveAt(lastIndex);
                savepoints[savepoints.Count - 1].Merge(last);
            }

            /*
             * else
             * {
             *  // 最外层存储过程提交在 Perform 中处理
             * }
             */
        }
Пример #4
0
        public void Merge(Savepoint other)
        {
            foreach (var e in other.Logs)
            {
                Logs[e.Key] = e.Value;
            }

            foreach (var e in other.ChangeNotes)
            {
                if (this.ChangeNotes.TryGetValue(e.Key, out var cur))
                {
                    cur.Merge(e.Value);
                }
                else
                {
                    this.ChangeNotes.Add(e.Key, e.Value);
                }
            }
        }
Пример #5
0
        public void Begin()
        {
            Savepoint sp = savepoints.Count > 0 ? savepoints[savepoints.Count - 1].Duplicate() : new Savepoint();

            savepoints.Add(sp);
        }
Пример #6
0
        private void _final_commit_(Procedure procedure)
        {
            // 下面不允许失败了,因为最终提交失败,数据可能不一致,而且没法恢复。
            // 可以在最终提交里可以实现每事务checkpoint。
            ChangeCollector cc = new ChangeCollector();

            try
            {
                savepoints[savepoints.Count - 1].Commit();
                foreach (var e in accessedRecords)
                {
                    if (e.Value.Dirty)
                    {
                        e.Value.OriginRecord.Commit(e.Value);
                        cc.BuildCollect(e.Key, e.Value); // 首先对脏记录创建Table,Record相关Collector。
                    }
                }
            }
            catch (Exception e)
            {
                logger.Error(e, "Transaction._final_commit_ {0}", procedure);
                Environment.Exit(54321);
            }

            try
            {
                Savepoint sp = savepoints[savepoints.Count - 1];
                foreach (Log log in sp.Logs.Values)
                {
                    if (log.Bean == null)
                    {
                        continue; // 特殊日志没有Bean。
                    }
                    // 写成回调是为了优化,仅在需要的时候才创建path。
                    cc.CollectChanged(log.Bean.TableKey,
                                      (out List <Util.KV <Bean, int> > path, out ChangeNote note) =>
                    {
                        path = new List <Util.KV <Bean, int> >();
                        note = null;
                        path.Add(Util.KV.Create(log.Bean, log.VariableId));
                        log.Bean.BuildChangeListenerPath(path);
                    });
                }
                foreach (ChangeNote cn in sp.ChangeNotes.Values)
                {
                    if (cn.Bean == null)
                    {
                        continue;
                    }

                    // 写成回调是为了优化,仅在需要的时候才创建path。
                    cc.CollectChanged(cn.Bean.TableKey,
                                      (out List <Util.KV <Bean, int> > path, out ChangeNote note) =>
                    {
                        path = new List <Util.KV <Bean, int> >();
                        note = cn;
                        path.Add(Util.KV.Create(cn.Bean.Parent, cn.Bean.VariableId));
                        cn.Bean.Parent.BuildChangeListenerPath(path);
                    });
                }

                savepoints.Clear();
                //accessedRecords.Clear(); // 事务内访问过的记录保留,这样在Listener中可以读取。

                // 禁止在listener回调中访问表格的操作。除了回调参数中给定的记录可以访问。
                // 不再支持在回调中再次执行事务。
                IsCompleted = true; // 在Notify之前设置的。
                cc.Notify();
            }
            catch (Exception ex)
            {
                logger.Error(ex, "ChangeListener Collect And Notify");
            }
            finally
            {
                IsCompleted = true; // 懒得判断什么时候设置这个合适了,防止ChangListener触发异常,没有设置,再设置一遍。
            }

            foreach (Action action in CommitActions)
            {
                try
                {
                    action();
                }
                catch (Exception e)
                {
                    logger.Error(e, "Commit Procedure {0} Action {1}", procedure, action.Method.Name);
                }
            }
            CommitActions.Clear();
        }