public interface Pipe extends Flushable, Closeable, ObjectInput, ObjectOutput, Link
asynchronous remote method. Pipes can remain open as long as
the session is open, and all pipes are closed when the session is
closed. Here's an example remote method declaration which uses a pipe:
@Asynchronous Pipe uploadFile(String name, Pipe pipe) throws RemoteException;The remote method declaration requires the return type to be a pipe and one parameter must also be a pipe. The client-side invocation of the remote method simply passes null for the pipe parameter, and the server-side implementation returns null instead of a pipe. Example client call:
Pipe pipe = server.uploadFile("notes.txt", null);
byte[] notes = ...
pipe.writeInt(notes.length);
pipe.write(notes);
pipe.close();
The remote method implementation might look like this:
public Pipe uploadFile(String name, Pipe pipe) {
byte[] notes = new byte[pipe.readInt()];
pipe.readFully(notes);
pipe.close();
...
return null;
}
Pipes are an extension of the remote method invocation itself, which is why
only one pipe can be established per call. Any arguments which were passed
along with the pipe are written to the same underlying object stream. For
long-lived pipes, be sure to call reset occasionally to allow
any previously written objects to be freed.
If the pipe is used to pass additional method arguments, consider
declaring the method with the eventual calling
mode. By calling flush after all arguments are written, the
number of transported packets is reduced. For the above example, the remote
method can be declared as:
@Asynchronous(CallMode.EVENTUAL) Pipe uploadFile(String name, Pipe pipe) throws RemoteException;The example client call doesn't need to do anything different, since closing the pipe implicitly flushes it. If the server is required to return a value over the pipe, then the client call might be written as:
Pipe pipe = server.uploadFile("notes.txt", null);
byte[] notes = ...
pipe.writeInt(notes.length);
pipe.write(notes);
// Flush to ensure arguments and file are transported.
pipe.flush();
// Read server response.
Object response = pipe.readObject();
pipe.close();
Methods which use pipes may also utilize timeout
annotations. A timeout task is started when the remote method is invoked,
and it must be explicitly cancelled upon receiving
the pipe. Timeout tasks may also be explicitly started
without requiring the annotation.
Because pipes are bidirectional, extra communication overhead is required
to support safe connection recycling. The request/reply call mode requires less overhead, and is more suitable for
short-lived pipes. A request/reply pipe starts in "request" mode, and then
it switches to "reply" mode. Initially, the client can write to the pipe,
and the server can read from the pipe. As soon as the client performs a
read, it automatically flushes the pipe and then it can only perform further
reads. Attempting to write again causes an IOException to be thrown.
Likewise, as soon as the server performs a write, it cannot read again. As
with normal pipes, both endpoints must close the pipe in order for the
connection resource to be fully recycled.
Request/reply pipes cannot be efficiently closed by the remote server until the pipe is in reply mode. Closing the pipe prematurely requires that all request input be automatically drained. If the request is of an unbounded size, then the server has no means to effectively abort it. Normal pipes should be used for this case instead.
| Modifier and Type | Method and Description |
|---|---|
boolean |
cancelTimeout()
Cancels a timeout task which was started by
startTimeout or an initial timeout when using the eventual calling mode. |
void |
close()
Closes both the input and output of the pipe.
|
void |
flush()
Flushes the pipe by writing any buffered output to the transport layer.
|
InputStream |
getInputStream()
Returns the pipe's InputStream which also implements ObjectInput.
|
OutputStream |
getOutputStream()
Returns the pipe's OutputStream which also implements ObjectOutput.
|
Throwable |
readThrowable()
Reads a Throwable which was written via writeThrowable, which may be null.
|
void |
reset()
Disregard the state of any objects already written to the pipe, allowing
them to get freed.
|
boolean |
startTimeout(long timeout,
TimeUnit unit)
Starts a task which forcibly closes this pipe after the timeout has
elapsed, unless it is
cancelled in time. |
void |
writeThrowable(Throwable t)
Writes the given Throwable with additional remote information.
|
available, read, read, read, readObject, skipreadBoolean, readByte, readChar, readDouble, readFloat, readFully, readFully, readInt, readLine, readLong, readShort, readUnsignedByte, readUnsignedShort, readUTF, skipByteswrite, write, write, writeObjectwriteBoolean, writeByte, writeBytes, writeChar, writeChars, writeDouble, writeFloat, writeInt, writeLong, writeShort, writeUTFgetLocalAddress, getRemoteAddressInputStream getInputStream()
OutputStream getOutputStream()
Throwable readThrowable() throws IOException, ReconstructedException
IOExceptionReconstructedExceptionvoid writeThrowable(Throwable t) throws IOException
IOExceptionvoid reset()
throws IOException
IOExceptionvoid flush()
throws IOException
flush in interface Flushableflush in interface ObjectOutputIOExceptionboolean startTimeout(long timeout,
TimeUnit unit)
throws IOException
cancelled in time. If a
timeout is already in progress when this method is called, it is
replaced with a new timeout.IOException - if task could not be scheduledboolean cancelTimeout()
startTimeout or an initial timeout when using the eventual calling mode. If no timeout task exists when
this method is called, it does nothing and returns true.void close()
throws IOException
close in interface AutoCloseableclose in interface Closeableclose in interface ObjectInputclose in interface ObjectOutputIOExceptionCopyright © 2006–2015 Cojen. All rights reserved.