Patchwork [5,of,6] branchcache: let localrepo own the revbranchcache instance, save on close

login
register
mail settings
Submitter Mads Kiilerich
Date Dec. 14, 2014, 6:34 p.m.
Message ID <186394f5dbf37adf268f.1418582064@ssl.google-analytics.com>
Download mbox | patch
Permalink /patch/7091/
State Changes Requested
Headers show

Comments

Mads Kiilerich - Dec. 14, 2014, 6:34 p.m.
# HG changeset patch
# User Mads Kiilerich <madski@unity3d.com>
# Date 1418581984 -3600
#      Sun Dec 14 19:33:04 2014 +0100
# Node ID 186394f5dbf37adf268fa034fc897201fd2dbe0d
# Parent  a84099ef1a332eb93bc9287d74c64af7e510f90e
branchcache: let localrepo own the revbranchcache instance, save on close

This seems to be the best of way of making a shared branchcache available
everywhere, also to read-only operations like revsets.
Pierre-Yves David - Dec. 15, 2014, 12:29 a.m.
On 12/14/2014 10:34 AM, Mads Kiilerich wrote:
> # HG changeset patch
> # User Mads Kiilerich <madski@unity3d.com>
> # Date 1418581984 -3600
> #      Sun Dec 14 19:33:04 2014 +0100
> # Node ID 186394f5dbf37adf268fa034fc897201fd2dbe0d
> # Parent  a84099ef1a332eb93bc9287d74c64af7e510f90e
> branchcache: let localrepo own the revbranchcache instance, save on close
>
> This seems to be the best of way of making a shared branchcache available
> everywhere, also to read-only operations like revsets.
>
> diff --git a/mercurial/branchmap.py b/mercurial/branchmap.py
> --- a/mercurial/branchmap.py
> +++ b/mercurial/branchmap.py
> @@ -234,15 +234,14 @@
>           cl = repo.changelog
>           # collect new branch entries
>           newbranches = {}
> -        cache = revbranchcache(repo)
> -        getbranchinfoutf8 = cache.branchinfoutf8
> +        getbranchinfoutf8 = repo.revbranchcache.branchinfoutf8
>           for r in revgen:
>               branchutf8, closesbranch = getbranchinfoutf8(r)
>               branch = encoding.tolocal(branchutf8)
>               newbranches.setdefault(branch, []).append(r)
>               if closesbranch:
>                   self._closednodes.add(cl.node(r))
> -        cache.save()
> +        repo.revbranchcache.save()
>
>           # fetch current topological heads to speed up filtering
>           topoheads = set(cl.headrevs())
> diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
> --- a/mercurial/localrepo.py
> +++ b/mercurial/localrepo.py
> @@ -298,7 +298,8 @@
>           self.filteredrevcache = {}
>
>       def close(self):
> -        pass
> +        if hasunfilteredcache(self, 'revbranchcache'):
> +            self.revbranchcache.save()

We should save much sooner than close. It makes it very likely that 
simple longlived reader overwrites data from actual writter. You should 
probably tight some of the saving to the transaction logic to ensure 
cache are updated an coherent most of the time. And find a way to get it 
flushed as soon as possible after massive write.


>
>       def _restrictcapabilities(self, caps):
>           # bundle2 is not ready for prime time, drop it unless explicitly
> @@ -728,6 +729,11 @@
>           repo = (remote and remote.local()) and remote or self
>           return repo[key].branch()
>
> +    @unfilteredpropertycache
> +    def revbranchcache(self):
> +        """persistent cache of revision branch names"""
> +        return branchmap.revbranchcache(self)
> +

You very likely want this to be some sort of filecache to benefit from 
other process update (and reduce le likelyness of process writting on 
each other).

>       def known(self, nodes):
>           nm = self.changelog.nodemap
>           pc = self._phasecache
> diff --git a/mercurial/statichttprepo.py b/mercurial/statichttprepo.py
> --- a/mercurial/statichttprepo.py
> +++ b/mercurial/statichttprepo.py
> @@ -90,6 +90,12 @@
>       def canpush(self):
>           return False
>
> +class statichttprevbranchcache(object):
> +    def __init__(self, repo):
> +        self.branchinfoutf8 = repo.changelog.branchinfoutf8
> +    def save(self):
> +        pass

What about having and vfs attribute set to None in the readonly case? 
(or some way to detect readonly vfs on the vfs themself)

Patch

diff --git a/mercurial/branchmap.py b/mercurial/branchmap.py
--- a/mercurial/branchmap.py
+++ b/mercurial/branchmap.py
@@ -234,15 +234,14 @@ 
         cl = repo.changelog
         # collect new branch entries
         newbranches = {}
-        cache = revbranchcache(repo)
-        getbranchinfoutf8 = cache.branchinfoutf8
+        getbranchinfoutf8 = repo.revbranchcache.branchinfoutf8
         for r in revgen:
             branchutf8, closesbranch = getbranchinfoutf8(r)
             branch = encoding.tolocal(branchutf8)
             newbranches.setdefault(branch, []).append(r)
             if closesbranch:
                 self._closednodes.add(cl.node(r))
-        cache.save()
+        repo.revbranchcache.save()
 
         # fetch current topological heads to speed up filtering
         topoheads = set(cl.headrevs())
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -298,7 +298,8 @@ 
         self.filteredrevcache = {}
 
     def close(self):
-        pass
+        if hasunfilteredcache(self, 'revbranchcache'):
+            self.revbranchcache.save()
 
     def _restrictcapabilities(self, caps):
         # bundle2 is not ready for prime time, drop it unless explicitly
@@ -728,6 +729,11 @@ 
         repo = (remote and remote.local()) and remote or self
         return repo[key].branch()
 
+    @unfilteredpropertycache
+    def revbranchcache(self):
+        """persistent cache of revision branch names"""
+        return branchmap.revbranchcache(self)
+
     def known(self, nodes):
         nm = self.changelog.nodemap
         pc = self._phasecache
diff --git a/mercurial/statichttprepo.py b/mercurial/statichttprepo.py
--- a/mercurial/statichttprepo.py
+++ b/mercurial/statichttprepo.py
@@ -90,6 +90,12 @@ 
     def canpush(self):
         return False
 
+class statichttprevbranchcache(object):
+    def __init__(self, repo):
+        self.branchinfoutf8 = repo.changelog.branchinfoutf8
+    def save(self):
+        pass
+
 class statichttprepository(localrepo.localrepository):
     supported = localrepo.localrepository._basesupported
 
@@ -141,6 +147,7 @@ 
         self._branchcaches = {}
         self.encodepats = None
         self.decodepats = None
+        self.revbranchcache = statichttprevbranchcache(self)
 
     def _restrictcapabilities(self, caps):
         caps = super(statichttprepository, self)._restrictcapabilities(caps)