Permalink
Browse files

ISPN-1293 Implement Default Lifespan/MaxIdle over HotRod

  • Loading branch information...
1 parent 67f2027 commit 26a64f8539be29be7971d6843f404b29631525f4 @tristantarrant tristantarrant committed with danberindei Nov 21, 2012
Showing with 580 additions and 228 deletions.
  1. +1 −0 .gitignore
  2. +20 −1 client/hotrod-client/src/main/java/org/infinispan/client/hotrod/Flag.java
  3. +2 −1 client/hotrod-client/src/main/java/org/infinispan/client/hotrod/impl/ConfigurationProperties.java
  4. +23 −11 client/hotrod-client/src/main/java/org/infinispan/client/hotrod/impl/RemoteCacheImpl.java
  5. +26 −6 ...t/hotrod-client/src/main/java/org/infinispan/client/hotrod/impl/operations/OperationsFactory.java
  6. +5 −4 client/hotrod-client/src/main/java/org/infinispan/client/hotrod/impl/protocol/Codec10.java
  7. +0 −1 client/hotrod-client/src/main/java/org/infinispan/client/hotrod/impl/protocol/Codec11.java
  8. +70 −0 client/hotrod-client/src/main/java/org/infinispan/client/hotrod/impl/protocol/Codec12.java
  9. +15 −5 client/hotrod-client/src/main/java/org/infinispan/client/hotrod/impl/protocol/CodecFactory.java
  10. +2 −1 client/hotrod-client/src/main/java/org/infinispan/client/hotrod/impl/protocol/HotRodConstants.java
  11. +115 −0 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/DefaultExpirationTest.java
  12. +4 −4 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/ForceReturnValuesTest.java
  13. +3 −3 client/hotrod-client/src/test/java/org/infinispan/client/hotrod/HotRodIntegrationTest.java
  14. +2 −2 core/src/main/java/org/infinispan/CacheImpl.java
  15. +30 −13 server/core/src/main/scala/org/infinispan/server/core/AbstractProtocolDecoder.scala
  16. +30 −0 server/core/src/main/scala/org/infinispan/server/core/ServerConstants.scala
  17. +18 −19 server/core/src/main/scala/org/infinispan/server/core/transport/NettyTransport.scala
  18. +1 −1 server/hotrod/src/main/scala/org/infinispan/server/hotrod/AbstractEncoder1x.scala
  19. +166 −0 server/hotrod/src/main/scala/org/infinispan/server/hotrod/AbstractTopologyAwareEncoder1x.scala
  20. +2 −2 server/hotrod/src/main/scala/org/infinispan/server/hotrod/AbstractVersionedDecoder.scala
  21. +1 −1 server/hotrod/src/main/scala/org/infinispan/server/hotrod/AbstractVersionedEncoder.scala
  22. +1 −0 server/hotrod/src/main/scala/org/infinispan/server/hotrod/Constants.scala
  23. +1 −1 server/hotrod/src/main/scala/org/infinispan/server/hotrod/CrashedMemberDetectorListener.scala
  24. +23 −15 server/hotrod/src/main/scala/org/infinispan/server/hotrod/Decoder10.scala
  25. +5 −123 server/hotrod/src/main/scala/org/infinispan/server/hotrod/Encoders.scala
  26. +2 −2 server/hotrod/src/main/scala/org/infinispan/server/hotrod/HotRodDecoder.scala
  27. +3 −2 server/hotrod/src/main/scala/org/infinispan/server/hotrod/HotRodEncoder.scala
  28. +1 −1 server/hotrod/src/main/scala/org/infinispan/server/hotrod/HotRodOperation.scala
  29. +1 −1 server/hotrod/src/main/scala/org/infinispan/server/hotrod/LifecycleCallbacks.scala
  30. +1 −1 server/hotrod/src/main/scala/org/infinispan/server/hotrod/OperationStatus.scala
  31. +1 −2 server/hotrod/src/main/scala/org/infinispan/server/hotrod/Response.scala
  32. +1 −1 server/hotrod/src/main/scala/org/infinispan/server/hotrod/ServerAddress.scala
  33. +4 −4 server/hotrod/src/test/scala/org/infinispan/server/hotrod/test/HotRodClient.scala
