コード例 #1
0
        public void Test_ClientLeafSubGridFactoryTests_ReturnClientGrids2()
        {
            var factory = new ClientLeafSubGridFactory();

            factory.RegisterClientLeafSubGridType(GridDataType.Height, () => new ClientHeightLeafSubGrid());

            IClientLeafSubGrid[][] newClients = new[]
            {
                new[] { factory.GetSubGrid(GridDataType.Height), factory.GetSubGrid(GridDataType.Height) },
                new[] { factory.GetSubGrid(GridDataType.Height), factory.GetSubGrid(GridDataType.Height) }
            };

            factory.ReturnClientSubGrids(newClients, newClients.Length);

            Assert.True(null == newClients[0][0], "Factory did not accept first/first sub grid back");
            Assert.True(null == newClients[0][1], "Factory did not accept first/second sub grid back");

            Assert.True(null == newClients[1][0], "Factory did not accept second/first sub grid back");
            Assert.True(null == newClients[1][1], "Factory did not accept second/second sub grid back");

            Assert.Throws <ArgumentException>(() => factory.ReturnClientSubGrids(newClients, 10));

            // Attempt repatriating it twice - nothing should happen
            factory.ReturnClientSubGrids(newClients, newClients.Length);
        }
コード例 #2
0
        public void Test_ClientLeafSubGridFactoryTests_RegisterClientLeafSubGridType_FailWithInvalidDataType()
        {
            var factory = new ClientLeafSubGridFactory();

            Action act = () => factory.RegisterClientLeafSubGridType((GridDataType)100, () => new ClientHeightLeafSubGrid());

            act.Should().Throw <ArgumentException>().WithMessage("Unknown grid data type in RegisterClientLeafSubGridType*");
        }
コード例 #3
0
        public void Test_ClientLeafSubGridFactoryTests_GetSubGrid()
        {
            var factory = new ClientLeafSubGridFactory();

            factory.RegisterClientLeafSubGridType(GridDataType.Height, () => new ClientHeightLeafSubGrid());

            var newClient = factory.GetSubGrid(GridDataType.Height);

            Assert.NotNull(newClient);
            Assert.True(newClient is ClientHeightLeafSubGrid, "Returned sub grid unexpected type");
        }
コード例 #4
0
        public void Test_SubGridClientLeafFactory_Creation()
        {
            IClientLeafSubGridFactory factory = new ClientLeafSubGridFactory();

            Assert.NotNull(factory);

            IClientLeafSubGrid HeightLeaf = factory.GetSubGrid(Types.GridDataType.Height);

            Assert.NotNull(factory);

            IClientLeafSubGrid HeightAndTimeLeaf = factory.GetSubGrid(Types.GridDataType.HeightAndTime);

            Assert.NotNull(factory);
        }
コード例 #5
0
        public void Test_ClientLeafSubGridFactoryTests_ReturnClientGrid()
        {
            var factory = new ClientLeafSubGridFactory();

            factory.RegisterClientLeafSubGridType(GridDataType.Height, () => new ClientHeightLeafSubGrid());

            var newClient = factory.GetSubGrid(GridDataType.Height);

            factory.ReturnClientSubGrid(ref newClient);

            Assert.True(null == newClient, "Factory did not accept sub grid back");

            // Attempt repatriating it twice - nothing should happen
            factory.ReturnClientSubGrid(ref newClient);
        }
コード例 #6
0
        public void Test_ClientLeafSubGridFactoryTests_GetSubGridEx()
        {
            var factory = new ClientLeafSubGridFactory();

            factory.RegisterClientLeafSubGridType(GridDataType.Height, () => new ClientHeightLeafSubGrid());

            var newClient = factory.GetSubGridEx(GridDataType.Height, 1.0, SubGridTreeConsts.SubGridTreeLevels, 123456, 234567);

            Assert.NotNull(newClient);
            Assert.True(newClient is ClientHeightLeafSubGrid, "Returned sub grid unexpected type");

            newClient.CellSize.Should().Be(1.0);
            newClient.Level.Should().Be(SubGridTreeConsts.SubGridTreeLevels);
            newClient.OriginX.Should().Be(123456);
            newClient.OriginY.Should().Be(234567);
        }
