# HG changeset patch # User Pierre-Yves David # Date 2020-01-15 14:50:14 # Node ID e41a164db7a98a957d5e88f4bd8b0d5a443e1714 # Parent 6614b301ea5887acc30a694344188b0ad826a613 nodemap: track the maximum revision tracked in the nodemap We need a simple way to detect when the on disk data contains less revision than the index we read from disk. The docket file is meant for this, we just had to start tracking that data. We should also try to detect strip operation, but we will deal with this in later changesets. Right now we are focusing on defining the API for index supporting persistent nodemap. Differential Revision: https://phab.mercurial-scm.org/D7888 diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -2137,6 +2137,7 @@ def debugnodemap(ui, repo, **opts): if nm_data is not None: docket, data = nm_data ui.write((b"uid: %s\n") % docket.uid) + ui.write((b"tip-rev: %d\n") % docket.tip_rev) @command( diff --git a/mercurial/pure/parsers.py b/mercurial/pure/parsers.py --- a/mercurial/pure/parsers.py +++ b/mercurial/pure/parsers.py @@ -170,15 +170,15 @@ class PersistentNodeMapIndexObject(Index self._nm_root = self._nm_max_idx = self._nm_rev = None return data - def update_nodemap_data(self, nm_data): - """provide full blokc of persisted binary data for a nodemap + def update_nodemap_data(self, docket, nm_data): + """provide full block of persisted binary data for a nodemap The data are expected to come from disk. See `nodemap_data_all` for a produceur of such data.""" if nm_data is not None: self._nm_root, self._nm_max_idx = nodemaputil.parse_data(nm_data) if self._nm_root: - self._nm_rev = len(self) - 1 + self._nm_rev = docket.tip_rev else: self._nm_root = self._nm_max_idx = self._nm_rev = None diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py @@ -639,7 +639,7 @@ class revlog(object): if use_nodemap: nodemap_data = nodemaputil.persisted_data(self) if nodemap_data is not None: - index.update_nodemap_data(nodemap_data[1]) + index.update_nodemap_data(*nodemap_data) except (ValueError, IndexError): raise error.RevlogError( _(b"index %s is corrupted") % self.indexfile diff --git a/mercurial/revlogutils/nodemap.py b/mercurial/revlogutils/nodemap.py --- a/mercurial/revlogutils/nodemap.py +++ b/mercurial/revlogutils/nodemap.py @@ -36,9 +36,11 @@ def persisted_data(revlog): if version != ONDISK_VERSION: return None offset += S_VERSION.size - (uid_size,) = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size]) + headers = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size]) + uid_size, tip_rev = headers offset += S_HEADER.size docket = NodeMapDocket(pdata[offset : offset + uid_size]) + docket.tip_rev = tip_rev filename = _rawdata_filepath(revlog, docket) return docket, revlog.opener.tryread(filename) @@ -94,6 +96,7 @@ def _persist_nodemap(tr, revlog): # store vfs with revlog.opener(datafile, b'w') as fd: fd.write(data) + target_docket.tip_rev = revlog.tiprev() # EXP-TODO: if this is a cache, this should use a cache vfs, not a # store vfs with revlog.opener(revlog.nodemap_file, b'w', atomictemp=True) as fp: @@ -142,7 +145,7 @@ def _persist_nodemap(tr, revlog): ONDISK_VERSION = 0 S_VERSION = struct.Struct(">B") -S_HEADER = struct.Struct(">B") +S_HEADER = struct.Struct(">BQ") ID_SIZE = 8 @@ -164,15 +167,19 @@ class NodeMapDocket(object): if uid is None: uid = _make_uid() self.uid = uid + self.tip_rev = None def copy(self): - return NodeMapDocket(uid=self.uid) + new = NodeMapDocket(uid=self.uid) + new.tip_rev = self.tip_rev + return new def serialize(self): """return serialized bytes for a docket using the passed uid""" data = [] data.append(S_VERSION.pack(ONDISK_VERSION)) - data.append(S_HEADER.pack(len(self.uid))) + headers = (len(self.uid), self.tip_rev) + data.append(S_HEADER.pack(*headers)) data.append(self.uid) return b''.join(data) diff --git a/tests/test-persistent-nodemap.t b/tests/test-persistent-nodemap.t --- a/tests/test-persistent-nodemap.t +++ b/tests/test-persistent-nodemap.t @@ -14,8 +14,9 @@ Test the persistent on-disk nodemap $ hg debugbuilddag .+5000 $ hg debugnodemap --metadata uid: ???????????????? (glob) + tip-rev: 5000 $ f --size .hg/store/00changelog.n - .hg/store/00changelog.n: size=18 + .hg/store/00changelog.n: size=26 $ f --sha256 .hg/store/00changelog-*.nd .hg/store/00changelog-????????????????.nd: sha256=b961925120e1c9bc345c199b2cc442abc477029fdece37ef9d99cbe59c0558b7 (glob) $ hg debugnodemap --dump-new | f --sha256 --size @@ -51,8 +52,9 @@ add a new commit $ hg ci -m 'foo' $ hg debugnodemap --metadata uid: ???????????????? (glob) + tip-rev: 5001 $ f --size .hg/store/00changelog.n - .hg/store/00changelog.n: size=18 + .hg/store/00changelog.n: size=26 (The pure code use the debug code that perform incremental update, the C code reencode from scratch)