@@ -42,6 +42,9 @@ type mergingIterLevel struct {
4242 // positioning tombstones at lower levels which cannot possibly shadow the
4343 // current key.
4444 tombstone * keyspan.Span
45+
46+ // lastKey is used only during treesteps recordings.
47+ lastIterKey invariants.Value [string ]
4548}
4649
4750// Assert that *mergingIterLevel implements rangeDelIterSetter.
@@ -56,6 +59,17 @@ func (ml *mergingIterLevel) setRangeDelIter(iter keyspan.FragmentIterator) {
5659 ml .rangeDelIterGeneration ++
5760}
5861
62+ // updateLastIterKey updates the lastIterKey field; only used for treesteps. We
63+ // cannot use iterKV directly because it is not valid while we are updating it
64+ // (i.e. when stepping through an operation on ml.iter).
65+ func (ml * mergingIterLevel ) updateLastIterKey () {
66+ if ml .iterKV == nil {
67+ ml .lastIterKey .Set ("<nil>" )
68+ } else {
69+ ml .lastIterKey .Set (ml .iterKV .K .String ())
70+ }
71+ }
72+
5973// mergingIter provides a merged view of multiple iterators from different
6074// levels of the LSM.
6175//
@@ -328,6 +342,9 @@ func (m *mergingIter) initHeap() {
328342 for i := range m .levels {
329343 if l := & m .levels [i ]; l .iterKV != nil {
330344 m .heap .items = append (m .heap .items , mergingIterHeapItem {mergingIterLevel : l })
345+ if treesteps .Enabled && treesteps .IsRecording (m ) {
346+ l .updateLastIterKey ()
347+ }
331348 }
332349 }
333350 m .heap .init ()
@@ -433,6 +450,7 @@ func (m *mergingIter) switchToMinHeap() error {
433450 }
434451 // key >= iter-key
435452 }
453+ l .updateLastIterKey ()
436454 if l .iterKV == nil {
437455 if err := l .iter .Error (); err != nil {
438456 return err
@@ -486,6 +504,7 @@ func (m *mergingIter) switchToMaxHeap() error {
486504 }
487505 // key <= iter-key
488506 }
507+ l .updateLastIterKey ()
489508 if l .iterKV == nil {
490509 if err := l .iter .Error (); err != nil {
491510 return err
@@ -563,6 +582,9 @@ func (m *mergingIter) nextEntry(l *mergingIterLevel, succKey []byte) error {
563582 oldTopLevel --
564583 }
565584 }
585+ if treesteps .Enabled && treesteps .IsRecording (m ) {
586+ l .updateLastIterKey ()
587+ }
566588
567589 // The cached tombstones are only valid for the levels
568590 // [0,oldTopLevel]. Updated the cached tombstones for any levels in the range
@@ -775,6 +797,10 @@ func (m *mergingIter) prevEntry(l *mergingIterLevel) error {
775797 m .heap .pop ()
776798 }
777799
800+ if treesteps .Enabled && treesteps .IsRecording (m ) {
801+ l .updateLastIterKey ()
802+ }
803+
778804 // The cached tombstones are only valid for the levels
779805 // [0,oldTopLevel]. Updated the cached tombstones for any levels in the range
780806 // [oldTopLevel+1,heap[0].index].
@@ -1021,7 +1047,13 @@ func (m *mergingIter) String() string {
10211047// SeekGE implements base.InternalIterator.SeekGE. Note that SeekGE only checks
10221048// the upper bound. It is up to the caller to ensure that key is greater than
10231049// or equal to the lower bound.
1024- func (m * mergingIter ) SeekGE (key []byte , flags base.SeekGEFlags ) * base.InternalKV {
1050+ func (m * mergingIter ) SeekGE (key []byte , flags base.SeekGEFlags ) (kv * base.InternalKV ) {
1051+ if treesteps .Enabled && treesteps .IsRecording (m ) {
1052+ op := treesteps .StartOpf (m , "SeekGE(%q, %d)" , key , flags )
1053+ defer func () {
1054+ op .Finishf ("= %s" , kv .String ())
1055+ }()
1056+ }
10251057 m .prefix = nil
10261058 m .err = m .seekGE (key , 0 /* start level */ , flags )
10271059 if m .err != nil {
@@ -1039,7 +1071,13 @@ func (m *mergingIter) SeekPrefixGE(prefix, key []byte, flags base.SeekGEFlags) *
10391071// SeekPrefixGEStrict explicitly checks that the key has a matching prefix.
10401072func (m * mergingIter ) SeekPrefixGEStrict (
10411073 prefix , key []byte , flags base.SeekGEFlags ,
1042- ) * base.InternalKV {
1074+ ) (kv * base.InternalKV ) {
1075+ if treesteps .Enabled && treesteps .IsRecording (m ) {
1076+ op := treesteps .StartOpf (m , "SeekPrefixGE(%q, %q, %d)" , prefix , key , flags )
1077+ defer func () {
1078+ op .Finishf ("= %s" , kv .String ())
1079+ }()
1080+ }
10431081 m .prefix = prefix
10441082 m .err = m .seekGE (key , 0 /* start level */ , flags )
10451083 if m .err != nil {
@@ -1114,7 +1152,13 @@ func (m *mergingIter) seekLT(key []byte, level int, flags base.SeekLTFlags) erro
11141152// SeekLT implements base.InternalIterator.SeekLT. Note that SeekLT only checks
11151153// the lower bound. It is up to the caller to ensure that key is less than the
11161154// upper bound.
1117- func (m * mergingIter ) SeekLT (key []byte , flags base.SeekLTFlags ) * base.InternalKV {
1155+ func (m * mergingIter ) SeekLT (key []byte , flags base.SeekLTFlags ) (kv * base.InternalKV ) {
1156+ if treesteps .Enabled && treesteps .IsRecording (m ) {
1157+ op := treesteps .StartOpf (m , "SeekLT(%q, %d)" , key , flags )
1158+ defer func () {
1159+ op .Finishf ("= %s" , kv .String ())
1160+ }()
1161+ }
11181162 m .prefix = nil
11191163 m .err = m .seekLT (key , 0 /* start level */ , flags )
11201164 if m .err != nil {
@@ -1126,7 +1170,13 @@ func (m *mergingIter) SeekLT(key []byte, flags base.SeekLTFlags) *base.InternalK
11261170// First implements base.InternalIterator.First. Note that First only checks
11271171// the upper bound. It is up to the caller to ensure that key is greater than
11281172// or equal to the lower bound (e.g. via a call to SeekGE(lower)).
1129- func (m * mergingIter ) First () * base.InternalKV {
1173+ func (m * mergingIter ) First () (kv * base.InternalKV ) {
1174+ if treesteps .Enabled && treesteps .IsRecording (m ) {
1175+ op := treesteps .StartOpf (m , "First()" )
1176+ defer func () {
1177+ op .Finishf ("= %s" , kv .String ())
1178+ }()
1179+ }
11301180 m .err = nil // clear cached iteration error
11311181 m .prefix = nil
11321182 m .heap .items = m .heap .items [:0 ]
@@ -1148,7 +1198,13 @@ func (m *mergingIter) First() *base.InternalKV {
11481198// Last implements base.InternalIterator.Last. Note that Last only checks the
11491199// lower bound. It is up to the caller to ensure that key is less than the
11501200// upper bound (e.g. via a call to SeekLT(upper))
1151- func (m * mergingIter ) Last () * base.InternalKV {
1201+ func (m * mergingIter ) Last () (kv * base.InternalKV ) {
1202+ if treesteps .Enabled && treesteps .IsRecording (m ) {
1203+ op := treesteps .StartOpf (m , "Last()" )
1204+ defer func () {
1205+ op .Finishf ("= %s" , kv .String ())
1206+ }()
1207+ }
11521208 m .err = nil // clear cached iteration error
11531209 m .prefix = nil
11541210 for i := range m .levels {
@@ -1166,7 +1222,13 @@ func (m *mergingIter) Last() *base.InternalKV {
11661222 return m .findPrevEntry ()
11671223}
11681224
1169- func (m * mergingIter ) Next () * base.InternalKV {
1225+ func (m * mergingIter ) Next () (kv * base.InternalKV ) {
1226+ if treesteps .Enabled && treesteps .IsRecording (m ) {
1227+ op := treesteps .StartOpf (m , "Next()" )
1228+ defer func () {
1229+ op .Finishf ("= %s" , kv .String ())
1230+ }()
1231+ }
11701232 if m .err != nil {
11711233 return nil
11721234 }
@@ -1199,7 +1261,13 @@ func (m *mergingIter) Next() *base.InternalKV {
11991261 return iterKV
12001262}
12011263
1202- func (m * mergingIter ) NextPrefix (succKey []byte ) * base.InternalKV {
1264+ func (m * mergingIter ) NextPrefix (succKey []byte ) (kv * base.InternalKV ) {
1265+ if treesteps .Enabled && treesteps .IsRecording (m ) {
1266+ op := treesteps .StartOpf (m , "NextPrefix(%q)" , succKey )
1267+ defer func () {
1268+ op .Finishf ("= %s" , kv .String ())
1269+ }()
1270+ }
12031271 if m .dir != 1 {
12041272 panic ("pebble: cannot switch directions with NextPrefix" )
12051273 }
@@ -1269,7 +1337,13 @@ func (m *mergingIter) NextPrefix(succKey []byte) *base.InternalKV {
12691337 return m .findNextEntry ()
12701338}
12711339
1272- func (m * mergingIter ) Prev () * base.InternalKV {
1340+ func (m * mergingIter ) Prev () (kv * base.InternalKV ) {
1341+ if treesteps .Enabled && treesteps .IsRecording (m ) {
1342+ op := treesteps .StartOpf (m , "Prev()" )
1343+ defer func () {
1344+ op .Finishf ("= %s" , kv .String ())
1345+ }()
1346+ }
12731347 if m .err != nil {
12741348 return nil
12751349 }
@@ -1330,11 +1404,47 @@ func (m *mergingIter) SetContext(ctx context.Context) {
13301404 }
13311405}
13321406
1407+ type dummyNode struct {
1408+ info treesteps.NodeInfo
1409+ }
1410+
1411+ func (d * dummyNode ) TreeStepsNode () treesteps.NodeInfo {
1412+ return d .info
1413+ }
1414+
13331415// TreeStepsNode is part of the InternalIterator interface.
13341416func (m * mergingIter ) TreeStepsNode () treesteps.NodeInfo {
1417+ levelName := func (index int ) string {
1418+ return string ('A' + byte (index ))
1419+ }
13351420 info := treesteps .NodeInfof (m , "mergingIter" )
1421+ if m .heap .len () > 0 {
1422+ item := m .heap .items [0 ].mergingIterLevel
1423+ heapProp := "heap min"
1424+ if m .heap .reverse {
1425+ heapProp = "heap max"
1426+ }
1427+ info .AddPropf (heapProp , "%s:%s" , levelName (item .index ), item .lastIterKey .Get ())
1428+ }
1429+ if m .prefix != nil {
1430+ info .AddPropf ("prefix" , "%s" , m .prefix )
1431+ }
13361432 for i := range m .levels {
1337- info .AddChildren (m .levels [i ].iter )
1433+ l := & m .levels [i ]
1434+ name := levelName (i )
1435+ if l .iterKV != nil {
1436+ name = fmt .Sprintf ("%s:%s" , name , l .lastIterKey .Get ())
1437+ }
1438+ d := & dummyNode {}
1439+ d .info = treesteps .NodeInfof (d , "%s" , name )
1440+ if l .tombstone != nil {
1441+ d .info .AddPropf ("tombstone" , "%s" , l .tombstone .String ())
1442+ }
1443+ d .info .AddChildren (l .iter )
1444+ if l .rangeDelIter != nil {
1445+ d .info .AddChildren (l .rangeDelIter )
1446+ }
1447+ info .AddChildren (d )
13381448 }
13391449 return info
13401450}
0 commit comments