4 # Copyright (C) 2011 Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 """This module implements caching."""
27 from ganeti import locking
28 from ganeti import serializer
31 TIMESTAMP = "timestamp"
37 """This is the base class for all caches.
45 def Store(self, key, value, ttl=0):
46 """Stores key with value in the cache.
48 @param key: The key to associate this cached value
49 @param value: The value to cache
50 @param ttl: TTL in seconds after when this entry is considered outdated
51 @returns: L{True} on success, L{False} on failure
54 raise NotImplementedError
56 def GetMulti(self, keys):
57 """Retrieve multiple values from the cache.
59 @param keys: The keys to retrieve
60 @returns: The list of values
63 raise NotImplementedError
66 """Retrieve the value from the cache.
68 @param key: The key to retrieve
69 @returns: The value or L{None} if not found
72 raise NotImplementedError
74 def Invalidate(self, keys):
75 """Invalidate given keys.
77 @param keys: The list of keys to invalidate
78 @returns: L{True} on success, L{False} otherwise
81 raise NotImplementedError
84 """Invalidates all of the keys and flushes the cache.
87 raise NotImplementedError
90 """Used to reset the state of the cache.
92 This can be used to reinstantiate connection or any other state refresh
97 """Cleanup the cache from expired entries.
102 class SimpleCache(CacheBase):
103 """Implements a very simple, dict base cache.
109 def __init__(self, _time_fn=time.time):
110 """Initialize this class.
112 @param _time_fn: Function used to return time (unittest only)
115 CacheBase.__init__(self)
117 self._time_fn = _time_fn
120 self.lock = locking.SharedLock("SimpleCache")
121 self.last_cleanup = self._time_fn()
123 def _UnlockedCleanup(self):
124 """Does cleanup of the cache.
127 check_time = self._time_fn()
128 if (self.last_cleanup + self.CLEANUP_ROUND) <= check_time:
130 for key, value in self.cache.items():
134 expired = value[TIMESTAMP] + value[TTL]
135 if expired < check_time:
137 self._UnlockedInvalidate(keys)
138 self.last_cleanup = check_time
140 @locking.ssynchronized(_LOCK)
142 """Cleanup our cache.
145 self._UnlockedCleanup()
147 @locking.ssynchronized(_LOCK)
148 def Store(self, key, value, ttl=0):
149 """Stores a value at key in the cache.
151 See L{CacheBase.Store} for parameter description
155 self._UnlockedCleanup()
156 val = serializer.Dump(value)
158 TIMESTAMP: self._time_fn(),
162 self.cache[key] = cache_val
165 @locking.ssynchronized(_LOCK, shared=1)
166 def GetMulti(self, keys):
167 """Retrieve the values of keys from cache.
169 See L{CacheBase.GetMulti} for parameter description
172 return [self._ExtractValue(key) for key in keys]
174 @locking.ssynchronized(_LOCK, shared=1)
176 """Retrieve the value of key from cache.
178 See L{CacheBase.Get} for parameter description
181 return self._ExtractValue(key)
183 @locking.ssynchronized(_LOCK)
184 def Invalidate(self, keys):
185 """Invalidates value for keys in cache.
187 See L{CacheBase.Invalidate} for parameter description
190 return self._UnlockedInvalidate(keys)
192 @locking.ssynchronized(_LOCK)
194 """Invalidates all keys and values in cache.
196 See L{CacheBase.Flush} for parameter description
200 self.last_cleanup = self._time_fn()
202 def _UnlockedInvalidate(self, keys):
203 """Invalidate keys in cache.
205 This is the unlocked version, see L{Invalidate} for parameter description
209 self.cache.pop(key, None)
213 def _ExtractValue(self, key):
214 """Extracts just the value for a key.
216 This method is taking care if the value did not expire ans returns it
218 @param key: The key to look for
219 @returns: The value if key is not expired, L{None} otherwise
223 cache_val = self.cache[key]
227 if cache_val[TTL] == 0:
228 return serializer.Load(cache_val[VALUE])
230 expired = cache_val[TIMESTAMP] + cache_val[TTL]
232 if self._time_fn() <= expired:
233 return serializer.Load(cache_val[VALUE])