/* * Copyright 2011 Couchbase, Inc.. * * 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. * under the License. */ package org.couchbase.mock.memcached; import org.couchbase.mock.memcached.protocol.BinaryArithmeticCommand; import org.couchbase.mock.memcached.protocol.BinaryArithmeticResponse; import org.couchbase.mock.memcached.protocol.BinaryCommand; import org.couchbase.mock.memcached.protocol.BinaryResponse; import org.couchbase.mock.memcached.protocol.CommandCode; import org.couchbase.mock.memcached.protocol.ErrorCode; /** * @author Trond Norbye <trond.norbye@gmail.com> */ public class ArithmeticCommandExecutor implements CommandExecutor { @Override public void execute(BinaryCommand command, MemcachedServer server, MemcachedConnection client) { BinaryArithmeticCommand cmd = (BinaryArithmeticCommand) command; VBucketStore cache = server.getStorage().getCache(server, cmd.getVBucketId()); Item item = cache.get(cmd.getKeySpec()); CommandCode cc = cmd.getComCode(); MutationInfoWriter miw = client.getMutinfoWriter(); if (item == null) { if (cmd.create()) { item = new Item(cmd.getKeySpec(), 0, cmd.getExpiration(), Long.toString(cmd.getInitial()).getBytes(), null, 0); MutationStatus ms = cache.add(item); ErrorCode err = ms.getStatus(); switch (err) { case KEY_EEXISTS: execute(command, server, client); break; case SUCCESS: if (cc == CommandCode.INCREMENT || cc == CommandCode.DECREMENT) { client.sendResponse(new BinaryArithmeticResponse(cmd, cmd.getInitial(), item.getCas(), ms, miw)); } break; default: client.sendResponse(new BinaryResponse(command, err)); } } else { client.sendResponse(new BinaryResponse(command, ErrorCode.KEY_ENOENT)); } } else { long value; if (!item.ensureUnlocked(command.getCas())) { client.sendResponse(new BinaryResponse(command, ErrorCode.ETMPFAIL)); return; } try { value = Long.parseLong(new String(item.getValue())); } catch (NumberFormatException ex) { client.sendResponse(new BinaryResponse(command, ErrorCode.DELTA_BADVAL)); return; } if (cc == CommandCode.INCREMENT || cc == CommandCode.INCREMENTQ) { value += cmd.getDelta(); } else { value -= cmd.getDelta(); } int exp = cmd.getExpiration() > 0 ? cmd.getExpiration() : item.getExpiryTime(); Item newValue = new Item(cmd.getKeySpec(), item.getFlags(), exp, Long.toString(value).getBytes(), null, item.getCas()); MutationStatus ms = cache.set(newValue); if (ms.getStatus() == ErrorCode.SUCCESS) { if (cc == CommandCode.INCREMENT || cc == CommandCode.DECREMENT) { // return value client.sendResponse(new BinaryArithmeticResponse(cmd, value, newValue.getCas(), ms, miw)); } } else { client.sendResponse(new BinaryResponse(command, ms.getStatus())); } } } }