예제 #1
0
 private void DoSomethingWithAddressAsStruct(SubGridCellAddress address)
 {
     if (address.X == 123456 || address.Y == 45678)
     {
         Console.WriteLine("Ooops!");
     }
 }
예제 #2
0
 public static string GetLeafSubGridFullFileName(SubGridCellAddress cellAddress)
 {
     // Work out the cell address of the origin cell in the appropriate leaf
     // sub grid. We use this cell position to derive the name of the file
     // containing the leaf sub grid data
     return(ServerSubGridTreeLeaf.FileNameFromOriginPosition(new SubGridCellAddress(cellAddress.X & ~SubGridTreeConsts.SubGridLocalKeyMask, cellAddress.Y & ~SubGridTreeConsts.SubGridLocalKeyMask)));
 }
예제 #3
0
        /// <summary>
        /// Calculates a filter mask for a designated sub grid on this design
        /// </summary>
        public (SubGridTreeBitmapSubGridBits filterMask, DesignProfilerRequestResult errorCode) GetFilterMaskViaLocalCompute(
            ISiteModelBase siteModel,
            SubGridCellAddress originCellAddress,
            double cellSize)
        {
            // Calculate an elevation patch for the requested location and convert it into a bitmask detailing which cells have non-null values
            var patch = _designElevationCalculator.Execute(siteModel, new DesignOffset(DesignDescriptor.DesignID, 0),
                                                           cellSize, originCellAddress.X, originCellAddress.Y, out var calcResult);

            if (patch == null)
            {
                _log.LogWarning($"Request for design elevation patch that does not exist: Project: {siteModel.ID}, design {DesignDescriptor.DesignID}, location {originCellAddress.X}:{originCellAddress.Y}, calcResult: {calcResult}");
                return(null, calcResult); // Requestors should not ask for sub grids that don't exist in the design.
            }

            var mask       = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled);
            var patchCells = patch.Cells;

            for (byte i = 0; i < SubGridTreeConsts.SubGridTreeDimension; i++)
            {
                for (byte j = 0; j < SubGridTreeConsts.SubGridTreeDimension; j++)
                {
                    if (patchCells[i, j].Equals(Common.Consts.NullHeight))
                    {
                        mask[i, j] = true;
                    }
                }
            }

            return(mask, calcResult);
        }
예제 #4
0
        public void Test_SubgridCellAddress_ToNormalisedInt64()
        {
            SubGridCellAddress ca = new SubGridCellAddress(1, 1);

            long correct = (1L << 32) | 1;

            Assert.Equal(ca.ToNormalisedInt64, correct);
        }
예제 #5
0
        /// <summary>
        /// Cleaves all dirty segments requiring cleaving within the given sub grid
        /// </summary>
        public void PerformSegmentCleaving(IStorageProxy storageProxyForSubGridSegments, IServerLeafSubGrid subGrid, int subGridSegmentPassCountLimit = 0)
        {
            var iterator = new SubGridSegmentIterator(subGrid, storageProxyForSubGridSegments)
            {
                IterationDirection = IterationDirection.Forwards,
                ReturnDirtyOnly    = true,
                RetrieveAllPasses  = true
            };

            var origin = new SubGridCellAddress(subGrid.OriginX, subGrid.OriginY);

            if (!iterator.MoveToFirstSubGridSegment())
            {
                return;
            }

            do
            {
                var segment = iterator.CurrentSubGridSegment;

                var cleavedTimeRangeStart = segment.SegmentInfo.StartTime;
                var cleavedTimeRangeEnd   = segment.SegmentInfo.EndTime;

                if (!segment.RequiresCleaving(out var totalPassCount, out var maximumPassCount))
                {
                    continue;
                }

                if (subGrid.Cells.CleaveSegment(segment, NewSegmentsFromCleaving, PersistedClovenSegments, subGridSegmentPassCountLimit))
                {
                    iterator.SegmentListExtended();

                    if (_segmentCleavingOperationsToLog)
                    {
                        _log.LogInformation(
                            $"Info: Performed cleave on segment ({cleavedTimeRangeStart}-{cleavedTimeRangeEnd}) of sub grid {ServerSubGridTree.GetLeafSubGridFullFileName(origin)}. TotalPassCount = {totalPassCount} MaximumPassCount = {maximumPassCount}");
                    }
                }
                else
                {
                    // The segment cleave failed. While this is not a serious problem (as the sub grid will be
                    // cleaved at some point in the future when it is modified again via tag file processing etc)
                    // it will be noted in the log.

                    _log.LogWarning(
                        $"Cleave on segment ({cleavedTimeRangeStart}-{cleavedTimeRangeEnd}) of sub grid {ServerSubGridTree.GetLeafSubGridFullFileName(origin)} failed. TotalPassCount = {totalPassCount} MaximumPassCount = {maximumPassCount}");
                }

                if (_segmentCleavingOperationsToLog)
                {
                    if (segment.RequiresCleaving(out totalPassCount, out maximumPassCount))
                    {
                        _log.LogWarning(
                            $"Cleave on segment ({cleavedTimeRangeStart}-{cleavedTimeRangeEnd}) of sub grid {subGrid.Moniker()} failed to reduce cell pass count below maximums (max passes = {totalPassCount}/{subGridSegmentPassCountLimit}, per cell = {maximumPassCount}/{_subGridMaxSegmentCellPassesLimit})");
                    }
                }
            } while (iterator.MoveToNextSubGridSegment());
        }
예제 #6
0
        /// <summary>
        /// Constructs a mask using all spatial filtering elements active in the supplied filter
        /// </summary>
        public static bool ConstructSubGridCellFilterMask(ISiteModel siteModel, SubGridCellAddress currentSubGridOrigin,
                                                          InterceptList intercepts,
                                                          int fromProfileCellIndex,
                                                          SubGridTreeBitmapSubGridBits mask,
                                                          ICellSpatialFilter cellFilter,
                                                          IDesign surfaceDesignMaskDesign)
        {
            ConstructSubGridSpatialAndPositionalMask(currentSubGridOrigin, intercepts, fromProfileCellIndex, mask, cellFilter, siteModel.Grid);

            // If the filter contains an alignment design mask filter then compute this and AND it with the
            // mask calculated in the step above to derive the final required filter mask

            if (cellFilter.HasAlignmentDesignMask())
            {
                if (cellFilter.AlignmentFence.IsNull()) // Should have been done in ASNode but if not
                {
                    throw new ArgumentException($"Spatial filter does not contained pre-prepared alignment fence for design {cellFilter.AlignmentDesignMaskDesignUID}");
                }

                var tree = siteModel.Grid;
                // Go over set bits and determine if they are in Design fence boundary
                mask.ForEachSetBit((x, y) =>
                {
                    tree.GetCellCenterPosition(currentSubGridOrigin.X + x, currentSubGridOrigin.Y + y, out var cx, out var cy);
                    if (!cellFilter.AlignmentFence.IncludesPoint(cx, cy))
                    {
                        mask.ClearBit(x, y); // remove interest as its not in design boundary
                    }
                });
            }

            // If the filter contains a design mask filter then compute this and AND it with the
            // mask calculated in the step above to derive the final required filter mask

            if (surfaceDesignMaskDesign != null)
            {
                var getFilterMaskResult = surfaceDesignMaskDesign.GetFilterMaskViaLocalCompute(siteModel, currentSubGridOrigin, siteModel.CellSize);

                if (getFilterMaskResult.errorCode == DesignProfilerRequestResult.OK || getFilterMaskResult.errorCode == DesignProfilerRequestResult.NoElevationsInRequestedPatch)
                {
                    if (getFilterMaskResult.filterMask == null)
                    {
                        _log.LogWarning("FilterMask null in response from surfaceDesignMaskDesign.GetFilterMask, ignoring it's contribution to filter mask");
                    }
                    else
                    {
                        mask.AndWith(getFilterMaskResult.filterMask);
                    }
                }
                else
                {
                    _log.LogError($"Call (A2) to {nameof(ConstructSubGridCellFilterMask)} returned error result {getFilterMaskResult.errorCode} for {cellFilter.SurfaceDesignMaskDesignUid}");
                    return(false);
                }
            }

            return(true);
        }
