[sctp-dev] [Fwd: RE: IAE multiple sends]
Christopher Hegarty -Sun Microsystems Ireland
Christopher.Hegarty at Sun.COM
Fri Jan 15 02:52:18 PST 2010
[Forwarding because the original message did not make it]
-------- Original Message --------
Subject: RE: IAE multiple sends
Date: Thu, 14 Jan 2010 12:12:47 -0500
From: Bruce Buffam <bbuffam at rim.com>
To: sctp-dev at openjdk.java.net
Hi Chris,
I have test code that sends a sequence of data packets, generated
consecutively from a common byte array, such that on each send a new
ByteBuffer is wrapped on the next portion of the byte array.
Consistently, the second packet sent (the one with an offset other than
0 triggers the following exception from within SctpChannel.send,
regardless of the size of the packets sent
The test code looks like the following:
byte data[128];
.
.
.
for (int i = 0; i < data.length;) {
int length = 64;
cc.write(ChannelBuffers.wrappedBuffer(data, i,
length),messageInfo);
i += length;
}
This code loops around, wrapping the data in a ChannelBuffer using the
function ChannelBuffers.wrappedBuffer, and then scheduling each
ChannelBuffer for transmission via the write function. If the data
starts at offset 0, but does not encompass all of the contents in the
byte array, data, the ChannelBuffer will be instantiated as a
TruncatedChannelBuffer. Otherwise, the ChannelBuffer is instantiated as
SlicedChannelBuffer. A SlicedChannelBuffer stores the offset into the
underlying byte array in integer field named, adjustment.
Inside the writer thread, the following sequence ensues:
* *
.
.
.
ByteBuffer sendBuf = buf.toByteBuffer();
* *
if (!sendBuf.hasRemaining())
break;
localWrittenBytes += channel.socket.send(
sendBuf, messageInfo);
.
.
.
The function SlicedChannelBuffer.toByteBuffer does the conversion of the
ChannelBuffer to a ChannelBuffer executing the following:
public ByteBuffer toByteBuffer(int index, int length) {
checkIndex(index, length);
return buffer.toByteBuffer(index + adjustment, length);
}
…setting the offset to adjustment + index, and
ChannelBuffer.toByteBuffer does the final conversion to a ByteBuffer as
follows:
public ByteBuffer toByteBuffer(int index, int length) {
return ByteBuffer.wrap(array, index, length).order(order());
}
The error consistently occurs on the second message sent from the
underlying data array. As you can see from the following trace where
the underlying data array consists of 128 bytes, and the test loop is
traversing the byte array creating a sequence of 64 byte messages, the
individual ByteBuffers seem to be formatted correctly, with adjustment
reflected in the pos value:
1st Buffer
java.nio.HeapByteBuffer[pos=0 lim=64 cap=128]
2nd Buffer
java.nio.HeapByteBuffer[pos=64 lim=128 cap=128]
however, on the second buffer in the sequence, I get the following
exception from within the send function.
java.lang.IllegalArgumentException
at java.nio.Buffer.position(Buffer.java:236)
at
sun.nio.ch.SctpChannelImpl.sendFromNativeBuffer(SctpChannelImpl.java:1032)
at sun.nio.ch.SctpChannelImpl.send(SctpChannelImpl.java:1008)
at sun.nio.ch.SctpChannelImpl.send(SctpChannelImpl.java:972)
at
org.jboss.netty.channel.socket.nio.NioSctpWorker.writeNow(NioSctpWorker.java:517)
at
org.jboss.netty.channel.socket.nio.NioSctpWorker.write(NioSctpWorker.java:430)
at
org.jboss.netty.channel.socket.nio.NioSctpSocketChannel$WriteTask.run(NioSctpSocketChannel.java:503)
at
org.jboss.netty.channel.socket.nio.NioSctpWorker.processWriteTaskQueue(NioSctpWorker.java:307)
at
org.jboss.netty.channel.socket.nio.NioSctpWorker.run(NioSctpWorker.java:238)
at
org.jboss.netty.util.internal.IoWorkerRunnable.run(IoWorkerRunnable.java:46)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:717)
I can reproduce this problem consistently while varying the size of the
data array, and varying the size of each message to be generated from
the array, the problem still occurs on the second iteration of the test
loop. The first instance wherein pos ~= 0?
If I change the loop to instead copy the data from the underlying data
array, thus resulting in ByteBuffers that wrap from the start of the
data array ala the following trace:
1st Buffer
java.nio.HeapByteBuffer[pos=0 lim=64 cap=64]
2nd Buffer
java.nio.HeapByteBuffer[pos=0 lim=64 cap=64]
…it executes without exception.
Hope this helps.
Rgds,
Bruce
More information about the sctp-dev
mailing list