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); }
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*"); }
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"); }
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); }
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); }
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); }
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); }
public void Test_ClientLeafSubGridFactoryTests_Creation() { var factory = new ClientLeafSubGridFactory(); Assert.NotNull(factory); }
/// <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); }
/// <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); }
/// <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); }