@@ -7,6 +7,7 @@ package pebble
77import (
88 "bytes"
99 "context"
10+ "fmt"
1011 "io"
1112 "math/rand/v2"
1213 "sync"
@@ -1296,6 +1297,17 @@ func (i *Iterator) SeekGE(key []byte) bool {
12961297// guarantees it will surface any range keys with bounds overlapping the
12971298// keyspace [key, limit).
12981299func (i * Iterator ) SeekGEWithLimit (key []byte , limit []byte ) IterValidityState {
1300+ if treesteps .Enabled && treesteps .IsRecording (i ) {
1301+ var op * treesteps.Op
1302+ if limit == nil {
1303+ op = treesteps .StartOpf (i , "SeekGE(%q)" , key )
1304+ } else {
1305+ op = treesteps .StartOpf (i , "SeekGEWithLimit(%q, %q)" , key , limit )
1306+ }
1307+ defer func () {
1308+ op .Finishf ("= %s" , iterValidityString (i .iterValidityState , i .key ))
1309+ }()
1310+ }
12991311 if i .rangeKey != nil {
13001312 // NB: Check Valid() before clearing requiresReposition.
13011313 i .rangeKey .prevPosHadRangeKey = i .rangeKey .hasRangeKey && i .Valid ()
@@ -1445,6 +1457,12 @@ func (i *Iterator) SeekGEWithLimit(key []byte, limit []byte) IterValidityState {
14451457// ImmediateSuccessor method. For example, a SeekPrefixGE("a@9") call with the
14461458// prefix "a" will truncate range key bounds to [a,ImmediateSuccessor(a)].
14471459func (i * Iterator ) SeekPrefixGE (key []byte ) bool {
1460+ if treesteps .Enabled && treesteps .IsRecording (i ) {
1461+ op := treesteps .StartOpf (i , "SeekPrefixGE(%q)" , key )
1462+ defer func () {
1463+ op .Finishf ("= %s" , iterValidityString (i .iterValidityState , i .key ))
1464+ }()
1465+ }
14481466 if i .rangeKey != nil {
14491467 // NB: Check Valid() before clearing requiresReposition.
14501468 i .rangeKey .prevPosHadRangeKey = i .rangeKey .hasRangeKey && i .Valid ()
@@ -1575,6 +1593,17 @@ func (i *Iterator) SeekLT(key []byte) bool {
15751593// guarantees it will surface any range keys with bounds overlapping the
15761594// keyspace up to limit.
15771595func (i * Iterator ) SeekLTWithLimit (key []byte , limit []byte ) IterValidityState {
1596+ if treesteps .Enabled && treesteps .IsRecording (i ) {
1597+ var op * treesteps.Op
1598+ if limit == nil {
1599+ op = treesteps .StartOpf (i , "SeekLT(%q)" , key )
1600+ } else {
1601+ op = treesteps .StartOpf (i , "SeekLTWithLimit(%q, %q)" , key , limit )
1602+ }
1603+ defer func () {
1604+ op .Finishf ("= %s" , iterValidityString (i .iterValidityState , i .key ))
1605+ }()
1606+ }
15781607 if i .rangeKey != nil {
15791608 // NB: Check Valid() before clearing requiresReposition.
15801609 i .rangeKey .prevPosHadRangeKey = i .rangeKey .hasRangeKey && i .Valid ()
@@ -1657,6 +1686,12 @@ func (i *Iterator) SeekLTWithLimit(key []byte, limit []byte) IterValidityState {
16571686// First moves the iterator the first key/value pair. Returns true if the
16581687// iterator is pointing at a valid entry and false otherwise.
16591688func (i * Iterator ) First () bool {
1689+ if treesteps .Enabled && treesteps .IsRecording (i ) {
1690+ op := treesteps .StartOpf (i , "First()" )
1691+ defer func () {
1692+ op .Finishf ("= %s" , iterValidityString (i .iterValidityState , i .key ))
1693+ }()
1694+ }
16601695 if i .rangeKey != nil {
16611696 // NB: Check Valid() before clearing requiresReposition.
16621697 i .rangeKey .prevPosHadRangeKey = i .rangeKey .hasRangeKey && i .Valid ()
@@ -1693,6 +1728,12 @@ func (i *Iterator) First() bool {
16931728// Last moves the iterator the last key/value pair. Returns true if the
16941729// iterator is pointing at a valid entry and false otherwise.
16951730func (i * Iterator ) Last () bool {
1731+ if treesteps .Enabled && treesteps .IsRecording (i ) {
1732+ op := treesteps .StartOpf (i , "Last()" )
1733+ defer func () {
1734+ op .Finishf ("= %s" , iterValidityString (i .iterValidityState , i .key ))
1735+ }()
1736+ }
16961737 if i .rangeKey != nil {
16971738 // NB: Check Valid() before clearing requiresReposition.
16981739 i .rangeKey .prevPosHadRangeKey = i .rangeKey .hasRangeKey && i .Valid ()
@@ -1757,6 +1798,12 @@ func (i *Iterator) NextWithLimit(limit []byte) IterValidityState {
17571798// upper-bound that is a versioned MVCC key (see the comment for
17581799// Comparer.Split). It returns an error in this case.
17591800func (i * Iterator ) NextPrefix () bool {
1801+ if treesteps .Enabled && treesteps .IsRecording (i ) {
1802+ op := treesteps .StartOpf (i , "NextPrefix()" )
1803+ defer func () {
1804+ op .Finishf ("= %s" , iterValidityString (i .iterValidityState , i .key ))
1805+ }()
1806+ }
17601807 if i .nextPrefixNotPermittedByUpperBound {
17611808 i .lastPositioningOp = unknownLastPositionOp
17621809 i .requiresReposition = false
@@ -1924,6 +1971,17 @@ func (i *Iterator) internalNextPrefix(currKeyPrefixLen int) {
19241971}
19251972
19261973func (i * Iterator ) nextWithLimit (limit []byte ) IterValidityState {
1974+ if treesteps .Enabled && treesteps .IsRecording (i ) {
1975+ var op * treesteps.Op
1976+ if limit == nil {
1977+ op = treesteps .StartOpf (i , "Next()" )
1978+ } else {
1979+ op = treesteps .StartOpf (i , "NextWithLimit(%q)" , limit )
1980+ }
1981+ defer func () {
1982+ op .Finishf ("= %s" , iterValidityString (i .iterValidityState , i .key ))
1983+ }()
1984+ }
19271985 i .stats .ForwardStepCount [InterfaceCall ]++
19281986 if i .hasPrefix {
19291987 if limit != nil {
@@ -2034,6 +2092,17 @@ func (i *Iterator) Prev() bool {
20342092// guarantees it will surface any range keys with bounds overlapping the
20352093// keyspace up to limit.
20362094func (i * Iterator ) PrevWithLimit (limit []byte ) IterValidityState {
2095+ if treesteps .Enabled && treesteps .IsRecording (i ) {
2096+ var op * treesteps.Op
2097+ if limit == nil {
2098+ op = treesteps .StartOpf (i , "Prev()" )
2099+ } else {
2100+ op = treesteps .StartOpf (i , "PrevWithLimit(%q)" , limit )
2101+ }
2102+ defer func () {
2103+ op .Finishf ("= %s" , iterValidityString (i .iterValidityState , i .key ))
2104+ }()
2105+ }
20372106 i .stats .ReverseStepCount [InterfaceCall ]++
20382107 if i .err != nil {
20392108 return i .iterValidityState
@@ -3156,9 +3225,31 @@ var _ treesteps.Node = (*Iterator)(nil)
31563225// TreeStepsNode implements the treesteps.Node interface.
31573226func (i * Iterator ) TreeStepsNode () treesteps.NodeInfo {
31583227 info := treesteps .NodeInfof (i , "pebble.Iterator" )
3228+ switch i .iterValidityState {
3229+ case IterExhausted :
3230+ info .AddPropf ("exhausted" , "" )
3231+ case IterAtLimit :
3232+ info .AddPropf ("at limit" , "" )
3233+ case IterValid :
3234+ info .AddPropf ("at" , "%s" , i .key )
3235+ }
31593236 info .AddChildren (i .iter )
31603237 if i .pointIter != i .iter {
31613238 info .AddChildren (i .pointIter )
31623239 }
31633240 return info
31643241}
3242+
3243+ // iterValidityString returns a string representation of the iterator's validity state.
3244+ func iterValidityString (state IterValidityState , key []byte ) string {
3245+ switch state {
3246+ case IterExhausted :
3247+ return "exhausted"
3248+ case IterAtLimit :
3249+ return "at limit"
3250+ case IterValid :
3251+ return fmt .Sprintf ("%q" , key )
3252+ default :
3253+ return "unknown"
3254+ }
3255+ }
0 commit comments