예제 #7
0
 /// <summary>
 /// Computes a unique file name for a segment within a particular sub grid
 /// </summary>
 public static string GetLeafSubGridSegmentFullFileName(SubGridCellAddress cellAddress,
                                                        ISubGridCellPassesDataSegmentInfo segmentInfo)
 {
     // Work out the cell address of the origin cell in the appropriate leaf
     // sub grid. We use this cell position to derive the name of the file
     // containing the leaf sub grid data
     return(segmentInfo.FileName(cellAddress.X & ~SubGridTreeConsts.SubGridLocalKeyMask,
                                 cellAddress.Y & ~SubGridTreeConsts.SubGridLocalKeyMask));
 }
예제 #8
0
        public void Test_SubgridCellAddress_Equality()
        {
            SubGridCellAddress ca  = new SubGridCellAddress(1, 1);
            SubGridCellAddress ca2 = new SubGridCellAddress(1, 1);
            SubGridCellAddress ca3 = new SubGridCellAddress(3, 3);

            Assert.True(ca.Equals(ca2), "Equality check between identical addresses failed");
            Assert.False(ca.Equals(ca3), "Inequality between different addresses failed");
        }
예제 #9
0
        public void Test_SubgridCellAddress_Set()
        {
            SubGridCellAddress ca = new SubGridCellAddress();

            ca.Set(1, 2, true, false);

            // Check the simple style of creation is OK
            Assert.True(ca.X == 1 && ca.Y == 2 && ca.ProdDataRequested == true && ca.SurveyedSurfaceDataRequested == false,
                        "Setting simple cell address not set properties as expected");
        }
예제 #10
0
        /// <summary>
        /// Calculates an elevation sub grid for a designated sub grid on this design
        /// </summary>
        public (IClientHeightLeafSubGrid designHeights, DesignProfilerRequestResult errorCode) GetDesignHeightsViaLocalCompute(
            ISiteModelBase siteModel,
            double offset,
            SubGridCellAddress originCellAddress,
            double cellSize)
        {
            var heightsResult = _designElevationCalculator.Execute(siteModel, new DesignOffset(DesignDescriptor.DesignID, offset),
                                                                   cellSize, originCellAddress.X, originCellAddress.Y, out var calcResult);

            return(heightsResult, calcResult);
        }
예제 #11
0
        public void Test_SubgridCellAddress_ToSpatialPartitionDescriptor(int cellX, int cellY, int expectedPartition)
        {
            // These tests assume the default number of 1024 partitions from the configuration

            // Test the instance method
            SubGridCellAddress ca = new SubGridCellAddress(cellX, cellY);

            ca.ToSpatialPartitionDescriptor().Should().Be(expectedPartition);

            // Test the static method
            SubGridCellAddress.ToSpatialPartitionDescriptor(cellX, cellY).Should().Be(expectedPartition);
        }
예제 #12
0
        public void Test_SubgridCellAddress_ToNormalisedSubgridOriginInt64()
        {
            SubGridCellAddress ca = new SubGridCellAddress(1, 1);

            long correct = 0;

            Assert.Equal(ca.ToNormalisedSubgridOriginInt64, correct);

            SubGridCellAddress ca2 = new SubGridCellAddress(1 << 5, 1 << 5);

            long correct2 = (1L << 25) | 1;

            Assert.Equal(ca2.ToNormalisedSubgridOriginInt64, correct2);
        }
예제 #13
0
        public void ScanAllSetBitsAsSubGridAddresses_SingleAllocedSameStructAsStruct()
        {
            SubGridCellAddress address = new SubGridCellAddress(12, 34);

            for (int lots = 0; lots < 50; lots++)
            {
                for (int i = 0; i < 32; i++)
                {
                    for (int j = 0; j < 32; j++)
                    {
                        DoSomethingWithAddressAsStruct(address);
                    }
                }
            }
        }
예제 #14
0
        public void Test_SubgridCellAddress_FlagManagement()
        {
            SubGridCellAddress ca2 = new SubGridCellAddress(1, 1, true, true);

            // Check setting/clearing the bit flag based properties
            ca2.ProdDataRequested = false;
            Assert.False(ca2.ProdDataRequested);
            ca2.ProdDataRequested = true;
            Assert.True(ca2.ProdDataRequested);

            ca2.SurveyedSurfaceDataRequested = false;
            Assert.False(ca2.SurveyedSurfaceDataRequested);
            ca2.SurveyedSurfaceDataRequested = true;
            Assert.True(ca2.SurveyedSurfaceDataRequested);
        }
예제 #15
0
        /// <summary>
        /// Given a cache key, determine which partition the cache item should reside
        /// </summary>
        public override int GetPartition(object key)
        {
            // Pull the sub grid origin location for the sub grid or segment represented in the cache key and calculate the
            // spatial processing division descriptor to use as the partition affinity key

            if (key is ISubGridSpatialAffinityKey value)
            {
                // Compute partition number against the sub grid location in the spatial affinity key
                return(SubGridCellAddress.ToSpatialPartitionDescriptor(value.SubGridX, value.SubGridY));
            }

            Log.LogCritical($"Unknown key type to compute spatial affinity partition key for: [{key.GetType().FullName}] {key}. Returning partition 0 to avoid thrown exception");
            return(0);

            //throw new ArgumentException($"Unknown key type to compute spatial affinity partition key for: [{key.GetType().FullName}] {key}");
        }
예제 #16
0
        public void Test_SubgridCellAddress_ToSkipInterleavedDescriptor()
        {
            SubGridCellAddress ca;
            long correct;

            ca      = new SubGridCellAddress(1, 1);
            correct = 1;
            Assert.Equal(ca.ToSkipInterleavedDescriptor, correct);

            ca      = new SubGridCellAddress(1 << 5, 1);
            correct = (1 << 5) | 1;
            Assert.Equal(ca.ToSkipInterleavedDescriptor, correct);

            ca      = new SubGridCellAddress(1 << 5, 1 << 5);
            correct = 1 << 5;
            Assert.Equal(ca.ToSkipInterleavedDescriptor, correct);
        }
