Skip to content

Commit 064aa81

Browse files
committed
Implemented __len__ method in buffer, including small test. This has its caveats, but should be fine for responsible clients
1 parent 4466476 commit 064aa81

2 files changed

Lines changed: 28 additions & 3 deletions

File tree

smmap/buf.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ class MappedMemoryBuffer(object):
1111
1212
The buffer is relative, that is if you map an offset, index 0 will map to the
1313
first byte at the offset you used during initialization or begin_access"""
14-
__slots__ = '_c' # our cursor
14+
__slots__ = (
15+
'_c', # our cursor
16+
'_size', # our supposed size
17+
)
1518

1619

1720
def __init__(self, cursor = None, offset = 0, size = sys.maxint, flags = 0):
@@ -20,6 +23,10 @@ def __init__(self, cursor = None, offset = 0, size = sys.maxint, flags = 0):
2023
If None, you have call begin_access before using the buffer and provide a cursor
2124
:param offset: absolute offset in bytes
2225
:param size: the total size of the mapping. Defaults to the maximum possible size
26+
From that point on, the __len__ of the buffer will be the given size or the file size.
27+
If the size is larger than the mappable area, you can only access the actually available
28+
area, although the length of the buffer is reported to be your given size.
29+
Hence it is in your own interest to provide a proper size !
2330
:param flags: Additional flags to be passed to os.open
2431
:raise ValueError: if the buffer could not achieve a valid state"""
2532
self._c = cursor
@@ -30,6 +37,9 @@ def __init__(self, cursor = None, offset = 0, size = sys.maxint, flags = 0):
3037
def __del__(self):
3138
self.end_access()
3239

40+
def __len__(self):
41+
return self._size
42+
3343
def __getitem__(self, i):
3444
c = self._c
3545
assert c.is_valid()
@@ -76,7 +86,18 @@ def begin_access(self, cursor = None, offset = 0, size = sys.maxint, flags = 0):
7686

7787
# reuse existing cursors if possible
7888
if self._c is not None and self._c.is_associated():
79-
return self._c.use_region(offset, size, flags).is_valid()
89+
res = self._c.use_region(offset, size, flags).is_valid()
90+
if res:
91+
# if given size is too large or default, we computer a proper size
92+
# If its smaller, we assume the combination between offset and size
93+
# as chosen by the user is correct and use it !
94+
# If not, the user is in trouble.
95+
if size > self._c.file_size():
96+
size = self._c.file_size() - offset
97+
#END handle size
98+
self._size = size
99+
#END set size
100+
return res
80101
return False
81102

82103
def end_access(self):
@@ -85,6 +106,7 @@ def end_access(self):
85106
resources to be freed.
86107
87108
Once you called end_access, you must call begin access before reusing this instance!"""
109+
self._size = 0
88110
if self._c is not None:
89111
self._c.unuse_region()
90112
#END unuse region

smmap/test/test_buf.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,18 @@ def test_basics(self):
3030
# can call end access any time
3131
buf.end_access()
3232
buf.end_access()
33+
assert len(buf) == 0
3334

3435
# begin access can revive it, if the offset is suitable
3536
offset = 100
3637
assert buf.begin_access(c, fc.size) == False
3738
assert buf.begin_access(c, offset) == True
39+
assert len(buf) == fc.size - offset
3840
assert buf.cursor().is_valid()
3941

4042
# empty begin access keeps it valid on the same path, but alters the offset
4143
assert buf.begin_access() == True
44+
assert len(buf) == fc.size
4245
assert buf.cursor().is_valid()
4346

4447
# simple access
@@ -63,7 +66,7 @@ def test_basics(self):
6366
# exagerate the manager's overhead, but measure the buffer overhead
6467
# We do it once with an optimal setting, and with a worse manager which
6568
# will produce small mappings only !
66-
max_num_accesses = 400
69+
max_num_accesses = 100
6770
fd = os.open(fc.path, os.O_RDONLY)
6871
for item in (fc.path, fd):
6972
for manager, man_id in ( (man_optimal, 'optimal'),

0 commit comments

Comments
 (0)