mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-11-14 04:05:17 +00:00
502 lines
10 KiB
Plaintext
502 lines
10 KiB
Plaintext
|
# Test the scenario illustrated in the below visualization.
|
||
|
#
|
||
|
# ^
|
||
|
# @9 | •―――――――――――――――○ [e,m)@9
|
||
|
# s 8 | • l@8
|
||
|
# u 7 |------------------------------------ @7 masking
|
||
|
# f 6 | [h,q)@6 •―――――――――――――――――○ threshold
|
||
|
# f 5 | • h@5
|
||
|
# f 4 | • n@4
|
||
|
# i 3 | •―――――――――――○ [f,l)@3
|
||
|
# x 2 | • b@2
|
||
|
# 1 |
|
||
|
# 0 |___________________________________
|
||
|
# a b c d e f g h i j k l m n o p q
|
||
|
#
|
||
|
|
||
|
define-rangekeys
|
||
|
e-f:{(#1,RANGEKEYSET,@9,foo)}
|
||
|
f-h:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@3,bar)}
|
||
|
h-l:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax) (#1,RANGEKEYSET,@3,bar)}
|
||
|
l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)}
|
||
|
m-q:{(#1,RANGEKEYSET,@6,bax)}
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
define-pointkeys
|
||
|
b@2.SET.1
|
||
|
h@5.SET.1
|
||
|
l@8.SET.1
|
||
|
n@4.SET.1
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
set-masking-threshold
|
||
|
@7
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
iter
|
||
|
first
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
----
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(nil)
|
||
|
PointKey: b@2#1,1
|
||
|
Span: <invalid>
|
||
|
-
|
||
|
-- SpanChanged(e-f:{(#1,RANGEKEYSET,@9,foo)})
|
||
|
PointKey: e#72057594037927935,21
|
||
|
Span: e-f:{(#1,RANGEKEYSET,@9,foo)}
|
||
|
-
|
||
|
-- SpanChanged(f-h:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@3,bar)})
|
||
|
PointKey: f#72057594037927935,21
|
||
|
Span: f-h:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@3,bar)}
|
||
|
-
|
||
|
-- SpanChanged(h-l:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax) (#1,RANGEKEYSET,@3,bar)})
|
||
|
PointKey: h#72057594037927935,21
|
||
|
Span: h-l:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax) (#1,RANGEKEYSET,@3,bar)}
|
||
|
-
|
||
|
-- SpanChanged(l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)})
|
||
|
PointKey: l#72057594037927935,21
|
||
|
Span: l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)}
|
||
|
-
|
||
|
PointKey: l@8#1,1
|
||
|
Span: l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)}
|
||
|
-
|
||
|
-- SpanChanged(m-q:{(#1,RANGEKEYSET,@6,bax)})
|
||
|
PointKey: m#72057594037927935,21
|
||
|
Span: m-q:{(#1,RANGEKEYSET,@6,bax)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
.
|
||
|
|
||
|
iter
|
||
|
last
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
----
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(m-q:{(#1,RANGEKEYSET,@6,bax)})
|
||
|
PointKey: m#72057594037927935,21
|
||
|
Span: m-q:{(#1,RANGEKEYSET,@6,bax)}
|
||
|
-
|
||
|
-- SpanChanged(l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)})
|
||
|
PointKey: l@8#1,1
|
||
|
Span: l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)}
|
||
|
-
|
||
|
PointKey: l#72057594037927935,21
|
||
|
Span: l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)}
|
||
|
-
|
||
|
-- SpanChanged(h-l:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax) (#1,RANGEKEYSET,@3,bar)})
|
||
|
PointKey: h#72057594037927935,21
|
||
|
Span: h-l:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax) (#1,RANGEKEYSET,@3,bar)}
|
||
|
-
|
||
|
-- SpanChanged(f-h:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@3,bar)})
|
||
|
PointKey: f#72057594037927935,21
|
||
|
Span: f-h:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@3,bar)}
|
||
|
-
|
||
|
-- SpanChanged(e-f:{(#1,RANGEKEYSET,@9,foo)})
|
||
|
PointKey: e#72057594037927935,21
|
||
|
Span: e-f:{(#1,RANGEKEYSET,@9,foo)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
PointKey: b@2#1,1
|
||
|
Span: <invalid>
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
.
|
||
|
|
||
|
iter
|
||
|
seek-ge a
|
||
|
seek-ge c
|
||
|
seek-ge h
|
||
|
seek-ge i
|
||
|
seek-ge l
|
||
|
next
|
||
|
seek-ge m
|
||
|
seek-ge r
|
||
|
----
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(nil)
|
||
|
PointKey: b@2#1,1
|
||
|
Span: <invalid>
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(e-f:{(#1,RANGEKEYSET,@9,foo)})
|
||
|
PointKey: e#72057594037927935,21
|
||
|
Span: e-f:{(#1,RANGEKEYSET,@9,foo)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(h-l:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax) (#1,RANGEKEYSET,@3,bar)})
|
||
|
PointKey: h#72057594037927935,21
|
||
|
Span: h-l:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax) (#1,RANGEKEYSET,@3,bar)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(h-l:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax) (#1,RANGEKEYSET,@3,bar)})
|
||
|
PointKey: i#72057594037927935,21
|
||
|
Span: h-l:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax) (#1,RANGEKEYSET,@3,bar)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)})
|
||
|
PointKey: l#72057594037927935,21
|
||
|
Span: l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)}
|
||
|
-
|
||
|
PointKey: l@8#1,1
|
||
|
Span: l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(m-q:{(#1,RANGEKEYSET,@6,bax)})
|
||
|
PointKey: m#72057594037927935,21
|
||
|
Span: m-q:{(#1,RANGEKEYSET,@6,bax)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(nil)
|
||
|
.
|
||
|
|
||
|
# Setting the masking threshold to @9 should result in l@8 being masked by
|
||
|
# [e,m)@9.
|
||
|
|
||
|
set-masking-threshold
|
||
|
@9
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
iter
|
||
|
seek-ge l
|
||
|
next
|
||
|
seek-lt l
|
||
|
seek-lt ll
|
||
|
prev
|
||
|
----
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)})
|
||
|
PointKey: l#72057594037927935,21
|
||
|
Span: l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)}
|
||
|
-
|
||
|
-- SpanChanged(m-q:{(#1,RANGEKEYSET,@6,bax)})
|
||
|
PointKey: m#72057594037927935,21
|
||
|
Span: m-q:{(#1,RANGEKEYSET,@6,bax)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(h-l:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax) (#1,RANGEKEYSET,@3,bar)})
|
||
|
PointKey: h#72057594037927935,21
|
||
|
Span: h-l:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax) (#1,RANGEKEYSET,@3,bar)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)})
|
||
|
PointKey: l#72057594037927935,21
|
||
|
Span: l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)}
|
||
|
-
|
||
|
-- SpanChanged(h-l:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax) (#1,RANGEKEYSET,@3,bar)})
|
||
|
PointKey: h#72057594037927935,21
|
||
|
Span: h-l:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax) (#1,RANGEKEYSET,@3,bar)}
|
||
|
-
|
||
|
|
||
|
iter
|
||
|
seek-ge l
|
||
|
next
|
||
|
----
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)})
|
||
|
PointKey: l#72057594037927935,21
|
||
|
Span: l-m:{(#1,RANGEKEYSET,@9,foo) (#1,RANGEKEYSET,@6,bax)}
|
||
|
-
|
||
|
-- SpanChanged(m-q:{(#1,RANGEKEYSET,@6,bax)})
|
||
|
PointKey: m#72057594037927935,21
|
||
|
Span: m-q:{(#1,RANGEKEYSET,@6,bax)}
|
||
|
-
|
||
|
|
||
|
define-rangekeys
|
||
|
a-c:{(#1,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@2,bananas)}
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
define-pointkeys
|
||
|
a.SET.1
|
||
|
a@3.SET.1
|
||
|
a@12.SET.1
|
||
|
b@2.SET.1
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
set-masking-threshold
|
||
|
@10
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
# Test that both a@3 and b@2 are masked by the rangekey.
|
||
|
# The unsuffixed point key 'a' and the point key at a higher timestamp 'a@12'
|
||
|
# are not masked.
|
||
|
|
||
|
iter
|
||
|
first
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
----
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(a-c:{(#1,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@2,bananas)})
|
||
|
PointKey: a#72057594037927935,21
|
||
|
Span: a-c:{(#1,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@2,bananas)}
|
||
|
-
|
||
|
PointKey: a#1,1
|
||
|
Span: a-c:{(#1,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@2,bananas)}
|
||
|
-
|
||
|
PointKey: a@12#1,1
|
||
|
Span: a-c:{(#1,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@2,bananas)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
.
|
||
|
|
||
|
iter
|
||
|
last
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
----
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(a-c:{(#1,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@2,bananas)})
|
||
|
PointKey: a@12#1,1
|
||
|
Span: a-c:{(#1,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@2,bananas)}
|
||
|
-
|
||
|
PointKey: a#1,1
|
||
|
Span: a-c:{(#1,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@2,bananas)}
|
||
|
-
|
||
|
PointKey: a#72057594037927935,21
|
||
|
Span: a-c:{(#1,RANGEKEYSET,@5,apples) (#1,RANGEKEYSET,@2,bananas)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
.
|
||
|
|
||
|
# Try the same test, but with a range key that sorts before the masking
|
||
|
# threshold (eg, higher MVCC timestamp). Nothing should be masked.
|
||
|
|
||
|
define-rangekeys
|
||
|
a-c:{(#2,RANGEKEYSET,@20,apples)}
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
iter
|
||
|
first
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
----
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(a-c:{(#2,RANGEKEYSET,@20,apples)})
|
||
|
PointKey: a#72057594037927935,21
|
||
|
Span: a-c:{(#2,RANGEKEYSET,@20,apples)}
|
||
|
-
|
||
|
PointKey: a#1,1
|
||
|
Span: a-c:{(#2,RANGEKEYSET,@20,apples)}
|
||
|
-
|
||
|
PointKey: a@3#1,1
|
||
|
Span: a-c:{(#2,RANGEKEYSET,@20,apples)}
|
||
|
-
|
||
|
PointKey: a@12#1,1
|
||
|
Span: a-c:{(#2,RANGEKEYSET,@20,apples)}
|
||
|
-
|
||
|
PointKey: b@2#1,1
|
||
|
Span: a-c:{(#2,RANGEKEYSET,@20,apples)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
.
|
||
|
|
||
|
iter
|
||
|
last
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
----
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(a-c:{(#2,RANGEKEYSET,@20,apples)})
|
||
|
PointKey: b@2#1,1
|
||
|
Span: a-c:{(#2,RANGEKEYSET,@20,apples)}
|
||
|
-
|
||
|
PointKey: a@12#1,1
|
||
|
Span: a-c:{(#2,RANGEKEYSET,@20,apples)}
|
||
|
-
|
||
|
PointKey: a@3#1,1
|
||
|
Span: a-c:{(#2,RANGEKEYSET,@20,apples)}
|
||
|
-
|
||
|
PointKey: a#1,1
|
||
|
Span: a-c:{(#2,RANGEKEYSET,@20,apples)}
|
||
|
-
|
||
|
PointKey: a#72057594037927935,21
|
||
|
Span: a-c:{(#2,RANGEKEYSET,@20,apples)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
.
|
||
|
|
||
|
# Try the original test, but with an internal range key containing just an
|
||
|
# Unset, and no Set. Nothing should be masked. No range keys should be surfaced,
|
||
|
# because there are none.
|
||
|
|
||
|
define-rangekeys
|
||
|
a-c:{(#1,RANGEKEYUNSET,@5) (#1,RANGEKEYUNSET,@2)}
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
iter
|
||
|
first
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
----
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(a-c:{(#1,RANGEKEYUNSET,@5) (#1,RANGEKEYUNSET,@2)})
|
||
|
PointKey: a#72057594037927935,20
|
||
|
Span: a-c:{(#1,RANGEKEYUNSET,@5) (#1,RANGEKEYUNSET,@2)}
|
||
|
-
|
||
|
PointKey: a#1,1
|
||
|
Span: a-c:{(#1,RANGEKEYUNSET,@5) (#1,RANGEKEYUNSET,@2)}
|
||
|
-
|
||
|
PointKey: a@12#1,1
|
||
|
Span: a-c:{(#1,RANGEKEYUNSET,@5) (#1,RANGEKEYUNSET,@2)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
.
|
||
|
-- SpanChanged(nil)
|
||
|
.
|
||
|
|
||
|
iter
|
||
|
last
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
prev
|
||
|
----
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(a-c:{(#1,RANGEKEYUNSET,@5) (#1,RANGEKEYUNSET,@2)})
|
||
|
PointKey: a@12#1,1
|
||
|
Span: a-c:{(#1,RANGEKEYUNSET,@5) (#1,RANGEKEYUNSET,@2)}
|
||
|
-
|
||
|
PointKey: a#1,1
|
||
|
Span: a-c:{(#1,RANGEKEYUNSET,@5) (#1,RANGEKEYUNSET,@2)}
|
||
|
-
|
||
|
PointKey: a#72057594037927935,20
|
||
|
Span: a-c:{(#1,RANGEKEYUNSET,@5) (#1,RANGEKEYUNSET,@2)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
.
|
||
|
-- SpanChanged(nil)
|
||
|
.
|
||
|
|
||
|
# Test a scenario where a point key is masked in the forward direction, which in
|
||
|
# turn requires nexting to the next range key as well.
|
||
|
|
||
|
define-rangekeys
|
||
|
a-c:{(#1,RANGEKEYSET,@5,apples)}
|
||
|
c-z:{(#1,RANGEKEYSET,@10,bananas)}
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
define-pointkeys
|
||
|
b@3.SET.2
|
||
|
d@9.SET.4
|
||
|
j@11.SET.3
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
set-masking-threshold
|
||
|
@20
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
iter
|
||
|
first
|
||
|
next
|
||
|
next
|
||
|
----
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(a-c:{(#1,RANGEKEYSET,@5,apples)})
|
||
|
PointKey: a#72057594037927935,21
|
||
|
Span: a-c:{(#1,RANGEKEYSET,@5,apples)}
|
||
|
-
|
||
|
-- SpanChanged(c-z:{(#1,RANGEKEYSET,@10,bananas)})
|
||
|
PointKey: c#72057594037927935,21
|
||
|
Span: c-z:{(#1,RANGEKEYSET,@10,bananas)}
|
||
|
-
|
||
|
PointKey: j@11#3,1
|
||
|
Span: c-z:{(#1,RANGEKEYSET,@10,bananas)}
|
||
|
-
|
||
|
|
||
|
iter
|
||
|
last
|
||
|
prev
|
||
|
prev
|
||
|
----
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(c-z:{(#1,RANGEKEYSET,@10,bananas)})
|
||
|
PointKey: j@11#3,1
|
||
|
Span: c-z:{(#1,RANGEKEYSET,@10,bananas)}
|
||
|
-
|
||
|
PointKey: c#72057594037927935,21
|
||
|
Span: c-z:{(#1,RANGEKEYSET,@10,bananas)}
|
||
|
-
|
||
|
-- SpanChanged(a-c:{(#1,RANGEKEYSET,@5,apples)})
|
||
|
PointKey: a#72057594037927935,21
|
||
|
Span: a-c:{(#1,RANGEKEYSET,@5,apples)}
|
||
|
-
|
||
|
|
||
|
# Test a scenario where a there's an empty range key, requiring the interleaving
|
||
|
# iter to call SpanChanged(nil) which should clear the previous mask.
|
||
|
|
||
|
define-rangekeys
|
||
|
a-c:{(#1,RANGEKEYSET,@10,apples)}
|
||
|
c-e:{}
|
||
|
e-f:{(#1,RANGEKEYSET,@5,bananas)}
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
define-pointkeys
|
||
|
a@2.SET.4
|
||
|
b@9.SET.2
|
||
|
d@9.SET.3
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
set-masking-threshold
|
||
|
@20
|
||
|
----
|
||
|
OK
|
||
|
|
||
|
iter
|
||
|
seek-ge a
|
||
|
next
|
||
|
next
|
||
|
next
|
||
|
----
|
||
|
-- SpanChanged(nil)
|
||
|
-- SpanChanged(a-c:{(#1,RANGEKEYSET,@10,apples)})
|
||
|
PointKey: a#72057594037927935,21
|
||
|
Span: a-c:{(#1,RANGEKEYSET,@10,apples)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
PointKey: d@9#3,1
|
||
|
Span: <invalid>
|
||
|
-
|
||
|
-- SpanChanged(e-f:{(#1,RANGEKEYSET,@5,bananas)})
|
||
|
PointKey: e#72057594037927935,21
|
||
|
Span: e-f:{(#1,RANGEKEYSET,@5,bananas)}
|
||
|
-
|
||
|
-- SpanChanged(nil)
|
||
|
.
|