/// <summary> /// Get all of the dependencies from a workspace /// </summary> /// <param name="workspace">The workspace to read the dependencies from</param> /// <param name="customNodeManager">A custom node manager to look up dependencies</param> /// <returns>A WorkspaceDependencies object containing the workspace and its CustomNodeWorkspaceModel dependencies</returns> public static WorkspaceDependencies Collect(HomeWorkspaceModel workspace, ICustomNodeManager customNodeManager) { if (workspace == null) throw new ArgumentNullException("workspace"); if (customNodeManager == null) throw new ArgumentNullException("customNodeManager"); // collect all dependencies var dependencies = new HashSet<CustomNodeDefinition>(); foreach (var node in workspace.Nodes.OfType<Function>()) { dependencies.Add(node.Definition); foreach (var dep in node.Definition.Dependencies) { dependencies.Add(dep); } } var customNodeWorkspaces = new List<ICustomNodeWorkspaceModel>(); foreach (var dependency in dependencies) { ICustomNodeWorkspaceModel customNodeWs; var workspaceExists = customNodeManager.TryGetFunctionWorkspace(dependency.FunctionId, false, out customNodeWs); if (!workspaceExists) { throw new InvalidOperationException(String.Format(Resources.CustomNodeDefinitionNotFoundErrorMessage, dependency.FunctionName)); } if (!customNodeWorkspaces.Contains(customNodeWs)) { customNodeWorkspaces.Add(customNodeWs); } } return new WorkspaceDependencies(workspace, customNodeWorkspaces); }
/// <summary> /// This method is called by task creator to associate the trace data with /// the current instance of virtual machine. The given WorkspaceModel can /// optionally contain saved trace data in a previous execution session. As /// a side-effect, this method resets "WorkspaceModel.PreloadedTraceData" /// data member to ensure the correctness of the execution flow. /// </summary> /// <param name="controller">Reference to the EngineController on which the /// loaded trace data should be set.</param> /// <param name="workspace">The workspace from which the trace data should /// be retrieved.</param> /// <returns>If the given WorkspaceModel contains saved trace data, this /// method returns true, in which case the task needs to be scheduled. /// Otherwise, the method returns false.</returns> /// internal bool Initialize(EngineController controller, HomeWorkspaceModel workspace) { if (controller == null || (controller.LiveRunnerCore == null)) return false; engineController = controller; traceData = workspace.PreloadedTraceData; TargetedWorkspace = workspace; workspace.PreloadedTraceData = null; return ((traceData != null) && traceData.Any()); }
public HomeWorkspaceViewModel(HomeWorkspaceModel model, DynamoViewModel dynamoViewModel) : base(model, dynamoViewModel) { RunSettingsViewModel = new RunSettingsViewModel(((HomeWorkspaceModel)model).RunSettings, this, dynamoViewModel); RunSettingsViewModel.PropertyChanged += RunSettingsViewModel_PropertyChanged; StartPeriodicTimerCommand = new DelegateCommand(StartPeriodicTimer, CanStartPeriodicTimer); StopPeriodicTimerCommand = new DelegateCommand(StopPeriodicTimer, CanStopPeriodicTimer); CheckAndSetPeriodicRunCapability(); var hwm = (HomeWorkspaceModel)Model; hwm.EvaluationStarted += hwm_EvaluationStarted; hwm.EvaluationCompleted += hwm_EvaluationCompleted; hwm.SetNodeDeltaState +=hwm_SetNodeDeltaState; dynamoViewModel.Model.ShutdownStarted += Model_ShutdownStarted; }
/// <summary> /// Add a new HomeWorkspace and set as current /// </summary> /// <api_stability>1</api_stability> public void AddHomeWorkspace() { var defaultWorkspace = new HomeWorkspaceModel( EngineController, Scheduler, NodeFactory, DebugSettings.VerboseLogging, IsTestMode,string.Empty); RegisterHomeWorkspace(defaultWorkspace); AddWorkspace(defaultWorkspace); CurrentWorkspace = defaultWorkspace; }
private void RegisterHomeWorkspace(HomeWorkspaceModel newWorkspace) { newWorkspace.EvaluationCompleted += OnEvaluationCompleted; newWorkspace.RefreshCompleted += OnRefreshCompleted; newWorkspace.Disposed += () => { newWorkspace.EvaluationCompleted -= OnEvaluationCompleted; newWorkspace.RefreshCompleted -= OnRefreshCompleted; }; }
private bool OpenHomeWorkspace( XmlDocument xmlDoc, WorkspaceInfo workspaceInfo, out WorkspaceModel workspace) { var nodeGraph = NodeGraph.LoadGraphFromXml(xmlDoc, NodeFactory); var newWorkspace = new HomeWorkspaceModel( EngineController, Scheduler, NodeFactory, Utils.LoadTraceDataFromXmlDocument(xmlDoc), nodeGraph.Nodes, nodeGraph.Notes, nodeGraph.Annotations, nodeGraph.Presets, nodeGraph.ElementResolver, workspaceInfo, DebugSettings.VerboseLogging, IsTestMode ); RegisterHomeWorkspace(newWorkspace); workspace = newWorkspace; return true; }
protected virtual void Evaluate(HomeWorkspaceModel workspace) { var dynamoModel = workspace.DynamoModel; var sw = new Stopwatch(); try { sw.Start(); dynamoModel.EngineController.GenerateGraphSyncData(workspace.Nodes); //No additional work needed if (dynamoModel.EngineController.HasPendingGraphSyncData) Eval(workspace); } catch (Exception ex) { //Catch unhandled exception if (ex.Message.Length > 0) dynamoModel.Logger.Log(ex); OnRunCancelled(true); if (DynamoModel.IsTestMode) // Throw exception for NUnit. throw new Exception(ex.Message + ":" + ex.StackTrace); } finally { sw.Stop(); InstrumentationLogger.LogAnonymousEvent("Run", "Eval"); InstrumentationLogger.LogAnonymousTimedEvent("Perf", "EvalTime", sw.Elapsed); dynamoModel.Logger.Log( string.Format("Evaluation completed in {0}", sw.Elapsed)); } dynamoModel.OnEvaluationCompleted(this, EventArgs.Empty); }
/// <summary> /// Sends workspace and its' dependencies to Flood. /// </summary> /// <returns>String which is response from server.</returns> internal string Send(HomeWorkspaceModel workspace, WorkspaceProperties workspaceProperties = null) { if (String.IsNullOrWhiteSpace(serverUrl)) { Error = UploadErrorType.ServerNotFound; return Resources.FailedMessage; } if (String.IsNullOrWhiteSpace(authenticationProvider.Username)) { Error = UploadErrorType.AuthenticationFailed; return Resources.FailedMessage; } if (authenticationProvider == null) { Error = UploadErrorType.AuthProviderNotFound; return Resources.FailedMessage; } if (reachClient == null) { reachClient = new WorkspaceStorageClient(authenticationProvider, serverUrl); } var dependencies = WorkspaceDependencies.Collect(workspace, customNodeManager); string result; try { result = reachClient.Send( workspace, dependencies.CustomNodeWorkspaces, workspaceProperties); InvalidNodeNames = null; } catch (InvalidNodesException ex) { InvalidNodeNames = ex.InvalidNodeNames; result = Resources.FailedMessage; } catch { result = Resources.FailedMessage; } return result; }
private void Eval(HomeWorkspaceModel workspaceModel) { var dynamoModel = workspaceModel.DynamoModel; //Print some stuff if we're in debug mode if (dynamoModel.RunInDebug) { } // We have caught all possible exceptions in UpdateGraph call, I am // not certain if this try-catch block is still meaningful or not. try { Exception fatalException = null; bool updated = dynamoModel.EngineController.UpdateGraph(ref fatalException); // If there's a fatal exception, show it to the user, unless of course // if we're running in a unit-test, in which case there's no user. I'd // like not to display the dialog and hold up the continuous integration. // if (DynamoModel.IsTestMode == false && (fatalException != null)) { Action showFailureMessage = () => Nodes.Utilities.DisplayEngineFailureMessage(dynamoModel, fatalException); // The "Run" method is guaranteed to be called on a background // thread (for Revit's case, it is the idle thread). Here we // schedule the message to show up when the UI gets around and // handle it. // dynamoModel.OnRequestDispatcherBeginInvoke(showFailureMessage); } // Currently just use inefficient way to refresh preview values. // After we switch to async call, only those nodes that are really // updated in this execution session will be required to update // preview value. if (updated) { ObservableCollection<NodeModel> nodes = workspaceModel.Nodes; foreach (NodeModel node in nodes) node.IsUpdated = true; } } catch (Exception ex) { /* Evaluation failed due to error */ dynamoModel.Logger.Log(ex); OnRunCancelled(true); //If we are testing, we need to throw an exception here //which will, in turn, throw an Assert.Fail in the //Evaluation thread. if (DynamoModel.IsTestMode) throw new Exception(ex.Message); } }
/// <summary> /// Method to group together all the tasks associated with an execution being complete /// </summary> private void RunComplete(HomeWorkspaceModel workspaceModel) { var dynamoModel = workspaceModel.DynamoModel; dynamoModel.OnRunCompleted(this, false); lock (RunControlMutex) { Running = false; dynamoModel.RunEnabled = true; } if (cancelSet) { dynamoModel.ResetEngine(true); cancelSet = false; } }
protected override void Evaluate(HomeWorkspaceModel workspace) { //Run in idle thread no matter what IdlePromise.ExecuteOnIdleSync(() => base.Evaluate(workspace)); }
protected override void Evaluate(HomeWorkspaceModel workspace) { // SCHEDULER: RevitDynamoRunner is to be retired. throw new System.NotImplementedException(); }
/// <summary> /// Add a workspace to the dynamo model. /// </summary> /// <param name="workspace"></param> public void AddHomeWorkspace() { var workspace = new HomeWorkspaceModel() { WatchChanges = true }; HomeSpace = workspace; _workSpaces.Insert(0, workspace); // to front }
private WorkspaceDependencies(HomeWorkspaceModel homeWorkspace, IEnumerable<ICustomNodeWorkspaceModel> customNodeWorkspaces) { this.HomeWorkspace = homeWorkspace; this.CustomNodeWorkspaces = customNodeWorkspaces.OfType<CustomNodeWorkspaceModel>(); }
private void RunAsync(HomeWorkspaceModel workspaceModel) { evaluationThread = new Thread(() => RunSync(workspaceModel)); evaluationThread.Start(); }
private void AssertManual(HomeWorkspaceModel ws) { Assert.AreEqual(RunType.Manual, ws.RunSettings.RunType); }
private void RunSync(HomeWorkspaceModel workspaceModel) { do { Evaluate(workspaceModel); if (execInternval == null) break; int sleep = execInternval.Value; Thread.Sleep(sleep); } while (!cancelSet); RunComplete(workspaceModel); }
private void AssertAuto(HomeWorkspaceModel ws) { Assert.AreEqual(RunType.Automatic, ws.RunSettings.RunType); }
protected virtual void Evaluate(HomeWorkspaceModel workspace) { var dynamoModel = workspace.DynamoModel; var sw = new Stopwatch(); try { sw.Start(); dynamoModel.EngineController.GenerateGraphSyncData(workspace.Nodes); if (dynamoModel.EngineController.HasPendingGraphSyncData) { ExecutionEvents.OnGraphPreExecution(); Eval(workspace); } } catch (Exception ex) { //Catch unhandled exception if (ex.Message.Length > 0) dynamoModel.Logger.Log(ex); OnRunCancelled(true); if (DynamoModel.IsTestMode) // Throw exception for NUnit. throw new Exception(ex.Message + ":" + ex.StackTrace); } finally { sw.Stop(); InstrumentationLogger.LogAnonymousEvent("Run", "Eval"); InstrumentationLogger.LogAnonymousTimedEvent("Perf", "EvalTime", sw.Elapsed); dynamoModel.Logger.Log( string.Format("Evaluation completed in {0}", sw.Elapsed)); } // When evaluation is completed, we mark all // nodes as ForceReexecuteOfNode = false to prevent // cyclical graph updates. It is therefore the responsibility // of the node implementor to mark this flag = true, if they // want to require update. foreach (var n in workspace.Nodes) { n.ForceReExecuteOfNode = false; } dynamoModel.OnEvaluationCompleted(this, EventArgs.Empty); ExecutionEvents.OnGraphPostExecution(); }
/// <summary> /// Add a workspace to the dynamo model. /// </summary> /// <param name="workspace"></param> private void AddHomeWorkspace() { var workspace = new HomeWorkspaceModel(this) { WatchChanges = true }; HomeSpace = workspace; workspaces.Insert(0, workspace); // to front }
public void RunExpression(HomeWorkspaceModel workspaceModel, int? executionInterval = null) { if (workspaceModel == null) { return; } var dynamoModel = workspaceModel.DynamoModel; execInternval = executionInterval; lock (RunControlMutex) { if (Running) { //We're already running, so we might need an additional run NeedsAdditionalRun = true; return; } //We're new so if we needed an additional run, this one counts NeedsAdditionalRun = false; // If there is preloaded trace data, send that along to the current // LiveRunner instance. Here we make sure it is done exactly once // by resetting WorkspaceModel.PreloadedTraceData property after it // is obtained. // IEnumerable<KeyValuePair<Guid, List<string>>> traceData = workspaceModel.PreloadedTraceData; workspaceModel.PreloadedTraceData = null; // Reset. if (dynamoModel == null || dynamoModel.EngineController == null) { return; } dynamoModel.EngineController.LiveRunnerCore.SetTraceDataForNodes(traceData); //We are now considered running Running = true; } if (!DynamoModel.IsTestMode) { //Setup background worker dynamoModel.RunEnabled = false; //As we are the only place that is allowed to activate this, it is a trap door, so this is safe lock (RunControlMutex) { Validity.Assert(Running); } RunAsync(workspaceModel); } else { //for testing, we do not want to run asynchronously, as it will finish the //test before the evaluation (and the run) is complete //RunThread(evaluationWorker, new DoWorkEventArgs(executionInterval)); RunSync(workspaceModel); } }
internal void SendAsynchronously(HomeWorkspaceModel workspace, WorkspaceProperties workspaceProperties = null) { State = UploadState.Uploading; Task.Factory.StartNew(() => { var result = this.Send(workspace, workspaceProperties); var serverResponce = serverResponceRegex.Match(result); if (serverResponce.Success) { State = UploadState.Succeeded; Error = UploadErrorType.None; CustomizerURL = String.Concat(serverUrl, serverResponce.Value); } else if (InvalidNodeNames != null) { Error = UploadErrorType.InvalidNodes; } else { // If there wasn't any error during uploading, // that means it's some error on the server side. Error = UploadErrorType.UnknownServerError; } }); }