예제 #17
0
        /// <summary>
        /// Gets the production data values for the requested cell
        /// </summary>
        private async Task GetProductionData(ISiteModel siteModel, IDesignWrapper cutFillDesign, CellDatumResponse_ClusterCompute result, CellDatumRequestArgument_ClusterCompute arg)
        {
            var existenceMap = siteModel.ExistenceMap;

            var utilities  = DIContext.Obtain <IRequestorUtilities>();
            var requestors = utilities.ConstructRequestors(null, siteModel, arg.Overrides, arg.LiftParams,
                                                           utilities.ConstructRequestorIntermediaries(siteModel, arg.Filters, true, GridDataType.CellProfile),
                                                           AreaControlSet.CreateAreaControlSet(), existenceMap);

            // Get the sub grid relative cell location
            int cellX = arg.OTGCellX & SubGridTreeConsts.SubGridLocalKeyMask;
            int cellY = arg.OTGCellY & SubGridTreeConsts.SubGridLocalKeyMask;

            // Reach into the sub-grid request layer and retrieve an appropriate sub-grid
            var cellOverrideMask = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled);

            cellOverrideMask.SetBit(cellX, cellY);
            requestors[0].CellOverrideMask = cellOverrideMask;

            // using the cell address get the index of cell in clientGrid
            var thisSubGridOrigin            = new SubGridCellAddress(arg.OTGCellX, arg.OTGCellY);
            var requestSubGridInternalResult = requestors[0].RequestSubGridInternal(thisSubGridOrigin, true, true);

            if (requestSubGridInternalResult.requestResult != ServerRequestResult.NoError)
            {
                if (requestSubGridInternalResult.requestResult == ServerRequestResult.SubGridNotFound)
                {
                    result.ReturnCode = CellDatumReturnCode.NoValueFound;
                }
                else
                {
                    Log.LogError($"Request for sub grid {thisSubGridOrigin} request failed with code {requestSubGridInternalResult.requestResult}");
                }
                return;
            }

            var cell = ((ClientCellProfileLeafSubgrid)requestSubGridInternalResult.clientGrid).Cells[cellX, cellY];

            if (cell.PassCount > 0) // Cell is not in our areaControlSet...
            {
                await ExtractRequiredValue(cutFillDesign, cell, result, arg);

                result.TimeStampUTC = cell.LastPassTime;
            }
        }
예제 #18
0
        public void ScanAllSetBitsAsSubGridAddresses_SingleAlloced()
        {
            SubGridCellAddress address = new SubGridCellAddress();

            for (int lots = 0; lots < 50; lots++)
            {
                for (int i = 0; i < 32; i++)
                {
                    for (int j = 0; j < 32; j++)
                    {
                        address.X = i;
                        address.Y = j;

                        DoSomethingWithAddress(address);
                    }
                }
            }
        }
예제 #19
0
        /// <summary>
        /// Calculates a filter mask for a designated sub grid on this design
        /// </summary>
        public async Task <(SubGridTreeBitmapSubGridBits filterMask, DesignProfilerRequestResult errorCode)> GetFilterMaskViaDesignElevationService(
            Guid siteModelId,
            SubGridCellAddress originCellAddress,
            double cellSize)
        {
            // Query the DesignProfiler service to get the requested filter mask
            var filterMaskRequest = new DesignFilterSubGridMaskRequest();

            var maskResponse = await filterMaskRequest.ExecuteAsync(new DesignSubGridFilterMaskArgument
            {
                CellSize        = cellSize,
                ReferenceDesign = new DesignOffset(DesignDescriptor.DesignID, 0),
                OriginX         = originCellAddress.X,
                OriginY         = originCellAddress.Y,
                ProjectID       = siteModelId
            });

            return(maskResponse?.Bits, maskResponse?.RequestResult ?? DesignProfilerRequestResult.UnknownError);
        }
예제 #20
0
        /// <summary>
        /// Constructs a mask using polygonal and positional spatial filtering aspects of a filter.
        /// </summary>
        private static void ConstructSubGridSpatialAndPositionalMask(SubGridCellAddress currentSubGridOrigin,
                                                                     InterceptList intercepts,
                                                                     int fromProfileCellIndex,
                                                                     SubGridTreeBitmapSubGridBits mask,
                                                                     ICellSpatialFilter cellFilter,
                                                                     ISubGridTree subGridTree)
        {
            var cellFilterHasSpatialOrPositionalFilters = cellFilter.HasSpatialOrPositionalFilters;
            var interceptsCount = intercepts.Count;

            mask.Clear();

            for (var interceptIdx = fromProfileCellIndex; interceptIdx < interceptsCount; interceptIdx++)
            {
                // Determine the on-the-ground cell underneath the midpoint of each cell on the intercept line
                subGridTree.CalculateIndexOfCellContainingPosition(intercepts.Items[interceptIdx].MidPointX,
                                                                   intercepts.Items[interceptIdx].MidPointY, out var otgCellX, out var otgCellY);

                var thisSubGridOrigin = new SubGridCellAddress(otgCellX & ~SubGridTreeConsts.SubGridLocalKeyMask, otgCellY & ~SubGridTreeConsts.SubGridLocalKeyMask);

                if (!currentSubGridOrigin.Equals(thisSubGridOrigin))
                {
                    break;
                }

                var cellX = otgCellX & SubGridTreeConsts.SubGridLocalKeyMask;
                var cellY = otgCellY & SubGridTreeConsts.SubGridLocalKeyMask;

                if (cellFilterHasSpatialOrPositionalFilters)
                {
                    subGridTree.GetCellCenterPosition(otgCellX, otgCellY, out var cellCenterX, out var cellCenterY);

                    if (cellFilter.IsCellInSelection(cellCenterX, cellCenterY))
                    {
                        mask.SetBit(cellX, cellY);
                    }
                }
                else
                {
                    mask.SetBit(cellX, cellY);
                }
            }
        }
예제 #21
0
        /// <summary>
        /// Calculates an elevation sub grid for a designated sub grid on this design
        /// </summary>
        public async Task <(IClientHeightLeafSubGrid designHeights, DesignProfilerRequestResult errorCode)> GetDesignHeightsViaDesignElevationService(
            Guid siteModelId,
            double offset,
            SubGridCellAddress originCellAddress,
            double cellSize)
        {
            // Query the DesignProfiler service to get the patch of elevations calculated
            var elevPatchRequest = new DesignElevationPatchRequest();

            var response = await elevPatchRequest.ExecuteAsync(new CalculateDesignElevationPatchArgument
            {
                CellSize        = cellSize,
                ReferenceDesign = new DesignOffset(DesignDescriptor.DesignID, offset),
                OriginX         = originCellAddress.X,
                OriginY         = originCellAddress.Y,
                ProjectID       = siteModelId
            });

            return(response.Heights, response.CalcResult);
        }
