tests/test-transaction-rollback-on-revlog-split.t
branchstable
changeset 50316 87f0155d68aa
parent 50314 6487737e0f00
child 50334 2231f7d8a602
equal deleted inserted replaced
50315:cf6e1d535602 50316:87f0155d68aa
     7   > import os
     7   > import os
     8   > import signal
     8   > import signal
     9   > from mercurial import extensions, util
     9   > from mercurial import extensions, util
    10   > 
    10   > 
    11   > def extsetup(ui):
    11   > def extsetup(ui):
    12   >     def close(orig, *args, **kwargs):
    12   >     def rename(orig, src, dest, *args, **kwargs):
    13   >         path = util.normpath(args[0]._atomictempfile__name)
    13   >         path = util.normpath(dest)
    14   >         if path.endswith(b'/.hg/store/data/file.i'):
    14   >         if path.endswith(b'data/file.i'):
    15   >             os.kill(os.getpid(), signal.SIGKILL)
    15   >             os.kill(os.getpid(), signal.SIGKILL)
    16   >         return orig(*args, **kwargs)
    16   >         return orig(src, dest, *args, **kwargs)
    17   >     extensions.wrapfunction(util.atomictempfile, 'close', close)
    17   >     extensions.wrapfunction(util, 'rename', rename)
    18   > EOF
    18   > EOF
    19 
    19 
    20   $ cat > $TESTTMP/intercept_after_rename.py << EOF
    20   $ cat > $TESTTMP/intercept_after_rename.py << EOF
    21   > import os
    21   > import os
    22   > import signal
    22   > import signal
    28   >         r = orig(*args, **kwargs)
    28   >         r = orig(*args, **kwargs)
    29   >         if path.endswith(b'/.hg/store/data/file.i'):
    29   >         if path.endswith(b'/.hg/store/data/file.i'):
    30   >             os.kill(os.getpid(), signal.SIGKILL)
    30   >             os.kill(os.getpid(), signal.SIGKILL)
    31   >         return r
    31   >         return r
    32   >     extensions.wrapfunction(util.atomictempfile, 'close', close)
    32   >     extensions.wrapfunction(util.atomictempfile, 'close', close)
       
    33   > def extsetup(ui):
       
    34   >     def rename(orig, src, dest, *args, **kwargs):
       
    35   >         path = util.normpath(dest)
       
    36   >         r = orig(src, dest, *args, **kwargs)
       
    37   >         if path.endswith(b'data/file.i'):
       
    38   >             os.kill(os.getpid(), signal.SIGKILL)
       
    39   >         return r
       
    40   >     extensions.wrapfunction(util, 'rename', rename)
    33   > EOF
    41   > EOF
    34 
    42 
    35   $ cat > $TESTTMP/killme.py << EOF
    43   $ cat > $TESTTMP/killme.py << EOF
    36   > import os
    44   > import os
    37   > import signal
    45   > import signal
    73   $ printf '%1024d' '1' > file
    81   $ printf '%1024d' '1' > file
    74   $ hg commit -Aqmb
    82   $ hg commit -Aqmb
    75   $ printf '%20d' '1' > file
    83   $ printf '%20d' '1' > file
    76   $ hg commit -Aqmc
    84   $ hg commit -Aqmc
    77   $ dd if=/dev/zero of=file bs=1k count=128 > /dev/null 2>&1
    85   $ dd if=/dev/zero of=file bs=1k count=128 > /dev/null 2>&1
    78   $ hg commit -AqmD
    86   $ hg commit -AqmD --traceback
    79 
    87 
    80 Reference size:
    88 Reference size:
    81   $ f -s file
    89   $ f -s file
    82   file: size=131072
    90   file: size=131072
    83   $ f -s .hg/store/data/file*
    91   $ f -s .hg/store/data/file*
   125   Killed
   133   Killed
   126   [137]
   134   [137]
   127 #endif
   135 #endif
   128 
   136 
   129 
   137 
   130 The revlog have been split on disk
   138 The inline revlog still exist, but a split version exist next to it
   131 
   139 
   132   $ f -s .hg/store/data/file*
   140   $ f -s .hg/store/data/file*
   133   .hg/store/data/file.d: size=132139
   141   .hg/store/data/file.d: size=132139
   134   .hg/store/data/file.i: size=256
   142   .hg/store/data/file.i: size=132395
   135 
   143   .hg/store/data/file.i.s: size=256
   136   $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file | tail -1
   144 
   137   data/file.i 128
       
   138 
   145 
   139 The first file.i entry should match the "Reference size" above.
   146 The first file.i entry should match the "Reference size" above.
   140 The first file.d entry is the temporary record during the split,
   147 The first file.d entry is the temporary record during the split,
   141 
   148 
   142 The second entry after the split happened. The sum of the second file.d
   149 A "temporary file" entry exist for the split index.
   143 and the second file.i entry should match the first file.i entry.
       
   144 
   150 
   145   $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file
   151   $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file
   146   data/file.i 1174
   152   data/file.i 1174
   147   data/file.d 0
   153   data/file.d 0
   148   data/file.d 1046
   154   $ cat .hg/store/journal.backupfiles | tr -s '\000' ' ' | tr -s '\00' ' '| grep data/file
   149   data/file.i 128
   155    data/file.i data/journal.backup.file.i 0
       
   156    data/file.i.s 0
       
   157 
       
   158 recover is rolling the split back, the fncache is still valid
       
   159 
   150   $ hg recover
   160   $ hg recover
   151   rolling back interrupted transaction
   161   rolling back interrupted transaction
   152   (verify step skipped, run `hg verify` to check your repository content)
   162   (verify step skipped, run `hg verify` to check your repository content)
   153   $ f -s .hg/store/data/file*
   163   $ f -s .hg/store/data/file*
   154   .hg/store/data/file.d: size=1046
   164   .hg/store/data/file.i: size=1174
   155   .hg/store/data/file.i: size=128
       
   156   $ hg tip
   165   $ hg tip
   157   changeset:   1:cfa8d6e60429
   166   changeset:   1:cfa8d6e60429
   158   tag:         tip
   167   tag:         tip
   159   user:        test
   168   user:        test
   160   date:        Thu Jan 01 00:00:00 1970 +0000
   169   date:        Thu Jan 01 00:00:00 1970 +0000
   161   summary:     b
   170   summary:     b
   162   
   171   
   163   $ hg verify -q
   172   $ hg verify -q
   164    warning: revlog 'data/file.d' not in fncache!
       
   165   1 warnings encountered!
       
   166   hint: run "hg debugrebuildfncache" to recover from corrupt fncache
       
   167   $ hg debugrebuildfncache --only-data
   173   $ hg debugrebuildfncache --only-data
   168   adding data/file.d
   174   fncache already up to date
   169   1 items added, 0 removed from fncache
       
   170   $ hg verify -q
   175   $ hg verify -q
   171   $ cd ..
   176   $ cd ..
   172 
   177 
   173 Test a hard crash right before the index is move into place
   178 Test a hard crash right before the index is move into place
   174 ===========================================================
   179 ===========================================================
   187   .hg/store/data/file.i: size=1174
   192   .hg/store/data/file.i: size=1174
   188 
   193 
   189   $ cat > .hg/hgrc <<EOF
   194   $ cat > .hg/hgrc <<EOF
   190   > [extensions]
   195   > [extensions]
   191   > intercept_rename = $TESTTMP/intercept_before_rename.py
   196   > intercept_rename = $TESTTMP/intercept_before_rename.py
   192   > [hooks]
       
   193   > pretxnchangegroup = python:$TESTTMP/killme.py:killme
       
   194   > EOF
   197   > EOF
   195 #if chg
   198 #if chg
   196   $ hg pull ../troffset-computation
   199   $ hg pull ../troffset-computation
   197   pulling from ../troffset-computation
   200   pulling from ../troffset-computation
       
   201   searching for changes
       
   202   adding changesets
       
   203   adding manifests
       
   204   adding file changes
   198   [255]
   205   [255]
   199 #else
   206 #else
   200   $ hg pull ../troffset-computation
   207   $ hg pull ../troffset-computation
   201   pulling from ../troffset-computation
   208   pulling from ../troffset-computation
       
   209   searching for changes
       
   210   adding changesets
       
   211   adding manifests
       
   212   adding file changes
   202   Killed
   213   Killed
   203   [137]
   214   [137]
   204 #endif
   215 #endif
   205 
   216 
   206 The data file is created, but the revlog is still inline
   217 The inline revlog still exist, but a split version exist next to it
   207 
   218 
   208   $ f -s .hg/store/data/file*
   219   $ f -s .hg/store/data/file*
   209   .hg/store/data/file.d: size=132139
   220   .hg/store/data/file.d: size=132139
   210   .hg/store/data/file.i: size=132395
   221   .hg/store/data/file.i: size=132395
       
   222   .hg/store/data/file.i.s: size=256
   211 
   223 
   212   $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file
   224   $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file
   213   data/file.i 1174
   225   data/file.i 1174
   214   data/file.d 0
   226   data/file.d 0
   215   data/file.d 1046
   227 
       
   228 recover is rolling the split back, the fncache is still valid
   216 
   229 
   217   $ hg recover
   230   $ hg recover
   218   rolling back interrupted transaction
   231   rolling back interrupted transaction
   219   (verify step skipped, run `hg verify` to check your repository content)
   232   (verify step skipped, run `hg verify` to check your repository content)
   220   $ f -s .hg/store/data/file*
   233   $ f -s .hg/store/data/file*
   221   .hg/store/data/file.d: size=1046
       
   222   .hg/store/data/file.i: size=1174
   234   .hg/store/data/file.i: size=1174
   223   $ hg tip
   235   $ hg tip
   224   changeset:   1:cfa8d6e60429
   236   changeset:   1:cfa8d6e60429
   225   tag:         tip
   237   tag:         tip
   226   user:        test
   238   user:        test
   233 Test a hard crash right after the index is move into place
   245 Test a hard crash right after the index is move into place
   234 ===========================================================
   246 ===========================================================
   235 
   247 
   236 Now retry the procedure but intercept the rename of the index.
   248 Now retry the procedure but intercept the rename of the index.
   237 
   249 
   238 Things get corrupted /o\
       
   239 
       
   240   $ hg clone --quiet --rev 1 troffset-computation troffset-computation-crash-after-rename
   250   $ hg clone --quiet --rev 1 troffset-computation troffset-computation-crash-after-rename
   241   $ cd troffset-computation-crash-after-rename
   251   $ cd troffset-computation-crash-after-rename
   242 
   252 
   243 Reference size:
   253 Reference size:
   244   $ f -s file
   254   $ f -s file
   247   .hg/store/data/file.i: size=1174
   257   .hg/store/data/file.i: size=1174
   248 
   258 
   249   $ cat > .hg/hgrc <<EOF
   259   $ cat > .hg/hgrc <<EOF
   250   > [extensions]
   260   > [extensions]
   251   > intercept_rename = $TESTTMP/intercept_after_rename.py
   261   > intercept_rename = $TESTTMP/intercept_after_rename.py
   252   > [hooks]
       
   253   > pretxnchangegroup = python:$TESTTMP/killme.py:killme
       
   254   > EOF
   262   > EOF
   255 #if chg
   263 #if chg
   256   $ hg pull ../troffset-computation
   264   $ hg pull ../troffset-computation
   257   pulling from ../troffset-computation
   265   pulling from ../troffset-computation
       
   266   searching for changes
       
   267   adding changesets
       
   268   adding manifests
       
   269   adding file changes
   258   [255]
   270   [255]
   259 #else
   271 #else
   260   $ hg pull ../troffset-computation
   272   $ hg pull ../troffset-computation
   261   pulling from ../troffset-computation
   273   pulling from ../troffset-computation
       
   274   searching for changes
       
   275   adding changesets
       
   276   adding manifests
       
   277   adding file changes
   262   Killed
   278   Killed
   263   [137]
   279   [137]
   264 #endif
   280 #endif
   265 
   281 
   266 the revlog has been split on disk
   282 The inline revlog was over written on disk
   267 
   283 
   268   $ f -s .hg/store/data/file*
   284   $ f -s .hg/store/data/file*
   269   .hg/store/data/file.d: size=132139
   285   .hg/store/data/file.d: size=132139
   270   .hg/store/data/file.i: size=256
   286   .hg/store/data/file.i: size=256
   271 
   287 
   272   $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file
   288   $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file
   273   data/file.i 1174
   289   data/file.i 1174
   274   data/file.d 0
   290   data/file.d 0
   275   data/file.d 1046
   291 
       
   292 recover is rolling the split back, the fncache is still valid
   276 
   293 
   277   $ hg recover
   294   $ hg recover
   278   rolling back interrupted transaction
   295   rolling back interrupted transaction
   279   abort: attempted to truncate data/file.i to 1174 bytes, but it was already 256 bytes
   296   (verify step skipped, run `hg verify` to check your repository content)
   280   
   297   $ f -s .hg/store/data/file*
   281   [255]
   298   .hg/store/data/file.i: size=1174
   282   $ f -s .hg/store/data/file*
       
   283   .hg/store/data/file.d: size=1046
       
   284   .hg/store/data/file.i: size=256
       
   285   $ hg tip
   299   $ hg tip
   286   changeset:   1:cfa8d6e60429
   300   changeset:   1:cfa8d6e60429
   287   tag:         tip
   301   tag:         tip
   288   user:        test
   302   user:        test
   289   date:        Thu Jan 01 00:00:00 1970 +0000
   303   date:        Thu Jan 01 00:00:00 1970 +0000
   290   summary:     b
   304   summary:     b
   291   
   305   
   292   $ hg verify -q
   306   $ hg verify -q
   293   abandoned transaction found - run hg recover
       
   294    warning: revlog 'data/file.d' not in fncache!
       
   295    file@0: data length off by -131093 bytes
       
   296    file@2: unpacking fa1120531cc1: partial read of revlog data/file.d; expected 21 bytes from offset 1046, got 0
       
   297    file@3: unpacking a631378adaa3: partial read of revlog data/file.d; expected 131072 bytes from offset 1067, got -21
       
   298    file@?: rev 2 points to nonexistent changeset 2
       
   299    (expected )
       
   300    file@?: fa1120531cc1 not in manifests
       
   301    file@?: rev 3 points to nonexistent changeset 3
       
   302    (expected )
       
   303    file@?: a631378adaa3 not in manifests
       
   304   not checking dirstate because of previous errors
       
   305   3 warnings encountered!
       
   306   hint: run "hg debugrebuildfncache" to recover from corrupt fncache
       
   307   7 integrity errors encountered!
       
   308   (first damaged changeset appears to be 0)
       
   309   [1]
       
   310   $ cd ..
   307   $ cd ..
   311 
   308 
   312 Have the transaction rollback itself without any hard crash
   309 Have the transaction rollback itself without any hard crash
   313 ===========================================================
   310 ===========================================================
   314 
   311 
   330   transaction abort!
   327   transaction abort!
   331   rollback completed
   328   rollback completed
   332   abort: pretxnchangegroup hook exited with status 1
   329   abort: pretxnchangegroup hook exited with status 1
   333   [40]
   330   [40]
   334 
   331 
   335 File are still split on disk, with the expected size.
   332 The split was rollback
   336 
   333 
   337   $ f -s .hg/store/data/file*
   334   $ f -s .hg/store/data/file*
   338   .hg/store/data/file.d: size=1046
   335   .hg/store/data/file.d: size=0
   339   .hg/store/data/file.i: size=128
   336   .hg/store/data/file.i: size=1174
       
   337 
   340 
   338 
   341   $ hg tip
   339   $ hg tip
   342   changeset:   1:cfa8d6e60429
   340   changeset:   1:cfa8d6e60429
   343   tag:         tip
   341   tag:         tip
   344   user:        test
   342   user:        test
   345   date:        Thu Jan 01 00:00:00 1970 +0000
   343   date:        Thu Jan 01 00:00:00 1970 +0000
   346   summary:     b
   344   summary:     b
   347   
   345   
   348   $ hg verify -q
   346   $ hg verify -q
   349    warning: revlog 'data/file.d' not in fncache!
       
   350   1 warnings encountered!
       
   351   hint: run "hg debugrebuildfncache" to recover from corrupt fncache
       
   352   $ cd ..
   347   $ cd ..
   353 
   348 
   354 Read race
   349 Read race
   355 =========
   350 =========
   356 
   351