package org.jboss.cache.eviction;
import org.jboss.cache.Fqn;
import org.jboss.cache.TreeCache;
import org.jboss.cache.TreeCacheListener;
import org.jboss.logging.Logger;
import org.jgroups.View;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import java.util.Timer;
public class LRUPolicy extends BaseEvictionPolicy implements TreeCacheListener
{
protected Logger log_ = Logger.getLogger(LRUPolicy.class);
static final int WAKEUP_DEFAULT = 5;
final static String ATTR = "attribute";
static final String NAME = "name";
static final Fqn ROOT =new Fqn("/");
private int wakeUpIntervalSeconds_;
private RegionValue[] regionValues_;
private Timer timer_;
public LRUPolicy() {
super();
}
public void nodeAdded(Fqn fqn)
{
if(fqn.equals(ROOT)) return;
if(log_.isTraceEnabled()) {
log_.trace("nodeAdded(): fqn- " +fqn);
}
Region region = regionManager_.getRegion(fqn.toString());
region.setAddedNode(fqn);
}
public void nodeRemoved(Fqn fqn)
{
if(log_.isTraceEnabled()) {
log_.trace("nodeRemoved(): fqn- " +fqn );
}
Region region = regionManager_.getRegion(fqn.toString());
region.setRemovedNode(fqn);
}
public void nodeEvicted(Fqn fqn) {
;
}
public void nodeModified(Fqn fqn)
{
if(log_.isTraceEnabled()) {
log_.trace("nodeModified(): redirecting to node visited. fqn- " +fqn);
}
nodeVisited(fqn);
}
public void nodeLoaded(Fqn fqn) {
}
public void nodeCreated(Fqn fqn) {
nodeAdded(fqn);
}
public void nodeVisited(Fqn fqn)
{
if(log_.isTraceEnabled()) {
log_.trace("nodeVisited(): fqn- " +fqn);
}
Region region = regionManager_.getRegion(fqn.toString());
region.setVisitedNode(fqn);
}
public void cacheStarted(TreeCache cache)
{
log_.info("Starting eviction policy using the provider: " +this.getClass().getName());
log_.info("Starting a eviction timer with wake up interval of (secs) "
+wakeUpIntervalSeconds_);
timer_ = new Timer();
timer_.schedule( new EvictionTimerTask(this), wakeUpIntervalSeconds_ *1000,
wakeUpIntervalSeconds_ *1000);
}
protected EvictionAlgorithm getEvictionAlgorithm() {
return new LRUAlgorithm();
}
private void parseConfig(Element elem)
{
String REGION = "region";
wakeUpIntervalSeconds_ = Integer.parseInt(getAttr(elem, "wakeUpIntervalSeconds"));
if( wakeUpIntervalSeconds_ <= 0 ) wakeUpIntervalSeconds_ = WAKEUP_DEFAULT;
NodeList list=elem.getElementsByTagName(REGION);
regionValues_ = new RegionValue[list.getLength()];
for(int i=0; i < list.getLength(); i++) {
RegionValue val = new RegionValue();
org.w3c.dom.Node node = list.item(i);
if(node.getNodeType() != org.w3c.dom.Node.ELEMENT_NODE)
continue;
Element element=(Element)node;
String name=element.getAttribute(NAME);
val.name_ = name;
val.maxNodes_ = Integer.parseInt(getAttr(element, "maxNodes"));
String timeToLive = getAttr(element, "timeToIdleSeconds");
if(timeToLive == null) {
timeToLive = getAttr(element, "timeToLiveSeconds");
if(timeToLive == null)
throw new RuntimeException("LRUPolicy.parseConfig(): Null timeToLiveSeconds element");
}
val.timeToLiveSeconds_ = Integer.parseInt(timeToLive);
if(log_.isDebugEnabled()) {
log_.debug("parseConfig: name -- " +name + " maxNodes -- "
+val.maxNodes_ + " timeToLiveSeconds -- " +val.timeToLiveSeconds_ );
}
regionValues_[i] = val;
}
}
private String getAttr(Element elem, String myName)
{
NodeList list=elem.getElementsByTagName(ATTR);
for(int s=0; s < list.getLength(); s++) {
org.w3c.dom.Node node=list.item(s);
if(node.getNodeType() != org.w3c.dom.Node.ELEMENT_NODE)
continue;
Element element=(Element)node;
String name=element.getAttribute(NAME);
if( name.equals(myName)) {
String valueStr=getElementContent(element, true);
return valueStr;
}
}
return null;
}
private String getElementContent(Element element, boolean trim)
{
NodeList nl=element.getChildNodes();
String attributeText="";
for(int i=0; i < nl.getLength(); i++) {
Node n=nl.item(i);
if(n instanceof Text) {
attributeText+=((Text)n).getData();
}
} if(trim)
attributeText=attributeText.trim();
return attributeText;
}
public void cacheStopped(TreeCache cache)
{
log_.info("Stopping eviction policy timer ... ");
timer_.cancel();
}
public void viewChange(View new_view) {
}
public int getWakeupIntervalSeconds()
{
return wakeUpIntervalSeconds_;
}
public void configure(TreeCache cache)
{
cache_ = cache;
Element elem = cache.getEvictionPolicyConfig();
parseConfig(elem);
regionManager_ = new RegionManager(this);
for(int i=0; i< regionValues_.length; i++) {
EvictionAlgorithm algo = getEvictionAlgorithm();
try {
Region region = regionManager_.createRegion(regionValues_[i].name_, algo);
region.setMaxNodes(regionValues_[i].maxNodes_ );
region.setTimeToLiveSeconds(regionValues_[i].timeToLiveSeconds_);
} catch (RegionNameConflictException e) {
throw new RuntimeException(
"LRUPolicy.cacheStarted(): illegal region name specified for eviction policy "
+ " exception: " +e);
}
}
}
static class RegionValue {
String name_;
int maxNodes_;
int timeToLiveSeconds_;
}
}