@@ -78,10 +78,12 @@ def assign(self, rhs):
7878 self ._destroy ()
7979 self ._copy_from (rhs )
8080
81- def use_region (self , offset , size , _is_recursive = False ):
81+ def use_region (self , offset , size , flags = 0 , _is_recursive = False ):
8282 """Assure we point to a window which allows access to the given offset into the file
8383 :param offset: absolute offset in bytes into the file
8484 :param size: amount of bytes to map
85+ :param flags: additional flags to be given to os.open in case a file handle is initially opened
86+ for mapping. Has no effect if a region can actually be reused.
8587 :return: this instance - it should be queried for whether it points to a valid memory region.
8688 This is not the case if the mapping failed becaues we reached the end of the file
8789 :note: The size actually mapped may be smaller than the given size. If that is the case,
@@ -106,6 +108,8 @@ def use_region(self, offset, size, _is_recursive=False):
106108 return self
107109 # END handle offset too large
108110
111+ # bisect to find an existing region. The c++ implementation cannot
112+ # do that as it uses a linked list for regions.
109113 existing_region = None
110114 a = self ._rlist
111115 lo = 0
@@ -181,7 +185,7 @@ def use_region(self, offset, size, _is_recursive=False):
181185 if man ._handle_count >= man ._max_handle_count :
182186 raise Exception
183187 #END assert own imposed max file handles
184- self ._region = MappedRegion (a .path (), mid .ofs , mid .size )
188+ self ._region = MappedRegion (a .path (), mid .ofs , mid .size , flags )
185189 except Exception :
186190 # apparently we are out of system resources or hit a limit
187191 # As many more operations are likely to fail in that condition (
@@ -195,7 +199,7 @@ def use_region(self, offset, size, _is_recursive=False):
195199 raise
196200 #END handle existing recursion
197201 man ._collect_lru_region (0 )
198- return self .use_region (offset , size , True )
202+ return self .use_region (offset , size , flags , True )
199203 #END handle exceptions
200204
201205 man ._handle_count += 1
@@ -218,11 +222,15 @@ def unuse_region(self):
218222 to unuse the region once you are done reading from it in persistent cursors as it
219223 helps to free up resource more quickly"""
220224 self ._region = None
225+ # note: should reset ofs and size, but we spare that for performance. Its not
226+ # allowed to query information if we are not valid !
221227
222228 def buffer (self ):
223229 """Return a buffer object which allows access to our memory region from our offset
224230 to the window size. Please note that it might be smaller than you requested
225- :note: You can only obtain a buffer if this instance is_valid() !"""
231+ :note: You can only obtain a buffer if this instance is_valid() !
232+ :note: buffers should not be cached passed the duration of your access as it will
233+ prevent resources from being freed even though they might not be accounted for anymore !"""
226234 return buffer (self ._region .buffer (), self ._ofs , self ._size )
227235
228236 def is_valid (self ):
@@ -234,7 +242,8 @@ def is_associated(self):
234242 return self ._rlist is not None
235243
236244 def ofs_begin (self ):
237- """:return: offset to the first byte pointed to by our cursor"""
245+ """:return: offset to the first byte pointed to by our cursor
246+ :note: only if is_valid() is True"""
238247 return self ._region ._b + self ._ofs
239248
240249 def ofs_end (self ):
@@ -332,6 +341,7 @@ def _collect_lru_region(self, size):
332341 :param size: size of the region we want to map next (assuming its not already mapped partially or full
333342 if 0, we try to free any available region
334343 :raise RegionCollectionError:
344+ :return: Amount of freed regions
335345 :todo: implement a case where all unusued regions are discarded efficiently. Currently its only brute force"""
336346 num_found = 0
337347 while (size == 0 ) or (self ._memory_size + size > self ._max_memory_size ):
@@ -361,6 +371,8 @@ def _collect_lru_region(self, size):
361371 self ._handle_count -= 1
362372 #END while there is more memory to free
363373
374+ return num_found
375+
364376 #{ Interface
365377 def make_cursor (self , path ):
366378 """:return: a cursor pointing to the given path. It can be used to map new regions of the file into memory"""
@@ -371,6 +383,11 @@ def make_cursor(self, path):
371383 # END obtain region for path
372384 return MemoryCursor (self , regions )
373385
386+ def collect (self ):
387+ """Collect all available free-to-collect mapped regions
388+ :return: Amount of freed handles"""
389+ return self ._collect_lru_region (0 )
390+
374391 def num_file_handles (self ):
375392 """:return: amount of file handles in use. Each mapped region uses one file handle"""
376393 return self ._handle_count
0 commit comments