package org.radargun.service;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import org.infinispan.AdvancedCache;
import org.infinispan.container.DataContainer;
import org.infinispan.distribution.DistributionManager;
import org.infinispan.factories.ComponentRegistry;
import org.radargun.traits.Debugable;
import org.radargun.logging.Level;
import org.radargun.logging.Log;
import org.radargun.logging.LogFactory;
/**
* @author Radim Vansa <rvansa@redhat.com>
*/
public class InfinispanDebugable implements Debugable {
protected final Log log = LogFactory.getLog(getClass());
protected final boolean trace = log.isTraceEnabled();
protected final InfinispanEmbeddedService service;
public InfinispanDebugable(InfinispanEmbeddedService service) {
this.service = service;
}
@Override
public Debugable.Cache getCache(String cacheName) {
return new Cache(service.getCache(cacheName).getAdvancedCache());
}
protected String[] getDebugKeyPackages() {
return new String[] { "org.infinispan", "org.jgroups" };
}
protected String[] getDebugKeyClassesTraceFix() {
return new String[] { "org.infinispan.container.EntryFactoryImpl" };
}
private void setTraceField(ComponentRegistry registry, String clazzName, boolean value) {
/* Use -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=exclude,my/package/MyClass,myMethod */
try {
Class<?> clazz = Class.forName(clazzName);
Field traceField = clazz.getDeclaredField("trace");
traceField.setAccessible(true);
Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
modifiers.setInt(traceField, traceField.getModifiers() & ~Modifier.FINAL);
if (Modifier.isStatic(traceField.getModifiers())) {
traceField.setBoolean(null, value);
} else {
// if this is instance-variable, try to get instance from registry
Object component = null;
component = registry.getComponent(clazz);
if (component == null) {
Class<?>[] ifaces = clazz.getInterfaces();
if (ifaces.length > 0) {
component = registry.getComponent(ifaces[0]);
}
}
if (component == null) {
log.warn("No instance can be found for " + clazzName);
} else if (!clazz.isAssignableFrom(component.getClass())) {
log.warn("The actual instance is not " + clazzName + ", it is " + component.getClass().getName());
} else {
traceField.setBoolean(component, value);
}
}
} catch (ClassNotFoundException e) {
log.warn("Failed to set " + clazzName + "trace=" + value + " (cannot load class)", e);
} catch (NoSuchFieldException e) {
log.warn("Failed to set " + clazzName + "trace=" + value + " (cannot find field)", e);
} catch (SecurityException e) {
log.warn("Failed to set " + clazzName + "trace=" + value + " (cannot access field)", e);
} catch (IllegalAccessException e) {
log.warn("Failed to set " + clazzName + "trace=" + value + " (cannot write field)", e);
} catch (Throwable e) {
log.warn("Failed to set " + clazzName + "trace=" + value, e);
}
}
protected class Cache<K> implements Debugable.Cache<K> {
protected final AdvancedCache cache;
public Cache(AdvancedCache cache) {
this.cache = cache;
}
@Override
public void debugKey(K key) {
try {
log.debug(service.getKeyInfo(cache, key));
List<Level> levels = new ArrayList<Level>();
String[] debugPackages = getDebugKeyPackages();
ComponentRegistry componentRegistry = cache.getComponentRegistry();
try {
for (String pkg : debugPackages) {
Log logger = LogFactory.getLog(pkg);
levels.add(logger.getLevel());
logger.setLevel(Level.TRACE);
}
for (String clazz : getDebugKeyClassesTraceFix()) {
setTraceField(componentRegistry, clazz, true);
}
cache.get(key);
} finally {
int i = 0;
for (Level l : levels) {
LogFactory.getLog(debugPackages[i]).setLevel(l);
++i;
}
for (String clazz : getDebugKeyClassesTraceFix()) {
setTraceField(componentRegistry, clazz, false);
}
}
} catch (Throwable t) {
log.error("Debugging key " + key + " failed", t);
}
}
@Override
public void debugInfo() {
DistributionManager dm = cache.getDistributionManager();
DataContainer container = cache.getDataContainer();
StringBuilder sb = new StringBuilder(256);
sb.append("Debug info for ").append(cache.getName()).append(": joinComplete=").append(dm.isJoinComplete());
sb.append(", rehashInProgress=").append(dm.isRehashInProgress());
sb.append(", numEntries=").append(container.size());
sb.append(service.getCHInfo(dm));
log.debug(sb.toString());
}
}
}