Beispiel #1
0
        public void BuildLiftsForSinglePassCell_CMVPercentChange(float[] heights, short[] cmvs)
        {
            var siteModel = DITAGFileAndSubGridRequestsWithIgniteFixture.NewEmptyModel();
            var baseTime  = DateTime.UtcNow;

            var cellPasses = new[]
            {
                new CellPass
                {
                    Time   = baseTime,
                    Height = heights[0],
                    CCV    = cmvs[0]
                },
                new CellPass
                {
                    Time   = baseTime.AddHours(1),
                    Height = heights[1],
                    CCV    = cmvs[1]
                },
                new CellPass
                {
                    Time   = baseTime.AddHours(2),
                    Height = heights[2],
                    CCV    = cmvs[2]
                },
                new CellPass
                {
                    Time   = baseTime.AddHours(3),
                    Height = heights[3],
                    CCV    = cmvs[3]
                }
            };

            DITAGFileAndSubGridRequestsFixture.AddSingleCellWithPasses
                (siteModel, SubGridTreeConsts.DefaultIndexOriginOffset, SubGridTreeConsts.DefaultIndexOriginOffset, cellPasses);

            IClientLeafSubGrid clientGrid = ClientLeafSubGridFactoryFactory.CreateClientSubGridFactory().GetSubGrid(GridDataType.CCVPercentChange) as ClientCMVLeafSubGrid;

            var serverGrid = TRex.SubGridTrees.Server.Utilities.SubGridUtilities.LocateSubGridContaining(
                siteModel.PrimaryStorageProxy, siteModel.Grid,
                SubGridTreeConsts.DefaultIndexOriginOffset, SubGridTreeConsts.DefaultIndexOriginOffset,
                siteModel.Grid.NumLevels, false, false) as IServerLeafSubGrid;

            var builder = new CellLiftBuilder(siteModel, GridDataType.CCVPercentChange, new FilteredValuePopulationControl(),
                                              new FilterSet(new CombinedFilter()), new CellPassFastEventLookerUpper(siteModel));

            var cell = new ProfileCell();

            var segmentIterator  = new SubGridSegmentIterator(serverGrid, serverGrid.Directory, siteModel.PrimaryStorageProxy);
            var cellPassIterator = new SubGridSegmentCellPassIterator_NonStatic(segmentIterator);

            var filteredValueAssignmentContext = new FilteredValueAssignmentContext();

            builder.Build(cell, new LiftParameters(), clientGrid, filteredValueAssignmentContext, cellPassIterator, true).Should().BeTrue();

            cell.Layers.Count().Should().Be(1);
            cell.Layers[0].PassCount.Should().Be(4);
            filteredValueAssignmentContext.FilteredValue.FilteredPassData.FilteredPass.CCV.Should().Be(cmvs[cmvs.Length - 1]);
            filteredValueAssignmentContext.PreviousFilteredValue.FilteredPassData.FilteredPass.CCV.Should().Be(cmvs[cmvs.Length - 2]);
        }
Beispiel #2
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());
        }
Beispiel #3
0
        public void Test_SubGridSegmentIterator_SubGridSegmentIterator()
        {
            ServerSubGridTree  tree = new ServerSubGridTree(SubGridTreeConsts.SubGridTreeLevels, 1.0, new SubGridFactory <NodeSubGrid, ServerSubGridTreeLeaf>(), StorageMutability.Mutable);
            IServerLeafSubGrid leaf = new ServerSubGridTreeLeaf(tree, null, SubGridTreeConsts.SubGridTreeLevels, StorageMutability.Mutable);

            SubGridSegmentIterator iterator = new SubGridSegmentIterator(leaf, leaf.Directory, StorageProxy.Instance(StorageMutability.Mutable));

            Assert.True(iterator.Directory == leaf.Directory &&
                        iterator.SubGrid == leaf, "SubGrid segment iterator not correctly initialised");
        }
