Skip to content

Commit 895ad9f

Browse files
committed
db: treesteps support for Iterator
1 parent a07853d commit 895ad9f

File tree

3 files changed

+130
-0
lines changed

3 files changed

+130
-0
lines changed

iterator.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package pebble
77
import (
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).
12981299
func (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)].
14471459
func (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.
15771595
func (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.
16591688
func (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.
16951730
func (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.
17591800
func (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

19261973
func (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.
20362094
func (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.
31573226
func (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+
}

testdata/treesteps/iterator

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
define
2+
L1
3+
a@1#10,SET:va1
4+
b#10,SET:vb
5+
e#10,SET:ve
6+
L2
7+
a#5,SET:va
8+
a@1#5,SET:va1b
9+
b@2#5,SET:vb2
10+
c#5,DEL:
11+
d#5,SET:vd
12+
L3
13+
c#1,SET:vc
14+
----
15+
L1:
16+
000004:[a@1#10,SET-e#10,SET] seqnums:[10-10] points:[a@1#10,SET-e#10,SET] size:680
17+
L2:
18+
000005:[a#5,SET-d#5,SET] seqnums:[5-5] points:[a#5,SET-d#5,SET] size:844
19+
L3:
20+
000006:[c#1,SET-c#1,SET] seqnums:[1-1] points:[c#1,SET-c#1,SET] size:651
21+
22+
iterator depth=3
23+
seek-ge a@1
24+
next
25+
prev
26+
next
27+
----
28+
a@1: (va1, .)
29+
b: (vb, .)
30+
a@1: (va1, .)
31+
b: (vb, .)
32+
https://raduberinde.github.io/treesteps/decode.html#eNrsm0Fr2zAUx-_7FMK9tBDWJF13MBS6bmUMRil0t7kHuX1tTB032GoIjEHpYZdddshxn2EfKp9k2IkTx5NiO7HsJf7n0jR6siX9f3qynp--GRe8T4ZpCArELRf8UPhEgaBBcOgI8rl49M1u12gZV4IGoW1gmF8Nx3OEw93wZ6KHj-fs0WMDsm2XXn-a1WKB4L6g2yWbPvn3jncf2kjLXRqSG5XeOZ4T9EotTt5capDuQcLogkZidSdjC3kX41JpE2VVM4rLvfKKjl_6NFzd8dhC3ry4VNq8zQsVHSuhTbVduW4K1y-sjd8aZsb11CNG3jBlZHlsMn5hNOrxp0DQbfT_eDJ-noyfk_ezPBZ9JuPfs8J3i59epn_iatwnjwcPbvImqcpnysqLAfjc-bfe-zz1ugujuPRD_BNT1jqyPKOVHh7GJj9-sanX3bcMftqxjAOMmb4xk1VusfYBxnLLx1LVGHbC-Glnr9NuXZ1_SV1p_v3Occlk7fDzRmrz8w-0yqWVWRD8ynTI4OM4Jx7Hmc2CzJpkNgvOt4o0XAHWzV4niRVTNeitxCJsTkVwKF1kj_iA9R3PZGemzKIklpT-uRKqVLO_CrxMGSEqV6EXInbCZl9nOHFhhlhkP3yCk53mJNz97R8ACkCxJhSpGgAEgGwzIMnWshNma9lagpuC3Ki2cQuGpGNaEkI2PMyWexjQATpAR54Q2mLlO-3qCJtt6epjZ8RPbF2PL3Xyo0KgGd4lCpnYSwETu-jOGFjsEBaXPg2X3AdwAA7FovPzOsADeACPwngkh0nfq11gg41vOXikeLWe2u2jG89xoy_UPAok83fn4qsbJYasL_zqECkf6Q1zNPc1THly54pIqGY5BIbAjRE47ff-u_y-dWXPyNUKGdjlt-mY49AX-lad7KDenjReQvnisrQg61mO1z1gst0CbZ6lClFKFGWz3FBIoUuKnHEBVcoDhIEw-bIf9cXnILZWsfGgnxWTnzOu6xQXWCmflTwpwTuUolaIGhzza3wi7IZeBogAEZzWATnlLUY4rwNWcCYDfIAPnNmpYw3CqR2c2sExjYZgcf391d8AAAD__5AVntE=

treesteps_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ func TestTreeSteps(t *testing.T) {
8282
url := rec.Finish().URL()
8383
return out + url.String()
8484

85+
case "iterator":
86+
iter, _ := d.NewIter(nil)
87+
rec := treeStepsStartRecording(t, td, iter)
88+
out := runIterCmd(td, iter, true /* closeIter */)
89+
url := rec.Finish().URL()
90+
return out + url.String()
91+
8592
default:
8693
return "unknown command"
8794
}

0 commit comments

Comments
 (0)