hudson.remoting
Class Channel

java.lang.Object
  extended by hudson.remoting.Channel
All Implemented Interfaces:
VirtualChannel

public class Channel
extends java.lang.Object
implements VirtualChannel

Represents a communication channel to the remote peer.

A Channel is a mechanism for two JVMs to communicate over bi-directional InputStream/OutputStream pair. Channel represents an endpoint of the stream, and thus two Channels are always used in a pair.

Communication is established as soon as two Channel instances are created at the end fo the stream pair until the stream is terminated via close().

The basic unit of remoting is an executable Callable object. An application can create a Callable object, and execute it remotely by using the call(Callable) method or callAsync(Callable) method.

In this sense, Channel is a mechanism to delegate/offload computation to other JVMs and somewhat like an agent system. This is bit different from remoting technologies like CORBA or web services, where the server exposes a certain functionality that clients invoke.

Callable object, as well as the return value / exceptions, are transported by using Java serialization. All the necessary class files are also shipped over Channel on-demand, so there's no need to pre-deploy such classes on both JVMs.

Implementor's Note

Channel builds its features in a layered model. Its higher-layer features are built on top of its lower-layer features, and they are called layer-0, layer-1, etc.

Author:
Kohsuke Kawaguchi

Nested Class Summary
static class Channel.Listener
          Callback "interface" for changes in the state of Channel.
static class Channel.Mode
          Communication mode.
 
Field Summary
 java.util.concurrent.atomic.AtomicInteger classLoadingCount
          Total counts of remote classloading activities.
 java.util.concurrent.atomic.AtomicLong classLoadingTime
          Total number of nanoseconds spent for remote class loading.
static int PIPE_WINDOW_SIZE
           
 Capability remoteCapability
          Capability of the remote Channel.
 java.util.concurrent.atomic.AtomicInteger resourceLoadingCount
          Total count of remote resource loading.
 java.util.concurrent.atomic.AtomicLong resourceLoadingTime
          Total number of nanoseconds spent for remote resource loading.
 
Constructor Summary
Channel(java.lang.String name, java.util.concurrent.ExecutorService exec, Channel.Mode mode, java.io.InputStream is, java.io.OutputStream os)
           
Channel(java.lang.String name, java.util.concurrent.ExecutorService exec, Channel.Mode mode, java.io.InputStream is, java.io.OutputStream os, java.io.OutputStream header)
           
Channel(java.lang.String name, java.util.concurrent.ExecutorService exec, Channel.Mode mode, java.io.InputStream is, java.io.OutputStream os, java.io.OutputStream header, boolean restricted)
           
Channel(java.lang.String name, java.util.concurrent.ExecutorService exec, Channel.Mode mode, java.io.InputStream is, java.io.OutputStream os, java.io.OutputStream header, boolean restricted, java.lang.ClassLoader base)
          Creates a new channel.
Channel(java.lang.String name, java.util.concurrent.ExecutorService exec, java.io.InputStream is, java.io.OutputStream os)
           
Channel(java.lang.String name, java.util.concurrent.ExecutorService exec, java.io.InputStream is, java.io.OutputStream os, java.io.OutputStream header)
           
 
Method Summary
 void addListener(Channel.Listener l)
          Registers a new Channel.Listener.
<V,T extends java.lang.Throwable>
V
call(Callable<V,T> callable)
          Makes a remote procedure call.
<V,T extends java.lang.Throwable>
Future<V>
callAsync(Callable<V,T> callable)
          Makes an asynchronous remote procedure call.
 void close()
          Performs an orderly shut down of this channel (and the remote peer.)
 void close(java.lang.Throwable diagnosis)
          Closes the channel.
 ListeningPort createLocalToRemotePortForwarding(int recvPort, java.lang.String forwardHost, int forwardPort)
          Starts a local to remote port forwarding (the equivalent of "ssh -L").
 ListeningPort createRemoteToLocalPortForwarding(int recvPort, java.lang.String forwardHost, int forwardPort)
          Starts a remote to local port forwarding (the equivalent of "ssh -R").
static Channel current()
          This method can be invoked during the serialization/deserialization of objects when they are transferred to the remote Channel, as well as during Callable.call() is invoked.
 void dumpExportTable(java.io.PrintWriter w)
          Dumps the list of exported objects and their allocation traces to the given output.
<T> T
export(java.lang.Class<T> type, T instance)
          Exports an object for remoting to the other Channel by creating a remotable proxy.
 long getLastHeard()
           
<T> T
getProperty(ChannelProperty<T> key)
           
 java.lang.Object getProperty(java.lang.Object key)
          Gets the application specific property set by setProperty(Object, Object).
<T> T
getRemoteProperty(ChannelProperty<T> key)
           
 java.lang.Object getRemoteProperty(java.lang.Object key)
          Gets the property set on the remote peer.
 java.io.OutputStream getUnderlyingOutput()
          Deprecated. Future version of the remoting module may add other modes of creating channel that doesn't involve stream pair. Therefore, we aren't committing to this method. This method isn't a part of the committed API of the channel class.
 boolean isRestricted()
          Returns true if this channel is currently does not load classes from the remote peer.
 void join()
          Waits for this Channel to be closed down.
 void join(long timeout)
          Waits for this Channel to be closed down, but only up the given milliseconds.
 void pin(java.lang.Object instance)
          Increase reference count so much to effectively prevent de-allocation.
 void pinClassLoader(java.lang.ClassLoader cl)
          Pin down the exported classloader.
 boolean preloadJar(Callable<?,?> classLoaderRef, java.lang.Class... classesInJar)
          Preloads jar files on the remote side.
 boolean preloadJar(java.lang.ClassLoader local, java.lang.Class... classesInJar)
           
 boolean preloadJar(java.lang.ClassLoader local, java.net.URL... jars)
           
 boolean removeListener(Channel.Listener l)
          Removes a listener.
 void resetPerformanceCounters()
          Resets all the performance counters.
<T> T
setProperty(ChannelProperty<T> key, T value)
           
 java.lang.Object setProperty(java.lang.Object key, java.lang.Object value)
          Sets the property value on this side of the channel.
 void setRestricted(boolean b)
           
 hudson.remoting.ExportTable.ExportList startExportRecording()
           
 void syncIO()
          Blocks until all the I/O packets sent before this gets fully executed by the remote side, then return.
 void syncLocalIO()
          Blocks until all the I/O packets sent from remote is fully locally executed, then return.
protected  void terminate(java.io.IOException e)
          Aborts the connection in response to an error.
 java.lang.String toString()
           
<T> T
waitForProperty(ChannelProperty<T> key)
           
 java.lang.Object waitForProperty(java.lang.Object key)
          Works like getProperty(Object) but wait until some value is set by someone.
<T> T
waitForRemoteProperty(ChannelProperty<T> key)
           
 java.lang.Object waitForRemoteProperty(java.lang.Object key)
          Gets the property set on the remote peer.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

classLoadingTime

public final java.util.concurrent.atomic.AtomicLong classLoadingTime
Total number of nanoseconds spent for remote class loading.

Remote code execution often results in classloading activity (more precisely, when the remote peer requests some computation on this channel, this channel often has to load necessary classes from the remote peer.)

This counter represents the total amount of time this channel had to spend loading classes from the remote peer. The time measurement doesn't include the time locally spent to actually define the class (as the local classloading would have incurred the same cost.)


classLoadingCount

public final java.util.concurrent.atomic.AtomicInteger classLoadingCount
Total counts of remote classloading activities. Used in a pair with classLoadingTime.


resourceLoadingTime

public final java.util.concurrent.atomic.AtomicLong resourceLoadingTime
Total number of nanoseconds spent for remote resource loading.

See Also:
classLoadingTime

resourceLoadingCount

public final java.util.concurrent.atomic.AtomicInteger resourceLoadingCount
Total count of remote resource loading.

See Also:
classLoadingCount

remoteCapability

public final Capability remoteCapability
Capability of the remote Channel.


PIPE_WINDOW_SIZE

public static final int PIPE_WINDOW_SIZE
Constructor Detail

Channel

public Channel(java.lang.String name,
               java.util.concurrent.ExecutorService exec,
               java.io.InputStream is,
               java.io.OutputStream os)
        throws java.io.IOException
Throws:
java.io.IOException

Channel

public Channel(java.lang.String name,
               java.util.concurrent.ExecutorService exec,
               Channel.Mode mode,
               java.io.InputStream is,
               java.io.OutputStream os)
        throws java.io.IOException
Throws:
java.io.IOException

Channel

