< Summary

Information
Class: Trailblazer.Pathing.NavigationAutomaticSeamRefreshWork
Assembly: Trailblazer
File(s): /home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Graph/NavigationAutomaticSeamRefreshWork.cs
Line coverage
100%
Covered lines: 1036
Uncovered lines: 0
Coverable lines: 1036
Total lines: 1692
Line coverage: 100%
Branch coverage
100%
Covered branches: 536
Total branches: 536
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor(...)100%11100%
.ctor(...)100%11100%
.ctor(...)100%11100%
get_Result()100%11100%
get_IsComplete()100%11100%
get_ChangedMapCount()100%11100%
GetChangedMapIdAt(...)100%11100%
get_ChangedStructuralEndpointCount()100%11100%
GetChangedStructuralEndpointAt(...)100%11100%
RevalidateForPublication()100%11100%
get_RetainedBytes()100%1616100%
get_PersistentPageCount()100%1414100%
AdvanceOne(...)100%1414100%
AdvanceGather(...)100%2626100%
TrySetupNextMode(...)100%4242100%
TrySetupFullRebuildMode(...)100%88100%
TrySetupNextGridEventMode(...)100%2222100%
AdvanceMode(...)100%1616100%
CompleteMapMode()100%22100%
AdvanceDiscovery(...)100%66100%
AdvanceDiscoveryAfterCursorStart(...)100%88100%
AdvanceBegunDiscovery(...)100%1212100%
PrepareDiscoveredPair(...)100%88100%
AdvanceQueuedMutation(...)100%88100%
CoalescePendingMutation()100%1010100%
BeginPairApplication()100%22100%
AdvancePairApplication(...)100%7878100%
NormalizeCurrentPairDelta()100%1212100%
GetUncertifiedCount(...)100%44100%
TouchAddress(...)100%22100%
AppendAddressPair(...)100%22100%
AddLinkDelta(...)100%66100%
SealSecondaryJournals()100%44100%
AdvanceAddressApplication(...)100%2828100%
BeginRow(...)100%22100%
AdvanceRow(...)100%4646100%
ShouldFilterSourcePair(...)100%22100%
ShouldFilterChangedPair(...)100%44100%
AdvanceLinkApplication(...)100%5252100%
ConsumeCurrentLinkDelta()100%11100%
ClearRowEnumeration()100%11100%
SealResult()100%22100%
RevalidateCompletedCursor()100%22100%
IsCompletedCursorCurrent()100%66100%
RestartDiscoveryAfterInvalidation()100%11100%
BeginMapMode(...)100%11100%
BeginAddressMode(...)100%11100%
BeginDiscovery(...)100%11100%
QueueMutation(...)100%11100%
FinishMode()100%11100%
TryGetCurrentPair(...)100%66100%
EnsurePairEditor()100%22100%
EnsureAddressEditor()100%22100%
EnsureLinkEditor()100%22100%
AddChangedMapId(...)100%22100%
RecordAddressPayloadChange(...)100%11100%
GetPairJournalBytes()100%66100%
GetPairJournalPages()100%66100%
GetAddressJournalBytes()100%66100%
GetAddressJournalPages()100%66100%
GetLinkJournalBytes()100%66100%
GetLinkJournalPages()100%66100%
ResetToSource()100%11100%
ComparePairs(...)100%11100%
.ctor(...)100%44100%
.ctor()100%11100%
get_RetainedBytes()100%44100%
get_PersistentPageCount()100%44100%
AppendDependency(...)100%22100%
AppendActive(...)100%22100%
SealAdditions()100%44100%
ReleaseAdditions()100%11100%

File(s)

/home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Graph/NavigationAutomaticSeamRefreshWork.cs

