Skip to content

Commit

Permalink
Changes to mirror changes in the pmem_map() on newer version of nvml.
Browse files Browse the repository at this point in the history
  • Loading branch information
perone committed Mar 17, 2016
1 parent 66c469c commit 43785d2
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 36 deletions.
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ after_success:
before_install:
- sudo apt-get -qq update
- sudo apt-get install -y uuid-dev
- wget https://github.com/pmem/nvml/archive/0.4.tar.gz
- tar -xzvf 0.4.tar.gz
- cd nvml-0.4 && make && sudo make install
- wget https://github.com/pmem/nvml/archive/master.tar.gz
- tar -xzvf master.tar.gz
- cd nvml-master && make && sudo make install
- sudo ldconfig

install:
Expand Down
6 changes: 4 additions & 2 deletions nvm/libex.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@

ffi.cdef("""
/* libpmem */
void *pmem_map(int fd);
typedef int mode_t;
void *pmem_map_file(const char *path, size_t len, int flags, mode_t mode,
size_t *mapped_lenp, int *is_pmemp);
int pmem_unmap(void *addr, size_t len);
int pmem_has_hw_drain(void);
int pmem_is_pmem(void *addr, size_t len);
Expand All @@ -25,7 +28,6 @@
/* libpmemlog */
typedef struct pmemlog PMEMlogpool;
typedef int mode_t;
typedef int off_t;
PMEMlogpool *pmemlog_open(const char *path);
Expand Down
59 changes: 48 additions & 11 deletions nvm/pmem.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,27 @@
import os
from _pmem import lib, ffi

#: Create the named file if it does not exist.
FILE_CREATE = 1

#: Ensure that this call creates the file.
FILE_EXCL = 2

#: When creating a file, create a sparse (holey) file instead of calling
#: posix_fallocate(2)
FILE_SPARSE = 4

#: Create a mapping for an unnamed temporary file.
FILE_TMPFILE = 8


class MemoryBuffer(object):
"""A file-like I/O (similar to cStringIO) for persistent mmap'd regions."""

def __init__(self, buffer_):
def __init__(self, buffer_, is_pmem, mapped_len):
self.buffer = buffer_
self.is_pmem = is_pmem
self.mapped_len = mapped_len
self.size = len(buffer_)
self.pos = 0

Expand Down Expand Up @@ -152,23 +167,45 @@ def has_hw_drain():
return bool(ret)


def map(file_, size):
"""Map the entire file for read/write access
:param file: The file descriptor of a file object.
def map_file(file_name, file_size, flags, mode):
"""Given a path, this function creates a new read/write
mapping for the named file. It will map the file using mmap,
but it also takes extra steps to make large page mappings more
likely.
If creation flags are not supplied, then this function creates a mapping
for an existing file. In such case, `file_size` should be zero. The entire
file is mapped to memory; its length is used as the length of the
mapping.
.. seealso:: `NVML libpmem documentation <http://pmem.io/nvml/libpmem/libpm
em.3.html>`_.
:param file_name: The file name to use.
:param file_size: the size to allocate
:param flags: The flags argument can be 0 or bitwise OR of one or more of
the following file creation flags:
:const:`~nvm.pmem.FILE_CREATE`,
:const:`~nvm.pmem.FILE_EXCL`,
:const:`~nvm.pmem.FILE_TMPFILE`,
:const:`~nvm.pmem.FILE_SPARSE`.
:return: The mapping, an exception will rise in case
of error.
"""
if hasattr(file_, 'fileno'):
ret = lib.pmem_map(file_.fileno())
else:
ret = lib.pmem_map(file_)
ret_mappend_len = ffi.new("size_t *")
ret_is_pmem = ffi.new("int *")

ret = lib.pmem_map_file(file_name, file_size, flags, mode,
ret_mappend_len, ret_is_pmem)

if ret == ffi.NULL:
raise RuntimeError(os.strerror(ffi.errno))

cast = ffi.buffer(ret, size)
return MemoryBuffer(cast)
ret_mapped_len = ret_mappend_len[0]
ret_is_pmem = bool(ret_is_pmem[0])

cast = ffi.buffer(ret, file_size)
return MemoryBuffer(cast, ret_is_pmem, ret_mapped_len)


def unmap(memory_buffer):
Expand Down
3 changes: 1 addition & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from setuptools import setup
import nvm

install_requirements = ['fallocate>=1.4.0',
'nose>=1.3.7',
install_requirements = ['nose>=1.3.7',
'cffi>=1.0.0']

setup_requirements = ['cffi>=1.0.0',
Expand Down
24 changes: 6 additions & 18 deletions tests/test_pmem.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@
import uuid

from nvm import pmem
from fallocate import posix_fallocate


class MapMixin(object):

def create_mapping(self, size=4096):
filename = "{}.pmem".format(uuid.uuid4())
fhandle = open(filename, "w+")
posix_fallocate(fhandle, 0, size)
mapping = pmem.map(fhandle, size)
fhandle.close()
mapping = pmem.map_file(filename, size,
pmem.FILE_CREATE | pmem.FILE_EXCL,
0666)
return filename, mapping

def clear_mapping(self, filename, mapping):
Expand All @@ -36,14 +34,6 @@ def test_has_hw_drain(self):


class TestMap(unittest.TestCase, MapMixin):
def test_map_zero(self):
filename = "{}.pmem".format(uuid.uuid4())
fhandle = open(filename, "w+")
with self.assertRaises(RuntimeError):
mapping = pmem.map(fhandle, 4096)
fhandle.close()
os.unlink(filename)

def test_map_ok(self):
filename, mapping = self.create_mapping()
self.assertIsInstance(mapping, pmem.MemoryBuffer)
Expand Down Expand Up @@ -111,13 +101,11 @@ def test_hw_drain(self):
class TestMapContext(unittest.TestCase):
def test_map_context(self):
filename = "{}.pmem".format(uuid.uuid4())
fhandle = open(filename, "w+")
posix_fallocate(fhandle, 0, 4096)

with pmem.map(fhandle, 4096) as reg:
with pmem.map_file(filename, 4096,
pmem.FILE_CREATE | pmem.FILE_EXCL,
0666) as reg:
reg.write("test")

fhandle.close()
os.unlink(filename)

if __name__ == '__main__':
Expand Down

0 comments on commit 43785d2

Please sign in to comment.