comparison mercurial/revlogutils/docket.py @ 47242:4abd474a10af

revlogv2: also keep track for the size of the "data" file This is useful to make sure we always start writing at the right location, without effort. Differential Revision: https://phab.mercurial-scm.org/D10632
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Mon, 03 May 2021 12:35:35 +0200
parents 2219853a1503
children ff9fd7107d11
comparison
equal deleted inserted replaced
47241:2219853a1503 47242:4abd474a10af
30 # Docket format 30 # Docket format
31 # 31 #
32 # * 4 bytes: revlog version 32 # * 4 bytes: revlog version
33 # | This is mandatory as docket must be compatible with the previous 33 # | This is mandatory as docket must be compatible with the previous
34 # | revlog index header. 34 # | revlog index header.
35 # * 8 bytes: size of index data 35 # * 8 bytes: size of index-data
36 # * 8 bytes: pending size of index data 36 # * 8 bytes: pending size of index-data
37 S_HEADER = struct.Struct(constants.INDEX_HEADER.format + 'LL') 37 # * 8 bytes: size of data
38 # * 8 bytes: pending size of data
39 S_HEADER = struct.Struct(constants.INDEX_HEADER.format + 'LLLL')
38 40
39 41
40 class RevlogDocket(object): 42 class RevlogDocket(object):
41 """metadata associated with revlog""" 43 """metadata associated with revlog"""
42 44
45 revlog, 47 revlog,
46 use_pending=False, 48 use_pending=False,
47 version_header=None, 49 version_header=None,
48 index_end=0, 50 index_end=0,
49 pending_index_end=0, 51 pending_index_end=0,
52 data_end=0,
53 pending_data_end=0,
50 ): 54 ):
51 self._version_header = version_header 55 self._version_header = version_header
52 self._read_only = bool(use_pending) 56 self._read_only = bool(use_pending)
53 self._dirty = False 57 self._dirty = False
54 self._radix = revlog.radix 58 self._radix = revlog.radix
55 self._path = revlog._docket_file 59 self._path = revlog._docket_file
56 self._opener = revlog.opener 60 self._opener = revlog.opener
57 # this assert should be True as long as we have a single index filename 61 # thes asserts should be True as long as we have a single index filename
58 assert index_end <= pending_index_end 62 assert index_end <= pending_index_end
63 assert data_end <= pending_data_end
59 self._initial_index_end = index_end 64 self._initial_index_end = index_end
60 self._pending_index_end = pending_index_end 65 self._pending_index_end = pending_index_end
66 self._initial_data_end = data_end
67 self._pending_data_end = pending_data_end
61 if use_pending: 68 if use_pending:
62 self._index_end = self._pending_index_end 69 self._index_end = self._pending_index_end
70 self._data_end = self._pending_data_end
63 else: 71 else:
64 self._index_end = self._initial_index_end 72 self._index_end = self._initial_index_end
73 self._data_end = self._initial_data_end
65 74
66 def index_filepath(self): 75 def index_filepath(self):
67 """file path to the current index file associated to this docket""" 76 """file path to the current index file associated to this docket"""
68 # very simplistic version at first 77 # very simplistic version at first
69 return b"%s.idx" % self._radix 78 return b"%s.idx" % self._radix
74 83
75 @index_end.setter 84 @index_end.setter
76 def index_end(self, new_size): 85 def index_end(self, new_size):
77 if new_size != self._index_end: 86 if new_size != self._index_end:
78 self._index_end = new_size 87 self._index_end = new_size
88 self._dirty = True
89
90 @property
91 def data_end(self):
92 return self._data_end
93
94 @data_end.setter
95 def data_end(self, new_size):
96 if new_size != self._data_end:
97 self._data_end = new_size
79 self._dirty = True 98 self._dirty = True
80 99
81 def write(self, transaction, pending=False, stripping=False): 100 def write(self, transaction, pending=False, stripping=False):
82 """write the modification of disk if any 101 """write the modification of disk if any
83 102
100 return True 119 return True
101 120
102 def _serialize(self, pending=False): 121 def _serialize(self, pending=False):
103 if pending: 122 if pending:
104 official_index_end = self._initial_index_end 123 official_index_end = self._initial_index_end
124 official_data_end = self._initial_data_end
105 else: 125 else:
106 official_index_end = self._index_end 126 official_index_end = self._index_end
127 official_data_end = self._data_end
107 128
108 # this assert should be True as long as we have a single index filename 129 # this assert should be True as long as we have a single index filename
109 assert official_index_end <= self._index_end 130 assert official_data_end <= self._data_end
110 data = ( 131 data = (
111 self._version_header, 132 self._version_header,
112 official_index_end, 133 official_index_end,
113 self._index_end, 134 self._index_end,
135 official_data_end,
136 self._data_end,
114 ) 137 )
115 return S_HEADER.pack(*data) 138 return S_HEADER.pack(*data)
116 139
117 140
118 def default_docket(revlog, version_header): 141 def default_docket(revlog, version_header):
125 148
126 149
127 def parse_docket(revlog, data, use_pending=False): 150 def parse_docket(revlog, data, use_pending=False):
128 """given some docket data return a docket object for the given revlog""" 151 """given some docket data return a docket object for the given revlog"""
129 header = S_HEADER.unpack(data[: S_HEADER.size]) 152 header = S_HEADER.unpack(data[: S_HEADER.size])
130 version_header, index_size, pending_index_size = header 153 version_header = header[0]
154 index_size = header[1]
155 pending_index_size = header[2]
156 data_size = header[3]
157 pending_data_size = header[4]
131 docket = RevlogDocket( 158 docket = RevlogDocket(
132 revlog, 159 revlog,
133 use_pending=use_pending, 160 use_pending=use_pending,
134 version_header=version_header, 161 version_header=version_header,
135 index_end=index_size, 162 index_end=index_size,
136 pending_index_end=pending_index_size, 163 pending_index_end=pending_index_size,
164 data_end=data_size,
165 pending_data_end=pending_data_size,
137 ) 166 )
138 return docket 167 return docket