Update of /cvsroot/freenet/freenet/src/freenet In directory sc8-pr-cvs1:/tmp/cvs-serv22073/src/freenet
Modified Files: OpenConnectionManager.java Log Message: More locking improvements. -Moved KillSurplusConnections to a thread of it's own, this is in the hopes of reducing contention for the highly contested lru lock in OpenConnectionManager -Completely redid locking in QThreadFactory, locking the whole class for most of the operations in here didn't make sense, so I used several different locks to ensure synchronization w/o blocking threads trying to return themselves (Committed at Zab's request) Index: OpenConnectionManager.java =================================================================== RCS file: /cvsroot/freenet/freenet/src/freenet/OpenConnectionManager.java,v retrieving revision 1.107 retrieving revision 1.108 diff -u -r1.107 -r1.108 --- OpenConnectionManager.java 23 Sep 2003 00:55:10 -0000 1.107 +++ OpenConnectionManager.java 26 Sep 2003 02:02:08 -0000 1.108 @@ -73,6 +73,10 @@ 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(); } /** @@ -104,8 +108,9 @@ synchronized(openConnsSync) { openConns++; } - - KillSurplusConnections(); + synchronized(lru) { + lru.notifyAll(); + } } // Removing a connection that isn't in the OCM is a @@ -466,63 +471,82 @@ } } } - + /** * 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 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; - while (true) { - synchronized (lru) { - - if (maxConnections > 0 && lru.size() > maxConnections) { - - // Dump an idle connection if possible. - for (Enumeration e = lru.elements(); e.hasMoreElements();) { - ConnectionHandler candidate = - (ConnectionHandler)e.nextElement(); - if (!(candidate.sending() || candidate.receiving())) { - if(oldest != null) { - // If the oldest is open and the candidate is closed... - if(oldest.isOpen() && (!candidate.isOpen())) - oldest = null; - // Or the oldest is an only-conn-to-this-RTNode and the - // candidate is not... then use the candidate - else if((!onlyRTNodeConn(candidate)) && onlyRTNodeConn(oldest)) - oldest = null; - } - if(oldest == null) { - oldest = candidate; - if(!oldest.isOpen()) break; - } - // Otherwise wait for the best open conn - //lru.remove(candidate); - } - } - if (oldest == null) { - // Not good. This connection will most likely - // be restarted, causing even more traffic :-( - //System.err.println("!KILLED OPEN CONNECTION!"); - oldest = (ConnectionHandler)lru.pop(); - } - - } else break; // break outer loop - we have killed enough connections - } - if (oldest != null) { - Core.diagnostics.occurrenceBinomial("connectionTimedout", 1, 0); - oldest.terminate(); - oldest = null; - } - } - } - + 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 ) { + } + } 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(); + } + + } + } + if (oldest != null) { + Core.diagnostics.occurrenceBinomial("connectionTimedout", 1, 0); + oldest.terminate(); + oldest = null; + } + } + } + } + } /** * Returns a free connection, making a new one if none is available. */ _______________________________________________ cvs mailing list [EMAIL PROTECTED] http://dodo.freenetproject.org/cgi-bin/mailman/listinfo/cvs