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

org.glassfish.grizzly.memcached.MemcachedResponse Maven / Gradle / Ivy

There is a newer version: 1.3.18
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2012-2013 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package org.glassfish.grizzly.memcached;

import org.glassfish.grizzly.Buffer;
import org.glassfish.grizzly.Cacheable;
import org.glassfish.grizzly.Grizzly;
import org.glassfish.grizzly.ThreadCache;
import org.glassfish.grizzly.memory.MemoryManager;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Memcached response
 * 

* Key and value will be decoded by {@link #setDecodedKey} and {@link #setDecodedValue}. * {@link #setResult} sets the last result based on other fields of this response in according to memcached's command. * * @author Bongjae Chang */ public class MemcachedResponse implements Cacheable { private static final Logger logger = Grizzly.logger(MemcachedResponse.class); private static final Long INVALID_LONG = (long) -1; private static final ThreadCache.CachedTypeIndex CACHE_IDX = ThreadCache.obtainIndex(MemcachedResponse.class, 16); // header private CommandOpcodes op; private short keyLength; private byte extraLength; private byte dataType; private ResponseStatus status; private int totalBodyLength; private int opaque; private long cas; // extras and body private int flags; private Object decodedKey; private Object decodedValue; private Object result; private MemcachedResponse() { } public static MemcachedResponse create() { final MemcachedResponse response = ThreadCache.takeFromCache(CACHE_IDX); if (response != null) { return response; } return new MemcachedResponse(); } public CommandOpcodes getOp() { return op; } public short getKeyLength() { return keyLength; } public byte getExtraLength() { return extraLength; } public byte getDataType() { return dataType; } public ResponseStatus getStatus() { return status; } public int getTotalBodyLength() { return totalBodyLength; } public int getOpaque() { return opaque; } public long getCas() { return cas; } public int getFlags() { return flags; } public Object getDecodedKey() { return decodedKey; } public Object getDecodedValue() { return decodedValue; } public Object getResult() { return result; } public void setOp(final CommandOpcodes op) { this.op = op; } public void setKeyLength(final short keyLength) { this.keyLength = keyLength; } public void setExtraLength(final byte extraLength) { this.extraLength = extraLength; } public void setDataType(final byte dataType) { this.dataType = dataType; } public void setStatus(final ResponseStatus status) { this.status = status; } public void setTotalBodyLength(final int totalBodyLength) { this.totalBodyLength = totalBodyLength; } public void setOpaque(final int opaque) { this.opaque = opaque; } public void setCas(final long cas) { this.cas = cas; } public void setFlags(final int flags) { this.flags = flags; } public void setDecodedKey(final Buffer buffer, final int position, final int limit, final MemoryManager memoryManager) { if (buffer == null || position > limit) { return; } final Object result; switch (op) { case Stat: if (!isError()) { result = BufferWrapper.unwrap(buffer, position, limit, BufferWrapper.BufferType.STRING, memoryManager); } else { result = null; } break; default: result = null; break; } decodedKey = result; } public void setDecodedKey(final Object decodedKey) { this.decodedKey = decodedKey; } public void setDecodedValue(final Buffer buffer, final int position, final int limit, final MemoryManager memoryManager) { if (buffer == null || position > limit) { return; } final Object result; switch (op) { // user value type case Get: case GetQ: case GAT: case GATQ: case GetK: case GetKQ: case Gets: case GetsQ: if (!isError()) { result = BufferWrapper.unwrap(buffer, position, limit, BufferWrapper.BufferType.getBufferType(this.flags), memoryManager); } else { result = null; } break; case Increment: case Decrement: if (!isError()) { result = BufferWrapper.unwrap(buffer, position, limit, BufferWrapper.BufferType.LONG, memoryManager); } else { result = INVALID_LONG; } break; case Version: case Stat: if (!isError()) { result = BufferWrapper.unwrap(buffer, position, limit, BufferWrapper.BufferType.STRING, memoryManager); } else { result = null; } break; default: result = null; break; } decodedValue = result; } public void setDecodedValue(final Object decodedValue) { this.decodedValue = decodedValue; } @SuppressWarnings("unchecked") public void setResult(final K originKey, final MemcachedClientFilter.ParsingStatus parsingStatus) { if (isError() && parsingStatus == MemcachedClientFilter.ParsingStatus.DONE) { if (status == ResponseStatus.Key_Not_Found) { if (logger.isLoggable(Level.FINER)) { logger.log(Level.FINER, "error status code={0}, status msg={1}, op={2}, key={3}", new Object[]{status, status.message(), op, originKey}); } } else { if (logger.isLoggable(Level.WARNING)) { logger.log(Level.WARNING, "error status code={0}, status msg={1}, op={2}, key={3}", new Object[]{status, status.message(), op, originKey}); } } } final Object result; switch (op) { // user value type case Get: case GetQ: case GAT: case GATQ: if (!isError()) { result = decodedValue; } else { result = null; } break; // ValueWithKey type case GetK: case GetKQ: if (!isError() && decodedValue != null) { result = new ValueWithKey(originKey, decodedValue); } else { result = null; } break; // ValueWithCas type case Gets: case GetsQ: if (!isError() && decodedValue != null) { result = new ValueWithCas(decodedValue, this.cas); } else { result = null; } break; // boolean and void type. there are no responses except for error case Set: case Add: case Replace: case Delete: case Quit: case Flush: case Append: case Prepend: case Verbosity: case Touch: case Noop: case SetQ: case AddQ: case ReplaceQ: case DeleteQ: case IncrementQ: case DecrementQ: case QuitQ: case FlushQ: case AppendQ: case PrependQ: if (!isError() || parsingStatus == MemcachedClientFilter.ParsingStatus.NO_REPLY) { result = Boolean.TRUE; } else { result = Boolean.FALSE; } break; // long type case Increment: case Decrement: if (!isError() && decodedValue instanceof Long) { result = decodedValue; } else { result = INVALID_LONG; } break; // string type case Version: if (!isError() && decodedValue instanceof String) { result = decodedValue; } else { result = null; } break; case Stat: if (!isError() && decodedKey instanceof String && decodedValue instanceof String) { result = new ValueWithKey((String) decodedKey, (String) decodedValue); } else { result = null; } break; // currently not supported case SASL_List: case SASL_Auth: case SASL_Step: case RGet: case RSet: case RSetQ: case RAppend: case RAppendQ: case RPrepend: case RPrependQ: case RDelete: case RDeleteQ: case RIncr: case RIncrQ: case RDecr: case RDecrQ: case Set_VBucket: case Get_VBucket: case Del_VBucket: case TAP_Connect: case TAP_Mutation: case TAP_Delete: case TAP_Flush: case TAP_Opaque: case TAP_VBucket_Set: case TAP_Checkpoint_Start: case TAP_Checkpoint_End: default: result = null; break; } this.result = result; } public boolean isError() { switch (op) { case Delete: case DeleteQ: return status != null && status != ResponseStatus.No_Error && status != ResponseStatus.Key_Not_Found; default: return status != null && status != ResponseStatus.No_Error; } } public boolean complete() { switch (op) { // one request - many response case Stat: return decodedKey == null || decodedValue == null; //return key == null || value == null; default: return true; } } public void clear() { op = null; keyLength = 0; extraLength = 0; dataType = 0; status = null; totalBodyLength = 0; opaque = 0; cas = 0; flags = 0; decodedKey = null; decodedValue = null; result = null; } @Override public void recycle() { clear(); ThreadCache.putToCache(CACHE_IDX, this); } @Override public String toString() { return "MemcachedResponse{" + "op=" + op + ", keyLength=" + keyLength + ", extraLength=" + extraLength + ", dataType=" + dataType + ", status=" + status + ", totalBodyLength=" + totalBodyLength + ", opaque=" + opaque + ", cas=" + cas + ", flags=" + flags + ", decodedKey=" + decodedKey + ", decodedValue=" + decodedValue + ", result=" + result + '}'; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy