/*
* Copyright 2011 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.service.scopes;
import com.google.common.collect.ImmutableList;
import org.gradle.BuildAdapter;
import org.gradle.BuildResult;
import org.gradle.StartParameter;
import org.gradle.api.execution.TaskActionListener;
import org.gradle.api.execution.internal.TaskInputsListener;
import org.gradle.api.internal.GradleInternal;
import org.gradle.api.internal.cache.StringInterner;
import org.gradle.api.internal.changedetection.TaskArtifactStateRepository;
import org.gradle.api.internal.changedetection.changes.DefaultTaskArtifactStateRepository;
import org.gradle.api.internal.changedetection.changes.ShortCircuitTaskArtifactStateRepository;
import org.gradle.api.internal.changedetection.state.CacheBackedFileSnapshotRepository;
import org.gradle.api.internal.changedetection.state.CacheBackedTaskHistoryRepository;
import org.gradle.api.internal.changedetection.state.DefaultFileCollectionSnapshotterRegistry;
import org.gradle.api.internal.changedetection.state.DefaultTaskHistoryStore;
import org.gradle.api.internal.changedetection.state.FileCollectionSnapshot;
import org.gradle.api.internal.changedetection.state.FileCollectionSnapshotter;
import org.gradle.api.internal.changedetection.state.FileCollectionSnapshotterRegistry;
import org.gradle.api.internal.changedetection.state.GenericFileCollectionSnapshotter;
import org.gradle.api.internal.changedetection.state.InMemoryCacheDecoratorFactory;
import org.gradle.api.internal.changedetection.state.OutputFilesSnapshotter;
import org.gradle.api.internal.changedetection.state.TaskHistoryRepository;
import org.gradle.api.internal.changedetection.state.TaskHistoryStore;
import org.gradle.api.internal.changedetection.state.ValueSnapshotter;
import org.gradle.api.internal.file.FileCollectionFactory;
import org.gradle.api.internal.project.taskfactory.FileSnapshottingPropertyAnnotationHandler;
import org.gradle.api.internal.tasks.TaskExecuter;
import org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter;
import org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter;
import org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter;
import org.gradle.api.internal.tasks.execution.ResolveBuildCacheKeyExecuter;
import org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter;
import org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter;
import org.gradle.api.internal.tasks.execution.SkipCachedTaskExecuter;
import org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter;
import org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter;
import org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter;
import org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter;
import org.gradle.api.internal.tasks.execution.TaskOutputsGenerationListener;
import org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter;
import org.gradle.api.internal.tasks.execution.VerifyNoInputChangesTaskExecuter;
import org.gradle.api.invocation.Gradle;
import org.gradle.cache.CacheRepository;
import org.gradle.caching.BuildCacheService;
import org.gradle.caching.internal.BuildCacheServiceProvider;
import org.gradle.caching.internal.tasks.GZipTaskOutputPacker;
import org.gradle.caching.internal.tasks.TarTaskOutputPacker;
import org.gradle.caching.internal.tasks.TaskCacheKeyCalculator;
import org.gradle.caching.internal.tasks.TaskOutputPacker;
import org.gradle.caching.internal.tasks.origin.TaskOutputOriginFactory;
import org.gradle.execution.taskgraph.TaskPlanExecutor;
import org.gradle.execution.taskgraph.TaskPlanExecutorFactory;
import org.gradle.internal.SystemProperties;
import org.gradle.internal.classloader.ClassLoaderHierarchyHasher;
import org.gradle.internal.concurrent.CompositeStoppable;
import org.gradle.internal.concurrent.ExecutorFactory;
import org.gradle.internal.environment.GradleBuildEnvironment;
import org.gradle.internal.event.ListenerManager;
import org.gradle.internal.id.RandomLongIdGenerator;
import org.gradle.internal.nativeplatform.filesystem.FileSystem;
import org.gradle.internal.operations.BuildOperationExecutor;
import org.gradle.internal.os.OperatingSystem;
import org.gradle.internal.reflect.Instantiator;
import org.gradle.internal.remote.internal.inet.InetAddressFactory;
import org.gradle.internal.scopeids.id.BuildScopeId;
import org.gradle.internal.serialize.DefaultSerializerRegistry;
import org.gradle.internal.serialize.SerializerRegistry;
import org.gradle.internal.service.ServiceRegistry;
import org.gradle.internal.time.TimeProvider;
import org.gradle.internal.work.AsyncWorkTracker;
import org.gradle.internal.work.WorkerLeaseService;
import org.gradle.util.GradleVersion;
import java.io.File;
import java.util.List;
public class TaskExecutionServices {
TaskExecuter createTaskExecuter(TaskArtifactStateRepository repository,
TaskOutputPacker packer,
BuildCacheService buildCacheService,
StartParameter startParameter,
ListenerManager listenerManager,
TaskInputsListener inputsListener,
TaskOutputOriginFactory taskOutputOriginFactory,
BuildOperationExecutor buildOperationExecutor,
AsyncWorkTracker asyncWorkTracker) {
boolean taskOutputCacheEnabled = startParameter.isBuildCacheEnabled();
TaskOutputsGenerationListener taskOutputsGenerationListener = listenerManager.getBroadcaster(TaskOutputsGenerationListener.class);
TaskExecuter executer = new ExecuteActionsTaskExecuter(
taskOutputsGenerationListener,
listenerManager.getBroadcaster(TaskActionListener.class),
buildOperationExecutor,
asyncWorkTracker
);
boolean verifyInputsEnabled = Boolean.getBoolean("org.gradle.tasks.verifyinputs");
if (verifyInputsEnabled) {
executer = new VerifyNoInputChangesTaskExecuter(repository, executer);
}
if (taskOutputCacheEnabled) {
executer = new SkipCachedTaskExecuter(
taskOutputOriginFactory,
buildCacheService,
packer,
taskOutputsGenerationListener,
executer
);
}
executer = new SkipUpToDateTaskExecuter(executer);
executer = new ResolveTaskOutputCachingStateExecuter(taskOutputCacheEnabled, executer);
if (verifyInputsEnabled || taskOutputCacheEnabled) {
executer = new ResolveBuildCacheKeyExecuter(executer, buildOperationExecutor);
}
executer = new ValidatingTaskExecuter(executer);
executer = new SkipEmptySourceFilesTaskExecuter(inputsListener, executer);
executer = new ResolveTaskArtifactStateTaskExecuter(repository, executer);
executer = new SkipTaskWithNoActionsExecuter(executer);
executer = new SkipOnlyIfTaskExecuter(executer);
executer = new ExecuteAtMostOnceTaskExecuter(executer);
executer = new CatchExceptionTaskExecuter(executer);
return executer;
}
TaskHistoryStore createCacheAccess(Gradle gradle, CacheRepository cacheRepository, InMemoryCacheDecoratorFactory inMemoryCacheDecoratorFactory, GradleBuildEnvironment environment) {
return new DefaultTaskHistoryStore(gradle, cacheRepository, inMemoryCacheDecoratorFactory);
}
FileCollectionSnapshotterRegistry createFileCollectionSnapshotterRegistry(ServiceRegistry serviceRegistry) {
List<FileSnapshottingPropertyAnnotationHandler> handlers = serviceRegistry.getAll(FileSnapshottingPropertyAnnotationHandler.class);
ImmutableList.Builder<FileCollectionSnapshotter> snapshotters = ImmutableList.builder();
snapshotters.add(serviceRegistry.get(GenericFileCollectionSnapshotter.class));
for (FileSnapshottingPropertyAnnotationHandler handler : handlers) {
snapshotters.add(serviceRegistry.get(handler.getSnapshotterType()));
}
return new DefaultFileCollectionSnapshotterRegistry(snapshotters.build());
}
TaskArtifactStateRepository createTaskArtifactStateRepository(Instantiator instantiator, TaskHistoryStore cacheAccess, StartParameter startParameter, StringInterner stringInterner, FileCollectionFactory fileCollectionFactory, ClassLoaderHierarchyHasher classLoaderHierarchyHasher, FileCollectionSnapshotterRegistry fileCollectionSnapshotterRegistry, TaskCacheKeyCalculator cacheKeyCalculator, ValueSnapshotter valueSnapshotter, BuildScopeId buildScopeId) {
OutputFilesSnapshotter outputFilesSnapshotter = new OutputFilesSnapshotter();
SerializerRegistry serializerRegistry = new DefaultSerializerRegistry();
for (FileCollectionSnapshotter snapshotter : fileCollectionSnapshotterRegistry.getAllSnapshotters()) {
snapshotter.registerSerializers(serializerRegistry);
}
TaskHistoryRepository taskHistoryRepository = new CacheBackedTaskHistoryRepository(
cacheAccess,
new CacheBackedFileSnapshotRepository(cacheAccess,
serializerRegistry.build(FileCollectionSnapshot.class),
new RandomLongIdGenerator()
),
stringInterner,
buildScopeId
);
return new ShortCircuitTaskArtifactStateRepository(
startParameter,
instantiator,
new DefaultTaskArtifactStateRepository(
taskHistoryRepository,
instantiator,
outputFilesSnapshotter,
fileCollectionSnapshotterRegistry,
fileCollectionFactory,
classLoaderHierarchyHasher,
cacheKeyCalculator,
valueSnapshotter
)
);
}
TaskCacheKeyCalculator createTaskCacheKeyCalculator() {
return new TaskCacheKeyCalculator();
}
TaskPlanExecutor createTaskExecutorFactory(StartParameter startParameter, ExecutorFactory executorFactory, WorkerLeaseService workerLeaseService) {
int parallelThreads = startParameter.getMaxWorkerCount();
return new TaskPlanExecutorFactory(parallelThreads, executorFactory, workerLeaseService).create();
}
TaskOutputPacker createTaskResultPacker(FileSystem fileSystem) {
return new GZipTaskOutputPacker(
new TarTaskOutputPacker(fileSystem)
);
}
TaskOutputOriginFactory createTaskOutputOriginFactory(TimeProvider timeProvider, InetAddressFactory inetAddressFactory, GradleInternal gradleInternal, BuildScopeId buildScopeId) {
File rootDir = gradleInternal.getRootProject().getRootDir();
return new TaskOutputOriginFactory(timeProvider, inetAddressFactory, rootDir, SystemProperties.getInstance().getUserName(), OperatingSystem.current().getName(), GradleVersion.current(), buildScopeId);
}
BuildCacheService createBuildCacheService(BuildCacheServiceProvider provider, GradleInternal gradle, ListenerManager listenerManager) {
final BuildCacheService buildCacheService = provider.createBuildCacheService(gradle.getIdentityPath());
// Stop the build cache at the end of the build vs waiting for the service registry to shut it down.
listenerManager.addListener(new BuildAdapter() {
@Override
public void buildFinished(BuildResult result) {
CompositeStoppable.stoppable(buildCacheService).stop();
}
});
return buildCacheService;
}
}