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
|
# This file is part of Buildbot. Buildbot is free software: you can
# redistribute it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright Buildbot Team Members
from buildbot.util import lru
from buildbot import config
from twisted.application import service
class CacheManager(config.ReconfigurableServiceMixin, service.Service):
"""
A manager for a collection of caches, each for different types of objects
and with potentially-overlapping key spaces.
There is generally only one instance of this class, available at
C{master.caches}.
"""
# a cache of length one still has many benefits: it collects objects that
# remain referenced elsewhere; it collapses simultaneous misses into one
# miss function; and it will optimize repeated fetches of the same object.
DEFAULT_CACHE_SIZE = 1
def __init__(self):
self.setName('caches')
self.config = {}
self._caches = {}
def get_cache(self, cache_name, miss_fn):
"""
Get an L{AsyncLRUCache} object with the given name. If such an object
does not exist, it will be created. Since the cache is permanent, this
method can be called only once, e.g., in C{startService}, and it value
stored indefinitely.
@param cache_name: name of the cache (usually the name of the type of
object it stores)
@param miss_fn: miss function for the cache; see L{AsyncLRUCache}
constructor.
@returns: L{AsyncLRUCache} instance
"""
try:
return self._caches[cache_name]
except KeyError:
max_size = self.config.get(cache_name, self.DEFAULT_CACHE_SIZE)
assert max_size >= 1
c = self._caches[cache_name] = lru.AsyncLRUCache(miss_fn, max_size)
return c
def reconfigService(self, new_config):
self.config = new_config.caches
for name, cache in self._caches.iteritems():
cache.set_max_size(new_config.caches.get(name,
self.DEFAULT_CACHE_SIZE))
return config.ReconfigurableServiceMixin.reconfigService(self,
new_config)
def get_metrics(self):
return dict([
(n, dict(hits=c.hits, refhits=c.refhits,
misses=c.misses, max_size=c.max_size))
for n, c in self._caches.iteritems()])
|