org.gradle.internal.resolve.caching.CrossBuildCachingRuleExecutor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
Gradle 6.9.1 API redistribution.
/*
* Copyright 2018 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.internal.resolve.caching;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import org.gradle.api.Action;
import org.gradle.api.Transformer;
import org.gradle.api.internal.artifacts.configurations.dynamicversion.CachePolicy;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.cache.FileLockManager;
import org.gradle.cache.PersistentCache;
import org.gradle.cache.PersistentIndexedCache;
import org.gradle.cache.PersistentIndexedCacheParameters;
import org.gradle.cache.internal.InMemoryCacheDecoratorFactory;
import org.gradle.cache.internal.filelock.LockOptionsBuilder;
import org.gradle.cache.scopes.GlobalScopedCache;
import org.gradle.internal.Cast;
import org.gradle.internal.action.ConfigurableRule;
import org.gradle.internal.action.ConfigurableRules;
import org.gradle.internal.action.InstantiatingAction;
import org.gradle.internal.hash.HashCode;
import org.gradle.internal.hash.Hasher;
import org.gradle.internal.hash.Hashing;
import org.gradle.internal.isolation.Isolatable;
import org.gradle.internal.reflect.Instantiator;
import org.gradle.internal.serialize.AbstractSerializer;
import org.gradle.internal.serialize.BaseSerializerFactory;
import org.gradle.internal.serialize.Decoder;
import org.gradle.internal.serialize.Encoder;
import org.gradle.internal.serialize.HashCodeSerializer;
import org.gradle.internal.serialize.Serializer;
import org.gradle.internal.snapshot.ValueSnapshotter;
import org.gradle.util.internal.BuildCommencedTimeProvider;
import javax.annotation.Nullable;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class CrossBuildCachingRuleExecutor implements CachingRuleExecutor, Closeable {
private final static Logger LOGGER = Logging.getLogger(CrossBuildCachingRuleExecutor.class);
private final ValueSnapshotter snapshotter;
private final Transformer, KEY> keyToSnapshottable;
private final PersistentCache cache;
private final PersistentIndexedCache> store;
private final BuildCommencedTimeProvider timeProvider;
private final EntryValidator validator;
public CrossBuildCachingRuleExecutor(String name,
GlobalScopedCache cacheRepository,
InMemoryCacheDecoratorFactory cacheDecoratorFactory,
ValueSnapshotter snapshotter,
BuildCommencedTimeProvider timeProvider,
EntryValidator validator,
Transformer, KEY> keyToSnapshottable,
Serializer resultSerializer) {
this.snapshotter = snapshotter;
this.validator = validator;
this.keyToSnapshottable = keyToSnapshottable;
this.timeProvider = timeProvider;
this.cache = cacheRepository
.cache(name)
.withLockOptions(LockOptionsBuilder.mode(FileLockManager.LockMode.OnDemand))
.open();
PersistentIndexedCacheParameters> cacheParams = createCacheConfiguration(name, resultSerializer, cacheDecoratorFactory);
this.store = this.cache.createCache(cacheParams);
}
private PersistentIndexedCacheParameters> createCacheConfiguration(String name, Serializer resultSerializer, InMemoryCacheDecoratorFactory cacheDecoratorFactory) {
return PersistentIndexedCacheParameters.of(
name,
new HashCodeSerializer(),
createEntrySerializer(resultSerializer)
).withCacheDecorator(
cacheDecoratorFactory.decorator(2000, true)
);
}
private Serializer> createEntrySerializer(final Serializer resultSerializer) {
return new CacheEntrySerializer<>(resultSerializer);
}
@Override
public RESULT execute(final KEY key, final InstantiatingAction action, final Transformer detailsToResult, final Transformer onCacheMiss, final CachePolicy cachePolicy) {
if (action == null) {
return null;
}
final ConfigurableRules rules = action.getRules();
if (rules.isCacheable()) {
return tryFromCache(key, action, detailsToResult, onCacheMiss, cachePolicy, rules);
} else {
return executeRule(key, action, detailsToResult, onCacheMiss);
}
}
private RESULT tryFromCache(KEY key, InstantiatingAction action, Transformer detailsToResult, Transformer onCacheMiss, CachePolicy cachePolicy, ConfigurableRules rules) {
final HashCode keyHash = computeExplicitInputsSnapshot(key, rules);
DefaultImplicitInputRegistrar registrar = new DefaultImplicitInputRegistrar();
ImplicitInputsCapturingInstantiator instantiator = findInputCapturingInstantiator(action);
if (instantiator != null) {
action = action.withInstantiator(instantiator.capturing(registrar));
}
// First step is to find an entry with the explicit inputs in the cache
CachedEntry entry = store.getIfPresent(keyHash);
if (entry != null) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Found result for rule {} and key {} in cache", rules, key);
}
if (validator.isValid(cachePolicy, entry) && areImplicitInputsUpToDate(instantiator, key, rules, entry)) {
// Here it means that we have validated that the entry is still up-to-date, and that means a couple of things:
// 1. the cache policy said that the entry is still valid (for example, `--refresh-dependencies` wasn't called)
// 2. if the rule is cacheable, we have validated that its discovered inputs are still the same
return entry.getResult();
} else if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Invalidating result for rule {} and key {} in cache", rules, key);
}
}
RESULT result = executeRule(key, action, detailsToResult, onCacheMiss);
store.put(keyHash, new CachedEntry<>(timeProvider.getCurrentTime(), registrar.implicits, result));
return result;
}
/**
* This method computes a snapshot of the explicit inputs of the rule, which consist of the rule implementation,
* the rule key (for example, a module identifier) and the optional rule parameters.
* @param key the primary key
* @param rules the rules to be snapshotted
* @return a snapshot of the inputs
*/
private HashCode computeExplicitInputsSnapshot(KEY key, ConfigurableRules rules) {
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy