Commits

Roberto De Almeida  committed 15df1c0

Use mmap offset if available. Renamed some confusing variable names.

  • Participants
  • Parent commits a74f288

Comments (0)

Files changed (1)

     9
     >>> f.close()
 
-TODO:
- * properly implement ``_FillValue``.
- * implement Jeff Whitaker's patch for masked variables.
- * fix character variables.
- * implement PAGESIZE for Python 2.6?
 """
 
 __all__ = ['netcdf_file']
 
 
 from operator import mul
-from mmap import mmap, ACCESS_READ, ALLOCATIONGRANULARITY
+from mmap import mmap, ACCESS_READ
+try:
+    from mmap import ALLOCATIONGRANULARITY
+except ImportError:
+    ALLOCATIONGRANULARITY = None
 
 import numpy as np
 from numpy.compat import asbytes, asstr
         if not header in [ZERO, NC_VARIABLE]:
             raise ValueError("Unexpected header.")
 
-        begin = 0
+        records = 0
         dtypes = {'names': [], 'formats': []}
         rec_vars = []
         count = self._unpack_int()
         for var in range(count):
-            name, dimensions, shape, attributes, type, begin_, vsize = self._read_var()
+            name, dimensions, shape, attributes, type, start, vsize = self._read_var()
             # http://www.unidata.ucar.edu/software/netcdf/docs/netcdf.html
             # Note that vsize is the product of the dimension lengths
             # (omitting the record dimension) and the number of bytes
                 # The netCDF "record size" is calculated as the sum of
                 # the vsize's of all the record variables.
                 self.__dict__['_recsize'] += vsize
-                if begin == 0: begin = begin_
+                # Store the position where record arrays start.
+                if records == 0:
+                    records = start
                 dtypes['names'].append(name)
                 dtypes['formats'].append(str(shape[1:]) + type)
 
                 size = reduce(mul, shape, 1) * type.itemsize
                 pos = self.fp.tell()
                 if self.use_mmap:
-                    offset = begin_ - (begin_ % ALLOCATIONGRANULARITY)
-                    begin_ = begin_ % ALLOCATIONGRANULARITY
-                    mm = mmap(self.fp.fileno(), begin_+size, access=ACCESS_READ, offset=offset)
+                    if ALLOCATIONGRANULARITY:
+                        pages = start // ALLOCATIONGRANULARITY
+                        offset = pages * ALLOCATIONGRANULARITY
+                        start = start % ALLOCATIONGRANULARITY
+                        mm = mmap(self.fp.fileno(), start+size, access=ACCESS_READ, offset=offset)
+                    else:
+                        mm = mmap(self.fp.fileno(), start+size, access=ACCESS_READ)
+
                     data = ndarray.__new__(ndarray, shape, dtype=type,
-                            buffer=mm, offset=begin_, order=0)
+                            buffer=mm, offset=start, order=0)
                 else:
-                    self.fp.seek(begin_)
+                    self.fp.seek(start)
                     data = fromstring(self.fp.read(size), type)
                     data.shape = shape
                 self.fp.seek(pos)
             # Build rec array.
             pos = self.fp.tell()
             if self.use_mmap:
-                offset = begin - (begin % ALLOCATIONGRANULARITY)
-                begin = begin % ALLOCATIONGRANULARITY
-                mm = mmap(self.fp.fileno(), begin+self._recs*self._recsize, access=ACCESS_READ, offset=offset)
+                if ALLOCATIONGRANULARITY:
+                    pages = records // ALLOCATIONGRANULARITY
+                    offset = pages * ALLOCATIONGRANULARITY
+                    records = records % ALLOCATIONGRANULARITY
+                    mm = mmap(self.fp.fileno(), records+self._recs*self._recsize, access=ACCESS_READ, offset=offset)
+                else:
+                    mm = mmap(self.fp.fileno(), records+self._recs*self._recsize, access=ACCESS_READ)
+
                 rec_array = ndarray.__new__(ndarray, (self._recs,), dtype=dtypes,
-                        buffer=mm, offset=begin, order=0)
+                        buffer=mm, offset=records, order=0)
             else:
-                self.fp.seek(begin)
+                self.fp.seek(records)
                 rec_array = fromstring(self.fp.read(self._recs*self._recsize), dtype=dtypes)
                 rec_array.shape = (self._recs,)
             self.fp.seek(pos)
         attributes = self._read_att_array()
         nc_type = self.fp.read(4)
         vsize = self._unpack_int()
-        begin = [self._unpack_int, self._unpack_int64][self.version_byte-1]()
+        start = [self._unpack_int, self._unpack_int64][self.version_byte-1]()
         type = TYPEMAP[nc_type]
 
-        return name, dimensions, shape, attributes, type, begin, vsize
+        return name, dimensions, shape, attributes, type, start, vsize
 
     def _read_values(self):
         nc_type = self.fp.read(4)