public Channel(java.lang.String name,
               java.util.concurrent.ExecutorService exec,
               java.io.InputStream is,
               java.io.OutputStream os,
               java.io.OutputStream header)
        throws java.io.IOException
Throws:
java.io.IOException

Channel

public Channel(java.lang.String name,
               java.util.concurrent.ExecutorService exec,
               Channel.Mode mode,
               java.io.InputStream is,
               java.io.OutputStream os,
               java.io.OutputStream header)
        throws java.io.IOException
Throws:
java.io.IOException

Channel

public Channel(java.lang.String name,
               java.util.concurrent.ExecutorService exec,
               Channel.Mode mode,
               java.io.InputStream is,
               java.io.OutputStream os,
               java.io.OutputStream header,
               boolean restricted)
        throws java.io.IOException
Throws:
java.io.IOException

Channel

public Channel(java.lang.String name,
               java.util.concurrent.ExecutorService exec,
               Channel.Mode mode,
               java.io.InputStream is,
               java.io.OutputStream os,
               java.io.OutputStream header,
               boolean restricted,
               java.lang.ClassLoader base)
        throws java.io.IOException
Creates a new channel.

Parameters:
name - Human readable name of this channel. Used for debug/logging. Can be anything.
exec - Commands sent from the remote peer will be executed by using this Executor.
mode - The encoding to be used over the stream.
is - Stream connected to the remote peer. It's the caller's responsibility to do buffering on this stream, if that's necessary.
os - Stream connected to the remote peer. It's the caller's responsibility to do buffering on this stream, if that's necessary.
header - If non-null, receive the portion of data in is 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.
base - Specify the classloader used for deserializing remote commands. This is primarily related to getRemoteProperty(Object). Sometimes two parties communicate over a channel and pass objects around as properties, but those types might not be visible from the classloader loading the Channel class. In such a case, specify a classloader so that those classes resolve. If null, Channel.class.getClassLoader() is used.
restricted - If true, this channel won't accept Commands that allow the remote end to execute arbitrary closures --- instead they can only call methods on objects that are exported by this channel. This also prevents the remote end from loading classes into JVM. Note that it still allows the remote end to deserialize arbitrary object graph (provided that all the classes are already available in this JVM), so exactly how safe the resulting behavior is is up to discussion.
Throws:
java.io.IOException
Method Detail

export

public <T> T export(java.lang.Class<T> type,
                    T instance)
Exports an object for remoting to the other Channel by creating a remotable proxy.

All the parameters and return values must be serializable.

Specified by:
export in interface VirtualChannel
Parameters:
type - Interface to be remoted.
Returns:
the proxy object that implements T. This object can be transfered to the other Channel, and calling methods on it from the remote side will invoke the same method on the given local instance object.

pin

public void pin(java.lang.Object instance)
Increase reference count so much to effectively prevent de-allocation.

See Also:
ExportTable.Entry.pin()

pinClassLoader

public void pinClassLoader(java.lang.ClassLoader cl)
Pin down the exported classloader.


preloadJar

public boolean preloadJar(Callable<?,?> classLoaderRef,
                          java.lang.Class... classesInJar)
                   throws java.io.IOException,
                          java.lang.InterruptedException
Preloads jar files on the remote side.

This is a performance improvement method that can be safely ignored if your goal is just to make things working.

Normally, classes are transferred over the network one at a time, on-demand. This design is mainly driven by how Java classloading works — we can't predict what classes will be necessarily upfront very easily.

Classes are loaded only once, so for long-running Channel, this is normally an acceptable overhead. But sometimes, for example when a channel is short-lived, or when you know that you'll need a majority of classes in certain jar files, then it is more efficient to send a whole jar file over the network upfront and thereby avoiding individual class transfer over the network.

That is what this method does. It ensures that a series of jar files are copied to the remote side (AKA "preloading.") Classloading will consult the preloaded jars before performing network transfer of class files.

Parameters:
classLoaderRef - This parameter is used to identify the remote classloader that will prefetch the specified jar files. That is, prefetching will ensure that prefetched jars will kick in when this Callable object is actually executed remote side.

RemoteClassLoaders are created wisely, one per local ClassLoader, so this parameter doesn't have to be exactly the same Callable to be executed later — it just has to be of the same class.