Beispiel #4
0
        public void BuildLiftsForMultiplePassCell(float height1, float height2, float height3, float first, float last, float lowest, float heighest)
        {
            var siteModel  = DITAGFileAndSubGridRequestsWithIgniteFixture.NewEmptyModel();
            var baseTime   = DateTime.UtcNow;
            var cellPasses = new[]
            {
                new CellPass
                {
                    Time   = baseTime,
                    Height = height1
                },
                new CellPass
                {
                    Time   = baseTime.AddHours(1),
                    Height = height2
                },
                new CellPass
                {
                    Time   = baseTime.AddHours(2),
                    Height = height3
                }
            };

            DITAGFileAndSubGridRequestsFixture.AddSingleCellWithPasses
                (siteModel, SubGridTreeConsts.DefaultIndexOriginOffset, SubGridTreeConsts.DefaultIndexOriginOffset, cellPasses);

            IClientLeafSubGrid clientGrid = ClientLeafSubGridFactoryFactory.CreateClientSubGridFactory().GetSubGrid(GridDataType.Height) as ClientHeightLeafSubGrid;

            var serverGrid = TRex.SubGridTrees.Server.Utilities.SubGridUtilities.LocateSubGridContaining(
                siteModel.PrimaryStorageProxy, siteModel.Grid,
                SubGridTreeConsts.DefaultIndexOriginOffset, SubGridTreeConsts.DefaultIndexOriginOffset,
                siteModel.Grid.NumLevels, false, false) as IServerLeafSubGrid;

            var builder = new CellLiftBuilder(siteModel, GridDataType.Height, new FilteredValuePopulationControl(),
                                              new FilterSet(new CombinedFilter()), new CellPassFastEventLookerUpper(siteModel));

            var cell = new ProfileCell();

            var segmentIterator  = new SubGridSegmentIterator(serverGrid, serverGrid.Directory, siteModel.PrimaryStorageProxy);
            var cellPassIterator = new SubGridSegmentCellPassIterator_NonStatic(segmentIterator);

            builder.Build(cell, new LiftParameters(), clientGrid, new FilteredValueAssignmentContext(), cellPassIterator, false).Should().BeTrue();

            cell.Layers.Count().Should().Be(1);
            cell.Layers[0].PassCount.Should().Be(3);
            cell.Layers[0].MinimumPassHeight.Should().Be(lowest);
            cell.Layers[0].MaximumPassHeight.Should().Be(heighest);
            cell.Layers[0].FirstPassHeight.Should().Be(first);
            cell.Layers[0].LastPassHeight.Should().Be(last);
        }
Beispiel #5
0
        public void Test_SubGridSegmentIterator_SetIteratorElevationRange()
        {
            ServerSubGridTree  tree = new ServerSubGridTree(SubGridTreeConsts.SubGridTreeLevels, 1.0, new SubGridFactory <NodeSubGrid, ServerSubGridTreeLeaf>(), StorageMutability.Mutable);
            IServerLeafSubGrid leaf = new ServerSubGridTreeLeaf(tree, null, SubGridTreeConsts.SubGridTreeLevels, StorageMutability.Mutable);

            SubGridSegmentIterator iterator = new SubGridSegmentIterator(leaf, leaf.Directory, StorageProxy.Instance(StorageMutability.Mutable));

            const double lowerElevation = 9.0;
            const double upperElevation = 19.0;

            iterator.SetIteratorElevationRange(lowerElevation, upperElevation);

            Assert.True(iterator.IterationState.MinIterationElevation == lowerElevation && iterator.IterationState.MaxIterationElevation == upperElevation,
                        "Elevation lower and upper bounds not set correctly");
        }
Beispiel #6
0
        public void Test_SubGridSegmentIterator_SetTimeRange()
        {
            ServerSubGridTree  tree = new ServerSubGridTree(SubGridTreeConsts.SubGridTreeLevels, 1.0, new SubGridFactory <NodeSubGrid, ServerSubGridTreeLeaf>(), StorageMutability.Mutable);
            IServerLeafSubGrid leaf = new ServerSubGridTreeLeaf(tree, null, SubGridTreeConsts.SubGridTreeLevels, StorageMutability.Mutable);

            SubGridSegmentIterator iterator = new SubGridSegmentIterator(leaf, leaf.Directory, StorageProxy.Instance(StorageMutability.Mutable));

            DateTime start = DateTime.SpecifyKind(new DateTime(2000, 1, 1, 1, 1, 1), DateTimeKind.Utc);
            DateTime end   = DateTime.SpecifyKind(new DateTime(2000, 1, 2, 1, 1, 1), DateTimeKind.Utc);

            iterator.SetTimeRange(start, end);

            Assert.True(iterator.IterationState.StartSegmentTime == start && iterator.IterationState.EndSegmentTime == end,
                        "Start and end time not set correctly");
        }
