Skip to content

Commit d7e4f17

Browse files
committed
FEAT: Add gat(get and touch) command to get item & update item expiration
1 parent eff557c commit d7e4f17

File tree

10 files changed

+414
-0
lines changed

10 files changed

+414
-0
lines changed

src/main/java/net/spy/memcached/ArcusClientPool.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,16 @@ public GetFuture<CASValue<Object>> asyncGets(String key) {
242242
return this.getClient().asyncGets(key);
243243
}
244244

245+
@Override
246+
public <T> Future<T> asyncGetAndTouch(String key, int exp, Transcoder<T> tc) {
247+
return this.getClient().asyncGetAndTouch(key, exp, tc);
248+
}
249+
250+
@Override
251+
public Future<Object> asyncGetAndTouch(String key, int exp) {
252+
return this.getClient().asyncGetAndTouch(key, exp);
253+
}
254+
245255
@Override
246256
public <T> CASValue<T> gets(String key, Transcoder<T> tc)
247257
throws OperationTimeoutException {
@@ -264,6 +274,16 @@ public Object get(String key) throws OperationTimeoutException {
264274
return this.getClient().get(key);
265275
}
266276

277+
@Override
278+
public <T> T getAndTouch(String key, int exp, Transcoder<T> tc) {
279+
return this.getClient().getAndTouch(key, exp, tc);
280+
}
281+
282+
@Override
283+
public Object getAndTouch(String key, int exp) {
284+
return this.getClient().getAndTouch(key, exp);
285+
}
286+
267287
@Override
268288
public <T> BulkFuture<Map<String, T>> asyncGetBulk(Collection<String> keys,
269289
Iterator<Transcoder<T>> tcs) {

src/main/java/net/spy/memcached/MemcachedClient.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import net.spy.memcached.ops.CancelledOperationStatus;
6060
import net.spy.memcached.ops.ConcatenationType;
6161
import net.spy.memcached.ops.DeleteOperation;
62+
import net.spy.memcached.ops.GetAndTouchOperation;
6263
import net.spy.memcached.ops.GetOperation;
6364
import net.spy.memcached.ops.GetsOperation;
6465
import net.spy.memcached.ops.Mutator;
@@ -986,6 +987,57 @@ public GetFuture<CASValue<Object>> asyncGets(final String key) {
986987
return asyncGets(key, transcoder);
987988
}
988989

990+
/**
991+
* Get the given key to reset its expiration time.
992+
*
993+
* @param key the key to fetch
994+
* @param exp the new expiration to set for the given key
995+
* @param tc the transcoder to serialize and unserialize value
996+
* @return a future that will hold the return value of the fetch
997+
* @throws IllegalStateException in the rare circumstance where queue is too
998+
* full to accept any more requests
999+
*/
1000+
public <T> OperationFuture<T> asyncGetAndTouch(final String key, final int exp,
1001+
final Transcoder<T> tc) {
1002+
final CountDownLatch latch = new CountDownLatch(1);
1003+
final OperationFuture<T> rv = new OperationFuture<>(latch, operationTimeout);
1004+
1005+
Operation op = opFact.getAndTouch(key, exp,
1006+
new GetAndTouchOperation.Callback() {
1007+
private T val;
1008+
1009+
public void receivedStatus(OperationStatus status) {
1010+
rv.set(val, status);
1011+
}
1012+
1013+
public void complete() {
1014+
latch.countDown();
1015+
}
1016+
1017+
public void gotData(String k, int flags, byte[] data) {
1018+
assert k.equals(key) : "Wrong key returned";
1019+
this.val = tc.decode(new CachedData(flags, data, tc.getMaxSize()));
1020+
}
1021+
});
1022+
rv.setOperation(op);
1023+
addOp(key, op);
1024+
return rv;
1025+
}
1026+
1027+
/**
1028+
* Get the given key to reset its expiration time.
1029+
*
1030+
* @param key the key to fetch
1031+
* @param exp the new expiration to set for the given key
1032+
* @return a future that will hold the return value of the fetch
1033+
* @throws IllegalStateException in the rare circumstance where queue is too
1034+
* full to accept any more requests
1035+
*/
1036+
public OperationFuture<Object> asyncGetAndTouch(final String key,
1037+
final int exp) {
1038+
return asyncGetAndTouch(key, exp, transcoder);
1039+
}
1040+
9891041
/**
9901042
* Gets (with CAS support) with a single key.
9911043
*
@@ -1048,6 +1100,40 @@ public Object get(String key) {
10481100
return get(key, transcoder);
10491101
}
10501102

1103+
/**
1104+
* Get with a single key and reset its expiration.
1105+
*
1106+
* @param <T>
1107+
* @param key the key to get
1108+
* @param exp the new expiration for the key
1109+
* @param tc the transcoder to serialize and unserialize value
1110+
* @return the result from the cache (null if there is none)
1111+
* @throws OperationTimeoutException if the global operation timeout is
1112+
* exceeded
1113+
* @throws java.util.concurrent.CancellationException if operation was canceled
1114+
* @throws IllegalStateException in the rare circumstance where queue is too
1115+
* full to accept any more requests
1116+
*/
1117+
public <T> T getAndTouch(String key, int exp, Transcoder<T> tc) {
1118+
Future<T> future = asyncGetAndTouch(key, exp, tc);
1119+
return getFromFuture(future);
1120+
}
1121+
1122+
/**
1123+
* Get a single key and reset its expiration using the default transcoder.
1124+
*
1125+
* @param key the key to get
1126+
* @param exp the new expiration for the key
1127+
* @return the result from the cache and CAS id (null if there is none)
1128+
* @throws OperationTimeoutException if the global operation timeout is
1129+
* exceeded
1130+
* @throws IllegalStateException in the rare circumstance where queue is too
1131+
* full to accept any more requests
1132+
*/
1133+
public Object getAndTouch(String key, int exp) {
1134+
return getAndTouch(key, exp, transcoder);
1135+
}
1136+
10511137
/**
10521138
* Asynchronously get a bunch of objects from the cache.
10531139
*

src/main/java/net/spy/memcached/MemcachedClientIF.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ <T> Future<CASValue<T>> asyncGets(String key,
8282

8383
Future<CASValue<Object>> asyncGets(String key);
8484

85+
<T> Future<T> asyncGetAndTouch(final String key, final int exp, final Transcoder<T> tc);
86+
87+
Future<Object> asyncGetAndTouch(final String key, final int exp);
88+
8589
<T> CASValue<T> gets(String key, Transcoder<T> tc)
8690
throws OperationTimeoutException;
8791

@@ -92,6 +96,10 @@ <T> T get(String key, Transcoder<T> tc)
9296

9397
Object get(String key) throws OperationTimeoutException;
9498

99+
<T> T getAndTouch(String key, int exp, Transcoder<T> tc);
100+
101+
Object getAndTouch(String key, int exp);
102+
95103
<T> BulkFuture<Map<String, T>> asyncGetBulk(Collection<String> keys,
96104
Iterator<Transcoder<T>> tcs);
97105

src/main/java/net/spy/memcached/OperationFactory.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import net.spy.memcached.ops.ConcatenationType;
6565
import net.spy.memcached.ops.DeleteOperation;
6666
import net.spy.memcached.ops.FlushOperation;
67+
import net.spy.memcached.ops.GetAndTouchOperation;
6768
import net.spy.memcached.ops.GetAttrOperation;
6869
import net.spy.memcached.ops.GetOperation;
6970
import net.spy.memcached.ops.GetsOperation;
@@ -152,6 +153,17 @@ public interface OperationFactory {
152153
*/
153154
GetsOperation gets(Collection<String> keys, GetsOperation.Callback cb, boolean isMGet);
154155

156+
/**
157+
* Gets the value of a key and resets its timeout.
158+
*
159+
* @param key the key to get a value for and reset its timeout
160+
* @param expiration the new expiration for the key
161+
* @param cb the callback that will contain the result
162+
* @return a new GATOperation
163+
*/
164+
GetAndTouchOperation getAndTouch(String key, int expiration,
165+
GetAndTouchOperation.Callback cb);
166+
155167
/**
156168
* Create a mutator operation.
157169
*

src/main/java/net/spy/memcached/ops/BaseOperationFactory.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ public Collection<Operation> clone(KeyedOperation op) {
6060
for (String k : op.getKeys()) {
6161
rv.add(gets(k, getsCb));
6262
}
63+
} else if (op instanceof GetAndTouchOperation) {
64+
GetAndTouchOperation gt = (GetAndTouchOperation) op;
65+
rv.add(getAndTouch(first(gt.getKeys()), gt.getExpiration(),
66+
(GetAndTouchOperation.Callback) gt.getCallback()));
6367
} else if (op instanceof CASOperation) {
6468
CASOperation cop = (CASOperation) op;
6569
rv.add(cas(cop.getStoreType(), first(op.getKeys()),
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* arcus-java-client : Arcus Java client
3+
* Copyright 2010-2014 NAVER Corp.
4+
* Copyright 2014-present JaM2in Co., Ltd.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package net.spy.memcached.ops;
20+
21+
/**
22+
* Gat operation.
23+
*/
24+
public interface GetAndTouchOperation extends KeyedOperation {
25+
26+
/**
27+
* Operation callback for the gat request.
28+
*/
29+
interface Callback extends OperationCallback {
30+
/**
31+
* Callback for each result from a gat.
32+
*
33+
* @param key the key that was retrieved
34+
* @param flags the flags for this value
35+
* @param data the data stored under this key
36+
*/
37+
void gotData(String key, int flags, byte[] data);
38+
}
39+
40+
/**
41+
* Get the expiration to set in case of a new entry.
42+
*/
43+
int getExpiration();
44+
}

src/main/java/net/spy/memcached/protocol/ascii/AsciiOperationFactory.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import net.spy.memcached.ops.ConcatenationType;
6565
import net.spy.memcached.ops.DeleteOperation;
6666
import net.spy.memcached.ops.FlushOperation;
67+
import net.spy.memcached.ops.GetAndTouchOperation;
6768
import net.spy.memcached.ops.GetAttrOperation;
6869
import net.spy.memcached.ops.GetOperation;
6970
import net.spy.memcached.ops.GetsOperation;
@@ -109,6 +110,11 @@ public GetsOperation gets(Collection<String> keys, GetsOperation.Callback cb, bo
109110
return new GetsOperationImpl(keys, cb, isMGet);
110111
}
111112

113+
public GetAndTouchOperation getAndTouch(String key, int expiration,
114+
GetAndTouchOperation.Callback cb) {
115+
return new GetAndTouchOperationImpl(key, expiration, cb, key);
116+
}
117+
112118
public MutatorOperation mutate(Mutator m, String key, int by,
113119
long def, int exp, OperationCallback cb) {
114120
return new MutatorOperationImpl(m, key, by, def, exp, cb);

0 commit comments

Comments
 (0)