提交 d46ba52c 编写于 作者: K Kohsuke Kawaguchi

massaging the change a bit.

- doc improvement
- report the result and the problem to the listener
上级 f3ddb285
......@@ -45,7 +45,6 @@ import hudson.model.Descriptor.FormException;
import hudson.model.Fingerprint.RangeSet;
import hudson.model.Queue.Executable;
import hudson.model.Queue.Task;
import hudson.model.listeners.SCMListener;
import hudson.model.queue.SubTask;
import hudson.model.Queue.WaitingItem;
import hudson.model.RunMap.Constructor;
......@@ -56,7 +55,6 @@ import hudson.model.queue.CauseOfBlockage;
import hudson.model.queue.SubTaskContributor;
import hudson.scm.ChangeLogSet;
import hudson.scm.ChangeLogSet.Entry;
import hudson.scm.NullChangeLogParser;
import hudson.scm.NullSCM;
import hudson.scm.PollingResult;
import hudson.scm.SCM;
......@@ -79,7 +77,6 @@ import hudson.util.AlternativeUiTextProvider.Message;
import hudson.util.DescribableList;
import hudson.util.EditDistance;
import hudson.util.FormValidation;
import hudson.util.IOException2;
import hudson.widgets.BuildHistoryWidget;
import hudson.widgets.HistoryWidget;
import jenkins.model.Jenkins;
......@@ -91,7 +88,6 @@ import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.ForwardToView;
import org.kohsuke.stapler.HttpRedirect;
import org.kohsuke.stapler.HttpResponse;
......@@ -105,8 +101,6 @@ import org.kohsuke.stapler.interceptor.RequirePOST;
import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
......@@ -1318,86 +1312,93 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A
}
try {
try {
SCMPollListener.fireBeforePolling(this, listener);
} catch( Exception e ) {
/* Make sure, that the listeners do not have any impact on the actual poll */
}
if (scm.requiresWorkspaceForPolling()) {
// lock the workspace of the last build
FilePath ws=lb.getWorkspace();
if (workspaceOffline(lb)) {
// workspace offline. build now, or nothing will ever be built
Label label = getAssignedLabel();
if (label != null && label.isSelfLabel()) {
// if the build is fixed on a node, then attempting a build will do us
// no good. We should just wait for the slave to come back.
listener.getLogger().println(Messages.AbstractProject_NoWorkspace());
return NO_CHANGES;
}
listener.getLogger().println( ws==null
? Messages.AbstractProject_WorkspaceOffline()
: Messages.AbstractProject_NoWorkspace());
if (isInQueue()) {
listener.getLogger().println(Messages.AbstractProject_AwaitingBuildForWorkspace());
return NO_CHANGES;
} else {
listener.getLogger().println(Messages.AbstractProject_NewBuildForWorkspace());
return BUILD_NOW;
}
} else {
WorkspaceList l = lb.getBuiltOn().toComputer().getWorkspaceList();
// if doing non-concurrent build, acquire a workspace in a way that causes builds to block for this workspace.
// this prevents multiple workspaces of the same job --- the behavior of Hudson < 1.319.
//
// OTOH, if a concurrent build is chosen, the user is willing to create a multiple workspace,
// so better throughput is achieved over time (modulo the initial cost of creating that many workspaces)
// by having multiple workspaces
WorkspaceList.Lease lease = l.acquire(ws, !concurrentBuild);
Launcher launcher = ws.createLauncher(listener);
try {
LOGGER.fine("Polling SCM changes of " + getName());
if (pollingBaseline==null) // see NOTE-NO-BASELINE above
calcPollingBaseline(lb,launcher,listener);
PollingResult r = scm.poll(this, launcher, ws, listener, pollingBaseline);
pollingBaseline = r.remote;
return r;
} finally {
lease.release();
}
}
} else {
// polling without workspace
LOGGER.fine("Polling SCM changes of " + getName());
if (pollingBaseline==null) // see NOTE-NO-BASELINE above
calcPollingBaseline(lb,null,listener);
PollingResult r = scm.poll(this, null, null, listener, pollingBaseline);
pollingBaseline = r.remote;
return r;
}
SCMPollListener.fireBeforePolling(this, listener);
PollingResult r = _poll(listener, scm, lb);
SCMPollListener.firePollingSuccess(this,listener, r);
return r;
} catch (AbortException e) {
listener.getLogger().println(e.getMessage());
listener.fatalError(Messages.AbstractProject_Aborted());
LOGGER.log(Level.FINE, "Polling "+this+" aborted",e);
SCMPollListener.firePollingFailed(this, listener,e);
return NO_CHANGES;
} catch (IOException e) {
e.printStackTrace(listener.fatalError(e.getMessage()));
SCMPollListener.firePollingFailed(this, listener,e);
return NO_CHANGES;
} catch (InterruptedException e) {
e.printStackTrace(listener.fatalError(Messages.AbstractProject_PollingABorted()));
SCMPollListener.firePollingFailed(this, listener,e);
return NO_CHANGES;
} finally {
/* Do this no matter what */
try {
SCMPollListener.fireAfterPolling(this, listener);
} catch( Exception e ) {
/* Make sure, that the listeners do not have any impact on the actual poll */
}
} catch (RuntimeException e) {
SCMPollListener.firePollingFailed(this, listener,e);
throw e;
} catch (Error e) {
SCMPollListener.firePollingFailed(this, listener,e);
throw e;
}
}
/**
* {@link #poll(TaskListener)} method without the try/catch block that does listener notification and .
*/
private PollingResult _poll(TaskListener listener, SCM scm, R lb) throws IOException, InterruptedException {
if (scm.requiresWorkspaceForPolling()) {
// lock the workspace of the last build
FilePath ws=lb.getWorkspace();
if (workspaceOffline(lb)) {
// workspace offline. build now, or nothing will ever be built
Label label = getAssignedLabel();
if (label != null && label.isSelfLabel()) {
// if the build is fixed on a node, then attempting a build will do us
// no good. We should just wait for the slave to come back.
listener.getLogger().println(Messages.AbstractProject_NoWorkspace());
return NO_CHANGES;
}
listener.getLogger().println( ws==null
? Messages.AbstractProject_WorkspaceOffline()
: Messages.AbstractProject_NoWorkspace());
if (isInQueue()) {
listener.getLogger().println(Messages.AbstractProject_AwaitingBuildForWorkspace());
return NO_CHANGES;
} else {
listener.getLogger().println(Messages.AbstractProject_NewBuildForWorkspace());
return BUILD_NOW;
}
} else {
WorkspaceList l = lb.getBuiltOn().toComputer().getWorkspaceList();
// if doing non-concurrent build, acquire a workspace in a way that causes builds to block for this workspace.
// this prevents multiple workspaces of the same job --- the behavior of Hudson < 1.319.
//
// OTOH, if a concurrent build is chosen, the user is willing to create a multiple workspace,
// so better throughput is achieved over time (modulo the initial cost of creating that many workspaces)
// by having multiple workspaces
WorkspaceList.Lease lease = l.acquire(ws, !concurrentBuild);
Launcher launcher = ws.createLauncher(listener);
try {
LOGGER.fine("Polling SCM changes of " + getName());
if (pollingBaseline==null) // see NOTE-NO-BASELINE above
calcPollingBaseline(lb,launcher,listener);
PollingResult r = scm.poll(this, launcher, ws, listener, pollingBaseline);
pollingBaseline = r.remote;
return r;
} finally {
lease.release();
}
}
} else {
// polling without workspace
LOGGER.fine("Polling SCM changes of " + getName());
if (pollingBaseline==null) // see NOTE-NO-BASELINE above
calcPollingBaseline(lb,null,listener);
PollingResult r = scm.poll(this, null, null, listener, pollingBaseline);
pollingBaseline = r.remote;
return r;
}
}
private boolean workspaceOffline(R build) throws IOException, InterruptedException {
FilePath ws = build.getWorkspace();
if (ws==null || !ws.exists()) {
......
......@@ -25,28 +25,78 @@ package hudson.model.listeners;
import hudson.ExtensionList;
import hudson.ExtensionPoint;
import hudson.scm.PollingResult;
import jenkins.model.Jenkins;
import hudson.model.AbstractProject;
import hudson.model.TaskListener;
public abstract class SCMPollListener implements ExtensionPoint {
import java.io.IOException;
/**
* A hook for listening to polling activities in Jenkins.
*
* @author Christian Wolfgang
* @author Kohsuke Kawaguchi
* @since 1.474
*/
public abstract class SCMPollListener implements ExtensionPoint {
/**
* Called before the polling execution.
*
* @param project
* Project that's about to run polling.
* @param listener
* Connected to the polling log.
*/
public void onBeforePolling( AbstractProject<?, ?> project, TaskListener listener ) {}
public void onAfterPolling( AbstractProject<?, ?> project, TaskListener listener ) {}
/**
* Called when the polling successfully concluded.
*
* @param result
* The result of the polling.
*/
public void onPollingSuccess( AbstractProject<?, ?> project, TaskListener listener, PollingResult result) {}
/**
* Called when the polling concluded with an error.
*
* @param exception
* The problem reported. This can include {@link InterruptedException} (that corresponds to the user cancelling it),
* some anticipated problems like {@link IOException}, or bug in the code ({@link RuntimeException})
*/
public void onPollingFailed( AbstractProject<?, ?> project, TaskListener listener, Throwable exception) {}
public static void fireBeforePolling( AbstractProject<?, ?> project, TaskListener listener ) {
for( SCMPollListener l : all() ) {
l.onBeforePolling( project, listener );
}
}
for (SCMPollListener l : all()) {
try {
l.onBeforePolling(project, listener);
} catch (Exception e) {
/* Make sure, that the listeners do not have any impact on the actual poll */
}
}
}
public static void fireAfterPolling( AbstractProject<?, ?> project, TaskListener listener ) {
public static void firePollingSuccess( AbstractProject<?, ?> project, TaskListener listener, PollingResult result ) {
for( SCMPollListener l : all() ) {
l.onAfterPolling( project, listener );
try {
l.onPollingSuccess(project, listener, result);
} catch (Exception e) {
/* Make sure, that the listeners do not have any impact on the actual poll */
}
}
}
public static void firePollingFailed( AbstractProject<?, ?> project, TaskListener listener, Throwable exception ) {
for( SCMPollListener l : all() ) {
try {
l.onPollingFailed(project, listener, exception);
} catch (Exception e) {
/* Make sure, that the listeners do not have any impact on the actual poll */
}
}
}
/**
* Returns all the registered {@link SCMPollListener}s.
*/
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册