define
----

# An empty LSM ingests into the bottom level.
target
000000:[a#5,SET-b#5,SET] seqnums:[5-5]
----
6

define
L5
  b.SET.1:1
  c.SET.2:2
----
L5:
  000004:[b#1,SET-c#2,SET]

# Overlapping cases.
target
000000:[a#5,SET-b#5,SET] seqnums:[5-5]
000000:[b#5,SET-c#5,SET] seqnums:[5-5]
000000:[c#5,SET-d#5,SET] seqnums:[5-5]
----
4
4
4

# Non-overlapping cases:
# - Ingested file lies entirely before the existing file.
# - Ingested file lies entirely after the existing file.
# - Ingested file has no data overlap (falls through the middle of the existing
#   file).
target
000000:[a#5,SET-aa#5,SET] seqnums:[5-5]
000000:[d#5,SET-e#5,SET] seqnums:[5-5]
000000:[bb#5,SET-bb#5,SET] seqnums:[5-5]
----
6
6
6

define
L0
  b.SET.3:3
  e.SET.4:4
L0
  d.SET.5:5
  f.SET.6:6
L0
  x.SET.7:7
  y.SET.8:8
L3
  g.SET.1:1
  h.SET.2:2
----
L0.1:
  000005:[d#5,SET-f#6,SET]
L0.0:
  000004:[b#3,SET-e#4,SET]
  000006:[x#7,SET-y#8,SET]
L3:
  000007:[g#1,SET-h#2,SET]

# Files overlap with L0. Files ingested into L0.
target
000000:[b#5,SET-c#5,SET] seqnums:[5-5]
000000:[d#5,SET-e#5,SET] seqnums:[5-5]
----
0
0

# Files overlap with L3. Files ingested into L2.
target
000000:[g#5,SET-m#5,SET] seqnums:[5-5]
----
2

# No overlap. Files ingested into L6.
target
000000:[i#5,SET-m#5,SET] seqnums:[5-5]
000000:[c#5,SET-c#5,SET] seqnums:[5-5]
----
6
6

define
L5
  a.SET.4:4
L5
  c.SET.3:3
L6
  a.SET.2:2
L6
  c.SET.1:1
----
L5:
  000004:[a#4,SET-a#4,SET]
  000005:[c#3,SET-c#3,SET]
L6:
  000006:[a#2,SET-a#2,SET]
  000007:[c#1,SET-c#1,SET]

# The ingested file slips through the gaps in both L5 and L6.
target
000000:[b#5,SET-b#5,SET] seqnums:[5-5]
----
6

define
L5
  a.SET.4:4
L5
  c.SET.3:3
L6
  a.SET.2:2
L6
  c.SET.1:1
  compact:a-c
----
L5:
  000004:[a#4,SET-a#4,SET]
  000005:[c#3,SET-c#3,SET]
L6:
  000006:[a#2,SET-a#2,SET]
  000007:[c#1,SET-c#1,SET]

# The ingested file cannot reach L6 as there is a compaction outputting a file
# into the range [a,c].
target
000000:[b#5,SET-b#5,SET] seqnums:[5-5]
----
5

define
L0
  c.SET.4:4
  d.SET.3:3
  d.RANGEDEL.2:g
L2
  a.RANGEDEL.1:g
----
L0.0:
  000004:[c#4,SET-g#inf,RANGEDEL]
L2:
  000005:[a#1,RANGEDEL-g#inf,RANGEDEL]

# Overlapping cases:
# - The ingested file overlaps with with [c,c].
# - The rangedel over [d,g) keeps the ingested file in L0.
# - Ditto.
target
000000:[c#5,SET-c#5,SET] seqnums:[5-5]
000000:[d#5,SET-d#5,SET] seqnums:[5-5]
000000:[e#5,SET-e#5,SET] seqnums:[5-5]
----
0
0
0

# Non-overlapping cases:
# - The ingested file [cc,cc] slips through L0, but is kept at L1 by the
#   rangedel in L2.
# - The ingested file is to completely to right of all files.
# - The ingested file is to the left of all files in L0, but is kept at L1 by
#   the rangedel in L2.
target
000000:[cc#5,SET-cc#5,SET] seqnums:[5-5]
000000:[g#5,SET-g#5,SET] seqnums:[5-5]
000000:[a#5,SET-a#5,SET] seqnums:[5-5]
----
1
6
1

# A more complicated example demonstrating data overlap.
#            |--|        ingested file: [d-e] - data overlap
#          |-|           ingested file: [cc-d] - no data overlap
#                |--|    ingested file: [ee-ff] - no data overlap
#  |*--*--*----*------*| existing file: [a-g], points: [a, b, c, dd, g]
#  _____________________
#   a  b  c  d  e  f  g
define
L1
  a.SET.0:a
  b.SET.0:b
  c.SET.0:c
  dd.SET.0:dd
  g.SET.0:g
----
L1:
  000004:[a#0,SET-g#0,SET]

# Data overlap.
target
000000:[d#5,SET-e#5,SET] seqnums:[5-5]
----
0

# No data overlap.
target
000000:[cc#5,SET-d#5,SET] seqnums:[5-5]
000000:[ee#5,SET-ff#5,SET] seqnums:[5-5]
----
6
6

# Range key-point key data overlap will always correctly identify overlap because
# we seek using the combined point and range key bounds of the ingested file
# to determine overlap and don't check the data within the ingested file.
define
L5
  a.SET.0:a
  b.SET.0:b
  c.SET.0:c
----
L5:
  000004:[a#0,SET-c#0,SET]

target
000000:[a#5,RANGEKEYDEL-c#inf,RANGEKEYDEL] seqnums:[5-5] ranges:[a#5,RANGEKEYDEL-c#inf,RANGEKEYDEL]
----
4

# Point key-range key overlap
define
L5
  rangekey:a-c:{(#1,RANGEKEYSET,@10,foo)}
----
L5:
  000004:[a#1,RANGEKEYSET-c#inf,RANGEKEYSET]

target
000000:[a#5,SET-c#5,SET] seqnums:[5-5]
----
4

# Range key-range key overlap.
define
L5
  rangekey:a-c:{(#1,RANGEKEYSET,@10,foo)}
----
L5:
  000004:[a#1,RANGEKEYSET-c#inf,RANGEKEYSET]

target
000000:[a#5,RANGEKEYDEL-c#inf,RANGEKEYDEL] seqnums:[5-5] ranges:[a#5,RANGEKEYDEL-c#inf,RANGEKEYDEL]
----
4

# Cases with boundary overlap and no data overlap. With suggest-split off
# we get a target level of L0, but with suggest-split on, we get suggested
# a file split.

define
L6
  a.SET.2:2
  d.SET.3:3
L6
  f.SET.4:4
  k.SET.6:6
----
L6:
  000004:[a#2,SET-d#3,SET]
  000005:[f#4,SET-k#6,SET]

target
000000:[b#5,SET-c#5,SET] seqnums:[5-5]
000000:[e#5,SET-g#5,SET] seqnums:[5-5]
----
5
5

target suggest-split
000000:[b#5,SET-c#5,SET] seqnums:[5-5]
000000:[e#5,SET-g#5,SET] seqnums:[5-5]
----
6 (split file: 000004)
5

target suggest-split
000000:[g#5,SET-i#5,SET] seqnums:[5-5]
----
6 (split file: 000005)

# suggest-split recognizes and avoids in-progress compactions.

define
L6
  a.SET.2:2
  d.SET.3:3
L6
  f.SET.4:4
  k.SET.6:6
  compact:f-k
----
L6:
  000004:[a#2,SET-d#3,SET]
  000005:[f#4,SET-k#6,SET]

target suggest-split
000000:[g#5,SET-i#5,SET] seqnums:[5-5]
----
5

# Ingestion splitting correctly recognizes data overlap in L6, and suggests
# split in L5.

define
L5
  a.SET.2:2
  e.SET.3:3
L6
  c.SET.1:1
  k.SET.1:1
----
L5:
  000004:[a#2,SET-e#3,SET]
L6:
  000005:[c#1,SET-k#1,SET]

target suggest-split
000000:[b#5,SET-c#5,SET] seqnums:[5-5]
----
5 (split file: 000004)

# Exclusive end boundary of ingested sstable is considered.

define
L0
  a.SET.22:22
  g.SET.22:22
L0
  j.RANGEDEL.21:k
  m.SET.21:21
----
L0.0:
  000004:[a#22,SET-g#22,SET]
  000005:[j#21,RANGEDEL-m#21,SET]

target
000000:[i#5,RANGEDEL-j#inf,RANGEDEL] seqnums:[5-5]
----
6
