Author: toad
Date: 2008-02-08 18:31:57 +0000 (Fri, 08 Feb 2008)
New Revision: 17705
Modified:
trunk/freenet/src/freenet/node/FailureTable.java
trunk/freenet/src/freenet/node/FailureTableEntry.java
trunk/freenet/src/freenet/support/LRUHashtable.java
Log:
Cleanup the failure table every 30 minutes.
Modified: trunk/freenet/src/freenet/node/FailureTable.java
===================================================================
--- trunk/freenet/src/freenet/node/FailureTable.java 2008-02-08 18:31:02 UTC
(rev 17704)
+++ trunk/freenet/src/freenet/node/FailureTable.java 2008-02-08 18:31:57 UTC
(rev 17705)
@@ -53,6 +53,8 @@
static final int OFFER_EXPIRY_TIME = 10*60*1000;
/** HMAC key for the offer authenticator */
final byte[] offerAuthenticatorKey;
+ /** Clean up old data every 30 minutes to save memory and improve
privacy */
+ static final int CLEANUP_PERIOD = 30*60*1000;
static boolean logMINOR;
static boolean logDEBUG;
@@ -66,6 +68,7 @@
node.random.nextBytes(offerAuthenticatorKey);
logMINOR = Logger.shouldLog(Logger.MINOR, this);
logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
+ node.ps.queueTimedJob(new FailureTableCleaner(),
CLEANUP_PERIOD);
}
/**
@@ -120,11 +123,6 @@
while(entriesByKey.size() > MAX_ENTRIES) {
entriesByKey.popKey();
}
- while(true) {
- FailureTableEntry e = (FailureTableEntry)
entriesByKey.peekValue();
- if(now - e.creationTime > MAX_LIFETIME)
entriesByKey.popKey();
- else break;
- }
}
private final class BlockOfferList {
@@ -454,4 +452,38 @@
return (FailureTableEntry) entriesByKey.get(key);
}
}
+
+ public class FailureTableCleaner implements Runnable {
+
+ public void run() {
+ try {
+ realRun();
+ } catch (Throwable t) {
+ Logger.error(this, "FailureTableCleaner caught
"+t, t);
+ } finally {
+ node.ps.queueTimedJob(this, CLEANUP_PERIOD);
+ }
+ }
+
+ private void realRun() {
+ logMINOR = Logger.shouldLog(Logger.MINOR,
FailureTable.this);
+ logDEBUG = Logger.shouldLog(Logger.DEBUG,
FailureTable.this);
+ if(logMINOR) Logger.minor(this, "Starting FailureTable
cleanup");
+ long startTime = System.currentTimeMillis();
+ FailureTableEntry[] entries;
+ synchronized(FailureTable.this) {
+ entries = new
FailureTableEntry[entriesByKey.size()];
+ 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...
+ }
+ 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:31:02 UTC (rev 17704)
+++ trunk/freenet/src/freenet/node/FailureTableEntry.java 2008-02-08
18:31:57 UTC (rev 17705)
@@ -429,4 +429,71 @@
return -1; // not timed out
}
+ public synchronized void cleanup() {
+ 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++) {
+ WeakReference ref = requestorNodes[i];
+ if(ref == null) continue;
+ PeerNode pn = (PeerNode) ref.get();
+ if(pn == null) continue;
+ long bootID = pn.getBootID();
+ if(bootID != requestorBootIDs[i]) continue;
+ if(!pn.isConnected()) continue;
+ if(now - requestorTimes[i] >
MAX_TIME_BETWEEN_REQUEST_AND_OFFER) continue;
+ requestorNodes[x] = requestorNodes[i];
+ requestorTimes[x] = requestorTimes[i];
+ requestorBootIDs[x] = requestorBootIDs[i];
+ x++;
+ }
+ if(x < requestorNodes.length) {
+ WeakReference[] newRequestorNodes = new
WeakReference[x];
+ long[] newRequestorTimes = new long[x];
+ long[] newRequestorBootIDs = new long[x];
+ System.arraycopy(requestorNodes, 0, newRequestorNodes,
0, x);
+ System.arraycopy(requestorTimes, 0, newRequestorTimes,
0, x);
+ System.arraycopy(requestorBootIDs, 0,
newRequestorBootIDs, 0, x);
+ requestorNodes = newRequestorNodes;
+ requestorTimes = newRequestorTimes;
+ requestorBootIDs = newRequestorBootIDs;
+ }
+ x = 0;
+ for(int i=0;i<requestedNodes.length;i++) {
+ WeakReference ref = requestedNodes[i];
+ if(ref == null) continue;
+ PeerNode pn = (PeerNode) ref.get();
+ if(pn == null) continue;
+ long bootID = pn.getBootID();
+ if(bootID != requestedBootIDs[i]) continue;
+ if(!pn.isConnected()) continue;
+ if(now - requestedTimes[i] >
MAX_TIME_BETWEEN_REQUEST_AND_OFFER) continue;
+ requestedNodes[x] = requestedNodes[i];
+ requestedTimes[x] = requestedTimes[i];
+ requestedBootIDs[x] = requestedBootIDs[i];
+ if(now < requestedTimeouts[x]) {
+ requestedTimeouts[x] = requestedTimeouts[i];
+ requestedTimeoutHTLs[x] =
requestedTimeoutHTLs[i];
+ } else {
+ requestedTimeouts[x] = -1;
+ requestedTimeoutHTLs[x] = (short)-1;
+ }
+ x++;
+ }
+ if(x < requestedNodes.length) {
+ WeakReference[] newRequestedNodes = new
WeakReference[x];
+ long[] newRequestedTimes = new long[x];
+ long[] newRequestedBootIDs = new long[x];
+ long[] newRequestedTimeouts = new long[x];
+ short[] newRequestedTimeoutHTLs = new short[x];
+ System.arraycopy(requestedNodes, 0, newRequestedNodes,
0, x);
+ System.arraycopy(requestedTimes, 0, newRequestedTimes,
0, x);
+ System.arraycopy(requestedBootIDs, 0,
newRequestedBootIDs, 0, x);
+ requestedNodes = newRequestedNodes;
+ requestedTimes = newRequestedTimes;
+ requestedBootIDs = newRequestedBootIDs;
+ requestedTimeouts = newRequestedTimeouts;
+ requestedTimeoutHTLs = newRequestedTimeoutHTLs;
+ }
+ }
+
}
\ No newline at end of file
Modified: trunk/freenet/src/freenet/support/LRUHashtable.java
===================================================================
--- trunk/freenet/src/freenet/support/LRUHashtable.java 2008-02-08 18:31:02 UTC
(rev 17704)
+++ trunk/freenet/src/freenet/support/LRUHashtable.java 2008-02-08 18:31:57 UTC
(rev 17705)
@@ -133,4 +133,17 @@
return list.isEmpty();
}
+ /**
+ * Note that unlike the java.util versions, this will not reallocate
(hence it doesn't return),
+ * so pass in an appropriately big array, and make sure you hold the
lock!
+ * @param entries
+ * @return
+ */
+ public synchronized void toArray(Object[] entries) {
+ Enumeration keys = keys();
+ int i=0;
+ while(keys.hasMoreElements())
+ entries[i++] = keys.nextElement();
+ }
+
}