Skip to content

Commit 6ce52d2

Browse files
Mike WiederholdMichael Wiederhold
authored andcommitted
Added all memcached error codes to spymemcached.
Previously we only checked a subset of the error codes that memcached can send back to a client. This created an issue because if a user recieves an error code that it doesn't expect it resets the connection. This commit adds all error codes. Change-Id: I9317eccd688b6fa1e7113847cd7c7ef160a6624f Reviewed-on: http://review.couchbase.org/7006 Reviewed-by: Michael Wiederhold <[email protected]> Tested-by: Michael Wiederhold <[email protected]>
1 parent d6008b7 commit 6ce52d2

File tree

9 files changed

+100
-145
lines changed

9 files changed

+100
-145
lines changed

src/main/java/net/spy/memcached/protocol/binary/ConcatenationOperationImpl.java

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import net.spy.memcached.ops.ConcatenationOperation;
77
import net.spy.memcached.ops.ConcatenationType;
88
import net.spy.memcached.ops.OperationCallback;
9-
import net.spy.memcached.ops.OperationStatus;
109

1110
class ConcatenationOperationImpl extends OperationImpl
1211
implements ConcatenationOperation {
@@ -44,27 +43,6 @@ public void initialize() {
4443
prepareBuffer(key, cas, data);
4544
}
4645

47-
@Override
48-
protected OperationStatus getStatusForErrorCode(int errCode, byte[] errPl) {
49-
OperationStatus baseStatus = super.getStatusForErrorCode(errCode, errPl);
50-
if (baseStatus != null) {
51-
return baseStatus;
52-
}
53-
OperationStatus rv=null;
54-
switch(errCode) {
55-
case ERR_EXISTS:
56-
rv=EXISTS_STATUS;
57-
break;
58-
case ERR_NOT_FOUND:
59-
rv=NOT_FOUND_STATUS;
60-
break;
61-
case ERR_NOT_STORED:
62-
rv=NOT_FOUND_STATUS;
63-
break;
64-
}
65-
return rv;
66-
}
67-
6846
public Collection<String> getKeys() {
6947
return Collections.singleton(key);
7048
}

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

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import net.spy.memcached.ops.DeleteOperation;
77
import net.spy.memcached.ops.OperationCallback;
8-
import net.spy.memcached.ops.OperationStatus;
98

109
class DeleteOperationImpl extends OperationImpl implements
1110
DeleteOperation {
@@ -30,15 +29,6 @@ public void initialize() {
3029
prepareBuffer(key, cas, EMPTY_BYTES);
3130
}
3231

33-
@Override
34-
protected OperationStatus getStatusForErrorCode(int errCode, byte[] errPl) {
35-
OperationStatus baseStatus = super.getStatusForErrorCode(errCode, errPl);
36-
if (baseStatus != null) {
37-
return baseStatus;
38-
}
39-
return errCode == ERR_NOT_FOUND ? NOT_FOUND_STATUS : null;
40-
}
41-
4232
public Collection<String> getKeys() {
4333
return Collections.singleton(key);
4434
}

src/main/java/net/spy/memcached/protocol/binary/GetOperationImpl.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import net.spy.memcached.ops.GetlOperation;
99
import net.spy.memcached.ops.GetsOperation;
1010
import net.spy.memcached.ops.OperationCallback;
11-
import net.spy.memcached.ops.OperationStatus;
1211

1312
class GetOperationImpl extends OperationImpl
1413
implements GetOperation, GetsOperation, GetlOperation,
@@ -84,15 +83,6 @@ protected void decodePayload(byte[] pl) {
8483
getCallback().receivedStatus(STATUS_OK);
8584
}
8685

87-
@Override
88-
protected OperationStatus getStatusForErrorCode(int errCode, byte[] errPl) {
89-
OperationStatus baseStatus = super.getStatusForErrorCode(errCode, errPl);
90-
if (baseStatus != null) {
91-
return baseStatus;
92-
}
93-
return errCode == ERR_NOT_FOUND ? NOT_FOUND_STATUS : null;
94-
}
95-
9686
public Collection<String> getKeys() {
9787
return Collections.singleton(key);
9888
}

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

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,6 @@ public void initialize() {
4646
prepareBuffer(key, 0, EMPTY_BYTES, by, defBytes, exp);
4747
}
4848

49-
@Override
50-
protected OperationStatus getStatusForErrorCode(int errCode, byte[] errPl) {
51-
OperationStatus baseStatus = super.getStatusForErrorCode(errCode, errPl);
52-
if (baseStatus != null) {
53-
return baseStatus;
54-
}
55-
return errCode == ERR_NOT_FOUND ? NOT_FOUND_STATUS : null;
56-
}
57-
5849
@Override
5950
protected void decodePayload(byte[] pl) {
6051
getCallback().receivedStatus(new OperationStatus(true,

src/main/java/net/spy/memcached/protocol/binary/OperationImpl.java

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,23 @@ abstract class OperationImpl extends BaseOperationImpl implements Operation {
2525
protected static final int MIN_RECV_PACKET=24;
2626

2727
/**
28-
* Error code for items that were not found.
28+
* Error code for operations.
2929
*/
30+
protected static final int SUCCESS = 0x00;
3031
protected static final int ERR_NOT_FOUND = 0x01;
3132
protected static final int ERR_EXISTS = 0x02;
32-
protected static final int ERR_EINVAL = 0x04;
33+
protected static final int ERR_2BIG = 0x03;
34+
protected static final int ERR_INVAL = 0x04;
3335
protected static final int ERR_NOT_STORED = 0x05;
36+
protected static final int ERR_DELTA_BADVAL = 0x06;
3437
protected static final int ERR_NOT_MY_VBUCKET = 0x07;
38+
protected static final int ERR_UNKNOWN_COMMAND = 0x81;
39+
protected static final int ERR_NO_MEM = 0x82;
40+
protected static final int ERR_NOT_SUPPORTED = 0x83;
41+
protected static final int ERR_INTERNAL = 0x84;
42+
protected static final int ERR_BUSY = 0x85;
3543
protected static final int ERR_TEMP_FAIL = 0x86;
3644

37-
protected static final OperationStatus NOT_FOUND_STATUS =
38-
new CASOperationStatus(false, "Not Found", CASResponse.NOT_FOUND);
39-
protected static final OperationStatus EXISTS_STATUS =
40-
new CASOperationStatus(false, "Object exists", CASResponse.EXISTS);
41-
protected static final OperationStatus NOT_STORED_STATUS =
42-
new CASOperationStatus(false, "Not Stored", CASResponse.NOT_FOUND);
43-
protected static final OperationStatus NOT_MY_VBUCKET_STATUS =
44-
new OperationStatus(false, "Not my vbucket");
45-
protected static final OperationStatus TEMP_FAIL =
46-
new OperationStatus(false, "Temporary Error");
47-
4845
protected static final byte[] EMPTY_BYTES = new byte[0];
4946

5047
protected static final OperationStatus STATUS_OK =
@@ -148,20 +145,18 @@ public void readFromBuffer(ByteBuffer b) throws IOException {
148145
}
149146

150147
protected void finishedPayload(byte[] pl) throws IOException {
151-
if(errorCode != 0) {
152-
OperationStatus status=getStatusForErrorCode(errorCode, pl);
153-
if(status == null) {
154-
handleError(OperationErrorType.SERVER, new String(pl));
155-
} else if (status == NOT_MY_VBUCKET_STATUS && !getState().equals(OperationState.COMPLETE)) {
156-
transitionState(OperationState.RETRY);
157-
//errorCode = 0;
158-
} else {
159-
getCallback().receivedStatus(status);
160-
transitionState(OperationState.COMPLETE);
161-
}
162-
} else {
148+
OperationStatus status=getStatusForErrorCode(errorCode, pl);
149+
150+
if(status == null) {
151+
handleError(OperationErrorType.SERVER, new String(pl));
152+
} else if(errorCode == SUCCESS) {
163153
decodePayload(pl);
164154
transitionState(OperationState.COMPLETE);
155+
} else if (errorCode == ERR_NOT_MY_VBUCKET && !getState().equals(OperationState.COMPLETE)) {
156+
transitionState(OperationState.RETRY);
157+
} else {
158+
getCallback().receivedStatus(status);
159+
transitionState(OperationState.COMPLETE);
165160
}
166161
}
167162

@@ -172,11 +167,29 @@ protected void finishedPayload(byte[] pl) throws IOException {
172167
* @return the status to return, or null if this is an exceptional case
173168
*/
174169
protected OperationStatus getStatusForErrorCode(int errCode, byte[] errPl) {
175-
if (errCode == ERR_NOT_MY_VBUCKET) {
176-
getLogger().warn("Not_my_vbucket on operation " + this);
177-
return NOT_MY_VBUCKET_STATUS;
178-
}
179-
return null;
170+
switch (errCode) {
171+
case SUCCESS:
172+
return STATUS_OK;
173+
case ERR_NOT_FOUND:
174+
return new CASOperationStatus(false, new String(errPl), CASResponse.NOT_FOUND);
175+
case ERR_EXISTS:
176+
return new CASOperationStatus(false, new String(errPl), CASResponse.EXISTS);
177+
case ERR_NOT_STORED:
178+
return new CASOperationStatus(false, new String(errPl), CASResponse.NOT_FOUND);
179+
case ERR_2BIG:
180+
case ERR_INVAL:
181+
case ERR_DELTA_BADVAL:
182+
case ERR_NOT_MY_VBUCKET:
183+
case ERR_UNKNOWN_COMMAND:
184+
case ERR_NO_MEM:
185+
case ERR_NOT_SUPPORTED:
186+
case ERR_INTERNAL:
187+
case ERR_BUSY:
188+
case ERR_TEMP_FAIL:
189+
return new OperationStatus(false, new String(errPl));
190+
default:
191+
return null;
192+
}
180193
}
181194

182195
/**

src/main/java/net/spy/memcached/protocol/binary/OptimizedSetImpl.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -137,26 +137,6 @@ protected void finishedPayload(byte[] pl) throws IOException {
137137
resetInput();
138138
}
139139

140-
@Override
141-
protected OperationStatus getStatusForErrorCode(int errCode, byte[] errPl) {
142-
OperationStatus rv=null;
143-
switch(errCode) {
144-
case ERR_EXISTS:
145-
rv=EXISTS_STATUS;
146-
break;
147-
case ERR_NOT_FOUND:
148-
rv=NOT_FOUND_STATUS;
149-
break;
150-
case ERR_TEMP_FAIL:
151-
rv=TEMP_FAIL;
152-
break;
153-
case ERR_NOT_MY_VBUCKET:
154-
rv = NOT_MY_VBUCKET_STATUS;
155-
break;
156-
}
157-
return rv;
158-
}
159-
160140
@Override
161141
protected boolean opaqueIsValid() {
162142
return responseOpaque == terminalOpaque

src/main/java/net/spy/memcached/protocol/binary/StoreOperationImpl.java

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import net.spy.memcached.ops.CASOperation;
77
import net.spy.memcached.ops.OperationCallback;
8-
import net.spy.memcached.ops.OperationStatus;
98
import net.spy.memcached.ops.StoreOperation;
109
import net.spy.memcached.ops.StoreType;
1110

@@ -58,27 +57,6 @@ public void initialize() {
5857
prepareBuffer(key, cas, data, flags, exp);
5958
}
6059

61-
@Override
62-
protected OperationStatus getStatusForErrorCode(int errCode, byte[] errPl) {
63-
OperationStatus baseStatus = super.getStatusForErrorCode(errCode, errPl);
64-
if (baseStatus != null) {
65-
return baseStatus;
66-
}
67-
OperationStatus rv=null;
68-
switch(errCode) {
69-
case ERR_EXISTS:
70-
rv=EXISTS_STATUS;
71-
break;
72-
case ERR_NOT_FOUND:
73-
rv=NOT_FOUND_STATUS;
74-
break;
75-
case ERR_TEMP_FAIL:
76-
rv=TEMP_FAIL;
77-
break;
78-
}
79-
return rv;
80-
}
81-
8260
public Collection<String> getKeys() {
8361
return Collections.singleton(key);
8462
}

src/main/java/net/spy/memcached/protocol/binary/TouchOperationImpl.java

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import net.spy.memcached.ops.KeyedOperation;
77
import net.spy.memcached.ops.OperationCallback;
8-
import net.spy.memcached.ops.OperationStatus;
98

109
/**
1110
* Operation to reset a timeout in Membase server.
@@ -29,27 +28,6 @@ public Collection<String> getKeys() {
2928
return Collections.singleton(key);
3029
}
3130

32-
@Override
33-
protected OperationStatus getStatusForErrorCode(int errCode, byte[] errPl) {
34-
OperationStatus baseStatus = super.getStatusForErrorCode(errCode, errPl);
35-
if (baseStatus != null) {
36-
return baseStatus;
37-
}
38-
OperationStatus rv=null;
39-
switch(errCode) {
40-
case ERR_EXISTS:
41-
rv=EXISTS_STATUS;
42-
break;
43-
case ERR_NOT_FOUND:
44-
rv=NOT_FOUND_STATUS;
45-
break;
46-
case ERR_TEMP_FAIL:
47-
rv=TEMP_FAIL;
48-
break;
49-
}
50-
return rv;
51-
}
52-
5331
@Override
5432
public void initialize() {
5533
prepareBuffer(key, 0, EMPTY_BYTES, exp);
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package net.spy.memcached;
2+
3+
import java.nio.ByteBuffer;
4+
import java.util.HashMap;
5+
import java.util.Map.Entry;
6+
7+
import net.spy.memcached.ops.GetOperation;
8+
import net.spy.memcached.ops.OperationStatus;
9+
import net.spy.memcached.protocol.binary.BinaryOperationFactory;
10+
import junit.framework.TestCase;
11+
12+
public class ErrorCodeTest extends TestCase {
13+
14+
public void testErrorCodes() throws Exception {
15+
HashMap<Byte, String> err_map = new HashMap<Byte, String>();
16+
OperationFactory opFact = new BinaryOperationFactory();
17+
18+
err_map.put(new Byte((byte) 0x01), "NOT FOUND");
19+
err_map.put(new Byte((byte) 0x02), "EXISTS");
20+
err_map.put(new Byte((byte) 0x03), "2BIG");
21+
err_map.put(new Byte((byte) 0x04), "INVAL");
22+
err_map.put(new Byte((byte) 0x05), "NOT STORED");
23+
err_map.put(new Byte((byte) 0x06), "DELTA BAD VAL");
24+
err_map.put(new Byte((byte) 0x07), "NOT MY VBUCKET");
25+
err_map.put(new Byte((byte) 0x81), "UNKNOWN COMMAND");
26+
err_map.put(new Byte((byte) 0x82), "NO MEM");
27+
err_map.put(new Byte((byte) 0x83), "NOT SUPPORTED");
28+
err_map.put(new Byte((byte) 0x84), "INTERNAL ERROR");
29+
err_map.put(new Byte((byte) 0x85), "BUSY");
30+
err_map.put(new Byte((byte) 0x86), "TEMP FAIL");
31+
32+
int opaque = 0;
33+
for (final Entry<Byte, String> err : err_map.entrySet()) {
34+
byte[] b = new byte[24 + err.getValue().length()];
35+
b[0] = (byte)0x81;
36+
b[7] = err.getKey();
37+
b[11] = (byte) err.getValue().length();
38+
b[15] = (byte) ++opaque;
39+
System.arraycopy(err.getValue().getBytes(), 0, b, 24, err.getValue().length());
40+
41+
GetOperation op=opFact.get("key",
42+
new GetOperation.Callback() {
43+
public void receivedStatus(OperationStatus s) {
44+
assert !s.isSuccess();
45+
assert err.getValue().equals(s.getMessage());
46+
}
47+
public void gotData(String k, int flags, byte[] data) {
48+
49+
}
50+
public void complete() {
51+
}});
52+
ByteBuffer bb = ByteBuffer.wrap(b);
53+
bb.flip();
54+
op.readFromBuffer(bb);
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)