Beispiel #7
0
        public void Test_SubGridSegmentIterator_InitialiseIterator()
        {
            ServerSubGridTree  tree = new ServerSubGridTree(SubGridTreeConsts.SubGridTreeLevels, 1.0, new SubGridFactory <NodeSubGrid, ServerSubGridTreeLeaf>(), StorageMutability.Mutable);
            IServerLeafSubGrid leaf = new ServerSubGridTreeLeaf(tree, null, SubGridTreeConsts.SubGridTreeLevels, StorageMutability.Mutable);

            SubGridSegmentIterator iterator = new SubGridSegmentIterator(leaf, leaf.Directory,
                                                                         StorageProxy.Instance(StorageMutability.Mutable))
            {
                IterationDirection = IterationDirection.Forwards
            };

            iterator.InitialiseIterator();
            Assert.Equal(-1, iterator.IterationState.Idx);

            iterator.IterationDirection = IterationDirection.Backwards;
            iterator.InitialiseIterator();

            Assert.Equal(iterator.IterationState.Idx, leaf.Directory.SegmentDirectory.Count);
        }
Beispiel #8
0
        public void Test_SegmentIterator_MoveToFirstSegment()
        {
            var subGrid = MakeSubgridWith10240CellPassesAtOneSecondIntervals();

            var Iterator = new SubGridSegmentIterator(subGrid, StorageProxy.Instance(StorageMutability.Mutable))
            {
                IterationDirection = IterationDirection.Forwards,
                ReturnDirtyOnly    = true,
                RetrieveAllPasses  = true
            };

            Assert.True(Iterator.MoveToFirstSubGridSegment(), "Was not able to move to first segment (forwards) when requesting only dirty segments");

            Iterator = new SubGridSegmentIterator(subGrid, StorageProxy.Instance(StorageMutability.Mutable))
            {
                IterationDirection = IterationDirection.Backwards,
                ReturnDirtyOnly    = true,
                RetrieveAllPasses  = true
            };

            Assert.True(Iterator.MoveToFirstSubGridSegment(), "Was not able to move to first segment (backwards) when requesting only dirty segments");

            Iterator = new SubGridSegmentIterator(subGrid, StorageProxy.Instance(StorageMutability.Mutable))
            {
                IterationDirection = IterationDirection.Forwards,
                ReturnDirtyOnly    = false,
                RetrieveAllPasses  = true
            };

            Assert.True(Iterator.MoveToFirstSubGridSegment(), "Was not able to move to first segment (forwards) when requesting all segments");

            Iterator = new SubGridSegmentIterator(subGrid, StorageProxy.Instance(StorageMutability.Mutable))
            {
                IterationDirection = IterationDirection.Backwards,
                ReturnDirtyOnly    = false,
                RetrieveAllPasses  = true
            };

            Assert.True(Iterator.MoveToFirstSubGridSegment(), "Was not able to move to first segment (backwards) when requesting all segments");
        }
Beispiel #9
0
        public bool IntegrateSubGridTree(SubGridTreeIntegrationMode integrationMode,
                                         Action <int, int> subGridChangeNotifier)
        {
            // Iterate over the sub grids in source and merge the cell passes from source
            // into the sub grids in this sub grid tree;

            var iterator = new SubGridTreeIterator(_storageProxySubGrids, false)
            {
                Grid = _source
            };
            var segmentIterator = new SubGridSegmentIterator(null, _storageProxySubGridSegments)
            {
                IterationDirection = IterationDirection.Forwards
            };

            while (iterator.MoveToNextSubGrid())
            {
                var sourceSubGrid = iterator.CurrentSubGrid as IServerLeafSubGrid;

                /*
                 * // TODO: Terminated check for integration processing
                 * if (Terminated)
                 * {
                 *  // Service has been shutdown. Abort integration of changes and flag the
                 *  // operation as failed. The TAG file will be reprocessed when the service restarts
                 *  return false;
                 * }
                 */

                IntegrateSubGrid(sourceSubGrid, integrationMode, subGridChangeNotifier, segmentIterator);

                // Release the resources used by SourceSubGrid as this is the last point it is needed
                sourceSubGrid?.DeAllocateLeafFullPassStacks();
                sourceSubGrid?.DeAllocateLeafLatestPassGrid();
            }

            return(true);
        }
