Fix epoll spliceTo file descriptor with offset (#9369)
Motivation The AbstractEpollStreamChannel::spliceTo(FileDescriptor, ...) methods take an offset parameter but this was effectively ignored due to what looks like a typo in the corresponding JNI function impl. Instead it would always use the file's own native offset. Modification - Fix typo in netty_epoll_native_splice0() and offset accounting in AbstractEpollStreamChannel::SpliceFdTask. - Modify unit test to include an invocation of the public spliceTo method using non-zero offset. Result spliceTo FD methods work as expected when an offset is provided.
This commit is contained in:
parent
cd824e4e31
commit
1748352d98
@ -385,7 +385,7 @@ static jint netty_epoll_native_splice0(JNIEnv* env, jclass clazz, jint fd, jlong
|
||||
loff_t off_out = (loff_t) offOut;
|
||||
|
||||
loff_t* p_off_in = off_in >= 0 ? &off_in : NULL;
|
||||
loff_t* p_off_out = off_in >= 0 ? &off_out : NULL;
|
||||
loff_t* p_off_out = off_out >= 0 ? &off_out : NULL;
|
||||
|
||||
do {
|
||||
res = splice(fd, p_off_in, fdOut, p_off_out, (size_t) len, SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
|
||||
|
@ -205,7 +205,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im
|
||||
public final ChannelFuture spliceTo(final FileDescriptor ch, final int offset, final int len,
|
||||
final ChannelPromise promise) {
|
||||
checkPositiveOrZero(len, "len");
|
||||
checkPositiveOrZero(offset, "offser");
|
||||
checkPositiveOrZero(offset, "offset");
|
||||
if (config().getEpollMode() != EpollMode.LEVEL_TRIGGERED) {
|
||||
throw new IllegalStateException("spliceTo() supported only when using " + EpollMode.LEVEL_TRIGGERED);
|
||||
}
|
||||
@ -977,7 +977,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im
|
||||
private final class SpliceFdTask extends SpliceInTask {
|
||||
private final FileDescriptor fd;
|
||||
private final ChannelPromise promise;
|
||||
private final int offset;
|
||||
private int offset;
|
||||
|
||||
SpliceFdTask(FileDescriptor fd, int offset, int len, ChannelPromise promise) {
|
||||
super(len, promise);
|
||||
@ -1007,6 +1007,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel im
|
||||
}
|
||||
do {
|
||||
int splicedOut = Native.splice(pipeIn.intValue(), -1, fd.intValue(), offset, splicedIn);
|
||||
offset += splicedOut;
|
||||
splicedIn -= splicedOut;
|
||||
} while (splicedIn > 0);
|
||||
if (len == 0) {
|
||||
|
@ -189,7 +189,7 @@ public class EpollSpliceTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(timeout = 10000)
|
||||
public void spliceToFile() throws Throwable {
|
||||
EventLoopGroup group = new EpollEventLoopGroup(1);
|
||||
File file = File.createTempFile("netty-splice", null);
|
||||
@ -215,7 +215,7 @@ public class EpollSpliceTest {
|
||||
i += length;
|
||||
}
|
||||
|
||||
while (sh.future == null || !sh.future.isDone()) {
|
||||
while (sh.future2 == null || !sh.future2.isDone() || !sh.future.isDone()) {
|
||||
if (sh.exception.get() != null) {
|
||||
break;
|
||||
}
|
||||
@ -291,8 +291,8 @@ public class EpollSpliceTest {
|
||||
private static class SpliceHandler extends ChannelInboundHandlerAdapter {
|
||||
private final File file;
|
||||
|
||||
volatile Channel channel;
|
||||
volatile ChannelFuture future;
|
||||
volatile ChannelFuture future2;
|
||||
final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
|
||||
|
||||
SpliceHandler(File file) {
|
||||
@ -300,13 +300,13 @@ public class EpollSpliceTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx)
|
||||
throws Exception {
|
||||
channel = ctx.channel();
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
final EpollSocketChannel ch = (EpollSocketChannel) ctx.channel();
|
||||
final FileDescriptor fd = FileDescriptor.from(file);
|
||||
|
||||
future = ch.spliceTo(fd, 0, data.length);
|
||||
// splice two halves separately to test starting offset
|
||||
future = ch.spliceTo(fd, 0, data.length / 2);
|
||||
future2 = ch.spliceTo(fd, data.length / 2, data.length / 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user