import time
import errno
import logging
+import weakref
_logger = logging.getLogger('arvados.keep')
cacheblock_suffix = ".keepcacheblock"
class DiskCacheSlot(object):
- __slots__ = ("locator", "ready", "content", "cachedir", "filehandle")
+ __slots__ = ("locator", "ready", "content", "cachedir", "filehandle", "linger")
def __init__(self, locator, cachedir):
self.locator = locator
self.content = None
self.cachedir = cachedir
self.filehandle = None
+ self.linger = None
def get(self):
self.ready.wait()
try:
if value is None:
self.content = None
+ self.ready.set()
return
if len(value) == 0:
# Can't mmap a 0 length file
self.content = b''
+ self.ready.set()
return
if self.content is not None:
# Has been set already
+ self.ready.set()
return
blockdir = os.path.join(self.cachedir, self.locator[0:3])
tmpfile = None
self.content = mmap.mmap(self.filehandle.fileno(), 0, access=mmap.ACCESS_READ)
+ # only set the event when mmap is successful
+ self.ready.set()
finally:
if tmpfile is not None:
# If the tempfile hasn't been renamed on disk yet, try to delete it.
def size(self):
if self.content is None:
+ if self.linger is not None:
+ # If it is still lingering (object is still accessible
+ # through the weak reference) it is still taking up
+ # space.
+ content = self.linger()
+ if content is not None:
+ return len(content)
return 0
else:
return len(self.content)
pass
finally:
self.filehandle = None
+ self.linger = weakref.ref(self.content)
self.content = None
- return False
+ return False
+
+ def gone(self):
+ # Test if an evicted object is lingering
+ return self.content is None and (self.linger is None or self.linger() is None)
@staticmethod
def get_from_disk(locator, cachedir):