#LineLine coverage
 1//=======================================================================
 2// NavigationAutomaticSeamRefreshWork.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using System;
 9using GridForge.Configuration;
 10using GridForge.Grids;
 11using GridForge.Grids.Topology;
 12
 13namespace Trailblazer.Pathing;
 14
 15/// <summary>Applies bounded incident automatic-seam changes to one unpublished graph candidate.</summary>
 16internal sealed class NavigationAutomaticSeamRefreshWork
 17{
 18    internal const long FixedRetainedBytes = 3_480L;
 19
 20    private const int CursorHeight = 64;
 21    private const int PairDeltaNodeBytes = 104;
 22    private const int AddressDeltaNodeBytes = 80;
 23    private const int LinkDeltaNodeBytes = 72;
 24    private const long PairDeltaBytes = 40L;
 25    private const long AddressDeltaBytes = 56L;
 26    private const long LinkDeltaBytes = 24L;
 27
 128    private static readonly NavigationSeamEditTree<NavigationAutomaticSeamPairKey, PairDelta>
 129        EmptyPairDeltas = new(PairDeltaNodeBytes);
 130    private static readonly NavigationSeamEditTree<NavigationCellAddress, AddressDelta>
 131        EmptyAddressDeltas = new(AddressDeltaNodeBytes);
 132    private static readonly NavigationSeamEditTree<NavigationAutomaticSeamLinkKey, LinkDelta>
 133        EmptyLinkDeltas = new(LinkDeltaNodeBytes);
 34
 35    private readonly GridWorld _world;
 36    private readonly NavigationWorldGraph _sourceGraph;
 37    private readonly NavigationWorldGraph _preparedGraph;
 38    private readonly NavigationOperationFrameChange[] _changes;
 39    private readonly int _changeCount;
 40    private readonly GridEventInfo[] _gridEvents;
 41    private readonly int _gridEventCount;
 42    private readonly PersistentStringMap<bool> _discoveryMapIds;
 43    private readonly bool _fullRebuild;
 44    private NavigationSeamEditToken _ownershipToken;
 324245    private GridBoundaryContactCursor _cursor = new();
 324246    private GridBoundaryContactCursor _validatorCursor = new();
 324247    private readonly GridBoundaryContact[] _contact = new GridBoundaryContact[1];
 48    private NavigationAutomaticSeamIndex _working;
 324249    private PersistentStringMap<bool> _changedMapIds = PersistentStringMap<bool>.Empty;
 324250    private NavigationCellAddressSet _changedStructuralEndpoints =
 324251        NavigationCellAddressSet.Empty;
 52
 53    private NavigationSeamEditTree<NavigationAutomaticSeamPairKey, PairDelta>.Editor? _pairEditor;
 54    private NavigationSeamEditTree<NavigationAutomaticSeamPairKey, PairDelta>? _pairDeltas;
 55    private NavigationSeamEditTree<NavigationAutomaticSeamPairKey, PairDelta>.Cursor? _pairCursor;
 56    private NavigationSeamEditTree<NavigationCellAddress, AddressDelta>.Editor? _addressEditor;
 57    private NavigationSeamEditTree<NavigationCellAddress, AddressDelta>? _addressDeltas;
 58    private NavigationSeamEditTree<NavigationCellAddress, AddressDelta>.Cursor? _addressCursor;
 59    private NavigationSeamEditTree<NavigationAutomaticSeamLinkKey, LinkDelta>.Editor? _linkEditor;
 60    private NavigationSeamEditTree<NavigationAutomaticSeamLinkKey, LinkDelta>? _linkDeltas;
 61    private NavigationSeamEditTree<NavigationAutomaticSeamLinkKey, LinkDelta>.Cursor? _linkCursor;
 62    private NavigationAutomaticSeamIndex.EditSession? _indexEditor;
 63
 64    private NavigationSeamEditTree<NavigationCellAddress, NavigationPagedSequence<NavigationAutomaticSeamPair>>.Cursor?
 65        _dependencyCursor;
 66    private NavigationAutomaticSeamIndex.EndpointEnumerator _dependencyRow;
 67    private NavigationCellAddress _dependencyAddress;
 68    private int _dependencyRowRemaining;
 69
 70    private NavigationAutomaticSeamPair? _pendingPair;
 71    private MutationKind _pendingMutation;
 72    private int _mutationStage;
 73    private bool _pendingPairOwned;
 74
 75    private PairDelta? _currentPairDelta;
 76    private NavigationAutomaticSeamPairKey _currentPairKey;
 77    private int _pairApplyStage;
 78    private bool _currentGeometryChanged;
 79    private bool _currentActiveChanged;
 80    private bool _currentActiveRowChanged;
 81    private bool _currentStructuralLinkChanged;
 82
 83    private AddressDelta? _currentAddressDelta;
 84    private NavigationCellAddress _currentAddress;
 85    private int _addressApplyStage;
 86    private RowKind _rowKind;
 87    private NavigationPagedSequence<NavigationAutomaticSeamPair>.Enumerator _sourceRow;
 88    private NavigationPagedSequence<NavigationAutomaticSeamPair>.Enumerator _additionRow;
 89    private bool _sourceRowHasNext;
 90    private bool _sourceRowComplete;
 91    private bool _additionRowHasNext;
 92    private bool _additionRowComplete;
 93    private NavigationAutomaticSeamPair? _sourceRowPair;
 94    private NavigationAutomaticSeamPair? _additionRowPair;
 95    private NavigationAutomaticSeamPair? _pendingRowOutput;
 96    private NavigationPagedSequence<NavigationAutomaticSeamPair>.Builder? _rowBuilder;
 97
 98    private NavigationAutomaticSeamLinkKey _currentLinkKey;
 99    private LinkDelta? _currentLinkDelta;
 100    private bool _linkDeltaReady;
 101    private bool _linkDeltaComplete;
 102    private string? _linkSourceMapId;
 103    private NavigationPagedSequence<NavigationStructuralLink>.Enumerator _sourceLinks;
 104    private bool _sourceLinkReady;
 105    private bool _sourceLinksComplete;
 106    private NavigationStructuralLink _sourceLink;
 107    private NavigationStructuralLink? _pendingLinkOutput;
 108    private NavigationPagedSequence<NavigationStructuralLink>.Builder? _linkBuilder;
 109
 110    private long _pairDeltaPayloadBytes;
 111    private int _pairDeltaPayloadPages;
 112    private long _addressDeltaPayloadBytes;
 113    private int _addressDeltaPayloadPages;
 114    private long _linkDeltaPayloadBytes;
 115    private int _linkDeltaPayloadPages;
 116    private long _sealedIndexBytes;
 117    private int _sealedIndexPages;
 118
 119    private string? _modeMapId;
 120    private GridConfigurationKey _pendingDiscoveryKey;
 121    private int _changeIndex;
 122    private int _overlayMapIndex;
 123    private int _overlayCellIndex;
 124    private int _gridEventIndex;
 125    private int _discoveryMapIndex;
 126    private int _worldResetMapIndex;
 127    private int _fullRebuildRemoveMapIndex;
 128    private int _fullRebuildDiscoverMapIndex;
 129    private bool _worldResetPending;
 130    private bool _overlayMapInspected;
 131    private WorkMode _mode;
 132    private WorkPhase _phase;
 133    private GridBoundaryContactRunStamp _runStamp;
 134    private bool _hasRunStamp;
 135    private bool _cursorBegun;
 136    private bool _hasValidatorCursor;
 137    private bool _complete;
 138
 2151139    internal NavigationAutomaticSeamRefreshWork(
 2151140        GridWorld world,
 2151141        NavigationWorldGraph sourceGraph,
 2151142        NavigationWorldGraph preparedGraph,
 2151143        NavigationOperationFrameChange[] changes,
 2151144        int changeCount)
 145    {
 2151146        _world = world;
 2151147        _sourceGraph = sourceGraph;
 2151148        _preparedGraph = preparedGraph;
 2151149        _changes = changes;
 2151150        _changeCount = changeCount;
 2151151        _gridEvents = Array.Empty<GridEventInfo>();
 2151152        _gridEventCount = 0;
 2151153        _discoveryMapIds = PersistentStringMap<bool>.Empty;
 2151154        _fullRebuild = false;
 2151155        _working = sourceGraph.AutomaticSeams;
 2151156        _ownershipToken = NavigationSeamEditToken.Create();
 2151157    }
 158
 1066159    internal NavigationAutomaticSeamRefreshWork(
 1066160        GridWorld world,
 1066161        NavigationWorldGraph sourceGraph,
 1066162        NavigationWorldGraph preparedGraph,
 1066163        GridEventInfo[] gridEvents,
 1066164        int gridEventCount,
 1066165        bool fullRebuild = false)
 166    {
 1066167        _world = world;
 1066168        _sourceGraph = sourceGraph;
 1066169        _preparedGraph = preparedGraph;
 1066170        _changes = Array.Empty<NavigationOperationFrameChange>();
 1066171        _changeCount = 0;
 1066172        _gridEvents = gridEvents;
 1066173        _gridEventCount = gridEventCount;
 1066174        _discoveryMapIds = PersistentStringMap<bool>.Empty;
 1066175        _fullRebuild = fullRebuild;
 1066176        _working = sourceGraph.AutomaticSeams;
 1066177        _ownershipToken = NavigationSeamEditToken.Create();
 1066178    }
 179
 25180    internal NavigationAutomaticSeamRefreshWork(
 25181        GridWorld world,
 25182        NavigationWorldGraph sourceGraph,
 25183        NavigationWorldGraph preparedGraph,
 25184        PersistentStringMap<bool> discoveryMapIds)
 185    {
 25186        _world = world;
 25187        _sourceGraph = sourceGraph;
 25188        _preparedGraph = preparedGraph;
 25189        _changes = Array.Empty<NavigationOperationFrameChange>();
 25190        _changeCount = 0;
 25191        _gridEvents = Array.Empty<GridEventInfo>();
 25192        _gridEventCount = 0;
 25193        _discoveryMapIds = discoveryMapIds;
 25194        _fullRebuild = false;
 25195        _working = sourceGraph.AutomaticSeams;
 25196        _ownershipToken = NavigationSeamEditToken.Create();
 25197    }
 198
 1200199    internal NavigationAutomaticSeamIndex Result => _working;
 200
 238499201    internal bool IsComplete => _complete;
 202
 203    internal bool GeometryChanged { get; private set; }
 204
 205    internal bool StructuralLinksChanged { get; private set; }
 206
 207    internal long Revision { get; private set; }
 208
 1524209    internal int ChangedMapCount => _changedMapIds.Count;
 210
 352211    internal string GetChangedMapIdAt(int ordinal) => _changedMapIds.GetKeyAt(ordinal);
 212
 3341213    internal int ChangedStructuralEndpointCount => _changedStructuralEndpoints.Count;
 214
 215    internal NavigationCellAddress GetChangedStructuralEndpointAt(int ordinal) =>
 463216        _changedStructuralEndpoints.GetAt(ordinal);
 217
 540218    internal bool RevalidateForPublication() => RevalidateCompletedCursor();
 219
 265297220    internal long RetainedBytes => checked(
 265297221        FixedRetainedBytes
 265297222        + (ReferenceEquals(_changedMapIds, PersistentStringMap<bool>.Empty)
 265297223            ? 0L
 265297224            : _changedMapIds.RetainedBytes)
 265297225        + (ReferenceEquals(_discoveryMapIds, PersistentStringMap<bool>.Empty)
 265297226            ? 0L
 265297227            : _discoveryMapIds.RetainedBytes)
 265297228        + (ReferenceEquals(_changedStructuralEndpoints, NavigationCellAddressSet.Empty)
 265297229            ? 0L
 265297230            : _changedStructuralEndpoints.RetainedBytes)
 265297231        + (_pendingPairOwned ? NavigationAutomaticSeamPair.RetainedSize : 0L)
 265297232        + GetPairJournalBytes()
 265297233        + GetAddressJournalBytes()
 265297234        + GetLinkJournalBytes()
 265297235        + (_dependencyCursor?.RetainedBytes ?? 0L)
 265297236        + (_indexEditor?.RetainedBytes ?? _sealedIndexBytes)
 265297237        + (_rowBuilder?.RetainedBytes ?? 0L)
 265297238        + (_linkBuilder?.RetainedBytes ?? 0L));
 239
 265640240    internal int PersistentPageCount => checked(
 265640241        4
 265640242        + (ReferenceEquals(_changedMapIds, PersistentStringMap<bool>.Empty)
 265640243            ? 0
 265640244            : 1 + _changedMapIds.PersistentNodeCount)
 265640245        + (ReferenceEquals(_discoveryMapIds, PersistentStringMap<bool>.Empty)
 265640246            ? 0
 265640247            : 1 + _discoveryMapIds.PersistentNodeCount)
 265640248        + (ReferenceEquals(_changedStructuralEndpoints, NavigationCellAddressSet.Empty)
 265640249            ? 0
 265640250            : _changedStructuralEndpoints.PersistentPageCount)
 265640251        + (_pendingPairOwned ? 1 : 0)
 265640252        + GetPairJournalPages()
 265640253        + GetAddressJournalPages()
 265640254        + GetLinkJournalPages()
 265640255        + (_dependencyCursor?.PersistentPageCount ?? 0)
 265640256        + (_indexEditor?.PersistentPageCount ?? _sealedIndexPages)
 265640257        + (_rowBuilder?.PersistentPageCount ?? 0)
 265640258        + (_linkBuilder?.PersistentPageCount ?? 0));
 259
 260    internal SeamAdvanceStatus AdvanceOne(MaintenanceWorkMeter meter)
 261    {
 234111262        if (_complete)
 2263            return RevalidateCompletedCursor()
 2264                ? SeamAdvanceStatus.Complete
 2265                : SeamAdvanceStatus.Blocked;
 234109266        bool progressed = false;
 234109267        switch (_phase)
 268        {
 269            case WorkPhase.Gather:
 125778270                progressed = AdvanceGather(meter);
 125778271                break;
 272            case WorkPhase.ApplyPairs:
 58209273                progressed = AdvancePairApplication(meter);
 58209274                break;
 275            case WorkPhase.ApplyAddresses:
 47598276                progressed = AdvanceAddressApplication(meter);
 47598277                break;
 278            case WorkPhase.ApplyLinks:
 2343279                progressed = AdvanceLinkApplication(meter);
 2343280                break;
 281            case WorkPhase.Seal:
 181282                progressed = SealResult();
 283                break;
 284        }
 234109285        if (_complete)
 1183286            return SeamAdvanceStatus.Complete;
 232926287        return progressed ? SeamAdvanceStatus.Progressed : SeamAdvanceStatus.Blocked;
 288    }
 289
 290    private bool AdvanceGather(MaintenanceWorkMeter meter)
 291    {
 125778292        if (_pendingPair != null)
 49758293            return AdvanceQueuedMutation(meter);
 76020294        if (_mode != WorkMode.None)
 56806295            return AdvanceMode(meter);
 19214296        if (TrySetupNextMode(meter))
 17823297            return true;
 1391298        if ((!_fullRebuild && _worldResetPending)
 1391299            || (_fullRebuild
 1391300                && (_fullRebuildRemoveMapIndex < _sourceGraph.MapCount
 1391301                    || _fullRebuildDiscoverMapIndex < _preparedGraph.MapCount))
 1391302            || (!_fullRebuild && _gridEventIndex < _gridEventCount)
 1391303            || _discoveryMapIndex < _discoveryMapIds.Count
 1391304            || _changeIndex < _changeCount)
 204305            return false;
 1187306        if (!RevalidateCompletedCursor())
 1307            return false;
 1186308        BeginPairApplication();
 1186309        return true;
 310    }
 311
 312    private bool TrySetupNextMode(MaintenanceWorkMeter meter)
 313    {
 19214314        if (_fullRebuild)
 315        {
 73316            if (TrySetupFullRebuildMode(meter))
 48317                return true;
 25318            if (_fullRebuildRemoveMapIndex < _sourceGraph.MapCount
 25319                || _fullRebuildDiscoverMapIndex < _preparedGraph.MapCount)
 320            {
 10321                return false;
 322            }
 323        }
 19141324        else if (TrySetupNextGridEventMode(meter))
 325        {
 30326            return true;
 327        }
 19126328        while (_discoveryMapIndex < _discoveryMapIds.Count)
 329        {
 38330            if (!meter.TryConsumeComponentNodes(1))
 11331                return false;
 27332            string mapId = _discoveryMapIds.GetKeyAt(_discoveryMapIndex++);
 27333            if (_preparedGraph.TryGetMap(mapId, out NavigationMapInstance instance))
 334            {
 27335                _pendingDiscoveryKey = instance.Map.GridBinding.Key;
 27336                BeginMapMode(mapId, WorkMode.RevalidateMap);
 27337                return true;
 338            }
 339        }
 19278340        while (_changeIndex < _changeCount)
 341        {
 18088342            NavigationOperationFrameChange change = _changes[_changeIndex];
 18088343            if (change.Kind == NavigationOperationFrameChangeKind.MapCommit)
 344            {
 1280345                if (!meter.TryConsumeComponentNodes(1))
 143346                    return false;
 1137347                _changeIndex++;
 1137348                string mapId = change.MapId!;
 1137349                _sourceGraph.TryGetMap(mapId, out NavigationMapInstance? prior);
 1137350                _preparedGraph.TryGetMap(mapId, out NavigationMapInstance? next);
 1137351                if (next == null)
 352                    continue;
 1136353                if (prior == null)
 354                {
 1096355                    BeginDiscovery(next.Map.GridBinding.Key);
 1096356                    return true;
 357                }
 40358                if (!prior.Map.GridBinding.Key.Equals(next.Map.GridBinding.Key))
 359                {
 1360                    _pendingDiscoveryKey = next.Map.GridBinding.Key;
 1361                    BeginMapMode(mapId, WorkMode.RemoveMap);
 1362                    return true;
 363                }
 39364                BeginMapMode(mapId, WorkMode.RevalidateMap);
 39365                return true;
 366            }
 16808367            if (change.Kind == NavigationOperationFrameChangeKind.MapRemove)
 368            {
 11369                if (!meter.TryConsumeComponentNodes(1))
 1370                    return false;
 10371                _changeIndex++;
 10372                BeginMapMode(change.MapId!, WorkMode.RemoveMap);
 10373                return true;
 374            }
 375
 16797376            ReadOnlySpan<NavigationMapOverlayDelta> maps =
 16797377                change.PreparedOverlay!.Transaction.MapSpan;
 17001378            while (_overlayMapIndex < maps.Length)
 379            {
 16812380                if (!_overlayMapInspected)
 381                {
 238382                    if (!meter.TryConsumeComponentNodes(1))
 34383                        return false;
 204384                    _overlayMapInspected = true;
 385                }
 16778386                ReadOnlySpan<NavigationCellOverlayOperation> cells = maps[_overlayMapIndex].CellSpan;
 16778387                if (_overlayCellIndex < cells.Length)
 388                {
 16574389                    if (!meter.TryConsumeDependencyEntries(1))
 2390                        return false;
 16572391                    NavigationCellAddress address = new(
 16572392                        maps[_overlayMapIndex].MapId,
 16572393                        cells[_overlayCellIndex++].Index);
 16572394                    BeginAddressMode(address);
 16572395                    return true;
 396                }
 204397                _overlayMapIndex++;
 204398                _overlayCellIndex = 0;
 204399                _overlayMapInspected = false;
 400            }
 189401            _overlayMapIndex = 0;
 189402            _overlayMapInspected = false;
 189403            _changeIndex++;
 404        }
 1190405        return false;
 406    }
 407
 408    private bool TrySetupFullRebuildMode(MaintenanceWorkMeter meter)
 409    {
 73410        if (_fullRebuildRemoveMapIndex < _sourceGraph.MapCount)
 411        {
 26412            if (!meter.TryConsumeComponentNodes(1))
 2413                return false;
 24414            BeginMapMode(
 24415                _sourceGraph.GetInstance(_fullRebuildRemoveMapIndex++).MapId,
 24416                WorkMode.RemoveMap);
 24417            return true;
 418        }
 47419        if (_fullRebuildDiscoverMapIndex < _preparedGraph.MapCount)
 420        {
 32421            if (!meter.TryConsumeComponentNodes(1))
 8422                return false;
 24423            BeginDiscovery(
 24424                _preparedGraph.GetInstance(_fullRebuildDiscoverMapIndex++)
 24425                    .Map.GridBinding.Key);
 24426            return true;
 427        }
 15428        return false;
 429    }
 430
 431    private bool TrySetupNextGridEventMode(MaintenanceWorkMeter meter)
 432    {
 19141433        while (_worldResetPending || _gridEventIndex < _gridEventCount)
 434        {
 33435            if (_worldResetPending)
 436            {
 3437                if (_worldResetMapIndex < _sourceGraph.MapCount)
 438                {
 2439                    if (!meter.TryConsumeComponentNodes(1))
 1440                        return false;
 1441                    BeginMapMode(
 1442                        _sourceGraph.GetInstance(_worldResetMapIndex++).MapId,
 1443                        WorkMode.RemoveMap);
 1444                    return true;
 445                }
 1446                _worldResetPending = false;
 1447                _worldResetMapIndex = 0;
 1448                _gridEventIndex++;
 1449                return true;
 450            }
 451
 30452            if (!meter.TryConsumeComponentNodes(1))
 2453                return false;
 28454            GridEventInfo eventInfo = _gridEvents[_gridEventIndex];
 28455            GridConfigurationKey key = eventInfo.Configuration.ToGridKey();
 28456            switch (eventInfo.ChangeKind)
 457            {
 458                case GridEventKind.GridRemoved:
 11459                    _gridEventIndex++;
 11460                    if (_sourceGraph.TryGetMapId(key, out string removedMapId))
 461                    {
 10462                        BeginMapMode(removedMapId, WorkMode.RemoveMap);
 10463                        return true;
 464                    }
 465                    break;
 466                case GridEventKind.GridAdded:
 15467                    _gridEventIndex++;
 15468                    if (_preparedGraph.TryGetMapId(key, out _))
 469                    {
 14470                        BeginDiscovery(key);
 14471                        return true;
 472                    }
 473                    break;
 474                case GridEventKind.WorldReset:
 1475                    _worldResetPending = true;
 1476                    _worldResetMapIndex = 0;
 1477                    return true;
 478                default:
 1479                    _gridEventIndex++;
 480                    break;
 481            }
 3482            return true;
 483        }
 19108484        return false;
 485    }
 486
 487    private bool AdvanceMode(MaintenanceWorkMeter meter)
 488    {
 56806489        if (_mode == WorkMode.Discover)
 39892490            return AdvanceDiscovery(meter);
 16914491        if (_dependencyRowRemaining > 0)
 492        {
 155493            if (!meter.TryConsumeDependencyEntries(1))
 1494                return false;
 154495            _dependencyRow.MoveNext();
 154496            NavigationAutomaticSeamPair pair = _dependencyRow.Current.Pair;
 154497            _dependencyRowRemaining--;
 154498            QueueMutation(
 154499                pair,
 154500                _mode == WorkMode.RemoveMap ? MutationKind.Remove : MutationKind.Revalidate);
 154501            return true;
 502        }
 16759503        if (_mode == WorkMode.RevalidateAddress)
 504        {
 16572505            FinishMode();
 16572506            return true;
 507        }
 187508        if (!_dependencyCursor!.HasNext)
 98509            return CompleteMapMode();
 89510        if (!meter.TryConsumeDependencyEntries(1))
 3511            return false;
 86512        _dependencyCursor.MoveNext();
 86513        NavigationCellAddress address = _dependencyCursor.CurrentKey;
 86514        if (!address.MapId.Equals(_modeMapId, StringComparison.Ordinal))
 14515            return CompleteMapMode();
 72516        _dependencyAddress = address;
 72517        NavigationPagedSequence<NavigationAutomaticSeamPair> row =
 72518            _sourceGraph.AutomaticSeams.GetDependencyRow(address);
 72519        _dependencyRow = new NavigationAutomaticSeamIndex.EndpointEnumerator(address, row);
 72520        _dependencyRowRemaining = row.Count;
 72521        return true;
 522    }
 523
 524    private bool CompleteMapMode()
 525    {
 526        System.Diagnostics.Debug.Assert(
 527            _pendingDiscoveryKey.Equals(default(GridConfigurationKey))
 528                || _mode is WorkMode.RemoveMap or WorkMode.RevalidateMap,
 529            "A queued discovery is owned by the map mode that must complete before it begins.");
 112530        FinishMode();
 112531        if (!_pendingDiscoveryKey.Equals(default(GridConfigurationKey)))
 532        {
 28533            GridConfigurationKey key = _pendingDiscoveryKey;
 28534            _pendingDiscoveryKey = default;
 28535            BeginDiscovery(key);
 536        }
 112537        return true;
 538    }
 539
 540    private bool AdvanceDiscovery(MaintenanceWorkMeter meter)
 541    {
 39892542        if (!_cursorBegun)
 543        {
 1159544            if (!RevalidateCompletedCursor())
 1545                return false;
 1158546            bool began = _world.TryBeginBoundaryContacts(_pendingDiscoveryKey, _cursor);
 1158547            bool completedCursorCurrent = true;
 1158548            if (!began)
 36549                completedCursorCurrent = IsCompletedCursorCurrent();
 1158550            return AdvanceDiscoveryAfterCursorStart(
 1158551                meter,
 1158552                began,
 1158553                completedCursorCurrent,
 1158554                _hasRunStamp,
 1158555                !(_cursor.RunStamp != _runStamp));
 556        }
 557
 38733558        return AdvanceBegunDiscovery(meter);
 559    }
 560
 561    internal bool AdvanceDiscoveryAfterCursorStart(
 562        MaintenanceWorkMeter meter,
 563        bool began,
 564        bool completedCursorCurrent,
 565        bool hadRunStamp,
 566        bool runStampMatches)
 567    {
 1161568        if (!began)
 569        {
 38570            if (!completedCursorCurrent)
 1571                return RestartDiscoveryAfterInvalidation();
 37572            _pendingDiscoveryKey = default;
 37573            FinishMode();
 37574            return true;
 575        }
 1123576        if (hadRunStamp && !runStampMatches)
 1577            return RestartDiscoveryAfterInvalidation();
 1122578        _runStamp = _cursor.RunStamp;
 1122579        _hasRunStamp = true;
 1122580        _cursorBegun = true;
 1122581        return AdvanceBegunDiscovery(meter);
 582    }
 583
 584    private bool AdvanceBegunDiscovery(MaintenanceWorkMeter meter)
 585    {
 39855586        GridBoundaryContactCursorStatus status = _world.AdvanceBoundaryContacts(
 39855587            _cursor,
 39855588            _contact,
 39855589            meter.RemainingSeamCandidateProbes,
 39855590            outputLimit: 1,
 39855591            out int consumed,
 39855592            out int outputCount);
 39855593        meter.TryConsumeSeamCandidateProbes(consumed);
 39855594        if (status == GridBoundaryContactCursorStatus.Stale
 39855595            || _cursor.RunStamp != _runStamp)
 596        {
 1597            return RestartDiscoveryAfterInvalidation();
 598        }
 39854599        if (outputCount != 0)
 38293600            PrepareDiscoveredPair(_contact[0]);
 601        System.Diagnostics.Debug.Assert(
 602            status != GridBoundaryContactCursorStatus.Complete || outputCount == 0,
 603            "A one-output boundary-contact advance returns More as soon as it emits that output.");
 39854604        if (status == GridBoundaryContactCursorStatus.Complete)
 605        {
 1121606            GridBoundaryContactCursor previousValidator = _validatorCursor;
 1121607            _validatorCursor = _cursor;
 1121608            _cursor = previousValidator;
 1121609            _hasValidatorCursor = true;
 1121610            _cursorBegun = false;
 1121611            _pendingDiscoveryKey = default;
 1121612            FinishMode();
 613        }
 39854614        return outputCount != 0 || consumed != 0
 39854615            || status == GridBoundaryContactCursorStatus.Complete;
 616    }
 617
 618    private void PrepareDiscoveredPair(GridBoundaryContact contact)
 619    {
 38293620        if (!_preparedGraph.TryGetMapId(contact.SourceConfigurationKey, out string sourceMapId)
 38293621            || !_preparedGraph.TryGetMapId(contact.TargetConfigurationKey, out string targetMapId))
 622        {
 35623            return;
 624        }
 38258625        NavigationCellAddress first = new(sourceMapId, contact.Contact.Source.VoxelIndex);
 38258626        NavigationCellAddress second = new(targetMapId, contact.Contact.Target.VoxelIndex);
 38258627        var key = new NavigationAutomaticSeamPairKey(first, second);
 38258628        if (TryGetCurrentPair(key, out NavigationAutomaticSeamPair existing))
 629        {
 5974630            QueueMutation(existing, MutationKind.Revalidate);
 5974631            return;
 632        }
 32284633        bool foundFirstPrism = _preparedGraph.TryGetSeamPrism(
 32284634            key.First,
 32284635            out GridCellPrism firstPrism);
 32284636        bool foundSecondPrism = _preparedGraph.TryGetSeamPrism(
 32284637            key.Second,
 32284638            out GridCellPrism secondPrism);
 639        System.Diagnostics.Debug.Assert(foundFirstPrism && foundSecondPrism,
 640            "Boundary contacts resolved through the same normalized map bindings own both cell prisms.");
 32284641        if (!GridCellGeometry.TryCreateNavigationPortal(
 32284642                firstPrism,
 32284643                secondPrism,
 32284644                out GridNavigationPortal portal))
 645        {
 26268646            return;
 647        }
 6016648        QueueMutation(
 6016649            new NavigationAutomaticSeamPair(key.First, key.Second, portal),
 6016650            MutationKind.Add,
 6016651            ownsPair: true);
 6016652    }
 653
 654    private bool AdvanceQueuedMutation(MaintenanceWorkMeter meter)
 655    {
 49758656        if (_mutationStage < 2)
 657        {
 24501658            if (!meter.TryConsumeExplicitEdges(1))
 213659                return false;
 24288660            _mutationStage++;
 24288661            return true;
 662        }
 25257663        if (!meter.TryConsumeDependencyEntries(1))
 969664            return false;
 24288665        _mutationStage++;
 24288666        if (_mutationStage == 4)
 12144667            CoalescePendingMutation();
 24288668        return true;
 669    }
 670
 671    private void CoalescePendingMutation()
 672    {
 12144673        NavigationAutomaticSeamPair pair = _pendingPair!;
 12144674        var key = new NavigationAutomaticSeamPairKey(pair.First, pair.Second);
 12144675        EnsurePairEditor();
 12144676        if (!_pairEditor!.TryGetValue(key, out PairDelta delta))
 677        {
 6148678            _sourceGraph.AutomaticSeams.TryGetPairRecord(key, out NavigationAutomaticSeamPairRecord source);
 6148679            delta = new PairDelta(source);
 6148680            _pairEditor.Set(key, delta);
 6148681            _pairDeltaPayloadBytes = checked(_pairDeltaPayloadBytes + PairDeltaBytes);
 6148682            _pairDeltaPayloadPages++;
 683        }
 12144684        NavigationAutomaticSeamPair? prior = delta.FinalPair;
 12144685        if (_pendingMutation == MutationKind.Remove)
 83686            delta.FinalPair = null;
 12061687        else if (_pendingMutation == MutationKind.Add)
 688        {
 689            System.Diagnostics.Debug.Assert(_pendingPairOwned,
 690                "Only newly discovered seam geometry enters the add mutation.");
 691            System.Diagnostics.Debug.Assert(delta.FinalPair == null,
 692                "Discovery queues an add only after the current seam pair is absent.");
 693            System.Diagnostics.Debug.Assert(!ReferenceEquals(prior, pair));
 6016694            delta.FinalPair = pair;
 6016695            _pairDeltaPayloadBytes = checked(
 6016696                _pairDeltaPayloadBytes + NavigationAutomaticSeamPair.RetainedSize);
 6016697            _pairDeltaPayloadPages++;
 6016698            delta.OwnsFinalPair = true;
 6016699            _pendingPairOwned = false;
 700        }
 701        else
 702        {
 703            System.Diagnostics.Debug.Assert(_pendingMutation == MutationKind.Revalidate);
 704            System.Diagnostics.Debug.Assert(!_pendingPairOwned);
 705        }
 12144706        delta.FinalActive = delta.FinalPair != null
 12144707            && _preparedGraph.HasEffectiveCell(delta.FinalPair.First)
 12144708            && _preparedGraph.HasEffectiveCell(delta.FinalPair.Second);
 12144709        _pendingPair = null;
 12144710        _pendingPairOwned = false;
 12144711        _pendingMutation = MutationKind.None;
 12144712        _mutationStage = 0;
 12144713    }
 714
 715    private void BeginPairApplication()
 716    {
 1186717        if (_pairEditor == null)
 718        {
 1005719            _complete = true;
 1005720            return;
 721        }
 181722        _pairDeltas = _pairEditor.Seal();
 181723        _pairEditor = null;
 181724        _pairCursor = _pairDeltas.CreateCursor(
 181725            CursorHeight,
 181726            NavigationAutomaticSeamIndex.PairCursorShellBytes);
 181727        _pairCursor.BeginAll(_pairDeltas);
 181728        _indexEditor = _sourceGraph.AutomaticSeams.Edit(_ownershipToken);
 181729        _phase = WorkPhase.ApplyPairs;
 181730    }
 731
 732    private bool AdvancePairApplication(MaintenanceWorkMeter meter)
 733    {
 58209734        if (_currentPairDelta == null)
 735        {
 6331736            if (!_pairCursor!.HasNext)
 737            {
 181738                _pairCursor = null;
 181739                SealSecondaryJournals();
 181740                return true;
 741            }
 6150742            if (!meter.TryConsumeDependencyEntries(1))
 3743                return false;
 6147744            _pairCursor.MoveNext();
 6147745            _currentPairKey = _pairCursor.CurrentKey;
 6147746            _currentPairDelta = _pairCursor.Current;
 6147747            NormalizeCurrentPairDelta();
 6147748            _pairApplyStage = 0;
 6147749            return true;
 750        }
 751
 51878752        PairDelta delta = _currentPairDelta;
 63669753        while (_pairApplyStage < 13)
 754        {
 57522755            switch (_pairApplyStage)
 756            {
 757                case 0:
 6166758                    if (!_currentGeometryChanged && !_currentActiveChanged)
 759                    {
 46760                        _pairApplyStage = 13;
 46761                        continue;
 762                    }
 6120763                    if (!meter.TryConsumeDependencyEntries(1))
 19764                        return false;
 6101765                    NavigationAutomaticSeamPairRecord? record = delta.FinalPair == null
 6101766                        ? null
 6101767                        : new NavigationAutomaticSeamPairRecord(delta.FinalPair, delta.FinalActive);
 6101768                    _indexEditor!.SetPair(_currentPairKey, record);
 6101769                    if (delta.OwnsFinalPair)
 770                    {
 6016771                        _pairDeltaPayloadBytes -= NavigationAutomaticSeamPair.RetainedSize;
 6016772                        _pairDeltaPayloadPages--;
 6016773                        delta.OwnsFinalPair = false;
 774                    }
 6101775                    _pairApplyStage++;
 6101776                    return true;
 777                case 1:
 778                case 3:
 12193779                    if (!_currentGeometryChanged)
 780                    {
 23781                        _pairApplyStage = 5;
 23782                        continue;
 783                    }
 12170784                    if (!meter.TryConsumeDependencyEntries(1))
 14785                        return false;
 12156786                    TouchAddress(
 12156787                        _pairApplyStage == 1 ? _currentPairKey.First : _currentPairKey.Second,
 12156788                        dependency: true,
 12156789                        active: false);
 12156790                    _pairApplyStage++;
 12156791                    return true;
 792                case 2:
 793                case 4:
 12913794                    if (!meter.TryConsumeDependencyEntries(1))
 757795                        return false;
 12156796                    if (delta.FinalPair != null)
 12032797                        AppendAddressPair(
 12032798                            _pairApplyStage == 2 ? _currentPairKey.First : _currentPairKey.Second,
 12032799                            delta.FinalPair,
 12032800                            active: false);
 12156801                    _pairApplyStage++;
 12156802                    return true;
 803                case 5:
 804                case 7:
 6381805                    if (!_currentActiveRowChanged)
 806                    {
 5861807                        _pairApplyStage = 9;
 5861808                        continue;
 809                    }
 520810                    if (!meter.TryConsumeDependencyEntries(1))
 40811                        return false;
 480812                    TouchAddress(
 480813                        _pairApplyStage == 5 ? _currentPairKey.First : _currentPairKey.Second,
 480814                        dependency: false,
 480815                        active: true);
 480816                    _pairApplyStage++;
 480817                    return true;
 818                case 6:
 819                case 8:
 518820                    if (!meter.TryConsumeDependencyEntries(1))
 38821                        return false;
 480822                    if (delta.FinalActive)
 428823                        AppendAddressPair(
 428824                            _pairApplyStage == 6 ? _currentPairKey.First : _currentPairKey.Second,
 428825                            delta.FinalPair!,
 428826                            active: true);
 480827                    _pairApplyStage++;
 480828                    return true;
 829                case 9:
 830                case 10:
 6361831                    if (!_currentActiveRowChanged && !_currentStructuralLinkChanged)
 832                    {
 5861833                        _pairApplyStage = 11;
 5861834                        continue;
 835                    }
 500836                    if (!meter.TryConsumeDependencyEntries(1))
 20837                        return false;
 480838                    bool reverse = _pairApplyStage == 10;
 480839                    NavigationCellAddress endpoint = reverse
 480840                        ? _currentPairKey.Second
 480841                        : _currentPairKey.First;
 480842                    _changedStructuralEndpoints =
 480843                        _changedStructuralEndpoints.Add(endpoint);
 480844                    if (!_currentStructuralLinkChanged)
 845                    {
 18846                        _pairApplyStage++;
 18847                        return true;
 848                    }
 462849                    string source = reverse ? _currentPairKey.Second.MapId : _currentPairKey.First.MapId;
 462850                    string destination = reverse ? _currentPairKey.First.MapId : _currentPairKey.Second.MapId;
 462851                    NavigationAutomaticSeamPair? sourcePair = delta.SourceRecord?.Pair;
 462852                    bool sourceActive = delta.SourceRecord?.IsActive ?? false;
 462853                    AddLinkDelta(
 462854                        source,
 462855                        destination,
 462856                        (delta.FinalActive ? 1 : 0) - (sourceActive ? 1 : 0),
 462857                        GetUncertifiedCount(delta.FinalPair, delta.FinalActive)
 462858                            - GetUncertifiedCount(sourcePair, sourceActive));
 462859                    _pairApplyStage++;
 462860                    return true;
 861                case 11:
 862                case 12:
 12990863                    if (!meter.TryConsumeComponentNodes(1))
 788864                        return false;
 12202865                    AddChangedMapId(_pairApplyStage == 11
 12202866                        ? _currentPairKey.First.MapId
 12202867                        : _currentPairKey.Second.MapId);
 12202868                    _pairApplyStage++;
 12202869                    return true;
 870            }
 871        }
 6147872        _currentPairDelta = null;
 6147873        return true;
 874    }
 875
 876    private void NormalizeCurrentPairDelta()
 877    {
 6147878        PairDelta delta = _currentPairDelta!;
 6147879        if (delta.FinalPair != null)
 880        {
 881            System.Diagnostics.Debug.Assert(
 882                _preparedGraph.TryGetMap(delta.FinalPair.First.MapId, out _)
 883                && _preparedGraph.TryGetMap(delta.FinalPair.Second.MapId, out _),
 884                "Removed-map modes clear every incident pair before journal normalization.");
 885        }
 6147886        NavigationAutomaticSeamPair? sourcePair = delta.SourceRecord?.Pair;
 6147887        _currentGeometryChanged = !ReferenceEquals(sourcePair, delta.FinalPair);
 6147888        bool sourceActive = delta.SourceRecord?.IsActive ?? false;
 6147889        _currentActiveChanged = sourceActive != delta.FinalActive;
 6147890        _currentActiveRowChanged = _currentActiveChanged
 6147891            || (_currentGeometryChanged && (sourceActive || delta.FinalActive));
 6147892        _currentStructuralLinkChanged = _currentActiveChanged
 6147893            || GetUncertifiedCount(sourcePair, sourceActive)
 6147894                != GetUncertifiedCount(delta.FinalPair, delta.FinalActive);
 6147895        GeometryChanged |= _currentGeometryChanged;
 6147896        StructuralLinksChanged |= _currentStructuralLinkChanged;
 6147897    }
 898
 899    private static int GetUncertifiedCount(
 900        NavigationAutomaticSeamPair? pair,
 12758901        bool active) => active
 12758902            && pair!.Portal.FaceKind != VoxelContactFaceKind.Vertical
 12758903                ? 1
 12758904                : 0;
 905
 906    private void TouchAddress(NavigationCellAddress address, bool dependency, bool active)
 907    {
 12636908        EnsureAddressEditor();
 12636909        if (!_addressEditor!.TryGetValue(address, out AddressDelta delta))
 910        {
 1600911            delta = new AddressDelta();
 1600912            _addressEditor.Set(address, delta);
 1600913            _addressDeltaPayloadBytes = checked(_addressDeltaPayloadBytes + AddressDeltaBytes);
 1600914            _addressDeltaPayloadPages++;
 915        }
 12636916        delta.DependencyChanged |= dependency;
 12636917        delta.ActiveChanged |= active;
 12636918    }
 919
 920    private void AppendAddressPair(
 921        NavigationCellAddress address,
 922        NavigationAutomaticSeamPair pair,
 923        bool active)
 924    {
 12460925        _addressEditor!.TryGetValue(address, out AddressDelta delta);
 12460926        long beforeBytes = delta.RetainedBytes;
 12460927        int beforePages = delta.PersistentPageCount;
 12460928        if (active)
 428929            delta.AppendActive(pair);
 930        else
 12032931            delta.AppendDependency(pair);
 12460932        RecordAddressPayloadChange(delta, beforeBytes, beforePages);
 12460933    }
 934
 935    private void AddLinkDelta(
 936        string sourceMapId,
 937        string destinationMapId,
 938        int countChange,
 939        int uncertifiedCountChange)
 940    {
 462941        EnsureLinkEditor();
 462942        var key = new NavigationAutomaticSeamLinkKey(sourceMapId, destinationMapId);
 462943        if (!_linkEditor!.TryGetValue(key, out LinkDelta delta))
 944        {
 418945            delta = new LinkDelta();
 418946            _linkEditor.Set(key, delta);
 418947            _linkDeltaPayloadBytes = checked(_linkDeltaPayloadBytes + LinkDeltaBytes);
 418948            _linkDeltaPayloadPages++;
 949        }
 462950        delta.Count = checked(delta.Count + countChange);
 462951        delta.UncertifiedCount = checked(
 462952            delta.UncertifiedCount + uncertifiedCountChange);
 462953        if (delta.Count != 0 || delta.UncertifiedCount != 0)
 460954            return;
 2955        _linkEditor.Remove(key);
 2956        _linkDeltaPayloadBytes -= LinkDeltaBytes;
 2957        _linkDeltaPayloadPages--;
 2958    }
 959
 960    private void SealSecondaryJournals()
 961    {
 181962        if (_addressEditor != null)
 963        {
 172964            _addressDeltas = _addressEditor.Seal();
 172965            _addressEditor = null;
 172966            _addressCursor = _addressDeltas.CreateCursor(
 172967                CursorHeight,
 172968                NavigationAutomaticSeamIndex.AddressCursorShellBytes);
 172969            _addressCursor.BeginAll(_addressDeltas);
 970        }
 181971        if (_linkEditor != null)
 972        {
 159973            _linkDeltas = _linkEditor.Seal();
 159974            _linkEditor = null;
 159975            _linkCursor = _linkDeltas.CreateCursor(
 159976                CursorHeight,
 159977                NavigationAutomaticSeamIndex.LinkCursorShellBytes);
 159978            _linkCursor.BeginAll(_linkDeltas);
 979        }
 181980        _phase = WorkPhase.ApplyAddresses;
 181981    }
 982
 983    private bool AdvanceAddressApplication(MaintenanceWorkMeter meter)
 984    {
 47598985        if (_addressCursor == null)
 986        {
 9987            _phase = WorkPhase.ApplyLinks;
 9988            return true;
 989        }
 47589990        if (_currentAddressDelta == null)
 991        {
 1875992            if (!_addressCursor.HasNext)
 993            {
 172994                _addressCursor = null;
 172995                _addressDeltas = null;
 172996                _addressDeltaPayloadBytes = 0;
 172997                _addressDeltaPayloadPages = 0;
 172998                _phase = WorkPhase.ApplyLinks;
 172999                return true;
 1000            }
 17031001            if (!meter.TryConsumeDependencyEntries(1))
 1031002                return false;
 16001003            _addressCursor.MoveNext();
 16001004            _currentAddress = _addressCursor.CurrentKey;
 16001005            _currentAddressDelta = _addressCursor.Current;
 16001006            long beforeBytes = _currentAddressDelta.RetainedBytes;
 16001007            int beforePages = _currentAddressDelta.PersistentPageCount;
 16001008            _currentAddressDelta.SealAdditions();
 16001009            RecordAddressPayloadChange(_currentAddressDelta, beforeBytes, beforePages);
 16001010            _addressApplyStage = 0;
 16001011            return true;
 1012        }
 457141013        if (_addressApplyStage == 0)
 1014        {
 405921015            if (!_currentAddressDelta.DependencyChanged)
 1016            {
 431017                _addressApplyStage = 1;
 431018                return true;
 1019            }
 405491020            if (_rowKind == RowKind.None)
 15571021                BeginRow(RowKind.Dependency, _currentAddressDelta.DependencyAdditions);
 405491022            if (!AdvanceRow(meter))
 11661023                return false;
 393831024            if (_rowKind != RowKind.None)
 378261025                return true;
 15571026            _addressApplyStage = 1;
 15571027            return true;
 1028        }
 51221029        if (_addressApplyStage == 1)
 1030        {
 35221031            if (!_currentAddressDelta.ActiveChanged)
 1032            {
 11711033                _addressApplyStage = 2;
 11711034                return true;
 1035            }
 23511036            if (_rowKind == RowKind.None)
 4291037                BeginRow(RowKind.Active, _currentAddressDelta.ActiveAdditions);
 23511038            if (!AdvanceRow(meter))
 1081039                return false;
 22431040            if (_rowKind != RowKind.None)
 18141041                return true;
 4291042            _addressApplyStage = 2;
 4291043            return true;
 1044        }
 16001045        long retained = _currentAddressDelta.RetainedBytes;
 16001046        int pages = _currentAddressDelta.PersistentPageCount;
 16001047        _currentAddressDelta.ReleaseAdditions();
 16001048        RecordAddressPayloadChange(_currentAddressDelta, retained, pages);
 16001049        _currentAddressDelta = null;
 16001050        return true;
 1051    }
 1052
 1053    private void BeginRow(
 1054        RowKind kind,
 1055        NavigationPagedSequence<NavigationAutomaticSeamPair> additions)
 1056    {
 19861057        ClearRowEnumeration();
 19861058        _rowKind = kind;
 19861059        NavigationPagedSequence<NavigationAutomaticSeamPair> source = kind == RowKind.Dependency
 19861060            ? _sourceGraph.AutomaticSeams.GetDependencyRow(_currentAddress)
 19861061            : _sourceGraph.AutomaticSeams.GetActiveRow(_currentAddress);
 19861062        _sourceRow = source.GetEnumerator();
 19861063        _additionRow = additions.GetEnumerator();
 19861064        _sourceRowComplete = source.Count == 0;
 19861065        _additionRowComplete = additions.Count == 0;
 19861066        _sourceRowHasNext = false;
 19861067        _additionRowHasNext = false;
 19861068        _pendingRowOutput = null;
 19861069    }
 1070
 1071    private bool AdvanceRow(MaintenanceWorkMeter meter)
 1072    {
 429001073        if (_pendingRowOutput != null)
 1074        {
 130121075            if (!meter.TryConsumeDependencyEntries(1))
 5471076                return false;
 124651077            _rowBuilder ??= new NavigationPagedSequence<NavigationAutomaticSeamPair>.Builder(8);
 124651078            _rowBuilder.Append(_pendingRowOutput);
 124651079            _pendingRowOutput = null;
 124651080            return true;
 1081        }
 298881082        if (!_sourceRowHasNext && !_sourceRowComplete)
 1083        {
 4001084            if (!meter.TryConsumeDependencyEntries(1))
 201085                return false;
 3801086            if (!_sourceRow.MoveNext())
 1087            {
 1571088                _sourceRowComplete = true;
 1571089                return true;
 1090            }
 2231091            NavigationAutomaticSeamPair pair = _sourceRow.Current;
 2231092            if (ShouldFilterSourcePair(pair, _rowKind))
 2181093                return true;
 51094            _sourceRowPair = pair;
 51095            _sourceRowHasNext = true;
 51096            return true;
 1097        }
 294881098        if (!_additionRowHasNext && !_additionRowComplete)
 1099        {
 149531100            if (!meter.TryConsumeDependencyEntries(1))
 6231101                return false;
 143301102            if (!_additionRow.MoveNext())
 1103            {
 18701104                _additionRowComplete = true;
 18701105                return true;
 1106            }
 124601107            _additionRowPair = _additionRow.Current;
 124601108            _additionRowHasNext = true;
 124601109            return true;
 1110        }
 145351111        if (!_sourceRowHasNext && _sourceRowComplete
 145351112            && !_additionRowHasNext && _additionRowComplete)
 1113        {
 20701114            if (!meter.TryConsumeDependencyEntries(1))
 841115                return false;
 19861116            NavigationPagedSequence<NavigationAutomaticSeamPair> result =
 19861117                _rowBuilder?.Seal() ?? NavigationPagedSequence<NavigationAutomaticSeamPair>.Empty;
 19861118            if (_rowKind == RowKind.Dependency)
 15571119                _indexEditor!.SetDependencyRow(_currentAddress, result);
 1120            else
 4291121                _indexEditor!.SetActiveRow(_currentAddress, result);
 19861122            _rowBuilder = null;
 19861123            ClearRowEnumeration();
 19861124            _rowKind = RowKind.None;
 19861125            return true;
 1126        }
 124651127        if (!_sourceRowHasNext)
 1128        {
 124581129            _pendingRowOutput = _additionRowPair;
 124581130            _additionRowHasNext = false;
 124581131            return true;
 1132        }
 71133        if (!_additionRowHasNext)
 1134        {
 31135            _pendingRowOutput = _sourceRowPair;
 31136            _sourceRowHasNext = false;
 31137            return true;
 1138        }
 41139        int comparison = ComparePairs(_sourceRowPair!, _additionRowPair!);
 41140        if (comparison <= 0)
 1141        {
 21142            _pendingRowOutput = _sourceRowPair;
 21143            _sourceRowHasNext = false;
 1144        }
 1145        else
 1146        {
 21147            _pendingRowOutput = _additionRowPair;
 21148            _additionRowHasNext = false;
 1149        }
 41150        return true;
 1151    }
 1152
 1153    private bool ShouldFilterSourcePair(NavigationAutomaticSeamPair pair, RowKind kind)
 1154    {
 2231155        if (!_pairDeltas!.TryGetValue(
 2231156                new NavigationAutomaticSeamPairKey(pair.First, pair.Second),
 2231157                out PairDelta delta))
 1158        {
 51159            return false;
 1160        }
 1161        System.Diagnostics.Debug.Assert(delta.SourceRecord != null,
 1162            "A delta reached through a source row retains that row's indexed pair record.");
 2181163        NavigationAutomaticSeamPairRecord source = delta.SourceRecord!;
 2181164        return ShouldFilterChangedPair(
 2181165            kind == RowKind.Dependency,
 2181166            !ReferenceEquals(source.Pair, delta.FinalPair),
 2181167            source.IsActive,
 2181168            delta.FinalActive);
 1169    }
 1170
 1171    internal static bool ShouldFilterChangedPair(
 1172        bool dependencyRow,
 1173        bool geometryChanged,
 1174        bool sourceActive,
 2251175        bool finalActive) => dependencyRow
 2251176        ? geometryChanged
 2251177        : geometryChanged || sourceActive != finalActive;
 1178
 1179    private bool AdvanceLinkApplication(MaintenanceWorkMeter meter)
 1180    {
 23431181        if (_linkCursor == null)
 1182        {
 221183            _phase = WorkPhase.Seal;
 221184            return true;
 1185        }
 23211186        if (!_linkDeltaReady && !_linkDeltaComplete)
 1187        {
 6161188            if (!_linkCursor.HasNext)
 1189            {
 1591190                _linkDeltaComplete = true;
 1191            }
 1192            else
 1193            {
 4571194                if (!meter.TryConsumeDependencyEntries(1))
 411195                    return false;
 4161196                _linkCursor.MoveNext();
 4161197                _currentLinkKey = _linkCursor.CurrentKey;
 4161198                _currentLinkDelta = _linkCursor.Current;
 4161199                _linkDeltaReady = true;
 4161200                return true;
 1201            }
 1202        }
 18641203        if (_linkSourceMapId == null)
 1204        {
 5251205            if (_linkDeltaComplete)
 1206            {
 1591207                _linkCursor = null;
 1591208                _linkDeltas = null;
 1591209                _currentLinkDelta = null;
 1591210                _linkDeltaPayloadBytes = 0;
 1591211                _linkDeltaPayloadPages = 0;
 1591212                _phase = WorkPhase.Seal;
 1591213                return true;
 1214            }
 3661215            _linkSourceMapId = _currentLinkKey.SourceMapId;
 3661216            NavigationPagedSequence<NavigationStructuralLink> source =
 3661217                _sourceGraph.AutomaticSeams.GetStructuralLinks(_linkSourceMapId);
 3661218            _sourceLinks = source.GetEnumerator();
 3661219            _sourceLinksComplete = source.Count == 0;
 3661220            return true;
 1221        }
 13391222        if (_pendingLinkOutput.HasValue)
 1223        {
 3961224            if (!meter.TryConsumeDependencyEntries(1))
 171225                return false;
 3791226            _linkBuilder ??= new NavigationPagedSequence<NavigationStructuralLink>.Builder(16);
 3791227            _linkBuilder.Append(_pendingLinkOutput.Value);
 3791228            _pendingLinkOutput = null;
 3791229            return true;
 1230        }
 9431231        if (!_sourceLinkReady && !_sourceLinksComplete)
 1232        {
 1271233            if (!meter.TryConsumeDependencyEntries(1))
 171234                return false;
 1101235            if (!_sourceLinks.MoveNext())
 1236            {
 511237                _sourceLinksComplete = true;
 511238                return true;
 1239            }
 591240            _sourceLink = _sourceLinks.Current;
 591241            _sourceLinkReady = true;
 591242            return true;
 1243        }
 8161244        bool deltaInGroup = _linkDeltaReady
 8161245            && _currentLinkKey.SourceMapId.Equals(_linkSourceMapId, StringComparison.Ordinal);
 8161246        if (!_sourceLinkReady && _sourceLinksComplete && !deltaInGroup)
 1247        {
 3911248            if (!meter.TryConsumeDependencyEntries(1))
 251249                return false;
 3661250            NavigationPagedSequence<NavigationStructuralLink> result =
 3661251                _linkBuilder?.Seal() ?? NavigationPagedSequence<NavigationStructuralLink>.Empty;
 3661252            _indexEditor!.SetStructuralLinks(_linkSourceMapId, result);
 3661253            _linkBuilder = null;
 3661254            _linkSourceMapId = null;
 3661255            _sourceLinks = default;
 3661256            _sourceLink = default;
 3661257            return true;
 1258        }
 4251259        if (!_sourceLinkReady)
 1260        {
 1261            System.Diagnostics.Debug.Assert(_currentLinkDelta!.Count > 0,
 1262                "An unmatched negative link delta requires the source link it removes.");
 3651263            _pendingLinkOutput = new NavigationStructuralLink(
 3651264                _currentLinkKey.DestinationMapId,
 3651265                _currentLinkDelta.Count,
 3651266                _currentLinkDelta.UncertifiedCount);
 3651267            ConsumeCurrentLinkDelta();
 3651268            return true;
 1269        }
 601270        if (!deltaInGroup)
 1271        {
 11272            _pendingLinkOutput = _sourceLink;
 11273            _sourceLinkReady = false;
 11274            _sourceLink = default;
 11275            return true;
 1276        }
 591277        int comparison = string.CompareOrdinal(
 591278            _sourceLink.DestinationMapId,
 591279            _currentLinkKey.DestinationMapId);
 591280        if (comparison < 0)
 1281        {
 81282            _pendingLinkOutput = _sourceLink;
 81283            _sourceLinkReady = false;
 81284            return true;
 1285        }
 511286        if (comparison > 0)
 1287        {
 1288            System.Diagnostics.Debug.Assert(_currentLinkDelta!.Count > 0,
 1289                "A negative link delta must sort with the source link it removes.");
 11290            _pendingLinkOutput = new NavigationStructuralLink(
 11291                _currentLinkKey.DestinationMapId,
 11292                _currentLinkDelta.Count,
 11293                _currentLinkDelta.UncertifiedCount);
 11294            ConsumeCurrentLinkDelta();
 11295            return true;
 1296        }
 501297        int count = checked(_sourceLink.Count + _currentLinkDelta!.Count);
 501298        int uncertifiedCount = checked(
 501299            _sourceLink.UncertifiedCount + _currentLinkDelta.UncertifiedCount);
 501300        if (count > 0)
 1301        {
 41302            _pendingLinkOutput = new NavigationStructuralLink(
 41303                _sourceLink.DestinationMapId,
 41304                count,
 41305                uncertifiedCount);
 1306        }
 501307        _sourceLinkReady = false;
 501308        _sourceLink = default;
 501309        ConsumeCurrentLinkDelta();
 501310        return true;
 1311    }
 1312
 1313    private void ConsumeCurrentLinkDelta()
 1314    {
 4161315        _currentLinkDelta = null;
 4161316        _linkDeltaReady = false;
 4161317    }
 1318
 1319    private void ClearRowEnumeration()
 1320    {
 39851321        _sourceRow = default;
 39851322        _additionRow = default;
 39851323        _sourceRowPair = null;
 39851324        _additionRowPair = null;
 39851325        _pendingRowOutput = null;
 39851326        _sourceRowHasNext = false;
 39851327        _sourceRowComplete = false;
 39851328        _additionRowHasNext = false;
 39851329        _additionRowComplete = false;
 39851330    }
 1331
 1332    private bool SealResult()
 1333    {
 1811334        if (!RevalidateCompletedCursor())
 31335            return false;
 1781336        _sealedIndexBytes = _indexEditor!.SealedAdditionalRetainedBytes;
 1781337        _sealedIndexPages = _indexEditor.SealedAdditionalPersistentPages;
 1781338        _working = _indexEditor.Seal();
 1781339        _indexEditor = null;
 1781340        _pairDeltas = null;
 1781341        _pairDeltaPayloadBytes = 0;
 1781342        _pairDeltaPayloadPages = 0;
 1781343        _complete = true;
 1781344        return true;
 1345    }
 1346
 1347    private bool RevalidateCompletedCursor()
 1348    {
 30691349        if (IsCompletedCursorCurrent())
 30591350            return true;
 101351        ResetToSource();
 101352        return false;
 1353    }
 1354
 1355    private bool IsCompletedCursorCurrent()
 1356    {
 31051357        if (!_hasValidatorCursor)
 14741358            return true;
 16311359        GridBoundaryContactCursorStatus status = _world.AdvanceBoundaryContacts(
 16311360            _validatorCursor,
 16311361            _contact.AsSpan(0, 0),
 16311362            0,
 16311363            0,
 16311364            out _,
 16311365            out _);
 16311366        if (status != GridBoundaryContactCursorStatus.Stale
 16311367            && _validatorCursor.RunStamp == _runStamp)
 1368        {
 16211369            return true;
 1370        }
 101371        return false;
 1372    }
 1373
 1374    private bool RestartDiscoveryAfterInvalidation()
 1375    {
 31376        ResetToSource();
 31377        return false;
 1378    }
 1379
 1380    private void BeginMapMode(string mapId, WorkMode mode)
 1381    {
 1121382        _modeMapId = mapId;
 1121383        _dependencyCursor = _sourceGraph.AutomaticSeams.CreateDependencyCursor(CursorHeight);
 1121384        _sourceGraph.AutomaticSeams.BeginDependencyRange(_dependencyCursor, mapId);
 1121385        _dependencyRowRemaining = 0;
 1121386        _mode = mode;
 1121387    }
 1388
 1389    private void BeginAddressMode(NavigationCellAddress address)
 1390    {
 165721391        _modeMapId = address.MapId;
 165721392        _dependencyAddress = address;
 165721393        NavigationPagedSequence<NavigationAutomaticSeamPair> row =
 165721394            _sourceGraph.AutomaticSeams.GetDependencyRow(address);
 165721395        _dependencyRow = new NavigationAutomaticSeamIndex.EndpointEnumerator(address, row);
 165721396        _dependencyRowRemaining = row.Count;
 165721397        _mode = WorkMode.RevalidateAddress;
 165721398    }
 1399
 1400    private void BeginDiscovery(GridConfigurationKey key)
 1401    {
 11621402        _pendingDiscoveryKey = key;
 11621403        _cursorBegun = false;
 11621404        _mode = WorkMode.Discover;
 11621405    }
 1406
 1407    private void QueueMutation(
 1408        NavigationAutomaticSeamPair pair,
 1409        MutationKind mutation,
 1410        bool ownsPair = false)
 1411    {
 121441412        _pendingPair = pair;
 121441413        _pendingMutation = mutation;
 121441414        _pendingPairOwned = ownsPair;
 121441415        _mutationStage = 0;
 121441416    }
 1417
 1418    private void FinishMode()
 1419    {
 178421420        _mode = WorkMode.None;
 178421421        _modeMapId = null;
 178421422        _dependencyCursor = null;
 178421423        _dependencyRow = default;
 178421424        _dependencyRowRemaining = 0;
 178421425    }
 1426
 1427    private bool TryGetCurrentPair(
 1428        NavigationAutomaticSeamPairKey key,
 1429        out NavigationAutomaticSeamPair pair)
 1430    {
 382581431        if (_pairEditor != null && _pairEditor.TryGetValue(key, out PairDelta delta))
 1432        {
 59851433            if (delta.FinalPair != null)
 1434            {
 59741435                pair = delta.FinalPair;
 59741436                return true;
 1437            }
 111438            pair = null!;
 111439            return false;
 1440        }
 322731441        return _sourceGraph.AutomaticSeams.TryGetPair(key.First, key.Second, out pair);
 1442    }
 1443
 1444    private void EnsurePairEditor() =>
 121441445        _pairEditor ??= EmptyPairDeltas.Edit(_ownershipToken);
 1446
 1447    private void EnsureAddressEditor() =>
 126361448        _addressEditor ??= EmptyAddressDeltas.Edit(_ownershipToken);
 1449
 1450    private void EnsureLinkEditor() =>
 4621451        _linkEditor ??= EmptyLinkDeltas.Edit(_ownershipToken);
 1452
 1453    private void AddChangedMapId(string mapId)
 1454    {
 122021455        if (!_changedMapIds.ContainsKey(mapId))
 3951456            _changedMapIds = _changedMapIds.Set(mapId, true);
 122021457    }
 1458
 1459    private void RecordAddressPayloadChange(
 1460        AddressDelta delta,
 1461        long beforeBytes,
 1462        int beforePages)
 1463    {
 156601464        _addressDeltaPayloadBytes = checked(
 156601465            _addressDeltaPayloadBytes - beforeBytes + delta.RetainedBytes);
 156601466        _addressDeltaPayloadPages = checked(
 156601467            _addressDeltaPayloadPages - beforePages + delta.PersistentPageCount);
 156601468    }
 1469
 2652971470    private long GetPairJournalBytes() => checked(
 2652971471        (_pairEditor?.RetainedBytes ?? _pairDeltas?.RetainedBytes ?? 0L)
 2652971472        + (_pairCursor?.RetainedBytes ?? 0L)
 2652971473        + _pairDeltaPayloadBytes);
 1474
 2656401475    private int GetPairJournalPages() => checked(
 2656401476        (_pairEditor?.PersistentPageCount ?? _pairDeltas?.PersistentPageCount ?? 0)
 2656401477        + (_pairCursor?.PersistentPageCount ?? 0)
 2656401478        + _pairDeltaPayloadPages);
 1479
 2652971480    private long GetAddressJournalBytes() => checked(
 2652971481        (_addressEditor?.RetainedBytes ?? _addressDeltas?.RetainedBytes ?? 0L)
 2652971482        + (_addressCursor?.RetainedBytes ?? 0L)
 2652971483        + _addressDeltaPayloadBytes);
 1484
 2656401485    private int GetAddressJournalPages() => checked(
 2656401486        (_addressEditor?.PersistentPageCount ?? _addressDeltas?.PersistentPageCount ?? 0)
 2656401487        + (_addressCursor?.PersistentPageCount ?? 0)
 2656401488        + _addressDeltaPayloadPages);
 1489
 2652971490    private long GetLinkJournalBytes() => checked(
 2652971491        (_linkEditor?.RetainedBytes ?? _linkDeltas?.RetainedBytes ?? 0L)
 2652971492        + (_linkCursor?.RetainedBytes ?? 0L)
 2652971493        + _linkDeltaPayloadBytes);
 1494
 2656401495    private int GetLinkJournalPages() => checked(
 2656401496        (_linkEditor?.PersistentPageCount ?? _linkDeltas?.PersistentPageCount ?? 0)
 2656401497        + (_linkCursor?.PersistentPageCount ?? 0)
 2656401498        + _linkDeltaPayloadPages);
 1499
 1500    private void ResetToSource()
 1501    {
 131502        _working = _sourceGraph.AutomaticSeams;
 131503        _changedMapIds = PersistentStringMap<bool>.Empty;
 131504        _changedStructuralEndpoints = NavigationCellAddressSet.Empty;
 131505        _pairEditor = null;
 131506        _pairDeltas = null;
 131507        _pairCursor = null;
 131508        _addressEditor = null;
 131509        _addressDeltas = null;
 131510        _addressCursor = null;
 131511        _linkEditor = null;
 131512        _linkDeltas = null;
 131513        _linkCursor = null;
 131514        _indexEditor = null;
 131515        _dependencyCursor = null;
 131516        _dependencyRow = default;
 131517        _pendingPair = null;
 131518        _pendingPairOwned = false;
 131519        _pendingMutation = MutationKind.None;
 131520        _mutationStage = 0;
 131521        _currentPairDelta = null;
 131522        _currentStructuralLinkChanged = false;
 131523        _currentAddressDelta = null;
 131524        _rowBuilder = null;
 131525        _linkBuilder = null;
 131526        _rowKind = RowKind.None;
 131527        ClearRowEnumeration();
 131528        _pendingLinkOutput = null;
 131529        _linkSourceMapId = null;
 131530        _currentLinkDelta = null;
 131531        _linkDeltaReady = false;
 131532        _linkDeltaComplete = false;
 131533        _sourceLinks = default;
 131534        _sourceLink = default;
 131535        _sourceLinkReady = false;
 131536        _sourceLinksComplete = false;
 131537        _modeMapId = null;
 131538        _pendingDiscoveryKey = default;
 131539        _dependencyRowRemaining = 0;
 131540        _changeIndex = 0;
 131541        _overlayMapIndex = 0;
 131542        _overlayCellIndex = 0;
 131543        _overlayMapInspected = false;
 131544        _gridEventIndex = 0;
 131545        _discoveryMapIndex = 0;
 131546        _worldResetMapIndex = 0;
 131547        _fullRebuildRemoveMapIndex = 0;
 131548        _fullRebuildDiscoverMapIndex = 0;
 131549        _worldResetPending = false;
 131550        _mode = WorkMode.None;
 131551        _phase = WorkPhase.Gather;
 131552        _runStamp = default;
 131553        _hasRunStamp = false;
 131554        _cursorBegun = false;
 131555        _hasValidatorCursor = false;
 131556        _complete = false;
 131557        _pairDeltaPayloadBytes = 0;
 131558        _pairDeltaPayloadPages = 0;
 131559        _addressDeltaPayloadBytes = 0;
 131560        _addressDeltaPayloadPages = 0;
 131561        _linkDeltaPayloadBytes = 0;
 131562        _linkDeltaPayloadPages = 0;
 131563        _sealedIndexBytes = 0;
 131564        _sealedIndexPages = 0;
 131565        GeometryChanged = false;
 131566        StructuralLinksChanged = false;
 131567        Revision++;
 131568        _ownershipToken = NavigationSeamEditToken.Create();
 131569    }
 1570
 1571    private static int ComparePairs(
 1572        NavigationAutomaticSeamPair first,
 1573        NavigationAutomaticSeamPair second) =>
 41574        new NavigationAutomaticSeamPairKey(first.First, first.Second).CompareTo(
 41575            new NavigationAutomaticSeamPairKey(second.First, second.Second));
 1576
 1577    private sealed class PairDelta
 1578    {
 61481579        internal PairDelta(NavigationAutomaticSeamPairRecord? sourceRecord)
 1580        {
 61481581            SourceRecord = sourceRecord;
 61481582            FinalPair = sourceRecord?.Pair;
 61481583            FinalActive = sourceRecord?.IsActive ?? false;
 61481584        }
 1585
 1586        internal NavigationAutomaticSeamPairRecord? SourceRecord;
 1587        internal NavigationAutomaticSeamPair? FinalPair;
 1588        internal bool FinalActive;
 1589        internal bool OwnsFinalPair;
 1590    }
 1591
 1592    private sealed class AddressDelta
 1593    {
 1594        private NavigationPagedSequence<NavigationAutomaticSeamPair>.Builder? _dependencyBuilder;
 1595        private NavigationPagedSequence<NavigationAutomaticSeamPair>.Builder? _activeBuilder;
 1596
 1597        internal bool DependencyChanged;
 1598        internal bool ActiveChanged;
 16001599        internal NavigationPagedSequence<NavigationAutomaticSeamPair> DependencyAdditions =
 16001600            NavigationPagedSequence<NavigationAutomaticSeamPair>.Empty;
 16001601        internal NavigationPagedSequence<NavigationAutomaticSeamPair> ActiveAdditions =
 16001602            NavigationPagedSequence<NavigationAutomaticSeamPair>.Empty;
 1603
 313201604        internal long RetainedBytes => checked(
 313201605            AddressDeltaBytes
 313201606            + (_dependencyBuilder?.RetainedBytes ?? DependencyAdditions.RetainedBytes)
 313201607            + (_activeBuilder?.RetainedBytes ?? ActiveAdditions.RetainedBytes));
 1608
 313201609        internal int PersistentPageCount => checked(
 313201610            1
 313201611            + (_dependencyBuilder?.PersistentPageCount ?? DependencyAdditions.PersistentPageCount)
 313201612            + (_activeBuilder?.PersistentPageCount ?? ActiveAdditions.PersistentPageCount));
 1613
 1614        internal void AppendDependency(NavigationAutomaticSeamPair pair)
 1615        {
 120321616            _dependencyBuilder ??= new NavigationPagedSequence<NavigationAutomaticSeamPair>.Builder(8);
 120321617            _dependencyBuilder.Append(pair);
 120321618        }
 1619
 1620        internal void AppendActive(NavigationAutomaticSeamPair pair)
 1621        {
 4281622            _activeBuilder ??= new NavigationPagedSequence<NavigationAutomaticSeamPair>.Builder(8);
 4281623            _activeBuilder.Append(pair);
 4281624        }
 1625
 1626        internal void SealAdditions()
 1627        {
 16001628            if (_dependencyBuilder != null)
 1629            {
 14901630                DependencyAdditions = _dependencyBuilder.Seal();
 14901631                _dependencyBuilder = null;
 1632            }
 16001633            if (_activeBuilder != null)
 1634            {
 3801635                ActiveAdditions = _activeBuilder.Seal();
 3801636                _activeBuilder = null;
 1637            }
 16001638        }
 1639
 1640        internal void ReleaseAdditions()
 1641        {
 16001642            DependencyAdditions = NavigationPagedSequence<NavigationAutomaticSeamPair>.Empty;
 16001643            ActiveAdditions = NavigationPagedSequence<NavigationAutomaticSeamPair>.Empty;
 16001644        }
 1645    }
 1646
 1647    private sealed class LinkDelta
 1648    {
 1649        internal int Count;
 1650        internal int UncertifiedCount;
 1651    }
 1652
 1653    private enum WorkPhase : byte
 1654    {
 1655        Gather,
 1656        ApplyPairs,
 1657        ApplyAddresses,
 1658        ApplyLinks,
 1659        Seal
 1660    }
 1661
 1662    private enum WorkMode : byte
 1663    {
 1664        None,
 1665        RemoveMap,
 1666        RevalidateMap,
 1667        RevalidateAddress,
 1668        Discover
 1669    }
 1670
 1671    private enum MutationKind : byte
 1672    {
 1673        None,
 1674        Add,
 1675        Remove,
 1676        Revalidate
 1677    }
 1678
 1679    private enum RowKind : byte
 1680    {
 1681        None,
 1682        Dependency,
 1683        Active
 1684    }
 1685
 1686    internal enum SeamAdvanceStatus : byte
 1687    {
 1688        Blocked,
 1689        Progressed,
 1690        Complete
 1691    }
 1692}

Methods/Properties

.cctor()
.ctor(GridForge.Grids.GridWorld,Trailblazer.Pathing.NavigationWorldGraph,Trailblazer.Pathing.NavigationWorldGraph,Trailblazer.Pathing.NavigationOperationFrameChange[],System.Int32)
.ctor(GridForge.Grids.GridWorld,Trailblazer.Pathing.NavigationWorldGraph,Trailblazer.Pathing.NavigationWorldGraph,GridForge.Grids.GridEventInfo[],System.Int32,System.Boolean)
.ctor(GridForge.Grids.GridWorld,Trailblazer.Pathing.NavigationWorldGraph,Trailblazer.Pathing.NavigationWorldGraph,Trailblazer.Pathing.PersistentStringMap`1<System.Boolean>)
get_Result()
get_IsComplete()
get_ChangedMapCount()
GetChangedMapIdAt(System.Int32)
get_ChangedStructuralEndpointCount()
GetChangedStructuralEndpointAt(System.Int32)
RevalidateForPublication()
get_RetainedBytes()
get_PersistentPageCount()
AdvanceOne(Trailblazer.Pathing.MaintenanceWorkMeter)
AdvanceGather(Trailblazer.Pathing.MaintenanceWorkMeter)
TrySetupNextMode(Trailblazer.Pathing.MaintenanceWorkMeter)
TrySetupFullRebuildMode(Trailblazer.Pathing.MaintenanceWorkMeter)
TrySetupNextGridEventMode(Trailblazer.Pathing.MaintenanceWorkMeter)
AdvanceMode(Trailblazer.Pathing.MaintenanceWorkMeter)
CompleteMapMode()
AdvanceDiscovery(Trailblazer.Pathing.MaintenanceWorkMeter)
AdvanceDiscoveryAfterCursorStart(Trailblazer.Pathing.MaintenanceWorkMeter,System.Boolean,System.Boolean,System.Boolean,System.Boolean)
AdvanceBegunDiscovery(Trailblazer.Pathing.MaintenanceWorkMeter)
PrepareDiscoveredPair(GridForge.Grids.Topology.GridBoundaryContact)
AdvanceQueuedMutation(Trailblazer.Pathing.MaintenanceWorkMeter)
CoalescePendingMutation()
BeginPairApplication()
AdvancePairApplication(Trailblazer.Pathing.MaintenanceWorkMeter)
NormalizeCurrentPairDelta()
GetUncertifiedCount(Trailblazer.Pathing.NavigationAutomaticSeamPair,System.Boolean)
TouchAddress(Trailblazer.Pathing.NavigationCellAddress,System.Boolean,System.Boolean)
AppendAddressPair(Trailblazer.Pathing.NavigationCellAddress,Trailblazer.Pathing.NavigationAutomaticSeamPair,System.Boolean)
AddLinkDelta(System.String,System.String,System.Int32,System.Int32)
SealSecondaryJournals()
AdvanceAddressApplication(Trailblazer.Pathing.MaintenanceWorkMeter)
BeginRow(Trailblazer.Pathing.NavigationAutomaticSeamRefreshWork/RowKind,Trailblazer.Pathing.NavigationPagedSequence`1<Trailblazer.Pathing.NavigationAutomaticSeamPair>)
AdvanceRow(Trailblazer.Pathing.MaintenanceWorkMeter)
ShouldFilterSourcePair(Trailblazer.Pathing.NavigationAutomaticSeamPair,Trailblazer.Pathing.NavigationAutomaticSeamRefreshWork/RowKind)
ShouldFilterChangedPair(System.Boolean,System.Boolean,System.Boolean,System.Boolean)
AdvanceLinkApplication(Trailblazer.Pathing.MaintenanceWorkMeter)
ConsumeCurrentLinkDelta()
ClearRowEnumeration()
SealResult()
RevalidateCompletedCursor()
IsCompletedCursorCurrent()
RestartDiscoveryAfterInvalidation()
BeginMapMode(System.String,Trailblazer.Pathing.NavigationAutomaticSeamRefreshWork/WorkMode)
BeginAddressMode(Trailblazer.Pathing.NavigationCellAddress)
BeginDiscovery(GridForge.Configuration.GridConfigurationKey)
QueueMutation(Trailblazer.Pathing.NavigationAutomaticSeamPair,Trailblazer.Pathing.NavigationAutomaticSeamRefreshWork/MutationKind,System.Boolean)
FinishMode()
TryGetCurrentPair(Trailblazer.Pathing.NavigationAutomaticSeamPairKey,Trailblazer.Pathing.NavigationAutomaticSeamPair&)
EnsurePairEditor()
EnsureAddressEditor()
EnsureLinkEditor()
AddChangedMapId(System.String)
RecordAddressPayloadChange(Trailblazer.Pathing.NavigationAutomaticSeamRefreshWork/AddressDelta,System.Int64,System.Int32)
GetPairJournalBytes()
GetPairJournalPages()
GetAddressJournalBytes()
GetAddressJournalPages()
GetLinkJournalBytes()
GetLinkJournalPages()
ResetToSource()
ComparePairs(Trailblazer.Pathing.NavigationAutomaticSeamPair,Trailblazer.Pathing.NavigationAutomaticSeamPair)
.ctor(Trailblazer.Pathing.NavigationAutomaticSeamPairRecord)
.ctor()
get_RetainedBytes()
get_PersistentPageCount()
AppendDependency(Trailblazer.Pathing.NavigationAutomaticSeamPair)
AppendActive(Trailblazer.Pathing.NavigationAutomaticSeamPair)
SealAdditions()
ReleaseAdditions()