forked from Tribler/dispersy
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrequestcache.py
120 lines (93 loc) · 4.82 KB
/
requestcache.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
from random import random
from .revision import update_revision_information
if __debug__:
def identifier_to_string(identifier):
return identifier.encode("HEX") if isinstance(identifier, str) else identifier
from .dprint import dprint
# update version information directly from SVN
update_revision_information("$HeadURL$", "$Revision$")
class Cache(object):
timeout_delay = 10.0
cleanup_delay = 10.0
def on_timeout(self):
raise NotImplementedError()
def on_cleanup(self):
pass
def __str__(self):
return "<%s>" % self.__class__.__name__
class RequestCache(object):
def __init__(self, callback):
self._callback = callback
self._identifiers = dict()
def generate_identifier(self):
while True:
identifier = int(random() * 2**16)
if not identifier in self._identifiers:
if __debug__: dprint("claiming on ", identifier_to_string(identifier))
return identifier
def claim(self, cache):
identifier = self.generate_identifier()
if __debug__: dprint("claiming on ", identifier_to_string(identifier), " for ", cache)
self.set(identifier, cache)
return identifier
def set(self, identifier, cache):
assert isinstance(identifier, (int, long, str)), type(identifier)
assert not identifier in self._identifiers, identifier
assert isinstance(cache, Cache)
assert isinstance(cache.timeout_delay, float)
assert cache.timeout_delay > 0.0
if __debug__: dprint("set ", identifier_to_string(identifier), " for ", cache, " (", cache.timeout_delay, "s timeout)")
self._callback.register(self._on_timeout, (identifier,), id_="requestcache-%s" % identifier, delay=cache.timeout_delay)
self._identifiers[identifier] = cache
cache.identifier = identifier
def replace(self, identifier, cache):
assert isinstance(identifier, (int, long, str)), type(identifier)
assert identifier in self._identifiers, identifier
assert isinstance(cache, Cache)
assert isinstance(cache.timeout_delay, float)
assert cache.timeout_delay > 0.0
if __debug__: dprint("replace ", identifier_to_string(identifier), " for ", cache, " (", cache.timeout_delay, "s timeout)")
self._callback.replace_register("requestcache-%s" % identifier, self._on_timeout, (identifier,), delay=cache.cleanup_delay)
self._identifiers[identifier] = cache
cache.identifier = identifier
def has(self, identifier, cls):
assert isinstance(identifier, (int, long, str)), type(identifier)
assert issubclass(cls, Cache), cls
if __debug__: dprint("cache contains ", identifier_to_string(identifier), "? ", identifier in self._identifiers)
return isinstance(self._identifiers.get(identifier), cls)
def get(self, identifier, cls):
assert isinstance(identifier, (int, long, str)), type(identifier)
assert issubclass(cls, Cache), cls
cache = self._identifiers.get(identifier)
if cache and isinstance(cache, cls):
return cache
def pop(self, identifier, cls):
assert isinstance(identifier, (int, long, str)), type(identifier)
assert issubclass(cls, Cache), cls
cache = self._identifiers.get(identifier)
if cache and isinstance(cache, cls):
assert isinstance(cache.cleanup_delay, float)
assert cache.cleanup_delay >= 0.0
if __debug__: dprint("canceling timeout on ", identifier_to_string(identifier), " for ", cache)
if cache.cleanup_delay:
self._callback.replace_register("requestcache-%s" % identifier, self._on_cleanup, (identifier,), delay=cache.cleanup_delay)
elif identifier in self._identifiers:
self._callback.unregister("requestcache-%s" % identifier)
del self._identifiers[identifier]
return cache
def _on_timeout(self, identifier):
assert identifier in self._identifiers, identifier
cache = self._identifiers[identifier]
if __debug__: dprint("timeout on ", identifier_to_string(identifier), " for ", cache)
cache.on_timeout()
if cache.cleanup_delay:
self._callback.replace_register("requestcache-%s" % identifier, self._on_cleanup, (identifier,), delay=cache.cleanup_delay)
elif identifier in self._identifiers:
del self._identifiers[identifier]
def _on_cleanup(self, identifier):
assert identifier in self._identifiers
cache = self._identifiers[identifier]
if __debug__: dprint("cleanup on ", identifier_to_string(identifier), " for ", cache)
cache.on_cleanup()
if identifier in self._identifiers:
del self._identifiers[identifier]