# Test a simple scenario where two distinct sstables contain blob handles
# referencing the same file.

define verbose format-major-version=21
L5
  b@9.SET.9:v
  c@9.SET.9:blob{fileNum=000921 value=helloworld}
  d@9.SET.9:v
L6
  b@2.SET.2:v
  c@2.SET.2:blob{fileNum=000921 value=foobar}
  d@2.SET.2:v
----
L5:
  000004:[b@9#9,SET-d@9#9,SET] seqnums:[9-9] points:[b@9#9,SET-d@9#9,SET] size:984 blobrefs:[(B000921: 10); depth:1]
L6:
  000005:[b@2#2,SET-d@2#2,SET] seqnums:[2-2] points:[b@2#2,SET-d@2#2,SET] size:979 blobrefs:[(B000921: 6); depth:1]
Blob files:
  B000921 physical:{000921 size:[106 (106B)] vals:[16 (16B)]}

combined-iter
first
next
next
next
next
next
next
stats
----
b@9: (v, .)
b@2: (v, .)
c@9: (helloworld, .)
c@2: (foobar, .)
d@9: (v, .)
d@2: (v, .)
.
stats: seeked 1 times (1 internal); stepped 6 times (6 internal); blocks: 0B cached, 365B not cached (read time: 0s); points: 6 (18B keys, 8B values); separated: 2 (16B, 16B fetched)

# Try the same but avoid fetching one of the values (by using NextPrefix to step
# over it).

combined-iter
first
next
next
next-prefix
next
next
stats
----
b@9: (v, .)
b@2: (v, .)
c@9: (helloworld, .)
d@9: (v, .)
d@2: (v, .)
.
stats: seeked 1 times (1 internal); stepped 5 times (6 internal); blocks: 365B cached; points: 6 (18B keys, 8B values); separated: 2 (16B, 10B fetched)

# Test a couple of blob files interleaved.

define verbose format-major-version=21
L5
  b@9.SETWITHDEL.9:blob{fileNum=000039 value=orange}
  c@9.SETWITHDEL.9:blob{fileNum=000921 value=canteloupe}
  d@9.SETWITHDEL.9:blob{fileNum=000039 value=honeydew}
  e@1.SETWITHDEL.9:blob{fileNum=000921 value=watermelon}
L6
  b@2.SETWITHDEL.9:blob{fileNum=000039 value=lemon}
  c@2.SETWITHDEL.2:blob{fileNum=000921 value=kiwi}
  d@2.SETWITHDEL.2:blob{fileNum=000921 value=tangerine}
  f@2.SETWITHDEL.3:blob{fileNum=000039 value=grapes}
----
L5:
  000004:[b@9#9,SETWITHDEL-e@1#9,SETWITHDEL] seqnums:[9-9] points:[b@9#9,SETWITHDEL-e@1#9,SETWITHDEL] size:985 blobrefs:[(B000039: 14), (B000921: 20); depth:2]
L6:
  000005:[b@2#9,SETWITHDEL-f@2#3,SETWITHDEL] seqnums:[2-9] points:[b@2#9,SETWITHDEL-f@2#3,SETWITHDEL] size:993 blobrefs:[(B000039: 11), (B000921: 13); depth:2]
Blob files:
  B000039 physical:{000039 size:[117 (117B)] vals:[25 (25B)]}
  B000921 physical:{000921 size:[125 (125B)] vals:[33 (33B)]}

# The iterator stats should indicate that only the first value from each file
# should trigger a read of the blob file. Once loaded, subsequent reads of the
# values within the same blocks should not be recorded as block loads cached or
# uncached, because the blob value fetcher retains its handle on the block.
#
# TODO(jackson): Add stats on the count of blob value retrievals that hit on the
# existing cached readers.

combined-iter
first
stats
next
stats
next
stats
next
next
next
stats
next
next
next
stats
----
b@9: (orange, .)
stats: seeked 1 times (1 internal); stepped 0 times (0 internal); blocks: 0B cached, 381B not cached (read time: 0s); points: 1 (3B keys, 2B values); separated: 2 (11B, 6B fetched)
b@2: (lemon, .)
stats: seeked 1 times (1 internal); stepped 1 times (1 internal); blocks: 0B cached, 381B not cached (read time: 0s); points: 2 (6B keys, 4B values); separated: 3 (21B, 11B fetched)
c@9: (canteloupe, .)
stats: seeked 1 times (1 internal); stepped 2 times (2 internal); blocks: 0B cached, 458B not cached (read time: 0s); points: 3 (9B keys, 6B values); separated: 4 (25B, 21B fetched)
c@2: (kiwi, .)
d@9: (honeydew, .)
d@2: (tangerine, .)
stats: seeked 1 times (1 internal); stepped 5 times (5 internal); blocks: 0B cached, 458B not cached (read time: 0s); points: 6 (18B keys, 12B values); separated: 7 (52B, 42B fetched)
e@1: (watermelon, .)
f@2: (grapes, .)
.
stats: seeked 1 times (1 internal); stepped 8 times (8 internal); blocks: 0B cached, 458B not cached (read time: 0s); points: 8 (24B keys, 16B values); separated: 8 (58B, 58B fetched)

# Test scanning a table, stepping into new blocks of the blob file. The stats
# should reflect that a block is only loaded when stepping into a new block.

define verbose format-major-version=21
L6
  a.SETWITHDEL.2:blob{fileNum=000009 value=lemonmeringue}
  b.SETWITHDEL.2:blob{fileNum=000009 value=keylime}
  c.SETWITHDEL.2:blob{fileNum=000009 value=pecan blockID=1 valueID=0}
  d.SETWITHDEL.2:blob{fileNum=000009 value=cherry}
  e.SETWITHDEL.2:blob{fileNum=000009 value=apple}
  f.SETWITHDEL.2:blob{fileNum=000009 value=bananacream blockID=2 valueID=0}
  g.SETWITHDEL.2:blob{fileNum=000009 value=chocolate}
  h.SETWITHDEL.2:blob{fileNum=000009 value=strawberry blockID=3 valueID=0}
  i.SETWITHDEL.2:blob{fileNum=000009 value=custard}
  j.SETWITHDEL.2:blob{fileNum=000009 value=blueberry blockID=4 valueID=0}
  k.SETWITHDEL.2:blob{fileNum=000009 value=raspberry blockID=5 valueID=0}
  l.SETWITHDEL.2:blob{fileNum=000009 value=peach blockID=6 valueID=0}
----
L6:
  000004:[a#2,SETWITHDEL-l#2,SETWITHDEL] seqnums:[2-2] points:[a#2,SETWITHDEL-l#2,SETWITHDEL] size:1083 blobrefs:[(B000009: 96); depth:1]
Blob files:
  B000009 physical:{000009 size:[322 (322B)] vals:[96 (96B)]}

combined-iter
first
stats
next
stats
next
stats
next
stats
next
stats
next
stats
next
stats
next
stats
next
stats
next
stats
next
stats
next
stats
next
stats
----
a: (lemonmeringue, .)
stats: seeked 1 times (1 internal); stepped 0 times (0 internal); blocks: 0B cached, 289B not cached (read time: 0s); points: 1 (1B keys, 2B values); separated: 1 (13B, 13B fetched)
b: (keylime, .)
stats: seeked 1 times (1 internal); stepped 1 times (1 internal); blocks: 0B cached, 289B not cached (read time: 0s); points: 2 (2B keys, 4B values); separated: 2 (20B, 20B fetched)
c: (pecan, .)
stats: seeked 1 times (1 internal); stepped 2 times (2 internal); blocks: 0B cached, 323B not cached (read time: 0s); points: 3 (3B keys, 6B values); separated: 3 (25B, 25B fetched)
d: (cherry, .)
stats: seeked 1 times (1 internal); stepped 3 times (3 internal); blocks: 0B cached, 323B not cached (read time: 0s); points: 4 (4B keys, 8B values); separated: 4 (31B, 31B fetched)
e: (apple, .)
stats: seeked 1 times (1 internal); stepped 4 times (4 internal); blocks: 0B cached, 323B not cached (read time: 0s); points: 5 (5B keys, 10B values); separated: 5 (36B, 36B fetched)
f: (bananacream, .)
stats: seeked 1 times (1 internal); stepped 5 times (5 internal); blocks: 0B cached, 360B not cached (read time: 0s); points: 6 (6B keys, 12B values); separated: 6 (47B, 47B fetched)
g: (chocolate, .)
stats: seeked 1 times (1 internal); stepped 6 times (6 internal); blocks: 0B cached, 360B not cached (read time: 0s); points: 7 (7B keys, 14B values); separated: 7 (56B, 56B fetched)
h: (strawberry, .)
stats: seeked 1 times (1 internal); stepped 7 times (7 internal); blocks: 0B cached, 394B not cached (read time: 0s); points: 8 (8B keys, 16B values); separated: 8 (66B, 66B fetched)
i: (custard, .)
stats: seeked 1 times (1 internal); stepped 8 times (8 internal); blocks: 0B cached, 394B not cached (read time: 0s); points: 9 (9B keys, 18B values); separated: 9 (73B, 73B fetched)
j: (blueberry, .)
stats: seeked 1 times (1 internal); stepped 9 times (9 internal); blocks: 0B cached, 419B not cached (read time: 0s); points: 10 (10B keys, 20B values); separated: 10 (82B, 82B fetched)
k: (raspberry, .)
stats: seeked 1 times (1 internal); stepped 10 times (10 internal); blocks: 0B cached, 444B not cached (read time: 0s); points: 11 (11B keys, 22B values); separated: 11 (91B, 91B fetched)
l: (peach, .)
stats: seeked 1 times (1 internal); stepped 11 times (11 internal); blocks: 0B cached, 465B not cached (read time: 0s); points: 12 (12B keys, 24B values); separated: 12 (96B, 96B fetched)
.
stats: seeked 1 times (1 internal); stepped 12 times (12 internal); blocks: 0B cached, 465B not cached (read time: 0s); points: 12 (12B keys, 24B values); separated: 12 (96B, 96B fetched)

# Regression test for #4741.
#
# Previously an iterator traversing in reverse direction would not reset i.value
# to an empty InternalValue if it landed on a range key. While i.Value() would
# never use the garbage value in i.value, maybeSampleRead would in order to
# retrieve the value length. This resulted in a data race if the underlying
# sstable iterator backing a LazyValue stored in i.value was pooled and reused.

define verbose format-major-version=21
L6
  rangekey:a-d:{(#5,RANGEKEYSET,@2,foo)}
  b.SETWITHDEL.2:blob{fileNum=000009 value=keylime}
----
L6:
  000004:[a#5,RANGEKEYSET-d#inf,RANGEKEYSET] seqnums:[2-5] points:[b#2,SETWITHDEL-b#2,SETWITHDEL] ranges:[a#5,RANGEKEYSET-d#inf,RANGEKEYSET] size:1133 blobrefs:[(B000009: 7); depth:1]
Blob files:
  B000009 physical:{000009 size:[96 (96B)] vals:[7 (7B)]}

combined-iter
seek-lt c
seek-lt b
inspect value.Len()
----
b: (keylime, [a-d) @2=foo UPDATED)
a: (., [a-d) @2=foo)
value.Len()=0
