Skip to content

Commit 7367c7f

Browse files
committed
fix getmulti bugs
upgrade to 2.5.3 add more test cases improve the performance a little bit for the getMulti
1 parent f58fbd6 commit 7367c7f

File tree

10 files changed

+120
-207
lines changed

10 files changed

+120
-207
lines changed

build.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ build.dir=classes
3333
test.build.dir=testclasses
3434
build.instr.dir=classesinstr
3535
project=java_memcached-release
36-
ver=2.5.2
36+
ver=2.5.3
3737
junit.jar=lib/junit.jar
3838
log4j.jar=lib/log4j.jar
3939
emma.dir=lib

doc/CVS/Entries

Lines changed: 0 additions & 6 deletions
This file was deleted.

doc/CVS/Repository

Lines changed: 0 additions & 1 deletion
This file was deleted.

doc/CVS/Root

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/main/com/schooner/MemCached/AscIIClient.java

Lines changed: 27 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public AscIIClient(String poolName, ClassLoader cl, ErrorHandler eh) {
120120
private void init() {
121121
this.sanitizeKeys = true;
122122
this.primitiveAsString = false;
123-
this.compressEnable = true;
123+
this.compressEnable = false;
124124
this.compressThreshold = COMPRESS_THRESH;
125125
this.defaultEncoding = "UTF-8";
126126
this.poolName = (this.poolName == null) ? "default" : this.poolName;
@@ -185,13 +185,13 @@ public boolean delete(String key, Integer hashCode, Date expiry) {
185185
String line = new SockInputStream(sock, Integer.MAX_VALUE).getLine();
186186
if (DELETED.equals(line)) { // successful
187187
if (log.isInfoEnabled())
188-
log.info(new StringBuffer().append("++++ deletion of key: ").append(key).append(
189-
" from cache was a success").toString());
188+
log.info(new StringBuffer().append("++++ deletion of key: ").append(key)
189+
.append(" from cache was a success").toString());
190190
return true;
191191
} else if (NOTFOUND.equals(line)) { // key not found
192192
if (log.isInfoEnabled())
193-
log.info(new StringBuffer().append("++++ deletion of key: ").append(key).append(
194-
" from cache failed as the key was not found").toString());
193+
log.info(new StringBuffer().append("++++ deletion of key: ").append(key)
194+
.append(" from cache failed as the key was not found").toString());
195195
} else { // other error information
196196
log.error(new StringBuffer().append("++++ error deleting key: ").append(key).toString());
197197
log.error(new StringBuffer().append("++++ server response: ").append(line).toString());
@@ -559,8 +559,8 @@ private long incrdecr(String cmdname, String key, long inc, Integer hashCode) {
559559
}
560560

561561
try {
562-
String cmd = new StringBuffer().append(cmdname).append(" ").append(key).append(" ").append(inc).append(
563-
"\r\n").toString();
562+
String cmd = new StringBuffer().append(cmdname).append(" ").append(key).append(" ").append(inc)
563+
.append("\r\n").toString();
564564
sock.write(cmd.getBytes());
565565
// get result code
566566
String line = new SockInputStream(sock, Integer.MAX_VALUE).getLine().split("\r\n")[0];
@@ -626,7 +626,7 @@ public MemcachedItem gets(String key, Integer hashCode) {
626626
* If the data was compressed or serialized when compressed, it will
627627
* automatically<br/>
628628
* be decompressed or serialized, as appropriate. (Inclusive or)<br/>
629-
*<br/>
629+
* <br/>
630630
* Non-serialized data will be returned as a string, so explicit conversion
631631
* to<br/>
632632
* numeric types will be necessary, if desired<br/>
@@ -1004,49 +1004,7 @@ public Map<String, Object> getMulti(String[] keys) {
10041004
}
10051005

10061006
public Map<String, Object> getMulti(String[] keys, Integer[] hashCodes) {
1007-
1008-
if (keys == null || keys.length == 0) {
1009-
log.error("missing keys for getMulti()");
1010-
return null;
1011-
}
1012-
1013-
Map<String, StringBuilder> cmdMap = new HashMap<String, StringBuilder>();
1014-
1015-
for (int i = 0; i < keys.length; ++i) {
1016-
1017-
String key = keys[i];
1018-
if (key == null) {
1019-
log.error("null key, so skipping");
1020-
continue;
1021-
}
1022-
1023-
Integer hash = null;
1024-
if (hashCodes != null && hashCodes.length > i)
1025-
hash = hashCodes[i];
1026-
1027-
// get SockIO obj from cache key
1028-
SchoonerSockIO sock = pool.getSock(key, hash);
1029-
1030-
if (sock == null) {
1031-
continue;
1032-
}
1033-
1034-
// store in map and list if not already
1035-
if (!cmdMap.containsKey(sock.getHost()))
1036-
cmdMap.put(sock.getHost(), new StringBuilder("get"));
1037-
1038-
cmdMap.get(sock.getHost()).append(" " + key);
1039-
1040-
// return to pool
1041-
sock.close();
1042-
}
1043-
// now query memcache
1044-
Map<String, Object> ret = new HashMap<String, Object>(keys.length);
1045-
1046-
// now use new NIO implementation
1047-
(new NIOLoader(this)).doMulti(cmdMap, keys, ret);
1048-
1049-
return ret;
1007+
return getMulti(keys, hashCodes, false);
10501008
}
10511009

10521010
/**
@@ -1074,9 +1032,8 @@ public Map<String, Object> getMulti(String[] keys, Integer[] hashCodes, boolean
10741032
}
10751033

10761034
Map<String, StringBuilder> cmdMap = new HashMap<String, StringBuilder>();
1077-
1035+
String[] cleanKeys = new String[keys.length];
10781036
for (int i = 0; i < keys.length; ++i) {
1079-
10801037
String key = keys[i];
10811038
if (key == null) {
10821039
log.error("null key, so skipping");
@@ -1087,9 +1044,9 @@ public Map<String, Object> getMulti(String[] keys, Integer[] hashCodes, boolean
10871044
if (hashCodes != null && hashCodes.length > i)
10881045
hash = hashCodes[i];
10891046

1090-
String cleanKey = key;
1047+
cleanKeys[i] = key;
10911048
try {
1092-
cleanKey = sanitizeKey(key);
1049+
cleanKeys[i] = sanitizeKey(key);
10931050
} catch (UnsupportedEncodingException e) {
10941051
// if we have an errorHandler, use its hook
10951052
if (errorHandler != null)
@@ -1099,7 +1056,7 @@ public Map<String, Object> getMulti(String[] keys, Integer[] hashCodes, boolean
10991056
}
11001057

11011058
// get SockIO obj from cache key
1102-
SchoonerSockIO sock = pool.getSock(cleanKey, hash);
1059+
SchoonerSockIO sock = pool.getSock(cleanKeys[i], hash);
11031060

11041061
if (sock == null) {
11051062
if (errorHandler != null)
@@ -1111,7 +1068,7 @@ public Map<String, Object> getMulti(String[] keys, Integer[] hashCodes, boolean
11111068
if (!cmdMap.containsKey(sock.getHost()))
11121069
cmdMap.put(sock.getHost(), new StringBuilder("get"));
11131070

1114-
cmdMap.get(sock.getHost()).append(" " + cleanKey);
1071+
cmdMap.get(sock.getHost()).append(" " + cleanKeys[i]);
11151072

11161073
// return to pool
11171074
sock.close();
@@ -1127,28 +1084,17 @@ public Map<String, Object> getMulti(String[] keys, Integer[] hashCodes, boolean
11271084
(new NIOLoader(this)).doMulti(asString, cmdMap, keys, ret);
11281085

11291086
// fix the return array in case we had to rewrite any of the keys
1130-
for (String key : keys) {
1131-
1132-
String cleanKey = key;
1133-
try {
1134-
cleanKey = sanitizeKey(key);
1135-
} catch (UnsupportedEncodingException e) {
1136-
// if we have an errorHandler, use its hook
1137-
if (errorHandler != null)
1138-
errorHandler.handleErrorOnGet(this, e, key);
1139-
1140-
log.error("failed to sanitize your key!", e);
1141-
continue;
1142-
}
1087+
for (int i=0;i<keys.length;++i) {
11431088

1144-
if (!key.equals(cleanKey) && ret.containsKey(cleanKey)) {
1145-
ret.put(key, ret.get(cleanKey));
1146-
ret.remove(cleanKey);
1089+
//if key!=cleanKey and result has cleankey
1090+
if (!keys[i].equals(cleanKeys[i]) && ret.containsKey(cleanKeys[i])) {
1091+
ret.put(keys[i], ret.get(cleanKeys[i]));
1092+
ret.remove(cleanKeys[i]);
11471093
}
11481094

11491095
// backfill missing keys w/ null value
1150-
if (!ret.containsKey(key))
1151-
ret.put(key, null);
1096+
if (!ret.containsKey(keys[i]))
1097+
ret.put(keys[i], null);
11521098
}
11531099

11541100
if (log.isDebugEnabled())
@@ -1501,8 +1447,8 @@ public ByteBuffer getBuffer() {
15011447
}
15021448

15031449
public String toString() {
1504-
return new StringBuffer().append("Connection to ").append(sock.getHost()).append(" with ").append(
1505-
incoming.size()).append(" bufs; done is ").append(isDone).toString();
1450+
return new StringBuffer().append("Connection to ").append(sock.getHost()).append(" with ")
1451+
.append(incoming.size()).append(" bufs; done is ").append(isDone).toString();
15061452
}
15071453
}
15081454

@@ -1658,15 +1604,15 @@ public boolean sync(String key, Integer hashCode) {
16581604
String line = new SockInputStream(sock, Integer.MAX_VALUE).getLine();
16591605
if (SYNCED.equals(line)) {
16601606
if (log.isInfoEnabled())
1661-
log.info(new StringBuffer().append("++++ sync of key: ").append(key).append(
1662-
" from cache was a success").toString());
1607+
log.info(new StringBuffer().append("++++ sync of key: ").append(key)
1608+
.append(" from cache was a success").toString());
16631609

16641610
// return sock to pool and bail here
16651611
return true;
16661612
} else if (NOTFOUND.equals(line)) {
16671613
if (log.isInfoEnabled())
1668-
log.info(new StringBuffer().append("++++ sync of key: ").append(key).append(
1669-
" from cache failed as the key was not found").toString());
1614+
log.info(new StringBuffer().append("++++ sync of key: ").append(key)
1615+
.append(" from cache failed as the key was not found").toString());
16701616
} else {
16711617
log.error(new StringBuffer().append("++++ error sync key: ").append(key).toString());
16721618
log.error(new StringBuffer().append("++++ server response: ").append(line).toString());

src/main/com/schooner/MemCached/BinaryClient.java

Lines changed: 30 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -777,53 +777,26 @@ public Map<String, Object> getMulti(String[] keys) {
777777
}
778778

779779
public Map<String, Object> getMulti(String[] keys, Integer[] hashCodes) {
780-
781-
if (keys == null || keys.length == 0) {
782-
log.error("missing keys for getMulti()");
783-
return null;
784-
}
785-
786-
Map<String, ArrayList<String>> cmdMap = new HashMap<String, ArrayList<String>>();
787-
788-
for (int i = 0; i < keys.length; ++i) {
789-
790-
String key = keys[i];
791-
if (key == null) {
792-
log.error("null key, so skipping");
793-
continue;
794-
}
795-
796-
Integer hash = null;
797-
if (hashCodes != null && hashCodes.length > i)
798-
hash = hashCodes[i];
799-
800-
// get SockIO obj from cache key
801-
SchoonerSockIO sock = pool.getSock(key, hash);
802-
803-
if (sock == null) {
804-
if (errorHandler != null)
805-
errorHandler.handleErrorOnGet(this, new IOException("no socket to server available"), key);
806-
continue;
807-
}
808-
809-
// store in map and list if not already
810-
if (!cmdMap.containsKey(sock.getHost()))
811-
cmdMap.put(sock.getHost(), new ArrayList<String>());
812-
813-
cmdMap.get(sock.getHost()).add(key);
814-
815-
// return to pool
816-
sock.close();
817-
}
818-
// now query memcache
819-
Map<String, Object> ret = new HashMap<String, Object>(keys.length);
820-
821-
// now use new NIO implementation
822-
(new NIOLoader(this)).doMulti(cmdMap, keys, ret);
823-
824-
return ret;
780+
return getMulti(keys, hashCodes, false);
825781
}
826782

783+
/**
784+
* Retrieve multiple keys from the memcache.
785+
*
786+
* This is recommended over repeated calls to {@link #get(String) get()},
787+
* since it<br/>
788+
* is more efficient.<br/>
789+
*
790+
* @param keys
791+
* keys to retrieve
792+
* @param hashCodes
793+
* if not null, then the Integer array of hashCodes
794+
* @param asString
795+
* if true then retrieve using String val
796+
* @return a hashmap with entries for each key is found by the server, keys
797+
* that are not found are not entered into the hashmap, but
798+
* attempting to retrieve them from the hashmap gives you null.
799+
*/
827800
public Map<String, Object> getMulti(String[] keys, Integer[] hashCodes, boolean asString) {
828801

829802
if (keys == null || keys.length == 0) {
@@ -832,7 +805,7 @@ public Map<String, Object> getMulti(String[] keys, Integer[] hashCodes, boolean
832805
}
833806

834807
Map<String, ArrayList<String>> cmdMap = new HashMap<String, ArrayList<String>>();
835-
808+
String[] cleanKeys = new String[keys.length];
836809
for (int i = 0; i < keys.length; ++i) {
837810

838811
String key = keys[i];
@@ -845,9 +818,9 @@ public Map<String, Object> getMulti(String[] keys, Integer[] hashCodes, boolean
845818
if (hashCodes != null && hashCodes.length > i)
846819
hash = hashCodes[i];
847820

848-
String cleanKey = key;
821+
cleanKeys[i] = key;
849822
try {
850-
cleanKey = sanitizeKey(key);
823+
cleanKeys[i] = sanitizeKey(key);
851824
} catch (UnsupportedEncodingException e) {
852825

853826
// if we have an errorHandler, use its hook
@@ -859,7 +832,7 @@ public Map<String, Object> getMulti(String[] keys, Integer[] hashCodes, boolean
859832
}
860833

861834
// get SockIO obj from cache key
862-
SchoonerSockIO sock = pool.getSock(cleanKey, hash);
835+
SchoonerSockIO sock = pool.getSock(cleanKeys[i], hash);
863836

864837
if (sock == null) {
865838
if (errorHandler != null)
@@ -871,7 +844,7 @@ public Map<String, Object> getMulti(String[] keys, Integer[] hashCodes, boolean
871844
if (!cmdMap.containsKey(sock.getHost()))
872845
cmdMap.put(sock.getHost(), new ArrayList<String>());
873846

874-
cmdMap.get(sock.getHost()).add(cleanKey);
847+
cmdMap.get(sock.getHost()).add(cleanKeys[i]);
875848

876849
// return to pool
877850
sock.close();
@@ -886,29 +859,17 @@ public Map<String, Object> getMulti(String[] keys, Integer[] hashCodes, boolean
886859
(new NIOLoader(this)).doMulti(asString, cmdMap, keys, ret);
887860

888861
// fix the return array in case we had to rewrite any of the keys
889-
for (String key : keys) {
890-
891-
String cleanKey = key;
892-
try {
893-
cleanKey = sanitizeKey(key);
894-
} catch (UnsupportedEncodingException e) {
895-
896-
// if we have an errorHandler, use its hook
897-
if (errorHandler != null)
898-
errorHandler.handleErrorOnGet(this, e, key);
899-
900-
log.error("failed to sanitize your key!", e);
901-
continue;
902-
}
862+
for (int i=0;i<keys.length;++i) {
903863

904-
if (!key.equals(cleanKey) && ret.containsKey(cleanKey)) {
905-
ret.put(key, ret.get(cleanKey));
906-
ret.remove(cleanKey);
864+
//if key!=cleanKey and result has cleankey
865+
if (!keys[i].equals(cleanKeys[i]) && ret.containsKey(cleanKeys[i])) {
866+
ret.put(keys[i], ret.get(cleanKeys[i]));
867+
ret.remove(cleanKeys[i]);
907868
}
908869

909870
// backfill missing keys w/ null value
910-
if (!ret.containsKey(key))
911-
ret.put(key, null);
871+
if (!ret.containsKey(cleanKeys[i]))
872+
ret.put(keys[i], null);
912873
}
913874

914875
if (log.isDebugEnabled())

0 commit comments

Comments
 (0)