changeset 51907:bd7359c18d69

rev-branch-cache: fallback on "v1" data if no v2 is found This will help smooth the transition to the v2 format for existing large repository.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 24 Sep 2024 15:44:10 +0200
parents 0f26ee69cf36
children 16efed18ae4e
files mercurial/branching/rev_cache.py tests/test-branches.t tests/test-static-http.t
diffstat 3 files changed, 90 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/branching/rev_cache.py	Tue Sep 24 03:16:35 2024 +0200
+++ b/mercurial/branching/rev_cache.py	Tue Sep 24 15:44:10 2024 +0200
@@ -33,6 +33,9 @@
 _rbcversion = b'-v2'
 _rbcnames = b'rbc-names' + _rbcversion
 _rbcrevs = b'rbc-revs' + _rbcversion
+_rbc_legacy_version = b'-v1'
+_rbc_legacy_names = b'rbc-names' + _rbc_legacy_version
+_rbc_legacy_revs = b'rbc-revs' + _rbc_legacy_version
 # [4 byte hash prefix][4 byte branch name number with sign bit indicating open]
 _rbcrecfmt = b'>4sI'
 _rbcrecsize = calcsize(_rbcrecfmt)
@@ -143,8 +146,17 @@
         self._names = []  # branch names in local encoding with static index
         self._rbcrevs = rbcrevs(bytearray())
         self._rbcsnameslen = 0  # length of names read at _rbcsnameslen
+        v1_fallback = False
         try:
-            bndata = repo.cachevfs.read(_rbcnames)
+            try:
+                bndata = repo.cachevfs.read(_rbcnames)
+            except (IOError, OSError):
+                # If we don't have "v2" data, we might have "v1" data worth
+                # using.
+                #
+                # consider stop doing this many version after hg-6.9 release
+                bndata = repo.cachevfs.read(_rbc_legacy_names)
+                v1_fallback = True
             self._rbcsnameslen = len(bndata)  # for verification before writing
             if bndata:
                 self._names = [
@@ -158,10 +170,19 @@
         if self._names:
             try:
                 usemmap = repo.ui.configbool(b'storage', b'revbranchcache.mmap')
-                with repo.cachevfs(_rbcrevs) as fp:
-                    if usemmap and repo.cachevfs.is_mmap_safe(_rbcrevs):
-                        data = util.buffer(util.mmapread(fp))
-                    else:
+                if not v1_fallback:
+                    with repo.cachevfs(_rbcrevs) as fp:
+                        if usemmap and repo.cachevfs.is_mmap_safe(_rbcrevs):
+                            data = util.buffer(util.mmapread(fp))
+                        else:
+                            data = fp.read()
+                else:
+                    # If we don't have "v2" data, we might have "v1" data worth
+                    # using.
+                    #
+                    # Consider stop doing this many version after hg-6.9
+                    # release.
+                    with repo.cachevfs(_rbc_legacy_revs) as fp:
                         data = fp.read()
                 self._rbcrevs = rbcrevs(data)
             except (IOError, OSError) as inst:
--- a/tests/test-branches.t	Tue Sep 24 03:16:35 2024 +0200
+++ b/tests/test-branches.t	Tue Sep 24 15:44:10 2024 +0200
@@ -877,6 +877,69 @@
   .hg/cache/rbc-revs-v2: size=160
   0000: 19 70 9c 5a 00 00 00 00 dd 6b 44 0d 00 00 00 01 |.p.Z.....kD.....|
 
+Smoothly reuse "v1" format if no v2 exists
+------------------------------------------
+
+read only operation with valid data(
+(does not need to rewrite anything, maybe we should force it?)
+
+  $ rm .hg/cache/rbc-names-v2
+  $ rm .hg/cache/rbc-revs-v2
+  $ rm .hg/cache/branch*
+  $ hg head a -T '{rev}\n' --debug
+  5
+  $ mv .hg/cache/rbc-names-v2 .hg/cache/rbc-names-v1
+  $ mv .hg/cache/rbc-revs-v2 .hg/cache/rbc-revs-v1
+  $ rm .hg/cache/branch*
+  $ hg head a -T '{rev}\n' --debug
+  5
+  $ f --size .hg/cache/rbc-*-*
+  .hg/cache/rbc-names-v1: size=92
+  .hg/cache/rbc-revs-v1: size=160
+
+
+Write operation write a full v2 files
+
+  $ hg branch not-here-for-long
+  marked working directory as branch not-here-for-long
+  $ hg ci -m not-long --debug
+  reusing manifest from p1 (no file change)
+  committing changelog
+  rbc-names-v2 changed - rewriting it
+  updating the branch cache
+  committed changeset * (glob)
+  $ f --size .hg/cache/rbc-*
+  .hg/cache/rbc-names-v1: size=92
+  .hg/cache/rbc-names-v2: size=110
+  .hg/cache/rbc-revs-v1: size=160
+  .hg/cache/rbc-revs-v2: size=168
+
+
+With invalid v1 data, we rewrite it too (as v2)
+
+  $ cp .hg/cache/rbc-names-v2 .hg/cache/rbc-names-v1
+  $ mv .hg/cache/rbc-names-v2 .hg/cache/rbc-revs-v1
+  $ rm .hg/cache/rbc-revs-v2
+  $ rm .hg/cache/branch*
+  $ 
+  $ hg head a -T '{rev}\n' --debug
+  history modification detected - truncating revision branch cache to revision 0
+  5
+  $ f --size .hg/cache/rbc-*-*
+  .hg/cache/rbc-names-v1: size=110
+  .hg/cache/rbc-revs-v1: size=110
+  .hg/cache/rbc-revs-v2: size=168
+
+cleanup
+
+  $ hg up -qr '.^'
+  $ hg rollback -qf
+  $ rm .hg/cache/*
+  $ hg debugupdatecache
+  $ f --size .hg/cache/rbc-*
+  .hg/cache/rbc-names-v2: size=92
+  .hg/cache/rbc-revs-v2: size=160
+
 cache is updated when committing
   $ hg branch i-will-regret-this
   marked working directory as branch i-will-regret-this
--- a/tests/test-static-http.t	Tue Sep 24 03:16:35 2024 +0200
+++ b/tests/test-static-http.t	Tue Sep 24 15:44:10 2024 +0200
@@ -267,6 +267,7 @@
   /remote/.hg/cache/branch2-immutable
   /remote/.hg/cache/branch2-served
   /remote/.hg/cache/hgtagsfnodes1
+  /remote/.hg/cache/rbc-names-v1
   /remote/.hg/cache/rbc-names-v2
   /remote/.hg/cache/tags2-served
   /remote/.hg/dirstate