Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
eaa6b02
[JENKINS-38381] Prototype API to receive asynchronous notifications o…
jglick Sep 29, 2016
7ab9e49
In the case of WithContainerStep, do not even try to have ShellContro…
jglick Sep 30, 2016
642d7be
2.16 parent
jglick Oct 3, 2016
51a6b8d
Watcher is on the hook to call cleanup.
jglick Oct 3, 2016
0dc0960
A bit more logging.
jglick Oct 4, 2016
89fd319
Mistyped issue number.
jglick Oct 4, 2016
d0e9f76
Recode process output into UTF-8.
jglick Oct 5, 2016
3f58d6c
Switching to StandardCharsets rather than using the Guava version.
jglick Oct 5, 2016
8f11c53
Updated parent to pick up jitpack.io support.
jglick Dec 7, 2016
1998be6
Merge branch 'master' into logs-JENKINS-38381
jglick Feb 5, 2018
b108f5a
Merge branch 'master' into logs-JENKINS-38381
jglick Feb 5, 2018
532ac57
Comments.
jglick Feb 9, 2018
52259cb
Merge branch 'Queue.withLock' into logs-JENKINS-38381
jglick Feb 9, 2018
b945cf2
[JENKINS-38381] Controller.watch API.
jglick Feb 9, 2018
a455cc4
Merge branch 'watch-JENKINS-38381' into logs-JENKINS-38381
jglick Feb 9, 2018
6cdc198
Merge branch 'master' into logs-JENKINS-38381
jglick Feb 12, 2018
e703cc8
[JENKINS-31096] Define API for gathering command output in a local en…
jglick Feb 12, 2018
27f957f
Reminder to pick up https://github.com/jenkinsci/jenkins/pull/3272.
jglick Feb 13, 2018
3768e1e
Merge branch 'watch-JENKINS-38381' into logs-JENKINS-38381
jglick Feb 13, 2018
cc6029c
Merge branch 'UTF-8-JENKINS-31096' into watch-plus-UTF-8-JENKINS-31096
jglick Feb 13, 2018
5d7ea7f
Integrating transcoding into watches.
jglick Feb 13, 2018
cc53b18
ByteBuffer.array is not what I wanted.
jglick Feb 13, 2018
6141407
Merge branch 'UTF-8-JENKINS-31096' into watch-plus-UTF-8-JENKINS-31096
jglick Feb 13, 2018
deb425d
Completing test coverage.
jglick Feb 13, 2018
a2aaa13
Merge branch 'watch-plus-UTF-8-JENKINS-31096' into logs-JENKINS-38381
jglick Feb 13, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,8 @@ private FilePath pidFile(FilePath ws) throws IOException, InterruptedException {
return controlDir(ws).child("pid");
}

