SnmpRequestSensitiveDispatchCollection.java
package eu.linuxengineering.snmp;
import java.util.NavigableMap;
import java.util.TreeMap;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import eu.javaexperience.collection.map.KeyVal;
import eu.javaexperience.interfaces.simple.getBy.GetBy1;
import eu.javaexperience.log.JavaExperienceLoggingFacility;
import eu.javaexperience.log.LogLevel;
import eu.javaexperience.log.Loggable;
import eu.javaexperience.log.Logger;
import eu.javaexperience.log.LoggingTools;
import net.sf.snmpadaptor4j.api.AttributeAccessor;
import net.sf.snmpadaptor4j.object.SnmpOid;
public class SnmpRequestSensitiveDispatchCollection implements SnmpNode
{
protected static final Logger LOG = JavaExperienceLoggingFacility.getLogger(new Loggable("SnmpRequestSensitiveDispatchCollection"));
protected ConcurrentMap<SnmpOid, Entry<Integer, SnmpNode>> nodeCache = new ConcurrentHashMap<>();
protected NavigableMap<Integer, GetBy1<SnmpNode, SnmpOid>> nodeFactories = Collections.synchronizedNavigableMap
(
new TreeMap<>()
);
public SnmpRequestSensitiveDispatchCollection(){}
public void addNodeFactory
(
Integer index,
GetBy1<SnmpNode, SnmpOid> factory
)
{
nodeFactories.put(index, factory);
}
public void addNodeFactory
(
Integer index,
SnmpNode node
)
{
nodeFactories.put(index, (a)->node);
}
@Override
public Entry<Integer, SnmpNode> getSubNodeGte(SnmpPathDispatch dispatch)
{
SnmpOid oid = SnmpOid.newInstance(dispatch.copyCurrentPath());
dispatch.jumpNextNode();
Entry<Integer, SnmpNode> ret = nodeCache.get(oid);
if(null == ret)
{
int[] roid = oid.getOid();
roid = Arrays.copyOf(roid, roid.length);
Integer index = roid[roid.length-1];
Entry<Integer, GetBy1<SnmpNode, SnmpOid>> creEnt = nodeFactories.ceilingEntry(index);
if(null == creEnt)
{
LoggingTools.tryLogFormat(LOG, LogLevel.TRACE, "Requesting oid `%s` returns: null", oid);
//TODO accumulate cache miss
return null;
}
int dst = creEnt.getKey();
roid[roid.length-1] = creEnt.getKey();
SnmpOid actOid = SnmpOid.newInstance(roid);
Entry<Integer, SnmpNode> add = new KeyVal<>(creEnt.getKey(), creEnt.getValue().getBy(actOid));
//populate intermedaite element, therefor result an instant cache hit.
for(int i=index;i <= dst;++i)
{
roid[roid.length-1] = i;
nodeCache.put
(
SnmpOid.newInstance(Arrays.copyOf(roid, roid.length)),
add
);
}
ret = add;
}
LoggingTools.tryLogFormat(LOG, LogLevel.TRACE, "Requesting oid `%s` returns: `%s`: `%s`", oid, ret.getKey(), ret.getValue());
return ret;
}
@Override
public boolean hasSubNodes()
{
return true;
}
@Override
public AttributeAccessor getAccessor()
{
return null;
}
}