Index: third_party/buildbot_8_4p1/buildbot/status/builder.py |
=================================================================== |
--- third_party/buildbot_8_4p1/buildbot/status/builder.py (revision 127129) |
+++ third_party/buildbot_8_4p1/buildbot/status/builder.py (working copy) |
@@ -24,6 +24,7 @@ |
from twisted.persisted import styles |
from buildbot.process import metrics |
from buildbot import interfaces, util |
+from buildbot.util.lru import SyncLRUCache |
from buildbot.status.event import Event |
from buildbot.status.build import BuildStatus |
from buildbot.status.buildrequest import BuildRequestStatus |
@@ -86,8 +87,7 @@ |
self.currentBuilds = [] |
self.nextBuild = None |
self.watchers = [] |
- self.buildCache = weakref.WeakValueDictionary() |
- self.buildCache_LRU = [] |
+ self.buildCache = SyncLRUCache(self.cacheMiss, self.buildCacheSize) |
self.logCompressionLimit = False # default to no compression for tests |
self.logCompressionMethod = "bz2" |
self.logMaxSize = None # No default limit |
@@ -103,7 +103,6 @@ |
d = styles.Versioned.__getstate__(self) |
d['watchers'] = [] |
del d['buildCache'] |
- del d['buildCache_LRU'] |
for b in self.currentBuilds: |
b.saveYourself() |
# TODO: push a 'hey, build was interrupted' event |
@@ -119,8 +118,7 @@ |
# when loading, re-initialize the transient stuff. Remember that |
# upgradeToVersion1 and such will be called after this finishes. |
styles.Versioned.__setstate__(self, d) |
- self.buildCache = weakref.WeakValueDictionary() |
- self.buildCache_LRU = [] |
+ self.buildCache = SyncLRUCache(self.cacheMiss, self.buildCacheSize) |
self.currentBuilds = [] |
self.watchers = [] |
self.slavenames = [] |
@@ -132,6 +130,7 @@ |
# gets pickled and unpickled. |
if buildmaster.buildCacheSize is not None: |
self.buildCacheSize = buildmaster.buildCacheSize |
+ self.buildCache.set_max_size(buildmaster.buildCacheSize) |
def upgradeToVersion1(self): |
if hasattr(self, 'slavename'): |
@@ -186,33 +185,17 @@ |
except: |
log.msg("unable to save builder %s" % self.name) |
log.err() |
- |
+ |
# build cache management |
def makeBuildFilename(self, number): |
return os.path.join(self.basedir, "%d" % number) |
- def touchBuildCache(self, build): |
- self.buildCache[build.number] = build |
- if build in self.buildCache_LRU: |
- self.buildCache_LRU.remove(build) |
- self.buildCache_LRU = self.buildCache_LRU[-(self.buildCacheSize-1):] + [ build ] |
- return build |
- |
def getBuildByNumber(self, number): |
- # first look in currentBuilds |
- for b in self.currentBuilds: |
- if b.number == number: |
- return self.touchBuildCache(b) |
+ return self.buildCache.get(number) |
- # then in the buildCache |
- if number in self.buildCache: |
- metrics.MetricCountEvent.log("buildCache.hits", 1) |
- return self.touchBuildCache(self.buildCache[number]) |
- metrics.MetricCountEvent.log("buildCache.misses", 1) |
- |
- # then fall back to loading it from disk |
+ def loadBuildFromFile(self, number): |
filename = self.makeBuildFilename(number) |
try: |
log.msg("Loading builder %s's build %d from on-disk pickle" |
@@ -235,12 +218,20 @@ |
build.upgradeLogfiles() |
# check that logfiles exist |
build.checkLogfiles() |
- return self.touchBuildCache(build) |
+ return build |
except IOError: |
raise IndexError("no such build %d" % number) |
except EOFError: |
raise IndexError("corrupted build pickle %d" % number) |
+ def cacheMiss(self, number): |
+ # first look in currentBuilds |
+ for b in self.currentBuilds: |
+ if b.number == number: |
+ return b |
+ # then fall back to loading it from disk |
+ return self.loadBuildFromFile(number) |
+ |
def prune(self, events_only=False): |
# begin by pruning our own events |
self.events = self.events[-self.eventHorizon:] |
@@ -287,7 +278,7 @@ |
is_logfile = True |
if num is None: continue |
- if num in self.buildCache: continue |
+ if num in self.buildCache.cache: continue |
if (is_logfile and num < earliest_log) or num < earliest_build: |
pathname = os.path.join(self.basedir, filename) |
@@ -510,7 +501,7 @@ |
assert s.number == self.nextBuildNumber - 1 |
assert s not in self.currentBuilds |
self.currentBuilds.append(s) |
- self.touchBuildCache(s) |
+ self.buildCache.put(s.number, s) |
# now that the BuildStatus is prepared to answer queries, we can |
# announce the new build to all our watchers |
@@ -620,7 +611,7 @@ |
# Collect build numbers. |
# Important: Only grab the *cached* builds numbers to reduce I/O. |
current_builds = [b.getNumber() for b in self.currentBuilds] |
- cached_builds = list(set(self.buildCache.keys() + current_builds)) |
+ cached_builds = list(set(self.buildCache.cache.keys() + current_builds)) |
cached_builds.sort() |
result['cachedBuilds'] = cached_builds |
result['currentBuilds'] = current_builds |