Index: src/org/eclipse/core/internal/events/BuildDescription.java =================================================================== RCS file: src/org/eclipse/core/internal/events/BuildDescription.java diff -N src/org/eclipse/core/internal/events/BuildDescription.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/events/BuildDescription.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.events; + +import org.eclipse.core.resources.IBuildConfiguration; +import org.eclipse.core.resources.IBuildContext; + +import org.eclipse.core.resources.IBuildDescription; + +/** + * + */ +public class BuildDescription implements IBuildDescription { + + private IBuildContext buildContext; + + private IBuildConfiguration buildConfiguration; + + public BuildDescription(IBuildContext buildContext, IBuildConfiguration buildConfiguration) { + super(); + this.buildContext = buildContext; + this.buildConfiguration = buildConfiguration; + } + + public IBuildContext getBuildContext() { + return buildContext; + } + + public IBuildConfiguration getBuildConfiguration() { + return buildConfiguration; + } + +} Index: src/org/eclipse/core/internal/events/BuildManager.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/events/BuildManager.java,v retrieving revision 1.126 diff -u -r1.126 BuildManager.java --- src/org/eclipse/core/internal/events/BuildManager.java 3 May 2011 15:11:54 -0000 1.126 +++ src/org/eclipse/core/internal/events/BuildManager.java 4 Jul 2011 07:55:27 -0000 @@ -14,6 +14,10 @@ *******************************************************************************/ package org.eclipse.core.internal.events; +import org.eclipse.core.runtime.Status; + +import org.eclipse.core.resources.IncrementalProjectBuilder; + import java.util.*; import org.eclipse.core.internal.dtree.DeltaDataTree; import org.eclipse.core.internal.resources.*; @@ -134,12 +138,14 @@ private void basicBuild(int trigger, IncrementalProjectBuilder builder, Map args, MultiStatus status, IProgressMonitor monitor) { try { - currentBuilder = builder; +// currentBuilder = builder; + InternalBuilder currentBuilder2 = builder; //clear any old requests to forget built state - currentBuilder.clearLastBuiltStateRequests(); +// currentBuilder.clearLastBuiltStateRequests(); + currentBuilder2.clearLastBuiltStateRequests(); // Figure out want kind of build is needed boolean clean = trigger == IncrementalProjectBuilder.CLEAN_BUILD; - currentLastBuiltTree = currentBuilder.getLastBuiltTree(); + currentLastBuiltTree = currentBuilder2.getLastBuiltTree(); // Does the build command respond to this trigger? boolean isBuilding = builder.getCommand().isBuilding(trigger); @@ -167,14 +173,14 @@ ISchedulingRule rule = null; try { //short-circuit if none of the projects this builder cares about have changed. - if (!needsBuild(currentBuilder, trigger)) { + if (!needsBuild(currentBuilder2, trigger)) { //use up the progress allocated for this builder monitor.beginTask("", 1); //$NON-NLS-1$ monitor.done(); return; } rule = builder.getRule(trigger, args); - String name = currentBuilder.getLabel(); + String name = currentBuilder2.getLabel(); String message; if (name != null) message = NLS.bind(Messages.events_invoking_2, name, builder.getProject().getFullPath()); @@ -189,6 +195,7 @@ depth = getWorkManager().beginUnprotected(); // Acquire the rule required for running this builder if (rule != null) { +// System.out.println("starting rule " + rule.toString()); //$NON-NLS-1$ Job.getJobManager().beginRule(rule, monitor); // Now that we've acquired the rule, changes may have been made concurrently, ensure we're pointing at the // correct currentTree so delta contains concurrent changes made in areas guarded by the scheduling rule @@ -196,27 +203,28 @@ currentTree = workspace.getElementTree(); } //do the build - SafeRunner.run(getSafeRunnable(trigger, args, status, monitor)); + SafeRunner.run(getSafeRunnable(trigger, args, status, monitor, currentBuilder2)); } finally { // Re-acquire the WS lock, then release the scheduling rule if (depth >= 0) getWorkManager().endUnprotected(depth); if (rule != null) Job.getJobManager().endRule(rule); +// System.out.println("end rule " + rule.toString()); //$NON-NLS-1$ // Be sure to clean up after ourselves. - if (clean || currentBuilder.wasForgetStateRequested()) { - currentBuilder.setLastBuiltTree(null); - } else if (currentBuilder.wasRememberStateRequested()) { + if (clean || currentBuilder2.wasForgetStateRequested()) { + currentBuilder2.setLastBuiltTree(null); + } else if (currentBuilder2.wasRememberStateRequested()) { // If remember last build state, and FULL_BUILD // last tree must be set to => null for next build if (trigger == IncrementalProjectBuilder.FULL_BUILD) - currentBuilder.setLastBuiltTree(null); + currentBuilder2.setLastBuiltTree(null); // else don't modify the last built tree } else { // remember the current state as the last built state. ElementTree lastTree = workspace.getElementTree(); - lastTree.immutable(); - currentBuilder.setLastBuiltTree(lastTree); +// lastTree.immutable(); + currentBuilder2.setLastBuiltTree(lastTree); } hookEndBuild(builder); } @@ -234,7 +242,13 @@ checkCanceled(trigger, monitor); BuildCommand command = (BuildCommand) commands[i]; IProgressMonitor sub = Policy.subMonitorFor(monitor, 1); - IncrementalProjectBuilder builder = getBuilder(buildConfiguration, command, i, status, context); +// IncrementalProjectBuilder builder = getBuilder(buildConfiguration, command, i, status, context); + IncrementalProjectBuilder builder; + if(IncrementalProjectBuilder.PARALLEL_FULL_BUILD == trigger) { + builder = getParallelBuilder(buildConfiguration, command, i, status, context); + } else { + builder = getBuilder(buildConfiguration, command, i, status, context); + } if (builder != null) basicBuild(trigger, builder, command.getArguments(false), status, sub); } @@ -511,7 +525,7 @@ * The outermost workspace operation has finished. Do an autobuild if necessary. */ public void endTopLevel(boolean needsBuild) { - autoBuildJob.build(needsBuild); +// autoBuildJob.build(needsBuild); } /** @@ -694,7 +708,7 @@ /** * Returns the safe runnable instance for invoking a builder */ - private ISafeRunnable getSafeRunnable(final int trigger, final Map args, final MultiStatus status, final IProgressMonitor monitor) { + private ISafeRunnable getSafeRunnable(final int trigger, final Map args, final MultiStatus status, final IProgressMonitor monitor, final InternalBuilder currentBuilder2) { return new ISafeRunnable() { public void handleException(Throwable e) { if (e instanceof OperationCanceledException) { @@ -702,18 +716,18 @@ Policy.debug("Build canceled"); //$NON-NLS-1$ //just discard built state when a builder cancels, to ensure //that it is called again on the very next build. - currentBuilder.forgetLastBuiltState(); + currentBuilder2.forgetLastBuiltState(); throw (OperationCanceledException) e; } //ResourceStats.buildException(e); // don't log the exception....it is already being logged in SafeRunner#run //add a generic message to the MultiStatus - String builderName = currentBuilder.getLabel(); + String builderName = currentBuilder2.getLabel(); if (builderName == null || builderName.length() == 0) - builderName = currentBuilder.getClass().getName(); - String pluginId = currentBuilder.getPluginId(); - String message = NLS.bind(Messages.events_builderError, builderName, currentBuilder.getProject().getName()); + builderName = currentBuilder2.getClass().getName(); + String pluginId = currentBuilder2.getPluginId(); + String message = NLS.bind(Messages.events_builderError, builderName, currentBuilder2.getProject().getName()); status.add(new Status(IStatus.ERROR, pluginId, IResourceStatus.BUILD_FAILED, message, e)); //add the exception status to the MultiStatus @@ -725,12 +739,12 @@ IProject[] prereqs = null; //invoke the appropriate build method depending on the trigger if (trigger != IncrementalProjectBuilder.CLEAN_BUILD) - prereqs = currentBuilder.build(trigger, args, monitor); + prereqs = currentBuilder2.build(trigger, args, monitor); else - currentBuilder.clean(monitor); + currentBuilder2.clean(monitor); if (prereqs == null) prereqs = new IProject[0]; - currentBuilder.setInterestingProjects(prereqs.clone()); + currentBuilder2.setInterestingProjects(prereqs.clone()); } }; } @@ -1145,4 +1159,59 @@ Policy.log(status); return workspace.getRoot(); } + + public void buildParallel(IProgressMonitor subMonitorFor) { + final MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, Messages.events_errors, null); + + IProject[] projects = workspace.getRoot().getProjects(IContainer.INCLUDE_HIDDEN); + DirectedGraphs directedGraphs = new DirectedGraphs(); + for (IProject project : projects) { + directedGraphs.addNode(new Node(project)); + } + for (IProject project : projects) { + if (!project.isAccessible()) + continue; + ProjectDescription desc = ((Project)project).internalGetDescription(); + if (desc == null) + continue; + IProject[] refs = desc.getAllReferences(false); + Node node = directedGraphs.getNodeWithContent(project); + for (IProject referencedProject : refs) { + Node node2 = directedGraphs.getNodeWithContent(referencedProject); + if(node2 != null) { + node2.addOutgoingEdge(node); + } + } + } + ThreadPoolBuilder threadPoolBuilder = new ThreadPoolBuilder(); + try { + IBuildExecutor buildExecutor = new IBuildExecutor() { + public void executeBuild(IBuildDescription buildDescription) { + NullProgressMonitor progressMonitor = new NullProgressMonitor(); + basicBuild(buildDescription.getBuildConfiguration(), IncrementalProjectBuilder.PARALLEL_FULL_BUILD, buildDescription.getBuildContext(), status, progressMonitor); + }}; + threadPoolBuilder.run(directedGraphs, buildExecutor); + } catch (InterruptedException e) { + status.add(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, Messages.events_errors, e)); + } + } + + private IncrementalProjectBuilder getParallelBuilder(IBuildConfiguration buildConfiguration, BuildCommand command, int buildSpecIndex, MultiStatus status, IBuildContext buildContext) throws CoreException { + // always construct a new builder for parallel builds (think about pooling here) + InternalBuilder result = initializeBuilder(command.getBuilderName(), buildConfiguration, buildSpecIndex, status); + command.setBuilders(result); + result.setCommand(command); + result.setBuildConfig(buildConfiguration); + result.startupOnInitialize(); + // } + + if (!validateNature(result, command.getBuilderName())) { + //skip this builder and null its last built tree because it is invalid + //if the nature gets added or re-enabled a full build will be triggered + result.setLastBuiltTree(null); + return null; + } + return (IncrementalProjectBuilder) result; + } + } Index: src/org/eclipse/core/internal/events/BuildRunnable.java =================================================================== RCS file: src/org/eclipse/core/internal/events/BuildRunnable.java diff -N src/org/eclipse/core/internal/events/BuildRunnable.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/events/BuildRunnable.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,34 @@ +package org.eclipse.core.internal.events; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import org.eclipse.core.internal.resources.BuildConfiguration; +import org.eclipse.core.resources.IProject; + +public final class BuildRunnable implements Runnable { + + private final Node currentNode; + private final BlockingQueue> queue; + private final IBuildExecutor executor; + + protected BuildRunnable(Node currentNode, BlockingQueue> queue, IBuildExecutor executor) { + this.currentNode = currentNode; + this.queue = queue; + this.executor = executor; + } + + public void run() { + System.out.println("start compile " + currentNode.getContent()); //$NON-NLS-1$ + BuildDescription buildDescription = new BuildDescription(null, new BuildConfiguration(currentNode.getContent())); + executor.executeBuild(buildDescription); + System.out.println("end compile " + currentNode.getContent()); //$NON-NLS-1$ + List> outgoingNodes = new ArrayList>(currentNode.getOutgoingEdges()); + currentNode.removeAllOutgoingEdges(); + for (Node node : outgoingNodes) { + if(node.getIncomingEdges().isEmpty()) { + queue.add(node); + } + } + } +} \ No newline at end of file Index: src/org/eclipse/core/internal/events/DirectedGraphs.java =================================================================== RCS file: src/org/eclipse/core/internal/events/DirectedGraphs.java diff -N src/org/eclipse/core/internal/events/DirectedGraphs.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/events/DirectedGraphs.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,58 @@ +package org.eclipse.core.internal.events; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * A directed graph holds all nodes. Nodes need not be connected which is why a container object is required + * + * @author jens + * + */ +public class DirectedGraphs { + + private Set> nodes; + + public DirectedGraphs() { + nodes = Collections.synchronizedSet(new HashSet>()); + } + + public void addNode(Node node) { + nodes.add(node); + } + + public void removeNode(Node node) { + nodes.remove(node); + } + + public void addAll(Collection> nodesToBeAdded) { + nodes.addAll(nodesToBeAdded); + } + + public Node getNodeWithContent(T content) { + for (Node node : nodes) { + if(content.equals(node.getContent())) { + return node; + } + } + return null; + } + + public synchronized Set> getRootNodes() { + Set> set = new LinkedHashSet>(); + for (Node node : nodes) { + if(node.getIncomingEdges().isEmpty()) { + set.add(node); + } + } + return set; + } + + public boolean isEmtpy() { + return nodes.isEmpty(); + } + +} Index: src/org/eclipse/core/internal/events/IBuildExecutor.java =================================================================== RCS file: src/org/eclipse/core/internal/events/IBuildExecutor.java diff -N src/org/eclipse/core/internal/events/IBuildExecutor.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/events/IBuildExecutor.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.internal.events; + +import org.eclipse.core.resources.IBuildDescription; + + +/** + * + */ +public interface IBuildExecutor { + + public void executeBuild(IBuildDescription buildDescription); + +} Index: src/org/eclipse/core/internal/events/Node.java =================================================================== RCS file: src/org/eclipse/core/internal/events/Node.java diff -N src/org/eclipse/core/internal/events/Node.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/events/Node.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,129 @@ +package org.eclipse.core.internal.events; + +import java.text.MessageFormat; + +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * A simple node object having references to other node objects + * + * @param + */ +public class Node { + + private Set> incomingEdges; + + private Set> outgoingEdges; + + private T content; + + public Node(T content) { + this.content = content; + incomingEdges = Collections.synchronizedSet(new LinkedHashSet>()); + outgoingEdges = Collections.synchronizedSet(new LinkedHashSet>()); + } + + public T getContent() { + return content; + } + + public void setContent(T content) { + this.content = content; + } + + public synchronized Set> getIncomingEdges() { + return incomingEdges; + } + + public synchronized Set> getOutgoingEdges() { + return outgoingEdges; + } + + public synchronized void addIncomingEdge(Node node) { + if(!incomingEdges.contains(node)) { + incomingEdges.add(node); + node.addOutgoingEdge(this); + } + } + + public synchronized void addOutgoingEdge(Node node) { + if(!outgoingEdges.contains(node)) { + outgoingEdges.add(node); + node.addIncomingEdge(this); + } + } + + public synchronized void removeOutgoingEdge(Node node) { + if(outgoingEdges.contains(node)) { + outgoingEdges.remove(node); + node.removeIncomingEdge(this); + } + } + + public synchronized void removeIncomingEdge(Node node) { + if(incomingEdges.contains(node)) { + incomingEdges.remove(node); + node.removeOutgoingEdge(this); + } + } + + public synchronized void removeAllOutgoingEdges() { + for (Iterator> iterator = outgoingEdges.iterator(); iterator.hasNext();) { + Node node = iterator.next(); + node.internalRemoveIncomingEdge(this); + iterator.remove(); + } + } + + public synchronized void removeAllIncomingEdges() { + for (Iterator> iterator = incomingEdges.iterator(); iterator.hasNext();) { + Node node = iterator.next(); + node.internalRemoveOutgoingEdge(this); + iterator.remove(); + } + } + + synchronized void internalRemoveOutgoingEdge(Node node) { + outgoingEdges.remove(node); + } + + synchronized void internalRemoveIncomingEdge(Node node) { + incomingEdges.remove(node); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((content == null) ? 0 : content.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Node other = (Node) obj; + if (content == null) { + if (other.content != null) + return false; + } else if (!content.equals(other.content)) + return false; + return true; + } + + @Override + public String toString() { + return MessageFormat.format("Node [content={0}]", content); //$NON-NLS-1$ + } + + + +} Index: src/org/eclipse/core/internal/events/ThreadPoolBuilder.java =================================================================== RCS file: src/org/eclipse/core/internal/events/ThreadPoolBuilder.java diff -N src/org/eclipse/core/internal/events/ThreadPoolBuilder.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/internal/events/ThreadPoolBuilder.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,29 @@ +package org.eclipse.core.internal.events; + +import java.util.concurrent.*; +import org.eclipse.core.resources.IProject; + +public class ThreadPoolBuilder { + + private ExecutorService threadPool; + + private BlockingQueue> queue; + + public ThreadPoolBuilder() { + threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() - 1); + queue = new ArrayBlockingQueue>(6000); + } + + public void run(DirectedGraphs directedGraphs, IBuildExecutor runnable) throws InterruptedException { + queue.addAll(directedGraphs.getRootNodes()); + while (!threadPool.isTerminated()) { + if(directedGraphs.isEmtpy()) { + threadPool.shutdown(); + } else { + NodenodeToCompile = queue.take(); + directedGraphs.removeNode((Node) nodeToCompile); + threadPool.execute(new BuildRunnable(nodeToCompile, queue, runnable)); + } + } + } +} Index: src/org/eclipse/core/internal/resources/WorkManager.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/WorkManager.java,v retrieving revision 1.41 diff -u -r1.41 WorkManager.java --- src/org/eclipse/core/internal/resources/WorkManager.java 1 Feb 2011 11:37:52 -0000 1.41 +++ src/org/eclipse/core/internal/resources/WorkManager.java 4 Jul 2011 07:55:28 -0000 @@ -99,8 +99,10 @@ */ public int beginUnprotected() { int depth = lock.getDepth(); - for (int i = 0; i < depth; i++) + for (int i = 0; i < depth; i++) { lock.release(); + System.out.println("Lock released by " + Thread.currentThread().getName()); //$NON-NLS-1$ + } return depth; } @@ -115,8 +117,12 @@ String msg = Messages.resources_cannotModify; throw new ResourceException(IResourceStatus.WORKSPACE_LOCKED, null, msg, null); } + if(rule != null) { + System.out.println("Begin rule " + rule.toString()); //$NON-NLS-1$ + } jobManager.beginRule(rule, monitor); lock.acquire(); + System.out.println("Lock aquired by " + Thread.currentThread().getName() + " Rule " + (rule == null ? "" : rule.toString())); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ incrementPreparedOperations(); success = true; } finally { @@ -157,9 +163,13 @@ operationCanceled = hasBuildChanges = false; try { lock.release(); + System.out.println("Lock released by " + Thread.currentThread().getName() + " Rule " + (rule == null ? "" : rule.toString())); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } finally { //end rule in finally in case lock.release throws an exception jobManager.endRule(rule); + if(rule != null) { + System.out.println("end rule " + rule.toString()); //$NON-NLS-1$ + } } } @@ -178,8 +188,10 @@ * @see #beginUnprotected() */ public void endUnprotected(int depth) { - for (int i = 0; i < depth; i++) + for (int i = 0; i < depth; i++) { lock.acquire(); + System.out.println("Lock aquired by " + Thread.currentThread().getName()); //$NON-NLS-1$ + } } /** @@ -246,6 +258,7 @@ // before result = lock.getDepth() > 1; lock.release(); + System.out.println("Lock released by " + Thread.currentThread().getName()); //$NON-NLS-1$ } } catch (InterruptedException e) { // ignore @@ -300,6 +313,7 @@ public void startup(IProgressMonitor monitor) { jobManager.beginRule(workspace.getRoot(), monitor); lock.acquire(); + System.out.println("Lock aquired by " + Thread.currentThread().getName()); //$NON-NLS-1$ } /** @@ -310,6 +324,8 @@ void postWorkspaceStartup() { try { lock.release(); + System.out.println("Lock released by " + Thread.currentThread().getName()); //$NON-NLS-1$ + } finally { //end rule in finally in case lock.release throws an exception jobManager.endRule(workspace.getRoot()); Index: src/org/eclipse/core/internal/resources/Workspace.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/Workspace.java,v retrieving revision 1.245 diff -u -r1.245 Workspace.java --- src/org/eclipse/core/internal/resources/Workspace.java 3 May 2011 15:11:54 -0000 1.245 +++ src/org/eclipse/core/internal/resources/Workspace.java 4 Jul 2011 07:55:29 -0000 @@ -363,8 +363,8 @@ public void beginOperation(boolean createNewTree) throws CoreException { WorkManager workManager = getWorkManager(); workManager.incrementNestedOperations(); - if (!workManager.isBalanced()) - Assert.isTrue(false, "Operation was not prepared."); //$NON-NLS-1$ +// if (!workManager.isBalanced()) +// Assert.isTrue(false, "Operation was not prepared."); //$NON-NLS-1$ if (workManager.getPreparedOperationDepth() > 1) { if (createNewTree && tree.isImmutable()) newWorkingTree(); Index: src/org/eclipse/core/resources/IBuildDescription.java =================================================================== RCS file: src/org/eclipse/core/resources/IBuildDescription.java diff -N src/org/eclipse/core/resources/IBuildDescription.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/core/resources/IBuildDescription.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.core.resources; + +/** + * + */ +public interface IBuildDescription { + + IBuildContext getBuildContext(); + + IBuildConfiguration getBuildConfiguration(); + +} Index: src/org/eclipse/core/resources/IncrementalProjectBuilder.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/resources/IncrementalProjectBuilder.java,v retrieving revision 1.49 diff -u -r1.49 IncrementalProjectBuilder.java --- src/org/eclipse/core/resources/IncrementalProjectBuilder.java 7 Feb 2011 09:43:31 -0000 1.49 +++ src/org/eclipse/core/resources/IncrementalProjectBuilder.java 4 Jul 2011 07:55:30 -0000 @@ -71,6 +71,8 @@ * @see IWorkspace#build(int, IProgressMonitor) */ public static final int INCREMENTAL_BUILD = 10; + + public static final int PARALLEL_FULL_BUILD = 11; /** * Build kind constant (value 15) indicating a clean build request. A clean * build discards any additional state that has been computed as a result of @@ -451,7 +453,8 @@ * @since 3.6 */ public ISchedulingRule getRule(int kind, Map args) { - return getRule(); + return getProject(); +// return getRule(); } /**