##// END OF EJS Templates
test-tx-rollback: more lenient glob for kill status (issue6807)...
pacien -
r51277:2231f7d8 stable
parent child Browse files
Show More
@@ -1,428 +1,428 b''
1 1 Test correctness of revlog inline -> non-inline transition
2 2 ----------------------------------------------------------
3 3
4 4 Helper extension to intercept renames and kill process
5 5
6 6 $ cat > $TESTTMP/intercept_before_rename.py << EOF
7 7 > import os
8 8 > import signal
9 9 > from mercurial import extensions, util
10 10 >
11 11 > def extsetup(ui):
12 12 > def rename(orig, src, dest, *args, **kwargs):
13 13 > path = util.normpath(dest)
14 14 > if path.endswith(b'data/file.i'):
15 15 > os.kill(os.getpid(), signal.SIGKILL)
16 16 > return orig(src, dest, *args, **kwargs)
17 17 > extensions.wrapfunction(util, 'rename', rename)
18 18 > EOF
19 19
20 20 $ cat > $TESTTMP/intercept_after_rename.py << EOF
21 21 > import os
22 22 > import signal
23 23 > from mercurial import extensions, util
24 24 >
25 25 > def extsetup(ui):
26 26 > def close(orig, *args, **kwargs):
27 27 > path = util.normpath(args[0]._atomictempfile__name)
28 28 > r = orig(*args, **kwargs)
29 29 > if path.endswith(b'/.hg/store/data/file.i'):
30 30 > os.kill(os.getpid(), signal.SIGKILL)
31 31 > return r
32 32 > extensions.wrapfunction(util.atomictempfile, 'close', close)
33 33 > def extsetup(ui):
34 34 > def rename(orig, src, dest, *args, **kwargs):
35 35 > path = util.normpath(dest)
36 36 > r = orig(src, dest, *args, **kwargs)
37 37 > if path.endswith(b'data/file.i'):
38 38 > os.kill(os.getpid(), signal.SIGKILL)
39 39 > return r
40 40 > extensions.wrapfunction(util, 'rename', rename)
41 41 > EOF
42 42
43 43 $ cat > $TESTTMP/killme.py << EOF
44 44 > import os
45 45 > import signal
46 46 >
47 47 > def killme(ui, repo, hooktype, **kwargs):
48 48 > os.kill(os.getpid(), signal.SIGKILL)
49 49 > EOF
50 50
51 51 $ cat > $TESTTMP/reader_wait_split.py << EOF
52 52 > import os
53 53 > import signal
54 54 > from mercurial import extensions, revlog, testing
55 55 > def _wait_post_load(orig, self, *args, **kwargs):
56 56 > wait = b'data/file' in self.radix
57 57 > if wait:
58 58 > testing.wait_file(b"$TESTTMP/writer-revlog-split")
59 59 > r = orig(self, *args, **kwargs)
60 60 > if wait:
61 61 > testing.write_file(b"$TESTTMP/reader-index-read")
62 62 > testing.wait_file(b"$TESTTMP/writer-revlog-unsplit")
63 63 > return r
64 64 >
65 65 > def extsetup(ui):
66 66 > extensions.wrapfunction(revlog.revlog, '_loadindex', _wait_post_load)
67 67 > EOF
68 68
69 69 setup a repository for tests
70 70 ----------------------------
71 71
72 72 $ cat >> $HGRCPATH << EOF
73 73 > [format]
74 74 > revlog-compression=none
75 75 > EOF
76 76
77 77 $ hg init troffset-computation
78 78 $ cd troffset-computation
79 79 $ printf '%20d' '1' > file
80 80 $ hg commit -Aqma
81 81 $ printf '%1024d' '1' > file
82 82 $ hg commit -Aqmb
83 83 $ printf '%20d' '1' > file
84 84 $ hg commit -Aqmc
85 85 $ dd if=/dev/zero of=file bs=1k count=128 > /dev/null 2>&1
86 86 $ hg commit -AqmD --traceback
87 87
88 88 Reference size:
89 89 $ f -s file
90 90 file: size=131072
91 91 $ f -s .hg/store/data/file*
92 92 .hg/store/data/file.d: size=132139
93 93 .hg/store/data/file.i: size=256
94 94
95 95 $ cd ..
96 96
97 97
98 98 Test a hard crash after the file was split but before the transaction was committed
99 99 ===================================================================================
100 100
101 101 Test offset computation to correctly factor in the index entries themselves.
102 102 Also test that the new data size has the correct size if the transaction is aborted
103 103 after the index has been replaced.
104 104
105 105 Test repo has commits a, b, c, D, where D is large (grows the revlog enough that it
106 106 transitions to non-inline storage). The clone initially has changes a, b
107 107 and will transition to non-inline storage when adding c, D.
108 108
109 109 If the transaction adding c, D is rolled back, then we don't undo the revlog split,
110 110 but truncate the index and the data to remove both c and D.
111 111
112 112
113 113 $ hg clone --quiet --rev 1 troffset-computation troffset-computation-copy
114 114 $ cd troffset-computation-copy
115 115
116 116 Reference size:
117 117 $ f -s file
118 118 file: size=1024
119 119 $ f -s .hg/store/data/file*
120 120 .hg/store/data/file.i: size=1174
121 121
122 122 $ cat > .hg/hgrc <<EOF
123 123 > [hooks]
124 124 > pretxnchangegroup = python:$TESTTMP/killme.py:killme
125 125 > EOF
126 126 #if chg
127 127 $ hg pull ../troffset-computation
128 128 pulling from ../troffset-computation
129 129 [255]
130 130 #else
131 131 $ hg pull ../troffset-computation
132 132 pulling from ../troffset-computation
133 Killed
133 *Killed* (glob)
134 134 [137]
135 135 #endif
136 136
137 137
138 138 The inline revlog still exist, but a split version exist next to it
139 139
140 140 $ f -s .hg/store/data/file*
141 141 .hg/store/data/file.d: size=132139
142 142 .hg/store/data/file.i: size=132395
143 143 .hg/store/data/file.i.s: size=256
144 144
145 145
146 146 The first file.i entry should match the "Reference size" above.
147 147 The first file.d entry is the temporary record during the split,
148 148
149 149 A "temporary file" entry exist for the split index.
150 150
151 151 $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file
152 152 data/file.i 1174
153 153 data/file.d 0
154 154 $ cat .hg/store/journal.backupfiles | tr -s '\000' ' ' | tr -s '\00' ' '| grep data/file
155 155 data/file.i data/journal.backup.file.i 0
156 156 data/file.i.s 0
157 157
158 158 recover is rolling the split back, the fncache is still valid
159 159
160 160 $ hg recover
161 161 rolling back interrupted transaction
162 162 (verify step skipped, run `hg verify` to check your repository content)
163 163 $ f -s .hg/store/data/file*
164 164 .hg/store/data/file.i: size=1174
165 165 $ hg tip
166 166 changeset: 1:cfa8d6e60429
167 167 tag: tip
168 168 user: test
169 169 date: Thu Jan 01 00:00:00 1970 +0000
170 170 summary: b
171 171
172 172 $ hg verify -q
173 173 $ hg debugrebuildfncache --only-data
174 174 fncache already up to date
175 175 $ hg verify -q
176 176 $ cd ..
177 177
178 178 Test a hard crash right before the index is move into place
179 179 ===========================================================
180 180
181 181 Now retry the procedure but intercept the rename of the index and check that
182 182 the journal does not contain the new index size. This demonstrates the edge case
183 183 where the data file is left as garbage.
184 184
185 185 $ hg clone --quiet --rev 1 troffset-computation troffset-computation-copy2
186 186 $ cd troffset-computation-copy2
187 187
188 188 Reference size:
189 189 $ f -s file
190 190 file: size=1024
191 191 $ f -s .hg/store/data/file*
192 192 .hg/store/data/file.i: size=1174
193 193
194 194 $ cat > .hg/hgrc <<EOF
195 195 > [extensions]
196 196 > intercept_rename = $TESTTMP/intercept_before_rename.py
197 197 > EOF
198 198 #if chg
199 199 $ hg pull ../troffset-computation
200 200 pulling from ../troffset-computation
201 201 searching for changes
202 202 adding changesets
203 203 adding manifests
204 204 adding file changes
205 205 [255]
206 206 #else
207 207 $ hg pull ../troffset-computation
208 208 pulling from ../troffset-computation
209 209 searching for changes
210 210 adding changesets
211 211 adding manifests
212 212 adding file changes
213 Killed
213 *Killed* (glob)
214 214 [137]
215 215 #endif
216 216
217 217 The inline revlog still exist, but a split version exist next to it
218 218
219 219 $ f -s .hg/store/data/file*
220 220 .hg/store/data/file.d: size=132139
221 221 .hg/store/data/file.i: size=132395
222 222 .hg/store/data/file.i.s: size=256
223 223
224 224 $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file
225 225 data/file.i 1174
226 226 data/file.d 0
227 227
228 228 recover is rolling the split back, the fncache is still valid
229 229
230 230 $ hg recover
231 231 rolling back interrupted transaction
232 232 (verify step skipped, run `hg verify` to check your repository content)
233 233 $ f -s .hg/store/data/file*
234 234 .hg/store/data/file.i: size=1174
235 235 $ hg tip
236 236 changeset: 1:cfa8d6e60429
237 237 tag: tip
238 238 user: test
239 239 date: Thu Jan 01 00:00:00 1970 +0000
240 240 summary: b
241 241
242 242 $ hg verify -q
243 243 $ cd ..
244 244
245 245 Test a hard crash right after the index is move into place
246 246 ===========================================================
247 247
248 248 Now retry the procedure but intercept the rename of the index.
249 249
250 250 $ hg clone --quiet --rev 1 troffset-computation troffset-computation-crash-after-rename
251 251 $ cd troffset-computation-crash-after-rename
252 252
253 253 Reference size:
254 254 $ f -s file
255 255 file: size=1024
256 256 $ f -s .hg/store/data/file*
257 257 .hg/store/data/file.i: size=1174
258 258
259 259 $ cat > .hg/hgrc <<EOF
260 260 > [extensions]
261 261 > intercept_rename = $TESTTMP/intercept_after_rename.py
262 262 > EOF
263 263 #if chg
264 264 $ hg pull ../troffset-computation
265 265 pulling from ../troffset-computation
266 266 searching for changes
267 267 adding changesets
268 268 adding manifests
269 269 adding file changes
270 270 [255]
271 271 #else
272 272 $ hg pull ../troffset-computation
273 273 pulling from ../troffset-computation
274 274 searching for changes
275 275 adding changesets
276 276 adding manifests
277 277 adding file changes
278 Killed
278 *Killed* (glob)
279 279 [137]
280 280 #endif
281 281
282 282 The inline revlog was over written on disk
283 283
284 284 $ f -s .hg/store/data/file*
285 285 .hg/store/data/file.d: size=132139
286 286 .hg/store/data/file.i: size=256
287 287
288 288 $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file
289 289 data/file.i 1174
290 290 data/file.d 0
291 291
292 292 recover is rolling the split back, the fncache is still valid
293 293
294 294 $ hg recover
295 295 rolling back interrupted transaction
296 296 (verify step skipped, run `hg verify` to check your repository content)
297 297 $ f -s .hg/store/data/file*
298 298 .hg/store/data/file.i: size=1174
299 299 $ hg tip
300 300 changeset: 1:cfa8d6e60429
301 301 tag: tip
302 302 user: test
303 303 date: Thu Jan 01 00:00:00 1970 +0000
304 304 summary: b
305 305
306 306 $ hg verify -q
307 307 $ cd ..
308 308
309 309 Have the transaction rollback itself without any hard crash
310 310 ===========================================================
311 311
312 312
313 313 Repeat the original test but let hg rollback the transaction.
314 314
315 315 $ hg clone --quiet --rev 1 troffset-computation troffset-computation-copy-rb
316 316 $ cd troffset-computation-copy-rb
317 317 $ cat > .hg/hgrc <<EOF
318 318 > [hooks]
319 319 > pretxnchangegroup = false
320 320 > EOF
321 321 $ hg pull ../troffset-computation
322 322 pulling from ../troffset-computation
323 323 searching for changes
324 324 adding changesets
325 325 adding manifests
326 326 adding file changes
327 327 transaction abort!
328 328 rollback completed
329 329 abort: pretxnchangegroup hook exited with status 1
330 330 [40]
331 331
332 332 The split was rollback
333 333
334 334 $ f -s .hg/store/data/file*
335 335 .hg/store/data/file.d: size=0
336 336 .hg/store/data/file.i: size=1174
337 337
338 338
339 339 $ hg tip
340 340 changeset: 1:cfa8d6e60429
341 341 tag: tip
342 342 user: test
343 343 date: Thu Jan 01 00:00:00 1970 +0000
344 344 summary: b
345 345
346 346 $ hg verify -q
347 347 $ cd ..
348 348
349 349 Read race
350 350 =========
351 351
352 352 We check that a client that started reading a revlog (its index) after the
353 353 split and end reading (the data) after the rollback should be fine
354 354
355 355 $ hg clone --quiet --rev 1 troffset-computation troffset-computation-race
356 356 $ cd troffset-computation-race
357 357 $ cat > .hg/hgrc <<EOF
358 358 > [hooks]
359 359 > pretxnchangegroup=$RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/reader-index-read $TESTTMP/writer-revlog-split
360 360 > pretxnclose = false
361 361 > EOF
362 362
363 363 start a reader
364 364
365 365 $ hg cat --rev 0 file \
366 366 > --config "extensions.wait_read=$TESTTMP/reader_wait_split.py" \
367 367 > 2> $TESTTMP/reader.stderr \
368 368 > > $TESTTMP/reader.stdout &
369 369
370 370 Do a failed pull in //
371 371
372 372 $ hg pull ../troffset-computation
373 373 pulling from ../troffset-computation
374 374 searching for changes
375 375 adding changesets
376 376 adding manifests
377 377 adding file changes
378 378 transaction abort!
379 379 rollback completed
380 380 abort: pretxnclose hook exited with status 1
381 381 [40]
382 382 $ touch $TESTTMP/writer-revlog-unsplit
383 383 $ wait
384 384
385 385 The reader should be fine
386 386 $ cat $TESTTMP/reader.stderr
387 387 $ cat $TESTTMP/reader.stdout
388 388 1 (no-eol)
389 389 $ cd ..
390 390
391 391 pending hooks
392 392 =============
393 393
394 394 We checks that hooks properly see the inside of the transaction, while other process don't.
395 395
396 396 $ hg clone --quiet --rev 1 troffset-computation troffset-computation-hooks
397 397 $ cd troffset-computation-hooks
398 398 $ cat > .hg/hgrc <<EOF
399 399 > [hooks]
400 400 > pretxnclose.01-echo = hg cat -r 'max(all())' file | f --size
401 401 > pretxnclose.02-echo = $RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/hook-done $TESTTMP/hook-tr-ready
402 402 > pretxnclose.03-abort = false
403 403 > EOF
404 404
405 405 $ (
406 406 > $RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/hook-tr-ready;\
407 407 > hg cat -r 'max(all())' file | f --size;\
408 408 > touch $TESTTMP/hook-done
409 409 > ) >stdout 2>stderr &
410 410
411 411 $ hg pull ../troffset-computation
412 412 pulling from ../troffset-computation
413 413 searching for changes
414 414 adding changesets
415 415 adding manifests
416 416 adding file changes
417 417 size=131072
418 418 transaction abort!
419 419 rollback completed
420 420 abort: pretxnclose.03-abort hook exited with status 1
421 421 [40]
422 422
423 423 $ cat stdout
424 424 size=1024
425 425 $ cat stderr
426 426
427 427
428 428 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now