use of hudson.remoting.Channel in project hudson-2.x by hudson.
the class ChannelTestCase method setUp.
@Override
protected void setUp() throws Exception {
super.setUp();
final FastPipedInputStream p1i = new FastPipedInputStream();
final FastPipedInputStream p2i = new FastPipedInputStream();
final FastPipedOutputStream p1o = new FastPipedOutputStream(p1i);
final FastPipedOutputStream p2o = new FastPipedOutputStream(p2i);
Future<Channel> f1 = executors.submit(new Callable<Channel>() {
public Channel call() throws Exception {
return new Channel("This side of the channel", executors, p1i, p2o);
}
});
Future<Channel> f2 = executors.submit(new Callable<Channel>() {
public Channel call() throws Exception {
return new Channel("The other side of the channel", executors, p2i, p1o);
}
});
french = f1.get();
british = f2.get();
}
use of hudson.remoting.Channel in project hudson-2.x by hudson.
the class Channels method forProcess.
public static Channel forProcess(String name, ExecutorService execService, final Process proc, OutputStream header) throws IOException {
final Thread thread = new StreamCopyThread(name + " stderr", proc.getErrorStream(), header);
thread.start();
return new Channel(name, execService, proc.getInputStream(), proc.getOutputStream(), header) {
/**
* Kill the process when the channel is severed.
*/
@Override
protected synchronized void terminate(IOException e) {
super.terminate(e);
proc.destroy();
// the stderr copier should exit by itself
}
@Override
public synchronized void close() throws IOException {
super.close();
// wait for Maven to complete
try {
proc.waitFor();
thread.join();
} catch (InterruptedException e) {
// process the interrupt later
Thread.currentThread().interrupt();
}
}
};
}
use of hudson.remoting.Channel in project hudson-2.x by hudson.
the class ConnectionActivityMonitor method execute.
protected void execute(TaskListener listener) throws IOException, InterruptedException {
if (!enabled)
return;
long now = System.currentTimeMillis();
for (Computer c : Hudson.getInstance().getComputers()) {
VirtualChannel ch = c.getChannel();
if (ch instanceof Channel) {
Channel channel = (Channel) ch;
if (now - channel.getLastHeard() > TIME_TILL_PING) {
// haven't heard from this slave for a while.
Long lastPing = (Long) channel.getProperty(ConnectionActivityMonitor.class);
if (lastPing != null && now - lastPing > TIMEOUT) {
LOGGER.info("Repeated ping attempts failed on " + c.getName() + ". Disconnecting");
c.disconnect(OfflineCause.create(Messages._ConnectionActivityMonitor_OfflineCause()));
} else {
// send a ping. if we receive a reply, it will be reflected in the next getLastHeard() call.
channel.callAsync(PING_COMMAND);
if (lastPing == null)
channel.setProperty(ConnectionActivityMonitor.class, now);
}
} else {
// we are receiving data nicely
channel.setProperty(ConnectionActivityMonitor.class, null);
}
}
}
}
use of hudson.remoting.Channel in project hudson-2.x by hudson.
the class SlaveComputer method closeChannel.
/**
* If still connected, disconnect.
*/
private void closeChannel() {
// TODO: race condition between this and the setChannel method.
Channel c = channel;
channel = null;
isUnix = null;
if (c != null) {
try {
c.close();
} catch (IOException e) {
logger.log(Level.SEVERE, "Failed to terminate channel to " + getDisplayName(), e);
}
}
for (ComputerListener cl : ComputerListener.all()) cl.onOffline(this);
}
use of hudson.remoting.Channel in project hudson-2.x by hudson.
the class SlaveComputer method setChannel.
/**
* Creates a {@link Channel} from the given stream and sets that to this slave.
*
* @param in
* Stream connected to the remote "slave.jar". It's the caller's responsibility to do
* buffering on this stream, if that's necessary.
* @param out
* Stream connected to the remote peer. It's the caller's responsibility to do
* buffering on this stream, if that's necessary.
* @param launchLog
* If non-null, receive the portion of data in <tt>is</tt> before
* the data goes into the "binary mode". This is useful
* when the established communication channel might include some data that might
* be useful for debugging/trouble-shooting.
* @param listener
* Gets a notification when the channel closes, to perform clean up. Can be null.
* By the time this method is called, the cause of the termination is reported to the user,
* so the implementation of the listener doesn't need to do that again.
*/
public void setChannel(InputStream in, OutputStream out, OutputStream launchLog, Channel.Listener listener) throws IOException, InterruptedException {
if (this.channel != null)
throw new IllegalStateException("Already connected");
final TaskListener taskListener = new StreamTaskListener(launchLog);
PrintStream log = taskListener.getLogger();
Channel channel = new Channel(nodeName, threadPoolForRemoting, Channel.Mode.NEGOTIATE, in, out, launchLog);
channel.addListener(new Channel.Listener() {
@Override
public void onClosed(Channel c, IOException cause) {
SlaveComputer.this.channel = null;
// Orderly shutdown will have null exception
if (cause != null) {
offlineCause = new ChannelTermination(cause);
cause.printStackTrace(taskListener.error("Connection terminated"));
} else {
taskListener.getLogger().println("Connection terminated");
}
launcher.afterDisconnect(SlaveComputer.this, taskListener);
}
});
if (listener != null)
channel.addListener(listener);
String slaveVersion = channel.call(new SlaveVersion());
log.println("Slave.jar version: " + slaveVersion);
boolean _isUnix = channel.call(new DetectOS());
log.println(_isUnix ? hudson.model.Messages.Slave_UnixSlave() : hudson.model.Messages.Slave_WindowsSlave());
String defaultCharsetName = channel.call(new DetectDefaultCharset());
String remoteFs = getNode().getRemoteFS();
if (_isUnix && !remoteFs.contains("/") && remoteFs.contains("\\"))
log.println("WARNING: " + remoteFs + " looks suspiciously like Windows path. Maybe you meant " + remoteFs.replace('\\', '/') + "?");
FilePath root = new FilePath(channel, getNode().getRemoteFS());
channel.call(new SlaveInitializer());
channel.call(new WindowsSlaveInstaller(remoteFs));
for (ComputerListener cl : ComputerListener.all()) cl.preOnline(this, channel, root, taskListener);
offlineCause = null;
// update the data structure atomically to prevent others from seeing a channel that's not properly initialized yet
synchronized (channelLock) {
if (this.channel != null) {
// check again. we used to have this entire method in a big sycnhronization block,
// but Channel constructor blocks for an external process to do the connection
// if CommandLauncher is used, and that cannot be interrupted because it blocks at InputStream.
// so if the process hangs, it hangs the thread in a lock, and since Hudson will try to relaunch,
// we'll end up queuing the lot of threads in a pseudo deadlock.
// This implementation prevents that by avoiding a lock. HUDSON-1705 is likely a manifestation of this.
channel.close();
throw new IllegalStateException("Already connected");
}
isUnix = _isUnix;
numRetryAttempt = 0;
this.channel = channel;
defaultCharset = Charset.forName(defaultCharsetName);
}
for (ComputerListener cl : ComputerListener.all()) cl.onOnline(this, taskListener);
log.println("Slave successfully connected and online");
Hudson.getInstance().getQueue().scheduleMaintenance();
}
Aggregations