classesInJar - Class objects that identify jar files to be preloaded. Jar files that contain the specified classes will be preloaded into the remote peer. You just need to specify one class per one jar.
Returns:
true if the preloading actually happened. false if all the jars are already preloaded. This method is implemented in such a way that unnecessary jar file transfer will be avoided, and the return value will tell you if this optimization kicked in. Under normal circumstances your program shouldn't depend on this return value. It's just a hint.
Throws:
java.io.IOException - if the preloading fails.
java.lang.InterruptedException

preloadJar

public boolean preloadJar(java.lang.ClassLoader local,
                          java.lang.Class... classesInJar)
                   throws java.io.IOException,
                          java.lang.InterruptedException
Throws:
java.io.IOException
java.lang.InterruptedException

preloadJar

public boolean preloadJar(java.lang.ClassLoader local,
                          java.net.URL... jars)
                   throws java.io.IOException,
                          java.lang.InterruptedException
Throws:
java.io.IOException
java.lang.InterruptedException

call

public <V,T extends java.lang.Throwable> V call(Callable<V,T> callable)
       throws java.io.IOException,
              T extends java.lang.Throwable,
              java.lang.InterruptedException
Makes a remote procedure call.

Sends Callable to the remote system, executes it, and returns its result.

Specified by:
call in interface VirtualChannel
Throws:
java.io.IOException - If there's any error in the communication between Channels.
java.lang.InterruptedException - If the current thread is interrupted while waiting for the completion.
T extends java.lang.Throwable

callAsync

public <V,T extends java.lang.Throwable> Future<V> callAsync(Callable<V,T> callable)
                    throws java.io.IOException
Makes an asynchronous remote procedure call.

Similar to VirtualChannel.call(Callable) but returns immediately. The result of the Callable can be obtained through the Future object.

Specified by:
callAsync in interface VirtualChannel
Returns:
The Future object that can be used to wait for the completion.
Throws:
java.io.IOException - If there's an error during the communication.

terminate

protected void terminate(java.io.IOException e)
Aborts the connection in response to an error.

Parameters:
e - The error that caused the connection to be aborted. Never null.

addListener

public void addListener(Channel.Listener l)
Registers a new Channel.Listener.

See Also:
removeListener(Listener)

removeListener

public boolean removeListener(Channel.Listener l)
Removes a listener.

Returns:
false if the given listener has not been registered to begin with.

join

public void join()
          throws java.lang.InterruptedException
Waits for this Channel to be closed down. The close-down of a Channel might be initiated locally or remotely.

Specified by:
join in interface VirtualChannel
Throws:
java.lang.InterruptedException - If the current thread is interrupted while waiting for the completion.

isRestricted

public boolean isRestricted()
Returns true if this channel is currently does not load classes from the remote peer.


setRestricted

public void setRestricted(boolean b)

join

public void join(long timeout)
          throws java.lang.InterruptedException
Waits for this Channel to be closed down, but only up the given milliseconds.

Specified by:
join in interface VirtualChannel
Throws:
java.lang.InterruptedException - If the current thread is interrupted while waiting for the completion.
Since:
1.299

resetPerformanceCounters

public void resetPerformanceCounters()
Resets all the performance counters.


close

public void close()
           throws java.io.IOException
Performs an orderly shut down of this channel (and the remote peer.)

Specified by:
close in interface VirtualChannel
Throws:
java.io.IOException - if the orderly shut-down failed.

close

public void close(java.lang.Throwable diagnosis)
           throws java.io.IOException
Closes the channel.

Parameters:
diagnosis - If someone (either this side or the other side) tries to use a channel that's already closed, they'll get a stack trace indicating that the channel has already been closed. This diagnosis, if provided, will further chained to that exception, providing more contextual information about why the channel was closed.
Throws:
java.io.IOException
Since:
2.8

getProperty

public java.lang.Object getProperty(java.lang.Object key)
Gets the application specific property set by setProperty(Object, Object). These properties are also accessible from the remote channel via getRemoteProperty(Object).