예제 #22
0
        public void Test_SubgridCellAddress_Creation()
        {
            SubGridCellAddress ca = new SubGridCellAddress();

            // Check the simple style of creation is OK
            Assert.True(ca.X == 0 && ca.Y == 0 && ca.ProdDataRequested == false && ca.SurveyedSurfaceDataRequested == false,
                        "Default simple cell address creation did not set properties as expected");

            ca = new SubGridCellAddress(1, 1);

            // Check the simple style of creation is OK
            Assert.True(ca.X == 1 && ca.Y == 1 && ca.ProdDataRequested == false && ca.SurveyedSurfaceDataRequested == false,
                        "Simple cell address creation did not set properties as expected");

            SubGridCellAddress ca2 = new SubGridCellAddress(1, 1, true, true);

            // Check the simple style of creation is OK
            Assert.True(ca2.X == 1 && ca2.Y == 1 && ca2.ProdDataRequested == true && ca2.SurveyedSurfaceDataRequested == true,
                        "Complete cell address creation did not set properties as expected");
        }
예제 #23
0
        private static void ConstructSubGridSpatialAndPositionalMask(ISubGridTree tree,
                                                                     SubGridCellAddress currentSubGridOrigin,
                                                                     List <T> profileCells,
                                                                     SubGridTreeBitmapSubGridBits mask,
                                                                     int fromProfileCellIndex,
                                                                     ICellSpatialFilter cellFilter)
        {
            mask.Clear();

            // From current position to end...
            for (var cellIdx = fromProfileCellIndex; cellIdx < profileCells.Count; cellIdx++)
            {
                var profileCell       = profileCells[cellIdx];
                var thisSubGridOrigin = new SubGridCellAddress(
                    profileCell.OTGCellX & ~SubGridTreeConsts.SubGridLocalKeyMask,
                    profileCell.OTGCellY & ~SubGridTreeConsts.SubGridLocalKeyMask);

                if (!currentSubGridOrigin.Equals(thisSubGridOrigin))
                {
                    break;
                }

                var cellX = (byte)(profileCell.OTGCellX & SubGridTreeConsts.SubGridLocalKeyMask);
                var cellY = (byte)(profileCell.OTGCellY & SubGridTreeConsts.SubGridLocalKeyMask);

                if (cellFilter.HasSpatialOrPositionalFilters)
                {
                    tree.GetCellCenterPosition(profileCell.OTGCellX, profileCell.OTGCellY,
                                               out var cellCenterX, out var cellCenterY);
                    if (cellFilter.IsCellInSelection(cellCenterX, cellCenterY))
                    {
                        mask.SetBit(cellX, cellY);
                    }
                }
                else
                {
                    mask.SetBit(cellX, cellY);
                }
            }
        }
예제 #24
0
        /// <summary>
        /// For each point in the list, get the sub grid and extract productionData at the station/offset i.e pointOfInterest
        ///    This could be optimized to get any poi from each sub grid before disposal
        /// </summary>
        private StationOffsetReportRequestResponse_ClusterCompute GetProductionData()
        {
            var result = new StationOffsetReportRequestResponse_ClusterCompute {
                ResultStatus = RequestErrorStatus.Unknown
            };

            IDesignWrapper cutFillDesignWrapper = null;

            if (requestArgument.ReferenceDesign != null && requestArgument.ReferenceDesign.DesignID != Guid.Empty)
            {
                var cutFillDesign = siteModel.Designs.Locate(requestArgument.ReferenceDesign.DesignID);
                if (cutFillDesign == null)
                {
                    throw new ArgumentException($"Design {requestArgument.ReferenceDesign.DesignID} not a recognized design in project {requestArgument.ProjectID}");
                }
                cutFillDesignWrapper = new DesignWrapper(requestArgument.ReferenceDesign, cutFillDesign);
            }

            var existenceMap = siteModel.ExistenceMap;
            var utilities    = DIContext.Obtain <IRequestorUtilities>();
            var requestors   = utilities.ConstructRequestors(null, siteModel, requestArgument.Overrides, requestArgument.LiftParams,
                                                             utilities.ConstructRequestorIntermediaries(siteModel, requestArgument.Filters, true, GridDataType.CellProfile),
                                                             AreaControlSet.CreateAreaControlSet(), existenceMap);

            // Obtain the primary partition map to allow this request to determine the elements it needs to process
            bool[] primaryPartitionMap = ImmutableSpatialAffinityPartitionMap.Instance().PrimaryPartitions();
            SubGridTreeBitmapSubGridBits cellOverrideMask = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled);

            foreach (var point in requestArgument.Points)
            {
                // Determine the on-the-ground cell
                siteModel.Grid.CalculateIndexOfCellContainingPosition(point.Easting, point.Northing, out int OTGCellX, out int OTGCellY);

                var thisSubGridOrigin = new SubGridCellAddress(OTGCellX, OTGCellY);

                if (!primaryPartitionMap[thisSubGridOrigin.ToSpatialPartitionDescriptor()])
                {
                    continue;
                }

                // Get the sub grid relative cell location
                int cellX = OTGCellX & SubGridTreeConsts.SubGridLocalKeyMask;
                int cellY = OTGCellY & SubGridTreeConsts.SubGridLocalKeyMask;

                // Reach into the sub-grid request layer and retrieve an appropriate sub-grid
                cellOverrideMask.Clear();
                cellOverrideMask.SetBit(cellX, cellY);
                requestors[0].CellOverrideMask = cellOverrideMask;

                // using the cell address get the index of cell in clientGrid
                var requestSubGridInternalResult = requestors[0].RequestSubGridInternal(
                    thisSubGridOrigin, true, true);

                if (requestSubGridInternalResult.requestResult != ServerRequestResult.NoError)
                {
                    Log.LogError($"Request for sub grid {thisSubGridOrigin} request failed with code {result}");
                    result.StationOffsetRows.Add(new StationOffsetRow(point.Station, point.Offset, point.Northing, point.Easting));
                    continue;
                }

                var hydratedPoint = ExtractRequiredValues(cutFillDesignWrapper, point, requestSubGridInternalResult.clientGrid as ClientCellProfileLeafSubgrid, cellX, cellY);
                result.StationOffsetRows.Add(hydratedPoint);
            }

            result.ResultStatus = RequestErrorStatus.OK;
            return(result);
        }
