public void Rollback() { int lastIndex = savepoints.Count - 1; Savepoint last = savepoints[lastIndex]; savepoints.RemoveAt(lastIndex); last.Rollback(); }
public Savepoint Duplicate() { Savepoint sp = new Savepoint(); foreach (var e in Logs) { sp.Logs[e.Key] = e.Value; } return(sp); }
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 中处理 * } */ }
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); } } }
public void Begin() { Savepoint sp = savepoints.Count > 0 ? savepoints[savepoints.Count - 1].Duplicate() : new Savepoint(); savepoints.Add(sp); }
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(); }