Skip to content

Commit

Permalink
Merge branch 'release'
Browse files Browse the repository at this point in the history
  • Loading branch information
bot-teamcity committed Nov 24, 2023
2 parents f0e7f3f + ff7bf18 commit 93d70ab
Show file tree
Hide file tree
Showing 63 changed files with 4,485 additions and 1,519 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,8 @@ class ConfigurationCacheBuildOperationsIntegrationTest extends AbstractConfigura

def calculateGraphOp2 = calculateGraphOps[1]
assert calculateGraphOp2.parentId == calculateTreeGraphOp2.id

assert calculateGraphOp.result.requestedTaskPaths == calculateGraphOp2.result.requestedTaskPaths
}

private void hasCompositeBuildsWorkGraphPopulated() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package org.gradle.configurationcache

import org.gradle.execution.plan.Node
import org.gradle.execution.plan.ScheduledWork
import org.gradle.normalization.internal.InputNormalizationHandlerInternal
import org.gradle.util.Path
import java.io.File
Expand Down Expand Up @@ -91,7 +91,7 @@ class BuildWithWork(
val build: ConfigurationCacheBuild,
rootProjectName: String,
projects: List<CachedProjectState>,
val workGraph: List<Node>
val workGraph: ScheduledWork
) : BuildWithProjects(identityPath, rootProjectName, projects)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import org.gradle.api.internal.initialization.ClassLoaderScope
import org.gradle.api.internal.initialization.ScriptHandlerFactory
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.internal.project.ProjectStateRegistry
import org.gradle.execution.plan.Node
import org.gradle.execution.plan.ScheduledWork
import org.gradle.groovy.scripts.TextResourceScriptSource
import org.gradle.initialization.ClassLoaderScopeRegistry
import org.gradle.initialization.DefaultProjectDescriptor
Expand Down Expand Up @@ -79,11 +79,11 @@ class ConfigurationCacheHost internal constructor(
override val hasScheduledWork: Boolean
get() = gradle.taskGraph.size() > 0

override val scheduledWork: List<Node>
override val scheduledWork: ScheduledWork
get() {
lateinit var nodes: List<Node>
gradle.taskGraph.visitScheduledNodes { nodes = it }
return nodes
lateinit var work: ScheduledWork
gradle.taskGraph.visitScheduledNodes { nodes, entryNodes -> work = ScheduledWork(nodes, entryNodes) }
return work
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import org.gradle.configurationcache.serialization.writeEnum
import org.gradle.configurationcache.serialization.writeStrings
import org.gradle.configurationcache.services.ConfigurationCacheEnvironmentChangeTracker
import org.gradle.execution.plan.Node
import org.gradle.execution.plan.ScheduledWork
import org.gradle.initialization.BuildIdentifiedProgressDetails
import org.gradle.initialization.BuildStructureOperationProject
import org.gradle.initialization.GradlePropertiesController
Expand Down Expand Up @@ -213,7 +214,7 @@ class ConfigurationCacheState(
for (build in builds) {
if (build is BuildWithWork) {
builder.withWorkGraph(build.build.state) {
it.setScheduledNodes(build.workGraph)
it.setScheduledWork(build.workGraph)
}
}
}
Expand Down Expand Up @@ -422,15 +423,15 @@ class ConfigurationCacheState(
val state = build.state
if (state.projectsAvailable) {
writeBoolean(true)
val scheduledNodes = build.scheduledWork
val scheduledWork = build.scheduledWork
withDebugFrame({ "Gradle" }) {
writeGradleState(gradle)
val projects = collectProjects(state.projects, scheduledNodes, gradle.serviceOf())
val projects = collectProjects(state.projects, scheduledWork.scheduledNodes, gradle.serviceOf())
writeProjects(gradle, projects)
writeRequiredBuildServicesOf(state, buildTreeState)
}
withDebugFrame({ "Work Graph" }) {
writeWorkGraphOf(gradle, scheduledNodes)
writeWorkGraphOf(gradle, scheduledWork)
}
withDebugFrame({ "Flow Scope" }) {
writeFlowScopeOf(gradle)
Expand Down Expand Up @@ -467,9 +468,9 @@ class ConfigurationCacheState(
}

private
suspend fun DefaultWriteContext.writeWorkGraphOf(gradle: GradleInternal, scheduledNodes: List<Node>) {
suspend fun DefaultWriteContext.writeWorkGraphOf(gradle: GradleInternal, scheduledWork: ScheduledWork) {
workNodeCodec(gradle).run {
writeWork(scheduledNodes)
writeWork(scheduledWork)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import org.gradle.execution.taskgraph.TaskExecutionGraphInternal
import org.gradle.internal.build.ExecutionResult
import org.gradle.util.Path
import java.util.Objects
import java.util.function.Consumer
import java.util.function.BiConsumer


internal
Expand Down Expand Up @@ -202,7 +202,7 @@ class CrossProjectConfigurationReportingTaskExecutionGraph(
override fun execute(plan: FinalizedExecutionPlan?): ExecutionResult<Void>? =
delegate.execute(plan)

override fun visitScheduledNodes(visitor: Consumer<MutableList<Node>>?) =
override fun visitScheduledNodes(visitor: BiConsumer<List<Node>, Set<Node>>) =
delegate.visitScheduledNodes(visitor)

override fun size(): Int = delegate.size()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package org.gradle.configurationcache

import org.gradle.api.internal.GradleInternal
import org.gradle.execution.plan.Node
import org.gradle.execution.plan.ScheduledWork
import org.gradle.internal.build.BuildState


Expand All @@ -26,5 +26,5 @@ interface VintageGradleBuild {
val state: BuildState
val gradle: GradleInternal
val hasScheduledWork: Boolean
val scheduledWork: List<Node>
val scheduledWork: ScheduledWork
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.gradle.configurationcache.serialization.codecs

import com.google.common.collect.ImmutableSet
import org.gradle.api.internal.GradleInternal
import org.gradle.api.internal.artifacts.transform.DefaultTransformUpstreamDependenciesResolver
import org.gradle.api.internal.tasks.NodeExecutionContext
Expand All @@ -25,6 +26,7 @@ import org.gradle.configurationcache.serialization.WriteContext
import org.gradle.configurationcache.serialization.decodePreservingIdentity
import org.gradle.configurationcache.serialization.encodePreservingIdentityOf
import org.gradle.configurationcache.serialization.ownerService
import org.gradle.configurationcache.serialization.readCollection
import org.gradle.configurationcache.serialization.readCollectionInto
import org.gradle.configurationcache.serialization.readNonNull
import org.gradle.configurationcache.serialization.withGradleIsolate
Expand All @@ -37,6 +39,7 @@ import org.gradle.execution.plan.Node
import org.gradle.execution.plan.NodeGroup
import org.gradle.execution.plan.OrdinalGroup
import org.gradle.execution.plan.OrdinalGroupFactory
import org.gradle.execution.plan.ScheduledWork
import org.gradle.execution.plan.TaskNode


Expand All @@ -47,38 +50,53 @@ class WorkNodeCodec(
private val ordinalGroups: OrdinalGroupFactory
) {

suspend fun WriteContext.writeWork(nodes: List<Node>) {
suspend fun WriteContext.writeWork(work: ScheduledWork) {
// Share bean instances across all nodes (except tasks, which have their own isolate)
withGradleIsolate(owner, internalTypesCodec) {
writeNodes(nodes)
doWrite(work)
}
}

suspend fun ReadContext.readWork(): List<Node> =
suspend fun ReadContext.readWork(): ScheduledWork =
withGradleIsolate(owner, internalTypesCodec) {
readNodes()
doRead()
}

private
suspend fun WriteContext.writeNodes(nodes: List<Node>) {
suspend fun WriteContext.doWrite(work: ScheduledWork) {
val nodes = work.scheduledNodes
val nodeCount = nodes.size
writeSmallInt(nodeCount)
val scheduledNodeIds = HashMap<Node, Int>(nodeCount)
// Not all entry nodes are always scheduled.
// In particular, it happens when the entry node is a task of the included plugin build that runs as part of building the plugin.
// Such tasks do not rerun when configuration cache is re-used, even if specified on the command line.
// Not restoring them as entry points doesn't affect the resulting execution plan.
val scheduledEntryNodeIds = mutableListOf<Int>()
nodes.forEach { node ->
write(node)
scheduledNodeIds[node] = scheduledNodeIds.size
val nodeId = scheduledNodeIds.size
scheduledNodeIds[node] = nodeId
if (node in work.entryNodes) {
scheduledEntryNodeIds.add(nodeId)
}
if (node is LocalTaskNode) {
scheduledNodeIds[node.prepareNode] = scheduledNodeIds.size
}
}
// A large build may have many nodes but not so many entry nodes.
// To save some disk space, we're only saving entry node ids rather than writing "entry/non-entry" boolean for every node.
writeCollection(scheduledEntryNodeIds) {
writeSmallInt(it)
}
nodes.forEach { node ->
writeSuccessorReferencesOf(node, scheduledNodeIds)
writeNodeGroup(node.group, scheduledNodeIds)
}
}

private
suspend fun ReadContext.readNodes(): List<Node> {
suspend fun ReadContext.doRead(): ScheduledWork {
val nodeCount = readSmallInt()
val nodes = ArrayList<Node>(nodeCount)
val nodesById = HashMap<Int, Node>(nodeCount)
Expand All @@ -91,11 +109,16 @@ class WorkNodeCodec(
}
nodes.add(node)
}
// Note that using the ImmutableSet retains the original ordering of entry nodes.
val entryNodes = ImmutableSet.builder<Node>()
readCollection {
entryNodes.add(nodesById.getValue(readSmallInt()))
}
nodes.forEach { node ->
readSuccessorReferencesOf(node, nodesById)
node.group = readNodeGroup(nodesById)
}
return nodes
return ScheduledWork(nodes, entryNodes.build())
}

private
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public ExecutionResult<Void> execute(GradleInternal gradle, FinalizedExecutionPl

private void bindAllReferencesOfProject(FinalizedExecutionPlan plan) {
Set<Project> seen = Sets.newHashSet();
plan.getContents().getScheduledNodes().visitNodes(nodes -> {
plan.getContents().getScheduledNodes().visitNodes((nodes, entryNodes) -> {
for (Node node : nodes) {
if (node instanceof LocalTaskNode) {
ProjectInternal taskProject = node.getOwningProject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -104,13 +103,13 @@ public TaskNode getNode(Task task) {
}

@Override
public void setScheduledNodes(Collection<? extends Node> nodes) {
public void setScheduledWork(ScheduledWork work) {
if (scheduledNodes != null) {
throw new IllegalStateException("This execution plan already has nodes scheduled.");
}
entryNodes.addAll(nodes);
scheduledNodes = ImmutableList.copyOf(nodes);
nodeMapping.addAll(nodes);
scheduledNodes = work.getScheduledNodes();
entryNodes.addAll(work.getEntryNodes());
nodeMapping.addAll(scheduledNodes);
}

@Override
Expand All @@ -135,7 +134,7 @@ public void addEntryNodes(Collection<? extends Node> nodes) {
addEntryNodes(nodes, order++);
}

public void addEntryNodes(Collection<? extends Node> nodes, int ordinal) {
private void addEntryNodes(Collection<? extends Node> nodes, int ordinal) {
SortedSet<Node> sorted = new TreeSet<>(NodeComparator.INSTANCE);
sorted.addAll(nodes);
doAddEntryNodes(sorted, ordinal);
Expand Down Expand Up @@ -300,15 +299,9 @@ public ScheduledNodes getScheduledNodes() {
((TaskNode) node).getTask();
}
}
return new ScheduledNodes() {
// Hold a reference to the plan, as the field is discarded when the plan completes
final ImmutableList<Node> plan = scheduledNodes;

@Override
public void visitNodes(Consumer<List<Node>> visitor) {
visitor.accept(plan);
}
};
// We're not filtering entryNodes to only contain scheduled nodes here to avoid performance penalty for clients that
// don't care about the entry nodes at all.
return new ScheduledWork(scheduledNodes, entryNodes);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public interface ExecutionPlan extends Describable, Closeable {

void setContinueOnFailure(boolean continueOnFailure);

void setScheduledNodes(Collection<? extends Node> nodes);
void setScheduledWork(ScheduledWork work);

/**
* Adds an entry task to the execution plan. If called multiple times then execution plan follows the method invocation order.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.BiConsumer;

/**
* An execution plan that has been finalized and can no longer be mutated.
Expand Down Expand Up @@ -52,7 +52,7 @@ public int size() {

@Override
public ScheduledNodes getScheduledNodes() {
return visitor -> visitor.accept(Collections.emptyList());
return visitor -> visitor.accept(Collections.emptyList(), Collections.emptySet());
}

@Override
Expand Down Expand Up @@ -97,6 +97,11 @@ public TaskNode getNode(Task task) {
* An immutable snapshot of the set of scheduled nodes.
*/
interface ScheduledNodes {
void visitNodes(Consumer<List<Node>> visitor);
/**
* Invokes the consumer with the list of scheduled nodes and the set of entry nodes. Entry nodes may not be a subset of scheduled nodes.
*
* @param visitor the consumer of nodes and entry nodes
*/
void visitNodes(BiConsumer<List<Node>, Set<Node>> visitor);
}
}
Loading

0 comments on commit 93d70ab

Please sign in to comment.