Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2014 The Bazel Authors. All rights reserved. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 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. |
| 14 | package com.google.devtools.build.lib.skyframe; |
| 15 | |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 16 | import com.google.common.base.Function; |
tomlu | a155b53 | 2017-11-08 20:12:47 +0100 | [diff] [blame] | 17 | import com.google.common.base.Preconditions; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 18 | import com.google.common.base.Predicate; |
felly | bb07aa9 | 2018-09-04 09:42:39 -0700 | [diff] [blame] | 19 | import com.google.common.base.Supplier; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 20 | import com.google.common.collect.ImmutableList; |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 21 | import com.google.common.collect.ImmutableMap; |
| 22 | import com.google.common.collect.Iterables; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 23 | import com.google.devtools.build.lib.actions.Action; |
Rumou Duan | 33bab46 | 2016-04-25 17:55:12 +0000 | [diff] [blame] | 24 | import com.google.devtools.build.lib.actions.ActionAnalysisMetadata; |
| 25 | import com.google.devtools.build.lib.actions.ActionAnalysisMetadata.MiddlemanType; |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 26 | import com.google.devtools.build.lib.actions.ActionLookupValue; |
| 27 | import com.google.devtools.build.lib.actions.ActionLookupValue.ActionLookupKey; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 28 | import com.google.devtools.build.lib.actions.Artifact; |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 29 | import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact; |
janakr | 0c42fc8 | 2018-09-14 10:37:25 -0700 | [diff] [blame] | 30 | import com.google.devtools.build.lib.actions.ArtifactFileMetadata; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 31 | import com.google.devtools.build.lib.actions.ArtifactOwner; |
shahan | e35e8cf | 2018-06-18 08:14:01 -0700 | [diff] [blame] | 32 | import com.google.devtools.build.lib.actions.ArtifactSkyKey; |
shahan | 602cc85 | 2018-06-06 20:09:57 -0700 | [diff] [blame] | 33 | import com.google.devtools.build.lib.actions.FileArtifactValue; |
| 34 | import com.google.devtools.build.lib.actions.FileValue; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 35 | import com.google.devtools.build.lib.actions.MissingInputFileException; |
Lukacs Berki | 6e91eb9 | 2015-09-21 09:12:37 +0000 | [diff] [blame] | 36 | import com.google.devtools.build.lib.cmdline.Label; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 37 | import com.google.devtools.build.lib.events.Event; |
| 38 | import com.google.devtools.build.lib.events.EventHandler; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 39 | import com.google.devtools.build.lib.util.Pair; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 40 | import com.google.devtools.build.lib.vfs.RootedPath; |
| 41 | import com.google.devtools.build.skyframe.SkyFunction; |
| 42 | import com.google.devtools.build.skyframe.SkyFunctionException; |
| 43 | import com.google.devtools.build.skyframe.SkyFunctionException.Transience; |
| 44 | import com.google.devtools.build.skyframe.SkyKey; |
| 45 | import com.google.devtools.build.skyframe.SkyValue; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 46 | import java.io.IOException; |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 47 | import java.util.ArrayList; |
Googler | 84bfb9a | 2018-07-12 05:41:49 -0700 | [diff] [blame] | 48 | import java.util.Comparator; |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 49 | import java.util.List; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 50 | import java.util.Map; |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 51 | import javax.annotation.Nullable; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 52 | |
Janak Ramakrishnan | ad77f97 | 2016-07-29 20:58:42 +0000 | [diff] [blame] | 53 | /** A builder of values for {@link ArtifactSkyKey} keys. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 54 | class ArtifactFunction implements SkyFunction { |
| 55 | |
felly | bb07aa9 | 2018-09-04 09:42:39 -0700 | [diff] [blame] | 56 | private final Supplier<Boolean> usesActionFS; |
| 57 | |
| 58 | public ArtifactFunction(Supplier<Boolean> usesActionFS) { |
| 59 | this.usesActionFS = usesActionFS; |
| 60 | } |
| 61 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 62 | @Override |
Janak Ramakrishnan | 3c0adb2 | 2016-08-15 21:54:55 +0000 | [diff] [blame] | 63 | public SkyValue compute(SkyKey skyKey, Environment env) |
| 64 | throws ArtifactFunctionException, InterruptedException { |
janakr | bf4123d | 2018-07-24 11:38:19 -0700 | [diff] [blame] | 65 | Artifact artifact = ArtifactSkyKey.artifact(skyKey); |
| 66 | boolean isMandatory = ArtifactSkyKey.isMandatory(skyKey); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 67 | if (artifact.isSourceArtifact()) { |
| 68 | try { |
janakr | bf4123d | 2018-07-24 11:38:19 -0700 | [diff] [blame] | 69 | return createSourceValue(artifact, isMandatory, env); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 70 | } catch (MissingInputFileException e) { |
| 71 | // The error is not necessarily truly transient, but we mark it as such because we have |
| 72 | // the above side effect of posting an event to the EventBus. Importantly, that event |
| 73 | // is potentially used to report root causes. |
| 74 | throw new ArtifactFunctionException(e, Transience.TRANSIENT); |
| 75 | } |
| 76 | } |
| 77 | |
janakr | baf52ae | 2018-02-14 09:03:18 -0800 | [diff] [blame] | 78 | ActionLookupKey actionLookupKey = getActionLookupKey(artifact); |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 79 | ActionLookupValue actionLookupValue = getActionLookupValue(actionLookupKey, env, artifact); |
| 80 | if (actionLookupValue == null) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 81 | return null; |
| 82 | } |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 83 | Integer actionIndex = actionLookupValue.getGeneratingActionIndex(artifact); |
| 84 | if (artifact.hasParent() && actionIndex == null) { |
| 85 | // If a TreeFileArtifact is created by a templated action, then it should have the proper |
| 86 | // reference to its owner. However, if it was created as part of a directory, by the first |
| 87 | // TreeArtifact-generating action in a chain, then its parent's generating action also |
| 88 | // generated it. This catches that case. |
| 89 | actionIndex = actionLookupValue.getGeneratingActionIndex(artifact.getParent()); |
| 90 | } |
| 91 | Preconditions.checkNotNull( |
| 92 | actionIndex, "%s %s %s", artifact, actionLookupKey, actionLookupValue); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 93 | |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 94 | // If the action is an ActionTemplate, we need to expand the ActionTemplate into concrete |
| 95 | // actions, execute those actions in parallel and then aggregate the action execution results. |
janakr | cb314a2 | 2018-02-15 10:33:53 -0800 | [diff] [blame] | 96 | if (artifact.isTreeArtifact() && actionLookupValue.isActionTemplate(actionIndex)) { |
| 97 | // Create the directory structures for the output TreeArtifact first. |
felly | bb07aa9 | 2018-09-04 09:42:39 -0700 | [diff] [blame] | 98 | if (!usesActionFS.get()) { |
| 99 | try { |
| 100 | artifact.getPath().createDirectoryAndParents(); |
| 101 | } catch (IOException e) { |
| 102 | env.getListener() |
| 103 | .handle( |
| 104 | Event.error( |
| 105 | String.format( |
| 106 | "Failed to create output directory for TreeArtifact %s: %s", |
| 107 | artifact, e.getMessage()))); |
| 108 | throw new ArtifactFunctionException(e, Transience.TRANSIENT); |
| 109 | } |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 110 | } |
janakr | cb314a2 | 2018-02-15 10:33:53 -0800 | [diff] [blame] | 111 | |
| 112 | return createTreeArtifactValueFromActionKey(actionLookupKey, actionIndex, artifact, env); |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 113 | } |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 114 | ActionExecutionValue actionValue = |
| 115 | (ActionExecutionValue) env.getValue(ActionExecutionValue.key(actionLookupKey, actionIndex)); |
| 116 | if (actionValue == null) { |
| 117 | return null; |
| 118 | } |
| 119 | |
| 120 | if (artifact.isTreeArtifact()) { |
| 121 | // We get a request for the whole tree artifact. We can just return the associated |
| 122 | // TreeArtifactValue. |
| 123 | return Preconditions.checkNotNull(actionValue.getTreeArtifactValue(artifact), artifact); |
| 124 | } |
| 125 | if (artifact.isMiddlemanArtifact()) { |
| 126 | Action action = |
| 127 | Preconditions.checkNotNull( |
| 128 | actionLookupValue.getAction(actionIndex), |
| 129 | "Null middleman action? %s %s %s %s", |
| 130 | artifact, |
| 131 | actionLookupKey, |
| 132 | actionLookupValue, |
| 133 | actionIndex); |
| 134 | if (isAggregatingValue(action)) { |
buchgr | d4d3d50 | 2018-08-02 06:47:19 -0700 | [diff] [blame] | 135 | return createAggregatingValue( |
| 136 | artifact, action, actionValue.getArtifactValue(artifact), env); |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 137 | } |
| 138 | } |
| 139 | return createSimpleFileArtifactValue(artifact, actionValue); |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 140 | } |
| 141 | |
janakr | cb314a2 | 2018-02-15 10:33:53 -0800 | [diff] [blame] | 142 | private static TreeArtifactValue createTreeArtifactValueFromActionKey( |
| 143 | ActionLookupKey actionLookupKey, |
| 144 | int actionIndex, |
| 145 | final Artifact treeArtifact, |
| 146 | Environment env) |
| 147 | throws InterruptedException { |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 148 | // Request the list of expanded actions from the ActionTemplate. |
janakr | baf52ae | 2018-02-14 09:03:18 -0800 | [diff] [blame] | 149 | ActionTemplateExpansionValue.ActionTemplateExpansionKey templateKey = |
janakr | cb314a2 | 2018-02-15 10:33:53 -0800 | [diff] [blame] | 150 | ActionTemplateExpansionValue.key(actionLookupKey, actionIndex); |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 151 | ActionTemplateExpansionValue expansionValue = |
| 152 | (ActionTemplateExpansionValue) env.getValue(templateKey); |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 153 | |
| 154 | // The expanded actions are not yet available. |
| 155 | if (env.valuesMissing()) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 156 | return null; |
| 157 | } |
| 158 | |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 159 | List<SkyKey> expandedActionExecutionKeys = new ArrayList<>(expansionValue.getNumActions()); |
| 160 | for (int i = 0; i < expansionValue.getNumActions(); i++) { |
| 161 | expandedActionExecutionKeys.add(ActionExecutionValue.key(templateKey, i)); |
| 162 | } |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 163 | Map<SkyKey, SkyValue> expandedActionValueMap = env.getValues(expandedActionExecutionKeys); |
| 164 | |
| 165 | // The execution values of the expanded actions are not yet all available. |
| 166 | if (env.valuesMissing()) { |
| 167 | return null; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 168 | } |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 169 | |
| 170 | // Aggregate the ArtifactValues for individual TreeFileArtifacts into a TreeArtifactValue for |
| 171 | // the parent TreeArtifact. |
| 172 | ImmutableMap.Builder<TreeFileArtifact, FileArtifactValue> map = ImmutableMap.builder(); |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 173 | for (int i = 0; i < expansionValue.getNumActions(); i++) { |
| 174 | final ActionExecutionValue actionExecutionValue = |
| 175 | (ActionExecutionValue) |
| 176 | Preconditions.checkNotNull( |
| 177 | expandedActionValueMap.get(expandedActionExecutionKeys.get(i)), |
janakr | cb314a2 | 2018-02-15 10:33:53 -0800 | [diff] [blame] | 178 | "Missing tree value: %s %s %s %s %s", |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 179 | treeArtifact, |
janakr | cb314a2 | 2018-02-15 10:33:53 -0800 | [diff] [blame] | 180 | actionLookupKey, |
| 181 | actionIndex, |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 182 | expansionValue, |
tomlu | 32d2edc | 2017-11-08 18:14:23 +0100 | [diff] [blame] | 183 | expandedActionValueMap); |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 184 | Iterable<TreeFileArtifact> treeFileArtifacts = |
| 185 | Iterables.transform( |
| 186 | Iterables.filter( |
| 187 | actionExecutionValue.getAllFileValues().keySet(), |
| 188 | new Predicate<Artifact>() { |
| 189 | @Override |
| 190 | public boolean apply(Artifact artifact) { |
| 191 | Preconditions.checkState( |
| 192 | artifact.hasParent(), |
janakr | cb314a2 | 2018-02-15 10:33:53 -0800 | [diff] [blame] | 193 | "No parent: %s %s %s %s %s", |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 194 | artifact, |
| 195 | treeArtifact, |
| 196 | actionExecutionValue, |
janakr | cb314a2 | 2018-02-15 10:33:53 -0800 | [diff] [blame] | 197 | actionLookupKey, |
| 198 | actionIndex); |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 199 | return artifact.getParent().equals(treeArtifact); |
| 200 | } |
| 201 | }), |
| 202 | new Function<Artifact, TreeFileArtifact>() { |
| 203 | @Override |
| 204 | public TreeFileArtifact apply(Artifact artifact) { |
| 205 | return (TreeFileArtifact) artifact; |
| 206 | } |
| 207 | }); |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 208 | |
| 209 | Preconditions.checkState( |
| 210 | !Iterables.isEmpty(treeFileArtifacts), |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 211 | "Action denoted by %s does not output TreeFileArtifact under %s", |
| 212 | expandedActionExecutionKeys.get(i), |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 213 | treeArtifact); |
| 214 | |
| 215 | for (TreeFileArtifact treeFileArtifact : treeFileArtifacts) { |
Janak Ramakrishnan | 59fec4e | 2017-03-20 17:51:39 +0000 | [diff] [blame] | 216 | FileArtifactValue value = |
| 217 | createSimpleFileArtifactValue(treeFileArtifact, actionExecutionValue); |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 218 | map.put(treeFileArtifact, value); |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | // Return the aggregated TreeArtifactValue. |
| 223 | return TreeArtifactValue.create(map.build()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 224 | } |
| 225 | |
Janak Ramakrishnan | ad77f97 | 2016-07-29 20:58:42 +0000 | [diff] [blame] | 226 | private FileArtifactValue createSourceValue(Artifact artifact, boolean mandatory, Environment env) |
Janak Ramakrishnan | 3c0adb2 | 2016-08-15 21:54:55 +0000 | [diff] [blame] | 227 | throws MissingInputFileException, InterruptedException { |
tomlu | ee6a686 | 2018-01-17 14:36:26 -0800 | [diff] [blame] | 228 | SkyKey fileSkyKey = |
| 229 | FileValue.key(RootedPath.toRootedPath(artifact.getRoot().getRoot(), artifact.getPath())); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 230 | FileValue fileValue; |
| 231 | try { |
ulfjack | e479453 | 2018-01-12 02:11:17 -0800 | [diff] [blame] | 232 | fileValue = (FileValue) env.getValueOrThrow(fileSkyKey, IOException.class); |
| 233 | } catch (IOException e) { |
ulfjack | ef5c35b | 2017-07-25 15:17:49 +0200 | [diff] [blame] | 234 | throw makeMissingInputFileException(artifact, mandatory, e, env.getListener()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 235 | } |
| 236 | if (fileValue == null) { |
| 237 | return null; |
| 238 | } |
| 239 | if (!fileValue.exists()) { |
Googler | 17810ad | 2017-11-29 10:54:23 -0800 | [diff] [blame] | 240 | if (!mandatory) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 241 | return FileArtifactValue.MISSING_FILE_MARKER; |
| 242 | } else { |
ulfjack | ef5c35b | 2017-07-25 15:17:49 +0200 | [diff] [blame] | 243 | throw makeMissingInputFileException(artifact, mandatory, null, env.getListener()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 244 | } |
| 245 | } |
| 246 | try { |
| 247 | return FileArtifactValue.create(artifact, fileValue); |
| 248 | } catch (IOException e) { |
ulfjack | ef5c35b | 2017-07-25 15:17:49 +0200 | [diff] [blame] | 249 | throw makeMissingInputFileException(artifact, mandatory, e, env.getListener()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 250 | } |
| 251 | } |
| 252 | |
ulfjack | ef5c35b | 2017-07-25 15:17:49 +0200 | [diff] [blame] | 253 | private static MissingInputFileException makeMissingInputFileException( |
| 254 | Artifact artifact, boolean mandatory, Exception failure, EventHandler reporter) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 255 | String extraMsg = (failure == null) ? "" : (":" + failure.getMessage()); |
buchgr | d4d3d50 | 2018-08-02 06:47:19 -0700 | [diff] [blame] | 256 | MissingInputFileException ex = |
| 257 | new MissingInputFileException(constructErrorMessage(artifact) + extraMsg, null); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 258 | if (mandatory) { |
| 259 | reporter.handle(Event.error(ex.getLocation(), ex.getMessage())); |
| 260 | } |
| 261 | return ex; |
| 262 | } |
| 263 | |
| 264 | // Non-aggregating artifact -- should contain at most one piece of artifact data. |
| 265 | // data may be null if and only if artifact is a middleman artifact. |
Janak Ramakrishnan | 59fec4e | 2017-03-20 17:51:39 +0000 | [diff] [blame] | 266 | private static FileArtifactValue createSimpleFileArtifactValue( |
ulfjack | ef5c35b | 2017-07-25 15:17:49 +0200 | [diff] [blame] | 267 | Artifact artifact, ActionExecutionValue actionValue) { |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 268 | FileArtifactValue value = actionValue.getArtifactValue(artifact); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 269 | if (value != null) { |
| 270 | return value; |
| 271 | } |
| 272 | // Middleman artifacts have no corresponding files, so their ArtifactValues should have already |
| 273 | // been constructed during execution of the action. |
| 274 | Preconditions.checkState(!artifact.isMiddlemanArtifact(), artifact); |
janakr | 0c42fc8 | 2018-09-14 10:37:25 -0700 | [diff] [blame] | 275 | ArtifactFileMetadata data = |
buchgr | d4d3d50 | 2018-08-02 06:47:19 -0700 | [diff] [blame] | 276 | Preconditions.checkNotNull(actionValue.getData(artifact), "%s %s", artifact, actionValue); |
| 277 | Preconditions.checkNotNull( |
| 278 | data.getDigest(), "Digest should already have been calculated for %s (%s)", artifact, data); |
Janak Ramakrishnan | 59fec4e | 2017-03-20 17:51:39 +0000 | [diff] [blame] | 279 | // Directories are special-cased because their mtimes are used, so should have been constructed |
| 280 | // during execution of the action (in ActionMetadataHandler#maybeStoreAdditionalData). |
| 281 | Preconditions.checkState(data.isFile(), "Unexpected not file %s (%s)", artifact, data); |
ulfjack | 8896d2e | 2018-01-19 02:55:21 -0800 | [diff] [blame] | 282 | return FileArtifactValue.createNormalFile(data); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 283 | } |
| 284 | |
shahan | 7bcb8ed | 2018-06-27 16:25:59 -0700 | [diff] [blame] | 285 | @Nullable |
Janak Ramakrishnan | ad77f97 | 2016-07-29 20:58:42 +0000 | [diff] [blame] | 286 | private static AggregatingArtifactValue createAggregatingValue( |
| 287 | Artifact artifact, |
| 288 | ActionAnalysisMetadata action, |
| 289 | FileArtifactValue value, |
Janak Ramakrishnan | 3c0adb2 | 2016-08-15 21:54:55 +0000 | [diff] [blame] | 290 | SkyFunction.Environment env) |
| 291 | throws InterruptedException { |
buchgr | d4d3d50 | 2018-08-02 06:47:19 -0700 | [diff] [blame] | 292 | ImmutableList.Builder<Pair<Artifact, FileArtifactValue>> fileInputsBuilder = |
| 293 | ImmutableList.builder(); |
| 294 | ImmutableList.Builder<Pair<Artifact, TreeArtifactValue>> directoryInputsBuilder = |
| 295 | ImmutableList.builder(); |
janakr | bf4123d | 2018-07-24 11:38:19 -0700 | [diff] [blame] | 296 | for (Map.Entry<SkyKey, SkyValue> entry : env.getValues(action.getInputs()).entrySet()) { |
Janak Ramakrishnan | ad77f97 | 2016-07-29 20:58:42 +0000 | [diff] [blame] | 297 | Artifact input = ArtifactSkyKey.artifact(entry.getKey()); |
| 298 | SkyValue inputValue = entry.getValue(); |
shahan | 7bcb8ed | 2018-06-27 16:25:59 -0700 | [diff] [blame] | 299 | if (inputValue == null) { |
| 300 | return null; |
| 301 | } |
Benjamin Peterson | 63748e4 | 2018-06-03 22:11:16 -0700 | [diff] [blame] | 302 | if (inputValue instanceof FileArtifactValue) { |
buchgr | d4d3d50 | 2018-08-02 06:47:19 -0700 | [diff] [blame] | 303 | fileInputsBuilder.add(Pair.of(input, (FileArtifactValue) inputValue)); |
Benjamin Peterson | 63748e4 | 2018-06-03 22:11:16 -0700 | [diff] [blame] | 304 | } else if (inputValue instanceof TreeArtifactValue) { |
buchgr | d4d3d50 | 2018-08-02 06:47:19 -0700 | [diff] [blame] | 305 | directoryInputsBuilder.add(Pair.of(input, (TreeArtifactValue) inputValue)); |
Benjamin Peterson | 63748e4 | 2018-06-03 22:11:16 -0700 | [diff] [blame] | 306 | } else { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 307 | // We do not recurse in aggregating middleman artifacts. |
buchgr | d4d3d50 | 2018-08-02 06:47:19 -0700 | [diff] [blame] | 308 | Preconditions.checkState( |
| 309 | !(inputValue instanceof AggregatingArtifactValue), |
| 310 | "%s %s %s", |
| 311 | artifact, |
| 312 | action, |
| 313 | inputValue); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 314 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 315 | } |
buchgr | d4d3d50 | 2018-08-02 06:47:19 -0700 | [diff] [blame] | 316 | |
| 317 | ImmutableList<Pair<Artifact, FileArtifactValue>> fileInputs = |
| 318 | ImmutableList.sortedCopyOf( |
| 319 | Comparator.comparing(pair -> pair.getFirst().getExecPathString()), |
| 320 | fileInputsBuilder.build()); |
| 321 | ImmutableList<Pair<Artifact, TreeArtifactValue>> directoryInputs = |
| 322 | ImmutableList.sortedCopyOf( |
| 323 | Comparator.comparing(pair -> pair.getFirst().getExecPathString()), |
| 324 | directoryInputsBuilder.build()); |
| 325 | |
Benjamin Peterson | c868c47 | 2018-05-28 08:37:15 -0700 | [diff] [blame] | 326 | return (action.getActionType() == MiddlemanType.AGGREGATING_MIDDLEMAN) |
buchgr | d4d3d50 | 2018-08-02 06:47:19 -0700 | [diff] [blame] | 327 | ? new AggregatingArtifactValue(fileInputs, directoryInputs, value) |
| 328 | : new RunfilesArtifactValue(fileInputs, directoryInputs, value); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 329 | } |
| 330 | |
| 331 | /** |
| 332 | * Returns whether this value needs to contain the data of all its inputs. Currently only tests to |
Benjamin Peterson | c868c47 | 2018-05-28 08:37:15 -0700 | [diff] [blame] | 333 | * see if the action is an aggregating or runfiles middleman action. However, may include Fileset |
| 334 | * artifacts in the future. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 335 | */ |
Rumou Duan | 33bab46 | 2016-04-25 17:55:12 +0000 | [diff] [blame] | 336 | private static boolean isAggregatingValue(ActionAnalysisMetadata action) { |
Benjamin Peterson | c868c47 | 2018-05-28 08:37:15 -0700 | [diff] [blame] | 337 | switch (action.getActionType()) { |
| 338 | case AGGREGATING_MIDDLEMAN: |
| 339 | case RUNFILES_MIDDLEMAN: |
| 340 | return true; |
| 341 | default: |
| 342 | return false; |
| 343 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 344 | } |
| 345 | |
| 346 | @Override |
| 347 | public String extractTag(SkyKey skyKey) { |
janakr | bf4123d | 2018-07-24 11:38:19 -0700 | [diff] [blame] | 348 | return Label.print(ArtifactSkyKey.artifact(skyKey).getOwner()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 349 | } |
| 350 | |
janakr | baf52ae | 2018-02-14 09:03:18 -0800 | [diff] [blame] | 351 | static ActionLookupKey getActionLookupKey(Artifact artifact) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 352 | ArtifactOwner artifactOwner = artifact.getArtifactOwner(); |
| 353 | |
| 354 | Preconditions.checkState(artifactOwner instanceof ActionLookupKey, "", artifact, artifactOwner); |
janakr | 573807d | 2018-01-11 14:02:35 -0800 | [diff] [blame] | 355 | return (ActionLookupKey) artifactOwner; |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 356 | } |
| 357 | |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 358 | @Nullable |
janakr | b9d8d58 | 2018-06-13 21:57:19 -0700 | [diff] [blame] | 359 | static ActionLookupValue getActionLookupValue( |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 360 | SkyKey actionLookupKey, SkyFunction.Environment env, Artifact artifact) |
| 361 | throws InterruptedException { |
| 362 | ActionLookupValue value = (ActionLookupValue) env.getValue(actionLookupKey); |
| 363 | if (value == null) { |
| 364 | ArtifactOwner artifactOwner = artifact.getArtifactOwner(); |
| 365 | Preconditions.checkState( |
janakr | 573807d | 2018-01-11 14:02:35 -0800 | [diff] [blame] | 366 | artifactOwner == CoverageReportValue.COVERAGE_REPORT_KEY, |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 367 | "Not-yet-present artifact owner: %s (%s %s)", |
| 368 | artifactOwner, |
| 369 | artifact, |
| 370 | actionLookupKey); |
| 371 | return null; |
Rumou Duan | 7387620 | 2016-06-06 18:52:08 +0000 | [diff] [blame] | 372 | } |
janakr | 93e3eea | 2017-03-30 22:09:37 +0000 | [diff] [blame] | 373 | return value; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 374 | } |
| 375 | |
| 376 | private static final class ArtifactFunctionException extends SkyFunctionException { |
| 377 | ArtifactFunctionException(MissingInputFileException e, Transience transience) { |
| 378 | super(e, transience); |
| 379 | } |
| 380 | |
Rumou Duan | 3ddb4c9 | 2016-06-13 20:10:48 +0000 | [diff] [blame] | 381 | ArtifactFunctionException(IOException e, Transience transience) { |
| 382 | super(e, transience); |
| 383 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 384 | } |
| 385 | |
| 386 | private static String constructErrorMessage(Artifact artifact) { |
| 387 | if (artifact.getOwner() == null) { |
| 388 | return String.format("missing input file '%s'", artifact.getPath().getPathString()); |
| 389 | } else { |
| 390 | return String.format("missing input file '%s'", artifact.getOwner()); |
| 391 | } |
| 392 | } |
| 393 | } |