summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJürg Billeter <j@bitron.ch>2018-02-27 08:35:48 +0100
committerJürg Billeter <j@bitron.ch>2018-02-27 13:09:56 +0100
commit33b14eb508f52108835bbc8248d1e934b0389fae (patch)
tree6072487a74e59a8e7052eb86384949ac2d187f91
parentf685ea6898a8121caba1f8f2450cb957350f14ea (diff)
downloadbuildstream-33b14eb508f52108835bbc8248d1e934b0389fae.tar.gz
Determine as early as possible whether a build is pending
Workspaced sources are considered unstable if a build is pending as the build will modify the contents of the workspace. Determine as early as possible if a build is pending to be able to discard unstable cache keys. Fixes #273
-rw-r--r--buildstream/_scheduler/buildqueue.py4
-rw-r--r--buildstream/element.py41
2 files changed, 41 insertions, 4 deletions
diff --git a/buildstream/_scheduler/buildqueue.py b/buildstream/_scheduler/buildqueue.py
index ffa99a92d..512fe6c22 100644
--- a/buildstream/_scheduler/buildqueue.py
+++ b/buildstream/_scheduler/buildqueue.py
@@ -30,10 +30,6 @@ class BuildQueue(Queue):
complete_name = "Built"
queue_type = QueueType.BUILD
- def prepare(self, element):
- # Inform element in main process that it is scheduled for assembly
- element._schedule_assemble()
-
def process(self, element):
element._assemble()
return element._get_unique_id()
diff --git a/buildstream/element.py b/buildstream/element.py
index cd2299252..29c4f8b89 100644
--- a/buildstream/element.py
+++ b/buildstream/element.py
@@ -152,6 +152,8 @@ class Element(Plugin):
self.__strong_cached = None # Whether we have a cached artifact
self.__remotely_cached = None # Whether we have a remotely cached artifact
self.__remotely_strong_cached = None # Whether we have a remotely cached artifact
+ self.__assemble_scheduled = False # Element is scheduled to be assembled
+ self.__assemble_done = False # Element is assembled
self.__pull_failed = False # Whether pull was attempted but failed
self.__log_path = None # Path to dedicated log file or None
self.__splits = None
@@ -787,6 +789,9 @@ class Element(Plugin):
# in a subprocess.
#
def _schedule_assemble(self):
+ assert(not self.__assemble_scheduled)
+ self.__assemble_scheduled = True
+
for source in self.__sources:
source._schedule_assemble()
@@ -798,9 +803,14 @@ class Element(Plugin):
# in a subprocess.
#
def _assemble_done(self):
+ assert(self.__assemble_scheduled)
+
for source in self.__sources:
source._assemble_done()
+ self.__assemble_scheduled = False
+ self.__assemble_done = True
+
self._update_state()
# _cached():
@@ -954,6 +964,14 @@ class Element(Plugin):
# (bool): True if cache can be queried
#
def _can_query_cache(self):
+ # If build has already been scheduled, we know that the element is
+ # not cached and thus can allow cache query even if the strict cache key
+ # is not available yet.
+ # This special case is required for workspaced elements to prevent
+ # them from getting blocked in the pull queue.
+ if self.__assemble_scheduled:
+ return True
+
# cache cannot be queried until strict cache key is available
return self.__strict_cache_key is not None
@@ -1567,6 +1585,20 @@ class Element(Plugin):
# Weak cache key could not be calculated yet
return
+ if not self._get_strict():
+ # Full cache query in non-strict mode requires both the weak and
+ # strict cache keys. However, we need to determine as early as
+ # possible whether a build is pending to discard unstable cache keys
+ # for workspaced elements. For this cache check the weak cache keys
+ # are sufficient. However, don't update the `cached` attributes
+ # until the full cache query below.
+ cached = self.__artifacts.contains(self, self.__weak_cache_key)
+ remotely_cached = self.__artifacts.remote_contains(self, self.__weak_cache_key)
+ if (not self.__assemble_scheduled and not self.__assemble_done and
+ not cached and not remotely_cached):
+ self._schedule_assemble()
+ return
+
if self.__strict_cache_key is None:
dependencies = [
e.__strict_cache_key for e in self.dependencies(Scope.BUILD)
@@ -1588,6 +1620,15 @@ class Element(Plugin):
if not self.__remotely_strong_cached:
self.__remotely_strong_cached = self.__artifacts.remote_contains(self, self.__strict_cache_key)
+ if (not self.__assemble_scheduled and not self.__assemble_done and
+ not self.__cached and not self.__remotely_cached):
+ # Workspaced sources are considered unstable if a build is pending
+ # as the build will modify the contents of the workspace.
+ # Determine as early as possible if a build is pending to discard
+ # unstable cache keys.
+ self._schedule_assemble()
+ return
+
if self.__cache_key is None:
# Calculate strong cache key
if self._get_strict():