From ed801f5fe0111793df3ee2ea97eb43ecad9315f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=86=8A=E8=BE=89?= Date: Sat, 20 Dec 2014 02:16:30 +0800 Subject: [PATCH] 1. add feature to support Object keys(@see interface TransBytecode);2.fixed the issue of AscIIUDPClient to support UDPSockIO --- .classpath | 53 +- pom.xml | 11 + .../com/schooner/MemCached/AscIIClient.java | 690 +++++++++++------- .../schooner/MemCached/AscIIUDPClient.java | 435 ++++++----- .../com/schooner/MemCached/BinaryClient.java | 675 ++++++++++------- .../com/schooner/MemCached/KeyTransCoder.java | 124 ++++ .../com/schooner/MemCached/NativeHandler.java | 263 ++++--- .../com/schooner/MemCached/TransBytecode.java | 14 + .../MemCached/command/StorageCommand.java | 32 +- .../com/whalin/MemCached/ErrorHandler.java | 31 +- .../com/whalin/MemCached/MemCachedClient.java | 416 ++++++----- .../MemCached/MemCachedBenchBinaryKey.java | 10 + .../MemCached/MemCachedBenchTcpKey.java | 262 +++++++ .../MemCached/MemCachedBenchUdpKey.java | 10 + .../MemCached/MemCachedClientAsciiTest.java | 89 ++- .../MemCached/MemCachedClientBinaryTest.java | 100 ++- .../MemCached/MemcachedClientUDPTest.java | 66 +- .../MemCached/WhalinScenarioTest.java | 62 +- .../com/whalin/MemCached/test/UnitTests.java | 66 +- src/test/resources/log4j.properties | 7 + src/test/resources/memcached.properties | 2 + .../resources/spring-memcached-Binary.xml | 34 + src/test/resources/spring-memcached-TCP.xml | 28 + src/test/resources/spring-memcached-UDP.xml | 34 + 24 files changed, 2323 insertions(+), 1191 deletions(-) create mode 100644 src/main/java/com/schooner/MemCached/KeyTransCoder.java create mode 100644 src/main/java/com/schooner/MemCached/TransBytecode.java create mode 100644 src/test/java/com/schooner/MemCached/MemCachedBenchBinaryKey.java create mode 100644 src/test/java/com/schooner/MemCached/MemCachedBenchTcpKey.java create mode 100644 src/test/java/com/schooner/MemCached/MemCachedBenchUdpKey.java create mode 100644 src/test/resources/log4j.properties create mode 100644 src/test/resources/memcached.properties create mode 100644 src/test/resources/spring-memcached-Binary.xml create mode 100644 src/test/resources/spring-memcached-TCP.xml create mode 100644 src/test/resources/spring-memcached-UDP.xml diff --git a/.classpath b/.classpath index c9464c0..afcbba5 100644 --- a/.classpath +++ b/.classpath @@ -1,26 +1,27 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index b572e97..91d40ee 100644 --- a/pom.xml +++ b/pom.xml @@ -83,6 +83,16 @@ 1.6.4 provided + + org.springframework + spring-context-support + 4.1.2.RELEASE + + + log4j + log4j + 1.2.16 + @@ -138,6 +148,7 @@ org.apache.maven.plugins maven-gpg-plugin + 1.5 sign-artifacts diff --git a/src/main/java/com/schooner/MemCached/AscIIClient.java b/src/main/java/com/schooner/MemCached/AscIIClient.java index 724e2f4..d2e62f8 100755 --- a/src/main/java/com/schooner/MemCached/AscIIClient.java +++ b/src/main/java/com/schooner/MemCached/AscIIClient.java @@ -1,9 +1,9 @@ /******************************************************************************* * Copyright (c) 2009 Schooner Information Technology, Inc. * All rights reserved. - * + * * http://www.schoonerinfotech.com/ - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -14,7 +14,7 @@ * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -32,8 +32,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; +import java.io.Serializable; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; @@ -56,12 +55,14 @@ *
* Please use the wrapper class {@link MemCachedClient} for accessing the * memcached server. - * + * * @author Xingen Wang * @since 2.5.0 * @see BinaryClient */ public class AscIIClient extends MemCachedClient { + private TransBytecode keyTransCoder = new KeyTransCoder(); + private TransCoder transCoder = new ObjectTransCoder(); // pool instance @@ -70,8 +71,6 @@ public class AscIIClient extends MemCachedClient { // which pool to use private String poolName; - // flags - private boolean sanitizeKeys; private boolean primitiveAsString; @SuppressWarnings("unused") private boolean compressEnable; @@ -79,6 +78,7 @@ public class AscIIClient extends MemCachedClient { private long compressThreshold; private String defaultEncoding; + @Override public boolean isUseBinaryProtocol() { return false; } @@ -93,7 +93,7 @@ public AscIIClient() { /** * Creates a new instance of MemCachedClient accepting a passed in pool * name. - * + * * @param poolName * name of SockIOPool * @param binaryProtocal @@ -115,11 +115,10 @@ public AscIIClient(String poolName, ClassLoader cl, ErrorHandler eh) { /** * Initializes client object to defaults. - * + * * This enables compression and sets compression threshhold to 15 KB. */ private void init() { - this.sanitizeKeys = true; this.primitiveAsString = false; this.compressEnable = false; this.compressThreshold = COMPRESS_THRESH; @@ -130,51 +129,49 @@ private void init() { this.pool = SchoonerSockIOPool.getInstance(poolName); } - public boolean keyExists(String key) { - return (this.get(key, null) != null); + @Override + public boolean keyExists(Serializable key) { + return this.get(key, null) != null; } - public boolean delete(String key) { + @Override + public boolean delete(Serializable key) { return delete(key, null, null); } - public boolean delete(String key, Date expiry) { + @Override + public boolean delete(Serializable key, Date expiry) { return delete(key, null, expiry); } - public boolean delete(String key, Integer hashCode, Date expiry) { + @Override + public boolean delete(Serializable origin, Integer hashCode, Date expiry) { + String key = null; - if (key == null) { + if (origin == null) { log.error("null value for key passed to delete()"); return false; } - try { - key = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - - // if we have an errorHandler, use its hook - if (errorHandler != null) - errorHandler.handleErrorOnDelete(this, e, key); - - log.error("failed to sanitize your key!", e); - return false; - } + key = keyTransCoder.encode(origin); // get SockIO obj from hash or from key SchoonerSockIO sock = pool.getSock(key, hashCode); // return false if unable to get SockIO obj if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnDelete(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnDelete(this, new IOException( + "no socket to server available"), key); + } return false; } // build command StringBuilder command = new StringBuilder("delete ").append(key); - if (expiry != null) + if (expiry != null) { command.append(" " + expiry.getTime() / 1000); + } command.append("\r\n"); @@ -187,23 +184,31 @@ public boolean delete(String key, Integer hashCode, Date expiry) { String line = sis.getLine(); sis.close(); if (DELETED.equals(line)) { // successful - log.debug(new StringBuffer().append("++++ deletion of key: ").append(key) - .append(" from cache was a success").toString()); + log.debug(new StringBuffer().append("++++ deletion of key: ") + .append(key).append(" from cache was a success") + .toString()); return true; } else if (NOTFOUND.equals(line)) { // key not found - log.debug(new StringBuffer().append("++++ deletion of key: ").append(key) - .append(" from cache failed as the key was not found").toString()); + log.debug(new StringBuffer().append("++++ deletion of key: ") + .append(key) + .append(" from cache failed as the key was not found") + .toString()); } else { // other error information if (log.isErrorEnabled()) { - log.error(new StringBuffer().append("++++ error deleting key: ").append(key).toString()); - log.error(new StringBuffer().append("++++ server response: ").append(line).toString()); + log.error(new StringBuffer() + .append("++++ error deleting key: ").append(key) + .toString()); + log.error(new StringBuffer() + .append("++++ server response: ").append(line) + .toString()); } } } catch (IOException e) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnDelete(this, e, key); + } // exception thrown if (log.isErrorEnabled()) { @@ -228,93 +233,127 @@ public boolean delete(String key, Integer hashCode, Date expiry) { return false; } - public boolean set(String key, Object value) { + @Override + public boolean set(Serializable key, Serializable value) { return set("set", key, value, null, null, 0L, primitiveAsString); } - public boolean set(String key, Object value, Integer hashCode) { + @Override + public boolean set(Serializable key, Serializable value, Integer hashCode) { return set("set", key, value, null, hashCode, 0L, primitiveAsString); } - public boolean set(String key, Object value, Date expiry) { + @Override + public boolean set(Serializable key, Serializable value, Date expiry) { return set("set", key, value, expiry, null, 0L, primitiveAsString); } - public boolean set(String key, Object value, Date expiry, Integer hashCode) { + @Override + public boolean set(Serializable key, Serializable value, Date expiry, + Integer hashCode) { return set("set", key, value, expiry, hashCode, 0L, primitiveAsString); } - - public boolean set(String key, Object value, Date expiry, Integer hashCode, boolean asString) { + + @Override + public boolean set(Serializable key, Serializable value, Date expiry, + Integer hashCode, boolean asString) { return set("set", key, value, expiry, hashCode, 0L, asString); } - public boolean add(String key, Object value) { + @Override + public boolean add(Serializable key, Serializable value) { return set("add", key, value, null, null, 0L, primitiveAsString); } - public boolean add(String key, Object value, Integer hashCode) { + @Override + public boolean add(Serializable key, Serializable value, Integer hashCode) { return set("add", key, value, null, hashCode, 0L, primitiveAsString); } - public boolean add(String key, Object value, Date expiry) { + @Override + public boolean add(Serializable key, Serializable value, Date expiry) { return set("add", key, value, expiry, null, 0L, primitiveAsString); } - public boolean add(String key, Object value, Date expiry, Integer hashCode) { + @Override + public boolean add(Serializable key, Serializable value, Date expiry, + Integer hashCode) { return set("add", key, value, expiry, hashCode, 0L, primitiveAsString); } - public boolean append(String key, Object value, Integer hashCode) { + @Override + public boolean append(Serializable key, Serializable value, Integer hashCode) { return set("append", key, value, null, hashCode, 0L, primitiveAsString); } - public boolean append(String key, Object value) { + @Override + public boolean append(Serializable key, Serializable value) { return set("append", key, value, null, null, 0L, primitiveAsString); } - public boolean cas(String key, Object value, Integer hashCode, long casUnique) { - return set("cas", key, value, null, hashCode, casUnique, primitiveAsString); + @Override + public boolean cas(Serializable key, Serializable value, Integer hashCode, + long casUnique) { + return set("cas", key, value, null, hashCode, casUnique, + primitiveAsString); } - public boolean cas(String key, Object value, Date expiry, long casUnique) { - return set("cas", key, value, expiry, null, casUnique, primitiveAsString); + @Override + public boolean cas(Serializable key, Serializable value, Date expiry, + long casUnique) { + return set("cas", key, value, expiry, null, casUnique, + primitiveAsString); } - public boolean cas(String key, Object value, Date expiry, Integer hashCode, long casUnique) { - return set("cas", key, value, expiry, hashCode, casUnique, primitiveAsString); + @Override + public boolean cas(Serializable key, Serializable value, Date expiry, + Integer hashCode, long casUnique) { + return set("cas", key, value, expiry, hashCode, casUnique, + primitiveAsString); } - public boolean cas(String key, Object value, long casUnique) { + @Override + public boolean cas(Serializable key, Serializable value, long casUnique) { return set("cas", key, value, null, null, casUnique, primitiveAsString); } - public boolean prepend(String key, Object value, Integer hashCode) { + @Override + public boolean prepend(Serializable key, Serializable value, + Integer hashCode) { return set("prepend", key, value, null, hashCode, 0L, primitiveAsString); } - public boolean prepend(String key, Object value) { + @Override + public boolean prepend(Serializable key, Serializable value) { return set("prepend", key, value, null, null, 0L, primitiveAsString); } - public boolean replace(String key, Object value) { + @Override + public boolean replace(Serializable key, Serializable value) { return set("replace", key, value, null, null, 0L, primitiveAsString); } - public boolean replace(String key, Object value, Integer hashCode) { + @Override + public boolean replace(Serializable key, Serializable value, + Integer hashCode) { return set("replace", key, value, null, hashCode, 0L, primitiveAsString); } - public boolean replace(String key, Object value, Date expiry) { + @Override + public boolean replace(Serializable key, Serializable value, Date expiry) { return set("replace", key, value, expiry, null, 0L, primitiveAsString); } - public boolean replace(String key, Object value, Date expiry, Integer hashCode) { - return set("replace", key, value, expiry, hashCode, 0L, primitiveAsString); + @Override + public boolean replace(Serializable key, Serializable value, Date expiry, + Integer hashCode) { + return set("replace", key, value, expiry, hashCode, 0L, + primitiveAsString); } /** * Stores data to cache. - * + * * If data does not already exist for this key on the server, or if the key * is being
* deleted, the specified value will not be stored.
@@ -327,7 +366,7 @@ public boolean replace(String key, Object value, Date expiry, Integer hashCode) *
* As of the current release, all objects stored will use java * serialization. - * + * * @param cmdname * action to take (set, add, replace) * @param key @@ -342,24 +381,15 @@ public boolean replace(String key, Object value, Date expiry, Integer hashCode) * if true, then store all primitives as their string value * @return true/false indicating success */ - private boolean set(String cmdname, String key, Object value, Date expiry, Integer hashCode, Long casUnique, + private boolean set(String cmdname, Serializable originKey, + Serializable value, Date expiry, Integer hashCode, Long casUnique, boolean asString) { - if (cmdname == null || key == null) { + if (cmdname == null || originKey == null) { log.error("key is null or cmd is null/empty for set()"); return false; } - - try { - key = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - - // if we have an errorHandler, use its hook - if (errorHandler != null) - errorHandler.handleErrorOnSet(this, e, key); - log.error("failed to sanitize your key!", e); - return false; - } + String key = keyTransCoder.encode(originKey); if (value == null) { log.error("trying to store a null value to cache"); @@ -370,18 +400,23 @@ private boolean set(String cmdname, String key, Object value, Date expiry, Integ SchoonerSockIO sock = pool.getSock(key, hashCode); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnSet(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnSet(this, new IOException( + "no socket to server available"), key); + } return false; } - if (expiry == null) + if (expiry == null) { expiry = new Date(0); + } // store flags - int flags = asString ? MemCachedClient.MARKER_STRING : NativeHandler.getMarkerFlag(value); + int flags = asString ? MemCachedClient.MARKER_STRING : NativeHandler + .getMarkerFlag(value); // construct the command - String cmd = new StringBuffer().append(cmdname).append(" ").append(key).append(" ").append(flags).append(" ") + String cmd = new StringBuffer().append(cmdname).append(" ").append(key) + .append(" ").append(flags).append(" ") .append(expiry.getTime() / 1000).append(" ").toString(); try { @@ -390,8 +425,9 @@ private boolean set(String cmdname, String key, Object value, Date expiry, Integ int offset = sock.writeBuf.position(); // write blank bytes size. sock.writeBuf.put(BLAND_DATA_SIZE); - if (casUnique != 0) + if (casUnique != 0) { sock.writeBuf.put((" " + casUnique.toString()).getBytes()); + } sock.writeBuf.put(B_RETURN); SockOutputStream output = new SockOutputStream(sock); int valLen = 0; @@ -439,8 +475,9 @@ private boolean set(String cmdname, String key, Object value, Date expiry, Integ } } catch (Exception e) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnSet(this, e, key); + } // exception thrown if (log.isErrorEnabled()) { @@ -465,15 +502,18 @@ private boolean set(String cmdname, String key, Object value, Date expiry, Integ return false; } - public long addOrIncr(String key) { + @Override + public long addOrIncr(Serializable key) { return addOrIncr(key, 0, null); } - public long addOrIncr(String key, long inc) { + @Override + public long addOrIncr(Serializable key, long inc) { return addOrIncr(key, inc, null); } - public long addOrIncr(String key, long inc, Integer hashCode) { + @Override + public long addOrIncr(Serializable key, long inc, Integer hashCode) { boolean ret = add(key, "" + inc, hashCode); if (ret) { @@ -483,15 +523,18 @@ public long addOrIncr(String key, long inc, Integer hashCode) { } } - public long addOrDecr(String key) { + @Override + public long addOrDecr(Serializable key) { return addOrDecr(key, 0, null); } - public long addOrDecr(String key, long inc) { + @Override + public long addOrDecr(Serializable key, long inc) { return addOrDecr(key, inc, null); } - public long addOrDecr(String key, long inc, Integer hashCode) { + @Override + public long addOrDecr(Serializable key, long inc, Integer hashCode) { boolean ret = add(key, "" + inc, hashCode); if (ret) { return inc; @@ -500,39 +543,45 @@ public long addOrDecr(String key, long inc, Integer hashCode) { } } - public long incr(String key) { + @Override + public long incr(Serializable key) { return incrdecr("incr", key, 1, null); } - public long incr(String key, long inc) { + @Override + public long incr(Serializable key, long inc) { return incrdecr("incr", key, inc, null); } - public long incr(String key, long inc, Integer hashCode) { + @Override + public long incr(Serializable key, long inc, Integer hashCode) { return incrdecr("incr", key, inc, hashCode); } - public long decr(String key) { + @Override + public long decr(Serializable key) { return incrdecr("decr", key, 1, null); } - public long decr(String key, long inc) { + @Override + public long decr(Serializable key, long inc) { return incrdecr("decr", key, inc, null); } - public long decr(String key, long inc, Integer hashCode) { + @Override + public long decr(Serializable key, long inc, Integer hashCode) { return incrdecr("decr", key, inc, hashCode); } /** * Increments/decrements the value at the specified key by inc. - * + * * Note that the server uses a 32-bit unsigned integer, and checks for
* underflow. In the event of underflow, the result will be zero. Because
* Java lacks unsigned types, the value is returned as a 64-bit integer.
* The server will only decrement a value if it already exists;
* if a value is not found, -1 will be returned. - * + * * @param cmdname * increment/decrement * @param key @@ -543,35 +592,31 @@ public long decr(String key, long inc, Integer hashCode) { * if not null, then the int hashcode to use * @return new value or -1 if not exist */ - private long incrdecr(String cmdname, String key, long inc, Integer hashCode) { + private long incrdecr(String cmdname, Serializable originKey, long inc, + Integer hashCode) { - if (key == null) { + if (originKey == null) { log.error("null key for incrdecr()"); return -1; } - try { - key = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - // if we have an errorHandler, use its hook - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, e, key); - log.error("failed to sanitize your key!", e); - return -1; - } + String key = keyTransCoder.encode(originKey); // get SockIO obj for given cache key SchoonerSockIO sock = pool.getSock(key, hashCode); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnSet(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnSet(this, new IOException( + "no socket to server available"), key); + } return -1; } try { - String cmd = new StringBuffer().append(cmdname).append(" ").append(key).append(" ").append(inc) - .append("\r\n").toString(); + String cmd = new StringBuffer().append(cmdname).append(" ") + .append(key).append(" ").append(inc).append("\r\n") + .toString(); sock.write(cmd.getBytes()); // get result code SockInputStream sis = new SockInputStream(sock, Integer.MAX_VALUE); @@ -582,18 +627,25 @@ private long incrdecr(String cmdname, String key, long inc, Integer hashCode) { // return sock to pool and return result return Long.parseLong(line); } else if (NOTFOUND.equals(line + "\r\n")) { - log.info(new StringBuffer().append("++++ key not found to incr/decr for key: ").append(key).toString()); + log.info(new StringBuffer() + .append("++++ key not found to incr/decr for key: ") + .append(key).toString()); } else { if (log.isErrorEnabled()) { - log.error(new StringBuffer().append("++++ error incr/decr key: ").append(key).toString()); - log.error(new StringBuffer().append("++++ server response: ").append(line).toString()); + log.error(new StringBuffer() + .append("++++ error incr/decr key: ").append(key) + .toString()); + log.error(new StringBuffer() + .append("++++ server response: ").append(line) + .toString()); } } } catch (Exception e) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnGet(this, e, key); + } // exception thrown if (log.isErrorEnabled()) { @@ -618,25 +670,29 @@ private long incrdecr(String cmdname, String key, long inc, Integer hashCode) { return -1; } - public Object get(String key) { + @Override + public Object get(Serializable key) { return get(key, null); } - public Object get(String key, Integer hashCode) { + @Override + public Object get(Serializable key, Integer hashCode) { return get("get", key, hashCode, false); } - public MemcachedItem gets(String key) { + @Override + public MemcachedItem gets(Serializable key) { return gets(key, null); } - public MemcachedItem gets(String key, Integer hashCode) { + @Override + public MemcachedItem gets(Serializable key, Integer hashCode) { return gets("gets", key, hashCode, false); } /** * Retrieve a key from the server, using a specific hash. - * + * * If the data was compressed or serialized when compressed, it will * automatically
* be decompressed or serialized, as appropriate. (Inclusive or)
@@ -644,7 +700,7 @@ public MemcachedItem gets(String key, Integer hashCode) { * Non-serialized data will be returned as a string, so explicit conversion * to
* numeric types will be necessary, if desired
- * + * * @param key * key where data is stored * @param hashCode @@ -654,13 +710,14 @@ public MemcachedItem gets(String key, Integer hashCode) { * @return the object that was previously stored, or null if it was not * previously stored */ - public Object get(String key, Integer hashCode, boolean asString) { + @Override + public Object get(Serializable key, Integer hashCode, boolean asString) { return get("get", key, hashCode, asString); } /** * get memcached item from server. - * + * * @param cmd * cmd to be used, get/gets * @param key @@ -669,26 +726,23 @@ public Object get(String key, Integer hashCode, boolean asString) { * specified hashcode * @return memcached item with value in it. */ - private Object get(String cmd, String key, Integer hashCode, boolean asString) { - - if (key == null) { + private Object get(String cmd, Serializable originKey, Integer hashCode, + boolean asString) { + if (originKey == null) { log.error("key is null for get()"); return null; } - try { - key = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - log.error("failed to sanitize your key!", e); - return null; - } + String key = keyTransCoder.encode(originKey); // get SockIO obj using cache key SchoonerSockIO sock = pool.getSock(key, hashCode); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnGet(this, new IOException( + "no socket to server available"), key); + } return null; } @@ -720,8 +774,9 @@ private Object get(String cmd, String key, Integer hashCode, boolean asString) { if (b == ' ' || b == '\r') { switch (index) { case 0: - if (END.startsWith(sb.toString())) + if (END.startsWith(sb.toString())) { return null; + } case 1: break; case 2: @@ -751,8 +806,10 @@ private Object get(String cmd, String key, Integer hashCode, boolean asString) { // decoding object byte[] buf = input.getBuffer(); if ((flag & F_COMPRESSED) == F_COMPRESSED) { - GZIPInputStream gzi = new GZIPInputStream(new ByteArrayInputStream(buf)); - ByteArrayOutputStream bos = new ByteArrayOutputStream(buf.length); + GZIPInputStream gzi = new GZIPInputStream( + new ByteArrayInputStream(buf)); + ByteArrayOutputStream bos = new ByteArrayOutputStream( + buf.length); int count; byte[] tmp = new byte[2048]; while ((count = gzi.read(tmp)) != -1) { @@ -764,17 +821,21 @@ private Object get(String cmd, String key, Integer hashCode, boolean asString) { } if (primitiveAsString || asString) { o = new String(buf, defaultEncoding); - } else + } else { o = NativeHandler.decode(buf, flag); + } } else if (transCoder != null) { // decode object with default transcoder. InputStream in = input; - if ((flag & F_COMPRESSED) == F_COMPRESSED) + if ((flag & F_COMPRESSED) == F_COMPRESSED) { in = new GZIPInputStream(in); - if (classLoader == null) + } + if (classLoader == null) { o = transCoder.decode(in); - else - o = ((ObjectTransCoder) transCoder).decode(in, classLoader); + } else { + o = ((ObjectTransCoder) transCoder).decode(in, + classLoader); + } } } input.willRead(Integer.MAX_VALUE); @@ -785,12 +846,14 @@ private Object get(String cmd, String key, Integer hashCode, boolean asString) { return o; } catch (Exception ce) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnGet(this, ce, key); + } // exception thrown if (log.isErrorEnabled()) { - log.error("++++ exception thrown while trying to get object from cache for key: " + key); + log.error("++++ exception thrown while trying to get object from cache for key: " + + key); log.error(ce.getMessage(), ce); } @@ -812,26 +875,24 @@ private Object get(String cmd, String key, Integer hashCode, boolean asString) { } - public MemcachedItem gets(String cmd, String key, Integer hashCode, boolean asString) { + public MemcachedItem gets(String cmd, Serializable originKey, + Integer hashCode, boolean asString) { - if (key == null) { + if (originKey == null) { log.error("key is null for get()"); return null; } - try { - key = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - log.error("failed to sanitize your key!", e); - return null; - } + String key = keyTransCoder.encode(originKey); // get SockIO obj using cache key SchoonerSockIO sock = pool.getSock(key, hashCode); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnGet(this, new IOException( + "no socket to server available"), key); + } return null; } @@ -864,8 +925,9 @@ public MemcachedItem gets(String cmd, String key, Integer hashCode, boolean asSt if (b == ' ' || b == '\r') { switch (index) { case 0: - if (END.startsWith(sb.toString())) + if (END.startsWith(sb.toString())) { return null; + } case 1: break; case 2: @@ -876,8 +938,9 @@ public MemcachedItem gets(String cmd, String key, Integer hashCode, boolean asSt dataSize = Integer.parseInt(sb.toString()); break; case 4: - if (cmd.equals("gets")) + if (cmd.equals("gets")) { item.casUnique = Long.parseLong(sb.toString()); + } break; } index++; @@ -897,8 +960,10 @@ public MemcachedItem gets(String cmd, String key, Integer hashCode, boolean asSt if (NativeHandler.isHandled(flag)) { byte[] buf = input.getBuffer(); if ((flag & F_COMPRESSED) == F_COMPRESSED) { - GZIPInputStream gzi = new GZIPInputStream(new ByteArrayInputStream(buf)); - ByteArrayOutputStream bos = new ByteArrayOutputStream(buf.length); + GZIPInputStream gzi = new GZIPInputStream( + new ByteArrayInputStream(buf)); + ByteArrayOutputStream bos = new ByteArrayOutputStream( + buf.length); int count; byte[] tmp = new byte[2048]; while ((count = gzi.read(tmp)) != -1) { @@ -910,13 +975,15 @@ public MemcachedItem gets(String cmd, String key, Integer hashCode, boolean asSt } if (primitiveAsString || asString) { o = new String(buf, defaultEncoding); - } else + } else { // decoding object o = NativeHandler.decode(buf, flag); + } } else if (transCoder != null) { InputStream in = input; - if ((flag & F_COMPRESSED) == F_COMPRESSED) + if ((flag & F_COMPRESSED) == F_COMPRESSED) { in = new GZIPInputStream(in); + } // decode object with default transcoder. o = transCoder.decode(in); } @@ -931,12 +998,14 @@ public MemcachedItem gets(String cmd, String key, Integer hashCode, boolean asSt } catch (Exception ce) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnGet(this, ce, key); + } // exception thrown if (log.isErrorEnabled()) { - log.error("++++ exception thrown while trying to get object from cache for key: " + key); + log.error("++++ exception thrown while trying to get object from cache for key: " + + key); log.error(ce.getMessage(), ce); } @@ -957,26 +1026,39 @@ public MemcachedItem gets(String cmd, String key, Integer hashCode, boolean asSt return null; } + /** + * set key transcoder + * + * @param keyTransCoder + */ + @Override + public void setKeyTransCoder(TransBytecode keyTransCoder) { + this.keyTransCoder = keyTransCoder; + } + /** * set transcoder. TransCoder is used to customize the serialization and * deserialization. - * + * * @param transCoder */ + @Override public void setTransCoder(TransCoder transCoder) { this.transCoder = transCoder; } - public Object[] getMultiArray(String[] keys) { + @Override + public Object[] getMultiArray(Serializable[] keys) { return getMultiArray(keys, null); } - public Object[] getMultiArray(String[] keys, Integer[] hashCodes) { - - Map data = getMulti(keys, hashCodes); + @Override + public Object[] getMultiArray(Serializable[] keys, Integer[] hashCodes) { + Map data = getMulti(keys, hashCodes); - if (data == null) + if (data == null) { return null; + } Object[] res = new Object[keys.length]; for (int i = 0; i < keys.length; i++) { @@ -988,11 +1070,11 @@ public Object[] getMultiArray(String[] keys, Integer[] hashCodes) { /** * Retrieve multiple objects from the memcache. - * + * * This is recommended over repeated calls to {@link #get(String) get()}, * since it
* is more efficient.
- * + * * @param keys * String array of keys to retrieve * @param hashCodes @@ -1002,12 +1084,14 @@ public Object[] getMultiArray(String[] keys, Integer[] hashCodes) { * @return Object array ordered in same order as key array containing * results */ - public Object[] getMultiArray(String[] keys, Integer[] hashCodes, boolean asString) { - - Map data = getMulti(keys, hashCodes, asString); + @Override + public Object[] getMultiArray(Serializable[] keys, Integer[] hashCodes, + boolean asString) { + Map data = getMulti(keys, hashCodes, asString); - if (data == null) + if (data == null) { return null; + } Object[] res = new Object[keys.length]; for (int i = 0; i < keys.length; i++) { @@ -1017,21 +1101,24 @@ public Object[] getMultiArray(String[] keys, Integer[] hashCodes, boolean asStri return res; } - public Map getMulti(String[] keys) { + @Override + public Map getMulti(Serializable[] keys) { return getMulti(keys, null); } - public Map getMulti(String[] keys, Integer[] hashCodes) { + @Override + public Map getMulti(Serializable[] keys, + Integer[] hashCodes) { return getMulti(keys, hashCodes, false); } /** * Retrieve multiple keys from the memcache. - * + * * This is recommended over repeated calls to {@link #get(String) get()}, * since it
* is more efficient.
- * + * * @param keys * keys to retrieve * @param hashCodes @@ -1042,8 +1129,9 @@ public Map getMulti(String[] keys, Integer[] hashCodes) { * that are not found are not entered into the hashmap, but * attempting to retrieve them from the hashmap gives you null. */ - public Map getMulti(String[] keys, Integer[] hashCodes, boolean asString) { - + @Override + public Map getMulti(Serializable[] keys, + Integer[] hashCodes, boolean asString) { if (keys == null || keys.length == 0) { log.error("missing keys for getMulti()"); return null; @@ -1052,39 +1140,36 @@ public Map getMulti(String[] keys, Integer[] hashCodes, boolean Map cmdMap = new HashMap(); String[] cleanKeys = new String[keys.length]; for (int i = 0; i < keys.length; ++i) { - String key = keys[i]; - if (key == null) { + Serializable originKey = keys[i]; + if (originKey == null) { log.error("null key, so skipping"); continue; } Integer hash = null; - if (hashCodes != null && hashCodes.length > i) + if (hashCodes != null && hashCodes.length > i) { hash = hashCodes[i]; + } + + String key = keyTransCoder.encode(originKey); cleanKeys[i] = key; - try { - cleanKeys[i] = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - // if we have an errorHandler, use its hook - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, e, key); - log.error("failed to sanitize your key!", e); - continue; - } // get SockIO obj from cache key SchoonerSockIO sock = pool.getSock(cleanKeys[i], hash); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnGet(this, new IOException( + "no socket to server available"), key); + } continue; } // store in map and list if not already - if (!cmdMap.containsKey(sock.getHost())) + if (!cmdMap.containsKey(sock.getHost())) { cmdMap.put(sock.getHost(), new StringBuilder("get")); + } cmdMap.get(sock.getHost()).append(" " + cleanKeys[i]); @@ -1095,7 +1180,8 @@ public Map getMulti(String[] keys, Integer[] hashCodes, boolean log.debug("multi get socket count : " + cmdMap.size()); // now query memcache - Map ret = new HashMap(keys.length); + Map ret = new HashMap( + keys.length); // now use new NIO implementation (new NIOLoader(this)).doMulti(asString, cmdMap, keys, ret); @@ -1120,10 +1206,10 @@ public Map getMulti(String[] keys, Integer[] hashCodes, boolean /** * This method loads the data from cache into a Map. - * + * * Pass a SockIO object which is ready to receive data and a HashMap
* to store the results. - * + * * @param sock * socket waiting to pass back data * @param hm @@ -1133,7 +1219,8 @@ public Map getMulti(String[] keys, Integer[] hashCodes, boolean * @throws IOException * if io exception happens while reading from socket */ - private void loadMulti(LineInputStream input, Map hm, boolean asString) throws IOException { + private void loadMulti(LineInputStream input, Map hm, + boolean asString) throws IOException { while (true) { String line = input.readLine(); @@ -1153,8 +1240,10 @@ private void loadMulti(LineInputStream input, Map hm, boolean as Object o = null; // we can only take out serialized objects if ((flag & F_COMPRESSED) == F_COMPRESSED) { - GZIPInputStream gzi = new GZIPInputStream(new ByteArrayInputStream(buf)); - ByteArrayOutputStream bos = new ByteArrayOutputStream(buf.length); + GZIPInputStream gzi = new GZIPInputStream( + new ByteArrayInputStream(buf)); + ByteArrayOutputStream bos = new ByteArrayOutputStream( + buf.length); int count; byte[] tmp = new byte[2048]; while ((count = gzi.read(tmp)) != -1) { @@ -1173,8 +1262,8 @@ private void loadMulti(LineInputStream input, Map hm, boolean as try { o = NativeHandler.decode(buf, flag); } catch (Exception e) { - log.error("++++ Exception thrown while trying to deserialize for key: " + key + " -- " - + e.getMessage()); + log.error("++++ Exception thrown while trying to deserialize for key: " + + key + " -- " + e.getMessage()); e.printStackTrace(); } } @@ -1190,10 +1279,12 @@ private void loadMulti(LineInputStream input, Map hm, boolean as } } + @Override public boolean flushAll() { return flushAll(null); } + @Override public boolean flushAll(String[] servers) { // get SockIOPool instance @@ -1220,8 +1311,10 @@ public boolean flushAll(String[] servers) { if (sock == null) { log.error("++++ unable to get connection to : " + servers[i]); success = false; - if (errorHandler != null) - errorHandler.handleErrorOnFlush(this, new IOException("no socket to server available")); + if (errorHandler != null) { + errorHandler.handleErrorOnFlush(this, new IOException( + "no socket to server available")); + } continue; } @@ -1232,15 +1325,17 @@ public boolean flushAll(String[] servers) { sock.write(command.getBytes()); // if we get appropriate response back, then we return true // get result code - SockInputStream sis = new SockInputStream(sock, Integer.MAX_VALUE); + SockInputStream sis = new SockInputStream(sock, + Integer.MAX_VALUE); String line = sis.getLine(); sis.close(); success = (OK.equals(line)) ? success && true : false; } catch (IOException e) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnFlush(this, e); + } // exception thrown if (log.isErrorEnabled()) { @@ -1251,7 +1346,8 @@ public boolean flushAll(String[] servers) { try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString()); + log.error("++++ failed to close socket : " + + sock.toString()); } success = false; @@ -1267,40 +1363,52 @@ public boolean flushAll(String[] servers) { return success; } + @Override public Map> stats() { return stats(null); } + @Override public Map> stats(String[] servers) { return stats(servers, "stats\r\n", STATS); } + @Override public Map> statsItems() { return statsItems(null); } + @Override public Map> statsItems(String[] servers) { return stats(servers, "stats items\r\n", STATS); } + @Override public Map> statsSlabs() { return statsSlabs(null); } + @Override public Map> statsSlabs(String[] servers) { return stats(servers, "stats slabs\r\n", STATS); } - public Map> statsCacheDump(int slabNumber, int limit) { + @Override + public Map> statsCacheDump(int slabNumber, + int limit) { return statsCacheDump(null, slabNumber, limit); } - public Map> statsCacheDump(String[] servers, int slabNumber, int limit) { - return stats(servers, String.format("stats cachedump %d %d\r\n", slabNumber, limit), ITEM); + @Override + public Map> statsCacheDump(String[] servers, + int slabNumber, int limit) { + return stats(servers, + String.format("stats cachedump %d %d\r\n", slabNumber, limit), + ITEM); } - private Map> stats(String[] servers, String command, String lineStart) { - + private Map> stats(String[] servers, + String command, String lineStart) { if (command == null || command.trim().equals("")) { log.error("++++ invalid / missing command for stats()"); return null; @@ -1322,8 +1430,10 @@ private Map> stats(String[] servers, String command, SchoonerSockIO sock = pool.getConnection(servers[i]); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnStats(this, new IOException("no socket to server available")); + if (errorHandler != null) { + errorHandler.handleErrorOnStats(this, new IOException( + "no socket to server available")); + } continue; } @@ -1334,7 +1444,8 @@ private Map> stats(String[] servers, String command, // map to hold key value pairs Map stats = new HashMap(); // get result code - SockInputStream input = new SockInputStream(sock, Integer.MAX_VALUE); + SockInputStream input = new SockInputStream(sock, + Integer.MAX_VALUE); String line; // loop over results while ((line = input.getLine()) != null) { @@ -1347,7 +1458,9 @@ private Map> stats(String[] servers, String command, } else if (END.startsWith(line)) { // finish when we get end from server break; - } else if (line.startsWith(ERROR) || line.startsWith(CLIENT_ERROR) || line.startsWith(SERVER_ERROR)) { + } else if (line.startsWith(ERROR) + || line.startsWith(CLIENT_ERROR) + || line.startsWith(SERVER_ERROR)) { if (log.isErrorEnabled()) { log.error("++++ failed to query stats"); log.error("++++ server response: " + line); @@ -1361,8 +1474,9 @@ private Map> stats(String[] servers, String command, } catch (Exception e) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnStats(this, e); + } // exception thrown if (log.isErrorEnabled()) { @@ -1373,7 +1487,8 @@ private Map> stats(String[] servers, String command, try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString()); + log.error("++++ failed to close socket : " + + sock.toString()); } sock = null; @@ -1406,13 +1521,17 @@ private final class Connection { public SocketChannel channel; private boolean isDone = false; - public Connection(SchoonerSockIO sock, StringBuilder request) throws IOException { + public Connection(SchoonerSockIO sock, StringBuilder request) + throws IOException { this.sock = sock; - outgoing = ByteBuffer.wrap(request.append("\r\n").toString().getBytes()); + outgoing = ByteBuffer.wrap(request.append("\r\n").toString() + .getBytes()); - channel = (SocketChannel) sock.getChannel(); - if (channel == null) - throw new IOException("dead connection to: " + sock.getHost()); + channel = sock.getChannel(); + if (channel == null) { + throw new IOException("dead connection to: " + + sock.getHost()); + } channel.configureBlocking(false); channel.register(selector, SelectionKey.OP_WRITE, this); @@ -1426,20 +1545,25 @@ public void close() { return; } } catch (IOException e) { - log.warn("++++ memcache: unexpected error closing normally", e); + log.warn( + "++++ memcache: unexpected error closing normally", + e); } try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error( + "++++ failed to close socket : " + sock.toString(), + e1); } } public boolean isDone() { // if we know we're done, just say so - if (isDone) + if (isDone) { return true; + } // else find out the hard way int strPos = B_END.length - 1; @@ -1449,8 +1573,9 @@ public boolean isDone() { ByteBuffer buf = incoming.get(bi); int pos = buf.position() - 1; while (pos >= 0 && strPos >= 0) { - if (buf.get(pos--) != B_END[strPos--]) + if (buf.get(pos--) != B_END[strPos--]) { return false; + } } bi--; @@ -1471,14 +1596,18 @@ public ByteBuffer getBuffer() { } } + @Override public String toString() { - return new StringBuffer().append("Connection to ").append(sock.getHost()).append(" with ") - .append(incoming.size()).append(" bufs; done is ").append(isDone).toString(); + return new StringBuffer().append("Connection to ") + .append(sock.getHost()).append(" with ") + .append(incoming.size()).append(" bufs; done is ") + .append(isDone).toString(); } } - public void doMulti(boolean asString, Map sockKeys, String[] keys, - Map ret) { + public void doMulti(boolean asString, + Map sockKeys, Serializable[] keys, + Map ret) { long timeRemaining = 0; try { @@ -1488,16 +1617,20 @@ public void doMulti(boolean asString, Map sockKeys, Strin // structures conns = new Connection[sockKeys.keySet().size()]; numConns = 0; - for (Iterator i = sockKeys.keySet().iterator(); i.hasNext();) { + for (Iterator i = sockKeys.keySet().iterator(); i + .hasNext();) { // get SockIO obj from hostname String host = i.next(); SchoonerSockIO sock = pool.getConnection(host); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnGet(this.mc, new IOException("no socket to server available"), + if (errorHandler != null) { + errorHandler.handleErrorOnGet(this.mc, + new IOException( + "no socket to server available"), keys); + } return; } @@ -1516,7 +1649,8 @@ public void doMulti(boolean asString, Map sockKeys, Strin int n = selector.select(Math.min(timeout, 5000)); if (n > 0) { // we've got some activity; handle it - Iterator it = selector.selectedKeys().iterator(); + Iterator it = selector.selectedKeys() + .iterator(); while (it.hasNext()) { SelectionKey key = it.next(); it.remove(); @@ -1529,24 +1663,28 @@ public void doMulti(boolean asString, Map sockKeys, Strin log.error("selector timed out waiting for activity"); } - timeRemaining = timeout - (System.currentTimeMillis() - startTime); + timeRemaining = timeout + - (System.currentTimeMillis() - startTime); } } catch (IOException e) { return; } finally { - log.debug("Disconnecting; numConns=" + numConns + " timeRemaining=" + timeRemaining); + log.debug("Disconnecting; numConns=" + numConns + + " timeRemaining=" + timeRemaining); // run through our conns and either return them to the pool // or forcibly close them try { - if (selector != null) + if (selector != null) { selector.close(); + } } catch (IOException ignoreMe) { } for (Connection c : conns) { - if (c != null) + if (c != null) { c.close(); + } } } @@ -1555,8 +1693,10 @@ public void doMulti(boolean asString, Map sockKeys, Strin // not done. But we'll return what we've got... for (Connection c : conns) { try { - if (c.incoming.size() > 0 && c.isDone()) - loadMulti(new ByteBufArrayInputStream(c.incoming), ret, asString); + if (c.incoming.size() > 0 && c.isDone()) { + loadMulti(new ByteBufArrayInputStream(c.incoming), ret, + asString); + } } catch (Exception e) { // shouldn't happen; we have all the data already log.debug("Caught the aforementioned exception on " + c); @@ -1564,15 +1704,17 @@ public void doMulti(boolean asString, Map sockKeys, Strin } } - public void doMulti(Map sockKeys, String[] keys, Map ret) { + public void doMulti(Map sockKeys, String[] keys, + Map ret) { doMulti(false, sockKeys, keys, ret); } private void handleKey(SelectionKey key) throws IOException { - if (key.isReadable()) + if (key.isReadable()) { readResponse(key); - else if (key.isWritable()) + } else if (key.isWritable()) { writeRequest(key); + } } public void writeRequest(SelectionKey key) throws IOException { @@ -1602,11 +1744,13 @@ public void readResponse(SelectionKey key) throws IOException { } } - public boolean sync(String key, Integer hashCode) { - if (key == null) { + @Override + public boolean sync(Serializable originKey, Integer hashCode) { + if (originKey == null) { log.error("null value for key passed to sync()"); return false; } + String key = keyTransCoder.encode(originKey); // get SockIO obj from hash or from key SchoonerSockIO sock = pool.getSock(key, hashCode); @@ -1629,18 +1773,25 @@ public boolean sync(String key, Integer hashCode) { String line = sis.getLine(); sis.close(); if (SYNCED.equals(line)) { - log.info(new StringBuffer().append("++++ sync of key: ").append(key) - .append(" from cache was a success").toString()); + log.info(new StringBuffer().append("++++ sync of key: ") + .append(key).append(" from cache was a success") + .toString()); // return sock to pool and bail here return true; } else if (NOTFOUND.equals(line)) { - log.info(new StringBuffer().append("++++ sync of key: ").append(key) - .append(" from cache failed as the key was not found").toString()); + log.info(new StringBuffer().append("++++ sync of key: ") + .append(key) + .append(" from cache failed as the key was not found") + .toString()); } else { if (log.isErrorEnabled()) { - log.error(new StringBuffer().append("++++ error sync key: ").append(key).toString()); - log.error(new StringBuffer().append("++++ server response: ").append(line).toString()); + log.error(new StringBuffer() + .append("++++ error sync key: ").append(key) + .toString()); + log.error(new StringBuffer() + .append("++++ server response: ").append(line) + .toString()); } } } catch (IOException e) { @@ -1653,7 +1804,8 @@ public boolean sync(String key, Integer hashCode) { try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error("++++ failed to close socket : " + sock.toString(), + e1); } sock = null; @@ -1667,14 +1819,17 @@ public boolean sync(String key, Integer hashCode) { return false; } - public boolean sync(String key) { + @Override + public boolean sync(Serializable key) { return sync(key, null); } + @Override public boolean syncAll() { return syncAll(null); } + @Override public boolean syncAll(String[] servers) { // get SockIOPool instance @@ -1711,7 +1866,8 @@ public boolean syncAll(String[] servers) { sock.write(command.getBytes()); // if we get appropriate response back, then we return true // get result code - SockInputStream sis = new SockInputStream(sock, Integer.MAX_VALUE); + SockInputStream sis = new SockInputStream(sock, + Integer.MAX_VALUE); String line = sis.getLine(); sis.close(); success = (SYNCED.equals(line)) ? success && true : false; @@ -1725,7 +1881,9 @@ public boolean syncAll(String[] servers) { try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error( + "++++ failed to close socket : " + sock.toString(), + e1); } success = false; @@ -1750,14 +1908,4 @@ public void setDefaultEncoding(String defaultEncoding) { public void setPrimitiveAsString(boolean primitiveAsString) { this.primitiveAsString = primitiveAsString; } - - @Override - public void setSanitizeKeys(boolean sanitizeKeys) { - this.sanitizeKeys = sanitizeKeys; - } - - private String sanitizeKey(String key) throws UnsupportedEncodingException { - return (sanitizeKeys) ? URLEncoder.encode(key, "UTF-8") : key; - } - } diff --git a/src/main/java/com/schooner/MemCached/AscIIUDPClient.java b/src/main/java/com/schooner/MemCached/AscIIUDPClient.java index 2c080cc..2e99d15 100755 --- a/src/main/java/com/schooner/MemCached/AscIIUDPClient.java +++ b/src/main/java/com/schooner/MemCached/AscIIUDPClient.java @@ -1,9 +1,9 @@ /******************************************************************************* * Copyright (c) 2009 Schooner Information Technology, Inc. * All rights reserved. - * + * * http://www.schoonerinfotech.com/ - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -14,7 +14,7 @@ * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -29,8 +29,7 @@ package com.schooner.MemCached; import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; +import java.io.Serializable; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -53,23 +52,25 @@ * Please use the wrapper class {@link MemCachedClient} for accessing the * memcached server.
*
- * + * * When you are using memcached UDP protocol, pay attention that the data size * limit is about 64K due to the datagram length limit of UDP protocol.
*
- * + * * A UDP datagram length field specifies the length in bytes of the entire * datagram: header and data. The minimum length is 8 bytes since that's the * length of the header. The field size sets a theoretical limit of 65,535 bytes * (8 byte header + 65,527 bytes of data) for a UDP datagram. The practical * limit for the data length which is imposed by the underlying IPv4 protocol is * 65,507 bytes (65,535 − 8 byte UDP header − 20 byte IP header). - * + * * @author Xingen Wang * @since 2.5.0 * @see BinaryClient */ public class AscIIUDPClient extends MemCachedClient { + private TransBytecode keyTransCoder = new KeyTransCoder(); + private TransCoder transCoder = new ObjectTransCoder(); // pool instance @@ -78,8 +79,6 @@ public class AscIIUDPClient extends MemCachedClient { // which pool to use private String poolName; - // flags - private boolean sanitizeKeys; @SuppressWarnings("unused") private boolean primitiveAsString; @SuppressWarnings("unused") @@ -92,6 +91,7 @@ public class AscIIUDPClient extends MemCachedClient { public static final byte B_DELIMITER = 32; public static final byte B_RETURN = (byte) 13; + @Override public boolean isUseBinaryProtocol() { return false; } @@ -106,13 +106,14 @@ public AscIIUDPClient() { /** * Creates a new instance of MemCachedClient accepting a passed in pool * name. - * + * * @param poolName * name of SockIOPool * @param binaryProtocal * whether use binary protocol. */ public AscIIUDPClient(String poolName) { + super((MemCachedClient) null); this.poolName = poolName; init(); } @@ -126,11 +127,10 @@ public AscIIUDPClient(String poolName, ClassLoader cl, ErrorHandler eh) { /** * Initializes client object to defaults. - * + * * This enables compression and sets compression threshhold to 15 KB. */ private void init() { - this.sanitizeKeys = true; this.primitiveAsString = false; this.compressEnable = true; this.compressThreshold = COMPRESS_THRESH; @@ -138,96 +138,126 @@ private void init() { this.poolName = (this.poolName == null) ? "default" : this.poolName; // get a pool instance to work with for the life of this instance - this.pool = SchoonerSockIOPool.getInstance(poolName); + this.pool = SchoonerSockIOPool.getInstance(poolName, false); } - public boolean set(String key, Object value) { + @Override + public boolean set(Serializable key, Serializable value) { return set("set", key, value, null, null, 0L); } - public boolean set(String key, Object value, Integer hashCode) { + @Override + public boolean set(Serializable key, Serializable value, Integer hashCode) { return set("set", key, value, null, hashCode, 0L); } - public boolean set(String key, Object value, Date expiry) { + @Override + public boolean set(Serializable key, Serializable value, Date expiry) { return set("set", key, value, expiry, null, 0L); } - public boolean set(String key, Object value, Date expiry, Integer hashCode) { + @Override + public boolean set(Serializable key, Serializable value, Date expiry, + Integer hashCode) { return set("set", key, value, expiry, hashCode, 0L); } - - public boolean set(String key, Object value, Date expiry, Integer hashCode, boolean asString) { + + @Override + public boolean set(Serializable key, Serializable value, Date expiry, + Integer hashCode, boolean asString) { return set("set", key, value, expiry, hashCode, 0L); } - public boolean add(String key, Object value) { + @Override + public boolean add(Serializable key, Serializable value) { return set("add", key, value, null, null, 0L); } - public boolean add(String key, Object value, Integer hashCode) { + @Override + public boolean add(Serializable key, Serializable value, Integer hashCode) { return set("add", key, value, null, hashCode, 0L); } - public boolean add(String key, Object value, Date expiry) { + @Override + public boolean add(Serializable key, Serializable value, Date expiry) { return set("add", key, value, expiry, null, 0L); } - public boolean add(String key, Object value, Date expiry, Integer hashCode) { + @Override + public boolean add(Serializable key, Serializable value, Date expiry, + Integer hashCode) { return set("add", key, value, expiry, hashCode, 0L); } - public boolean append(String key, Object value, Integer hashCode) { + @Override + public boolean append(Serializable key, Serializable value, Integer hashCode) { return set("append", key, value, null, hashCode, 0L); } - public boolean append(String key, Object value) { + @Override + public boolean append(Serializable key, Serializable value) { return set("append", key, value, null, null, 0L); } - public boolean cas(String key, Object value, Integer hashCode, long casUnique) { + @Override + public boolean cas(Serializable key, Serializable value, Integer hashCode, + long casUnique) { return set("cas", key, value, null, hashCode, casUnique); } - public boolean cas(String key, Object value, Date expiry, long casUnique) { + @Override + public boolean cas(Serializable key, Serializable value, Date expiry, + long casUnique) { return set("cas", key, value, expiry, null, casUnique); } - public boolean cas(String key, Object value, Date expiry, Integer hashCode, long casUnique) { + @Override + public boolean cas(Serializable key, Serializable value, Date expiry, + Integer hashCode, long casUnique) { return set("cas", key, value, expiry, hashCode, casUnique); } - public boolean cas(String key, Object value, long casUnique) { + @Override + public boolean cas(Serializable key, Serializable value, long casUnique) { return set("cas", key, value, null, null, casUnique); } - public boolean prepend(String key, Object value, Integer hashCode) { + @Override + public boolean prepend(Serializable key, Serializable value, + Integer hashCode) { return set("prepend", key, value, null, hashCode, 0L); } - public boolean prepend(String key, Object value) { + @Override + public boolean prepend(Serializable key, Serializable value) { return set("prepend", key, value, null, null, 0L); } - public boolean replace(String key, Object value) { + @Override + public boolean replace(Serializable key, Serializable value) { return set("replace", key, value, null, null, 0L); } - public boolean replace(String key, Object value, Integer hashCode) { + @Override + public boolean replace(Serializable key, Serializable value, + Integer hashCode) { return set("replace", key, value, null, hashCode, 0L); } - public boolean replace(String key, Object value, Date expiry) { + @Override + public boolean replace(Serializable key, Serializable value, Date expiry) { return set("replace", key, value, expiry, null, 0L); } - public boolean replace(String key, Object value, Date expiry, Integer hashCode) { + @Override + public boolean replace(Serializable key, Serializable value, Date expiry, + Integer hashCode) { return set("replace", key, value, expiry, hashCode, 0L); } /** * Stores data to cache. - * + * * If data does not already exist for this key on the server, or if the key * is being
* deleted, the specified value will not be stored.
@@ -240,7 +270,7 @@ public boolean replace(String key, Object value, Date expiry, Integer hashCode) *
* As of the current release, all objects stored will use java * serialization. - * + * * @param cmdname * action to take (set, add, replace) * @param key @@ -253,24 +283,15 @@ public boolean replace(String key, Object value, Date expiry, Integer hashCode) * if not null, then the int hashcode to use * @return true/false indicating success */ - private boolean set(String cmdname, String key, Object value, Date expiry, Integer hashCode, Long casUnique) { + private boolean set(String cmdname, Serializable originKey, + Serializable value, Date expiry, Integer hashCode, Long casUnique) { - if (cmdname == null || key == null) { + if (cmdname == null || originKey == null) { log.error("key is null or cmd is null/empty for set()"); return false; } - try { - key = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - - // if we have an errorHandler, use its hook - if (errorHandler != null) - errorHandler.handleErrorOnSet(this, e, key); - - log.error("failed to sanitize your key!", e); - return false; - } + String key = keyTransCoder.encode(originKey); if (value == null) { log.error("trying to store a null value to cache"); @@ -281,22 +302,27 @@ private boolean set(String cmdname, String key, Object value, Date expiry, Integ SchoonerSockIO sock = pool.getSock(key, hashCode); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnSet(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnSet(this, new IOException( + "no socket to server available"), key); + } return false; } - if (expiry == null) + if (expiry == null) { expiry = new Date(0); + } try { - StorageCommand setCmd = new StorageCommand(cmdname, key, value, expiry, hashCode, casUnique, transCoder); + StorageCommand setCmd = new StorageCommand(cmdname, key, value, + expiry, hashCode, casUnique, transCoder); short rid = setCmd.request(sock); return setCmd.response(sock, rid); } catch (IOException e) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnSet(this, e, key); + } // exception thrown if (log.isErrorEnabled()) { @@ -307,7 +333,8 @@ private boolean set(String cmdname, String key, Object value, Date expiry, Integ try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error("++++ failed to close socket : " + sock.toString(), + e1); } sock = null; } finally { @@ -319,25 +346,39 @@ private boolean set(String cmdname, String key, Object value, Date expiry, Integ return false; } + /** + * set key transcoder + * + * @param keyTransCoder + */ + @Override + public void setKeyTransCoder(TransBytecode keyTransCoder) { + this.keyTransCoder = keyTransCoder; + } + /** * set transcoder. TransCoder is used to customize the serialization and * deserialization. - * + * * @param transCoder */ + @Override public void setTransCoder(TransCoder transCoder) { this.transCoder = transCoder; } - public long addOrDecr(String key) { + @Override + public long addOrDecr(Serializable key) { return addOrDecr(key, 0, null); } - public long addOrDecr(String key, long inc) { + @Override + public long addOrDecr(Serializable key, long inc) { return addOrDecr(key, inc, null); } - public long addOrDecr(String key, long inc, Integer hashCode) { + @Override + public long addOrDecr(Serializable key, long inc, Integer hashCode) { boolean ret = add(key, "" + inc, hashCode); if (ret) { return inc; @@ -346,15 +387,18 @@ public long addOrDecr(String key, long inc, Integer hashCode) { } } - public long addOrIncr(String key) { + @Override + public long addOrIncr(Serializable key) { return addOrIncr(key, 0, null); } - public long addOrIncr(String key, long inc) { + @Override + public long addOrIncr(Serializable key, long inc) { return addOrIncr(key, inc, null); } - public long addOrIncr(String key, long inc, Integer hashCode) { + @Override + public long addOrIncr(Serializable key, long inc, Integer hashCode) { boolean ret = add(key, "" + inc, hashCode); if (ret) { @@ -364,30 +408,37 @@ public long addOrIncr(String key, long inc, Integer hashCode) { } } - public long decr(String key) { + @Override + public long decr(Serializable key) { return incrdecr("decr", key, 1, null); } - public long decr(String key, long inc) { + @Override + public long decr(Serializable key, long inc) { return incrdecr("decr", key, inc, null); } - public long decr(String key, long inc, Integer hashCode) { + @Override + public long decr(Serializable key, long inc, Integer hashCode) { return incrdecr("decr", key, inc, hashCode); } - public boolean delete(String key) { + @Override + public boolean delete(Serializable key) { return delete(key, null, null); } - public boolean delete(String key, Date expiry) { + @Override + public boolean delete(Serializable key, Date expiry) { return delete(key, null, expiry); } + @Override public boolean flushAll() { return flushAll(null); } + @Override public boolean flushAll(String[] servers) { // get SockIOPool instance // return false if unable to get SockIO obj @@ -411,8 +462,10 @@ public boolean flushAll(String[] servers) { SchoonerSockIO sock = pool.getConnection(servers[i]); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnFlush(this, new IOException("no socket to server available")); + if (errorHandler != null) { + errorHandler.handleErrorOnFlush(this, new IOException( + "no socket to server available")); + } log.error("++++ unable to get connection to : " + servers[i]); success = false; @@ -440,7 +493,9 @@ public boolean flushAll(String[] servers) { try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error( + "++++ failed to close socket : " + sock.toString(), + e1); } success = false; @@ -456,64 +511,76 @@ public boolean flushAll(String[] servers) { return success; } - public Object get(String key) { + @Override + public Object get(Serializable key) { return get(key, null); } - public Object get(String key, Integer hashCode) { + @Override + public Object get(Serializable key, Integer hashCode) { return get("get", key, hashCode).value; } - public Map getMulti(String[] keys) { + @Override + public Map getMulti(Serializable[] keys) { return getMulti(keys, null); } - public Map getMulti(String[] keys, Integer[] hashCodes) { - + @Override + public Map getMulti(Serializable[] keys, + Integer[] hashCodes) { if (keys == null || keys.length == 0) { log.error("missing keys for getMulti()"); return null; } - Map ret = new HashMap(keys.length); + Map ret = new HashMap( + keys.length); for (int i = 0; i < keys.length; ++i) { - String key = keys[i]; - if (key == null) { + Serializable originKey = keys[i]; + if (originKey == null) { log.error("null key, so skipping"); continue; } + String key = keyTransCoder.encode(originKey); + Integer hash = null; - if (hashCodes != null && hashCodes.length > i) + if (hashCodes != null && hashCodes.length > i) { hash = hashCodes[i]; + } // get SockIO obj from cache key SchoonerSockIO sock = pool.getSock(key, hash); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnGet(this, new IOException( + "no socket to server available"), key); + } continue; } - ret.put(key, get("get", key, hash).value); + ret.put(originKey, get("get", key, hash).value); sock.close(); } return ret; } - public Object[] getMultiArray(String[] keys) { + @Override + public Object[] getMultiArray(Serializable[] keys) { return getMultiArray(keys, null); } - public Object[] getMultiArray(String[] keys, Integer[] hashCodes) { - - Map data = getMulti(keys, hashCodes); + @Override + public Object[] getMultiArray(Serializable[] keys, Integer[] hashCodes) { + Map data = getMulti(keys, hashCodes); - if (data == null) + if (data == null) { return null; + } Object[] res = new Object[keys.length]; for (int i = 0; i < keys.length; i++) { @@ -525,11 +592,11 @@ public Object[] getMultiArray(String[] keys, Integer[] hashCodes) { /** * Retrieve multiple objects from the memcache. - * + * * This is recommended over repeated calls to {@link #get(String) get()}, * since it
* is more efficient.
- * + * * @param keys * String array of keys to retrieve * @param hashCodes @@ -539,12 +606,15 @@ public Object[] getMultiArray(String[] keys, Integer[] hashCodes) { * @return Object array ordered in same order as key array containing * results */ - public Object[] getMultiArray(String[] keys, Integer[] hashCodes, boolean asString) { + @Override + public Object[] getMultiArray(Serializable[] keys, Integer[] hashCodes, + boolean asString) { - Map data = getMulti(keys, hashCodes, asString); + Map data = getMulti(keys, hashCodes, asString); - if (data == null) + if (data == null) { return null; + } Object[] res = new Object[keys.length]; for (int i = 0; i < keys.length; i++) { @@ -554,17 +624,19 @@ public Object[] getMultiArray(String[] keys, Integer[] hashCodes, boolean asStri return res; } - public MemcachedItem gets(String key) { + @Override + public MemcachedItem gets(Serializable key) { return gets(key, null); } - public MemcachedItem gets(String key, Integer hashCode) { + @Override + public MemcachedItem gets(Serializable key, Integer hashCode) { return get("gets", key, hashCode); } /** * get memcached item from server. - * + * * @param cmd * cmd to be used, get/gets * @param key @@ -573,31 +645,25 @@ public MemcachedItem gets(String key, Integer hashCode) { * specified hashcode * @return memcached item with value in it. */ - private MemcachedItem get(String cmd, String key, Integer hashCode) { + private MemcachedItem get(String cmd, Serializable originKey, + Integer hashCode) { MemcachedItem item = new MemcachedItem(); - if (key == null) { + if (originKey == null) { log.error("key is null for get()"); return item; } - try { - key = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - // if we have an errorHandler, use its hook - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, e, key); - - log.error("failed to sanitize your key!", e); - return null; - } + String key = keyTransCoder.encode(originKey); // get SockIO obj using cache key SchoonerSockIO sock = pool.getSock(key, hashCode); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnGet(this, new IOException( + "no socket to server available"), key); + } return item; } @@ -609,7 +675,8 @@ private MemcachedItem get(String cmd, String key, Integer hashCode) { try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error("++++ failed to close socket : " + sock.toString(), + e1); } sock = null; } finally { @@ -622,61 +689,81 @@ private MemcachedItem get(String cmd, String key, Integer hashCode) { } - public long incr(String key) { + @Override + public long incr(Serializable key) { return incrdecr("incr", key, 1, null); } - public long incr(String key, long inc) { + @Override + public long incr(Serializable key, long inc) { return incrdecr("incr", key, inc, null); } - public long incr(String key, long inc, Integer hashCode) { + @Override + public long incr(Serializable key, long inc, Integer hashCode) { return incrdecr("incr", key, inc, hashCode); } - public boolean keyExists(String key) { + @Override + public boolean keyExists(Serializable key) { return (this.get(key, null) != null); } + @Override public Map> stats() { return stats(null); } + @Override public Map> stats(String[] servers) { return stats(servers, "stats\r\n", STATS); } - public Map> statsCacheDump(int slabNumber, int limit) { + @Override + public Map> statsCacheDump(int slabNumber, + int limit) { return statsCacheDump(null, slabNumber, limit); } - public Map> statsCacheDump(String[] servers, int slabNumber, int limit) { - return stats(servers, String.format("stats cachedump %d %d\r\n", slabNumber, limit), ITEM); + @Override + public Map> statsCacheDump(String[] servers, + int slabNumber, int limit) { + return stats(servers, + String.format("stats cachedump %d %d\r\n", slabNumber, limit), + ITEM); } + @Override public Map> statsItems() { return statsItems(null); } + @Override public Map> statsItems(String[] servers) { return stats(servers, "stats items\r\n", STATS); } + @Override public Map> statsSlabs() { return statsSlabs(null); } + @Override public Map> statsSlabs(String[] servers) { return stats(servers, "stats slabs\r\n", STATS); } - public boolean sync(String key, Integer hashCode) { - if (key == null) { - if (log.isErrorEnabled()) + @Override + public boolean sync(Serializable originKey, Integer hashCode) { + if (originKey == null) { + if (log.isErrorEnabled()) { log.error("null value for key passed to delete()"); + } return false; } + String key = keyTransCoder.encode(originKey); + // get SockIO obj from hash or from key SchoonerSockIO sock = pool.getSock(key, hashCode); @@ -699,7 +786,8 @@ public boolean sync(String key, Integer hashCode) { try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error("++++ failed to close socket : " + sock.toString(), + e1); } sock = null; @@ -713,14 +801,17 @@ public boolean sync(String key, Integer hashCode) { return false; } - public boolean sync(String key) { + @Override + public boolean sync(Serializable key) { return sync(key, null); } + @Override public boolean syncAll() { return syncAll(null); } + @Override public boolean syncAll(String[] servers) { // get SockIOPool instance // return false if unable to get SockIO obj @@ -754,8 +845,9 @@ public boolean syncAll(String[] servers) { short rid = syncCmd.request(sock); success = syncCmd.response(sock, rid); - if (!success) + if (!success) { return false; + } } catch (IOException e) { // exception thrown if (log.isErrorEnabled()) { @@ -766,7 +858,9 @@ public boolean syncAll(String[] servers) { try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error( + "++++ failed to close socket : " + sock.toString(), + e1); } success = false; @@ -782,30 +876,36 @@ public boolean syncAll(String[] servers) { return success; } - public boolean delete(String key, Integer hashCode, Date expiry) { - - if (key == null) { + @Override + public boolean delete(Serializable originKey, Integer hashCode, Date expiry) { + if (originKey == null) { log.error("null value for key passed to delete()"); return false; } + String key = keyTransCoder.encode(originKey); + // get SockIO obj from hash or from key SchoonerSockIO sock = pool.getSock(key, hashCode); // return false if unable to get SockIO obj if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnDelete(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnDelete(this, new IOException( + "no socket to server available"), key); + } return false; } try { - DeletionCommand deletion = new DeletionCommand(key, hashCode, expiry); + DeletionCommand deletion = new DeletionCommand(key, hashCode, + expiry); short rid = deletion.request(sock); return deletion.response(sock, rid); } catch (IOException e) { - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnDelete(this, e, key); + } // exception thrown if (log.isErrorEnabled()) { @@ -815,7 +915,8 @@ public boolean delete(String key, Integer hashCode, Date expiry) { try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error("++++ failed to close socket : " + sock.toString(), + e1); } sock = null; } finally { @@ -829,13 +930,13 @@ public boolean delete(String key, Integer hashCode, Date expiry) { /** * Increments/decrements the value at the specified key by inc. - * + * * Note that the server uses a 32-bit unsigned integer, and checks for
* underflow. In the event of underflow, the result will be zero. Because
* Java lacks unsigned types, the value is returned as a 64-bit integer.
* The server will only decrement a value if it already exists;
* if a value is not found, -1 will be returned. - * + * * @param cmdname * increment/decrement * @param key @@ -846,35 +947,30 @@ public boolean delete(String key, Integer hashCode, Date expiry) { * if not null, then the int hashcode to use * @return new value or -1 if not exist */ - private long incrdecr(String cmdname, String key, long inc, Integer hashCode) { + private long incrdecr(String cmdname, Serializable originKey, long inc, + Integer hashCode) { - if (key == null) { + if (originKey == null) { log.error("null key for incrdecr()"); return -1; } - try { - key = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - // if we have an errorHandler, use its hook - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, e, key); - - log.error("failed to sanitize your key!", e); - return -1; - } + String key = keyTransCoder.encode(originKey); // get SockIO obj for given cache key SchoonerSockIO sock = pool.getSock(key, hashCode); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnSet(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnSet(this, new IOException( + "no socket to server available"), key); + } return -1; } try { - IncrdecrCommand idCmd = new IncrdecrCommand(cmdname, key, inc, hashCode); + IncrdecrCommand idCmd = new IncrdecrCommand(cmdname, key, inc, + hashCode); short rid = idCmd.request(sock); if (idCmd.response(sock, rid)) { return idCmd.getResult(); @@ -883,8 +979,9 @@ private long incrdecr(String cmdname, String key, long inc, Integer hashCode) { } } catch (IOException e) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnGet(this, e, key); + } // exception thrown if (log.isErrorEnabled()) { @@ -895,7 +992,8 @@ private long incrdecr(String cmdname, String key, long inc, Integer hashCode) { try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error("++++ failed to close socket : " + sock.toString(), + e1); } sock = null; @@ -909,7 +1007,8 @@ private long incrdecr(String cmdname, String key, long inc, Integer hashCode) { return -1; } - private Map> stats(String[] servers, String command, String lineStart) { + private Map> stats(String[] servers, + String command, String lineStart) { if (command == null || command.trim().equals("")) { log.error("++++ invalid / missing command for stats()"); @@ -932,8 +1031,10 @@ private Map> stats(String[] servers, String command, SchoonerSockIO sock = pool.getConnection(servers[i]); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnStats(this, new IOException("no socket to server available")); + if (errorHandler != null) { + errorHandler.handleErrorOnStats(this, new IOException( + "no socket to server available")); + } continue; } // build command @@ -944,8 +1045,9 @@ private Map> stats(String[] servers, String command, statsMaps.put(servers[i], stats); } catch (IOException e) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnStats(this, e); + } // exception thrown if (log.isErrorEnabled()) { @@ -956,7 +1058,9 @@ private Map> stats(String[] servers, String command, try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error( + "++++ failed to close socket : " + sock.toString(), + e1); } sock = null; @@ -982,22 +1086,13 @@ public void setPrimitiveAsString(boolean primitiveAsString) { } @Override - public void setSanitizeKeys(boolean sanitizeKeys) { - this.sanitizeKeys = sanitizeKeys; - } - - private String sanitizeKey(String key) throws UnsupportedEncodingException { - return (sanitizeKeys) ? URLEncoder.encode(key, "UTF-8") : key; - } - - @Override - public Object get(String key, Integer hashCode, boolean asString) { + public Object get(Serializable key, Integer hashCode, boolean asString) { return get("get", key, hashCode).value; } @Override - public Map getMulti(String[] keys, Integer[] hashCodes, boolean asString) { + public Map getMulti(Serializable[] keys, + Integer[] hashCodes, boolean asString) { return getMulti(keys, hashCodes); } - } diff --git a/src/main/java/com/schooner/MemCached/BinaryClient.java b/src/main/java/com/schooner/MemCached/BinaryClient.java index e5908e2..1471804 100755 --- a/src/main/java/com/schooner/MemCached/BinaryClient.java +++ b/src/main/java/com/schooner/MemCached/BinaryClient.java @@ -1,9 +1,9 @@ /******************************************************************************* * Copyright (c) 2009 Schooner Information Technology, Inc. * All rights reserved. - * + * * http://www.schoonerinfotech.com/ - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -14,7 +14,7 @@ * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -33,8 +33,7 @@ import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; +import java.io.Serializable; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; @@ -56,12 +55,13 @@ *
* Please use the wrapper class {@link MemCachedClient} for accessing the * memcached server. - * + * * @author Xingen Wang * @since 2.5.0 * @see AscIIClient */ public class BinaryClient extends MemCachedClient { + private TransBytecode keyTransCoder = new KeyTransCoder(); private TransCoder transCoder = new ObjectTransCoder(); @@ -71,8 +71,6 @@ public class BinaryClient extends MemCachedClient { // which pool to use private String poolName; - // flags - private boolean sanitizeKeys; private boolean primitiveAsString; @SuppressWarnings("unused") private boolean compressEnable; @@ -80,6 +78,7 @@ public class BinaryClient extends MemCachedClient { private long compressThreshold; private String defaultEncoding = "utf-8"; + @Override public boolean isUseBinaryProtocol() { return true; } @@ -94,7 +93,7 @@ public BinaryClient() { /** * Creates a new instance of MemCachedClient accepting a passed in pool * name. - * + * * @param poolName * name of SockIOPool */ @@ -112,7 +111,7 @@ public BinaryClient(String poolName, ClassLoader cl, ErrorHandler eh) { /** * Initializes client object to defaults. - * + * * This enables compression and sets compression threshhold to 15 KB. */ private void init() { @@ -122,42 +121,39 @@ private void init() { this.pool = SchoonerSockIOPool.getInstance(poolName); } - public boolean keyExists(String key) { + @Override + public boolean keyExists(Serializable key) { return (this.get(key, null) != null); } - public boolean delete(String key) { + @Override + public boolean delete(Serializable key) { return delete(key, null, null); } - public boolean delete(String key, Date expiry) { + @Override + public boolean delete(Serializable key, Date expiry) { return delete(key, null, expiry); } - public boolean delete(String key, Integer hashCode, Date expiry) { - - if (key == null) { + @Override + public boolean delete(Serializable originKey, Integer hashCode, Date expiry) { + if (originKey == null) { log.error("null value for key passed to delete()"); return false; } - try { - key = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - if (errorHandler != null) - errorHandler.handleErrorOnDelete(this, e, key); - - log.error("failed to sanitize your key!", e); - return false; - } + String key = keyTransCoder.encode(originKey); // get SockIO obj from hash or from key SchoonerSockIO sock = pool.getSock(key, hashCode); // return false if unable to get SockIO obj if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnDelete(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnDelete(this, new IOException( + "no socket to server available"), key); + } return false; } @@ -182,12 +178,14 @@ public boolean delete(String key, Integer hashCode, Date expiry) { short status = dis.readShort(); dis.close(); if (status == STAT_NO_ERROR) { - log.debug("++++ deletion of key: " + key + " from cache was a success"); + log.debug("++++ deletion of key: " + key + + " from cache was a success"); // return sock to pool and bail here return true; } else if (status == STAT_KEY_NOT_FOUND) { - log.debug("++++ deletion of key: " + key + " from cache failed as the key was not found"); + log.debug("++++ deletion of key: " + key + + " from cache failed as the key was not found"); } else { if (log.isErrorEnabled()) { log.error("++++ error deleting key: " + key); @@ -196,8 +194,9 @@ public boolean delete(String key, Integer hashCode, Date expiry) { } } catch (IOException e) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnDelete(this, e, key); + } // exception thrown if (log.isErrorEnabled()) { @@ -208,7 +207,8 @@ public boolean delete(String key, Integer hashCode, Date expiry) { try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error("++++ failed to close socket : " + sock.toString(), + e1); } sock = null; @@ -223,93 +223,135 @@ public boolean delete(String key, Integer hashCode, Date expiry) { return false; } - public boolean set(String key, Object value) { + @Override + public boolean set(Serializable key, Serializable value) { return set(OPCODE_SET, key, value, null, null, 0L, primitiveAsString); } - public boolean set(String key, Object value, Integer hashCode) { - return set(OPCODE_SET, key, value, null, hashCode, 0L, primitiveAsString); + @Override + public boolean set(Serializable key, Serializable value, Integer hashCode) { + return set(OPCODE_SET, key, value, null, hashCode, 0L, + primitiveAsString); } - public boolean set(String key, Object value, Date expiry) { + @Override + public boolean set(Serializable key, Serializable value, Date expiry) { return set(OPCODE_SET, key, value, expiry, null, 0L, primitiveAsString); } - public boolean set(String key, Object value, Date expiry, Integer hashCode) { - return set(OPCODE_SET, key, value, expiry, hashCode, 0L, primitiveAsString); + @Override + public boolean set(Serializable key, Serializable value, Date expiry, + Integer hashCode) { + return set(OPCODE_SET, key, value, expiry, hashCode, 0L, + primitiveAsString); } - - public boolean set(String key, Object value, Date expiry, Integer hashCode, boolean asString) { + + @Override + public boolean set(Serializable key, Serializable value, Date expiry, + Integer hashCode, boolean asString) { return set(OPCODE_SET, key, value, expiry, hashCode, 0L, asString); } - public boolean add(String key, Object value) { + @Override + public boolean add(Serializable key, Serializable value) { return set(OPCODE_ADD, key, value, null, null, 0L, primitiveAsString); } - public boolean add(String key, Object value, Integer hashCode) { - return set(OPCODE_ADD, key, value, null, hashCode, 0L, primitiveAsString); + @Override + public boolean add(Serializable key, Serializable value, Integer hashCode) { + return set(OPCODE_ADD, key, value, null, hashCode, 0L, + primitiveAsString); } - public boolean add(String key, Object value, Date expiry) { + @Override + public boolean add(Serializable key, Serializable value, Date expiry) { return set(OPCODE_ADD, key, value, expiry, null, 0L, primitiveAsString); } - public boolean add(String key, Object value, Date expiry, Integer hashCode) { - return set(OPCODE_ADD, key, value, expiry, hashCode, 0L, primitiveAsString); + @Override + public boolean add(Serializable key, Serializable value, Date expiry, + Integer hashCode) { + return set(OPCODE_ADD, key, value, expiry, hashCode, 0L, + primitiveAsString); } - public boolean append(String key, Object value, Integer hashCode) { + @Override + public boolean append(Serializable key, Serializable value, Integer hashCode) { return apPrepend(OPCODE_APPEND, key, value, hashCode, 0L); } - public boolean append(String key, Object value) { + @Override + public boolean append(Serializable key, Serializable value) { return apPrepend(OPCODE_APPEND, key, value, null, 0L); } - public boolean cas(String key, Object value, Integer hashCode, long casUnique) { - return set(OPCODE_SET, key, value, null, hashCode, casUnique, primitiveAsString); + @Override + public boolean cas(Serializable key, Serializable value, Integer hashCode, + long casUnique) { + return set(OPCODE_SET, key, value, null, hashCode, casUnique, + primitiveAsString); } - public boolean cas(String key, Object value, Date expiry, long casUnique) { - return set(OPCODE_SET, key, value, expiry, null, casUnique, primitiveAsString); + @Override + public boolean cas(Serializable key, Serializable value, Date expiry, + long casUnique) { + return set(OPCODE_SET, key, value, expiry, null, casUnique, + primitiveAsString); } - public boolean cas(String key, Object value, Date expiry, Integer hashCode, long casUnique) { - return set(OPCODE_SET, key, value, expiry, hashCode, casUnique, primitiveAsString); + @Override + public boolean cas(Serializable key, Serializable value, Date expiry, + Integer hashCode, long casUnique) { + return set(OPCODE_SET, key, value, expiry, hashCode, casUnique, + primitiveAsString); } - public boolean cas(String key, Object value, long casUnique) { - return set(OPCODE_SET, key, value, null, null, casUnique, primitiveAsString); + @Override + public boolean cas(Serializable key, Serializable value, long casUnique) { + return set(OPCODE_SET, key, value, null, null, casUnique, + primitiveAsString); } - public boolean prepend(String key, Object value, Integer hashCode) { + @Override + public boolean prepend(Serializable key, Serializable value, + Integer hashCode) { return apPrepend(OPCODE_PREPEND, key, value, hashCode, 0L); } - public boolean prepend(String key, Object value) { + @Override + public boolean prepend(Serializable key, Serializable value) { return apPrepend(OPCODE_PREPEND, key, value, null, 0L); } - public boolean replace(String key, Object value) { - return set(OPCODE_REPLACE, key, value, null, null, 0L, primitiveAsString); + @Override + public boolean replace(Serializable key, Serializable value) { + return set(OPCODE_REPLACE, key, value, null, null, 0L, + primitiveAsString); } - public boolean replace(String key, Object value, Integer hashCode) { - return set(OPCODE_REPLACE, key, value, null, hashCode, 0L, primitiveAsString); + @Override + public boolean replace(Serializable key, Serializable value, + Integer hashCode) { + return set(OPCODE_REPLACE, key, value, null, hashCode, 0L, + primitiveAsString); } - public boolean replace(String key, Object value, Date expiry) { - return set(OPCODE_REPLACE, key, value, expiry, null, 0L, primitiveAsString); + @Override + public boolean replace(Serializable key, Serializable value, Date expiry) { + return set(OPCODE_REPLACE, key, value, expiry, null, 0L, + primitiveAsString); } - public boolean replace(String key, Object value, Date expiry, Integer hashCode) { - return set(OPCODE_REPLACE, key, value, expiry, hashCode, 0L, primitiveAsString); + @Override + public boolean replace(Serializable key, Serializable value, Date expiry, + Integer hashCode) { + return set(OPCODE_REPLACE, key, value, expiry, hashCode, 0L, + primitiveAsString); } /** * Set, Add, Replace data to cache. - * + * * If data does not already exist for this key on the server, or if the key * is being
* deleted, the specified value will not be stored.
@@ -322,7 +364,7 @@ public boolean replace(String key, Object value, Date expiry, Integer hashCode) *
* As of the current release, all objects stored will use java * serialization. - * + * * @param cmdname * action to take (set, add, replace) * @param key @@ -335,25 +377,15 @@ public boolean replace(String key, Object value, Date expiry, Integer hashCode) * if not null, then the int hashcode to use * @return true/false indicating success */ - private boolean set(byte opcode, String key, Object value, Date expiry, Integer hashCode, long casUnique, + private boolean set(byte opcode, Serializable originKey, + Serializable value, Date expiry, Integer hashCode, long casUnique, boolean asString) { - - if (key == null) { + if (originKey == null) { log.error("key is null or cmd is null/empty for set()"); return false; } - try { - key = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - - // if we have an errorHandler, use its hook - if (errorHandler != null) - errorHandler.handleErrorOnSet(this, e, key); - - log.error("failed to sanitize your key!", e); - return false; - } + String key = keyTransCoder.encode(originKey); if (value == null) { log.error("trying to store a null value to cache"); @@ -364,17 +396,21 @@ private boolean set(byte opcode, String key, Object value, Date expiry, Integer SchoonerSockIO sock = pool.getSock(key, hashCode); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnSet(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnSet(this, new IOException( + "no socket to server available"), key); + } return false; } - if (expiry == null) + if (expiry == null) { expiry = new Date(0); + } try { // store flags - int flags = asString ? MemCachedClient.MARKER_STRING : NativeHandler.getMarkerFlag(value); + int flags = asString ? MemCachedClient.MARKER_STRING + : NativeHandler.getMarkerFlag(value); byte[] buf = key.getBytes(); sock.writeBuf.clear(); sock.writeBuf.put(MAGIC_REQ); @@ -422,7 +458,8 @@ private boolean set(byte opcode, String key, Object value, Date expiry, Integer // now write the data to the cache server sock.flush(); // get result code - DataInputStream dis = new DataInputStream(new SockInputStream(sock, Integer.MAX_VALUE)); + DataInputStream dis = new DataInputStream(new SockInputStream(sock, + Integer.MAX_VALUE)); dis.readInt(); dis.readShort(); short stat = dis.readShort(); @@ -433,8 +470,9 @@ private boolean set(byte opcode, String key, Object value, Date expiry, Integer } catch (IOException e) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnSet(this, e, key); + } // exception thrown if (log.isErrorEnabled()) { @@ -445,7 +483,8 @@ private boolean set(byte opcode, String key, Object value, Date expiry, Integer try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error("++++ failed to close socket : " + sock.toString(), + e1); } sock = null; @@ -462,7 +501,7 @@ private boolean set(byte opcode, String key, Object value, Date expiry, Integer /** * Append & Prepend data to cache. - * + * * If data does not already exist for this key on the server, or if the key * is being
* deleted, the specified value will not be stored.
@@ -475,7 +514,7 @@ private boolean set(byte opcode, String key, Object value, Date expiry, Integer *
* As of the current release, all objects stored will use java * serialization. - * + * * @param cmdname * action to take (set, add, replace) * @param key @@ -486,19 +525,14 @@ private boolean set(byte opcode, String key, Object value, Date expiry, Integer * if not null, then the int hashcode to use * @return true/false indicating success */ - private boolean apPrepend(byte opcode, String key, Object value, Integer hashCode, Long casUnique) { - - if (key == null) { + private boolean apPrepend(byte opcode, Serializable originKey, + Serializable value, Integer hashCode, Long casUnique) { + if (originKey == null) { log.error("key is null or cmd is null/empty for set()"); return false; } - try { - key = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - log.error("failed to sanitize your key!", e); - return false; - } + String key = keyTransCoder.encode(originKey); if (value == null) { log.error("trying to store a null value to cache"); @@ -547,7 +581,8 @@ private boolean apPrepend(byte opcode, String key, Object value, Integer hashCod // now write the data to the cache server sock.flush(); // get result code - DataInputStream dis = new DataInputStream(new SockInputStream(sock, Integer.MAX_VALUE)); + DataInputStream dis = new DataInputStream(new SockInputStream(sock, + Integer.MAX_VALUE)); dis.readInt(); dis.readShort(); short stat = dis.readShort(); @@ -565,7 +600,8 @@ private boolean apPrepend(byte opcode, String key, Object value, Integer hashCod try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error("++++ failed to close socket : " + sock.toString(), + e1); } sock = null; @@ -579,15 +615,18 @@ private boolean apPrepend(byte opcode, String key, Object value, Integer hashCod return false; } - public long addOrIncr(String key) { + @Override + public long addOrIncr(Serializable key) { return addOrIncr(key, 0, null); } - public long addOrIncr(String key, long inc) { + @Override + public long addOrIncr(Serializable key, long inc) { return addOrIncr(key, inc, null); } - public long addOrIncr(String key, long inc, Integer hashCode) { + @Override + public long addOrIncr(Serializable key, long inc, Integer hashCode) { boolean ret = add(key, "" + inc, hashCode); if (ret) { @@ -597,15 +636,18 @@ public long addOrIncr(String key, long inc, Integer hashCode) { } } - public long addOrDecr(String key) { + @Override + public long addOrDecr(Serializable key) { return addOrDecr(key, 0, null); } - public long addOrDecr(String key, long inc) { + @Override + public long addOrDecr(Serializable key, long inc) { return addOrDecr(key, inc, null); } - public long addOrDecr(String key, long inc, Integer hashCode) { + @Override + public long addOrDecr(Serializable key, long inc, Integer hashCode) { boolean ret = add(key, "" + inc, hashCode); if (ret) { return inc; @@ -614,39 +656,45 @@ public long addOrDecr(String key, long inc, Integer hashCode) { } } - public long incr(String key) { + @Override + public long incr(Serializable key) { return incrdecr(OPCODE_INCREMENT, key, 1, null); } - public long incr(String key, long inc) { + @Override + public long incr(Serializable key, long inc) { return incrdecr(OPCODE_INCREMENT, key, inc, null); } - public long incr(String key, long inc, Integer hashCode) { + @Override + public long incr(Serializable key, long inc, Integer hashCode) { return incrdecr(OPCODE_INCREMENT, key, inc, hashCode); } - public long decr(String key) { + @Override + public long decr(Serializable key) { return incrdecr(OPCODE_DECREMENT, key, 1, null); } - public long decr(String key, long inc) { + @Override + public long decr(Serializable key, long inc) { return incrdecr(OPCODE_DECREMENT, key, inc, null); } - public long decr(String key, long inc, Integer hashCode) { + @Override + public long decr(Serializable key, long inc, Integer hashCode) { return incrdecr(OPCODE_DECREMENT, key, inc, hashCode); } /** * Increments/decrements the value at the specified key by inc. - * + * * Note that the server uses a 32-bit unsigned integer, and checks for
* underflow. In the event of underflow, the result will be zero. Because
* Java lacks unsigned types, the value is returned as a 64-bit integer.
* The server will only decrement a value if it already exists;
* if a value is not found, -1 will be returned. - * + * * @param opcode * increment/decrement * @param key @@ -657,30 +705,23 @@ public long decr(String key, long inc, Integer hashCode) { * if not null, then the int hashcode to use * @return new value or -1 if not exist */ - private long incrdecr(byte opcode, String key, long inc, Integer hashCode) { - - if (key == null) { + private long incrdecr(byte opcode, Serializable originKey, long inc, + Integer hashCode) { + if (originKey == null) { log.error("null key for incrdecr()"); return -1; } - try { - key = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - // if we have an errorHandler, use its hook - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, e, key); - - log.error("failed to sanitize your key!", e); - return -1; - } + String key = keyTransCoder.encode(originKey); // get SockIO obj for given cache key SchoonerSockIO sock = pool.getSock(key, hashCode); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnSet(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnSet(this, new IOException( + "no socket to server available"), key); + } return -1; } @@ -702,7 +743,8 @@ private long incrdecr(byte opcode, String key, long inc, Integer hashCode) { sock.writeBuf.put(keyBuf); sock.flush(); // get result code - DataInputStream dis = new DataInputStream(new SockInputStream(sock, Integer.MAX_VALUE)); + DataInputStream dis = new DataInputStream(new SockInputStream(sock, + Integer.MAX_VALUE)); dis.readInt(); dis.readShort(); short status = dis.readShort(); @@ -715,15 +757,20 @@ private long incrdecr(byte opcode, String key, long inc, Integer hashCode) { return res; } else { if (log.isErrorEnabled()) { - log.error(new StringBuffer().append("++++ error incr/decr key: ").append(key).toString()); - log.error(new StringBuffer().append("++++ server response: ").append(status).toString()); + log.error(new StringBuffer() + .append("++++ error incr/decr key: ").append(key) + .toString()); + log.error(new StringBuffer() + .append("++++ server response: ").append(status) + .toString()); } } } catch (IOException e) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnGet(this, e, key); + } // exception thrown if (log.isErrorEnabled()) { @@ -734,7 +781,8 @@ private long incrdecr(byte opcode, String key, long inc, Integer hashCode) { try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error("++++ failed to close socket : " + sock.toString(), + e1); } sock = null; @@ -748,36 +796,48 @@ private long incrdecr(byte opcode, String key, long inc, Integer hashCode) { return -1; } - public Object get(String key) { + @Override + public Object get(Serializable key) { return get(key, null); } - public Object get(String key, Integer hashCode) { + @Override + public Object get(Serializable key, Integer hashCode) { return get(OPCODE_GET, key, hashCode, false); } - public MemcachedItem gets(String key) { + @Override + public MemcachedItem gets(Serializable key) { return gets(key, null); } - public MemcachedItem gets(String key, Integer hashCode) { + @Override + public MemcachedItem gets(Serializable key, Integer hashCode) { return gets(OPCODE_GET, key, hashCode, false); } + @Override + public void setKeyTransCoder(TransBytecode keyTransCoder) { + this.keyTransCoder = keyTransCoder; + } + + @Override public void setTransCoder(TransCoder transCoder) { this.transCoder = transCoder; } - public Object[] getMultiArray(String[] keys) { + @Override + public Object[] getMultiArray(Serializable[] keys) { return getMultiArray(keys, null); } - public Object[] getMultiArray(String[] keys, Integer[] hashCodes) { - - Map data = getMulti(keys, hashCodes); + @Override + public Object[] getMultiArray(Serializable[] keys, Integer[] hashCodes) { + Map data = getMulti(keys, hashCodes); - if (data == null) + if (data == null) { return null; + } Object[] res = new Object[keys.length]; for (int i = 0; i < keys.length; i++) { @@ -787,21 +847,24 @@ public Object[] getMultiArray(String[] keys, Integer[] hashCodes) { return res; } - public Map getMulti(String[] keys) { + @Override + public Map getMulti(Serializable[] keys) { return getMulti(keys, null); } - public Map getMulti(String[] keys, Integer[] hashCodes) { + @Override + public Map getMulti(Serializable[] keys, + Integer[] hashCodes) { return getMulti(keys, hashCodes, false); } /** * Retrieve multiple keys from the memcache. - * + * * This is recommended over repeated calls to {@link #get(String) get()}, * since it
* is more efficient.
- * + * * @param keys * keys to retrieve * @param hashCodes @@ -812,8 +875,9 @@ public Map getMulti(String[] keys, Integer[] hashCodes) { * that are not found are not entered into the hashmap, but * attempting to retrieve them from the hashmap gives you null. */ - public Map getMulti(String[] keys, Integer[] hashCodes, boolean asString) { - + @Override + public Map getMulti(Serializable[] keys, + Integer[] hashCodes, boolean asString) { if (keys == null || keys.length == 0) { log.error("missing keys for getMulti()"); return null; @@ -822,42 +886,36 @@ public Map getMulti(String[] keys, Integer[] hashCodes, boolean Map> cmdMap = new HashMap>(); String[] cleanKeys = new String[keys.length]; for (int i = 0; i < keys.length; ++i) { - - String key = keys[i]; - if (key == null) { + Serializable originKey = keys[i]; + if (originKey == null) { log.error("null key, so skipping"); continue; } + String key = keyTransCoder.encode(originKey); + Integer hash = null; - if (hashCodes != null && hashCodes.length > i) + if (hashCodes != null && hashCodes.length > i) { hash = hashCodes[i]; + } cleanKeys[i] = key; - try { - cleanKeys[i] = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - - // if we have an errorHandler, use its hook - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, e, key); - - log.error("failed to sanitize your key!", e); - continue; - } // get SockIO obj from cache key SchoonerSockIO sock = pool.getSock(cleanKeys[i], hash); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnGet(this, new IOException( + "no socket to server available"), key); + } continue; } // store in map and list if not already - if (!cmdMap.containsKey(sock.getHost())) + if (!cmdMap.containsKey(sock.getHost())) { cmdMap.put(sock.getHost(), new ArrayList()); + } cmdMap.get(sock.getHost()).add(cleanKeys[i]); @@ -868,7 +926,8 @@ public Map getMulti(String[] keys, Integer[] hashCodes, boolean log.debug("multi get socket count : " + cmdMap.size()); // now query memcache - Map ret = new HashMap(keys.length); + Map ret = new HashMap( + keys.length); // now use new NIO implementation (new NIOLoader(this)).doMulti(asString, cmdMap, keys, ret); @@ -893,10 +952,10 @@ public Map getMulti(String[] keys, Integer[] hashCodes, boolean /** * This method loads the data from cache into a Map. - * + * * Pass a SockIO object which is ready to receive data and a HashMap
* to store the results. - * + * * @param sock * socket waiting to pass back data * @param hm @@ -906,7 +965,8 @@ public Map getMulti(String[] keys, Integer[] hashCodes, boolean * @throws IOException * if io exception happens while reading from socket */ - private void loadMulti(DataInputStream input, Map hm) throws IOException { + private void loadMulti(DataInputStream input, Map hm) + throws IOException { while (true) { input.readByte(); @@ -930,8 +990,10 @@ private void loadMulti(DataInputStream input, Map hm) throws IOE Object o = null; // we can only take out serialized objects if ((flag & F_COMPRESSED) == F_COMPRESSED) { - GZIPInputStream gzi = new GZIPInputStream(new ByteArrayInputStream(buf)); - ByteArrayOutputStream bos = new ByteArrayOutputStream(buf.length); + GZIPInputStream gzi = new GZIPInputStream( + new ByteArrayInputStream(buf)); + ByteArrayOutputStream bos = new ByteArrayOutputStream( + buf.length); int count; byte[] tmp = new byte[2048]; while ((count = gzi.read(tmp)) != -1) { @@ -948,10 +1010,13 @@ private void loadMulti(DataInputStream input, Map hm) throws IOE } catch (Exception e) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnGet(this, e, key); + } - log.error("++++ Exception thrown while trying to deserialize for key: " + key, e); + log.error( + "++++ Exception thrown while trying to deserialize for key: " + + key, e); e.printStackTrace(); } } else if (transCoder != null) { @@ -965,12 +1030,13 @@ private void loadMulti(DataInputStream input, Map hm) throws IOE } } + @Override public boolean flushAll() { return flushAll(null); } + @Override public boolean flushAll(String[] servers) { - // get SockIOPool instance // return false if unable to get SockIO obj if (pool == null) { @@ -993,8 +1059,10 @@ public boolean flushAll(String[] servers) { SchoonerSockIO sock = pool.getConnection(servers[i]); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnFlush(this, new IOException("no socket to server available")); + if (errorHandler != null) { + errorHandler.handleErrorOnFlush(this, new IOException( + "no socket to server available")); + } log.error("++++ unable to get connection to : " + servers[i]); success = false; continue; @@ -1014,16 +1082,19 @@ public boolean flushAll(String[] servers) { sock.flush(); // if we get appropriate response back, then we return true // get result code - DataInputStream dis = new DataInputStream(new SockInputStream(sock, Integer.MAX_VALUE)); + DataInputStream dis = new DataInputStream(new SockInputStream( + sock, Integer.MAX_VALUE)); dis.readInt(); dis.readShort(); - success = dis.readShort() == STAT_NO_ERROR ? success && true : false; + success = dis.readShort() == STAT_NO_ERROR ? success && true + : false; dis.close(); } catch (IOException e) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnFlush(this, e); + } // exception thrown if (log.isErrorEnabled()) { @@ -1034,7 +1105,9 @@ public boolean flushAll(String[] servers) { try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error( + "++++ failed to close socket : " + sock.toString(), + e1); } success = false; @@ -1050,39 +1123,51 @@ public boolean flushAll(String[] servers) { return success; } + @Override public Map> stats() { return stats(null); } + @Override public Map> stats(String[] servers) { return stats(servers, OPCODE_STAT, null); } + @Override public Map> statsItems() { return statsItems(null); } + @Override public Map> statsItems(String[] servers) { return stats(servers, OPCODE_STAT, "items".getBytes()); } + @Override public Map> statsSlabs() { return statsSlabs(null); } + @Override public Map> statsSlabs(String[] servers) { return stats(servers, OPCODE_STAT, "slabs".getBytes()); } - public Map> statsCacheDump(int slabNumber, int limit) { + @Override + public Map> statsCacheDump(int slabNumber, + int limit) { return statsCacheDump(null, slabNumber, limit); } - public Map> statsCacheDump(String[] servers, int slabNumber, int limit) { - return stats(servers, OPCODE_STAT, String.format("cachedump %d %d", slabNumber, limit).getBytes()); + @Override + public Map> statsCacheDump(String[] servers, + int slabNumber, int limit) { + return stats(servers, OPCODE_STAT, + String.format("cachedump %d %d", slabNumber, limit).getBytes()); } - private Map> stats(String[] servers, byte opcode, byte[] reqKey) { + private Map> stats(String[] servers, + byte opcode, byte[] reqKey) { // get all servers and iterate over them @@ -1106,8 +1191,10 @@ private Map> stats(String[] servers, byte opcode, by SchoonerSockIO sock = pool.getConnection(servers[i]); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnStats(this, new IOException("no socket to server available")); + if (errorHandler != null) { + errorHandler.handleErrorOnStats(this, new IOException( + "no socket to server available")); + } continue; } @@ -1137,15 +1224,17 @@ private Map> stats(String[] servers, byte opcode, by sock.getChannel().write(sock.writeBuf); // response - DataInputStream input = new DataInputStream(new SockInputStream(sock, Integer.MAX_VALUE)); + DataInputStream input = new DataInputStream( + new SockInputStream(sock, Integer.MAX_VALUE)); while (true) { input.skip(2); statKeyLen = input.readShort(); input.skip(4); statValLen = input.readInt() - statKeyLen; input.skip(12); - if (statKeyLen == 0) + if (statKeyLen == 0) { break; + } key = new byte[statKeyLen]; value = new byte[statValLen]; input.read(key); @@ -1156,8 +1245,9 @@ private Map> stats(String[] servers, byte opcode, by input.close(); } catch (IOException e) { // if we have an errorHandler, use its hook - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnStats(this, e); + } // exception thrown if (log.isErrorEnabled()) { @@ -1168,7 +1258,9 @@ private Map> stats(String[] servers, byte opcode, by try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error( + "++++ failed to close socket : " + sock.toString(), + e1); } sock = null; @@ -1200,10 +1292,13 @@ private final class Connection { public SchoonerSockIO sock; public SocketChannel channel; private boolean isDone = false; - private final byte[] NOOPFLAG = { MAGIC_RESP, OPCODE_NOOP, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + private final byte[] NOOPFLAG = { MAGIC_RESP, OPCODE_NOOP, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 }; - public Connection(SchoonerSockIO sock, ArrayList keys) throws IOException { + public Connection(SchoonerSockIO sock, ArrayList keys) + throws IOException { this.sock = sock; List bufList = new ArrayList(keys.size()); int size = 0; @@ -1233,9 +1328,11 @@ public Connection(SchoonerSockIO sock, ArrayList keys) throws IOExceptio outgoing.putLong(0L); outgoing.putLong(0L); outgoing.flip(); - channel = (SocketChannel) sock.getChannel(); - if (channel == null) - throw new IOException("dead connection to: " + sock.getHost()); + channel = sock.getChannel(); + if (channel == null) { + throw new IOException("dead connection to: " + + sock.getHost()); + } channel.configureBlocking(false); channel.register(selector, SelectionKey.OP_WRITE, this); @@ -1249,20 +1346,25 @@ public void close() { return; } } catch (IOException e) { - log.warn("++++ memcache: unexpected error closing normally", e); + log.warn( + "++++ memcache: unexpected error closing normally", + e); } try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error( + "++++ failed to close socket : " + sock.toString(), + e1); } } public boolean isDone() { // if we know we're done, just say so - if (isDone) + if (isDone) { return true; + } // else find out the hard way int strPos = NOOPFLAG.length - 1; @@ -1272,8 +1374,9 @@ public boolean isDone() { ByteBuffer buf = incoming.get(bi); int pos = buf.position() - 1; while (pos >= 0 && strPos >= 0) { - if (buf.get(pos--) != NOOPFLAG[strPos--]) + if (buf.get(pos--) != NOOPFLAG[strPos--]) { return false; + } } bi--; @@ -1294,19 +1397,23 @@ public ByteBuffer getBuffer() { } } + @Override public String toString() { - return new StringBuffer().append("Connection to ").append(sock.getHost()).append(" with ") - .append(incoming.size()).append(" bufs; done is ").append(isDone).toString(); + return new StringBuffer().append("Connection to ") + .append(sock.getHost()).append(" with ") + .append(incoming.size()).append(" bufs; done is ") + .append(isDone).toString(); } } - public void doMulti(Map> sockKeys, String[] keys, Map ret) { + public void doMulti(Map> sockKeys, + String[] keys, Map ret) { doMulti(false, sockKeys, keys, ret); } - public void doMulti(boolean asString, Map> sockKeys, String[] keys, - Map ret) { - + public void doMulti(boolean asString, + Map> sockKeys, Serializable[] keys, + Map ret) { long timeRemaining = 0; try { selector = Selector.open(); @@ -1315,7 +1422,8 @@ public void doMulti(boolean asString, Map> sockKeys, S // structures conns = new Connection[sockKeys.keySet().size()]; numConns = 0; - for (Iterator i = sockKeys.keySet().iterator(); i.hasNext();) { + for (Iterator i = sockKeys.keySet().iterator(); i + .hasNext();) { // get SockIO obj from hostname String host = i.next(); @@ -1340,7 +1448,8 @@ public void doMulti(boolean asString, Map> sockKeys, S int n = selector.select(Math.min(timeout, 5000)); if (n > 0) { // we've got some activity; handle it - Iterator it = selector.selectedKeys().iterator(); + Iterator it = selector.selectedKeys() + .iterator(); while (it.hasNext()) { SelectionKey key = it.next(); it.remove(); @@ -1353,7 +1462,8 @@ public void doMulti(boolean asString, Map> sockKeys, S log.error("selector timed out waiting for activity"); } - timeRemaining = timeout - (System.currentTimeMillis() - startTime); + timeRemaining = timeout + - (System.currentTimeMillis() - startTime); } } catch (IOException e) { // errors can happen just about anywhere above, from @@ -1364,14 +1474,16 @@ public void doMulti(boolean asString, Map> sockKeys, S // run through our conns and either return them to the pool // or forcibly close them try { - if (selector != null) + if (selector != null) { selector.close(); + } } catch (IOException ignoreMe) { } for (Connection c : conns) { - if (c != null) + if (c != null) { c.close(); + } } } @@ -1380,8 +1492,10 @@ public void doMulti(boolean asString, Map> sockKeys, S // not done. But we'll return what we've got... for (Connection c : conns) { try { - if (c.incoming.size() > 0 && c.isDone()) - loadMulti(new DataInputStream(new ByteBufArrayInputStream(c.incoming)), ret); + if (c.incoming.size() > 0 && c.isDone()) { + loadMulti(new DataInputStream( + new ByteBufArrayInputStream(c.incoming)), ret); + } } catch (Exception e) { // shouldn't happen; we have all the data already log.debug("Caught the aforementioned exception on " + c); @@ -1390,10 +1504,11 @@ public void doMulti(boolean asString, Map> sockKeys, S } private void handleKey(SelectionKey key) throws IOException { - if (key.isReadable()) + if (key.isReadable()) { readResponse(key); - else if (key.isWritable()) + } else if (key.isWritable()) { writeRequest(key); + } } public void writeRequest(SelectionKey key) throws IOException { @@ -1423,18 +1538,22 @@ public void readResponse(SelectionKey key) throws IOException { } } - public boolean sync(String key, Integer hashCode) { + @Override + public boolean sync(Serializable key, Integer hashCode) { return false; } - public boolean sync(String key) { + @Override + public boolean sync(Serializable key) { return sync(key, null); } + @Override public boolean syncAll() { return syncAll(null); } + @Override public boolean syncAll(String[] servers) { return false; } @@ -1450,42 +1569,27 @@ public void setPrimitiveAsString(boolean primitiveAsString) { } @Override - public void setSanitizeKeys(boolean sanitizeKeys) { - this.sanitizeKeys = sanitizeKeys; - } - - private String sanitizeKey(String key) throws UnsupportedEncodingException { - return (sanitizeKeys) ? URLEncoder.encode(key, "UTF-8") : key; - } - - @Override - public Object get(String key, Integer hashCode, boolean asString) { + public Object get(Serializable key, Integer hashCode, boolean asString) { return get(OPCODE_GET, key, hashCode, asString); } - private Object get(byte opCode, String key, Integer hashCode, boolean asString) { - if (key == null) { + private Object get(byte opCode, Serializable originKey, Integer hashCode, + boolean asString) { + if (originKey == null) { log.error("key is null for get()"); return null; } - try { - key = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - // if we have an errorHandler, use its hook - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, e, key); - - log.error("failed to sanitize your key!", e); - return null; - } + String key = keyTransCoder.encode(originKey); // get SockIO obj using cache key SchoonerSockIO sock = pool.getSock(key, hashCode); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnGet(this, new IOException( + "no socket to server available"), key); + } return null; } @@ -1528,8 +1632,10 @@ private Object get(byte opCode, String key, Integer hashCode, boolean asString) // decoding object buf = input.getBuffer(); if ((flag & F_COMPRESSED) == F_COMPRESSED) { - GZIPInputStream gzi = new GZIPInputStream(new ByteArrayInputStream(buf)); - ByteArrayOutputStream bos = new ByteArrayOutputStream(buf.length); + GZIPInputStream gzi = new GZIPInputStream( + new ByteArrayInputStream(buf)); + ByteArrayOutputStream bos = new ByteArrayOutputStream( + buf.length); int count; byte[] tmp = new byte[2048]; while ((count = gzi.read(tmp)) != -1) { @@ -1541,23 +1647,28 @@ private Object get(byte opCode, String key, Integer hashCode, boolean asString) } if (primitiveAsString || asString) { o = new String(buf, defaultEncoding); - } else + } else { o = NativeHandler.decode(buf, flag); + } } else if (transCoder != null) { // decode object with default transcoder. InputStream in = input; - if ((flag & F_COMPRESSED) == F_COMPRESSED) + if ((flag & F_COMPRESSED) == F_COMPRESSED) { in = new GZIPInputStream(in); - if (classLoader == null) + } + if (classLoader == null) { o = transCoder.decode(in); - else - o = ((ObjectTransCoder) transCoder).decode(in, classLoader); + } else { + o = ((ObjectTransCoder) transCoder).decode(in, + classLoader); + } } } return o; } catch (IOException e) { - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnDelete(this, e, key); + } // exception thrown if (log.isErrorEnabled()) { @@ -1567,7 +1678,8 @@ private Object get(byte opCode, String key, Integer hashCode, boolean asString) try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error("++++ failed to close socket : " + sock.toString(), + e1); } sock = null; } catch (RuntimeException e) { @@ -1580,29 +1692,23 @@ private Object get(byte opCode, String key, Integer hashCode, boolean asString) return null; } - private MemcachedItem gets(byte opCode, String key, Integer hashCode, boolean asString) { - if (key == null) { + private MemcachedItem gets(byte opCode, Serializable originKey, + Integer hashCode, boolean asString) { + if (originKey == null) { log.error("key is null for get()"); return null; } - try { - key = sanitizeKey(key); - } catch (UnsupportedEncodingException e) { - // if we have an errorHandler, use its hook - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, e, key); - - log.error("failed to sanitize your key!", e); - return null; - } + String key = keyTransCoder.encode(originKey); // get SockIO obj using cache key SchoonerSockIO sock = pool.getSock(key, hashCode); if (sock == null) { - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, new IOException("no socket to server available"), key); + if (errorHandler != null) { + errorHandler.handleErrorOnGet(this, new IOException( + "no socket to server available"), key); + } return null; } @@ -1646,8 +1752,10 @@ private MemcachedItem gets(byte opCode, String key, Integer hashCode, boolean as // decoding object buf = input.getBuffer(); if ((flag & F_COMPRESSED) == F_COMPRESSED) { - GZIPInputStream gzi = new GZIPInputStream(new ByteArrayInputStream(buf)); - ByteArrayOutputStream bos = new ByteArrayOutputStream(buf.length); + GZIPInputStream gzi = new GZIPInputStream( + new ByteArrayInputStream(buf)); + ByteArrayOutputStream bos = new ByteArrayOutputStream( + buf.length); int count; byte[] tmp = new byte[2048]; while ((count = gzi.read(tmp)) != -1) { @@ -1659,24 +1767,29 @@ private MemcachedItem gets(byte opCode, String key, Integer hashCode, boolean as } if (primitiveAsString || asString) { o = new String(buf, defaultEncoding); - } else + } else { o = NativeHandler.decode(buf, flag); + } } else if (transCoder != null) { // decode object with default transcoder. InputStream in = input; - if ((flag & F_COMPRESSED) == F_COMPRESSED) + if ((flag & F_COMPRESSED) == F_COMPRESSED) { in = new GZIPInputStream(in); - if (classLoader == null) + } + if (classLoader == null) { o = transCoder.decode(in); - else - o = ((ObjectTransCoder) transCoder).decode(in, classLoader); + } else { + o = ((ObjectTransCoder) transCoder).decode(in, + classLoader); + } } } item.value = o; return item; } catch (IOException e) { - if (errorHandler != null) + if (errorHandler != null) { errorHandler.handleErrorOnDelete(this, e, key); + } // exception thrown if (log.isErrorEnabled()) { @@ -1686,7 +1799,8 @@ private MemcachedItem gets(byte opCode, String key, Integer hashCode, boolean as try { sock.sockets.invalidateObject(sock); } catch (Exception e1) { - log.error("++++ failed to close socket : " + sock.toString(), e1); + log.error("++++ failed to close socket : " + sock.toString(), + e1); } sock = null; } finally { @@ -1698,11 +1812,14 @@ private MemcachedItem gets(byte opCode, String key, Integer hashCode, boolean as return null; } - public Object[] getMultiArray(String[] keys, Integer[] hashCodes, boolean asString) { - Map data = getMulti(keys, hashCodes, asString); + @Override + public Object[] getMultiArray(Serializable[] keys, Integer[] hashCodes, + boolean asString) { + Map data = getMulti(keys, hashCodes, asString); - if (data == null) + if (data == null) { return null; + } Object[] res = new Object[keys.length]; for (int i = 0; i < keys.length; i++) { diff --git a/src/main/java/com/schooner/MemCached/KeyTransCoder.java b/src/main/java/com/schooner/MemCached/KeyTransCoder.java new file mode 100644 index 0000000..10271ac --- /dev/null +++ b/src/main/java/com/schooner/MemCached/KeyTransCoder.java @@ -0,0 +1,124 @@ +package com.schooner.MemCached; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Date; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * {@link KeyTransCoder} is the default object translator,it used to change the + * key to String to + * + * @author xionghui + * + */ +public class KeyTransCoder implements TransBytecode { + // logger + public static final Logger LOG = LoggerFactory + .getLogger(KeyTransCoder.class); + + @Override + public String encode(Serializable origin) { + String result = null; + if (origin instanceof String) { + result = Constant.STRING_PREFIX + (String) origin; + } else if (origin instanceof StringBuilder + || origin instanceof StringBuffer) { + result = Constant.STRING_PREFIX + origin; + } else if (origin instanceof Boolean) { + result = Constant.BOOLEAN_PREFIX + + Boolean.toString((Boolean) origin); + } else if (origin instanceof Byte) { + result = Constant.BYTE_PREFIX + Byte.toString((Byte) origin); + } else if (origin instanceof Short) { + result = Constant.SHORT_PREFIX + Short.toString((Short) origin); + } else if (origin instanceof Character) { + result = Constant.CHARACTER_PREFIX + + Character.toString((Character) origin); + } else if (origin instanceof Integer) { + result = Constant.INTEGER_PREFIX + + Integer.toString((Integer) origin); + } else if (origin instanceof Long) { + result = Constant.LONG_PREFIX + Long.toString((Long) origin); + } else if (origin instanceof Float) { + result = Constant.FLOAT_PREFIX + Float.toString((Float) origin); + } else if (origin instanceof Double) { + result = Constant.DOUBLE_PREFIX + Double.toString((Double) origin); + } else if (origin instanceof Date) { + result = Constant.DATE_PREFIX + ((Date) origin).getTime(); + } else { + byte[] bys = serializable(origin); + if (origin.getClass().isArray()) { + result = Constant.ARRAY_PREFIX + byte2hex(bys); + } else { + result = Constant.OBJECT_PREFIX + byte2hex(bys); + } + } + return result; + } + + /** + * Get Object's byte code + * + * @param key + * @return + */ + private byte[] serializable(Serializable key) { + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(256); + try { + ObjectOutputStream objectOutputStream = new ObjectOutputStream( + byteStream); + objectOutputStream.writeObject(key); + objectOutputStream.flush(); + } catch (IOException e) { + // exception thrown + if (LOG.isErrorEnabled()) { + LOG.error("++++ exception thrown while serializabling"); + LOG.error(e.getMessage(), e); + } + } + return byteStream.toByteArray(); + } + + /** + * Change byte code to String + */ + private String byte2hex(byte[] bys) { + StringBuilder builder = new StringBuilder(); + String tmp = null; + for (int i = 0, len = bys.length; i < len; i++) { + // exchange integer to hex + tmp = (java.lang.Integer.toHexString(bys[i] & 0XFF)); + if (tmp.length() == 1) { + builder.append("0"); + } + builder.append(tmp); + } + return builder.toString(); + } + + /** + * Prefix of java class. + * + * @author xionghui + */ + private static class Constant { + private static final String STRING_PREFIX = "S_"; + private static final String BOOLEAN_PREFIX = "B_"; + private static final String INTEGER_PREFIX = "I_"; + private static final String LONG_PREFIX = "L_"; + private static final String CHARACTER_PREFIX = "C_"; + private static final String FLOAT_PREFIX = "F_"; + private static final String SHORT_PREFIX = "SH_"; + private static final String DOUBLE_PREFIX = "D_"; + private static final String DATE_PREFIX = "DATE_"; + private static final String BYTE_PREFIX = "BYTE_"; + + private static final String ARRAY_PREFIX = "A_"; + private static final String OBJECT_PREFIX = "O_"; + } +} diff --git a/src/main/java/com/schooner/MemCached/NativeHandler.java b/src/main/java/com/schooner/MemCached/NativeHandler.java index 5ceaf16..8990f1e 100644 --- a/src/main/java/com/schooner/MemCached/NativeHandler.java +++ b/src/main/java/com/schooner/MemCached/NativeHandler.java @@ -14,7 +14,7 @@ * You should have received a copy of the BSD License along with this * library. * - * @author Greg Whalin + * @author Greg Whalin * @version 2.0 */ package com.schooner.MemCached; @@ -27,67 +27,67 @@ /** * Handle encoding standard Java types directly which can result in significant * memory savings: - * + * * Currently the Memcached driver for Java supports the setSerialize() option. * This can increase performance in some situations but has a few issues: - * + * * Code that performs class casting will throw ClassCastExceptions when * setSerialize is enabled. For example: - * + * * mc.set( "foo", new Integer( 1 ) ); Integer output = (Integer)mc.get("foo"); - * + * * Will work just file when setSerialize is true but when its false will just * throw a ClassCastException. - * + * * Also internally it doesn't support Boolean and since toString is called * wastes a lot of memory and causes additional performance issue. For example * an Integer can take anywhere from 1 byte to 10 bytes. - * + * * Due to the way the memcached slab allocator works it seems like a LOT of * wasted memory to store primitive types as serialized objects (from a * performance and memory perspective). In our applications we have millions of * small objects and wasted memory would become a big problem. - * + * * For example a Serialized Boolean takes 47 bytes which means it will fit into * the 64byte LRU. Using 1 byte means it will fit into the 8 byte LRU thus * saving 8x the memory. This also saves the CPU performance since we don't have * to serialize bytes back and forth and we can compute the byte[] value * directly. - * + * * One problem would be when the user calls get() because doing so would require * the app to know the type of the object stored as a bytearray inside memcached * (since the user will probably cast). - * + * * If we assume the basic types are interned we could use the first byte as the * type with the remaining bytes as the value. Then on get() we could read the * first byte to determine the type and then construct the correct object for * it. This would prevent the ClassCastException I talked about above. - * + * * We could remove the setSerialize() option and just assume that standard VM * types are always internd in this manner. - * + * * mc.set( "foo", new Boolean.TRUE ); Boolean b = (Boolean)mc.get( "foo" ); - * + * * And the type casts would work because internally we would create a new * Boolean to return back to the client. - * + * * This would reduce memory footprint and allow for a virtual implementation of * the Externalizable interface which is much faster than Serialzation. - * + * * Currently the memory improvements would be: - * + * * java.lang.Boolean - 8x performance improvement (now just two bytes) * java.lang.Integer - 16x performance improvement (now just 5 bytes) - * + * * Most of the other primitive types would benefit from this optimization. * java.lang.Character being another obvious example. - * + * * I know it seems like I'm being really picky here but for our application I'd * save 1G of memory right off the bat. We'd go down from 1.152G of memory used * down to 144M of memory used which is much better IMO. - * + * * http://java.sun.com/docs/books/tutorial/native1.1/integrating/types.html - * + * * @author Kevin A. Burton * @author Greg Whalin */ @@ -95,17 +95,20 @@ public class NativeHandler { /** * Detemine of object can be natively serialized by this class. - * + * * @param value * Object to test. * @return true/false */ public static final boolean isHandled(Object value) { - return (value instanceof Byte || value instanceof Boolean || value instanceof Integer || value instanceof Long - || value instanceof Character || value instanceof String || value instanceof StringBuffer - || value instanceof Float || value instanceof Short || value instanceof Double || value instanceof Date - || value instanceof StringBuilder || value instanceof byte[]) ? true : false; + return (value instanceof Byte || value instanceof Boolean + || value instanceof Integer || value instanceof Long + || value instanceof Character || value instanceof String + || value instanceof StringBuffer || value instanceof Float + || value instanceof Short || value instanceof Double + || value instanceof Date || value instanceof StringBuilder || value instanceof byte[]) ? true + : false; } public static final boolean isHandled(int flag) { @@ -121,112 +124,140 @@ public static final boolean isHandled(int flag) { || (flag & MemCachedClient.MARKER_DOUBLE) == MemCachedClient.MARKER_DOUBLE || (flag & MemCachedClient.MARKER_DATE) == MemCachedClient.MARKER_DATE || (flag & MemCachedClient.MARKER_STRINGBUILDER) == MemCachedClient.MARKER_STRINGBUILDER - || (flag & MemCachedClient.MARKER_BYTEARR) == MemCachedClient.MARKER_BYTEARR) + || (flag & MemCachedClient.MARKER_BYTEARR) == MemCachedClient.MARKER_BYTEARR) { return true; + } return false; } /** * Returns the flag for marking the type of the byte array. - * + * * @param value * Object we are storing. * @return int marker */ public static final int getMarkerFlag(Object value) { - if (value instanceof Byte) + if (value instanceof String) { + return MemCachedClient.MARKER_STRING; + } + + if (value instanceof Byte) { return MemCachedClient.MARKER_BYTE; + } - if (value instanceof Boolean) + if (value instanceof Boolean) { return MemCachedClient.MARKER_BOOLEAN; + } - if (value instanceof Integer) + if (value instanceof Integer) { return MemCachedClient.MARKER_INTEGER; + } - if (value instanceof Long) + if (value instanceof Long) { return MemCachedClient.MARKER_LONG; + } - if (value instanceof Character) + if (value instanceof Character) { return MemCachedClient.MARKER_CHARACTER; + } - if (value instanceof String) - return MemCachedClient.MARKER_STRING; - - if (value instanceof StringBuffer) + if (value instanceof StringBuffer) { return MemCachedClient.MARKER_STRINGBUFFER; + } - if (value instanceof Float) + if (value instanceof Float) { return MemCachedClient.MARKER_FLOAT; + } - if (value instanceof Short) + if (value instanceof Short) { return MemCachedClient.MARKER_SHORT; + } - if (value instanceof Double) + if (value instanceof Double) { return MemCachedClient.MARKER_DOUBLE; + } - if (value instanceof Date) + if (value instanceof Date) { return MemCachedClient.MARKER_DATE; + } - if (value instanceof StringBuilder) + if (value instanceof StringBuilder) { return MemCachedClient.MARKER_STRINGBUILDER; + } - if (value instanceof byte[]) + if (value instanceof byte[]) { return MemCachedClient.MARKER_BYTEARR; + } return MemCachedClient.MARKER_OTHERS; } /** * Encodes supported types - * + * * @param value * Object to encode. * @return byte array - * + * * @throws UnsupportedEncodingException * If fail to encode. */ - public static byte[] encode(Object value) throws UnsupportedEncodingException { + public static byte[] encode(Object value) + throws UnsupportedEncodingException { - if (value instanceof Byte) + if (value instanceof String) { + return encode((String) value); + } + + if (value instanceof Byte) { return encode((Byte) value); + } - if (value instanceof Boolean) + if (value instanceof Boolean) { return encode((Boolean) value); + } - if (value instanceof Integer) + if (value instanceof Integer) { return encode(((Integer) value).intValue()); + } - if (value instanceof Long) + if (value instanceof Long) { return encode(((Long) value).longValue()); + } - if (value instanceof Character) + if (value instanceof Character) { return encode((Character) value); + } - if (value instanceof String) - return encode((String) value); - - if (value instanceof StringBuffer) + if (value instanceof StringBuffer) { return encode((StringBuffer) value); + } - if (value instanceof Float) + if (value instanceof Float) { return encode(((Float) value).floatValue()); + } - if (value instanceof Short) + if (value instanceof Short) { return encode((Short) value); + } - if (value instanceof Double) + if (value instanceof Double) { return encode(((Double) value).doubleValue()); + } - if (value instanceof Date) + if (value instanceof Date) { return encode((Date) value); + } - if (value instanceof StringBuilder) + if (value instanceof StringBuilder) { return encode((StringBuilder) value); + } - if (value instanceof byte[]) + if (value instanceof byte[]) { return encode((byte[]) value); + } return null; } @@ -240,10 +271,11 @@ protected static byte[] encode(Byte value) { protected static byte[] encode(Boolean value) { byte[] b = new byte[1]; - if (value.booleanValue()) + if (value.booleanValue()) { b[0] = 1; - else + } else { b[0] = 0; + } return b; } @@ -252,7 +284,8 @@ protected static byte[] encode(int value) { return getBytes(value); } - protected static byte[] encode(long value) throws UnsupportedEncodingException { + protected static byte[] encode(long value) + throws UnsupportedEncodingException { return getBytes(value); } @@ -264,27 +297,33 @@ protected static byte[] encode(Character value) { return encode(value.charValue()); } - protected static byte[] encode(String value) throws UnsupportedEncodingException { + protected static byte[] encode(String value) + throws UnsupportedEncodingException { return value.getBytes("UTF-8"); } - protected static byte[] encode(StringBuffer value) throws UnsupportedEncodingException { + protected static byte[] encode(StringBuffer value) + throws UnsupportedEncodingException { return encode(value.toString()); } - protected static byte[] encode(float value) throws UnsupportedEncodingException { - return encode((int) Float.floatToIntBits(value)); + protected static byte[] encode(float value) + throws UnsupportedEncodingException { + return encode(Float.floatToIntBits(value)); } - protected static byte[] encode(Short value) throws UnsupportedEncodingException { - return encode((int) value.shortValue()); + protected static byte[] encode(Short value) + throws UnsupportedEncodingException { + return encode(value.shortValue()); } - protected static byte[] encode(double value) throws UnsupportedEncodingException { - return encode((long) Double.doubleToLongBits(value)); + protected static byte[] encode(double value) + throws UnsupportedEncodingException { + return encode(Double.doubleToLongBits(value)); } - protected static byte[] encode(StringBuilder value) throws UnsupportedEncodingException { + protected static byte[] encode(StringBuilder value) + throws UnsupportedEncodingException { return encode(value.toString()); } @@ -316,55 +355,70 @@ protected static byte[] getBytes(int value) { /** * Decodes byte array using memcache flag to determine type. - * + * * @param b * @param marker * @return * @throws UnsupportedEncodingException */ - public static Object decode(byte[] b, int flag) throws UnsupportedEncodingException { + public static Object decode(byte[] b, int flag) + throws UnsupportedEncodingException { - if (b.length < 1) + if (b.length < 1) { return null; + } - if ((flag & MemCachedClient.MARKER_BYTE) == MemCachedClient.MARKER_BYTE) + if ((flag & MemCachedClient.MARKER_BYTE) == MemCachedClient.MARKER_BYTE) { return decodeByte(b); + } - if ((flag & MemCachedClient.MARKER_BOOLEAN) == MemCachedClient.MARKER_BOOLEAN) + if ((flag & MemCachedClient.MARKER_BOOLEAN) == MemCachedClient.MARKER_BOOLEAN) { return decodeBoolean(b); + } - if ((flag & MemCachedClient.MARKER_INTEGER) == MemCachedClient.MARKER_INTEGER) + if ((flag & MemCachedClient.MARKER_INTEGER) == MemCachedClient.MARKER_INTEGER) { return decodeInteger(b); + } - if ((flag & MemCachedClient.MARKER_LONG) == MemCachedClient.MARKER_LONG) + if ((flag & MemCachedClient.MARKER_LONG) == MemCachedClient.MARKER_LONG) { return decodeLong(b); + } - if ((flag & MemCachedClient.MARKER_CHARACTER) == MemCachedClient.MARKER_CHARACTER) + if ((flag & MemCachedClient.MARKER_CHARACTER) == MemCachedClient.MARKER_CHARACTER) { return decodeCharacter(b); + } - if ((flag & MemCachedClient.MARKER_STRING) == MemCachedClient.MARKER_STRING) + if ((flag & MemCachedClient.MARKER_STRING) == MemCachedClient.MARKER_STRING) { return decodeString(b); + } - if ((flag & MemCachedClient.MARKER_STRINGBUFFER) == MemCachedClient.MARKER_STRINGBUFFER) + if ((flag & MemCachedClient.MARKER_STRINGBUFFER) == MemCachedClient.MARKER_STRINGBUFFER) { return decodeStringBuffer(b); + } - if ((flag & MemCachedClient.MARKER_FLOAT) == MemCachedClient.MARKER_FLOAT) + if ((flag & MemCachedClient.MARKER_FLOAT) == MemCachedClient.MARKER_FLOAT) { return decodeFloat(b); + } - if ((flag & MemCachedClient.MARKER_SHORT) == MemCachedClient.MARKER_SHORT) + if ((flag & MemCachedClient.MARKER_SHORT) == MemCachedClient.MARKER_SHORT) { return decodeShort(b); + } - if ((flag & MemCachedClient.MARKER_DOUBLE) == MemCachedClient.MARKER_DOUBLE) + if ((flag & MemCachedClient.MARKER_DOUBLE) == MemCachedClient.MARKER_DOUBLE) { return decodeDouble(b); + } - if ((flag & MemCachedClient.MARKER_DATE) == MemCachedClient.MARKER_DATE) + if ((flag & MemCachedClient.MARKER_DATE) == MemCachedClient.MARKER_DATE) { return decodeDate(b); + } - if ((flag & MemCachedClient.MARKER_STRINGBUILDER) == MemCachedClient.MARKER_STRINGBUILDER) + if ((flag & MemCachedClient.MARKER_STRINGBUILDER) == MemCachedClient.MARKER_STRINGBUILDER) { return decodeStringBuilder(b); + } - if ((flag & MemCachedClient.MARKER_BYTEARR) == MemCachedClient.MARKER_BYTEARR) + if ((flag & MemCachedClient.MARKER_BYTEARR) == MemCachedClient.MARKER_BYTEARR) { return decodeByteArr(b); + } return null; } @@ -383,7 +437,8 @@ protected static Integer decodeInteger(byte[] b) { return new Integer(toInt(b)); } - protected static Long decodeLong(byte[] b) throws UnsupportedEncodingException { + protected static Long decodeLong(byte[] b) + throws UnsupportedEncodingException { return new Long(toLong(b)); } @@ -391,24 +446,29 @@ protected static Character decodeCharacter(byte[] b) { return new Character((char) decodeInteger(b).intValue()); } - protected static String decodeString(byte[] b) throws UnsupportedEncodingException { + protected static String decodeString(byte[] b) + throws UnsupportedEncodingException { return new String(b, "UTF-8"); } - protected static StringBuffer decodeStringBuffer(byte[] b) throws UnsupportedEncodingException { + protected static StringBuffer decodeStringBuffer(byte[] b) + throws UnsupportedEncodingException { return new StringBuffer(decodeString(b)); } - protected static Float decodeFloat(byte[] b) throws UnsupportedEncodingException { + protected static Float decodeFloat(byte[] b) + throws UnsupportedEncodingException { Integer l = decodeInteger(b); return new Float(Float.intBitsToFloat(l.intValue())); } - protected static Short decodeShort(byte[] b) throws UnsupportedEncodingException { + protected static Short decodeShort(byte[] b) + throws UnsupportedEncodingException { return new Short((short) decodeInteger(b).intValue()); } - protected static Double decodeDouble(byte[] b) throws UnsupportedEncodingException { + protected static Double decodeDouble(byte[] b) + throws UnsupportedEncodingException { Long l = decodeLong(b); return new Double(Double.longBitsToDouble(l.longValue())); } @@ -417,7 +477,8 @@ protected static Date decodeDate(byte[] b) { return new Date(toLong(b)); } - protected static StringBuilder decodeStringBuilder(byte[] b) throws UnsupportedEncodingException { + protected static StringBuilder decodeStringBuilder(byte[] b) + throws UnsupportedEncodingException { return new StringBuilder(decodeString(b)); } @@ -428,17 +489,21 @@ protected static byte[] decodeByteArr(byte[] b) { /** * This works by taking each of the bit patterns and converting them to ints * taking into account 2s complement and then adding them.. - * + * * @param b * @return */ protected static int toInt(byte[] b) { - return (((((int) b[3]) & 0xFF) << 32) + ((((int) b[2]) & 0xFF) << 40) + ((((int) b[1]) & 0xFF) << 48) + ((((int) b[0]) & 0xFF) << 56)); + return ((((b[3]) & 0xFF) << 32) + (((b[2]) & 0xFF) << 40) + + (((b[1]) & 0xFF) << 48) + (((b[0]) & 0xFF) << 56)); } protected static long toLong(byte[] b) { - return ((((long) b[7]) & 0xFF) + ((((long) b[6]) & 0xFF) << 8) + ((((long) b[5]) & 0xFF) << 16) - + ((((long) b[4]) & 0xFF) << 24) + ((((long) b[3]) & 0xFF) << 32) + ((((long) b[2]) & 0xFF) << 40) + return ((((long) b[7]) & 0xFF) + ((((long) b[6]) & 0xFF) << 8) + + ((((long) b[5]) & 0xFF) << 16) + + ((((long) b[4]) & 0xFF) << 24) + + ((((long) b[3]) & 0xFF) << 32) + + ((((long) b[2]) & 0xFF) << 40) + ((((long) b[1]) & 0xFF) << 48) + ((((long) b[0]) & 0xFF) << 56)); } } diff --git a/src/main/java/com/schooner/MemCached/TransBytecode.java b/src/main/java/com/schooner/MemCached/TransBytecode.java new file mode 100644 index 0000000..fad17a7 --- /dev/null +++ b/src/main/java/com/schooner/MemCached/TransBytecode.java @@ -0,0 +1,14 @@ +package com.schooner.MemCached; + +import java.io.Serializable; + +/** + * {@link TransBytecode} is used to translate the {@link Serializable} Object to + * String. + * + * @author xionghui + * + */ +public interface TransBytecode { + public String encode(Serializable origin); +} diff --git a/src/main/java/com/schooner/MemCached/command/StorageCommand.java b/src/main/java/com/schooner/MemCached/command/StorageCommand.java index 8e676aa..2e4ee08 100644 --- a/src/main/java/com/schooner/MemCached/command/StorageCommand.java +++ b/src/main/java/com/schooner/MemCached/command/StorageCommand.java @@ -1,9 +1,9 @@ /******************************************************************************* * Copyright (c) 2009 Schooner Information Technology, Inc. * All rights reserved. - * + * * http://www.schoonerinfotech.com/ - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -14,7 +14,7 @@ * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -29,6 +29,7 @@ package com.schooner.MemCached.command; import java.io.IOException; +import java.io.Serializable; import java.util.Arrays; import java.util.Date; @@ -44,7 +45,7 @@ /** * This command implements the set command using memcached UDP protocol. - * + * * @author Meng Li * @since 2.5.0 * @see com.schooner.Memcached.StorageCommand @@ -61,7 +62,7 @@ public class StorageCommand extends Command { private TransCoder transCoder = new ObjectTransCoder(); - private Object value; + private Serializable value; private int valLen = 0; @@ -72,28 +73,31 @@ public class StorageCommand extends Command { /** * set request textline: * "set [noreply]\r\n" - * + * */ - public StorageCommand(String cmdname, String key, Object value, Date expiry, Integer hashCode, Long casUnique) { + public StorageCommand(String cmdname, String key, Serializable value, + Date expiry, Integer hashCode, Long casUnique) { init(cmdname, key, value, expiry, hashCode, casUnique); } /** * set request textline: * "set [noreply]\r\n" - * + * */ - public StorageCommand(String cmdname, String key, Object value, Date expiry, Integer hashCode, Long casUnique, - TransCoder transCoder) { + public StorageCommand(String cmdname, String key, Serializable value, + Date expiry, Integer hashCode, Long casUnique, TransCoder transCoder) { init(cmdname, key, value, expiry, hashCode, casUnique); this.transCoder = transCoder; } - private void init(String cmdname, String key, Object value, Date expiry, Integer hashCode, Long casUnique) { + private void init(String cmdname, String key, Serializable value, + Date expiry, Integer hashCode, Long casUnique) { // store flags flags = NativeHandler.getMarkerFlag(value); // construct the command - String cmd = new StringBuffer().append(cmdname).append(" ").append(key).append(" ").append(flags).append(" ") + String cmd = new StringBuffer().append(cmdname).append(" ").append(key) + .append(" ").append(flags).append(" ") .append(expiry.getTime() / 1000).append(" ").toString(); textLine = cmd.getBytes(); @@ -132,6 +136,7 @@ private boolean writeDataBlock(SchoonerSockIO sock) throws IOException { return true; } + @Override public short request(SchoonerSockIO sock) throws IOException { short rid = sock.preWrite(); sock.writeBuf.put(textLine); @@ -139,8 +144,9 @@ public short request(SchoonerSockIO sock) throws IOException { offset = sock.writeBuf.position(); // write blank bytes size. sock.writeBuf.put(BLAND_DATA_SIZE); - if (casUnique != 0) + if (casUnique != 0) { sock.writeBuf.put((" " + casUnique.toString()).getBytes()); + } sock.writeBuf.put(B_RETURN); diff --git a/src/main/java/com/whalin/MemCached/ErrorHandler.java b/src/main/java/com/whalin/MemCached/ErrorHandler.java index 195be4b..52f3b22 100644 --- a/src/main/java/com/whalin/MemCached/ErrorHandler.java +++ b/src/main/java/com/whalin/MemCached/ErrorHandler.java @@ -23,9 +23,9 @@ /******************************************************************************* * Copyright (c) 2009 Schooner Information Technology, Inc. * All rights reserved. - * + * * http://www.schoonerinfotech.com/ - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,7 +36,7 @@ * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -50,51 +50,60 @@ ******************************************************************************/ package com.whalin.MemCached; +import java.io.Serializable; + /** * You can customize your error handle processes in this class. - * + * */ public interface ErrorHandler { /** * Called for errors thrown during initialization. */ - public void handleErrorOnInit(final MemCachedClient client, final Throwable error); + public void handleErrorOnInit(final MemCachedClient client, + final Throwable error); /** * Called for errors thrown during {@link MemCachedClient#get(String)} and * related methods. */ - public void handleErrorOnGet(final MemCachedClient client, final Throwable error, final String cacheKey); + public void handleErrorOnGet(final MemCachedClient client, + final Throwable error, final String cacheKey); /** * Called for errors thrown during {@link MemCachedClient#getMulti(String)} * and related methods. */ - public void handleErrorOnGet(final MemCachedClient client, final Throwable error, final String[] cacheKeys); + public void handleErrorOnGet(final MemCachedClient client, + final Throwable error, final Serializable[] cacheKeys); /** * Called for errors thrown during * {@link MemCachedClient#set(String,Object)} and related methods. */ - public void handleErrorOnSet(final MemCachedClient client, final Throwable error, final String cacheKey); + public void handleErrorOnSet(final MemCachedClient client, + final Throwable error, final String cacheKey); /** * Called for errors thrown during {@link MemCachedClient#delete(String)} * and related methods. */ - public void handleErrorOnDelete(final MemCachedClient client, final Throwable error, final String cacheKey); + public void handleErrorOnDelete(final MemCachedClient client, + final Throwable error, final String cacheKey); /** * Called for errors thrown during {@link MemCachedClient#flushAll()} and * related methods. */ - public void handleErrorOnFlush(final MemCachedClient client, final Throwable error); + public void handleErrorOnFlush(final MemCachedClient client, + final Throwable error); /** * Called for errors thrown during {@link MemCachedClient#stats()} and * related methods. */ - public void handleErrorOnStats(final MemCachedClient client, final Throwable error); + public void handleErrorOnStats(final MemCachedClient client, + final Throwable error); } // interface diff --git a/src/main/java/com/whalin/MemCached/MemCachedClient.java b/src/main/java/com/whalin/MemCached/MemCachedClient.java index a1f2ac2..0b1ef17 100755 --- a/src/main/java/com/whalin/MemCached/MemCachedClient.java +++ b/src/main/java/com/whalin/MemCached/MemCachedClient.java @@ -14,16 +14,16 @@ * You should have received a copy of the BSD License along with this * library. * - * @author Greg Whalin + * @author Greg Whalin * @version 2.0 */ /******************************************************************************* * Copyright (c) 2009 Schooner Information Technology, Inc. * All rights reserved. - * + * * http://www.schoonerinfotech.com/ - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,7 +34,7 @@ * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -48,6 +48,7 @@ ******************************************************************************/ package com.whalin.MemCached; +import java.io.Serializable; import java.util.Date; import java.util.Map; @@ -58,6 +59,7 @@ import com.schooner.MemCached.AscIIUDPClient; import com.schooner.MemCached.BinaryClient; import com.schooner.MemCached.MemcachedItem; +import com.schooner.MemCached.TransBytecode; import com.schooner.MemCached.TransCoder; /** @@ -69,68 +71,68 @@ * Here is an example to use schooner memcached client.
*
* Firstly, we should initialize the SockIOPool, which is a connection pool.
- * + * *

An example of initializing using defaults:

- * + * *
  * static {
  * 	String[] serverlist = { "server1.com:port", "server2.com:port" };
- * 
+ *
  * 	SockIOPool pool = SockIOPool.getInstance();
  * 	pool.setServers(serverlist);
  * 	pool.initialize();
  * }
  * 
- * + * *
* Then we can create the client object.
- * + * *

To create cache client object:

- * + * *
  * MemCachedClient mc = new MemCachedClient();
  * 
- * + * *

To store an object:

- * + * *
  * MemCachedClient mc = new MemCachedClient();
  * String key = "cacheKey1";
  * Object value = SomeClass.getObject();
  * mc.set(key, value);
  * 
- * + * *

To delete a cache entry:

- * + * *
  * MemCachedClient mc = new MemCachedClient();
  * String key = "cacheKey1";
  * mc.delete(key);
  * 
- * + * *

To retrieve an object from the cache:

- * + * *
  * MemCachedClient mc = new MemCachedClient();
  * String key = "key";
  * Object value = mc.get(key);
  * 
- * + * *

To retrieve an multiple objects from the cache

- * + * *
  * MemCachedClient mc = new MemCachedClient();
  * String[] keys = { "key", "key1", "key2" };
  * Map<Object> values = mc.getMulti(keys);
  * 
- * + * *

To flush all items in server(s)

- * + * *
  * MemCachedClient mc = new MemCachedClient();
  * mc.flushAll();
  * 
- * + * */ public class MemCachedClient { @@ -309,7 +311,7 @@ public MemCachedClient() { /** * Creates a new instance of MemCachedClient.
* Use binary protocol with TCP. - * + * * @param binaryProtocal * whether use binary protocol. */ @@ -320,7 +322,7 @@ public MemCachedClient(boolean binaryProtocal) { /** * Creates a new instance of MemCachedClient accepting a passed in pool * name. - * + * * @param poolName * name of SockIOPool */ @@ -331,7 +333,7 @@ public MemCachedClient(String poolName) { /** * Creates a new instance of MemCachedClient accepting a passed in pool * name. - * + * * @param poolName * name of SockIOPool * @param binaryProtocal @@ -343,7 +345,7 @@ public MemCachedClient(String poolName, boolean binaryProtocal) { /** * Create default memcached client. - * + * * @param isTCP * true - use tcp protocol
* false - use udp protocol @@ -356,7 +358,7 @@ public MemCachedClient(boolean isTCP, boolean binaryProtocal) { /** * Create memcached client. - * + * * @param poolName * name of SockIOPool * @param isTCP @@ -364,16 +366,19 @@ public MemCachedClient(boolean isTCP, boolean binaryProtocal) { * @param binaryProtocal * use binary protocol. */ - public MemCachedClient(String poolName, boolean isTcp, boolean binaryProtocal) { - if (binaryProtocal) + public MemCachedClient(String poolName, boolean isTcp, + boolean binaryProtocal) { + if (binaryProtocal) { client = new BinaryClient(poolName); - else - client = isTcp ? new AscIIClient(poolName) : new AscIIUDPClient(poolName); + } else { + client = isTcp ? new AscIIClient(poolName) : new AscIIUDPClient( + poolName); + } } /** * create memcached client. - * + * * @param poolName * pool name * @param isTcp @@ -389,17 +394,21 @@ public MemCachedClient(String poolName, boolean isTcp, boolean binaryProtocal) { * {@link com.schooner.MemCached.AbstractTransCoder} to achieve * the same objective. */ - public MemCachedClient(String poolName, boolean isTcp, boolean binaryProtocol, ClassLoader cl, ErrorHandler eh) { - if (binaryProtocol) + @Deprecated + public MemCachedClient(String poolName, boolean isTcp, + boolean binaryProtocol, ClassLoader cl, ErrorHandler eh) { + if (binaryProtocol) { client = new BinaryClient(poolName, cl, eh); - else - client = isTcp ? new AscIIClient(poolName, cl, eh) : new AscIIUDPClient(poolName, cl, eh); + } else { + client = isTcp ? new AscIIClient(poolName, cl, eh) + : new AscIIUDPClient(poolName, cl, eh); + } } /** * Creates a new instance of MemCacheClient but acceptes a passed in * ClassLoader. - * + * * @param classLoader * ClassLoader object. * @deprecated will be removed in next release.
@@ -408,6 +417,7 @@ public MemCachedClient(String poolName, boolean isTcp, boolean binaryProtocol, C * the same objective. */ + @Deprecated public MemCachedClient(ClassLoader classLoader) { this(); client.setClassLoader(classLoader); @@ -416,7 +426,7 @@ public MemCachedClient(ClassLoader classLoader) { /** * Creates a new instance of MemCacheClient but acceptes a passed in * ClassLoader and a passed in ErrorHandler. - * + * * @param classLoader * ClassLoader object. * @param errorHandler @@ -426,6 +436,7 @@ public MemCachedClient(ClassLoader classLoader) { * {@link com.schooner.MemCached.AbstractTransCoder} to achieve * the same objective. */ + @Deprecated public MemCachedClient(ClassLoader classLoader, ErrorHandler errorHandler) { this(null, true, false, classLoader, errorHandler); } @@ -433,7 +444,7 @@ public MemCachedClient(ClassLoader classLoader, ErrorHandler errorHandler) { /** * Creates a new instance of MemCacheClient but acceptes a passed in * ClassLoader, ErrorHandler, and SockIOPool name. - * + * * @param classLoader * ClassLoader object. * @param errorHandler @@ -446,31 +457,35 @@ public MemCachedClient(ClassLoader classLoader, ErrorHandler errorHandler) { * the same objective. */ - public MemCachedClient(ClassLoader classLoader, ErrorHandler errorHandler, String poolName) { + @Deprecated + public MemCachedClient(ClassLoader classLoader, ErrorHandler errorHandler, + String poolName) { this(poolName, true, false, classLoader, errorHandler); } /** * Sets an optional ClassLoader to be used for serialization. - * + * * @param classLoader * @deprecated will be removed in next release.
* Please use customized transcoder * {@link com.schooner.MemCached.AbstractTransCoder} to achieve * the same objective. */ + @Deprecated public void setClassLoader(ClassLoader classLoader) { throw new UnsupportedOperationException(); } /** * Sets an optional ErrorHandler. - * + * * @param errorHandler * @deprecated will be removed in next release. The purpose of adding this * support was to make it compatible with previous releases. */ + @Deprecated public void setErrorHandler(ErrorHandler errorHandler) { throw new UnsupportedOperationException(); } @@ -478,7 +493,7 @@ public void setErrorHandler(ErrorHandler errorHandler) { /** * Enable storing compressed data, provided it meets the threshold * requirements. - * + * * If enabled, data will be stored in compressed form if it is
* longer than the threshold length set with setCompressThreshold(int)
*
@@ -486,29 +501,31 @@ public void setErrorHandler(ErrorHandler errorHandler) { *
* Even if compression is disabled, compressed data will be automatically
* decompressed. - * + * * @param compressEnable * true to enable compression, false to * disable compression * @deprecated will be removed in next release. */ + @Deprecated public void setCompressEnable(boolean compressEnable) { throw new UnsupportedOperationException(); } /** * Sets the required length for data to be considered for compression. - * + * * If the length of the data to be stored is not equal or larger than this * value, it will not be compressed. - * + * * This defaults to 15 KB. - * + * * @param compressThreshold * required length of data to consider compression * @deprecated will be removed in next release. */ + @Deprecated public void setCompressThreshold(long compressThreshold) { throw new UnsupportedOperationException(); } @@ -516,7 +533,7 @@ public void setCompressThreshold(long compressThreshold) { /** * Sets default String encoding when storing primitives as Strings. Default * is UTF-8. - * + * * @param defaultEncoding */ public void setDefaultEncoding(String defaultEncoding) { @@ -525,7 +542,7 @@ public void setDefaultEncoding(String defaultEncoding) { /** * Enables storing primitive types as their String values. - * + * * @param primitiveAsString * if true, then store all primitives as their string value. */ @@ -535,7 +552,7 @@ public void setPrimitiveAsString(boolean primitiveAsString) { /** * Enables/disables sanitizing keys by URLEncoding. - * + * * @param sanitizeKeys * if true, then URLEncode all keys */ @@ -545,29 +562,29 @@ public void setSanitizeKeys(boolean sanitizeKeys) { /** * Checks to see if key exists in cache. - * + * * @param key * the key to look for * @return true if key found in cache, false if not (or if cache is down) */ - public boolean keyExists(String key) { + public boolean keyExists(Serializable key) { return client.keyExists(key); } /** * Deletes an object from cache given cache key. - * + * * @param key * the key to be removed * @return true, if the data was deleted successfully */ - public boolean delete(String key) { + public boolean delete(Serializable key) { return client.delete(key); } /** * Deletes an object from cache given cache key and expiration date. - * + * * @deprecated not supported in memcached 1.4+ * @param key * the key to be removed @@ -575,14 +592,15 @@ public boolean delete(String key) { * when to expire the record. * @return true, if the data was deleted successfully */ - public boolean delete(String key, Date expiry) { + @Deprecated + public boolean delete(Serializable key, Date expiry) { return client.delete(key, expiry); } /** * Deletes an object from cache given cache key, a delete time, and an * optional hashcode. - * + * * The item is immediately made non retrievable.
* Keep in mind {@link #add(String, Object) add} and * {@link #replace(String, Object) replace}
@@ -590,7 +608,7 @@ public boolean delete(String key, Date expiry) { * the
* specified time. However, {@link #set(String, Object) set} will succeed,
* and the new value will not be deleted. - * + * * @deprecated not supported in memcached 1.4+ * @param key * the key to be removed @@ -600,26 +618,27 @@ public boolean delete(String key, Date expiry) { * when to expire the record. * @return true, if the data was deleted successfully */ - public boolean delete(String key, Integer hashCode, Date expiry) { + @Deprecated + public boolean delete(Serializable key, Integer hashCode, Date expiry) { return client.delete(key, hashCode, expiry); } /** * Stores data on the server; only the key and the value are specified. - * + * * @param key * key to store data under * @param value * value to store * @return true, if the data was successfully stored */ - public boolean set(String key, Object value) { + public boolean set(Serializable key, Serializable value) { return client.set(key, value); } /** * Stores data on the server; only the key and the value are specified. - * + * * @param key * key to store data under * @param value @@ -628,14 +647,14 @@ public boolean set(String key, Object value) { * if not null, then the int hashcode to use * @return true, if the data was successfully stored */ - public boolean set(String key, Object value, Integer hashCode) { + public boolean set(Serializable key, Serializable value, Integer hashCode) { return client.set(key, value, hashCode); } /** * Stores data on the server; the key, value, and an expiration time are * specified. - * + * * @param key * key to store data under * @param value @@ -644,14 +663,14 @@ public boolean set(String key, Object value, Integer hashCode) { * when to expire the record * @return true, if the data was successfully stored */ - public boolean set(String key, Object value, Date expiry) { + public boolean set(Serializable key, Serializable value, Date expiry) { return client.set(key, value, expiry); } /** * Stores data on the server; the key, value, and an expiration time are * specified. - * + * * @param key * key to store data under * @param value @@ -662,14 +681,15 @@ public boolean set(String key, Object value, Date expiry) { * if not null, then the int hashcode to use * @return true, if the data was successfully stored */ - public boolean set(String key, Object value, Date expiry, Integer hashCode) { + public boolean set(Serializable key, Serializable value, Date expiry, + Integer hashCode) { return client.set(key, value, expiry, hashCode); } - + /** * Stores data on the server; the key, value, and an expiration time are * specified. - * + * * @param key * key to store data under * @param value @@ -682,27 +702,28 @@ public boolean set(String key, Object value, Date expiry, Integer hashCode) { * if true, then store all primitives as their string value * @return true, if the data was successfully stored */ - public boolean set(String key, Object value, Date expiry, Integer hashCode, boolean asString) { + public boolean set(Serializable key, Serializable value, Date expiry, + Integer hashCode, boolean asString) { return client.set(key, value, expiry, hashCode, asString); } /** * Adds data to the server; only the key and the value are specified. - * + * * @param key * key to store data under * @param value * value to store * @return true, if the data was successfully stored */ - public boolean add(String key, Object value) { + public boolean add(Serializable key, Serializable value) { return client.add(key, value); } /** * Adds data to the server; the key, value, and an optional hashcode are * passed in. - * + * * @param key * key to store data under * @param value @@ -711,14 +732,14 @@ public boolean add(String key, Object value) { * if not null, then the int hashcode to use * @return true, if the data was successfully stored */ - public boolean add(String key, Object value, Integer hashCode) { + public boolean add(Serializable key, Serializable value, Integer hashCode) { return client.add(key, value, hashCode); } /** * Adds data to the server; the key, value, and an expiration time are * specified. - * + * * @param key * key to store data under * @param value @@ -727,14 +748,14 @@ public boolean add(String key, Object value, Integer hashCode) { * when to expire the record * @return true, if the data was successfully stored */ - public boolean add(String key, Object value, Date expiry) { + public boolean add(Serializable key, Serializable value, Date expiry) { return client.add(key, value, expiry); } /** * Adds data to the server; the key, value, and an expiration time are * specified. - * + * * @param key * key to store data under * @param value @@ -745,27 +766,28 @@ public boolean add(String key, Object value, Date expiry) { * if not null, then the int hashcode to use * @return true, if the data was successfully stored */ - public boolean add(String key, Object value, Date expiry, Integer hashCode) { + public boolean add(Serializable key, Serializable value, Date expiry, + Integer hashCode) { return client.add(key, value, expiry, hashCode); } /** * Updates data on the server; only the key and the value are specified. - * + * * @param key * key to store data under * @param value * value to store * @return true, if the data was successfully stored */ - public boolean replace(String key, Object value) { + public boolean replace(Serializable key, Serializable value) { return client.replace(key, value); } /** * Updates data on the server; only the key and the value and an optional * hash are specified. - * + * * @param key * key to store data under * @param value @@ -774,14 +796,15 @@ public boolean replace(String key, Object value) { * if not null, then the int hashcode to use * @return true, if the data was successfully stored */ - public boolean replace(String key, Object value, Integer hashCode) { + public boolean replace(Serializable key, Serializable value, + Integer hashCode) { return client.replace(key, value, hashCode); } /** * Updates data on the server; the key, value, and an expiration time are * specified. - * + * * @param key * key to store data under * @param value @@ -790,14 +813,14 @@ public boolean replace(String key, Object value, Integer hashCode) { * when to expire the record * @return true, if the data was successfully stored */ - public boolean replace(String key, Object value, Date expiry) { + public boolean replace(Serializable key, Serializable value, Date expiry) { return client.replace(key, value, expiry); } /** * Updates data on the server; the key, value, and an expiration time are * specified. - * + * * @param key * key to store data under * @param value @@ -808,26 +831,27 @@ public boolean replace(String key, Object value, Date expiry) { * if not null, then the int hashcode to use * @return true, if the data was successfully stored */ - public boolean replace(String key, Object value, Date expiry, Integer hashCode) { + public boolean replace(Serializable key, Serializable value, Date expiry, + Integer hashCode) { return client.replace(key, value, expiry, hashCode); } /** * Store a counter to memcached given a key - * + * * @param key * cache key * @param counter * number to store * @return true/false indicating success */ - public boolean storeCounter(String key, Long counter) { + public boolean storeCounter(Serializable key, Long counter) { return storeCounter(key, counter, null, null); } /** * Store a counter to memcached given a key - * + * * @param key * cache key * @param counter @@ -836,13 +860,13 @@ public boolean storeCounter(String key, Long counter) { * when to expire the record * @return true/false indicating success */ - public boolean storeCounter(String key, Long counter, Date date) { + public boolean storeCounter(Serializable key, Long counter, Date date) { return storeCounter(key, counter, date, null); } /** * Store a counter to memcached given a key - * + * * @param key * cache key * @param counter @@ -853,13 +877,14 @@ public boolean storeCounter(String key, Long counter, Date date) { * if not null, then the int hashcode to use * @return true/false indicating success */ - public boolean storeCounter(String key, Long counter, Date date, Integer hashCode) { + public boolean storeCounter(Serializable key, Long counter, Date date, + Integer hashCode) { return set(key, counter, date, hashCode, true); } /** * Store a counter to memcached given a key - * + * * @param key * cache key * @param counter @@ -868,35 +893,36 @@ public boolean storeCounter(String key, Long counter, Date date, Integer hashCod * if not null, then the int hashcode to use * @return true/false indicating success */ - public boolean storeCounter(String key, Long counter, Integer hashCode) { + public boolean storeCounter(Serializable key, Long counter, Integer hashCode) { return storeCounter(key, counter, null, hashCode); } /** * Returns value in counter at given key as long. - * + * * @param key * cache ket * @return counter value or -1 if not found */ - public long getCounter(String key) { + public long getCounter(Serializable key) { return getCounter(key, null); } /** * Returns value in counter at given key as long. - * + * * @param key * cache ket * @param hashCode * if not null, then the int hashcode to use * @return counter value or -1 if not found */ - public long getCounter(String key, Integer hashCode) { + public long getCounter(Serializable key, Integer hashCode) { if (key == null) { - if (log.isErrorEnabled()) + if (log.isErrorEnabled()) { log.error("null key for getCounter()"); + } return -1; } @@ -906,12 +932,15 @@ public long getCounter(String key, Integer hashCode) { } catch (Exception ex) { // if we have an errorHandler, use its hook - if (errorHandler != null) - errorHandler.handleErrorOnGet(this, ex, key); + if (errorHandler != null) { + errorHandler.handleErrorOnGet(this, ex, key.toString()); + } // not found or error getting out - if (log.isDebugEnabled()) - log.info(String.format("Failed to parse Long value for key: %s", key)); + if (log.isDebugEnabled()) { + log.info(String.format( + "Failed to parse Long value for key: %s", key)); + } } return counter; @@ -919,31 +948,31 @@ public long getCounter(String key, Integer hashCode) { /** * Thread safe way to initialize and increment a counter. - * + * * @param key * key where the data is stored * @return value of incrementer */ - public long addOrIncr(String key) { + public long addOrIncr(Serializable key) { return client.addOrIncr(key); } /** * Thread safe way to initialize and increment a counter. - * + * * @param key * key where the data is stored * @param inc * value to set or increment by * @return value of incrementer */ - public long addOrIncr(String key, long inc) { + public long addOrIncr(Serializable key, long inc) { return client.addOrIncr(key, inc); } /** * Thread safe way to initialize and increment a counter. - * + * * @param key * key where the data is stored * @param inc @@ -952,37 +981,37 @@ public long addOrIncr(String key, long inc) { * if not null, then the int hashcode to use * @return value of incrementer */ - public long addOrIncr(String key, long inc, Integer hashCode) { + public long addOrIncr(Serializable key, long inc, Integer hashCode) { return client.addOrIncr(key, inc, hashCode); } /** * Thread safe way to initialize and decrement a counter. - * + * * @param key * key where the data is stored * @return value of incrementer */ - public long addOrDecr(String key) { + public long addOrDecr(Serializable key) { return client.addOrDecr(key); } /** * Thread safe way to initialize and decrement a counter. - * + * * @param key * key where the data is stored * @param inc * value to set or increment by * @return value of incrementer */ - public long addOrDecr(String key, long inc) { + public long addOrDecr(Serializable key, long inc) { return client.addOrDecr(key, inc); } /** * Thread safe way to initialize and decrement a counter. - * + * * @param key * key where the data is stored * @param inc @@ -991,7 +1020,7 @@ public long addOrDecr(String key, long inc) { * if not null, then the int hashcode to use * @return value of incrementer */ - public long addOrDecr(String key, long inc, Integer hashCode) { + public long addOrDecr(Serializable key, long inc, Integer hashCode) { return client.addOrDecr(key, inc, hashCode); } @@ -999,13 +1028,13 @@ public long addOrDecr(String key, long inc, Integer hashCode) { * Increment the value at the specified key by 1, and then return it.
* Please make sure setPrimitiveAsString=true if the key/value pair is * stored with set command. - * + * * @param key * key where the data is stored * @return -1, if the key is not found, the value after incrementing * otherwise */ - public long incr(String key) { + public long incr(Serializable key) { return client.incr(key); } @@ -1013,7 +1042,7 @@ public long incr(String key) { * Increment the value at the specified key by passed in val.
* Please make sure setPrimitiveAsString=true if the key/value pair is * stored with set command. - * + * * @param key * key where the data is stored * @param inc @@ -1021,7 +1050,7 @@ public long incr(String key) { * @return -1, if the key is not found, the value after incrementing * otherwise */ - public long incr(String key, long inc) { + public long incr(Serializable key, long inc) { return client.incr(key, inc); } @@ -1030,7 +1059,7 @@ public long incr(String key, long inc) { * then return it.
* Please make sure setPrimitiveAsString=true if the key/value pair is * stored with set command. - * + * * @param key * key where the data is stored * @param inc @@ -1040,7 +1069,7 @@ public long incr(String key, long inc) { * @return -1, if the key is not found, the value after incrementing * otherwise */ - public long incr(String key, long inc, Integer hashCode) { + public long incr(Serializable key, long inc, Integer hashCode) { return client.incr(key, inc, hashCode); } @@ -1048,13 +1077,13 @@ public long incr(String key, long inc, Integer hashCode) { * Decrement the value at the specified key by 1, and then return it.
* Please make sure setPrimitiveAsString=true if the key/value pair is * stored with set command. - * + * * @param key * key where the data is stored * @return -1, if the key is not found, the value after incrementing * otherwise */ - public long decr(String key) { + public long decr(Serializable key) { return client.decr(key); } @@ -1063,7 +1092,7 @@ public long decr(String key) { * return it.
* Please make sure setPrimitiveAsString=true if the key/value pair is * stored with set command. - * + * * @param key * key where the data is stored * @param inc @@ -1071,7 +1100,7 @@ public long decr(String key) { * @return -1, if the key is not found, the value after incrementing * otherwise */ - public long decr(String key, long inc) { + public long decr(Serializable key, long inc) { return client.decr(key, inc); } @@ -1080,7 +1109,7 @@ public long decr(String key, long inc) { * then return it.
* Please make sure setPrimitiveAsString=true if the key/value pair is * stored with set command. - * + * * @param key * key where the data is stored * @param inc @@ -1090,13 +1119,13 @@ public long decr(String key, long inc) { * @return -1, if the key is not found, the value after incrementing * otherwise */ - public long decr(String key, long inc, Integer hashCode) { + public long decr(Serializable key, long inc, Integer hashCode) { return client.decr(key, inc, hashCode); } /** * Retrieve a key from the server, using a specific hash. - * + * * If the data was compressed or serialized when compressed, it will * automatically
* be decompressed or serialized, as appropriate. (Inclusive or)
@@ -1104,19 +1133,19 @@ public long decr(String key, long inc, Integer hashCode) { * Non-serialized data will be returned as a string, so explicit conversion * to
* numeric types will be necessary, if desired
- * + * * @param key * key where data is stored * @return the object that was previously stored, or null if it was not * previously stored */ - public Object get(String key) { + public Object get(Serializable key) { return client.get(key); } /** * Retrieve a key from the server, using a specific hash. - * + * * If the data was compressed or serialized when compressed, it will * automatically
* be decompressed or serialized, as appropriate. (Inclusive or)
@@ -1124,7 +1153,7 @@ public Object get(String key) { * Non-serialized data will be returned as a string, so explicit conversion * to
* numeric types will be necessary, if desired
- * + * * @param key * key where data is stored * @param hashCode @@ -1132,25 +1161,29 @@ public Object get(String key) { * @return the object that was previously stored, or null if it was not * previously stored */ - public Object get(String key, Integer hashCode) { + public Object get(Serializable key, Integer hashCode) { return client.get(key, hashCode); } - public MemcachedItem gets(String key) { + public MemcachedItem gets(Serializable key) { return client.gets(key); } - public MemcachedItem gets(String key, Integer hashCode) { + public MemcachedItem gets(Serializable key, Integer hashCode) { return client.gets(key, hashCode); } + public void setKeyTransCoder(TransBytecode transCoder) { + client.setKeyTransCoder(transCoder); + } + public void setTransCoder(TransCoder transCoder) { client.setTransCoder(transCoder); } /** * Retrieve a key from the server, using a specific hash. - * + * * If the data was compressed or serialized when compressed, it will * automatically
* be decompressed or serialized, as appropriate. (Inclusive or)
@@ -1158,7 +1191,7 @@ public void setTransCoder(TransCoder transCoder) { * Non-serialized data will be returned as a string, so explicit conversion * to
* numeric types will be necessary, if desired
- * + * * @param key * key where data is stored * @param hashCode @@ -1168,33 +1201,33 @@ public void setTransCoder(TransCoder transCoder) { * @return the object that was previously stored, or null if it was not * previously stored */ - public Object get(String key, Integer hashCode, boolean asString) { + public Object get(Serializable key, Integer hashCode, boolean asString) { return client.get(key, hashCode, asString); } /** * Retrieve multiple objects from the memcache. - * + * * This is recommended over repeated calls to {@link #get(String) get()}, * since it
* is more efficient.
- * + * * @param keys * String array of keys to retrieve * @return Object array ordered in same order as key array containing * results */ - public Object[] getMultiArray(String[] keys) { + public Object[] getMultiArray(Serializable[] keys) { return client.getMultiArray(keys); } /** * Retrieve multiple objects from the memcache. - * + * * This is recommended over repeated calls to {@link #get(String) get()}, * since it
* is more efficient.
- * + * * @param keys * String array of keys to retrieve * @param hashCodes @@ -1202,17 +1235,17 @@ public Object[] getMultiArray(String[] keys) { * @return Object array ordered in same order as key array containing * results */ - public Object[] getMultiArray(String[] keys, Integer[] hashCodes) { + public Object[] getMultiArray(Serializable[] keys, Integer[] hashCodes) { return client.getMultiArray(keys, hashCodes); } /** * Retrieve multiple objects from the memcache. - * + * * This is recommended over repeated calls to {@link #get(String) get()}, * since it
* is more efficient.
- * + * * @param keys * String array of keys to retrieve * @param hashCodes @@ -1222,34 +1255,35 @@ public Object[] getMultiArray(String[] keys, Integer[] hashCodes) { * @return Object array ordered in same order as key array containing * results */ - public Object[] getMultiArray(String[] keys, Integer[] hashCodes, boolean asString) { + public Object[] getMultiArray(Serializable[] keys, Integer[] hashCodes, + boolean asString) { return client.getMultiArray(keys, hashCodes, asString); } /** * Retrieve multiple objects from the memcache. - * + * * This is recommended over repeated calls to {@link #get(String) get()}, * since it
* is more efficient.
- * + * * @param keys * String array of keys to retrieve * @return a hashmap with entries for each key is found by the server, keys * that are not found are not entered into the hashmap, but * attempting to retrieve them from the hashmap gives you null. */ - public Map getMulti(String[] keys) { + public Map getMulti(Serializable[] keys) { return getMulti(keys, null); } /** * Retrieve multiple keys from the memcache. - * + * * This is recommended over repeated calls to {@link #get(String) get()}, * since it
* is more efficient.
- * + * * @param keys * keys to retrieve * @param hashCodes @@ -1258,17 +1292,18 @@ public Map getMulti(String[] keys) { * that are not found are not entered into the hashmap, but * attempting to retrieve them from the hashmap gives you null. */ - public Map getMulti(String[] keys, Integer[] hashCodes) { + public Map getMulti(Serializable[] keys, + Integer[] hashCodes) { return client.getMulti(keys, hashCodes); } /** * Retrieve multiple keys from the memcache. - * + * * This is recommended over repeated calls to {@link #get(String) get()}, * since it
* is more efficient.
- * + * * @param keys * keys to retrieve * @param hashCodes @@ -1279,15 +1314,16 @@ public Map getMulti(String[] keys, Integer[] hashCodes) { * that are not found are not entered into the hashmap, but * attempting to retrieve them from the hashmap gives you null. */ - public Map getMulti(String[] keys, Integer[] hashCodes, boolean asString) { + public Map getMulti(Serializable[] keys, + Integer[] hashCodes, boolean asString) { return client.getMulti(keys, hashCodes, asString); } /** * Invalidates the entire cache. - * + * * Will return true only if succeeds in clearing all servers. - * + * * @return success true/false */ public boolean flushAll() { @@ -1296,10 +1332,10 @@ public boolean flushAll() { /** * Invalidates the entire cache. - * + * * Will return true only if succeeds in clearing all servers. If pass in * null, then will try to flush all servers. - * + * * @param servers * optional array of host(s) to flush (host:port) * @return success true/false @@ -1310,10 +1346,10 @@ public boolean flushAll(String[] servers) { /** * Retrieves stats for all servers. - * + * * Returns a map keyed on the servername. The value is another map which * contains stats with stat name as key and value as value. - * + * * @return Stats map */ public Map> stats() { @@ -1322,10 +1358,10 @@ public Map> stats() { /** * Retrieves stats for passed in servers (or all servers). - * + * * Returns a map keyed on the servername. The value is another map which * contains stats with stat name as key and value as value. - * + * * @param servers * string array of servers to retrieve stats from, or all if this * is null @@ -1337,10 +1373,10 @@ public Map> stats(String[] servers) { /** * Retrieves stats items for all servers. - * + * * Returns a map keyed on the servername. The value is another map which * contains item stats with itemname:number:field as key and value as value. - * + * * @return Stats map */ public Map> statsItems() { @@ -1349,10 +1385,10 @@ public Map> statsItems() { /** * Retrieves stats for passed in servers (or all servers). - * + * * Returns a map keyed on the servername. The value is another map which * contains item stats with itemname:number:field as key and value as value. - * + * * @param servers * string array of servers to retrieve stats from, or all if this * is null @@ -1364,10 +1400,10 @@ public Map> statsItems(String[] servers) { /** * Retrieves stats items for all servers. - * + * * Returns a map keyed on the servername. The value is another map which * contains slabs stats with slabnumber:field as key and value as value. - * + * * @return Stats map */ public Map> statsSlabs() { @@ -1376,10 +1412,10 @@ public Map> statsSlabs() { /** * Retrieves stats for passed in servers (or all servers). - * + * * Returns a map keyed on the servername. The value is another map which * contains slabs stats with slabnumber:field as key and value as value. - * + * * @param servers * string array of servers to retrieve stats from, or all if this * is null @@ -1391,26 +1427,27 @@ public Map> statsSlabs(String[] servers) { /** * Retrieves items cachedump for all servers. - * + * * Returns a map keyed on the servername. The value is another map which * contains cachedump stats with the cachekey as key and byte size and unix * timestamp as value. - * + * * @param slabNumber * the item number of the cache dump * @return Stats map */ - public Map> statsCacheDump(int slabNumber, int limit) { + public Map> statsCacheDump(int slabNumber, + int limit) { return client.statsCacheDump(slabNumber, limit); } /** * Retrieves stats for passed in servers (or all servers). - * + * * Returns a map keyed on the servername. The value is another map which * contains cachedump stats with the cachekey as key and byte size and unix * timestamp as value. - * + * * @param servers * string array of servers to retrieve stats from, or all if this * is null @@ -1418,15 +1455,16 @@ public Map> statsCacheDump(int slabNumber, int limit * the item number of the cache dump * @return Stats map */ - public Map> statsCacheDump(String[] servers, int slabNumber, int limit) { + public Map> statsCacheDump(String[] servers, + int slabNumber, int limit) { return client.statsCacheDump(servers, slabNumber, limit); } - public boolean sync(String key, Integer hashCode) { + public boolean sync(Serializable key, Integer hashCode) { return client.sync(key, hashCode); } - public boolean sync(String key) { + public boolean sync(Serializable key) { return client.sync(key); } @@ -1438,35 +1476,39 @@ public boolean syncAll(String[] servers) { return client.syncAll(servers); } - public boolean append(String key, Object value, Integer hashCode) { + public boolean append(Serializable key, Serializable value, Integer hashCode) { return client.append(key, value, hashCode); } - public boolean append(String key, Object value) { + public boolean append(Serializable key, Serializable value) { return client.append(key, value); } - public boolean cas(String key, Object value, Integer hashCode, long casUnique) { + public boolean cas(Serializable key, Serializable value, Integer hashCode, + long casUnique) { return client.cas(key, value, hashCode, casUnique); } - public boolean cas(String key, Object value, Date expiry, long casUnique) { + public boolean cas(Serializable key, Serializable value, Date expiry, + long casUnique) { return client.cas(key, value, expiry, casUnique); } - public boolean cas(String key, Object value, Date expiry, Integer hashCode, long casUnique) { + public boolean cas(Serializable key, Serializable value, Date expiry, + Integer hashCode, long casUnique) { return client.cas(key, value, expiry, hashCode, casUnique); } - public boolean cas(String key, Object value, long casUnique) { + public boolean cas(Serializable key, Serializable value, long casUnique) { return client.cas(key, value, casUnique); } - public boolean prepend(String key, Object value, Integer hashCode) { + public boolean prepend(Serializable key, Serializable value, + Integer hashCode) { return client.prepend(key, value, hashCode); } - public boolean prepend(String key, Object value) { + public boolean prepend(Serializable key, Serializable value) { return client.prepend(key, value); } } diff --git a/src/test/java/com/schooner/MemCached/MemCachedBenchBinaryKey.java b/src/test/java/com/schooner/MemCached/MemCachedBenchBinaryKey.java new file mode 100644 index 0000000..74b9ab1 --- /dev/null +++ b/src/test/java/com/schooner/MemCached/MemCachedBenchBinaryKey.java @@ -0,0 +1,10 @@ +package com.schooner.MemCached; + +public class MemCachedBenchBinaryKey extends MemCachedBenchTcpKey { + protected String FILE_URL = "spring-memcached-Binary.xml"; + + @Override + public String getFileUrl() { + return FILE_URL; + } +} diff --git a/src/test/java/com/schooner/MemCached/MemCachedBenchTcpKey.java b/src/test/java/com/schooner/MemCached/MemCachedBenchTcpKey.java new file mode 100644 index 0000000..a130c08 --- /dev/null +++ b/src/test/java/com/schooner/MemCached/MemCachedBenchTcpKey.java @@ -0,0 +1,262 @@ +package com.schooner.MemCached; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.Serializable; +import java.util.Calendar; +import java.util.Date; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import junit.framework.TestCase; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import com.whalin.MemCached.MemCachedClient; + +public class MemCachedBenchTcpKey extends TestCase { + private static final String FILE_URL = "spring-memcached-TCP.xml"; + + private static final String BEAN_NAME = "memcachedClient"; + + private ClassPathXmlApplicationContext context; + + public String getFileUrl() { + return FILE_URL; + } + + @Override + public void setUp() { + String fileUrl = this.getFileUrl(); + context = new ClassPathXmlApplicationContext(fileUrl); + MemCachedClient memcachedClient = getClient(); + memcachedClient.flushAll(); + } + + public void testStringKey() { + System.out.println("-----test string key begin-----"); + MemCachedClient memcachedClient = getClient(); + memcachedClient.set("test", "test"); + System.out.println(memcachedClient.get(new String("test"))); + System.out.println("-----test string key end-----"); + } + + public void testStringBuilderKey() { + System.out.println("-----test stringbuilder key begin-----"); + MemCachedClient memcachedClient = getClient(); + StringBuilder builder = new StringBuilder("test"); + memcachedClient.set(builder, "test"); + builder = new StringBuilder("test"); + System.out.println(memcachedClient.get(builder)); + System.out.println("-----test stringbuilder key end-----"); + } + + public void testStringBufferKey() { + System.out.println("-----test stringbuffer key begin-----"); + MemCachedClient memcachedClient = getClient(); + StringBuffer buffer = new StringBuffer("test"); + memcachedClient.set(buffer, "test"); + buffer = new StringBuffer("test"); + System.out.println(memcachedClient.get(buffer)); + System.out.println("-----test stringbuffer key end-----"); + } + + public void testBooleanKey() { + System.out.println("-----test Boolean key begin-----"); + MemCachedClient memcachedClient = getClient(); + memcachedClient.set(true, "test"); + Boolean b = true; + System.out.println(memcachedClient.get(b)); + System.out.println("-----test Boolean key end-----"); + } + + public void testByteKey() { + System.out.println("-----test byte key begin-----"); + MemCachedClient memcachedClient = getClient(); + memcachedClient.set((byte) 1, "test"); + Byte b = 1; + System.out.println(memcachedClient.get(b)); + System.out.println("-----test byte key end-----"); + } + + public void testShortKey() { + System.out.println("-----test Short key begin-----"); + MemCachedClient memcachedClient = getClient(); + memcachedClient.set((short) 1, "test"); + Short s = 1; + System.out.println(memcachedClient.get(s)); + System.out.println("-----test Short key end-----"); + } + + public void testCharacterKey() { + System.out.println("-----test Character key begin-----"); + MemCachedClient memcachedClient = getClient(); + memcachedClient.set('c', "test"); + Character c = 'c'; + System.out.println(memcachedClient.get(c)); + System.out.println("-----test Character key end-----"); + } + + public void testIntegerKey() { + System.out.println("-----test Integer key begin-----"); + MemCachedClient memcachedClient = getClient(); + memcachedClient.set(1, "test"); + Integer i = 1; + System.out.println(memcachedClient.get(i)); + System.out.println("-----test Integer key end-----"); + } + + public void testLongKey() { + System.out.println("-----test Long key begin-----"); + MemCachedClient memcachedClient = getClient(); + memcachedClient.set(1L, "test"); + Long lg = 1L; + System.out.println(memcachedClient.get(lg)); + System.out.println("-----test Long key end-----"); + } + + public void testFloatKey() { + System.out.println("-----test Float key begin-----"); + MemCachedClient memcachedClient = getClient(); + memcachedClient.set(1.0F, "test"); + Float f = 1.0F; + System.out.println(memcachedClient.get(f)); + System.out.println("-----test Float key end-----"); + } + + public void testDoubleKey() { + System.out.println("-----test Double key begin-----"); + MemCachedClient memcachedClient = getClient(); + memcachedClient.set(1.0, "test"); + Double d = 1.0; + System.out.println(memcachedClient.get(d)); + System.out.println("-----test Double key end-----"); + } + + public void testDateKey() { + System.out.println("-----test array key begin-----"); + MemCachedClient memcachedClient = getClient(); + Date date = Calendar.getInstance().getTime(); + memcachedClient.set(date, "test"); + System.out.println(memcachedClient.get(date)); + System.out.println("-----test array key end-----"); + } + + public void testArrayKey() { + System.out.println("-----test array key begin-----"); + MemCachedClient memcachedClient = getClient(); + User[] array = new User[10]; + memcachedClient.set(array, "test"); + array = new User[10]; + System.out.println(memcachedClient.get(array)); + System.out.println("-----test array key end-----"); + } + + public void testSerializableKey() { + System.out.println("-----test Serializable key begin-----"); + MemCachedClient memcachedClient = getClient(); + SUser user = new SUser("test"); + memcachedClient.set(user, "test"); + user = new SUser("test"); + System.out.println(memcachedClient.get(user)); + System.out.println("-----test Serializabl key end-----"); + } + + public void testExternalizableKey() { + System.out.println("-----test Externalizable key begin-----"); + MemCachedClient memcachedClient = getClient(); + EUser user = new EUser("test"); + memcachedClient.set(user, "test"); + user = new EUser("test"); + System.out.println(memcachedClient.get(user)); + System.out.println("-----test Externalizable key end-----"); + } + + private MemCachedClient getClient() { + MemCachedClient memcachedClient = (MemCachedClient) context + .getBean(BEAN_NAME); + return memcachedClient; + } + + @Override + public void tearDown() { + MemCachedClient memcachedClient = getClient(); + showKeys(memcachedClient); + memcachedClient.flushAll(); + if (context != null) { + context.close(); + } + } + + private static void showKeys(MemCachedClient memcachedClient) { + System.out.println("----show keys begin-----"); + Map> map = memcachedClient.statsItems(); + Set set = new HashSet(); + for (Map m : map.values()) { + for (String s : m.keySet()) { + int first = s.indexOf(":"); + int second = s.indexOf(":", first + 1); + set.add(s.substring(first + 1, second)); + } + } + Set keySet = new HashSet(); + for (String s : set) { + int slab = Integer.valueOf(s); + Map> dumpMap = memcachedClient + .statsCacheDump(slab, 0); + for (Map m : dumpMap.values()) { + keySet.addAll(m.keySet()); + } + } + System.out.println(keySet); + System.out.println("-----show keys end-----"); + System.out.println(); + } + + private static class User { + } + + private static class SUser implements Serializable { + private static final long serialVersionUID = -1921923046163600659L; + + private String name; + + SUser(String name) { + this.name = name; + } + + @Override + public String toString() { + return "hashcode:" + this.hashCode() + " name:" + name; + } + } + + private static class EUser implements Externalizable { + private static final long serialVersionUID = 8674506162535178907L; + + private String name; + + EUser(String name) { + this.name = name; + } + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(name); + } + + @Override + public void readExternal(ObjectInput in) throws IOException, + ClassNotFoundException { + name = (String) in.readObject(); + } + + @Override + public String toString() { + return "hashcode:" + this.hashCode() + " name:" + name; + } + } +} diff --git a/src/test/java/com/schooner/MemCached/MemCachedBenchUdpKey.java b/src/test/java/com/schooner/MemCached/MemCachedBenchUdpKey.java new file mode 100644 index 0000000..fa65bc8 --- /dev/null +++ b/src/test/java/com/schooner/MemCached/MemCachedBenchUdpKey.java @@ -0,0 +1,10 @@ +package com.schooner.MemCached; + +public class MemCachedBenchUdpKey extends MemCachedBenchTcpKey { + protected String FILE_URL = "spring-memcached-UDP.xml"; + + @Override + public String getFileUrl() { + return FILE_URL; + } +} diff --git a/src/test/java/com/schooner/MemCached/MemCachedClientAsciiTest.java b/src/test/java/com/schooner/MemCached/MemCachedClientAsciiTest.java index ba40a24..6846ac2 100755 --- a/src/test/java/com/schooner/MemCached/MemCachedClientAsciiTest.java +++ b/src/test/java/com/schooner/MemCached/MemCachedClientAsciiTest.java @@ -1,9 +1,9 @@ /******************************************************************************* * Copyright (c) 2009 Schooner Information Technology, Inc. * All rights reserved. - * + * * http://www.schoonerinfotech.com/ - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -14,7 +14,7 @@ * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -68,13 +68,15 @@ private static synchronized String initString(int len) { private MemCacheDaemon daemon = null; + @Override protected void setUp() throws Exception { String servers = System.getProperty("memcached.host"); if (servers == null) { // create daemon and start it daemon = new MemCacheDaemon(); - CacheStorage storage = ConcurrentLinkedHashMap.create( - ConcurrentLinkedHashMap.EvictionPolicy.FIFO, 100000, 5 * 1024 * 1024); + CacheStorage storage = ConcurrentLinkedHashMap + .create(ConcurrentLinkedHashMap.EvictionPolicy.FIFO, + 100000, 5 * 1024 * 1024); daemon.setCache(new CacheImpl(storage)); daemon.setBinary(false); daemon.setAddr(new InetSocketAddress(11211)); @@ -91,6 +93,7 @@ protected void setUp() throws Exception { mc = new MemCachedClient("test"); } + @Override protected void tearDown() throws Exception { super.tearDown(); mc.flushAll(); @@ -269,8 +272,8 @@ public void testIncr() { long j = mc.addOrIncr("foo", i); // now == 0 assertEquals(mc.get("foo"), new Long(i).toString()); j = mc.incr("foo"); // foo now == 1 - j = mc.incr("foo", (long) 5); // foo now == 6 - j = mc.decr("foo", (long) 2); // foo now == 4 + j = mc.incr("foo", 5); // foo now == 6 + j = mc.decr("foo", 2); // foo now == 4 assertEquals(4, j); j = mc.incr("foo1"); assertEquals(-1, j); @@ -318,11 +321,11 @@ public void testAddOrIncr() { j = mc.addOrIncr("foo"); // foo now == 0 assertEquals(0, j); j = mc.incr("foo"); // foo now == 1 - j = mc.incr("foo", (long) 5); // foo now == 6 + j = mc.incr("foo", 5); // foo now == 6 j = mc.addOrIncr("foo", 1); // foo now 7 - j = mc.decr("foo", (long) 3); // foo now == 4 + j = mc.decr("foo", 3); // foo now == 4 assertEquals(4, j); } @@ -383,7 +386,7 @@ public void testGetMulti() { mc.set(keys[i], "value" + i); } - Map results = mc.getMulti(keys); + Map results = mc.getMulti(keys); for (int i = 0; i < max; i++) { assertEquals(results.get(keys[i]), "value" + i); } @@ -430,8 +433,9 @@ public void testGets() { public void testSetByteArray() { byte[] b = new byte[10]; - for (int i = 0; i < 10; i++) + for (int i = 0; i < 10; i++) { b[i] = (byte) i; + } mc.set("foo", b); assertTrue(Arrays.equals((byte[]) mc.get("foo"), b)); @@ -447,13 +451,15 @@ public void testSetObj() { public void testCusTransCoder() { TransCoder coder = new ObjectTransCoder() { @Override - public void encode(OutputStream out, Object object) throws IOException { + public void encode(OutputStream out, Object object) + throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); ObjectOutputStream oOut = new ObjectOutputStream(bOut); oOut.writeObject(object); byte[] bytes = bOut.toByteArray(); - for (byte b : bytes) + for (byte b : bytes) { out.write(b); + } } }; mc.setTransCoder(coder); @@ -493,14 +499,15 @@ public void testSetStringObjectInteger() { public void testMultiKey() { - String[] allKeys = { "key1", "key2", "key3", "key4", "key5", "key6", "key7" }; + String[] allKeys = { "key1", "key2", "key3", "key4", "key5", "key6", + "key7" }; String[] setKeys = { "key1", "key3", "key5", "key7" }; for (String key : setKeys) { mc.set(key, key); } - Map results = mc.getMulti(allKeys); + Map results = mc.getMulti(allKeys); assert allKeys.length == results.size(); for (String key : setKeys) { @@ -654,60 +661,61 @@ public void testPrependStringObjectInteger() { * assertEquals("bb", item.getValue()); mc.set("aa", "cc"); * assertEquals("cc", mc.get("aa")); mc.cas("aa", "dd", * item.getCasUnique()); assertEquals("cc", mc.get("aa")); } - * + * * public void testCasStringObjectIntegerLong() { String expected, actual; * mc.set("foo", "bar", 10); MemcachedItem item = mc.gets("foo", 10); * expected = "bar"; actual = (String) item.getValue(); * assertEquals(expected, actual); - * + * * mc.cas("foo", "bar1", 10, item.getCasUnique()); expected = "bar1"; actual * = (String) mc.get("foo", 10); assertEquals(expected, actual); - * + * * mc.set("foo", "bar2", 10); expected = "bar2"; actual = (String) * mc.get("foo", 10); assertEquals(expected, actual); - * + * * boolean res = mc.cas("foo", "bar3", 10, item.getCasUnique()); * assertFalse(res); } - * + * * public void testCasStringObjectDateLong() { String expected, actual; * mc.set("foo", "bar"); MemcachedItem item = mc.gets("foo"); expected = * "bar"; actual = (String) item.getValue(); assertEquals(expected, actual); - * + * * Date expiry = new Date(1000); mc.cas("foo", "bar1", expiry, * item.getCasUnique()); expected = "bar1"; actual = (String) mc.get("foo"); * assertEquals(expected, actual); - * + * * try { Thread.sleep(2000); } catch (InterruptedException e) { * e.printStackTrace(); } assertNull(mc.get("foo")); - * + * * mc.set("foo", "bar2"); expected = "bar2"; actual = (String) * mc.get("foo"); assertEquals(expected, actual); - * + * * boolean res = mc.cas("foo", "bar3", expiry, item.getCasUnique()); * assertFalse(res); } - * + * * public void testCasStringObjectDateIntegerLong() { String expected, * actual; mc.set("foo", "bar", 10); MemcachedItem item = mc.gets("foo", * 10); expected = "bar"; actual = (String) item.getValue(); * assertEquals(expected, actual); - * + * * Date expiry = new Date(1000); mc.cas("foo", "bar1", expiry, 10, * item.getCasUnique()); expected = "bar1"; actual = (String) mc.get("foo", * 10); assertEquals(expected, actual); - * + * * try { Thread.sleep(2000); } catch (InterruptedException e) { * e.printStackTrace(); } actual = (String) mc.get("foo", 10); * assertNull(actual); - * + * * mc.set("foo", "bar2", 10); expected = "bar2"; actual = (String) * mc.get("foo", 10); assertEquals(expected, actual); - * + * * boolean res = mc.cas("foo", "bar3", expiry, 10, item.getCasUnique()); * assertFalse(res); } */ public void testBigData() { - TestClass cls = new TestClass(initString(1024), initString(10240), 10240); + TestClass cls = new TestClass(initString(1024), initString(10240), + 10240); for (int i = 0; i < 10; ++i) { mc.set("foo" + i, cls); assertEquals(cls, mc.get("foo" + i)); @@ -721,7 +729,8 @@ public void testBigData() { } public void testExtremeBigData() { - TestClass cls = new TestClass(initString(1024), initString(10240), 10240); + TestClass cls = new TestClass(initString(1024), initString(10240), + 10240); for (int i = 0; i < 10; ++i) { mc.set("foo" + i, cls); assertEquals(cls, mc.get("foo" + i)); @@ -823,7 +832,7 @@ public void testStoreCounterWithAsString() { mc.storeCounter(key, 3L); mc.incr(key); - assertTrue((Long) mc.getCounter(key) == 4); + assertTrue(mc.getCounter(key) == 4); } public void testStoreCounterWithoutAsString() { @@ -882,17 +891,23 @@ public Integer getField3() { return this.field3; } + @Override public boolean equals(Object o) { - if (this == o) + if (this == o) { return true; - if (!(o instanceof TestClass)) + } + if (!(o instanceof TestClass)) { return false; + } TestClass obj = (TestClass) o; - return ((this.field1 == obj.getField1() || (this.field1 != null && this.field1.equals(obj.getField1()))) - && (this.field2 == obj.getField2() || (this.field2 != null && this.field2.equals(obj.getField2()))) && (this.field3 == obj - .getField3() || (this.field3 != null && this.field3.equals(obj.getField3())))); + return ((this.field1 == obj.getField1() || (this.field1 != null && this.field1 + .equals(obj.getField1()))) + && (this.field2 == obj.getField2() || (this.field2 != null && this.field2 + .equals(obj.getField2()))) && (this.field3 == obj + .getField3() || (this.field3 != null && this.field3 + .equals(obj.getField3())))); } } diff --git a/src/test/java/com/schooner/MemCached/MemCachedClientBinaryTest.java b/src/test/java/com/schooner/MemCached/MemCachedClientBinaryTest.java index 533ac4a..fde7e57 100755 --- a/src/test/java/com/schooner/MemCached/MemCachedClientBinaryTest.java +++ b/src/test/java/com/schooner/MemCached/MemCachedClientBinaryTest.java @@ -1,9 +1,9 @@ /******************************************************************************* * Copyright (c) 2009 Schooner Information Technology, Inc. * All rights reserved. - * + * * http://www.schoonerinfotech.com/ - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -14,7 +14,7 @@ * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -70,13 +70,15 @@ private static synchronized String initString(int len) { private MemCacheDaemon daemon = null; + @Override protected void setUp() throws Exception { String servers = System.getProperty("memcached.host"); if (servers == null) { // create daemon and start it daemon = new MemCacheDaemon(); - CacheStorage storage = ConcurrentLinkedHashMap.create( - ConcurrentLinkedHashMap.EvictionPolicy.FIFO, 100000, 5 * 1024 * 1024); + CacheStorage storage = ConcurrentLinkedHashMap + .create(ConcurrentLinkedHashMap.EvictionPolicy.FIFO, + 100000, 5 * 1024 * 1024); daemon.setCache(new CacheImpl(storage)); daemon.setBinary(false); daemon.setAddr(new InetSocketAddress(11211)); @@ -93,6 +95,7 @@ protected void setUp() throws Exception { mc = new MemCachedClient("test", true); } + @Override protected void tearDown() throws Exception { super.tearDown(); mc.flushAll(); @@ -350,8 +353,8 @@ public void testIncr() { mc.addOrIncr("foo", i); // now == 0 assertEquals(mc.get("foo"), new Long(i).toString()); mc.incr("foo"); // foo now == 1 - mc.incr("foo", (long) 5); // foo now == 6 - long j = mc.decr("foo", (long) 2); // foo now == 4 + mc.incr("foo", 5); // foo now == 6 + long j = mc.decr("foo", 2); // foo now == 4 assertEquals(j, 4); } @@ -395,11 +398,11 @@ public void testAddOrIncr() { j = mc.addOrIncr("foo"); // foo now == 0 assertEquals(0, j); j = mc.incr("foo"); // foo now == 1 - j = mc.incr("foo", (long) 5); // foo now == 6 + j = mc.incr("foo", 5); // foo now == 6 j = mc.addOrIncr("foo", 1); // foo now 7 - j = mc.decr("foo", (long) 3); // foo now == 4 + j = mc.decr("foo", 3); // foo now == 4 assertEquals(4, j); } @@ -460,7 +463,7 @@ public void testGetMulti() { mc.set(keys[i], "value" + i); } - Map results = mc.getMulti(keys); + Map results = mc.getMulti(keys); for (int i = 0; i < max; i++) { assertEquals(results.get(keys[i]), "value" + i); } @@ -476,7 +479,7 @@ public void testGetMultiString() { mc.set(keys[i], "value" + i); } - Map results = mc.getMulti(keys, null, true); + Map results = mc.getMulti(keys, null, true); for (int i = 0; i < max; i++) { assertEquals(results.get(keys[i]), "value" + i); } @@ -535,8 +538,9 @@ public void testGets() { public void testSetByteArray() { byte[] b = new byte[10]; - for (int i = 0; i < 10; i++) + for (int i = 0; i < 10; i++) { b[i] = (byte) i; + } mc.set("foo", b); assertTrue(Arrays.equals((byte[]) mc.get("foo"), b)); @@ -552,13 +556,15 @@ public void testSetObj() { public void testCusTransCoder() { TransCoder coder = new ObjectTransCoder() { @Override - public void encode(OutputStream out, Object object) throws IOException { + public void encode(OutputStream out, Object object) + throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); ObjectOutputStream oOut = new ObjectOutputStream(bOut); oOut.writeObject(object); byte[] bytes = bOut.toByteArray(); - for (byte b : bytes) + for (byte b : bytes) { out.write(b); + } } }; mc.setTransCoder(coder); @@ -598,14 +604,15 @@ public void testSetStringObjectInteger() { public void testMultiKey() { - String[] allKeys = { "key1", "key2", "key3", "key4", "key5", "key6", "key7" }; + String[] allKeys = { "key1", "key2", "key3", "key4", "key5", "key6", + "key7" }; String[] setKeys = { "key1", "key3", "key5", "key7" }; for (String key : setKeys) { mc.set(key, key); } - Map results = mc.getMulti(allKeys); + Map results = mc.getMulti(allKeys); assert allKeys.length == results.size(); for (String key : setKeys) { @@ -852,7 +859,8 @@ public void testCasStringObjectDateIntegerLong() { } public void testBigData() { - TestClass cls = new TestClass(initString(1024), initString(10240), 10240); + TestClass cls = new TestClass(initString(1024), initString(10240), + 10240); for (int i = 0; i < 10; ++i) { mc.set("foo" + i, cls); assertEquals(cls, mc.get("foo" + i)); @@ -866,7 +874,8 @@ public void testBigData() { } public void testExtremeBigData() { - TestClass cls = new TestClass(initString(1024), initString(10240), 10240); + TestClass cls = new TestClass(initString(1024), initString(10240), + 10240); for (int i = 0; i < 10; ++i) { mc.set("foo" + i, cls); assertEquals(cls, mc.get("foo" + i)); @@ -907,7 +916,8 @@ public void testStatsSlabsStringArray() { } public void testStatsCacheDumpStringArrayIntegerInteger() { - Map> res = mc.statsCacheDump(serverlist, 1, 2); + Map> res = mc.statsCacheDump(serverlist, 1, + 2); assertFalse(res.isEmpty()); } @@ -923,10 +933,13 @@ public void testGetWithIOException() { assertEquals(expect, actual); mc.setTransCoder(new TransCoder() { - public int encode(SockOutputStream out, Object object) throws IOException { + @Override + public int encode(SockOutputStream out, Object object) + throws IOException { throw new IOException(); } + @Override public Object decode(InputStream input) throws IOException { throw new IOException(); } @@ -944,10 +957,13 @@ public void testGetsWithIOException() { assertEquals(expect, actual); mc.setTransCoder(new TransCoder() { - public int encode(SockOutputStream out, Object object) throws IOException { + @Override + public int encode(SockOutputStream out, Object object) + throws IOException { throw new IOException(); } + @Override public Object decode(InputStream input) throws IOException { throw new IOException(); } @@ -959,10 +975,13 @@ public Object decode(InputStream input) throws IOException { public void testSetWithIOException() { mc.setTransCoder(new TransCoder() { - public int encode(SockOutputStream out, Object object) throws IOException { + @Override + public int encode(SockOutputStream out, Object object) + throws IOException { throw new IOException(); } + @Override public Object decode(InputStream input) throws IOException { throw new IOException(); } @@ -979,7 +998,7 @@ public void testStoreCounterWithAsString() { mc.storeCounter(key, 3L); mc.incr(key); - assertTrue((Long) mc.getCounter(key) == 4); + assertTrue(mc.getCounter(key) == 4); } public void testStoreCounterWithoutAsString() { @@ -1012,25 +1031,36 @@ public static class TestErrorHandler implements ErrorHandler { public boolean tag = false; - public void handleErrorOnDelete(MemCachedClient client, Throwable error, String cacheKey) { + @Override + public void handleErrorOnDelete(MemCachedClient client, + Throwable error, String cacheKey) { } + @Override public void handleErrorOnFlush(MemCachedClient client, Throwable error) { } - public void handleErrorOnGet(MemCachedClient client, Throwable error, String cacheKey) { + @Override + public void handleErrorOnGet(MemCachedClient client, Throwable error, + String cacheKey) { tag = true; } - public void handleErrorOnGet(MemCachedClient client, Throwable error, String[] cacheKeys) { + @Override + public void handleErrorOnGet(MemCachedClient client, Throwable error, + Serializable[] cacheKeys) { } + @Override public void handleErrorOnInit(MemCachedClient client, Throwable error) { } - public void handleErrorOnSet(MemCachedClient client, Throwable error, String cacheKey) { + @Override + public void handleErrorOnSet(MemCachedClient client, Throwable error, + String cacheKey) { } + @Override public void handleErrorOnStats(MemCachedClient client, Throwable error) { } @@ -1061,17 +1091,23 @@ public Integer getField3() { return this.field3; } + @Override public boolean equals(Object o) { - if (this == o) + if (this == o) { return true; - if (!(o instanceof TestClass)) + } + if (!(o instanceof TestClass)) { return false; + } TestClass obj = (TestClass) o; - return ((this.field1 == obj.getField1() || (this.field1 != null && this.field1.equals(obj.getField1()))) - && (this.field2 == obj.getField2() || (this.field2 != null && this.field2.equals(obj.getField2()))) && (this.field3 == obj - .getField3() || (this.field3 != null && this.field3.equals(obj.getField3())))); + return ((this.field1 == obj.getField1() || (this.field1 != null && this.field1 + .equals(obj.getField1()))) + && (this.field2 == obj.getField2() || (this.field2 != null && this.field2 + .equals(obj.getField2()))) && (this.field3 == obj + .getField3() || (this.field3 != null && this.field3 + .equals(obj.getField3())))); } } diff --git a/src/test/java/com/schooner/MemCached/MemcachedClientUDPTest.java b/src/test/java/com/schooner/MemCached/MemcachedClientUDPTest.java index 6095007..2f22da3 100644 --- a/src/test/java/com/schooner/MemCached/MemcachedClientUDPTest.java +++ b/src/test/java/com/schooner/MemCached/MemcachedClientUDPTest.java @@ -1,9 +1,9 @@ /******************************************************************************* * Copyright (c) 2009 Schooner Information Technology, Inc. * All rights reserved. - * + * * http://www.schoonerinfotech.com/ - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -14,7 +14,7 @@ * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -72,11 +72,13 @@ private static synchronized String initString(int len) { pool.setInitConn(1); } + @Override protected void setUp() throws Exception { super.setUp(); mc = new MemCachedClient("test", false, false); } + @Override protected void tearDown() throws Exception { super.tearDown(); assertNotNull(mc); @@ -240,8 +242,8 @@ public void testIncr() { mc.addOrIncr("foo", i); // now == 0 assertEquals(mc.get("foo"), new Long(i).toString()); mc.incr("foo"); // foo now == 1 - mc.incr("foo", (long) 5); // foo now == 6 - long j = mc.decr("foo", (long) 2); // foo now == 4 + mc.incr("foo", 5); // foo now == 6 + long j = mc.decr("foo", 2); // foo now == 4 assertEquals(j, 4); } @@ -285,11 +287,11 @@ public void testAddOrIncr() { j = mc.addOrIncr("foo"); // foo now == 0 assertEquals(0, j); j = mc.incr("foo"); // foo now == 1 - j = mc.incr("foo", (long) 5); // foo now == 6 + j = mc.incr("foo", 5); // foo now == 6 j = mc.addOrIncr("foo", 1); // foo now 7 - j = mc.decr("foo", (long) 3); // foo now == 4 + j = mc.decr("foo", 3); // foo now == 4 assertEquals(4, j); } @@ -355,7 +357,7 @@ public void testGetMulti() { keys[0] = null; - Map results = mc.getMulti(keys); + Map results = mc.getMulti(keys); for (int i = 1; i < max; i++) { assertEquals(results.get(keys[i]), "value" + i); } @@ -390,8 +392,9 @@ public void testGetMutiArrayStringArrayIntegerArray() { public void testSetByteArray() { byte[] b = new byte[10]; - for (int i = 0; i < 10; i++) + for (int i = 0; i < 10; i++) { b[i] = (byte) i; + } mc.set("foo", b); assertTrue(Arrays.equals((byte[]) mc.get("foo"), b)); @@ -437,14 +440,15 @@ public void testSetStringObjectInteger() { public void testMultiKey() { - String[] allKeys = { "key1", "key2", "key3", "key4", "key5", "key6", "key7" }; + String[] allKeys = { "key1", "key2", "key3", "key4", "key5", "key6", + "key7" }; String[] setKeys = { "key1", "key3", "key5", "key7" }; for (String key : setKeys) { mc.set(key, key); } - Map results = mc.getMulti(allKeys); + Map results = mc.getMulti(allKeys); assert allKeys.length == results.size(); for (String key : setKeys) { @@ -738,7 +742,8 @@ public void testStatsSlabsStringArray() { } public void testStatsCacheDumpStringArrayIntegerInteger() { - Map> res = mc.statsCacheDump(serverlist, 1, 2); + Map> res = mc.statsCacheDump(serverlist, 1, + 2); assertFalse(res.isEmpty()); } @@ -754,10 +759,13 @@ public void testGetWithIOException() { assertEquals(expect, actual); mc.setTransCoder(new TransCoder() { - public int encode(SockOutputStream out, Object object) throws IOException { + @Override + public int encode(SockOutputStream out, Object object) + throws IOException { throw new IOException(); } + @Override public Object decode(InputStream input) throws IOException { throw new IOException(); } @@ -775,10 +783,13 @@ public void testGetsWithIOException() { assertEquals(expect, actual); mc.setTransCoder(new TransCoder() { - public int encode(SockOutputStream out, Object object) throws IOException { + @Override + public int encode(SockOutputStream out, Object object) + throws IOException { throw new IOException(); } + @Override public Object decode(InputStream input) throws IOException { throw new IOException(); } @@ -790,10 +801,13 @@ public Object decode(InputStream input) throws IOException { public void testSetWithIOException() { mc.setTransCoder(new TransCoder() { - public int encode(SockOutputStream out, Object object) throws IOException { + @Override + public int encode(SockOutputStream out, Object object) + throws IOException { throw new IOException(); } + @Override public Object decode(InputStream input) throws IOException { throw new IOException(); } @@ -827,13 +841,15 @@ public Object decode(InputStream input) throws IOException { public void testCusTransCoder() { TransCoder coder = new ObjectTransCoder() { @Override - public void encode(OutputStream out, Object object) throws IOException { + public void encode(OutputStream out, Object object) + throws IOException { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); ObjectOutputStream oOut = new ObjectOutputStream(bOut); oOut.writeObject(object); byte[] bytes = bOut.toByteArray(); - for (byte b : bytes) + for (byte b : bytes) { out.write(b); + } } }; mc.setTransCoder(coder); @@ -872,17 +888,23 @@ public Integer getField3() { return this.field3; } + @Override public boolean equals(Object o) { - if (this == o) + if (this == o) { return true; - if (!(o instanceof TestClass)) + } + if (!(o instanceof TestClass)) { return false; + } TestClass obj = (TestClass) o; - return ((this.field1 == obj.getField1() || (this.field1 != null && this.field1.equals(obj.getField1()))) - && (this.field2 == obj.getField2() || (this.field2 != null && this.field2.equals(obj.getField2()))) && (this.field3 == obj - .getField3() || (this.field3 != null && this.field3.equals(obj.getField3())))); + return ((this.field1 == obj.getField1() || (this.field1 != null && this.field1 + .equals(obj.getField1()))) + && (this.field2 == obj.getField2() || (this.field2 != null && this.field2 + .equals(obj.getField2()))) && (this.field3 == obj + .getField3() || (this.field3 != null && this.field3 + .equals(obj.getField3())))); } } diff --git a/src/test/java/com/schooner/MemCached/WhalinScenarioTest.java b/src/test/java/com/schooner/MemCached/WhalinScenarioTest.java index 1ccf580..9e000aa 100644 --- a/src/test/java/com/schooner/MemCached/WhalinScenarioTest.java +++ b/src/test/java/com/schooner/MemCached/WhalinScenarioTest.java @@ -1,5 +1,5 @@ /** - * + * */ package com.schooner.MemCached; @@ -16,7 +16,7 @@ /** * @author newrootwang - * + * */ public class WhalinScenarioTest extends TestCase { @@ -47,17 +47,23 @@ public Integer getField3() { return this.field3; } + @Override public boolean equals(Object o) { - if (this == o) + if (this == o) { return true; - if (!(o instanceof TestClass)) + } + if (!(o instanceof TestClass)) { return false; + } TestClass obj = (TestClass) o; - return ((this.field1 == obj.getField1() || (this.field1 != null && this.field1.equals(obj.getField1()))) - && (this.field2 == obj.getField2() || (this.field2 != null && this.field2.equals(obj.getField2()))) && (this.field3 == obj - .getField3() || (this.field3 != null && this.field3.equals(obj.getField3())))); + return ((this.field1 == obj.getField1() || (this.field1 != null && this.field1 + .equals(obj.getField1()))) + && (this.field2 == obj.getField2() || (this.field2 != null && this.field2 + .equals(obj.getField2()))) && (this.field3 == obj + .getField3() || (this.field3 != null && this.field3 + .equals(obj.getField3())))); } } @@ -102,7 +108,9 @@ public void testMaxConn() { assertEquals(19, pool.getMaxConn()); final MemCachedClient mc = new MemCachedClient(); Thread[] threads = new Thread[20]; - assertEquals(pool.getInitConn(), SchoonerSockIOPool.getInstance().socketPool.get(hosts[0]).getNumIdle()); + assertEquals(pool.getInitConn(), + SchoonerSockIOPool.getInstance().socketPool.get(hosts[0]) + .getNumIdle()); for (int i = 0; i < 20; ++i) { threads[i] = new Thread() { @Override @@ -124,7 +132,8 @@ public void run() { e.printStackTrace(); } } - assertTrue(SchoonerSockIOPool.getInstance().socketPool.get(hosts[0]).getNumActive() < 20); + assertTrue(SchoonerSockIOPool.getInstance().socketPool.get(hosts[0]) + .getNumActive() < 20); mc.flushAll(); pool.shutDown(); } @@ -137,7 +146,9 @@ public void testMinConn() { assertEquals(2, pool.getMinConn()); final MemCachedClient mc = new MemCachedClient(); Thread thread = new Thread(); - assertEquals(2, SchoonerSockIOPool.getInstance().socketPool.get(hosts[0]).getMinIdle()); + assertEquals(2, + SchoonerSockIOPool.getInstance().socketPool.get(hosts[0]) + .getMinIdle()); thread = new Thread() { @Override public void run() { @@ -155,7 +166,9 @@ public void run() { } catch (InterruptedException e) { e.printStackTrace(); } - assertEquals(2, SchoonerSockIOPool.getInstance().socketPool.get(hosts[0]).getNumActive()); + assertEquals(2, + SchoonerSockIOPool.getInstance().socketPool.get(hosts[0]) + .getNumActive()); mc.flushAll(); pool.shutDown(); } @@ -167,8 +180,9 @@ public void testSetWeight() { pool.setWeights(weights); pool.initialize(); MemCachedClient mc = new MemCachedClient(); - for (int i = 0; i < 100; i++) + for (int i = 0; i < 100; i++) { mc.set("key " + i, "value " + i); + } pool.shutDown(); pool = SockIOPool.getInstance("check"); @@ -177,8 +191,9 @@ public void testSetWeight() { pool.initialize(); mc = new MemCachedClient("check"); for (int i = 0; i < 100; i++) { - if (mc.get("key " + i) != null) + if (mc.get("key " + i) != null) { count++; + } } assertTrue(count <= 95 && count >= 85); pool.shutDown(); @@ -389,7 +404,7 @@ public void testGetMultiArray() { values[i] = "value " + i; mc.set(keys[i], values[i]); } - Map rValues = mc.getMulti(keys, null, false); + Map rValues = mc.getMulti(keys, null, false); for (int i = 0; i < 10; i++) { assertEquals(values[i], rValues.get(keys[i])); } @@ -428,10 +443,13 @@ public void testGetWithIOException() { assertEquals(expect, actual); mc.setTransCoder(new TransCoder() { - public int encode(SockOutputStream out, Object object) throws IOException { + @Override + public int encode(SockOutputStream out, Object object) + throws IOException { throw new IOException(); } + @Override public Object decode(InputStream input) throws IOException { throw new IOException(); } @@ -455,10 +473,13 @@ public void testGetsWithIOException() { assertEquals(expect, actual); mc.setTransCoder(new TransCoder() { - public int encode(SockOutputStream out, Object object) throws IOException { + @Override + public int encode(SockOutputStream out, Object object) + throws IOException { throw new IOException(); } + @Override public Object decode(InputStream input) throws IOException { throw new IOException(); } @@ -476,10 +497,13 @@ public void testSetWithIOException() { final MemCachedClient mc = new MemCachedClient(true, false); mc.setTransCoder(new TransCoder() { - public int encode(SockOutputStream out, Object object) throws IOException { + @Override + public int encode(SockOutputStream out, Object object) + throws IOException { throw new IOException(); } + @Override public Object decode(InputStream input) throws IOException { throw new IOException(); } @@ -522,7 +546,7 @@ public void testGetMulti() { values[i] = "value " + i; mc.set(keys[i], values[i]); } - Map rValues = mc.getMulti(keys); + Map rValues = mc.getMulti(keys); for (int i = 0; i < 10; i++) { assertEquals(values[i], rValues.get("key/ " + i)); } @@ -543,7 +567,7 @@ public void testGetMultiBin() { values[i] = "value " + i; mc.set(keys[i], values[i]); } - Map rValues = mc.getMulti(keys); + Map rValues = mc.getMulti(keys); for (int i = 0; i < 10; i++) { assertEquals(values[i], rValues.get("key/ " + i)); } diff --git a/src/test/java/com/whalin/MemCached/test/UnitTests.java b/src/test/java/com/whalin/MemCached/test/UnitTests.java index 0677fe4..a5a3256 100644 --- a/src/test/java/com/whalin/MemCached/test/UnitTests.java +++ b/src/test/java/com/whalin/MemCached/test/UnitTests.java @@ -14,7 +14,7 @@ * library. * * @author Kevin Burton - * @author greg whalin + * @author greg whalin */ package com.whalin.MemCached.test; @@ -121,8 +121,8 @@ public static void test12() { long i = 0; mc.storeCounter("foo", i); mc.incr("foo"); // foo now == 1 - mc.incr("foo", (long) 5); // foo now == 6 - long j = mc.decr("foo", (long) 2); // foo now == 4 + mc.incr("foo", 5); // foo now == 6 + long j = mc.decr("foo", 2); // foo now == 4 assert j == 4; assert j == mc.getCounter("foo"); log.error("+ incr/decr test passed"); @@ -174,11 +174,11 @@ public static void test17() { public static void test18() { mc.addOrIncr("foo"); // foo now == 0 mc.incr("foo"); // foo now == 1 - mc.incr("foo", (long) 5); // foo now == 6 + mc.incr("foo", 5); // foo now == 6 mc.addOrIncr("foo"); // foo now 7 - long j = mc.decr("foo", (long) 3); // foo now == 4 + long j = mc.decr("foo", 3); // foo now == 4 assert j == 4; assert j == mc.getCounter("foo"); @@ -193,7 +193,7 @@ public static void test19() { mc.set(keys[i], "value" + i); } - Map results = mc.getMulti(keys); + Map results = mc.getMulti(keys); for (int i = 0; i < max; i++) { assert results.get(keys[i]).equals("value" + i); } @@ -201,7 +201,9 @@ public static void test19() { } public static void test20(int max, int skip, int start) { - log.warn(String.format("test 20 starting with start=%5d skip=%5d max=%7d", start, skip, max)); + log.warn(String.format( + "test 20 starting with start=%5d skip=%5d max=%7d", start, + skip, max)); int numEntries = max / skip + 1; String[] keys = new String[numEntries]; byte[][] vals = new byte[numEntries][]; @@ -210,18 +212,22 @@ public static void test20(int max, int skip, int start) { for (int i = 0; i < numEntries; i++) { keys[i] = Integer.toString(size); vals[i] = new byte[size + 1]; - for (int j = 0; j < size + 1; j++) + for (int j = 0; j < size + 1; j++) { vals[i][j] = (byte) j; + } mc.set(keys[i], vals[i]); size += skip; } - Map results = mc.getMulti(keys); - for (int i = 0; i < numEntries; i++) + Map results = mc.getMulti(keys); + for (int i = 0; i < numEntries; i++) { assert Arrays.equals((byte[]) results.get(keys[i]), vals[i]); + } - log.warn(String.format("test 20 finished with start=%5d skip=%5d max=%7d", start, skip, max)); + log.warn(String.format( + "test 20 finished with start=%5d skip=%5d max=%7d", start, + skip, max)); } public static void test21() { @@ -233,8 +239,9 @@ public static void test21() { public static void test22() { byte[] b = new byte[10]; - for (int i = 0; i < 10; i++) + for (int i = 0; i < 10; i++) { b[i] = (byte) i; + } mc.set("foo", b); assert Arrays.equals((byte[]) mc.get("foo"), b); @@ -244,20 +251,21 @@ public static void test22() { public static void test23() { TestClass tc = new TestClass("foo", "bar", new Integer(32)); mc.set("foo", tc); - assert tc.equals((TestClass) mc.get("foo")); + assert tc.equals(mc.get("foo")); log.error("+ store/retrieve serialized object test passed"); } public static void test24() { - String[] allKeys = { "key1", "key2", "key3", "key4", "key5", "key6", "key7" }; + String[] allKeys = { "key1", "key2", "key3", "key4", "key5", "key6", + "key7" }; String[] setKeys = { "key1", "key3", "key5", "key7" }; for (String key : setKeys) { mc.set(key, key); } - Map results = mc.getMulti(allKeys); + Map results = mc.getMulti(allKeys); assert allKeys.length == results.size(); for (String key : setKeys) { @@ -293,8 +301,9 @@ public static void runAlTests(MemCachedClient mc) { test23(); test24(); - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { test19(); + } test20(8191, 1, 0); test20(8192, 1, 0); @@ -321,10 +330,10 @@ public static void runAlTests(MemCachedClient mc) { /** * This runs through some simple tests of the MemcacheClient. - * + * * Command line args: args[0] = number of threads to spawn args[1] = number * of runs per thread args[2] = size of object to store - * + * * @param args * the command line arguments */ @@ -342,8 +351,9 @@ public static void main(String[] args) { Integer[] weights = { 1 }; - if (args.length > 0) + if (args.length > 0) { serverlist = args; + } // initialize the pool for memcache servers SockIOPool pool = SockIOPool.getInstance("test"); @@ -360,7 +370,7 @@ public static void main(String[] args) { /** * Class for testing serializing of objects. - * + * * @author $Author: $ * @version $Revision: $ $Date: $ */ @@ -389,17 +399,23 @@ public Integer getField3() { return this.field3; } + @Override public boolean equals(Object o) { - if (this == o) + if (this == o) { return true; - if (!(o instanceof TestClass)) + } + if (!(o instanceof TestClass)) { return false; + } TestClass obj = (TestClass) o; - return ((this.field1 == obj.getField1() || (this.field1 != null && this.field1.equals(obj.getField1()))) - && (this.field2 == obj.getField2() || (this.field2 != null && this.field2.equals(obj.getField2()))) && (this.field3 == obj - .getField3() || (this.field3 != null && this.field3.equals(obj.getField3())))); + return ((this.field1 == obj.getField1() || (this.field1 != null && this.field1 + .equals(obj.getField1()))) + && (this.field2 == obj.getField2() || (this.field2 != null && this.field2 + .equals(obj.getField2()))) && (this.field3 == obj + .getField3() || (this.field3 != null && this.field3 + .equals(obj.getField3())))); } } } diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties new file mode 100644 index 0000000..71131a8 --- /dev/null +++ b/src/test/resources/log4j.properties @@ -0,0 +1,7 @@ +log4j.rootLogger=error,console +log4j.threshold=ALL + +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.target=System.out +log4j.appender.console.layout=org.apache.log4j.PatternLayout +#log4j.appender.console.layout.ConversionPattern=%d{ISO8601} [%t] %p %c{2}: %m%n diff --git a/src/test/resources/memcached.properties b/src/test/resources/memcached.properties new file mode 100644 index 0000000..c0ae6bf --- /dev/null +++ b/src/test/resources/memcached.properties @@ -0,0 +1,2 @@ +#memcached server ip and port +memcache.server=10.1.169.132:12321 \ No newline at end of file diff --git a/src/test/resources/spring-memcached-Binary.xml b/src/test/resources/spring-memcached-Binary.xml new file mode 100644 index 0000000..a5b9d6e --- /dev/null +++ b/src/test/resources/spring-memcached-Binary.xml @@ -0,0 +1,34 @@ + + + + + test + + + false + + + true + + + + + + test + + + + ${memcache.server} + + + + + + \ No newline at end of file diff --git a/src/test/resources/spring-memcached-TCP.xml b/src/test/resources/spring-memcached-TCP.xml new file mode 100644 index 0000000..6be6fe9 --- /dev/null +++ b/src/test/resources/spring-memcached-TCP.xml @@ -0,0 +1,28 @@ + + + + + test + + + + + + test + + + + ${memcache.server} + + + + + + \ No newline at end of file diff --git a/src/test/resources/spring-memcached-UDP.xml b/src/test/resources/spring-memcached-UDP.xml new file mode 100644 index 0000000..b6ed7eb --- /dev/null +++ b/src/test/resources/spring-memcached-UDP.xml @@ -0,0 +1,34 @@ + + + + + test + + + false + + + false + + + + + + test + + + + ${memcache.server} + + + + + + \ No newline at end of file