python3 - 2to3 + miscell obvious tweaks
[sfa.git] / sfa / util / cache.py
1 #
2 # This module implements general purpose caching system
3 #
4
5 import time
6 import threading
7 import pickle
8 from datetime import datetime
9
10 # maximum lifetime of cached data (in seconds)
11 DEFAULT_CACHE_TTL = 60 * 60
12
13
14 class CacheData:
15
16     data = None
17     created = None
18     expires = None
19     lock = None
20
21     def __init__(self, data, ttl=DEFAULT_CACHE_TTL):
22         self.lock = threading.RLock()
23         self.data = data
24         self.renew(ttl)
25
26     def is_expired(self):
27         return time.time() > self.expires
28
29     def get_created_date(self):
30         return str(datetime.fromtimestamp(self.created))
31
32     def get_expires_date(self):
33         return str(datetime.fromtimestamp(self.expires))
34
35     def renew(self, ttl=DEFAULT_CACHE_TTL):
36         self.created = time.time()
37         self.expires = self.created + ttl
38
39     def set_data(self, data, renew=True, ttl=DEFAULT_CACHE_TTL):
40         with self.lock:
41             self.data = data
42             if renew:
43                 self.renew(ttl)
44
45     def get_data(self):
46         return self.data
47
48     def dump(self):
49         return self.__dict__
50
51     def __str__(self):
52         return str(self.dump())
53
54     def tostring(self):
55         return self.__str__()
56
57     def __getstate__(self):
58         d = dict(self.__dict__)
59         del d['lock']
60         return d
61
62     def __setstate__(self, d):
63         self.__dict__.update(d)
64         self.lock = threading.RLock()
65
66
67 class Cache:
68
69     cache = {}
70     lock = threading.RLock()
71
72     def __init__(self, filename=None):
73         if filename:
74             self.load_from_file(filename)
75
76     def add(self, key, value, ttl=DEFAULT_CACHE_TTL):
77         with self.lock:
78             if key in self.cache:
79                 self.cache[key].set_data(value, ttl=ttl)
80             else:
81                 self.cache[key] = CacheData(value, ttl)
82
83     def get(self, key):
84         data = self.cache.get(key)
85         if not data:
86             data = None
87         elif data.is_expired():
88             self.pop(key)
89             data = None
90         else:
91             data = data.get_data()
92         return data
93
94     def pop(self, key):
95         if key in self.cache:
96             self.cache.pop(key)
97
98     def dump(self):
99         result = {}
100         for key in self.cache:
101             result[key] = self.cache[key].__getstate__()
102         return result
103
104     def __str__(self):
105         return str(self.dump())
106
107     def tostring(self):
108         return self.__str()
109
110     def save_to_file(self, filename):
111         f = open(filename, 'wb')
112         pickle.dump(self.cache, f)
113
114     def load_from_file(self, filename):
115         f = open(filename, 'rb')
116         self.cache = pickle.load(f)