Beispiel #10
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);
        }
Beispiel #11
0
        private void CompareSiteModels(ISiteModel sm1, ISiteModel sm2,
                                       int expectedExistanceMapSubGridCount, int expectedCallPassCount, int expectedNonNullCelCount)
        {
            var bitCount1 = sm1.ExistenceMap.CountBits();
            var bitCount2 = sm2.ExistenceMap.CountBits();

            // Check both site models have the same number of sub grids in their existence maps
            bitCount1.Should().Be(bitCount2);
            bitCount1.Should().Be(expectedExistanceMapSubGridCount);

            // Check the content of the existence maps is identical
            var testMap = new SubGridTreeSubGridExistenceBitMask();

            testMap.SetOp_OR(sm1.ExistenceMap);
            testMap.SetOp_XOR(sm2.ExistenceMap);
            testMap.CountBits().Should().Be(0);

            // The expected distribution of cell pass counts
            long[] expectedCounts = { 93, 687, 68, 385, 57, 598, 65, 986, 52, 63, 0, 0, 0, 0, 0 };

            // Scan the leaves in each model and count cell passes
            int sm1Count     = 0;
            int sm1LeafCount = 0;

            long[] actualCounts1     = new long[15];
            int    segmentCount1     = 0;
            int    nonNullCellCount1 = 0;

            sm1.ExistenceMap.ScanAllSetBitsAsSubGridAddresses(address =>
            {
                sm1LeafCount++;
                var leaf     = SubGridUtilities.LocateSubGridContaining(sm1.PrimaryStorageProxy, sm1.Grid, address.X, address.Y, sm1.Grid.NumLevels, false, false) as IServerLeafSubGrid;
                var iterator = new SubGridSegmentIterator(leaf, sm1.PrimaryStorageProxy);
                while (iterator.MoveNext())
                {
                    segmentCount1++;
                    TRex.SubGridTrees.Core.Utilities.SubGridUtilities.SubGridDimensionalIterator((x, y) =>
                    {
                        var passCount = iterator.CurrentSubGridSegment.PassesData.PassCount(x, y);
                        sm1Count     += passCount;
                        if (passCount > 0)
                        {
                            nonNullCellCount1++;
                            actualCounts1[passCount - 1]++;
                        }
                    });
                }
            });

            int sm2Count     = 0;
            int sm2LeafCount = 0;

            long[] actualCounts2     = new long[15];
            int    segmentCount2     = 0;
            int    nonNullCellCount2 = 0;

            sm2.ExistenceMap.ScanAllSetBitsAsSubGridAddresses(address =>
            {
                sm2LeafCount++;
                var leaf     = SubGridUtilities.LocateSubGridContaining(sm2.PrimaryStorageProxy, sm2.Grid, address.X, address.Y, sm2.Grid.NumLevels, false, false) as IServerLeafSubGrid;
                var iterator = new SubGridSegmentIterator(leaf, sm2.PrimaryStorageProxy);
                while (iterator.MoveNext())
                {
                    segmentCount2++;
                    TRex.SubGridTrees.Core.Utilities.SubGridUtilities.SubGridDimensionalIterator((x, y) =>
                    {
                        var passCount = iterator.CurrentSubGridSegment.PassesData.PassCount(x, y);
                        sm2Count     += passCount;
                        if (passCount > 0)
                        {
                            nonNullCellCount2++;
                            actualCounts2[passCount - 1]++;
                        }
                    });
                }
            });

            segmentCount1.Should().Be(segmentCount2);
            segmentCount1.Should().Be(sm1LeafCount);

            sm1LeafCount.Should().Be(expectedExistanceMapSubGridCount);
            sm1Count.Should().Be(sm2Count);

            sm2LeafCount.Should().Be(expectedExistanceMapSubGridCount);
            sm1Count.Should().Be(expectedCallPassCount);

            actualCounts1.Should().BeEquivalentTo(actualCounts2);
            actualCounts1.Should().BeEquivalentTo(expectedCounts);

            nonNullCellCount1.Should().Be(nonNullCellCount2);
            nonNullCellCount1.Should().Be(expectedNonNullCelCount);
        }