package de.desy.tine.client;
import java.util.Iterator;
import java.util.LinkedList;
import de.desy.tine.client.TLinkFactory.RedirectedItem;
import de.desy.tine.dataUtils.TDataType;
import de.desy.tine.definitions.*;
import de.desy.tine.queryUtils.TQuery;
import de.desy.tine.server.logger.DbgLog;
import de.desy.tine.server.logger.MsgLog;
public class TWatchdogLink implements TLinkCallback
{
private static TLinkFactory tlf = null;
private static TLinkFactory getLinkFactory()
{
if (tlf == null) tlf = TLinkFactory.getInstance();
return tlf;
}
TLink tgt = null;
String key = null;
private static final String lwdProperty = "SRVSTARTTIME";
private static final String lwdTag = "WDOG";
static final int LWD_TIMER_DEADBAND = 5;
private int[] srvStartTime = new int[1];
private static int pollingInterval = 1000;
LinkedList <TLink>lnks = new LinkedList<TLink>();
private TWatchdogLink parent;
private int lastLinkStatus = 0;
public TWatchdogLink(TLink lnk)
{
key = "/"+lnk.cntName+"/"+lnk.expName;
if (lnk.isRedirected)
{
MsgLog.log("TWatchdogLink", "watchdog key "+key+" is redirected",0,null,0);
RedirectedItem rdr = TLinkFactory.getRedirectionInformation(lnk);
if (rdr == null)
{
MsgLog.log("TWatchdogLink", "redirected without valid redirection information",0,null,0);
return;
}
key = "/"+rdr.getDstContext()+"/"+rdr.getDstServer();
}
parent = getLinkFactory().getWatchdogLink(key);
lnk.isBeingWatched = true;
if (parent == null)
{ // this is the parent watchdog link for this key
if (lnk.sub.pollingInterval < pollingInterval &&
TMode.getBaseMode(lnk.sub.mode) != TMode.CM_EVENT)
{
MsgLog.log("TWatchdogLink", lnk.getFullDeviceNameAndProperty()+" adjust watchdog polling interval to "+lnk.sub.pollingInterval+" msec",0,null,1);
setPollingInterval(lnk.sub.pollingInterval);
}
getLinkFactory().addWatchdogLink(key, this);
parent = this;
TDataType dout = new TDataType(srvStartTime);
dout.setTag(lwdTag);
tgt = new TLink(key,lwdProperty,dout,null,TAccess.CA_READ);
tgt.attach(TMode.CM_TIMER, this, pollingInterval);
MsgLog.log("TWatchdogLink", "add "+key+" to the watched links table",0,null,0);
}
if (!parent.lnks.contains(lnk))
{
parent.lnks.add(lnk);
}
}
public void remove(TLink lnk)
{
if (lnk == null) return;
parent.lnks.remove(lnk);
lnk.isBeingWatched = false;
if (lnks.size() == 0 && tgt != null)
{
DbgLog.log("TWatchdogLink", "removing watchdog link to "+parent.tgt.getFullDeviceName());
tgt.close();
tgt = null;
parent = null;
getLinkFactory().rmvWatchdogLink(key);
}
}
public static boolean isWatchableLink(TLink lnk)
{
if (lnk == null) return false;
if (lnk.dOutput.getTag().compareTo(lwdTag) == 0) return false;
if (TQuery.isStockProperty(lnk.con.eqmProperty)) return false;
if (lnk.con.eqmProperty.compareTo(lwdProperty) == 0) return false;
if (lnk.isBound()) return false;
if (lnk.isBeingWatched) return false;
int bmode = TMode.getBaseMode(lnk.getLinkAccessMode());
if (bmode < TMode.CM_DATACHANGE) return false;
if (bmode == TMode.CM_TIMER &&
lnk.getLinkPollingInterval() < pollingInterval * LWD_TIMER_DEADBAND)
{
return false;
}
String key = "/"+lnk.cntName+"/"+lnk.expName;
if (bmode == TMode.CM_TIMER && !getLinkFactory().hasWatchdogLink(key))
return false;
return true;
}
public void callback(TLink link)
{
if (lnks.size() == 0)
{ // nobody left to watch
link.close();
getLinkFactory().rmvWatchdogLink(key);
MsgLog.log("TWatchdogLink", "remove "+key+" from the watched links table",0,null,0);
return;
}
if (link.getLinkStatus() == lastLinkStatus) return;
lastLinkStatus = link.getLinkStatus();
switch (link.getLinkStatus())
{
case 0:
default:
break;
case TErrorList.link_not_open:
case TErrorList.connection_timeout:
TLink lnk;
Iterator<TLink> it = lnks.iterator();
while (it.hasNext())
{
lnk = it.next();
lnk.linkStatus = lastLinkStatus;
lnk.linkTimeouts = TLinkFactory.RETRY_THRESHOLD;
lnk.sub.linkLastTime = 0;
}
break;
}
}
public static int getPollingInterval()
{
return pollingInterval;
}
public static void setPollingInterval(int value)
{
if (value < 50) value = 50;
if (value > 10000) value = 10000;
pollingInterval = value;
}
}