final NIOConnection nioConnection = (NIOConnection) connection;
// create and initialize the write queue record
final AsyncWriteQueueRecord queueRecord = createRecord(
nioConnection, message, completionHandler,
dstAddress, pushBackHandler,
!message.hasRemaining() || message.isExternal());
if (nioConnection == null) {
queueRecord.notifyFailure(new IOException("Connection is null"));
return;
}
if (!nioConnection.isOpen()) {
onWriteFailure(nioConnection, queueRecord,
nioConnection.getCloseReason().getCause());
return;
}
// Get connection async write queue
final TaskQueue<AsyncWriteQueueRecord> writeTaskQueue =
nioConnection.getAsyncWriteQueue();
final boolean isEmptyRecord = queueRecord.isEmptyRecord();
final int messageSize = message.remaining();
// For empty buffer reserve 1 byte space
final int bytesToReserve = isEmptyRecord ?
EMPTY_RECORD_SPACE_VALUE : messageSize;
final int pendingBytes = writeTaskQueue.reserveSpace(bytesToReserve);
final boolean isCurrent = (pendingBytes == bytesToReserve);
final boolean isLogFine = LOGGER.isLoggable(Level.FINEST);
if (isLogFine) {
doFineLog("AsyncQueueWriter.write connection={0} record={1} directWrite={2}",
nioConnection, queueRecord, isCurrent);
}
final Reentrant reentrants = Reentrant.getWriteReentrant();
try {
if (!reentrants.inc()) {
// Max number of reentrants is reached
queueRecord.setMessage(
cloneRecordIfNeeded(nioConnection, cloner, message));
if (isCurrent) { //current but not finished.
writeTaskQueue.setCurrentElement(queueRecord);
nioConnection.simulateIOEvent(IOEvent.WRITE);
} else {
writeTaskQueue.offer(queueRecord);
}
return;
}
if (isCurrent && isAllowDirectWrite) {
// If we can write directly - do it w/o creating queue record (simple)
final int written = messageSize > 0 ?
(int) write0(nioConnection, queueRecord) :
0;
final boolean isFinished = queueRecord.isFinished();
final int bytesToRelease = !isEmptyRecord ?
written :
(isFinished ? EMPTY_RECORD_SPACE_VALUE : 0);
final boolean isQueueEmpty =
(writeTaskQueue.releaseSpaceAndNotify(bytesToRelease) == 0);
if (isFinished) {
queueRecord.notifyCompleteAndRecycle();
if (!isQueueEmpty) {
nioConnection.simulateIOEvent(IOEvent.WRITE);
}
return;
}
}
queueRecord.setMessage(
cloneRecordIfNeeded(nioConnection, cloner, message));
if (isCurrent) { //current but not finished.
writeTaskQueue.setCurrentElement(queueRecord);
onReadyToWrite(nioConnection);