/** * Flush the buffer by looping until the {@link Buffer} is empty * * @param connection the {@link org.glassfish.grizzly.Connection}. * @param dstAddress the destination address. * @param message * @param currentResult the result of the write operation * @param timeout operation timeout value value * @param timeunit the timeout unit * @return The number of bytes written. * @throws java.io.IOException */ protected long write0( final NIOConnection connection, final SocketAddress dstAddress, final WritableMessage message, final WriteResult<WritableMessage, SocketAddress> currentResult, final long timeout, final TimeUnit timeunit) throws IOException { final SelectableChannel channel = connection.getChannel(); final long writeTimeout = TimeUnit.MILLISECONDS.convert(timeout, timeunit); SelectionKey key = null; Selector writeSelector = null; int attempts = 0; int bytesWritten = 0; try { synchronized (connection) { while (message.hasRemaining()) { long len = writeNow0(connection, dstAddress, message, currentResult); if (len > 0) { attempts = 0; bytesWritten += len; } else { attempts++; if (writeSelector == null) { writeSelector = transport.getTemporarySelectorIO().getSelectorPool().poll(); if (writeSelector == null) { // Continue using the main one. continue; } key = channel.register(writeSelector, SelectionKey.OP_WRITE); } else { writeSelector.selectedKeys().clear(); } if (writeSelector.select(writeTimeout) == 0) { if (attempts > 2) { throw new IOException("Client disconnected"); } } } } } } finally { transport.getTemporarySelectorIO().recycleTemporaryArtifacts(writeSelector, key); } return bytesWritten; }
/** * Method writes the {@link WritableMessage} to the specific address. * * @param connection the {@link org.glassfish.grizzly.Connection} to write to * @param dstAddress the destination address the <tt>message</tt> will be sent to * @param message the {@link WritableMessage}, from which the data will be written * @param completionHandler {@link org.glassfish.grizzly.CompletionHandler}, which will get * notified, when write will be completed */ public void write( Connection<SocketAddress> connection, SocketAddress dstAddress, WritableMessage message, CompletionHandler<WriteResult<WritableMessage, SocketAddress>> completionHandler, final org.glassfish.grizzly.asyncqueue.PushBackHandler pushBackHandler, long timeout, TimeUnit timeunit) { if (message == null) { failure(new IllegalStateException("Message cannot be null"), completionHandler); return; } if (connection == null || !(connection instanceof NIOConnection)) { failure( new IllegalStateException("Connection should be NIOConnection and cannot be null"), completionHandler); return; } final NIOConnection nioConnection = (NIOConnection) connection; final WriteResult<WritableMessage, SocketAddress> writeResult = WriteResult.create(connection, message, dstAddress, 0); try { write0(nioConnection, dstAddress, message, writeResult, timeout, timeunit); // Call PushBackHandler after data is written. // IMO It has more sense for blocking case if (pushBackHandler != null) { pushBackHandler.onAccept(connection, message); } if (completionHandler != null) { completionHandler.completed(writeResult); } message.release(); } catch (IOException e) { failure(e, completionHandler); } }