github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/pkg/sentry/fsutil/file_range_set_impl.go (about) 1 package fsutil 2 3 import ( 4 __generics_imported0 "github.com/metacubex/gvisor/pkg/sentry/memmap" 5 ) 6 7 import ( 8 "bytes" 9 "context" 10 "fmt" 11 ) 12 13 // trackGaps is an optional parameter. 14 // 15 // If trackGaps is 1, the Set will track maximum gap size recursively, 16 // enabling the GapIterator.{Prev,Next}LargeEnoughGap functions. In this 17 // case, Key must be an unsigned integer. 18 // 19 // trackGaps must be 0 or 1. 20 const FileRangetrackGaps = 0 21 22 var _ = uint8(FileRangetrackGaps << 7) // Will fail if not zero or one. 23 24 // dynamicGap is a type that disappears if trackGaps is 0. 25 type FileRangedynamicGap [FileRangetrackGaps]uint64 26 27 // Get returns the value of the gap. 28 // 29 // Precondition: trackGaps must be non-zero. 30 func (d *FileRangedynamicGap) Get() uint64 { 31 return d[:][0] 32 } 33 34 // Set sets the value of the gap. 35 // 36 // Precondition: trackGaps must be non-zero. 37 func (d *FileRangedynamicGap) Set(v uint64) { 38 d[:][0] = v 39 } 40 41 const ( 42 // minDegree is the minimum degree of an internal node in a Set B-tree. 43 // 44 // - Any non-root node has at least minDegree-1 segments. 45 // 46 // - Any non-root internal (non-leaf) node has at least minDegree children. 47 // 48 // - The root node may have fewer than minDegree-1 segments, but it may 49 // only have 0 segments if the tree is empty. 50 // 51 // Our implementation requires minDegree >= 3. Higher values of minDegree 52 // usually improve performance, but increase memory usage for small sets. 53 FileRangeminDegree = 3 54 55 FileRangemaxDegree = 2 * FileRangeminDegree 56 ) 57 58 // A Set is a mapping of segments with non-overlapping Range keys. The zero 59 // value for a Set is an empty set. Set values are not safely movable nor 60 // copyable. Set is thread-compatible. 61 // 62 // +stateify savable 63 type FileRangeSet struct { 64 root FileRangenode `state:".([]FileRangeFlatSegment)"` 65 } 66 67 // IsEmpty returns true if the set contains no segments. 68 func (s *FileRangeSet) IsEmpty() bool { 69 return s.root.nrSegments == 0 70 } 71 72 // IsEmptyRange returns true iff no segments in the set overlap the given 73 // range. This is semantically equivalent to s.SpanRange(r) == 0, but may be 74 // more efficient. 75 func (s *FileRangeSet) IsEmptyRange(r __generics_imported0.MappableRange) bool { 76 switch { 77 case r.Length() < 0: 78 panic(fmt.Sprintf("invalid range %v", r)) 79 case r.Length() == 0: 80 return true 81 } 82 _, gap := s.Find(r.Start) 83 if !gap.Ok() { 84 return false 85 } 86 return r.End <= gap.End() 87 } 88 89 // Span returns the total size of all segments in the set. 90 func (s *FileRangeSet) Span() uint64 { 91 var sz uint64 92 for seg := s.FirstSegment(); seg.Ok(); seg = seg.NextSegment() { 93 sz += seg.Range().Length() 94 } 95 return sz 96 } 97 98 // SpanRange returns the total size of the intersection of segments in the set 99 // with the given range. 100 func (s *FileRangeSet) SpanRange(r __generics_imported0.MappableRange) uint64 { 101 switch { 102 case r.Length() < 0: 103 panic(fmt.Sprintf("invalid range %v", r)) 104 case r.Length() == 0: 105 return 0 106 } 107 var sz uint64 108 for seg := s.LowerBoundSegment(r.Start); seg.Ok() && seg.Start() < r.End; seg = seg.NextSegment() { 109 sz += seg.Range().Intersect(r).Length() 110 } 111 return sz 112 } 113 114 // FirstSegment returns the first segment in the set. If the set is empty, 115 // FirstSegment returns a terminal iterator. 116 func (s *FileRangeSet) FirstSegment() FileRangeIterator { 117 if s.root.nrSegments == 0 { 118 return FileRangeIterator{} 119 } 120 return s.root.firstSegment() 121 } 122 123 // LastSegment returns the last segment in the set. If the set is empty, 124 // LastSegment returns a terminal iterator. 125 func (s *FileRangeSet) LastSegment() FileRangeIterator { 126 if s.root.nrSegments == 0 { 127 return FileRangeIterator{} 128 } 129 return s.root.lastSegment() 130 } 131 132 // FirstGap returns the first gap in the set. 133 func (s *FileRangeSet) FirstGap() FileRangeGapIterator { 134 n := &s.root 135 for n.hasChildren { 136 n = n.children[0] 137 } 138 return FileRangeGapIterator{n, 0} 139 } 140 141 // LastGap returns the last gap in the set. 142 func (s *FileRangeSet) LastGap() FileRangeGapIterator { 143 n := &s.root 144 for n.hasChildren { 145 n = n.children[n.nrSegments] 146 } 147 return FileRangeGapIterator{n, n.nrSegments} 148 } 149 150 // Find returns the segment or gap whose range contains the given key. If a 151 // segment is found, the returned Iterator is non-terminal and the 152 // returned GapIterator is terminal. Otherwise, the returned Iterator is 153 // terminal and the returned GapIterator is non-terminal. 154 func (s *FileRangeSet) Find(key uint64) (FileRangeIterator, FileRangeGapIterator) { 155 n := &s.root 156 for { 157 158 lower := 0 159 upper := n.nrSegments 160 for lower < upper { 161 i := lower + (upper-lower)/2 162 if r := n.keys[i]; key < r.End { 163 if key >= r.Start { 164 return FileRangeIterator{n, i}, FileRangeGapIterator{} 165 } 166 upper = i 167 } else { 168 lower = i + 1 169 } 170 } 171 i := lower 172 if !n.hasChildren { 173 return FileRangeIterator{}, FileRangeGapIterator{n, i} 174 } 175 n = n.children[i] 176 } 177 } 178 179 // FindSegment returns the segment whose range contains the given key. If no 180 // such segment exists, FindSegment returns a terminal iterator. 181 func (s *FileRangeSet) FindSegment(key uint64) FileRangeIterator { 182 seg, _ := s.Find(key) 183 return seg 184 } 185 186 // LowerBoundSegment returns the segment with the lowest range that contains a 187 // key greater than or equal to min. If no such segment exists, 188 // LowerBoundSegment returns a terminal iterator. 189 func (s *FileRangeSet) LowerBoundSegment(min uint64) FileRangeIterator { 190 seg, gap := s.Find(min) 191 if seg.Ok() { 192 return seg 193 } 194 return gap.NextSegment() 195 } 196 197 // UpperBoundSegment returns the segment with the highest range that contains a 198 // key less than or equal to max. If no such segment exists, UpperBoundSegment 199 // returns a terminal iterator. 200 func (s *FileRangeSet) UpperBoundSegment(max uint64) FileRangeIterator { 201 seg, gap := s.Find(max) 202 if seg.Ok() { 203 return seg 204 } 205 return gap.PrevSegment() 206 } 207 208 // FindGap returns the gap containing the given key. If no such gap exists 209 // (i.e. the set contains a segment containing that key), FindGap returns a 210 // terminal iterator. 211 func (s *FileRangeSet) FindGap(key uint64) FileRangeGapIterator { 212 _, gap := s.Find(key) 213 return gap 214 } 215 216 // LowerBoundGap returns the gap with the lowest range that is greater than or 217 // equal to min. 218 func (s *FileRangeSet) LowerBoundGap(min uint64) FileRangeGapIterator { 219 seg, gap := s.Find(min) 220 if gap.Ok() { 221 return gap 222 } 223 return seg.NextGap() 224 } 225 226 // UpperBoundGap returns the gap with the highest range that is less than or 227 // equal to max. 228 func (s *FileRangeSet) UpperBoundGap(max uint64) FileRangeGapIterator { 229 seg, gap := s.Find(max) 230 if gap.Ok() { 231 return gap 232 } 233 return seg.PrevGap() 234 } 235 236 // FirstLargeEnoughGap returns the first gap in the set with at least the given 237 // length. If no such gap exists, FirstLargeEnoughGap returns a terminal 238 // iterator. 239 // 240 // Precondition: trackGaps must be 1. 241 func (s *FileRangeSet) FirstLargeEnoughGap(minSize uint64) FileRangeGapIterator { 242 if FileRangetrackGaps != 1 { 243 panic("set is not tracking gaps") 244 } 245 gap := s.FirstGap() 246 if gap.Range().Length() >= minSize { 247 return gap 248 } 249 return gap.NextLargeEnoughGap(minSize) 250 } 251 252 // LastLargeEnoughGap returns the last gap in the set with at least the given 253 // length. If no such gap exists, LastLargeEnoughGap returns a terminal 254 // iterator. 255 // 256 // Precondition: trackGaps must be 1. 257 func (s *FileRangeSet) LastLargeEnoughGap(minSize uint64) FileRangeGapIterator { 258 if FileRangetrackGaps != 1 { 259 panic("set is not tracking gaps") 260 } 261 gap := s.LastGap() 262 if gap.Range().Length() >= minSize { 263 return gap 264 } 265 return gap.PrevLargeEnoughGap(minSize) 266 } 267 268 // LowerBoundLargeEnoughGap returns the first gap in the set with at least the 269 // given length and whose range contains a key greater than or equal to min. If 270 // no such gap exists, LowerBoundLargeEnoughGap returns a terminal iterator. 271 // 272 // Precondition: trackGaps must be 1. 273 func (s *FileRangeSet) LowerBoundLargeEnoughGap(min, minSize uint64) FileRangeGapIterator { 274 if FileRangetrackGaps != 1 { 275 panic("set is not tracking gaps") 276 } 277 gap := s.LowerBoundGap(min) 278 if gap.Range().Length() >= minSize { 279 return gap 280 } 281 return gap.NextLargeEnoughGap(minSize) 282 } 283 284 // UpperBoundLargeEnoughGap returns the last gap in the set with at least the 285 // given length and whose range contains a key less than or equal to max. If no 286 // such gap exists, UpperBoundLargeEnoughGap returns a terminal iterator. 287 // 288 // Precondition: trackGaps must be 1. 289 func (s *FileRangeSet) UpperBoundLargeEnoughGap(max, minSize uint64) FileRangeGapIterator { 290 if FileRangetrackGaps != 1 { 291 panic("set is not tracking gaps") 292 } 293 gap := s.UpperBoundGap(max) 294 if gap.Range().Length() >= minSize { 295 return gap 296 } 297 return gap.PrevLargeEnoughGap(minSize) 298 } 299 300 // Insert inserts the given segment into the given gap. If the new segment can 301 // be merged with adjacent segments, Insert will do so. Insert returns an 302 // iterator to the segment containing the inserted value (which may have been 303 // merged with other values). All existing iterators (including gap, but not 304 // including the returned iterator) are invalidated. 305 // 306 // If the gap cannot accommodate the segment, or if r is invalid, Insert panics. 307 // 308 // Insert is semantically equivalent to a InsertWithoutMerging followed by a 309 // Merge, but may be more efficient. Note that there is no unchecked variant of 310 // Insert since Insert must retrieve and inspect gap's predecessor and 311 // successor segments regardless. 312 func (s *FileRangeSet) Insert(gap FileRangeGapIterator, r __generics_imported0.MappableRange, val uint64) FileRangeIterator { 313 if r.Length() <= 0 { 314 panic(fmt.Sprintf("invalid segment range %v", r)) 315 } 316 prev, next := gap.PrevSegment(), gap.NextSegment() 317 if prev.Ok() && prev.End() > r.Start { 318 panic(fmt.Sprintf("new segment %v overlaps predecessor %v", r, prev.Range())) 319 } 320 if next.Ok() && next.Start() < r.End { 321 panic(fmt.Sprintf("new segment %v overlaps successor %v", r, next.Range())) 322 } 323 if prev.Ok() && prev.End() == r.Start { 324 if mval, ok := (FileRangeSetFunctions{}).Merge(prev.Range(), prev.Value(), r, val); ok { 325 shrinkMaxGap := FileRangetrackGaps != 0 && gap.Range().Length() == gap.node.maxGap.Get() 326 prev.SetEndUnchecked(r.End) 327 prev.SetValue(mval) 328 if shrinkMaxGap { 329 gap.node.updateMaxGapLeaf() 330 } 331 if next.Ok() && next.Start() == r.End { 332 val = mval 333 if mval, ok := (FileRangeSetFunctions{}).Merge(prev.Range(), val, next.Range(), next.Value()); ok { 334 prev.SetEndUnchecked(next.End()) 335 prev.SetValue(mval) 336 return s.Remove(next).PrevSegment() 337 } 338 } 339 return prev 340 } 341 } 342 if next.Ok() && next.Start() == r.End { 343 if mval, ok := (FileRangeSetFunctions{}).Merge(r, val, next.Range(), next.Value()); ok { 344 shrinkMaxGap := FileRangetrackGaps != 0 && gap.Range().Length() == gap.node.maxGap.Get() 345 next.SetStartUnchecked(r.Start) 346 next.SetValue(mval) 347 if shrinkMaxGap { 348 gap.node.updateMaxGapLeaf() 349 } 350 return next 351 } 352 } 353 354 return s.InsertWithoutMergingUnchecked(gap, r, val) 355 } 356 357 // InsertWithoutMerging inserts the given segment into the given gap and 358 // returns an iterator to the inserted segment. All existing iterators 359 // (including gap, but not including the returned iterator) are invalidated. 360 // 361 // If the gap cannot accommodate the segment, or if r is invalid, 362 // InsertWithoutMerging panics. 363 func (s *FileRangeSet) InsertWithoutMerging(gap FileRangeGapIterator, r __generics_imported0.MappableRange, val uint64) FileRangeIterator { 364 if r.Length() <= 0 { 365 panic(fmt.Sprintf("invalid segment range %v", r)) 366 } 367 if gr := gap.Range(); !gr.IsSupersetOf(r) { 368 panic(fmt.Sprintf("cannot insert segment range %v into gap range %v", r, gr)) 369 } 370 return s.InsertWithoutMergingUnchecked(gap, r, val) 371 } 372 373 // InsertWithoutMergingUnchecked inserts the given segment into the given gap 374 // and returns an iterator to the inserted segment. All existing iterators 375 // (including gap, but not including the returned iterator) are invalidated. 376 // 377 // Preconditions: 378 // - r.Start >= gap.Start(). 379 // - r.End <= gap.End(). 380 func (s *FileRangeSet) InsertWithoutMergingUnchecked(gap FileRangeGapIterator, r __generics_imported0.MappableRange, val uint64) FileRangeIterator { 381 gap = gap.node.rebalanceBeforeInsert(gap) 382 splitMaxGap := FileRangetrackGaps != 0 && (gap.node.nrSegments == 0 || gap.Range().Length() == gap.node.maxGap.Get()) 383 copy(gap.node.keys[gap.index+1:], gap.node.keys[gap.index:gap.node.nrSegments]) 384 copy(gap.node.values[gap.index+1:], gap.node.values[gap.index:gap.node.nrSegments]) 385 gap.node.keys[gap.index] = r 386 gap.node.values[gap.index] = val 387 gap.node.nrSegments++ 388 if splitMaxGap { 389 gap.node.updateMaxGapLeaf() 390 } 391 return FileRangeIterator{gap.node, gap.index} 392 } 393 394 // InsertRange inserts the given segment into the set. If the new segment can 395 // be merged with adjacent segments, InsertRange will do so. InsertRange 396 // returns an iterator to the segment containing the inserted value (which may 397 // have been merged with other values). All existing iterators (excluding the 398 // returned iterator) are invalidated. 399 // 400 // If the new segment would overlap an existing segment, or if r is invalid, 401 // InsertRange panics. 402 // 403 // InsertRange searches the set to find the gap to insert into. If the caller 404 // already has the appropriate GapIterator, or if the caller needs to do 405 // additional work between finding the gap and insertion, use Insert instead. 406 func (s *FileRangeSet) InsertRange(r __generics_imported0.MappableRange, val uint64) FileRangeIterator { 407 if r.Length() <= 0 { 408 panic(fmt.Sprintf("invalid segment range %v", r)) 409 } 410 seg, gap := s.Find(r.Start) 411 if seg.Ok() { 412 panic(fmt.Sprintf("new segment %v overlaps existing segment %v", r, seg.Range())) 413 } 414 if gap.End() < r.End { 415 panic(fmt.Sprintf("new segment %v overlaps existing segment %v", r, gap.NextSegment().Range())) 416 } 417 return s.Insert(gap, r, val) 418 } 419 420 // InsertWithoutMergingRange inserts the given segment into the set and returns 421 // an iterator to the inserted segment. All existing iterators (excluding the 422 // returned iterator) are invalidated. 423 // 424 // If the new segment would overlap an existing segment, or if r is invalid, 425 // InsertWithoutMergingRange panics. 426 // 427 // InsertWithoutMergingRange searches the set to find the gap to insert into. 428 // If the caller already has the appropriate GapIterator, or if the caller 429 // needs to do additional work between finding the gap and insertion, use 430 // InsertWithoutMerging instead. 431 func (s *FileRangeSet) InsertWithoutMergingRange(r __generics_imported0.MappableRange, val uint64) FileRangeIterator { 432 if r.Length() <= 0 { 433 panic(fmt.Sprintf("invalid segment range %v", r)) 434 } 435 seg, gap := s.Find(r.Start) 436 if seg.Ok() { 437 panic(fmt.Sprintf("new segment %v overlaps existing segment %v", r, seg.Range())) 438 } 439 if gap.End() < r.End { 440 panic(fmt.Sprintf("new segment %v overlaps existing segment %v", r, gap.NextSegment().Range())) 441 } 442 return s.InsertWithoutMerging(gap, r, val) 443 } 444 445 // TryInsertRange attempts to insert the given segment into the set. If the new 446 // segment can be merged with adjacent segments, TryInsertRange will do so. 447 // TryInsertRange returns an iterator to the segment containing the inserted 448 // value (which may have been merged with other values). All existing iterators 449 // (excluding the returned iterator) are invalidated. 450 // 451 // If the new segment would overlap an existing segment, TryInsertRange does 452 // nothing and returns a terminal iterator. 453 // 454 // TryInsertRange searches the set to find the gap to insert into. If the 455 // caller already has the appropriate GapIterator, or if the caller needs to do 456 // additional work between finding the gap and insertion, use Insert instead. 457 func (s *FileRangeSet) TryInsertRange(r __generics_imported0.MappableRange, val uint64) FileRangeIterator { 458 if r.Length() <= 0 { 459 panic(fmt.Sprintf("invalid segment range %v", r)) 460 } 461 seg, gap := s.Find(r.Start) 462 if seg.Ok() { 463 return FileRangeIterator{} 464 } 465 if gap.End() < r.End { 466 return FileRangeIterator{} 467 } 468 return s.Insert(gap, r, val) 469 } 470 471 // TryInsertWithoutMergingRange attempts to insert the given segment into the 472 // set. If successful, it returns an iterator to the inserted segment; all 473 // existing iterators (excluding the returned iterator) are invalidated. If the 474 // new segment would overlap an existing segment, TryInsertWithoutMergingRange 475 // does nothing and returns a terminal iterator. 476 // 477 // TryInsertWithoutMergingRange searches the set to find the gap to insert 478 // into. If the caller already has the appropriate GapIterator, or if the 479 // caller needs to do additional work between finding the gap and insertion, 480 // use InsertWithoutMerging instead. 481 func (s *FileRangeSet) TryInsertWithoutMergingRange(r __generics_imported0.MappableRange, val uint64) FileRangeIterator { 482 if r.Length() <= 0 { 483 panic(fmt.Sprintf("invalid segment range %v", r)) 484 } 485 seg, gap := s.Find(r.Start) 486 if seg.Ok() { 487 return FileRangeIterator{} 488 } 489 if gap.End() < r.End { 490 return FileRangeIterator{} 491 } 492 return s.InsertWithoutMerging(gap, r, val) 493 } 494 495 // Remove removes the given segment and returns an iterator to the vacated gap. 496 // All existing iterators (including seg, but not including the returned 497 // iterator) are invalidated. 498 func (s *FileRangeSet) Remove(seg FileRangeIterator) FileRangeGapIterator { 499 500 if seg.node.hasChildren { 501 502 victim := seg.PrevSegment() 503 504 seg.SetRangeUnchecked(victim.Range()) 505 seg.SetValue(victim.Value()) 506 507 nextAdjacentNode := seg.NextSegment().node 508 if FileRangetrackGaps != 0 { 509 nextAdjacentNode.updateMaxGapLeaf() 510 } 511 return s.Remove(victim).NextGap() 512 } 513 copy(seg.node.keys[seg.index:], seg.node.keys[seg.index+1:seg.node.nrSegments]) 514 copy(seg.node.values[seg.index:], seg.node.values[seg.index+1:seg.node.nrSegments]) 515 FileRangeSetFunctions{}.ClearValue(&seg.node.values[seg.node.nrSegments-1]) 516 seg.node.nrSegments-- 517 if FileRangetrackGaps != 0 { 518 seg.node.updateMaxGapLeaf() 519 } 520 return seg.node.rebalanceAfterRemove(FileRangeGapIterator{seg.node, seg.index}) 521 } 522 523 // RemoveAll removes all segments from the set. All existing iterators are 524 // invalidated. 525 func (s *FileRangeSet) RemoveAll() { 526 s.root = FileRangenode{} 527 } 528 529 // RemoveRange removes all segments in the given range. An iterator to the 530 // newly formed gap is returned, and all existing iterators are invalidated. 531 // 532 // RemoveRange searches the set to find segments to remove. If the caller 533 // already has an iterator to either end of the range of segments to remove, or 534 // if the caller needs to do additional work before removing each segment, 535 // iterate segments and call Remove in a loop instead. 536 func (s *FileRangeSet) RemoveRange(r __generics_imported0.MappableRange) FileRangeGapIterator { 537 seg, gap := s.Find(r.Start) 538 if seg.Ok() { 539 seg = s.Isolate(seg, r) 540 gap = s.Remove(seg) 541 } 542 for seg = gap.NextSegment(); seg.Ok() && seg.Start() < r.End; seg = gap.NextSegment() { 543 seg = s.SplitAfter(seg, r.End) 544 gap = s.Remove(seg) 545 } 546 return gap 547 } 548 549 // RemoveFullRange is equivalent to RemoveRange, except that if any key in the 550 // given range does not correspond to a segment, RemoveFullRange panics. 551 func (s *FileRangeSet) RemoveFullRange(r __generics_imported0.MappableRange) FileRangeGapIterator { 552 seg := s.FindSegment(r.Start) 553 if !seg.Ok() { 554 panic(fmt.Sprintf("missing segment at %v", r.Start)) 555 } 556 seg = s.SplitBefore(seg, r.Start) 557 for { 558 seg = s.SplitAfter(seg, r.End) 559 end := seg.End() 560 gap := s.Remove(seg) 561 if r.End <= end { 562 return gap 563 } 564 seg = gap.NextSegment() 565 if !seg.Ok() || seg.Start() != end { 566 panic(fmt.Sprintf("missing segment at %v", end)) 567 } 568 } 569 } 570 571 // Merge attempts to merge two neighboring segments. If successful, Merge 572 // returns an iterator to the merged segment, and all existing iterators are 573 // invalidated. Otherwise, Merge returns a terminal iterator. 574 // 575 // If first is not the predecessor of second, Merge panics. 576 func (s *FileRangeSet) Merge(first, second FileRangeIterator) FileRangeIterator { 577 if first.NextSegment() != second { 578 panic(fmt.Sprintf("attempt to merge non-neighboring segments %v, %v", first.Range(), second.Range())) 579 } 580 return s.MergeUnchecked(first, second) 581 } 582 583 // MergeUnchecked attempts to merge two neighboring segments. If successful, 584 // MergeUnchecked returns an iterator to the merged segment, and all existing 585 // iterators are invalidated. Otherwise, MergeUnchecked returns a terminal 586 // iterator. 587 // 588 // Precondition: first is the predecessor of second: first.NextSegment() == 589 // second, first == second.PrevSegment(). 590 func (s *FileRangeSet) MergeUnchecked(first, second FileRangeIterator) FileRangeIterator { 591 if first.End() == second.Start() { 592 if mval, ok := (FileRangeSetFunctions{}).Merge(first.Range(), first.Value(), second.Range(), second.Value()); ok { 593 594 first.SetEndUnchecked(second.End()) 595 first.SetValue(mval) 596 597 return s.Remove(second).PrevSegment() 598 } 599 } 600 return FileRangeIterator{} 601 } 602 603 // MergePrev attempts to merge the given segment with its predecessor if 604 // possible, and returns an updated iterator to the extended segment. All 605 // existing iterators (including seg, but not including the returned iterator) 606 // are invalidated. 607 // 608 // MergePrev is usually used when mutating segments while iterating them in 609 // order of increasing keys, to attempt merging of each mutated segment with 610 // its previously-mutated predecessor. In such cases, merging a mutated segment 611 // with its unmutated successor would incorrectly cause the latter to be 612 // skipped. 613 func (s *FileRangeSet) MergePrev(seg FileRangeIterator) FileRangeIterator { 614 if prev := seg.PrevSegment(); prev.Ok() { 615 if mseg := s.MergeUnchecked(prev, seg); mseg.Ok() { 616 seg = mseg 617 } 618 } 619 return seg 620 } 621 622 // MergeNext attempts to merge the given segment with its successor if 623 // possible, and returns an updated iterator to the extended segment. All 624 // existing iterators (including seg, but not including the returned iterator) 625 // are invalidated. 626 // 627 // MergeNext is usually used when mutating segments while iterating them in 628 // order of decreasing keys, to attempt merging of each mutated segment with 629 // its previously-mutated successor. In such cases, merging a mutated segment 630 // with its unmutated predecessor would incorrectly cause the latter to be 631 // skipped. 632 func (s *FileRangeSet) MergeNext(seg FileRangeIterator) FileRangeIterator { 633 if next := seg.NextSegment(); next.Ok() { 634 if mseg := s.MergeUnchecked(seg, next); mseg.Ok() { 635 seg = mseg 636 } 637 } 638 return seg 639 } 640 641 // Unisolate attempts to merge the given segment with its predecessor and 642 // successor if possible, and returns an updated iterator to the extended 643 // segment. All existing iterators (including seg, but not including the 644 // returned iterator) are invalidated. 645 // 646 // Unisolate is usually used in conjunction with Isolate when mutating part of 647 // a single segment in a way that may affect its mergeability. For the reasons 648 // described by MergePrev and MergeNext, it is usually incorrect to use the 649 // return value of Unisolate in a loop variable. 650 func (s *FileRangeSet) Unisolate(seg FileRangeIterator) FileRangeIterator { 651 if prev := seg.PrevSegment(); prev.Ok() { 652 if mseg := s.MergeUnchecked(prev, seg); mseg.Ok() { 653 seg = mseg 654 } 655 } 656 if next := seg.NextSegment(); next.Ok() { 657 if mseg := s.MergeUnchecked(seg, next); mseg.Ok() { 658 seg = mseg 659 } 660 } 661 return seg 662 } 663 664 // MergeAll merges all mergeable adjacent segments in the set. All existing 665 // iterators are invalidated. 666 func (s *FileRangeSet) MergeAll() { 667 seg := s.FirstSegment() 668 if !seg.Ok() { 669 return 670 } 671 next := seg.NextSegment() 672 for next.Ok() { 673 if mseg := s.MergeUnchecked(seg, next); mseg.Ok() { 674 seg, next = mseg, mseg.NextSegment() 675 } else { 676 seg, next = next, next.NextSegment() 677 } 678 } 679 } 680 681 // MergeInsideRange attempts to merge all adjacent segments that contain a key 682 // in the specific range. All existing iterators are invalidated. 683 // 684 // MergeInsideRange only makes sense after mutating the set in a way that may 685 // change the mergeability of modified segments; callers should prefer to use 686 // MergePrev or MergeNext during the mutating loop instead (depending on the 687 // direction of iteration), in order to avoid a redundant search. 688 func (s *FileRangeSet) MergeInsideRange(r __generics_imported0.MappableRange) { 689 seg := s.LowerBoundSegment(r.Start) 690 if !seg.Ok() { 691 return 692 } 693 next := seg.NextSegment() 694 for next.Ok() && next.Start() < r.End { 695 if mseg := s.MergeUnchecked(seg, next); mseg.Ok() { 696 seg, next = mseg, mseg.NextSegment() 697 } else { 698 seg, next = next, next.NextSegment() 699 } 700 } 701 } 702 703 // MergeOutsideRange attempts to merge the segment containing r.Start with its 704 // predecessor, and the segment containing r.End-1 with its successor. 705 // 706 // MergeOutsideRange only makes sense after mutating the set in a way that may 707 // change the mergeability of modified segments; callers should prefer to use 708 // MergePrev or MergeNext during the mutating loop instead (depending on the 709 // direction of iteration), in order to avoid two redundant searches. 710 func (s *FileRangeSet) MergeOutsideRange(r __generics_imported0.MappableRange) { 711 first := s.FindSegment(r.Start) 712 if first.Ok() { 713 if prev := first.PrevSegment(); prev.Ok() { 714 s.Merge(prev, first) 715 } 716 } 717 last := s.FindSegment(r.End - 1) 718 if last.Ok() { 719 if next := last.NextSegment(); next.Ok() { 720 s.Merge(last, next) 721 } 722 } 723 } 724 725 // Split splits the given segment at the given key and returns iterators to the 726 // two resulting segments. All existing iterators (including seg, but not 727 // including the returned iterators) are invalidated. 728 // 729 // If the segment cannot be split at split (because split is at the start or 730 // end of the segment's range, so splitting would produce a segment with zero 731 // length, or because split falls outside the segment's range altogether), 732 // Split panics. 733 func (s *FileRangeSet) Split(seg FileRangeIterator, split uint64) (FileRangeIterator, FileRangeIterator) { 734 if !seg.Range().CanSplitAt(split) { 735 panic(fmt.Sprintf("can't split %v at %v", seg.Range(), split)) 736 } 737 return s.SplitUnchecked(seg, split) 738 } 739 740 // SplitUnchecked splits the given segment at the given key and returns 741 // iterators to the two resulting segments. All existing iterators (including 742 // seg, but not including the returned iterators) are invalidated. 743 // 744 // Preconditions: seg.Start() < key < seg.End(). 745 func (s *FileRangeSet) SplitUnchecked(seg FileRangeIterator, split uint64) (FileRangeIterator, FileRangeIterator) { 746 val1, val2 := (FileRangeSetFunctions{}).Split(seg.Range(), seg.Value(), split) 747 end2 := seg.End() 748 seg.SetEndUnchecked(split) 749 seg.SetValue(val1) 750 seg2 := s.InsertWithoutMergingUnchecked(seg.NextGap(), __generics_imported0.MappableRange{split, end2}, val2) 751 752 return seg2.PrevSegment(), seg2 753 } 754 755 // SplitBefore ensures that the given segment's start is at least start by 756 // splitting at start if necessary, and returns an updated iterator to the 757 // bounded segment. All existing iterators (including seg, but not including 758 // the returned iterator) are invalidated. 759 // 760 // SplitBefore is usually when mutating segments in a range. In such cases, 761 // when iterating segments in order of increasing keys, the first segment may 762 // extend beyond the start of the range to be mutated, and needs to be 763 // SplitBefore to ensure that only the part of the segment within the range is 764 // mutated. When iterating segments in order of decreasing keys, SplitBefore 765 // and SplitAfter; i.e. SplitBefore needs to be invoked on each segment, while 766 // SplitAfter only needs to be invoked on the first. 767 // 768 // Preconditions: start < seg.End(). 769 func (s *FileRangeSet) SplitBefore(seg FileRangeIterator, start uint64) FileRangeIterator { 770 if seg.Range().CanSplitAt(start) { 771 _, seg = s.SplitUnchecked(seg, start) 772 } 773 return seg 774 } 775 776 // SplitAfter ensures that the given segment's end is at most end by splitting 777 // at end if necessary, and returns an updated iterator to the bounded segment. 778 // All existing iterators (including seg, but not including the returned 779 // iterator) are invalidated. 780 // 781 // SplitAfter is usually used when mutating segments in a range. In such cases, 782 // when iterating segments in order of increasing keys, each iterated segment 783 // may extend beyond the end of the range to be mutated, and needs to be 784 // SplitAfter to ensure that only the part of the segment within the range is 785 // mutated. When iterating segments in order of decreasing keys, SplitBefore 786 // and SplitAfter exchange roles; i.e. SplitBefore needs to be invoked on each 787 // segment, while SplitAfter only needs to be invoked on the first. 788 // 789 // Preconditions: seg.Start() < end. 790 func (s *FileRangeSet) SplitAfter(seg FileRangeIterator, end uint64) FileRangeIterator { 791 if seg.Range().CanSplitAt(end) { 792 seg, _ = s.SplitUnchecked(seg, end) 793 } 794 return seg 795 } 796 797 // Isolate ensures that the given segment's range is a subset of r by splitting 798 // at r.Start and r.End if necessary, and returns an updated iterator to the 799 // bounded segment. All existing iterators (including seg, but not including 800 // the returned iterators) are invalidated. 801 // 802 // Isolate is usually used when mutating part of a single segment, or when 803 // mutating segments in a range where the first segment is not necessarily 804 // split, making use of SplitBefore/SplitAfter complex. 805 // 806 // Preconditions: seg.Range().Overlaps(r). 807 func (s *FileRangeSet) Isolate(seg FileRangeIterator, r __generics_imported0.MappableRange) FileRangeIterator { 808 if seg.Range().CanSplitAt(r.Start) { 809 _, seg = s.SplitUnchecked(seg, r.Start) 810 } 811 if seg.Range().CanSplitAt(r.End) { 812 seg, _ = s.SplitUnchecked(seg, r.End) 813 } 814 return seg 815 } 816 817 // LowerBoundSegmentSplitBefore combines LowerBoundSegment and SplitBefore. 818 // 819 // LowerBoundSegmentSplitBefore is usually used when mutating segments in a 820 // range while iterating them in order of increasing keys. In such cases, 821 // LowerBoundSegmentSplitBefore provides an iterator to the first segment to be 822 // mutated, suitable as the initial value for a loop variable. 823 func (s *FileRangeSet) LowerBoundSegmentSplitBefore(min uint64) FileRangeIterator { 824 seg := s.LowerBoundSegment(min) 825 if seg.Ok() { 826 seg = s.SplitBefore(seg, min) 827 } 828 return seg 829 } 830 831 // UpperBoundSegmentSplitAfter combines UpperBoundSegment and SplitAfter. 832 // 833 // UpperBoundSegmentSplitAfter is usually used when mutating segments in a 834 // range while iterating them in order of decreasing keys. In such cases, 835 // UpperBoundSegmentSplitAfter provides an iterator to the first segment to be 836 // mutated, suitable as the initial value for a loop variable. 837 func (s *FileRangeSet) UpperBoundSegmentSplitAfter(max uint64) FileRangeIterator { 838 seg := s.UpperBoundSegment(max) 839 if seg.Ok() { 840 seg = s.SplitAfter(seg, max) 841 } 842 return seg 843 } 844 845 // VisitRange applies the function f to all segments intersecting the range r, 846 // in order of ascending keys. Segments will not be split, so f may be called 847 // on segments lying partially outside r. Non-empty gaps between segments are 848 // skipped. If a call to f returns false, VisitRange stops iteration 849 // immediately. 850 // 851 // N.B. f must not invalidate iterators into s. 852 func (s *FileRangeSet) VisitRange(r __generics_imported0.MappableRange, f func(seg FileRangeIterator) bool) { 853 for seg := s.LowerBoundSegment(r.Start); seg.Ok() && seg.Start() < r.End; seg = seg.NextSegment() { 854 if !f(seg) { 855 return 856 } 857 } 858 } 859 860 // VisitFullRange is equivalent to VisitRange, except that if any key in r that 861 // is visited before f returns false does not correspond to a segment, 862 // VisitFullRange panics. 863 func (s *FileRangeSet) VisitFullRange(r __generics_imported0.MappableRange, f func(seg FileRangeIterator) bool) { 864 pos := r.Start 865 seg := s.FindSegment(r.Start) 866 for { 867 if !seg.Ok() { 868 panic(fmt.Sprintf("missing segment at %v", pos)) 869 } 870 if !f(seg) { 871 return 872 } 873 pos = seg.End() 874 if r.End <= pos { 875 return 876 } 877 seg, _ = seg.NextNonEmpty() 878 } 879 } 880 881 // MutateRange applies the function f to all segments intersecting the range r, 882 // in order of ascending keys. Segments that lie partially outside r are split 883 // before f is called, such that f only observes segments entirely within r. 884 // Iterated segments are merged again after f is called. Non-empty gaps between 885 // segments are skipped. If a call to f returns false, MutateRange stops 886 // iteration immediately. 887 // 888 // MutateRange invalidates all existing iterators. 889 // 890 // N.B. f must not invalidate iterators into s. 891 func (s *FileRangeSet) MutateRange(r __generics_imported0.MappableRange, f func(seg FileRangeIterator) bool) { 892 seg := s.LowerBoundSegmentSplitBefore(r.Start) 893 for seg.Ok() && seg.Start() < r.End { 894 seg = s.SplitAfter(seg, r.End) 895 cont := f(seg) 896 seg = s.MergePrev(seg) 897 if !cont { 898 s.MergeNext(seg) 899 return 900 } 901 seg = seg.NextSegment() 902 } 903 if seg.Ok() { 904 s.MergePrev(seg) 905 } 906 } 907 908 // MutateFullRange is equivalent to MutateRange, except that if any key in r 909 // that is visited before f returns false does not correspond to a segment, 910 // MutateFullRange panics. 911 func (s *FileRangeSet) MutateFullRange(r __generics_imported0.MappableRange, f func(seg FileRangeIterator) bool) { 912 seg := s.FindSegment(r.Start) 913 if !seg.Ok() { 914 panic(fmt.Sprintf("missing segment at %v", r.Start)) 915 } 916 seg = s.SplitBefore(seg, r.Start) 917 for { 918 seg = s.SplitAfter(seg, r.End) 919 cont := f(seg) 920 end := seg.End() 921 seg = s.MergePrev(seg) 922 if !cont || r.End <= end { 923 s.MergeNext(seg) 924 return 925 } 926 seg = seg.NextSegment() 927 if !seg.Ok() || seg.Start() != end { 928 panic(fmt.Sprintf("missing segment at %v", end)) 929 } 930 } 931 } 932 933 // +stateify savable 934 type FileRangenode struct { 935 // An internal binary tree node looks like: 936 // 937 // K 938 // / \ 939 // Cl Cr 940 // 941 // where all keys in the subtree rooted by Cl (the left subtree) are less 942 // than K (the key of the parent node), and all keys in the subtree rooted 943 // by Cr (the right subtree) are greater than K. 944 // 945 // An internal B-tree node's indexes work out to look like: 946 // 947 // K0 K1 K2 ... Kn-1 948 // / \/ \/ \ ... / \ 949 // C0 C1 C2 C3 ... Cn-1 Cn 950 // 951 // where n is nrSegments. 952 nrSegments int 953 954 // parent is a pointer to this node's parent. If this node is root, parent 955 // is nil. 956 parent *FileRangenode 957 958 // parentIndex is the index of this node in parent.children. 959 parentIndex int 960 961 // Flag for internal nodes that is technically redundant with "children[0] 962 // != nil", but is stored in the first cache line. "hasChildren" rather 963 // than "isLeaf" because false must be the correct value for an empty root. 964 hasChildren bool 965 966 // The longest gap within this node. If the node is a leaf, it's simply the 967 // maximum gap among all the (nrSegments+1) gaps formed by its nrSegments keys 968 // including the 0th and nrSegments-th gap possibly shared with its upper-level 969 // nodes; if it's a non-leaf node, it's the max of all children's maxGap. 970 maxGap FileRangedynamicGap 971 972 // Nodes store keys and values in separate arrays to maximize locality in 973 // the common case (scanning keys for lookup). 974 keys [FileRangemaxDegree - 1]__generics_imported0.MappableRange 975 values [FileRangemaxDegree - 1]uint64 976 children [FileRangemaxDegree]*FileRangenode 977 } 978 979 // firstSegment returns the first segment in the subtree rooted by n. 980 // 981 // Preconditions: n.nrSegments != 0. 982 func (n *FileRangenode) firstSegment() FileRangeIterator { 983 for n.hasChildren { 984 n = n.children[0] 985 } 986 return FileRangeIterator{n, 0} 987 } 988 989 // lastSegment returns the last segment in the subtree rooted by n. 990 // 991 // Preconditions: n.nrSegments != 0. 992 func (n *FileRangenode) lastSegment() FileRangeIterator { 993 for n.hasChildren { 994 n = n.children[n.nrSegments] 995 } 996 return FileRangeIterator{n, n.nrSegments - 1} 997 } 998 999 func (n *FileRangenode) prevSibling() *FileRangenode { 1000 if n.parent == nil || n.parentIndex == 0 { 1001 return nil 1002 } 1003 return n.parent.children[n.parentIndex-1] 1004 } 1005 1006 func (n *FileRangenode) nextSibling() *FileRangenode { 1007 if n.parent == nil || n.parentIndex == n.parent.nrSegments { 1008 return nil 1009 } 1010 return n.parent.children[n.parentIndex+1] 1011 } 1012 1013 // rebalanceBeforeInsert splits n and its ancestors if they are full, as 1014 // required for insertion, and returns an updated iterator to the position 1015 // represented by gap. 1016 func (n *FileRangenode) rebalanceBeforeInsert(gap FileRangeGapIterator) FileRangeGapIterator { 1017 if n.nrSegments < FileRangemaxDegree-1 { 1018 return gap 1019 } 1020 if n.parent != nil { 1021 gap = n.parent.rebalanceBeforeInsert(gap) 1022 } 1023 if n.parent == nil { 1024 1025 left := &FileRangenode{ 1026 nrSegments: FileRangeminDegree - 1, 1027 parent: n, 1028 parentIndex: 0, 1029 hasChildren: n.hasChildren, 1030 } 1031 right := &FileRangenode{ 1032 nrSegments: FileRangeminDegree - 1, 1033 parent: n, 1034 parentIndex: 1, 1035 hasChildren: n.hasChildren, 1036 } 1037 copy(left.keys[:FileRangeminDegree-1], n.keys[:FileRangeminDegree-1]) 1038 copy(left.values[:FileRangeminDegree-1], n.values[:FileRangeminDegree-1]) 1039 copy(right.keys[:FileRangeminDegree-1], n.keys[FileRangeminDegree:]) 1040 copy(right.values[:FileRangeminDegree-1], n.values[FileRangeminDegree:]) 1041 n.keys[0], n.values[0] = n.keys[FileRangeminDegree-1], n.values[FileRangeminDegree-1] 1042 FileRangezeroValueSlice(n.values[1:]) 1043 if n.hasChildren { 1044 copy(left.children[:FileRangeminDegree], n.children[:FileRangeminDegree]) 1045 copy(right.children[:FileRangeminDegree], n.children[FileRangeminDegree:]) 1046 FileRangezeroNodeSlice(n.children[2:]) 1047 for i := 0; i < FileRangeminDegree; i++ { 1048 left.children[i].parent = left 1049 left.children[i].parentIndex = i 1050 right.children[i].parent = right 1051 right.children[i].parentIndex = i 1052 } 1053 } 1054 n.nrSegments = 1 1055 n.hasChildren = true 1056 n.children[0] = left 1057 n.children[1] = right 1058 1059 if FileRangetrackGaps != 0 { 1060 left.updateMaxGapLocal() 1061 right.updateMaxGapLocal() 1062 } 1063 if gap.node != n { 1064 return gap 1065 } 1066 if gap.index < FileRangeminDegree { 1067 return FileRangeGapIterator{left, gap.index} 1068 } 1069 return FileRangeGapIterator{right, gap.index - FileRangeminDegree} 1070 } 1071 1072 copy(n.parent.keys[n.parentIndex+1:], n.parent.keys[n.parentIndex:n.parent.nrSegments]) 1073 copy(n.parent.values[n.parentIndex+1:], n.parent.values[n.parentIndex:n.parent.nrSegments]) 1074 n.parent.keys[n.parentIndex], n.parent.values[n.parentIndex] = n.keys[FileRangeminDegree-1], n.values[FileRangeminDegree-1] 1075 copy(n.parent.children[n.parentIndex+2:], n.parent.children[n.parentIndex+1:n.parent.nrSegments+1]) 1076 for i := n.parentIndex + 2; i < n.parent.nrSegments+2; i++ { 1077 n.parent.children[i].parentIndex = i 1078 } 1079 sibling := &FileRangenode{ 1080 nrSegments: FileRangeminDegree - 1, 1081 parent: n.parent, 1082 parentIndex: n.parentIndex + 1, 1083 hasChildren: n.hasChildren, 1084 } 1085 n.parent.children[n.parentIndex+1] = sibling 1086 n.parent.nrSegments++ 1087 copy(sibling.keys[:FileRangeminDegree-1], n.keys[FileRangeminDegree:]) 1088 copy(sibling.values[:FileRangeminDegree-1], n.values[FileRangeminDegree:]) 1089 FileRangezeroValueSlice(n.values[FileRangeminDegree-1:]) 1090 if n.hasChildren { 1091 copy(sibling.children[:FileRangeminDegree], n.children[FileRangeminDegree:]) 1092 FileRangezeroNodeSlice(n.children[FileRangeminDegree:]) 1093 for i := 0; i < FileRangeminDegree; i++ { 1094 sibling.children[i].parent = sibling 1095 sibling.children[i].parentIndex = i 1096 } 1097 } 1098 n.nrSegments = FileRangeminDegree - 1 1099 1100 if FileRangetrackGaps != 0 { 1101 n.updateMaxGapLocal() 1102 sibling.updateMaxGapLocal() 1103 } 1104 1105 if gap.node != n { 1106 return gap 1107 } 1108 if gap.index < FileRangeminDegree { 1109 return gap 1110 } 1111 return FileRangeGapIterator{sibling, gap.index - FileRangeminDegree} 1112 } 1113 1114 // rebalanceAfterRemove "unsplits" n and its ancestors if they are deficient 1115 // (contain fewer segments than required by B-tree invariants), as required for 1116 // removal, and returns an updated iterator to the position represented by gap. 1117 // 1118 // Precondition: n is the only node in the tree that may currently violate a 1119 // B-tree invariant. 1120 func (n *FileRangenode) rebalanceAfterRemove(gap FileRangeGapIterator) FileRangeGapIterator { 1121 for { 1122 if n.nrSegments >= FileRangeminDegree-1 { 1123 return gap 1124 } 1125 if n.parent == nil { 1126 1127 return gap 1128 } 1129 1130 if sibling := n.prevSibling(); sibling != nil && sibling.nrSegments >= FileRangeminDegree { 1131 copy(n.keys[1:], n.keys[:n.nrSegments]) 1132 copy(n.values[1:], n.values[:n.nrSegments]) 1133 n.keys[0] = n.parent.keys[n.parentIndex-1] 1134 n.values[0] = n.parent.values[n.parentIndex-1] 1135 n.parent.keys[n.parentIndex-1] = sibling.keys[sibling.nrSegments-1] 1136 n.parent.values[n.parentIndex-1] = sibling.values[sibling.nrSegments-1] 1137 FileRangeSetFunctions{}.ClearValue(&sibling.values[sibling.nrSegments-1]) 1138 if n.hasChildren { 1139 copy(n.children[1:], n.children[:n.nrSegments+1]) 1140 n.children[0] = sibling.children[sibling.nrSegments] 1141 sibling.children[sibling.nrSegments] = nil 1142 n.children[0].parent = n 1143 n.children[0].parentIndex = 0 1144 for i := 1; i < n.nrSegments+2; i++ { 1145 n.children[i].parentIndex = i 1146 } 1147 } 1148 n.nrSegments++ 1149 sibling.nrSegments-- 1150 1151 if FileRangetrackGaps != 0 { 1152 n.updateMaxGapLocal() 1153 sibling.updateMaxGapLocal() 1154 } 1155 if gap.node == sibling && gap.index == sibling.nrSegments { 1156 return FileRangeGapIterator{n, 0} 1157 } 1158 if gap.node == n { 1159 return FileRangeGapIterator{n, gap.index + 1} 1160 } 1161 return gap 1162 } 1163 if sibling := n.nextSibling(); sibling != nil && sibling.nrSegments >= FileRangeminDegree { 1164 n.keys[n.nrSegments] = n.parent.keys[n.parentIndex] 1165 n.values[n.nrSegments] = n.parent.values[n.parentIndex] 1166 n.parent.keys[n.parentIndex] = sibling.keys[0] 1167 n.parent.values[n.parentIndex] = sibling.values[0] 1168 copy(sibling.keys[:sibling.nrSegments-1], sibling.keys[1:]) 1169 copy(sibling.values[:sibling.nrSegments-1], sibling.values[1:]) 1170 FileRangeSetFunctions{}.ClearValue(&sibling.values[sibling.nrSegments-1]) 1171 if n.hasChildren { 1172 n.children[n.nrSegments+1] = sibling.children[0] 1173 copy(sibling.children[:sibling.nrSegments], sibling.children[1:]) 1174 sibling.children[sibling.nrSegments] = nil 1175 n.children[n.nrSegments+1].parent = n 1176 n.children[n.nrSegments+1].parentIndex = n.nrSegments + 1 1177 for i := 0; i < sibling.nrSegments; i++ { 1178 sibling.children[i].parentIndex = i 1179 } 1180 } 1181 n.nrSegments++ 1182 sibling.nrSegments-- 1183 1184 if FileRangetrackGaps != 0 { 1185 n.updateMaxGapLocal() 1186 sibling.updateMaxGapLocal() 1187 } 1188 if gap.node == sibling { 1189 if gap.index == 0 { 1190 return FileRangeGapIterator{n, n.nrSegments} 1191 } 1192 return FileRangeGapIterator{sibling, gap.index - 1} 1193 } 1194 return gap 1195 } 1196 1197 p := n.parent 1198 if p.nrSegments == 1 { 1199 1200 left, right := p.children[0], p.children[1] 1201 p.nrSegments = left.nrSegments + right.nrSegments + 1 1202 p.hasChildren = left.hasChildren 1203 p.keys[left.nrSegments] = p.keys[0] 1204 p.values[left.nrSegments] = p.values[0] 1205 copy(p.keys[:left.nrSegments], left.keys[:left.nrSegments]) 1206 copy(p.values[:left.nrSegments], left.values[:left.nrSegments]) 1207 copy(p.keys[left.nrSegments+1:], right.keys[:right.nrSegments]) 1208 copy(p.values[left.nrSegments+1:], right.values[:right.nrSegments]) 1209 if left.hasChildren { 1210 copy(p.children[:left.nrSegments+1], left.children[:left.nrSegments+1]) 1211 copy(p.children[left.nrSegments+1:], right.children[:right.nrSegments+1]) 1212 for i := 0; i < p.nrSegments+1; i++ { 1213 p.children[i].parent = p 1214 p.children[i].parentIndex = i 1215 } 1216 } else { 1217 p.children[0] = nil 1218 p.children[1] = nil 1219 } 1220 1221 if gap.node == left { 1222 return FileRangeGapIterator{p, gap.index} 1223 } 1224 if gap.node == right { 1225 return FileRangeGapIterator{p, gap.index + left.nrSegments + 1} 1226 } 1227 return gap 1228 } 1229 // Merge n and either sibling, along with the segment separating the 1230 // two, into whichever of the two nodes comes first. This is the 1231 // reverse of the non-root splitting case in 1232 // node.rebalanceBeforeInsert. 1233 var left, right *FileRangenode 1234 if n.parentIndex > 0 { 1235 left = n.prevSibling() 1236 right = n 1237 } else { 1238 left = n 1239 right = n.nextSibling() 1240 } 1241 1242 if gap.node == right { 1243 gap = FileRangeGapIterator{left, gap.index + left.nrSegments + 1} 1244 } 1245 left.keys[left.nrSegments] = p.keys[left.parentIndex] 1246 left.values[left.nrSegments] = p.values[left.parentIndex] 1247 copy(left.keys[left.nrSegments+1:], right.keys[:right.nrSegments]) 1248 copy(left.values[left.nrSegments+1:], right.values[:right.nrSegments]) 1249 if left.hasChildren { 1250 copy(left.children[left.nrSegments+1:], right.children[:right.nrSegments+1]) 1251 for i := left.nrSegments + 1; i < left.nrSegments+right.nrSegments+2; i++ { 1252 left.children[i].parent = left 1253 left.children[i].parentIndex = i 1254 } 1255 } 1256 left.nrSegments += right.nrSegments + 1 1257 copy(p.keys[left.parentIndex:], p.keys[left.parentIndex+1:p.nrSegments]) 1258 copy(p.values[left.parentIndex:], p.values[left.parentIndex+1:p.nrSegments]) 1259 FileRangeSetFunctions{}.ClearValue(&p.values[p.nrSegments-1]) 1260 copy(p.children[left.parentIndex+1:], p.children[left.parentIndex+2:p.nrSegments+1]) 1261 for i := 0; i < p.nrSegments; i++ { 1262 p.children[i].parentIndex = i 1263 } 1264 p.children[p.nrSegments] = nil 1265 p.nrSegments-- 1266 1267 if FileRangetrackGaps != 0 { 1268 left.updateMaxGapLocal() 1269 } 1270 1271 n = p 1272 } 1273 } 1274 1275 // updateMaxGapLeaf updates maxGap bottom-up from the calling leaf until no 1276 // necessary update. 1277 // 1278 // Preconditions: n must be a leaf node, trackGaps must be 1. 1279 func (n *FileRangenode) updateMaxGapLeaf() { 1280 if n.hasChildren { 1281 panic(fmt.Sprintf("updateMaxGapLeaf should always be called on leaf node: %v", n)) 1282 } 1283 max := n.calculateMaxGapLeaf() 1284 if max == n.maxGap.Get() { 1285 1286 return 1287 } 1288 oldMax := n.maxGap.Get() 1289 n.maxGap.Set(max) 1290 if max > oldMax { 1291 1292 for p := n.parent; p != nil; p = p.parent { 1293 if p.maxGap.Get() >= max { 1294 1295 break 1296 } 1297 1298 p.maxGap.Set(max) 1299 } 1300 return 1301 } 1302 1303 for p := n.parent; p != nil; p = p.parent { 1304 if p.maxGap.Get() > oldMax { 1305 1306 break 1307 } 1308 1309 parentNewMax := p.calculateMaxGapInternal() 1310 if p.maxGap.Get() == parentNewMax { 1311 1312 break 1313 } 1314 1315 p.maxGap.Set(parentNewMax) 1316 } 1317 } 1318 1319 // updateMaxGapLocal updates maxGap of the calling node solely with no 1320 // propagation to ancestor nodes. 1321 // 1322 // Precondition: trackGaps must be 1. 1323 func (n *FileRangenode) updateMaxGapLocal() { 1324 if !n.hasChildren { 1325 1326 n.maxGap.Set(n.calculateMaxGapLeaf()) 1327 } else { 1328 1329 n.maxGap.Set(n.calculateMaxGapInternal()) 1330 } 1331 } 1332 1333 // calculateMaxGapLeaf iterates the gaps within a leaf node and calculate the 1334 // max. 1335 // 1336 // Preconditions: n must be a leaf node. 1337 func (n *FileRangenode) calculateMaxGapLeaf() uint64 { 1338 max := FileRangeGapIterator{n, 0}.Range().Length() 1339 for i := 1; i <= n.nrSegments; i++ { 1340 if current := (FileRangeGapIterator{n, i}).Range().Length(); current > max { 1341 max = current 1342 } 1343 } 1344 return max 1345 } 1346 1347 // calculateMaxGapInternal iterates children's maxGap within an internal node n 1348 // and calculate the max. 1349 // 1350 // Preconditions: n must be a non-leaf node. 1351 func (n *FileRangenode) calculateMaxGapInternal() uint64 { 1352 max := n.children[0].maxGap.Get() 1353 for i := 1; i <= n.nrSegments; i++ { 1354 if current := n.children[i].maxGap.Get(); current > max { 1355 max = current 1356 } 1357 } 1358 return max 1359 } 1360 1361 // searchFirstLargeEnoughGap returns the first gap having at least minSize length 1362 // in the subtree rooted by n. If not found, return a terminal gap iterator. 1363 func (n *FileRangenode) searchFirstLargeEnoughGap(minSize uint64) FileRangeGapIterator { 1364 if n.maxGap.Get() < minSize { 1365 return FileRangeGapIterator{} 1366 } 1367 if n.hasChildren { 1368 for i := 0; i <= n.nrSegments; i++ { 1369 if largeEnoughGap := n.children[i].searchFirstLargeEnoughGap(minSize); largeEnoughGap.Ok() { 1370 return largeEnoughGap 1371 } 1372 } 1373 } else { 1374 for i := 0; i <= n.nrSegments; i++ { 1375 currentGap := FileRangeGapIterator{n, i} 1376 if currentGap.Range().Length() >= minSize { 1377 return currentGap 1378 } 1379 } 1380 } 1381 panic(fmt.Sprintf("invalid maxGap in %v", n)) 1382 } 1383 1384 // searchLastLargeEnoughGap returns the last gap having at least minSize length 1385 // in the subtree rooted by n. If not found, return a terminal gap iterator. 1386 func (n *FileRangenode) searchLastLargeEnoughGap(minSize uint64) FileRangeGapIterator { 1387 if n.maxGap.Get() < minSize { 1388 return FileRangeGapIterator{} 1389 } 1390 if n.hasChildren { 1391 for i := n.nrSegments; i >= 0; i-- { 1392 if largeEnoughGap := n.children[i].searchLastLargeEnoughGap(minSize); largeEnoughGap.Ok() { 1393 return largeEnoughGap 1394 } 1395 } 1396 } else { 1397 for i := n.nrSegments; i >= 0; i-- { 1398 currentGap := FileRangeGapIterator{n, i} 1399 if currentGap.Range().Length() >= minSize { 1400 return currentGap 1401 } 1402 } 1403 } 1404 panic(fmt.Sprintf("invalid maxGap in %v", n)) 1405 } 1406 1407 // A Iterator is conceptually one of: 1408 // 1409 // - A pointer to a segment in a set; or 1410 // 1411 // - A terminal iterator, which is a sentinel indicating that the end of 1412 // iteration has been reached. 1413 // 1414 // Iterators are copyable values and are meaningfully equality-comparable. The 1415 // zero value of Iterator is a terminal iterator. 1416 // 1417 // Unless otherwise specified, any mutation of a set invalidates all existing 1418 // iterators into the set. 1419 type FileRangeIterator struct { 1420 // node is the node containing the iterated segment. If the iterator is 1421 // terminal, node is nil. 1422 node *FileRangenode 1423 1424 // index is the index of the segment in node.keys/values. 1425 index int 1426 } 1427 1428 // Ok returns true if the iterator is not terminal. All other methods are only 1429 // valid for non-terminal iterators. 1430 func (seg FileRangeIterator) Ok() bool { 1431 return seg.node != nil 1432 } 1433 1434 // Range returns the iterated segment's range key. 1435 func (seg FileRangeIterator) Range() __generics_imported0.MappableRange { 1436 return seg.node.keys[seg.index] 1437 } 1438 1439 // Start is equivalent to Range().Start, but should be preferred if only the 1440 // start of the range is needed. 1441 func (seg FileRangeIterator) Start() uint64 { 1442 return seg.node.keys[seg.index].Start 1443 } 1444 1445 // End is equivalent to Range().End, but should be preferred if only the end of 1446 // the range is needed. 1447 func (seg FileRangeIterator) End() uint64 { 1448 return seg.node.keys[seg.index].End 1449 } 1450 1451 // SetRangeUnchecked mutates the iterated segment's range key. This operation 1452 // does not invalidate any iterators. 1453 // 1454 // Preconditions: 1455 // - r.Length() > 0. 1456 // - The new range must not overlap an existing one: 1457 // - If seg.NextSegment().Ok(), then r.end <= seg.NextSegment().Start(). 1458 // - If seg.PrevSegment().Ok(), then r.start >= seg.PrevSegment().End(). 1459 func (seg FileRangeIterator) SetRangeUnchecked(r __generics_imported0.MappableRange) { 1460 seg.node.keys[seg.index] = r 1461 } 1462 1463 // SetRange mutates the iterated segment's range key. If the new range would 1464 // cause the iterated segment to overlap another segment, or if the new range 1465 // is invalid, SetRange panics. This operation does not invalidate any 1466 // iterators. 1467 func (seg FileRangeIterator) SetRange(r __generics_imported0.MappableRange) { 1468 if r.Length() <= 0 { 1469 panic(fmt.Sprintf("invalid segment range %v", r)) 1470 } 1471 if prev := seg.PrevSegment(); prev.Ok() && r.Start < prev.End() { 1472 panic(fmt.Sprintf("new segment range %v overlaps segment range %v", r, prev.Range())) 1473 } 1474 if next := seg.NextSegment(); next.Ok() && r.End > next.Start() { 1475 panic(fmt.Sprintf("new segment range %v overlaps segment range %v", r, next.Range())) 1476 } 1477 seg.SetRangeUnchecked(r) 1478 } 1479 1480 // SetStartUnchecked mutates the iterated segment's start. This operation does 1481 // not invalidate any iterators. 1482 // 1483 // Preconditions: The new start must be valid: 1484 // - start < seg.End() 1485 // - If seg.PrevSegment().Ok(), then start >= seg.PrevSegment().End(). 1486 func (seg FileRangeIterator) SetStartUnchecked(start uint64) { 1487 seg.node.keys[seg.index].Start = start 1488 } 1489 1490 // SetStart mutates the iterated segment's start. If the new start value would 1491 // cause the iterated segment to overlap another segment, or would result in an 1492 // invalid range, SetStart panics. This operation does not invalidate any 1493 // iterators. 1494 func (seg FileRangeIterator) SetStart(start uint64) { 1495 if start >= seg.End() { 1496 panic(fmt.Sprintf("new start %v would invalidate segment range %v", start, seg.Range())) 1497 } 1498 if prev := seg.PrevSegment(); prev.Ok() && start < prev.End() { 1499 panic(fmt.Sprintf("new start %v would cause segment range %v to overlap segment range %v", start, seg.Range(), prev.Range())) 1500 } 1501 seg.SetStartUnchecked(start) 1502 } 1503 1504 // SetEndUnchecked mutates the iterated segment's end. This operation does not 1505 // invalidate any iterators. 1506 // 1507 // Preconditions: The new end must be valid: 1508 // - end > seg.Start(). 1509 // - If seg.NextSegment().Ok(), then end <= seg.NextSegment().Start(). 1510 func (seg FileRangeIterator) SetEndUnchecked(end uint64) { 1511 seg.node.keys[seg.index].End = end 1512 } 1513 1514 // SetEnd mutates the iterated segment's end. If the new end value would cause 1515 // the iterated segment to overlap another segment, or would result in an 1516 // invalid range, SetEnd panics. This operation does not invalidate any 1517 // iterators. 1518 func (seg FileRangeIterator) SetEnd(end uint64) { 1519 if end <= seg.Start() { 1520 panic(fmt.Sprintf("new end %v would invalidate segment range %v", end, seg.Range())) 1521 } 1522 if next := seg.NextSegment(); next.Ok() && end > next.Start() { 1523 panic(fmt.Sprintf("new end %v would cause segment range %v to overlap segment range %v", end, seg.Range(), next.Range())) 1524 } 1525 seg.SetEndUnchecked(end) 1526 } 1527 1528 // Value returns a copy of the iterated segment's value. 1529 func (seg FileRangeIterator) Value() uint64 { 1530 return seg.node.values[seg.index] 1531 } 1532 1533 // ValuePtr returns a pointer to the iterated segment's value. The pointer is 1534 // invalidated if the iterator is invalidated. This operation does not 1535 // invalidate any iterators. 1536 func (seg FileRangeIterator) ValuePtr() *uint64 { 1537 return &seg.node.values[seg.index] 1538 } 1539 1540 // SetValue mutates the iterated segment's value. This operation does not 1541 // invalidate any iterators. 1542 func (seg FileRangeIterator) SetValue(val uint64) { 1543 seg.node.values[seg.index] = val 1544 } 1545 1546 // PrevSegment returns the iterated segment's predecessor. If there is no 1547 // preceding segment, PrevSegment returns a terminal iterator. 1548 func (seg FileRangeIterator) PrevSegment() FileRangeIterator { 1549 if seg.node.hasChildren { 1550 return seg.node.children[seg.index].lastSegment() 1551 } 1552 if seg.index > 0 { 1553 return FileRangeIterator{seg.node, seg.index - 1} 1554 } 1555 if seg.node.parent == nil { 1556 return FileRangeIterator{} 1557 } 1558 return FileRangesegmentBeforePosition(seg.node.parent, seg.node.parentIndex) 1559 } 1560 1561 // NextSegment returns the iterated segment's successor. If there is no 1562 // succeeding segment, NextSegment returns a terminal iterator. 1563 func (seg FileRangeIterator) NextSegment() FileRangeIterator { 1564 if seg.node.hasChildren { 1565 return seg.node.children[seg.index+1].firstSegment() 1566 } 1567 if seg.index < seg.node.nrSegments-1 { 1568 return FileRangeIterator{seg.node, seg.index + 1} 1569 } 1570 if seg.node.parent == nil { 1571 return FileRangeIterator{} 1572 } 1573 return FileRangesegmentAfterPosition(seg.node.parent, seg.node.parentIndex) 1574 } 1575 1576 // PrevGap returns the gap immediately before the iterated segment. 1577 func (seg FileRangeIterator) PrevGap() FileRangeGapIterator { 1578 if seg.node.hasChildren { 1579 1580 return seg.node.children[seg.index].lastSegment().NextGap() 1581 } 1582 return FileRangeGapIterator{seg.node, seg.index} 1583 } 1584 1585 // NextGap returns the gap immediately after the iterated segment. 1586 func (seg FileRangeIterator) NextGap() FileRangeGapIterator { 1587 if seg.node.hasChildren { 1588 return seg.node.children[seg.index+1].firstSegment().PrevGap() 1589 } 1590 return FileRangeGapIterator{seg.node, seg.index + 1} 1591 } 1592 1593 // PrevNonEmpty returns the iterated segment's predecessor if it is adjacent, 1594 // or the gap before the iterated segment otherwise. If seg.Start() == 1595 // Functions.MinKey(), PrevNonEmpty will return two terminal iterators. 1596 // Otherwise, exactly one of the iterators returned by PrevNonEmpty will be 1597 // non-terminal. 1598 func (seg FileRangeIterator) PrevNonEmpty() (FileRangeIterator, FileRangeGapIterator) { 1599 if prev := seg.PrevSegment(); prev.Ok() && prev.End() == seg.Start() { 1600 return prev, FileRangeGapIterator{} 1601 } 1602 return FileRangeIterator{}, seg.PrevGap() 1603 } 1604 1605 // NextNonEmpty returns the iterated segment's successor if it is adjacent, or 1606 // the gap after the iterated segment otherwise. If seg.End() == 1607 // Functions.MaxKey(), NextNonEmpty will return two terminal iterators. 1608 // Otherwise, exactly one of the iterators returned by NextNonEmpty will be 1609 // non-terminal. 1610 func (seg FileRangeIterator) NextNonEmpty() (FileRangeIterator, FileRangeGapIterator) { 1611 if next := seg.NextSegment(); next.Ok() && next.Start() == seg.End() { 1612 return next, FileRangeGapIterator{} 1613 } 1614 return FileRangeIterator{}, seg.NextGap() 1615 } 1616 1617 // A GapIterator is conceptually one of: 1618 // 1619 // - A pointer to a position between two segments, before the first segment, or 1620 // after the last segment in a set, called a *gap*; or 1621 // 1622 // - A terminal iterator, which is a sentinel indicating that the end of 1623 // iteration has been reached. 1624 // 1625 // Note that the gap between two adjacent segments exists (iterators to it are 1626 // non-terminal), but has a length of zero. GapIterator.IsEmpty returns true 1627 // for such gaps. An empty set contains a single gap, spanning the entire range 1628 // of the set's keys. 1629 // 1630 // GapIterators are copyable values and are meaningfully equality-comparable. 1631 // The zero value of GapIterator is a terminal iterator. 1632 // 1633 // Unless otherwise specified, any mutation of a set invalidates all existing 1634 // iterators into the set. 1635 type FileRangeGapIterator struct { 1636 // The representation of a GapIterator is identical to that of an Iterator, 1637 // except that index corresponds to positions between segments in the same 1638 // way as for node.children (see comment for node.nrSegments). 1639 node *FileRangenode 1640 index int 1641 } 1642 1643 // Ok returns true if the iterator is not terminal. All other methods are only 1644 // valid for non-terminal iterators. 1645 func (gap FileRangeGapIterator) Ok() bool { 1646 return gap.node != nil 1647 } 1648 1649 // Range returns the range spanned by the iterated gap. 1650 func (gap FileRangeGapIterator) Range() __generics_imported0.MappableRange { 1651 return __generics_imported0.MappableRange{gap.Start(), gap.End()} 1652 } 1653 1654 // Start is equivalent to Range().Start, but should be preferred if only the 1655 // start of the range is needed. 1656 func (gap FileRangeGapIterator) Start() uint64 { 1657 if ps := gap.PrevSegment(); ps.Ok() { 1658 return ps.End() 1659 } 1660 return FileRangeSetFunctions{}.MinKey() 1661 } 1662 1663 // End is equivalent to Range().End, but should be preferred if only the end of 1664 // the range is needed. 1665 func (gap FileRangeGapIterator) End() uint64 { 1666 if ns := gap.NextSegment(); ns.Ok() { 1667 return ns.Start() 1668 } 1669 return FileRangeSetFunctions{}.MaxKey() 1670 } 1671 1672 // IsEmpty returns true if the iterated gap is empty (that is, the "gap" is 1673 // between two adjacent segments.) 1674 func (gap FileRangeGapIterator) IsEmpty() bool { 1675 return gap.Range().Length() == 0 1676 } 1677 1678 // PrevSegment returns the segment immediately before the iterated gap. If no 1679 // such segment exists, PrevSegment returns a terminal iterator. 1680 func (gap FileRangeGapIterator) PrevSegment() FileRangeIterator { 1681 return FileRangesegmentBeforePosition(gap.node, gap.index) 1682 } 1683 1684 // NextSegment returns the segment immediately after the iterated gap. If no 1685 // such segment exists, NextSegment returns a terminal iterator. 1686 func (gap FileRangeGapIterator) NextSegment() FileRangeIterator { 1687 return FileRangesegmentAfterPosition(gap.node, gap.index) 1688 } 1689 1690 // PrevGap returns the iterated gap's predecessor. If no such gap exists, 1691 // PrevGap returns a terminal iterator. 1692 func (gap FileRangeGapIterator) PrevGap() FileRangeGapIterator { 1693 seg := gap.PrevSegment() 1694 if !seg.Ok() { 1695 return FileRangeGapIterator{} 1696 } 1697 return seg.PrevGap() 1698 } 1699 1700 // NextGap returns the iterated gap's successor. If no such gap exists, NextGap 1701 // returns a terminal iterator. 1702 func (gap FileRangeGapIterator) NextGap() FileRangeGapIterator { 1703 seg := gap.NextSegment() 1704 if !seg.Ok() { 1705 return FileRangeGapIterator{} 1706 } 1707 return seg.NextGap() 1708 } 1709 1710 // NextLargeEnoughGap returns the iterated gap's first next gap with larger 1711 // length than minSize. If not found, return a terminal gap iterator (does NOT 1712 // include this gap itself). 1713 // 1714 // Precondition: trackGaps must be 1. 1715 func (gap FileRangeGapIterator) NextLargeEnoughGap(minSize uint64) FileRangeGapIterator { 1716 if FileRangetrackGaps != 1 { 1717 panic("set is not tracking gaps") 1718 } 1719 if gap.node != nil && gap.node.hasChildren && gap.index == gap.node.nrSegments { 1720 1721 gap.node = gap.NextSegment().node 1722 gap.index = 0 1723 return gap.nextLargeEnoughGapHelper(minSize) 1724 } 1725 return gap.nextLargeEnoughGapHelper(minSize) 1726 } 1727 1728 // nextLargeEnoughGapHelper is the helper function used by NextLargeEnoughGap 1729 // to do the real recursions. 1730 // 1731 // Preconditions: gap is NOT the trailing gap of a non-leaf node. 1732 func (gap FileRangeGapIterator) nextLargeEnoughGapHelper(minSize uint64) FileRangeGapIterator { 1733 for { 1734 1735 for gap.node != nil && 1736 (gap.node.maxGap.Get() < minSize || (!gap.node.hasChildren && gap.index == gap.node.nrSegments)) { 1737 gap.node, gap.index = gap.node.parent, gap.node.parentIndex 1738 } 1739 1740 if gap.node == nil { 1741 return FileRangeGapIterator{} 1742 } 1743 1744 gap.index++ 1745 for gap.index <= gap.node.nrSegments { 1746 if gap.node.hasChildren { 1747 if largeEnoughGap := gap.node.children[gap.index].searchFirstLargeEnoughGap(minSize); largeEnoughGap.Ok() { 1748 return largeEnoughGap 1749 } 1750 } else { 1751 if gap.Range().Length() >= minSize { 1752 return gap 1753 } 1754 } 1755 gap.index++ 1756 } 1757 gap.node, gap.index = gap.node.parent, gap.node.parentIndex 1758 if gap.node != nil && gap.index == gap.node.nrSegments { 1759 1760 gap.node, gap.index = gap.node.parent, gap.node.parentIndex 1761 } 1762 } 1763 } 1764 1765 // PrevLargeEnoughGap returns the iterated gap's first prev gap with larger or 1766 // equal length than minSize. If not found, return a terminal gap iterator 1767 // (does NOT include this gap itself). 1768 // 1769 // Precondition: trackGaps must be 1. 1770 func (gap FileRangeGapIterator) PrevLargeEnoughGap(minSize uint64) FileRangeGapIterator { 1771 if FileRangetrackGaps != 1 { 1772 panic("set is not tracking gaps") 1773 } 1774 if gap.node != nil && gap.node.hasChildren && gap.index == 0 { 1775 1776 gap.node = gap.PrevSegment().node 1777 gap.index = gap.node.nrSegments 1778 return gap.prevLargeEnoughGapHelper(minSize) 1779 } 1780 return gap.prevLargeEnoughGapHelper(minSize) 1781 } 1782 1783 // prevLargeEnoughGapHelper is the helper function used by PrevLargeEnoughGap 1784 // to do the real recursions. 1785 // 1786 // Preconditions: gap is NOT the first gap of a non-leaf node. 1787 func (gap FileRangeGapIterator) prevLargeEnoughGapHelper(minSize uint64) FileRangeGapIterator { 1788 for { 1789 1790 for gap.node != nil && 1791 (gap.node.maxGap.Get() < minSize || (!gap.node.hasChildren && gap.index == 0)) { 1792 gap.node, gap.index = gap.node.parent, gap.node.parentIndex 1793 } 1794 1795 if gap.node == nil { 1796 return FileRangeGapIterator{} 1797 } 1798 1799 gap.index-- 1800 for gap.index >= 0 { 1801 if gap.node.hasChildren { 1802 if largeEnoughGap := gap.node.children[gap.index].searchLastLargeEnoughGap(minSize); largeEnoughGap.Ok() { 1803 return largeEnoughGap 1804 } 1805 } else { 1806 if gap.Range().Length() >= minSize { 1807 return gap 1808 } 1809 } 1810 gap.index-- 1811 } 1812 gap.node, gap.index = gap.node.parent, gap.node.parentIndex 1813 if gap.node != nil && gap.index == 0 { 1814 1815 gap.node, gap.index = gap.node.parent, gap.node.parentIndex 1816 } 1817 } 1818 } 1819 1820 // segmentBeforePosition returns the predecessor segment of the position given 1821 // by n.children[i], which may or may not contain a child. If no such segment 1822 // exists, segmentBeforePosition returns a terminal iterator. 1823 func FileRangesegmentBeforePosition(n *FileRangenode, i int) FileRangeIterator { 1824 for i == 0 { 1825 if n.parent == nil { 1826 return FileRangeIterator{} 1827 } 1828 n, i = n.parent, n.parentIndex 1829 } 1830 return FileRangeIterator{n, i - 1} 1831 } 1832 1833 // segmentAfterPosition returns the successor segment of the position given by 1834 // n.children[i], which may or may not contain a child. If no such segment 1835 // exists, segmentAfterPosition returns a terminal iterator. 1836 func FileRangesegmentAfterPosition(n *FileRangenode, i int) FileRangeIterator { 1837 for i == n.nrSegments { 1838 if n.parent == nil { 1839 return FileRangeIterator{} 1840 } 1841 n, i = n.parent, n.parentIndex 1842 } 1843 return FileRangeIterator{n, i} 1844 } 1845 1846 func FileRangezeroValueSlice(slice []uint64) { 1847 1848 for i := range slice { 1849 FileRangeSetFunctions{}.ClearValue(&slice[i]) 1850 } 1851 } 1852 1853 func FileRangezeroNodeSlice(slice []*FileRangenode) { 1854 for i := range slice { 1855 slice[i] = nil 1856 } 1857 } 1858 1859 // String stringifies a Set for debugging. 1860 func (s *FileRangeSet) String() string { 1861 return s.root.String() 1862 } 1863 1864 // String stringifies a node (and all of its children) for debugging. 1865 func (n *FileRangenode) String() string { 1866 var buf bytes.Buffer 1867 n.writeDebugString(&buf, "") 1868 return buf.String() 1869 } 1870 1871 func (n *FileRangenode) writeDebugString(buf *bytes.Buffer, prefix string) { 1872 if n.hasChildren != (n.nrSegments > 0 && n.children[0] != nil) { 1873 buf.WriteString(prefix) 1874 buf.WriteString(fmt.Sprintf("WARNING: inconsistent value of hasChildren: got %v, want %v\n", n.hasChildren, !n.hasChildren)) 1875 } 1876 for i := 0; i < n.nrSegments; i++ { 1877 if child := n.children[i]; child != nil { 1878 cprefix := fmt.Sprintf("%s- % 3d ", prefix, i) 1879 if child.parent != n || child.parentIndex != i { 1880 buf.WriteString(cprefix) 1881 buf.WriteString(fmt.Sprintf("WARNING: inconsistent linkage to parent: got (%p, %d), want (%p, %d)\n", child.parent, child.parentIndex, n, i)) 1882 } 1883 child.writeDebugString(buf, fmt.Sprintf("%s- % 3d ", prefix, i)) 1884 } 1885 buf.WriteString(prefix) 1886 if n.hasChildren { 1887 if FileRangetrackGaps != 0 { 1888 buf.WriteString(fmt.Sprintf("- % 3d: %v => %v, maxGap: %d\n", i, n.keys[i], n.values[i], n.maxGap.Get())) 1889 } else { 1890 buf.WriteString(fmt.Sprintf("- % 3d: %v => %v\n", i, n.keys[i], n.values[i])) 1891 } 1892 } else { 1893 buf.WriteString(fmt.Sprintf("- % 3d: %v => %v\n", i, n.keys[i], n.values[i])) 1894 } 1895 } 1896 if child := n.children[n.nrSegments]; child != nil { 1897 child.writeDebugString(buf, fmt.Sprintf("%s- % 3d ", prefix, n.nrSegments)) 1898 } 1899 } 1900 1901 // FlatSegment represents a segment as a single object. FlatSegment is used as 1902 // an intermediate representation for save/restore and tests. 1903 // 1904 // +stateify savable 1905 type FileRangeFlatSegment struct { 1906 Start uint64 1907 End uint64 1908 Value uint64 1909 } 1910 1911 // ExportSlice returns a copy of all segments in the given set, in ascending 1912 // key order. 1913 func (s *FileRangeSet) ExportSlice() []FileRangeFlatSegment { 1914 var fs []FileRangeFlatSegment 1915 for seg := s.FirstSegment(); seg.Ok(); seg = seg.NextSegment() { 1916 fs = append(fs, FileRangeFlatSegment{ 1917 Start: seg.Start(), 1918 End: seg.End(), 1919 Value: seg.Value(), 1920 }) 1921 } 1922 return fs 1923 } 1924 1925 // ImportSlice initializes the given set from the given slice. 1926 // 1927 // Preconditions: 1928 // - s must be empty. 1929 // - fs must represent a valid set (the segments in fs must have valid 1930 // lengths that do not overlap). 1931 // - The segments in fs must be sorted in ascending key order. 1932 func (s *FileRangeSet) ImportSlice(fs []FileRangeFlatSegment) error { 1933 if !s.IsEmpty() { 1934 return fmt.Errorf("cannot import into non-empty set %v", s) 1935 } 1936 gap := s.FirstGap() 1937 for i := range fs { 1938 f := &fs[i] 1939 r := __generics_imported0.MappableRange{f.Start, f.End} 1940 if !gap.Range().IsSupersetOf(r) { 1941 return fmt.Errorf("segment overlaps a preceding segment or is incorrectly sorted: %v => %v", r, f.Value) 1942 } 1943 gap = s.InsertWithoutMerging(gap, r, f.Value).NextGap() 1944 } 1945 return nil 1946 } 1947 1948 // segmentTestCheck returns an error if s is incorrectly sorted, does not 1949 // contain exactly expectedSegments segments, or contains a segment which 1950 // fails the passed check. 1951 // 1952 // This should be used only for testing, and has been added to this package for 1953 // templating convenience. 1954 func (s *FileRangeSet) segmentTestCheck(expectedSegments int, segFunc func(int, __generics_imported0.MappableRange, uint64) error) error { 1955 havePrev := false 1956 prev := uint64(0) 1957 nrSegments := 0 1958 for seg := s.FirstSegment(); seg.Ok(); seg = seg.NextSegment() { 1959 next := seg.Start() 1960 if havePrev && prev >= next { 1961 return fmt.Errorf("incorrect order: key %d (segment %d) >= key %d (segment %d)", prev, nrSegments-1, next, nrSegments) 1962 } 1963 if segFunc != nil { 1964 if err := segFunc(nrSegments, seg.Range(), seg.Value()); err != nil { 1965 return err 1966 } 1967 } 1968 prev = next 1969 havePrev = true 1970 nrSegments++ 1971 } 1972 if nrSegments != expectedSegments { 1973 return fmt.Errorf("incorrect number of segments: got %d, wanted %d", nrSegments, expectedSegments) 1974 } 1975 return nil 1976 } 1977 1978 // countSegments counts the number of segments in the set. 1979 // 1980 // Similar to Check, this should only be used for testing. 1981 func (s *FileRangeSet) countSegments() (segments int) { 1982 for seg := s.FirstSegment(); seg.Ok(); seg = seg.NextSegment() { 1983 segments++ 1984 } 1985 return segments 1986 } 1987 func (s *FileRangeSet) saveRoot() []FileRangeFlatSegment { 1988 fs := s.ExportSlice() 1989 1990 fs = fs[:len(fs):len(fs)] 1991 return fs 1992 } 1993 1994 func (s *FileRangeSet) loadRoot(_ context.Context, fs []FileRangeFlatSegment) { 1995 if err := s.ImportSlice(fs); err != nil { 1996 panic(err) 1997 } 1998 }