comparison mercurial/revlogutils/docket.py @ 47389:e6292eb33384

revlog: store sidedata in their own file This makes sidedata manipulation simpler and results in more compact data when traversing either data or sidedata. Differential Revision: https://phab.mercurial-scm.org/D10787
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Fri, 28 May 2021 23:41:17 +0200
parents bcf92bdc2bca
children be903d043099
comparison
equal deleted inserted replaced
47388:bcf92bdc2bca 47389:e6292eb33384
88 # * 4 bytes: revlog version 88 # * 4 bytes: revlog version
89 # | This is mandatory as docket must be compatible with the previous 89 # | This is mandatory as docket must be compatible with the previous
90 # | revlog index header. 90 # | revlog index header.
91 # * 1 bytes: size of index uuid 91 # * 1 bytes: size of index uuid
92 # * 1 bytes: size of data uuid 92 # * 1 bytes: size of data uuid
93 # * 1 bytes: size of sizedata uuid
93 # * 8 bytes: size of index-data 94 # * 8 bytes: size of index-data
94 # * 8 bytes: pending size of index-data 95 # * 8 bytes: pending size of index-data
95 # * 8 bytes: size of data 96 # * 8 bytes: size of data
97 # * 8 bytes: size of sidedata
96 # * 8 bytes: pending size of data 98 # * 8 bytes: pending size of data
99 # * 8 bytes: pending size of sidedata
97 # * 1 bytes: default compression header 100 # * 1 bytes: default compression header
98 S_HEADER = struct.Struct(constants.INDEX_HEADER_FMT + b'BBLLLLc') 101 S_HEADER = struct.Struct(constants.INDEX_HEADER_FMT + b'BBBLLLLLLc')
99 102
100 103
101 class RevlogDocket(object): 104 class RevlogDocket(object):
102 """metadata associated with revlog""" 105 """metadata associated with revlog"""
103 106
106 revlog, 109 revlog,
107 use_pending=False, 110 use_pending=False,
108 version_header=None, 111 version_header=None,
109 index_uuid=None, 112 index_uuid=None,
110 data_uuid=None, 113 data_uuid=None,
114 sidedata_uuid=None,
111 index_end=0, 115 index_end=0,
112 pending_index_end=0, 116 pending_index_end=0,
113 data_end=0, 117 data_end=0,
114 pending_data_end=0, 118 pending_data_end=0,
119 sidedata_end=0,
120 pending_sidedata_end=0,
115 default_compression_header=None, 121 default_compression_header=None,
116 ): 122 ):
117 self._version_header = version_header 123 self._version_header = version_header
118 self._read_only = bool(use_pending) 124 self._read_only = bool(use_pending)
119 self._dirty = False 125 self._dirty = False
120 self._radix = revlog.radix 126 self._radix = revlog.radix
121 self._path = revlog._docket_file 127 self._path = revlog._docket_file
122 self._opener = revlog.opener 128 self._opener = revlog.opener
123 self._index_uuid = index_uuid 129 self._index_uuid = index_uuid
124 self._data_uuid = data_uuid 130 self._data_uuid = data_uuid
131 self._sidedata_uuid = sidedata_uuid
125 # thes asserts should be True as long as we have a single index filename 132 # thes asserts should be True as long as we have a single index filename
126 assert index_end <= pending_index_end 133 assert index_end <= pending_index_end
127 assert data_end <= pending_data_end 134 assert data_end <= pending_data_end
135 assert sidedata_end <= pending_sidedata_end
128 self._initial_index_end = index_end 136 self._initial_index_end = index_end
129 self._pending_index_end = pending_index_end 137 self._pending_index_end = pending_index_end
130 self._initial_data_end = data_end 138 self._initial_data_end = data_end
131 self._pending_data_end = pending_data_end 139 self._pending_data_end = pending_data_end
140 self._initial_sidedata_end = sidedata_end
141 self._pending_sidedata_end = pending_sidedata_end
132 if use_pending: 142 if use_pending:
133 self._index_end = self._pending_index_end 143 self._index_end = self._pending_index_end
134 self._data_end = self._pending_data_end 144 self._data_end = self._pending_data_end
145 self._sidedata_end = self._pending_sidedata_end
135 else: 146 else:
136 self._index_end = self._initial_index_end 147 self._index_end = self._initial_index_end
137 self._data_end = self._initial_data_end 148 self._data_end = self._initial_data_end
149 self._sidedata_end = self._initial_sidedata_end
138 self.default_compression_header = default_compression_header 150 self.default_compression_header = default_compression_header
139 151
140 def index_filepath(self): 152 def index_filepath(self):
141 """file path to the current index file associated to this docket""" 153 """file path to the current index file associated to this docket"""
142 # very simplistic version at first 154 # very simplistic version at first
149 # very simplistic version at first 161 # very simplistic version at first
150 if self._data_uuid is None: 162 if self._data_uuid is None:
151 self._data_uuid = make_uid() 163 self._data_uuid = make_uid()
152 return b"%s-%s.dat" % (self._radix, self._data_uuid) 164 return b"%s-%s.dat" % (self._radix, self._data_uuid)
153 165
166 def sidedata_filepath(self):
167 """file path to the current sidedata file associated to this docket"""
168 # very simplistic version at first
169 if self._sidedata_uuid is None:
170 self._sidedata_uuid = make_uid()
171 return b"%s-%s.sda" % (self._radix, self._sidedata_uuid)
172
154 @property 173 @property
155 def index_end(self): 174 def index_end(self):
156 return self._index_end 175 return self._index_end
157 176
158 @index_end.setter 177 @index_end.setter
167 186
168 @data_end.setter 187 @data_end.setter
169 def data_end(self, new_size): 188 def data_end(self, new_size):
170 if new_size != self._data_end: 189 if new_size != self._data_end:
171 self._data_end = new_size 190 self._data_end = new_size
191 self._dirty = True
192
193 @property
194 def sidedata_end(self):
195 return self._sidedata_end
196
197 @sidedata_end.setter
198 def sidedata_end(self, new_size):
199 if new_size != self._sidedata_end:
200 self._sidedata_end = new_size
172 self._dirty = True 201 self._dirty = True
173 202
174 def write(self, transaction, pending=False, stripping=False): 203 def write(self, transaction, pending=False, stripping=False):
175 """write the modification of disk if any 204 """write the modification of disk if any
176 205
194 223
195 def _serialize(self, pending=False): 224 def _serialize(self, pending=False):
196 if pending: 225 if pending:
197 official_index_end = self._initial_index_end 226 official_index_end = self._initial_index_end
198 official_data_end = self._initial_data_end 227 official_data_end = self._initial_data_end
228 official_sidedata_end = self._initial_sidedata_end
199 else: 229 else:
200 official_index_end = self._index_end 230 official_index_end = self._index_end
201 official_data_end = self._data_end 231 official_data_end = self._data_end
232 official_sidedata_end = self._sidedata_end
202 233
203 # this assert should be True as long as we have a single index filename 234 # this assert should be True as long as we have a single index filename
204 assert official_data_end <= self._data_end 235 assert official_data_end <= self._data_end
236 assert official_sidedata_end <= self._sidedata_end
205 data = ( 237 data = (
206 self._version_header, 238 self._version_header,
207 len(self._index_uuid), 239 len(self._index_uuid),
208 len(self._data_uuid), 240 len(self._data_uuid),
241 len(self._sidedata_uuid),
209 official_index_end, 242 official_index_end,
210 self._index_end, 243 self._index_end,
211 official_data_end, 244 official_data_end,
212 self._data_end, 245 self._data_end,
246 official_sidedata_end,
247 self._sidedata_end,
213 self.default_compression_header, 248 self.default_compression_header,
214 ) 249 )
215 s = [] 250 s = []
216 s.append(S_HEADER.pack(*data)) 251 s.append(S_HEADER.pack(*data))
217 s.append(self._index_uuid) 252 s.append(self._index_uuid)
218 s.append(self._data_uuid) 253 s.append(self._data_uuid)
254 s.append(self._sidedata_uuid)
219 return b''.join(s) 255 return b''.join(s)
220 256
221 257
222 def default_docket(revlog, version_header): 258 def default_docket(revlog, version_header):
223 """given a revlog version a new docket object for the given revlog""" 259 """given a revlog version a new docket object for the given revlog"""
260 index_uuid = get_data(index_uuid_size) 296 index_uuid = get_data(index_uuid_size)
261 297
262 data_uuid_size = next(iheader) 298 data_uuid_size = next(iheader)
263 data_uuid = get_data(data_uuid_size) 299 data_uuid = get_data(data_uuid_size)
264 300
301 sidedata_uuid_size = next(iheader)
302 sidedata_uuid = get_data(sidedata_uuid_size)
303
265 index_size = next(iheader) 304 index_size = next(iheader)
266 305
267 pending_index_size = next(iheader) 306 pending_index_size = next(iheader)
268 307
269 data_size = next(iheader) 308 data_size = next(iheader)
270 309
271 pending_data_size = next(iheader) 310 pending_data_size = next(iheader)
311
312 sidedata_size = next(iheader)
313
314 pending_sidedata_size = next(iheader)
272 315
273 default_compression_header = next(iheader) 316 default_compression_header = next(iheader)
274 317
275 docket = RevlogDocket( 318 docket = RevlogDocket(
276 revlog, 319 revlog,
277 use_pending=use_pending, 320 use_pending=use_pending,
278 version_header=version_header, 321 version_header=version_header,
279 index_uuid=index_uuid, 322 index_uuid=index_uuid,
280 data_uuid=data_uuid, 323 data_uuid=data_uuid,
324 sidedata_uuid=sidedata_uuid,
281 index_end=index_size, 325 index_end=index_size,
282 pending_index_end=pending_index_size, 326 pending_index_end=pending_index_size,
283 data_end=data_size, 327 data_end=data_size,
284 pending_data_end=pending_data_size, 328 pending_data_end=pending_data_size,
329 sidedata_end=sidedata_size,
330 pending_sidedata_end=pending_sidedata_size,
285 default_compression_header=default_compression_header, 331 default_compression_header=default_compression_header,
286 ) 332 )
287 return docket 333 return docket