/// <summary> /// Adds the node. /// </summary> /// <param name="id">The id.</param> /// <param name="metadata">The metadata.</param> public override void AddNode(String id, Metadata metadata, LoggerNameRoot loggerNameRoot) { // adds a node to the graph RunnableNode node = m_nodesFactory.CreateNode(id, metadata, loggerNameRoot, Library, ComponentsAppDomain, TerminateExperimentExecutionResetEvent); if (node is RunnableStartNode) { //allow set only once if (m_startNode != null) { throw new TraceLab.Core.Exceptions.InconsistentTemplateException("Template cannot have two start nodes defined."); } m_startNode = node; } if (node is RunnableEndNode) { //allow set only once if (m_endNode != null) { throw new TraceLab.Core.Exceptions.InconsistentTemplateException("Template cannot have two end nodes defined."); } m_endNode = node; } m_nodes.Add(node); }
private static void ThreadRun(object obj) { RunnableNodeThreadArgs args = (RunnableNodeThreadArgs)obj; RunnableNode activeNode = (RunnableNode)args.Node; //System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); // Notify that this node is starting work args.ExperimentRunner.OnNodeExecuting(activeNode); Exception error = null; try { activeNode.RunInternal(); } catch (Exception e) { error = e; } if (error != null) { activeNode.HasError = true; activeNode.ErrorMessage = error.Message; RunnableComponentNode componentNode = activeNode as RunnableComponentNode; if (componentNode != null) { if (error is ComponentException) { componentNode.Logger.Error(error.Message); } else { componentNode.Logger.ErrorException(error.Message, error); } } args.ExperimentRunner.OnNodeHasError(activeNode, activeNode.ErrorMessage); args.ExperimentRunner.TerminateExperimentExecution(); } else { // Notify this node is done, then start preparing for any remaining nodes. args.ExperimentRunner.OnNodeFinished(activeNode); //SIGNAL COMPLETION, allowing the waiting Experiment Runner to proceed activeNode.SignalCompletion(); } //sw.Stop(); //System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.Name + ": " + sw.ElapsedMilliseconds); //System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.Name + ": " + sw.Elapsed.TotalMilliseconds); //System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.Name + ": " + (sw.ElapsedTicks)); }
/// <summary> /// Takes the out node from the collection from specified index. /// In other words, it removes the node from the collection and returns it. /// </summary> /// <param name="index">The index.</param> /// <returns></returns> public RunnableNode TakeOutNode(int index) { //the index of active nodes list is shifted by one, because node reset events have terminate events at the beginning RunnableNode node = m_activeNodesList[index - 1]; //remove node from both lists m_activeNodesList.RemoveAt(index - 1); m_nodeResetEvents.RemoveAt(index); //return the node return(node); }
public override bool Equals(object obj) { bool isEqual = false; RunnableNode other = obj as RunnableNode; if (other != null) { isEqual = object.Equals(Id, other.Id); } else { isEqual = base.Equals(obj); } return(isEqual); }
/// <summary> /// Executes the experiment. /// </summary> /// <param name="progress">The progress.</param> public void ExecuteExperiment(IProgress progress) { try { bool successful = true; string endMessage = Messages.ExperimentRunnerSuccessMessage; OnExperimentStarted(); if (m_runnableExperiment.IsEmpty == false) { if (progress != null) { progress.Reset(); progress.NumSteps = m_runnableExperiment.Nodes.Count; // Start at 1 so user can tell something is happening. progress.Increment(); progress.CurrentStatus = Messages.ProgressExperimentProcessing; } // collection of nodes currently executing ActiveNodesList currentActiveNodesList = new ActiveNodesList(m_runnableExperiment.TerminateExperimentExecutionResetEvent); // collection of nodes pending to be started Queue <RunnableNode> pendingNodesToBeRun = new Queue <RunnableNode>(); // enqueue start node pendingNodesToBeRun.Enqueue(m_runnableExperiment.StartNode); bool end = false; while (!end) //until end component is not completed { //activate all pending nodes while (pendingNodesToBeRun.Count > 0) { RunnableNode node = pendingNodesToBeRun.Dequeue(); if (currentActiveNodesList.Contains(node) == false) { RunnableNodeThreadArgs args = new RunnableNodeThreadArgs { ExperimentRunner = this }; var resetEvent = node.Run(args); currentActiveNodesList.Add(node, resetEvent); } } if (currentActiveNodesList.Count > 0) { //wait for any node to be completed int index = WaitHandle.WaitAny(currentActiveNodesList.NodeResetEvents); //the index 0 is the termination signal... if the index is higher than zero then process the completed node if (index > 0) { RunnableNode completedNode = currentActiveNodesList.TakeOutNode(index); if (progress != null) { progress.Increment(); } // if experiment runner reaches end node, then prepare to exit the experiment runner if (completedNode.Equals(m_runnableExperiment.EndNode)) { end = true; // if there are any other nodes still running other than end node if (currentActiveNodesList.Count > 1) { successful = false; endMessage = Messages.ExperimentRunnerErrorMessage; TerminateExperimentExecution(); //send signal terminate in case sth else in sub level experiment is running NLog.LogManager.GetCurrentClassLogger().Error(Messages.ExperimentRunnerEarlyTerminationErrorMessage); } } else { // send one token to all successor nodes foreach (RunnableNode successorNode in completedNode.NextNodes) { //sends token; method will return true if successor node is ready to be run bool readyToRun = successorNode.SendToken(); if (readyToRun) { //add node to the pending nodes to be activated pendingNodesToBeRun.Enqueue(successorNode); } } } } else { //EXECUTED ON SIGNAL TERMINATED // If any node signal TERMINATE for any reason, we shut down the experiment and stop processing new nodes. end = true; successful = false; endMessage = Messages.ExperimentExecutionTerminated; System.Diagnostics.Trace.WriteLine("TERMINATED!"); } } else { end = true; successful = false; endMessage = Messages.ExperimentRunnerInfiniteWaitDetected; TerminateExperimentExecution(); //send signal terminate in case sth else in sub level experiment is running System.Diagnostics.Trace.WriteLine("Infinite wait detected!"); } } // while(!end) //wait if there are any still running threads, only in case if experiment runner ended on termination foreach (RunnableNode n in currentActiveNodesList.Nodes) { //Blocks this thread until all node threads terminate. n.JoinNodeThread(); } } else // if (m_runnableExperiment.IsEmpty == false) { #if DEBUG NLog.LogManager.GetCurrentClassLogger().Debug("RunnableExperiment is empty"); #endif successful = false; endMessage = Messages.ExperimentRunnerErrorMessage; } if (progress != null) { progress.Reset(); if (!successful) { progress.SetError(true); } progress.CurrentStatus = endMessage; } } finally { if (m_disposeRunnableExperiment == true) { // destroy components app domain... note the app domain should not be destroyed by sub level experiments TraceLab.Core.Components.LibraryHelper.DestroyDomain(m_runnableExperiment.ComponentsAppDomain); //dispose entire experiment - it disposes all subexperiments as well. m_runnableExperiment.Dispose(); } OnExperimentFinished(); } }
public bool Contains(RunnableNode node) { return(m_activeNodesList.Contains(node)); }
/// <summary> /// Adds the specified node with its corresponding auto reset event. /// </summary> /// <param name="node">The node.</param> /// <returns></returns> public void Add(RunnableNode node, EventWaitHandle nodeResetEvent) { m_activeNodesList.Add(node); m_nodeResetEvents.Add(nodeResetEvent); }
public bool Contains(RunnableNode node) { return m_activeNodesList.Contains(node); }