public void Commit(int transactionID) { if (paused) { throw new Exception("Transaction handling is currently paused, can't commit!"); } #if LOG_TRANSACTION_HANDLING writer.WriteLine(new String(' ', transactionLevel) + "Commit to " + transactionID); writer.Flush(); --transactionLevel; #endif #if CHECK_RINGLISTS procEnv.graph.CheckTypeRinglistsBroken(); #endif if (procEnv.Recorder != null) { procEnv.Recorder.TransactionCommit(transactionID); } // removes rollback information only if the transaction is outermost // otherwise we might need to undo it because a transaction enclosing this transaction failed if (transactionID == 0) { if (wasVisitedFreeRecorded && undoItems.Count > 0) { if (wasGraphChanged) { undoing = true; procEnv.SwitchToSubgraph(procEnv.Graph); } for (int i = undoItems.Count - 1; i >= 0; --i) { IUndoItem curItem = undoItems[i]; if (curItem is LGSPUndoVisitedFree) { procEnv.graph.UnreserveVisitedFlag(((LGSPUndoVisitedFree)curItem)._visitorID); } else if (curItem is LGSPUndoGraphChange) { curItem.DoUndo(procEnv); } } if (wasGraphChanged) { procEnv.ReturnFromSubgraph(); undoing = false; } } undoItems.Clear(); UnsubscribeEvents(); wasVisitedFreeRecorded = false; wasGraphChanged = false; } }
public void Rollback(int transactionID) { if (paused) { throw new Exception("Transaction handling is currently paused, can't roll back!"); } #if LOG_TRANSACTION_HANDLING writer.WriteLine(new String(' ', transactionLevel) + "Rollback to " + transactionID); writer.Flush(); #endif if (procEnv.Recorder != null) { procEnv.Recorder.TransactionRollback(transactionID, true); } undoing = true; if (wasGraphChanged) { procEnv.SwitchToSubgraph(procEnv.Graph); } while (undoItems.Count > transactionID) { IUndoItem lastItem = undoItems[undoItems.Count - 1]; #if LOG_TRANSACTION_HANDLING writer.Write(new String(' ', transactionLevel) + "rolling back " + undoItems.Count + " - "); if (lastItem is LGSPUndoTransactionStarted) { writer.WriteLine("TransactionStarted"); } else if (lastItem is LGSPUndoElemAdded) { LGSPUndoElemAdded item = (LGSPUndoElemAdded)lastItem; if (item._elem is INode) { INode node = (INode)item._elem; writer.WriteLine("ElementAdded: " + ((LGSPNamedGraph)procEnv.graph).GetElementName(node) + ":" + node.Type.Name); } else if (item._elem is IEdge) { IEdge edge = (IEdge)item._elem; writer.WriteLine("ElementAdded: " + ((LGSPNamedGraph)procEnv.graph).GetElementName(edge.Source) + " -" + ((LGSPNamedGraph)procEnv.graph).GetElementName(edge) + ":" + edge.Type.Name + " ->" + ((LGSPNamedGraph)procEnv.graph).GetElementName(edge.Target)); } else { IObject obj = (IObject)item._elem; writer.WriteLine("ElementAdded: hash" + obj.GetHashCode() + ":" + obj.Type.Name); } } else if (lastItem is LGSPUndoElemRemoved) { LGSPUndoElemRemoved item = (LGSPUndoElemRemoved)lastItem; if (item._elem is INode) { INode node = (INode)item._elem; writer.WriteLine("RemovingElement: " + ((LGSPNamedGraph)procEnv.graph).GetElementName(node) + ":" + node.Type.Name); } else if (item._elem is IEdge) { IEdge edge = (IEdge)item._elem; writer.WriteLine("RemovingElement: " + ((LGSPNamedGraph)procEnv.graph).GetElementName(edge.Source) + " -" + ((LGSPNamedGraph)procEnv.graph).GetElementName(edge) + ":" + edge.Type.Name + "-> " + ((LGSPNamedGraph)procEnv.graph).GetElementName(edge.Target)); } else { IObject obj = (IObject)item._elem; writer.WriteLine("RemovingElement: hash" + obj.GetHashCode() + ":" + obj.Type.Name); } } else if (lastItem is LGSPUndoAttributeChanged) { LGSPUndoAttributeChanged item = (LGSPUndoAttributeChanged)lastItem; if (item._elem is IGraphElement) { writer.WriteLine("ChangingElementAttribute: " + ((LGSPNamedGraph)procEnv.graph).GetElementName((IGraphElement)item._elem) + ":" + item._elem.Type.Name + "." + item._attrType.Name); } else { writer.WriteLine("ChangingElementAttribute: hash" + ((IObject)item._elem).GetHashCode() + ":" + item._elem.Type.Name + "." + item._attrType.Name); } } else if (lastItem is LGSPUndoElemRetyped) { LGSPUndoElemRetyped item = (LGSPUndoElemRetyped)lastItem; writer.WriteLine("RetypingElement: " + ((LGSPNamedGraph)procEnv.graph).GetElementName(item._newElem) + ":" + item._newElem.Type.Name + "<" + ((LGSPNamedGraph)procEnv.graph).GetElementName(item._oldElem) + ":" + item._oldElem.Type.Name + ">"); } else if (lastItem is LGSPUndoElemRedirecting) { LGSPUndoElemRedirecting item = (LGSPUndoElemRedirecting)lastItem; writer.WriteLine("RedirectingEdge: " + ((LGSPNamedGraph)procEnv.graph).GetElementName(item._edge) + " before undoing removal"); } else if (lastItem is LGSPUndoVisitedAlloc) { LGSPUndoVisitedAlloc item = (LGSPUndoVisitedAlloc)lastItem; writer.WriteLine("VisitedAlloc: " + item._visitorID); } else if (lastItem is LGSPUndoVisitedFree) { LGSPUndoVisitedFree item = (LGSPUndoVisitedFree)lastItem; writer.WriteLine("VisitedFree: " + item._visitorID); } else if (lastItem is LGSPUndoSettingVisited) { LGSPUndoSettingVisited item = (LGSPUndoSettingVisited)lastItem; writer.WriteLine("SettingVisited: " + ((LGSPNamedGraph)procEnv.graph).GetElementName(item._elem) + ".visited[" + item._visitorID + "]"); } else if (lastItem is LGSPUndoGraphChange) { LGSPUndoGraphChange item = (LGSPUndoGraphChange)lastItem; writer.WriteLine("GraphChange: to previous " + item._oldGraph.Name); } #endif if (wasGraphChanged) { if (lastItem is LGSPUndoGraphChange) { if (undoItems.Count - 2 >= 0 && undoItems[undoItems.Count - 2] is LGSPUndoGraphChange) { undoItems.RemoveAt(undoItems.Count - 1); continue; // skip graph change without effect to preceeding graph change } } } lastItem.DoUndo(procEnv); undoItems.RemoveAt(undoItems.Count - 1); } if (wasGraphChanged) { procEnv.ReturnFromSubgraph(); } undoing = false; if (transactionID == 0) { UnsubscribeEvents(); wasVisitedFreeRecorded = false; wasGraphChanged = false; } if (procEnv.Recorder != null) { procEnv.Recorder.TransactionRollback(transactionID, false); } #if LOG_TRANSACTION_HANDLING --transactionLevel; writer.Flush(); #endif #if CHECK_RINGLISTS procEnv.graph.CheckTypeRinglistsBroken(); #endif }