comparison mercurial/revlogutils/docket.py @ 47459:c252631500e4

revlog: add a way to keep track of older uids in the docket When the revlog content is rewritten, we will use new files, to avoid truncating the previous ones. We need some way to keep track of the older files before we clean them up. Differential Revision: https://phab.mercurial-scm.org/D10866
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Thu, 20 May 2021 21:47:09 +0200
parents be903d043099
children 865c260d7163
comparison
equal deleted inserted replaced
47458:c6844912c327 47459:c252631500e4
89 # 89 #
90 # * 4 bytes: revlog version 90 # * 4 bytes: revlog version
91 # | This is mandatory as docket must be compatible with the previous 91 # | This is mandatory as docket must be compatible with the previous
92 # | revlog index header. 92 # | revlog index header.
93 # * 1 bytes: size of index uuid 93 # * 1 bytes: size of index uuid
94 # * 1 bytes: number of outdated index uuid
94 # * 1 bytes: size of data uuid 95 # * 1 bytes: size of data uuid
96 # * 1 bytes: number of outdated data uuid
95 # * 1 bytes: size of sizedata uuid 97 # * 1 bytes: size of sizedata uuid
98 # * 1 bytes: number of outdated data uuid
96 # * 8 bytes: size of index-data 99 # * 8 bytes: size of index-data
97 # * 8 bytes: pending size of index-data 100 # * 8 bytes: pending size of index-data
98 # * 8 bytes: size of data 101 # * 8 bytes: size of data
99 # * 8 bytes: size of sidedata 102 # * 8 bytes: size of sidedata
100 # * 8 bytes: pending size of data 103 # * 8 bytes: pending size of data
101 # * 8 bytes: pending size of sidedata 104 # * 8 bytes: pending size of sidedata
102 # * 1 bytes: default compression header 105 # * 1 bytes: default compression header
103 S_HEADER = struct.Struct(constants.INDEX_HEADER_FMT + b'BBBLLLLLLc') 106 S_HEADER = struct.Struct(constants.INDEX_HEADER_FMT + b'BBBBBBLLLLLLc')
107 # * 1 bytes: size of index uuid
108 # * 8 bytes: size of file
109 S_OLD_UID = struct.Struct('>BL')
104 110
105 111
106 class RevlogDocket(object): 112 class RevlogDocket(object):
107 """metadata associated with revlog""" 113 """metadata associated with revlog"""
108 114
110 self, 116 self,
111 revlog, 117 revlog,
112 use_pending=False, 118 use_pending=False,
113 version_header=None, 119 version_header=None,
114 index_uuid=None, 120 index_uuid=None,
121 older_index_uuids=(),
115 data_uuid=None, 122 data_uuid=None,
123 older_data_uuids=(),
116 sidedata_uuid=None, 124 sidedata_uuid=None,
125 older_sidedata_uuids=(),
117 index_end=0, 126 index_end=0,
118 pending_index_end=0, 127 pending_index_end=0,
119 data_end=0, 128 data_end=0,
120 pending_data_end=0, 129 pending_data_end=0,
121 sidedata_end=0, 130 sidedata_end=0,
127 self._dirty = False 136 self._dirty = False
128 self._radix = revlog.radix 137 self._radix = revlog.radix
129 self._path = revlog._docket_file 138 self._path = revlog._docket_file
130 self._opener = revlog.opener 139 self._opener = revlog.opener
131 self._index_uuid = index_uuid 140 self._index_uuid = index_uuid
141 self._older_index_uuids = older_index_uuids
132 self._data_uuid = data_uuid 142 self._data_uuid = data_uuid
143 self._older_data_uuids = older_data_uuids
133 self._sidedata_uuid = sidedata_uuid 144 self._sidedata_uuid = sidedata_uuid
145 self._older_sidedata_uuids = older_sidedata_uuids
146 assert not set(older_index_uuids) & set(older_data_uuids)
147 assert not set(older_data_uuids) & set(older_sidedata_uuids)
148 assert not set(older_index_uuids) & set(older_sidedata_uuids)
134 # thes asserts should be True as long as we have a single index filename 149 # thes asserts should be True as long as we have a single index filename
135 assert index_end <= pending_index_end 150 assert index_end <= pending_index_end
136 assert data_end <= pending_data_end 151 assert data_end <= pending_data_end
137 assert sidedata_end <= pending_sidedata_end 152 assert sidedata_end <= pending_sidedata_end
138 self._initial_index_end = index_end 153 self._initial_index_end = index_end
237 assert official_data_end <= self._data_end 252 assert official_data_end <= self._data_end
238 assert official_sidedata_end <= self._sidedata_end 253 assert official_sidedata_end <= self._sidedata_end
239 data = ( 254 data = (
240 self._version_header, 255 self._version_header,
241 len(self._index_uuid), 256 len(self._index_uuid),
257 len(self._older_index_uuids),
242 len(self._data_uuid), 258 len(self._data_uuid),
259 len(self._older_data_uuids),
243 len(self._sidedata_uuid), 260 len(self._sidedata_uuid),
261 len(self._older_sidedata_uuids),
244 official_index_end, 262 official_index_end,
245 self._index_end, 263 self._index_end,
246 official_data_end, 264 official_data_end,
247 self._data_end, 265 self._data_end,
248 official_sidedata_end, 266 official_sidedata_end,
249 self._sidedata_end, 267 self._sidedata_end,
250 self.default_compression_header, 268 self.default_compression_header,
251 ) 269 )
252 s = [] 270 s = []
253 s.append(S_HEADER.pack(*data)) 271 s.append(S_HEADER.pack(*data))
272
254 s.append(self._index_uuid) 273 s.append(self._index_uuid)
274 for u, size in self._older_index_uuids:
275 s.append(S_OLD_UID.pack(len(u), size))
276 for u, size in self._older_index_uuids:
277 s.append(u)
278
255 s.append(self._data_uuid) 279 s.append(self._data_uuid)
280 for u, size in self._older_data_uuids:
281 s.append(S_OLD_UID.pack(len(u), size))
282 for u, size in self._older_data_uuids:
283 s.append(u)
284
256 s.append(self._sidedata_uuid) 285 s.append(self._sidedata_uuid)
286 for u, size in self._older_sidedata_uuids:
287 s.append(S_OLD_UID.pack(len(u), size))
288 for u, size in self._older_sidedata_uuids:
289 s.append(u)
257 return b''.join(s) 290 return b''.join(s)
258 291
259 292
260 def default_docket(revlog, version_header): 293 def default_docket(revlog, version_header):
261 """given a revlog version a new docket object for the given revlog""" 294 """given a revlog version a new docket object for the given revlog"""
270 ) 303 )
271 docket._dirty = True 304 docket._dirty = True
272 return docket 305 return docket
273 306
274 307
308 def _parse_old_uids(get_data, count):
309 all_sizes = []
310 all_uids = []
311 for i in range(0, count):
312 raw = get_data(S_OLD_UID.size)
313 all_sizes.append(S_OLD_UID.unpack(raw))
314
315 for uid_size, file_size in all_sizes:
316 uid = get_data(uid_size)
317 all_uids.append((uid, file_size))
318 return all_uids
319
320
275 def parse_docket(revlog, data, use_pending=False): 321 def parse_docket(revlog, data, use_pending=False):
276 """given some docket data return a docket object for the given revlog""" 322 """given some docket data return a docket object for the given revlog"""
277 header = S_HEADER.unpack(data[: S_HEADER.size]) 323 header = S_HEADER.unpack(data[: S_HEADER.size])
278 324
279 # this is a mutable closure capture used in `get_data` 325 # this is a mutable closure capture used in `get_data`
295 version_header = next(iheader) 341 version_header = next(iheader)
296 342
297 index_uuid_size = next(iheader) 343 index_uuid_size = next(iheader)
298 index_uuid = get_data(index_uuid_size) 344 index_uuid = get_data(index_uuid_size)
299 345
346 older_index_uuid_count = next(iheader)
347 older_index_uuids = _parse_old_uids(get_data, older_index_uuid_count)
348
300 data_uuid_size = next(iheader) 349 data_uuid_size = next(iheader)
301 data_uuid = get_data(data_uuid_size) 350 data_uuid = get_data(data_uuid_size)
302 351
352 older_data_uuid_count = next(iheader)
353 older_data_uuids = _parse_old_uids(get_data, older_data_uuid_count)
354
303 sidedata_uuid_size = next(iheader) 355 sidedata_uuid_size = next(iheader)
304 sidedata_uuid = get_data(sidedata_uuid_size) 356 sidedata_uuid = get_data(sidedata_uuid_size)
357
358 older_sidedata_uuid_count = next(iheader)
359 older_sidedata_uuids = _parse_old_uids(get_data, older_sidedata_uuid_count)
305 360
306 index_size = next(iheader) 361 index_size = next(iheader)
307 362
308 pending_index_size = next(iheader) 363 pending_index_size = next(iheader)
309 364
320 docket = RevlogDocket( 375 docket = RevlogDocket(
321 revlog, 376 revlog,
322 use_pending=use_pending, 377 use_pending=use_pending,
323 version_header=version_header, 378 version_header=version_header,
324 index_uuid=index_uuid, 379 index_uuid=index_uuid,
380 older_index_uuids=older_index_uuids,
325 data_uuid=data_uuid, 381 data_uuid=data_uuid,
382 older_data_uuids=older_data_uuids,
326 sidedata_uuid=sidedata_uuid, 383 sidedata_uuid=sidedata_uuid,
384 older_sidedata_uuids=older_sidedata_uuids,
327 index_end=index_size, 385 index_end=index_size,
328 pending_index_end=pending_index_size, 386 pending_index_end=pending_index_size,
329 data_end=data_size, 387 data_end=data_size,
330 pending_data_end=pending_data_size, 388 pending_data_end=pending_data_size,
331 sidedata_end=sidedata_size, 389 sidedata_end=sidedata_size,