Skip to content

Commit c937409

Browse files
committed
fix #13 #9
1 parent 1ae0ce5 commit c937409

File tree

6 files changed

+170
-51
lines changed

6 files changed

+170
-51
lines changed

src/main/java/com/mc/hibernate/memcached/Config.java

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,78 +15,77 @@
1515

1616
package com.mc.hibernate.memcached;
1717

18+
import com.mc.hibernate.memcached.keystrategy.KeyStrategy;
1819
import com.mc.hibernate.memcached.keystrategy.Sha1KeyStrategy;
20+
import org.slf4j.Logger;
21+
import org.slf4j.LoggerFactory;
1922

2023
public class Config {
2124

25+
private final Logger log = LoggerFactory.getLogger(Config.class);
26+
2227
public static final String PROP_PREFIX = "hibernate.memcached.";
2328

2429
private static final String CACHE_TIME_SECONDS = "cacheTimeSeconds";
25-
public static final String PROP_CACHE_TIME_SECONDS = PROP_PREFIX + CACHE_TIME_SECONDS;
26-
2730
private static final String CLEAR_SUPPORTED = "clearSupported";
28-
public static final String PROP_CLEAR_SUPPORTED = PROP_PREFIX + CLEAR_SUPPORTED;
29-
3031
private static final String MEMCACHE_CLIENT_FACTORY = "memcacheClientFactory";
31-
public static final String PROP_MEMCACHE_CLIENT_FACTORY = PROP_PREFIX + MEMCACHE_CLIENT_FACTORY;
32-
3332
private static final String DOGPILE_PREVENTION = "dogpilePrevention";
34-
public static final String PROP_DOGPILE_PREVENTION = PROP_PREFIX + DOGPILE_PREVENTION;
35-
3633
private static final String DOGPILE_PREVENTION_EXPIRATION_FACTOR = "dogpilePrevention.expirationFactor";
37-
public static final String PROP_DOGPILE_PREVENTION_EXPIRATION_FACTOR = PROP_PREFIX + DOGPILE_PREVENTION_EXPIRATION_FACTOR;
38-
3934
private static final String KEY_STRATEGY = "keyStrategy";
4035

41-
public static final int DEFAULT_CACHE_TIME_SECONDS = 300;
42-
public static final boolean DEFAULT_CLEAR_SUPPORTED = false;
43-
public static final boolean DEFAULT_DOGPILE_PREVENTION = false;
44-
public static final String DEFAULT_MEMCACHE_CLIENT_FACTORY = "com.mc.hibernate.memcached.spymemcached.SpyMemcacheClientFactory";
36+
private static final int DEFAULT_CACHE_TIME_SECONDS = 300;
37+
private static final boolean DEFAULT_CLEAR_SUPPORTED = false;
38+
private static final boolean DEFAULT_DOGPILE_PREVENTION = false;
39+
private static final int DEFAULT_DOGPILE_EXPIRATION_FACTOR = 2;
40+
private static final String DEFAULT_MEMCACHE_CLIENT_FACTORY = "com.mc.hibernate.memcached.spymemcached.SpyMemcacheClientFactory";
4541

4642
private PropertiesHelper props;
47-
private static final int DEFAULT_DOGPILE_EXPIRATION_FACTOR = 2;
4843

4944
public Config(PropertiesHelper props) {
5045
this.props = props;
5146
}
5247

5348
public int getCacheTimeSeconds(String cacheRegion) {
54-
int globalCacheTimeSeconds = props.getInt(PROP_CACHE_TIME_SECONDS,
55-
DEFAULT_CACHE_TIME_SECONDS);
56-
return props.getInt(cacheRegionPrefix(cacheRegion) + CACHE_TIME_SECONDS,
57-
globalCacheTimeSeconds);
49+
int globalCacheTimeSeconds = props.getInt(PROP_PREFIX + CACHE_TIME_SECONDS, DEFAULT_CACHE_TIME_SECONDS);
50+
return props.getInt(cacheRegionPrefix(cacheRegion) + CACHE_TIME_SECONDS, globalCacheTimeSeconds);
5851
}
5952

6053
public String getKeyStrategyName(String cacheRegion) {
61-
String globalKeyStrategy = props.get(PROP_PREFIX + KEY_STRATEGY,
62-
Sha1KeyStrategy.class.getName());
54+
String globalKeyStrategy = props.get(PROP_PREFIX + KEY_STRATEGY, Sha1KeyStrategy.class.getName());
6355
return props.get(cacheRegionPrefix(cacheRegion) + KEY_STRATEGY, globalKeyStrategy);
6456
}
6557

58+
private KeyStrategy instantiateKeyStrategy(String cls) {
59+
try {
60+
return (KeyStrategy) Class.forName(cls).newInstance();
61+
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
62+
log.warn("Could not instantiate keyStrategy class " + cls + ". Will use default: Sha1KeyStrategy", e);
63+
}
64+
return new Sha1KeyStrategy();
65+
}
66+
67+
public KeyStrategy getKeyStrategy(String cacheRegion) {
68+
String strategyClassName = getKeyStrategyName(cacheRegion);
69+
return instantiateKeyStrategy(strategyClassName);
70+
}
71+
6672
public boolean isClearSupported(String cacheRegion) {
67-
boolean globalClearSupported = props.getBoolean(PROP_CLEAR_SUPPORTED,
68-
DEFAULT_CLEAR_SUPPORTED);
69-
return props.getBoolean(cacheRegionPrefix(cacheRegion) + CLEAR_SUPPORTED,
70-
globalClearSupported);
73+
boolean globalClearSupported = props.getBoolean(PROP_PREFIX + CLEAR_SUPPORTED, DEFAULT_CLEAR_SUPPORTED);
74+
return props.getBoolean(cacheRegionPrefix(cacheRegion) + CLEAR_SUPPORTED, globalClearSupported);
7175
}
7276

7377
public boolean isDogpilePreventionEnabled(String cacheRegion) {
74-
boolean globalDogpilePrevention = props.getBoolean(PROP_DOGPILE_PREVENTION,
75-
DEFAULT_DOGPILE_PREVENTION);
76-
return props.getBoolean(cacheRegionPrefix(cacheRegion) + DOGPILE_PREVENTION,
77-
globalDogpilePrevention);
78+
boolean globalDogpilePrevention = props.getBoolean(PROP_PREFIX + DOGPILE_PREVENTION, DEFAULT_DOGPILE_PREVENTION);
79+
return props.getBoolean(cacheRegionPrefix(cacheRegion) + DOGPILE_PREVENTION, globalDogpilePrevention);
7880
}
7981

8082
public double getDogpilePreventionExpirationFactor(String cacheRegion) {
81-
double globalFactor = props.getDouble(PROP_DOGPILE_PREVENTION_EXPIRATION_FACTOR,
82-
DEFAULT_DOGPILE_EXPIRATION_FACTOR);
83-
return props.getDouble(cacheRegionPrefix(cacheRegion) + DOGPILE_PREVENTION_EXPIRATION_FACTOR,
84-
globalFactor);
83+
double globalFactor = props.getDouble(PROP_PREFIX + DOGPILE_PREVENTION_EXPIRATION_FACTOR, DEFAULT_DOGPILE_EXPIRATION_FACTOR);
84+
return props.getDouble(cacheRegionPrefix(cacheRegion) + DOGPILE_PREVENTION_EXPIRATION_FACTOR, globalFactor);
8585
}
8686

8787
public String getMemcachedClientFactoryName() {
88-
return props.get(PROP_MEMCACHE_CLIENT_FACTORY,
89-
DEFAULT_MEMCACHE_CLIENT_FACTORY);
88+
return props.get(PROP_PREFIX + MEMCACHE_CLIENT_FACTORY, DEFAULT_MEMCACHE_CLIENT_FACTORY);
9089
}
9190

9291
private String cacheRegionPrefix(String cacheRegion) {
@@ -96,4 +95,4 @@ private String cacheRegionPrefix(String cacheRegion) {
9695
public PropertiesHelper getPropertiesHelper() {
9796
return props;
9897
}
99-
}
98+
}

src/main/java/com/mc/hibernate/memcached/MemcachedCache.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,26 @@ public class MemcachedCache {
6565
public MemcachedCache(String regionName, Memcache memcachedClient, Config config) {
6666
this.regionName = (regionName != null) ? regionName : "default";
6767
this.memcache = memcachedClient;
68-
this.cacheTimeSeconds = config.getCacheTimeSeconds(this.regionName);
6968
clearIndexKey = this.regionName.replaceAll("\\s", "") + ":index_key";
69+
70+
configureInstance(config);
7071
}
7172

73+
private void configureInstance(Config config) {
74+
75+
this.cacheTimeSeconds = config.getCacheTimeSeconds(this.regionName);
76+
77+
this.clearSupported = config.isClearSupported(this.regionName);
78+
79+
this.dogpilePreventionEnabled = config.isDogpilePreventionEnabled(this.regionName);
80+
if (this.dogpilePreventionEnabled) {
81+
this.dogpilePreventionExpirationFactor = config.getDogpilePreventionExpirationFactor(this.regionName);
82+
}
83+
84+
this.keyStrategy = config.getKeyStrategy(this.regionName);
85+
}
86+
87+
7288
public int getCacheTimeSeconds() {
7389
return cacheTimeSeconds;
7490
}
@@ -264,4 +280,4 @@ public KeyStrategy getKeyStrategy() {
264280
public void setKeyStrategy(KeyStrategy keyStrategy) {
265281
this.keyStrategy = keyStrategy;
266282
}
267-
}
283+
}

src/test/java/com/integration/com/mc/hibernate/memcached/spymemcached/SpyMemcacheIT.java

Lines changed: 84 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import com.mc.hibernate.memcached.Config;
44
import com.mc.hibernate.memcached.MemcachedCache;
55
import com.mc.hibernate.memcached.PropertiesHelper;
6+
import com.mc.hibernate.memcached.keystrategy.Md5KeyStrategy;
7+
import com.mc.hibernate.memcached.keystrategy.Sha1KeyStrategy;
68
import com.mc.hibernate.memcached.spymemcached.SpyMemcache;
79
import net.spy.memcached.AddrUtil;
810
import net.spy.memcached.MemcachedClient;
@@ -36,21 +38,96 @@ public void tearDown() {
3638
}
3739

3840
@Test
39-
public void test() throws InterruptedException {
40-
cache.put("test", "value");
41+
public void testGetFromCache() throws InterruptedException {
42+
cache.put("test_1", "value");
4143
Thread.sleep(100);
42-
assertEquals("value", cache.get("test"));
44+
assertEquals("value", cache.get("test_1"));
4345
}
4446

4547
@Test
4648
public void testClear() throws InterruptedException {
4749
cache.setClearSupported(true);
48-
cache.put("test", "value");
50+
cache.put("test_2", "value");
4951
Thread.sleep(100);
50-
assertEquals("value", cache.get("test"));
52+
assertEquals("value", cache.get("test_2"));
5153
cache.clear();
5254
Thread.sleep(100);
53-
assertNull(cache.get("test"));
55+
assertNull(cache.get("test_2"));
5456
}
5557

56-
}
58+
@Test
59+
public void testPropertiesClear() throws InterruptedException {
60+
61+
Properties properties = new Properties();
62+
properties.put("hibernate.memcached.clearSupported", "true");
63+
PropertiesHelper props = new PropertiesHelper(properties);
64+
Config config = new Config(props);
65+
cache = new MemcachedCache("MemcachedCacheTest", new SpyMemcache(client), config);
66+
67+
cache.put("test_3", "value");
68+
Thread.sleep(100);
69+
assertEquals("value", cache.get("test_3"));
70+
71+
cache.clear();
72+
Thread.sleep(100);
73+
assertNull(cache.get("test_3"));
74+
}
75+
76+
@Test
77+
public void testPropertiesKeyStrategy() throws InterruptedException {
78+
79+
Properties properties = new Properties();
80+
properties.put("hibernate.memcached.keyStrategy", Md5KeyStrategy.class.getName());
81+
PropertiesHelper props = new PropertiesHelper(properties);
82+
Config config = new Config(props);
83+
MemcachedCache mc1 = new MemcachedCache("MemcachedCacheTest", new SpyMemcache(client), config);
84+
assertEquals(mc1.getKeyStrategy().getClass(), Md5KeyStrategy.class);
85+
String key = "test_md5_" + System.currentTimeMillis();
86+
mc1.put(key, "value");
87+
Thread.sleep(100);
88+
assertEquals("value", mc1.get(key));
89+
}
90+
91+
@Test
92+
public void testNoPropertyKeyStrategy() throws InterruptedException {
93+
94+
Properties properties = new Properties();
95+
properties.put("hibernate.memcached.keyStrategy", "InvalidClass");
96+
PropertiesHelper props = new PropertiesHelper(properties);
97+
Config config = new Config(props);
98+
MemcachedCache mc1 = new MemcachedCache("MemcachedCacheTest", new SpyMemcache(client), config);
99+
assertEquals(mc1.getKeyStrategy().getClass(), Sha1KeyStrategy.class);
100+
String key = "test_6" + System.currentTimeMillis();
101+
mc1.put(key, "value");
102+
Thread.sleep(100);
103+
assertEquals("value", mc1.get(key));
104+
}
105+
106+
@Test
107+
public void testInvalidPropertyKeyStrategy() throws InterruptedException {
108+
109+
Properties properties = new Properties();
110+
PropertiesHelper props = new PropertiesHelper(properties);
111+
Config config = new Config(props);
112+
MemcachedCache mc1 = new MemcachedCache("MemcachedCacheTest", new SpyMemcache(client), config);
113+
assertEquals(mc1.getKeyStrategy().getClass(), Sha1KeyStrategy.class);
114+
String key = "test_7" + System.currentTimeMillis();
115+
mc1.put(key, "value");
116+
Thread.sleep(100);
117+
assertEquals("value", mc1.get(key));
118+
}
119+
120+
121+
@Test
122+
public void testClearFalse() throws InterruptedException {
123+
cache.setClearSupported(false);
124+
cache.put("test_8", "value");
125+
Thread.sleep(100);
126+
assertEquals("value", cache.get("test_8"));
127+
cache.clear();
128+
Thread.sleep(100);
129+
assertEquals("value", cache.get("test_8"));
130+
}
131+
132+
133+
}

src/test/java/com/mc/hibernate/memcached/MemcachedCacheTest.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,23 @@ public void testDogpileCacheHit() {
6464
assertEquals(MemcachedCache.DOGPILE_TOKEN, mockCache.get(key + ".dogpileTokenKey"));
6565
}
6666

67-
}
67+
@Test
68+
public void testClearCacheWithProperties() {
69+
MockMemcached mockCache = new MockMemcached();
70+
Properties properties = new Properties();
71+
properties.put("hibernate.memcached.clearSupported", "true");
72+
Config config = new Config(new PropertiesHelper(properties));
73+
74+
cache = new MemcachedCache("region", mockCache, config);
75+
cache.put("test", "value");
76+
Object retrieved = cache.get("test");
77+
assertEquals("value", retrieved);
78+
79+
cache.clear();
80+
81+
Object retrievedAfterClean = cache.get("test");
82+
assertNull(retrievedAfterClean);
83+
}
84+
85+
86+
}

src/test/java/com/mc/hibernate/memcached/mock/MockMemcached.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,24 @@ public void delete(String key) {
2222
}
2323

2424
public void incr(String key, int factor, int startingValue) {
25-
Integer counter = (Integer) cache.get(key);
25+
String counter = (String) cache.get(key);
2626
if (counter != null) {
27-
cache.put(key, counter + 1);
27+
cache.put(key, Long.parseLong(counter) + 1);
2828
} else {
29-
cache.put(key, null);
29+
cache.put(key, String.valueOf(startingValue));
3030
}
3131
}
3232

3333
public void shutdown() {
3434

3535
}
3636

37-
3837
public Map<String, Object> getMulti(String... keys) {
3938
Map<String, Object> result = new HashMap<>();
4039
for (String key : keys) {
4140
result.put(key, cache.get(key));
4241
}
4342
return result;
4443
}
45-
}
44+
45+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Root logger option
2+
log4j.rootLogger=INFO, stdout
3+
4+
# Direct log messages to stdout
5+
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
6+
log4j.appender.stdout.Target=System.out
7+
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
8+
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

0 commit comments

Comments
 (0)