-
Notifications
You must be signed in to change notification settings - Fork 563
/
splice
193 lines (173 loc) · 4.01 KB
/
splice
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# Splicing at index 0 should fail.
!splice 0@1=foo
---
Panic: spliced entry has index or term 0
# Splicing at index 2 should fail (creates gap).
!splice 2@1=foo
---
Panic: first index 2 must touch existing log
# Splicing entries at start should work, both with and without commands, and
# starting at a term after 1. They should be written to the engine and flushed
# to durable storage. It should also update the state.
splice 1@2= 2@2=command oplog=true
status
scan
---
engine: set Entry(1) 0x000000000000000001 = 0x010200
engine: set Entry(2) 0x000000000000000002 = 0x02020107636f6d6d616e64
engine: flush
splice → 2@2 command
last=2@2 commit=0@0
1@2 None
2@2 command
# Splicing an empty list should work and be a noop.
splice oplog=true
status
scan
---
splice → 2@2 command
last=2@2 commit=0@0
1@2 None
2@2 command
# Splicing multiple duplicate entries should fail.
!splice 3@2= 3@2=
---
Panic: spliced entries are not contiguous
# Splicing entries with a gap should fail.
!splice 3@2= 5@2=
---
Panic: spliced entries are not contiguous
# Splicing entries with a term regression should fail.
!splice 3@2= 4@1=
---
Panic: spliced entries have term regression
# Splicing entries with a gap from the base should fail.
!splice 4@2=
---
Panic: first index 4 must touch existing log
# Splicing with a term regression from the base should fail.
!splice 3@1=
---
Panic: splice term regression 2 → 1
# Fully overlapping entries is a noop.
splice 1@2= 2@2=command oplog=true
scan
---
splice → 2@2 command
1@2 None
2@2 command
# An overlapping prefix is a noop.
splice 1@2= oplog=true
scan
---
splice → 2@2 command
1@2 None
2@2 command
# An overlapping suffix is a noop.
splice 2@2=command oplog=true
scan
---
splice → 2@2 command
1@2 None
2@2 command
# Changing a command with the same term/index should fail.
!splice 2@2=foo
scan
---
Panic: command mismatch at Entry { index: 2, term: 2, command: Some([99, 111, 109, 109, 97, 110, 100]) }
1@2 None
2@2 command
# Appending a new entry in the same term should work, as should
# appending one in a new term.
splice 3@2=bar
splice 4@3=
scan
---
splice → 3@2 bar
splice → 4@3 None
1@2 None
2@2 command
3@2 bar
4@3 None
# Splicing with suffix overlap should work, and only write the new entries.
splice 3@2=bar 4@3= 5@3=foo 6@3=bar oplog=true
scan
---
engine: set Entry(5) 0x000000000000000005 = 0x05030103666f6f
engine: set Entry(6) 0x000000000000000006 = 0x06030103626172
engine: flush
splice → 6@3 bar
1@2 None
2@2 command
3@2 bar
4@3 None
5@3 foo
6@3 bar
# Splicing at an existing index with a new term should replace the tail.
splice 4@4= oplog=true
status
scan
---
engine: set Entry(4) 0x000000000000000004 = 0x040400
engine: delete Entry(5) 0x000000000000000005
engine: delete Entry(6) 0x000000000000000006
engine: flush
splice → 4@4 None
last=4@4 commit=0@0
1@2 None
2@2 command
3@2 bar
4@4 None
# This also holds at the start of the log.
splice 1@5= 2@5=foo 3@5=bar oplog=true
status
scan
---
engine: set Entry(1) 0x000000000000000001 = 0x010500
engine: set Entry(2) 0x000000000000000002 = 0x02050103666f6f
engine: set Entry(3) 0x000000000000000003 = 0x03050103626172
engine: delete Entry(4) 0x000000000000000004
engine: flush
splice → 3@5 bar
last=3@5 commit=0@0
1@5 None
2@5 foo
3@5 bar
# Splicing across the commit index should work, as long as the entries match.
commit 2
splice 1@5= 2@5=foo 3@5=bar 4@5=
status
scan
---
commit → 2@5 foo
splice → 4@5 None
last=4@5 commit=2@5
1@5 None
2@5 foo
3@5 bar
4@5 None
# Splicing across the commit index can replace a tail after the commit index.
splice 3@6= 4@6=bar
status
scan
---
splice → 4@6 bar
last=4@6 commit=2@5
1@5 None
2@5 foo
3@6 None
4@6 bar
# But replacing a tail at or before the commit index should fail.
!splice 2@7=
!splice 1@7=
---
Panic: spliced entries below commit index
Panic: spliced entries below commit index
# Dump the raw data.
dump
---
Entry(1) 0x000000000000000001 = 0x010500
Entry(2) 0x000000000000000002 = 0x02050103666f6f
Entry(3) 0x000000000000000003 = 0x030600
Entry(4) 0x000000000000000004 = 0x04060103626172
CommitIndex 0x02 = 0x0205