mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-11-10 18:25:17 +00:00
724 lines
16 KiB
Plaintext
724 lines
16 KiB
Plaintext
# Test repeated seeks into the same range key, while TrySeekUsingNext=true.
|
|
# Test for regression fixed in #1849.
|
|
|
|
reset
|
|
----
|
|
|
|
batch commit
|
|
range-key-set a c @5 boop
|
|
range-key-set c e @5 beep
|
|
----
|
|
committed 2 keys
|
|
|
|
combined-iter
|
|
seek-ge a
|
|
seek-ge b
|
|
----
|
|
a: (., [a-c) @5=boop UPDATED)
|
|
b: (., [a-c) @5=boop)
|
|
|
|
# Ensure that no-op optimizations do not reuse range key iterator state across
|
|
# SetOptions calls. No-op optimizations have the potential to fail to update
|
|
# RangeKeyChanged().
|
|
|
|
reset
|
|
----
|
|
|
|
batch commit
|
|
range-key-set p s @1 foo
|
|
----
|
|
committed 1 keys
|
|
|
|
combined-iter lower=n@9 upper=x@5
|
|
seek-lt y@3
|
|
set-options lower=n@9 upper=x@5
|
|
seek-lt-limit t o
|
|
----
|
|
p: (., [p-s) @1=foo UPDATED)
|
|
.
|
|
p: valid (., [p-s) @1=foo UPDATED)
|
|
|
|
combined-iter lower=n@9 upper=x@5
|
|
seek-ge o
|
|
set-options lower=n@9 upper=x@5
|
|
seek-ge oat
|
|
----
|
|
p: (., [p-s) @1=foo UPDATED)
|
|
.
|
|
p: (., [p-s) @1=foo UPDATED)
|
|
|
|
combined-iter lower=n@9 upper=x@5
|
|
seek-prefix-ge p@5
|
|
set-options lower=n@9 upper=x@5
|
|
seek-prefix-ge p
|
|
----
|
|
p@5: (., [p-"p\x00") @1=foo UPDATED)
|
|
.
|
|
p: (., [p-"p\x00") @1=foo UPDATED)
|
|
|
|
# Regression test for #1963 / cockroachdb/cockroach#88296.
|
|
#
|
|
# The iterators in this test move their bounds monotonically forward
|
|
# [a,b)→[b,e). This enables the sstable iterator optimization for monotonically
|
|
# moving bounds (see boundsCmp in sstable/reader.go). With this optimization,
|
|
# the first seek after the SetBounds may use the fact that the bounds moved
|
|
# forward monotonically to avoid re-seeking within the index.
|
|
#
|
|
# The test cases below exercise a seek to a key, followed by a seek to a smaller
|
|
# key. The second seek should not make use of the bounds optimization because
|
|
# doing so may incorrectly skip all keys between the lower bound and the first
|
|
# seek key. Previously, the code paths that handled block-property filtering on
|
|
# a two-level iterator could leave the iterator in a state such that the second
|
|
# seek would improperly also exercise the monotonic bounds optimization. In the
|
|
# test cases below, this would result in the key 'b' not being found. Each test
|
|
# case exercises a different combination of seek-ge and seek-prefix-ge.
|
|
|
|
reset block-size=1 index-block-size=1
|
|
----
|
|
|
|
batch commit
|
|
set a a
|
|
set b b
|
|
set b@4 b@4
|
|
set z@6 z@6
|
|
----
|
|
committed 4 keys
|
|
|
|
flush
|
|
----
|
|
|
|
combined-iter lower=a upper=b point-key-filter=(1,4)
|
|
seek-ge a
|
|
set-bounds lower=b upper=e
|
|
seek-prefix-ge d@5
|
|
seek-prefix-ge b
|
|
----
|
|
a: (a, .)
|
|
.
|
|
.
|
|
b: (b, .)
|
|
|
|
combined-iter lower=a upper=b point-key-filter=(1,4)
|
|
seek-ge a
|
|
set-bounds lower=b upper=e
|
|
seek-ge d@5
|
|
seek-prefix-ge b
|
|
----
|
|
a: (a, .)
|
|
.
|
|
.
|
|
b: (b, .)
|
|
|
|
combined-iter lower=a upper=b point-key-filter=(1,4)
|
|
seek-ge a
|
|
set-bounds lower=b upper=e
|
|
seek-ge d@5
|
|
seek-ge b
|
|
----
|
|
a: (a, .)
|
|
.
|
|
.
|
|
b: (b, .)
|
|
|
|
combined-iter lower=a upper=b point-key-filter=(1,4)
|
|
seek-ge a
|
|
set-bounds lower=b upper=e
|
|
seek-prefix-ge d@5
|
|
seek-ge b
|
|
----
|
|
a: (a, .)
|
|
.
|
|
.
|
|
b: (b, .)
|
|
|
|
# Test a similar case with range key masking. The previous bug did not apply to
|
|
# this case, because range-key masking never skips blocks on a seek.
|
|
|
|
reset block-size=1 index-block-size=1
|
|
----
|
|
|
|
batch commit
|
|
set a a
|
|
set b b
|
|
set b@4 b@4
|
|
set z@6 z@6
|
|
range-key-set a z @9 v
|
|
----
|
|
committed 5 keys
|
|
|
|
flush
|
|
----
|
|
|
|
combined-iter lower=a upper=b mask-suffix=@10 mask-filter
|
|
seek-ge a
|
|
set-bounds lower=b upper=e
|
|
seek-prefix-ge d@5
|
|
seek-ge b
|
|
----
|
|
a: (a, [a-b) @9=v UPDATED)
|
|
.
|
|
d@5: (., [d-"d\x00") @9=v UPDATED)
|
|
b: (b, [b-e) @9=v UPDATED)
|
|
|
|
# Test TrySeekUsingNext across no-op SetOptions when reading through an indexed
|
|
# batch with modifications. The seek-prefix-ges after the first should make use
|
|
# of the TrySeekUsingNext optimization.
|
|
#
|
|
# TODO(jackson): The iterator stats don't signal the use of try-seek-using-next,
|
|
# so we inspect lastPositioningOp as a proxy since that's the
|
|
# try-seek-using-next prerequisite that previously regressed. Is there a way to
|
|
# adapt to this test so that the absence of the try-seek-using-next optimization
|
|
# is visible in the iterator statistics?
|
|
#
|
|
# Regression test for cockroachdb/cockroach#88819.
|
|
|
|
reset
|
|
----
|
|
|
|
batch commit
|
|
set b@5 b@5
|
|
set c@3 c@3
|
|
set d@9 d@9
|
|
set e@8 e@8
|
|
set f@8 f@8
|
|
----
|
|
committed 5 keys
|
|
|
|
flush
|
|
----
|
|
|
|
batch name=foo
|
|
set g@4 g@4
|
|
----
|
|
wrote 1 keys to batch "foo"
|
|
|
|
combined-iter reader=foo name=fooiter
|
|
inspect lastPositioningOp
|
|
seek-prefix-ge b@10
|
|
stats
|
|
----
|
|
lastPositioningOp="unknown"
|
|
b@5: (b@5, .)
|
|
stats: (interface (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 1, 0), (rev, 0, 0)),
|
|
(internal-stats: (block-bytes: (total 119B, cached 0B, read-time 0s)), (points: (count 1, key-bytes 3B, value-bytes 3B, tombstoned 0)))
|
|
|
|
mutate batch=foo
|
|
set h@2 h@2
|
|
----
|
|
|
|
iter iter=fooiter
|
|
set-options
|
|
inspect lastPositioningOp
|
|
seek-prefix-ge c@10
|
|
stats
|
|
----
|
|
.
|
|
lastPositioningOp="seekprefixge"
|
|
c@3: (c@3, .)
|
|
stats: (interface (dir, seek, step): (fwd, 2, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 2, 0), (rev, 0, 0)),
|
|
(internal-stats: (block-bytes: (total 119B, cached 0B, read-time 0s)), (points: (count 2, key-bytes 6B, value-bytes 6B, tombstoned 0)))
|
|
|
|
mutate batch=foo
|
|
set i@1 i@1
|
|
----
|
|
|
|
iter iter=fooiter
|
|
set-options
|
|
inspect lastPositioningOp
|
|
seek-prefix-ge d@10
|
|
stats
|
|
----
|
|
.
|
|
lastPositioningOp="seekprefixge"
|
|
d@9: (d@9, .)
|
|
stats: (interface (dir, seek, step): (fwd, 3, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 3, 0), (rev, 0, 0)),
|
|
(internal-stats: (block-bytes: (total 119B, cached 0B, read-time 0s)), (points: (count 3, key-bytes 9B, value-bytes 9B, tombstoned 0)))
|
|
|
|
mutate batch=foo
|
|
set j@6 j@6
|
|
----
|
|
|
|
iter iter=fooiter
|
|
set-options
|
|
inspect lastPositioningOp
|
|
seek-prefix-ge e@10
|
|
stats
|
|
----
|
|
.
|
|
lastPositioningOp="seekprefixge"
|
|
e@8: (e@8, .)
|
|
stats: (interface (dir, seek, step): (fwd, 4, 0), (rev, 0, 0)), (internal (dir, seek, step): (fwd, 4, 0), (rev, 0, 0)),
|
|
(internal-stats: (block-bytes: (total 119B, cached 0B, read-time 0s)), (points: (count 4, key-bytes 12B, value-bytes 12B, tombstoned 0)))
|
|
|
|
# Ensure that a case eligible for TrySeekUsingNext across a SetOptions correctly
|
|
# sees new batch mutations. The batch iterator should ignore the
|
|
# TrySeekUsingNext designation.
|
|
|
|
reset
|
|
----
|
|
|
|
batch commit
|
|
set b@3 b@3
|
|
set c@3 c@3
|
|
----
|
|
committed 2 keys
|
|
|
|
batch name=b1
|
|
----
|
|
wrote 0 keys to batch "b1"
|
|
|
|
combined-iter name=i1 reader=b1
|
|
seek-prefix-ge b@6
|
|
----
|
|
b@3: (b@3, .)
|
|
|
|
mutate batch=b1
|
|
set b@4 b@4
|
|
----
|
|
|
|
iter iter=i1
|
|
set-options
|
|
inspect lastPositioningOp
|
|
seek-prefix-ge b@5
|
|
----
|
|
.
|
|
lastPositioningOp="seekprefixge"
|
|
b@4: (b@4, .)
|
|
|
|
# Similar case with SeekGE.
|
|
|
|
iter iter=i1
|
|
seek-ge b@2
|
|
----
|
|
c@3: (c@3, .)
|
|
|
|
mutate batch=b1
|
|
set c@9 c@9
|
|
----
|
|
|
|
iter iter=i1
|
|
set-options
|
|
inspect lastPositioningOp
|
|
seek-ge b@1
|
|
----
|
|
.
|
|
lastPositioningOp="seekge"
|
|
c@9: (c@9, .)
|
|
|
|
# Test a case similar to the above, but with an intermediate switch to
|
|
# range-key-only iteration, so that the batchIter is not re-seeked.
|
|
|
|
reset
|
|
----
|
|
|
|
batch commit
|
|
set b@5 b@5
|
|
set c@3 c@3
|
|
----
|
|
committed 2 keys
|
|
|
|
batch name=b1
|
|
----
|
|
wrote 0 keys to batch "b1"
|
|
|
|
combined-iter name=i1 reader=b1
|
|
seek-ge b@9
|
|
----
|
|
b@5: (b@5, .)
|
|
|
|
mutate batch=b1
|
|
set b@6 b@6
|
|
----
|
|
|
|
iter iter=i1
|
|
set-options key-types=range
|
|
seek-ge b@8
|
|
set-options key-types=both
|
|
inspect lastPositioningOp
|
|
seek-ge b@7
|
|
----
|
|
.
|
|
.
|
|
.
|
|
lastPositioningOp="invalidate"
|
|
b@6: (b@6, .)
|
|
|
|
reset
|
|
----
|
|
|
|
batch commit
|
|
set b@2 b@2
|
|
set c@3 c@3
|
|
----
|
|
committed 2 keys
|
|
|
|
batch name=b1
|
|
----
|
|
wrote 0 keys to batch "b1"
|
|
|
|
combined-iter name=i1 reader=b1
|
|
seek-prefix-ge b@1
|
|
----
|
|
.
|
|
|
|
mutate batch=b1
|
|
set c@4 c@4
|
|
----
|
|
|
|
iter iter=i1
|
|
set-options
|
|
inspect lastPositioningOp
|
|
seek-prefix-ge c@8
|
|
----
|
|
.
|
|
lastPositioningOp="seekprefixge"
|
|
c@4: (c@4, .)
|
|
|
|
# Regression test for #2084.
|
|
#
|
|
# The optimization added in #2058 began using an enabled TrySeekUsingNext flag
|
|
# to avoid re-seeking within a level's file metadata. This optimization was
|
|
# dependent on the invariant that the iterator remained positioned at the
|
|
# previous seek key, so that a subsequent seek to a larger key does not need to
|
|
# backtrack.
|
|
#
|
|
# This invariant wasn't strictly preserved by the levelIter during SeekPrefixGE
|
|
# calls. During a SeekPrefixGE, the sstable iterator may return nil despite the
|
|
# existence of sstable keys greater than the seek key if the sstable's bloom
|
|
# filter excludes the seek prefix. If the sstable DOES NOT contain any range
|
|
# tombstones, the levelIter does not advance to the next file if the file's
|
|
# largest bound has a prefix larger than the seek prefix, returning nil, else it
|
|
# does advance since the next file could contain the seek prefix.
|
|
#
|
|
# However, if the file DOES contain range tombstones, the levelIter returns a
|
|
# synthetic largest boundary key so that the file remains open until the merging
|
|
# iterator passes beyond its bounds. This ensures the file's range deletions'
|
|
# effects on other keys are observed. If another level returned a key greater
|
|
# than this largest boundary key (eg, because the other level doesn't restrict
|
|
# results to the seek prefix), the merging iterator could step beyond the
|
|
# level's synthetic boundary key. This step could advance the levelIter to the
|
|
# next file, despite its irrelevance to the current prefix. This step would also
|
|
# break the invariant that the level iterator remained positioned at the seek
|
|
# key.
|
|
#
|
|
# The bug was fixed by comparing the synthetic boundary key to the seek prefix,
|
|
# avoiding ever Next-ing the level iterator beyond the seek prefix.
|
|
|
|
# Set 100 bloom-filter bits per key to ensure the bloom-filter exclusivity
|
|
# checks successfully exclude prefixes that aren't present.
|
|
reset bloom-bits-per-key=100
|
|
----
|
|
|
|
# [a -d)
|
|
# b@3 d@1
|
|
batch commit
|
|
del-range a d
|
|
set b@3 b@3
|
|
set d@1 d@1
|
|
----
|
|
committed 3 keys
|
|
|
|
flush
|
|
----
|
|
|
|
# c@0 e@0
|
|
batch commit
|
|
del c@0
|
|
set e@0 e@0
|
|
----
|
|
committed 2 keys
|
|
|
|
flush
|
|
----
|
|
|
|
lsm
|
|
----
|
|
0.1:
|
|
000007:[c@0#13,DEL-e@0#14,SET]
|
|
0.0:
|
|
000005:[a#10,RANGEDEL-d@1#12,SET]
|
|
|
|
# The first SeekPrefixGE(b@3) positions each level iterator over their
|
|
# respective files and correctly finds b@3.
|
|
#
|
|
# The second SeekPrefixGE(c@5) seeks in both files. The 0.0 level iterator finds
|
|
# that its file does not contain the prefix 'c', so it returns nil. Since the file
|
|
# contains a range deletion, it returns a synthetic boundary key with user key
|
|
# d@1 to ensure the file stays open until the iterator has moved beyond the
|
|
# file's bounds. The seek in level 0.1 finds a key with the prefix 'c': a point
|
|
# tombstone c@0#4,DEL. This gets bubbled up to the Iterator, which skips it
|
|
# because it's a point tombstone, nexting within 000007 to e@0#5.
|
|
#
|
|
# Previously, in the bug highlighted by #2084, the merging iterator would then
|
|
# see that level 0.0's synthetic boundary key at d@1 was at the top of the heap
|
|
# and move to the next file in 0.0. The subsequent call to SeekPrefixGE(d@1,
|
|
# TrySeekUsingNext=true) would incorrectly use the current position within the
|
|
# 0.0 file metadata (nil), and miss the d@1 key.
|
|
|
|
combined-iter
|
|
seek-prefix-ge b@3
|
|
seek-prefix-ge c@5
|
|
seek-prefix-ge d@1
|
|
----
|
|
b@3: (b@3, .)
|
|
.
|
|
d@1: (d@1, .)
|
|
|
|
|
|
# Test an instance where unequal application of TrySeekUsingNext optimizations
|
|
# among a merging iterator's levels can result in surfacing deleted keys.
|
|
# Regression test for #2101.
|
|
|
|
reset
|
|
----
|
|
|
|
batch commit
|
|
set b b
|
|
----
|
|
committed 1 keys
|
|
|
|
flush
|
|
----
|
|
|
|
compact a-h
|
|
----
|
|
6:
|
|
000005:[b#10,SET-b#10,SET]
|
|
|
|
batch commit
|
|
set g g
|
|
----
|
|
committed 1 keys
|
|
|
|
flush
|
|
----
|
|
|
|
compact a-h
|
|
----
|
|
6:
|
|
000005:[b#10,SET-b#10,SET]
|
|
000007:[g#11,SET-g#11,SET]
|
|
|
|
batch commit
|
|
del-range b d
|
|
----
|
|
committed 1 keys
|
|
|
|
flush
|
|
----
|
|
|
|
batch commit
|
|
set e e
|
|
----
|
|
committed 1 keys
|
|
|
|
flush
|
|
----
|
|
|
|
lsm
|
|
----
|
|
0.0:
|
|
000009:[b#12,RANGEDEL-d#inf,RANGEDEL]
|
|
000011:[e#13,SET-e#13,SET]
|
|
6:
|
|
000005:[b#10,SET-b#10,SET]
|
|
000007:[g#11,SET-g#11,SET]
|
|
|
|
# The `seek-ge b` could incorrectly return `b` if the level 0.0 levelIter obeys
|
|
# the TrySeekUsingNext optimization but the level 6 levelIter does not. The
|
|
# TrySeekUsingNext optimization must be applied equally across all the levels of
|
|
# a merging iterator.
|
|
|
|
combined-iter
|
|
seek-ge a
|
|
seek-ge b
|
|
----
|
|
e: (e, .)
|
|
e: (e, .)
|
|
|
|
# Regression test for #2118, where a MERGE pushes child iterators to the next
|
|
# key, and possibly past a file that contained a range tombstone that we
|
|
# should have paused at in a SeekPrefixGE, affecting future TrySeekUsingNexts.
|
|
# This test constructs this example (suffixes ignored), where square brackets
|
|
# consist of one SST:
|
|
#
|
|
# L0: [(b, MERGE) (c-d, RANGEDEL)] [(m, DEL)]
|
|
# L6: [(c, SET) (c-e, RANGEKEYSET)] [(j, SET)]
|
|
#
|
|
# We create an iterator with L6 filters enabled and create relatively large
|
|
# bloom filter blocks to reduce the false positive rate. Then we SeekPrefixGE(b)
|
|
# and end up with the L0 levelIter landing on the (b, MERGE), and the L6 iterator
|
|
# is exhausted as no SST filter blocks match the prefix. The top-level iterator
|
|
# then Next()s to find the next internal key at b if there is any, we land
|
|
# on the pause key at (d, RANGEDELSENTINEL). Crucially since there are no
|
|
# more items in the mergingIter heap and the merging iter is set to elide
|
|
# range tombstones, we Next() the level iter again as part of the same top-level
|
|
# iterator Next(), and land on (m, DEL). The type of the key here doesn't really
|
|
# matter.
|
|
#
|
|
# We then do a SeekPrefixGE(c), and since c > b, in the buggy scenario we
|
|
# TrySeekUsingNext. The bottom levelIter correctly finds the sstable containing
|
|
# the set, but the upper levelIter is already past the sstable containing the
|
|
# rangedel, so it just returns (m, DEL) again, and we surface the (c, SET) that
|
|
# should have been deleted.
|
|
|
|
reset bloom-bits-per-key=100
|
|
----
|
|
|
|
batch commit
|
|
set c@2 foo
|
|
range-key-set c e @5 bar
|
|
----
|
|
committed 2 keys
|
|
|
|
flush
|
|
----
|
|
|
|
compact a-z
|
|
----
|
|
6:
|
|
000005:[c#11,RANGEKEYSET-e#inf,RANGEKEYSET]
|
|
|
|
batch commit
|
|
set j k
|
|
----
|
|
committed 1 keys
|
|
|
|
flush
|
|
----
|
|
|
|
compact a-z
|
|
----
|
|
6:
|
|
000005:[c#11,RANGEKEYSET-e#inf,RANGEKEYSET]
|
|
000007:[j#12,SET-j#12,SET]
|
|
|
|
batch commit
|
|
del-range c@2 d
|
|
merge b@2 g
|
|
----
|
|
committed 2 keys
|
|
|
|
flush
|
|
----
|
|
|
|
batch commit
|
|
del m
|
|
----
|
|
committed 1 keys
|
|
|
|
flush
|
|
----
|
|
|
|
lsm
|
|
----
|
|
0.0:
|
|
000009:[b@2#14,MERGE-d#inf,RANGEDEL]
|
|
000011:[m#15,DEL-m#15,DEL]
|
|
6:
|
|
000005:[c#11,RANGEKEYSET-e#inf,RANGEKEYSET]
|
|
000007:[j#12,SET-j#12,SET]
|
|
|
|
combined-iter upper=z@3 mask-suffix=@3 mask-filter use-l6-filter
|
|
seek-prefix-ge b@2
|
|
seek-prefix-ge c@2
|
|
----
|
|
b@2: (g, .)
|
|
c@2: (., [c-"c\x00") @5=bar UPDATED)
|
|
|
|
# Regression test for Cockroachdb#92205. This test constructs this scenario:
|
|
#
|
|
# A DEL in a middle level (L0.0) that we SeekPrefixGE directly for. Note that
|
|
# this DEL is not deleted by any range deletes; it gets exposed to the
|
|
# Iterator. There's a key after this DEL in the L0.0 levelIter, and there's a
|
|
# level above it (L0.1) that has a rangedel deleting that key, but not the DEL
|
|
# we SeekPrefixGE for. In the lowest level, there's a SET at L6 that is to the
|
|
# right of the DEL in L0.0, but is also not deleted by the RANGEDEL in L0.1.
|
|
# Our second SeekPrefixGE will be for this SET. Visualization, where square
|
|
# brackets are files:
|
|
#
|
|
# L0.1 [dd-ee#RANGEDEL]
|
|
# L0.0 [b#DEL e#SET]
|
|
# L6 [d#SET] [f#SET g#SET]
|
|
#
|
|
# When the Iterator encounters the above DEL internal key in the SeekPrefixGE, it
|
|
# calls Iterator.nextUserKey in the Iterator.findNextEntry call that was part of the
|
|
# SeekPrefixGE call. While Iterator.findNextEntry has a conditional to exit
|
|
# out of the loop if we're in prefix iteration and have gone past the prefix,
|
|
# this break only happens _after_ nextUserKey() has run. As a result we Next()
|
|
# the levelIter in L0.0, land on e#SET, and the mergingIter realizes that it
|
|
# is deleted by the rangedel in a higher level (L0.1). The mergingIter does not
|
|
# see d#SET because that sstable was excluded by the bloom filter. We then do a relative
|
|
# seek of all levels below L0.1 to ee (the end key of the rangedel), and in that
|
|
# process we advance the L6 levelIter to the second file.
|
|
#
|
|
# When we do the second SeekPrefixGE for d, the outer Iterator thinks d > b and
|
|
# so TrySeekUsingNext can work. However, the L6 levelIter has already advanced
|
|
# past the file containing d#SET, so we don't surface it even though we should
|
|
# have.
|
|
|
|
reset bloom-bits-per-key=100
|
|
----
|
|
|
|
batch commit
|
|
set d@4 foo
|
|
----
|
|
committed 1 keys
|
|
|
|
flush
|
|
----
|
|
|
|
compact a-f
|
|
----
|
|
6:
|
|
000005:[d@4#10,SET-d@4#10,SET]
|
|
|
|
batch commit
|
|
set f@5 bar
|
|
set g@5 baz
|
|
----
|
|
committed 2 keys
|
|
|
|
flush
|
|
----
|
|
|
|
compact e-k
|
|
----
|
|
6:
|
|
000005:[d@4#10,SET-d@4#10,SET]
|
|
000007:[f@5#11,SET-g@5#12,SET]
|
|
|
|
batch commit
|
|
del b@5
|
|
set e@4 foobar
|
|
----
|
|
committed 2 keys
|
|
|
|
flush
|
|
----
|
|
|
|
batch commit
|
|
del-range dd ee
|
|
----
|
|
committed 1 keys
|
|
|
|
flush
|
|
----
|
|
|
|
lsm
|
|
----
|
|
0.1:
|
|
000011:[dd#15,RANGEDEL-ee#inf,RANGEDEL]
|
|
0.0:
|
|
000009:[b@5#13,DEL-e@4#14,SET]
|
|
6:
|
|
000005:[d@4#10,SET-d@4#10,SET]
|
|
000007:[f@5#11,SET-g@5#12,SET]
|
|
|
|
combined-iter upper=z@3 use-l6-filter
|
|
seek-prefix-ge b@6
|
|
seek-prefix-ge d@5
|
|
----
|
|
.
|
|
d@4: (foo, .)
|