Skip to content

Commit eb4c019

Browse files
committed
SPY-153: Adding a typesafe StatusCode for OperationStatus instances.
This makes it possible to add easier checks on futures, while not having to rely on string matching in the status message. This is an addition, so old behavior will not be changed, its just more convenient and can be better documented (it does not directly rely on a server response). Change-Id: Ie416e317d5fd21af2c3efb177b08b68dd8c45639
1 parent ffe7133 commit eb4c019

30 files changed

+242
-52
lines changed

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import net.spy.memcached.ops.OperationState;
7070
import net.spy.memcached.ops.OperationStatus;
7171
import net.spy.memcached.ops.StatsOperation;
72+
import net.spy.memcached.ops.StatusCode;
7273
import net.spy.memcached.ops.StoreOperation;
7374
import net.spy.memcached.ops.StoreType;
7475
import net.spy.memcached.ops.TimedOutOperationStatus;
@@ -2256,7 +2257,7 @@ public boolean cancel(boolean ign) {
22562257
@Override
22572258
public Boolean get(long duration, TimeUnit units)
22582259
throws InterruptedException, TimeoutException, ExecutionException {
2259-
status = new OperationStatus(true, "OK");
2260+
status = new OperationStatus(true, "OK", StatusCode.SUCCESS);
22602261
return super.get(duration, units);
22612262
}
22622263

src/main/java/net/spy/memcached/internal/BulkGetFuture.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import net.spy.memcached.ops.Operation;
4141
import net.spy.memcached.ops.OperationState;
4242
import net.spy.memcached.ops.OperationStatus;
43+
import net.spy.memcached.ops.StatusCode;
4344

4445
/**
4546
* Future for handling results from bulk gets.
@@ -78,7 +79,7 @@ public boolean cancel(boolean ign) {
7879
v.cancel(ign);
7980
}
8081
cancelled = true;
81-
status = new OperationStatus(false, "Cancelled");
82+
status = new OperationStatus(false, "Cancelled", StatusCode.CANCELLED);
8283
notifyListeners();
8384
return rv;
8485
}
@@ -173,7 +174,7 @@ public OperationStatus getStatus() {
173174
try {
174175
get();
175176
} catch (InterruptedException e) {
176-
status = new OperationStatus(false, "Interrupted");
177+
status = new OperationStatus(false, "Interrupted", StatusCode.INTERRUPTED);
177178
Thread.currentThread().interrupt();
178179
} catch (ExecutionException e) {
179180
return status;

src/main/java/net/spy/memcached/internal/OperationFuture.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import net.spy.memcached.ops.Operation;
3737
import net.spy.memcached.ops.OperationState;
3838
import net.spy.memcached.ops.OperationStatus;
39+
import net.spy.memcached.ops.StatusCode;
3940

4041
/**
4142
* Managed future for operations.
@@ -216,7 +217,7 @@ public Long getCas() {
216217
try {
217218
get();
218219
} catch (InterruptedException e) {
219-
status = new OperationStatus(false, "Interrupted");
220+
status = new OperationStatus(false, "Interrupted", StatusCode.INTERRUPTED);
220221
Thread.currentThread().isInterrupted();
221222
} catch (ExecutionException e) {
222223
getLogger().warn("Error getting cas of operation", e);
@@ -241,7 +242,7 @@ public OperationStatus getStatus() {
241242
try {
242243
get();
243244
} catch (InterruptedException e) {
244-
status = new OperationStatus(false, "Interrupted");
245+
status = new OperationStatus(false, "Interrupted", StatusCode.INTERRUPTED);
245246
Thread.currentThread().isInterrupted();
246247
} catch (ExecutionException e) {
247248
getLogger().warn("Error getting status of operation", e);

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ public class CASOperationStatus extends OperationStatus {
3131

3232
private final CASResponse casResponse;
3333

34-
public CASOperationStatus(boolean success, String msg, CASResponse cres) {
35-
super(success, msg);
34+
public CASOperationStatus(boolean success, String msg, CASResponse cres,
35+
StatusCode code) {
36+
super(success, msg, code);
3637
casResponse = cres;
3738
}
3839

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@
2828
public class CancelledOperationStatus extends OperationStatus {
2929

3030
public CancelledOperationStatus() {
31-
super(false, "cancelled");
31+
super(false, "cancelled", StatusCode.CANCELLED);
3232
}
3333
}

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

+13-1
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,16 @@ public class OperationStatus {
2929

3030
private final boolean isSuccess;
3131
private final String message;
32+
private final StatusCode statusCode;
3233

3334
public OperationStatus(boolean success, String msg) {
34-
super();
35+
this(success, msg, null);
36+
}
37+
38+
public OperationStatus(boolean success, String msg, StatusCode code) {
3539
isSuccess = success;
3640
message = msg;
41+
statusCode = code;
3742
}
3843

3944
/**
@@ -50,6 +55,13 @@ public String getMessage() {
5055
return message;
5156
}
5257

58+
/**
59+
* Get the status code associated with the operation status.
60+
*/
61+
public StatusCode getStatusCode() {
62+
return statusCode;
63+
}
64+
5365
@Override
5466
public String toString() {
5567
return "{OperationStatus success=" + isSuccess + ": " + message + "}";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/**
2+
* Copyright (C) 2006-2009 Dustin Sallings
3+
* Copyright (C) 2009-2011 Couchbase, Inc.
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALING
21+
* IN THE SOFTWARE.
22+
*/
23+
24+
package net.spy.memcached.ops;
25+
26+
/**
27+
* Represents status and error codes from the binary protocol.
28+
*/
29+
public enum StatusCode {
30+
31+
SUCCESS,
32+
ERR_NOT_FOUND,
33+
ERR_EXISTS,
34+
ERR_2BIG,
35+
ERR_INVAL,
36+
ERR_NOT_STORED,
37+
ERR_DELTA_BADVAL,
38+
ERR_NOT_MY_VBUCKET,
39+
ERR_UNKNOWN_COMMAND,
40+
ERR_NO_MEM,
41+
ERR_NOT_SUPPORTED,
42+
ERR_INTERNAL,
43+
ERR_BUSY,
44+
ERR_TEMP_FAIL,
45+
CANCELLED,
46+
INTERRUPTED,
47+
TIMEDOUT,
48+
ERR_CLIENT;
49+
50+
public static StatusCode fromBinaryCode(int code) {
51+
switch(code) {
52+
case 0x00:
53+
return SUCCESS;
54+
case 0x01:
55+
return ERR_NOT_FOUND;
56+
case 0x02:
57+
return ERR_EXISTS;
58+
case 0x03:
59+
return ERR_2BIG;
60+
case 0x04:
61+
return ERR_INVAL;
62+
case 0x05:
63+
return ERR_NOT_STORED;
64+
case 0x06:
65+
return ERR_DELTA_BADVAL;
66+
case 0x07:
67+
return ERR_NOT_MY_VBUCKET;
68+
case 0x81:
69+
return ERR_UNKNOWN_COMMAND;
70+
case 0x82:
71+
return ERR_NO_MEM;
72+
case 0x83:
73+
return ERR_NOT_SUPPORTED;
74+
case 0x84:
75+
return ERR_INTERNAL;
76+
case 0x85:
77+
return ERR_BUSY;
78+
case 0x86:
79+
return ERR_TEMP_FAIL;
80+
default:
81+
return ERR_CLIENT;
82+
}
83+
}
84+
85+
public static StatusCode fromAsciiLine(String line) {
86+
if (line.equals("STORED") || line.equals("DELETED")) {
87+
return SUCCESS;
88+
} else if (line.equals("NOT_STORED")) {
89+
return ERR_NOT_STORED;
90+
} else if (line.equals("EXISTS")) {
91+
return ERR_EXISTS;
92+
} else if (line.equals("NOT_FOUND")) {
93+
return ERR_NOT_FOUND;
94+
} else if (line.equals("ERROR")
95+
|| line.matches("^(CLIENT|SERVER)_ERROR.*")) {
96+
return ERR_INTERNAL;
97+
} else {
98+
return ERR_CLIENT;
99+
}
100+
}
101+
102+
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@
2828
public class TimedOutOperationStatus extends OperationStatus {
2929

3030
public TimedOutOperationStatus() {
31-
super(false, "timed out");
31+
super(false, "timed out", StatusCode.TIMEDOUT);
3232
}
3333
}

src/main/java/net/spy/memcached/protocol/BaseOperationImpl.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import net.spy.memcached.ops.OperationException;
3838
import net.spy.memcached.ops.OperationState;
3939
import net.spy.memcached.ops.OperationStatus;
40+
import net.spy.memcached.ops.StatusCode;
4041
import net.spy.memcached.ops.TimedOutOperationStatus;
4142

4243
/**
@@ -172,7 +173,7 @@ protected void handleError(OperationErrorType eType, String line)
172173
assert false;
173174
}
174175
callback.receivedStatus(new OperationStatus(false,
175-
exception.getMessage()));
176+
exception.getMessage(), StatusCode.ERR_INTERNAL));
176177
transitionState(OperationState.COMPLETE);
177178
throw exception;
178179
}

src/main/java/net/spy/memcached/protocol/GetCallbackWrapper.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@
2424

2525
import net.spy.memcached.ops.GetOperation;
2626
import net.spy.memcached.ops.OperationStatus;
27+
import net.spy.memcached.ops.StatusCode;
2728

2829
/**
2930
* Wrapper callback for use in optimized gets.
3031
*/
3132
public class GetCallbackWrapper implements GetOperation.Callback {
3233

33-
private static final OperationStatus END = new OperationStatus(true, "END");
34+
private static final OperationStatus END = new OperationStatus(true, "END",
35+
StatusCode.SUCCESS);
3436

3537
private boolean completed = false;
3638
private int remainingKeys = 0;

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,20 @@
3535
import net.spy.memcached.ops.OperationCallback;
3636
import net.spy.memcached.ops.OperationState;
3737
import net.spy.memcached.ops.OperationStatus;
38+
import net.spy.memcached.ops.StatusCode;
3839
import net.spy.memcached.util.StringUtils;
3940

4041
/**
4142
* Base class for get and gets handlers.
4243
*/
4344
abstract class BaseGetOpImpl extends OperationImpl {
4445

45-
private static final OperationStatus END = new OperationStatus(true, "END");
46+
private static final OperationStatus END = new OperationStatus(true, "END",
47+
StatusCode.SUCCESS);
4648
private static final OperationStatus NOT_FOUND = new OperationStatus(false,
47-
"NOT_FOUND");
49+
"NOT_FOUND", StatusCode.ERR_NOT_FOUND);
4850
private static final OperationStatus LOCK_ERROR = new OperationStatus(false,
49-
"LOCK_ERROR");
51+
"LOCK_ERROR", StatusCode.ERR_TEMP_FAIL);
5052
private static final byte[] RN_BYTES = "\r\n".getBytes();
5153
private final String cmd;
5254
private final Collection<String> keys;

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import net.spy.memcached.ops.OperationCallback;
3131
import net.spy.memcached.ops.OperationState;
3232
import net.spy.memcached.ops.OperationStatus;
33+
import net.spy.memcached.ops.StatusCode;
3334

3435
/**
3536
* Base class for ascii store operations (add, set, replace, append, prepend).
@@ -38,7 +39,7 @@ abstract class BaseStoreOperationImpl extends OperationImpl {
3839

3940
private static final int OVERHEAD = 32;
4041
private static final OperationStatus STORED = new OperationStatus(true,
41-
"STORED");
42+
"STORED", StatusCode.SUCCESS);
4243
protected final String type;
4344
protected final String key;
4445
protected final int flags;

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import net.spy.memcached.ops.OperationCallback;
3434
import net.spy.memcached.ops.OperationState;
3535
import net.spy.memcached.ops.OperationStatus;
36+
import net.spy.memcached.ops.StatusCode;
3637
import net.spy.memcached.ops.StoreType;
3738

3839
class CASOperationImpl extends OperationImpl implements CASOperation {
@@ -43,11 +44,11 @@ class CASOperationImpl extends OperationImpl implements CASOperation {
4344
private static final int OVERHEAD = 64;
4445

4546
private static final OperationStatus STORED = new CASOperationStatus(true,
46-
"STORED", CASResponse.OK);
47+
"STORED", CASResponse.OK, StatusCode.SUCCESS);
4748
private static final OperationStatus NOT_FOUND = new CASOperationStatus(
48-
false, "NOT_FOUND", CASResponse.NOT_FOUND);
49+
false, "NOT_FOUND", CASResponse.NOT_FOUND, StatusCode.ERR_NOT_FOUND);
4950
private static final OperationStatus EXISTS = new CASOperationStatus(false,
50-
"EXISTS", CASResponse.EXISTS);
51+
"EXISTS", CASResponse.EXISTS, StatusCode.ERR_EXISTS);
5152

5253
private final String key;
5354
private final long casValue;

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import net.spy.memcached.ops.OperationCallback;
3232
import net.spy.memcached.ops.OperationState;
3333
import net.spy.memcached.ops.OperationStatus;
34+
import net.spy.memcached.ops.StatusCode;
3435

3536
/**
3637
* Operation to delete an item from the cache.
@@ -41,9 +42,9 @@ final class DeleteOperationImpl extends OperationImpl implements
4142
private static final int OVERHEAD = 32;
4243

4344
private static final OperationStatus DELETED = new OperationStatus(true,
44-
"DELETED");
45+
"DELETED", StatusCode.SUCCESS);
4546
private static final OperationStatus NOT_FOUND = new OperationStatus(false,
46-
"NOT_FOUND");
47+
"NOT_FOUND", StatusCode.ERR_NOT_FOUND);
4748

4849
private final String key;
4950

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import net.spy.memcached.ops.OperationCallback;
2929
import net.spy.memcached.ops.OperationState;
3030
import net.spy.memcached.ops.OperationStatus;
31+
import net.spy.memcached.ops.StatusCode;
3132

3233
/**
3334
* Memcached flush_all operation.
@@ -36,7 +37,8 @@ final class FlushOperationImpl extends OperationImpl implements FlushOperation {
3637

3738
private static final byte[] FLUSH = "flush_all\r\n".getBytes();
3839

39-
private static final OperationStatus OK = new OperationStatus(true, "OK");
40+
private static final OperationStatus OK = new OperationStatus(true, "OK",
41+
StatusCode.SUCCESS);
4042

4143
private final int delay;
4244

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import net.spy.memcached.ops.OperationCallback;
3333
import net.spy.memcached.ops.OperationState;
3434
import net.spy.memcached.ops.OperationStatus;
35+
import net.spy.memcached.ops.StatusCode;
3536

3637
/**
3738
* Operation for mutating integers inside of memcached.
@@ -42,7 +43,7 @@ final class MutatorOperationImpl extends OperationImpl implements
4243
public static final int OVERHEAD = 32;
4344

4445
private static final OperationStatus NOT_FOUND = new OperationStatus(false,
45-
"NOT_FOUND");
46+
"NOT_FOUND", StatusCode.ERR_NOT_FOUND);
4647

4748
private final Mutator mutator;
4849
private final String key;
@@ -63,7 +64,7 @@ public void handleLine(String line) {
6364
if (line.equals("NOT_FOUND")) {
6465
found = NOT_FOUND;
6566
} else {
66-
found = new OperationStatus(true, line);
67+
found = new OperationStatus(true, line, StatusCode.SUCCESS);
6768
}
6869
getCallback().receivedStatus(found);
6970
transitionState(OperationState.COMPLETE);

0 commit comments

Comments
 (0)