Mercurial > public > mercurial-scm > hg
comparison mercurial/revlogutils/nodemap.py @ 44515:6c906eaedd0d
nodemap: track the tip_node for validation
Differential Revision: https://phab.mercurial-scm.org/D8184
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Thu, 27 Feb 2020 16:32:43 +0100 |
parents | 3265c92f7d13 |
children | 64e2f603de9d |
comparison
equal
deleted
inserted
replaced
44514:15a033cabc19 | 44515:6c906eaedd0d |
---|---|
36 (version,) = S_VERSION.unpack(pdata[offset : offset + S_VERSION.size]) | 36 (version,) = S_VERSION.unpack(pdata[offset : offset + S_VERSION.size]) |
37 if version != ONDISK_VERSION: | 37 if version != ONDISK_VERSION: |
38 return None | 38 return None |
39 offset += S_VERSION.size | 39 offset += S_VERSION.size |
40 headers = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size]) | 40 headers = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size]) |
41 uid_size, tip_rev, data_length, data_unused = headers | 41 uid_size, tip_rev, data_length, data_unused, tip_node_size = headers |
42 offset += S_HEADER.size | 42 offset += S_HEADER.size |
43 docket = NodeMapDocket(pdata[offset : offset + uid_size]) | 43 docket = NodeMapDocket(pdata[offset : offset + uid_size]) |
44 offset += uid_size | |
44 docket.tip_rev = tip_rev | 45 docket.tip_rev = tip_rev |
46 docket.tip_node = pdata[offset : offset + tip_node_size] | |
45 docket.data_length = data_length | 47 docket.data_length = data_length |
46 docket.data_unused = data_unused | 48 docket.data_unused = data_unused |
47 | 49 |
48 filename = _rawdata_filepath(revlog, docket) | 50 filename = _rawdata_filepath(revlog, docket) |
49 use_mmap = revlog.opener.options.get("exp-persistent-nodemap.mmap") | 51 use_mmap = revlog.opener.options.get("exp-persistent-nodemap.mmap") |
162 else: | 164 else: |
163 fd.flush() | 165 fd.flush() |
164 new_data = util.buffer(util.mmapread(fd, len(data))) | 166 new_data = util.buffer(util.mmapread(fd, len(data))) |
165 target_docket.data_length = len(data) | 167 target_docket.data_length = len(data) |
166 target_docket.tip_rev = revlog.tiprev() | 168 target_docket.tip_rev = revlog.tiprev() |
169 target_docket.tip_node = revlog.node(target_docket.tip_rev) | |
167 # EXP-TODO: if this is a cache, this should use a cache vfs, not a | 170 # EXP-TODO: if this is a cache, this should use a cache vfs, not a |
168 # store vfs | 171 # store vfs |
169 with revlog.opener(revlog.nodemap_file, b'w', atomictemp=True) as fp: | 172 with revlog.opener(revlog.nodemap_file, b'w', atomictemp=True) as fp: |
170 fp.write(target_docket.serialize()) | 173 fp.write(target_docket.serialize()) |
171 revlog._nodemap_docket = target_docket | 174 revlog._nodemap_docket = target_docket |
212 # nodemap gains the necessary features to be used in production. | 215 # nodemap gains the necessary features to be used in production. |
213 | 216 |
214 # version 0 is experimental, no BC garantee, do no use outside of tests. | 217 # version 0 is experimental, no BC garantee, do no use outside of tests. |
215 ONDISK_VERSION = 0 | 218 ONDISK_VERSION = 0 |
216 S_VERSION = struct.Struct(">B") | 219 S_VERSION = struct.Struct(">B") |
217 S_HEADER = struct.Struct(">BQQQ") | 220 S_HEADER = struct.Struct(">BQQQQ") |
218 | 221 |
219 ID_SIZE = 8 | 222 ID_SIZE = 8 |
220 | 223 |
221 | 224 |
222 def _make_uid(): | 225 def _make_uid(): |
240 # - When a new data file is created, a new identifier is generated. | 243 # - When a new data file is created, a new identifier is generated. |
241 self.uid = uid | 244 self.uid = uid |
242 # the tipmost revision stored in the data file. This revision and all | 245 # the tipmost revision stored in the data file. This revision and all |
243 # revision before it are expected to be encoded in the data file. | 246 # revision before it are expected to be encoded in the data file. |
244 self.tip_rev = None | 247 self.tip_rev = None |
248 # the node of that tipmost revision, if it mismatch the current index | |
249 # data the docket is not valid for the current index and should be | |
250 # discarded. | |
251 # | |
252 # note: this method is not perfect as some destructive operation could | |
253 # preserve the same tip_rev + tip_node while altering lower revision. | |
254 # However this multiple other caches have the same vulnerability (eg: | |
255 # brancmap cache). | |
256 self.tip_node = None | |
245 # the size (in bytes) of the persisted data to encode the nodemap valid | 257 # the size (in bytes) of the persisted data to encode the nodemap valid |
246 # for `tip_rev`. | 258 # for `tip_rev`. |
247 # - data file shorter than this are corrupted, | 259 # - data file shorter than this are corrupted, |
248 # - any extra data should be ignored. | 260 # - any extra data should be ignored. |
249 self.data_length = None | 261 self.data_length = None |
252 self.data_unused = 0 | 264 self.data_unused = 0 |
253 | 265 |
254 def copy(self): | 266 def copy(self): |
255 new = NodeMapDocket(uid=self.uid) | 267 new = NodeMapDocket(uid=self.uid) |
256 new.tip_rev = self.tip_rev | 268 new.tip_rev = self.tip_rev |
269 new.tip_node = self.tip_node | |
257 new.data_length = self.data_length | 270 new.data_length = self.data_length |
258 new.data_unused = self.data_unused | 271 new.data_unused = self.data_unused |
259 return new | 272 return new |
260 | 273 |
261 def __cmp__(self, other): | 274 def __cmp__(self, other): |
279 headers = ( | 292 headers = ( |
280 len(self.uid), | 293 len(self.uid), |
281 self.tip_rev, | 294 self.tip_rev, |
282 self.data_length, | 295 self.data_length, |
283 self.data_unused, | 296 self.data_unused, |
297 len(self.tip_node), | |
284 ) | 298 ) |
285 data.append(S_HEADER.pack(*headers)) | 299 data.append(S_HEADER.pack(*headers)) |
286 data.append(self.uid) | 300 data.append(self.uid) |
301 data.append(self.tip_node) | |
287 return b''.join(data) | 302 return b''.join(data) |
288 | 303 |
289 | 304 |
290 def _rawdata_filepath(revlog, docket): | 305 def _rawdata_filepath(revlog, docket): |
291 """The (vfs relative) nodemap's rawdata file for a given uid""" | 306 """The (vfs relative) nodemap's rawdata file for a given uid""" |