| | | 1 | | //======================================================================= |
| | | 2 | | // NavigationAutomaticSeamIndex.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 | | |
| | | 8 | | namespace Trailblazer.Pathing; |
| | | 9 | | |
| | | 10 | | /// <summary>Stores canonical seam geometry plus dependency, active-endpoint, and link incidence.</summary> |
| | | 11 | | internal sealed class NavigationAutomaticSeamIndex |
| | | 12 | | { |
| | | 13 | | internal const int PairNodeBytes = 104; |
| | | 14 | | internal const int AddressNodeBytes = 80; |
| | | 15 | | internal const int MapNodeBytes = 64; |
| | | 16 | | internal const int PairCursorShellBytes = 144; |
| | | 17 | | internal const int AddressCursorShellBytes = 96; |
| | | 18 | | internal const int MapCursorShellBytes = 64; |
| | | 19 | | internal const int LinkCursorShellBytes = 80; |
| | | 20 | | private const long BaseRetainedBytes = 96L; |
| | | 21 | | |
| | 1 | 22 | | internal static readonly NavigationAutomaticSeamIndex Empty = new( |
| | 1 | 23 | | new NavigationSeamEditTree<NavigationAutomaticSeamPairKey, NavigationAutomaticSeamPairRecord>(PairNodeBytes), |
| | 1 | 24 | | new NavigationSeamEditTree<NavigationCellAddress, NavigationPagedSequence<NavigationAutomaticSeamPair>>(AddressN |
| | 1 | 25 | | new NavigationSeamEditTree<NavigationCellAddress, NavigationPagedSequence<NavigationAutomaticSeamPair>>(AddressN |
| | 1 | 26 | | new NavigationSeamEditTree<NavigationAutomaticSeamMapKey, NavigationPagedSequence<NavigationStructuralLink>>(Map |
| | 1 | 27 | | 0, 0, 0, 0, 0, 0, 0, 0); |
| | | 28 | | |
| | | 29 | | private readonly NavigationSeamEditTree<NavigationAutomaticSeamPairKey, NavigationAutomaticSeamPairRecord> _pairs; |
| | | 30 | | private readonly NavigationSeamEditTree<NavigationCellAddress, NavigationPagedSequence<NavigationAutomaticSeamPair>> |
| | | 31 | | private readonly NavigationSeamEditTree<NavigationCellAddress, NavigationPagedSequence<NavigationAutomaticSeamPair>> |
| | | 32 | | private readonly NavigationSeamEditTree<NavigationAutomaticSeamMapKey, NavigationPagedSequence<NavigationStructuralL |
| | | 33 | | private readonly long _pairBytes; |
| | | 34 | | private readonly long _dependencyRowBytes; |
| | | 35 | | private readonly long _activeRowBytes; |
| | | 36 | | private readonly long _linkRowBytes; |
| | | 37 | | private readonly int _pairPages; |
| | | 38 | | private readonly int _dependencyRowPages; |
| | | 39 | | private readonly int _activeRowPages; |
| | | 40 | | private readonly int _linkRowPages; |
| | | 41 | | |
| | 181 | 42 | | private NavigationAutomaticSeamIndex( |
| | 181 | 43 | | NavigationSeamEditTree<NavigationAutomaticSeamPairKey, NavigationAutomaticSeamPairRecord> pairs, |
| | 181 | 44 | | NavigationSeamEditTree<NavigationCellAddress, NavigationPagedSequence<NavigationAutomaticSeamPair>> dependencies |
| | 181 | 45 | | NavigationSeamEditTree<NavigationCellAddress, NavigationPagedSequence<NavigationAutomaticSeamPair>> active, |
| | 181 | 46 | | NavigationSeamEditTree<NavigationAutomaticSeamMapKey, NavigationPagedSequence<NavigationStructuralLink>> links, |
| | 181 | 47 | | long pairBytes, |
| | 181 | 48 | | long dependencyRowBytes, |
| | 181 | 49 | | long activeRowBytes, |
| | 181 | 50 | | long linkRowBytes, |
| | 181 | 51 | | int pairPages, |
| | 181 | 52 | | int dependencyRowPages, |
| | 181 | 53 | | int activeRowPages, |
| | 181 | 54 | | int linkRowPages) |
| | | 55 | | { |
| | 181 | 56 | | _pairs = pairs; |
| | 181 | 57 | | _dependencies = dependencies; |
| | 181 | 58 | | _active = active; |
| | 181 | 59 | | _links = links; |
| | 181 | 60 | | _pairBytes = pairBytes; |
| | 181 | 61 | | _dependencyRowBytes = dependencyRowBytes; |
| | 181 | 62 | | _activeRowBytes = activeRowBytes; |
| | 181 | 63 | | _linkRowBytes = linkRowBytes; |
| | 181 | 64 | | _pairPages = pairPages; |
| | 181 | 65 | | _dependencyRowPages = dependencyRowPages; |
| | 181 | 66 | | _activeRowPages = activeRowPages; |
| | 181 | 67 | | _linkRowPages = linkRowPages; |
| | 181 | 68 | | } |
| | | 69 | | |
| | 48 | 70 | | internal int PairCount => _pairs.Count; |
| | | 71 | | |
| | 1037 | 72 | | internal long RetainedBytes => checked( |
| | 1037 | 73 | | BaseRetainedBytes |
| | 1037 | 74 | | + _pairs.RetainedBytes |
| | 1037 | 75 | | + _dependencies.RetainedBytes |
| | 1037 | 76 | | + _active.RetainedBytes |
| | 1037 | 77 | | + _links.RetainedBytes |
| | 1037 | 78 | | + _pairBytes |
| | 1037 | 79 | | + _dependencyRowBytes |
| | 1037 | 80 | | + _activeRowBytes |
| | 1037 | 81 | | + _linkRowBytes); |
| | | 82 | | |
| | 1037 | 83 | | internal int PersistentPageCount => checked( |
| | 1037 | 84 | | _pairs.PersistentPageCount |
| | 1037 | 85 | | + _dependencies.PersistentPageCount |
| | 1037 | 86 | | + _active.PersistentPageCount |
| | 1037 | 87 | | + _links.PersistentPageCount |
| | 1037 | 88 | | + _pairPages |
| | 1037 | 89 | | + _dependencyRowPages |
| | 1037 | 90 | | + _activeRowPages |
| | 1037 | 91 | | + _linkRowPages); |
| | | 92 | | |
| | | 93 | | internal bool TryGetPair( |
| | | 94 | | NavigationCellAddress first, |
| | | 95 | | NavigationCellAddress second, |
| | | 96 | | out NavigationAutomaticSeamPair pair) |
| | | 97 | | { |
| | 32280 | 98 | | if (_pairs.TryGetValue( |
| | 32280 | 99 | | new NavigationAutomaticSeamPairKey(first, second), |
| | 32280 | 100 | | out NavigationAutomaticSeamPairRecord record)) |
| | | 101 | | { |
| | 7 | 102 | | pair = record.Pair; |
| | 7 | 103 | | return true; |
| | | 104 | | } |
| | 32273 | 105 | | pair = null!; |
| | 32273 | 106 | | return false; |
| | | 107 | | } |
| | | 108 | | |
| | | 109 | | internal bool TryGetPairRecord( |
| | | 110 | | NavigationAutomaticSeamPairKey key, |
| | 6148 | 111 | | out NavigationAutomaticSeamPairRecord record) => _pairs.TryGetValue(key, out record); |
| | | 112 | | |
| | | 113 | | internal bool IsActive(NavigationAutomaticSeamRef seam) => |
| | 20005 | 114 | | _pairs.TryGetValue( |
| | 20005 | 115 | | new NavigationAutomaticSeamPairKey(seam.Pair.First, seam.Pair.Second), |
| | 20005 | 116 | | out NavigationAutomaticSeamPairRecord record) |
| | 20005 | 117 | | && ReferenceEquals(record.Pair, seam.Pair) |
| | 20005 | 118 | | && record.IsActive; |
| | | 119 | | |
| | | 120 | | internal NavigationPagedSequence<NavigationAutomaticSeamPair> GetDependencyRow( |
| | 18203 | 121 | | NavigationCellAddress address) => GetRow(_dependencies, address); |
| | | 122 | | |
| | | 123 | | internal NavigationPagedSequence<NavigationAutomaticSeamPair> GetActiveRow( |
| | 524496 | 124 | | NavigationCellAddress address) => GetRow(_active, address); |
| | | 125 | | |
| | | 126 | | internal EndpointEnumerator GetActiveEndpointEnumerator(NavigationCellAddress address) => |
| | 524067 | 127 | | new(address, GetActiveRow(address)); |
| | | 128 | | |
| | | 129 | | internal NavigationPagedSequence<NavigationStructuralLink> GetStructuralLinks(string mapId) => |
| | 371 | 130 | | _links.TryGetValue( |
| | 371 | 131 | | new NavigationAutomaticSeamMapKey(mapId), |
| | 371 | 132 | | out NavigationPagedSequence<NavigationStructuralLink> links) |
| | 371 | 133 | | ? links |
| | 371 | 134 | | : NavigationPagedSequence<NavigationStructuralLink>.Empty; |
| | | 135 | | |
| | | 136 | | internal EditSession Edit(NavigationSeamEditToken ownershipToken) => |
| | 192 | 137 | | new(this, ownershipToken); |
| | | 138 | | |
| | | 139 | | internal NavigationSeamEditTree<NavigationCellAddress, NavigationPagedSequence<NavigationAutomaticSeamPair>>.Cursor |
| | | 140 | | CreateDependencyCursor(int maximumHeight) => |
| | 112 | 141 | | _dependencies.CreateCursor(maximumHeight, AddressCursorShellBytes); |
| | | 142 | | |
| | | 143 | | internal void BeginDependencyRange( |
| | | 144 | | NavigationSeamEditTree<NavigationCellAddress, NavigationPagedSequence<NavigationAutomaticSeamPair>>.Cursor curso |
| | | 145 | | string mapId) |
| | | 146 | | { |
| | 112 | 147 | | cursor.BeginAtLeast( |
| | 112 | 148 | | _dependencies, |
| | 112 | 149 | | new NavigationCellAddress( |
| | 112 | 150 | | mapId, |
| | 112 | 151 | | new GridForge.Spatial.VoxelIndex(int.MinValue, int.MinValue, int.MinValue))); |
| | 112 | 152 | | } |
| | | 153 | | |
| | | 154 | | private static NavigationPagedSequence<NavigationAutomaticSeamPair> GetRow( |
| | | 155 | | NavigationSeamEditTree<NavigationCellAddress, NavigationPagedSequence<NavigationAutomaticSeamPair>> root, |
| | 542699 | 156 | | NavigationCellAddress address) => root.TryGetValue(address, out NavigationPagedSequence<NavigationAutomaticSeamP |
| | 542699 | 157 | | ? row |
| | 542699 | 158 | | : NavigationPagedSequence<NavigationAutomaticSeamPair>.Empty; |
| | | 159 | | |
| | | 160 | | internal struct EndpointEnumerator |
| | | 161 | | { |
| | | 162 | | private readonly NavigationCellAddress _origin; |
| | | 163 | | private NavigationPagedSequence<NavigationAutomaticSeamPair>.Enumerator _pairs; |
| | | 164 | | |
| | | 165 | | internal EndpointEnumerator( |
| | | 166 | | NavigationCellAddress origin, |
| | | 167 | | NavigationPagedSequence<NavigationAutomaticSeamPair> pairs) |
| | | 168 | | { |
| | 540711 | 169 | | _origin = origin; |
| | 540711 | 170 | | _pairs = pairs.GetEnumerator(); |
| | 540711 | 171 | | Current = default; |
| | 540711 | 172 | | } |
| | | 173 | | |
| | | 174 | | internal NavigationAutomaticSeamRef Current { get; private set; } |
| | | 175 | | |
| | | 176 | | internal bool MoveNext() |
| | | 177 | | { |
| | 646507 | 178 | | if (!_pairs.MoveNext()) |
| | | 179 | | { |
| | 443038 | 180 | | Current = default; |
| | 443038 | 181 | | return false; |
| | | 182 | | } |
| | 203469 | 183 | | NavigationAutomaticSeamPair pair = _pairs.Current; |
| | 203469 | 184 | | Current = new NavigationAutomaticSeamRef( |
| | 203469 | 185 | | pair, |
| | 203469 | 186 | | reverse: _origin.Equals(pair.Second)); |
| | 203469 | 187 | | return true; |
| | | 188 | | } |
| | | 189 | | } |
| | | 190 | | |
| | | 191 | | internal sealed class EditSession |
| | | 192 | | { |
| | | 193 | | private const long BaseRetainedBytes = 160L; |
| | | 194 | | private readonly NavigationAutomaticSeamIndex _source; |
| | | 195 | | private readonly NavigationSeamEditTree<NavigationAutomaticSeamPairKey, NavigationAutomaticSeamPairRecord>.Edito |
| | | 196 | | private readonly NavigationSeamEditTree<NavigationCellAddress, NavigationPagedSequence<NavigationAutomaticSeamPa |
| | | 197 | | private readonly NavigationSeamEditTree<NavigationCellAddress, NavigationPagedSequence<NavigationAutomaticSeamPa |
| | | 198 | | private readonly NavigationSeamEditTree<NavigationAutomaticSeamMapKey, NavigationPagedSequence<NavigationStructu |
| | | 199 | | private long _pairBytes; |
| | | 200 | | private long _dependencyRowBytes; |
| | | 201 | | private long _activeRowBytes; |
| | | 202 | | private long _linkRowBytes; |
| | | 203 | | private int _pairPages; |
| | | 204 | | private int _dependencyRowPages; |
| | | 205 | | private int _activeRowPages; |
| | | 206 | | private int _linkRowPages; |
| | | 207 | | private long _additionalPairBytes; |
| | | 208 | | private long _additionalDependencyRowBytes; |
| | | 209 | | private long _additionalActiveRowBytes; |
| | | 210 | | private long _additionalLinkRowBytes; |
| | | 211 | | private int _additionalPairPages; |
| | | 212 | | private int _additionalDependencyRowPages; |
| | | 213 | | private int _additionalActiveRowPages; |
| | | 214 | | private int _additionalLinkRowPages; |
| | | 215 | | private bool _sealed; |
| | | 216 | | |
| | 192 | 217 | | internal EditSession( |
| | 192 | 218 | | NavigationAutomaticSeamIndex source, |
| | 192 | 219 | | NavigationSeamEditToken ownershipToken) |
| | | 220 | | { |
| | 192 | 221 | | _source = source; |
| | 192 | 222 | | _pairs = source._pairs.Edit(ownershipToken); |
| | 192 | 223 | | _dependencies = source._dependencies.Edit(ownershipToken); |
| | 192 | 224 | | _active = source._active.Edit(ownershipToken); |
| | 192 | 225 | | _links = source._links.Edit(ownershipToken); |
| | 192 | 226 | | _pairBytes = source._pairBytes; |
| | 192 | 227 | | _dependencyRowBytes = source._dependencyRowBytes; |
| | 192 | 228 | | _activeRowBytes = source._activeRowBytes; |
| | 192 | 229 | | _linkRowBytes = source._linkRowBytes; |
| | 192 | 230 | | _pairPages = source._pairPages; |
| | 192 | 231 | | _dependencyRowPages = source._dependencyRowPages; |
| | 192 | 232 | | _activeRowPages = source._activeRowPages; |
| | 192 | 233 | | _linkRowPages = source._linkRowPages; |
| | 192 | 234 | | } |
| | | 235 | | |
| | 117249 | 236 | | internal long RetainedBytes => checked( |
| | 117249 | 237 | | BaseRetainedBytes |
| | 117249 | 238 | | + _pairs.RetainedBytes |
| | 117249 | 239 | | + _dependencies.RetainedBytes |
| | 117249 | 240 | | + _active.RetainedBytes |
| | 117249 | 241 | | + _links.RetainedBytes |
| | 117249 | 242 | | + _additionalPairBytes |
| | 117249 | 243 | | + _additionalDependencyRowBytes |
| | 117249 | 244 | | + _additionalActiveRowBytes |
| | 117249 | 245 | | + _additionalLinkRowBytes); |
| | | 246 | | |
| | 117246 | 247 | | internal int PersistentPageCount => checked( |
| | 117246 | 248 | | 1 |
| | 117246 | 249 | | + _pairs.PersistentPageCount |
| | 117246 | 250 | | + _dependencies.PersistentPageCount |
| | 117246 | 251 | | + _active.PersistentPageCount |
| | 117246 | 252 | | + _links.PersistentPageCount |
| | 117246 | 253 | | + _additionalPairPages |
| | 117246 | 254 | | + _additionalDependencyRowPages |
| | 117246 | 255 | | + _additionalActiveRowPages |
| | 117246 | 256 | | + _additionalLinkRowPages); |
| | | 257 | | |
| | | 258 | | internal bool IsChanged => |
| | 553 | 259 | | _pairs.IsChanged || _dependencies.IsChanged || _active.IsChanged || _links.IsChanged; |
| | | 260 | | |
| | 182 | 261 | | internal long SealedAdditionalRetainedBytes => !IsChanged |
| | 182 | 262 | | ? 0L |
| | 182 | 263 | | : checked( |
| | 182 | 264 | | NavigationAutomaticSeamIndex.BaseRetainedBytes |
| | 182 | 265 | | + GetSealedTreeBytes(_pairs, PairNodeBytes) |
| | 182 | 266 | | + GetSealedTreeBytes(_dependencies, AddressNodeBytes) |
| | 182 | 267 | | + GetSealedTreeBytes(_active, AddressNodeBytes) |
| | 182 | 268 | | + GetSealedTreeBytes(_links, MapNodeBytes) |
| | 182 | 269 | | + _additionalPairBytes |
| | 182 | 270 | | + _additionalDependencyRowBytes |
| | 182 | 271 | | + _additionalActiveRowBytes |
| | 182 | 272 | | + _additionalLinkRowBytes); |
| | | 273 | | |
| | 182 | 274 | | internal int SealedAdditionalPersistentPages => !IsChanged |
| | 182 | 275 | | ? 0 |
| | 182 | 276 | | : checked( |
| | 182 | 277 | | GetSealedTreePages(_pairs) |
| | 182 | 278 | | + GetSealedTreePages(_dependencies) |
| | 182 | 279 | | + GetSealedTreePages(_active) |
| | 182 | 280 | | + GetSealedTreePages(_links) |
| | 182 | 281 | | + _additionalPairPages |
| | 182 | 282 | | + _additionalDependencyRowPages |
| | 182 | 283 | | + _additionalActiveRowPages |
| | 182 | 284 | | + _additionalLinkRowPages); |
| | | 285 | | |
| | | 286 | | internal void SetPair( |
| | | 287 | | NavigationAutomaticSeamPairKey key, |
| | | 288 | | NavigationAutomaticSeamPairRecord? record) |
| | | 289 | | { |
| | 6126 | 290 | | _pairs.TryGetValue(key, out NavigationAutomaticSeamPairRecord prior); |
| | 6126 | 291 | | _source._pairs.TryGetValue(key, out NavigationAutomaticSeamPairRecord shared); |
| | 6126 | 292 | | ReplacePairPayload(prior, record, shared); |
| | 6126 | 293 | | if (prior != null) |
| | | 294 | | { |
| | 100 | 295 | | _pairBytes -= NavigationAutomaticSeamPair.RetainedSize |
| | 100 | 296 | | + NavigationAutomaticSeamPairRecord.RetainedSize; |
| | 100 | 297 | | _pairPages -= 2; |
| | | 298 | | } |
| | 6126 | 299 | | if (record == null) |
| | 62 | 300 | | _pairs.Remove(key); |
| | | 301 | | else |
| | | 302 | | { |
| | 6064 | 303 | | _pairs.Set(key, record); |
| | 6064 | 304 | | _pairBytes += NavigationAutomaticSeamPair.RetainedSize |
| | 6064 | 305 | | + NavigationAutomaticSeamPairRecord.RetainedSize; |
| | 6064 | 306 | | _pairPages += 2; |
| | | 307 | | } |
| | 6064 | 308 | | } |
| | | 309 | | |
| | | 310 | | internal void SetDependencyRow( |
| | | 311 | | NavigationCellAddress address, |
| | 1562 | 312 | | NavigationPagedSequence<NavigationAutomaticSeamPair> row) => SetRow( |
| | 1562 | 313 | | address, |
| | 1562 | 314 | | row, |
| | 1562 | 315 | | _source._dependencies, |
| | 1562 | 316 | | _dependencies, |
| | 1562 | 317 | | ref _dependencyRowBytes, |
| | 1562 | 318 | | ref _dependencyRowPages, |
| | 1562 | 319 | | ref _additionalDependencyRowBytes, |
| | 1562 | 320 | | ref _additionalDependencyRowPages); |
| | | 321 | | |
| | | 322 | | internal void SetActiveRow( |
| | | 323 | | NavigationCellAddress address, |
| | 441 | 324 | | NavigationPagedSequence<NavigationAutomaticSeamPair> row) => SetRow( |
| | 441 | 325 | | address, |
| | 441 | 326 | | row, |
| | 441 | 327 | | _source._active, |
| | 441 | 328 | | _active, |
| | 441 | 329 | | ref _activeRowBytes, |
| | 441 | 330 | | ref _activeRowPages, |
| | 441 | 331 | | ref _additionalActiveRowBytes, |
| | 441 | 332 | | ref _additionalActiveRowPages); |
| | | 333 | | |
| | | 334 | | internal void SetStructuralLinks( |
| | | 335 | | string mapId, |
| | | 336 | | NavigationPagedSequence<NavigationStructuralLink> row) |
| | | 337 | | { |
| | 369 | 338 | | var key = new NavigationAutomaticSeamMapKey(mapId); |
| | 369 | 339 | | _links.TryGetValue(key, out NavigationPagedSequence<NavigationStructuralLink> prior); |
| | 369 | 340 | | _source._links.TryGetValue(key, out NavigationPagedSequence<NavigationStructuralLink> shared); |
| | 369 | 341 | | prior ??= NavigationPagedSequence<NavigationStructuralLink>.Empty; |
| | 369 | 342 | | shared ??= NavigationPagedSequence<NavigationStructuralLink>.Empty; |
| | 369 | 343 | | ReplacePayload( |
| | 369 | 344 | | prior, |
| | 369 | 345 | | row, |
| | 369 | 346 | | shared, |
| | 369 | 347 | | row.RetainedBytes, |
| | 369 | 348 | | row.PersistentPageCount, |
| | 369 | 349 | | ref _additionalLinkRowBytes, |
| | 369 | 350 | | ref _additionalLinkRowPages); |
| | 369 | 351 | | _linkRowBytes = checked(_linkRowBytes - prior.RetainedBytes + row.RetainedBytes); |
| | 369 | 352 | | _linkRowPages = checked( |
| | 369 | 353 | | _linkRowPages - prior.PersistentPageCount + row.PersistentPageCount); |
| | 369 | 354 | | if (row.Count == 0) |
| | 38 | 355 | | _links.Remove(key); |
| | | 356 | | else |
| | 331 | 357 | | _links.Set(key, row); |
| | 331 | 358 | | } |
| | | 359 | | |
| | | 360 | | internal NavigationAutomaticSeamIndex Seal() |
| | | 361 | | { |
| | 190 | 362 | | SwiftThrowHelper.ThrowIfTrue( |
| | 190 | 363 | | _sealed, |
| | 190 | 364 | | message: "The seam index edit is already sealed."); |
| | 189 | 365 | | _sealed = true; |
| | 189 | 366 | | if (!IsChanged) |
| | 9 | 367 | | return _source; |
| | 180 | 368 | | return new NavigationAutomaticSeamIndex( |
| | 180 | 369 | | _pairs.Seal(), |
| | 180 | 370 | | _dependencies.Seal(), |
| | 180 | 371 | | _active.Seal(), |
| | 180 | 372 | | _links.Seal(), |
| | 180 | 373 | | _pairBytes, |
| | 180 | 374 | | _dependencyRowBytes, |
| | 180 | 375 | | _activeRowBytes, |
| | 180 | 376 | | _linkRowBytes, |
| | 180 | 377 | | _pairPages, |
| | 180 | 378 | | _dependencyRowPages, |
| | 180 | 379 | | _activeRowPages, |
| | 180 | 380 | | _linkRowPages); |
| | | 381 | | } |
| | | 382 | | |
| | | 383 | | private void ReplacePairPayload( |
| | | 384 | | NavigationAutomaticSeamPairRecord? prior, |
| | | 385 | | NavigationAutomaticSeamPairRecord? next, |
| | | 386 | | NavigationAutomaticSeamPairRecord? shared) |
| | | 387 | | { |
| | 6126 | 388 | | if (prior != null && !ReferenceEquals(prior, shared)) |
| | | 389 | | { |
| | 3 | 390 | | _additionalPairBytes -= NavigationAutomaticSeamPairRecord.RetainedSize; |
| | 3 | 391 | | _additionalPairPages--; |
| | 3 | 392 | | if (shared == null || !ReferenceEquals(prior.Pair, shared.Pair)) |
| | | 393 | | { |
| | 2 | 394 | | _additionalPairBytes -= NavigationAutomaticSeamPair.RetainedSize; |
| | 2 | 395 | | _additionalPairPages--; |
| | | 396 | | } |
| | | 397 | | } |
| | 6126 | 398 | | if (next == null || ReferenceEquals(next, shared)) |
| | 62 | 399 | | return; |
| | 6064 | 400 | | _additionalPairBytes = checked( |
| | 6064 | 401 | | _additionalPairBytes + NavigationAutomaticSeamPairRecord.RetainedSize); |
| | 6064 | 402 | | _additionalPairPages++; |
| | 6064 | 403 | | if (shared == null || !ReferenceEquals(next.Pair, shared.Pair)) |
| | | 404 | | { |
| | 6039 | 405 | | _additionalPairBytes = checked( |
| | 6039 | 406 | | _additionalPairBytes + NavigationAutomaticSeamPair.RetainedSize); |
| | 6039 | 407 | | _additionalPairPages++; |
| | | 408 | | } |
| | 6064 | 409 | | } |
| | | 410 | | |
| | | 411 | | private static void SetRow( |
| | | 412 | | NavigationCellAddress address, |
| | | 413 | | NavigationPagedSequence<NavigationAutomaticSeamPair> row, |
| | | 414 | | NavigationSeamEditTree<NavigationCellAddress, NavigationPagedSequence<NavigationAutomaticSeamPair>> source, |
| | | 415 | | NavigationSeamEditTree<NavigationCellAddress, NavigationPagedSequence<NavigationAutomaticSeamPair>>.Editor e |
| | | 416 | | ref long rowBytes, |
| | | 417 | | ref int rowPages, |
| | | 418 | | ref long additionalBytes, |
| | | 419 | | ref int additionalPages) |
| | | 420 | | { |
| | 2003 | 421 | | editor.TryGetValue(address, out NavigationPagedSequence<NavigationAutomaticSeamPair> prior); |
| | 2003 | 422 | | source.TryGetValue(address, out NavigationPagedSequence<NavigationAutomaticSeamPair> shared); |
| | 2003 | 423 | | prior ??= NavigationPagedSequence<NavigationAutomaticSeamPair>.Empty; |
| | 2003 | 424 | | shared ??= NavigationPagedSequence<NavigationAutomaticSeamPair>.Empty; |
| | 2003 | 425 | | ReplacePayload( |
| | 2003 | 426 | | prior, |
| | 2003 | 427 | | row, |
| | 2003 | 428 | | shared, |
| | 2003 | 429 | | row.RetainedBytes, |
| | 2003 | 430 | | row.PersistentPageCount, |
| | 2003 | 431 | | ref additionalBytes, |
| | 2003 | 432 | | ref additionalPages); |
| | 2003 | 433 | | rowBytes = checked(rowBytes - prior.RetainedBytes + row.RetainedBytes); |
| | 2003 | 434 | | rowPages = checked(rowPages - prior.PersistentPageCount + row.PersistentPageCount); |
| | 2003 | 435 | | if (row.Count == 0) |
| | 115 | 436 | | editor.Remove(address); |
| | | 437 | | else |
| | 1888 | 438 | | editor.Set(address, row); |
| | 1888 | 439 | | } |
| | | 440 | | |
| | | 441 | | private static void ReplacePayload<T>( |
| | | 442 | | T prior, |
| | | 443 | | T next, |
| | | 444 | | T shared, |
| | | 445 | | long nextBytes, |
| | | 446 | | int nextPages, |
| | | 447 | | ref long bytes, |
| | | 448 | | ref int pages) |
| | | 449 | | where T : class |
| | | 450 | | { |
| | 2372 | 451 | | if (!ReferenceEquals(prior, shared)) |
| | | 452 | | { |
| | 3 | 453 | | GetPayloadSize(prior, out long priorBytes, out int priorPages); |
| | 3 | 454 | | bytes -= priorBytes; |
| | 3 | 455 | | pages -= priorPages; |
| | | 456 | | } |
| | 2372 | 457 | | if (!ReferenceEquals(next, shared)) |
| | | 458 | | { |
| | 2371 | 459 | | bytes = checked(bytes + nextBytes); |
| | 2371 | 460 | | pages = checked(pages + nextPages); |
| | | 461 | | } |
| | 2372 | 462 | | } |
| | | 463 | | |
| | | 464 | | private static void GetPayloadSize<T>(T value, out long bytes, out int pages) |
| | | 465 | | where T : class |
| | | 466 | | { |
| | 3 | 467 | | if (value is NavigationPagedSequence<NavigationAutomaticSeamPair> seamRow) |
| | | 468 | | { |
| | 2 | 469 | | bytes = seamRow.RetainedBytes; |
| | 2 | 470 | | pages = seamRow.PersistentPageCount; |
| | 2 | 471 | | return; |
| | | 472 | | } |
| | 1 | 473 | | var linkRow = (NavigationPagedSequence<NavigationStructuralLink>)(object)value; |
| | 1 | 474 | | bytes = linkRow.RetainedBytes; |
| | 1 | 475 | | pages = linkRow.PersistentPageCount; |
| | 1 | 476 | | } |
| | | 477 | | |
| | | 478 | | private static long GetSealedTreeBytes<TK, TV>( |
| | | 479 | | NavigationSeamEditTree<TK, TV>.Editor editor, |
| | | 480 | | int nodeBytes) |
| | | 481 | | where TK : struct, System.IComparable<TK> |
| | 692 | 482 | | where TV : class => editor.IsChanged |
| | 692 | 483 | | ? checked(32L + ((long)editor.OwnedNodeCount * nodeBytes)) |
| | 692 | 484 | | : 0L; |
| | | 485 | | |
| | | 486 | | private static int GetSealedTreePages<TK, TV>( |
| | | 487 | | NavigationSeamEditTree<TK, TV>.Editor editor) |
| | | 488 | | where TK : struct, System.IComparable<TK> |
| | 692 | 489 | | where TV : class => editor.IsChanged ? checked(1 + editor.OwnedNodeCount) : 0; |
| | | 490 | | } |
| | | 491 | | } |