All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gemstone.gemfire.internal.memcached.commands.GetCommand Maven / Gradle / Ivy

/*
 * Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License. You
 * may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License. See accompanying
 * LICENSE file.
 */
package com.gemstone.gemfire.internal.memcached.commands;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.internal.memcached.Command;
import com.gemstone.gemfire.internal.memcached.KeyWrapper;
import com.gemstone.gemfire.internal.memcached.Reply;
import com.gemstone.gemfire.internal.memcached.RequestReader;
import com.gemstone.gemfire.internal.memcached.ResponseStatus;
import com.gemstone.gemfire.internal.memcached.ValueWrapper;
import com.gemstone.gemfire.memcached.GemFireMemcachedServer.Protocol;

/**
 * 
 * The retrieval commands "get" and "gets" operates like this:
* * get <key>*\r\n
* gets <key>*\r\n *
*

* Each item sent by the server looks like this:
* * VALUE <key> <flags> <bytes> [<cas unique>]\r\n
* <data block>\r\n *
* * @author Swapnil Bawaskar * */ public class GetCommand extends AbstractCommand { private static final String VALUE = "VALUE"; private static final String W_SPACE = " "; private static final String RN = "\r\n"; private static final ByteBuffer RN_BUF = asciiCharset.encode(RN); private static final ByteBuffer END_BUF = asciiCharset.encode(Reply.END.toString()); /** * buffer used to compose one line of reply */ private static ThreadLocal lineBuffer = new ThreadLocal(); /** * defaults to the default send buffer size on socket */ private static final int REPLY_BUFFER_CAPACITY = Integer.getInteger("replyBufferCapacity", 146988); /** * buffer for sending get replies, one per thread */ private static ThreadLocal replyBuffer = new ThreadLocal(); private static final int EXTRAS_LENGTH = 4; @Override public ByteBuffer processCommand(RequestReader request, Protocol protocol, Cache cache) { if (protocol == Protocol.ASCII) { return processAsciiCommand(request, cache); } return processBinaryCommand(request.getRequest(), request, cache, request.getResponse()); } protected ByteBuffer processBinaryCommand(ByteBuffer buffer, RequestReader request, Cache cache, ByteBuffer response) { Region r = getMemcachedRegion(cache); KeyWrapper key = getKey(buffer, HEADER_LENGTH); ValueWrapper val = r.get(key); if (getLogger().fineEnabled()) { getLogger().fine("get:key:"+key+" val:"+val); } if (val == null) { if (isQuiet()) { return null; } response.putShort(POSITION_RESPONSE_STATUS, ResponseStatus.KEY_NOT_FOUND.asShort()); } else { byte[] realValue = val.getValue(); int responseLength = HEADER_LENGTH + realValue.length + EXTRAS_LENGTH + (sendKeysInResponse() ? key.getKey().length : 0); if (response.capacity() < responseLength) { response = request.getResponse(responseLength); } response.limit(responseLength); response.putShort(POSITION_RESPONSE_STATUS, ResponseStatus.NO_ERROR.asShort()); response.put(EXTRAS_LENGTH_INDEX, (byte) EXTRAS_LENGTH); response.putInt(TOTAL_BODY_LENGTH_INDEX, EXTRAS_LENGTH + realValue.length + (sendKeysInResponse() ? key.getKey().length : 0)); response.putLong(POSITION_CAS, val.getVersion()); response.position(HEADER_LENGTH); response.putInt(val.getFlags()); if (sendKeysInResponse()) { response.put(key.getKey()); } response.put(realValue); response.flip(); } return response; } /** * Overridden by GetQ and getKQ to not send reply on cache miss */ protected boolean isQuiet() { return false; } /** * Overridden by GetK command */ protected boolean sendKeysInResponse() { return false; } private ByteBuffer processAsciiCommand(RequestReader request, Cache cache) { ByteBuffer buffer = request.getRequest(); CharBuffer flb = getFirstLineBuffer(); getAsciiDecoder().reset(); getAsciiDecoder().decode(buffer, flb, false); flb.flip(); String firstLine = getFirstLine(); String[] firstLineElements = firstLine.split(" "); boolean isGets = firstLineElements[0].equals("gets"); Set keys = new HashSet(); for (int i=1; i r = getMemcachedRegion(cache); Map results = r.getAll(keys); return composeReply(results, isGets); } private ByteBuffer composeReply(Map results, boolean isGets) { Iterator> it = results.entrySet().iterator(); ByteBuffer buffer = getReplyBuffer(); while (it.hasNext()) { Entry e = it.next(); if (getLogger().fineEnabled()) { getLogger().fine("get compose reply:"+e); } ValueWrapper valWrapper = e.getValue(); if (valWrapper != null) { byte[] v = valWrapper.getValue(); CharBuffer reply = getLineBuffer(); reply.put(VALUE).put(W_SPACE); reply.put(e.getKey().toString()).put(W_SPACE); reply.put(Integer.toString(valWrapper.getFlags())).put(W_SPACE); // flags String valBytes = v == null ? Integer.toString(0) : Integer.toString(v.length); reply.put(valBytes); if (isGets) { // send the version for gets command reply.put(W_SPACE); reply.put(Long.toString(valWrapper.getVersion())); } reply.put(RN); reply.flip(); getAsciiEncoder().encode(reply, buffer, false); // put the actual value buffer.put(v); RN_BUF.rewind(); buffer.put(RN_BUF); } } END_BUF.rewind(); buffer.put(END_BUF); buffer.flip(); return buffer; } private ByteBuffer getReplyBuffer() { ByteBuffer retVal = replyBuffer.get(); if (retVal == null) { retVal = ByteBuffer.allocate(REPLY_BUFFER_CAPACITY); replyBuffer.set(retVal); } retVal.clear(); return retVal; } private CharBuffer getLineBuffer() { CharBuffer retVal = lineBuffer.get(); if (retVal == null) { retVal = CharBuffer.allocate(1024); lineBuffer.set(retVal); } retVal.clear(); return retVal; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy