< Summary

Information
Class: Trailblazer.Pathing.NavigationGraphRuntime
Assembly: Trailblazer
File(s): /home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Graph/NavigationGraphRuntime.cs
Line coverage
100%
Covered lines: 1154
Uncovered lines: 0
Coverable lines: 1154
Total lines: 1911
Line coverage: 100%
Branch coverage
100%
Covered branches: 409
Total branches: 409
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_Current()100%11100%
get_Store()100%11100%
get_RetainedBaselineCaptureCount()100%44100%
get_RetainedCompositionWorkCount()100%11100%
get_RetainedCompositionWorkBytes()100%66100%
get_RetainedOperationWorkBytes()100%11100%
get_RetainedOperationWorkCount()100%11100%
get_RetainedCompositionWorkPageCount()100%66100%
get_RetainedOperationWorkPageCount()100%11100%
get_MaintenanceMeter()100%11100%
get_LastAffectedMapCollectionCount()100%11100%
Admit(...)100%11100%
Admit(...)100%11100%
Admit(...)100%11100%
Admit(...)100%11100%
TryAcquire()100%11100%
Maintain(...)100%7676100%
CompletePolicyFrame(...)100%44100%
ClassifyPolicyFrameDisposition(...)100%66100%
ContinueAfterRetainedClosure(...)100%22100%
ClassifyAutomaticSeamAdvance(...)100%66100%
ClassifyMaterializedAdvance(...)100%88100%
ClassifyOperationTerminalDisposition(...)100%1212100%
GetOwnedClosureBaselineAdditionalCapacity(...)100%66100%
IsRetainedWorkWithinCapacity(...)100%66100%
MaintainSnapshot()100%1212100%
ReconcileAndPublish(...)100%3838100%
TryPrepareMaterializedComponents(...)100%1010100%
MaintainMaterializedComponentWork(...)100%1616100%
RestartMaterializedSnapshot(...)100%11100%
AbandonMaterializedSnapshot(...)100%22100%
AdvanceCoveredBaselineRebuilds(...)100%1212100%
HasRelevantAutomaticSeamLifecycleEvent(...)100%1616100%
StartAutomaticSeamLifecycle(...)100%11100%
MaintainAutomaticSeamLifecycle()100%77100%
GetLifecycleWorkAllowance(...)100%11100%
RequeueAutomaticSeamLifecyclePrefix()100%11100%
RestartAutomaticSeamLifecycle()100%11100%
TryGetCellState(...)100%66100%
TryResolveAreaPolicy(...)100%11100%
GetDiagnostics(...)100%22100%
GetSurfaceComponentDiagnostic(...)100%1010100%
Reset()100%22100%
Dispose()100%22100%
PublishCandidate(...)100%3636100%
IsWithinRetainedWorkCapacity(...)100%22100%
TryRollbackCompositionClosure()100%22100%
RollbackCompositionForCapacityRejection()100%11100%
RejectInitialCompositionForCapacity()100%11100%
CompleteCompositionPublication()100%11100%
PublishAffectedCompositionClosureAndDefer(...)100%11100%
PublishAllCompositionClosureAndDefer(...)100%11100%
BeginOperationClosureRollback()100%11100%
ApplyOperationTerminalRollback(...)100%44100%
RejectDeferredOperationForCapacity()100%11100%
TryCompleteOperationClosureRollback()100%11100%
TryPublishReopenedStructuralScopes()100%11100%
ApplyPublishedCandidate(...)100%1616100%
CaptureOwnedStructuralClosureBaseline(...)100%22100%
CreateOwnedStructuralClosure(...)100%22100%
PreservePriorStructuralClosures(...)100%22100%
ClearOwnedStructuralClosureBaseline()100%11100%
IsOperationWithinRetainedWorkCapacity(...)100%11100%
GetCombinedCompositionWorkBytes(...)100%11100%
GetCombinedCompositionWorkPages(...)100%11100%
GetCombinedMaterializedWorkBytes(...)100%22100%
GetCombinedMaterializedWorkPages(...)100%22100%
GetOwnedClosureBaselineAdditionalRetainedBytes(...)100%11100%
GetOwnedClosureBaselineAdditionalPersistentPages(...)100%11100%
GetCompositionWorkAllowance(...)100%11100%
PublishPendingCandidate(...)100%66100%
PrepareResnapshotScopes(...)100%66100%
CommitBlockedScopes(...)100%22100%
MergeBlockedScopes(...)100%88100%
ContainsScope(...)100%44100%
EnqueueCommittedChange(...)100%44100%
MarkResnapshotRequired()100%11100%
MarkSafetyPendingIf(...)100%22100%
ClearSafetyPendingAfterExactResnapshot()100%22100%
CanClearSafetyPendingAfterSnapshot(...)100%66100%
RequeuePublicationEvents()100%11100%
DrainSafetyPrefixUnderPressure()100%88100%
ContainsTopologyLifecycle(...)100%88100%
ClearBaselineCaptures()100%22100%
RemoveCompletedBaselineRebuilds()100%44100%
EnsureUsable()100%11100%

File(s)

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

