Skip to content

Commit c6d47e5

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

File tree

16 files changed

+433
-5
lines changed

16 files changed

+433
-5
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,26 @@ public GetFuture<CASValue<Object>> asyncGets(String key) {
242242
return this.getClient().asyncGets(key);
243243
}
244244

245+
@Override
246+
public <T> GetFuture<T> asyncGetAndTouch(String key, int exp, Transcoder<T> tc) {
247+
return this.getClient().asyncGetAndTouch(key, exp, tc);
248+
}
249+
250+
@Override
251+
public GetFuture<Object> asyncGetAndTouch(String key, int exp) {
252+
return this.getClient().asyncGetAndTouch(key, exp);
253+
}
254+
255+
@Override
256+
public <T> GetFuture<CASValue<T>> asyncGetsAndTouch(String key, int exp, Transcoder<T> tc) {
257+
return this.getClient().asyncGetsAndTouch(key, exp, tc);
258+
}
259+
260+
@Override
261+
public GetFuture<CASValue<Object>> asyncGetsAndTouch(String key, int exp) {
262+
return this.getClient().asyncGetsAndTouch(key, exp);
263+
}
264+
245265
@Override
246266
public <T> CASValue<T> gets(String key, Transcoder<T> tc)
247267
throws OperationTimeoutException {

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

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@
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;
64+
import net.spy.memcached.ops.GetsAndTouchOperation;
6365
import net.spy.memcached.ops.GetsOperation;
6466
import net.spy.memcached.ops.Mutator;
6567
import net.spy.memcached.ops.Operation;
@@ -986,6 +988,107 @@ public GetFuture<CASValue<Object>> asyncGets(final String key) {
986988
return asyncGets(key, transcoder);
987989
}
988990

991+
/**
992+
* Get the given key to reset its expiration time asynchronously.
993+
*
994+
* @param key the key to fetch
995+
* @param exp the new expiration to set for the given key
996+
* @param tc the transcoder to serialize and unserialize value
997+
* @return a future that will hold the return value of the fetch
998+
* @throws IllegalStateException in the rare circumstance where queue is too
999+
* full to accept any more requests
1000+
*/
1001+
public <T> GetFuture<T> asyncGetAndTouch(final String key, final int exp,
1002+
final Transcoder<T> tc) {
1003+
final CountDownLatch latch = new CountDownLatch(1);
1004+
final GetFuture<T> future = new GetFuture<>(latch, operationTimeout);
1005+
1006+
Operation op = opFact.getAndTouch(key, exp,
1007+
new GetAndTouchOperation.Callback() {
1008+
private GetResult<T> result = null;
1009+
1010+
public void receivedStatus(OperationStatus status) {
1011+
future.set(result, status);
1012+
}
1013+
1014+
public void gotData(String k, int flags, byte[] data) {
1015+
assert k.equals(key) : "Wrong key returned";
1016+
result = new GetResultImpl<>(new CachedData(flags, data, tc.getMaxSize()), tc);
1017+
}
1018+
1019+
public void complete() {
1020+
latch.countDown();
1021+
}
1022+
});
1023+
future.setOperation(op);
1024+
addOp(key, op);
1025+
return future;
1026+
}
1027+
1028+
/**
1029+
* Get the given key to reset its expiration time asynchronously.
1030+
*
1031+
* @param key the key to fetch
1032+
* @param exp the new expiration to set for the given key
1033+
* @return a future that will hold the return value of the fetch
1034+
* @throws IllegalStateException in the rare circumstance where queue is too
1035+
* full to accept any more requests
1036+
*/
1037+
public GetFuture<Object> asyncGetAndTouch(final String key, final int exp) {
1038+
return asyncGetAndTouch(key, exp, transcoder);
1039+
}
1040+
1041+
/**
1042+
* Gets (with CAS support) the given key to reset its expiration time asynchronously.
1043+
*
1044+
* @param key the key to fetch
1045+
* @param exp the new expiration to set for the given key
1046+
* @param tc the transcoder to serialize and unserialize value
1047+
* @return a future that will hold the return value of the fetch
1048+
* @throws IllegalStateException in the rare circumstance where queue is too
1049+
* full to accept any more requests
1050+
*/
1051+
public <T> GetFuture<CASValue<T>> asyncGetsAndTouch(final String key, final int exp,
1052+
final Transcoder<T> tc) {
1053+
final CountDownLatch latch = new CountDownLatch(1);
1054+
final GetFuture<CASValue<T>> rv = new GetFuture<>(latch, operationTimeout);
1055+
1056+
Operation op = opFact.getsAndTouch(key, exp,
1057+
new GetsAndTouchOperation.Callback() {
1058+
private GetResult<CASValue<T>> val = null;
1059+
1060+
public void receivedStatus(OperationStatus status) {
1061+
rv.set(val, status);
1062+
}
1063+
1064+
public void gotData(String k, int flags, long cas, byte[] data) {
1065+
assert key.equals(k) : "Wrong key returned";
1066+
assert cas > 0 : "CAS was less than zero: " + cas;
1067+
val = new GetsResultImpl<>(cas, new CachedData(flags, data, tc.getMaxSize()), tc);
1068+
}
1069+
1070+
public void complete() {
1071+
latch.countDown();
1072+
}
1073+
});
1074+
rv.setOperation(op);
1075+
addOp(key, op);
1076+
return rv;
1077+
}
1078+
1079+
/**
1080+
* Gets (with CAS support) the given key to reset its expiration time asynchronously.
1081+
*
1082+
* @param key the key to fetch
1083+
* @param exp the new expiration to set for the given key
1084+
* @return a future that will hold the return value of the fetch
1085+
* @throws IllegalStateException in the rare circumstance where queue is too
1086+
* full to accept any more requests
1087+
*/
1088+
public GetFuture<CASValue<Object>> asyncGetsAndTouch(final String key, final int exp) {
1089+
return asyncGetsAndTouch(key, exp, transcoder);
1090+
}
1091+
9891092
/**
9901093
* Gets (with CAS support) with a single key.
9911094
*

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ <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+
89+
<T> Future<CASValue<T>> asyncGetsAndTouch(final String key, final int exp,
90+
final Transcoder<T> tc);
91+
92+
Future<CASValue<Object>> asyncGetsAndTouch(final String key, final int exp);
93+
8594
<T> CASValue<T> gets(String key, Transcoder<T> tc)
8695
throws OperationTimeoutException;
8796

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@
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;
70+
import net.spy.memcached.ops.GetsAndTouchOperation;
6971
import net.spy.memcached.ops.GetsOperation;
7072
import net.spy.memcached.ops.KeyedOperation;
7173
import net.spy.memcached.ops.MultiOperationCallback;
@@ -152,6 +154,28 @@ public interface OperationFactory {
152154
*/
153155
GetsOperation gets(Collection<String> keys, GetsOperation.Callback cb, boolean isMGet);
154156

157+
/**
158+
* Get the key and resets its timeout.
159+
*
160+
* @param key the key to get a value for and reset its timeout
161+
* @param expiration the new expiration for the key
162+
* @param cb the callback that will contain the result
163+
* @return a new GetAndTouchOperation
164+
*/
165+
GetAndTouchOperation getAndTouch(String key, int expiration,
166+
GetAndTouchOperation.Callback cb);
167+
168+
/**
169+
* Gets (with CAS support) the key and resets its timeout.
170+
*
171+
* @param key the key to get a value for and reset its timeout
172+
* @param expiration the new expiration for the key
173+
* @param cb the callback that will contain the result
174+
* @return a new GetsAndTouchOperation
175+
*/
176+
GetsAndTouchOperation getsAndTouch(String key, int expiration,
177+
GetsAndTouchOperation.Callback cb);
178+
155179
/**
156180
* Create a mutator operation.
157181
*

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public enum APIType {
2525
INCR(OperationType.WRITE), DECR(OperationType.WRITE),
2626
DELETE(OperationType.WRITE),
2727
GET(OperationType.READ), GETS(OperationType.READ),
28+
GAT(OperationType.WRITE), GATS(OperationType.WRITE),
2829

2930
// List API Type
3031
LOP_CREATE(OperationType.WRITE),

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ 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()));
67+
} else if (op instanceof GetsAndTouchOperation) {
68+
GetsAndTouchOperation gt = (GetsAndTouchOperation) op;
69+
rv.add(getsAndTouch(first(gt.getKeys()), gt.getExpiration(),
70+
(GetsAndTouchOperation.Callback) gt.getCallback()));
6371
} else if (op instanceof CASOperation) {
6472
CASOperation cop = (CASOperation) op;
6573
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(GetAndTouch) 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+
}
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+
* Gats(GetsAndTouch) operation.
23+
*/
24+
public interface GetsAndTouchOperation extends KeyedOperation {
25+
/**
26+
* Operation callback for the gats request.
27+
*/
28+
interface Callback extends OperationCallback {
29+
/**
30+
* Callback for each result from a gats.
31+
*
32+
* @param key the key that was retrieved
33+
* @param flags the flags for this value
34+
* @param cas the CAS value for this record
35+
* @param data the data stored under this key
36+
*/
37+
void gotData(String key, int flags, long cas, 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/ops/OperationType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public enum OperationType {
2525
* BTreeInsertAndGetOperationImpl (asyncBopInsertAndGetTrimmed)
2626
* FlushOperationImpl / FlushByPrefixOperationImpl (flush)
2727
* SetAttrOperationImpl (asyncSetAttr)
28+
* GetAndTouchOperationImpl / GetsAndTouchOperationImpl (asyncGetAndTouch / asyncGetsAndTouch)
2829
*/
2930
WRITE,
3031

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@
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;
70+
import net.spy.memcached.ops.GetsAndTouchOperation;
6971
import net.spy.memcached.ops.GetsOperation;
7072
import net.spy.memcached.ops.Mutator;
7173
import net.spy.memcached.ops.MutatorOperation;
@@ -109,6 +111,16 @@ public GetsOperation gets(Collection<String> keys, GetsOperation.Callback cb, bo
109111
return new GetsOperationImpl(keys, cb, isMGet);
110112
}
111113

114+
public GetAndTouchOperation getAndTouch(String key, int expiration,
115+
GetAndTouchOperation.Callback cb) {
116+
return new GetAndTouchOperationImpl(key, expiration, cb);
117+
}
118+
119+
public GetsAndTouchOperation getsAndTouch(String key, int expiration,
120+
GetsAndTouchOperation.Callback cb) {
121+
return new GetsAndTouchOperationImpl(key, expiration, cb);
122+
}
123+
112124
public MutatorOperation mutate(Mutator m, String key, int by,
113125
long def, int exp, OperationCallback cb) {
114126
return new MutatorOperationImpl(m, key, by, def, exp, cb);

0 commit comments

Comments
 (0)