diff options
author | bst-marge-bot <marge-bot@buildstream.build> | 2019-08-08 13:51:40 +0000 |
---|---|---|
committer | bst-marge-bot <marge-bot@buildstream.build> | 2019-08-08 13:51:40 +0000 |
commit | 3e0eb25361e09124e56b5167212e9623a76da98f (patch) | |
tree | 202ea721a4ae49d52b166052a46460097da252f1 | |
parent | 2fb1d57c4043d8da5e47326a3184a69fcd877afd (diff) | |
parent | 89d5ccc8973766f24356ebc5b5f6ae58e62b0f8f (diff) | |
download | buildstream-3e0eb25361e09124e56b5167212e9623a76da98f.tar.gz |
Merge branch 'juerg/artifact-blobs' into 'master'
Artifact blob handling
See merge request BuildStream/buildstream!1527
-rw-r--r-- | src/buildstream/_artifact.py | 2 | ||||
-rw-r--r-- | src/buildstream/_cas/cascache.py | 22 | ||||
-rw-r--r-- | src/buildstream/_frontend/cli.py | 3 | ||||
-rw-r--r-- | src/buildstream/element.py | 2 | ||||
-rw-r--r-- | src/buildstream/sandbox/_sandboxremote.py | 29 | ||||
-rw-r--r-- | src/buildstream/sandbox/sandbox.py | 11 |
6 files changed, 42 insertions, 27 deletions
diff --git a/src/buildstream/_artifact.py b/src/buildstream/_artifact.py index 493ca5d26..5499b0dab 100644 --- a/src/buildstream/_artifact.py +++ b/src/buildstream/_artifact.py @@ -363,7 +363,7 @@ class Artifact(): # Check whether 'files' subdirectory is available, with or without file contents if (require_directories and str(artifact.files) and - not self._cas.contains_directory(artifact.files, with_files=require_files)): + not self._cas.contains_directory(artifact.files, with_files=require_files, update_mtime=True)): self._cached = False return False diff --git a/src/buildstream/_cas/cascache.py b/src/buildstream/_cas/cascache.py index dbdfa41a8..535d9199e 100644 --- a/src/buildstream/_cas/cascache.py +++ b/src/buildstream/_cas/cascache.py @@ -124,24 +124,33 @@ class CASCache(): # Args: # digest (Digest): The directory digest to check # with_files (bool): Whether to check files as well + # update_mtime (bool): Whether to update the timestamp # # Returns: True if the directory is available in the local cache # - def contains_directory(self, digest, *, with_files): + def contains_directory(self, digest, *, with_files, update_mtime=False): try: directory = remote_execution_pb2.Directory() - with open(self.objpath(digest), 'rb') as f: + path = self.objpath(digest) + with open(path, 'rb') as f: directory.ParseFromString(f.read()) + if update_mtime: + os.utime(f.fileno()) # Optionally check presence of files if with_files: for filenode in directory.files: - if not os.path.exists(self.objpath(filenode.digest)): + path = self.objpath(filenode.digest) + if update_mtime: + # No need for separate `exists()` call as this will raise + # FileNotFoundError if the file does not exist. + os.utime(path) + elif not os.path.exists(path): return False # Check subdirectories for dirnode in directory.directories: - if not self.contains_directory(dirnode.digest, with_files=with_files): + if not self.contains_directory(dirnode.digest, with_files=with_files, update_mtime=update_mtime): return False return True @@ -792,6 +801,9 @@ class CASCache(): directory.ParseFromString(f.read()) except FileNotFoundError: + if check_exists: + raise + # Just exit early if the file doesn't exist return @@ -961,6 +973,8 @@ class CASCache(): def fetch_blobs(self, remote, digests): missing_blobs = [] + remote.init() + batch = _CASBatchRead(remote) for digest in digests: diff --git a/src/buildstream/_frontend/cli.py b/src/buildstream/_frontend/cli.py index 276f81a6a..81ee4ad83 100644 --- a/src/buildstream/_frontend/cli.py +++ b/src/buildstream/_frontend/cli.py @@ -496,9 +496,6 @@ def show(app, elements, deps, except_, order, format_): $'---------- %{name} ----------\\n%{vars}' """ with app.initialized(): - # Do not require artifact directory trees or file contents to be present for `bst show` - app.context.set_artifact_directories_optional() - if not elements: elements = app.project.get_default_targets() diff --git a/src/buildstream/element.py b/src/buildstream/element.py index 21c38bc1a..0d80113ab 100644 --- a/src/buildstream/element.py +++ b/src/buildstream/element.py @@ -1703,6 +1703,7 @@ class Element(Plugin): try: sandbox_build_dir = sandbox_vroot.descend( *self.get_variable('build-root').lstrip(os.sep).split(os.sep)) + sandbox._fetch_missing_blobs(sandbox_build_dir) except VirtualDirectoryError: # Directory could not be found. Pre-virtual # directory behaviour was to continue silently @@ -1712,6 +1713,7 @@ class Element(Plugin): if collect is not None: try: collectvdir = sandbox_vroot.descend(*collect.lstrip(os.sep).split(os.sep)) + sandbox._fetch_missing_blobs(collectvdir) except VirtualDirectoryError: pass diff --git a/src/buildstream/sandbox/_sandboxremote.py b/src/buildstream/sandbox/_sandboxremote.py index c84bfa4ef..8c9515497 100644 --- a/src/buildstream/sandbox/_sandboxremote.py +++ b/src/buildstream/sandbox/_sandboxremote.py @@ -30,7 +30,6 @@ from .. import utils from ..node import Node from .._message import Message, MessageType from .sandbox import Sandbox, SandboxCommandError, _SandboxBatch -from ..storage.directory import VirtualDirectoryError from ..storage._casbaseddirectory import CasBasedDirectory from .. import _signals from .._protos.build.bazel.remote.execution.v2 import remote_execution_pb2, remote_execution_pb2_grpc @@ -280,7 +279,6 @@ class SandboxRemote(Sandbox): raise SandboxError("Output directory structure had no digest attached.") context = self._get_context() - project = self._get_project() cascache = context.get_cascache() artifactcache = context.artifactcache casremote = CASRemote(self.storage_remote_spec) @@ -294,27 +292,20 @@ class SandboxRemote(Sandbox): # to replace the sandbox's virtual directory with that. Creating a new virtual directory object # from another hash will be interesting, though... - new_dir = CasBasedDirectory(context.artifactcache.cas, digest=dir_digest) + new_dir = CasBasedDirectory(artifactcache.cas, digest=dir_digest) self._set_virtual_directory(new_dir) + def _fetch_missing_blobs(self, vdir): + context = self._get_context() + project = self._get_project() + cascache = context.get_cascache() + artifactcache = context.artifactcache + casremote = CASRemote(self.storage_remote_spec) + # Fetch the file blobs if needed if self._output_files_required or artifactcache.has_push_remotes(): - required_blobs = [] - directories = [] - - directories.append(self._output_directory) - if self._build_directory and (self._build_directory_always or failure): - directories.append(self._build_directory) - - for directory in directories: - try: - vdir = new_dir.descend(*directory.strip(os.sep).split(os.sep)) - dir_digest = vdir._get_digest() - required_blobs += cascache.required_blobs_for_directory(dir_digest) - except VirtualDirectoryError: - # If the directory does not exist, there is no need to - # download file blobs. - pass + dir_digest = vdir._get_digest() + required_blobs = cascache.required_blobs_for_directory(dir_digest) local_missing_blobs = cascache.local_missing_blobs(required_blobs) if local_missing_blobs: diff --git a/src/buildstream/sandbox/sandbox.py b/src/buildstream/sandbox/sandbox.py index ece15c949..8ff0aafa2 100644 --- a/src/buildstream/sandbox/sandbox.py +++ b/src/buildstream/sandbox/sandbox.py @@ -410,6 +410,17 @@ class Sandbox(): return 'BST_CAS_DIRECTORIES' in os.environ + # _fetch_missing_blobs() + # + # Fetch required file blobs missing from the local cache for sandboxes using + # remote execution. This is a no-op for local sandboxes. + # + # Args: + # vdir (Directory): The virtual directory whose blobs to fetch + # + def _fetch_missing_blobs(self, vdir): + pass + ################################################ # Private methods # ################################################ |