Index: third_party/buildbot_8_4p1/buildbot/status/builder.py |
diff --git a/third_party/buildbot_8_4p1/buildbot/status/builder.py b/third_party/buildbot_8_4p1/buildbot/status/builder.py |
index 3f42eb6f7e445be7020d9cd79108f854d7abc97c..c5bd1ec93bf31208fd25a971ba86617ff8eb6e55 100644 |
--- a/third_party/buildbot_8_4p1/buildbot/status/builder.py |
+++ b/third_party/buildbot_8_4p1/buildbot/status/builder.py |
@@ -17,6 +17,7 @@ |
import weakref |
import gc |
import os, re, itertools |
+import random |
from cPickle import load, dump |
from zope.interface import implements |
@@ -323,17 +324,58 @@ class BuilderStatus(styles.Versioned): |
def getCategory(self): |
return self.category |
- def getBuild(self, number): |
+ def _resolveBuildNumber(self, number): |
if number < 0: |
number = self.nextBuildNumber + number |
if number < 0 or number >= self.nextBuildNumber: |
return None |
+ return number |
+ def _safeGetBuild(self, build_number): |
try: |
- return self.getBuildByNumber(number) |
+ return self.getBuildByNumber(build_number) |
except IndexError: |
return None |
+ def getBuild(self, number): |
+ number = self._resolveBuildNumber(number) |
+ |
+ if number is None: |
+ return None |
+ |
+ return self._safeGetBuild(number) |
+ |
+ def getBuilds(self, numbers): |
+ """Cache-aware method to get multiple builds. |
+ |
+ Prevents cascading evict/load when multiple builds are requested in |
+ succession: requesting build 1 evicts build 2, requesting build 2 evicts |
+ build 3, etc. |
+ |
+ We query the buildCache and load hits first, then misses. When loading, |
+ we randomize the load order to alleviate the problem when external web |
+ requests load builds sequentially (they don't have access to this |
+ function). |
+ """ |
+ |
+ numbers = list(enumerate(self._resolveBuildNumber(x) for x in numbers)) |
+ random.shuffle(numbers) |
+ |
+ builds = [None] * len(numbers) |
+ misses = [] |
+ for idx, build_number in numbers: |
+ if build_number is None: |
+ continue |
+ if build_number in self.buildCache.cache: |
+ builds[idx] = self._safeGetBuild(build_number) |
+ else: |
+ misses.append((idx, build_number)) |
+ |
+ for idx, build_number in misses: |
+ builds[idx] = self._safeGetBuild(build_number) |
+ |
+ return builds |
+ |
def getEvent(self, number): |
try: |
return self.events[number] |
@@ -616,6 +658,11 @@ class BuilderStatus(styles.Versioned): |
# Collect build numbers. |
# Important: Only grab the *cached* builds numbers to reduce I/O. |
current_builds = [b.getNumber() for b in self.currentBuilds] |
+ |
+ # Populates buildCache with last N builds. |
+ buildnums = range(-1, -(self.buildCacheSize - 1), -1) |
+ self.getBuilds(buildnums) |
+ |
cached_builds = list(set(self.buildCache.cache.keys() + current_builds)) |
cached_builds.sort() |
result['cachedBuilds'] = cached_builds |