package org.jboss.cache.interceptors;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.jboss.cache.TreeCache;
import org.jboss.cache.loader.CacheLoader;
import org.jgroups.blocks.MethodCall;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class CacheLoaderInterceptor extends Interceptor {
private CacheLoader loader=null;
public void setCache(TreeCache cache) {
super.setCache(cache);
this.loader=cache.getCacheLoader();
}
public Object invoke(MethodCall m) throws Throwable {
Fqn fqn=null;
Node n=null;
Method meth=m.getMethod();
Object[] args=m.getArgs();
boolean load_attributes=false;
if(meth.equals(TreeCache.putDataMethodLocal) || meth.equals(TreeCache.putDataEraseMethodLocal) ||
meth.equals(TreeCache.putKeyValMethodLocal)) {
fqn=(Fqn)args[1];
load_attributes=true;
}
else if(meth.equals(TreeCache.removeNodeMethodLocal)) {
}
else if(meth.equals(TreeCache.removeKeyMethodLocal) || meth.equals(TreeCache.removeDataMethodLocal)) {
fqn=(Fqn)args[1];
load_attributes=true;
}
else if(meth.equals(TreeCache.addChildMethodLocal)) {
fqn=(Fqn)args[1];
}
else if(meth.equals(TreeCache.getKeyValueMethodLocal)) {
fqn=(Fqn)args[0];
load_attributes=true;
}
else if(meth.equals(TreeCache.getNodeMethodLocal)) {
fqn=(Fqn)args[0];
}
else if(meth.equals(TreeCache.getKeysMethodLocal)) {
fqn=(Fqn)args[0];
load_attributes=true;
}
else if(meth.equals(TreeCache.getChildrenNamesMethodLocal) || meth.equals(TreeCache.releaseAllLocksMethodLocal) ||
meth.equals(TreeCache.printMethodLocal)) {
fqn=(Fqn)args[0];
}
synchronized(this) {
if(fqn != null && (!cache.exists(fqn) || cache.exists(fqn, TreeCache.UNINITIALIZED))) {
n=loadNode(fqn);
if(load_attributes && n != null)
loadAttributesFromCacheLoader(n);
lock(fqn, Node.LOCK_TYPE_WRITE, false); }
if(meth.equals(TreeCache.getChildrenNamesMethodLocal) && n != null && fqn != null) {
Map children=n.getChildren();
if(children == null) {
Set children_names=null;
try {
children_names=loader.getChildrenNames(fqn);
}
catch(Exception e) {
log.error("failed getting the children names for " + fqn + " from the cache loader", e);
}
if(children_names != null) {
for(Iterator it=children_names.iterator(); it.hasNext();) {
String child_name=(String)it.next();
Fqn child_fqn=new Fqn(n.getFqn(), child_name);
n.createChild(child_name, child_fqn, n, TreeCache.UNINITIALIZED, null);
}
lock(fqn, Node.LOCK_TYPE_READ, true); }
}
}
}
return super.invoke(m);
}
private void lock(Fqn fqn, int lock_type, boolean recursive) throws Throwable {
MethodCall meth=new MethodCall(TreeCache.lockMethodLocal,
new Object[]{fqn,
new Integer(lock_type),
new Boolean(recursive)});
super.invoke(meth);
}
private Node loadNode(Fqn fqn) {
Node n, child_node=null;
Object child_name;
Fqn tmp_fqn=new Fqn();
if(fqn == null) return null;
int treeNodeSize=fqn.size();
n=cache.getRoot();
for(int i=0; i < treeNodeSize && n != null; i++) {
child_name=fqn.get(i);
tmp_fqn=new Fqn(tmp_fqn, child_name);
child_node=n.getChild(child_name);
if(child_node == null) {
try {
if(loader.exists(fqn)) {
child_node=n.createChild(child_name, tmp_fqn, n, TreeCache.UNINITIALIZED, null);
cache.notifyNodeLoaded(tmp_fqn);
}
}
catch(Throwable t) {
log.error("failed loading node " + fqn + " from CacheLoader", t);
}
}
n=child_node;
}
return n;
}
private void loadAttributesFromCacheLoader(Node n) {
if(n == null || !n.containsKey(TreeCache.UNINITIALIZED))
return;
try {
Map m=loader.get(n.getFqn());
n.remove(TreeCache.UNINITIALIZED); n.put(m);
}
catch(Throwable t) {
log.error("failure when lazily loading attributes of " + n.getFqn(), t);
}
}
}