< Summary

Information
Class: Trailblazer.Pathing.NavigationAreaCatalogProcessor
Assembly: Trailblazer
File(s): /home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Graph/NavigationAreaCatalogProcessor.cs
Line coverage
100%
Covered lines: 109
Uncovered lines: 0
Coverable lines: 109
Total lines: 200
Line coverage: 100%
Branch coverage
100%
Covered branches: 54
Total branches: 54
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%22100%
get_PendingCount()100%11100%
get_PendingRuleCount()100%11100%
get_PendingRetainedBytes()100%11100%
Reset()100%22100%
Admit(...)100%2424100%
Prepare(...)100%1616100%
.ctor(...)100%11100%
Complete(...)100%44100%
CompleteCapacityRejected()100%44100%
RemovePrefix(...)100%22100%

File(s)

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

#LineLine coverage
 1//=======================================================================
 2// NavigationAreaCatalogProcessor.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 SwiftCollections;
 9
 10namespace Trailblazer.Pathing;
 11
 12internal sealed class NavigationAreaCatalogProcessor
 13{
 121214    private readonly SwiftQueue<NavigationAreaPolicyCommitOperation> _pending = new();
 15    private readonly int _maxPending;
 16    private readonly int _maxBatchItems;
 17    private readonly int _maxPolicies;
 18    private readonly int _maxRulesPerPolicy;
 19    private readonly int _maxRules;
 20    private readonly int _navigationAreaCount;
 21    private readonly long _maxPendingBytes;
 22    private readonly NavigationOperationRejection[] _outcomes;
 23    private int _pendingRuleCount;
 24    private long _pendingRetainedBytes;
 25    private long _sequenceHighWater;
 121226    private int _effectiveFrameHighWater = -1;
 121227    private int _lastFrame = -1;
 28
 121229    internal NavigationAreaCatalogProcessor(TrailblazerWorldContextSettings settings)
 30    {
 121231        _maxPending = settings.OperationLimits.MaxPendingOperations;
 121232        _maxBatchItems = settings.OperationLimits.MaxBatchItems;
 121233        _maxPolicies = settings.MaxAreaPolicies;
 121234        _maxRulesPerPolicy = settings.MaxAreaRulesPerPolicy;
 121235        _maxRules = settings.MaxAreaRules;
 121236        _navigationAreaCount = settings.NavigationAreaCount;
 121237        long maximumRuleBytes = (long)settings.MaxAreaRules * 24L;
 121238        _maxPendingBytes = settings.OperationLimits.MaxPendingDescriptorBytes
 121239            > long.MaxValue - maximumRuleBytes
 121240            ? long.MaxValue
 121241            : settings.OperationLimits.MaxPendingDescriptorBytes + maximumRuleBytes;
 121242        _outcomes = new NavigationOperationRejection[_maxPending];
 121243    }
 44
 441045    internal int PendingCount => _pending.Count;
 46
 220647    internal int PendingRuleCount => _pendingRuleCount;
 48
 440849    internal long PendingRetainedBytes => _pendingRetainedBytes;
 50
 51    internal void Reset()
 52    {
 5053        for (int i = 0; i < _pending.Count; i++)
 154            _pending[i].Receipt.CompleteSuperseded();
 2455        _pending.Clear();
 2456        _pendingRuleCount = 0;
 2457        _pendingRetainedBytes = 0;
 2458        _sequenceHighWater = 0;
 2459        _effectiveFrameHighWater = -1;
 2460        _lastFrame = -1;
 2461    }
 62
 63    internal bool Admit(NavigationAreaPolicyCommitOperation operation)
 64    {
 19965        if (!operation.Receipt.TryClaimAdmission())
 166            return false;
 67
 19868        NavigationOperationRejection rejection = NavigationOperationRejection.None;
 19869        if (operation.PublicationSequence == _sequenceHighWater)
 170            rejection = NavigationOperationRejection.DuplicateSequence;
 19771        else if (operation.PublicationSequence < _sequenceHighWater)
 172            rejection = NavigationOperationRejection.RegressingSequence;
 19673        else if (operation.EffectiveFrame < _effectiveFrameHighWater)
 174            rejection = NavigationOperationRejection.RegressingEffectiveFrame;
 19575        else if (operation.EffectiveFrame <= _lastFrame)
 176            rejection = NavigationOperationRejection.LateEffectiveFrame;
 19477        else if (operation.Policy.RuleCount != _navigationAreaCount)
 278            rejection = NavigationOperationRejection.ValidationFailed;
 19279        else if (_pending.Count >= _maxPending)
 180            rejection = NavigationOperationRejection.CapacityExceeded;
 19181        else if (operation.Policy.RuleCount > _maxRules - _pendingRuleCount
 19182            || operation.Policy.RetainedBytes > _maxPendingBytes - _pendingRetainedBytes)
 283            rejection = NavigationOperationRejection.CapacityExceeded;
 84
 19885        if (operation.PublicationSequence > _sequenceHighWater)
 86        {
 19687            _sequenceHighWater = operation.PublicationSequence;
 19688            if (operation.EffectiveFrame > _effectiveFrameHighWater)
 18989                _effectiveFrameHighWater = operation.EffectiveFrame;
 90        }
 91
 19892        if (rejection != NavigationOperationRejection.None)
 93        {
 994            operation.Receipt.CompleteRejected(rejection);
 995            return false;
 96        }
 18997        _pending.Enqueue(operation);
 18998        _pendingRuleCount += operation.Policy.RuleCount;
 18999        _pendingRetainedBytes += operation.Policy.RetainedBytes;
 189100        return true;
 101    }
 102
 103    internal PreparedFrame Prepare(
 104        int frame,
 105        NavigationAreaCatalog current,
 106        MaintenanceWorkMeter meter,
 107        long maxCatalogBytes,
 108        int maxCatalogPages)
 109    {
 3479110        _lastFrame = frame;
 3479111        NavigationAreaCatalog candidate = current;
 3479112        int eligible = 0;
 3664113        while (eligible < _pending.Count
 3664114            && eligible < _maxBatchItems
 3664115            && _pending[eligible].EffectiveFrame <= frame)
 116        {
 188117            NavigationAreaPolicy policy = _pending[eligible].Policy;
 188118            if (!meter.TryConsumeDependencyEntries(candidate.GetPublishWork(
 188119                    policy,
 188120                    _maxPolicies,
 188121                    _maxRules)))
 122                break;
 185123            _outcomes[eligible] = candidate.TryPublish(
 185124                policy,
 185125                _maxPolicies,
 185126                _navigationAreaCount,
 185127                _maxRulesPerPolicy,
 185128                _maxRules,
 185129                out NavigationAreaCatalog next);
 185130            if (_outcomes[eligible] == NavigationOperationRejection.None
 185131                && (next.RetainedBytes > maxCatalogBytes
 185132                    || next.PersistentPageCount > maxCatalogPages))
 133            {
 2134                _outcomes[eligible] = NavigationOperationRejection.CapacityExceeded;
 135            }
 183136            else if (_outcomes[eligible] == NavigationOperationRejection.None)
 178137                candidate = next;
 185138            eligible++;
 139        }
 3479140        return new PreparedFrame(this, candidate, _outcomes, eligible);
 141    }
 142
 143    internal readonly struct PreparedFrame
 144    {
 145        private readonly NavigationAreaCatalogProcessor _owner;
 146        private readonly NavigationOperationRejection[] _outcomes;
 147
 148        internal PreparedFrame(
 149            NavigationAreaCatalogProcessor owner,
 150            NavigationAreaCatalog candidate,
 151            NavigationOperationRejection[] outcomes,
 152            int count)
 153        {
 3479154            _owner = owner;
 3479155            Candidate = candidate;
 3479156            _outcomes = outcomes;
 3479157            Count = count;
 3479158        }
 159
 160        internal NavigationAreaCatalog Candidate { get; }
 161
 162        internal int Count { get; }
 163
 164        internal void Complete(int frame)
 165        {
 6918166            for (int i = 0; i < Count; i++)
 167            {
 180168                NavigationAreaPolicyCommitOperation operation = _owner._pending[i];
 180169                if (_outcomes[i] == NavigationOperationRejection.None)
 174170                    operation.Receipt.CompleteApplied(frame);
 171                else
 6172                    operation.Receipt.CompleteRejected(_outcomes[i]);
 173            }
 3279174            _owner.RemovePrefix(Count);
 3279175        }
 176
 177        internal void CompleteCapacityRejected()
 178        {
 8179            for (int i = 0; i < Count; i++)
 180            {
 2181                NavigationAreaPolicyCommitOperation operation = _owner._pending[i];
 2182                NavigationOperationRejection rejection = _outcomes[i] == NavigationOperationRejection.None
 2183                    ? NavigationOperationRejection.CapacityExceeded
 2184                    : _outcomes[i];
 2185                operation.Receipt.CompleteRejected(rejection);
 186            }
 2187            _owner.RemovePrefix(Count);
 2188        }
 189    }
 190
 191    private void RemovePrefix(int count)
 192    {
 6926193        for (int i = 0; i < count; i++)
 194        {
 182195            NavigationAreaPolicyCommitOperation operation = _pending.Dequeue();
 182196            _pendingRuleCount -= operation.Policy.RuleCount;
 182197            _pendingRetainedBytes -= operation.Policy.RetainedBytes;
 198        }
 3281199    }
 200}