use of java.nio.channels.SelectionKey in project tomcat by apache.
the class NioBlockingSelector method write.
/**
* Performs a blocking write using the bytebuffer for data to be written
* If the <code>selector</code> parameter is null, then it will perform a busy write that could
* take up a lot of CPU cycles.
* @param buf ByteBuffer - the buffer containing the data, we will write as long as <code>(buf.hasRemaining()==true)</code>
* @param socket SocketChannel - the socket to write data to
* @param writeTimeout long - the timeout for this write operation in milliseconds, -1 means no timeout
* @return int - returns the number of bytes written
* @throws EOFException if write returns -1
* @throws SocketTimeoutException if the write times out
* @throws IOException if an IO Exception occurs in the underlying socket logic
*/
public int write(ByteBuffer buf, NioChannel socket, long writeTimeout) throws IOException {
SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
if (key == null)
throw new IOException("Key no longer registered");
KeyReference reference = keyReferenceStack.pop();
if (reference == null) {
reference = new KeyReference();
}
NioSocketWrapper att = (NioSocketWrapper) key.attachment();
int written = 0;
boolean timedout = false;
//assume we can write
int keycount = 1;
//start the timeout timer
long time = System.currentTimeMillis();
try {
while ((!timedout) && buf.hasRemaining()) {
if (keycount > 0) {
//only write if we were registered for a write
//write the data
int cnt = socket.write(buf);
if (cnt == -1)
throw new EOFException();
written += cnt;
if (cnt > 0) {
//reset our timeout timer
time = System.currentTimeMillis();
//we successfully wrote, try again without a selector
continue;
}
}
try {
if (att.getWriteLatch() == null || att.getWriteLatch().getCount() == 0)
att.startWriteLatch(1);
poller.add(att, SelectionKey.OP_WRITE, reference);
if (writeTimeout < 0) {
att.awaitWriteLatch(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
} else {
att.awaitWriteLatch(writeTimeout, TimeUnit.MILLISECONDS);
}
} catch (InterruptedException ignore) {
// Ignore
}
if (att.getWriteLatch() != null && att.getWriteLatch().getCount() > 0) {
//we got interrupted, but we haven't received notification from the poller.
keycount = 0;
} else {
//latch countdown has happened
keycount = 1;
att.resetWriteLatch();
}
if (writeTimeout > 0 && (keycount == 0))
timedout = (System.currentTimeMillis() - time) >= writeTimeout;
}
//while
if (timedout)
throw new SocketTimeoutException();
} finally {
poller.remove(att, SelectionKey.OP_WRITE);
if (timedout && reference.key != null) {
poller.cancelKey(reference.key);
}
reference.key = null;
keyReferenceStack.push(reference);
}
return written;
}
use of java.nio.channels.SelectionKey in project tomcat by apache.
the class NioBlockingSelector method read.
/**
* Performs a blocking read using the bytebuffer for data to be read
* If the <code>selector</code> parameter is null, then it will perform a busy read that could
* take up a lot of CPU cycles.
* @param buf ByteBuffer - the buffer containing the data, we will read as until we have read at least one byte or we timed out
* @param socket SocketChannel - the socket to write data to
* @param readTimeout long - the timeout for this read operation in milliseconds, -1 means no timeout
* @return int - returns the number of bytes read
* @throws EOFException if read returns -1
* @throws SocketTimeoutException if the read times out
* @throws IOException if an IO Exception occurs in the underlying socket logic
*/
public int read(ByteBuffer buf, NioChannel socket, long readTimeout) throws IOException {
SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
if (key == null)
throw new IOException("Key no longer registered");
KeyReference reference = keyReferenceStack.pop();
if (reference == null) {
reference = new KeyReference();
}
NioSocketWrapper att = (NioSocketWrapper) key.attachment();
int read = 0;
boolean timedout = false;
//assume we can read
int keycount = 1;
//start the timeout timer
long time = System.currentTimeMillis();
try {
while (!timedout) {
if (keycount > 0) {
//only read if we were registered for a read
read = socket.read(buf);
if (read != 0) {
break;
}
}
try {
if (att.getReadLatch() == null || att.getReadLatch().getCount() == 0)
att.startReadLatch(1);
poller.add(att, SelectionKey.OP_READ, reference);
if (readTimeout < 0) {
att.awaitReadLatch(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
} else {
att.awaitReadLatch(readTimeout, TimeUnit.MILLISECONDS);
}
} catch (InterruptedException ignore) {
// Ignore
}
if (att.getReadLatch() != null && att.getReadLatch().getCount() > 0) {
//we got interrupted, but we haven't received notification from the poller.
keycount = 0;
} else {
//latch countdown has happened
keycount = 1;
att.resetReadLatch();
}
if (readTimeout >= 0 && (keycount == 0))
timedout = (System.currentTimeMillis() - time) >= readTimeout;
}
//while
if (timedout)
throw new SocketTimeoutException();
} finally {
poller.remove(att, SelectionKey.OP_READ);
if (timedout && reference.key != null) {
poller.cancelKey(reference.key);
}
reference.key = null;
keyReferenceStack.push(reference);
}
return read;
}
use of java.nio.channels.SelectionKey in project tomcat by apache.
the class NioSelectorPool method read.
/**
* Performs a read using the bytebuffer for data to be read and a selector to register for events should
* you have the block=true.
* If the <code>selector</code> parameter is null, then it will perform a busy read that could
* take up a lot of CPU cycles.
* @param buf ByteBuffer - the buffer containing the data, we will read as until we have read at least one byte or we timed out
* @param socket SocketChannel - the socket to write data to
* @param selector Selector - the selector to use for blocking, if null then a busy read will be initiated
* @param readTimeout long - the timeout for this read operation in milliseconds, -1 means no timeout
* @param block - true if you want to block until data becomes available or timeout time has been reached
* @return int - returns the number of bytes read
* @throws EOFException if read returns -1
* @throws SocketTimeoutException if the read times out
* @throws IOException if an IO Exception occurs in the underlying socket logic
*/
public int read(ByteBuffer buf, NioChannel socket, Selector selector, long readTimeout, boolean block) throws IOException {
if (SHARED && block) {
return blockingSelector.read(buf, socket, readTimeout);
}
SelectionKey key = null;
int read = 0;
boolean timedout = false;
//assume we can write
int keycount = 1;
//start the timeout timer
long time = System.currentTimeMillis();
try {
while ((!timedout)) {
int cnt = 0;
if (keycount > 0) {
//only read if we were registered for a read
cnt = socket.read(buf);
if (cnt == -1) {
if (read == 0) {
read = -1;
}
break;
}
read += cnt;
//read some more
if (cnt > 0)
continue;
//we are done reading
if (cnt == 0 && (read > 0 || (!block)))
break;
}
if (selector != null) {
//register OP_WRITE to the selector
if (key == null)
key = socket.getIOChannel().register(selector, SelectionKey.OP_READ);
else
key.interestOps(SelectionKey.OP_READ);
if (readTimeout == 0) {
timedout = (read == 0);
} else if (readTimeout < 0) {
keycount = selector.select();
} else {
keycount = selector.select(readTimeout);
}
}
if (readTimeout > 0 && (selector == null || keycount == 0))
timedout = (System.currentTimeMillis() - time) >= readTimeout;
}
//while
if (timedout)
throw new SocketTimeoutException();
} finally {
if (key != null) {
key.cancel();
//removes the key from this selector
if (selector != null)
selector.selectNow();
}
}
return read;
}
use of java.nio.channels.SelectionKey in project tomcat by apache.
the class NioSelectorPool method write.
/**
* Performs a write using the bytebuffer for data to be written and a
* selector to block (if blocking is requested). If the
* <code>selector</code> parameter is null, and blocking is requested then
* it will perform a busy write that could take up a lot of CPU cycles.
* @param buf The buffer containing the data, we will write as long as <code>(buf.hasRemaining()==true)</code>
* @param socket The socket to write data to
* @param selector The selector to use for blocking, if null then a busy write will be initiated
* @param writeTimeout The timeout for this write operation in milliseconds, -1 means no timeout
* @param block <code>true</code> to perform a blocking write
* otherwise a non-blocking write will be performed
* @return int - returns the number of bytes written
* @throws EOFException if write returns -1
* @throws SocketTimeoutException if the write times out
* @throws IOException if an IO Exception occurs in the underlying socket logic
*/
public int write(ByteBuffer buf, NioChannel socket, Selector selector, long writeTimeout, boolean block) throws IOException {
if (SHARED && block) {
return blockingSelector.write(buf, socket, writeTimeout);
}
SelectionKey key = null;
int written = 0;
boolean timedout = false;
//assume we can write
int keycount = 1;
//start the timeout timer
long time = System.currentTimeMillis();
try {
while ((!timedout) && buf.hasRemaining()) {
int cnt = 0;
if (keycount > 0) {
//only write if we were registered for a write
//write the data
cnt = socket.write(buf);
if (cnt == -1)
throw new EOFException();
written += cnt;
if (cnt > 0) {
//reset our timeout timer
time = System.currentTimeMillis();
//we successfully wrote, try again without a selector
continue;
}
//don't block
if (cnt == 0 && (!block))
break;
}
if (selector != null) {
//register OP_WRITE to the selector
if (key == null)
key = socket.getIOChannel().register(selector, SelectionKey.OP_WRITE);
else
key.interestOps(SelectionKey.OP_WRITE);
if (writeTimeout == 0) {
timedout = buf.hasRemaining();
} else if (writeTimeout < 0) {
keycount = selector.select();
} else {
keycount = selector.select(writeTimeout);
}
}
if (writeTimeout > 0 && (selector == null || keycount == 0))
timedout = (System.currentTimeMillis() - time) >= writeTimeout;
}
//while
if (timedout)
throw new SocketTimeoutException();
} finally {
if (key != null) {
key.cancel();
//removes the key from this selector
if (selector != null)
selector.selectNow();
}
}
return written;
}
use of java.nio.channels.SelectionKey in project tomcat by apache.
the class SecureNioChannel method rehandshake.
/**
* Force a blocking handshake to take place for this key.
* This requires that both network and application buffers have been emptied out prior to this call taking place, or a
* IOException will be thrown.
* @param timeout - timeout in milliseconds for each socket operation
* @throws IOException - if an IO exception occurs or if application or network buffers contain data
* @throws SocketTimeoutException - if a socket operation timed out
*/
// key cannot be null
@SuppressWarnings("null")
public void rehandshake(long timeout) throws IOException {
//validate the network buffers are empty
if (netInBuffer.position() > 0 && netInBuffer.position() < netInBuffer.limit())
throw new IOException(sm.getString("channel.nio.ssl.netInputNotEmpty"));
if (netOutBuffer.position() > 0 && netOutBuffer.position() < netOutBuffer.limit())
throw new IOException(sm.getString("channel.nio.ssl.netOutputNotEmpty"));
if (!getBufHandler().isReadBufferEmpty())
throw new IOException(sm.getString("channel.nio.ssl.appInputNotEmpty"));
if (!getBufHandler().isWriteBufferEmpty())
throw new IOException(sm.getString("channel.nio.ssl.appOutputNotEmpty"));
handshakeComplete = false;
boolean isReadable = false;
boolean isWriteable = false;
boolean handshaking = true;
Selector selector = null;
SelectionKey key = null;
try {
sslEngine.beginHandshake();
handshakeStatus = sslEngine.getHandshakeStatus();
while (handshaking) {
int hsStatus = this.handshake(isReadable, isWriteable);
switch(hsStatus) {
case -1:
throw new EOFException(sm.getString("channel.nio.ssl.eofDuringHandshake"));
case 0:
handshaking = false;
break;
default:
{
long now = System.currentTimeMillis();
if (selector == null) {
selector = Selector.open();
key = getIOChannel().register(selector, hsStatus);
} else {
// null warning supressed
key.interestOps(hsStatus);
}
int keyCount = selector.select(timeout);
if (keyCount == 0 && ((System.currentTimeMillis() - now) >= timeout)) {
throw new SocketTimeoutException(sm.getString("channel.nio.ssl.timeoutDuringHandshake"));
}
isReadable = key.isReadable();
isWriteable = key.isWritable();
}
}
}
} catch (IOException x) {
throw x;
} catch (Exception cx) {
IOException x = new IOException(cx);
throw x;
} finally {
if (key != null)
try {
key.cancel();
} catch (Exception ignore) {
}
if (selector != null)
try {
selector.close();
} catch (Exception ignore) {
}
}
}
Aggregations