[pypy-svn] r47356 - in pypy/dist/pypy/module/mmap: . test
fijal at codespeak.net
fijal at codespeak.net
Tue Oct 9 17:10:21 CEST 2007
Author: fijal
Date: Tue Oct 9 17:10:20 2007
New Revision: 47356
Modified:
pypy/dist/pypy/module/mmap/__init__.py
pypy/dist/pypy/module/mmap/interp_mmap.py
pypy/dist/pypy/module/mmap/test/test_mmap.py
Log:
Move mmap module to use new interface. Windows version is broken because
of that (should be relatively trivial to fix)
Modified: pypy/dist/pypy/module/mmap/__init__.py
==============================================================================
--- pypy/dist/pypy/module/mmap/__init__.py (original)
+++ pypy/dist/pypy/module/mmap/__init__.py Tue Oct 9 17:10:20 2007
@@ -1,4 +1,5 @@
from pypy.interpreter.mixedmodule import MixedModule
+from pypy.rlib import rmmap
class Module(MixedModule):
interpleveldefs = {
@@ -15,7 +16,7 @@
def buildloaders(cls):
from pypy.module.mmap import interp_mmap
- for constant, value in interp_mmap.constants.iteritems():
+ for constant, value in rmmap.constants.iteritems():
if isinstance(value, int):
Module.interpleveldefs[constant] = "space.wrap(%r)" % value
Modified: pypy/dist/pypy/module/mmap/interp_mmap.py
==============================================================================
--- pypy/dist/pypy/module/mmap/interp_mmap.py (original)
+++ pypy/dist/pypy/module/mmap/interp_mmap.py Tue Oct 9 17:10:20 2007
@@ -4,529 +4,142 @@
from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable
from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.gateway import interp2app
+from pypy.rlib import rmmap
+from pypy.rlib.rmmap import RValueError, RTypeError, REnvironmentError
import sys
import os
import platform
import stat
-_POSIX = os.name == "posix"
-_MS_WINDOWS = os.name == "nt"
-_LINUX = "linux" in sys.platform
-_64BIT = "64bit" in platform.architecture()[0]
-
-class CConfig:
- _includes_ = ("sys/types.h",'unistd.h')
- _header_ = '#define _GNU_SOURCE\n'
- size_t = rffi_platform.SimpleType("size_t", rffi.LONG)
- off_t = rffi_platform.SimpleType("off_t", rffi.LONG)
-
-constants = {}
-if _POSIX:
- CConfig._includes_ += ("sys/mman.h",)
- # constants, look in sys/mman.h and platform docs for the meaning
- # some constants are linux only so they will be correctly exposed outside
- # depending on the OS
- constant_names = ['MAP_SHARED', 'MAP_PRIVATE',
- 'PROT_READ', 'PROT_WRITE',
- 'MS_SYNC']
- opt_constant_names = ['MAP_ANON', 'MAP_ANONYMOUS',
- 'PROT_EXEC',
- 'MAP_DENYWRITE', 'MAP_EXECUTABLE']
- for name in constant_names:
- setattr(CConfig, name, rffi_platform.ConstantInteger(name))
- for name in opt_constant_names:
- setattr(CConfig, name, rffi_platform.DefinedConstantInteger(name))
-
- CConfig.MREMAP_MAYMOVE = (
- rffi_platform.DefinedConstantInteger("MREMAP_MAYMOVE"))
- CConfig.has_mremap = rffi_platform.Has('mremap(NULL, 0, 0, 0)')
- # a dirty hack, this is probably a macro
-
-elif _MS_WINDOWS:
- CConfig._includes_ += ("windows.h",)
- constant_names = ['PAGE_READONLY', 'PAGE_READWRITE', 'PAGE_WRITECOPY',
- 'FILE_MAP_READ', 'FILE_MAP_WRITE', 'FILE_MAP_COPY',
- 'DUPLICATE_SAME_ACCESS']
- for name in constant_names:
- setattr(CConfig, name, rffi_platform.ConstantInteger(name))
-
-# export the constants inside and outside. see __init__.py
-cConfig = rffi_platform.configure(CConfig)
-constants.update(cConfig)
-
-if _POSIX:
- # MAP_ANONYMOUS is not always present but it's always available at CPython level
- if constants["MAP_ANONYMOUS"] is None:
- constants["MAP_ANONYMOUS"] = constants["MAP_ANON"]
- assert constants["MAP_ANONYMOUS"] is not None
- constants["MAP_ANON"] = constants["MAP_ANONYMOUS"]
-
-locals().update(constants)
-
-_ACCESS_DEFAULT, ACCESS_READ, ACCESS_WRITE, ACCESS_COPY = range(4)
-
-def external(name, args, result):
- return rffi.llexternal(name, args, result, includes=CConfig._includes_)
-
-PTR = rffi.CCHARP
-
-has_mremap = cConfig['has_mremap']
-
-c_memmove = external('memmove', [PTR, PTR, size_t], lltype.Void)
-
-if _POSIX:
- c_mmap = external('mmap', [PTR, size_t, rffi.INT, rffi.INT,
- rffi.INT, off_t], PTR)
- c_munmap = external('munmap', [PTR, size_t], rffi.INT)
- c_msync = external('msync', [PTR, size_t, rffi.INT], rffi.INT)
- if has_mremap:
- c_mremap = external('mremap', [PTR, size_t, size_t, rffi.ULONG], PTR)
-
- _get_page_size = external('getpagesize', [], rffi.INT)
-
- def _get_error_msg():
- errno = rffi.get_errno()
- return os.strerror(errno)
-elif _MS_WINDOWS:
- XXX
- from ctypes import wintypes
-
- WORD = wintypes.WORD
- DWORD = wintypes.DWORD
- BOOL = wintypes.BOOL
- LONG = wintypes.LONG
- LPVOID = PTR
- LPCVOID = LPVOID
- DWORD_PTR = DWORD
- rffi.INT = wintypes.rffi.INT
- INVALID_c_int_VALUE = c_int(-1).value
-
- class SYSINFO_STRUCT(Structure):
- _fields_ = [("wProcessorArchitecture", WORD),
- ("wReserved", WORD)]
-
- class SYSINFO_UNION(Union):
- _fields_ = [("dwOemId", DWORD),
- ("struct", SYSINFO_STRUCT)]
-
- class SYSTEM_INFO(Structure):
- _fields_ = [("union", SYSINFO_UNION),
- ("dwPageSize", DWORD),
- ("lpMinimumApplicationAddress", LPVOID),
- ("lpMaximumApplicationAddress", LPVOID),
- ("dwActiveProcessorMask", DWORD_PTR),
- ("dwNumberOfProcessors", DWORD),
- ("dwProcessorType", DWORD),
- ("dwAllocationGranularity", DWORD),
- ("wProcessorLevel", WORD),
- ("wProcessorRevision", WORD)]
-
- windll.kernel32.GetSystemInfo.argtypes = [POINTER(SYSTEM_INFO)]
- GetFileSize = windll.kernel32.GetFileSize
- GetFileSize.argtypes = [rffi.INT, POINTER(rffi.INT)]
- GetFileSize.restype = rffi.INT
- GetCurrentProcess = windll.kernel32.GetCurrentProcess
- GetCurrentProcess.restype = rffi.INT
- DuplicateHandle = windll.kernel32.DuplicateHandle
- DuplicateHandle.argtypes = [rffi.INT, rffi.INT, rffi.INT, POINTER(rffi.INT), DWORD,
- BOOL, DWORD]
- DuplicateHandle.restype = BOOL
- CreateFileMapping = windll.kernel32.CreateFileMappingA
- CreateFileMapping.argtypes = [rffi.INT, PTR, rffi.INT, rffi.INT, rffi.INT,
- c_char_p]
- CreateFileMapping.restype = rffi.INT
- MapViewOfFile = windll.kernel32.MapViewOfFile
- MapViewOfFile.argtypes = [rffi.INT, DWORD, DWORD, DWORD, DWORD]
- MapViewOfFile.restype = PTR
- CloseHandle = windll.kernel32.CloseHandle
- CloseHandle.argtypes = [rffi.INT]
- CloseHandle.restype = BOOL
- UnmapViewOfFile = windll.kernel32.UnmapViewOfFile
- UnmapViewOfFile.argtypes = [LPCVOID]
- UnmapViewOfFile.restype = BOOL
- FlushViewOfFile = windll.kernel32.FlushViewOfFile
- FlushViewOfFile.argtypes = [LPCVOID, rffi.INT]
- FlushViewOfFile.restype = BOOL
- SetFilePointer = windll.kernel32.SetFilePointer
- SetFilePointer.argtypes = [rffi.INT, rffi.INT, POINTER(rffi.INT), rffi.INT]
- SetEndOfFile = windll.kernel32.SetEndOfFile
- SetEndOfFile.argtypes = [rffi.INT]
- msvcr71 = cdll.LoadLibrary("msvcr71.dll")
- msvcr71._get_osfhandle.argtypes = [rffi.INT]
- msvcr71._get_osfhandle.restype = rffi.INT
- # libc._lseek.argtypes = [rffi.INT, rffi.INT, rffi.INT]
- # libc._lseek.restype = rffi.INT
-
-
- def _get_page_size():
- si = SYSTEM_INFO()
- windll.kernel32.GetSystemInfo(byref(si))
- return int(si.dwPageSize)
-
- def _get_file_size(space, handle):
- # XXX use native Windows types like WORD
- high = rffi.INT(0)
- low = rffi.INT(windll.kernel32.GetFileSize(rffi.INT(handle.value), byref(high)))
- # low might just happen to have the value INVALID_FILE_SIZE
- # so we need to check the last error also
- INVALID_FILE_SIZE = -1
- NO_ERROR = 0
- dwErr = GetLastError()
- if low.value == INVALID_FILE_SIZE and dwErr != NO_ERROR:
- raise OperationError(space.w_EnvironmentError,
- space.wrap(os.strerror(dwErr)))
- return low.value, high.value
-
- def _get_error_msg():
- errno = GetLastError()
- return os.strerror(errno)
-
-PAGESIZE = _get_page_size()
-NULL = lltype.nullptr(PTR.TO)
-NODATA = lltype.nullptr(PTR.TO)
-INVALID_INT_VALUE = -1
-
-# ____________________________________________________________
-
-# XXX the methods should take unsigned int arguments instead of int
-
class W_MMap(Wrappable):
- def __init__(self, space, access):
+ def __init__(self, space, mmap_obj):
self.space = space
- self.size = 0
- self.pos = 0
- self.access = access
-
- if _MS_WINDOWS:
- self.map_handle = 0
- self.file_handle = 0
- self.tagname = ""
- elif _POSIX:
- self.fd = -1
- self.closed = False
-
- def check_valid(self):
- if _MS_WINDOWS:
- to_close = self.map_handle.value == INVALID_INT_VALUE
- elif _POSIX:
- to_close = self.closed
-
- if to_close:
- raise OperationError(self.space.w_ValueError,
- self.space.wrap("map closed or invalid"))
-
- def check_writeable(self):
- if not (self.access != ACCESS_READ):
- raise OperationError(self.space.w_TypeError,
- self.space.wrap("mmap can't modify a readonly memory map."))
-
- def check_resizeable(self):
- if not (self.access == ACCESS_WRITE or self.access == _ACCESS_DEFAULT):
- raise OperationError(self.space.w_TypeError,
- self.space.wrap(
- "mmap can't resize a readonly or copy-on-write memory map."))
-
- def setdata(self, data, size):
- """Set the internal data and map size from a PTR."""
- assert size >= 0
- self.data = data
- self.size = size
-
+ self.mmap = mmap_obj
+
def close(self):
- if _MS_WINDOWS:
- if self.size > 0:
- self.unmapview()
- self.setdata(NODATA, 0)
- if self.map_handle.value != INVALID_rffi.INT_VALUE:
- CloseHandle(self.map_handle)
- self.map_handle.value = INVALID_rffi.INT_VALUE
- if self.file_handle.value != INVALID_rffi.INT_VALUE:
- CloseHandle(self.file_handle)
- self.file_handle.value = INVALID_rffi.INT_VALUE
- elif _POSIX:
- self.closed = True
- if self.fd != -1:
- os.close(self.fd)
- self.fd = -1
- if self.size > 0:
- c_munmap(self.getptr(0), self.size)
- self.setdata(NODATA, 0)
+ self.mmap.close()
close.unwrap_spec = ['self']
-
- def unmapview(self):
- UnmapViewOfFile(self.getptr(0))
-
- def read_byte(self):
- self.check_valid()
- if self.pos < self.size:
- value = self.data[self.pos]
- self.pos += 1
- return self.space.wrap(value)
- else:
+ def read_byte(self):
+ try:
+ return self.space.wrap(self.mmap.read_byte())
+ except RValueError, v:
raise OperationError(self.space.w_ValueError,
- self.space.wrap("read byte out of range"))
+ self.space.wrap(v.message))
read_byte.unwrap_spec = ['self']
def readline(self):
- self.check_valid()
-
- data = self.data
- for pos in xrange(self.pos, self.size):
- if data[pos] == '\n':
- eol = pos + 1 # we're interested in the position after new line
- break
- else: # no '\n' found
- eol = self.size
-
- res = "".join([data[i] for i in range(self.pos, eol)])
- self.pos += len(res)
- return self.space.wrap(res)
+ return self.space.wrap(self.mmap.readline())
readline.unwrap_spec = ['self']
def read(self, num=-1):
self.check_valid()
-
- if num < 0:
- # read all
- eol = self.size
- else:
- eol = self.pos + num
- # silently adjust out of range requests
- if eol > self.size:
- eol = self.size
-
- res = [self.data[i] for i in range(self.pos, eol)]
- res = "".join(res)
- self.pos += len(res)
- return self.space.wrap(res)
+ return self.space.wrap(self.mmap.read(num))
read.unwrap_spec = ['self', int]
def find(self, tofind, start=0):
- self.check_valid()
-
- # XXX naive! how can we reuse the rstr algorithm?
- if start < 0:
- start += self.size
- if start < 0:
- start = 0
- data = self.data
- for p in xrange(start, self.size - len(tofind) + 1):
- for q in range(len(tofind)):
- if data[p+q] != tofind[q]:
- break # position 'p' is not a match
- else:
- # full match
- return self.space.wrap(p)
- # failure
- return self.space.wrap(-1)
+ return self.space.wrap(self.mmap.find(tofind, start))
find.unwrap_spec = ['self', str, int]
def seek(self, pos, whence=0):
- self.check_valid()
-
- dist = pos
- how = whence
-
- if how == 0: # relative to start
- where = dist
- elif how == 1: # relative to current position
- where = self.pos + dist
- elif how == 2: # relative to the end
- where = self.size + dist
- else:
- raise OperationError(self.space.w_ValueError,
- self.space.wrap("unknown seek type"))
-
- if not (0 <= where <= self.size):
+ try:
+ self.mmap.seek(pos, whence)
+ except RValueError, v:
raise OperationError(self.space.w_ValueError,
- self.space.wrap("seek out of range"))
-
- self.pos = where
+ self.space.wrap(v.message))
seek.unwrap_spec = ['self', 'index', int]
def tell(self):
- self.check_valid()
-
- return self.space.wrap(self.pos)
+ return self.space.wrap(self.mmap.tell())
tell.unwrap_spec = ['self']
def descr_size(self):
- self.check_valid()
-
- size = self.size
- if _MS_WINDOWS:
- if self.file_handle.value != INVALID_rffi.INT_VALUE:
- low, high = _get_file_size(self.space, self.file_handle)
- if not high and low <= sys.maxint:
- return self.space.wrap(low)
- size = rffi.INT((high << 32) + low).value
- elif _POSIX:
- st = os.fstat(self.fd)
- size = st[stat.ST_SIZE]
- if size > sys.maxint:
- size = sys.maxint
- else:
- size = int(size)
- return self.space.wrap(size)
+ return self.space.wrap(self.mmap.file_size())
descr_size.unwrap_spec = ['self']
def write(self, data):
- self.check_valid()
self.check_writeable()
-
- data_len = len(data)
- if self.pos + data_len > self.size:
+ try:
+ self.mmap.write(data)
+ except RValueError, v:
raise OperationError(self.space.w_ValueError,
- self.space.wrap("data out of range"))
-
- internaldata = self.data
- start = self.pos
- for i in range(data_len):
- internaldata[start+i] = data[i]
- self.pos = start + data_len
+ self.space.wrap(v.message))
write.unwrap_spec = ['self', str]
def write_byte(self, byte):
- self.check_valid()
-
- if len(byte) != 1:
+ try:
+ self.mmap.write_byte(byte)
+ except RValueError, v:
+ raise OperationError(self.space.w_ValueError,
+ self.space.wrap(v.message))
+ except RTypeError, v:
raise OperationError(self.space.w_TypeError,
- self.space.wrap("write_byte() argument must be char"))
-
- self.check_writeable()
- self.data[self.pos] = byte[0]
- self.pos += 1
+ self.space.wrap(v.message))
write_byte.unwrap_spec = ['self', str]
- def getptr(self, offset):
- return rffi.ptradd(self.data, offset)
-
def flush(self, offset=0, size=0):
- self.check_valid()
-
- if size == 0:
- size = self.size
- if offset < 0 or size < 0 or offset + size > self.size:
+ try:
+ return self.space.wrap(self.mmap.flush(offset, size))
+ except RValueError, v:
raise OperationError(self.space.w_ValueError,
- self.space.wrap("flush values out of range"))
- else:
- start = self.getptr(offset)
- if _MS_WINDOWS:
- res = FlushViewOfFile(start, size)
- # XXX res == 0 means that an error occurred, but in CPython
- # this is not checked
- return self.space.wrap(res)
- elif _POSIX:
-## XXX why is this code here? There is no equivalent in CPython
-## if _LINUX:
-## # alignment of the address
-## value = cast(self.data, c_void_p).value
-## aligned_value = value & ~(PAGESIZE - 1)
-## # the size should be increased too. otherwise the final
-## # part is not "msynced"
-## new_size = size + value & (PAGESIZE - 1)
- res = c_msync(start, size, MS_SYNC)
- if res == -1:
- raise OperationError(self.space.w_EnvironmentError,
- self.space.wrap(_get_error_msg()))
-
- return self.space.wrap(0)
+ self.space.wrap(v.message))
flush.unwrap_spec = ['self', int, int]
def move(self, dest, src, count):
- self.check_valid()
-
- self.check_writeable()
-
- # check boundings
- if (src < 0 or dest < 0 or count < 0 or
- src + count > self.size or dest + count > self.size):
+ try:
+ self.mmap.move(dest, src, count)
+ except RValueError, v:
raise OperationError(self.space.w_ValueError,
- self.space.wrap("source or destination out of range"))
-
- datasrc = self.getptr(src)
- datadest = self.getptr(dest)
- c_memmove(datadest, datasrc, count)
+ self.space.wrap(v.message))
move.unwrap_spec = ['self', int, int, int]
def resize(self, newsize):
self.check_valid()
-
self.check_resizeable()
-
- if _POSIX:
- if not has_mremap:
- msg = "mmap: resizing not available -- no mremap()"
- raise OperationError(self.space.w_EnvironmentError,
- self.space.wrap(msg))
-
- # resize the underlying file first
- try:
- os.ftruncate(self.fd, newsize)
- except OSError, e:
- raise OperationError(self.space.w_EnvironmentError,
- self.space.wrap(os.strerror(e.errno)))
-
- # now resize the mmap
- newdata = c_mremap(self.getptr(0), self.size, newsize,
- MREMAP_MAYMOVE or 0)
- self.setdata(newdata, newsize)
- elif _MS_WINDOWS:
- # disconnect the mapping
- self.unmapview()
- CloseHandle(self.map_handle)
-
- # move to the desired EOF position
- if _64BIT:
- newsize_high = DWORD(newsize >> 32)
- newsize_low = DWORD(newsize & 0xFFFFFFFF)
- else:
- newsize_high = rffi.INT(0)
- newsize_low = rffi.INT(newsize)
-
- FILE_BEGIN = rffi.INT(0)
- SetFilePointer(self.file_handle, newsize_low, byref(newsize_high),
- FILE_BEGIN)
- # resize the file
- SetEndOfFile(self.file_handle)
- # create another mapping object and remap the file view
- res = CreateFileMapping(self.file_handle, NULL, PAGE_READWRITE,
- newsize_high, newsize_low, self.tagname)
- self.map_handle = rffi.INT(res)
-
- dwErrCode = DWORD(0)
- if self.map_handle:
- data = MapViewOfFile(self.map_handle, FILE_MAP_WRITE,
- 0, 0, 0)
- if data:
- self.setdata(data, newsize)
- return
- else:
- dwErrCode = GetLastError()
- else:
- dwErrCode = GetLastError()
-
- raise OperationError(self.space.w_EnvironmentError,
- self.space.wrap(os.strerror(dwErrCode)))
+ self.mmap.resize(newsize)
resize.unwrap_spec = ['self', int]
def __len__(self):
- self.check_valid()
-
- return self.space.wrap(self.size)
+ return self.space.wrap(self.mmap.size)
__len__.unwrap_spec = ['self']
-
+
+ def check_valid(self):
+ try:
+ self.mmap.check_valid()
+ except RValueError, v:
+ raise OperationError(self.space.w_ValueError,
+ self.space.wrap(v.message))
+
+ def check_writeable(self):
+ try:
+ self.mmap.check_writeable()
+ except RValueError, v:
+ raise OperationError(self.space.w_ValueError,
+ self.space.wrap(v.message))
+ except RTypeError, v:
+ raise OperationError(self.space.w_TypeError,
+ self.space.wrap(v.message))
+
+ def check_resizeable(self):
+ try:
+ self.mmap.check_resizeable()
+ except RValueError, v:
+ raise OperationError(self.space.w_ValueError,
+ self.space.wrap(v.message))
+ except RTypeError, v:
+ raise OperationError(self.space.w_TypeError,
+ self.space.wrap(v.message))
+
def descr_getitem(self, w_index):
self.check_valid()
space = self.space
- start, stop, step = space.decode_index(w_index, self.size)
+ start, stop, step = space.decode_index(w_index, self.mmap.size)
if step == 0: # index only
- return space.wrap(self.data[start])
+ return space.wrap(self.mmap.getitem(start))
elif step == 1:
if 0 <= start <= stop:
- res = "".join([self.data[i] for i in range(start, stop)])
+ res = "".join([self.mmap.getitem(i) for i in range(start, stop)])
else:
res = ''
return space.wrap(res)
@@ -541,13 +154,13 @@
self.check_writeable()
space = self.space
- start, stop, step = space.decode_index(w_index, self.size)
+ start, stop, step = space.decode_index(w_index, self.mmap.size)
if step == 0: # index only
if len(value) != 1:
raise OperationError(space.w_ValueError,
space.wrap("mmap assignment must be "
"single-character string"))
- self.data[start] = value[0]
+ self.mmap.setitem(start, value)
elif step == 1:
length = stop - start
if start < 0 or length < 0:
@@ -556,13 +169,12 @@
raise OperationError(space.w_ValueError,
space.wrap("mmap slice assignment is wrong size"))
for i in range(length):
- self.data[start + i] = value[i]
+ self.mmap.setitem(start + i, value[i])
else:
raise OperationError(space.w_ValueError,
space.wrap("mmap object does not support slicing with a step"))
descr_setitem.unwrap_spec = ['self', W_Root, str]
-
W_MMap.typedef = TypeDef("mmap",
close = interp2app(W_MMap.close),
read_byte = interp2app(W_MMap.read_byte),
@@ -592,170 +204,24 @@
raise OperationError(space.w_OverflowError,
space.wrap("memory mapped size is too large (limited by C int)"))
-if _POSIX:
- def mmap(space, fileno, length, flags=MAP_SHARED,
- prot=PROT_WRITE | PROT_READ, access=_ACCESS_DEFAULT):
-
- fd = fileno
-
- # check size boundaries
- _check_map_size(space, length)
- map_size = length
-
- # check access is not there when flags and prot are there
- if access != _ACCESS_DEFAULT and ((flags != MAP_SHARED) or\
- (prot != (PROT_WRITE | PROT_READ))):
- raise OperationError(space.w_ValueError,
- space.wrap("mmap can't specify both access and flags, prot."))
-
- if access == ACCESS_READ:
- flags = MAP_SHARED
- prot = PROT_READ
- elif access == ACCESS_WRITE:
- flags = MAP_SHARED
- prot = PROT_READ | PROT_WRITE
- elif access == ACCESS_COPY:
- flags = MAP_PRIVATE
- prot = PROT_READ | PROT_WRITE
- elif access == _ACCESS_DEFAULT:
- pass
- else:
- raise OperationError(space.w_ValueError,
- space.wrap("mmap invalid access parameter."))
+if rmmap._POSIX:
+ def mmap(space, fileno, length, flags=rmmap.MAP_SHARED,
+ prot=rmmap.PROT_WRITE | rmmap.PROT_READ, access=rmmap._ACCESS_DEFAULT):
- # check file size
try:
- st = os.fstat(fd)
- except OSError:
- pass # ignore errors and trust map_size
- else:
- mode = st[stat.ST_MODE]
- size = st[stat.ST_SIZE]
- if size > sys.maxint:
- size = sys.maxint
- else:
- size = int(size)
- if stat.S_ISREG(mode):
- if map_size == 0:
- map_size = size
- elif map_size > size:
- raise OperationError(space.w_ValueError,
- space.wrap("mmap length is greater than file size"))
-
- m = W_MMap(space, access)
- if fd == -1:
- # Assume the caller wants to map anonymous memory.
- # This is the same behaviour as Windows. mmap.mmap(-1, size)
- # on both Windows and Unix map anonymous memory.
- m.fd = -1
-
- flags |= MAP_ANONYMOUS
-
- else:
- try:
- m.fd = os.dup(fd)
- except OSError, e:
- raise OperationError(space.w_EnvironmentError,
- space.wrap(os.strerror(e.errno)))
-
- res = c_mmap(NULL, map_size, prot, flags, fd, 0)
- if res == rffi.cast(PTR, -1):
- raise OperationError(space.w_EnvironmentError,
- space.wrap(_get_error_msg()))
-
- m.setdata(res, map_size)
-
- return space.wrap(m)
+ return space.wrap(W_MMap(space, rmmap.mmap(fileno, length,
+ flags, prot, access)))
+ except REnvironmentError, e:
+ raise OperationError(space.w_EnvironmentError, space.wrap(e.message))
+ except RValueError, e:
+ raise OperationError(space.w_ValueError, space.wrap(e.message))
+ except RTypeError, e:
+ raise OperationError(space.w_TypeError, space.wrap(e.message))
mmap.unwrap_spec = [ObjSpace, int, 'index', int, int, int]
-elif _MS_WINDOWS:
+elif rmmap._MS_WINDOWS:
def mmap(space, fileno, length, tagname="", access=_ACCESS_DEFAULT):
- # check size boundaries
- _check_map_size(space, length)
- map_size = length
-
- flProtect = 0
- dwDesiredAccess = 0
- fh = 0
-
- if access == ACCESS_READ:
- flProtect = PAGE_READONLY
- dwDesiredAccess = FILE_MAP_READ
- elif access == _ACCESS_DEFAULT or access == ACCESS_WRITE:
- flProtect = PAGE_READWRITE
- dwDesiredAccess = FILE_MAP_WRITE
- elif access == ACCESS_COPY:
- flProtect = PAGE_WRITECOPY
- dwDesiredAccess = FILE_MAP_COPY
- else:
- raise OperationError(space.w_ValueError,
- space.wrap("mmap invalid access parameter."))
-
- # assume -1 and 0 both mean invalid file descriptor
- # to 'anonymously' map memory.
- if fileno != -1 and fileno != 0:
- fh = msvcr71._get_osfhandle(fileno)
- if fh == -1:
- raise OperationError(space.w_EnvironmentError,
- space.wrap(_get_error_msg()))
- # Win9x appears to need us seeked to zero
- # SEEK_SET = 0
- # libc._lseek(fileno, 0, SEEK_SET)
-
- m = W_MMap(space, access)
- # XXX the following two attributes should be plain RPython ints
- m.file_handle = rffi.INT(INVALID_rffi.INT_VALUE)
- m.map_handle = rffi.INT(INVALID_rffi.INT_VALUE)
-
- if fh:
- # it is necessary to duplicate the handle, so the
- # Python code can close it on us
- res = DuplicateHandle(GetCurrentProcess(), # source process handle
- fh, # handle to be duplicated
- GetCurrentProcess(), # target process handle
- byref(m.file_handle), # result
- 0, # access - ignored due to options value
- False, # inherited by child procs?
- DUPLICATE_SAME_ACCESS) # options
- if not res:
- raise OperationError(space.w_EnvironmentError,
- space.wrap(_get_error_msg()))
-
- if not map_size:
- low, high = _get_file_size(space, rffi.INT(fh))
- if _64BIT:
- map_size = rffi.INT((low << 32) + 1).value
- else:
- if high:
- # file is too large to map completely
- map_size = -1
- else:
- map_size = low
-
- if tagname:
- m.tagname = tagname
-
- # DWORD is a 4-byte int. If int > 4-byte it must be divided
- if _64BIT:
- size_hi = DWORD(map_size >> 32)
- size_lo = DWORD(map_size & 0xFFFFFFFF)
- else:
- size_hi = rffi.INT(0)
- size_lo = rffi.INT(map_size)
-
- m.map_handle = rffi.INT(CreateFileMapping(m.file_handle, NULL, flProtect,
- size_hi, size_lo, m.tagname))
-
- if m.map_handle:
- res = MapViewOfFile(m.map_handle, dwDesiredAccess,
- 0, 0, 0)
- if res:
- m.setdata(res, map_size)
- return space.wrap(m)
- else:
- dwErr = GetLastError()
- else:
- dwErr = GetLastError()
-
- raise OperationError(space.w_EnvironmentError,
- space.wrap(os.strerror(dwErr)))
+ XXX
mmap.unwrap_spec = [ObjSpace, int, 'index', str, int]
+
+constants = rmmap.constants
+PAGESIZE = rmmap.PAGESIZE
Modified: pypy/dist/pypy/module/mmap/test/test_mmap.py
==============================================================================
--- pypy/dist/pypy/module/mmap/test/test_mmap.py (original)
+++ pypy/dist/pypy/module/mmap/test/test_mmap.py Tue Oct 9 17:10:20 2007
@@ -611,3 +611,4 @@
assert m.read(10) == "ABCDEABCDE"
m.close()
f.close()
+
More information about the Pypy-commit
mailing list