コード例 #7
0
        public void Test_SubGridClientLeafFactory_Recycling()
        {
            IClientLeafSubGridFactory factory = new ClientLeafSubGridFactory();

            Assert.NotNull(factory);

            IClientLeafSubGrid HeightLeaf = factory.GetSubGrid(Types.GridDataType.Height);

            factory.ReturnClientSubGrid(ref HeightLeaf);

            Assert.Null(HeightLeaf);

            IClientLeafSubGrid HeightAndTimeLeaf = factory.GetSubGrid(Types.GridDataType.HeightAndTime);

            factory.ReturnClientSubGrid(ref HeightAndTimeLeaf);

            Assert.Null(HeightAndTimeLeaf);
        }
コード例 #8
0
        public void Test_ClientLeafSubGridFactoryTests_Creation()
        {
            var factory = new ClientLeafSubGridFactory();

            Assert.NotNull(factory);
        }
コード例 #9
0
        /// <summary>
        /// Responsible for coordinating the retrieval of production data for a sub grid from a site model and also annotating it with
        /// surveyed surface information for requests involving height data.
        /// </summary>
        public (ServerRequestResult requestResult, IClientLeafSubGrid clientGrid) RequestSubGridInternal(
            SubGridCellAddress subGridAddress,
            bool prodDataRequested,
            bool surveyedSurfaceDataRequested)
        {
            (ServerRequestResult requestResult, IClientLeafSubGrid clientGrid)result = (ServerRequestResult.UnknownError, null);

            if (!(prodDataRequested || surveyedSurfaceDataRequested))
            {
                result.requestResult = ServerRequestResult.MissingInputParameters;
                return(result);
            }

            _prodDataRequested            = prodDataRequested;
            _surveyedSurfaceDataRequested = surveyedSurfaceDataRequested;

            // if <config>.Debug_ExtremeLogSwitchB then Log.LogDebug("About to call RetrieveSubGrid()");

            result.clientGrid = ClientLeafSubGridFactory.GetSubGridEx(
                Utilities.IntermediaryICGridDataTypeForDataType(_gridDataType, subGridAddress.SurveyedSurfaceDataRequested),
                _siteModel.CellSize, SubGridTreeConsts.SubGridTreeLevels,
                subGridAddress.X & ~SubGridTreeConsts.SubGridLocalKeyMask,
                subGridAddress.Y & ~SubGridTreeConsts.SubGridLocalKeyMask);

            _clientGrid = result.clientGrid;

            if (ShouldInitialiseFilterContext() && !InitialiseFilterContext())
            {
                result.requestResult = ServerRequestResult.FilterInitialisationFailure;
                ClientLeafSubGridFactory.ReturnClientSubGrid(ref _clientGrid);
                return(result);
            }

            _haveComputedSpatialFilterMaskAndClientProdDataMap = false;

            if (_prodDataRequested)
            {
                if (_isTraceLoggingEnabled)
                {
                    _log.LogTrace("Performing data extraction");
                }

                if ((result.requestResult = PerformDataExtraction()) != ServerRequestResult.NoError)
                {
                    ClientLeafSubGridFactory.ReturnClientSubGrid(ref _clientGrid);
                    return(result);
                }
            }

            if (_surveyedSurfaceDataRequested)
            {
                if (_isTraceLoggingEnabled)
                {
                    _log.LogTrace("Performing height annotation");
                }

                if ((result.requestResult = PerformHeightAnnotation()) != ServerRequestResult.NoError)
                {
                    ClientLeafSubGridFactory.ReturnClientSubGrid(ref _clientGrid);
                    return(result);
                }
            }

            // Reassign _clientGrid to result as its reference may have been changed as a result of caching.
            result.clientGrid = _clientGrid;

            return(result);
        }
