|  | @@ -20,7 +20,9 @@
 | 
	
		
			
				|  |  |  package org.elasticsearch.memcached.netty;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.Unicode;
 | 
	
		
			
				|  |  | +import org.elasticsearch.common.logging.ESLogger;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.netty.buffer.ChannelBuffer;
 | 
	
		
			
				|  |  | +import org.elasticsearch.common.netty.buffer.ChannelBuffers;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.netty.channel.Channel;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.netty.channel.ChannelHandlerContext;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.netty.channel.ExceptionEvent;
 | 
	
	
		
			
				|  | @@ -36,6 +38,8 @@ import java.util.regex.Pattern;
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  public class MemcachedDecoder extends FrameDecoder {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    private final ESLogger logger;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      private final Pattern lineSplit = Pattern.compile(" +");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public static final byte CR = 13;
 | 
	
	
		
			
				|  | @@ -46,8 +50,9 @@ public class MemcachedDecoder extends FrameDecoder {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      private volatile MemcachedRestRequest request;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    public MemcachedDecoder() {
 | 
	
		
			
				|  |  | +    public MemcachedDecoder(ESLogger logger) {
 | 
	
		
			
				|  |  |          super(false);
 | 
	
		
			
				|  |  | +        this.logger = logger;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
 | 
	
	
		
			
				|  | @@ -78,30 +83,53 @@ public class MemcachedDecoder extends FrameDecoder {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  buffer.skipBytes(extraLength); // get extras, can be empty
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                if (keyLength != 0) {
 | 
	
		
			
				|  |  | +                if (opcode == 0x00) { // GET
 | 
	
		
			
				|  |  |                      byte[] key = new byte[keyLength];
 | 
	
		
			
				|  |  |                      buffer.readBytes(key);
 | 
	
		
			
				|  |  |                      String uri = Unicode.fromBytes(key);
 | 
	
		
			
				|  |  | -                    if (opcode == 0x00) { // GET
 | 
	
		
			
				|  |  | -                        request = new MemcachedRestRequest(RestRequest.Method.GET, uri, key, -1, true);
 | 
	
		
			
				|  |  | -                        request.setOpaque(opaque);
 | 
	
		
			
				|  |  | -                        return request;
 | 
	
		
			
				|  |  | -                    } else if (opcode == 0x04) { // DELETE
 | 
	
		
			
				|  |  | -                        request = new MemcachedRestRequest(RestRequest.Method.DELETE, uri, key, -1, true);
 | 
	
		
			
				|  |  | -                        request.setOpaque(opaque);
 | 
	
		
			
				|  |  | -                        return request;
 | 
	
		
			
				|  |  | -                    } else if (opcode == 0x01) { // SET
 | 
	
		
			
				|  |  | -                        // the remainder of the message -- that is, totalLength - (keyLength + extraLength) should be the payload
 | 
	
		
			
				|  |  | -                        int size = totalBodyLength - keyLength - extraLength;
 | 
	
		
			
				|  |  | -                        request = new MemcachedRestRequest(RestRequest.Method.POST, uri, key, size, true);
 | 
	
		
			
				|  |  | -                        request.setOpaque(opaque);
 | 
	
		
			
				|  |  | -                        byte[] data = new byte[size];
 | 
	
		
			
				|  |  | -                        buffer.readBytes(data, 0, size);
 | 
	
		
			
				|  |  | -                        request.setData(data);
 | 
	
		
			
				|  |  | -                        return request;
 | 
	
		
			
				|  |  | -                    }
 | 
	
		
			
				|  |  | +                    request = new MemcachedRestRequest(RestRequest.Method.GET, uri, key, -1, true);
 | 
	
		
			
				|  |  | +                    request.setOpaque(opaque);
 | 
	
		
			
				|  |  | +                    return request;
 | 
	
		
			
				|  |  | +                } else if (opcode == 0x04) { // DELETE
 | 
	
		
			
				|  |  | +                    byte[] key = new byte[keyLength];
 | 
	
		
			
				|  |  | +                    buffer.readBytes(key);
 | 
	
		
			
				|  |  | +                    String uri = Unicode.fromBytes(key);
 | 
	
		
			
				|  |  | +                    request = new MemcachedRestRequest(RestRequest.Method.DELETE, uri, key, -1, true);
 | 
	
		
			
				|  |  | +                    request.setOpaque(opaque);
 | 
	
		
			
				|  |  | +                    return request;
 | 
	
		
			
				|  |  | +                } else if (opcode == 0x01/* || opcode == 0x11*/) { // SET
 | 
	
		
			
				|  |  | +                    byte[] key = new byte[keyLength];
 | 
	
		
			
				|  |  | +                    buffer.readBytes(key);
 | 
	
		
			
				|  |  | +                    String uri = Unicode.fromBytes(key);
 | 
	
		
			
				|  |  | +                    // the remainder of the message -- that is, totalLength - (keyLength + extraLength) should be the payload
 | 
	
		
			
				|  |  | +                    int size = totalBodyLength - keyLength - extraLength;
 | 
	
		
			
				|  |  | +                    request = new MemcachedRestRequest(RestRequest.Method.POST, uri, key, size, true);
 | 
	
		
			
				|  |  | +                    request.setOpaque(opaque);
 | 
	
		
			
				|  |  | +                    byte[] data = new byte[size];
 | 
	
		
			
				|  |  | +                    buffer.readBytes(data, 0, size);
 | 
	
		
			
				|  |  | +                    request.setData(data);
 | 
	
		
			
				|  |  | +                    request.setQuiet(opcode == 0x11);
 | 
	
		
			
				|  |  | +                    return request;
 | 
	
		
			
				|  |  | +                } else if (opcode == 0x0A || opcode == 0x10) { // NOOP or STATS
 | 
	
		
			
				|  |  | +                    // TODO once we support setQ we need to wait for them to flush
 | 
	
		
			
				|  |  | +                    ChannelBuffer writeBuffer = ChannelBuffers.dynamicBuffer(24);
 | 
	
		
			
				|  |  | +                    writeBuffer.writeByte(0x81);  // magic
 | 
	
		
			
				|  |  | +                    writeBuffer.writeByte(opcode); // opcode
 | 
	
		
			
				|  |  | +                    writeBuffer.writeShort(0); // key length
 | 
	
		
			
				|  |  | +                    writeBuffer.writeByte(0); // extra length = flags + expiry
 | 
	
		
			
				|  |  | +                    writeBuffer.writeByte(0); // data type unused
 | 
	
		
			
				|  |  | +                    writeBuffer.writeShort(0x0000); // OK
 | 
	
		
			
				|  |  | +                    writeBuffer.writeInt(0); // data length
 | 
	
		
			
				|  |  | +                    writeBuffer.writeInt(opaque); // opaque
 | 
	
		
			
				|  |  | +                    writeBuffer.writeLong(0); // cas
 | 
	
		
			
				|  |  | +                    channel.write(writeBuffer);
 | 
	
		
			
				|  |  | +                    return MemcachedDispatcher.IGNORE_REQUEST;
 | 
	
		
			
				|  |  |                  } else if (opcode == 0x07) { // QUIT
 | 
	
		
			
				|  |  |                      channel.disconnect();
 | 
	
		
			
				|  |  | +                } else {
 | 
	
		
			
				|  |  | +                    logger.error("Unsupported opcode [0x{}], ignoring and closing connection", Integer.toHexString(opcode));
 | 
	
		
			
				|  |  | +                    channel.disconnect();
 | 
	
		
			
				|  |  | +                    return null;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              } else {
 | 
	
		
			
				|  |  |                  buffer.resetReaderIndex(); // reset to get to the first byte
 | 
	
	
		
			
				|  | @@ -152,6 +180,10 @@ public class MemcachedDecoder extends FrameDecoder {
 | 
	
		
			
				|  |  |                      buffer.markReaderIndex();
 | 
	
		
			
				|  |  |                  } else if ("quit".equals(cmd)) {
 | 
	
		
			
				|  |  |                      channel.disconnect();
 | 
	
		
			
				|  |  | +                } else {
 | 
	
		
			
				|  |  | +                    logger.error("Unsupported command [{}], ignoring and closing connection", cmd);
 | 
	
		
			
				|  |  | +                    channel.disconnect();
 | 
	
		
			
				|  |  | +                    return null;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          } else {
 |