All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gradle.api.internal.tasks.SnapshotTaskInputsBuildOperationResult Maven / Gradle / Ivy

There is a newer version: 8.6
Show newest version
/*
 * Copyright 2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.gradle.api.internal.tasks;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.gradle.api.NonNullApi;
import org.gradle.caching.BuildCacheKey;
import org.gradle.internal.execution.caching.CachingInputs;
import org.gradle.internal.execution.caching.CachingState;
import org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep;
import org.gradle.internal.fingerprint.CurrentFileCollectionFingerprint;
import org.gradle.internal.fingerprint.FileSystemLocationFingerprint;
import org.gradle.internal.hash.HashCode;
import org.gradle.internal.operations.trace.CustomOperationTraceSerialization;
import org.gradle.internal.snapshot.CompleteDirectorySnapshot;
import org.gradle.internal.snapshot.CompleteFileSystemLocationSnapshot;
import org.gradle.internal.snapshot.FileSystemSnapshotVisitor;
import org.gradle.internal.snapshot.impl.ImplementationSnapshot;

import javax.annotation.Nullable;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Consumer;

/**
 * This operation represents the work of analyzing the task's inputs plus the calculating the cache key.
 *
 * 

* These two operations should be captured separately, but for historical reasons we don't yet do that. * To reproduce this composite operation we capture across executors by starting an operation * in {@link StartSnapshotTaskInputsBuildOperationTaskExecuter} and finished in {@link MarkSnapshottingInputsFinishedStep}. *

*/ public class SnapshotTaskInputsBuildOperationResult implements SnapshotTaskInputsBuildOperationType.Result, CustomOperationTraceSerialization { @VisibleForTesting final CachingState cachingState; public SnapshotTaskInputsBuildOperationResult(CachingState cachingState) { this.cachingState = cachingState; } @Override public Map getInputValueHashesBytes() { return cachingState.getInputs() .map(new java.util.function.Function>() { @Nullable @Override public Map apply(CachingInputs cachingInputs) { ImmutableSortedMap inputValueFingerprints = cachingInputs.getInputValueFingerprints(); if (inputValueFingerprints.isEmpty()) { return null; } return Maps.transformValues(inputValueFingerprints, new Function() { @Override public byte[] apply(HashCode input) { return input.toByteArray(); } }); } }) .orElse(null); } @NonNullApi private static class State implements VisitState, FileSystemSnapshotVisitor { final InputFilePropertyVisitor visitor; Map fingerprints; String propertyName; HashCode propertyHash; String propertyNormalizationStrategyIdentifier; String name; String path; HashCode hash; int depth; public State(InputFilePropertyVisitor visitor) { this.visitor = visitor; } @Override public String getPropertyName() { return propertyName; } @Override public byte[] getPropertyHashBytes() { return propertyHash.toByteArray(); } @Override public String getPropertyNormalizationStrategyName() { return propertyNormalizationStrategyIdentifier; } @Override public String getName() { return name; } @Override public String getPath() { return path; } @Override public byte[] getHashBytes() { return hash.toByteArray(); } @Override public boolean preVisitDirectory(CompleteDirectorySnapshot physicalSnapshot) { this.path = physicalSnapshot.getAbsolutePath(); this.name = physicalSnapshot.getName(); this.hash = null; if (depth++ == 0) { visitor.preRoot(this); } visitor.preDirectory(this); return true; } @Override public void visitFile(CompleteFileSystemLocationSnapshot snapshot) { this.path = snapshot.getAbsolutePath(); this.name = snapshot.getName(); FileSystemLocationFingerprint fingerprint = fingerprints.get(path); if (fingerprint == null) { return; } this.hash = fingerprint.getNormalizedContentHash(); boolean isRoot = depth == 0; if (isRoot) { visitor.preRoot(this); } visitor.file(this); if (isRoot) { visitor.postRoot(); } } @Override public void postVisitDirectory(CompleteDirectorySnapshot directorySnapshot) { visitor.postDirectory(); if (--depth == 0) { visitor.postRoot(); } } } @Override public void visitInputFileProperties(final InputFilePropertyVisitor visitor) { cachingState.getInputs().ifPresent(new Consumer() { @Override public void accept(CachingInputs inputs) { State state = new State(visitor); for (Map.Entry entry : inputs.getInputFileFingerprints().entrySet()) { CurrentFileCollectionFingerprint fingerprint = entry.getValue(); state.propertyName = entry.getKey(); state.propertyHash = fingerprint.getHash(); state.propertyNormalizationStrategyIdentifier = fingerprint.getStrategyIdentifier(); state.fingerprints = fingerprint.getFingerprints(); visitor.preProperty(state); fingerprint.accept(state); visitor.postProperty(); } } }); } @Nullable @Override public Set getInputPropertiesLoadedByUnknownClassLoader() { return cachingState.getInputs() .map(new java.util.function.Function>() { @Nullable @Override public Set apply(CachingInputs inputs) { ImmutableSortedSet invalidInputProperties = inputs.getNonCacheableInputProperties(); if (invalidInputProperties.isEmpty()) { return null; } return invalidInputProperties; } }) .orElse(null); } @Override public byte[] getClassLoaderHashBytes() { return cachingState.getInputs() .map(new java.util.function.Function() { @Nullable @Override public byte[] apply(CachingInputs inputs) { ImplementationSnapshot implementation = inputs.getImplementation(); if (implementation.getClassLoaderHash() == null) { return null; } return implementation.getClassLoaderHash().toByteArray(); } }) .orElse(null); } @Override public List getActionClassLoaderHashesBytes() { return cachingState.getInputs() .map(new java.util.function.Function>() { @Nullable @Override public List apply(CachingInputs inputs) { List additionalImplementations = inputs.getAdditionalImplementations(); if (additionalImplementations.isEmpty()) { return null; } return Lists.transform(additionalImplementations, new Function() { @Override public byte[] apply(ImplementationSnapshot input) { return input.getClassLoaderHash() == null ? null : input.getClassLoaderHash().toByteArray(); } }); } }) .orElse(null); } @Nullable @Override public List getActionClassNames() { return cachingState.getInputs() .map(new java.util.function.Function>() { @Nullable @Override public List apply(CachingInputs inputs) { List additionalImplementations = inputs.getAdditionalImplementations(); if (additionalImplementations.isEmpty()) { return null; } return Lists.transform(additionalImplementations, new Function() { @Override public String apply(ImplementationSnapshot input) { return input.getTypeName(); } }); } }) .orElse(null); } @Nullable @Override public List getOutputPropertyNames() { return cachingState.getInputs() .map(new java.util.function.Function>() { @Nullable @Override public List apply(CachingInputs inputs) { ImmutableSortedSet outputPropertyNames = inputs.getOutputProperties(); if (outputPropertyNames.isEmpty()) { return null; } return outputPropertyNames.asList(); } }) .orElse(null); } @Override public byte[] getHashBytes() { return cachingState.getKey() .map(new java.util.function.Function() { @Override public byte[] apply(BuildCacheKey cacheKey) { return cacheKey.toByteArray(); } }) .orElse(null); } @Override public Object getCustomOperationTraceSerializableModel() { Map model = new TreeMap(); final Function bytesToString = new Function() { @Nullable @Override public String apply(@Nullable byte[] input) { if (input == null) { return null; } return HashCode.fromBytes(input).toString(); } }; List actionClassLoaderHashesBytes = getActionClassLoaderHashesBytes(); if (actionClassLoaderHashesBytes != null) { model.put("actionClassLoaderHashes", Lists.transform(getActionClassLoaderHashesBytes(), bytesToString)); } else { model.put("actionClassLoaderHashes", null); } model.put("actionClassNames", getActionClassNames()); byte[] hashBytes = getHashBytes(); if (hashBytes != null) { model.put("hash", HashCode.fromBytes(hashBytes).toString()); } else { model.put("hash", null); } byte[] classLoaderHashBytes = getClassLoaderHashBytes(); if (classLoaderHashBytes != null) { model.put("classLoaderHash", HashCode.fromBytes(classLoaderHashBytes).toString()); } else { model.put("classLoaderHash", null); } model.put("inputFileProperties", fileProperties()); model.put("inputPropertiesLoadedByUnknownClassLoader", getInputPropertiesLoadedByUnknownClassLoader()); Map inputValueHashesBytes = getInputValueHashesBytes(); if (inputValueHashesBytes != null) { model.put("inputValueHashes", Maps.transformEntries(inputValueHashesBytes, new Maps.EntryTransformer() { @Nullable @Override public String transformEntry(@Nullable String key, @Nullable byte[] value) { if (value == null) { return null; } return HashCode.fromBytes(value).toString(); } })); } else { model.put("inputValueHashes", null); } model.put("outputPropertyNames", getOutputPropertyNames()); return model; } protected Map fileProperties() { final Map fileProperties = new TreeMap(); visitInputFileProperties(new InputFilePropertyVisitor() { Property property; Deque dirStack = new ArrayDeque(); class Property { private final String hash; private final String normalization; private final List roots = new ArrayList(); public Property(String hash, String normalization) { this.hash = hash; this.normalization = normalization; } public String getHash() { return hash; } public String getNormalization() { return normalization; } public Collection getRoots() { return roots; } } abstract class Entry { private final String path; public Entry(String path) { this.path = path; } public String getPath() { return path; } } class FileEntry extends Entry { private final String hash; FileEntry(String path, String hash) { super(path); this.hash = hash; } public String getHash() { return hash; } } class DirEntry extends Entry { private final List children = new ArrayList(); DirEntry(String path) { super(path); } public Collection getChildren() { return children; } } @Override public void preProperty(VisitState state) { property = new Property(HashCode.fromBytes(state.getPropertyHashBytes()).toString(), state.getPropertyNormalizationStrategyName()); fileProperties.put(state.getPropertyName(), property); } @Override public void preRoot(VisitState state) { } @Override public void preDirectory(VisitState state) { boolean isRoot = dirStack.isEmpty(); DirEntry dir = new DirEntry(isRoot ? state.getPath() : state.getName()); if (isRoot) { property.roots.add(dir); } else { //noinspection ConstantConditions dirStack.peek().children.add(dir); } dirStack.push(dir); } @Override public void file(VisitState state) { boolean isRoot = dirStack.isEmpty(); FileEntry file = new FileEntry(isRoot ? state.getPath() : state.getName(), HashCode.fromBytes(state.getHashBytes()).toString()); if (isRoot) { property.roots.add(file); } else { //noinspection ConstantConditions dirStack.peek().children.add(file); } } @Override public void postDirectory() { dirStack.pop(); } @Override public void postRoot() { } @Override public void postProperty() { } }); return fileProperties; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy