Example #1
0
        private void ConfigurePipeline(SubGridPipelineAggregative <SubGridsRequestArgument, SimpleVolumesResponse> PipeLine)
        {
            //PipeLine.TimeToLiveSeconds := VLPDSvcLocations.VLPDPSNode_VolumePipelineTTLSeconds;
            PipeLine.RequestDescriptor = RequestDescriptor;
            //PipeLine.ExternalDescriptor := FExternalDescriptor;

            PipeLine.DataModelID = SiteModel.ID;

            Log.LogDebug($"Volume calculation extents for DM={SiteModel.ID}, Request={RequestDescriptor}: {Extents}");

            PipeLine.OverallExistenceMap     = OverallExistenceMap;
            PipeLine.ProdDataExistenceMap    = ProdDataExistenceMap;
            PipeLine.DesignSubGridOverlayMap = DesignSubgridOverlayMap;

            // Initialise a request analyzer to provide to the pipeline
            PipeLine.RequestAnalyser          = DIContext.Obtain <IRequestAnalyser>();
            PipeLine.RequestAnalyser.Pipeline = PipeLine;
            PipeLine.RequestAnalyser.WorldExtents.Assign(Extents);

            PipeLine.LiftParams = LiftParams;

            // Construct and assign the filter set into the pipeline
            IFilterSet FilterSet = FilterUtilities.ConstructFilters(new FilterSet(BaseFilter, TopFilter), VolumeType);

            if (FilterSet.Filters.Length == 3)
            {
                PipeLine.SubGridsRequestComputeStyle = SubGridsRequestComputeStyle.SimpleVolumeThreeWayCoalescing;
            }
            PipeLine.FilterSet    = FilterSet;
            PipeLine.GridDataType = GridDataType.Height;

            if (FilteredTopSurveyedSurfaces.Count > 0 || FilteredBaseSurveyedSurfaces.Count > 0)
            {
                PipeLine.IncludeSurveyedSurfaceInformation = true;
            }
        }
