package org.quickbundle.base.cache;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import javax.jws.WebService;
import org.quickbundle.itf.cache.IRmCacheHandler;
import org.quickbundle.itf.cache.IRmCacheListener;
import org.quickbundle.tools.support.log.RmLogHelper;
import org.slf4j.Logger;
@WebService(endpointInterface = "org.quickbundle.itf.cache.IRmCacheHandler")
public class RmCacheHandler<T> implements IRmCacheHandler<T>{
/**
* 线程池的最大容量
*/
public final static int MAX_THREAD_COUNT = 10;
/**
* 分布式缓存的log入口类
*/
public final static Logger logCache = RmLogHelper.getLogger("rmcache");
/**
* 线程池
*/
private ExecutorService threadPool = Executors.newFixedThreadPool(MAX_THREAD_COUNT, cacheThreadFactory);
private static Set<RmCacheHandler.FlushTask> sFlushTask = new CopyOnWriteArraySet<RmCacheHandler.FlushTask>();
private RmCacheHandler() {
}
/**
* 集群模式下的缓存刷新实现,被其他节点调用
*
* @param cacheClassName
* @param flushType
* @param keys
*/
public String reflectFlush(Class<T> cacheClassName, String flushType, Object... keys) {
String result = null;
try {
Method methodGs = cacheClassName.getMethod("getSingleton");
IRmCacheListener cl = (IRmCacheListener)methodGs.invoke(cacheClassName);
result = cl.flushCache(flushType, keys);
logCache.info(RmCacheHandler.class.getName() + ".reflectFlush(" + cacheClassName.getName() + ", " + flushType + ", " + Arrays.deepToString(keys) + "): " + result);
} catch (Exception e) {
logCache.error(RmCacheHandler.class.getName() + ".reflectFlush(" + cacheClassName.getName() + ", " + flushType + ", " + Arrays.deepToString(keys) + "): " + e.toString());
result = IRmCacheListener.Result.FAIL.pattern();
}
return result;
}
/**
* 本地缓存更新后,调用此方法通知远程的兄弟节点刷新缓存
*
* @param <T>
* @param cacheClassName
* @param flushType
* @param keys
*/
public void flushOtherNodes(final Class<T> cacheClassName, final String flushType, final Object... keys) {
//TODO
/*
sFlushTask.add(new RmCacheHandler.FlushTask(cacheClassName, flushType, keys));
final Map<String, String> mOther = RmClusterConfig.getOtherWsUrl();
for (final String nodeId : mOther.keySet()) {
String wsUrl = mOther.get(nodeId);
final String soaUrl = wsUrl + "RmCacheHandler";
Runnable task = new Runnable() {
public void run() {
try {
RmCacheHandler.FlushTask ftThis = new RmCacheHandler.FlushTask(cacheClassName, flushType, keys);
if(sFlushTask.contains(ftThis)) {
sFlushTask.remove(ftThis);
JaxWsProxyFactoryBean jw = new JaxWsProxyFactoryBean();
jw.setServiceClass(IRmCacheHandler.class);
jw.setAddress(soaUrl);
RmClusterConfig.appendAuth(jw, nodeId);
IRmCacheHandler ch = (IRmCacheHandler) jw.create();
ch.reflectFlush(cacheClassName, flushType, keys);
logCache.info(RmCacheHandler.class.getName() + ".flushOtherNodes(" + cacheClassName.getName() + ", " + flushType + ", " + Arrays.deepToString(keys) + "): " + mOther);
} else {
logCache.debug("ignore " + RmCacheHandler.class.getName() + ".flushOtherNodes(" + cacheClassName.getName() + ", " + flushType + ", " + Arrays.deepToString(keys) + "): " + mOther);
}
} catch (Exception e) {
//e.printStackTrace();
logCache.error(RmCacheHandler.class.getName() + ".flushOtherNodes(" + cacheClassName.getName() + ", " + flushType + ", " + Arrays.deepToString(keys) + "): " + e.toString());
}
}
};
threadPool.execute(task);
}
*/
}
/**
* 销毁缓存处理器,安全关闭线程池
*/
public void showdown() {
threadPool.shutdownNow();
}
/**
* The default thread factory
*/
static class CacheThreadFactory implements ThreadFactory {
final ThreadGroup group;
final AtomicInteger threadNumber = new AtomicInteger(1);
final String namePrefix;
CacheThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null)? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
namePrefix = "RM-CacheHandler-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
if (t.isDaemon()) {
t.setDaemon(false);
}
if (t.getPriority() != Thread.NORM_PRIORITY) {
t.setPriority(Thread.NORM_PRIORITY);
}
return t;
}
}
static CacheThreadFactory cacheThreadFactory = new CacheThreadFactory();
/**
* 默认实例
*/
private static RmCacheHandler singleton = new RmCacheHandler();
public static RmCacheHandler getSingleton() {
return singleton;
}
class FlushTask {
private Class cacheClassName;
private String flushType;
private Object[] keys;
public FlushTask(Class cacheClassName, String flushType, Object... keys) {
this.cacheClassName = cacheClassName;
this.flushType = flushType;
this.keys = keys;
}
@Override
public int hashCode() {
int result = 0;
if(cacheClassName != null) {
result += cacheClassName.hashCode() * 29;
}
if(flushType != null) {
result += flushType.hashCode() * 29;
}
if(keys != null) {
result += Arrays.deepToString(keys).hashCode() * 29;
}
return result;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof RmCacheHandler.FlushTask) {
RmCacheHandler.FlushTask ft = (RmCacheHandler.FlushTask)obj;
if(cacheClassName == null) {
if(ft.cacheClassName != null) {
return false;
}
} else {
return cacheClassName.equals(ft.cacheClassName);
}
if(flushType == null) {
if(ft.flushType != null) {
return false;
}
} else {
return flushType.equals(ft.flushType);
}
if(keys == null) {
if(ft.keys != null) {
return false;
}
} else {
return keys.equals(ft.keys);
}
} else {
return false;
}
return true;
}
}
}