/// <summary> /// Takes a site model spatial change map and incorporates those changes in the changes for each machine in the /// site model. /// Once items are processed they are removed from the change map queue retirement queue. /// </summary> private bool ProcessItem(ISiteModelChangeBufferQueueItem item) { try { if (item == null) { _log.LogError("Item supplied to queue processor is null. Aborting"); return(false); } if (item.Content == null) { _log.LogError("Item supplied to queue processor has no internal content. Aborting"); return(false); } var siteModel = DIContext.Obtain <ISiteModels>().GetSiteModel(item.ProjectUID); if (siteModel == null) { _log.LogError($"Site model {item.ProjectUID} does not exist [deleted?]. Aborting"); return(false); } // Implement change map integration into machine change maps // 0. Obtain transaction (will create implicit locks on items) // 1. Read record for machine // 2. Integrate new map // 3. Write record back to store // 4. Commit transaction _log.LogInformation($"Processing an item: {item.Operation}, project:{item.ProjectUID}, machine:{item.MachineUid}"); var sw = Stopwatch.StartNew(); switch (item.Operation) { case SiteModelChangeMapOperation.AddSpatialChanges: // Add the two of them together... { // Add the spatial change to every machine in the site model foreach (var machine in siteModel.Machines) { var l = _changeMapProxy.Lock(item.ProjectUID, machine.ID); l.Enter(); try { var currentMask = _changeMapProxy.Get(item.ProjectUID, machine.ID); if (currentMask == null) { currentMask = new SubGridTreeSubGridExistenceBitMask(); currentMask.SetOp_OR(siteModel.ExistenceMap); } // Extract the change map from the item var updateMask = new SubGridTreeSubGridExistenceBitMask(); updateMask.FromBytes(item.Content); currentMask.SetOp_OR(updateMask); _changeMapProxy.Put(item.ProjectUID, machine.ID, currentMask); } finally { l.Exit(); } } break; } case SiteModelChangeMapOperation.RemoveSpatialChanges: // Subtract from the change map... { var l = _changeMapProxy.Lock(item.ProjectUID, item.MachineUid); l.Enter(); try { // Remove the spatial change only from the machine the made the query var currentMask = _changeMapProxy.Get(item.ProjectUID, item.MachineUid); if (currentMask != null) { // Extract the change map from the item var updateMask = new SubGridTreeSubGridExistenceBitMask(); currentMask.SetOp_ANDNOT(updateMask); _changeMapProxy.Put(item.ProjectUID, item.MachineUid, currentMask); } } finally { l.Exit(); } break; } default: _log.LogError($"Unknown operation encountered: {(int) item.Operation}"); return(false); } _log.LogInformation($"Completed processing an item in {sw.Elapsed}: {item.Operation}, project:{item.ProjectUID}, machine:{item.MachineUid}"); return(true); } catch (Exception e) { _log.LogError(e, "Exception thrown while processing queued items:"); throw; } }
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); }