Patchwork [12,of,13] revlog: add a _datareadfp context manager for data access needs

login
register
mail settings
Submitter Boris Feld
Date Feb. 6, 2018, 1:21 p.m.
Message ID <6e3ed0354bf4f160bb7e.1517923293@FB>
Download mbox | patch
Permalink /patch/27364/
State New
Headers show

Comments

Boris Feld - Feb. 6, 2018, 1:21 p.m.
# HG changeset patch
# User Boris Feld <boris.feld@octobus.net>
# Date 1517849849 -3600
#      Mon Feb 05 17:57:29 2018 +0100
# Node ID 6e3ed0354bf4f160bb7e1402ca1548282ba8b772
# Parent  9073bbc68cb1ccc5685c78dbe837f31406324028
# EXP-Topic revlog-fp
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 6e3ed0354bf4
revlog: add a _datareadfp context manager for data access needs

The helper handles:
1) is there a file handle already open that we shall just reuse,
2) is the revlog inlined or not.

Using a context manager for all read access will help setting up file pointer
caching in later changesets.

Patch

diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -15,6 +15,7 @@  from __future__ import absolute_import
 
 import binascii
 import collections
+import contextlib
 import errno
 import hashlib
 import heapq
@@ -694,6 +695,19 @@  class revlog(object):
         """file object for the revlog's data file"""
         return self.opener(self.datafile, mode=mode)
 
+    @contextlib.contextmanager
+    def _datareadfp(self, existingfp=None):
+        """file object suitable to read data"""
+        if existingfp is not None:
+            yield existingfp
+        else:
+            if self._inline:
+                func = self._indexfp
+            else:
+                func = self._datafp
+            with func() as fp:
+                yield fp
+
     def tip(self):
         return self.node(len(self.index) - 2)
     def __contains__(self, rev):
@@ -1502,15 +1516,6 @@  class revlog(object):
 
         Returns a str or buffer of raw byte data.
         """
-        if df is not None:
-            closehandle = False
-        else:
-            if self._inline:
-                df = self._indexfp()
-            else:
-                df = self._datafp()
-            closehandle = True
-
         # Cache data both forward and backward around the requested
         # data, in a fixed size window. This helps speed up operations
         # involving reading the revlog backwards.
@@ -1518,10 +1523,9 @@  class revlog(object):
         realoffset = offset & ~(cachesize - 1)
         reallength = (((offset + length + cachesize) & ~(cachesize - 1))
                       - realoffset)
-        df.seek(realoffset)
-        d = df.read(reallength)
-        if closehandle:
-            df.close()
+        with self._datareadfp(df) as df:
+            df.seek(realoffset)
+            d = df.read(reallength)
         self._cachesegment(realoffset, d)
         if offset != realoffset or reallength != length:
             return util.buffer(d, offset - realoffset, length)