parseItem is a complex function because it needs to handle both forward and reverse iteration implementation. We store keys such that their versions are sorted in descending order. This makes forward iteration efficient, but revese iteration complicated. This tradeoff is better because forward itera
()
| 593 | // |
| 594 | // This function advances the iterator. |
| 595 | func (it *Iterator) parseItem() bool { |
| 596 | mi := it.iitr |
| 597 | key := mi.Key() |
| 598 | |
| 599 | setItem := func(item *Item) { |
| 600 | if it.item == nil { |
| 601 | it.item = item |
| 602 | } else { |
| 603 | it.data.push(item) |
| 604 | } |
| 605 | } |
| 606 | |
| 607 | // Skip badger keys. |
| 608 | if !it.opt.InternalAccess && bytes.HasPrefix(key, badgerPrefix) { |
| 609 | mi.Next() |
| 610 | return false |
| 611 | } |
| 612 | |
| 613 | // Skip any versions which are beyond the readTs. |
| 614 | version := y.ParseTs(key) |
| 615 | if version > it.readTs { |
| 616 | mi.Next() |
| 617 | return false |
| 618 | } |
| 619 | |
| 620 | if it.opt.AllVersions { |
| 621 | // Return deleted or expired values also, otherwise user can't figure out |
| 622 | // whether the key was deleted. |
| 623 | item := it.newItem() |
| 624 | it.fill(item) |
| 625 | setItem(item) |
| 626 | mi.Next() |
| 627 | return true |
| 628 | } |
| 629 | |
| 630 | // If iterating in forward direction, then just checking the last key against current key would |
| 631 | // be sufficient. |
| 632 | if !it.opt.Reverse { |
| 633 | if y.SameKey(it.lastKey, key) { |
| 634 | mi.Next() |
| 635 | return false |
| 636 | } |
| 637 | // Only track in forward direction. |
| 638 | // We should update lastKey as soon as we find a different key in our snapshot. |
| 639 | // Consider keys: a 5, b 7 (del), b 5. When iterating, lastKey = a. |
| 640 | // Then we see b 7, which is deleted. If we don't store lastKey = b, we'll then return b 5, |
| 641 | // which is wrong. Therefore, update lastKey here. |
| 642 | it.lastKey = y.SafeCopy(it.lastKey, mi.Key()) |
| 643 | } |
| 644 | |
| 645 | FILL: |
| 646 | // If deleted, advance and return. |
| 647 | vs := mi.Value() |
| 648 | if isDeletedOrExpired(vs.Meta, vs.ExpiresAt) { |
| 649 | mi.Next() |
| 650 | return false |
| 651 | } |
| 652 |