View
@@ -26,6 +26,7 @@ classes
PutObjectStoreDirHere
/query/person
ObjectStore
+.cache
# generated rhq plugin xml
rhq-plugin.xml
# Compiled python files
@@ -34,6 +34,12 @@
* the previous value associated with the key. By applying this flag, this default
* behavior is overridden for the scope of a single invocation, and the previous
* existing value is returned.</li>
+ * <li>{@link #DEFAULT_LIFESPAN} This flag can either be used as a request flag during a put operation to mean
+ * that the default server lifespan should be applied or as a response flag meaning that
+ * the return entry has a default lifespan value</li>
+ * <li>{@link #DEFAULT_MAXIDLE} This flag can either be used as a request flag during a put operation to mean
+ * that the default server maxIdle should be applied or as a response flag meaning that
+ * the return entry has a default maxIdle value</li>
* </ul>
*
* @author Mircea.Markus@jboss.com
@@ -48,7 +54,20 @@
* By applying this flag, this default behavior is overridden for the scope of a single invocation, and the previous
* existing value is returned.
*/
- FORCE_RETURN_VALUE(0x0001);
+ FORCE_RETURN_VALUE(0x0001),
+ /**
+ * This flag can either be used as a request flag during a put operation to mean that the default
+ * server lifespan should be applied or as a response flag meaning that the return entry has a
+ * default lifespan value
+ */
+ DEFAULT_LIFESPAN(0x0002),
+ /**
+ * This flag can either be used as a request flag during a put operation to mean that the default
+ * server maxIdle should be applied or as a response flag meaning that the return entry has a
+ * default maxIdle value
+ */
+ DEFAULT_MAXIDLE(0x0004)
+ ;
private int flagInt;
@@ -65,9 +65,10 @@
public static final int DEFAULT_HOTROD_PORT = 11222;
public static final int DEFAULT_SO_TIMEOUT = 60000;
public static final int DEFAULT_CONNECT_TIMEOUT = 60000;
+ public static final String PROTOCOL_VERSION_12 = "1.2";
public static final String PROTOCOL_VERSION_11 = "1.1";
public static final String PROTOCOL_VERSION_10 = "1.0";
- public static final String DEFAULT_PROTOCOL_VERSION = PROTOCOL_VERSION_11;
+ public static final String DEFAULT_PROTOCOL_VERSION = PROTOCOL_VERSION_12;
private final TypedProperties props;
@@ -103,7 +103,7 @@ public RemoteCacheManager getRemoteCacheManager() {
public boolean removeWithVersion(K key, long version) {
assertRemoteCacheManagerIsStarted();
RemoveIfUnmodifiedOperation op = operationsFactory.newRemoveIfUnmodifiedOperation(obj2bytes(key, true), version);
- VersionedOperationResponse response = (VersionedOperationResponse) op.execute();
+ VersionedOperationResponse response = op.execute();
return response.getCode().isUpdated();
}
@@ -127,7 +127,7 @@ public Boolean call() throws Exception {
public boolean replaceWithVersion(K key, V newValue, long version, int lifespanSeconds, int maxIdleTimeSeconds) {
assertRemoteCacheManagerIsStarted();
ReplaceIfUnmodifiedOperation op = operationsFactory.newReplaceIfUnmodifiedOperation(obj2bytes(key, true), obj2bytes(newValue, false), lifespanSeconds, maxIdleTimeSeconds, version);
- VersionedOperationResponse response = (VersionedOperationResponse) op.execute();
+ VersionedOperationResponse response = op.execute();
return response.getCode().isUpdated();
}
@@ -151,7 +151,7 @@ public Boolean call() throws Exception {
public VersionedValue<V> getVersioned(K key) {
assertRemoteCacheManagerIsStarted();
GetWithVersionOperation op = operationsFactory.newGetWithVersionOperation(obj2bytes(key, true));
- BinaryVersionedValue value = (BinaryVersionedValue) op.execute();
+ BinaryVersionedValue value = op.execute();
return binary2VersionedValue(value);
}
@@ -185,7 +185,7 @@ public Void call() throws Exception {
public int size() {
assertRemoteCacheManagerIsStarted();
StatsOperation op = operationsFactory.newStatsOperation();
- return Integer.parseInt(((Map<String, String>) op.execute()).get(ServerStatistics.CURRENT_NR_OF_ENTRIES));
+ return Integer.parseInt(op.execute().get(ServerStatistics.CURRENT_NR_OF_ENTRIES));
}
@Override
@@ -198,7 +198,7 @@ public boolean isEmpty() {
public ServerStatistics stats() {
assertRemoteCacheManagerIsStarted();
StatsOperation op = operationsFactory.newStatsOperation();
- Map<String, String> statsMap = (Map<String, String>) op.execute();
+ Map<String, String> statsMap = op.execute();
ServerStatisticsImpl stats = new ServerStatisticsImpl();
for (Map.Entry<String, String> entry : statsMap.entrySet()) {
stats.addStats(entry.getKey(), entry.getValue());
@@ -212,11 +212,12 @@ public V put(K key, V value, long lifespan, TimeUnit lifespanUnit, long maxIdleT
assertRemoteCacheManagerIsStarted();
int lifespanSecs = toSeconds(lifespan, lifespanUnit);
int maxIdleSecs = toSeconds(maxIdleTime, maxIdleTimeUnit);
+ applyDefaultExpirationFlags(lifespan, maxIdleTime);
if (log.isTraceEnabled()) {
log.tracef("About to add (K,V): (%s, %s) lifespanSecs:%d, maxIdleSecs:%d", key, value, lifespanSecs, maxIdleSecs);
}
PutOperation op = operationsFactory.newPutKeyValueOperation(obj2bytes(key, true), obj2bytes(value, false), lifespanSecs, maxIdleSecs);
- byte[] result = (byte[]) op.execute();
+ byte[] result = op.execute();
return (V) bytes2obj(result);
}
@@ -227,8 +228,9 @@ public V putIfAbsent(K key, V value, long lifespan, TimeUnit lifespanUnit, long
assertRemoteCacheManagerIsStarted();
int lifespanSecs = toSeconds(lifespan, lifespanUnit);
int maxIdleSecs = toSeconds(maxIdleTime, maxIdleTimeUnit);
+ applyDefaultExpirationFlags(lifespan, maxIdleTime);
PutIfAbsentOperation op = operationsFactory.newPutIfAbsentOperation(obj2bytes(key, true), obj2bytes(value, false), lifespanSecs, maxIdleSecs);
- byte[] bytes = (byte[]) op.execute();
+ byte[] bytes = op.execute();
return (V) bytes2obj(bytes);
}
@@ -238,8 +240,9 @@ public V replace(K key, V value, long lifespan, TimeUnit lifespanUnit, long maxI
assertRemoteCacheManagerIsStarted();
int lifespanSecs = toSeconds(lifespan, lifespanUnit);
int maxIdleSecs = toSeconds(maxIdleTime, maxIdleTimeUnit);
+ applyDefaultExpirationFlags(lifespan, maxIdleTime);
ReplaceOperation op = operationsFactory.newReplaceOperation(obj2bytes(key, true), obj2bytes(value, false), lifespanSecs, maxIdleSecs);
- byte[] bytes = (byte[]) op.execute();
+ byte[] bytes = op.execute();
return (V) bytes2obj(bytes);
}
@@ -327,7 +330,7 @@ public V call() throws Exception {
public boolean containsKey(Object key) {
assertRemoteCacheManagerIsStarted();
ContainsKeyOperation op = operationsFactory.newContainsKeyOperation(obj2bytes(key, true));
- return (Boolean)op.execute();
+ return op.execute();
}
@Override
@@ -336,7 +339,7 @@ public V get(Object key) {
assertRemoteCacheManagerIsStarted();
byte[] keyBytes = obj2bytes(key, true);
GetOperation gco = operationsFactory.newGetKeyOperation(keyBytes);
- byte[] bytes = (byte[]) gco.execute();
+ byte[] bytes = gco.execute();
V result = (V) bytes2obj(bytes);
if (log.isTraceEnabled()) {
log.tracef("For key(%s) returning %s", key, result);
@@ -369,7 +372,7 @@ public V get(Object key) {
public V remove(Object key) {
assertRemoteCacheManagerIsStarted();
RemoveOperation removeOperation = operationsFactory.newRemoveOperation(obj2bytes(key, true));
- byte[] existingValue = (byte[]) removeOperation.execute();
+ byte[] existingValue = removeOperation.execute();
// TODO: It sucks that you need the prev value to see if it works...
// We need to find a better API for RemoteCache...
return (V) bytes2obj(existingValue);
@@ -481,4 +484,13 @@ protected void set(K key, V value) {
// Warning: never invoke put(K,V) in this scope or we'll get a stackoverflow.
put(key, value, defaultLifespan, MILLISECONDS, defaultMaxIdleTime, MILLISECONDS);
}
+
+ private void applyDefaultExpirationFlags(long lifespan, long maxIdle) {
+ if (lifespan == 0) {
+ operationsFactory.addFlags(Flag.DEFAULT_LIFESPAN);
+ }
+ if (maxIdle == 0) {
+ operationsFactory.addFlags(Flag.DEFAULT_MAXIDLE);
+ }
+ }
}
@@ -31,6 +31,8 @@
import org.infinispan.client.hotrod.impl.transport.Transport;
import org.infinispan.client.hotrod.impl.transport.TransportFactory;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -44,7 +46,7 @@
private static final Flag[] FORCE_RETURN_VALUE = {Flag.FORCE_RETURN_VALUE};
- private final ThreadLocal<Flag[]> flagsMap = new ThreadLocal<Flag[]>();
+ private final ThreadLocal<List<Flag>> flagsMap = new ThreadLocal<List<Flag>>();
private final TransportFactory transportFactory;
@@ -157,15 +159,33 @@ public FaultTolerantPingOperation newFaultTolerantPingOperation() {
}
private Flag[] flags() {
- Flag[] flags = this.flagsMap.get();
+ List<Flag> flags = this.flagsMap.get();
this.flagsMap.remove();
- if (flags == null && forceReturnValue) {
- return FORCE_RETURN_VALUE;
+ if (forceReturnValue) {
+ if (flags == null) {
+ return FORCE_RETURN_VALUE;
+ } else {
+ flags.add(Flag.FORCE_RETURN_VALUE);
+ }
}
- return flags;
+ return flags != null ? flags.toArray(new Flag[0]) : null;
}
public void setFlags(Flag[] flags) {
- this.flagsMap.set(flags);
+ List<Flag> list = new ArrayList<Flag>();
+ for(Flag flag : flags)
+ list.add(flag);
+ this.flagsMap.set(list);
+ }
+
+ public void addFlags(Flag... flags) {
+ List<Flag> list = this.flagsMap.get();
+ if (list == null) {
+ list = new ArrayList<Flag>();
+ this.flagsMap.set(list);
+ }
+ for(Flag flag : flags)
+ list.add(flag);
+
}
}
@@ -66,7 +66,8 @@ protected HeaderParams writeHeader(
int flagInt = 0;
if (params.flags != null) {
for (Flag flag : params.flags) {
- flagInt = flag.getFlagInt() | flagInt;
+ if (flag.equals(Flag.FORCE_RETURN_VALUE)) // 1.0 / 1.1 servers only understand this flag
+ flagInt = flag.getFlagInt();
}
}
transport.writeVInt(flagInt);
@@ -126,12 +127,12 @@ public Log getLog() {
return log;
}
- private void checkForErrorsInResponseStatus(Transport transport, HeaderParams params, short status) {
+ protected void checkForErrorsInResponseStatus(Transport transport, HeaderParams params, short status) {
final Log localLog = getLog();
boolean isTrace = localLog.isTraceEnabled();
if (isTrace) localLog.tracef("Received operation status: %#x", status);
- switch ((int) status) {
+ switch (status) {
case HotRodConstants.INVALID_MAGIC_OR_MESSAGE_ID_STATUS:
case HotRodConstants.REQUEST_PARSING_ERROR_STATUS:
case HotRodConstants.UNKNOWN_COMMAND_STATUS:
@@ -161,7 +162,7 @@ private void checkForErrorsInResponseStatus(Transport transport, HeaderParams pa
}
}
- private void readNewTopologyIfPresent(Transport transport, HeaderParams params) {
+ protected void readNewTopologyIfPresent(Transport transport, HeaderParams params) {
short topologyChangeByte = transport.readByte();
if (topologyChangeByte == 1)
readNewTopologyAndHash(transport, params.topologyId);
@@ -25,7 +25,6 @@
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
import org.infinispan.client.hotrod.impl.consistenthash.ConsistentHash;
import org.infinispan.client.hotrod.impl.transport.Transport;
@@ -0,0 +1,70 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+package org.infinispan.client.hotrod.impl.protocol;
+
+import org.infinispan.client.hotrod.Flag;
+import org.infinispan.client.hotrod.impl.transport.Transport;
+import org.infinispan.client.hotrod.logging.Log;
+import org.infinispan.client.hotrod.logging.LogFactory;
+
+/**
+ * A Hot Rod encoder/decoder for version 1.2 of the protocol.
+ *
+ * @author Tristan Tarrant
+ * @author Galder Zamarreño
+ * @since 5.2
+ */
+public class Codec12 extends Codec11 {
+
+ private static final Log log = LogFactory.getLog(Codec12.class, Log.class);
+
+ @Override
+ public HeaderParams writeHeader(Transport transport, HeaderParams params) {
+ return writeHeader(transport, params, HotRodConstants.VERSION_12);
+ }
+
+ @Override
+ protected HeaderParams writeHeader(Transport transport, HeaderParams params, byte version) {
+ transport.writeByte(HotRodConstants.REQUEST_MAGIC);
+ transport.writeVLong(params.messageId(MSG_ID.incrementAndGet()).messageId);
+ transport.writeByte(version);
+ transport.writeByte(params.opCode);
+ transport.writeArray(params.cacheName);
+
+ int flagInt = 0;
+ if (params.flags != null) {
+ for (Flag flag : params.flags) {
+ flagInt = flag.getFlagInt() | flagInt;
+ }
+ }
+ transport.writeVInt(flagInt);
+ transport.writeByte(params.clientIntel);
+ transport.writeVInt(params.topologyId.get());
+ //todo change once TX support is added
+ transport.writeByte(params.txMarker);
+ getLog().tracef("Wrote header for message %d. Operation code: %#04x. Flags: %#x", params.messageId, params.opCode, flagInt);
+ return params;
+ }
+
+ @Override
+ public Log getLog() {
+ return log;
+ }
+
+}
@@ -19,7 +19,10 @@
package org.infinispan.client.hotrod.impl.protocol;
-import org.infinispan.client.hotrod.impl.ConfigurationProperties;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.infinispan.client.hotrod.impl.ConfigurationProperties.*;
/**
* Code factory.
@@ -28,15 +31,22 @@
* @since 5.1
*/
public class CodecFactory {
+ private static final Map<String, Codec> codecMap;
private static final Codec CODEC_10 = new Codec10();
private static final Codec CODEC_11 = new Codec11();
+ private static final Codec CODEC_12 = new Codec12();
+
+ static {
+ codecMap = new HashMap<String, Codec>();
+ codecMap.put(PROTOCOL_VERSION_10, CODEC_10);
+ codecMap.put(PROTOCOL_VERSION_11, CODEC_11);
+ codecMap.put(PROTOCOL_VERSION_12, CODEC_12);
+ }
public static Codec getCodec(String version) {
- if (version.equals(ConfigurationProperties.PROTOCOL_VERSION_10))
- return CODEC_10;
- else if (version.equals(ConfigurationProperties.PROTOCOL_VERSION_11))
- return CODEC_11;
+ if (codecMap.containsKey(version))
+ return codecMap.get(version);
else
throw new IllegalArgumentException("Invalid Hot Rod protocol version");
}
Oops, something went wrong.

0 comments on commit 26a64f8

Please sign in to comment.