private async void StartReceive() { var buffer = new byte[m_PipeStream.InBufferSize]; var cancellationToken = m_ChannelCancelToken.Token; while (!cancellationToken.IsCancellationRequested) { var result = await m_PipeStream.ReadAsync(buffer, 0, buffer.Length, cancellationToken); var processResult = m_PipeLineProcessor.Process(new ArraySegment <byte>(buffer, 0, result)); if (processResult.State == ProcessState.Error) { Debug.Fail("Pipeline processing failed."); break; } else if (processResult.State == ProcessState.Cached) { buffer = new byte[m_PipeStream.InBufferSize]; } if (processResult.Packages != null && processResult.Packages.Count > 0) { foreach (var item in processResult.Packages) { HandlePipePackage(item as PipePackageInfo); } } } }
List <PipelineStepContainer> _pipelineSteps = new List <PipelineStepContainer>(); // Reference to all steps public Pipeline <TPipelineIn, TPipelineOut> AddStepAndStart <TIn, TOut>(IPipelineProcessor <TIn, TOut> processor) { var step = new PipelineStep <TIn, TOut>(processor); int stepIndex = _pipelineSteps.Count; // Alternatively, I can store a list of the Task.Run() handlers here and then run them at a later point // Start the step Task.Run(() => { // Cached next step IBufferable <TOut> nextBuffer = null; foreach (Item <TIn> input in step.Buffer.GetConsumingEnumerable()) { // Give us the most up-to-date status on our current position in the pipeline bool isLastStep = stepIndex == _pipelineSteps.Count - 1; TOut outputValue; // Attempt to process value try { outputValue = processor.Process(input.Value); } catch (Exception e) { input.TaskCompletionSource.SetException(e); continue; } // Move to next step if (isLastStep) { input.TaskCompletionSource.SetResult((TPipelineOut)(object)outputValue); } else { nextBuffer = nextBuffer ?? _pipelineSteps[stepIndex + 1].Value as IBufferable <TOut>; try // In the case of the pipeline closing prematurely, catch the error and throw an exception to the task { nextBuffer.Buffer.Add(new Item <TOut> { Value = outputValue, TaskCompletionSource = input.TaskCompletionSource }); } catch (InvalidOperationException e) { input.TaskCompletionSource.SetException(e); } } } }); _pipelineSteps.Add(new PipelineStepContainer { Value = step, }); return(this); }
private void RunSubPipelines(PipelineContext pipelineContext, Pipeline subPipeline) { ILogger logger = pipelineContext.PipelineBatchContext.Logger; pipelineContext.CurrentPipeline = subPipeline; IPipelineProcessor pipelineProcessor = subPipeline.PipelineProcessor; if (pipelineProcessor == null) { logger.Error("Pipeline will be skipped because it does not have a processor assigned. (pipeline step: {0}, sub-pipeline: {1})", "Iterate and Run Async", (object)subPipeline.Name); } else if (!pipelineProcessor.CanProcess(subPipeline, pipelineContext)) { logger.Error("Pipeline will be skipped because the processor cannot processes the sub-pipeline. (pipeline step: {0}, sub-pipeline: {1}, sub-pipeline processor: {2})", "Iterate and Run Async", (object)subPipeline.Name, (object)pipelineProcessor.GetType().FullName); } else { pipelineProcessor.Process(subPipeline, pipelineContext); if (pipelineContext.CriticalError) { logger.Error("Sub pipeline processing will not abort since it's done async"); } } }
public static PipelineResult ProcessAction <TEvent>(this IPipelineProcessor processor, TEvent @event) where TEvent : IEvent { return(processor.Process(new Payload <TEvent>(@event))); }
/// <summary> /// Process a given payload through the stages in this pipeline using /// the processor in this pipeline. /// </summary> public TPayload Process(TPayload payload) { return(_processor.Process(payload, _stages)); }
/// <summary> /// Executor that implements requesting and rendering grid information to create the grid rows /// </summary> /// <returns></returns> public async Task <bool> ExecuteAsync() { // Get the lat lon boundary from xyz tile request TileBoundaryLL = MapGeo.TileXYZToRectLL(TileX, TileY, TileZ, out var yFlip); _log.LogInformation($"#Tile#.({TileX},{TileY}) Execute Start. DMode:{DisplayMode}, HasLighting:{HasLighting}, Zoom:{TileZ} FlipY:{yFlip}. TileBoundary:{TileBoundaryLL.ToDisplay()}, DataModel:{DataModelUid}"); if (TileZ == 0) // Send back default root tile { MakeRootTile(); return(true); } SiteModel = DIContext.Obtain <ISiteModels>().GetSiteModel(DataModelUid); if (SiteModel == null) { ResultStatus = RequestErrorStatus.NoSuchDataModel; _log.LogError($"Tile.({TileX},{TileY}) Failed to obtain site model for {DataModelUid}"); return(false); } var siteModelExtentWithSurveyedSurfaces = SiteModel.GetAdjustedDataModelSpatialExtents(null); _log.LogDebug($"Tile.({TileX},{TileY}) Site model extents are {siteModelExtentWithSurveyedSurfaces}. TileBoundary:{TileBoundaryLL.ToDisplay()}"); if (!siteModelExtentWithSurveyedSurfaces.IsValidPlanExtent) // No data return empty tile { return(BuildEmptyTile()); } // We will draw all missing data just below lowest elevation for site LowestElevation = (float)siteModelExtentWithSurveyedSurfaces.MinZ - 1F; Initialise(); // setup tile requirements if (TileGridSize == QMConstants.FlatResolutionGridSize) // Too far out to see detail so return empty tile { return(BuildEmptyTile()); } if (DisplayMode == QMConstants.DisplayModeDemo) // development use only { return(BuildDemoTile()); } try { var setupResult = await SetupPipelineTask(siteModelExtentWithSurveyedSurfaces, SiteModel.CellSize); if (!setupResult) { if (ResultStatus != RequestErrorStatus.InvalidCoordinateRange) { _log.LogError($"Tile.({TileX},{TileY}) Unable to setup pipelinetask."); } return(BuildEmptyTile()); } processor.Process(); if (GriddedElevationsResponse.ResultStatus != RequestErrorStatus.OK) { _log.LogError($"Tile.({TileX},{TileY}) Unable to obtain data for gridded data. GriddedElevationRequestResponse: {GriddedElevationsResponse.ResultStatus.ToString()}"); return(BuildEmptyTile()); } ElevData.HasData = !float.IsPositiveInfinity(task.MinElevation); // check for data // Developer Debugging Only if (ElevData.HasData) { OutputDebugTile("Raw"); } if (!ElevData.HasData) { return(BuildEmptyTile()); } _log.LogInformation($"#Tile#.({TileX},{TileY}) Data successfully sampled. GridSize:{TileGridSize} Min:{task.MinElevation}, Max:{task.MaxElevation} FirstElev:{GriddedElevDataArray[0, 0].Elevation}, LastElev:{GriddedElevDataArray[TileGridSize - 1, TileGridSize - 1].Elevation}"); ElevData.HasLighting = HasLighting; // Transform gridded data into a format the mesh builder can use ConvertGridToDEM(task.MinElevation, task.MaxElevation); // Build a quantized mesh from sampled elevations QMTileBuilder tileBuilder = new QMTileBuilder() { TileData = ElevData, GridSize = TileGridSize }; _log.LogInformation($"Tile.({TileX},{TileY}) BuildQuantizedMeshTile. GridSize:{TileGridSize} Min:{ElevData.MinimumHeight}, Max:{ElevData.MaximumHeight}"); if (!tileBuilder.BuildQuantizedMeshTile()) { _log.LogError($"Tile.({TileX},{TileY}) BuildQuantizedMeshTile returned false with error code: {tileBuilder.BuildTileFaultCode}"); return(false); } QMTileResponse.data = tileBuilder.QuantizedMeshTile; // Make tile from mesh ResultStatus = RequestErrorStatus.OK; QMTileResponse.ResultStatus = ResultStatus; _log.LogDebug($"#Tile#.({TileX},{TileY}) Execute End. Returning production tile. CesiumY:{yFlip}, Zoom:{TileZ}, GridSize:{TileGridSize}"); return(true); } catch (Exception ex) { _log.LogError(ex, $"#Tile#.({TileX},{TileY}). Exception building QuantizedMesh tile: "); return(false); } }
/// <summary> /// Perform rendering activities to produce a bitmap tile /// </summary> public RequestErrorStatus PerformRender(DisplayMode mode, IPipelineProcessor processor, IPlanViewPalette colourPalette, IFilterSet filters, ILiftParameters liftParams) { // Obtain the display responsible for rendering the thematic information for this mode Displayer = PVMDisplayerFactory.GetDisplayer(mode /*, FICOptions*/); if (Displayer == null) { processor.Response.ResultStatus = RequestErrorStatus.UnsupportedDisplayType; return(processor.Response.ResultStatus); } // Create and assign the colour palette logic for this mode to the displayer if (colourPalette == null) { if (mode == DisplayMode.CCA || mode == DisplayMode.CCASummary) { Displayer.SetPalette(Utilities.ComputeCCAPalette(processor.SiteModel, filters.Filters[0].AttributeFilter, mode)); if (Displayer.GetPalette() == null) { processor.Response.ResultStatus = RequestErrorStatus.FailedToGetCCAMinimumPassesValue; return(processor.Response.ResultStatus); } } else { Displayer.SetPalette(PVMPaletteFactory.GetPalette(processor.SiteModel, mode, processor.SpatialExtents)); } } else { Displayer.SetPalette(colourPalette); } // Create the world coordinate display surface the displayer will render onto Displayer.MapView = new MapSurface { SquareAspect = IsWhollyInTermsOfGridProjection }; var view = Displayer.MapView; // Set the world coordinate bounds of the display surface to be rendered on view.SetBounds(NPixelsX, NPixelsY); if (IsWhollyInTermsOfGridProjection) { view.FitAndSetWorldBounds(OriginX, OriginY, OriginX + Width, OriginY + Height, 0); } else { view.SetWorldBounds(OriginX, OriginY, OriginX + Width, OriginY + Height, 0); } // Provide data smoothing support to the displayer for the rendering operation being performed ((IProductionPVMConsistentDisplayer)Displayer).DataSmoother = DIContext.Obtain <Func <DisplayMode, IDataSmoother> >()(mode); // Set the rotation of the displayer rendering surface to match the tile rotation due to the project calibration rotation view.SetRotation(TileRotation); ConstructPVMTaskAccumulator(processor); // Displayer.ICOptions = ICOptions; // Set the skip-step area control cell selection parameters for this tile render. Note that the floating point // skip step algorithm is requested, and a user origin is configured that offsets the sampling grid by half a pixel // size to matching the skip-stepping the PVM accumulator will use when transcribing cell data from sub grids into // the accumulator. Note that the area control set is not configured with a rotation - this is taken into account // through the mapview rotation configured above processor.Pipeline.AreaControlSet = new AreaControlSet(false, view.XPixelSize, view.YPixelSize, view.XPixelSize / 2.0, view.YPixelSize / 2.0, 0.0); processor.Pipeline.LiftParams = liftParams; // todo PipeLine.NoChangeVolumeTolerance = FICOptions.NoChangeVolumeTolerance; // Perform the sub grid query and processing to render the tile var pipelineProcessorStopWatch = Stopwatch.StartNew(); processor.Process(); _log.LogInformation($"Pipeline processor completed in {pipelineProcessorStopWatch.Elapsed}"); if (processor.Response.ResultStatus == RequestErrorStatus.OK) { // Render the collection of data in the aggregator var consistentRenderStopWatch = Stopwatch.StartNew(); (Displayer as IProductionPVMConsistentDisplayer)?.PerformConsistentRender(); _log.LogInformation($"Consistent render complated in {consistentRenderStopWatch.Elapsed}"); PerformAnyRequiredDebugLevelDisplay(); if (DebugDrawDiagonalCrossOnRenderedTilesDefault) { // Draw diagonal cross and top left corner indicators view.DrawLine(view.OriginX, view.OriginY, view.LimitX, view.LimitY, Color.Red); view.DrawLine(view.OriginX, view.LimitY, view.LimitX, view.OriginY, Color.Red); // Draw the horizontal line a little below the world coordinate 'top' of the tile to encourage the line // drawing algorithm not to clip it view.DrawLine(view.OriginX, view.LimitY, view.OriginX, view.CenterY, Color.Red); view.DrawLine(view.OriginX, view.LimitY - 0.01, view.CenterX, view.LimitY - 0.01, Color.Red); } } return(processor.Response.ResultStatus); }