예제 #25
0
        /// <summary>
        /// Constructs a vector of cells in profileCells along the path of the profile geometry containing in nEECoords
        /// </summary>
        public bool Build(XYZ[] nEECoords, List <T> profileCells)
        {
            NEECoords    = nEECoords;
            ProfileCells = profileCells;

            CellSize = SiteModel.CellSize;

            CurrStationPos = 0;

            CurrentSubgridOrigin  = new SubGridCellAddress(int.MaxValue, int.MaxValue);
            ReturnDesignElevation = CutFillDesignWrapper?.Design != null;
            DesignElevations      = null;

            // Obtain the primary partition map to allow this request to determine the elements it needs to process
            bool[] primaryPartitionMap = ImmutableSpatialAffinityPartitionMap.Instance().PrimaryPartitions();

            for (int loopBound = NEECoords.Length - 1, I = 0; I < loopBound; I++)
            {
                StartX       = NEECoords[I].X;
                StartY       = NEECoords[I].Y;
                StartStation = NEECoords[I].Z;

                EndX       = NEECoords[I + 1].X;
                EndY       = NEECoords[I + 1].Y;
                EndStation = NEECoords[I + 1].Z;

                if (I == 0)                                               // Add start point of profile line to intercept list
                {
                    CurrStationPos = SlicerToolUsed ? 0 : NEECoords[I].Z; // alignment profiles pass in station for more accuracy
                    VtHzIntercepts.AddPoint(StartX, StartY, CurrStationPos);
                }

                Distance = SlicerToolUsed
          ? MathUtilities.Hypot(EndX - StartX, EndY - StartY) // station is not passed so compute
          : EndStation - StartStation;                        // use precise station passed

                if (Distance == 0)                            // if we have two points the same
                {
                    continue;
                }

                // Get all intercepts between profile line and cell boundaries for this segment
                CalculateHorizontalIntercepts(CurrStationPos); // pass the distance down alignment this segment starts
                CalculateVerticalIntercepts(CurrStationPos);

                CurrStationPos += Distance; // add distance to current station
            }

            // Merge vertical and horizontal cell boundary/profile line intercepts
            VtHzIntercepts.MergeInterceptLists(VtIntercepts, HzIntercepts);

            // Add end point of profile line to intercept list
            VtHzIntercepts.AddPoint(EndX, EndY, CurrStationPos);

            // Update each intercept with it's midpoint and intercept length
            // i.e. the midpoint on the line between one intercept and the next one
            // and the length between those intercepts
            VtHzIntercepts.UpdateMergedListInterceptMidPoints();

            if (VtHzIntercepts.Count > ProfileCells.Capacity)
            {
                ProfileCells.Capacity = VtHzIntercepts.Count;
            }

            // Iterate over all intercepts calculating the results for each cell that lies in
            // a subgrid handled by this node
            for (int i = 0; i < VtHzIntercepts.Count; i++)
            {
                if (Aborted)
                {
                    return(false);
                }

                // Determine the on-the-ground cell underneath the midpoint of each intercept line
                SiteModel.Grid.CalculateIndexOfCellContainingPosition(VtHzIntercepts.Items[i].MidPointX,
                                                                      VtHzIntercepts.Items[i].MidPointY, out OTGCellX, out OTGCellY);

                ThisSubgridOrigin = new SubGridCellAddress(OTGCellX & ~SubGridTreeConsts.SubGridLocalKeyMask, OTGCellY & ~SubGridTreeConsts.SubGridLocalKeyMask);

                if (!CurrentSubgridOrigin.Equals(ThisSubgridOrigin))
                {
                    if (!primaryPartitionMap[ThisSubgridOrigin.ToSpatialPartitionDescriptor()])
                    {
                        continue;
                    }

                    CurrentSubgridOrigin = ThisSubgridOrigin;

                    if (!ProfileFilterMask.ConstructSubGridCellFilterMask(SiteModel, CurrentSubgridOrigin, VtHzIntercepts, i, FilterMask, CellFilter,
                                                                          SurfaceDesignMaskDesign))
                    {
                        continue;
                    }

                    if (ReturnDesignElevation && CutFillDesignWrapper?.Design != null) // cut fill profile request then get elevation at same spot along design
                    {
                        var getDesignHeightsResult = CutFillDesignWrapper.Design.GetDesignHeightsViaLocalCompute(SiteModel, CutFillDesignWrapper.Offset, new SubGridCellAddress(OTGCellX, OTGCellY), CellSize);

                        DesignElevations = getDesignHeightsResult.designHeights;
                        DesignResult     = getDesignHeightsResult.errorCode;

                        if (DesignResult != DesignProfilerRequestResult.OK &&
                            DesignResult != DesignProfilerRequestResult.NoElevationsInRequestedPatch)
                        {
                            continue;
                        }

                        if (DesignResult == DesignProfilerRequestResult.NoElevationsInRequestedPatch)
                        {
                            DesignElevations = null; // force a null height to be written
                        }
                    }
                }

                if (FilterMask.BitSet(OTGCellX & SubGridTreeConsts.SubGridLocalKeyMask, OTGCellY & SubGridTreeConsts.SubGridLocalKeyMask))
                {
                    AddCellPassesDataToList(OTGCellX, OTGCellY, VtHzIntercepts.Items[i].ProfileItemIndex, VtHzIntercepts.Items[i].InterceptLength);
                }
            }

            Log.LogInformation($"CellProfileBuilder constructed a vector of {VtHzIntercepts.Count} vertices");

            return(true);
        }
예제 #26
0
        /// <summary>
        /// Executor that implements requesting and rendering sub grid information to create the cell datum
        /// </summary>
        public async Task <CellPassesResponse> ExecuteAsync(CellPassesRequestArgument_ClusterCompute arg, SubGridSpatialAffinityKey key)
        {
            Log.LogInformation($"Performing Execute for DataModel:{arg.ProjectID}");

            var result = new CellPassesResponse {
                ReturnCode = CellPassesReturnCode.Error
            };

            var siteModel = DIContext.Obtain <ISiteModels>().GetSiteModel(arg.ProjectID);

            if (siteModel == null)
            {
                Log.LogError($"Failed to locate site model {arg.ProjectID}");
                return(result);
            }

            var existenceMap = siteModel.ExistenceMap;
            var utilities    = DIContext.Obtain <IRequestorUtilities>();
            var requestors   = utilities.ConstructRequestors(null, siteModel, arg.Overrides, arg.LiftParams,
                                                             utilities.ConstructRequestorIntermediaries(siteModel, arg.Filters, true, GridDataType.CellPasses),
                                                             AreaControlSet.CreateAreaControlSet(),
                                                             existenceMap);

            // Get the sub grid relative cell location
            var cellX = arg.OTGCellX & SubGridTreeConsts.SubGridLocalKeyMask;
            var cellY = arg.OTGCellY & SubGridTreeConsts.SubGridLocalKeyMask;

            // Reach into the sub-grid request layer and retrieve an appropriate sub-grid
            var cellOverrideMask = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled);

            cellOverrideMask.SetBit(cellX, cellY);
            requestors[0].CellOverrideMask = cellOverrideMask;

            var thisSubGridOrigin            = new SubGridCellAddress(arg.OTGCellX, arg.OTGCellY);
            var requestSubGridInternalResult = requestors[0].RequestSubGridInternal(thisSubGridOrigin, true, true);

            if (requestSubGridInternalResult.requestResult != ServerRequestResult.NoError)
            {
                if (requestSubGridInternalResult.requestResult == ServerRequestResult.SubGridNotFound)
                {
                    result.ReturnCode = CellPassesReturnCode.NoDataFound;
                }
                else
                {
                    Log.LogError($"Request for sub grid {thisSubGridOrigin} request failed with code {requestSubGridInternalResult.requestResult}");
                }
                return(result);
            }

            if (!(requestSubGridInternalResult.clientGrid is ClientCellProfileAllPassesLeafSubgrid grid))
            {
                Log.LogError($"Request for sub grid {thisSubGridOrigin} request failed due the grid return type being incorrect. Expected {typeof(ClientCellProfileAllPassesLeafSubgrid).Name}, but got {requestSubGridInternalResult.clientGrid.GetType().Name}");
                return(result);
            }

            var cell = grid.Cells[cellX, cellY];

            if (cell.TotalPasses > 0)
            {
                result.ReturnCode = CellPassesReturnCode.DataFound;
                for (var idx = 0; idx < cell.TotalPasses; idx++)
                {
                    var cellPass = cell.CellPasses[idx];
                    result.CellPasses.Add(cellPass);
                }
            }
            else
            {
                result.ReturnCode = CellPassesReturnCode.NoDataFound;
            }

            return(result);
        }