@Override public Integer exitStatus(FilePath workspace, Launcher launcher, TaskListener listener) throws IOException, InterruptedException {
Integer status = super.exitStatus(workspace, launcher, listener);
@Override protected Integer exitStatus(FilePath workspace, TaskListener listener) throws IOException, InterruptedException {
Integer status = super.exitStatus(workspace, listener);
if (status != null) {
LOGGER.log(Level.FINE, "found exit code {0} in {1}", new Object[] {status, controlDir});
return status;
Expand Down
22 changes: 20 additions & 2 deletions src/main/java/org/jenkinsci/plugins/durabletask/Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,35 @@
*/
public abstract class Controller implements Serializable {

/**
* Begins watching the process asynchronously, so that the master may receive notification when output is available or the process has exited.
* This should be called as soon as the process is launched, and thereafter whenever reconnecting to the agent.
* You should not call {@link #writeLog} or {@link #cleanup} in this case; you do not need to call {@link #exitStatus(FilePath, Launcher)} frequently,
* though it is advisable to still call it occasionally to verify that the process is still running.
* @param workspace the workspace in use
* @param handler a remotable callback
* @param listener a remotable destination for messages
* @throws UnsupportedOperationException when this mode is not available, so you must fall back to polling {@link #writeLog} and {@link #exitStatus(FilePath, Launcher)}
*/
public void watch(@Nonnull FilePath workspace, @Nonnull Handler handler, @Nonnull TaskListener listener) throws IOException, InterruptedException, UnsupportedOperationException {
throw new UnsupportedOperationException("Asynchronous mode is not implemented in " + getClass().getName());
}

/**
* Obtains any new task log output.
* Could use a serializable field to keep track of how much output has been previously written.
* @param workspace the workspace in use
* @param sink where to send new log output
* @return true if something was written and the controller should be resaved, false if everything is idle
* @see DurableTask#charset
* @see DurableTask#defaultCharset
*/
public abstract boolean writeLog(FilePath workspace, OutputStream sink) throws IOException, InterruptedException;

/**
* Checks whether the task has finished.
* @param workspace the workspace in use
* @param launcher a way to start processes
* @param launcher a way to start processes (currently unused)
* @param logger a way to report special messages
* @return an exit code (zero is successful), or null if the task appears to still be running
*/
Expand Down Expand Up @@ -86,8 +102,10 @@ public abstract class Controller implements Serializable {
* Intended for use after {@link #exitStatus(FilePath, Launcher)} has returned a non-null status.
* The result is undefined if {@link DurableTask#captureOutput} was not called before launch; generally an {@link IOException} will result.
* @param workspace the workspace in use
* @param launcher a way to start processes
* @param launcher a way to start processes (currently unused)
* @return the output of the process as raw bytes (may be empty but not null)
* @see DurableTask#charset
* @see DurableTask#defaultCharset
*/
public @Nonnull byte[] getOutput(@Nonnull FilePath workspace, @Nonnull Launcher launcher) throws IOException, InterruptedException {
throw new IOException("Did not implement getOutput in " + getClass().getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import hudson.model.AbstractDescribableImpl;
import hudson.model.TaskListener;
import java.io.IOException;
import java.nio.charset.Charset;
import javax.annotation.Nonnull;

/**
* A task which may be run asynchronously on a build node and withstand disconnection of the slave agent.
Expand All @@ -53,8 +55,9 @@ public abstract class DurableTask extends AbstractDescribableImpl<DurableTask> i
public abstract Controller launch(EnvVars env, FilePath workspace, Launcher launcher, TaskListener listener) throws IOException, InterruptedException;

/**
* Requests that standard output of the task be captured rather than streamed to {@link Controller#writeLog}.
* If so, you may call {@link Controller#getOutput}.
* Requests that standard output of the task be captured rather than streamed.
* If you use {@link Controller#watch}, standard output will not be sent to {@link Handler#output}; it will be included in {@link Handler#exited} instead.
* Otherwise (using polling mode), standard output will not be sent to {@link Controller#writeLog}; call {@link Controller#getOutput} to collect.
* Standard error should still be streamed to the log.
* Should be called prior to {@link #launch} to take effect.
* @throws UnsupportedOperationException if this implementation does not support that mode
Expand All @@ -63,4 +66,23 @@ public void captureOutput() throws UnsupportedOperationException {
throw new UnsupportedOperationException("Capturing of output is not implemented in " + getClass().getName());
}

/**
* Requests that a specified charset be used to transcode process output.
* The encoding of {@link Controller#writeLog} and {@link Controller#getOutput} is then presumed to be UTF-8.
* If not called, no translation is performed.
* @param cs the character set in which process output is expected to be
*/
public void charset(@Nonnull Charset cs) {
// by default, ignore
}

/**
* Requests that the node’s system charset be used to transcode process output.
* The encoding of {@link Controller#writeLog} and {@link Controller#getOutput} is then presumed to be UTF-8.
* If not called, no translation is performed.
*/
public void defaultCharset() {
// by default, ignore
}

}
Loading