diff --git a/src/main/java/net/spy/memcached/MemcachedClient.java b/src/main/java/net/spy/memcached/MemcachedClient.java index 2375bafb6..563ed4fc1 100644 --- a/src/main/java/net/spy/memcached/MemcachedClient.java +++ b/src/main/java/net/spy/memcached/MemcachedClient.java @@ -342,6 +342,50 @@ public void complete() { return rv; } + /** + * Touch the given key to reset its expiration time with the default + * transcoder. + * + * @param key the key to fetch + * @param exp the new expiration to set for the given key + * @return a future that will hold the return value of whether or not + * the fetch succeeded + * @throws IllegalStateException in the rare circumstance where queue + * is too full to accept any more requests + */ + public Future touch(final String key, final int exp) { + return touch(key, exp, transcoder); + } + + /** + * Touch the given key to reset its expiration time. + * + * @param key the key to fetch + * @param exp the new expiration to set for the given key + * @param tc the transcoder to serialize and unserialize value + * @return a future that will hold the return value of whether or not + * the fetch succeeded + * @throws IllegalStateException in the rare circumstance where queue + * is too full to accept any more requests + */ + public Future touch(final String key, final int exp, + final Transcoder tc) { + final CountDownLatch latch=new CountDownLatch(1); + final OperationFuture rv=new OperationFuture(latch, + operationTimeout); + + Operation op=opFact.touch(key, exp, new OperationCallback() { + public void receivedStatus(OperationStatus status) { + rv.set(status.isSuccess()); + } + public void complete() { + latch.countDown(); + }}); + rv.setOperation(op); + addOp(key, op); + return rv; + } + /** * Append to an existing value in the cache. * diff --git a/src/main/java/net/spy/memcached/OperationFactory.java b/src/main/java/net/spy/memcached/OperationFactory.java index 0c1e33142..f39726f7d 100644 --- a/src/main/java/net/spy/memcached/OperationFactory.java +++ b/src/main/java/net/spy/memcached/OperationFactory.java @@ -122,6 +122,15 @@ MutatorOperation mutate(Mutator m, String key, int by, StoreOperation store(StoreType storeType, String key, int flags, int exp, byte[] data, OperationCallback cb); + /** + * Resets a keys expiration time + * @param key The key whose expiration time is to be reset. + * @param expiration The new expiration time for the key + * @param cb The status callback + * @return A touch operation + */ + KeyedOperation touch(String key, int expiration, OperationCallback cb); + /** * Get a concatenation operation. * diff --git a/src/main/java/net/spy/memcached/protocol/ascii/AsciiOperationFactory.java b/src/main/java/net/spy/memcached/protocol/ascii/AsciiOperationFactory.java index e10d0b94e..d4a030871 100644 --- a/src/main/java/net/spy/memcached/protocol/ascii/AsciiOperationFactory.java +++ b/src/main/java/net/spy/memcached/protocol/ascii/AsciiOperationFactory.java @@ -68,6 +68,11 @@ public StoreOperation store(StoreType storeType, String key, int flags, return new StoreOperationImpl(storeType, key, flags, exp, data, cb); } + public KeyedOperation touch(String key, int expiration, OperationCallback cb) { + throw new UnsupportedOperationException("Touch is only supported in" + + " the binary protocol"); + } + public VersionOperation version(OperationCallback cb) { return new VersionOperationImpl(cb); } diff --git a/src/main/java/net/spy/memcached/protocol/binary/BinaryOperationFactory.java b/src/main/java/net/spy/memcached/protocol/binary/BinaryOperationFactory.java index 89b3792eb..d1011b3f1 100644 --- a/src/main/java/net/spy/memcached/protocol/binary/BinaryOperationFactory.java +++ b/src/main/java/net/spy/memcached/protocol/binary/BinaryOperationFactory.java @@ -72,6 +72,10 @@ public StoreOperation store(StoreType storeType, String key, int flags, return new StoreOperationImpl(storeType, key, flags, exp, data, 0, cb); } + public KeyedOperation touch(String key, int expiration, OperationCallback cb) { + return new TouchOperationImpl(key, expiration, cb); + } + public VersionOperation version(OperationCallback cb) { return new VersionOperationImpl(cb); } diff --git a/src/main/java/net/spy/memcached/protocol/binary/TouchOperationImpl.java b/src/main/java/net/spy/memcached/protocol/binary/TouchOperationImpl.java new file mode 100644 index 000000000..9a0db9faf --- /dev/null +++ b/src/main/java/net/spy/memcached/protocol/binary/TouchOperationImpl.java @@ -0,0 +1,58 @@ +package net.spy.memcached.protocol.binary; + +import java.util.Collection; +import java.util.Collections; + +import net.spy.memcached.ops.KeyedOperation; +import net.spy.memcached.ops.OperationCallback; +import net.spy.memcached.ops.OperationStatus; + +/** + * Operation to reset a timeout in Membase server. + */ +public class TouchOperationImpl extends OperationImpl + implements KeyedOperation { + + static final int CMD=28; + + private final String key; + private final int exp; + + protected TouchOperationImpl(String k, int e, OperationCallback cb) { + super(CMD, generateOpaque(), cb); + key=k; + exp=e; + } + + @Override + public Collection getKeys() { + return Collections.singleton(key); + } + + @Override + protected OperationStatus getStatusForErrorCode(int errCode, byte[] errPl) { + OperationStatus baseStatus = super.getStatusForErrorCode(errCode, errPl); + if (baseStatus != null) { + return baseStatus; + } + OperationStatus rv=null; + switch(errCode) { + case ERR_EXISTS: + rv=EXISTS_STATUS; + break; + case ERR_NOT_FOUND: + rv=NOT_FOUND_STATUS; + break; + case ERR_TEMP_FAIL: + rv=TEMP_FAIL; + break; + } + return rv; + } + + @Override + public void initialize() { + prepareBuffer(key, 0, EMPTY_BYTES, exp); + } + +}