diff options
Diffstat (limited to 'buildstream/element.py')
-rw-r--r-- | buildstream/element.py | 211 |
1 files changed, 60 insertions, 151 deletions
diff --git a/buildstream/element.py b/buildstream/element.py index bc8f25cf8..95081b940 100644 --- a/buildstream/element.py +++ b/buildstream/element.py @@ -229,19 +229,14 @@ class Element(Plugin): self.__required = False # Whether the artifact is required in the current session self.__artifact_files_required = False # Whether artifact files are required in the local cache self.__build_result = None # The result of assembling this Element (success, description, detail) - self._build_log_path = None # The path of the build log for this Element - self.__artifact = Artifact(self, context) # Artifact class for direct artifact composite interaction + self._build_log_path = None # The path of the build log for this Element + self.__artifact = None # Artifact class for direct artifact composite interaction + self.__strict_artifact = None # Artifact for strict cache key self.__batch_prepare_assemble = False # Whether batching across prepare()/assemble() is configured self.__batch_prepare_assemble_flags = 0 # Sandbox flags for batching across prepare()/assemble() self.__batch_prepare_assemble_collect = None # Collect dir for batching across prepare()/assemble() - # hash tables of loaded artifact metadata, hashed by key - self.__metadata_keys = {} # Strong and weak keys for this key - self.__metadata_dependencies = {} # Dictionary of dependency strong keys - self.__metadata_workspaced = {} # Boolean of whether it's workspaced - self.__metadata_workspaced_dependencies = {} # List of which dependencies are workspaced - # Ensure we have loaded this class's defaults self.__init_defaults(plugin_conf) @@ -740,10 +735,11 @@ class Element(Plugin): files_written = {} old_dep_keys = None workspace = self._get_workspace() + context = self._get_context() if self.__can_build_incrementally() and workspace.last_successful: - # Workspaces do not need to work with the special node types - old_dep_keys = self.__get_artifact_metadata_dependencies(workspace.last_successful) + last_successful = Artifact(self, context, strong_key=workspace.last_successful) + old_dep_keys = last_successful.get_metadata_dependencies() for dep in self.dependencies(scope): # If we are workspaced, and we therefore perform an @@ -1055,7 +1051,10 @@ class Element(Plugin): # (str): Detailed description of the result # def _get_build_result(self): - return self.__get_build_result(keystrength=None) + if self.__build_result is None: + self.__load_build_result() + + return self.__build_result # __set_build_result(): # @@ -1076,7 +1075,11 @@ class Element(Plugin): # the artifact cache and the element assembled successfully # def _cached_success(self): - return self.__cached_success(keystrength=None) + if not self._cached(): + return False + + success, _, _ = self._get_build_result() + return success # _cached_failure(): # @@ -1180,6 +1183,8 @@ class Element(Plugin): self.__strong_cached = None self.__weak_cached = None self.__build_result = None + self.__artifact = None + self.__strict_artifact = None return if self.__weak_cache_key is None: @@ -1203,7 +1208,10 @@ class Element(Plugin): return if not context.get_strict(): - self.__weak_cached = self.__artifact.cached(self.__weak_cache_key) + # We've calculated the weak_key, so instantiate artifact instance member + self.__artifact = Artifact(self, context, weak_key=self.__weak_cache_key) + # and update the weak cached state (required early for workspaces) + self.__weak_cached = self.__artifact.cached() if not context.get_strict(): # Full cache query in non-strict mode requires both the weak and @@ -1213,7 +1221,7 @@ class Element(Plugin): # are sufficient. However, don't update the `cached` attributes # until the full cache query below. if (not self.__assemble_scheduled and not self.__assemble_done and - not self.__cached_success(keystrength=_KeyStrength.WEAK) and + not self._cached_success() and not self._pull_pending()): # For uncached workspaced elements, assemble is required # even if we only need the cache key @@ -1226,17 +1234,28 @@ class Element(Plugin): e.__strict_cache_key for e in self.dependencies(Scope.BUILD) ] self.__strict_cache_key = self._calculate_cache_key(dependencies) + if self.__strict_cache_key is None: # Strict cache key could not be calculated yet return - # Query caches now that the weak and strict cache keys are available - key_for_cache_lookup = self.__strict_cache_key if context.get_strict() else self.__weak_cache_key + self.__strict_artifact = Artifact(self, context, strong_key=self.__strict_cache_key, + weak_key=self.__weak_cache_key) + + # In strict mode, the strong cache key always matches the strict cache key + if context.get_strict(): + self.__cache_key = self.__strict_cache_key + self.__artifact = self.__strict_artifact + + # Query caches now that the weak and strict cache keys are available. + # strong_cached in non-strict mode is only of relevance when querying + # if a 'better' artifact could be pulled, which is redudant if we already + # have it cached locally with a strict_key. As such strong_cached is only + # checked against the 'strict' artifact. if not self.__strong_cached: - self.__strong_cached = self.__artifact.cached(self.__strict_cache_key) - if key_for_cache_lookup == self.__weak_cache_key: - if not self.__weak_cached: - self.__weak_cached = self.__artifact.cached(self.__weak_cache_key) + self.__strong_cached = self.__strict_artifact.cached() + if not self.__weak_cached and not context.get_strict(): + self.__weak_cached = self.__artifact.cached() if (not self.__assemble_scheduled and not self.__assemble_done and not self._cached_success() and not self._pull_pending()): @@ -1251,16 +1270,14 @@ class Element(Plugin): self._schedule_assemble() return + # __cache_key can be None here only in non-strict mode if self.__cache_key is None: - # Calculate strong cache key - if context.get_strict(): - self.__cache_key = self.__strict_cache_key - elif self._pull_pending(): + if self._pull_pending(): # Effective strong cache key is unknown until after the pull pass elif self._cached(): # Load the strong cache key from the artifact - strong_key, _ = self.__get_artifact_metadata_keys() + strong_key, _ = self.__artifact.get_metadata_keys() self.__cache_key = strong_key elif self.__assemble_scheduled or self.__assemble_done: # Artifact will or has been built, not downloaded @@ -1273,6 +1290,9 @@ class Element(Plugin): # Strong cache key could not be calculated yet return + # Now we have the strong cache key, update the Artifact + self.__artifact._cache_key = self.__cache_key + if not self.__ready_for_runtime and self.__cache_key is not None: self.__ready_for_runtime = all( dep.__ready_for_runtime for dep in self.__runtime_dependencies) @@ -1792,11 +1812,10 @@ class Element(Plugin): # ensure we have cache keys self._assemble_done() - keys = self.__get_cache_keys_for_commit() with self.timed_activity("Caching artifact"): artifact_size = self.__artifact.cache(rootdir, sandbox_build_dir, collectvdir, - buildresult, keys, publicdata) + buildresult, publicdata) if collect is not None and collectvdir is None: raise ElementError( @@ -2132,6 +2151,9 @@ class Element(Plugin): # not its contents. # def _cached_buildtree(self): + if not self._cached(): + return False + return self.__artifact.cached_buildtree() # _buildtree_exists() @@ -2140,9 +2162,13 @@ class Element(Plugin): # whether the buildtree is present in the local cache. # # Returns: - # (bool): True if artifact was created with buildtree + # (bool): True if artifact was created with buildtree, False if + # element not cached or not created with a buildtree. # def _buildtree_exists(self): + if not self._cached(): + return False + return self.__artifact.buildtree_exists() # _cached_logs() @@ -2364,10 +2390,10 @@ class Element(Plugin): if recalculate or self.__tainted is None: # Whether this artifact has a workspace - workspaced = self.__get_artifact_metadata_workspaced() + workspaced = self.__artifact.get_metadata_workspaced() # Whether this artifact's dependencies have workspaces - workspaced_dependencies = self.__get_artifact_metadata_workspaced_dependencies() + workspaced_dependencies = self.__artifact.get_metadata_workspaced_dependencies() # Other conditions should be or-ed self.__tainted = (workspaced or workspaced_dependencies or @@ -2774,138 +2800,21 @@ class Element(Plugin): self.__whitelist_regex = re.compile(expression) return self.__whitelist_regex.match(os.path.join(os.sep, path)) - # __get_artifact_metadata_keys(): - # - # Retrieve the strong and weak keys from the given artifact. - # - # Args: - # key (str): The artifact key, or None for the default key - # - # Returns: - # (str): The strong key - # (str): The weak key - # - def __get_artifact_metadata_keys(self, key=None): - - metadata_keys = self.__metadata_keys - - strong_key, weak_key, metadata_keys = self.__artifact.get_metadata_keys(key, metadata_keys) - - # Update keys if needed - if metadata_keys: - self.__metadata_keys = metadata_keys - - return (strong_key, weak_key) - - # __get_artifact_metadata_dependencies(): - # - # Retrieve the hash of dependency strong keys from the given artifact. - # - # Args: - # key (str): The artifact key, or None for the default key - # - # Returns: - # (dict): A dictionary of element names and their strong keys - # - def __get_artifact_metadata_dependencies(self, key=None): - - metadata = [self.__metadata_dependencies, self.__metadata_keys] - meta, meta_deps, meta_keys = self.__artifact.get_metadata_dependencies(key, *metadata) - - # Update deps if needed - if meta_deps: - self.__metadata_dependencies = meta_deps - # Update keys if needed, no need to check if deps not updated - if meta_keys: - self.__metadata_keys = meta_keys - - return meta - - # __get_artifact_metadata_workspaced(): - # - # Retrieve the hash of dependency strong keys from the given artifact. - # - # Args: - # key (str): The artifact key, or None for the default key - # - # Returns: - # (bool): Whether the given artifact was workspaced - # - - def __get_artifact_metadata_workspaced(self, key=None): - - metadata = [self.__metadata_workspaced, self.__metadata_keys] - workspaced, meta_workspaced, meta_keys = self.__artifact.get_metadata_workspaced(key, *metadata) - - # Update workspaced if needed - if meta_workspaced: - self.__metadata_workspaced = meta_workspaced - # Update keys if needed, no need to check if workspaced not updated - if meta_keys: - self.__metadata_keys = meta_keys - - return workspaced - - # __get_artifact_metadata_workspaced_dependencies(): - # - # Retrieve the hash of dependency strong keys from the given artifact. - # - # Args: - # key (str): The artifact key, or None for the default key - # - # Returns: - # (list): List of which dependencies are workspaced - # - def __get_artifact_metadata_workspaced_dependencies(self, key=None): - - metadata = [self.__metadata_workspaced_dependencies, self.__metadata_keys] - workspaced, meta_workspaced_deps,\ - meta_keys = self.__artifact.get_metadata_workspaced_dependencies(key, *metadata) - - # Update workspaced if needed - if meta_workspaced_deps: - self.__metadata_workspaced_dependencies = meta_workspaced_deps - # Update keys if needed, no need to check if workspaced not updated - if meta_keys: - self.__metadata_keys = meta_keys - - return workspaced - # __load_public_data(): # # Loads the public data from the cached artifact # def __load_public_data(self): + self.__assert_cached() assert self.__dynamic_public is None self.__dynamic_public = self.__artifact.load_public_data() - def __load_build_result(self, keystrength): - self.__assert_cached(keystrength=keystrength) + def __load_build_result(self): + self.__assert_cached() assert self.__build_result is None - # _get_cache_key with _KeyStrength.STRONG returns self.__cache_key, which can be `None` - # leading to a failed assertion from get_artifact_directory() using get_artifact_name(), - # so explicility pass self.__strict_cache_key - key = self.__weak_cache_key if keystrength is _KeyStrength.WEAK else self.__strict_cache_key - - self.__build_result = self.__artifact.load_build_result(key) - - def __get_build_result(self, keystrength): - if keystrength is None: - keystrength = _KeyStrength.STRONG if self._get_context().get_strict() else _KeyStrength.WEAK - - if self.__build_result is None: - self.__load_build_result(keystrength) - - return self.__build_result - - def __cached_success(self, keystrength): - if not self.__is_cached(keystrength=keystrength): - return False - - success, _, _ = self.__get_build_result(keystrength=keystrength) - return success + self.__build_result = self.__artifact.load_build_result() def __get_cache_keys_for_commit(self): keys = [] |