@@ -95,7 +95,8 @@ def use_region(self, offset, size, flags = 0):
9595 either the file has reached its end, or the map was created between two existing regions"""
9696 need_region = True
9797 man = self ._manager
98- size = min (size , man .window_size ()) # clamp size to window size
98+ fsize = self ._rlist .file_size ()
99+ size = min (size , man .window_size () or fsize ) # clamp size to window size
99100
100101 if self ._region is not None :
101102 if self ._region .includes_ofs (offset ):
@@ -106,7 +107,7 @@ def use_region(self, offset, size, flags = 0):
106107 # END check existing region
107108
108109 # offset too large ?
109- if offset >= self . _rlist . file_size () :
110+ if offset >= fsize :
110111 return self
111112 #END handle offset
112113
@@ -238,10 +239,11 @@ class StaticWindowMapManager(object):
238239
239240 _MB_in_bytes = 1024 * 1024
240241
241- def __init__ (self , window_size = sys . maxint , max_memory_size = 0 , max_open_handles = sys .maxint ):
242+ def __init__ (self , window_size = 0 , max_memory_size = 0 , max_open_handles = sys .maxint ):
242243 """initialize the manager with the given parameters.
243- :param window_size: if 0 , a default window size will be chosen depending on
244+ :param window_size: if -1 , a default window size will be chosen depending on
244245 the operating system's architechture. It will internally be quantified to a multiple of the page size
246+ If 0, the window may have any size, which basically results in mapping the whole file at one
245247 :param max_memory_size: maximum amount of memory we may map at once before releasing mapped regions.
246248 If 0, a viable default iwll be set dependning on the system's architecture.
247249 :param max_open_handles: if not maxin, limit the amount of open file handles to the given number.
@@ -254,7 +256,7 @@ def __init__(self, window_size = sys.maxint, max_memory_size = 0, max_open_handl
254256 self ._memory_size = 0
255257 self ._handle_count = 0
256258
257- if window_size == 0 :
259+ if window_size < 0 :
258260 coeff = 32
259261 if is_64_bit ():
260262 coeff = 1024
@@ -281,43 +283,40 @@ def _collect_lru_region(self, size):
281283 :todo: implement a case where all unusued regions are discarded efficiently. Currently its only brute force"""
282284 num_found = 0
283285 while (size == 0 ) or (self ._memory_size + size > self ._max_memory_size ):
284- for k , regions in self ._fdict .iteritems ():
285- found_lonely_region = False
286+ lru_region = None
287+ lru_list = None
288+ for regions in self ._fdict .itervalues ():
286289 for region in regions :
287290 # check client count - consider that we keep one reference ourselves !
288291 if (region .client_count ()- 2 == 0 and
289292 (lru_region is None or region ._uc < lru_region ._uc )):
290- # remove whole list
291- found_lonely_region = True
292- num_found += 1
293- self ._memory_size -= region .size ()
294- self ._handle_count -= 1
295- self ._fdict .pop (k )
296-
297- break
293+ lru_region = region
294+ lru_list = regions
298295 # END update lru_region
299296 #END for each region
300- if found_lonely_region :
301- continue
302- # END skip iteration and restart
303297 #END for each regions list
304298
305- # still here ?
306- if num_found == 0 and size != 0 :
307- raise RegionCollectionError ("Didn't find any region to free" )
308- #END raise if necessary
299+ if lru_region is None :
300+ if num_found == 0 and size != 0 :
301+ raise RegionCollectionError ("Didn't find any region to free" )
302+ #END raise if necessary
303+ break
304+ #END handle region not found
305+
306+ num_found += 1
307+ del (lru_list [lru_list .index (lru_region )])
308+ self ._memory_size -= lru_region .size ()
309+ self ._handle_count -= 1
309310 #END while there is more memory to free
310-
311311 return num_found
312312
313-
314313 def _obtain_region (self , a , offset , size , flags , is_recursive ):
315314 """Utilty to create a new region - for more information on the parameters,
316315 see MapCursor.use_region.
317316 :param a: A regions (a)rray
318317 :return: The newly created region"""
319- if self ._memory_size + window_size > self ._max_memory_size :
320- self ._collect_lru_region (window_size )
318+ if self ._memory_size + size > self ._max_memory_size :
319+ self ._collect_lru_region (size )
321320 #END handle collection
322321
323322 r = None
@@ -347,8 +346,8 @@ def _obtain_region(self, a, offset, size, flags, is_recursive):
347346 self ._memory_size += r .size ()
348347 # END handle array
349348
350- assert a .includes_ofs (offset )
351- assert a .includes_ofs (offset + size - 1 )
349+ assert r .includes_ofs (offset )
350+ assert r .includes_ofs (offset + size - 1 )
352351 return r
353352
354353 #}END internal methods
@@ -362,6 +361,8 @@ def make_cursor(self, path_or_fd):
362361 your existing file descriptor, but keep in mind that new windows can only
363362 be mapped as long as it stays valid. This is why the using actual file paths
364363 are preferred unless you plan to keep the file descriptor open.
364+ :note: file descriptors are problematic as they are not necessarily unique, as two
365+ different files opened and closed in succession might have the same file descriptor id.
365366 :note: Using file descriptors directly is faster once new windows are mapped as it
366367 prevents the file to be opened again just for the purpose of mapping it."""
367368 regions = self ._fdict .get (path_or_fd )
@@ -448,41 +449,10 @@ class SlidingWindowMapManager(StaticWindowMapManager):
448449
449450 __slots__ = tuple ()
450451
451- def __init__ (self , window_size = 0 , max_memory_size = 0 , max_open_handles = sys .maxint ):
452- """Adjusts the default window size to 0 """
452+ def __init__ (self , window_size = - 1 , max_memory_size = 0 , max_open_handles = sys .maxint ):
453+ """Adjusts the default window size to -1 """
453454 super (SlidingWindowMapManager , self ).__init__ (window_size , max_memory_size , max_open_handles )
454455
455- def _collect_lru_region (self , size ):
456- num_found = 0
457- while (size == 0 ) or (self ._memory_size + size > self ._max_memory_size ):
458- lru_region = None
459- lru_list = None
460- for regions in self ._fdict .itervalues ():
461- for region in regions :
462- # check client count - consider that we keep one reference ourselves !
463- if (region .client_count ()- 2 == 0 and
464- (lru_region is None or region ._uc < lru_region ._uc )):
465- lru_region = region
466- lru_list = regions
467- # END update lru_region
468- #END for each region
469- #END for each regions list
470-
471- if lru_region is None :
472- if num_found == 0 and size != 0 :
473- raise RegionCollectionError ("Didn't find any region to free" )
474- #END raise if necessary
475- break
476- #END handle region not found
477-
478- num_found += 1
479- del (lru_list [lru_list .index (lru_region )])
480- self ._memory_size -= lru_region .size ()
481- self ._handle_count -= 1
482- #END while there is more memory to free
483-
484- return num_found
485-
486456 def _obtain_region (self , a , offset , size , flags , is_recursive ):
487457 # bisect to find an existing region. The c++ implementation cannot
488458 # do that as it uses a linked list for regions.
0 commit comments