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()); } }