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