Example #2
0
        public RequestErrorStatus ExecutePipeline()
        {
            SubGridPipelineAggregative <SubGridsRequestArgument, SimpleVolumesResponse> PipeLine;

            var Result = RequestErrorStatus.Unknown;

            var PipelineAborted = false;

            // bool ShouldAbortDueToCompletedEventSet  = false;

            try
            {
                ProdDataExistenceMap = SiteModel.ExistenceMap;

                try
                {
                    if (ActiveDesign != null && (VolumeType == VolumeComputationType.BetweenFilterAndDesign || VolumeType == VolumeComputationType.BetweenDesignAndFilter))
                    {
                        if (ActiveDesign == null || ActiveDesign.Design.DesignDescriptor.IsNull)
                        {
                            Log.LogError($"No design provided to prod data/design volumes calc for datamodel {SiteModel.ID}");
                            return(RequestErrorStatus.NoDesignProvided);
                        }

                        DesignSubgridOverlayMap = GetExistenceMaps().GetSingleExistenceMap(SiteModel.ID, ExistenceMaps.Interfaces.Consts.EXISTENCE_MAP_DESIGN_DESCRIPTOR, ActiveDesign.Design.ID);

                        if (DesignSubgridOverlayMap == null)
                        {
                            return(RequestErrorStatus.NoDesignProvided);
                        }
                    }

                    OverallExistenceMap = new SubGridTreeSubGridExistenceBitMask();

                    // Work out the surveyed surfaces and coverage areas that need to be taken into account

                    var SurveyedSurfaces = SiteModel.SurveyedSurfaces;

                    if (SurveyedSurfaces != null)
                    {
                        // See if we need to handle surveyed surface data for 'base'
                        // Filter out any surveyed surfaces which don't match current filter (if any) - realistically, this is time filters we're thinking of here
                        if (VolumeType == VolumeComputationType.Between2Filters || VolumeType == VolumeComputationType.BetweenFilterAndDesign)
                        {
                            if (!SurveyedSurfaces.ProcessSurveyedSurfacesForFilter(SiteModel.ID, BaseFilter, FilteredTopSurveyedSurfaces, FilteredBaseSurveyedSurfaces, OverallExistenceMap))
                            {
                                return(RequestErrorStatus.Unknown);
                            }
                        }

                        // See if we need to handle surveyed surface data for 'top'
                        // Filter out any surveyed surfaces which don't match current filter (if any) - realistically, this is time filters we're thinking of here
                        if (VolumeType == VolumeComputationType.Between2Filters || VolumeType == VolumeComputationType.BetweenDesignAndFilter)
                        {
                            if (!SurveyedSurfaces.ProcessSurveyedSurfacesForFilter(SiteModel.ID, TopFilter, FilteredBaseSurveyedSurfaces, FilteredTopSurveyedSurfaces, OverallExistenceMap))
                            {
                                return(RequestErrorStatus.Unknown);
                            }
                        }
                    }

                    // Add in the production data existence map to the computed surveyed surfaces existence maps
                    OverallExistenceMap.SetOp_OR(ProdDataExistenceMap);

                    // If necessary, impose spatial constraints from filter design(s)
                    if (VolumeType == VolumeComputationType.Between2Filters || VolumeType == VolumeComputationType.BetweenFilterAndDesign)
                    {
                        if (!DesignFilterUtilities.ProcessDesignElevationsForFilter(SiteModel, BaseFilter, OverallExistenceMap))
                        {
                            return(RequestErrorStatus.Unknown);
                        }
                    }

                    if (VolumeType == VolumeComputationType.Between2Filters || VolumeType == VolumeComputationType.BetweenDesignAndFilter)
                    {
                        if (!DesignFilterUtilities.ProcessDesignElevationsForFilter(SiteModel, TopFilter, OverallExistenceMap))
                        {
                            return(RequestErrorStatus.Unknown);
                        }
                    }

                    var PipelinedTask = new VolumesComputationTask
                    {
                        Aggregator = Aggregator
                    };

                    try
                    {
                        PipeLine = new SubGridPipelineAggregative <SubGridsRequestArgument, SimpleVolumesResponse>(/*0, */ PipelinedTask);
                        PipelinedTask.PipeLine = PipeLine;

                        ConfigurePipeline(PipeLine);

                        if (PipeLine.Initiate())
                        {
                            var completionResult = PipeLine.WaitForCompletion();
                            Log.LogInformation(completionResult ? "WaitForCompletion successful" : $"WaitForCompletion timed out with {PipeLine.SubGridsRemainingToProcess} sub grids remaining to be processed");

                            if (PipeLine.SubGridsRemainingToProcess > 0)
                            {
                                Log.LogInformation($"Pipeline completed with {PipeLine.SubGridsRemainingToProcess} sub grids remaining to be processed");
                            }
                        }

                        /*
                         * while not FPipeLine.AllFinished and not FPipeLine.PipelineAborted do
                         * begin
                         *  WaitResult := FPipeLine.CompleteEvent.WaitFor(5000);
                         *
                         *  if VLPDSvcLocations.Debug_EmitSubgridPipelineProgressLogging then
                         *    begin
                         *      if ((FEpochCount > 0) or (FPipeLine.SubmissionNode.TotalNumberOfSubgridsScanned > 0)) and
                         *         ((FPipeLine.OperationNode.NumPendingResultsReceived > 0) or (FPipeLine.OperationNode.OustandingSubgridsToOperateOn > 0)) then
                         *        SIGLogMessage.PublishNoODS(Self, Format('%s: Pipeline (request %d, model %d): #Progress# - Scanned = %d, Submitted = %d, Processed = %d (with %d pending and %d results outstanding)',
                         *                                                [Self.ClassName,
                         *                                                 FRequestDescriptor, FPipeline.ProjectUid,
                         *                                                 FPipeLine.SubmissionNode.TotalNumberOfSubgridsScanned,
                         *                                                 FPipeLine.SubmissionNode.TotalSumbittedSubgridRequests,
                         *                                                 FPipeLine.OperationNode.TotalOperatedOnSubgrids,
                         *                                                 FPipeLine.OperationNode.NumPendingResultsReceived,
                         *                                                 FPipeLine.OperationNode.OustandingSubgridsToOperateOn]), slmcDebug);
                         *    end;
                         *
                         *  if (WaitResult = wrSignaled) and not FPipeLine.AllFinished and not FPipeLine.PipelineAborted and not FPipeLine.Terminated then
                         *    begin
                         *      if ShouldAbortDueToCompletedEventSet then
                         *        begin
                         *          if (FPipeLine.OperationNode.NumPendingResultsReceived > 0) or (FPipeLine.OperationNode.OustandingSubgridsToOperateOn > 0) then
                         *            SIGLogMessage.PublishNoODS(Self, Format('%s: Pipeline (request %d, model %d) being aborted as it''s completed event has remained set but still has work to do (%d outstanding subgrids, %d pending results to process) over a sleep epoch',
                         *                                                  [Self.ClassName,
                         *                                                   FRequestDescriptor, FPipeline.ProjectUid,
                         *                                                   FPipeLine.OperationNode.OustandingSubgridsToOperateOn,
                         *                                                   FPipeLine.OperationNode.NumPendingResultsReceived]), slmcError);
                         *          FPipeLine.Abort;
                         *          ASNodeImplInstance.AsyncResponder.ASNodeResponseProcessor.PerformTaskCancellation(FPipelinedTask);
                         *          Exit;
                         *        end
                         *      else
                         *        begin
                         *          if (FPipeLine.OperationNode.NumPendingResultsReceived > 0) or (FPipeLine.OperationNode.OustandingSubgridsToOperateOn > 0) then
                         *            SIGLogMessage.PublishNoODS(Self, Format('%s: Pipeline (request %d, model %d) has it''s completed event set but still has work to do (%d outstanding subgrids, %d pending results to process)',
                         *                                                  [Self.ClassName,
                         *                                                   FRequestDescriptor, FPipeline.ProjectUid,
                         *                                                   FPipeLine.OperationNode.OustandingSubgridsToOperateOn,
                         *                                                   FPipeLine.OperationNode.NumPendingResultsReceived]), slmcDebug);
                         *          Sleep(500);
                         *          ShouldAbortDueToCompletedEventSet := True;
                         *        end;
                         *    end;
                         *
                         *  if FPipeLine.TimeToLiveExpired then
                         *    begin
                         *      FAbortedDueToTimeout := True;
                         *      FPipeLine.Abort;
                         *      ASNodeImplInstance.AsyncResponder.ASNodeResponseProcessor.PerformTaskCancellation(FPipelinedTask);
                         *
                         *      // The pipeline has exceed its allotted time to complete. It will now
                         *      // be aborted and this request will be failed.
                         *      SIGLogMessage.PublishNoODS(Self, Format('%s: Pipeline (request %d) aborted due to time to live expiration (%d seconds)',
                         *                                              [Self.ClassName, FRequestDescriptor, FPipeLine.TimeToLiveSeconds]), slmcError);
                         *      Exit;
                         *    end;
                         */

                        PipelineAborted = PipeLine.Aborted;

                        if (!PipeLine.Terminated && !PipeLine.Aborted)
                        {
                            Result = RequestErrorStatus.OK;
                        }
                    }
                    finally
                    {
                        if (AbortedDueToTimeout)
                        {
                            Result = RequestErrorStatus.AbortedDueToPipelineTimeout;
                        }
                        else
                        if (PipelinedTask.IsCancelled || PipelineAborted)
                        {
                            Result = RequestErrorStatus.RequestHasBeenCancelled;
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.LogError(e, "ExecutePipeline raised exception");
                }

                return(Result);
            }
            catch (Exception e)
            {
                Log.LogError(e, "Exception");
            }

            return(RequestErrorStatus.Unknown);
        }