I tested it on my development machine, it works. But I have not do any stress test to compare this implementation and the previous implement. If anybody is going to do it, please post the result here.
Here is the code for the two classes: provider and cache.
/**
* Memcached plugin for Hibernate
* configuration (hibernate.cfg.xml)
*
< pproperty name="memcached.servers" > 192.168.1.2:11211,192.168.1.3:11211 < /pproperty >
< pproperty name="memcached.failover" > true < /pproperty >
< pproperty name="memcached.initConn" > 10 < /pproperty >
< pproperty name="memcached.minConn" > 10 < /pproperty >
< pproperty name="memcached.maxConn" > 1000 < /pproperty >
< pproperty name="memcached.maintSleep" > 30 < /pproperty >
< pproperty name="memcached.nagle" > false < /pproperty >
< pproperty name="memcached.socketTO" > 3000 < /pproperty >
< pproperty name="memcached.aliveCheck" > true < /pproperty >
< pproperty name="memcached.[cache_name_as_full_classname]" > 10s|20m|30h|40d < /pproperty >
*
*/
public class MemcachedHibernateCacheProvider2 implements CacheProvider {
private static final Log log = LogFactory.getLog(MemcachedHibernateCacheProvider2.class);
public final static String DEFAULT_CACHE_NAME="____DEFAULT_CACHE_REGION";
public static String serverlist;
private Hashtable
/* (non-Javadoc)
* @see org.hibernate.cache.CacheProvider#start(java.util.Properties)
*/
public void start(Properties props) throws CacheException {
String servers = props.getProperty("memcached.servers");
//log.debug("*** --- *** server is "+ servers);
serverlist = servers.replace(',', ' ');
log.debug("*** --- *** server is "+ serverlist);
//System.out.println("*** --- *** server is "+ serverlist);
//if(StringUtils.isBlank(servers)){
if(servers==null || servers.trim().length()==0) {
throw new CacheException("configuration 'memcached.servers' get a empty value");
}
}
/* (non-Javadoc)
* @see org.hibernate.cache.CacheProvider#buildCache(java.lang.String, java.util.Properties)
*/
public Cache buildCache(String cacheName, Properties props) throws CacheException {
if((cacheName==null || cacheName.trim().length()==0))
cacheName = DEFAULT_CACHE_NAME;
MemcachedCache2 mCache = cacheManager.get(cacheName);
if(mCache == null){
String timeToLive = props.getProperty("memcached."+cacheName);
int secondToLive = -1;
//if(StringUtils.isNotBlank(timeToLive)){
if(timeToLive!=null && timeToLive.trim().length()>0){
timeToLive = timeToLive.toLowerCase().trim();
secondToLive = getSeconds(timeToLive);
}
System.out.println("=== Building cache named "+cacheName+" using secondToLive is "+secondToLive);
try{
mCache = new MemcachedCache2(serverlist, cacheName, secondToLive);
cacheManager.put(cacheName, mCache);
}catch(Exception e){
throw new CacheException(e);
//cacheManager.put(cacheName, cacheManager.get(DEFAULT_CACHE_NAME));
}
}
return mCache;
}
private static int getSeconds(String str){
try{
switch(str.charAt(str.length()-1)){
case 's':
return Integer.parseInt(str.substring(0, str.length()-1));
case 'm':
return Integer.parseInt(str.substring(0, str.length()-1)) * 60;
case 'h':
return Integer.parseInt(str.substring(0, str.length()-1)) * 3600;
case 'd':
return Integer.parseInt(str.substring(0, str.length()-1)) * 86400;
default:
return Integer.parseInt(str);
}
}catch(NumberFormatException e){
log.warn("Illegal configuration value : " + str, e);
}
return -1;
}
/* (non-Javadoc)
* @see org.hibernate.cache.CacheProvider#stop()
*/
public void stop() {
}
/* (non-Javadoc)
* @see org.hibernate.cache.CacheProvider#isMinimalPutsEnabledByDefault()
*/
public boolean isMinimalPutsEnabledByDefault() {
return false;
}
/* (non-Javadoc)
* @see org.hibernate.cache.CacheProvider#nextTimestamp()
*/
public long nextTimestamp() {
return Timestamper.next();
}
}
----------------------------------------------------------------------------------------
/**
* Cache plugin for Hibernate
* @author Hank Li
*/
public class MemcachedCache2 implements Cache {
private static final Log log = LogFactory.getLog(MemcachedCache2.class);
private static final int SIXTY_THOUSAND_MS = 60000;
private MemcachedClient mc;
private int secondToLive;
private String cacheName;
/**
* Creates a new Hibernate pluggable cache based on a cache name.
*
*/
public MemcachedCache2(String serverlist, String name, int secondToLive)
throws IOException {
mc = new MemcachedClient(AddrUtil.getAddresses(serverlist));
this.secondToLive = secondToLive;
this.cacheName = name + '_';
}
private String makeupKey(Object key) {
return cacheName + String.valueOf(key).hashCode();
}
/**
* Gets a value of an element which matches the given key.
*
* @param key
* the key of the element to return.
* @return The value placed into the cache with an earlier put, or null if
* not found or expired
* @throws CacheException
*/
public Object get(Object key) throws CacheException {
//log.debug("key: " + key);
System.out.println("*** key: " + key);
if (key == null) {
return null;
} else {
//Object rt = mc.get(makeupKey(key));
// Try to get a value, for up to 2 seconds, and cancel if it doesn't return
Object rt=null;
//synchronized way
try {
rt=mc.get(makeupKey(key));
}catch(Exception alle){
System.out.println("memcached exception"+alle);
throw new CacheException(alle);
}
/* asynchronized way
java.util.concurrent.Future
No comments:
Post a Comment