Update of /cvsroot/freenet/freenet/src/freenet In directory sc8-pr-cvs1:/tmp/cvs-serv24104/src/freenet
Modified Files: ConnectionHandler.java OpenConnectionManager.java Log Message: Move KillSurplusConnections back out of a thread, but do it smarter. We will now keep a queue of closed connections to try and avoid even needing to search for closed connections to remove from the OCM. Many other speedups to KillSurplusConnections MultiValueTable has a new method - countAll(id) to get a count of connections to a peer (or whatever) Index: ConnectionHandler.java =================================================================== RCS file: /cvsroot/freenet/freenet/src/freenet/ConnectionHandler.java,v retrieving revision 1.160 retrieving revision 1.161 diff -u -r1.160 -r1.161 --- ConnectionHandler.java 23 Sep 2003 00:55:09 -0000 1.160 +++ ConnectionHandler.java 26 Sep 2003 22:38:34 -0000 1.161 @@ -1022,6 +1022,7 @@ Core.logger.log(this, "Trailer chunk send failed for "+this+ ", closing", Logger.MINOR); sendClosed.change(true); + ocm.markClosed(this); sendingCount = 0; synchronized(trailerSendLock) { sendingTrailerChunk = false; Index: OpenConnectionManager.java =================================================================== RCS file: /cvsroot/freenet/freenet/src/freenet/OpenConnectionManager.java,v retrieving revision 1.108 retrieving revision 1.109 diff -u -r1.108 -r1.109 --- OpenConnectionManager.java 26 Sep 2003 02:02:08 -0000 1.108 +++ OpenConnectionManager.java 26 Sep 2003 22:38:34 -0000 1.109 @@ -53,6 +53,8 @@ private int openConns; private Object openConnsSync = new Object(); + private LinkedList closedList = new LinkedList(); + private final LRUQueue lru = new LRUQueue(); // Queue of blacklisted peers private final BlackLRUQueue blq = new BlackLRUQueue(60000,100,3); @@ -73,10 +75,6 @@ logDEBUG = Core.logger.shouldLog(Logger.DEBUG, this); chs = new MultiValueTable(50, 3); openConns = 0; - SurplusKiller sk = new SurplusKiller(lru,maxConnections); - Thread skt = new Thread(sk,"Surplus connection killing thread"); - skt.setDaemon(true); - skt.start(); } /** @@ -108,8 +106,11 @@ synchronized(openConnsSync) { openConns++; } + if ( maxConnections != 0 && lru.size() < maxConnections ) return; synchronized(lru) { - lru.notifyAll(); + /* At toad's request moving back to diong this in every thred. */ +// lru.notifyAll(); + KillSurplusConnections(); } } @@ -231,6 +232,12 @@ id, Logger.DEBUG); return null; } + + public void markClosed(ConnectionHandler ch) { + synchronized(closedList) { + closedList.addFirst(ch); + } + } /** * This attempts to search for the open connection to id best suited for @@ -303,13 +310,8 @@ } protected final boolean onlyRTNodeConn(Identity id) { - if(!Main.node.rt.references(id)) - return false; - Enumeration e = chs.getAll(id); - if(!e.hasMoreElements()) return true; // it has zero - e.nextElement(); - if(!e.hasMoreElements()) return true; // it has one - else return false; // it has more than one + if ( chs.countAll(id) <= 1 && Main.node.rt.references(id) ) return true; + else return false; // it has more than one or is not in the route } public int countOutboundConnections(Identity id) { @@ -476,74 +478,71 @@ * Kills off one or more connections to ensure that we stay below the connection limit * This method is appropriate to call after a connection has been added to the OCM */ - private class SurplusKiller implements Runnable { - - private LRUQueue lru; - private int maxConnections; - - public SurplusKiller(LRUQueue lru,int maxConnections) { - this.lru = lru; - this.maxConnections = maxConnections; - } - - public void run() { - while (true) { - // Dump LRU idle connection. - // - // Note: You don't want to dump the simple LRU connection - // because under heavy load the LRU connections are - // the ones that are transferring data. - // - ConnectionHandler oldest = null; - while (true) { - synchronized (lru) { - if ( !(maxConnections > 0 && lru.size() > maxConnections) ) { - try { - // wait till we are awakened - no more need to die - lru.wait(); - } catch ( InterruptedException ie ) { + private void KillSurplusConnections() { + // Dump LRU idle connection. + // + // Note: You don't want to dump the simple LRU connection + // because under heavy load the LRU connections are + // the ones that are transferring data. + // + ConnectionHandler oldest = null; + ConnectionHandler cached = null; + boolean oldestCache = false; + boolean candidateCache = false; + while (true) { + if ( maxConnections > 0 && lru.size() > maxConnections ) { + synchronized(closedList) { + if ( !closedList.isEmpty() ) { + oldest = (ConnectionHandler)closedList.removeLast(); + } + } + // Dump an idle connection if possible. + if ( oldest == null ) for (Enumeration e = lru.elements(); e.hasMoreElements();) { + ConnectionHandler candidate = + (ConnectionHandler)e.nextElement(); + if (!(candidate.sending() || candidate.receiving())) { + // If the oldest is open and the candidate is closed... + if( !candidate.isOpen() ) { + oldest = candidate; + break; + } else if ( oldest != null ) { + //This can only happen if it closes during the run of + //this loop, very unlikely but _anything_ which could + //keep us from running onlyRTNodeConn is a good thing + //because that involves locking hashtables, BigInteger + //math and badness like that. + if ( oldest != null && (!oldest.isOpen()) ) + break; + // If the oldest is an only-conn-to-this-RTNode and the + // candidate is not... then use the candidate + if ( ( ( oldest == cached && oldestCache ) || + ( oldestCache = onlyRTNodeConn(oldest) ) ) && + ! ( candidateCache = onlyRTNodeConn(candidate) ) ) { + oldest = candidate; + oldestCache = candidateCache; } + cached = oldest; } else { - // Dump an idle connection if possible. - for (Enumeration e = lru.elements(); e.hasMoreElements();) { - ConnectionHandler candidate = - (ConnectionHandler)e.nextElement(); - if (!(candidate.sending() || candidate.receiving())) { - // If the oldest is open and the candidate is closed... - if( !candidate.isOpen() ) { - oldest = candidate; - break; - } else if ( oldest != null ) { - //This can only happen if it closes during the run of - //this loop, very unlikely but _anything_ which could - //keep us from running onlyRTNodeConn is a good thing - //because that involves locking hashtables, BigInteger - //math and badness like that. - if ( oldest != null && (!oldest.isOpen()) ) - break; - // If the oldest is an only-conn-to-this-RTNode and the - // candidate is not... then use the candidate - if(onlyRTNodeConn(oldest) && (!onlyRTNodeConn(candidate)) ) - oldest = candidate; - } else { - oldest = candidate; - } - } - } - if (oldest == null) { - // Not good. This connection will most likely - // be restarted, causing even more traffic :-( - oldest = (ConnectionHandler)lru.pop(); - } - + oldest = candidate; } } - if (oldest != null) { - Core.diagnostics.occurrenceBinomial("connectionTimedout", 1, 0); - oldest.terminate(); - oldest = null; - } } + if (oldest == null) { + // Not good. This connection will most likely + // be restarted, causing even more traffic :-( + oldest = (ConnectionHandler)lru.pop(); + } else { + lru.remove(oldest); + } + + } else { + //We have killed enough connections + return; + } + if (oldest != null) { + Core.diagnostics.occurrenceBinomial("connectionTimedout", 1, 0); + oldest.terminate(); + oldest = null; } } } _______________________________________________ cvs mailing list [EMAIL PROTECTED] http://dodo.freenetproject.org/cgi-bin/mailman/listinfo/cvs