D7888: nodemap: track the maximum revision tracked in the nodemap

marmoute (Pierre-Yves David) phabricator at mercurial-scm.org
Wed Jan 15 09:58:50 EST 2020


marmoute created this revision.
Herald added a reviewer: indygreg.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  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.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D7888

AFFECTED FILES
  mercurial/debugcommands.py
  mercurial/pure/parsers.py
  mercurial/revlog.py
  mercurial/revlogutils/nodemap.py
  tests/test-persistent-nodemap.t

CHANGE DETAILS

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 @@
   $ 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=bc400bf49f11e83bbd25630439feee6628a80a8602d2e38972eac44cc3efe10c (glob)
   $ hg debugnodemap --dump-new | f --sha256 --size
@@ -51,8 +52,9 @@
   $ 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)
 
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 @@
     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 @@
         # store vfs
         with revlog.opener(datafile, '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, 'w', atomictemp=True) as fp:
@@ -142,7 +145,7 @@
 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 @@
         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/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -639,7 +639,7 @@
             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/pure/parsers.py b/mercurial/pure/parsers.py
--- a/mercurial/pure/parsers.py
+++ b/mercurial/pure/parsers.py
@@ -170,7 +170,7 @@
         self._nm_root = self._nm_max_idx = self._nm_rev = None
         return data
 
-    def update_nodemap_data(self, nm_data):
+    def update_nodemap_data(self, docket, nm_data):
         """provide full serialiazed data from a nodemap
 
         The data are expected to come from disk. See `nodemap_data_all` for a
@@ -178,7 +178,7 @@
         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/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -2130,6 +2130,7 @@
         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(



To: marmoute, indygreg, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list