コード例 #10
0
        /// <summary>
        /// Annotates height information with elevations from surveyed surfaces
        /// </summary>
        private ServerRequestResult PerformHeightAnnotation()
        {
            if (!_haveComputedSpatialFilterMaskAndClientProdDataMap)
            {
                // At this point, the prod data map will be empty. Fill it here so the filter has something to filter against...
                _clientGrid.ProdDataMap.Fill();
            }

            if (!_haveComputedSpatialFilterMaskAndClientProdDataMap && (ComputeSpatialFilterMaskAndClientProdDataMap() != ServerRequestResult.NoError))
            {
                ClientLeafSubGridFactory.ReturnClientSubGrid(ref _clientGrid);
                return(ServerRequestResult.FilterInitialisationFailure);
            }

            if ((_filteredSurveyedSurfaces?.Count ?? 0) == 0)
            {
                return(ServerRequestResult.NoError);
            }

            var result = ServerRequestResult.NoError;

            // TODO: Add Debug_SwitchOffCompositeSurfaceGenerationFromSurveyedSurfaces to configuration
            // if <config>.Debug_SwitchOffCompositeSurfaceGenerationFromSurveyedSurfaces then Exit;

            if (!_clientGrid.UpdateProcessingMapForSurveyedSurfaces(_processingMap, _filteredSurveyedSurfaces as IList, _returnEarliestFilteredCellPass))
            {
                return(ServerRequestResult.NoError);
            }

            if (_processingMap.IsEmpty())
            {
                return(result);
            }

            try
            {
                // Hand client grid details, a mask of cells we need surveyed surface elevations for, and a temp grid to the Design Profiler

                // Instantiate an argument object for the surface elevation patch request. We always want to request all surface elevations to
                // promote cacheability.
                var surfaceElevationPatchArg = new SurfaceElevationPatchArgument
                {
                    SiteModelID              = _siteModel.ID,
                    OTGCellBottomLeftX       = _clientGrid.OriginX,
                    OTGCellBottomLeftY       = _clientGrid.OriginY,
                    CellSize                 = _siteModel.CellSize,
                    IncludedSurveyedSurfaces = _filteredSurveyedSurfacesAsGuidArray,
                    SurveyedSurfacePatchType = _surveyedSurfacePatchType,
                    ProcessingMap            = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Filled)
                };

                if (!(_surfaceElevationPatchRequest.Execute(surfaceElevationPatchArg) is ClientHeightAndTimeLeafSubGrid surfaceElevations))
                {
                    return(result);
                }

                // Construct the elevation range filter lambda
                Func <int, int, float, bool> elevationRangeFilterLambda = null;
                if (_filter.AttributeFilter.HasElevationRangeFilter)
                {
                    elevationRangeFilterLambda = ApplyElevationRangeFilter;
                }

                if (!_clientGrid.PerformHeightAnnotation(_processingMap, _filteredSurveyedSurfaces as IList, _returnEarliestFilteredCellPass, surfaceElevations, elevationRangeFilterLambda))
                {
                    return(ServerRequestResult.SubGridHeightAnnotationFailed);
                }

                result = ServerRequestResult.NoError;
            }
            finally
            {
                // TODO: Use client sub grid pool...
                //    PSNodeImplInstance.RequestProcessor.RepatriateClientGrid(TICSubGridTreeLeafSubGridBase(SurfaceElevations));
            }

            return(result);
        }
