package org.infinispan.server.hotrod;
import org.infinispan.Cache;
import org.infinispan.commons.logging.LogFactory;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.remoting.transport.Address;
import org.infinispan.server.hotrod.logging.Log;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.util.internal.PlatformDependent;
/**
* Hot Rod specific encoder.
*
* @author Galder ZamarreƱo
* @since 4.1
*/
@Sharable
class HotRodEncoder extends MessageToByteEncoder<Object> {
private final static Log log = LogFactory.getLog(HotRodEncoder.class, Log.class);
private final static boolean isTrace = log.isTraceEnabled();
private final EmbeddedCacheManager cacheManager;
private final HotRodServer server;
private final boolean isClustered;
private Cache<Address, ServerAddress> addressCache;
HotRodEncoder(EmbeddedCacheManager cacheManager, HotRodServer server) {
super(PlatformDependent.directBufferPreferred());
this.cacheManager = cacheManager;
this.server = server;
isClustered = cacheManager.getCacheManagerConfiguration().transport().transport() != null;
}
private Cache<Address, ServerAddress> getAddressCache() {
if (addressCache == null) {
addressCache = isClustered ? cacheManager.getCache(server.getConfiguration().topologyCacheName()) : null;
}
return addressCache;
}
@Override
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf buf) throws Exception {
try {
if (isTrace) {
log.tracef("Encode msg %s", msg);
}
if (msg instanceof Response) {
Response r = (Response) msg;
VersionedEncoder encoder = getEncoder(r.version);
try {
if (Constants.isVersionKnown(r.version)) {
encoder.writeHeader(r, buf, getAddressCache(), server);
} else {
// if error before reading version, don't send any topology changes
// cos the encoding might vary from one version to the other
encoder.writeHeader(r, buf, null, server);
}
encoder.writeResponse(r, buf, cacheManager, server);
} catch (Throwable t) {
log.errorWritingResponse(r.messageId, t);
buf.clear(); // reset buffer
ErrorResponse error = new ErrorResponse(r.version, r.messageId, r.cacheName, r.clientIntel,
OperationStatus.ServerError, r.topologyId, t.toString());
encoder.writeHeader(error, buf, getAddressCache(), server);
encoder.writeResponse(error, buf, cacheManager, server);
}
} else if (msg instanceof Events.Event) {
Events.Event e = (Events.Event) msg;
VersionedEncoder encoder = getEncoder(e.version);
encoder.writeEvent(e, buf);
} else if (msg != null) {
log.errorUnexpectedMessage(msg);
}
} catch (Throwable t) {
log.errorEncodingMessage(msg, t);
throw t;
}
}
private VersionedEncoder getEncoder(byte version) {
if (Constants.isVersion2x(version)) {
return new Encoder2x();
} else if (Constants.isVersion10(version)) {
return new AbstractEncoder1x() {
};
} else if (Constants.isVersion1x(version)) {
return new AbstractTopologyAwareEncoder1x() {
};
} else {
return new Encoder2x();
}
}
}