package freenet.node;
import java.util.HashMap;
import java.util.List;
import freenet.support.Logger;
import freenet.support.WeakHashSet;
/** Track a collection of PeerNode's for each status. */
class PeerStatusTracker<K extends Object> {
private static volatile boolean logMINOR;
static {
Logger.registerClass(PeerManager.class);
}
/** PeerNode statuses, by status. WARNING: LOCK THIS LAST. Must NOT call PeerNode inside this lock. */
private final HashMap<K, WeakHashSet<PeerNode>> statuses;
PeerStatusTracker() {
statuses = new HashMap<K, WeakHashSet<PeerNode>>();
}
public synchronized void addStatus(K peerNodeStatus, PeerNode peerNode, boolean noLog) {
WeakHashSet<PeerNode> statusSet = statuses.get(peerNodeStatus);
if(statusSet != null) {
if(statusSet.contains(peerNode)) {
if(!noLog)
Logger.error(this, "addPeerNodeStatus(): node already in peerNodeStatuses: " + peerNode + " status " + peerNodeStatus, new Exception("debug"));
return;
}
statuses.remove(peerNodeStatus);
} else
statusSet = new WeakHashSet<PeerNode>();
if(logMINOR)
Logger.minor(this, "addPeerNodeStatus(): adding PeerNode for '" + peerNode.getIdentityString() + "' with status '" + peerNodeStatus + "'");
statusSet.add(peerNode);
statuses.put(peerNodeStatus, statusSet);
}
public synchronized int statusSize(K pnStatus) {
WeakHashSet<PeerNode> statusSet = statuses.get(pnStatus);
if(statusSet != null)
return statusSet.size();
else
return 0;
}
public synchronized void removeStatus(K peerNodeStatus, PeerNode peerNode,
boolean noLog) {
WeakHashSet<PeerNode> statusSet = statuses.get(peerNodeStatus);
if(statusSet != null) {
if(!statusSet.remove(peerNode)) {
if(!noLog)
Logger.error(this, "removePeerNodeStatus(): identity '" + peerNode.getIdentityString() + " for " + peerNode.shortToString() + "' not in peerNodeStatuses with status '" + peerNodeStatus + "'", new Exception("debug"));
return;
}
if(statusSet.isEmpty())
statuses.remove(peerNodeStatus);
}
if(logMINOR)
Logger.minor(this, "removePeerNodeStatus(): removing PeerNode for '" + peerNode.getIdentityString() + "' with status '" + peerNodeStatus + "'");
}
public synchronized void changePeerNodeStatus(PeerNode peerNode, K oldPeerNodeStatus,
K peerNodeStatus, boolean noLog) {
if(logMINOR) Logger.minor(this, "Peer status change: "+oldPeerNodeStatus+" -> "+peerNodeStatus+" on "+peerNode);
removeStatus(oldPeerNodeStatus, peerNode, noLog);
addStatus(peerNodeStatus, peerNode, noLog);
}
public synchronized void addStatusList(List<K> list) {
list.addAll(statuses.keySet());
}
}