@Override
 public ByteBuffer processCommand(RequestReader request, Protocol protocol, Cache cache) {
   String version = GemFireMemcachedServer.version;
   if (protocol == Protocol.ASCII) {
     return asciiCharset.encode("VERSION " + version + "\r\n");
   }
   ByteBuffer response = request.getResponse(HEADER_LENGTH + version.length());
   response.putInt(TOTAL_BODY_LENGTH_INDEX, version.length());
   response.position(HEADER_LENGTH);
   response.put(asciiCharset.encode(version));
   response.rewind();
   request.getRequest().position(HEADER_LENGTH);
   return response;
 }
 @Override
 public ByteBuffer processBinaryStorageCommand(
     Object key, byte[] value, long cas, int flags, Cache cache, RequestReader request) {
   ByteBuffer response = request.getResponse();
   Region<Object, ValueWrapper> r = getMemcachedRegion(cache);
   ValueWrapper val = ValueWrapper.getWrappedValue(value, flags);
   try {
     Object oldVal = r.putIfAbsent(key, val);
     // set status
     if (oldVal == null) {
       if (getLogger().fineEnabled()) {
         getLogger().fine("added key: " + key);
       }
       if (isQuiet()) {
         return null;
       }
       response.putShort(POSITION_RESPONSE_STATUS, ResponseStatus.NO_ERROR.asShort());
       // set cas
       response.putLong(POSITION_CAS, val.getVersion());
     } else {
       if (getLogger().fineEnabled()) {
         getLogger().fine("key: " + key + " not added as is already exists");
       }
       response.putShort(POSITION_RESPONSE_STATUS, ResponseStatus.KEY_EXISTS.asShort());
     }
   } catch (Exception e) {
     response = handleBinaryException(key, request, response, "add", e);
   }
   return response;
 }
 @Override
 public ByteBuffer processCommand(RequestReader request, Protocol protocol, Cache cache) {
   if (protocol == Protocol.ASCII) {
     return processAsciiCommand(request.getRequest(), cache);
   }
   return processBinaryProtocol(request, cache);
 }
  private ByteBuffer processBinaryCommand(RequestReader request, Cache cache) {
    ByteBuffer buffer = request.getRequest();
    ByteBuffer response = request.getResponse();

    KeyWrapper key = getKey(buffer, HEADER_LENGTH);

    Region<Object, ValueWrapper> r = getMemcachedRegion(cache);
    try {
      r.destroy(key);
      if (isQuiet()) {
        return null;
      }
      response.putShort(POSITION_RESPONSE_STATUS, ResponseStatus.NO_ERROR.asShort());
    } catch (EntryNotFoundException e) {
      response.putShort(POSITION_RESPONSE_STATUS, ResponseStatus.KEY_NOT_FOUND.asShort());
    }
    if (getLogger().fineEnabled()) {
      getLogger().fine("delete:key:" + key);
    }
    return response;
  }
  private ByteBuffer processBinaryProtocol(RequestReader request, Cache cache) {
    ByteBuffer buffer = request.getRequest();
    int extrasLength = buffer.get(EXTRAS_LENGTH_INDEX);
    final KeyWrapper key = getKey(buffer, HEADER_LENGTH + extrasLength);

    long decrBy = buffer.getLong(HEADER_LENGTH);
    long initialVal = buffer.getLong(HEADER_LENGTH + LONG_LENGTH);
    int expiration = buffer.getInt(HEADER_LENGTH + LONG_LENGTH + LONG_LENGTH);

    final Region<Object, ValueWrapper> r = getMemcachedRegion(cache);
    ByteBuffer newVal = ByteBuffer.allocate(8);
    boolean notFound = false;
    ValueWrapper newValWrapper = null;

    try {
      while (true) {
        ValueWrapper oldValWrapper = r.get(key);
        if (oldValWrapper == null) {
          if (expiration == -1) {
            notFound = true;
          } else {
            newVal.putLong(0, initialVal);
            newValWrapper = ValueWrapper.getWrappedValue(newVal.array(), 0 /*flags*/);
            r.put(key, newValWrapper);
          }
          break;
        }
        byte[] oldVal = oldValWrapper.getValue();
        long oldLong = getLongFromByteArray(oldVal);
        long newLong = oldLong - decrBy;
        if (newLong < 0) {
          newLong = 0;
        }
        newVal.putLong(0, newLong);
        newValWrapper = ValueWrapper.getWrappedValue(newVal.array(), 0 /*flags*/);
        if (r.replace(key, oldValWrapper, newValWrapper)) {
          break;
        }
      }
    } catch (Exception e) {
      return handleBinaryException(key, request, request.getResponse(), "decrement", e);
    }

    if (expiration > 0) {
      StorageCommand.getExpiryExecutor()
          .schedule(
              new Runnable() {
                @Override
                public void run() {
                  r.destroy(key);
                }
              },
              expiration,
              TimeUnit.SECONDS);
    }

    if (getLogger().fineEnabled()) {
      getLogger()
          .fine(
              "decr:key:"
                  + key
                  + " decrBy:"
                  + decrBy
                  + " initVal:"
                  + initialVal
                  + " exp:"
                  + expiration
                  + " notFound:"
                  + notFound);
    }

    ByteBuffer response = null;
    if (notFound) {
      response = request.getResponse();
      response.putShort(POSITION_RESPONSE_STATUS, ResponseStatus.KEY_NOT_FOUND.asShort());
    } else {
      if (isQuiet()) {
        return null;
      }
      response = request.getResponse(HEADER_LENGTH + LONG_LENGTH);
      response.putInt(TOTAL_BODY_LENGTH_INDEX, LONG_LENGTH);
      response.putLong(HEADER_LENGTH, newVal.getLong(0));
      response.putLong(POSITION_CAS, newValWrapper.getVersion());
    }
    return response;
  }