Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
First pass at caching support in EAP 6.4 [IMMUTANT-569]
We introduce a bit of reflective hackiness in Config to account for ispan 5 not having keyEquivalence and loaders instead of persistence builders. The lack of keyEquivalence means byte[]'s can't be used as keys, so we override withCodec in WildFlyCaching to wrap byte[] keys with smarter hashCode/equals methods. We may convert this to a Codec in the future, but doing so comes at the cost of needlessly encoding values instead of keys. At least, as the code is currently structured.
- Loading branch information
1 parent
8de3c16
commit e9d268d
Showing
15 changed files
with
614 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<?xml version="1.0"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
|
||
<parent> | ||
<groupId>org.projectodd.wunderboss</groupId> | ||
<artifactId>wunderboss-modules</artifactId> | ||
<version>0.8.2-SNAPSHOT</version> | ||
</parent> | ||
|
||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>org.projectodd.wunderboss</groupId> | ||
<artifactId>wunderboss-caching-ispan5</artifactId> | ||
<name>WunderBoss Caching Module for Infinispan 5.x</name> | ||
|
||
<packaging>jar</packaging> | ||
|
||
<properties> | ||
<version.infinispan>5.2.11.Final</version.infinispan> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.projectodd.wunderboss</groupId> | ||
<artifactId>wunderboss-caching-ispan6</artifactId> | ||
<version>${project.version}</version> | ||
<exclusions> | ||
<exclusion> | ||
<groupId>org.infinispan</groupId> | ||
<artifactId>infinispan-core</artifactId> | ||
</exclusion> | ||
</exclusions> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.infinispan</groupId> | ||
<artifactId>infinispan-core</artifactId> | ||
<version>${version.infinispan}</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
|
||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>com.theoryinpractise</groupId> | ||
<artifactId>clojure-maven-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<id>test</id> | ||
<phase>test</phase> | ||
<goals> | ||
<goal>test</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
</project> |
42 changes: 42 additions & 0 deletions
42
modules/caching-ispan5/src/main/java/org/projectodd/wunderboss/caching/Config5.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* Copyright 2014-2015 Red Hat, Inc, and individual contributors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.projectodd.wunderboss.caching; | ||
|
||
import org.projectodd.wunderboss.Options; | ||
|
||
|
||
public class Config5 extends Config { | ||
|
||
public Config5(Options<Caching.CreateOption> options) { | ||
super(options); | ||
} | ||
|
||
void equivalate() { | ||
// No such feature in ispan5; must use wrapper object | ||
} | ||
|
||
void persist() { | ||
Object v = options.get(Caching.CreateOption.PERSIST); | ||
if (v instanceof Boolean && (boolean) v) { | ||
builder.loaders().addFileCacheStore(); | ||
} | ||
if (v instanceof String) { | ||
builder.loaders().addFileCacheStore().location(v.toString()); | ||
} | ||
} | ||
|
||
} |
211 changes: 211 additions & 0 deletions
211
...s/caching-ispan5/src/main/java/org/projectodd/wunderboss/caching/KeyEquivalenceCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
/* | ||
* Copyright 2014-2015 Red Hat, Inc, and individual contributors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package org.projectodd.wunderboss.caching; | ||
|
||
import org.infinispan.Cache; | ||
import org.infinispan.AbstractDelegatingCache; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.HashSet; | ||
import java.util.AbstractMap.SimpleImmutableEntry; | ||
import java.io.Serializable; | ||
|
||
|
||
public class KeyEquivalenceCache extends AbstractDelegatingCache { | ||
|
||
public KeyEquivalenceCache(Cache cache) { | ||
super(cache); | ||
} | ||
|
||
Object encode(Object key) { | ||
if (key==null) { | ||
return null; | ||
} else if (byte[].class == key.getClass()) { | ||
return new KeyWrapper(key); | ||
} else { | ||
return key; | ||
} | ||
} | ||
|
||
Object decode(Object key) { | ||
if (key==null) { | ||
return null; | ||
} else if (key instanceof KeyWrapper) { | ||
return ((KeyWrapper) key).getKey(); | ||
} else { | ||
return key; | ||
} | ||
} | ||
|
||
@Override | ||
public void putForExternalRead(Object key, Object value) { | ||
super.putForExternalRead(encode(key), value); | ||
} | ||
|
||
@Override | ||
public void evict(Object key) { | ||
super.evict(encode(key)); | ||
} | ||
|
||
@Override | ||
public Object put(Object key, Object value, long lifespan, TimeUnit unit) { | ||
return super.put(encode(key), value, lifespan, unit); | ||
} | ||
|
||
@Override | ||
public Object putIfAbsent(Object key, Object value, long lifespan, TimeUnit unit) { | ||
return super.putIfAbsent(encode(key), value, lifespan, unit); | ||
} | ||
|
||
@Override | ||
public void putAll(Map map, long lifespan, TimeUnit unit) { | ||
for (Object o: map.entrySet()) { | ||
Entry entry = (Entry) o; | ||
super.put(encode(entry.getKey()), entry.getValue(), lifespan, unit); | ||
} | ||
} | ||
|
||
@Override | ||
public Object replace(Object key, Object value, long lifespan, TimeUnit unit) { | ||
return super.replace(encode(key), value, lifespan, unit); | ||
} | ||
|
||
@Override | ||
public boolean replace(Object key, Object oldValue, Object value, long lifespan, TimeUnit unit) { | ||
return super.replace(encode(key), oldValue, value, lifespan, unit); | ||
} | ||
|
||
@Override | ||
public Object put(Object key, Object value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { | ||
return super.put(encode(key), value, lifespan, lifespanUnit, maxIdleTime, maxIdleTimeUnit); | ||
} | ||
|
||
@Override | ||
public Object putIfAbsent(Object key, Object value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { | ||
return super.putIfAbsent(encode(key), value, lifespan, lifespanUnit, maxIdleTime, maxIdleTimeUnit); | ||
} | ||
|
||
@Override | ||
public void putAll(Map map, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { | ||
for (Object o: map.entrySet()) { | ||
Entry entry = (Entry) o; | ||
super.put(encode(entry.getKey()), entry.getValue(), lifespan, lifespanUnit, maxIdleTime, maxIdleTimeUnit); | ||
} | ||
} | ||
|
||
@Override | ||
public Object replace(Object key, Object value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { | ||
return super.replace(encode(key), value, lifespan, lifespanUnit, maxIdleTime, maxIdleTimeUnit); | ||
} | ||
|
||
@Override | ||
public boolean replace(Object key, Object oldValue, Object value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit) { | ||
return super.replace(encode(key), oldValue, value, lifespan, lifespanUnit, maxIdleTime, maxIdleTimeUnit); | ||
} | ||
|
||
@Override | ||
public Object putIfAbsent(Object key, Object value) { | ||
return super.putIfAbsent(encode(key), value); | ||
} | ||
|
||
@Override | ||
public boolean remove(Object key, Object value) { | ||
return super.remove(encode(key), value); | ||
} | ||
|
||
@Override | ||
public boolean replace(Object key, Object oldValue, Object newValue) { | ||
return super.replace(encode(key), oldValue, newValue); | ||
} | ||
|
||
@Override | ||
public Object replace(Object key, Object value) { | ||
return super.replace(encode(key), value); | ||
} | ||
|
||
@Override | ||
public boolean containsKey(Object key) { | ||
return super.containsKey(encode(key)); | ||
} | ||
|
||
@Override | ||
public Object get(Object key) { | ||
return super.get(encode(key)); | ||
} | ||
|
||
@Override | ||
public Object put(Object key, Object value) { | ||
return super.put(encode(key), value); | ||
} | ||
|
||
@Override | ||
public Object remove(Object key) { | ||
return super.remove(encode(key)); | ||
} | ||
|
||
@Override | ||
public void putAll(Map t) { | ||
for (Object o: t.entrySet()) { | ||
Entry entry = (Entry) o; | ||
super.put(encode(entry.getKey()), entry.getValue()); | ||
} | ||
} | ||
|
||
@Override | ||
public Set keySet() { | ||
Set keys = super.keySet(); | ||
Set result = new HashSet(keys.size()); | ||
for (Object k: keys) { | ||
result.add(decode(k)); | ||
} | ||
return result; | ||
} | ||
|
||
@Override | ||
public Set entrySet() { | ||
Set entries = super.entrySet(); | ||
Set result = new HashSet(entries.size()); | ||
for (Object o: entries) { | ||
Entry entry = (Entry) o; | ||
result.add(new SimpleImmutableEntry(decode(entry.getKey()), entry.getValue())); | ||
} | ||
return result; | ||
} | ||
|
||
static class KeyWrapper implements Serializable { | ||
public KeyWrapper(Object key) { | ||
this.key = key; | ||
} | ||
public Object getKey() { | ||
return this.key; | ||
} | ||
public boolean equals(Object obj) { | ||
return obj instanceof KeyWrapper ? | ||
obj.equals(key) : | ||
equiv.equals(obj, key); | ||
} | ||
public int hashCode() { | ||
return equiv.hashCode(key); | ||
} | ||
public String toString() { | ||
return equiv.toString(key); | ||
} | ||
private final Object key; | ||
static final Equivalence equiv = new Equivalence(); | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
modules/caching-ispan5/src/test/clojure/wunderboss/caching_test.clj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
;; Copyright 2014-2015 Red Hat, Inc, and individual contributors. | ||
;; | ||
;; Licensed under the Apache License, Version 2.0 (the "License"); | ||
;; you may not use this file except in compliance with the License. | ||
;; You may obtain a copy of the License at | ||
;; | ||
;; http://www.apache.org/licenses/LICENSE-2.0 | ||
;; | ||
;; Unless required by applicable law or agreed to in writing, software | ||
;; distributed under the License is distributed on an "AS IS" BASIS, | ||
;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
;; See the License for the specific language governing permissions and | ||
;; limitations under the License. | ||
|
||
(ns wunderboss.caching-test | ||
(:require [clojure.test :refer :all]) | ||
(:import org.projectodd.wunderboss.WunderBoss | ||
[org.projectodd.wunderboss.caching Caching | ||
Caching$CreateOption Config KeyEquivalenceCache] | ||
org.projectodd.wunderboss.Options | ||
org.infinispan.configuration.cache.CacheMode | ||
java.util.Arrays)) | ||
|
||
(set! Config/className "org.projectodd.wunderboss.caching.Config5") | ||
|
||
(def default (doto (WunderBoss/findOrCreateComponent Caching) (.start))) | ||
|
||
(deftest byte-array-keys | ||
(let [c (KeyEquivalenceCache. (.findOrCreate default "bytes" (Options.))) | ||
k (byte-array [1 2 3]) | ||
v (byte-array [4 5 6])] | ||
(.put c k v) | ||
(is (Arrays/equals (byte-array [4 5 6]) (get c (byte-array [1 2 3])))))) | ||
|
||
(deftest mode-local-if-not-clustered | ||
(let [options (Options. {Caching$CreateOption/MODE "repl_sync"}) | ||
config (Config/uration options) | ||
c (.findOrCreate default "repl" options)] | ||
(is (= CacheMode/REPL_SYNC (.. config clustering cacheMode))) | ||
(is (= CacheMode/LOCAL (.. c getCacheConfiguration clustering cacheMode))))) | ||
|
30 changes: 30 additions & 0 deletions
30
modules/caching-ispan5/src/test/clojure/wunderboss/config_test.clj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
;; Copyright 2014-2015 Red Hat, Inc, and individual contributors. | ||
;; | ||
;; Licensed under the Apache License, Version 2.0 (the "License"); | ||
;; you may not use this file except in compliance with the License. | ||
;; You may obtain a copy of the License at | ||
;; | ||
;; http://www.apache.org/licenses/LICENSE-2.0 | ||
;; | ||
;; Unless required by applicable law or agreed to in writing, software | ||
;; distributed under the License is distributed on an "AS IS" BASIS, | ||
;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
;; See the License for the specific language governing permissions and | ||
;; limitations under the License. | ||
|
||
(ns wunderboss.config-test | ||
(:require [clojure.test :refer :all]) | ||
(:import [org.projectodd.wunderboss.caching Caching$CreateOption Config] | ||
org.projectodd.wunderboss.Options)) | ||
|
||
(set! Config/className "org.projectodd.wunderboss.caching.Config5") | ||
|
||
(deftest persistence | ||
(is (not (.. (Config/uration (Options.)) | ||
loaders usingCacheLoaders))) | ||
(is (not (.. (Config/uration (Options. {Caching$CreateOption/PERSIST false})) | ||
loaders usingCacheLoaders))) | ||
(is (.. (Config/uration (Options. {Caching$CreateOption/PERSIST true})) | ||
loaders usingCacheLoaders)) | ||
(is (.. (Config/uration (Options. {Caching$CreateOption/PERSIST "foo"})) | ||
loaders usingCacheLoaders))) |
Oops, something went wrong.