Encode FileRegion to ChannelBuffer's everytime the handler is called.

The user should add/remove it on the fly for better performance. See #89
This commit is contained in:
norman 2011-12-01 08:43:44 +01:00
parent 73b89a2b1f
commit 47af6bc9e8

View File

@ -1,5 +1,5 @@
/*
* Copyright 2009 Red Hat, Inc.
* Copyright 2011 Red Hat, Inc.
*
* Red Hat licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
@ -26,46 +26,23 @@ import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.FileRegion;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.handler.codec.compression.ZlibDecoder;
import org.jboss.netty.handler.codec.compression.ZlibEncoder;
import org.jboss.netty.handler.ssl.SslHandler;
/**
* {@link ChannelDownstreamHandler} implementation which encodes a {@link FileRegion} to {@link ChannelBuffer}'s if one of the given {@link ChannelHandler} was found in the {@link ChannelPipeline}.
*
* This {@link ChannelDownstreamHandler} should be used if you plan to write {@link FileRegion} objects and also have some {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} which needs to transform
* the to be written {@link ChannelBuffer} in any case. This is for example the case with {@link SslHandler} and {@link ZlibDecoder}.
* the to be written {@link ChannelBuffer} in any case. This could be for example {@link ChannelDownstreamHandler}'s which needs to encrypt or compress messages.
*
* Users of this {@link FileRegionEncoder} should add / remove this {@link ChannelDownstreamHandler} on the fly to get the best performance out of their system.
*
*
* @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
* @author <a href="http://www.murkycloud.com/">Norman Maurer</a>
*
*/
@ChannelHandler.Sharable
public class FileRegionEncoder implements ChannelDownstreamHandler{
private final Class<? extends ChannelHandler>[] handlers;
/**
* Create a new {@link FileRegionEncoder} which checks if one of the given {@link ChannelHandler}'s is contained in the {@link ChannelPipeline} and if so convert the {@link FileRegion} to {@link ChannelBuffer}'s.
*
* If the given <code>array</code> is empty it will encode the {@link FileRegion} to {@link ChannelBuffer}'s in all cases.
*/
public FileRegionEncoder(Class<? extends ChannelHandler>... handlers) {
if (handlers == null) {
throw new NullPointerException("handlers");
}
this.handlers = handlers;
}
/**
* Create a new {@link FileRegionEncoder} which checks for the present of {@link SslHandler} and {@link ZlibEncoder} once a {@link FileRegion} was written. If once of the two handlers is found it will encode the {@link FileRegion} to {@link ChannelBuffer}'s
*/
@SuppressWarnings("unchecked")
public FileRegionEncoder() {
this(SslHandler.class, ZlibEncoder.class);
}
@Override
public void handleDownstream(
ChannelHandlerContext ctx, ChannelEvent evt) throws Exception {
@ -77,46 +54,23 @@ public class FileRegionEncoder implements ChannelDownstreamHandler{
MessageEvent e = (MessageEvent) evt;
Object originalMessage = e.getMessage();
if (originalMessage instanceof FileRegion) {
if (isConvertNeeded(ctx, e)) {
FileRegion fr = (FileRegion) originalMessage;
WritableByteChannel bchannel = new ChannelWritableByteChannel(ctx, e);
int length = 0;
long i = 0;
while ((i = fr.transferTo(bchannel, length)) > 0) {
length += i;
if (length >= fr.getCount()) {
break;
}
FileRegion fr = (FileRegion) originalMessage;
WritableByteChannel bchannel = new ChannelWritableByteChannel(ctx, e);
int length = 0;
long i = 0;
while ((i = fr.transferTo(bchannel, length)) > 0) {
length += i;
if (length >= fr.getCount()) {
break;
}
} else {
// no converting is needed so just sent the event downstream
ctx.sendDownstream(evt);
}
} else {
// no converting is needed so just sent the event downstream
ctx.sendDownstream(evt);
}
}
/**
* Returns <code>true</code> if the {@link FileRegion} does need to get converted to {@link ChannelBuffer}'s
*
*/
private boolean isConvertNeeded(ChannelHandlerContext ctx, MessageEvent evt) throws Exception{
if (handlers.length == 0) {
return true;
} else {
for (int i = 0; i < handlers.length; i++) {
if(ctx.getPipeline().get(handlers[i]) != null) {
return true;
}
}
return false;
}
}
}