-
Notifications
You must be signed in to change notification settings - Fork 0
/
filecache_controller.py
91 lines (74 loc) · 3.51 KB
/
filecache_controller.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
"""A simple cache controller. Caching only one file at a time."""
from __future__ import absolute_import, division, print_function
import os
import threading
from builtins import object
import dxtbx.filecache
class simple_controller(object):
"""A simple cache controller. Caching one file at a time."""
def __init__(self):
# Reference to the identifier of the last seen object
# and the relevant cache object
self._cache_tag = None
self._cache = None
# Lock for concurrent access
self._lock = threading.Lock()
# Keep the current PID to detect the use of multiprocessing parallelization
# which breaks caching assumptions
self._pid = os.getpid()
def __del__(self):
"""Garbage collection.
Since only a cache controller can run .open() on lazy cache objects,
the lazy cache object can be told to close as soon as possible.
File handles can still be open legitimately."""
try:
if self._cache is not None and self._pid == os.getpid():
self._cache.close()
except (AttributeError, TypeError):
pass
self._cache = None
def check(self, tag, open_method):
"""The main cache controller access method. Checks if an object with name
"tag" is cached. If so, returns a (pseudo-, ie. cached) file handle to
this object.
Otherwise, create a cache first, using the passed open_method()
function, which returns a (true) file handle."""
with self._lock:
currentpid = os.getpid()
if currentpid != self._pid:
# print "(%5s) Controller %s detected PID change, flushing %s" % (os.getpid(), format(id(self), '#x'), self._cache_tag)
# Change the PID and drop reference to the previous cache.
self._cache = None
self._cache_tag = None
self._pid = currentpid
# NB: Explicitly do not close the cache in this case. Would be pointless.
# If tag has changed then we are changing cache contents
if tag != self._cache_tag:
if self._cache is not None:
# print "(%5s) Controller %s closing previous cache on %s" % (os.getpid(), format(id(self), '#x'), self._cache_tag)
try:
self._cache.close()
finally:
self._cache = None
self._cache_tag = None
# print "(%5s) Controller %s opening cache on %s" % (os.getpid(), format(id(self), '#x'), self._tag)
try:
self._cache_tag = tag
self._cache = dxtbx.filecache.lazy_file_cache(open_method())
except: # noqa: E722
# Make sure we leave in a valid state
self._cache_tag = None
self._cache = None
raise
# else:
# print "(%5s) Controller %s reporting cache hit on %s" % (os.getpid(), format(id(self), '#x'), self._cache_tag)
return self._cache.open()
class non_caching_controller(object):
"""A controller that does not do any caching."""
@staticmethod
def check(tag, open_method):
"""Open the file. No caching required."""
print("Caching disabled for", tag)
return open_method()
# To disable all caching uncomment the following line:
# simple_controller = non_caching_controller