This mechanism can be used for one side to discover contextual objects created by the other JVM (as opposed to executing Callable, which cannot have any reference to the context of the remote Channel.


getProperty

public <T> T getProperty(ChannelProperty<T> key)

waitForProperty

public java.lang.Object waitForProperty(java.lang.Object key)
                                 throws java.lang.InterruptedException
Works like getProperty(Object) but wait until some value is set by someone.

Throws:
java.lang.InterruptedException

waitForProperty

public <T> T waitForProperty(ChannelProperty<T> key)
                  throws java.lang.InterruptedException
Throws:
java.lang.InterruptedException

setProperty

public java.lang.Object setProperty(java.lang.Object key,
                                    java.lang.Object value)
Sets the property value on this side of the channel.

See Also:
getProperty(Object)

setProperty

public <T> T setProperty(ChannelProperty<T> key,
                         T value)

getRemoteProperty

public java.lang.Object getRemoteProperty(java.lang.Object key)
Gets the property set on the remote peer.

Returns:
null if the property of the said key isn't set.

getRemoteProperty

public <T> T getRemoteProperty(ChannelProperty<T> key)

waitForRemoteProperty

public java.lang.Object waitForRemoteProperty(java.lang.Object key)
                                       throws java.lang.InterruptedException
Gets the property set on the remote peer. This method blocks until the property is set by the remote peer.

Throws:
java.lang.InterruptedException

waitForRemoteProperty

public <T> T waitForRemoteProperty(ChannelProperty<T> key)
                        throws java.lang.InterruptedException
Throws:
java.lang.InterruptedException

getUnderlyingOutput

public java.io.OutputStream getUnderlyingOutput()
Deprecated. Future version of the remoting module may add other modes of creating channel that doesn't involve stream pair. Therefore, we aren't committing to this method. This method isn't a part of the committed API of the channel class.

Obtain the output stream passed to the constructor.

Returns:
While the current version always return a non-null value, the caller must not make that assumption for the above reason. This method may return null in the future version to indicate that the Channel is not sitting on top of a stream pair.

createLocalToRemotePortForwarding

public ListeningPort createLocalToRemotePortForwarding(int recvPort,
                                                       java.lang.String forwardHost,
                                                       int forwardPort)
                                                throws java.io.IOException,
                                                       java.lang.InterruptedException
Starts a local to remote port forwarding (the equivalent of "ssh -L").

Parameters:
recvPort - The port on this local machine that we'll listen to. 0 to let OS pick a random available port. If you specify 0, use ListeningPort.getPort() to figure out the actual assigned port.
forwardHost - The remote host that the connection will be forwarded to. Connection to this host will be made from the other JVM that this Channel represents.
forwardPort - The remote port that the connection will be forwarded to.
Returns:
Throws:
java.io.IOException
java.lang.InterruptedException

createRemoteToLocalPortForwarding

public ListeningPort createRemoteToLocalPortForwarding(int recvPort,
                                                       java.lang.String forwardHost,
                                                       int forwardPort)
                                                throws java.io.IOException,
                                                       java.lang.InterruptedException
Starts a remote to local port forwarding (the equivalent of "ssh -R").

Parameters:
recvPort - The port on the remote JVM (represented by this Channel) that we'll listen to. 0 to let OS pick a random available port. If you specify 0, use ListeningPort.getPort() to figure out the actual assigned port.
forwardHost - The remote host that the connection will be forwarded to. Connection to this host will be made from this JVM.
forwardPort - The remote port that the connection will be forwarded to.
Returns:
Throws:
java.io.IOException
java.lang.InterruptedException

syncIO

public void syncIO()
            throws java.io.IOException,
                   java.lang.InterruptedException
Blocks until all the I/O packets sent before this gets fully executed by the remote side, then return.

Throws:
java.io.IOException - If the remote doesn't support this operation, or if sync fails for other reasons.
java.lang.InterruptedException

syncLocalIO

public void syncLocalIO()
                 throws java.lang.InterruptedException
Description copied from interface: VirtualChannel
Blocks until all the I/O packets sent from remote is fully locally executed, then return.

Specified by:
syncLocalIO in interface VirtualChannel
Throws:
java.lang.InterruptedException

toString

public java.lang.String toString()
Overrides:
toString in class java.lang.Object

dumpExportTable

public void dumpExportTable(java.io.PrintWriter w)
                     throws java.io.IOException
Dumps the list of exported objects and their allocation traces to the given output.

Throws:
java.io.IOException

startExportRecording

public hudson.remoting.ExportTable.ExportList startExportRecording()

getLastHeard

public long getLastHeard()
See Also:
lastHeard

current

public static Channel current()
This method can be invoked during the serialization/deserialization of objects when they are transferred to the remote Channel, as well as during Callable.call() is invoked.

Returns:
null if the calling thread is not performing serialization.


Copyright © 2012. All Rights Reserved.