Package net.spy.memcached.vbucket

Source Code of net.spy.memcached.vbucket.BucketUpdateResponseHandler

package net.spy.memcached.vbucket;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipelineCoverage;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.http.HttpChunk;
import org.jboss.netty.handler.codec.http.HttpResponse;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

@ChannelPipelineCoverage("one")
public class BucketUpdateResponseHandler extends SimpleChannelUpstreamHandler {

    private volatile boolean readingChunks;
    private String lastResponse;
    private ChannelFuture receivedFuture;
    private CountDownLatch latch;
    private StringBuilder partialResponse;
    private static final Logger LOGGER = Logger.getLogger(BucketUpdateResponseHandler.class.getName());

    @Override
    public void messageReceived(final ChannelHandlerContext context, final MessageEvent event) {
        ChannelFuture channelFuture = event.getFuture();
        setReceivedFuture(channelFuture);
        if (this.partialResponse == null) {
            this.partialResponse = new StringBuilder();
        }
        if (readingChunks) {
            HttpChunk chunk = (HttpChunk) event.getMessage();
            if (chunk.isLast()) {
                readingChunks = false;
            } else {
                String curChunk = chunk.getContent().toString("UTF-8");
                /*
                 * Server sends four new lines in a chunk as a sentinal between
                 * responses.
                 */
                if (curChunk.matches("\n\n\n\n")) {
                    setLastResponse(partialResponse.toString());
                    partialResponse = null;
                    getLatch().countDown();
                    if (monitor != null) {
                        monitor.invalidate();
                    }
                } else {
                    finerLog(curChunk);
                    finerLog("Chunk length is: " + curChunk.length());
                    partialResponse.append(curChunk);
                    channelFuture.setSuccess();
                }

            }
        } else {
            HttpResponse response = (HttpResponse) event.getMessage();
            logResponse(response);
        }
    }

    private void logResponse(HttpResponse response) {
        finerLog("STATUS: " + response.getStatus());
        finerLog("VERSION: " + response.getProtocolVersion());

        if (!response.getHeaderNames().isEmpty()) {
            for (String name : response.getHeaderNames()) {
                for (String value : response.getHeaders(name)) {
                    finerLog("HEADER: " + name + " = " + value);
                }
            }
            finerLog(System.getProperty("line.separator"));
        }

        if (response.getStatus().getCode() == 200 && response.isChunked()) {
            readingChunks = true;
            finerLog("CHUNKED CONTENT {");
        } else {
            ChannelBuffer content = response.getContent();
            if (content.readable()) {
                finerLog("CONTENT {");
                finerLog(content.toString("UTF-8"));
                finerLog("} END OF CONTENT");
            }
        }
    }

    /**
     * @return the lastResponse
     */
    protected String getLastResponse() {
        ChannelFuture channelFuture = getReceivedFuture();
        if (channelFuture.awaitUninterruptibly(30, TimeUnit.SECONDS)) {
            return lastResponse;
        } else { // TODO: make this work with multiple servers
            throw new ConnectionException("Cannot contact any server in the pool");
        }
    }

    /**
     * @param lastResponse the lastResponse to set
     */
    private void setLastResponse(String lastResponse) {
        this.lastResponse = lastResponse;
    }

    /**
     * @return the receivedFuture
     */
    private ChannelFuture getReceivedFuture() {
        try {
            getLatch().await();
        } catch (InterruptedException ex) {
            finerLog("Getting received future has been interrupted.");
        }
        return receivedFuture;
    }

    /**
     * @param receivedFuture the receivedFuture to set
     */
    private void setReceivedFuture(ChannelFuture receivedFuture) {
        this.receivedFuture = receivedFuture;
    }

    /**
     * @return the latch
     */
    private CountDownLatch getLatch() {
        if (this.latch == null) {
            latch = new CountDownLatch(1);
        }
        return latch;
    }

    private void finerLog(String message) {
        LOGGER.log(Level.FINER, message);
    }

    @Override
    public void handleUpstream(ChannelHandlerContext context, ChannelEvent event) throws Exception {

        if (event instanceof ChannelStateEvent) {
            LOGGER.log(Level.FINEST, "Channel state changed: " + event + "\n\n");
        }
        super.handleUpstream(context, event);
    }

    BucketMonitor monitor;

    protected void setBucketMonitor(BucketMonitor monitor) {
        this.monitor = monitor;
    }

    /* @todo we need to investigate why the exception occurs, and if there
     *       is a better solution to the problem than just shutting down the
     *       connection. For now just invalidate the BucketMonitor, and the
     *       Client manager will recreate the connection.
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        LOGGER.log(Level.INFO, "Exception occurred: ");
        if (monitor != null) {
            monitor.invalidate();
        }
    }
}
TOP

Related Classes of net.spy.memcached.vbucket.BucketUpdateResponseHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.