use of org.apache.tomcat.util.net.NioEndpoint.NioSocketWrapper 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 org.apache.tomcat.util.net.NioEndpoint.NioSocketWrapper 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;
}
Aggregations