protected override async Task OnDispose(ActorUtil util) { disposedList.ShouldHaveBeenDisposed.Enqueue(this); await Task.FromResult(0); }
protected override async Task OnInit(ActorUtil util) { allDependencies.Dependencies.Enqueue(this); await Task.FromResult(0); }
protected override async Task OnRun(ActorUtil util) { await Task.FromResult(0); }
protected override async Task OnRun(ActorUtil util) { var cmds = Commands.DequeueAll(); var parentHasCompiled = parentFile.CompileStatus == CompileStatus.Compiled; var parentExecutableVersion = parentFile.ExecutableVersion; var parentWasRecompiled = parentHasCompiled && parentExecutableVersion != lastKnownExecutableVersion; if (parentHasCompiled) { lastKnownExecutableVersion = parentExecutableVersion; } var shouldPause = cmds.Any(x => x == CTestCommand.Cancel); var shouldResumeOrForce = !shouldPause && cmds.Any(x => x == CTestCommand.Run); var statusWas = this.runStatusAtom.Value; this.runStatusAtom.Value = step(); if (statusWas != RunStatus) { triggerUpdate(); } await Task.FromResult(0); return; //This state-machine actor combination which cancels if a particular //step stalls for long enough is a nice pattern. I wonder if there's //a nice way to abstract this. If putting this in a language, it would //be really neat to define the enum inline based on the needs of the actor, //and then reference the enum elsewhere. RunStatus step() { switch (statusWas) { case RunStatus.WaitingOnParent: case RunStatus.TimedOut: if (shouldPause) { return(RunStatus.Paused); } else if (parentWasRecompiled || (shouldResumeOrForce && parentHasCompiled)) { return(RunStatus.Scheduled); } else { return(statusWas); } case RunStatus.Scheduled: if (shouldPause) { return(RunStatus.Paused); } else if (!parentHasCompiled) { return(RunStatus.WaitingOnParent); } else { this.ProcHandle?.Cancel(); this.procHandleAtom.Value = null; var originalPath = parentFile.SourceFile.FilePath; var executablePath = Path.Combine(Path.GetDirectoryName(originalPath), "bin", Path.GetFileNameWithoutExtension(originalPath)); var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); if (isWindows) { executablePath += ".exe"; } //It would be nice if Actin provided a mechanism to automatically //handle this sort of interaction. We want another actor to do something, //and our next action requires the completion of it. The called actor needs //to know if we've canceled the request, and we need to cancel the request //if we go too long waiting for it. processReceiptAtom.Value = processRunner.StartProcess(new ProcStartInfo( path: executablePath, workingDirectory: Path.GetDirectoryName(executablePath), arguments: new string[] { Test.LineNumber.ToString() }, maxRunTime: new TimeSpan(0, 0, 10), accept: newHandle => { if (newHandle.Id == processReceiptAtom.Value) { this.procHandleAtom.Value = newHandle; } else { newHandle.Cancel(); } } )); startWait(); return(RunStatus.WaitingOnProcessStart); } case RunStatus.WaitingOnProcessStart: if (shouldPause) { this.processReceiptAtom.Value = Guid.Empty; return(RunStatus.Paused); } else if (ProcHandle != null) { startWait(); return(RunStatus.Running); } else if (haveWaited(new TimeSpan(0, 0, 5))) { ProcHandle?.Cancel(); return(RunStatus.TimedOut); } else { return(RunStatus.WaitingOnProcessStart); } case RunStatus.Running: if (shouldPause) { ProcHandle?.Cancel(); return(RunStatus.Paused); } else { var ph = this.ProcHandle; if (haveWaited(new TimeSpan(0, 0, 5))) { return(RunStatus.TimedOut); } else if (ph.Status != ProcessStatus.Finished) { return(RunStatus.Running); } else { lastCompletedRunResultAtom.Value = ph.Result; return(RunStatus.WaitingOnParent); } } case RunStatus.Paused: if (shouldResumeOrForce) { return(parentHasCompiled ? RunStatus.Scheduled : RunStatus.WaitingOnParent); } else { return(RunStatus.Paused); } default: throw new NotImplementedException(statusWas.ToString("g")); } } void startWait() { lastWaitStarted = util.Now; } bool haveWaited(TimeSpan moreThanThis) { var timeSpentWaiting = util.Now - lastWaitStarted; return(timeSpentWaiting > moreThanThis); } void triggerUpdate() { sendUpdates.Send_UpdateTest(parentFile.SourceFile.FilePath ?? "", this.Id); } }
public async Task OnInit(ActorUtil util) { allDependencies.Dependencies.Enqueue(this); await Task.FromResult(0); }
protected override async Task OnDispose(ActorUtil util) { theScene.Disposed.Enqueue(this.Id); await Task.FromResult(0); }
protected override async Task OnRun(ActorUtil util) { HashSet <string> rootCandidates = new HashSet <string>(); HashSet <string> changeCandidates = new HashSet <string>(); { if (RootSourceFileDetected.TryDequeueAll(out var reportedRootSourceFiles)) { foreach (var path in reportedRootSourceFiles) { rootCandidates.Add(path); changeCandidates.Add(path); } } if (AnySourceFileDetectedOrChanged.TryDequeueAll(out var reportedChangedSourceFiles)) { foreach (var path in reportedChangedSourceFiles) { changeCandidates.Add(path); } } } if (!(rootCandidates.Any() || changeCandidates.Any())) { return; } var currentParseTime = util.Now; var activeRootSourceFiles = this.parsedRoots; { var newRootPaths = rootCandidates.Where(candidatePath => !activeRootSourceFiles.Any(file => file.FilePath == candidatePath)).ToArray(); foreach (var rootPath in newRootPaths) { var errorMessagesAtom = new Atom <ImmutableList <string> >(ImmutableList.Create <string>()); var result = await CTestSourceFile.Create(rootPath, currentParseTime, errorMessagesAtom); activeRootSourceFiles = activeRootSourceFiles.Add(result); foreach (var message in errorMessagesAtom.Value) { util.Log.Error(message); } } } { var rootsCopy = activeRootSourceFiles; foreach (var root in rootsCopy) { if (root.ParseTime == currentParseTime) { //We already recompiled this round. continue; } if (root.ReferencesPaths(changeCandidates)) { var errorMessagesAtom = new Atom <ImmutableList <string> >(ImmutableList.Create <string>()); var result = await CTestSourceFile.Create(root.FilePath, currentParseTime, errorMessagesAtom); activeRootSourceFiles = activeRootSourceFiles.Replace(root, result); foreach (var message in errorMessagesAtom.Value) { util.Log.Error(message); } } } } //Remove any missing root files: activeRootSourceFiles = activeRootSourceFiles.Where(x => x.Exists).ToImmutableList(); this.parsedRoots = activeRootSourceFiles; //<== If anything external wants to look at these activeTestFiles.LatestRootFiles.Enqueue(activeRootSourceFiles); var allUniqueFiles = new HashSet <string>(); foreach (var root in activeRootSourceFiles) { var leaves = root.Leaves(); foreach (var leaf in leaves) { foreach (var path in leaf.Lineage) { allUniqueFiles.Add(path); } } } fileWatcher.AllDirectoriesToWatch.Enqueue(allUniqueFiles.Select(x => Path.GetDirectoryName(x)).Distinct().ToImmutableList()); }
/// <summary> /// Returns a description, what she's wearing /// </summary> public string GetClothesDescription(List <Clothing> clothes) { string output = Name + " "; bool topless = false; bool bottomless = false; bool barefoot = false; bool onepiece = false; long[] visibleClothes = new long[2]; long[] footwear = new long[2]; //Examine her clothes if (WornClothes[2] != 0) { visibleClothes[0] = WornClothes[2]; onepiece = true; } else { if (WornClothes[0] != 0) { visibleClothes[0] = WornClothes[0]; } else { if (WornClothes[3] != 0) { visibleClothes[0] = WornClothes[3]; } else { topless = true; } } if (WornClothes[1] != 0) { visibleClothes[1] = WornClothes[1]; } else { if (WornClothes[4] != 0) { visibleClothes[1] = WornClothes[4]; } else { bottomless = true; } } } //Examine her footwear if (WornClothes[5] == 0 && WornClothes[6] == 0) { barefoot = true; } else { footwear[0] = WornClothes[5]; footwear[1] = WornClothes[6]; } //Build output string if (topless && bottomless && barefoot) { return(String.Format("{0} doesn't wear any clothes at all.", Name)); } else { if (onepiece) { output += string.Format("wears {0}", ActorUtil.GetClothingById(clothes, visibleClothes[0]).GetClothingDescription()); } else if (topless || bottomless) { output += "only wears "; if (visibleClothes[0] != 0) { output += ActorUtil.GetClothingById(clothes, visibleClothes[0]).GetClothingDescription(); } else { output += ActorUtil.GetClothingById(clothes, visibleClothes[1]).GetClothingDescription(); } } else { output += String.Format("wears {0}, {1}", ActorUtil.GetClothingById(clothes, visibleClothes[0]).GetClothingDescription(), ActorUtil.GetClothingById(clothes, visibleClothes[1]).GetClothingDescription()); if (barefoot) { output += " and is barefoot."; return(output); } } if (barefoot) { output += " and is barefoot."; return(output); } else { if (footwear[0] != 0 && footwear[1] != 0) { output += String.Format(", {0} and {1}", ActorUtil.GetClothingById(clothes, footwear[0]).GetClothingDescription(), ActorUtil.GetClothingById(clothes, footwear[1]).GetClothingDescription()); } else { if (footwear[0] != 0) { output += String.Format(" and {0}.", ActorUtil.GetClothingById(clothes, footwear[0]).GetClothingDescription()); return(output); } else { output += String.Format(" and {0}.", ActorUtil.GetClothingById(clothes, footwear[0]).GetClothingDescription()); return(output); } } } } return(output); }
protected override async Task OnInit(ActorUtil util) { theScene.Initialized.Enqueue(this.Id); await Task.FromResult(0); }
protected override async Task OnRun(ActorUtil util) { await Task.FromResult(0); var userSettings = settings.UserSettings; var paths = userSettings.TestDirectories; if (paths == null || !paths.Any()) { fileWatcher.AllDirectoriesToWatch.Enqueue(ImmutableList.Create <string>()); } foreach (var path in paths) { try { if (!Directory.Exists(path)) { util.Log.RealTime($"Path not found: {path}"); continue; } if (!watchers.ContainsKey(path)) { var watcher = new FileSystemWatcher(path); foreach (var pattern in settings.UserSettings.TestRootPatterns) { watcher.Filters.Add(pattern); } watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.CreationTime | NotifyFilters.FileName; void enqueue(object sender, FileSystemEventArgs e) { switch (e) { case RenamedEventArgs re: parser.RootSourceFileDetected.Enqueue(re.OldFullPath); parser.RootSourceFileDetected.Enqueue(re.FullPath); break; case FileSystemEventArgs fe: parser.RootSourceFileDetected.Enqueue(fe.FullPath); break; } } watcher.Changed += enqueue; watcher.Created += enqueue; watcher.Deleted += enqueue; watcher.Renamed += enqueue; watcher.EnableRaisingEvents = true; watchers.Add(path, watcher); //Search for the files for the first time: foreach (var pattern in userSettings.TestRootPatterns) { try { var initialRootFiles = Directory.GetFiles(path, pattern); parser.RootSourceFileDetected.EnqueueRange(initialRootFiles); } catch (Exception ex) { util.Log.RealTime($"Failed to process root test pattern {pattern} in directory {path}", ex); } } } } catch (Exception ex) { util.Log.RealTime($"Failed to process root test directory {path}", ex); } } var watcherList = watchers.ToList(); foreach (var watcher in watcherList) { if (!paths.Contains(watcher.Key)) { watchers.Remove(watcher.Key); watcher.Value.Dispose(); } } }
protected async override Task OnRun(ActorUtil util) { System.Globalization.CultureInfo.CurrentCulture.ClearCachedData(); await Task.FromResult(0); }
protected override async Task <IEnumerable <Role> > CastActors(ActorUtil util, Dictionary <int, CTests_AvailableTest> myActors) { var mySourceFile = parent.RootSourceFiles.FirstOrDefault(x => x.FilePath == this.Id); if (mySourceFile.FilePath == null) { this.Dispose(); triggerUpdate(); return(null); } if (sourceFileAtom.Value.ParseTime != mySourceFile.ParseTime) { sourceFileAtom.Value = mySourceFile; triggerUpdate(); } var compileStatusWas = this.CompileStatus; this.compileStatusAtom.Value = step(); if (compileStatusWas != CompileStatus) { triggerUpdate(); } await Task.FromResult(0); return(mySourceFile.Tests.Select(x => new Role { Id = x.TestNumber, })); CompileStatus step() { switch (compileStatusWas) { case CompileStatus.Modified: executableVersionAtom.Value = mySourceFile.ParseTime; var us = settings.UserSettings; try { Directory.CreateDirectory(Path.Combine(Path.GetDirectoryName(mySourceFile.FilePath), "bin")); } catch { } this.ProcHandle?.Cancel(); this.procHandleAtom.Value = null; processReceiptAtom.Value = processRunner.StartProcess(new ProcStartInfo( path: us.CompilerPath, workingDirectory: Path.GetDirectoryName(mySourceFile.FilePath), arguments: us.GetProcessedCompileArguments(mySourceFile.FilePath), maxRunTime: new TimeSpan(0, 0, 10), accept: newHandle => { if (newHandle.Id == processReceiptAtom.Value) { this.procHandleAtom.Value = newHandle; } else { newHandle.Cancel(); } } )); startWait(); return(CompileStatus.WaitingOnProcessStart); case CompileStatus.WaitingOnProcessStart: if (ProcHandle != null) { startWait(); return(CompileStatus.Compiling); } else if (haveWaited(new TimeSpan(0, 0, 5))) { ProcHandle?.Cancel(); return(CompileStatus.TimedOut); } else { return(CompileStatus.WaitingOnProcessStart); } case CompileStatus.Compiling: var ph = this.ProcHandle; if (haveWaited(new TimeSpan(0, 0, 5))) { return(CompileStatus.TimedOut); } else if (ph.Status != ProcessStatus.Finished) { return(CompileStatus.Compiling); } else { var result = ph.Result; lastCompileResultAtom.Value = result; if (result.GracefulExit && result.ExitCode == 0) { return(CompileStatus.Compiled); } else { return(CompileStatus.Failed); } } case CompileStatus.Failed: case CompileStatus.TimedOut: case CompileStatus.Compiled: if (executableVersionAtom.Value != mySourceFile.ParseTime) { return(CompileStatus.Modified); } else { return(compileStatusWas); } default: throw new NotImplementedException(compileStatusWas.ToString("g")); } } void startWait() { lastWaitStarted = util.Now; } bool haveWaited(TimeSpan moreThanThis) { var timeSpentWaiting = util.Now - lastWaitStarted; return(timeSpentWaiting > moreThanThis); } void triggerUpdate() { sendUpdates.Send_UpdateTestsFile(mySourceFile.FilePath ?? ""); } }
protected async override Task OnRun(ActorUtil util) { SelfRan.Enqueue(0); await Task.FromResult(0); }
protected override async Task OnRun(ActorUtil util) { await UpdateAndReturnIfDbIsUp(); }
protected override Task OnRun(ActorUtil util) { return(Task.FromResult(0)); }
protected override Task OnDispose(ActorUtil util) { cTokenSource.Cancel(); return(Task.FromResult(0)); }