예제 #27
0
        /// <summary>
        /// Processes each sub grid in turn into the resulting profile.
        /// </summary>
        public void ProcessSubGroup(SubGridCellAddress address, bool prodDataAtAddress, SubGridTreeBitmapSubGridBits cellOverrideMask)
        {
            var okToProceed = false;

            // Execute a client grid request for each requester and create an array of the results
            var clientGrids = Requestors.Select(x =>
            {
                x.CellOverrideMask = cellOverrideMask;

                // Reach into the sub grid request layer and retrieve an appropriate sub grid
                var requestSubGridInternalResult = x.RequestSubGridInternal(address, prodDataAtAddress, true);
                if (requestSubGridInternalResult.requestResult != ServerRequestResult.NoError)
                {
                    Log.LogError($"Request for sub grid {address} request failed with code {requestSubGridInternalResult.requestResult}");
                }

                return(requestSubGridInternalResult.clientGrid);
            }).ToArray();

            // If an intermediary result was requested then merge the 'from' and intermediary sub grids now
            if (IntermediaryFilterRequired)
            {
                MergeIntermediaryResults(clientGrids[0] as ClientHeightAndTimeLeafSubGrid, clientGrids[1] as ClientHeightAndTimeLeafSubGrid);
                //... and chop out the intermediary grid
                clientGrids = new[] { clientGrids[0], clientGrids[2] };
            }

            // Assign the results of the sub grid requests according to the ordering of the filter in the overall
            // volume type context of the request
            ClientHeightAndTimeLeafSubGrid heightsGrid1 = null;

            if (VolumeType == VolumeComputationType.BetweenFilterAndDesign || VolumeType == VolumeComputationType.Between2Filters)
            {
                heightsGrid1 = clientGrids[0] as ClientHeightAndTimeLeafSubGrid;
            }

            ClientHeightAndTimeLeafSubGrid heightsGrid2 = null;

            if (VolumeType == VolumeComputationType.BetweenDesignAndFilter)
            {
                heightsGrid2 = clientGrids[0] as ClientHeightAndTimeLeafSubGrid;
            }
            else if (VolumeType == VolumeComputationType.Between2Filters)
            {
                heightsGrid2 = clientGrids[1] as ClientHeightAndTimeLeafSubGrid;
            }

            IClientHeightLeafSubGrid designHeights = null;

            if (VolumeType == VolumeComputationType.BetweenFilterAndDesign || VolumeType == VolumeComputationType.BetweenDesignAndFilter)
            {
                if (svDesignWrapper?.Design != null)
                {
                    var getDesignHeightsResult = svDesignWrapper.Design.GetDesignHeightsViaLocalCompute(SiteModel, svDesignWrapper.Offset, address, SiteModel.CellSize);

                    if (getDesignHeightsResult.errorCode != DesignProfilerRequestResult.OK || getDesignHeightsResult.designHeights == null)
                    {
                        if (getDesignHeightsResult.errorCode == DesignProfilerRequestResult.NoElevationsInRequestedPatch)
                        {
                            Log.LogInformation("Call to RequestDesignElevationPatch failed due to no elevations in requested patch.");
                        }
                        else
                        {
                            Log.LogError($"Call to RequestDesignElevationPatch failed due to no TDesignProfilerRequestResult return code {getDesignHeightsResult.errorCode}.");
                        }
                    }
                    else
                    {
                        designHeights = getDesignHeightsResult.designHeights;
                        okToProceed   = true;
                    }
                }
                else
                {
                    Log.LogError("Missing design reference. Call to request Summary Volumes Profile using design failed due to no reference design");
                }
            }
            else
            {
                okToProceed = true;
            }

            if (okToProceed)
            {
                for (int I = 0; I < cellCounter; I++)
                {
                    int cellX = profileCellList[I].OTGCellX & SubGridTreeConsts.SubGridLocalKeyMask;
                    int cellY = profileCellList[I].OTGCellY & SubGridTreeConsts.SubGridLocalKeyMask;
                    if (heightsGrid1 != null)
                    {
                        profileCellList[I].LastCellPassElevation1 = heightsGrid1.Cells[cellX, cellY];
                    }
                    if (heightsGrid2 != null)
                    {
                        profileCellList[I].LastCellPassElevation2 = heightsGrid2.Cells[cellX, cellY];
                    }
                    profileCellList[I].DesignElev = designHeights?.Cells[cellX, cellY] ?? CellPassConsts.NullHeight;
                }
            }
        }
