Skip to content
This repository has been archived by the owner on Apr 21, 2023. It is now read-only.

Commit

Permalink
[#1710] Don't touch the project again if it was already built
Browse files Browse the repository at this point in the history
The window of opportunity for the autobuild is the time between
forgetting the last built state and the touch of the project in its own
job. Check if there is a known built state before touching the project
again.

Signed-off-by: Sebastian Zarnekow <[email protected]>
  • Loading branch information
szarnekow committed Aug 21, 2021
1 parent 88513b6 commit 01f2fe6
Showing 1 changed file with 38 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
*******************************************************************************/
package org.eclipse.xtext.builder.impl;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Map;

import org.apache.log4j.Logger;
Expand All @@ -34,12 +37,34 @@
public class BuilderStateDiscarder {

private static final Logger logger = Logger.getLogger(BuilderStateDiscarder.class);
private static final MethodHandle InternalBuilder_getLastBuiltTree;

static {
try {
@SuppressWarnings("restriction")
MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(
org.eclipse.core.internal.events.InternalBuilder.class, MethodHandles.lookup());
@SuppressWarnings("restriction")
MethodHandle handle = lookup.findVirtual(
org.eclipse.core.internal.events.InternalBuilder.class,
"getLastBuiltTree",
MethodType.methodType(org.eclipse.core.internal.watson.ElementTree.class));
InternalBuilder_getLastBuiltTree = handle;
} catch (ReflectiveOperationException e) {
throw new ExceptionInInitializerError(e);
}
}

/**
* Returns true, if the given builderArguments indicate that we should discard the built state
* for the given projects.
*/
public boolean forgetLastBuildState(Iterable<IProject> toUpdate, Map<String, String> builderArguments) {
/*
* Implementation note:
* This is executed with the Workspace.lock being acquired, but the tree might be locked for modifications,
* so we may not directly touch a project.
*/
if (canHandleBuildFlag(builderArguments)) {
for (IProject project : toUpdate) {
XtextBuilder builder = BuildManagerAccess.findBuilder(project);
Expand All @@ -61,7 +86,8 @@ public boolean forgetLastBuildState(Iterable<IProject> toUpdate, Map<String, Str
protected void touchProject(IProject project) {
Job touchJob = Job.create("Touch project " + project.getName(), progressMonitor -> {
try {
if (project.isAccessible()) {
// Check if there is already a known built tree before touching the project
if (project.isAccessible() && !hasBeenBuilt(project)) {
project.touch(progressMonitor);
}
return Status.OK_STATUS;
Expand All @@ -77,6 +103,17 @@ protected void touchProject(IProject project) {

}

protected boolean hasBeenBuilt(IProject project) {
@SuppressWarnings("restriction")
org.eclipse.core.internal.events.InternalBuilder builder = BuildManagerAccess.findBuilder(project);
try {
return InternalBuilder_getLastBuiltTree.invoke(builder) != null;
} catch (Throwable e) {
logger.error("Failed to dermine if the project was already built. Assuming it wasn't built yet", e);
return false;
}
}

protected boolean canHandleBuildFlag(Map<String, String> builderArguments) {
return IBuildFlag.FORGET_BUILD_STATE_ONLY.isSet(builderArguments)
|| IBuildFlag.RECOVERY_BUILD.isSet(builderArguments);
Expand Down

0 comments on commit 01f2fe6

Please sign in to comment.