more misc methods
[sfa.git] / sfa / util / cache.py
1 #
2 # This module implements general purpose caching system
3 #
4 from __future__ import with_statement
5 import time
6 import threading
7 import pickle
8 from datetime import datetime
9 from pprint import pprint
10
11 # maximum lifetime of cached data (in seconds) 
12 MAX_CACHE_TTL = 60 * 60
13
14 class CacheData:
15
16     data = None
17     created = None
18     expires = None
19     lock = None
20
21     def __init__(self, data, ttl = MAX_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 = MAX_CACHE_TTL):
36         self.created = time.time()
37         self.expires = self.created + ttl   
38        
39     def set_data(self, data, renew=True, ttl = MAX_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
49     def dump(self):
50         return self.__dict__
51
52     def __str__(self):
53         return str(self.dump())  
54         
55     def tostring(self):
56         return self.__str__()
57
58     def __getstate__(self):
59         d = dict(self.__dict__)
60         del d['lock']
61         return d
62
63     def __setstate__(self, d):
64         self.__dict__.update(d)
65         self.lock = threading.RLock()
66         
67
68 class Cache:
69
70     cache  = {}
71     lock = threading.RLock()
72    
73     def add(self, key, value, ttl = MAX_CACHE_TTL):
74         with self.lock:
75             if self.cache.has_key(key):
76                 self.cache[key].set_data(value, ttl=ttl)
77             else:
78                 self.cache[key] = CacheData(value, ttl)
79            
80     def get(self, key):
81         data = self.cache.get(key)
82         if not data or data.is_expired():
83             return None 
84         return data.get_data()
85
86     def dump(self):
87         result = {}
88         for key in self.cache:
89             result[key] = self.cache[key].__getstate__()
90         return result
91
92     def __str__(self):
93         return str(self.dump())     
94  
95     def tostring(self):
96         return self.__str()    
97
98     def save_to_file(self, filename):
99         f = open(filename, 'w')
100         pickle.dump(self.cache, f)
101
102     def load_from_file(self, filename):
103         f = open(filename, 'r')
104         self.cache = pickle.load(f)