예제 #28
0
        /// <summary>
        /// Orchestrates all the activities relating to saving the state of a created or modified sub grid, including
        /// cleaving, saving updated elements, creating new elements and arranging for the retirement of
        /// elements that have been replaced in the persistent store as a result of this activity.
        /// </summary>
        public bool SaveLeafSubGrid(IServerLeafSubGrid subGrid,
                                    IStorageProxy storageProxyForSubGrids,
                                    IStorageProxy storageProxyForSubGridSegments,
                                    List <ISubGridSpatialAffinityKey> invalidatedSpatialStreams)
        {
            //Log.LogInformation($"Saving {subGrid.Moniker()} to persistent store");

            try
            {
                // Perform segment cleaving as the first activity in the action of saving a leaf sub grid
                // to disk. This reduces the number of segment cleaving actions that would otherwise
                // be performed in the context of the aggregated integrator.

                if (_segmentCleavingOperationsToLog)
                {
                    _log.LogDebug($"About to perform segment cleaving on {subGrid.Moniker()}");
                }

                var cleaver = new SubGridSegmentCleaver();

                cleaver.PerformSegmentCleaving(storageProxyForSubGridSegments, subGrid);

                // Calculate the cell last pass information here, immediately before it is
                // committed to the persistent store. The reason for this is to remove this
                // compute intensive operation from the critical path in TAG file processing
                // (which is the only writer of this information in the Raptor system).
                // The computer is instructed to do a partial recompute, which will recompute
                // all segments from the first segment marked as dirty.
                subGrid.ComputeLatestPassInformation(false, storageProxyForSubGridSegments);

                if (_segmentCleavingOperationsToLog)
                {
                    _log.LogInformation($"SaveLeafSubGrid: {subGrid.Moniker()} ({subGrid.Cells.PassesData.Count} segments)");
                }

                var modifiedOriginalSegments = new List <ISubGridCellPassesDataSegment>(100);
                var originAddress            = new SubGridCellAddress(subGrid.OriginX, subGrid.OriginY);

                // The following used to be an assert/exception. However, this is may readily
                // happen if there are no modified segments resulting from processing a
                // process TAG file where the Dirty flag for the sub grid is set but no cell
                // passes are added to segments in that sub grid. As this is not an integrity
                // issue the persistence of the modified sub grid is allowed, but noted in
                // the log for posterity.
                if (subGrid.Cells.PassesData.Count == 0)
                {
                    _log.LogInformation(
                        $"Note: Saving a sub grid, {subGrid.Moniker()}, (Segments = {subGrid.Cells.PassesData.Count}, Dirty = {subGrid.Dirty}) with no cached sub grid segments to the persistent store in SaveLeafSubGrid (possible reprocessing of TAG file with no cell pass changes). " +
                        $"SubGrid.Directory.PersistedClovenSegments.Count={cleaver.PersistedClovenSegments?.Count}, ModifiedOriginalFiles.Count={modifiedOriginalSegments.Count}, NewSegmentsFromCleaving.Count={cleaver.NewSegmentsFromCleaving.Count}");
                }

                var iterator = new SubGridSegmentIterator(subGrid, storageProxyForSubGridSegments)
                {
                    IterationDirection = IterationDirection.Forwards,
                    ReturnDirtyOnly    = true,
                };

                //**********************************************************************
                //***Construct list of original segment files that have been modified***
                //*** These files may be updated in-situ with no sub grid/segment    ***
                //*** integrity issues wrt the segment directory in the sub grid     ***
                //**********************************************************************

                iterator.MoveToFirstSubGridSegment();
                while (iterator.CurrentSubGridSegment != null)
                {
                    if (iterator.CurrentSubGridSegment.SegmentInfo.ExistsInPersistentStore && iterator.CurrentSubGridSegment.Dirty)
                    {
                        modifiedOriginalSegments.Add(iterator.CurrentSubGridSegment);
                    }
                    iterator.MoveToNextSubGridSegment();
                }

                //**********************************************************************
                //*** Construct list of spatial streams that will be deleted or replaced
                //*** in the FS file. These will be passed to the call that saves the
                //*** sub grid directory file as an instruction to place them into the
                //*** deferred deletion list
                //**********************************************************************

                lock (invalidatedSpatialStreams)
                {
                    if (cleaver.PersistedClovenSegments != null)
                    {
                        invalidatedSpatialStreams.AddRange(cleaver.PersistedClovenSegments);
                    }

                    invalidatedSpatialStreams.AddRange(modifiedOriginalSegments.Select(x => x.SegmentInfo.AffinityKey(ID)));
                }

                if (cleaver.NewSegmentsFromCleaving.Count > 0)
                {
                    //**********************************************************************
                    //***    Write new segment files generated by cleaving               ***
                    //*** File system integrity failures here will have no effect on the ***
                    //*** sub grid/segment directory as they are not referenced by it.   ***
                    //*** At worst they become orphans they may be cleaned by in the FS  ***
                    //*** recovery phase                                                 ***
                    //**********************************************************************

                    if (_segmentCleavingOperationsToLog)
                    {
                        _log.LogInformation($"Sub grid has {cleaver.NewSegmentsFromCleaving.Count} new segments from cleaving");
                    }

                    foreach (var segment in cleaver.NewSegmentsFromCleaving)
                    {
                        // Update the version of the segment as it is about to be written
                        segment.SegmentInfo.Touch();

                        segment.SaveToFile(storageProxyForSubGridSegments, GetLeafSubGridSegmentFullFileName(originAddress, segment.SegmentInfo), out var fsError);
                        segment.Dirty = false;

                        if (fsError == FileSystemErrorStatus.OK)
                        {
                            if (_segmentCleavingOperationsToLog)
                            {
                                _log.LogInformation($"Saved new cloven grid segment file: {GetLeafSubGridSegmentFullFileName(originAddress, segment.SegmentInfo)}");
                            }
                        }
                        else
                        {
                            _log.LogWarning($"Failed to save cloven grid segment {GetLeafSubGridSegmentFullFileName(originAddress, segment.SegmentInfo)}: Error:{fsError}");
                            return(false);
                        }
                    }
                }

                if (modifiedOriginalSegments.Count > 0)
                {
                    //**********************************************************************
                    //***    Write modified segment files                                ***
                    //*** File system integrity failures here will have no effect on the ***
                    //*** sub grid/segment directory as the previous version of the      ***
                    //*** modified file being written will be recovered.                 ***
                    //**********************************************************************

                    if (_log.IsTraceEnabled())
                    {
                        _log.LogTrace($"Sub grid has {modifiedOriginalSegments.Count} modified segments");
                    }

                    foreach (var segment in modifiedOriginalSegments)
                    {
                        // Update the version of the segment as it is about to be written
                        segment.SegmentInfo.Touch();
                        segment.Dirty = false;

                        if (segment.SaveToFile(storageProxyForSubGridSegments, GetLeafSubGridSegmentFullFileName(originAddress, segment.SegmentInfo), out var fsError))
                        {
                            segment.Dirty = false;
                            if (_log.IsTraceEnabled())
                            {
                                _log.LogTrace($"Saved modified grid segment file: {segment}");
                            }
                        }
                        else
                        {
                            _log.LogError($"Failed to save modified original grid segment {GetLeafSubGridSegmentFullFileName(originAddress, segment.SegmentInfo)}: Error:{fsError}");
                            return(false);
                        }
                    }
                }

                // Any remaining dirty segments in the sub grid will be due to previously empty sub grids with newly
                // created segments from ingest processing that have not required cleaving. These segments do not require any
                // special treatment are jsut saved to persistent store

                foreach (var segment in subGrid.Directory.SegmentDirectory.Select(x => x.Segment).Where(x => (x?.Dirty ?? false)))
                {
                    if (segment.SaveToFile(storageProxyForSubGridSegments, GetLeafSubGridSegmentFullFileName(originAddress, segment.SegmentInfo), out var fsError))
                    {
                        segment.Dirty = false;
                        if (_log.IsTraceEnabled())
                        {
                            _log.LogTrace($"Saved new sub grid segment file: {segment}");
                        }
                    }
                    else
                    {
                        _log.LogError($"Failed to save new sub grid segment {GetLeafSubGridSegmentFullFileName(originAddress, segment.SegmentInfo)}: Error:{fsError}");
                        return(false);
                    }
                }

                //**********************************************************************
                //***                 Write the sub grid directory file              ***
                //**********************************************************************

                /*
                 * There is no need to add the sub grid directory stream to the segment retirement
                 * queue as this will be automatically replaced when the new version of the
                 * sub grid directory is written to persistent store.
                 *
                 * // Add the stream representing the sub grid directory file to the list of
                 * // invalidated streams as this stream will be replaced with the stream
                 * // containing the updated directory information. Note: This only needs to
                 * // be done if the sub grid has previously been read from the FS file (if not
                 * // it has been created and not yet persisted to the store.
                 *
                 * if (subGrid.Directory.ExistsInPersistentStore)
                 * {
                 * // Include an additional invalidated spatial stream for the sub grid directory stream
                 * lock (invalidatedSpatialStreams)
                 * {
                 *  invalidatedSpatialStreams.Add(subGrid.AffinityKey());
                 * }
                 * }
                 */

                if (subGrid.SaveDirectoryToFile(storageProxyForSubGrids, GetLeafSubGridFullFileName(originAddress)))
                {
                    if (_log.IsTraceEnabled())
                    {
                        _log.LogTrace($"Saved grid directory file: {GetLeafSubGridFullFileName(originAddress)}");
                    }
                }
                else
                {
                    if (_log.IsTraceEnabled())
                    {
                        _log.LogTrace($"Failed to save grid: {GetLeafSubGridFullFileName(originAddress)}");
                    }
                    return(false);
                }

                //**********************************************************************
                //***                   Reset segment dirty flags                    ***
                //**********************************************************************

                iterator.MoveToFirstSubGridSegment();
                while (iterator.CurrentSubGridSegment != null)
                {
                    iterator.CurrentSubGridSegment.Dirty = false;
                    iterator.CurrentSubGridSegment.SegmentInfo.ExistsInPersistentStore = true;

                    iterator.MoveToNextSubGridSegment();
                }

                //Log.LogInformation($"Completed saving {subGrid.Moniker()} to persistent store");

                return(true);
            }
            catch (Exception e)
            {
                _log.LogError(e, "Exception raised in SaveLeafSubGrid");
            }

            return(false);
        }
