浏览代码

Add simple mmap wrapper.

Jelmer Vernooij 16 年之前
父节点
当前提交
2c0f278a2a
共有 1 个文件被更改,包括 17 次插入11 次删除
  1. 17 11
      dulwich/pack.py

+ 17 - 11
dulwich/pack.py

@@ -34,6 +34,10 @@ a pointer in to the corresponding packfile.
 
 
 import mmap
 import mmap
 import os
 import os
+import sys
+
+supports_mmap_offset = (sys.version_info[0] >= 3 or 
+        (sys.version_info[0] == 2 and sys.version_info[1] >= 6))
 
 
 from objects import (ShaFile,
 from objects import (ShaFile,
                      _decompress,
                      _decompress,
@@ -41,13 +45,23 @@ from objects import (ShaFile,
 
 
 hex_to_sha = lambda hex: int(hex, 16)
 hex_to_sha = lambda hex: int(hex, 16)
 
 
+def simple_mmap(f, offset, size, access=mmap.ACCESS_READ):
+    if offset+size > MAX_MMAP_SIZE and not supports_mmap_offset:
+        raise AssertionError("%s is larger than 256 meg, and this version "
+            "of Python does not support the offset argument to mmap().")
+    if supports_mmap_offset:
+        return mmap.mmap(f.fileno(), size, access=access, offset=offset), 0
+    else:
+        return mmap.mmap(f.fileno(), size, access=access), offset
+
+
 def multi_ord(map, start, count):
 def multi_ord(map, start, count):
   value = 0
   value = 0
   for i in range(count):
   for i in range(count):
     value = value * 256 + ord(map[start+i])
     value = value * 256 + ord(map[start+i])
   return value
   return value
 
 
-max_size = 256 * 1024 * 1024
+MAX_MMAP_SIZE = 256 * 1024 * 1024
 
 
 class PackIndex(object):
 class PackIndex(object):
   """An index in to a packfile.
   """An index in to a packfile.
@@ -82,10 +96,6 @@ class PackIndex(object):
     self._size = os.path.getsize(filename)
     self._size = os.path.getsize(filename)
     assert self._size > self.header_size, "%s is too small to be a packfile" % \
     assert self._size > self.header_size, "%s is too small to be a packfile" % \
         filename
         filename
-    assert self._size < max_size, "%s is larger than 256 meg, and it " \
-        "might not be a good idea to mmap it. If you want to go ahead " \
-        "delete this check, or get python to support mmap offsets so that " \
-        "I can map the files sensibly"
 
 
   def object_index(self, sha):
   def object_index(self, sha):
     """Return the index in to the corresponding packfile for the object.
     """Return the index in to the corresponding packfile for the object.
@@ -99,7 +109,7 @@ class PackIndex(object):
          "like that" % self._filename
          "like that" % self._filename
     f = open(self._filename, 'rb')
     f = open(self._filename, 'rb')
     try:
     try:
-      map = mmap.mmap(f.fileno(), size, access=mmap.ACCESS_READ)
+      map, _ = simple_mmap(f, 0, size)
       return self._object_index(map, sha)
       return self._object_index(map, sha)
     finally:
     finally:
       f.close()
       f.close()
@@ -163,10 +173,6 @@ class PackData(object):
     self._filename = filename
     self._filename = filename
     assert os.path.exists(filename), "%s is not a packfile" % filename
     assert os.path.exists(filename), "%s is not a packfile" % filename
     self._size = os.path.getsize(filename)
     self._size = os.path.getsize(filename)
-    assert self._size < max_size, "%s is larger than 256 meg, and it " \
-        "might not be a good idea to mmap it. If you want to go ahead " \
-        "delete this check, or get python to support mmap offsets so that " \
-        "I can map the files sensibly"
 
 
   def get_object_at(self, offset):
   def get_object_at(self, offset):
     """Given an offset in to the packfile return the object that is there.
     """Given an offset in to the packfile return the object that is there.
@@ -182,7 +188,7 @@ class PackData(object):
          "like that" % self._filename
          "like that" % self._filename
     f = open(self._filename, 'rb')
     f = open(self._filename, 'rb')
     try:
     try:
-      map = mmap.mmap(f.fileno(), size, access=mmap.ACCESS_READ)
+      map, offset = simple_mmap(f, offset, size)
       return self._get_object_at(map, offset)
       return self._get_object_at(map, offset)
     finally:
     finally:
       f.close()
       f.close()