Author: toad
Date: 2008-02-08 18:38:16 +0000 (Fri, 08 Feb 2008)
New Revision: 17707

Modified:
   trunk/freenet/src/freenet/node/FailureTable.java
   trunk/freenet/src/freenet/node/FailureTableEntry.java
Log:
Remove the entry as well if it's empty.

Modified: trunk/freenet/src/freenet/node/FailureTable.java
===================================================================
--- trunk/freenet/src/freenet/node/FailureTable.java    2008-02-08 18:33:37 UTC 
(rev 17706)
+++ trunk/freenet/src/freenet/node/FailureTable.java    2008-02-08 18:38:16 UTC 
(rev 17707)
@@ -24,6 +24,9 @@
 // Otherwise it will be much too easy to trace a request if an attacker busts 
the node afterwards.
 // We can use an HMAC or something to authenticate offers.

+// LOCKING: Always take the FailureTable lock first if you need both. Take the 
FailureTableEntry 
+// lock only on cheap internal operations.
+
 /**
  * Tracks recently DNFed keys, where they were routed to, what the location 
was at the time, who requested them.
  * Implements Ultra-Lightweight Persistent Requests: Refuse requests for a key 
for 10 minutes after it's DNFed 
@@ -473,9 +476,13 @@
                                entriesByKey.toArray(entries);
                        }
                        for(int i=0;i<entries.length;i++) {
-                               entries[i].cleanup();
-                               // FIXME how to safely remove them if empty?
-                               // I suppose we'll have to establish a lock 
taking order...
+                               if(entries[i].cleanup()) {
+                                       synchronized(FailureTable.this) {
+                                               if(entries[i].isEmpty()) {
+                                                       
entriesByKey.removeKey(entries[i].key);
+                                               }
+                                       }
+                               }
                        }
                        long endTime = System.currentTimeMillis();
                        if(logMINOR) Logger.minor(this, "Finished FailureTable 
cleanup took "+(endTime-startTime)+"ms");

Modified: trunk/freenet/src/freenet/node/FailureTableEntry.java
===================================================================
--- trunk/freenet/src/freenet/node/FailureTableEntry.java       2008-02-08 
18:33:37 UTC (rev 17706)
+++ trunk/freenet/src/freenet/node/FailureTableEntry.java       2008-02-08 
18:38:16 UTC (rev 17707)
@@ -429,7 +429,8 @@
                return -1; // not timed out
        }

-       public synchronized void cleanup() {
+       public synchronized boolean cleanup() {
+               boolean empty = true;
                int x = 0;
                long now = System.currentTimeMillis(); // don't pass in as a 
pass over the whole FT may take a while. get it in the method.
                for(int i=0;i<requestorNodes.length;i++) {
@@ -441,6 +442,7 @@
                        if(bootID != requestorBootIDs[i]) continue;
                        if(!pn.isConnected()) continue;
                        if(now - requestorTimes[i] > 
MAX_TIME_BETWEEN_REQUEST_AND_OFFER) continue;
+                       empty = false;
                        requestorNodes[x] = requestorNodes[i];
                        requestorTimes[x] = requestorTimes[i];
                        requestorBootIDs[x] = requestorBootIDs[i];
@@ -467,6 +469,7 @@
                        if(bootID != requestedBootIDs[i]) continue;
                        if(!pn.isConnected()) continue;
                        if(now - requestedTimes[i] > 
MAX_TIME_BETWEEN_REQUEST_AND_OFFER) continue;
+                       empty = false;
                        requestedNodes[x] = requestedNodes[i];
                        requestedTimes[x] = requestedTimes[i];
                        requestedBootIDs[x] = requestedBootIDs[i];
@@ -494,6 +497,11 @@
                        requestedTimeouts = newRequestedTimeouts;
                        requestedTimeoutHTLs = newRequestedTimeoutHTLs;
                }
+               return empty;
        }

+       public boolean isEmpty() {
+               return isEmpty(System.currentTimeMillis());
+       }
+
 }
\ No newline at end of file


Reply via email to