コード例 #11
0
        /// <summary>
        /// // Note: There is an assumption you have already checked on a existence map that there is a sub grid for this address
        /// </summary>
        private ServerRequestResult PerformDataExtraction()
        {
            // If there is a cache context for this sub grid, but the sub grid does not support assignation then complain
            var assignationSupported = ClientLeafSubGrid.SupportsAssignationFromCachedPreProcessedClientSubGrid[(int)_clientGrid.GridDataType];

            var subGridCacheContext = _subGridCacheContexts?.FirstOrDefault(x => x.GridDataType == _clientGrid.GridDataType);

            if (subGridCacheContext != null && !assignationSupported)
            {
                throw new TRexException($"Client sub grid of type {_clientGrid.GridDataType} does not support assignation from cached sub grids but has a cache context enabled for it.");
            }

            if (subGridCacheContext != null && assignationSupported)
            {
                if (subGridCacheContext != null && _clientGrid.GridDataType != subGridCacheContext.GridDataType)
                {
                    _log.LogWarning($"Client grid data type {_clientGrid.GridDataType} does not match type of sub grid cache context {subGridCacheContext.GridDataType}");
                }

                // Determine if there is a suitable pre-calculated result present in the general sub grid result cache.
                // If there is, then apply the filter mask to the cached data and copy it to the client grid
                var cachedSubGrid = (IClientLeafSubGrid)_subGridCache?.Get(subGridCacheContext, _clientGrid.CacheOriginX, _clientGrid.CacheOriginY);

                // If there was a cached sub grid located, assign its contents according the client grid mask into the client grid and return it
                if (cachedSubGrid != null)
                {
                    // Log.LogInformation($"Acquired sub grid {CachedSubGrid.Moniker()} for client sub grid {ClientGrid.Moniker()} in data model {SiteModel.ID} from result cache");

                    // Check the cache supplied a tpe of sub grid we can use. If not (due to an issue), ignore the returned item and request the result directly
                    if (_clientGrid.SupportsAssignationFrom(cachedSubGrid.GridDataType))
                    {
                        _clientGrid.ProdDataMap.Assign(cachedSubGrid.ProdDataMap);
                        var innerResult = ComputeSpatialFilterMaskAndClientProdDataMap();
                        if (innerResult != ServerRequestResult.NoError)
                        {
                            return(innerResult);
                        }

                        // Use the filter mask to copy the relevant cells from the cache to the client sub grid
                        _clientGrid.AssignFromCachedPreProcessedClientSubGrid(cachedSubGrid, _clientGrid.FilterMap);

                        return(ServerRequestResult.NoError);
                    }

                    _log.LogError($"Sub grid retrieved from cache is not valid for assigning into client grid. Ignoring. Client sub grid = {_clientGrid.Moniker()}/{_clientGrid.GridDataType}. Cache sub grid = {cachedSubGrid.Moniker()}/{cachedSubGrid.GridDataType}");
                }
            }

            var result = _retriever.RetrieveSubGrid(_clientGrid, CellOverrideMask, out var sieveFilterInUse, ComputeSpatialFilterMaskAndClientProdDataMap);

            // If a sub grid was retrieved and this is a supported data type in the cache then add it to the cache
            // If the sub grid does not support assignation from a precomputed sub grid then just return the result with
            // no reference to the cache.
            if (result == ServerRequestResult.NoError && assignationSupported)
            {
                // Determine if this sub grid is suitable for storage in the cache
                // Don't add sub grids computed using a non-trivial WMS sieve to the general sub grid cache
                var shouldBeCached = subGridCacheContext != null && !sieveFilterInUse && (_clientGrid.GridDataType == subGridCacheContext.GridDataType);

                var subGridInvalidationVersion = shouldBeCached ? subGridCacheContext.InvalidationVersion : 0;

                var clientGrid2 = ClientLeafSubGridFactory.GetSubGrid(_clientGrid.GridDataType);
                clientGrid2.Assign(_clientGrid);
                clientGrid2.AssignFromCachedPreProcessedClientSubGrid(_clientGrid, _clientGrid.FilterMap);

                if (shouldBeCached)
                {
                    //Log.LogInformation($"Adding sub grid {ClientGrid.Moniker()} in data model {SiteModel.ID} to result cache");

                    // Add the newly computed client sub grid to the cache by creating a clone of the client and adding it...
                    if (_subGridCache.Add(subGridCacheContext, _clientGrid, subGridInvalidationVersion) != CacheContextAdditionResult.Added)
                    {
                        _log.LogWarning($"Failed to add sub grid {clientGrid2.Moniker()}, data model {_siteModel.ID} to sub grid result cache context [FingerPrint:{subGridCacheContext.FingerPrint}], returning sub grid to factory as not added to cache");
                        ClientLeafSubGridFactory.ReturnClientSubGrid(ref _clientGrid);
                    }
                }

                _clientGrid = clientGrid2;
            }

            //if <config>.Debug_ExtremeLogSwitchB then  SIGLogMessage.PublishNoODS(Nil, 'Completed call to RetrieveSubGrid()');

            return(result);
        }