blob: 5dde5a5346584d82e3553c76629eb7b6c7195250 [file] [log] [blame]
Janak Ramakrishnana5c1f962015-04-03 23:06:31 +00001// Copyright 2014 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.skyframe;
15
16import com.google.common.base.Preconditions;
17import com.google.common.collect.Interner;
18import com.google.common.collect.Interners;
19import com.google.common.io.BaseEncoding;
20import com.google.devtools.build.lib.actions.ActionInput;
21import com.google.devtools.build.lib.actions.ActionInputFileCache;
22import com.google.devtools.build.lib.actions.Artifact;
23import com.google.protobuf.ByteString;
24
25import java.io.File;
26import java.io.IOException;
27import java.nio.charset.StandardCharsets;
28import java.util.Map;
29import java.util.concurrent.ConcurrentHashMap;
30
31import javax.annotation.Nullable;
32
33/**
34 * Cache provided by an {@link ActionExecutionFunction}, allowing Blaze to obtain artifact metadata
35 * from the graph.
36 *
37 * <p>Data for the action's inputs is injected into this cache on construction, using the graph as
38 * the source of truth.
39 */
40class PerActionFileCache implements ActionInputFileCache {
41 private final Map<Artifact, FileArtifactValue> inputArtifactData;
42 private final File execRoot;
43 // Populated lazily, on calls to #getDigest.
44 private final Map<ByteString, Artifact> reverseMap = new ConcurrentHashMap<>();
45
46 private static final Interner<ByteString> BYTE_INTERNER = Interners.newWeakInterner();
47
48 /**
49 * @param inputArtifactData Map from artifact to metadata, used to return metadata upon request.
50 * @param execRoot Path to the execution root, used to convert Artifacts' relative paths into
51 * absolute ones in the execution root.
52 */
53 PerActionFileCache(Map<Artifact, FileArtifactValue> inputArtifactData,
54 File execRoot) {
55 this.inputArtifactData = Preconditions.checkNotNull(inputArtifactData);
56 this.execRoot = Preconditions.checkNotNull(execRoot);
57 }
58
59 @Nullable
60 private FileArtifactValue getInputFileArtifactValue(ActionInput input) {
61 if (!(input instanceof Artifact)) {
62 return null;
63 }
64 return Preconditions.checkNotNull(inputArtifactData.get(input), input);
65 }
66
67 @Override
68 public long getSizeInBytes(ActionInput input) throws IOException {
69 FileArtifactValue metadata = getInputFileArtifactValue(input);
70 if (metadata != null) {
71 return metadata.getSize();
72 }
73 return -1;
74 }
75
76 @Nullable
77 @Override
78 public File getFileFromDigest(ByteString digest) throws IOException {
79 Artifact artifact = reverseMap.get(digest);
80 if (artifact != null) {
81 String relPath = artifact.getExecPathString();
82 return new File(execRoot, relPath);
83 }
84 return null;
85 }
86
87 @Nullable
88 @Override
89 public ByteString getDigest(ActionInput input) throws IOException {
90 FileArtifactValue value = getInputFileArtifactValue(input);
91 if (value != null) {
92 byte[] bytes = value.getDigest();
93 if (bytes != null) {
94 ByteString digest = ByteString.copyFrom(BaseEncoding.base16().lowerCase().encode(bytes)
95 .getBytes(StandardCharsets.US_ASCII));
96 reverseMap.put(BYTE_INTERNER.intern(digest), (Artifact) input);
97 return digest;
98 }
99 }
100 return null;
101 }
102
103 @Override
104 public boolean contentsAvailableLocally(ByteString digest) {
105 return reverseMap.containsKey(digest);
106 }
107}