##// END OF EJS Templates
revlogv2: track pending write in the docket and expose it to hooks...
marmoute -
r48015:2219853a default
parent child Browse files
Show More
@@ -395,7 +395,6 class changelog(revlog.revlog):
395 ``concurrencychecker`` will be passed to the revlog init function, see
395 ``concurrencychecker`` will be passed to the revlog init function, see
396 the documentation there.
396 the documentation there.
397 """
397 """
398
399 revlog.revlog.__init__(
398 revlog.revlog.__init__(
400 self,
399 self,
401 opener,
400 opener,
@@ -484,6 +483,8 class changelog(revlog.revlog):
484 def _writepending(self, tr):
483 def _writepending(self, tr):
485 """create a file containing the unfinalized state for
484 """create a file containing the unfinalized state for
486 pretxnchangegroup"""
485 pretxnchangegroup"""
486 if self._docket:
487 return self._docket.write(tr, pending=True)
487 if self._delaybuf:
488 if self._delaybuf:
488 # make a temporary copy of the index
489 # make a temporary copy of the index
489 fp1 = self._realopener(self._indexfile)
490 fp1 = self._realopener(self._indexfile)
@@ -1150,7 +1150,6 coreconfigitem(
1150 )
1150 )
1151 # "out of experimental" todo list.
1151 # "out of experimental" todo list.
1152 #
1152 #
1153 # * expose transaction content hooks during pre-commit validation
1154 # * include management of a persistent nodemap in the main docket
1153 # * include management of a persistent nodemap in the main docket
1155 # * enforce a "no-truncate" policy for mmap safety
1154 # * enforce a "no-truncate" policy for mmap safety
1156 # - for censoring operation
1155 # - for censoring operation
@@ -529,7 +529,9 class revlog(object):
529 if self._initempty:
529 if self._initempty:
530 self._docket = docketutil.default_docket(self, header)
530 self._docket = docketutil.default_docket(self, header)
531 else:
531 else:
532 self._docket = docketutil.parse_docket(self, entry_data)
532 self._docket = docketutil.parse_docket(
533 self, entry_data, use_pending=self._trypending
534 )
533 self._indexfile = self._docket.index_filepath()
535 self._indexfile = self._docket.index_filepath()
534 index_data = b''
536 index_data = b''
535 index_size = self._docket.index_end
537 index_size = self._docket.index_end
@@ -19,6 +19,10 from __future__ import absolute_import
19
19
20 import struct
20 import struct
21
21
22 from .. import (
23 error,
24 )
25
22 from . import (
26 from . import (
23 constants,
27 constants,
24 )
28 )
@@ -29,19 +33,35 from . import (
29 # | This is mandatory as docket must be compatible with the previous
33 # | This is mandatory as docket must be compatible with the previous
30 # | revlog index header.
34 # | revlog index header.
31 # * 8 bytes: size of index data
35 # * 8 bytes: size of index data
32 S_HEADER = struct.Struct(constants.INDEX_HEADER.format + 'L')
36 # * 8 bytes: pending size of index data
37 S_HEADER = struct.Struct(constants.INDEX_HEADER.format + 'LL')
33
38
34
39
35 class RevlogDocket(object):
40 class RevlogDocket(object):
36 """metadata associated with revlog"""
41 """metadata associated with revlog"""
37
42
38 def __init__(self, revlog, version_header=None, index_end=0):
43 def __init__(
44 self,
45 revlog,
46 use_pending=False,
47 version_header=None,
48 index_end=0,
49 pending_index_end=0,
50 ):
39 self._version_header = version_header
51 self._version_header = version_header
52 self._read_only = bool(use_pending)
40 self._dirty = False
53 self._dirty = False
41 self._radix = revlog.radix
54 self._radix = revlog.radix
42 self._path = revlog._docket_file
55 self._path = revlog._docket_file
43 self._opener = revlog.opener
56 self._opener = revlog.opener
44 self._index_end = index_end
57 # this assert should be True as long as we have a single index filename
58 assert index_end <= pending_index_end
59 self._initial_index_end = index_end
60 self._pending_index_end = pending_index_end
61 if use_pending:
62 self._index_end = self._pending_index_end
63 else:
64 self._index_end = self._initial_index_end
45
65
46 def index_filepath(self):
66 def index_filepath(self):
47 """file path to the current index file associated to this docket"""
67 """file path to the current index file associated to this docket"""
@@ -58,22 +78,38 class RevlogDocket(object):
58 self._index_end = new_size
78 self._index_end = new_size
59 self._dirty = True
79 self._dirty = True
60
80
61 def write(self, transaction, stripping=False):
81 def write(self, transaction, pending=False, stripping=False):
62 """write the modification of disk if any
82 """write the modification of disk if any
63
83
64 This make the new content visible to all process"""
84 This make the new content visible to all process"""
65 if self._dirty:
85 if not self._dirty:
86 return False
87 else:
88 if self._read_only:
89 msg = b'writing read-only docket: %s'
90 msg %= self._path
91 raise error.ProgrammingError(msg)
66 if not stripping:
92 if not stripping:
67 # XXX we could, leverage the docket while stripping. However it
93 # XXX we could, leverage the docket while stripping. However it
68 # is not powerfull enough at the time of this comment
94 # is not powerfull enough at the time of this comment
69 transaction.addbackup(self._path, location=b'store')
95 transaction.addbackup(self._path, location=b'store')
70 with self._opener(self._path, mode=b'w', atomictemp=True) as f:
96 with self._opener(self._path, mode=b'w', atomictemp=True) as f:
71 f.write(self._serialize())
97 f.write(self._serialize(pending=pending))
72 self._dirty = False
98 # if pending we still need to the write final data eventually
99 self._dirty = pending
100 return True
73
101
74 def _serialize(self):
102 def _serialize(self, pending=False):
103 if pending:
104 official_index_end = self._initial_index_end
105 else:
106 official_index_end = self._index_end
107
108 # this assert should be True as long as we have a single index filename
109 assert official_index_end <= self._index_end
75 data = (
110 data = (
76 self._version_header,
111 self._version_header,
112 official_index_end,
77 self._index_end,
113 self._index_end,
78 )
114 )
79 return S_HEADER.pack(*data)
115 return S_HEADER.pack(*data)
@@ -88,13 +124,15 def default_docket(revlog, version_heade
88 return docket
124 return docket
89
125
90
126
91 def parse_docket(revlog, data):
127 def parse_docket(revlog, data, use_pending=False):
92 """given some docket data return a docket object for the given revlog"""
128 """given some docket data return a docket object for the given revlog"""
93 header = S_HEADER.unpack(data[: S_HEADER.size])
129 header = S_HEADER.unpack(data[: S_HEADER.size])
94 version_header, index_size = header
130 version_header, index_size, pending_index_size = header
95 docket = RevlogDocket(
131 docket = RevlogDocket(
96 revlog,
132 revlog,
133 use_pending=use_pending,
97 version_header=version_header,
134 version_header=version_header,
98 index_end=index_size,
135 index_end=index_size,
136 pending_index_end=pending_index_size,
99 )
137 )
100 return docket
138 return docket
@@ -46,13 +46,13 synchronisation+output script:
46 $ cat << EOF > script/external.sh
46 $ cat << EOF > script/external.sh
47 > #!/bin/sh
47 > #!/bin/sh
48 > $RUNTESTDIR/testlib/wait-on-file 5 $HG_TEST_FILE_EXT_UNLOCK $HG_TEST_FILE_EXT_WAITING
48 > $RUNTESTDIR/testlib/wait-on-file 5 $HG_TEST_FILE_EXT_UNLOCK $HG_TEST_FILE_EXT_WAITING
49 > hg log --rev 'tip' -T 'external: {rev} {desc}\n' > $TESTTMP/output/external.out 2>/dev/null
49 > hg log --rev 'tip' -T 'external: {rev} {desc}\n' > $TESTTMP/output/external.out
50 > touch $HG_TEST_FILE_EXT_DONE
50 > touch $HG_TEST_FILE_EXT_DONE
51 > EOF
51 > EOF
52 $ chmod +x script/external.sh
52 $ chmod +x script/external.sh
53 $ cat << EOF > script/internal.sh
53 $ cat << EOF > script/internal.sh
54 > #!/bin/sh
54 > #!/bin/sh
55 > hg log --rev 'tip' -T 'internal: {rev} {desc}\n' > $TESTTMP/output/internal.out 2>/dev/null
55 > hg log --rev 'tip' -T 'internal: {rev} {desc}\n' > $TESTTMP/output/internal.out
56 > $RUNTESTDIR/testlib/wait-on-file 5 $HG_TEST_FILE_EXT_DONE $HG_TEST_FILE_EXT_UNLOCK
56 > $RUNTESTDIR/testlib/wait-on-file 5 $HG_TEST_FILE_EXT_DONE $HG_TEST_FILE_EXT_UNLOCK
57 > EOF
57 > EOF
58 $ chmod +x script/internal.sh
58 $ chmod +x script/internal.sh
@@ -124,8 +124,7 the repository should still be inline (f
124 $ make_one_commit first
124 $ make_one_commit first
125 pre-commit: -1
125 pre-commit: -1
126 external: -1
126 external: -1
127 internal: 0 first (revlogv1 !)
127 internal: 0 first
128 internal: -1 (revlogv2 known-bad-output !)
129 post-tr: 0 first
128 post-tr: 0 first
130
129
131 #if revlogv1
130 #if revlogv1
@@ -150,8 +149,7 the repository should still be inline (f
150 $ make_one_commit second
149 $ make_one_commit second
151 pre-commit: 0 first
150 pre-commit: 0 first
152 external: 0 first
151 external: 0 first
153 internal: 1 second (revlogv1 !)
152 internal: 1 second
154 internal: 0 first (revlogv2 known-bad-output !)
155 post-tr: 1 second
153 post-tr: 1 second
156
154
157 #if revlogv1
155 #if revlogv1
@@ -177,8 +175,7 the repository should still be inline (f
177 pre-commit: 1 second
175 pre-commit: 1 second
178 warning: repository is unrelated
176 warning: repository is unrelated
179 external: 1 second
177 external: 1 second
180 internal: 5 r3 (revlogv1 !)
178 internal: 5 r3
181 internal: 1 second (revlogv2 known-bad-output !)
182 post-tr: 5 r3
179 post-tr: 5 r3
183
180
184 #if revlogv1
181 #if revlogv1
@@ -203,8 +200,7 the repository should no longer be inlin
203 $ make_one_pull 400
200 $ make_one_pull 400
204 pre-commit: 5 r3
201 pre-commit: 5 r3
205 external: 5 r3
202 external: 5 r3
206 internal: 402 r400 (revlogv1 !)
203 internal: 402 r400
207 internal: 5 r3 (revlogv2 known-bad-output !)
208 post-tr: 402 r400
204 post-tr: 402 r400
209
205
210 #if revlogv1
206 #if revlogv1
@@ -229,8 +225,7 the repository should no longer be inlin
229 $ make_one_commit third
225 $ make_one_commit third
230 pre-commit: 402 r400
226 pre-commit: 402 r400
231 external: 402 r400
227 external: 402 r400
232 internal: 403 third (revlogv1 !)
228 internal: 403 third
233 internal: 402 r400 (revlogv2 known-bad-output !)
234 post-tr: 403 third
229 post-tr: 403 third
235
230
236 #if revlogv1
231 #if revlogv1
@@ -256,8 +251,7 the repository should no longer be inlin
256 $ make_one_pull tip
251 $ make_one_pull tip
257 pre-commit: 403 third
252 pre-commit: 403 third
258 external: 403 third
253 external: 403 third
259 internal: 503 r500 (revlogv1 !)
254 internal: 503 r500
260 internal: 403 third (revlogv2 known-bad-output !)
261 post-tr: 503 r500
255 post-tr: 503 r500
262
256
263 #if revlogv1
257 #if revlogv1
General Comments 0
You need to be logged in to leave comments. Login now