Package gavo :: Package base :: Module caches
[frames] | no frames]

Source Code for Module gavo.base.caches

  1  """ 
  2  Accessor functions for the various immutables we have. 
  3   
  4  The main purpose of this module is to keep caches of resource descriptors, 
  5  and other items the parsing of which may take some time. 
  6   
  7  All you need to do is provide a function taking a "key" (a string, most 
  8  likely) and returning the object.  Then call 
  9   
 10  base.caches.makeCache(<accessorName>, <function>) 
 11   
 12  After that, clients can call 
 13   
 14  base.caches.<accessorName>(key) 
 15   
 16  You can additionally provide an isDirty(res) function when calling makeCache. 
 17  This can return True if the resource is out of date and should be reloaded. 
 18   
 19  An alternative interface to registering caches is the registerCache function 
 20  (see there). 
 21  """ 
 22   
 23  #c Copyright 2008-2019, the GAVO project 
 24  #c 
 25  #c This program is free software, covered by the GNU GPL.  See the 
 26  #c COPYING file in the source distribution. 
 27   
 28   
29 -class CacheRegistry:
30 """is a registry for caches kept to be able to clear them. 31 32 A cache is assumed to be a dicitonary here. 33 """
34 - def __init__(self):
35 self.knownCaches = []
36
37 - def clearall(self):
38 for cache in self.knownCaches: 39 for key in cache.keys(): 40 del cache[key]
41
42 - def clearForName(self, key):
43 for cache in self.knownCaches: 44 if key in cache: 45 del cache[key]
46
47 - def register(self, cache):
48 self.knownCaches.append(cache)
49 50 51 _cacheRegistry = CacheRegistry() 52 clearCaches = _cacheRegistry.clearall 53 clearForName = _cacheRegistry.clearForName 54 55
56 -def _makeCache(creator, isDirty):
57 """returns a callable that memoizes the results of creator. 58 59 The creator has to be a function taking an id and returning the 60 designated object. 61 62 The whole thing is thread-safe only when the creators are. It is 63 possible that arbitrarily many creators for the same id run. Only one 64 will win in the end. 65 66 Race conditions are possible when exceptions occur, but then creators 67 behaviour should only depend on id, and so it shouldn't matter. 68 69 isDirty can be a function returning true when the cache should be 70 cleared. The function is passed the current resource. If isDirty 71 is None, no such check is performed. 72 """ 73 cache = {} 74 _cacheRegistry.register(cache) 75 76 def func(id): 77 if isDirty is not None and id in cache and isDirty(cache[id]): 78 clearForName(id) 79 80 if not id in cache: 81 try: 82 cache[id] = creator(id) 83 except Exception as exc: 84 cache[id] = exc 85 raise 86 if isinstance(cache[id], Exception): 87 raise cache[id] 88 else: 89 return cache[id]
90 91 return func 92 93
94 -def registerCache(name, cacheDict, creationFunction):
95 """registers a custom cache. 96 97 This function makes creationFunction available as base.caches.name, 98 and it registers cacheDict with the cache manager such that cacheDict 99 is cleared as necessary. 100 101 creationFunction must manage cacheDict itself, and of course it 102 must always use the instance passed to registerCache. 103 104 This is for "magic" things like getRD that has to deal with aliases 105 and such. For normal use, use makeCache. 106 """ 107 globals()[name] = creationFunction 108 _cacheRegistry.register(cacheDict)
109 110
111 -def makeCache(name, callable, isDirty=None):
112 """creates a new function name to cache results to calls to callable. 113 114 isDirty can be a function returning true when the cache should be 115 cleared. The function is passed the current resource. 116 """ 117 globals()[name] = _makeCache(callable, isDirty)
118