Author: toad
Date: 2009-01-22 18:32:20 +0000 (Thu, 22 Jan 2009)
New Revision: 25217
Added:
branches/db4o/freenet/src/freenet/node/InsertTag.java
branches/db4o/freenet/src/freenet/node/OfferReplyTag.java
branches/db4o/freenet/src/freenet/node/RequestTag.java
branches/db4o/freenet/src/freenet/node/UIDTag.java
Modified:
branches/db4o/freenet/src/freenet/node/CHKInsertHandler.java
branches/db4o/freenet/src/freenet/node/DarknetPeerNode.java
branches/db4o/freenet/src/freenet/node/FailureTable.java
branches/db4o/freenet/src/freenet/node/KeyTracker.java
branches/db4o/freenet/src/freenet/node/Node.java
branches/db4o/freenet/src/freenet/node/NodeClientCore.java
branches/db4o/freenet/src/freenet/node/NodeCrypto.java
branches/db4o/freenet/src/freenet/node/NodeDispatcher.java
branches/db4o/freenet/src/freenet/node/NodeStarter.java
branches/db4o/freenet/src/freenet/node/NodeStats.java
branches/db4o/freenet/src/freenet/node/PacketSender.java
branches/db4o/freenet/src/freenet/node/PeerManager.java
branches/db4o/freenet/src/freenet/node/PeerMessageQueue.java
branches/db4o/freenet/src/freenet/node/PeerNode.java
branches/db4o/freenet/src/freenet/node/RequestHandler.java
branches/db4o/freenet/src/freenet/node/RequestSender.java
branches/db4o/freenet/src/freenet/node/SSKInsertHandler.java
branches/db4o/freenet/src/freenet/node/SessionKey.java
branches/db4o/freenet/src/freenet/node/Version.java
branches/db4o/freenet/src/freenet/node/simulator/RealNodeNetworkColoringTest.java
branches/db4o/freenet/src/freenet/node/useralerts/UserAlertManager.java
Log:
Merge trunk up to 25205 (1203) into db4o.
Modified: branches/db4o/freenet/src/freenet/node/CHKInsertHandler.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/CHKInsertHandler.java
2009-01-22 18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/CHKInsertHandler.java
2009-01-22 18:32:20 UTC (rev 25217)
@@ -45,14 +45,16 @@
private BlockReceiver br;
private Thread runThread;
PartiallyReceivedBlock prb;
+ final InsertTag tag;
private static boolean logMINOR;
- CHKInsertHandler(Message req, PeerNode source, long id, Node node, long
startTime) {
+ CHKInsertHandler(Message req, PeerNode source, long id, Node node, long
startTime, InsertTag tag) {
this.req = req;
this.node = node;
this.uid = id;
this.source = source;
this.startTime = startTime;
+ this.tag = tag;
key = (NodeCHK) req.getObject(DMT.FREENET_ROUTING_KEY);
htl = req.getShort(DMT.HTL);
if(htl <= 0) htl = 1;
@@ -71,11 +73,13 @@
realRun();
} catch (OutOfMemoryError e) {
OOMHandler.handleOOM(e);
+ tag.handlerThrew(e);
} catch (Throwable t) {
Logger.error(this, "Caught in run() "+t, t);
+ tag.handlerThrew(t);
} finally {
if(logMINOR) Logger.minor(this, "Exiting CHKInsertHandler.run()
for "+uid);
- node.unlockUID(uid, false, true, false, false, false);
+ node.unlockUID(uid, false, true, false, false, false, tag);
}
}
@@ -117,7 +121,7 @@
Message m = DMT.createFNPInsertTransfersCompleted(uid,
true);
source.sendAsync(m, null, this);
prb = new PartiallyReceivedBlock(Node.PACKETS_IN_BLOCK,
Node.PACKET_SIZE);
- br = new BlockReceiver(node.usm, source, uid, prb,
this);
+ br = new BlockReceiver(node.usm, source, uid, prb,
this, node.getTicker(), false);
prb.abort(RetrievalException.NO_DATAINSERT, "No
DataInsert");
br.sendAborted(RetrievalException.NO_DATAINSERT, "No
DataInsert");
return;
@@ -139,7 +143,7 @@
prb = new PartiallyReceivedBlock(Node.PACKETS_IN_BLOCK,
Node.PACKET_SIZE);
if(htl > 0)
sender = node.makeInsertSender(key, htl, uid, source, headers,
prb, false, true);
- br = new BlockReceiver(node.usm, source, uid, prb, this);
+ br = new BlockReceiver(node.usm, source, uid, prb, this,
node.getTicker(), false);
// Receive the data, off thread
Runnable dataReceiver = new DataReceiver();
@@ -434,7 +438,7 @@
else
// Annoying, but we have stats for
this; no need to call attention to it, it's unlikely to be a bug.
Logger.normal(this, "Failed to retrieve
("+e.getReason()+"/"+RetrievalException.getErrString(e.getReason())+"): "+e, e);
- node.nodeStats.failedBlockReceive();
+ node.nodeStats.failedBlockReceive(false, false, false);
return;
} catch (Throwable t) {
Logger.error(this, "Caught "+t, t);
Modified: branches/db4o/freenet/src/freenet/node/DarknetPeerNode.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/DarknetPeerNode.java 2009-01-22
18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/DarknetPeerNode.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -364,7 +364,7 @@
for (File extraPeerDataFile : extraPeerDataFiles) {
Integer fileNumber;
try {
- fileNumber = new
Integer(extraPeerDataFile.getName());
+ fileNumber =
Integer.valueOf(extraPeerDataFile.getName());
} catch (NumberFormatException e) {
gotError = true;
continue;
@@ -532,7 +532,7 @@
synchronized(queuedToSendN2NMExtraPeerDataFileNumbers) {
fs.putOverwrite("extraPeerDataType",
Integer.toString(extraPeerDataType));
fs.removeValue("sentTime");
-
queuedToSendN2NMExtraPeerDataFileNumbers.add(new Integer(fileNumber));
+
queuedToSendN2NMExtraPeerDataFileNumbers.add(Integer.valueOf(fileNumber));
}
}
return true;
Modified: branches/db4o/freenet/src/freenet/node/FailureTable.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/FailureTable.java 2009-01-22
18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/FailureTable.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -380,16 +380,16 @@
* @param source The node that asked for the key.
* @throws NotConnectedException If the sender ceases to be connected.
*/
- public void sendOfferedKey(final Key key, final boolean isSSK, final
boolean needPubKey, final long uid, final PeerNode source) throws
NotConnectedException {
+ public void sendOfferedKey(final Key key, final boolean isSSK, final
boolean needPubKey, final long uid, final PeerNode source, final OfferReplyTag
tag) throws NotConnectedException {
this.offerExecutor.execute(new Runnable() {
public void run() {
try {
- innerSendOfferedKey(key, isSSK,
needPubKey, uid, source);
+ innerSendOfferedKey(key, isSSK,
needPubKey, uid, source, tag);
} catch (NotConnectedException e) {
- node.unlockUID(uid, isSSK, false,
false, true, false);
+ node.unlockUID(uid, isSSK, false,
false, true, false, tag);
// Too bad.
} catch (Throwable t) {
- node.unlockUID(uid, isSSK, false,
false, true, false);
+ node.unlockUID(uid, isSSK, false,
false, true, false, tag);
Logger.error(this, "Caught "+t+"
sending offered key");
}
}
@@ -401,13 +401,13 @@
* on a separate thread. However, blocking disk I/O *should happen on
this thread*. We deliberately
* serialise it, as high latencies can otherwise result.
*/
- protected void innerSendOfferedKey(Key key, final boolean isSSK,
boolean needPubKey, final long uid, final PeerNode source) throws
NotConnectedException {
+ protected void innerSendOfferedKey(Key key, final boolean isSSK,
boolean needPubKey, final long uid, final PeerNode source, final OfferReplyTag
tag) throws NotConnectedException {
if(isSSK) {
SSKBlock block = node.fetch((NodeSSK)key, false);
if(block == null) {
// Don't have the key
source.sendAsync(DMT.createFNPGetOfferedKeyInvalid(uid,
DMT.GET_OFFERED_KEY_REJECTED_NO_KEY), null, senderCounter);
- node.unlockUID(uid, isSSK, false, false, true,
false);
+ node.unlockUID(uid, isSSK, false, false, true,
false, tag);
return;
}
@@ -434,7 +434,7 @@
} catch (SyncSendWaitedTooLongException
e) {
// Impossible
} finally {
- node.unlockUID(uid, isSSK,
false, false, true, false);
+ node.unlockUID(uid, isSSK,
false, false, true, false, tag);
}
}
@@ -453,7 +453,7 @@
if(block == null) {
// Don't have the key
source.sendAsync(DMT.createFNPGetOfferedKeyInvalid(uid,
DMT.GET_OFFERED_KEY_REJECTED_NO_KEY), null, senderCounter);
- node.unlockUID(uid, isSSK, false, false, true,
false);
+ node.unlockUID(uid, isSSK, false, false, true,
false, tag);
return;
}
Message df = DMT.createFNPCHKDataFound(uid,
block.getRawHeaders());
@@ -474,7 +474,7 @@
} catch (Throwable t) {
Logger.error(this, "Sending
offered key failed: "+t, t);
} finally {
- node.unlockUID(uid, isSSK,
false, false, true, false);
+ node.unlockUID(uid, isSSK,
false, false, true, false, tag);
}
}
Copied: branches/db4o/freenet/src/freenet/node/InsertTag.java (from rev 25205,
trunk/freenet/src/freenet/node/InsertTag.java)
===================================================================
--- branches/db4o/freenet/src/freenet/node/InsertTag.java
(rev 0)
+++ branches/db4o/freenet/src/freenet/node/InsertTag.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -0,0 +1,45 @@
+package freenet.node;
+
+import freenet.support.Logger;
+import freenet.support.TimeUtil;
+
+/**
+ * Represents an insert.
+ * @author Matthew Toseland <toad at amphibian.dyndns.org> (0xE43DA450)
+ */
+public class InsertTag extends UIDTag {
+
+ final boolean ssk;
+
+ enum START {
+ LOCAL,
+ REMOTE
+ }
+
+ START start;
+ private Throwable handlerThrew;
+
+ InsertTag(boolean ssk, START start) {
+ super();
+ this.start = start;
+ this.ssk = ssk;
+ }
+
+ public void handlerThrew(Throwable t) {
+ handlerThrew = t;
+ }
+
+ @Override
+ public void logStillPresent(Long uid) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Still present after
").append(TimeUtil.formatTime(age()));
+ sb.append(" : ").append(uid).append(" : start=").append(start);
+ sb.append(" ssk=").append(ssk);
+ sb.append(" thrown=").append(handlerThrew);
+ if(handlerThrew != null)
+ Logger.error(this, sb.toString(), handlerThrew);
+ else
+ Logger.error(this, sb.toString());
+ }
+
+}
Modified: branches/db4o/freenet/src/freenet/node/KeyTracker.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/KeyTracker.java 2009-01-22
18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/KeyTracker.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -18,7 +18,6 @@
* without changing the session key. */
final PacketTracker packets;
- private static boolean logMINOR;
/** Parent PeerNode */
public final PeerNode pn;
/** Cipher to both encrypt outgoing packets with and decrypt
Modified: branches/db4o/freenet/src/freenet/node/Node.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/Node.java 2009-01-22 18:08:25 UTC
(rev 25216)
+++ branches/db4o/freenet/src/freenet/node/Node.java 2009-01-22 18:32:20 UTC
(rev 25217)
@@ -66,7 +66,9 @@
import freenet.io.comm.Peer;
import freenet.io.comm.PeerParseException;
import freenet.io.comm.ReferenceSignatureVerificationException;
+import freenet.io.comm.RetrievalException;
import freenet.io.comm.UdpSocketHandler;
+import freenet.io.xfer.BlockReceiver;
import freenet.io.xfer.PartiallyReceivedBlock;
import freenet.keys.CHKBlock;
import freenet.keys.CHKVerifyException;
@@ -380,17 +382,17 @@
public boolean disableHangCheckers;
/** HashSet of currently running request UIDs */
- private final HashSet<Long> runningUIDs;
- private final HashSet<Long> runningCHKGetUIDs;
- private final HashSet<Long> runningLocalCHKGetUIDs;
- private final HashSet<Long> runningSSKGetUIDs;
- private final HashSet<Long> runningLocalSSKGetUIDs;
- private final HashSet<Long> runningCHKPutUIDs;
- private final HashSet<Long> runningLocalCHKPutUIDs;
- private final HashSet<Long> runningSSKPutUIDs;
- private final HashSet<Long> runningLocalSSKPutUIDs;
- private final HashSet<Long> runningCHKOfferReplyUIDs;
- private final HashSet<Long> runningSSKOfferReplyUIDs;
+ private final HashMap<Long,UIDTag> runningUIDs;
+ private final HashMap<Long,RequestTag> runningCHKGetUIDs;
+ private final HashMap<Long,RequestTag> runningLocalCHKGetUIDs;
+ private final HashMap<Long,RequestTag> runningSSKGetUIDs;
+ private final HashMap<Long,RequestTag> runningLocalSSKGetUIDs;
+ private final HashMap<Long,InsertTag> runningCHKPutUIDs;
+ private final HashMap<Long,InsertTag> runningLocalCHKPutUIDs;
+ private final HashMap<Long,InsertTag> runningSSKPutUIDs;
+ private final HashMap<Long,InsertTag> runningLocalSSKPutUIDs;
+ private final HashMap<Long,OfferReplyTag> runningCHKOfferReplyUIDs;
+ private final HashMap<Long,OfferReplyTag> runningSSKOfferReplyUIDs;
/** Semi-unique ID for swap requests. Used to identify us so that the
* topology can be reconstructed. */
@@ -763,17 +765,17 @@
transferringRequestSenders = new HashMap<NodeCHK,
RequestSender>();
transferringRequestHandlers = new HashSet<Long>();
insertSenders = new HashMap<KeyHTLPair, AnyInsertSender>();
- runningUIDs = new HashSet<Long>();
- runningCHKGetUIDs = new HashSet<Long>();
- runningLocalCHKGetUIDs = new HashSet<Long>();
- runningSSKGetUIDs = new HashSet<Long>();
- runningLocalSSKGetUIDs = new HashSet<Long>();
- runningCHKPutUIDs = new HashSet<Long>();
- runningLocalCHKPutUIDs = new HashSet<Long>();
- runningSSKPutUIDs = new HashSet<Long>();
- runningLocalSSKPutUIDs = new HashSet<Long>();
- runningCHKOfferReplyUIDs = new HashSet<Long>();
- runningSSKOfferReplyUIDs = new HashSet<Long>();
+ runningUIDs = new HashMap<Long,UIDTag>();
+ runningCHKGetUIDs = new HashMap<Long,RequestTag>();
+ runningLocalCHKGetUIDs = new HashMap<Long,RequestTag>();
+ runningSSKGetUIDs = new HashMap<Long,RequestTag>();
+ runningLocalSSKGetUIDs = new HashMap<Long,RequestTag>();
+ runningCHKPutUIDs = new HashMap<Long,InsertTag>();
+ runningLocalCHKPutUIDs = new HashMap<Long,InsertTag>();
+ runningSSKPutUIDs = new HashMap<Long,InsertTag>();
+ runningLocalSSKPutUIDs = new HashMap<Long,InsertTag>();
+ runningCHKOfferReplyUIDs = new HashMap<Long,OfferReplyTag>();
+ runningSSKOfferReplyUIDs = new HashMap<Long,OfferReplyTag>();
this.securityLevels = new SecurityLevels(this, config);
@@ -2280,6 +2282,8 @@
this.clientCore.start(config);
+ startDeadUIDChecker();
+
// After everything has been created, write the config file
back to disk.
if(config instanceof FreenetFilePersistentConfig) {
FreenetFilePersistentConfig cfg =
(FreenetFilePersistentConfig) config;
@@ -2953,55 +2957,144 @@
return is;
}
- public boolean lockUID(long uid, boolean ssk, boolean insert, boolean
offerReply, boolean local) {
+ public boolean lockUID(long uid, boolean ssk, boolean insert, boolean
offerReply, boolean local, UIDTag tag) {
synchronized(runningUIDs) {
- if(!runningUIDs.add(uid)) {
- // Already present.
- return false;
- }
+ if(runningUIDs.containsKey(uid)) return false; //
Already present.
+ runningUIDs.put(uid, tag);
}
// If these are switched around, we must remember to remove
from both.
- HashSet<Long> set = getUIDTracker(ssk, insert, offerReply,
local);
- synchronized(set) {
- if(logMINOR) Logger.minor(this, "Locking "+uid+"
ssk="+ssk+" insert="+insert+" offerReply="+offerReply+" local="+local+"
size="+set.size());
- set.add(uid);
- if(logMINOR) Logger.minor(this, "Locked "+uid+"
ssk="+ssk+" insert="+insert+" offerReply="+offerReply+" local="+local+"
size="+set.size());
+ if(offerReply) {
+ HashMap<Long,OfferReplyTag> map = getOfferTracker(ssk);
+ innerLock(map, (OfferReplyTag)tag, uid, ssk, insert,
offerReply, local);
+ } else if(insert) {
+ HashMap<Long,InsertTag> map =
getInsertTracker(ssk,local);
+ innerLock(map, (InsertTag)tag, uid, ssk, insert,
offerReply, local);
+ } else {
+ HashMap<Long,RequestTag> map =
getRequestTracker(ssk,local);
+ innerLock(map, (RequestTag)tag, uid, ssk, insert,
offerReply, local);
}
return true;
}
- public void unlockUID(long uid, boolean ssk, boolean insert, boolean
canFail, boolean offerReply, boolean local) {
+ private<T extends UIDTag> void innerLock(HashMap<Long, T> map, T tag,
Long uid, boolean ssk, boolean insert, boolean offerReply, boolean local) {
+ synchronized(map) {
+ if(logMINOR) Logger.minor(this, "Locking "+uid+"
ssk="+ssk+" insert="+insert+" offerReply="+offerReply+" local="+local+"
size="+map.size(), new Exception("debug"));
+ if(map.containsKey(uid)) {
+ Logger.error(this, "Already have UID in
specific map ("+ssk+","+insert+","+offerReply+","+local+") but not in general
map: trying to register "+tag+" but already have "+map.get(uid));
+ }
+ map.put(uid, tag);
+ if(logMINOR) Logger.minor(this, "Locked "+uid+"
ssk="+ssk+" insert="+insert+" offerReply="+offerReply+" local="+local+"
size="+map.size());
+ }
+ }
+
+ public void unlockUID(long uid, boolean ssk, boolean insert, boolean
canFail, boolean offerReply, boolean local, UIDTag tag) {
completed(uid);
- HashSet<Long> set = getUIDTracker(ssk, insert, offerReply,
local);
- synchronized(set) {
- if(logMINOR) Logger.minor(this, "Unlocking "+uid+"
ssk="+ssk+" insert="+insert+" offerReply="+offerReply+", local="+local+"
size="+set.size());
- set.remove(uid);
- if(logMINOR) Logger.minor(this, "Unlocked "+uid+"
ssk="+ssk+" insert="+insert+" offerReply="+offerReply+", local="+local+"
size="+set.size());
+
+ if(offerReply) {
+ HashMap<Long,OfferReplyTag> map = getOfferTracker(ssk);
+ innerUnlock(map, (OfferReplyTag)tag, uid, ssk, insert,
offerReply, local, canFail);
+ } else if(insert) {
+ HashMap<Long,InsertTag> map =
getInsertTracker(ssk,local);
+ innerUnlock(map, (InsertTag)tag, uid, ssk, insert,
offerReply, local, canFail);
+ } else {
+ HashMap<Long,RequestTag> map =
getRequestTracker(ssk,local);
+ innerUnlock(map, (RequestTag)tag, uid, ssk, insert,
offerReply, local, canFail);
}
+
synchronized(runningUIDs) {
- if(!runningUIDs.remove(uid) && !canFail)
- throw new IllegalStateException("Could not
unlock "+uid+ '!');
+ UIDTag oldTag = runningUIDs.get(uid);
+ if(oldTag == null) {
+ if(canFail) return;
+ throw new IllegalStateException("Could not
unlock "+uid+ "! : ssk="+ssk+" insert="+insert+" canFail="+canFail+"
offerReply="+offerReply+" local="+local);
+ } else if(tag != oldTag) {
+ if(canFail) return;
+ Logger.error(this, "Removing "+tag+" for
"+uid+" but "+tag+" is registered!");
+ return;
+ } else {
+ runningUIDs.remove(uid);
+ }
}
}
- private HashSet<Long> getUIDTracker(boolean ssk, boolean insert,
boolean offerReply, boolean local) {
+ private<T extends UIDTag> void innerUnlock(HashMap<Long, T> map, T tag,
Long uid, boolean ssk, boolean insert, boolean offerReply, boolean local,
boolean canFail) {
+ synchronized(map) {
+ if(logMINOR) Logger.minor(this, "Unlocking "+uid+"
ssk="+ssk+" insert="+insert+" offerReply="+offerReply+" local="+local+"
size="+map.size(), new Exception("debug"));
+ if(map.get(uid) != tag) {
+ if(canFail) {
+ if(logMINOR) Logger.minor(this, "Can
fail and did fail: removing "+tag+" got "+map.get(uid)+" for "+uid);
+ } else {
+ Logger.error(this, "Removing "+tag+"
for "+uid+" returned "+map.get(uid));
+ }
+ } else
+ map.remove(uid);
+ if(logMINOR) Logger.minor(this, "Unlocked "+uid+"
ssk="+ssk+" insert="+insert+" offerReply="+offerReply+" local="+local+"
size="+map.size());
+ }
+ }
+
+ private HashMap<Long, RequestTag> getRequestTracker(boolean ssk,
boolean local) {
if(ssk) {
- if(offerReply)
- return runningSSKOfferReplyUIDs;
- if(!local)
- return insert ? runningSSKPutUIDs :
runningSSKGetUIDs;
- else
- return insert ? runningLocalSSKPutUIDs :
runningLocalSSKGetUIDs;
+ return local ? runningLocalSSKGetUIDs :
runningSSKGetUIDs;
} else {
- if(offerReply)
- return runningCHKOfferReplyUIDs;
- if(!local)
- return insert ? runningCHKPutUIDs :
runningCHKGetUIDs;
- else
- return insert ? runningLocalCHKPutUIDs :
runningLocalCHKGetUIDs;
+ return local ? runningLocalCHKGetUIDs :
runningCHKGetUIDs;
}
}
+
+ private HashMap<Long, InsertTag> getInsertTracker(boolean ssk, boolean
local) {
+ if(ssk) {
+ return local ? runningLocalSSKPutUIDs :
runningSSKPutUIDs;
+ } else {
+ return local ? runningLocalCHKPutUIDs :
runningCHKPutUIDs;
+ }
+ }
+
+ private HashMap<Long, OfferReplyTag> getOfferTracker(boolean ssk) {
+ return ssk ? runningSSKOfferReplyUIDs :
runningCHKOfferReplyUIDs;
+ }
+
+ static final int TIMEOUT = 10 * 60 * 1000;
+ private void startDeadUIDChecker() {
+ getTicker().queueTimedJob(deadUIDChecker, TIMEOUT);
+ }
+
+ private Runnable deadUIDChecker = new Runnable() {
+ public void run() {
+ try {
+ checkUIDs(runningLocalSSKGetUIDs);
+ checkUIDs(runningLocalCHKGetUIDs);
+ checkUIDs(runningLocalSSKPutUIDs);
+ checkUIDs(runningLocalCHKPutUIDs);
+ checkUIDs(runningSSKGetUIDs);
+ checkUIDs(runningCHKGetUIDs);
+ checkUIDs(runningSSKPutUIDs);
+ checkUIDs(runningCHKPutUIDs);
+ checkUIDs(runningSSKOfferReplyUIDs);
+ checkUIDs(runningCHKOfferReplyUIDs);
+ } finally {
+ getTicker().queueTimedJob(this, 60*1000);
+ }
+ }
+
+ private void checkUIDs(HashMap<Long, ? extends UIDTag> map) {
+ Long[] uids;
+ UIDTag[] tags;
+ synchronized(map) {
+ uids = map.keySet().toArray(new
Long[map.size()]);
+ tags = map.values().toArray(new
UIDTag[map.size()]);
+ }
+ long now = System.currentTimeMillis();
+ for(int i=0;i<uids.length;i++) {
+ if(now - tags[i].createdTime > TIMEOUT) {
+ tags[i].logStillPresent(uids[i]);
+ synchronized(map) {
+ map.remove(uids[i]);
+ }
+ }
+ }
+ }
+ };
+
+
/**
* @return Some status information.
*/
@@ -3927,7 +4020,7 @@
public void addRunningUIDs(Vector<Long> list) {
synchronized(runningUIDs) {
- list.addAll(runningUIDs);
+ list.addAll(runningUIDs.keySet());
}
}
@@ -3981,4 +4074,138 @@
return false;
}
+ private volatile long turtleCount;
+
+ /**
+ * Make a running request sender into a turtle request.
+ * Backoff: when the transfer finishes, or after 10 seconds if no
cancellation.
+ * Downstream: Cancel all dependant RequestHandler's and local requests.
+ * This also removes it from the load management code.
+ * Registration: We track the turtles for each peer, and overall. No
two turtles from the
+ * same node may share the same key, and there is an overall limit.
+ * @param sender
+ */
+ public void makeTurtle(RequestSender sender) {
+ // Registration
+ // FIXME check the datastore.
+ if(!this.registerTurtleTransfer(sender)) {
+ // Too many turtles running, or already two turtles for
this key (we allow two in case one peer turtles as a DoS).
+ sender.killTurtle();
+ Logger.error(this, "Didn't make turtle (global) for key
"+sender.key+" for "+sender);
+ return;
+ }
+ PeerNode from = sender.transferringFrom();
+ if(!from.registerTurtleTransfer(sender)) {
+ // Too many turtles running, or already a turtle for
this key.
+ // Abort it.
+ unregisterTurtleTransfer(sender);
+ sender.killTurtle();
+ Logger.error(this, "Didn't make turtle (peer) for key
"+sender.key+" for "+sender);
+ return;
+ }
+ Logger.error(this, "TURTLING: "+sender.key+" for "+sender);
+ // Do not transfer coalesce!!
+ synchronized(transferringRequestSenders) {
+ transferringRequestSenders.remove((NodeCHK)sender.key);
+ }
+ turtleCount++;
+
+ // Abort downstream transfers, set the turtle mode flag and set
up the backoff callback.
+ sender.setTurtle();
+ }
+
+ public long getTurtleCount() {
+ return turtleCount;
+ }
+
+ private static int MAX_TURTLES = 10;
+ private static int MAX_TURTLES_PER_KEY = 2;
+
+ private HashMap<Key,RequestSender[]> turtlingTransfers = new
HashMap<Key,RequestSender[]>();
+
+ private boolean registerTurtleTransfer(RequestSender sender) {
+ Key key = sender.key;
+ synchronized(turtlingTransfers) {
+ if(getNumIncomingTurtles() >= MAX_TURTLES) {
+ Logger.error(this, "Too many turtles running
globally");
+ return false;
+ }
+ if(!turtlingTransfers.containsKey(key)) {
+ turtlingTransfers.put(key, new RequestSender[]
{ sender });
+ Logger.error(this, "Running turtles (a):
"+getNumIncomingTurtles()+" : "+turtlingTransfers.size());
+ return true;
+ } else {
+ RequestSender[] senders =
turtlingTransfers.get(key);
+ if(senders.length >= MAX_TURTLES_PER_KEY) {
+ Logger.error(this, "Too many turtles
for key globally");
+ return false;
+ }
+ for(int i=0;i<senders.length;i++) {
+ if(senders[i] == sender) {
+ Logger.error(this, "Registering
turtle for "+sender+" : "+key+" twice! (globally)");
+ return false;
+ }
+ }
+ RequestSender[] newSenders = new
RequestSender[senders.length+1];
+ System.arraycopy(senders, 0, newSenders, 0,
senders.length);
+ newSenders[senders.length] = sender;
+ turtlingTransfers.put(key, newSenders);
+ Logger.error(this, "Running turtles (b):
"+getNumIncomingTurtles()+" : "+turtlingTransfers.size());
+ return true;
+ }
+ }
+ }
+
+ public void unregisterTurtleTransfer(RequestSender sender) {
+ Key key = sender.key;
+ synchronized(turtlingTransfers) {
+ if(!turtlingTransfers.containsKey(key)) {
+ Logger.error(this, "Removing turtle "+sender+"
for "+key+" : DOES NOT EXIST IN GLOBAL TURTLES LIST");
+ return;
+ }
+ RequestSender[] senders = turtlingTransfers.get(key);
+ if(senders.length == 1 && senders[0] == sender) {
+ turtlingTransfers.remove(key);
+ return;
+ }
+ if(senders.length == 2) {
+ if(senders[0] == sender) {
+ turtlingTransfers.put(key, new
RequestSender[] { senders[1] });
+ } else if(senders[1] == sender) {
+ turtlingTransfers.put(key, new
RequestSender[] { senders[0] });
+ }
+ return;
+ }
+ int x = 0;
+ for(int i=0;i<senders.length;i++) {
+ if(senders[i] == sender) x++;
+ }
+ if(x == 0) {
+ Logger.error(this, "Turtle not in global
register: "+sender+" for "+key);
+ return;
+ }
+ if(senders.length == x) {
+ Logger.error(this, "Lots of copies of turtle:
"+x);
+ turtlingTransfers.remove(key);
+ return;
+ }
+ RequestSender[] newSenders = new
RequestSender[senders.length - x];
+ int idx = 0;
+ for(RequestSender s : senders) {
+ if(s == sender) continue;
+ newSenders[idx++] = s;
+ }
+ turtlingTransfers.put(key, newSenders);
+ }
+ }
+
+ public int getNumIncomingTurtles() {
+ synchronized(turtlingTransfers) {
+ int turtles = 0;
+ for(RequestSender[] senders :
turtlingTransfers.values())
+ turtles += senders.length;
+ return turtles;
+ }
+ }
+
}
Modified: branches/db4o/freenet/src/freenet/node/NodeClientCore.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeClientCore.java 2009-01-22
18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/NodeClientCore.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -617,11 +617,12 @@
public void asyncGet(Key key, boolean cache, boolean offersOnly, final
SimpleRequestSenderCompletionListener listener) {
final long uid = random.nextLong();
final boolean isSSK = key instanceof NodeSSK;
- if(!node.lockUID(uid, isSSK, false, false, true)) {
+ final RequestTag tag = new RequestTag(isSSK,
RequestTag.START.ASYNC_GET);
+ if(!node.lockUID(uid, isSSK, false, false, true, tag)) {
Logger.error(this, "Could not lock UID just randomly
generated: " + uid + " - probably indicates broken PRNG");
return;
}
- asyncGet(key, cache, offersOnly, uid, new
RequestSender.Listener() {
+ asyncGet(key, isSSK, cache, offersOnly, uid, new
RequestSender.Listener() {
public void onCHKTransferBegins() {
// Ignore
@@ -633,11 +634,16 @@
public void onRequestSenderFinished(int status) {
// If transfer coalescing has happened, we may
have already unlocked.
- node.unlockUID(uid, isSSK, false, true, false,
true);
+ node.unlockUID(uid, isSSK, false, true, false,
true, tag);
+ tag.setRequestSenderFinished(status);
if(listener != null)
listener.completed(status ==
RequestSender.SUCCESS);
}
- });
+
+ public void onAbortDownstreamTransfers(int reason,
String desc) {
+ // Ignore, onRequestSenderFinished will also be
called.
+ }
+ }, tag);
}
/**
@@ -646,26 +652,28 @@
* anything and will run asynchronously. Caller is responsible for
unlocking the UID.
* @param key
*/
- void asyncGet(Key key, boolean cache, boolean offersOnly, long uid,
RequestSender.Listener listener) {
+ void asyncGet(Key key, boolean isSSK, boolean cache, boolean
offersOnly, long uid, RequestSender.Listener listener, RequestTag tag) {
try {
Object o = node.makeRequestSender(key, node.maxHTL(),
uid, null, false, cache, false, offersOnly);
if(o instanceof KeyBlock) {
- node.unlockUID(uid, false, false, true, false,
true);
+ tag.servedFromDatastore = true;
+ node.unlockUID(uid, isSSK, false, true, false,
true, tag);
return; // Already have it.
}
RequestSender rs = (RequestSender) o;
+ tag.setSender(rs);
rs.addListener(listener);
if(rs.uid != uid)
- node.unlockUID(uid, false, false, false, false,
true);
+ node.unlockUID(uid, isSSK, false, false, false,
true, tag);
// Else it has started a request.
if(logMINOR)
Logger.minor(this, "Started " + o + " for " +
uid + " for " + key);
} catch(RuntimeException e) {
Logger.error(this, "Caught error trying to start
request: " + e, e);
- node.unlockUID(uid, false, false, true, false, true);
+ node.unlockUID(uid, isSSK, false, true, false, true,
tag);
} catch(Error e) {
Logger.error(this, "Caught error trying to start
request: " + e, e);
- node.unlockUID(uid, false, false, true, false, true);
+ node.unlockUID(uid, isSSK, false, true, false, true,
tag);
}
}
@@ -682,7 +690,8 @@
logMINOR = Logger.shouldLog(Logger.MINOR, this);
long startTime = System.currentTimeMillis();
long uid = random.nextLong();
- if(!node.lockUID(uid, false, false, false, true)) {
+ RequestTag tag = new RequestTag(false, RequestTag.START.LOCAL);
+ if(!node.lockUID(uid, false, false, false, true, tag)) {
Logger.error(this, "Could not lock UID just randomly
generated: " + uid + " - probably indicates broken PRNG");
throw new
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR);
}
@@ -690,6 +699,7 @@
Object o = node.makeRequestSender(key.getNodeCHK(),
node.maxHTL(), uid, null, localOnly, cache, ignoreStore, false);
if(o instanceof CHKBlock)
try {
+ tag.setServedFromDatastore();
return new ClientCHKBlock((CHKBlock) o,
key);
} catch(CHKVerifyException e) {
Logger.error(this, "Does not verify: "
+ e, e);
@@ -709,6 +719,9 @@
}
int status = rs.getStatus();
+
+ if(rs.abortedDownstreamTransfers())
+ status = RequestSender.TRANSFER_FAILED;
if(status == RequestSender.NOT_FINISHED)
continue;
@@ -730,6 +743,8 @@
// See below
requestStarters.rejectedOverload(false, false);
rejectedOverload = true;
+ long rtt =
System.currentTimeMillis() - startTime;
+
node.nodeStats.reportCHKTime(rtt, false);
}
} else
if(rs.hasForwarded() &&
@@ -744,9 +759,13 @@
requestStarters.requestCompleted(false, false, key.getNodeKey());
// Count towards RTT even if
got a RejectedOverload - but not if timed out.
requestStarters.chkRequestThrottle.successfulCompletion(rtt);
+
node.nodeStats.reportCHKTime(rtt, status == RequestSender.SUCCESS);
+ if(status ==
RequestSender.SUCCESS) {
+ Logger.minor(this,
"Successful CHK fetch took "+rtt);
+ }
}
- if(rs.getStatus() == RequestSender.SUCCESS)
+ if(status == RequestSender.SUCCESS)
try {
return new
ClientCHKBlock(rs.getPRB().getBlock(), rs.getHeaders(), key, true);
} catch(CHKVerifyException e) {
@@ -757,8 +776,7 @@
throw new
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR);
}
else {
- int rStatus = rs.getStatus();
- switch(rStatus) {
+ switch(status) {
case RequestSender.NOT_FINISHED:
Logger.error(this, "RS
still running in getCHK!: " + rs);
throw new
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR);
@@ -780,13 +798,13 @@
case
RequestSender.INTERNAL_ERROR:
throw new
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR);
default:
- Logger.error(this,
"Unknown RequestSender code in getCHK: " + rStatus + " on " + rs);
+ Logger.error(this,
"Unknown RequestSender code in getCHK: " + status + " on " + rs);
throw new
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR);
}
}
}
} finally {
- node.unlockUID(uid, false, false, true, false, true);
+ node.unlockUID(uid, false, false, true, false, true,
tag);
}
}
@@ -794,7 +812,8 @@
logMINOR = Logger.shouldLog(Logger.MINOR, this);
long startTime = System.currentTimeMillis();
long uid = random.nextLong();
- if(!node.lockUID(uid, true, false, false, true)) {
+ RequestTag tag = new RequestTag(true, RequestTag.START.LOCAL);
+ if(!node.lockUID(uid, true, false, false, true, tag)) {
Logger.error(this, "Could not lock UID just randomly
generated: " + uid + " - probably indicates broken PRNG");
throw new
LowLevelGetException(LowLevelGetException.INTERNAL_ERROR);
}
@@ -802,6 +821,7 @@
Object o = node.makeRequestSender(key.getNodeKey(),
node.maxHTL(), uid, null, localOnly, cache, ignoreStore, false);
if(o instanceof SSKBlock)
try {
+ tag.setServedFromDatastore();
SSKBlock block = (SSKBlock) o;
key.setPublicKey(block.getPubKey());
return ClientSSKBlock.construct(block,
key);
@@ -897,7 +917,7 @@
}
}
} finally {
- node.unlockUID(uid, true, false, true, false, true);
+ node.unlockUID(uid, true, false, true, false, true,
tag);
}
}
@@ -917,7 +937,8 @@
PartiallyReceivedBlock prb = new
PartiallyReceivedBlock(Node.PACKETS_IN_BLOCK, Node.PACKET_SIZE, data);
CHKInsertSender is;
long uid = random.nextLong();
- if(!node.lockUID(uid, false, true, false, true)) {
+ InsertTag tag = new InsertTag(false, InsertTag.START.LOCAL);
+ if(!node.lockUID(uid, false, true, false, true, tag)) {
Logger.error(this, "Could not lock UID just randomly
generated: " + uid + " - probably indicates broken PRNG");
throw new
LowLevelPutException(LowLevelPutException.INTERNAL_ERROR);
}
@@ -1023,7 +1044,7 @@
}
}
} finally {
- node.unlockUID(uid, false, true, true, false, true);
+ node.unlockUID(uid, false, true, true, false, true,
tag);
}
}
@@ -1031,7 +1052,8 @@
logMINOR = Logger.shouldLog(Logger.MINOR, this);
SSKInsertSender is;
long uid = random.nextLong();
- if(!node.lockUID(uid, true, true, false, true)) {
+ InsertTag tag = new InsertTag(true, InsertTag.START.LOCAL);
+ if(!node.lockUID(uid, true, true, false, true, tag)) {
Logger.error(this, "Could not lock UID just randomly
generated: " + uid + " - probably indicates broken PRNG");
throw new
LowLevelPutException(LowLevelPutException.INTERNAL_ERROR);
}
@@ -1149,7 +1171,7 @@
}
}
} finally {
- node.unlockUID(uid, true, true, true, false, true);
+ node.unlockUID(uid, true, true, true, false, true, tag);
}
}
Modified: branches/db4o/freenet/src/freenet/node/NodeCrypto.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeCrypto.java 2009-01-22
18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/NodeCrypto.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -62,6 +62,8 @@
byte[] identityHash;
/** Hash of hash of identity i.e. hash of setup key. */
byte[] identityHashHash;
+ /** Nonce used to generate ?secureid= for fproxy etc */
+ byte[] clientNonce;
/** My crypto group */
private DSAGroup cryptoGroup;
/** My private key */
@@ -235,6 +237,18 @@
}
myARK = ark;
+ String cn = fs.get("clientNonce");
+ if(cn != null) {
+ try {
+ clientNonce = Base64.decode(cn);
+ } catch (IllegalBase64Exception e) {
+ throw new IOException("Invalid clientNonce
field: "+e);
+ }
+ } else {
+ clientNonce = new byte[32];
+ node.random.nextBytes(clientNonce);
+ }
+
}
/**
@@ -253,6 +267,8 @@
myARKNumber = 0;
SHA256.returnMessageDigest(md);
anonSetupCipher.initialize(identityHash);
+ clientNonce = new byte[32];
+ node.random.nextBytes(clientNonce);
}
public void start(boolean disableHangchecker) {
@@ -437,6 +453,7 @@
// We must save the location!
if(fs.get("location") == null)
fs.put("location", node.lm.getLocation());
+ fs.putSingle("clientNonce", Base64.encode(clientNonce));
}
Modified: branches/db4o/freenet/src/freenet/node/NodeDispatcher.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeDispatcher.java 2009-01-22
18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/NodeDispatcher.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -261,7 +261,8 @@
// Do we want it? We can RejectOverload if we don't have the
bandwidth...
boolean isSSK = key instanceof NodeSSK;
- node.lockUID(uid, isSSK, false, true, false);
+ OfferReplyTag tag = new OfferReplyTag(isSSK);
+ node.lockUID(uid, isSSK, false, true, false, tag);
boolean needPubKey;
try {
needPubKey = m.getBoolean(DMT.NEED_PUB_KEY);
@@ -275,22 +276,22 @@
} catch (NotConnectedException e) {
Logger.normal(this, "Rejecting (overload) data
request from "+source.getPeer()+": "+e);
}
- node.unlockUID(uid, isSSK, false, false, true, false);
+ node.unlockUID(uid, isSSK, false, false, true, false,
tag);
return true;
}
} catch (Error e) {
- node.unlockUID(uid, isSSK, false, false, true, false);
+ node.unlockUID(uid, isSSK, false, false, true, false,
tag);
throw e;
} catch (RuntimeException e) {
- node.unlockUID(uid, isSSK, false, false, true, false);
+ node.unlockUID(uid, isSSK, false, false, true, false,
tag);
throw e;
} // Otherwise, sendOfferedKey is responsible for unlocking.
// Accept it.
try {
- node.failureTable.sendOfferedKey(key, isSSK,
needPubKey, uid, source);
+ node.failureTable.sendOfferedKey(key, isSSK,
needPubKey, uid, source, tag);
} catch (NotConnectedException e) {
// Too bad.
}
@@ -354,7 +355,8 @@
}
short htl = m.getShort(DMT.HTL);
Key key = (Key) m.getObject(DMT.FREENET_ROUTING_KEY);
- if(!node.lockUID(id, isSSK, false, false, false)) {
+ final RequestTag tag = new RequestTag(isSSK, RequestTag.START.REMOTE);
+ if(!node.lockUID(id, isSSK, false, false, false, tag)) {
if(logMINOR) Logger.minor(this, "Could not lock ID
"+id+" -> rejecting (already running)");
Message rejected = DMT.createFNPRejectedLoop(id);
try {
@@ -377,7 +379,8 @@
} catch (NotConnectedException e) {
Logger.normal(this, "Rejecting (overload) data
request from "+source.getPeer()+": "+e);
}
- node.unlockUID(id, isSSK, false, false, false, false);
+ tag.setRejected();
+ node.unlockUID(id, isSSK, false, false, false, false,
tag);
// Do not tell failure table.
// Otherwise an attacker can flood us with requests
very cheaply and purge our
// failure table even though we didn't accept any of
them.
@@ -385,7 +388,7 @@
}
nodeStats.reportIncomingRequestLocation(key.toNormalizedDouble());
//if(!node.lockUID(id)) return false;
- RequestHandler rh = new RequestHandler(m, source, id, node,
htl, key);
+ RequestHandler rh = new RequestHandler(m, source, id, node,
htl, key, tag);
node.executor.execute(rh, "RequestHandler for UID "+id+" on
"+node.getDarknetPortNumber());
return true;
}
@@ -402,7 +405,8 @@
}
return true;
}
- if(!node.lockUID(id, isSSK, true, false, false)) {
+ InsertTag tag = new InsertTag(isSSK, InsertTag.START.REMOTE);
+ if(!node.lockUID(id, isSSK, true, false, false, tag)) {
if(logMINOR) Logger.minor(this, "Could not lock ID
"+id+" -> rejecting (already running)");
Message rejected = DMT.createFNPRejectedLoop(id);
try {
@@ -422,7 +426,7 @@
} catch (NotConnectedException e) {
Logger.normal(this, "Rejecting (overload)
insert request from "+source.getPeer()+": "+e);
}
- node.unlockUID(id, isSSK, true, false, false, false);
+ node.unlockUID(id, isSSK, true, false, false, false,
tag);
return true;
}
long now = System.currentTimeMillis();
@@ -431,17 +435,17 @@
byte[] data = ((ShortBuffer) m.getObject(DMT.DATA)).getData();
byte[] headers = ((ShortBuffer)
m.getObject(DMT.BLOCK_HEADERS)).getData();
short htl = m.getShort(DMT.HTL);
- SSKInsertHandler rh = new SSKInsertHandler(key, data,
headers, htl, source, id, node, now);
+ SSKInsertHandler rh = new SSKInsertHandler(key, data,
headers, htl, source, id, node, now, tag);
rh.receivedBytes(m.receivedByteCount());
node.executor.execute(rh, "SSKInsertHandler for "+id+"
on "+node.getDarknetPortNumber());
} else if(m.getSpec().equals(DMT.FNPSSKInsertRequestNew)) {
NodeSSK key = (NodeSSK)
m.getObject(DMT.FREENET_ROUTING_KEY);
short htl = m.getShort(DMT.HTL);
- SSKInsertHandler rh = new SSKInsertHandler(key, null,
null, htl, source, id, node, now);
+ SSKInsertHandler rh = new SSKInsertHandler(key, null,
null, htl, source, id, node, now, tag);
rh.receivedBytes(m.receivedByteCount());
node.executor.execute(rh, "SSKInsertHandler for "+id+"
on "+node.getDarknetPortNumber());
} else {
- CHKInsertHandler rh = new CHKInsertHandler(m, source,
id, node, now);
+ CHKInsertHandler rh = new CHKInsertHandler(m, source,
id, node, now, tag);
node.executor.execute(rh, "CHKInsertHandler for "+id+"
on "+node.getDarknetPortNumber());
}
if(logMINOR) Logger.minor(this, "Started InsertHandler for
"+id);
@@ -579,7 +583,7 @@
*/
private boolean handleRoutedRejected(Message m) {
long id = m.getLong(DMT.UID);
- Long lid = new Long(id);
+ Long lid = Long.valueOf(id);
RoutedContext rc = routedContexts.get(lid);
if(rc == null) {
// Gah
@@ -618,7 +622,7 @@
if(logMINOR) Logger.minor(this, "handleRouted("+m+ ')');
long id = m.getLong(DMT.UID);
- Long lid = new Long(id);
+ Long lid = Long.valueOf(id);
short htl = m.getShort(DMT.HTL);
byte[] identity = ((ShortBuffer)
m.getObject(DMT.NODE_IDENTITY)).getData();
if(source != null) htl = source.decrementHTL(htl);
@@ -661,7 +665,7 @@
boolean handleRoutedReply(Message m) {
long id = m.getLong(DMT.UID);
if(logMINOR) Logger.minor(this, "Got reply: "+m);
- Long lid = new Long(id);
+ Long lid = Long.valueOf(id);
RoutedContext ctx = routedContexts.get(lid);
if(ctx == null) {
Logger.error(this, "Unrecognized routed reply: "+m);
Modified: branches/db4o/freenet/src/freenet/node/NodeStarter.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeStarter.java 2009-01-22
18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/NodeStarter.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -76,7 +76,7 @@
public Integer start(String[] args) {
if(args.length > 1) {
System.out.println("Usage: $ java freenet.node.Node
<configFile>");
- return new Integer(-1);
+ return Integer.valueOf(-1);
}
getExtBuild();
@@ -98,7 +98,7 @@
} catch(IOException e) {
System.out.println("Error : " + e);
e.printStackTrace();
- return new Integer(-1);
+ return Integer.valueOf(-1);
}
// First, set up logging. It is global, and may be shared
between several nodes.
@@ -111,7 +111,7 @@
} catch(InvalidConfigValueException e) {
System.err.println("Error: could not set up logging: "
+ e.getMessage());
e.printStackTrace();
- return new Integer(-2);
+ return Integer.valueOf(-2);
}
executor.start();
Modified: branches/db4o/freenet/src/freenet/node/NodeStats.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeStats.java 2009-01-22
18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/NodeStats.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -3,8 +3,6 @@
import java.io.File;
import java.text.DecimalFormat;
import java.text.NumberFormat;
-import java.util.Arrays;
-import java.util.Comparator;
import freenet.config.InvalidConfigValueException;
import freenet.config.SubConfig;
@@ -134,7 +132,13 @@
final TrivialRunningAverage localFetchPSuccess;
final TrivialRunningAverage remoteFetchPSuccess;
final TrivialRunningAverage blockTransferPSuccess;
+ final TrivialRunningAverage blockTransferFailTurtled;
+ final TrivialRunningAverage blockTransferFailTimeout;
+ final TrivialRunningAverage successfulLocalCHKFetchTimeAverage;
+ final TrivialRunningAverage unsuccessfulLocalCHKFetchTimeAverage;
+ final TrivialRunningAverage localCHKFetchTimeAverage;
+
private long previous_input_stat;
private long previous_output_stat;
private long previous_io_stat_time;
@@ -343,7 +347,13 @@
localFetchPSuccess = new TrivialRunningAverage();
remoteFetchPSuccess = new TrivialRunningAverage();
blockTransferPSuccess = new TrivialRunningAverage();
+ blockTransferFailTurtled = new TrivialRunningAverage();
+ blockTransferFailTimeout = new TrivialRunningAverage();
+ successfulLocalCHKFetchTimeAverage = new
TrivialRunningAverage();
+ unsuccessfulLocalCHKFetchTimeAverage = new
TrivialRunningAverage();
+ localCHKFetchTimeAverage = new TrivialRunningAverage();
+
requestOutputThrottle =
new TokenBucket(Math.max(obwLimit*60, 32768*20),
(int)((1000L*1000L*1000L) / (obwLimit)), 0);
requestInputThrottle =
@@ -625,6 +635,138 @@
return "Input bandwidth liability
("+bandwidthLiabilityInput+" > "+bandwidthAvailableInput+")";
}
+// // We want fast transfers!
+// // We want it to be *possible* for all transfers currently
running to complete in a short period.
+// // This does NOT assume they are all successful, it uses the
averages.
+// // As of 09/01/09, the typical successful CHK fetch takes
around 18 seconds ...
+//
+// // Accept a transfer if our *current* load can be completed in
the target time.
+// // We do not care what the new request we are considering is.
+// // This is more or less equivalent to what we do above but lets
more requests through.
+//
+// numRemoteCHKRequests--;
+// numRemoteSSKRequests--;
+// numRemoteCHKInserts--;
+// numRemoteSSKInserts--;
+// numLocalCHKRequests--;
+// numLocalSSKRequests--;
+// numLocalCHKInserts--;
+// numLocalSSKInserts--;
+//
+// final double TRANSFER_EVERYTHING_TIME = 5.0; // 5 seconds target
+//
+// double completionBandwidthOutput;
+// if(ignoreLocalVsRemoteBandwidthLiability) {
+// completionBandwidthOutput =
+// remoteChkFetchBytesSentAverage.currentValue() *
(numRemoteCHKRequests + numLocalCHKRequests) +
+// remoteSskFetchBytesSentAverage.currentValue() *
(numRemoteSSKRequests + numLocalSSKRequests) +
+// remoteChkInsertBytesSentAverage.currentValue()
* (numRemoteCHKInserts + numLocalCHKInserts) +
+// remoteSskInsertBytesSentAverage.currentValue()
* (numRemoteSSKInserts + numLocalSSKInserts);
+// } else {
+// completionBandwidthOutput =
+// remoteChkFetchBytesSentAverage.currentValue() *
numRemoteCHKRequests +
+// localChkFetchBytesSentAverage.currentValue() *
numLocalCHKRequests +
+// remoteSskFetchBytesSentAverage.currentValue() *
numRemoteSSKRequests +
+// localSskFetchBytesSentAverage.currentValue() *
numLocalSSKRequests +
+// remoteChkInsertBytesSentAverage.currentValue() *
numRemoteCHKInserts +
+// localChkInsertBytesSentAverage.currentValue() *
numLocalCHKInserts +
+// remoteSskInsertBytesSentAverage.currentValue() *
numRemoteSSKInserts +
+// localSskInsertBytesSentAverage.currentValue() *
numLocalSSKInserts +
+// successfulChkOfferReplyBytesSentAverage.currentValue()
* numCHKOfferReplies +
+// successfulSskOfferReplyBytesSentAverage.currentValue()
* numSSKOfferReplies;
+// }
+//
+// int outputLimit = node.getOutputBandwidthLimit();
+//
+// double outputBandwidthAvailableInTargetTime = outputLimit *
TRANSFER_EVERYTHING_TIME;
+//
+// // Increase the target for slow nodes.
+//
+// double minimum =
+// remoteChkFetchBytesSentAverage.currentValue() +
+// localChkFetchBytesSentAverage.currentValue() +
+// remoteSskFetchBytesSentAverage.currentValue() +
+// localSskFetchBytesSentAverage.currentValue() +
+// remoteChkInsertBytesSentAverage.currentValue() +
+// localChkInsertBytesSentAverage.currentValue() +
+// remoteSskInsertBytesSentAverage.currentValue() +
+// localSskInsertBytesSentAverage.currentValue() +
+// successfulChkOfferReplyBytesSentAverage.currentValue() +
+// successfulSskOfferReplyBytesSentAverage.currentValue();
+// minimum /= 2; // roughly one of each type, averaged over remote
and local; FIXME get a real non-specific average
+//
+// if(outputBandwidthAvailableInTargetTime < minimum) {
+// outputBandwidthAvailableInTargetTime = minimum;
+// if(logMINOR) Logger.minor(this, "Increased minimum time
to transfer everything to "+(minimum / outputLimit)+"s = "+minimum+"B to
compensate for slow node");
+// }
+//
+// if(logMINOR) Logger.minor(this, TRANSFER_EVERYTHING_TIME+"
second limit: "+outputBandwidthAvailableInTargetTime+" expected transfers:
"+completionBandwidthOutput);
+//
+// if(completionBandwidthOutput >
outputBandwidthAvailableInTargetTime) {
+// pInstantRejectIncoming.report(1.0);
+// rejected("Transfer speed (output)", isLocal);
+// return "Transfer speed (output)
("+bandwidthLiabilityOutput+" > "+bandwidthAvailableOutput+")";
+// }
+//
+//
+//
+// double completionBandwidthInput;
+// if(ignoreLocalVsRemoteBandwidthLiability) {
+// completionBandwidthInput =
+//
remoteChkFetchBytesReceivedAverage.currentValue() * (numRemoteCHKRequests +
numLocalCHKRequests) +
+//
remoteSskFetchBytesReceivedAverage.currentValue() * (numRemoteSSKRequests +
numLocalSSKRequests) +
+//
remoteChkInsertBytesReceivedAverage.currentValue() * (numRemoteCHKInserts +
numLocalCHKInserts) +
+//
remoteSskInsertBytesReceivedAverage.currentValue() * (numRemoteSSKInserts +
numLocalSSKInserts);
+// } else {
+// completionBandwidthInput =
+// // For receiving data, local requests are the same as
remote ones
+// remoteChkFetchBytesReceivedAverage.currentValue() *
numRemoteCHKRequests +
+// localChkFetchBytesReceivedAverage.currentValue() *
numLocalCHKRequests +
+// remoteSskFetchBytesReceivedAverage.currentValue() *
numRemoteSSKRequests +
+// localSskFetchBytesReceivedAverage.currentValue() *
numLocalSSKRequests +
+// // Local inserts don't receive the data to relay, so
use the local variant
+// remoteChkInsertBytesReceivedAverage.currentValue() *
numRemoteCHKInserts +
+// localChkInsertBytesReceivedAverage.currentValue() *
numLocalCHKInserts +
+// remoteSskInsertBytesReceivedAverage.currentValue() *
numRemoteSSKInserts +
+// localSskInsertBytesReceivedAverage.currentValue() *
numLocalSSKInserts +
+//
successfulChkOfferReplyBytesReceivedAverage.currentValue() * numCHKOfferReplies
+
+//
successfulSskOfferReplyBytesReceivedAverage.currentValue() * numSSKOfferReplies;
+// }
+// int inputLimit = node.getInputBandwidthLimit();
+// double inputBandwidthAvailableInTargetTime =
+// inputLimit * TRANSFER_EVERYTHING_TIME;
+//
+// // Increase the target for slow nodes.
+//
+// minimum =
+// remoteChkFetchBytesReceivedAverage.currentValue() +
+// localChkFetchBytesReceivedAverage.currentValue() +
+// remoteSskFetchBytesReceivedAverage.currentValue() +
+// localSskFetchBytesReceivedAverage.currentValue() +
+// remoteChkInsertBytesReceivedAverage.currentValue() +
+// localChkInsertBytesReceivedAverage.currentValue() +
+// remoteSskInsertBytesReceivedAverage.currentValue() +
+// localSskInsertBytesReceivedAverage.currentValue() +
+//
successfulChkOfferReplyBytesReceivedAverage.currentValue() +
+//
successfulSskOfferReplyBytesReceivedAverage.currentValue();
+// minimum /= 2; // roughly one of each type, averaged over remote
and local; FIXME get a real non-specific average
+//
+// if(inputBandwidthAvailableInTargetTime < minimum) {
+// inputBandwidthAvailableInTargetTime = minimum;
+// if(logMINOR) Logger.minor(this, "Increased minimum time
to transfer everything (input) to "+(minimum / inputLimit)+"s = "+minimum+"B to
compensate for slow node");
+// }
+//
+//
+//
+// if(bandwidthAvailableInput < 0){
+// Logger.error(this, "Negative available bandwidth:
"+inputBandwidthAvailableInTargetTime+"
node.ibwlimit="+node.getInputBandwidthLimit()+"
node.obwlimit="+node.getOutputBandwidthLimit()+"
node.inputLimitDefault="+node.inputLimitDefault);
+// }
+// if(completionBandwidthInput >
inputBandwidthAvailableInTargetTime) {
+// pInstantRejectIncoming.report(1.0);
+// rejected("Transfer speed (input)", isLocal);
+// return "Transfer speed (input)
("+bandwidthLiabilityInput+" > "+bandwidthAvailableInput+")";
+// }
+
// Do we have the bandwidth?
double expected = this.getThrottle(isLocal, isInsert, isSSK,
true).currentValue();
int expectedSent = (int)Math.max(expected / overheadFraction,
0);
@@ -905,6 +1047,11 @@
}
fs.put("averagePingTime", getNodeAveragePingTime());
fs.put("bwlimitDelayTime", getBwlimitDelayTime());
+ fs.put("opennetSizeEstimateSession",
getOpennetSizeEstimate(-1));
+ int opennetSizeEstimate24hourRecent =
getOpennetSizeEstimate(now - (24 * 60 * 60 * 1000)); // 24 hours
+ fs.put("opennetSizeEstimate24hourRecent",
opennetSizeEstimate24hourRecent);
+ int opennetSizeEstimate48hourRecent =
getOpennetSizeEstimate(now - (48 * 60 * 60 * 1000)); // 48 hours
+ fs.put("opennetSizeEstimate48hourRecent",
opennetSizeEstimate48hourRecent);
fs.put("networkSizeEstimateSession",
getDarknetSizeEstimate(-1));
int networkSizeEstimate24hourRecent =
getDarknetSizeEstimate(now - (24*60*60*1000)); // 24 hours
fs.put("networkSizeEstimate24hourRecent",
networkSizeEstimate24hourRecent);
@@ -916,17 +1063,11 @@
fs.put("unclaimedFIFOSize", node.usm.getUnclaimedFIFOSize());
/* gather connection statistics */
- DarknetPeerNodeStatus[] peerNodeStatuses =
peers.getDarknetPeerNodeStatuses(true);
- Arrays.sort(peerNodeStatuses, new
Comparator<DarknetPeerNodeStatus>() {
- public int compare(DarknetPeerNodeStatus firstNode,
DarknetPeerNodeStatus secondNode) {
- int statusDifference =
firstNode.getStatusValue() - secondNode.getStatusValue();
- if (statusDifference != 0) {
- return statusDifference;
- }
- return
firstNode.getName().compareToIgnoreCase(secondNode.getName());
- }
- });
+ PeerNodeStatus[] peerNodeStatuses =
peers.getPeerNodeStatuses(true);
+ int numberOfSeedServers = getCountSeedServers(peerNodeStatuses);
+ int numberOfSeedClients = getCountSeedClients(peerNodeStatuses);
+
int numberOfConnected =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_CONNECTED);
int numberOfRoutingBackedOff =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_ROUTING_BACKED_OFF);
int numberOfTooNew =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_TOO_NEW);
@@ -941,6 +1082,8 @@
int numberOfSimpleConnected = numberOfConnected +
numberOfRoutingBackedOff;
int numberOfNotConnected = numberOfTooNew + numberOfTooOld +
numberOfDisconnected + numberOfNeverConnected + numberOfDisabled +
numberOfBursting + numberOfListening + numberOfListenOnly;
+ fs.put("numberOfSeedServers", numberOfSeedServers);
+ fs.put("numberOfSeedClients", numberOfSeedClients);
fs.put("numberOfConnected", numberOfConnected);
fs.put("numberOfRoutingBackedOff", numberOfRoutingBackedOff);
fs.put("numberOfTooNew", numberOfTooNew);
@@ -1149,7 +1292,9 @@
sskFetchPSuccess,
localFetchPSuccess,
remoteFetchPSuccess,
- blockTransferPSuccess
+ blockTransferPSuccess,
+ blockTransferFailTurtled,
+ blockTransferFailTimeout
};
final String[] names = new String[] {
// FIXME l10n, but atm this only shows up in
advanced mode
@@ -1158,7 +1303,9 @@
"SSKs",
"Local requests",
"Remote requests",
- "Block transfers"
+ "Block transfers",
+ "Turtled downstream",
+ "Transfers timed out"
};
HTMLNode row = list.addChild("tr");
row.addChild("th", "Group");
@@ -1176,6 +1323,22 @@
row.addChild("td",
thousendPoint.format(averages[i].countReports()));
}
}
+
+ row = list.addChild("tr");
+ row.addChild("td", "Turtle requests");
+ long total;
+ long succeeded;
+ synchronized(this) {
+ total = turtleTransfersCompleted;
+ succeeded = turtleSuccesses;
+ }
+ if(total == 0) {
+ row.addChild("td", "-");
+ row.addChild("td", "0");
+ } else {
+ row.addChild("td", fix3p3pct.format((double)succeeded /
total));
+ row.addChild("td", thousendPoint.format(total));
+ }
}
/* Total bytes sent by requests, excluding payload */
@@ -1701,7 +1864,11 @@
if(logMINOR) Logger.minor(this, "Successful receives:
"+blockTransferPSuccess.currentValue()+"
count="+blockTransferPSuccess.countReports());
}
- public synchronized void failedBlockReceive() {
+ public synchronized void failedBlockReceive(boolean normalFetch,
boolean timeout, boolean turtle) {
+ if(normalFetch) {
+ blockTransferFailTurtled.report(turtle ? 1.0 : 0.0);
+ blockTransferFailTimeout.report(timeout ? 1.0 : 0.0);
+ }
blockTransferPSuccess.report(0.0);
if(logMINOR) Logger.minor(this, "Successful receives:
"+blockTransferPSuccess.currentValue()+"
count="+blockTransferPSuccess.countReports());
}
@@ -1762,4 +1929,55 @@
return result;
}
+
+ private int getCountSeedServers(PeerNodeStatus[] peerNodeStatuses) {
+ int count = 0;
+ for (int peerIndex = 0; peerIndex < peerNodeStatuses.length;
peerIndex++) {
+ if (peerNodeStatuses[peerIndex].isSeedServer())
+ count++;
+ }
+ return count;
+ }
+
+ private int getCountSeedClients(PeerNodeStatus[] peerNodeStatuses) {
+ int count = 0;
+ for (int peerIndex = 0; peerIndex < peerNodeStatuses.length;
peerIndex++) {
+ if (peerNodeStatuses[peerIndex].isSeedClient())
+ count++;
+ }
+ return count;
+ }
+
+ public void reportCHKTime(long rtt, boolean successful) {
+ if(successful)
+ successfulLocalCHKFetchTimeAverage.report(rtt);
+ else
+ unsuccessfulLocalCHKFetchTimeAverage.report(rtt);
+ localCHKFetchTimeAverage.report(rtt);
+ }
+
+ public void fillDetailedTimingsBox(HTMLNode html) {
+ HTMLNode table = html.addChild("table");
+ HTMLNode row = table.addChild("tr");
+ row.addChild("td", "Successful");
+ row.addChild("td",
TimeUtil.formatTime((long)successfulLocalCHKFetchTimeAverage.currentValue(), 2,
true));
+ row = table.addChild("tr");
+ row.addChild("td", "Unsuccessful");
+ row.addChild("td",
TimeUtil.formatTime((long)unsuccessfulLocalCHKFetchTimeAverage.currentValue(),
2, true));
+ row = table.addChild("tr");
+ row.addChild("td", "Average");
+ row.addChild("td",
TimeUtil.formatTime((long)localCHKFetchTimeAverage.currentValue(), 2, true));
+ }
+
+ private long turtleTransfersCompleted;
+ private long turtleSuccesses;
+
+ synchronized void turtleSucceeded() {
+ turtleSuccesses++;
+ turtleTransfersCompleted++;
+ }
+
+ synchronized void turtleFailed() {
+ turtleTransfersCompleted++;
+ }
}
Copied: branches/db4o/freenet/src/freenet/node/OfferReplyTag.java (from rev
25205, trunk/freenet/src/freenet/node/OfferReplyTag.java)
===================================================================
--- branches/db4o/freenet/src/freenet/node/OfferReplyTag.java
(rev 0)
+++ branches/db4o/freenet/src/freenet/node/OfferReplyTag.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -0,0 +1,27 @@
+package freenet.node;
+
+import freenet.support.Logger;
+import freenet.support.TimeUtil;
+
+/**
+ * Tag tracking an offer reply.
+ * @author Matthew Toseland <toad at amphibian.dyndns.org> (0xE43DA450)
+ */
+public class OfferReplyTag extends UIDTag {
+
+ final boolean ssk;
+
+ public OfferReplyTag(boolean isSSK) {
+ super();
+ ssk = isSSK;
+ }
+
+ @Override
+ public void logStillPresent(Long uid) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Still present after
").append(TimeUtil.formatTime(age()));
+ sb.append(" : ssk=").append(ssk);
+ Logger.error(this, sb.toString());
+ }
+
+}
Modified: branches/db4o/freenet/src/freenet/node/PacketSender.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/PacketSender.java 2009-01-22
18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/PacketSender.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -29,6 +29,9 @@
* Thread that sends a packet whenever: - A packet needs to be resent
immediately -
* Acknowledgments or resend requests need to be sent urgently.
*/
+// j16sdiz (22-Dec-2008):
+// FIXME this is the only class implements Ticker, everbody is using this as
+// a generic task scheduler. Either rename this class, or create another
tricker for non-Packet tasks
public class PacketSender implements Runnable, Ticker {
private static boolean logMINOR;
@@ -55,7 +58,6 @@
long lastReceivedPacketFromAnyNode;
/** For watchdog. 32-bit to avoid locking. */
volatile int lastTimeInSeconds;
- private long timeLastSentOldOpennetConnectAttempt;
private Vector<ResendPacketItem> rpiTemp;
private int[] rpiIntTemp;
private boolean started = false;
@@ -570,7 +572,7 @@
Job job = new Job(name, runner);
if(offset < 0) offset = 0;
long now = System.currentTimeMillis();
- Long l = new Long(offset + now);
+ Long l = Long.valueOf(offset + now);
synchronized(timedJobsByTime) {
Object o = timedJobsByTime.get(l);
if(o == null)
Modified: branches/db4o/freenet/src/freenet/node/PeerManager.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/PeerManager.java 2009-01-22
18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/PeerManager.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -896,6 +896,10 @@
Logger.minor(this, "Skipping (not
connected): " + p.getPeer());
continue;
}
+ if(key != null && p.isTurtling(key)) {
+ if(logMINOR)
+ Logger.minor(this, "Skipping (already
turtling key): "+p.getPeer());
+ }
if(minVersion > 0 &&
Version.getArbitraryBuildNumber(p.getVersion(), -1) < minVersion) {
if(logMINOR)
Logger.minor(this, "Skipping old
version: " + p.getPeer());
@@ -1431,7 +1435,7 @@
* Add a PeerNode status to the map
*/
public void addPeerNodeStatus(int pnStatus, PeerNode peerNode, boolean
noLog) {
- Integer peerNodeStatus = new Integer(pnStatus);
+ Integer peerNodeStatus = Integer.valueOf(pnStatus);
addPeerNodeStatuses(pnStatus, peerNode, peerNodeStatus,
peerNodeStatuses, noLog);
if(!peerNode.isOpennet())
addPeerNodeStatuses(pnStatus, peerNode, peerNodeStatus,
peerNodeStatusesDarknet, noLog);
@@ -1462,7 +1466,7 @@
* @param darknet If true, only count darknet nodes, if false, count
all nodes.
*/
public int getPeerNodeStatusSize(int pnStatus, boolean darknet) {
- Integer peerNodeStatus = new Integer(pnStatus);
+ Integer peerNodeStatus = Integer.valueOf(pnStatus);
HashSet<PeerNode> statusSet = null;
HashMap<Integer, HashSet<PeerNode>> statuses = darknet ?
peerNodeStatusesDarknet : this.peerNodeStatuses;
synchronized(statuses) {
@@ -1479,7 +1483,7 @@
* @param isInPeers If true, complain if the node is not in the peers
list; if false, complain if it is.
*/
public void removePeerNodeStatus(int pnStatus, PeerNode peerNode,
boolean noLog) {
- Integer peerNodeStatus = new Integer(pnStatus);
+ Integer peerNodeStatus = Integer.valueOf(pnStatus);
removePeerNodeStatus(pnStatus, peerNodeStatus, peerNode,
peerNodeStatuses, noLog);
if(!peerNode.isOpennet())
removePeerNodeStatus(pnStatus, peerNodeStatus,
peerNode, peerNodeStatusesDarknet, noLog);
Modified: branches/db4o/freenet/src/freenet/node/PeerMessageQueue.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/PeerMessageQueue.java
2009-01-22 18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/PeerMessageQueue.java
2009-01-22 18:32:20 UTC (rev 25217)
@@ -16,7 +16,7 @@
private final PrioQueue[] queuesByPriority;
- private class PrioQueue {
+ private static class PrioQueue {
LinkedList<MessageItem> itemsNoID;
ArrayList<LinkedList<MessageItem>> itemsWithID;
ArrayList<Long> itemsIDs;
Modified: branches/db4o/freenet/src/freenet/node/PeerNode.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/PeerNode.java 2009-01-22
18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/PeerNode.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -4266,4 +4266,47 @@
if(logMINOR) Logger.minor(this, "getReusableTrackerID():
"+cur.packets.trackerID+" on "+this);
return cur.packets.trackerID;
}
+
+ static final int MAX_TURTLES_PER_PEER = 3;
+
+ private HashMap<Key,RequestSender> turtlingTransfers = new
HashMap<Key,RequestSender>();
+
+ public boolean registerTurtleTransfer(RequestSender sender) {
+ Key key = sender.key;
+ synchronized(turtlingTransfers) {
+ if(turtlingTransfers.size() >= MAX_TURTLES_PER_PEER) {
+ Logger.error(this, "Too many turtles for peer");
+ return false;
+ }
+ if(turtlingTransfers.containsKey(key)) {
+ Logger.error(this, "Already fetching key from
peer");
+ return false;
+ }
+ turtlingTransfers.put(key, sender);
+ Logger.error(this, "Turtles for "+getPeer()+" :
"+turtlingTransfers.size());
+ return true;
+ }
+ }
+
+ public void unregisterTurtleTransfer(RequestSender sender) {
+ Key key = sender.key;
+ synchronized(turtlingTransfers) {
+ if(!turtlingTransfers.containsKey(key)) {
+ Logger.error(this, "Removing turtle transfer
"+sender+" for "+key+" from "+this+" : DOES NOT EXIST");
+ return;
+ }
+ RequestSender oldSender = turtlingTransfers.remove(key);
+ if(oldSender != sender) {
+ Logger.error(this, "Removing turtle transfer
"+sender+" for "+key+" from "+this+" : WRONG SENDER: "+oldSender);
+ turtlingTransfers.put(key, oldSender);
+ return;
+ }
+ }
+ }
+
+ public boolean isTurtling(Key key) {
+ synchronized(turtlingTransfers) {
+ return turtlingTransfers.containsKey(key);
+ }
+ }
}
Modified: branches/db4o/freenet/src/freenet/node/RequestHandler.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/RequestHandler.java 2009-01-22
18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/RequestHandler.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -49,18 +49,20 @@
private long searchStartTime;
private long responseDeadline;
private BlockTransmitter bt;
+ private final RequestTag tag;
@Override
public String toString() {
return super.toString() + " for " + uid;
}
- public RequestHandler(Message m, PeerNode source, long id, Node n,
short htl, Key key) {
+ public RequestHandler(Message m, PeerNode source, long id, Node n,
short htl, Key key, RequestTag tag) {
req = m;
node = n;
uid = id;
this.source = source;
this.htl = htl;
+ this.tag = tag;
if(htl <= 0)
htl = 1;
this.key = key;
@@ -78,11 +80,13 @@
} catch(NotConnectedException e) {
Logger.normal(this, "requestor gone, could not start
request handler wait");
node.removeTransferringRequestHandler(uid);
- node.unlockUID(uid, key instanceof NodeSSK, false,
false, false, false);
+ tag.handlerThrew(e);
+ node.unlockUID(uid, key instanceof NodeSSK, false,
false, false, false, tag);
} catch(Throwable t) {
Logger.error(this, "Caught " + t, t);
node.removeTransferringRequestHandler(uid);
- node.unlockUID(uid, key instanceof NodeSSK, false,
false, false, false);
+ tag.handlerThrew(t);
+ node.unlockUID(uid, key instanceof NodeSSK, false,
false, false, false, tag);
}
}
private Exception previousApplyByteCountCall;
@@ -140,6 +144,7 @@
Object o = node.makeRequestSender(key, htl, uid, source, false,
true, false, false);
if(o instanceof KeyBlock) {
+ tag.setServedFromDatastore();
returnLocalData((KeyBlock) o);
return;
}
@@ -193,9 +198,25 @@
synchronized(this) {
disconnected = true;
}
+ tag.handlerDisconnected();
Logger.normal(this, "requestor is gone, can't begin CHK
transfer");
}
}
+
+ public void onAbortDownstreamTransfers(int reason, String desc) {
+ if(bt == null) {
+ Logger.error(this, "No downstream transfer to abort! on
"+this);
+ return;
+ }
+ if(logMINOR)
+ Logger.minor(this, "Aborting downstream transfer on
"+this);
+ tag.onAbortDownstreamTransfers(reason, desc);
+ try {
+ bt.abortSend(reason, desc);
+ } catch (NotConnectedException e) {
+ // Ignore
+ }
+ }
private void waitAndFinishCHKTransferOffThread() {
node.executor.execute(new Runnable() {
@@ -209,7 +230,7 @@
unregisterRequestHandlerWithNode();
}
}
- }, "Finish CHK transfer for " + key);
+ }, "Finish CHK transfer for " + key + " for " + this);
}
private void waitAndFinishCHKTransfer() throws NotConnectedException {
@@ -229,6 +250,7 @@
}
public void onRequestSenderFinished(int status) {
+ if(logMINOR) Logger.minor(this,
"onRequestSenderFinished("+status+") on "+this);
long now = System.currentTimeMillis();
this.status = status;
@@ -288,6 +310,8 @@
sendTerminal(reject);
} else if(!disconnected)
waitAndFinishCHKTransferOffThread();
+ else
+
unregisterRequestHandlerWithNode();
return;
case RequestSender.VERIFY_FAILURE:
case RequestSender.GET_OFFER_VERIFY_FAILURE:
@@ -301,6 +325,8 @@
} else if(!disconnected)
//Verify fails after
receive() is complete, so we might as well propagate it...
waitAndFinishCHKTransferOffThread();
+ else
+
unregisterRequestHandlerWithNode();
return;
}
reject =
DMT.createFNPRejectedOverload(uid, true);
@@ -317,6 +343,8 @@
sendTerminal(reject);
} else if(!disconnected)
waitAndFinishCHKTransferOffThread();
+ else
+
unregisterRequestHandlerWithNode();
return;
}
Logger.error(this,
"finish(TRANSFER_FAILED) should not be called on SSK?!?!", new
Exception("error"));
@@ -436,7 +464,7 @@
private void unregisterRequestHandlerWithNode() {
node.removeTransferringRequestHandler(uid);
- node.unlockUID(uid, key instanceof NodeSSK, false, false,
false, false);
+ node.unlockUID(uid, key instanceof NodeSSK, false, false,
false, false, tag);
}
/**
Modified: branches/db4o/freenet/src/freenet/node/RequestSender.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/RequestSender.java 2009-01-22
18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/RequestSender.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -33,7 +33,9 @@
import freenet.support.Logger;
import freenet.support.ShortBuffer;
import freenet.support.SimpleFieldSet;
+import freenet.support.TimeUtil;
import freenet.support.io.NativeThread;
+import freenet.support.math.MedianMeanRunningAverage;
/**
* @author amphibian
@@ -73,6 +75,11 @@
private byte[] sskData;
private SSKBlock block;
private boolean hasForwarded;
+ private PeerNode transferringFrom;
+ private boolean turtleMode;
+ private boolean sentBackoffTurtle;
+ /** Set when we start to think about going to turtle mode - not unset if
we get cancelled instead. */
+ private boolean tryTurtle;
/** If true, only try to fetch the key from nodes which have offered it */
private boolean tryOffersOnly;
@@ -97,6 +104,7 @@
static final int GET_OFFER_TRANSFER_FAILED = 11;
private PeerNode successFrom;
private PeerNode lastNode;
+ private final long startTime;
static String getStatusString(int status) {
switch(status) {
@@ -148,6 +156,7 @@
public RequestSender(Key key, DSAPublicKey pubKey, short htl, long uid,
Node n,
PeerNode source, boolean offersOnly) {
if(key.getRoutingKey() == null) throw new NullPointerException();
+ startTime = System.currentTimeMillis();
this.key = key;
this.pubKey = pubKey;
this.htl = htl;
@@ -264,12 +273,12 @@
}
fireCHKTransferBegins();
- BlockReceiver br = new BlockReceiver(node.usm,
pn, uid, prb, this);
+ BlockReceiver br = new BlockReceiver(node.usm,
pn, uid, prb, this, node.getTicker(), true);
try {
if(logMINOR) Logger.minor(this,
"Receiving data");
byte[] data = br.receive();
- pn.transferSuccess();
+ pn.transferSuccess();
if(logMINOR) Logger.minor(this,
"Received data");
// Received data
try {
@@ -290,9 +299,10 @@
// A certain
number of these are normal, it's better to track them through statistics than
call attention to them in the logs.
Logger.normal(this, "Transfer for offer failed
("+e.getReason()+"/"+RetrievalException.getErrString(e.getReason())+"): "+e+"
from "+pn, e);
finish(GET_OFFER_TRANSFER_FAILED, pn,
true);
-
pn.transferFailed("RequestSenderGetOfferedTransferFailed");
+ // Backoff here anyway - the node
really ought to have it!
+
pn.transferFailed("RequestSenderGetOfferedTransferFailed");
offers.deleteLastOffer();
- node.nodeStats.failedBlockReceive();
+
node.nodeStats.failedBlockReceive(false, false, false);
return;
}
} finally {
@@ -766,13 +776,57 @@
}
fireCHKTransferBegins();
- BlockReceiver br = new BlockReceiver(node.usm,
next, uid, prb, this);
+ long tStart = System.currentTimeMillis();
+ BlockReceiver br = new BlockReceiver(node.usm,
next, uid, prb, this, node.getTicker(), true);
try {
if(logMINOR) Logger.minor(this,
"Receiving data");
- byte[] data = br.receive();
- next.transferSuccess();
+ final PeerNode from = next;
+ synchronized(this) {
+ transferringFrom = next;
+ }
+ node.getTicker().queueTimedJob(new
Runnable() {
+
+ public void
run() {
+
synchronized(RequestSender.this) {
+
if(transferringFrom != from) return;
+ }
+
makeTurtle();
+ }
+
+ }, 60*1000);
+ byte[] data;
+ try {
+ data = br.receive();
+ } finally {
+ synchronized(this) {
+ transferringFrom = null;
+ }
+ }
+
+ long tEnd = System.currentTimeMillis();
+ this.transferTime = tEnd - tStart;
+ boolean turtle;
+ boolean turtleBackedOff;
+ synchronized(this) {
+ turtle = turtleMode;
+ turtleBackedOff =
sentBackoffTurtle;
+ sentBackoffTurtle = true;
+ }
+ if(!turtle)
+ next.transferSuccess();
+ else {
+ Logger.error(this, "TURTLE
SUCCEEDED: "+key+" for "+this+" in "+TimeUtil.formatTime(transferTime, 2,
true));
+ if(!turtleBackedOff)
+
next.transferFailed("Turtled transfer");
+
node.nodeStats.turtleSucceeded();
+ }
next.successNotOverload();
+ if(turtle) {
+ next.unregisterTurtleTransfer(this);
+ node.unregisterTurtleTransfer(this);
+ }
+ node.nodeStats.successfulBlockReceive();
if(logMINOR) Logger.minor(this,
"Received data");
// Received data
try {
@@ -786,6 +840,20 @@
finish(SUCCESS, next, false);
return;
} catch (RetrievalException e) {
+ boolean turtle;
+ synchronized(this) {
+ turtle = turtleMode;
+ }
+ if(turtle) {
+ if(e.getReason() !=
RetrievalException.GONE_TO_TURTLE_MODE) {
+ Logger.error(this,
"TURTLE FAILED: "+key+" for "+this+" : "+e);
+
node.nodeStats.turtleFailed();
+ } else {
+ if(logMINOR)
Logger.minor(this, "Upstream turtled for "+this+" from "+next);
+ }
+ next.unregisterTurtleTransfer(this);
+ node.unregisterTurtleTransfer(this);
+ }
if
(e.getReason()==RetrievalException.SENDER_DISCONNECTED)
Logger.normal(this, "Transfer failed (disconnect): "+e, e);
else
@@ -794,7 +862,20 @@
next.localRejectedOverload("TransferFailedRequest"+e.getReason());
finish(TRANSFER_FAILED, next, false);
node.failureTable.onFinalFailure(key,
next, htl, FailureTable.REJECT_TIME, source);
-
next.transferFailed("RequestSenderTransferFailed");
+ int reason = e.getReason();
+ boolean timeout = (!br.senderAborted())
&&
+ (reason ==
RetrievalException.SENDER_DIED || reason == RetrievalException.RECEIVER_DIED ||
reason == RetrievalException.TIMED_OUT
+ || reason ==
RetrievalException.UNABLE_TO_SEND_BLOCK_WITHIN_TIMEOUT);
+ if(timeout) {
+ // Looks like a
timeout. Backoff, even if it's a turtle.
+
next.transferFailed(e.getMessage());
+ } else {
+ // Quick failure (in
that we didn't have to timeout). Don't backoff.
+ // Treat as a DNF.
+ // If it was turtled,
and then failed, still treat it as a DNF.
+
node.failureTable.onFinalFailure(key, next, htl, FailureTable.REJECT_TIME,
source);
+ }
+ node.nodeStats.failedBlockReceive(true,
timeout, reason == RetrievalException.GONE_TO_TURTLE_MODE);
return;
}
} finally {
@@ -899,6 +980,14 @@
}
}
}
+
+ protected void makeTurtle() {
+ synchronized(this) {
+ if(tryTurtle) return;
+ tryTurtle = true;
+ }
+ node.makeTurtle(RequestSender.this);
+ }
/**
* Finish fetching an SSK. We must have received the data, the headers and
the pubkey by this point.
@@ -1036,7 +1125,7 @@
if(prb != null)
current |= WAIT_TRANSFERRING_DATA;
- if(status != NOT_FINISHED)
+ if(status != NOT_FINISHED || sentAbortDownstreamTransfers)
current |= WAIT_FINISHED;
if(current != mask) return current;
@@ -1055,17 +1144,46 @@
}
}
+ private static MedianMeanRunningAverage avgTimeTaken = new
MedianMeanRunningAverage();
+
+ private static MedianMeanRunningAverage avgTimeTakenTurtle = new
MedianMeanRunningAverage();
+
+ private static MedianMeanRunningAverage avgTimeTakenTransfer = new
MedianMeanRunningAverage();
+
+ private long transferTime;
+
private void finish(int code, PeerNode next, boolean fromOfferedKey) {
if(logMINOR) Logger.minor(this, "finish("+code+ ')');
+ boolean turtle;
+
synchronized(this) {
status = code;
notifyAll();
+ turtle = turtleMode;
if(status == SUCCESS)
successFrom = next;
}
if(status == SUCCESS) {
+ if(key instanceof NodeCHK && transferTime > 0 && logMINOR) {
+ long timeTaken = System.currentTimeMillis() - startTime;
+ synchronized(avgTimeTaken) {
+ if(turtle)
+ avgTimeTakenTurtle.report(timeTaken);
+ else {
+ avgTimeTaken.report(timeTaken);
+ avgTimeTakenTransfer.report(transferTime);
+ }
+ if(turtle) {
+ if(logMINOR) Logger.minor(this,
"Successful CHK turtle request took "+timeTaken+" average "+avgTimeTakenTurtle);
+ } else {
+ if(logMINOR) Logger.minor(this,
"Successful CHK request took "+timeTaken+" average "+avgTimeTaken);
+ if(logMINOR) Logger.minor(this, "Successful CHK
request transfer "+transferTime+" average "+avgTimeTakenTransfer);
+ if(logMINOR) Logger.minor(this, "Search phase:
median "+(avgTimeTaken.currentValue() -
avgTimeTakenTransfer.currentValue())+"ms, mean "+(avgTimeTaken.meanValue() -
avgTimeTakenTransfer.meanValue())+"ms");
+ }
+ }
+ }
if(next != null) {
next.onSuccess(false, key instanceof NodeSSK);
}
@@ -1283,6 +1401,9 @@
void onCHKTransferBegins();
/** Should return quickly, allocate a thread if it needs to
block etc */
void onRequestSenderFinished(int status);
+ /** Abort downstream transfers (not necessarily upstream ones,
so not via the PRB).
+ * Should return quickly, allocate a thread if it needs to
block etc. */
+ void onAbortDownstreamTransfers(int reason, String desc);
}
public void addListener(Listener l) {
@@ -1291,10 +1412,13 @@
boolean reject=false;
boolean transfer=false;
boolean sentFinished;
+ boolean sentTransferCancel = false;
int status;
synchronized (this) {
synchronized (listeners) {
- listeners.add(l);
+ sentTransferCancel =
sentAbortDownstreamTransfers;
+ if(!sentTransferCancel)
+ listeners.add(l);
reject = sentReceivedRejectOverload;
transfer = sentCHKTransferBegins;
sentFinished = sentRequestSenderFinished;
@@ -1307,6 +1431,8 @@
l.onReceivedRejectOverload();
if (transfer)
l.onCHKTransferBegins();
+ if(sentTransferCancel)
+
l.onAbortDownstreamTransfers(abortDownstreamTransfersReason,
abortDownstreamTransfersDesc);
if (status!=NOT_FINISHED && sentFinished)
l.onRequestSenderFinished(status);
}
@@ -1357,7 +1483,66 @@
}
}
+ private boolean sentAbortDownstreamTransfers;
+ private int abortDownstreamTransfersReason;
+ private String abortDownstreamTransfersDesc;
+
+ private void sendAbortDownstreamTransfers(int reason, String desc) {
+ synchronized (listeners) {
+ abortDownstreamTransfersReason = reason;
+ abortDownstreamTransfersDesc = desc;
+ sentAbortDownstreamTransfers = true;
+ for (Listener l : listeners) {
+ try {
+ l.onAbortDownstreamTransfers(reason,
desc);
+
l.onRequestSenderFinished(TRANSFER_FAILED);
+ } catch (Throwable t) {
+ Logger.error(this, "Caught: "+t, t);
+ }
+ }
+ listeners.clear();
+ }
+ synchronized(this) {
+ notifyAll();
+ }
+ }
+
public int getPriority() {
return NativeThread.HIGH_PRIORITY;
}
+
+ public void setTurtle() {
+ synchronized(this) {
+ this.turtleMode = true;
+ }
+
sendAbortDownstreamTransfers(RetrievalException.GONE_TO_TURTLE_MODE,
"Turtling");
+ node.getTicker().queueTimedJob(new Runnable() {
+
+ public void run() {
+ PeerNode from;
+ synchronized(RequestSender.this) {
+ if(sentBackoffTurtle) return;
+ sentBackoffTurtle = true;
+ from = transferringFrom;
+ if(from == null) return;
+ }
+ from.transferFailed("Turtled transfer");
+ }
+
+ }, 30*1000);
+ }
+
+ public PeerNode transferringFrom() {
+ return transferringFrom;
+ }
+
+ public void killTurtle() {
+ prb.abort(RetrievalException.TURTLE_KILLED, "Too many turtles /
already have turtles for this key");
+ node.failureTable.onFinalFailure(key, transferringFrom(), htl,
FailureTable.REJECT_TIME, source);
+ }
+
+ public boolean abortedDownstreamTransfers() {
+ return sentAbortDownstreamTransfers;
+ }
+
}
Copied: branches/db4o/freenet/src/freenet/node/RequestTag.java (from rev 25205,
trunk/freenet/src/freenet/node/RequestTag.java)
===================================================================
--- branches/db4o/freenet/src/freenet/node/RequestTag.java
(rev 0)
+++ branches/db4o/freenet/src/freenet/node/RequestTag.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -0,0 +1,104 @@
+package freenet.node;
+
+import java.lang.ref.WeakReference;
+
+import freenet.io.comm.NotConnectedException;
+import freenet.support.Logger;
+import freenet.support.TimeUtil;
+
+/**
+ * Tag for a request.
+ * @author Matthew Toseland <toad at amphibian.dyndns.org> (0xE43DA450)
+ */
+public class RequestTag extends UIDTag {
+
+ enum START {
+ ASYNC_GET,
+ LOCAL,
+ REMOTE
+ }
+
+ final START start;
+ final boolean isSSK;
+ boolean servedFromDatastore;
+ WeakReference<RequestSender> sender;
+ int requestSenderFinishedCode;
+ Throwable handlerThrew;
+ boolean rejected;
+ boolean abortedDownstreamTransfer;
+ int abortedDownstreamReason;
+ String abortedDownstreamDesc;
+ boolean handlerDisconnected;
+
+ public RequestTag(boolean isSSK, START start) {
+ super();
+ this.start = start;
+ this.isSSK = isSSK;
+ }
+
+ public void setRequestSenderFinished(int status) {
+ requestSenderFinishedCode = status;
+ }
+
+ public void setSender(RequestSender rs) {
+ sender = new WeakReference<RequestSender>(rs);
+ }
+
+ public void handlerThrew(Throwable t) {
+ this.handlerThrew = t;
+ }
+
+ public void setServedFromDatastore() {
+ servedFromDatastore = true;
+ }
+
+ public void setRejected() {
+ rejected = true;
+ }
+
+ @Override
+ public void logStillPresent(Long uid) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("Still present after
").append(TimeUtil.formatTime(age()));
+ sb.append(" : ").append(uid).append(" : start=").append(start);
+ sb.append(" ssk=").append(isSSK).append(" from
store=").append(servedFromDatastore);
+ if(sender == null) {
+ sb.append(" sender hasn't been set!");
+ } else {
+ RequestSender s = sender.get();
+ if(s == null) {
+ sb.append(" sender=null");
+ } else {
+ sb.append(" sender=").append(s);
+ sb.append(" status=");
+ sb.append(s.getStatusString());
+ }
+ }
+ sb.append(" finishedCode=").append(requestSenderFinishedCode);
+ sb.append(" rejected=").append(rejected);
+ sb.append(" thrown=").append(handlerThrew);
+ if(abortedDownstreamTransfer) {
+ sb.append(" abortedDownstreamTransfer reason=");
+ sb.append(abortedDownstreamReason);
+ sb.append(" desc=");
+ sb.append(abortedDownstreamDesc);
+ }
+ if(handlerDisconnected)
+ sb.append(" handlerDisconnected=true");
+ if(handlerThrew != null)
+ Logger.error(this, sb.toString(), handlerThrew);
+ else
+ Logger.error(this, sb.toString());
+ }
+
+ public void onAbortDownstreamTransfers(int reason, String desc) {
+ abortedDownstreamTransfer = true;
+ abortedDownstreamReason = reason;
+ abortedDownstreamDesc = desc;
+ }
+
+ public void handlerDisconnected() {
+ handlerDisconnected = true;
+ }
+
+}
Modified: branches/db4o/freenet/src/freenet/node/SSKInsertHandler.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/SSKInsertHandler.java
2009-01-22 18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/SSKInsertHandler.java
2009-01-22 18:32:20 UTC (rev 25217)
@@ -45,8 +45,9 @@
private byte[] data;
private byte[] headers;
private boolean canCommit;
+ final InsertTag tag;
- SSKInsertHandler(NodeSSK key, byte[] data, byte[] headers, short htl,
PeerNode source, long id, Node node, long startTime) {
+ SSKInsertHandler(NodeSSK key, byte[] data, byte[] headers, short htl,
PeerNode source, long id, Node node, long startTime, InsertTag tag) {
this.node = node;
this.uid = id;
this.source = source;
@@ -55,6 +56,7 @@
this.htl = htl;
this.data = data;
this.headers = headers;
+ this.tag = tag;
if(htl <= 0) htl = 1;
byte[] pubKeyHash = key.getPubKeyHash();
pubKey = node.getKey(pubKeyHash);
@@ -77,7 +79,7 @@
Logger.error(this, "Caught "+t, t);
} finally {
if(logMINOR) Logger.minor(this, "Exiting InsertHandler.run() for
"+uid);
- node.unlockUID(uid, true, true, false, false, false);
+ node.unlockUID(uid, true, true, false, false, false, tag);
}
}
Modified: branches/db4o/freenet/src/freenet/node/SessionKey.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/SessionKey.java 2009-01-22
18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/SessionKey.java 2009-01-22
18:32:20 UTC (rev 25217)
@@ -18,7 +18,6 @@
* without changing the session key. */
final PacketTracker packets;
- private static boolean logMINOR;
/** Parent PeerNode */
public final PeerNode pn;
/** Cipher to both encrypt outgoing packets with and decrypt
Copied: branches/db4o/freenet/src/freenet/node/UIDTag.java (from rev 25205,
trunk/freenet/src/freenet/node/UIDTag.java)
===================================================================
--- branches/db4o/freenet/src/freenet/node/UIDTag.java
(rev 0)
+++ branches/db4o/freenet/src/freenet/node/UIDTag.java 2009-01-22 18:32:20 UTC
(rev 25217)
@@ -0,0 +1,23 @@
+package freenet.node;
+
+/**
+ * Base class for tags representing a running request. These store enough
information
+ * to detect whether they are finished; if they are still in the list, this
normally
+ * represents a bug.
+ * @author Matthew Toseland <toad at amphibian.dyndns.org> (0xE43DA450)
+ */
+public abstract class UIDTag {
+
+ final long createdTime;
+
+ UIDTag() {
+ createdTime = System.currentTimeMillis();
+ }
+
+ public abstract void logStillPresent(Long uid);
+
+ long age() {
+ return System.currentTimeMillis() - createdTime;
+ }
+
+}
Modified: branches/db4o/freenet/src/freenet/node/Version.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/Version.java 2009-01-22 18:08:25 UTC
(rev 25216)
+++ branches/db4o/freenet/src/freenet/node/Version.java 2009-01-22 18:32:20 UTC
(rev 25217)
@@ -24,17 +24,17 @@
public static final String protocolVersion = "1.0";
/** The build number of the current revision */
- private static final int buildNumber = 1194;
+ private static final int buildNumber = 1203;
/** Oldest build of Fred we will talk to */
- private static final int oldLastGoodBuild = 1193;
- private static final int newLastGoodBuild = 1194;
+ private static final int oldLastGoodBuild = 1197;
+ private static final int newLastGoodBuild = 1198;
static final long transitionTime;
static {
final Calendar _cal =
Calendar.getInstance(TimeZone.getTimeZone("GMT"));
// year, month - 1 (or constant), day, hour, minute, second
- _cal.set( 2008, Calendar.DECEMBER, 19, 0, 0, 0 );
+ _cal.set( 2009, Calendar.JANUARY, 17, 0, 0, 0 );
transitionTime = _cal.getTimeInMillis();
}
Modified:
branches/db4o/freenet/src/freenet/node/simulator/RealNodeNetworkColoringTest.java
===================================================================
---
branches/db4o/freenet/src/freenet/node/simulator/RealNodeNetworkColoringTest.java
2009-01-22 18:08:25 UTC (rev 25216)
+++
branches/db4o/freenet/src/freenet/node/simulator/RealNodeNetworkColoringTest.java
2009-01-22 18:32:20 UTC (rev 25217)
@@ -178,8 +178,8 @@
rate = 1.0*good/total;
general.report(rate);
aRate.report(rate);
- generalIds.add(new Integer(id));
- aIds.add(new Integer(id));
+ generalIds.add(Integer.valueOf(id));
+ aIds.add(Integer.valueOf(id));
}
for (int i=0; i<NUMBER_OF_NODES; i++) {
@@ -195,8 +195,8 @@
rate = 1.0*good/total;
general.report(rate);
bRate.report(rate);
- generalIds.add(new Integer(id));
- bIds.add(new Integer(id));
+ generalIds.add(Integer.valueOf(id));
+ bIds.add(Integer.valueOf(id));
}
for (int i=0; i<BRIDGES; i++) {
@@ -211,8 +211,8 @@
rate = 1.0*good/total;
general.report(rate);
bridgeRate.report(rate);
- generalIds.add(new Integer(id));
- bridgeIds.add(new Integer(id));
+ generalIds.add(Integer.valueOf(id));
+ bridgeIds.add(Integer.valueOf(id));
}
Logger.error(log, "cycle = "+cycleNumber);
Modified:
branches/db4o/freenet/src/freenet/node/useralerts/UserAlertManager.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/useralerts/UserAlertManager.java
2009-01-22 18:08:25 UTC (rev 25216)
+++ branches/db4o/freenet/src/freenet/node/useralerts/UserAlertManager.java
2009-01-22 18:32:20 UTC (rev 25217)
@@ -285,6 +285,7 @@
summaryBox = new HTMLNode("div", "class", "infobox
infobox-information");
summaryBox.addChild("div", "class", "infobox-header",
l10n("alertsTitle"));
HTMLNode summaryContent = summaryBox.addChild("div", "class",
"infobox-content", alertSummaryString.toString());
+ summaryContent.addChild("#", " ");
L10n.addL10nSubstitution(summaryContent,
"UserAlertManager.alertsOnAlertsPage",
new String[] { "link", "/link" },
new String[] { "<a href=\"/alerts/\">", "</a>"
});