예제 #29
0
        public bool LoadLeafSubGrid(IStorageProxy storageProxy,
                                    SubGridCellAddress cellAddress,
                                    bool loadAllPasses, bool loadLatestPasses,
                                    IServerLeafSubGrid subGrid)
        {
            var fullFileName = string.Empty;
            var result       = false;

            try
            {
                // Loading contents into a dirty sub grid (which should happen only on the mutable nodes), or
                // when there is already content in the segment directory are strictly forbidden and break immutability
                // rules for sub grids
                if (subGrid.Dirty)
                {
                    throw new TRexSubGridIOException("Leaf sub grid directory loads may not be performed while the sub grid is dirty. The information should be taken from the cache instead.");
                }

                // Load the cells into it from its file
                // Briefly lock this sub grid just for the period required to read its contents
                lock (subGrid)
                {
                    // If more than thread wants this sub grid then they may concurrently attempt to load it.
                    // Make a check to see if this has happened and another thread has already loaded this sub grid directory.
                    // If so, just return success. Previously the commented out assert was enforced causing exceptions
                    // Debug.Assert(SubGrid.Directory?.SegmentDirectory?.Count == 0, "Loading a leaf sub grid directory when there are already segments present within it.");

                    // Check this thread is the winner of the lock to be able to load the contents
                    if (subGrid.Directory?.SegmentDirectory?.Count == 0)
                    {
                        // Ensure the appropriate storage is allocated
                        if (loadAllPasses)
                        {
                            subGrid.AllocateLeafFullPassStacks();
                        }

                        if (loadLatestPasses)
                        {
                            subGrid.AllocateLeafLatestPassGrid();
                        }

                        fullFileName = GetLeafSubGridFullFileName(cellAddress);

                        // Briefly lock this sub grid just for the period required to read its contents
                        result = subGrid.LoadDirectoryFromFile(storageProxy, fullFileName);
                    }
                    else
                    {
                        // A previous thread has already read the directory so there is nothing more to do, return a true result.
                        return(true);
                    }
                }
            }
            finally
            {
                if (result && RecordSubGridFileReadingToLog)
                {
                    _log.LogDebug($"Sub grid file {fullFileName} read from persistent store containing {subGrid.Directory.SegmentDirectory.Count} segments (Moniker: {subGrid.Moniker()}");
                }
            }

            return(result);
        }
예제 #30
0
        public FileSystemErrorStatus LoadLeafSubGridSegment(IStorageProxy storageProxy,
                                                            SubGridCellAddress cellAddress,
                                                            bool loadLatestData,
                                                            bool loadAllPasses,
                                                            IServerLeafSubGrid subGrid,
                                                            ISubGridCellPassesDataSegment segment)
        {
            //Log.LogInformation($"Segment load on {cellAddress}:{Segment.SegmentInfo.StartTime}-{Segment.SegmentInfo.EndTime} beginning, loadLatestData = {loadLatestData}, loadAllPasses = {loadAllPasses}");

            var needToLoadLatestData = loadLatestData && !segment.HasLatestData;
            var needToLoadAllPasses  = loadAllPasses && !segment.HasAllPasses;

            if (!needToLoadLatestData && !needToLoadAllPasses)
            {
                //Log.LogInformation($"Segment load on {cellAddress} exiting as neither latest nor all passes required");
                return(FileSystemErrorStatus.OK); // Nothing more to do here
            }

            // Lock the segment briefly while its contents is being loaded
            lock (segment)
            {
                if (!(needToLoadLatestData ^ segment.HasLatestData) && !(needToLoadAllPasses ^ segment.HasAllPasses))
                {
                    //Log.LogInformation($"Segment load on {cellAddress} leaving quietly as a previous thread has performed the load");
                    return(FileSystemErrorStatus.OK); // The load operation was performed on another thread. Leave quietly
                }

                // Ensure the appropriate storage is allocated
                if (needToLoadLatestData)
                {
                    segment.AllocateLatestPassGrid();
                }

                if (needToLoadAllPasses)
                {
                    segment.AllocateFullPassStacks();
                }

                if (!segment.SegmentInfo.ExistsInPersistentStore)
                {
                    //Log.LogInformation($"Segment load on {cellAddress} exiting as segment does not exist in persistent store");
                    return(FileSystemErrorStatus.OK); // Nothing more to do here
                }

                // Locate the segment file and load the data from it
                var fullFileName = GetLeafSubGridSegmentFullFileName(cellAddress, segment.SegmentInfo);

                // Load the cells into it from its file
                var fsError = subGrid.LoadSegmentFromStorage(storageProxy, fullFileName, segment, needToLoadLatestData, needToLoadAllPasses);

                if (fsError != FileSystemErrorStatus.OK)
                {
                    //Log.LogInformation($"Segment load on {cellAddress} failed, performing allocation cleanup activities");

                    // Something bad happened. Remove the segment from the list. Return failure to the caller.
                    if (loadAllPasses)
                    {
                        segment.DeAllocateFullPassStacks();
                    }

                    if (loadLatestData)
                    {
                        segment.DeAllocateLatestPassGrid();
                    }

                    return(fsError);
                }
            }

            //Log.LogInformation($"Segment load on {cellAddress} succeeded, AllPasses?={Segment.HasAllPasses}, Segment.PassesData?Null={Segment.PassesData==null} ");

            return(FileSystemErrorStatus.OK);
        }