comparison mercurial/revlogutils/docket.py @ 47238:6597255a4f94

revlogv2: track current index size in the docket This help use to fix transaction safety on repos. See next changesets for details. Differential Revision: https://phab.mercurial-scm.org/D10628
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Mon, 03 May 2021 12:34:52 +0200
parents 616b8f412676
children 2219853a1503
comparison
equal deleted inserted replaced
47237:864f4ebe6a8d 47238:6597255a4f94
26 # Docket format 26 # Docket format
27 # 27 #
28 # * 4 bytes: revlog version 28 # * 4 bytes: revlog version
29 # | This is mandatory as docket must be compatible with the previous 29 # | This is mandatory as docket must be compatible with the previous
30 # | revlog index header. 30 # | revlog index header.
31 S_HEADER = struct.Struct(constants.INDEX_HEADER.format) 31 # * 8 bytes: size of index data
32 S_HEADER = struct.Struct(constants.INDEX_HEADER.format + 'L')
32 33
33 34
34 class RevlogDocket(object): 35 class RevlogDocket(object):
35 """metadata associated with revlog""" 36 """metadata associated with revlog"""
36 37
37 def __init__(self, revlog, version_header=None): 38 def __init__(self, revlog, version_header=None, index_end=0):
38 self._version_header = version_header 39 self._version_header = version_header
39 self._dirty = False 40 self._dirty = False
40 self._radix = revlog.radix 41 self._radix = revlog.radix
41 self._path = revlog._docket_file 42 self._path = revlog._docket_file
42 self._opener = revlog.opener 43 self._opener = revlog.opener
44 self._index_end = index_end
43 45
44 def index_filepath(self): 46 def index_filepath(self):
45 """file path to the current index file associated to this docket""" 47 """file path to the current index file associated to this docket"""
46 # very simplistic version at first 48 # very simplistic version at first
47 return b"%s.idx" % self._radix 49 return b"%s.idx" % self._radix
48 50
49 def write(self, transaction): 51 @property
52 def index_end(self):
53 return self._index_end
54
55 @index_end.setter
56 def index_end(self, new_size):
57 if new_size != self._index_end:
58 self._index_end = new_size
59 self._dirty = True
60
61 def write(self, transaction, stripping=False):
50 """write the modification of disk if any 62 """write the modification of disk if any
51 63
52 This make the new content visible to all process""" 64 This make the new content visible to all process"""
53 if self._dirty: 65 if self._dirty:
54 transaction.addbackup(self._path, location=b'store') 66 if not stripping:
67 # XXX we could, leverage the docket while stripping. However it
68 # is not powerfull enough at the time of this comment
69 transaction.addbackup(self._path, location=b'store')
55 with self._opener(self._path, mode=b'w', atomictemp=True) as f: 70 with self._opener(self._path, mode=b'w', atomictemp=True) as f:
56 f.write(self._serialize()) 71 f.write(self._serialize())
57 self._dirty = False 72 self._dirty = False
58 73
59 def _serialize(self): 74 def _serialize(self):
60 return S_HEADER.pack(self._version_header) 75 data = (
76 self._version_header,
77 self._index_end,
78 )
79 return S_HEADER.pack(*data)
61 80
62 81
63 def default_docket(revlog, version_header): 82 def default_docket(revlog, version_header):
64 """given a revlog version a new docket object for the given revlog""" 83 """given a revlog version a new docket object for the given revlog"""
65 if (version_header & 0xFFFF) != constants.REVLOGV2: 84 if (version_header & 0xFFFF) != constants.REVLOGV2:
70 89
71 90
72 def parse_docket(revlog, data): 91 def parse_docket(revlog, data):
73 """given some docket data return a docket object for the given revlog""" 92 """given some docket data return a docket object for the given revlog"""
74 header = S_HEADER.unpack(data[: S_HEADER.size]) 93 header = S_HEADER.unpack(data[: S_HEADER.size])
75 (version_header,) = header 94 version_header, index_size = header
76 docket = RevlogDocket( 95 docket = RevlogDocket(
77 revlog, 96 revlog,
78 version_header=version_header, 97 version_header=version_header,
98 index_end=index_size,
79 ) 99 )
80 return docket 100 return docket