diff --git a/iterator.go b/iterator.go index b60c352e3f..6bfa85eb9c 100644 --- a/iterator.go +++ b/iterator.go @@ -15,6 +15,7 @@ import ( "github.com/cockroachdb/pebble/internal/fastrand" "github.com/cockroachdb/pebble/internal/invariants" "github.com/cockroachdb/pebble/internal/manifest" + "github.com/cockroachdb/redact" ) // iterPos describes the state of the internal iterator, in terms of whether it is @@ -49,7 +50,8 @@ const readBytesPeriod uint64 = 1 << 16 var errReversePrefixIteration = errors.New("pebble: unsupported reverse prefix iteration") -// IteratorMetrics holds per-iterator metrics. +// IteratorMetrics holds per-iterator metrics. These do not change over the +// lifetime of the iterator. type IteratorMetrics struct { // The read amplification experienced by this iterator. This is the sum of // the memtables, the L0 sublevels and the non-empty Ln levels. Higher read @@ -58,6 +60,32 @@ type IteratorMetrics struct { ReadAmp int } +// IteratorStatsKind describes the two kind of iterator stats. +type IteratorStatsKind int8 + +const ( + // InterfaceCall represents calls to Iterator. + InterfaceCall IteratorStatsKind = iota + // InternalIterCall represents calls by Iterator to its internalIterator. + InternalIterCall + // NumStatsKind is the number of kinds, and is used for array sizing. + NumStatsKind +) + +// IteratorStats contains iteration stats. +type IteratorStats struct { + // ForwardSeekCount includes SeekGE, SeekPrefixGE, First. + ForwardSeekCount [NumStatsKind]int + // ReverseSeek includes SeekLT, Last. + ReverseSeekCount [NumStatsKind]int + // ForwardStepCount includes Next. + ForwardStepCount [NumStatsKind]int + // ReverseStepCount includes Prev. + ReverseStepCount [NumStatsKind]int +} + +var _ redact.SafeFormatter = &IteratorStats{} + // Iterator iterates over a DB's key/value pairs in key order. // // An iterator must be closed after use, but it is not necessary to read an @@ -101,6 +129,7 @@ type Iterator struct { getIterAlloc *getIterAlloc prefixOrFullSeekKey []byte readSampling readSampling + stats IteratorStats // Following fields are only used in Clone. // Non-nil if this Iterator includes a Batch. @@ -257,6 +286,7 @@ func (i *Iterator) nextUserKey() { } for { i.iterKey, i.iterValue = i.iter.Next() + i.stats.ForwardStepCount[InternalIterCall]++ if done || i.iterKey == nil { break } @@ -412,6 +442,7 @@ func (i *Iterator) findPrevEntry(limit []byte) { i.iterValidityState = IterExhausted valueMerger = nil i.iterKey, i.iterValue = i.iter.Prev() + i.stats.ReverseStepCount[InternalIterCall]++ // Compare with the limit. We could optimize by only checking when // we step to the previous user key, but detecting that requires a // comparison too. Note that this position may already passed a @@ -439,6 +470,7 @@ func (i *Iterator) findPrevEntry(limit []byte) { i.value = i.valueBuf i.iterValidityState = IterValid i.iterKey, i.iterValue = i.iter.Prev() + i.stats.ReverseStepCount[InternalIterCall]++ valueMerger = nil continue @@ -468,6 +500,7 @@ func (i *Iterator) findPrevEntry(limit []byte) { } } i.iterKey, i.iterValue = i.iter.Prev() + i.stats.ReverseStepCount[InternalIterCall]++ continue default: @@ -501,6 +534,7 @@ func (i *Iterator) prevUserKey() { } for { i.iterKey, i.iterValue = i.iter.Prev() + i.stats.ReverseStepCount[InternalIterCall]++ if i.iterKey == nil { break } @@ -519,6 +553,7 @@ func (i *Iterator) mergeNext(key InternalKey, valueMerger ValueMerger) { // Loop looking for older values for this key and merging them. for { i.iterKey, i.iterValue = i.iter.Next() + i.stats.ForwardStepCount[InternalIterCall]++ if i.iterKey == nil { i.pos = iterPosNext return @@ -572,6 +607,7 @@ func (i *Iterator) SeekGEWithLimit(key []byte, limit []byte) IterValidityState { i.lastPositioningOp = unknownLastPositionOp i.err = nil // clear cached iteration error i.hasPrefix = false + i.stats.ForwardSeekCount[InterfaceCall]++ if lowerBound := i.opts.GetLowerBound(); lowerBound != nil && i.cmp(key, lowerBound) < 0 { key = lowerBound } else if upperBound := i.opts.GetUpperBound(); upperBound != nil && i.cmp(key, upperBound) > 0 { @@ -606,6 +642,7 @@ func (i *Iterator) SeekGEWithLimit(key []byte, limit []byte) IterValidityState { } if seekInternalIter { i.iterKey, i.iterValue = i.iter.SeekGE(key) + i.stats.ForwardSeekCount[InternalIterCall]++ } i.findNextEntry(limit) i.maybeSampleRead() @@ -667,6 +704,7 @@ func (i *Iterator) SeekPrefixGE(key []byte) bool { // iterator position. i.lastPositioningOp = unknownLastPositionOp i.err = nil // clear cached iteration error + i.stats.ForwardSeekCount[InterfaceCall]++ if i.split == nil { panic("pebble: split must be provided for SeekPrefixGE") @@ -728,6 +766,7 @@ func (i *Iterator) SeekPrefixGE(key []byte) bool { } i.iterKey, i.iterValue = i.iter.SeekPrefixGE(i.prefixOrFullSeekKey, key, trySeekUsingNext) + i.stats.ForwardSeekCount[InternalIterCall]++ i.findNextEntry(nil) i.maybeSampleRead() if i.Error() == nil { @@ -761,6 +800,7 @@ func (i *Iterator) SeekLTWithLimit(key []byte, limit []byte) IterValidityState { i.lastPositioningOp = unknownLastPositionOp i.err = nil // clear cached iteration error i.hasPrefix = false + i.stats.ReverseSeekCount[InterfaceCall]++ if upperBound := i.opts.GetUpperBound(); upperBound != nil && i.cmp(key, upperBound) > 0 { key = upperBound } else if lowerBound := i.opts.GetLowerBound(); lowerBound != nil && i.cmp(key, lowerBound) < 0 { @@ -797,6 +837,7 @@ func (i *Iterator) SeekLTWithLimit(key []byte, limit []byte) IterValidityState { } if seekInternalIter { i.iterKey, i.iterValue = i.iter.SeekLT(key) + i.stats.ReverseSeekCount[InternalIterCall]++ } i.findPrevEntry(limit) i.maybeSampleRead() @@ -814,10 +855,13 @@ func (i *Iterator) First() bool { i.err = nil // clear cached iteration error i.hasPrefix = false i.lastPositioningOp = unknownLastPositionOp + i.stats.ForwardSeekCount[InterfaceCall]++ if lowerBound := i.opts.GetLowerBound(); lowerBound != nil { i.iterKey, i.iterValue = i.iter.SeekGE(lowerBound) + i.stats.ForwardSeekCount[InternalIterCall]++ } else { i.iterKey, i.iterValue = i.iter.First() + i.stats.ForwardSeekCount[InternalIterCall]++ } i.findNextEntry(nil) i.maybeSampleRead() @@ -830,10 +874,13 @@ func (i *Iterator) Last() bool { i.err = nil // clear cached iteration error i.hasPrefix = false i.lastPositioningOp = unknownLastPositionOp + i.stats.ReverseSeekCount[InterfaceCall]++ if upperBound := i.opts.GetUpperBound(); upperBound != nil { i.iterKey, i.iterValue = i.iter.SeekLT(upperBound) + i.stats.ReverseSeekCount[InternalIterCall]++ } else { i.iterKey, i.iterValue = i.iter.Last() + i.stats.ReverseSeekCount[InternalIterCall]++ } i.findPrevEntry(nil) i.maybeSampleRead() @@ -848,6 +895,7 @@ func (i *Iterator) Next() bool { // NextWithLimit ... func (i *Iterator) NextWithLimit(limit []byte) IterValidityState { + i.stats.ForwardStepCount[InterfaceCall]++ if limit != nil && i.hasPrefix { i.err = errors.New("cannot use limit with prefix iteration") i.iterValidityState = IterExhausted @@ -875,8 +923,10 @@ func (i *Iterator) NextWithLimit(limit []byte) IterValidityState { // the first key. if lowerBound := i.opts.GetLowerBound(); lowerBound != nil { i.iterKey, i.iterValue = i.iter.SeekGE(lowerBound) + i.stats.ForwardSeekCount[InternalIterCall]++ } else { i.iterKey, i.iterValue = i.iter.First() + i.stats.ForwardSeekCount[InternalIterCall]++ } case iterPosCurReversePaused: // Switching directions. @@ -899,8 +949,10 @@ func (i *Iterator) NextWithLimit(limit []byte) IterValidityState { // the first key. if lowerBound := i.opts.GetLowerBound(); lowerBound != nil { i.iterKey, i.iterValue = i.iter.SeekGE(lowerBound) + i.stats.ForwardSeekCount[InternalIterCall]++ } else { i.iterKey, i.iterValue = i.iter.First() + i.stats.ForwardSeekCount[InternalIterCall]++ } } else { i.nextUserKey() @@ -922,6 +974,7 @@ func (i *Iterator) Prev() bool { // PrevWithLimit ... func (i *Iterator) PrevWithLimit(limit []byte) IterValidityState { + i.stats.ReverseStepCount[InterfaceCall]++ if i.err != nil { return i.iterValidityState } @@ -958,8 +1011,10 @@ func (i *Iterator) PrevWithLimit(limit []byte) IterValidityState { // the last key. if upperBound := i.opts.GetUpperBound(); upperBound != nil { i.iterKey, i.iterValue = i.iter.SeekLT(upperBound) + i.stats.ReverseSeekCount[InternalIterCall]++ } else { i.iterKey, i.iterValue = i.iter.Last() + i.stats.ReverseSeekCount[InternalIterCall]++ } } else { i.prevUserKey() @@ -1115,6 +1170,16 @@ func (i *Iterator) Metrics() IteratorMetrics { return m } +// ResetStats resets the stats to 0. +func (i *Iterator) ResetStats() { + i.stats = IteratorStats{} +} + +// Stats returns the current stats. +func (i *Iterator) Stats() IteratorStats { + return i.stats +} + // Clone creates a new Iterator over the same underlying data, i.e., over the // same {batch, memtables, sstables}). It starts with the same IterOptions but // is not positioned. Note that IterOptions is not deep-copied, so the @@ -1161,3 +1226,20 @@ func (i *Iterator) Clone() (*Iterator, error) { } return finishInitializingIter(buf), nil } + +func (stats *IteratorStats) String() string { + return redact.StringWithoutMarkers(stats) +} + +// SafeFormat implements the redact.SafeFormatter interface. +func (stats *IteratorStats) SafeFormat(s redact.SafePrinter, verb rune) { + for i := range stats.ForwardStepCount { + switch IteratorStatsKind(i) { + case InterfaceCall: s.SafeString("(interface (dir, seek, step): ") + case InternalIterCall: s.SafeString(", (internal (dir, seek, step): ") + } + s.Printf("(fwd, %d, %d), (rev, %d, %d))", + redact.Safe(stats.ForwardSeekCount[i]), redact.Safe(stats.ForwardStepCount[i]), + redact.Safe(stats.ReverseSeekCount[i]), redact.Safe(stats.ReverseStepCount[i])) + } +} diff --git a/iterator_test.go b/iterator_test.go index 797ac38f5d..3a4616d7e2 100644 --- a/iterator_test.go +++ b/iterator_test.go @@ -473,7 +473,9 @@ func TestIterator(t *testing.T) { } iter := newIter(uint64(seqNum), opts) - return runIterCmd(d, iter, true) + iterOutput := runIterCmd(d, iter, true) + stats := iter.Stats() + return fmt.Sprintf("%sstats: %s\n", iterOutput, stats.String()) default: return fmt.Sprintf("unknown command: %s", d.Cmd) diff --git a/testdata/iterator b/testdata/iterator index c268768beb..f9f331f12d 100644 --- a/testdata/iterator +++ b/testdata/iterator @@ -10,16 +10,19 @@ prev a:b . a:b +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 1, 1)) iter seq=2 seek-ge b ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=2 seek-lt a ---- . +stats: (interface (dir, seek, step): (fwd, 0, 0), (rev, 1, 0)), (internal (dir, seek, step): (fwd, 0, 0), (rev, 1, 0)) define @@ -35,6 +38,7 @@ prev a:b . a:b +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 1, 1)) iter seq=3 seek-ge a @@ -44,6 +48,7 @@ prev a:c . a:c +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 1, 2)) iter seq=2 seek-prefix-ge a @@ -55,6 +60,7 @@ a:b . err=pebble: unsupported reverse prefix iteration err=pebble: unsupported reverse prefix iteration +stats: (interface (dir, seek, step): (fwd, 1, 2), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=3 seek-prefix-ge a @@ -62,6 +68,7 @@ next ---- a:c . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) define @@ -73,6 +80,7 @@ iter seq=3 seek-ge a ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) iter seq=2 seek-ge 1 @@ -80,11 +88,13 @@ next ---- a:b . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=3 seek-lt b ---- . +stats: (interface (dir, seek, step): (fwd, 0, 0), (rev, 1, 0)), (internal (dir, seek, step): (fwd, 0, 0), (rev, 1, 2)) iter seq=2 seek-lt b @@ -94,16 +104,19 @@ next a:b . a:b +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 1, 1)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 1, 1)) iter seq=3 seek-prefix-ge a ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) iter seq=2 seek-prefix-ge 1 ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) define a.DEL.2: @@ -117,31 +130,37 @@ next ---- b:c . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 3), (rev, 0, 0)) iter seq=3 seek-ge a ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) iter seq=2 seek-ge a ---- a:b +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=4 seek-prefix-ge a ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) iter seq=3 seek-prefix-ge a ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) iter seq=2 seek-prefix-ge a ---- a:b +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=2 seek-prefix-ge a @@ -149,6 +168,7 @@ seek-prefix-ge b ---- a:b . +stats: (interface (dir, seek, step): (fwd, 2, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 0)) define a.DEL.3: @@ -166,6 +186,7 @@ seek-prefix-ge c . . c:d +stats: (interface (dir, seek, step): (fwd, 3, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 3, 4), (rev, 0, 0)) iter seq=3 seek-prefix-ge a @@ -175,6 +196,7 @@ seek-prefix-ge c a:b b:c . +stats: (interface (dir, seek, step): (fwd, 3, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 3, 0), (rev, 0, 0)) define a.SET.1:a @@ -192,6 +214,7 @@ a:a b:b c:c . +stats: (interface (dir, seek, step): (fwd, 1, 3), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 3), (rev, 0, 0)) iter seq=4 seek-ge b @@ -199,16 +222,19 @@ next ---- b:b c:c +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=4 seek-ge c ---- c:c +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=4 seek-lt a ---- . +stats: (interface (dir, seek, step): (fwd, 0, 0), (rev, 1, 0)), (internal (dir, seek, step): (fwd, 0, 0), (rev, 1, 0)) iter seq=4 seek-lt b @@ -218,6 +244,7 @@ next a:a . a:a +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 1, 1)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 1, 1)) iter seq=4 seek-lt c @@ -229,6 +256,7 @@ b:b a:a . a:a +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 1, 2)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 1, 2)) iter seq=4 @@ -243,6 +271,7 @@ b:b a:a . a:a +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 1, 3)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 1, 3)) iter seq=4 seek-prefix-ge a @@ -250,6 +279,7 @@ next ---- a:a . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=4 seek-prefix-ge b @@ -257,6 +287,7 @@ next ---- b:b . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=4 @@ -265,12 +296,14 @@ next ---- c:c . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=4 seek-prefix-ge d ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=4 seek-prefix-ge a @@ -280,6 +313,7 @@ seek-prefix-ge b a:a c:c b:b +stats: (interface (dir, seek, step): (fwd, 3, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 3, 0), (rev, 0, 0)) define a.SET.b2:b @@ -294,16 +328,19 @@ prev a:b . a:b +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 1, 1)) iter seq=2 seek-ge b ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=2 seek-lt a ---- . +stats: (interface (dir, seek, step): (fwd, 0, 0), (rev, 1, 0)), (internal (dir, seek, step): (fwd, 0, 0), (rev, 1, 0)) iter seq=2 seek-lt b @@ -313,6 +350,7 @@ next a:b . a:b +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 1, 1)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 1, 1)) iter seq=2 seek-lt c @@ -322,6 +360,7 @@ next a:b . a:b +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 1, 1)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 1, 1)) iter seq=2 seek-prefix-ge a @@ -329,11 +368,13 @@ next ---- a:b . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=2 seek-prefix-ge b ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) define @@ -349,6 +390,7 @@ next ---- a:a . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=5 seek-prefix-ge a @@ -356,11 +398,13 @@ next ---- a:a . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=5 seek-prefix-ge aa ---- aa:aa +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=5 seek-prefix-ge aa @@ -368,6 +412,7 @@ next ---- aa:aa . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=5 seek-prefix-ge aa @@ -375,6 +420,7 @@ next ---- aa:aa . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=5 seek-prefix-ge aaa @@ -382,11 +428,13 @@ next ---- aaa:aaa . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=5 seek-prefix-ge aaa ---- aaa:aaa +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=5 seek-prefix-ge b @@ -394,6 +442,7 @@ next ---- b:b . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=5 seek-prefix-ge aa @@ -409,6 +458,7 @@ aaa:aaa aa:aa a:a . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 1, 4)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 1, 4)) iter seq=5 seek-prefix-ge aa @@ -424,6 +474,7 @@ aa:aa aaa:aaa b:b . +stats: (interface (dir, seek, step): (fwd, 2, 4), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 2, 4), (rev, 0, 0)) iter seq=5 seek-prefix-ge aaa @@ -437,6 +488,7 @@ aa:aa aaa:aaa b:b . +stats: (interface (dir, seek, step): (fwd, 2, 3), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 2, 3), (rev, 0, 0)) iter seq=5 seek-prefix-ge aaa @@ -448,6 +500,7 @@ aaa:aaa aaa:aaa b:b . +stats: (interface (dir, seek, step): (fwd, 2, 2), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 2, 2), (rev, 0, 0)) iter seq=5 seek-prefix-ge aaa @@ -463,6 +516,7 @@ aa:aa aaa:aaa b:b . +stats: (interface (dir, seek, step): (fwd, 1, 4), (rev, 1, 0)), (internal (dir, seek, step): (fwd, 2, 4), (rev, 1, 1)) iter seq=5 @@ -475,6 +529,7 @@ aaa:aaa aaa:aaa b:b . +stats: (interface (dir, seek, step): (fwd, 1, 2), (rev, 1, 0)), (internal (dir, seek, step): (fwd, 1, 3), (rev, 1, 1)) iter seq=4 seek-prefix-ge a @@ -486,6 +541,7 @@ a:a aa:aa aaa:aaa . +stats: (interface (dir, seek, step): (fwd, 4, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 4, 0), (rev, 0, 0)) iter seq=3 seek-prefix-ge aaa @@ -499,6 +555,7 @@ seek-prefix-ge aaa a:a aa:aa . +stats: (interface (dir, seek, step): (fwd, 5, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 5, 0), (rev, 0, 0)) define bb.DEL.2: @@ -510,6 +567,7 @@ iter seq=4 seek-prefix-ge bb ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) # NB: RANGEDEL entries are ignored. @@ -536,6 +594,7 @@ a:bcd b:ab . b:ab +stats: (interface (dir, seek, step): (fwd, 1, 2), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 1, 5), (rev, 1, 2)) iter seq=3 seek-ge a @@ -543,6 +602,7 @@ next ---- a:bc b:ab +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 4), (rev, 0, 0)) iter seq=2 seek-ge a @@ -550,6 +610,7 @@ next ---- a:b b:a +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) iter seq=4 seek-lt c @@ -561,6 +622,7 @@ b:ab a:bcd . a:bcd +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 1, 2)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 1, 5)) iter seq=3 seek-lt c @@ -568,6 +630,7 @@ prev ---- b:ab a:bc +stats: (interface (dir, seek, step): (fwd, 0, 0), (rev, 1, 1)), (internal (dir, seek, step): (fwd, 0, 0), (rev, 1, 4)) iter seq=2 seek-lt c @@ -575,6 +638,7 @@ prev ---- b:a a:b +stats: (interface (dir, seek, step): (fwd, 0, 0), (rev, 1, 1)), (internal (dir, seek, step): (fwd, 0, 0), (rev, 1, 2)) iter seq=4 seek-ge a @@ -586,6 +650,7 @@ a:bcd b:ab a:bcd b:ab +stats: (interface (dir, seek, step): (fwd, 1, 2), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 2, 10), (rev, 1, 5)) iter seq=3 seek-ge a @@ -597,6 +662,7 @@ a:bc b:ab a:bc b:ab +stats: (interface (dir, seek, step): (fwd, 1, 2), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 2, 8), (rev, 1, 4)) iter seq=2 seek-ge a @@ -608,6 +674,7 @@ a:b b:a a:b b:a +stats: (interface (dir, seek, step): (fwd, 1, 2), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 2, 4), (rev, 1, 2)) iter seq=4 seek-lt c @@ -619,6 +686,7 @@ b:ab a:bcd b:ab a:bcd +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 1, 2)), (internal (dir, seek, step): (fwd, 1, 5), (rev, 2, 10)) iter seq=3 seek-lt c @@ -630,6 +698,7 @@ b:ab a:bc b:ab a:bc +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 1, 2)), (internal (dir, seek, step): (fwd, 1, 4), (rev, 2, 8)) iter seq=2 seek-lt c @@ -641,6 +710,7 @@ b:a a:b b:a a:b +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 1, 2)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 2, 4)) iter seq=3 seek-prefix-ge a @@ -648,6 +718,7 @@ next ---- a:bc . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) iter seq=2 seek-prefix-ge a @@ -655,6 +726,7 @@ next ---- a:b . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=4 seek-prefix-ge a @@ -662,6 +734,7 @@ next ---- a:bcd . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 3), (rev, 0, 0)) iter seq=2 seek-prefix-ge a @@ -669,6 +742,7 @@ next ---- a:b . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=3 seek-prefix-ge a @@ -676,21 +750,25 @@ next ---- a:bc . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) iter seq=3 seek-prefix-ge c ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=3 seek-prefix-ge 1 ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=3 seek-prefix-ge a ---- a:bc +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) # NB: RANGEDEL entries are ignored. @@ -719,6 +797,7 @@ next a:bc . . +stats: (interface (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 4), (rev, 0, 0)) iter seq=2 seek-prefix-ge a @@ -728,6 +807,7 @@ next a:b . . +stats: (interface (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) iter seq=4 seek-prefix-ge a @@ -735,6 +815,7 @@ next ---- a:bcd . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 3), (rev, 0, 0)) iter seq=2 seek-prefix-ge a @@ -742,6 +823,7 @@ next ---- a:b . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=3 seek-prefix-ge aa @@ -749,11 +831,13 @@ next ---- aa:ab . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) iter seq=4 seek-prefix-ge aa ---- aa:ab +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) define a.SET.1:a @@ -770,6 +854,7 @@ prev a:a a:a . +stats: (interface (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)) iter seq=2 lower=b seek-ge a @@ -779,6 +864,7 @@ prev b:b b:b . +stats: (interface (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)) iter seq=2 lower=c seek-ge a @@ -788,6 +874,7 @@ prev c:c c:c . +stats: (interface (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)) iter seq=2 lower=d seek-ge a @@ -797,6 +884,7 @@ prev d:d d:d . +stats: (interface (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)) iter seq=2 lower=e seek-ge a @@ -804,6 +892,7 @@ first ---- . . +stats: (interface (dir, seek, step): (fwd, 2, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 0)) iter seq=2 upper=d seek-lt d @@ -813,6 +902,7 @@ next c:c c:c . +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 2, 0)), (internal (dir, seek, step): (fwd, 0, 2), (rev, 2, 2)) iter seq=2 upper=c seek-lt d @@ -822,6 +912,7 @@ next b:b b:b . +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 2, 0)), (internal (dir, seek, step): (fwd, 0, 2), (rev, 2, 2)) iter seq=2 upper=b seek-lt d @@ -831,6 +922,7 @@ next a:a a:a . +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 2, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 2, 2)) iter seq=2 upper=a seek-lt d @@ -838,6 +930,7 @@ last ---- . . +stats: (interface (dir, seek, step): (fwd, 0, 0), (rev, 2, 0)), (internal (dir, seek, step): (fwd, 0, 0), (rev, 2, 0)) iter seq=2 lower=b upper=c seek-ge a @@ -845,6 +938,7 @@ next ---- b:b . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=2 set-bounds lower=a @@ -856,6 +950,7 @@ prev a:a a:a . +stats: (interface (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)) iter seq=2 set-bounds lower=b @@ -867,6 +962,7 @@ prev b:b b:b . +stats: (interface (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)) iter seq=2 set-bounds lower=c @@ -878,6 +974,7 @@ prev c:c c:c . +stats: (interface (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)) iter seq=2 set-bounds lower=d @@ -889,6 +986,7 @@ prev d:d d:d . +stats: (interface (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)) iter seq=2 set-bounds lower=e @@ -898,6 +996,7 @@ first . . . +stats: (interface (dir, seek, step): (fwd, 2, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 0)) iter seq=2 set-bounds upper=d @@ -909,6 +1008,7 @@ next c:c c:c . +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 2, 0)), (internal (dir, seek, step): (fwd, 0, 2), (rev, 2, 2)) iter seq=2 set-bounds upper=c @@ -920,6 +1020,7 @@ next b:b b:b . +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 2, 0)), (internal (dir, seek, step): (fwd, 0, 2), (rev, 2, 2)) iter seq=2 set-bounds upper=b @@ -931,6 +1032,7 @@ next a:a a:a . +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 2, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 2, 2)) iter seq=2 set-bounds upper=a @@ -940,6 +1042,7 @@ last . . . +stats: (interface (dir, seek, step): (fwd, 0, 0), (rev, 2, 0)), (internal (dir, seek, step): (fwd, 0, 0), (rev, 2, 0)) iter seq=2 set-bounds lower=a @@ -951,6 +1054,7 @@ next c:c d:d . +stats: (interface (dir, seek, step): (fwd, 0, 2), (rev, 1, 0)), (internal (dir, seek, step): (fwd, 0, 3), (rev, 1, 1)) iter seq=2 set-bounds lower=b upper=c @@ -960,6 +1064,7 @@ next . b:b . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=2 set-bounds lower=b @@ -971,6 +1076,7 @@ seek-ge a b:b . b:b +stats: (interface (dir, seek, step): (fwd, 2, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 0)) iter seq=2 seek-ge a @@ -978,6 +1084,7 @@ set-bounds upper=e ---- a:a . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=2 set-bounds lower=b @@ -987,6 +1094,7 @@ set-bounds upper=e . b:b . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=2 set-bounds lower=b @@ -994,6 +1102,7 @@ first ---- . b:b +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=2 set-bounds upper=b @@ -1001,6 +1110,7 @@ first ---- . a:a +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=2 set-bounds lower=b @@ -1008,6 +1118,7 @@ last ---- . d:d +stats: (interface (dir, seek, step): (fwd, 0, 0), (rev, 1, 0)), (internal (dir, seek, step): (fwd, 0, 0), (rev, 1, 1)) iter seq=2 set-bounds upper=b @@ -1015,6 +1126,7 @@ last ---- . a:a +stats: (interface (dir, seek, step): (fwd, 0, 0), (rev, 1, 0)), (internal (dir, seek, step): (fwd, 0, 0), (rev, 1, 1)) # The prev call after "set-bounds upper=c" will assume that the iterator # is exhausted due to having stepped up to c. Which means prev should step @@ -1029,6 +1141,7 @@ d:d . . b:b +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 1, 1)), (internal (dir, seek, step): (fwd, 0, 2), (rev, 2, 2)) # The next call after "set-bounds lower=b" will assume that the iterator # is exhausted due to having stepped below b. Which means next should step @@ -1043,6 +1156,7 @@ a:a . . b:b +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)) iter seq=2 set-bounds lower=b @@ -1052,6 +1166,7 @@ next . b:b c:c +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 1, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 1, 1)) iter seq=2 set-bounds upper=d @@ -1061,6 +1176,7 @@ prev . c:c b:b +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 2)) define a.SET.1:a @@ -1077,12 +1193,14 @@ prev a:a a:a . +stats: (interface (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 1)) iter seq=2 lower=aa seek-prefix-ge a ---- err=pebble: SeekPrefixGE supplied with key outside of lower bound +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 0, 0), (rev, 0, 0)) iter seq=2 lower=a upper=aa seek-prefix-ge a @@ -1090,6 +1208,7 @@ next ---- a:a . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=2 lower=a upper=aaa seek-prefix-ge a @@ -1097,6 +1216,7 @@ next ---- a:a . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=2 lower=a upper=b seek-prefix-ge a @@ -1104,6 +1224,7 @@ next ---- a:a . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=2 lower=a upper=c seek-prefix-ge a @@ -1111,11 +1232,13 @@ next ---- a:a . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) iter seq=2 lower=a upper=aaa seek-prefix-ge aa ---- aa:aa +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) iter seq=2 lower=a upper=aaa seek-prefix-ge aa @@ -1123,6 +1246,7 @@ next ---- aa:aa . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) # NB: RANGEDEL entries are ignored. define @@ -1141,6 +1265,7 @@ next a:a b:b . +stats: (interface (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) define a.SINGLEDEL.1: @@ -1150,6 +1275,7 @@ iter seq=2 first ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)) define a.SINGLEDEL.2: @@ -1160,6 +1286,7 @@ iter seq=3 first ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) define a.SINGLEDEL.2: @@ -1170,6 +1297,7 @@ iter seq=3 first ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) define a.SINGLEDEL.2: @@ -1180,6 +1308,7 @@ iter seq=3 first ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) define a.SINGLEDEL.2: @@ -1190,6 +1319,7 @@ iter seq=3 first ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) define a.SET.2:b @@ -1202,6 +1332,7 @@ next ---- a:b . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) define a.SINGLEDEL.2: @@ -1215,6 +1346,7 @@ next ---- b:c . +stats: (interface (dir, seek, step): (fwd, 1, 1), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 3), (rev, 0, 0)) define a.SINGLEDEL.3: @@ -1226,6 +1358,7 @@ iter first ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)) define a.SINGLEDEL.3: @@ -1237,6 +1370,7 @@ iter seq=4 first ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 3), (rev, 0, 0)) define a.SINGLEDEL.4: @@ -1249,6 +1383,7 @@ iter seq=5 first ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 4), (rev, 0, 0)) define a.SINGLEDEL.4: @@ -1261,6 +1396,7 @@ iter seq=5 first ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 4), (rev, 0, 0)) define a.SINGLEDEL.4: @@ -1273,6 +1409,7 @@ iter seq=5 first ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 4), (rev, 0, 0)) define a.SINGLEDEL.3: @@ -1284,6 +1421,7 @@ iter seq=4 first ---- . +stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 2), (rev, 0, 0)) # Exercise iteration with limits, when there are no deletes. define @@ -1325,6 +1463,7 @@ a:a valid . exhausted . at-limit a:a valid +stats: (interface (dir, seek, step): (fwd, 1, 6), (rev, 1, 7)), (internal (dir, seek, step): (fwd, 3, 3), (rev, 1, 6)) # Exercise iteration with limits when we have deletes. @@ -1371,6 +1510,7 @@ d:d valid . exhausted d:d valid . exhausted +stats: (interface (dir, seek, step): (fwd, 1, 10), (rev, 0, 5)), (internal (dir, seek, step): (fwd, 3, 13), (rev, 1, 8)) iter seq=4 seek-ge-limit b d @@ -1382,6 +1522,7 @@ next-limit e . at-limit . at-limit d:d valid +stats: (interface (dir, seek, step): (fwd, 1, 2), (rev, 0, 1)), (internal (dir, seek, step): (fwd, 1, 9), (rev, 0, 5)) iter seq=4 seek-lt-limit d c @@ -1397,3 +1538,4 @@ next-limit b a:a valid . exhausted a:a valid +stats: (interface (dir, seek, step): (fwd, 0, 1), (rev, 1, 4)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 1, 5))