#LineLine coverage
 1//=======================================================================
 2// NavigationGraphRuntime.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.Grids;
 10using GridForge.Grids.Topology;
 11using GridForge.Spatial;
 12
 13namespace Trailblazer.Pathing;
 14
 15/// <summary>Owns map operations, GridForge ingress, and immutable root publication for one context.</summary>
 16internal sealed class NavigationGraphRuntime : IDisposable
 17{
 18    internal enum OperationTerminalDisposition
 19    {
 20        None,
 21        Release,
 22        ReleaseAndBeginRollback,
 23        ReleaseAndTryReopen
 24    }
 25
 26    internal enum PolicyFrameDisposition
 27    {
 28        None,
 29        Complete,
 30        RejectCapacity
 31    }
 32
 33    internal enum AutomaticSeamAdvanceDisposition
 34    {
 35        Continue,
 36        Retain,
 37        Restart,
 38        Complete
 39    }
 40
 41    internal enum MaterializedAdvanceDisposition
 42    {
 43        Restart,
 44        RejectCapacity,
 45        Defer,
 46        Ready,
 47        Publish
 48    }
 49
 50    internal enum PublishedCandidateEffect
 51    {
 52        InstallMaterialized,
 53        CompleteMaterialized,
 54        CompleteMaterializedWithinStructuralPublication,
 55        CompleteAutomaticSeam,
 56        CompleteComposition,
 57        ReopenStructuralScopes,
 58        StartAutomaticSeam
 59    }
 60
 61    private readonly GridWorld _world;
 62    private readonly NavigationOperationProcessor _operations;
 63    private readonly NavigationGridChangeIngress _ingress;
 64    private readonly NavigationWorldGraphStore _store;
 65    private readonly NavigationAreaCatalogProcessor _areaPolicies;
 66    private readonly MaintenanceWorkBudget _maintenanceBudget;
 67    private readonly MaintenanceWorkMeter _maintenanceMeter;
 68    private readonly int _maxDynamicSlotsPerMap;
 69    private readonly int _maxDynamicSlots;
 70    private readonly long _maxActiveSnapshotBytes;
 71    private readonly int _maxPersistentGraphPages;
 72    private readonly NavigationCandidatePublisher _publishCandidate;
 73    private readonly NavigationRetainedWorkGuard _retainedWorkGuard;
 74    private readonly Action _maintainSnapshot;
 75    private readonly GridEventInfo[] _maintenanceEvents;
 76    private readonly NavigationGridChangeScope[] _blockedScopes;
 77    private readonly NavigationGridChangeScope[] _resnapshotScopes;
 78    private readonly NavigationGridChangeScope[] _deferredScopes;
 79    private readonly NavigationGridChangeScope[] _priorBlockedScopes;
 80    private readonly NavigationGridBaselineCapture[] _baselineCaptures;
 119781    private PersistentStringMap<NavigationBaselineRebuild> _baselineRebuilds =
 119782        PersistentStringMap<NavigationBaselineRebuild>.Empty;
 83    private NavigationStructuralCompositionWork? _compositionWork;
 84    private NavigationMaterializedComponentWork? _materializedComponentWork;
 85    private bool _materializedComponentWorkCompletesOperation;
 86    private bool _materializedStartsAutomaticSeamLifecycle;
 87    private NavigationAutomaticSeamLifecycleWork? _lifecycleWork;
 88    private readonly VoxelIndex[] _baselineAddressScratch;
 89    private readonly GridCoveredAddress[] _baselineCoveredAddressScratch;
 90    private int _publicationEventCount;
 91    private int _lifecycleEventCount;
 92    private int _publicationBlockedScopeCount;
 93    private int _publicationResnapshotScopeCount;
 119794    private NavigationAreaCatalog _publicationAreaCatalog = NavigationAreaCatalog.Empty;
 95    private bool _publicationResnapshotAll;
 96    private bool _publicationBlockAll;
 119797    private NavigationWorldGraph _snapshotGraph = NavigationWorldGraph.Empty;
 119798    private NavigationWorldGraph _snapshotPreviousGraph = NavigationWorldGraph.Empty;
 119799    private NavigationOperationFrameChange[] _snapshotChanges = Array.Empty<NavigationOperationFrameChange>();
 100    private int _snapshotChangeCount;
 101    private bool _snapshotStartsAutomaticSeamLifecycle;
 102    private int _snapshotAffectedCount;
 103    private int _snapshotDeferredScopeCount;
 104    private long _snapshotWorldSpawnToken;
 105    private bool _snapshotDeferAll;
 106    private int _priorBlockedScopeCount;
 107    private bool _priorBlockAll;
 108    private readonly int[] _affectedMapOrdinals;
 109    private readonly int[] _affectedMapStamps;
 110    private int _affectedMapStamp;
 111    private int _lastAffectedMapCollectionCount;
 112    private bool _publishedThisMaintenance;
 113    private bool _automaticSeamFullRebuildPending;
 114    private bool _operationClosureRollbackPending;
 115    private NavigationSurfaceComponentKeySet? _ownedStructuralClosureBaseline;
 116    private bool _ownedStructuralClosureBaselineAll;
 117    private bool _resetPending;
 118    private bool _disposed;
 119
 1197120    internal NavigationGraphRuntime(GridWorld world, TrailblazerWorldContextSettings settings)
 121    {
 1197122        SwiftThrowHelper.ThrowIfNull(world, nameof(world));
 1197123        SwiftThrowHelper.ThrowIfNull(settings, nameof(settings));
 1197124        _world = world;
 1197125        _operations = new NavigationOperationProcessor(
 1197126            settings.OperationLimits,
 1197127            int.MaxValue,
 1197128            settings.NavigationAreaCount);
 1197129        int ingressCapacity = NavigationGridChangeIngress.GetMaximumCapacity(
 1197130            settings.MaxIngressEntries,
 1197131            settings.MaxIngressBytes,
 1197132            settings.OperationLimits.MaxMaps);
 1197133        SwiftThrowHelper.ThrowIfArgument(
 1197134            ingressCapacity <= 0,
 1197135            nameof(settings),
 1197136            "Ingress byte capacity must fit at least one final-state event.");
 1197137        _ingress = new NavigationGridChangeIngress(
 1197138            ingressCapacity,
 1197139            settings.OperationLimits.MaxMaps);
 1197140        _store = new NavigationWorldGraphStore(
 1197141            settings.MaxActiveSnapshots,
 1197142            settings.MaxRetiredSnapshots,
 1197143            settings.MaxRetiredSnapshotBytes,
 1197144            settings.MaxActiveSnapshotBytes,
 1197145            settings.MaxPersistentGraphPages,
 1197146            settings.MaxConcurrentSnapshotLeases);
 1197147        _areaPolicies = new NavigationAreaCatalogProcessor(settings);
 1197148        _maintenanceBudget = settings.MaintenanceBudget;
 1197149        _maintenanceMeter = new MaintenanceWorkMeter(_maintenanceBudget);
 1197150        _maxDynamicSlotsPerMap = settings.MaxDynamicCellSlotsPerMap;
 1197151        _maxDynamicSlots = settings.MaxDynamicCellSlots;
 1197152        _maxActiveSnapshotBytes = settings.MaxActiveSnapshotBytes;
 1197153        _maxPersistentGraphPages = settings.MaxPersistentGraphPages;
 1197154        _maintenanceEvents = new GridEventInfo[_maintenanceBudget.MaxConsumedEnvelopes];
 1197155        _blockedScopes = new NavigationGridChangeScope[settings.OperationLimits.MaxMaps];
 1197156        _resnapshotScopes = new NavigationGridChangeScope[settings.OperationLimits.MaxMaps];
 1197157        _deferredScopes = new NavigationGridChangeScope[settings.OperationLimits.MaxMaps];
 1197158        _priorBlockedScopes = new NavigationGridChangeScope[settings.OperationLimits.MaxMaps];
 1197159        _baselineCaptures = new NavigationGridBaselineCapture[settings.OperationLimits.MaxMaps];
 1197160        _baselineAddressScratch = new VoxelIndex[_maintenanceBudget.MaxBaselineAddresses];
 1197161        _baselineCoveredAddressScratch =
 1197162            new GridCoveredAddress[_maintenanceBudget.MaxBaselineAddresses];
 1197163        _affectedMapOrdinals = new int[settings.OperationLimits.MaxMaps];
 1197164        _affectedMapStamps = new int[settings.OperationLimits.MaxMaps];
 1197165        _publishCandidate = PublishPendingCandidate;
 1197166        _retainedWorkGuard = IsOperationWithinRetainedWorkCapacity;
 1197167        _maintainSnapshot = MaintainSnapshot;
 1197168    }
 169
 466170    internal NavigationWorldGraph Current => _store.Current;
 171
 3043172    internal NavigationWorldGraphStore Store => _store;
 173
 174    internal int RetainedBaselineCaptureCount
 175    {
 176        get
 177        {
 24178            int count = 0;
 816179            for (int i = 0; i < _baselineCaptures.Length; i++)
 180            {
 384181                if (_baselineCaptures[i].IsRequested)
 1182                    count++;
 183            }
 24184            return count;
 185        }
 186    }
 187
 552188    internal int RetainedCompositionWorkCount => (_compositionWork == null ? 0 : 1)
 552189        + (_materializedComponentWork == null ? 0 : 1)
 552190        + (_lifecycleWork == null ? 0 : 1);
 191
 2232192    internal long RetainedCompositionWorkBytes => checked(
 2232193        (_compositionWork?.RetainedBytes ?? 0L)
 2232194        + (_materializedComponentWork?.RetainedBytes ?? 0L)
 2232195        + (_lifecycleWork?.RetainedBytes ?? 0L)
 2232196        + GetOwnedClosureBaselineAdditionalRetainedBytes(_store.Current));
 197
 31198    internal long RetainedOperationWorkBytes => _operations.RetainedOperationWorkBytes;
 199
 48200    internal int RetainedOperationWorkCount => _operations.RetainedOperationWorkCount;
 201
 202    internal int RetainedCompositionWorkPageCount =>
 2572203        checked(
 2572204            (_compositionWork?.PersistentPageCount ?? 0)
 2572205            + (_materializedComponentWork?.PersistentPageCount ?? 0)
 2572206            + (_lifecycleWork?.PersistentPageCount ?? 0)
 2572207            + GetOwnedClosureBaselineAdditionalPersistentPages(_store.Current));
 208
 373209    internal int RetainedOperationWorkPageCount => _operations.RetainedOperationWorkPageCount;
 210
 321211    internal MaintenanceWorkMeter MaintenanceMeter => _maintenanceMeter;
 212
 2213    internal int LastAffectedMapCollectionCount => _lastAffectedMapCollectionCount;
 214
 215    internal bool Admit(NavigationMapCommitOperation operation)
 216    {
 1136217        EnsureUsable();
 1136218        return _operations.Admit(operation);
 219    }
 220
 221    internal bool Admit(NavigationMapRemoveOperation operation)
 222    {
 9223        EnsureUsable();
 9224        return _operations.Admit(operation);
 225    }
 226
 227    internal bool Admit(NavigationOverlayCommitOperation operation)
 228    {
 191229        EnsureUsable();
 191230        return _operations.Admit(operation);
 231    }
 232
 233    internal bool Admit(NavigationAreaPolicyCommitOperation operation)
 234    {
 172235        EnsureUsable();
 172236        return _areaPolicies.Admit(operation);
 237    }
 238
 239    internal NavigationWorldGraphLease? TryAcquire()
 240    {
 1550241        EnsureUsable();
 1550242        return _store.TryAcquire();
 243    }
 244
 245    internal void Maintain(int frame)
 246    {
 20559247        EnsureUsable();
 20559248        _maintenanceMeter.Reset();
 20559249        _publicationEventCount = 0;
 20559250        _publishedThisMaintenance = false;
 20559251        if (_resetPending)
 252        {
 2253            NavigationCandidatePublication resetPublication = _store.TryPublish(
 2254                NavigationWorldGraph.CreateEmpty(_store.Current.GraphVersion + 1));
 2255            if (resetPublication != NavigationCandidatePublication.Published)
 1256                return;
 1257            _resetPending = false;
 1258            _store.ClearSafetyPending();
 259        }
 20558260        if (_operationClosureRollbackPending
 20558261            && !_automaticSeamFullRebuildPending
 20558262            && !_ingress.HasPendingWork
 20558263            && _materializedComponentWork == null
 20558264            && _lifecycleWork == null)
 265        {
 2266            ApplyOperationTerminalRollback(
 2267                OperationTerminalDisposition.ReleaseAndTryReopen);
 2268            return;
 269        }
 20556270        if (_lifecycleWork != null)
 271        {
 272            // Lifecycle work owns the detached prefix in _maintenanceEvents. Its published
 273            // source is already all-closed, so leave later ingress queued while leases block
 274            // publication rather than overwriting the retained prefix with a pressure drain.
 220275            if (!_store.CanPublish)
 2276                return;
 218277            MaintainAutomaticSeamLifecycle();
 218278            return;
 279        }
 280
 20336281        if (!_store.CanPublish)
 282        {
 17283            DrainSafetyPrefixUnderPressure();
 17284            return;
 285        }
 286
 20319287        if (_materializedComponentWork != null)
 288        {
 3518289            if (!_materializedComponentWorkCompletesOperation
 3518290                || _operations.RetainedOperationWorkCount == 0)
 291            {
 188292                MaintainMaterializedComponentWork();
 188293                return;
 294            }
 3330295            if (MaintainMaterializedComponentWork(publish: false)
 3330296                == NavigationCandidatePublication.Deferred)
 297            {
 3125298                return;
 299            }
 300        }
 301
 17006302        if (_operations.RetainedOperationWorkCount == 0
 17006303            && _compositionWork == null
 17006304            && _materializedComponentWork == null)
 305        {
 3600306            NavigationWorldGraph ingressCurrent = _store.Current;
 3600307            NavigationCandidatePublication ingressPublication = ReconcileAndPublish(
 3600308                ingressCurrent,
 3600309                Array.Empty<NavigationOperationFrameChange>(),
 3600310                0,
 3600311                ingressCurrent.GraphVersion + 1,
 3600312                startAutomaticSeamLifecycle: true);
 3600313            if (_lifecycleWork != null
 3600314                || _publishedThisMaintenance
 3600315                || ingressPublication != NavigationCandidatePublication.Published)
 316            {
 136317                return;
 318            }
 319        }
 320
 16870321        NavigationWorldGraph before = _store.Current;
 16870322        bool graphWorkWasPending = _operations.RetainedOperationWorkCount != 0
 16870323            || _compositionWork != null
 16870324            || _materializedComponentWork != null;
 16870325        NavigationAreaCatalogProcessor.PreparedFrame policyFrame = default;
 16870326        bool policyPrepared = !graphWorkWasPending;
 16870327        _publicationAreaCatalog = before.AreaCatalog;
 16870328        if (policyPrepared)
 329        {
 3464330            policyFrame = _areaPolicies.Prepare(
 3464331                frame,
 3464332                before.AreaCatalog,
 3464333                _maintenanceMeter,
 3464334                checked(_maxActiveSnapshotBytes - before.RetainedBytes + before.AreaCatalog.RetainedBytes),
 3464335                checked(_maxPersistentGraphPages - before.PersistentPageCount + before.AreaCatalog.PersistentPageCount))
 3464336            _publicationAreaCatalog = policyFrame.Candidate;
 337        }
 16870338        NavigationOperationFrameResult operationResult = _operations.ProcessFrame(
 16870339            frame,
 16870340            _publishCandidate,
 16870341            _maintenanceMeter,
 16870342            _retainedWorkGuard);
 16870343        OperationTerminalDisposition terminalDisposition =
 16870344            ClassifyOperationTerminalDisposition(
 16870345                operationResult,
 16870346                _operations.RetainedOperationWorkCount,
 16870347                _compositionWork != null,
 16870348                _materializedComponentWorkCompletesOperation,
 16870349                _store.Current.HasClosedStructuralScope,
 16870350                _automaticSeamFullRebuildPending);
 16870351        if (terminalDisposition != OperationTerminalDisposition.None)
 352        {
 176353            _compositionWork = null;
 176354            AbandonMaterializedSnapshot(_materializedComponentWorkCompletesOperation);
 176355            bool returnsAfterCleanup = terminalDisposition is
 176356                OperationTerminalDisposition.ReleaseAndBeginRollback or
 176357                OperationTerminalDisposition.ReleaseAndTryReopen;
 176358            ApplyOperationTerminalRollback(terminalDisposition);
 176359            if (returnsAfterCleanup)
 3360                return;
 361        }
 16867362        if (operationResult == NavigationOperationFrameResult.Published)
 363        {
 945364            if (policyPrepared)
 764365                policyFrame.Complete(frame);
 945366            return;
 367        }
 15922368        if (operationResult == NavigationOperationFrameResult.Deferred)
 369        {
 13414370            _publicationAreaCatalog = before.AreaCatalog;
 13414371            long retainedWorkBytes = checked(
 13414372                _operations.RetainedOperationWorkBytes
 13414373                + (_compositionWork?.RetainedBytes ?? 0L));
 13414374            int retainedWorkPages = checked(
 13414375                _operations.RetainedOperationWorkPageCount
 13414376                + (_compositionWork?.PersistentPageCount ?? 0));
 13415377            if (!IsWithinRetainedWorkCapacity(retainedWorkBytes, retainedWorkPages)) RejectDeferredOperationForCapacity(
 13413378            else if (_compositionWork != null)
 379            {
 10859380                if (!_publishedThisMaintenance)
 381                {
 10368382                    NavigationWorldGraph compositionCurrent = _store.Current;
 10368383                    ReconcileAndPublish(
 10368384                        compositionCurrent,
 10368385                        Array.Empty<NavigationOperationFrameChange>(),
 10368386                        0,
 10368387                        compositionCurrent.GraphVersion + 1);
 388                }
 389            }
 2554390            else if (!_publishedThisMaintenance)
 391            {
 2553392                NavigationWorldGraph publishedGraph = _store.Current;
 2553393                long safetyVersion = publishedGraph.GraphVersion + 1;
 2553394                CaptureOwnedStructuralClosureBaseline(publishedGraph);
 2553395                NavigationWorldGraph closed = publishedGraph.WithClosedStructuralComponents(
 2553396                    NavigationSurfaceComponentKeySet.Empty,
 2553397                    true,
 2553398                    safetyVersion);
 2553399                NavigationCandidatePublication closurePublication = ReconcileAndPublish(
 2553400                    closed,
 2553401                    Array.Empty<NavigationOperationFrameChange>(),
 2553402                    0,
 2553403                    safetyVersion);
 2553404                if (closurePublication == NavigationCandidatePublication.PermanentCapacity)
 1405                    RejectDeferredOperationForCapacity();
 406            }
 13414407            if (_compositionWork != null)
 10859408                RequeuePublicationEvents();
 13414409            return;
 410        }
 411
 2508412        NavigationWorldGraph current = _store.Current;
 2508413        long nextVersion = current.GraphVersion + 1;
 2508414        NavigationAreaCatalog fallbackCatalog = policyPrepared
 2508415            ? policyFrame.Candidate
 2508416            : current.AreaCatalog;
 2508417        NavigationCandidatePublication fallbackPublication = ReconcileAndPublish(
 2508418            current.WithAreaCatalog(fallbackCatalog, nextVersion),
 2508419            Array.Empty<NavigationOperationFrameChange>(),
 2508420            0,
 2508421            nextVersion);
 2508422        CompletePolicyFrame(policyFrame, frame, policyPrepared, fallbackPublication);
 2508423        _publicationAreaCatalog = _store.Current.AreaCatalog;
 2508424    }
 425
 426    internal static void CompletePolicyFrame(
 427        NavigationAreaCatalogProcessor.PreparedFrame policyFrame,
 428        int frame,
 429        bool policyPrepared,
 430        NavigationCandidatePublication publication)
 431    {
 2512432        switch (ClassifyPolicyFrameDisposition(policyPrepared, publication))
 433        {
 434            case PolicyFrameDisposition.Complete:
 2506435                policyFrame.Complete(frame);
 2506436                break;
 437            case PolicyFrameDisposition.RejectCapacity:
 1438                policyFrame.CompleteCapacityRejected();
 439                break;
 440        }
 1441    }
 442
 443    internal static PolicyFrameDisposition ClassifyPolicyFrameDisposition(
 444        bool policyPrepared,
 445        NavigationCandidatePublication publication)
 446    {
 2512447        if (!policyPrepared)
 4448            return PolicyFrameDisposition.None;
 2508449        return publication switch
 2508450        {
 2506451            NavigationCandidatePublication.Published => PolicyFrameDisposition.Complete,
 1452            NavigationCandidatePublication.PermanentCapacity => PolicyFrameDisposition.RejectCapacity,
 1453            _ => PolicyFrameDisposition.None
 2508454        };
 455    }
 456
 457    internal static NavigationCandidatePublication ContinueAfterRetainedClosure(
 458        NavigationCandidatePublication publication) =>
 415459        publication == NavigationCandidatePublication.Published
 415460            ? NavigationCandidatePublication.Deferred
 415461            : publication;
 462
 463    internal static AutomaticSeamAdvanceDisposition ClassifyAutomaticSeamAdvance(
 464        NavigationAutomaticSeamLifecycleWork.AdvanceStatus status)
 465    {
 1327466        if (status == NavigationAutomaticSeamLifecycleWork.AdvanceStatus.Progressed)
 1105467            return AutomaticSeamAdvanceDisposition.Continue;
 222468        if (status == NavigationAutomaticSeamLifecycleWork.AdvanceStatus.Blocked)
 184469            return AutomaticSeamAdvanceDisposition.Retain;
 38470        return status == NavigationAutomaticSeamLifecycleWork.AdvanceStatus.Complete
 38471            ? AutomaticSeamAdvanceDisposition.Complete
 38472            : AutomaticSeamAdvanceDisposition.Restart;
 473    }
 474
 475    internal static MaterializedAdvanceDisposition ClassifyMaterializedAdvance(
 476        bool requiresRestart,
 477        bool withinCapacity,
 478        bool complete,
 479        bool publish,
 480        out NavigationCandidatePublication? abandonmentPublication)
 481    {
 3728482        if (requiresRestart)
 483        {
 2484            abandonmentPublication = NavigationCandidatePublication.Deferred;
 2485            return MaterializedAdvanceDisposition.Restart;
 486        }
 3726487        if (!withinCapacity)
 488        {
 1489            abandonmentPublication = NavigationCandidatePublication.PermanentCapacity;
 1490            return MaterializedAdvanceDisposition.RejectCapacity;
 491        }
 3725492        abandonmentPublication = null;
 3725493        if (!complete)
 3277494            return MaterializedAdvanceDisposition.Defer;
 448495        return publish
 448496            ? MaterializedAdvanceDisposition.Publish
 448497            : MaterializedAdvanceDisposition.Ready;
 498    }
 499
 500    internal static OperationTerminalDisposition ClassifyOperationTerminalDisposition(
 501        NavigationOperationFrameResult result,
 502        int retainedOperationWorkCount,
 503        bool hasCompositionWork,
 504        bool materializedCompletesOperation,
 505        bool hasClosedStructuralScope,
 506        bool automaticSeamFullRebuildPending)
 507    {
 16876508        if (result == NavigationOperationFrameResult.Published
 16876509            && retainedOperationWorkCount == 0
 16876510            && (hasCompositionWork || materializedCompletesOperation))
 511        {
 3512            return OperationTerminalDisposition.ReleaseAndBeginRollback;
 513        }
 16873514        if (result != NavigationOperationFrameResult.Rejected)
 16695515            return OperationTerminalDisposition.None;
 178516        if (!hasClosedStructuralScope)
 174517            return OperationTerminalDisposition.Release;
 4518        return automaticSeamFullRebuildPending
 4519            ? OperationTerminalDisposition.ReleaseAndBeginRollback
 4520            : OperationTerminalDisposition.ReleaseAndTryReopen;
 521    }
 522
 523    internal static void GetOwnedClosureBaselineAdditionalCapacity(
 524        NavigationSurfaceComponentKeySet? baseline,
 525        NavigationWorldGraph ownerGraph,
 526        out long retainedBytes,
 527        out int persistentPages)
 528    {
 40215529        if (baseline == null
 40215530            || ReferenceEquals(baseline, NavigationSurfaceComponentKeySet.Empty)
 40215531            || ownerGraph.RetainsClosedComponentRoot(baseline))
 532        {
 40214533            retainedBytes = 0;
 40214534            persistentPages = 0;
 40214535            return;
 536        }
 1537        retainedBytes = baseline.RetainedBytes;
 1538        persistentPages = baseline.PersistentPageCount;
 1539    }
 540
 541    internal static bool IsRetainedWorkWithinCapacity(
 542        long rootBytes,
 543        int rootPages,
 544        long workBytes,
 545        int workPages,
 546        long rebuildBytes,
 547        int rebuildPages,
 548        long maximumBytes,
 549        int maximumPages)
 550    {
 551        System.Diagnostics.Debug.Assert(workPages >= 0);
 552        System.Diagnostics.Debug.Assert(rebuildPages >= 0);
 40001553        long retainedPages = (long)rootPages + workPages + rebuildPages;
 40001554        return rootBytes <= maximumBytes
 40001555            && workBytes <= maximumBytes - rootBytes
 40001556            && rebuildBytes <= maximumBytes - rootBytes - workBytes
 40001557            && retainedPages <= maximumPages;
 558    }
 559
 560    private void MaintainSnapshot()
 561    {
 20249562        _publicationEventCount = _ingress.DetachInto(
 20249563            _maintenanceEvents.AsSpan(0, _maintenanceMeter.RemainingEnvelopes),
 20249564            _blockedScopes,
 20249565            out _publicationBlockedScopeCount,
 20249566            out _publicationBlockAll,
 20249567            out bool topologyLifecycleCoverageLost);
 20249568        if (topologyLifecycleCoverageLost
 20249569            || (!_snapshotStartsAutomaticSeamLifecycle
 20249570                && ContainsTopologyLifecycle(_maintenanceEvents, _publicationEventCount)))
 571        {
 31572            _automaticSeamFullRebuildPending = true;
 573        }
 20249574        _maintenanceMeter.TryConsumeEnvelopes(_publicationEventCount);
 20249575        _publicationResnapshotScopeCount = PrepareResnapshotScopes(
 20249576            _publicationBlockedScopeCount,
 20249577            _publicationBlockAll);
 20249578        _publicationResnapshotAll = _priorBlockAll && !_publicationBlockAll;
 20249579        _snapshotWorldSpawnToken = _world.SpawnToken;
 20249580        long retainedWorkBytes = checked(
 20249581            _operations.RetainedOperationWorkBytes
 20249582            + (_compositionWork?.RetainedBytes ?? 0L));
 20249583        int retainedWorkPages = checked(
 20249584            _operations.RetainedOperationWorkPageCount
 20249585            + (_compositionWork?.PersistentPageCount ?? 0));
 20249586        long maximumGraphBytes = Math.Max(0L, _maxActiveSnapshotBytes - retainedWorkBytes);
 20249587        int maximumGraphPages = Math.Max(0, _maxPersistentGraphPages - retainedWorkPages);
 20249588        _snapshotAffectedCount = _snapshotGraph.CaptureMaintenanceSnapshot(
 20249589            _world,
 20249590            _snapshotPreviousGraph,
 20249591            _maintenanceEvents.AsSpan(0, _publicationEventCount),
 20249592            _resnapshotScopes.AsSpan(0, _publicationResnapshotScopeCount),
 20249593            _publicationResnapshotAll,
 20249594            _blockedScopes.AsSpan(0, _publicationBlockedScopeCount),
 20249595            _publicationBlockAll,
 20249596            _snapshotChanges,
 20249597            _snapshotChangeCount,
 20249598            _maintenanceMeter,
 20249599            maximumGraphBytes,
 20249600            maximumGraphPages,
 20249601            _baselineCaptures,
 20249602            ref _baselineRebuilds,
 20249603            _baselineAddressScratch,
 20249604            _baselineCoveredAddressScratch,
 20249605            _deferredScopes,
 20249606            out _snapshotDeferredScopeCount,
 20249607            out _snapshotDeferAll,
 20249608            _affectedMapOrdinals,
 20249609            _affectedMapStamps,
 20249610            ref _affectedMapStamp,
 20249611            out _lastAffectedMapCollectionCount);
 20249612    }
 613
 614    private NavigationCandidatePublication ReconcileAndPublish(
 615        NavigationWorldGraph graph,
 616        NavigationOperationFrameChange[] changes,
 617        int changeCount,
 618        long graphVersion,
 619        bool startAutomaticSeamLifecycle = false)
 620    {
 20454621        if (_materializedComponentWork != null)
 205622            return MaintainMaterializedComponentWork(structuralClosure: graph);
 20249623        AdvanceCoveredBaselineRebuilds(graph);
 20249624        _snapshotGraph = graph;
 20249625        _snapshotPreviousGraph = _store.Current;
 20249626        _snapshotChanges = changes;
 20249627        _snapshotChangeCount = changeCount;
 20249628        _snapshotStartsAutomaticSeamLifecycle = startAutomaticSeamLifecycle;
 20249629        _world.ExecuteNavigationMaintenanceSnapshot(_maintainSnapshot);
 630
 631        NavigationCandidatePublication publication;
 632        try
 633        {
 20249634            NavigationWorldGraph next = graph.ApplyMaintenanceSnapshot(
 20249635                _snapshotWorldSpawnToken,
 20249636                _snapshotPreviousGraph,
 20249637                _maintenanceEvents.AsSpan(0, _publicationEventCount),
 20249638                _resnapshotScopes.AsSpan(0, _publicationResnapshotScopeCount),
 20249639                _publicationResnapshotAll,
 20249640                _blockedScopes.AsSpan(0, _publicationBlockedScopeCount),
 20249641                _publicationBlockAll,
 20249642                changes,
 20249643                changeCount,
 20249644                _baselineCaptures,
 20249645                _affectedMapOrdinals,
 20249646                _snapshotAffectedCount,
 20249647                graphVersion);
 20249648            bool hasAutomaticSeamLifecycle = startAutomaticSeamLifecycle
 20249649                && HasRelevantAutomaticSeamLifecycleEvent(graph, next);
 20249650            NavigationCandidatePublication? componentHold =
 20249651                !next.IsWithinDynamicSlotCapacity(
 20249652                    _maxDynamicSlotsPerMap,
 20249653                    _maxDynamicSlots)
 20249654                    ? NavigationCandidatePublication.PermanentCapacity
 20249655                    : TryPrepareMaterializedComponents(
 20249656                        ref next,
 20249657                        hasAutomaticSeamLifecycle);
 20249658            if (_automaticSeamFullRebuildPending && !startAutomaticSeamLifecycle)
 659            {
 61660                next = next.WithClosedStructuralComponents(
 61661                    NavigationSurfaceComponentKeySet.Empty,
 61662                    true,
 61663                    graphVersion);
 664            }
 20249665            NavigationWorldGraph current = _store.Current;
 20249666            publication = componentHold.HasValue
 20249667                ? componentHold.Value
 20249668                : hasAutomaticSeamLifecycle
 20249669                ? StartAutomaticSeamLifecycle(
 20249670                    current,
 20249671                    next,
 20249672                    graphVersion)
 20249673                : ReferenceEquals(current, next)
 20249674                    ? NavigationCandidatePublication.Published
 20249675                    : _store.TryPublish(next);
 20249676            if (!ReferenceEquals(current, next)
 20249677                && publication == NavigationCandidatePublication.Published)
 678            {
 3787679                _publishedThisMaintenance = true;
 680            }
 20249681            if (publication == NavigationCandidatePublication.Published
 20249682                && _automaticSeamFullRebuildPending
 20249683                && next.HasClosedStructuralScope)
 684            {
 50685                _store.ClearSafetyPending();
 686            }
 20249687        }
 688        finally
 689        {
 20249690            if (_materializedComponentWork == null)
 20006691                ClearBaselineCaptures();
 20249692        }
 20249693        if (publication == NavigationCandidatePublication.Published)
 694        {
 19981695            RemoveCompletedBaselineRebuilds();
 19981696            CommitBlockedScopes(
 19981697                _publicationBlockedScopeCount,
 19981698                _publicationBlockAll,
 19981699                _snapshotDeferredScopeCount,
 19981700                _snapshotDeferAll);
 19981701            ClearSafetyPendingAfterExactResnapshot();
 702        }
 703        else
 704        {
 268705            bool hasMaterializedWork = _materializedComponentWork != null;
 268706            bool materializedWorkOwnsAllClosedSource = hasMaterializedWork
 268707                && _store.Current.AreAllStructuralComponentsClosed;
 268708            if (_automaticSeamFullRebuildPending
 268709                && !materializedWorkOwnsAllClosedSource)
 710            {
 1711                _store.MarkSafetyPending();
 712            }
 268713            if (!hasMaterializedWork)
 25714                MarkResnapshotRequired();
 715        }
 20249716        return publication;
 717    }
 718
 719    private NavigationCandidatePublication? TryPrepareMaterializedComponents(
 720        ref NavigationWorldGraph candidate,
 721        bool startsAutomaticSeamLifecycle)
 722    {
 20236723        if (_snapshotAffectedCount == 0 && _publicationEventCount == 0)
 18392724            return null;
 1844725        var work = new NavigationMaterializedComponentWork(
 1844726            candidate,
 1844727            NavigationSurfaceComponentKeySet.Empty,
 1844728            NavigationSurfaceComponentKeySet.Empty,
 1844729            NavigationCellAddressSet.Empty,
 1844730            affectedMemberCount: 0,
 1844731            _world,
 1844732            _baselineCaptures,
 1844733            _affectedMapOrdinals,
 1844734            _snapshotAffectedCount,
 1844735            _maintenanceEvents,
 1844736            _publicationEventCount,
 1844737            _operations.Candidate);
 1844738        bool complete = work.Advance(_maintenanceMeter);
 1844739        if (!IsWithinRetainedWorkCapacity(
 1844740                GetCombinedMaterializedWorkBytes(work),
 1844741                GetCombinedMaterializedWorkPages(work)))
 12742            return NavigationCandidatePublication.PermanentCapacity;
 1832743        if (complete && work.RevalidateForPublication())
 744        {
 1589745            candidate = work.Result;
 1589746            return null;
 747        }
 748
 243749        NavigationWorldGraph current = _store.Current;
 243750        CaptureOwnedStructuralClosureBaseline(current);
 243751        NavigationWorldGraph closed = CreateOwnedStructuralClosure(
 243752            current,
 243753            NavigationSurfaceComponentKeySet.Empty,
 243754            closeAll: true,
 243755            current.GraphVersion + 1);
 756        System.Diagnostics.Debug.Assert(!ReferenceEquals(current, closed),
 757            "Materialized work closes a newly versioned maintenance candidate.");
 243758        NavigationCandidatePublication publication = _store.TryPublish(closed);
 243759        ApplyPublishedCandidate(
 243760            publication,
 243761            PublishedCandidateEffect.InstallMaterialized,
 243762            work,
 243763            startsAutomaticSeamLifecycle);
 243764        return ContinueAfterRetainedClosure(publication);
 765    }
 766
 767    private NavigationCandidatePublication MaintainMaterializedComponentWork(
 768        bool publish = true,
 769        NavigationWorldGraph? structuralClosure = null)
 770    {
 3723771        NavigationMaterializedComponentWork work = _materializedComponentWork!;
 3723772        bool complete = work.Advance(_maintenanceMeter);
 3723773        bool requiresRestart = work.RequiresSnapshotRestart;
 3723774        bool revalidated = !requiresRestart
 3723775            && complete
 3723776            && work.RevalidateForPublication();
 3723777        requiresRestart |= work.RequiresSnapshotRestart;
 3723778        bool withinCapacity = requiresRestart
 3723779            || IsWithinRetainedWorkCapacity(
 3723780                GetCombinedMaterializedWorkBytes(work),
 3723781                GetCombinedMaterializedWorkPages(work));
 3723782        MaterializedAdvanceDisposition disposition = ClassifyMaterializedAdvance(
 3723783            requiresRestart,
 3723784            withinCapacity,
 3723785            complete,
 3723786            publish,
 3723787            out NavigationCandidatePublication? abandonmentPublication);
 3723788        if (abandonmentPublication.HasValue)
 1789            return RestartMaterializedSnapshot(abandonmentPublication.Value);
 3722790        if (disposition == MaterializedAdvanceDisposition.Defer)
 3276791            return NavigationCandidatePublication.Deferred;
 792        System.Diagnostics.Debug.Assert(revalidated,
 793            "Completed failed revalidation always requests a snapshot restart above.");
 446794        if (disposition == MaterializedAdvanceDisposition.Ready)
 205795            return NavigationCandidatePublication.Published;
 796
 241797        NavigationWorldGraph current = _store.Current;
 798        System.Diagnostics.Debug.Assert(_ownedStructuralClosureBaseline != null,
 799            "Retained materialized work owns the structural-closure baseline captured at installation.");
 241800        NavigationWorldGraph completed = structuralClosure == null
 241801            ? work.Result.WithClosedStructuralComponents(
 241802                _ownedStructuralClosureBaseline!,
 241803                _ownedStructuralClosureBaselineAll,
 241804                current.GraphVersion + 1)
 241805            : work.Result.WithStructuralClosureFrom(
 241806                structuralClosure,
 241807                current.GraphVersion + 1);
 808        NavigationCandidatePublication publication;
 241809        if (_materializedStartsAutomaticSeamLifecycle)
 810        {
 12811            _publicationEventCount = work.RetainedEventCount;
 12812            publication = StartAutomaticSeamLifecycle(
 12813                current,
 12814                completed,
 12815                completed.GraphVersion);
 816        }
 817        else
 818        {
 229819            publication = _store.TryPublish(completed);
 820        }
 241821        ApplyPublishedCandidate(
 241822            publication,
 241823            structuralClosure == null
 241824                ? PublishedCandidateEffect.CompleteMaterialized
 241825                : PublishedCandidateEffect.CompleteMaterializedWithinStructuralPublication);
 241826        return publication;
 827    }
 828
 829    private NavigationCandidatePublication RestartMaterializedSnapshot(
 830        NavigationCandidatePublication publication = NavigationCandidatePublication.Deferred)
 831    {
 1832        AbandonMaterializedSnapshot();
 1833        return publication;
 834    }
 835
 836    private void AbandonMaterializedSnapshot(bool required = true)
 837    {
 177838        if (!required)
 176839            return;
 1840        _publicationEventCount = _materializedComponentWork!.RetainedEventCount;
 1841        _materializedComponentWork = null;
 1842        _materializedComponentWorkCompletesOperation = false;
 1843        _materializedStartsAutomaticSeamLifecycle = false;
 1844        ClearBaselineCaptures();
 1845        RemoveCompletedBaselineRebuilds();
 1846        RequeuePublicationEvents();
 1847        MarkResnapshotRequired();
 1848    }
 849
 850    private void AdvanceCoveredBaselineRebuilds(NavigationWorldGraph graph)
 851    {
 20249852        int remainingAddresses = _maintenanceMeter.RemainingBaselineAddresses;
 20249853        if (remainingAddresses == 0 || _baselineRebuilds.Count == 0)
 20146854            return;
 103855        NavigationBaselineRebuild.GetRetainedTotals(
 103856            _baselineRebuilds,
 103857            out long totalBytes,
 103858            out int totalPages);
 420859        for (int i = 0; i < _baselineRebuilds.Count && remainingAddresses > 0; i++)
 860        {
 107861            NavigationBaselineRebuild rebuild = _baselineRebuilds.GetValueAt(i);
 107862            if (!rebuild.RequiresCoveredDiscovery
 107863                || rebuild.IsComplete)
 864            {
 865                continue;
 866            }
 51867            bool mapFound = graph.TryGetMap(
 51868                rebuild.MapId,
 51869                out NavigationMapInstance instance);
 870            System.Diagnostics.Debug.Assert(
 871                mapFound && rebuild.Matches(instance),
 872                "An inspectable covered-baseline rebuild retains the exact live map generation that owns it.");
 51873            long beforeBytes = rebuild.RetainedBytes;
 51874            int beforePages = rebuild.PersistentPageCount;
 51875            long maximumBytes = Math.Max(
 51876                0L,
 51877                _maxActiveSnapshotBytes - graph.RetainedBytes - (totalBytes - beforeBytes));
 51878            int maximumPages = Math.Max(
 51879                0,
 51880                _maxPersistentGraphPages - graph.PersistentPageCount - (totalPages - beforePages));
 51881            int consumed = rebuild.Advance(
 51882                _world,
 51883                instance,
 51884                remainingAddresses,
 51885                maximumBytes,
 51886                maximumPages,
 51887                _baselineAddressScratch,
 51888                _baselineCoveredAddressScratch,
 51889                out _,
 51890                out _);
 51891            totalBytes = checked(totalBytes - beforeBytes + rebuild.RetainedBytes);
 51892            totalPages = checked(totalPages - beforePages + rebuild.PersistentPageCount);
 51893            _maintenanceMeter.TryConsumeBaselineAddresses(consumed);
 51894            remainingAddresses -= consumed;
 895        }
 103896    }
 897
 898    private bool HasRelevantAutomaticSeamLifecycleEvent(
 899        NavigationWorldGraph source,
 900        NavigationWorldGraph prepared)
 901    {
 3600902        if (_automaticSeamFullRebuildPending)
 12903            return true;
 8992904        for (int i = 0; i < _publicationEventCount; i++)
 905        {
 932906            GridEventInfo eventInfo = _maintenanceEvents[i];
 932907            if (eventInfo.ChangeKind == GridEventKind.WorldReset)
 908            {
 1909                if (source.MapCount != 0)
 1910                    return true;
 911                continue;
 912            }
 931913            GridForge.Configuration.GridConfigurationKey key =
 931914                eventInfo.Configuration.ToGridKey();
 931915            if (eventInfo.ChangeKind == GridEventKind.GridRemoved
 931916                && source.TryGetMapId(key, out _))
 917            {
 11918                return true;
 919            }
 920920            if (eventInfo.ChangeKind == GridEventKind.GridAdded
 920921                && prepared.TryGetMapId(key, out _))
 922            {
 12923                return true;
 924            }
 925        }
 3564926        return false;
 927    }
 928
 929    private NavigationCandidatePublication StartAutomaticSeamLifecycle(
 930        NavigationWorldGraph current,
 931        NavigationWorldGraph prepared,
 932        long graphVersion)
 933    {
 36934        NavigationWorldGraph closed = prepared.WithClosedStructuralComponents(
 36935            NavigationSurfaceComponentKeySet.Empty,
 36936            true,
 36937            graphVersion);
 938        System.Diagnostics.Debug.Assert(IsWithinRetainedWorkCapacity(
 939                checked(
 940                    NavigationAutomaticSeamLifecycleWork.BaseRetainedBytes
 941                    + NavigationAutomaticSeamRefreshWork.FixedRetainedBytes),
 942                5,
 943                closed),
 944            "Successful materialized preparation strictly dominates the automatic-seam minimum retained-work envelope.")
 945        System.Diagnostics.Debug.Assert(!ReferenceEquals(current, closed),
 946            "Automatic seam lifecycle starts from a newly versioned closed candidate.");
 36947        NavigationCandidatePublication publication = _store.TryPublish(closed);
 948        System.Diagnostics.Debug.Assert(
 949            publication == NavigationCandidatePublication.Published,
 950            "Maintenance preflight and retained-work bounds guarantee automatic-seam closure publication.");
 36951        _store.SetSafetyPending(false);
 36952        ApplyPublishedCandidate(
 36953            publication,
 36954            PublishedCandidateEffect.StartAutomaticSeam,
 36955            automaticSeamGraph: closed);
 36956        return publication;
 957    }
 958
 959    private void MaintainAutomaticSeamLifecycle()
 960    {
 218961        NavigationAutomaticSeamLifecycleWork work = _lifecycleWork!;
 218962        GetLifecycleWorkAllowance(out long bytes, out int pages);
 963        while (true)
 964        {
 1322965            NavigationAutomaticSeamLifecycleWork.AdvanceStatus status = work.AdvanceOne(
 1322966                _maintenanceMeter,
 1322967                bytes,
 1322968                pages);
 1322969            AutomaticSeamAdvanceDisposition disposition =
 1322970                ClassifyAutomaticSeamAdvance(status);
 1322971            if (disposition == AutomaticSeamAdvanceDisposition.Complete)
 972            {
 33973                bool revalidated = work.RevalidateForPublication();
 33974                bool withinCapacity = IsWithinRetainedWorkCapacity(0, 0, work.Result);
 975                System.Diagnostics.Debug.Assert(revalidated,
 976                    "A completed seam cursor is revalidated on the same deterministic maintenance boundary.");
 977                System.Diagnostics.Debug.Assert(withinCapacity,
 978                    "Completed automatic-seam work remains inside its exact retained-work allowance.");
 33979                disposition = AutomaticSeamAdvanceDisposition.Complete;
 980            }
 981            switch (disposition)
 982            {
 983                case AutomaticSeamAdvanceDisposition.Continue:
 984                    continue;
 985                case AutomaticSeamAdvanceDisposition.Retain:
 183986                    return;
 987                case AutomaticSeamAdvanceDisposition.Restart:
 2988                    RestartAutomaticSeamLifecycle();
 2989                    return;
 990                case AutomaticSeamAdvanceDisposition.Complete:
 33991                    NavigationWorldGraph next = work.Result;
 33992                    NavigationCandidatePublication publication = _store.TryPublish(next);
 33993                    ApplyPublishedCandidate(
 33994                        publication,
 33995                        PublishedCandidateEffect.CompleteAutomaticSeam);
 33996                    return;
 997            }
 998        }
 999    }
 1000
 1001    private void GetLifecycleWorkAllowance(out long bytes, out int pages)
 1002    {
 1003        System.Diagnostics.Debug.Assert(_compositionWork == null,
 1004            "Automatic-seam lifecycle work starts only from ingress reconciliation without operation composition ownersh
 2181005        NavigationBaselineRebuild.GetRetainedTotals(
 2181006            _baselineRebuilds,
 2181007            out long rebuildBytes,
 2181008            out int rebuildPages);
 2181009        NavigationWorldGraph current = _store.Current;
 2181010        bytes = _maxActiveSnapshotBytes
 2181011            - current.RetainedBytes
 2181012            - rebuildBytes
 2181013            - _operations.RetainedOperationWorkBytes;
 2181014        pages = _maxPersistentGraphPages
 2181015            - current.PersistentPageCount
 2181016            - rebuildPages
 2181017            - _operations.RetainedOperationWorkPageCount;
 2181018    }
 1019
 1020    private void RequeueAutomaticSeamLifecyclePrefix()
 1021    {
 21022        _ingress.RequeuePrefix(_maintenanceEvents.AsSpan(0, _lifecycleEventCount));
 21023        _lifecycleEventCount = 0;
 21024    }
 1025
 1026    private void RestartAutomaticSeamLifecycle()
 1027    {
 21028        RequeueAutomaticSeamLifecyclePrefix();
 21029        _lifecycleWork = null;
 21030    }
 1031
 1032    internal bool TryGetCellState(
 1033        string mapId,
 1034        VoxelIndex index,
 1035        out NavigationGraphCellState state)
 1036    {
 5511037        EnsureUsable();
 5511038        NavigationWorldGraph graph = _store.Current;
 5511039        if (!graph.TryGetMap(mapId, out NavigationMapInstance instance)
 5511040            || !instance.TryGetSlot(index, out int slot))
 1041        {
 1921042            state = default;
 1921043            return false;
 1044        }
 1045
 3591046        bool hasCell = instance.TryGetEffectiveCell(slot, out NavigationCell cell);
 3591047        instance.TryGetPhysicalState(slot, out bool isPresent, out byte obstacleCount);
 3591048        state = new NavigationGraphCellState(
 3591049            mapId,
 3591050            index,
 3591051            slot,
 3591052            slot >= instance.BakedSlotCount,
 3591053            hasCell,
 3591054            cell,
 3591055            instance.IsMaterialized
 3591056                && !graph.IsSurfaceAddressClosed(
 3591057                    new NavigationCellAddress(mapId, index),
 3591058                    TraversalMedium.Solid),
 3591059            isPresent,
 3591060            obstacleCount,
 3591061            instance.GridIdentity.GridSpawnToken);
 3591062        return true;
 1063    }
 1064
 1065    internal bool TryResolveAreaPolicy(
 1066        NavigationAreaPolicyKey key,
 1067        out NavigationAreaPolicy? policy)
 1068    {
 71069        EnsureUsable();
 71070        return _store.Current.AreaCatalog.TryGet(key, out policy);
 1071    }
 1072
 1073    internal NavigationGraphDiagnosticsSnapshot GetDiagnostics(int maximumCells)
 1074    {
 22001075        EnsureUsable();
 22001076        NavigationWorldGraph graph = _store.Current;
 22001077        NavigationBaselineRebuild.GetRetainedTotals(
 22001078            _baselineRebuilds,
 22001079            out long baselineRebuildBytes,
 22001080            out int baselineRebuildPages);
 22001081        int baselineCapacityBlockedCount =
 22001082            NavigationBaselineRebuild.CountCapacityBlocked(_baselineRebuilds);
 22001083        long compositionWorkBytes = RetainedCompositionWorkBytes;
 22001084        int compositionWorkPages = RetainedCompositionWorkPageCount;
 22001085        long operationWorkBytes = _operations.RetainedOperationWorkBytes;
 22001086        int operationWorkPages = _operations.RetainedOperationWorkPageCount;
 22001087        var maps = new NavigationGraphMapDiagnostic[graph.MapCount];
 22001088        int remaining = maximumCells;
 22001089        bool truncated = false;
 336701090        for (int i = 0; i < graph.MapCount; i++)
 1091        {
 146351092            NavigationMapInstance instance = graph.GetInstance(i);
 146351093            GetSurfaceComponentDiagnostic(
 146351094                graph,
 146351095                instance,
 146351096                out int componentId,
 146351097                out long componentVersion);
 146351098            maps[i] = instance.CreateDiagnostic(
 146351099                remaining,
 146351100                componentId,
 146351101                componentVersion,
 146351102                graph.ExplicitConnections.GetActiveIncidentEdgeCount(
 146351103                    instance.MapId),
 146351104                out bool mapTruncated);
 146351105            remaining -= maps[i].Cells.Count;
 146351106            truncated |= mapTruncated;
 1107        }
 22001108        return new NavigationGraphDiagnosticsSnapshot(
 22001109            graph.GraphVersion,
 22001110            graph.AreaCatalog.Version,
 22001111            checked(
 22001112                graph.RetainedBytes
 22001113                + baselineRebuildBytes
 22001114                + compositionWorkBytes
 22001115                + operationWorkBytes
 22001116                + _areaPolicies.PendingRetainedBytes),
 22001117            _store.ActiveGenerationCount,
 22001118            _store.ActiveLeaseCount,
 22001119            checked(
 22001120                graph.PersistentPageCount
 22001121                + baselineRebuildPages
 22001122                + compositionWorkPages
 22001123                + operationWorkPages
 22001124                + _areaPolicies.PendingCount),
 22001125            _store.RetiredGenerationCount,
 22001126            _store.RetiredBytes,
 22001127            _areaPolicies.PendingCount,
 22001128            _areaPolicies.PendingRuleCount,
 22001129            _areaPolicies.PendingRetainedBytes,
 22001130            _baselineRebuilds.Count,
 22001131            baselineCapacityBlockedCount,
 22001132            baselineRebuildBytes,
 22001133            baselineRebuildPages,
 22001134            truncated,
 22001135            maps);
 1136    }
 1137
 1138    private static void GetSurfaceComponentDiagnostic(
 1139        NavigationWorldGraph graph,
 1140        NavigationMapInstance instance,
 1141        out int componentId,
 1142        out long componentVersion)
 1143    {
 146351144        componentId = 0;
 146351145        componentVersion = 0;
 146351146        NavigationSurfaceComponentKey selected = default;
 146351147        bool found = false;
 146351148        int bakedCursor = 0;
 146351149        int dynamicCursor = 0;
 146351150        Span<GridForge.Spatial.VoxelIndex> address =
 146351151            stackalloc GridForge.Spatial.VoxelIndex[1];
 43202421152        for (int ordinal = 0; ordinal < instance.AddressCount; ordinal++)
 1153        {
 21454931154            instance.CopyCanonicalAddressChunk(
 21454931155                ref bakedCursor,
 21454931156                ref dynamicCursor,
 21454931157                address);
 21454931158            var exact = new NavigationCellAddress(instance.MapId, address[0]);
 21454931159            if (!graph.HasEffectiveCell(exact)
 21454931160                || !graph.TryGetSurfaceComponent(
 21454931161                    exact,
 21454931162                    TraversalMedium.Solid,
 21454931163                    out NavigationSurfaceComponentKey key,
 21454931164                    out long version))
 1165            {
 1166                continue;
 1167            }
 21454901168            if (!found)
 1169            {
 146341170                selected = key;
 146341171                componentId = key.GetHashCode();
 146341172                componentVersion = version;
 146341173                found = true;
 1174            }
 21308561175            else if (!key.Equals(selected))
 1176            {
 71177                componentId = -1;
 71178                componentVersion = 0;
 71179                return;
 1180            }
 1181        }
 146281182    }
 1183
 1184    internal void Reset()
 1185    {
 231186        EnsureUsable();
 231187        _operations.Reset();
 231188        _areaPolicies.Reset();
 231189        _ingress.Reset();
 231190        _priorBlockedScopeCount = 0;
 231191        _priorBlockAll = false;
 231192        _baselineRebuilds = PersistentStringMap<NavigationBaselineRebuild>.Empty;
 231193        _compositionWork = null;
 231194        _materializedComponentWork = null;
 231195        _materializedComponentWorkCompletesOperation = false;
 231196        _materializedStartsAutomaticSeamLifecycle = false;
 231197        _lifecycleWork = null;
 231198        _lifecycleEventCount = 0;
 231199        _automaticSeamFullRebuildPending = false;
 231200        _operationClosureRollbackPending = false;
 231201        ClearOwnedStructuralClosureBaseline();
 231202        Array.Clear(_baselineCaptures, 0, _baselineCaptures.Length);
 231203        _resetPending = _store.TryPublish(
 231204            NavigationWorldGraph.CreateEmpty(_store.Current.GraphVersion + 1))
 231205            != NavigationCandidatePublication.Published;
 231206        MarkSafetyPendingIf(_resetPending);
 231207        if (!_resetPending)
 221208            _store.ClearSafetyPending();
 231209    }
 1210
 1211    public void Dispose()
 1212    {
 11971213        if (_disposed)
 11214            return;
 11961215        _disposed = true;
 11961216        _baselineRebuilds = PersistentStringMap<NavigationBaselineRebuild>.Empty;
 11961217        _compositionWork = null;
 11961218        _materializedComponentWork = null;
 11961219        _materializedComponentWorkCompletesOperation = false;
 11961220        _materializedStartsAutomaticSeamLifecycle = false;
 11961221        _lifecycleWork = null;
 11961222        _lifecycleEventCount = 0;
 11961223        _automaticSeamFullRebuildPending = false;
 11961224        Array.Clear(_baselineCaptures, 0, _baselineCaptures.Length);
 11961225        _ingress.Dispose();
 11961226        _store.Dispose();
 11961227    }
 1228
 1229    private NavigationCandidatePublication PublishCandidate(
 1230        NavigationOperationCandidate candidate,
 1231        NavigationAreaCatalog areaCatalog,
 1232        NavigationOperationFrameChange[] changes,
 1233        int changeCount)
 1234    {
 119671235        if (_compositionWork != null)
 1236        {
 108541237            if (_compositionWork.RequiresAllClosePublication) return PublishAllCompositionClosureAndDefer(_compositionWo
 108521238            if (_compositionWork.RequiresAffectedClosurePublication)
 1239            {
 1691240                if (!_compositionWork.RevalidateAutomaticSeamsForPublication()) return NavigationCandidatePublication.De
 1671241                return PublishAffectedCompositionClosureAndDefer(_compositionWork);
 1242            }
 106841243            GetCompositionWorkAllowance(out long resumedBytes, out int resumedPages);
 106841244            if (!_compositionWork.Advance(
 106841245                    _maintenanceMeter,
 106841246                    resumedBytes,
 106841247                    resumedPages,
 106841248                    out bool resumedCapacityExceeded))
 1249            {
 1250                System.Diagnostics.Debug.Assert(
 1251                    !_compositionWork.RequiresAllClosePublication,
 1252                    "Affected closure publication follows completed seam capture; incomplete advancement cannot invalida
 103701253                if (resumedCapacityExceeded) return RollbackCompositionForCapacityRejection();
 1254                System.Diagnostics.Debug.Assert(IsWithinRetainedWorkCapacity(
 1255                        GetCombinedCompositionWorkBytes(_compositionWork, _store.Current),
 1256                        GetCombinedCompositionWorkPages(_compositionWork, _store.Current)),
 1257                    "A non-capacity blocked advance remains inside its exact unchanged-root allowance.");
 103681258                return NavigationCandidatePublication.Deferred;
 1259            }
 3151260            if (!_compositionWork.RevalidateAutomaticSeamsForPublication())
 1261            {
 1262                System.Diagnostics.Debug.Assert(
 1263                    _compositionWork.RequiresAllClosePublication,
 1264                    "Failed completed-work revalidation invalidates an affected-closure owner and requires all-close rep
 11265                return PublishAllCompositionClosureAndDefer(_compositionWork);
 1266            }
 1267            System.Diagnostics.Debug.Assert(IsWithinRetainedWorkCapacity(
 1268                    GetCombinedCompositionWorkBytes(_compositionWork, _store.Current),
 1269                    GetCombinedCompositionWorkPages(_compositionWork, _store.Current)),
 1270                "Completed revalidated work has not grown since its exact advance allowance check.");
 3141271            long completedVersion = checked(_store.Current.GraphVersion + 1);
 3141272            NavigationWorldGraph completed = _compositionWork.Result.WithAreaCatalog(
 3141273                areaCatalog,
 3141274                completedVersion).WithGraphVersion(completedVersion);
 3141275            completed = PreservePriorStructuralClosures(completed);
 3161276            if (!completed.IsWithinDynamicSlotCapacity(_maxDynamicSlotsPerMap, _maxDynamicSlots)) return RollbackComposi
 3121277            NavigationCandidatePublication completedPublication = ReconcileAndPublish(
 3121278                completed,
 3121279                changes,
 3121280                changeCount,
 3121281                completedVersion);
 3141282            if (completedPublication == NavigationCandidatePublication.PermanentCapacity) return RollbackCompositionForC
 3101283            ApplyPublishedCandidate(
 3101284                completedPublication,
 3101285                PublishedCandidateEffect.CompleteComposition);
 3101286            return completedPublication;
 1287        }
 1288
 11141289        NavigationWorldGraph current = _store.Current;
 11141290        long nextVersion = current.GraphVersion + 1;
 11141291        NavigationWorldGraph? completedStructural = null;
 11141292        if (changeCount > 0)
 1293        {
 11101294            long minimumScratchBytes = NavigationStructuralCompositionWork.GetMinimumScratchBytes(
 11101295                current.MapCount,
 11101296                candidate.MapCount,
 11101297                changeCount,
 11101298                candidate.OverlayCellCount);
 11101299            int minimumScratchPages = NavigationStructuralCompositionWork.GetMinimumScratchPages(
 11101300                candidate.MapCount,
 11101301                candidate.OverlayCellCount);
 11101302            long candidateGrowthBytes = Math.Max(
 11101303                0L,
 11101304                candidate.RetainedBytes - current.RetainedBytes);
 11101305            int candidateGrowthPages = Math.Max(
 11101306                0,
 11101307                candidate.PersistentPageCount - current.PersistentPageCount);
 11101308            if (!IsWithinRetainedWorkCapacity(
 11101309                    checked(candidateGrowthBytes + minimumScratchBytes),
 11111310                    checked(candidateGrowthPages + minimumScratchPages))) return RejectInitialCompositionForCapacity();
 11091311            var work = new NavigationStructuralCompositionWork(
 11091312                _world,
 11091313                current,
 11091314                candidate,
 11091315                changes,
 11091316                changeCount);
 11091317            GetCompositionWorkAllowance(out long initialBytes, out int initialPages);
 11091318            if (!work.Advance(
 11091319                    _maintenanceMeter,
 11091320                    initialBytes,
 11091321                    initialPages,
 11091322                    out _))
 1323            {
 3441324                NavigationSurfaceComponentKeySet closureBaseline =
 3441325                    _ownedStructuralClosureBaseline ?? current.ClosedStructuralComponents;
 3441326                bool closureBaselineAll = _ownedStructuralClosureBaseline == null
 3441327                    ? current.AreAllStructuralComponentsClosed
 3441328                    : _ownedStructuralClosureBaselineAll;
 3441329                NavigationWorldGraph closed = current.WithOwnedStructuralClosure(
 3441330                    closureBaseline,
 3441331                    work.AffectedComponents,
 3441332                    !work.IsChangedMapCaptureComplete || closureBaselineAll,
 3441333                    current.GraphVersion + 1);
 3441334                if (!IsWithinRetainedWorkCapacity(
 3441335                        GetCombinedCompositionWorkBytes(work, closed),
 3441336                        GetCombinedCompositionWorkPages(work, closed),
 5121337                        closed)) return RejectInitialCompositionForCapacity();
 1761338                CaptureOwnedStructuralClosureBaseline(current);
 1339                System.Diagnostics.Debug.Assert(!ReferenceEquals(closed, current),
 1340                    "An operation closure always advances the graph version.");
 1761341                NavigationCandidatePublication closedPublication = ReconcileAndPublish(
 1761342                    closed,
 1761343                    Array.Empty<NavigationOperationFrameChange>(),
 1761344                    0,
 1761345                    closed.GraphVersion);
 1771346                if (closedPublication != NavigationCandidatePublication.Published) return closedPublication;
 1751347                work.MarkInitialClosurePublished();
 1751348                _compositionWork = work;
 1751349                return NavigationCandidatePublication.Deferred;
 1350            }
 7651351            completedStructural = PreservePriorStructuralClosures(work.Result);
 1352        }
 7691353        NavigationWorldGraph next = changeCount == 0
 7691354            ? current.ReopenStructuralScopes(nextVersion)
 7691355            : completedStructural!;
 7701356        if (!next.IsWithinDynamicSlotCapacity(_maxDynamicSlotsPerMap, _maxDynamicSlots)) return RejectInitialComposition
 7681357        NavigationCandidatePublication publication = ReconcileAndPublish(
 7681358            next.WithAreaCatalog(areaCatalog, nextVersion),
 7681359            changes,
 7681360            changeCount,
 7681361            nextVersion);
 7681362        ApplyPublishedCandidate(
 7681363            publication,
 7681364            PublishedCandidateEffect.CompleteComposition);
 7681365        return publication;
 1366    }
 1367
 1368    private bool IsWithinRetainedWorkCapacity(
 1369        long workBytes,
 1370        int workPages,
 1371        NavigationWorldGraph? graph = null)
 1372    {
 399961373        NavigationBaselineRebuild.GetRetainedTotals(
 399961374            _baselineRebuilds,
 399961375            out long rebuildBytes,
 399961376            out int rebuildPages);
 399961377        NavigationWorldGraph root = graph ?? _store.Current;
 1378        // Conservative sum: persistent roots share pages, but double-counting is safer than
 1379        // allowing aggregate active state to escape its configured ceiling.
 399961380        return IsRetainedWorkWithinCapacity(
 399961381            root.RetainedBytes,
 399961382            root.PersistentPageCount,
 399961383            workBytes,
 399961384            workPages,
 399961385            rebuildBytes,
 399961386            rebuildPages,
 399961387            _maxActiveSnapshotBytes,
 399961388            _maxPersistentGraphPages);
 1389    }
 1390
 1391    private bool TryRollbackCompositionClosure()
 51392        => _automaticSeamFullRebuildPending || TryPublishReopenedStructuralScopes();
 1393
 1394    private NavigationCandidatePublication RollbackCompositionForCapacityRejection()
 1395    {
 51396        bool rollbackCompleted = TryRollbackCompositionClosure();
 1397        System.Diagnostics.Debug.Assert(rollbackCompleted,
 1398            "A retained composition rolls back only after the maintenance writer preflight succeeds.");
 51399        _compositionWork = null;
 51400        return NavigationCandidatePublication.PermanentCapacity;
 1401    }
 1402
 1403    private NavigationCandidatePublication RejectInitialCompositionForCapacity()
 1404    {
 1405        System.Diagnostics.Debug.Assert(_compositionWork == null,
 1406            "Initial composition capacity rejection cannot own retained composition work.");
 1701407        return NavigationCandidatePublication.PermanentCapacity;
 1408    }
 1409
 1410    private void CompleteCompositionPublication()
 1411    {
 9311412        _compositionWork = null;
 9311413        ClearOwnedStructuralClosureBaseline();
 9311414    }
 1415
 1416    private NavigationCandidatePublication PublishAffectedCompositionClosureAndDefer(
 1417        NavigationStructuralCompositionWork work)
 1418    {
 1671419        NavigationWorldGraph current = _store.Current;
 1671420        CaptureOwnedStructuralClosureBaseline(current);
 1671421        NavigationWorldGraph narrowed = CreateOwnedStructuralClosure(
 1671422            current,
 1671423            work.AffectedComponents,
 1671424            false,
 1671425            current.GraphVersion + 1);
 1426        System.Diagnostics.Debug.Assert(!ReferenceEquals(current, narrowed),
 1427            "Narrowing an owned all-close publication changes its closure root.");
 1671428        NavigationCandidatePublication publication = ReconcileAndPublish(
 1671429            narrowed,
 1671430            Array.Empty<NavigationOperationFrameChange>(),
 1671431            0,
 1671432            narrowed.GraphVersion);
 1671433        work.RecordAffectedClosurePublication(publication);
 1671434        return ContinueAfterRetainedClosure(publication);
 1435    }
 1436
 1437    private NavigationCandidatePublication PublishAllCompositionClosureAndDefer(
 1438        NavigationStructuralCompositionWork work)
 1439    {
 21440        NavigationWorldGraph current = _store.Current;
 21441        CaptureOwnedStructuralClosureBaseline(current);
 21442        NavigationWorldGraph closed = current.WithClosedStructuralComponents(
 21443            NavigationSurfaceComponentKeySet.Empty,
 21444            true,
 21445            current.GraphVersion + 1);
 1446        System.Diagnostics.Debug.Assert(!ReferenceEquals(current, closed),
 1447            "A stale affected closure must broaden before seam work restarts.");
 21448        NavigationCandidatePublication publication = ReconcileAndPublish(
 21449            closed,
 21450            Array.Empty<NavigationOperationFrameChange>(),
 21451            0,
 21452            closed.GraphVersion);
 21453        work.RecordAllClosePublication(publication);
 21454        return ContinueAfterRetainedClosure(publication);
 1455    }
 1456
 1457    private void BeginOperationClosureRollback()
 1458    {
 1459        System.Diagnostics.Debug.Assert(_materializedComponentWork == null);
 1460        System.Diagnostics.Debug.Assert(_lifecycleWork == null);
 1461        System.Diagnostics.Debug.Assert(
 1462            _automaticSeamFullRebuildPending
 1463                || _publishedThisMaintenance
 1464                || _ingress.HasPendingWork,
 1465            "Terminal work begins rollback only while this maintenance pass still owns publication or ingress state.");
 51466        _operationClosureRollbackPending = true;
 51467    }
 1468
 1469    private void ApplyOperationTerminalRollback(
 1470        OperationTerminalDisposition disposition)
 1471    {
 1472        System.Diagnostics.Debug.Assert(disposition != OperationTerminalDisposition.None);
 1781473        if (disposition == OperationTerminalDisposition.ReleaseAndBeginRollback)
 1474        {
 31475            BeginOperationClosureRollback();
 31476            return;
 1477        }
 1751478        if (disposition == OperationTerminalDisposition.ReleaseAndTryReopen)
 21479            TryCompleteOperationClosureRollback();
 1751480    }
 1481
 1482    private void RejectDeferredOperationForCapacity()
 1483    {
 21484        _operations.RejectDeferredCapacity();
 21485        _compositionWork = null;
 21486        BeginOperationClosureRollback();
 21487    }
 1488
 1489    private void TryCompleteOperationClosureRollback()
 1490    {
 21491        _operationClosureRollbackPending = !TryPublishReopenedStructuralScopes();
 21492    }
 1493
 1494    private bool TryPublishReopenedStructuralScopes()
 1495    {
 1496        System.Diagnostics.Debug.Assert(!_automaticSeamFullRebuildPending);
 1497        System.Diagnostics.Debug.Assert(!_publishedThisMaintenance);
 1498        System.Diagnostics.Debug.Assert(
 1499            _ownedStructuralClosureBaseline != null,
 1500            "Only an operation-owned structural closure enters rollback.");
 191501        NavigationWorldGraph current = _store.Current;
 191502        NavigationWorldGraph reopened = current.WithClosedStructuralComponents(
 191503            _ownedStructuralClosureBaseline!,
 191504            _ownedStructuralClosureBaselineAll,
 191505            current.GraphVersion + 1);
 1506        System.Diagnostics.Debug.Assert(!ReferenceEquals(current, reopened),
 1507            "An owned closure differs from the baseline it must restore.");
 191508        NavigationCandidatePublication publication = _store.TryPublish(reopened);
 191509        ApplyPublishedCandidate(
 191510            publication,
 191511            PublishedCandidateEffect.ReopenStructuralScopes);
 191512        bool published = publication == NavigationCandidatePublication.Published;
 191513        return published;
 1514    }
 1515
 1516    private void ApplyPublishedCandidate(
 1517        NavigationCandidatePublication publication,
 1518        PublishedCandidateEffect effect,
 1519        NavigationMaterializedComponentWork? materializedWork = null,
 1520        bool startsAutomaticSeamLifecycle = false,
 1521        NavigationWorldGraph? automaticSeamGraph = null)
 1522    {
 16501523        if (publication != NavigationCandidatePublication.Published)
 1471524            return;
 15031525        _publishedThisMaintenance = true;
 15031526        if (effect == PublishedCandidateEffect.InstallMaterialized)
 1527        {
 1528            System.Diagnostics.Debug.Assert(materializedWork != null);
 2431529            _materializedComponentWork = materializedWork;
 2431530            _materializedComponentWorkCompletesOperation =
 2431531                _operations.RetainedOperationWorkCount != 0;
 2431532            _materializedStartsAutomaticSeamLifecycle = startsAutomaticSeamLifecycle;
 2431533            return;
 1534        }
 12601535        if (effect == PublishedCandidateEffect.CompleteMaterialized
 12601536            || effect == PublishedCandidateEffect.CompleteMaterializedWithinStructuralPublication)
 1537        {
 2411538            _materializedComponentWork = null;
 2411539            _materializedComponentWorkCompletesOperation = false;
 2411540            _materializedStartsAutomaticSeamLifecycle = false;
 2411541            ClearBaselineCaptures();
 2411542            RemoveCompletedBaselineRebuilds();
 2411543            CommitBlockedScopes(
 2411544                _publicationBlockedScopeCount,
 2411545                _publicationBlockAll,
 2411546                _snapshotDeferredScopeCount,
 2411547                _snapshotDeferAll);
 2411548            ClearSafetyPendingAfterExactResnapshot();
 2411549            if (effect == PublishedCandidateEffect.CompleteMaterialized)
 361550                ClearOwnedStructuralClosureBaseline();
 2411551            return;
 1552        }
 10191553        if (effect == PublishedCandidateEffect.CompleteAutomaticSeam)
 1554        {
 331555            _lifecycleWork = null;
 331556            _lifecycleEventCount = 0;
 331557            _automaticSeamFullRebuildPending = false;
 331558            _store.ClearSafetyPending();
 331559            return;
 1560        }
 9861561        if (effect == PublishedCandidateEffect.CompleteComposition)
 1562        {
 9311563            CompleteCompositionPublication();
 9311564            return;
 1565        }
 551566        if (effect == PublishedCandidateEffect.ReopenStructuralScopes)
 1567        {
 191568            ClearOwnedStructuralClosureBaseline();
 191569            return;
 1570        }
 1571        System.Diagnostics.Debug.Assert(
 1572            effect == PublishedCandidateEffect.StartAutomaticSeam,
 1573            "Every non-terminal published-candidate effect starts automatic-seam work.");
 1574        System.Diagnostics.Debug.Assert(automaticSeamGraph != null);
 361575        _lifecycleEventCount = _publicationEventCount;
 361576        _lifecycleWork = new NavigationAutomaticSeamLifecycleWork(
 361577            _world,
 361578            automaticSeamGraph!,
 361579            _maintenanceEvents,
 361580            _lifecycleEventCount,
 361581            _automaticSeamFullRebuildPending);
 361582    }
 1583
 1584    private void CaptureOwnedStructuralClosureBaseline(NavigationWorldGraph graph)
 1585    {
 31411586        if (_ownedStructuralClosureBaseline != null)
 29101587            return;
 2311588        _ownedStructuralClosureBaseline = graph.ClosedStructuralComponents;
 2311589        _ownedStructuralClosureBaselineAll = graph.AreAllStructuralComponentsClosed;
 2311590    }
 1591
 1592    private NavigationWorldGraph CreateOwnedStructuralClosure(
 1593        NavigationWorldGraph graph,
 1594        NavigationSurfaceComponentKeySet affected,
 1595        bool closeAll,
 1596        long graphVersion)
 1597    {
 4101598        return graph.WithOwnedStructuralClosure(
 4101599            _ownedStructuralClosureBaseline!,
 4101600            affected,
 4101601            closeAll || _ownedStructuralClosureBaselineAll,
 4101602            graphVersion);
 1603    }
 1604
 1605    private NavigationWorldGraph PreservePriorStructuralClosures(
 10791606        NavigationWorldGraph graph) => _ownedStructuralClosureBaseline == null
 10791607            ? graph
 10791608            : graph.WithClosedStructuralComponents(
 10791609                _ownedStructuralClosureBaseline,
 10791610                _ownedStructuralClosureBaselineAll,
 10791611                graph.GraphVersion);
 1612
 1613    private void ClearOwnedStructuralClosureBaseline()
 1614    {
 10091615        _ownedStructuralClosureBaseline = null;
 10091616        _ownedStructuralClosureBaselineAll = false;
 10091617    }
 1618
 1619    private bool IsOperationWithinRetainedWorkCapacity(long workBytes, int workPages) =>
 195291620        IsWithinRetainedWorkCapacity(workBytes, workPages);
 1621
 1622    private long GetCombinedCompositionWorkBytes(
 1623        NavigationStructuralCompositionWork work,
 1624        NavigationWorldGraph ownerGraph) =>
 3441625        checked(
 3441626            work.RetainedBytes
 3441627            + _operations.RetainedOperationWorkBytes
 3441628            + GetOwnedClosureBaselineAdditionalRetainedBytes(ownerGraph));
 1629
 1630    private int GetCombinedCompositionWorkPages(
 1631        NavigationStructuralCompositionWork work,
 1632        NavigationWorldGraph ownerGraph) =>
 3441633        checked(
 3441634            work.PersistentPageCount
 3441635            + _operations.RetainedOperationWorkPageCount
 3441636            + GetOwnedClosureBaselineAdditionalPersistentPages(ownerGraph));
 1637
 1638    private long GetCombinedMaterializedWorkBytes(
 1639        NavigationMaterializedComponentWork work)
 1640    {
 1641        System.Diagnostics.Debug.Assert(_lifecycleWork == null,
 1642            "Materialized and automatic-seam lifecycle work are mutually exclusive.");
 55661643        return checked(
 55661644            work.RetainedBytes
 55661645            + _operations.RetainedOperationWorkBytes
 55661646            + (_compositionWork?.RetainedBytes ?? 0L)
 55661647            + GetOwnedClosureBaselineAdditionalRetainedBytes(_store.Current));
 1648    }
 1649
 1650    private int GetCombinedMaterializedWorkPages(
 1651        NavigationMaterializedComponentWork work)
 1652    {
 1653        System.Diagnostics.Debug.Assert(_lifecycleWork == null,
 1654            "Materialized and automatic-seam lifecycle work are mutually exclusive.");
 55661655        return checked(
 55661656            work.PersistentPageCount
 55661657            + _operations.RetainedOperationWorkPageCount
 55661658            + (_compositionWork?.PersistentPageCount ?? 0)
 55661659            + GetOwnedClosureBaselineAdditionalPersistentPages(_store.Current));
 1660    }
 1661
 1662    private long GetOwnedClosureBaselineAdditionalRetainedBytes(
 1663        NavigationWorldGraph ownerGraph)
 1664    {
 199351665        GetOwnedClosureBaselineAdditionalCapacity(
 199351666            _ownedStructuralClosureBaseline,
 199351667            ownerGraph,
 199351668            out long retainedBytes,
 199351669            out _);
 199351670        return retainedBytes;
 1671    }
 1672
 1673    private int GetOwnedClosureBaselineAdditionalPersistentPages(
 1674        NavigationWorldGraph ownerGraph)
 1675    {
 202751676        GetOwnedClosureBaselineAdditionalCapacity(
 202751677            _ownedStructuralClosureBaseline,
 202751678            ownerGraph,
 202751679            out _,
 202751680            out int persistentPages);
 202751681        return persistentPages;
 1682    }
 1683
 1684    private void GetCompositionWorkAllowance(out long bytes, out int pages)
 1685    {
 117931686        NavigationBaselineRebuild.GetRetainedTotals(
 117931687            _baselineRebuilds,
 117931688            out long rebuildBytes,
 117931689            out int rebuildPages);
 117931690        NavigationWorldGraph current = _store.Current;
 117931691        bytes = _maxActiveSnapshotBytes
 117931692            - current.RetainedBytes
 117931693            - rebuildBytes
 117931694            - _operations.RetainedOperationWorkBytes
 117931695            - GetOwnedClosureBaselineAdditionalRetainedBytes(current);
 117931696        pages = _maxPersistentGraphPages
 117931697            - current.PersistentPageCount
 117931698            - rebuildPages
 117931699            - _operations.RetainedOperationWorkPageCount
 117931700            - GetOwnedClosureBaselineAdditionalPersistentPages(current);
 117931701    }
 1702
 1703    private NavigationCandidatePublication PublishPendingCandidate(
 1704        NavigationOperationCandidate candidate,
 1705        int frame,
 1706        NavigationOperationFrameChange[] changes,
 1707        int changeCount)
 1708    {
 119821709        if (changeCount == 0 && _store.Current.HasClosedStructuralScope)
 1710        {
 151711            bool available = _automaticSeamFullRebuildPending
 151712                || TryPublishReopenedStructuralScopes();
 1713            System.Diagnostics.Debug.Assert(available,
 1714                "A no-change operation reopens its owned closure only after writer preflight succeeds.");
 151715            return NavigationCandidatePublication.Published;
 1716        }
 119671717        return PublishCandidate(
 119671718            candidate,
 119671719            _publicationAreaCatalog,
 119671720            changes,
 119671721            changeCount);
 1722    }
 1723
 1724    private int PrepareResnapshotScopes(int blockedScopeCount, bool blockAll)
 1725    {
 202491726        if (_priorBlockAll || blockAll)
 571727            return 0;
 1728
 201921729        int count = 0;
 406061730        for (int i = 0; i < _priorBlockedScopeCount; i++)
 1731        {
 1111732            NavigationGridChangeScope prior = _priorBlockedScopes[i];
 1111733            if (!ContainsScope(_blockedScopes, blockedScopeCount, prior.ConfigurationKey))
 1101734                _resnapshotScopes[count++] = prior;
 1735        }
 201921736        return count;
 1737    }
 1738
 1739    private void CommitBlockedScopes(
 1740        int blockedScopeCount,
 1741        bool blockAll,
 1742        int deferredScopeCount,
 1743        bool deferAll)
 1744    {
 202221745        if (blockAll || deferAll)
 1746        {
 301747            _priorBlockedScopeCount = 0;
 301748            _priorBlockAll = true;
 301749            return;
 1750        }
 1751
 201921752        _priorBlockedScopeCount = MergeBlockedScopes(
 201921753            _blockedScopes,
 201921754            blockedScopeCount,
 201921755            _deferredScopes,
 201921756            deferredScopeCount,
 201921757            _priorBlockedScopes,
 201921758            out _priorBlockAll);
 201921759    }
 1760
 1761    internal static int MergeBlockedScopes(
 1762        NavigationGridChangeScope[] blockedScopes,
 1763        int blockedScopeCount,
 1764        NavigationGridChangeScope[] deferredScopes,
 1765        int deferredScopeCount,
 1766        NavigationGridChangeScope[] destination,
 1767        out bool blockAll)
 1768    {
 1769        System.Diagnostics.Debug.Assert(blockedScopeCount <= destination.Length,
 1770            "The runtime sizes blocked-scope capture to its committed-scope capacity.");
 201941771        int count = 0;
 404141772        for (int i = 0; i < blockedScopeCount; i++)
 131773            destination[count++] = blockedScopes[i];
 406081774        for (int i = 0; i < deferredScopeCount; i++)
 1775        {
 1111776            NavigationGridChangeScope deferred = deferredScopes[i];
 1111777            if (ContainsScope(destination, count, deferred.ConfigurationKey))
 1778                continue;
 1101779            if (count == destination.Length)
 1780            {
 11781                blockAll = true;
 11782                return 0;
 1783            }
 1091784            destination[count++] = deferred;
 1785        }
 201931786        blockAll = false;
 201931787        return count;
 1788    }
 1789
 1790    private static bool ContainsScope(
 1791        NavigationGridChangeScope[] scopes,
 1792        int count,
 1793        GridForge.Configuration.GridConfigurationKey key)
 1794    {
 4561795        for (int i = 0; i < count; i++)
 1796        {
 81797            if (scopes[i].ConfigurationKey.Equals(key))
 21798                return true;
 1799        }
 2201800        return false;
 1801    }
 1802
 1803    internal void EnqueueCommittedChange(GridEventInfo eventInfo)
 1804    {
 11891805        if (_disposed || eventInfo.WorldSpawnToken != _world.SpawnToken)
 21806            return;
 11871807        _ingress.Enqueue(eventInfo);
 11871808    }
 1809
 1810    private void MarkResnapshotRequired()
 1811    {
 261812        _ingress.MarkResnapshotRequired();
 261813    }
 1814
 1815    private void MarkSafetyPendingIf(bool required)
 1816    {
 401817        if (required)
 61818            _store.MarkSafetyPending();
 401819    }
 1820
 1821    private void ClearSafetyPendingAfterExactResnapshot()
 1822    {
 1823        System.Diagnostics.Debug.Assert(!_publicationResnapshotAll || !_publicationBlockAll);
 202221824        if (CanClearSafetyPendingAfterSnapshot(
 202221825                _store.IsSafetyPending,
 202221826                _publicationResnapshotAll,
 202221827                _publicationBlockedScopeCount,
 202221828                _snapshotDeferAll,
 202221829                _snapshotDeferredScopeCount))
 1830        {
 11831            _store.ClearSafetyPending();
 1832        }
 202221833    }
 1834
 1835    internal static bool CanClearSafetyPendingAfterSnapshot(
 1836        bool safetyPending,
 1837        bool resnapshotAll,
 1838        int blockedScopeCount,
 1839        bool deferAll,
 202281840        int deferredScopeCount) => safetyPending
 202281841        && resnapshotAll
 202281842        && blockedScopeCount == 0
 202281843        && !deferAll
 202281844        && deferredScopeCount == 0;
 1845
 1846    private void RequeuePublicationEvents()
 1847    {
 108601848        _ingress.RequeuePrefix(_maintenanceEvents.AsSpan(0, _publicationEventCount));
 108601849    }
 1850
 1851    private void DrainSafetyPrefixUnderPressure()
 1852    {
 171853        int count = _ingress.DetachInto(
 171854            _maintenanceEvents,
 171855            _blockedScopes,
 171856            out int blockedScopeCount,
 171857            out bool blockAll,
 171858            out bool topologyLifecycleCoverageLost);
 171859        _maintenanceMeter.TryConsumeEnvelopes(count);
 171860        if (topologyLifecycleCoverageLost
 171861            || ContainsTopologyLifecycle(_maintenanceEvents, count))
 1862        {
 41863            _automaticSeamFullRebuildPending = true;
 1864        }
 171865        bool requiresResnapshot = count != 0 || blockedScopeCount != 0 || blockAll;
 171866        MarkSafetyPendingIf(requiresResnapshot);
 171867        if (requiresResnapshot)
 1868        {
 1869            // Snapshot admission is already closed by the store while bounded leased generations
 1870            // prevent publication. Drain a bounded final-state prefix now, then require an exact
 1871            // baseline before any affected scope can reopen once publication pressure clears.
 51872            _ingress.MarkResnapshotRequired();
 1873        }
 171874    }
 1875
 1876    private static bool ContainsTopologyLifecycle(GridEventInfo[] events, int count)
 1877    {
 335061878        for (int i = 0; i < count; i++)
 1879        {
 1181880            GridEventKind kind = events[i].ChangeKind;
 1181881            if (kind == GridEventKind.GridAdded
 1181882                || kind == GridEventKind.GridRemoved
 1181883                || kind == GridEventKind.WorldReset)
 1884            {
 301885                return true;
 1886            }
 1887        }
 166351888        return false;
 1889    }
 1890
 1891    private void ClearBaselineCaptures()
 1892    {
 433041893        for (int i = 0; i < _snapshotAffectedCount; i++)
 14041894            _baselineCaptures[_affectedMapOrdinals[i]] = default;
 202481895    }
 1896
 1897    private void RemoveCompletedBaselineRebuilds()
 1898    {
 407681899        for (int i = _baselineRebuilds.Count - 1; i >= 0; i--)
 1900        {
 1611901            NavigationBaselineRebuild rebuild = _baselineRebuilds.GetValueAt(i);
 1611902            if (rebuild.IsComplete)
 531903                _baselineRebuilds = _baselineRebuilds.Remove(rebuild.MapId, out _);
 1904        }
 202231905    }
 1906
 1907    private void EnsureUsable()
 1908    {
 263981909        SwiftThrowHelper.ThrowIfDisposed(_disposed, nameof(NavigationGraphRuntime));
 263981910    }
 1911}

Methods/Properties

.ctor(GridForge.Grids.GridWorld,Trailblazer.TrailblazerWorldContextSettings)
get_Current()
get_Store()
get_RetainedBaselineCaptureCount()
get_RetainedCompositionWorkCount()
get_RetainedCompositionWorkBytes()
get_RetainedOperationWorkBytes()
get_RetainedOperationWorkCount()
get_RetainedCompositionWorkPageCount()
get_RetainedOperationWorkPageCount()
get_MaintenanceMeter()
get_LastAffectedMapCollectionCount()
Admit(Trailblazer.Pathing.NavigationMapCommitOperation)
Admit(Trailblazer.Pathing.NavigationMapRemoveOperation)
Admit(Trailblazer.Pathing.NavigationOverlayCommitOperation)
Admit(Trailblazer.Pathing.NavigationAreaPolicyCommitOperation)
TryAcquire()
Maintain(System.Int32)
CompletePolicyFrame(Trailblazer.Pathing.NavigationAreaCatalogProcessor/PreparedFrame,System.Int32,System.Boolean,Trailblazer.Pathing.NavigationCandidatePublication)
ClassifyPolicyFrameDisposition(System.Boolean,Trailblazer.Pathing.NavigationCandidatePublication)
ContinueAfterRetainedClosure(Trailblazer.Pathing.NavigationCandidatePublication)
ClassifyAutomaticSeamAdvance(Trailblazer.Pathing.NavigationAutomaticSeamLifecycleWork/AdvanceStatus)
ClassifyMaterializedAdvance(System.Boolean,System.Boolean,System.Boolean,System.Boolean,System.Nullable`1<Trailblazer.Pathing.NavigationCandidatePublication>&)
ClassifyOperationTerminalDisposition(Trailblazer.Pathing.NavigationOperationFrameResult,System.Int32,System.Boolean,System.Boolean,System.Boolean,System.Boolean)
GetOwnedClosureBaselineAdditionalCapacity(Trailblazer.Pathing.NavigationSurfaceComponentKeySet,Trailblazer.Pathing.NavigationWorldGraph,System.Int64&,System.Int32&)
IsRetainedWorkWithinCapacity(System.Int64,System.Int32,System.Int64,System.Int32,System.Int64,System.Int32,System.Int64,System.Int32)
MaintainSnapshot()
ReconcileAndPublish(Trailblazer.Pathing.NavigationWorldGraph,Trailblazer.Pathing.NavigationOperationFrameChange[],System.Int32,System.Int64,System.Boolean)
TryPrepareMaterializedComponents(Trailblazer.Pathing.NavigationWorldGraph&,System.Boolean)
MaintainMaterializedComponentWork(System.Boolean,Trailblazer.Pathing.NavigationWorldGraph)
RestartMaterializedSnapshot(Trailblazer.Pathing.NavigationCandidatePublication)
AbandonMaterializedSnapshot(System.Boolean)
AdvanceCoveredBaselineRebuilds(Trailblazer.Pathing.NavigationWorldGraph)
HasRelevantAutomaticSeamLifecycleEvent(Trailblazer.Pathing.NavigationWorldGraph,Trailblazer.Pathing.NavigationWorldGraph)
StartAutomaticSeamLifecycle(Trailblazer.Pathing.NavigationWorldGraph,Trailblazer.Pathing.NavigationWorldGraph,System.Int64)
MaintainAutomaticSeamLifecycle()
GetLifecycleWorkAllowance(System.Int64&,System.Int32&)
RequeueAutomaticSeamLifecyclePrefix()
RestartAutomaticSeamLifecycle()
TryGetCellState(System.String,GridForge.Spatial.VoxelIndex,Trailblazer.Pathing.NavigationGraphCellState&)
TryResolveAreaPolicy(Trailblazer.Pathing.NavigationAreaPolicyKey,Trailblazer.Pathing.NavigationAreaPolicy&)
GetDiagnostics(System.Int32)
GetSurfaceComponentDiagnostic(Trailblazer.Pathing.NavigationWorldGraph,Trailblazer.Pathing.NavigationMapInstance,System.Int32&,System.Int64&)
Reset()
Dispose()
PublishCandidate(Trailblazer.Pathing.NavigationOperationCandidate,Trailblazer.Pathing.NavigationAreaCatalog,Trailblazer.Pathing.NavigationOperationFrameChange[],System.Int32)
IsWithinRetainedWorkCapacity(System.Int64,System.Int32,Trailblazer.Pathing.NavigationWorldGraph)
TryRollbackCompositionClosure()
RollbackCompositionForCapacityRejection()
RejectInitialCompositionForCapacity()
CompleteCompositionPublication()
PublishAffectedCompositionClosureAndDefer(Trailblazer.Pathing.NavigationStructuralCompositionWork)
PublishAllCompositionClosureAndDefer(Trailblazer.Pathing.NavigationStructuralCompositionWork)
BeginOperationClosureRollback()
ApplyOperationTerminalRollback(Trailblazer.Pathing.NavigationGraphRuntime/OperationTerminalDisposition)
RejectDeferredOperationForCapacity()
TryCompleteOperationClosureRollback()
TryPublishReopenedStructuralScopes()
ApplyPublishedCandidate(Trailblazer.Pathing.NavigationCandidatePublication,Trailblazer.Pathing.NavigationGraphRuntime/PublishedCandidateEffect,Trailblazer.Pathing.NavigationMaterializedComponentWork,System.Boolean,Trailblazer.Pathing.NavigationWorldGraph)
CaptureOwnedStructuralClosureBaseline(Trailblazer.Pathing.NavigationWorldGraph)
CreateOwnedStructuralClosure(Trailblazer.Pathing.NavigationWorldGraph,Trailblazer.Pathing.NavigationSurfaceComponentKeySet,System.Boolean,System.Int64)
PreservePriorStructuralClosures(Trailblazer.Pathing.NavigationWorldGraph)
ClearOwnedStructuralClosureBaseline()
IsOperationWithinRetainedWorkCapacity(System.Int64,System.Int32)
GetCombinedCompositionWorkBytes(Trailblazer.Pathing.NavigationStructuralCompositionWork,Trailblazer.Pathing.NavigationWorldGraph)
GetCombinedCompositionWorkPages(Trailblazer.Pathing.NavigationStructuralCompositionWork,Trailblazer.Pathing.NavigationWorldGraph)
GetCombinedMaterializedWorkBytes(Trailblazer.Pathing.NavigationMaterializedComponentWork)
GetCombinedMaterializedWorkPages(Trailblazer.Pathing.NavigationMaterializedComponentWork)
GetOwnedClosureBaselineAdditionalRetainedBytes(Trailblazer.Pathing.NavigationWorldGraph)
GetOwnedClosureBaselineAdditionalPersistentPages(Trailblazer.Pathing.NavigationWorldGraph)
GetCompositionWorkAllowance(System.Int64&,System.Int32&)
PublishPendingCandidate(Trailblazer.Pathing.NavigationOperationCandidate,System.Int32,Trailblazer.Pathing.NavigationOperationFrameChange[],System.Int32)
PrepareResnapshotScopes(System.Int32,System.Boolean)
CommitBlockedScopes(System.Int32,System.Boolean,System.Int32,System.Boolean)
MergeBlockedScopes(Trailblazer.Pathing.NavigationGridChangeScope[],System.Int32,Trailblazer.Pathing.NavigationGridChangeScope[],System.Int32,Trailblazer.Pathing.NavigationGridChangeScope[],System.Boolean&)
ContainsScope(Trailblazer.Pathing.NavigationGridChangeScope[],System.Int32,GridForge.Configuration.GridConfigurationKey)
EnqueueCommittedChange(GridForge.Grids.GridEventInfo)
MarkResnapshotRequired()
MarkSafetyPendingIf(System.Boolean)
ClearSafetyPendingAfterExactResnapshot()
CanClearSafetyPendingAfterSnapshot(System.Boolean,System.Boolean,System.Int32,System.Boolean,System.Int32)
RequeuePublicationEvents()
DrainSafetyPrefixUnderPressure()
ContainsTopologyLifecycle(GridForge.Grids.GridEventInfo[],System.Int32)
ClearBaselineCaptures()
RemoveCompletedBaselineRebuilds()
EnsureUsable()