Author: toad
Date: 2008-11-29 19:21:46 +0000 (Sat, 29 Nov 2008)
New Revision: 23981

Added:
   branches/db4o/freenet/src/freenet/node/BlockedTooLongException.java
Modified:
   branches/db4o/freenet/
   
branches/db4o/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat
   branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties
   branches/db4o/freenet/src/freenet/node/FNPPacketMangler.java
   branches/db4o/freenet/src/freenet/node/KeyTracker.java
   branches/db4o/freenet/src/freenet/node/LoggingConfigHandler.java
   branches/db4o/freenet/src/freenet/node/NodeDispatcher.java
   branches/db4o/freenet/src/freenet/node/OutgoingPacketMangler.java
   branches/db4o/freenet/src/freenet/node/PacketSender.java
   branches/db4o/freenet/src/freenet/node/PeerNode.java
   branches/db4o/freenet/src/freenet/node/StillNotAckedException.java
   branches/db4o/freenet/src/freenet/node/Version.java
   branches/db4o/freenet/src/freenet/support/BinaryBloomFilter.java
   branches/db4o/freenet/src/freenet/support/BloomFilter.java
   branches/db4o/freenet/src/freenet/support/CountingBloomFilter.java
   branches/db4o/freenet/src/freenet/support/LimitedRangeIntByteArrayMap.java
   branches/db4o/freenet/test/freenet/support/io/MockInputStream.java
Log:
Merge 1176



Property changes on: branches/db4o/freenet
___________________________________________________________________
Modified: svn:mergeinfo
   - /trunk/freenet:19964-23531
   + /trunk/freenet:19964-23583

Modified: 
branches/db4o/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat
===================================================================
--- 
branches/db4o/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat 
    2008-11-29 19:18:00 UTC (rev 23980)
+++ 
branches/db4o/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat 
    2008-11-29 19:21:46 UTC (rev 23981)
@@ -22,7 +22,7 @@
 [EMAIL 
PROTECTED],xTFOV9ddCQQk6vQ6G~jfL6IzRUgmfMcZJ6nuySu~NUc,AQACAAE/activelink-index-text/54/
 BookmarkCategory1.Name=Freenet related software and documentation
 BookmarkCategory1.Content.BookmarkCategory=0
-BookmarkCategory1.Content.Bookmark=6
+BookmarkCategory1.Content.Bookmark=5
 BookmarkCategory1.Content.Bookmark0.Name=Freenet Message System
 BookmarkCategory1.Content.Bookmark0.Description=The official freesite of FMS, 
a spam resistant message board system for Freenet
 BookmarkCategory1.Content.Bookmark0.hasAnActivelink=true
@@ -43,8 +43,4 @@
 BookmarkCategory1.Content.Bookmark4.hasAnActivelink=true
 BookmarkCategory1.Content.Bookmark4.Name=The Freenet Applications Freesite
 BookmarkCategory1.Content.Bookmark4.Description=Various links to Freenet 
applications, and instructions for using them
-BookmarkCategory1.Content.Bookmark5.Name=wAnnA search Freenet?
-BookmarkCategory1.Content.Bookmark5.Description=How to search Freenet
-BookmarkCategory1.Content.Bookmark5.hasAnActivelink=true
[EMAIL PROTECTED],~31qR8wv08tVkj--3bfCwJAC7ndaXh7uLFgafpimOik,AQACAAE/wAnnA/13/
 End

Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties
===================================================================
--- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties   
2008-11-29 19:18:00 UTC (rev 23980)
+++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties   
2008-11-29 19:21:46 UTC (rev 23981)
@@ -472,6 +472,10 @@
 FileOffer.succeededReceiveTitle=Successfully received file
 FileOffer.succeededReceiveHeader=The transfer of the file ${filename} from 
${node} was a success.
 FileOffer.succeededReceiveShort=Successfully received ${filename} from ${node}.
+FNPPacketMangler.somePeersDisconnectedStillNotAcked=Probably a bug: please 
report: ${count} peers forcibly disconnected due to not acknowledging packets.
+FNPPacketMangler.somePeersDisconnectedStillNotAckedDetail=${count} of your 
peers are having severe problems (not acknowledging packets even after 10 
minutes). This is probably due to a bug in the code. Please report it to us at 
the bug tracker at ${link}https://bugs.freenetproject.org/${/link} or at [EMAIL 
PROTECTED] Please include this message and what version of the node you are 
running. The affected peers (you may not want to include this in your bug 
report if they are darknet peers) are:
+PacketSender.somePeersDisconnectedStillNotAcked=Probably a bug: please report: 
${count} peers forcibly disconnected due to blocking for a packet number for 
over 10 minutes.
+PacketSender.somePeersDisconnectedStillNotAckedDetail=${count} of your peers 
are having severe problems (failing to allocate a packet number after 10 
minutes). This is probably due to a bug in the code. Please report it to us at 
the bug tracker at ${link}https://bugs.freenetproject.org/${/link} or at [EMAIL 
PROTECTED] Please include this message and what version of the node you are 
running. The affected peers (you may not want to include this in your bug 
report if they are darknet peers) are:
 GIFFilter.invalidHeader=The file does not contain a valid GIF header.
 GIFFilter.invalidHeaderTitle=Invalid header
 GIFFilter.notGif=The file you tried to fetch is not a GIF. It might be some 
other file format, and your browser may do something dangerous with it, 
therefore we have blocked it.
@@ -704,8 +708,8 @@
 Node.opennetEnabledLong=Enable insecure mode (aka opennet)? If this is 
enabled, the node will automatically exchange node references with other 
untrusted nodes (Strangers as opposed to Friends). But this means that the fact 
that you are running a node is no longer private, and many attacks are much 
easier. If you know enough people running Freenet, you should stick to trusted 
(Friends) connections to them, and turn this off.
 Node.outBWLimit=Output bandwidth limit (bytes per second)
 Node.outBWLimitLong=Hard output bandwidth limit (bytes/sec); the node should 
almost never exceed this
-Node.paddDataPackets=Padd data packets sent by the node with random-length 
content? (READ WARNING!)
-Node.paddDataPacketsLong=Padd data packets sent by the node with random-length 
content? For security, on a single node, this is bad; if a large part of the 
network starts doing it, we become very vulnerable to a passive attacker. 
However, it should improve performance, particularly the payload percentage. 
You have been warned!
+Node.paddDataPackets=Pad data packets sent by the node with random-length 
content? (READ WARNING!)
+Node.paddDataPacketsLong=Pad data packets sent by the node with random-length 
content? For security, on a single node, turning this off is bad; if a large 
part of the network starts doing it, we become very vulnerable to a passive 
attacker. However, it should improve performance, particularly the payload 
percentage. You have been warned!
 Node.passOpennetPeersThroughDarknet=Relay opennet noderefs through darknet 
peers?
 Node.passOpennetPeersThroughDarknetLong=If true, opennet noderefs (NEVER our 
own darknet noderef) will be relayed through our darknet peers. So a node (this 
node, or its peers) can get opennet peers from its darknet peers. This is 
useful because it allows us to bootstrap new opennet peers after having lost 
our peers due to downtime, for example. However, it may make traffic analysis 
slightly easier, so turn it off if you are paranoid.
 Node.port=FNP port number (UDP)

Copied: branches/db4o/freenet/src/freenet/node/BlockedTooLongException.java 
(from rev 23583, trunk/freenet/src/freenet/node/BlockedTooLongException.java)
===================================================================
--- branches/db4o/freenet/src/freenet/node/BlockedTooLongException.java         
                (rev 0)
+++ branches/db4o/freenet/src/freenet/node/BlockedTooLongException.java 
2008-11-29 19:21:46 UTC (rev 23981)
@@ -0,0 +1,13 @@
+package freenet.node;
+
+public class BlockedTooLongException extends Exception {
+
+       public final KeyTracker tracker;
+       public final long delta;
+       
+       public BlockedTooLongException(KeyTracker tracker, long delta) {
+               this.tracker = tracker;
+               this.delta = delta;
+       }
+
+}

Modified: branches/db4o/freenet/src/freenet/node/FNPPacketMangler.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/FNPPacketMangler.java        
2008-11-29 19:18:00 UTC (rev 23980)
+++ branches/db4o/freenet/src/freenet/node/FNPPacketMangler.java        
2008-11-29 19:21:46 UTC (rev 23981)
@@ -8,6 +8,7 @@
 import java.security.MessageDigest;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedList;
 
 import net.i2p.util.NativeBigInteger;
@@ -39,8 +40,11 @@
 import freenet.io.comm.ReferenceSignatureVerificationException;
 import freenet.io.comm.SocketHandler;
 import freenet.io.comm.Peer.LocalAddressException;
+import freenet.l10n.L10n;
+import freenet.node.useralerts.UserAlert;
 import freenet.support.ByteArrayWrapper;
 import freenet.support.Fields;
+import freenet.support.HTMLNode;
 import freenet.support.HexUtil;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
@@ -950,8 +954,8 @@
                                Logger.normal(this, "We received an unexpected 
JFK(2) message from "+pn.getPeer()+" (time since added: 
"+pn.timeSinceAddedOrRestarted()+" time last 
receive:"+pn.lastReceivedPacketTime()+')');
                        return;
                } else if(!Arrays.equals(myNi, nonceInitiator)){
-                       if(logMINOR)
-                               Logger.minor(this, "Ignoring old JFK(2) 
(different nonce to the one we sent - either a timing artefact or an attempt to 
change the nonce)");
+                       if(shouldLogErrorInHandshake(t1))
+                               Logger.normal(this, "Ignoring old JFK(2) 
(different nonce to the one we sent - either a timing artefact or an attempt to 
change the nonce)");
                        return;
                }
                
@@ -1346,6 +1350,9 @@
                        return true;
                }
                
+               // Received a packet
+               pn.receivedPacket(true, false);
+               
                // Promote if necessary
                boolean dontWant = false;
                if(oldOpennetPeer) {
@@ -2007,7 +2014,7 @@
        /* (non-Javadoc)
         * @see 
freenet.node.OutgoingPacketMangler#processOutgoingOrRequeue(freenet.node.MessageItem[],
 freenet.node.PeerNode, boolean, boolean)
         */
-       public void processOutgoingOrRequeue(MessageItem[] messages, PeerNode 
pn, boolean neverWaitForPacketNumber, boolean dontRequeue, boolean onePacket) {
+       public boolean processOutgoingOrRequeue(MessageItem[] messages, 
PeerNode pn, boolean neverWaitForPacketNumber, boolean dontRequeue, boolean 
onePacket) throws BlockedTooLongException {
                String requeueLogString = "";
                if(!dontRequeue) {
                        requeueLogString = ", requeueing";
@@ -2018,8 +2025,12 @@
                KeyTracker kt = pn.getCurrentKeyTracker();
                if(kt == null) {
                        Logger.error(this, "Not connected while sending 
packets: "+pn);
-                       return;
+                       return false;
                }
+               if(kt.wouldBlock(false)) {
+                       if(logMINOR) Logger.minor(this, "Would block: "+kt);
+                       return false;
+               }
                int length = 1;
                length += kt.countAcks() + kt.countAckRequests() + 
kt.countResendRequests();
                int callbacksCount = 0;
@@ -2044,7 +2055,7 @@
                                                pn.requeueMessageItems(newMsgs, 
0, x, false, "NotConnectedException(1a)");
                                                
pn.requeueMessageItems(messages, i, messages.length-i, false, 
"NotConnectedException(1b)");
                                        }
-                                       return;
+                                       return false;
                                } catch (WouldBlockException e) {
                                        if(logMINOR) Logger.minor(this, "Caught 
"+e+" while sending messages ("+mi_name+") to "+pn.getPeer()+requeueLogString, 
e);
                                        // Requeue
@@ -2052,7 +2063,7 @@
                                                pn.requeueMessageItems(newMsgs, 
0, x, false, "WouldBlockException(1a)");
                                                
pn.requeueMessageItems(messages, i, messages.length-i, false, 
"WouldBlockException(1b)");
                                        }
-                                       return;
+                                       return false;
                                } catch (KeyChangedException e) {
                                        if(logMINOR) Logger.minor(this, "Caught 
"+e+" while sending messages ("+mi_name+") to "+pn.getPeer()+requeueLogString, 
e);
                                        // Requeue
@@ -2060,7 +2071,7 @@
                                                pn.requeueMessageItems(newMsgs, 
0, x, false, "KeyChangedException(1a)");
                                                
pn.requeueMessageItems(messages, i, messages.length-i, false, 
"KeyChangedException(1b)");
                                        }
-                                       return;
+                                       return false;
                                } catch (Throwable e) {
                                        Logger.error(this, "Caught "+e+" while 
sending messages ("+mi_name+") to "+pn.getPeer()+requeueLogString, e);
                                        // Requeue
@@ -2068,7 +2079,7 @@
                                                pn.requeueMessageItems(newMsgs, 
0, x, false, "Throwable(1)");
                                                
pn.requeueMessageItems(messages, i, messages.length-i, false, "Throwable(1)");
                                        }
-                                       return;
+                                       return false;
                                }
                        } else {
                                byte[] data = mi.getData();
@@ -2126,19 +2137,19 @@
                                // Requeue
                                if(!dontRequeue)
                                        pn.requeueMessageItems(messages, 0, 
messages.length, false, "NotConnectedException(2)");
-                               return;
+                               return false;
                        } catch (WouldBlockException e) {
                                if(logMINOR) Logger.minor(this, "Caught "+e+" 
while sending messages ("+mi_name+") to "+pn.getPeer()+requeueLogString, e);
                                // Requeue
                                if(!dontRequeue)
                                        pn.requeueMessageItems(messages, 0, 
messages.length, false, "WouldBlockException(2)");
-                               return;
+                               return false;
                        } catch (Throwable e) {
                                Logger.error(this, "Caught "+e+" while sending 
messages ("+mi_name+") to "+pn.getPeer()+requeueLogString, e);
                                // Requeue
                                if(!dontRequeue)
                                        pn.requeueMessageItems(messages, 0, 
messages.length, false, "Throwable(2)");
-                               return;
+                               return false;
 
                        }
                } else {
@@ -2180,23 +2191,23 @@
                                                        // Requeue
                                                        if(!dontRequeue)
                                                                
pn.requeueMessageItems(messages, lastIndex, messages.length - lastIndex, false, 
"NotConnectedException(3)");
-                                                       return;
+                                                       return false;
                                                } catch (WouldBlockException e) 
{
                                                        if(logMINOR) 
Logger.minor(this, "Caught "+e+" while sending messages ("+mi_name+") to 
"+pn.getPeer()+requeueLogString, e);
                                                        // Requeue
                                                        if(!dontRequeue)
                                                                
pn.requeueMessageItems(messages, lastIndex, messages.length - lastIndex, false, 
"WouldBlockException(3)");
-                                                       return;
+                                                       return false;
                                                } catch (Throwable e) {
                                                        Logger.error(this, 
"Caught "+e+" while sending messages ("+mi_name+") to 
"+pn.getPeer()+requeueLogString, e);
                                                        // Requeue
                                                        if(!dontRequeue)
                                                                
pn.requeueMessageItems(messages, lastIndex, messages.length - lastIndex, false, 
"Throwable(3)");
-                                                       return;
+                                                       return false;
                                                }
                                                if(onePacket) {
                                                        
pn.requeueMessageItems(messages, i, messageData.length - i, true, "Didn't fit 
in single packet");
-                                                       return;
+                                                       return false;
                                                }
                                        }
                                        lastIndex = i;
@@ -2209,6 +2220,7 @@
                                }
                        }
                }
+               return true;
        }
 
        /**
@@ -2354,6 +2366,7 @@
                } catch (StillNotAckedException e) {
                        Logger.error(this, "Forcing disconnect on 
"+tracker.pn+" for "+tracker+" because packets not acked after 10 minutes!");
                        tracker.pn.forceDisconnect(true);
+                       disconnectedStillNotAcked(tracker);
                        throw new NotConnectedException();
                }
 
@@ -2550,6 +2563,106 @@
                return ret;
        }
 
+       private HashSet<Peer> peersWithProblems = new HashSet<Peer>();
+       
+       private void disconnectedStillNotAcked(KeyTracker tracker) {
+               synchronized(peersWithProblems) {
+                       peersWithProblems.add(tracker.pn.getPeer());
+                       if(peersWithProblems.size() > 1) return;
+               }
+               node.clientCore.alerts.register(disconnectedStillNotAckedAlert);
+       }
+       
+       private UserAlert disconnectedStillNotAckedAlert = new UserAlert() {
+
+               public String anchor() {
+                       return "disconnectedStillNotAcked";
+               }
+
+               public String dismissButtonText() {
+                       return null;
+               }
+
+               public short getPriorityClass() {
+                       return UserAlert.ERROR;
+               }
+
+               public String getShortText() {
+                       int sz;
+                       synchronized(peersWithProblems) {
+                               sz = peersWithProblems.size();
+                       }
+                       return l10n("somePeersDisconnectedStillNotAcked", 
"count", Integer.toString(sz));
+               }
+
+               public HTMLNode getHTMLText() {
+                       HTMLNode div = new HTMLNode("div");
+                       Peer[] peers;
+                       synchronized(peersWithProblems) {
+                               peers = peersWithProblems.toArray(new 
Peer[peersWithProblems.size()]);
+                       }
+                       L10n.addL10nSubstitution(div, 
"FNPPacketMangler.somePeersDisconnectedStillNotAckedDetail", 
+                                       new String[] { "count", "link", "/link" 
}
+                                       , new String[] { 
Integer.toString(peers.length), "<a 
href=\"/?_CHECKED_HTTP_=https://bugs.freenetproject.org/\";>", "</a>" });
+                       HTMLNode list = div.addChild("ul");
+                       for(Peer peer : peers) {
+                               list.addChild("li", peer.toString());
+                       }
+                       return div;
+               }
+
+               public String getText() {
+                       StringBuffer sb = new StringBuffer();
+                       Peer[] peers;
+                       synchronized(peersWithProblems) {
+                               peers = peersWithProblems.toArray(new 
Peer[peersWithProblems.size()]);
+                       }
+                       
sb.append(l10n("somePeersDisconnectedStillNotAckedDetail", 
+                                       new String[] { "count", "link", "/link" 
},
+                                       new String[] { 
Integer.toString(peers.length), "", "" } ));
+                       sb.append('\n');
+                       for(Peer peer : peers) {
+                               sb.append('\t');
+                               sb.append(peer.toString());
+                               sb.append('\n');
+                       }
+                       return sb.toString();
+               }
+               
+               public String getTitle() {
+                       return getShortText();
+               }
+
+               public Object getUserIdentifier() {
+                       return FNPPacketMangler.this;
+               }
+
+               public boolean isEventNotification() {
+                       return false;
+               }
+
+               public boolean isValid() {
+                       return true;
+               }
+
+               public void isValid(boolean validity) {
+                       // Ignore
+               }
+
+               public void onDismiss() {
+                       // Ignore
+               }
+
+               public boolean shouldUnregisterOnDismiss() {
+                       return false;
+               }
+
+               public boolean userCanDismiss() {
+                       return false;
+               }
+
+       };
+
        /**
         * Encrypt and send a packet.
         * @param plaintext The packet's plaintext, including all formatting,
@@ -2619,6 +2732,14 @@
                return output.length + sock.getHeadersLength();
        }
 
+       protected String l10n(String key, String[] patterns, String[] values) {
+               return L10n.getString("FNPPacketMangler."+key, patterns, 
values);
+       }
+
+       protected String l10n(String key, String pattern, String value) {
+               return L10n.getString("FNPPacketMangler."+key, pattern, value);
+       }
+
        /* (non-Javadoc)
         * @see 
freenet.node.OutgoingPacketMangler#sendHandshake(freenet.node.PeerNode)
         */

Modified: branches/db4o/freenet/src/freenet/node/KeyTracker.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/KeyTracker.java      2008-11-29 
19:18:00 UTC (rev 23980)
+++ branches/db4o/freenet/src/freenet/node/KeyTracker.java      2008-11-29 
19:21:46 UTC (rev 23981)
@@ -541,6 +541,11 @@
                }
                if(cbCount > 0 && logMINOR)
                        Logger.minor(this, "Executed " + cbCount + " 
callbacks");
+               try {
+                       wouldBlock(true);
+               } catch (BlockedTooLongException e) {
+                       // Ignore, will come up again. In any case it's rather 
unlikely...
+               }
        }
 
        /**
@@ -570,6 +575,11 @@
                                throttle.notifyOfPacketAcknowledged();
                                
throttle.setRoundTripTime(System.currentTimeMillis() - timeAdded);
                        }
+               try {
+                       wouldBlock(true);
+               } catch (BlockedTooLongException e) {
+                       // Ignore, will come up again. In any case it's rather 
unlikely...
+               }
                if(callbacks != null) {
                        for(int i = 0; i < callbacks.length; i++)
                                callbacks[i].acknowledged();
@@ -711,6 +721,37 @@
                        }
                }
        }
+       
+       private long timeWouldBlock = -1;
+       
+       static final long MAX_WOULD_BLOCK_DELTA = 10*60*1000;
+       
+       public boolean wouldBlock(boolean wakeTicker) throws 
BlockedTooLongException {
+               long now = System.currentTimeMillis();
+               synchronized(this) {
+                       if(sentPacketsContents.wouldBlock(nextPacketNumber)) {
+                               if(timeWouldBlock == -1)
+                                       timeWouldBlock = now;
+                               else {
+                                       long delta = now - timeWouldBlock;
+                                       if(delta > MAX_WOULD_BLOCK_DELTA) {
+                                               Logger.error(this, "Not been 
able to allocate a packet to tracker "+this+" for "+TimeUtil.formatTime(delta));
+                                               throw new 
BlockedTooLongException(this, delta);
+                                       }
+                               }
+                               return true;
+                       } else {
+                               if(timeWouldBlock != -1) {
+                                       long delta = now - timeWouldBlock;
+                                       if(delta > 
PacketSender.MAX_COALESCING_DELAY) {
+                                               Logger.error(this, "Waking 
PacketSender: have been blocking for packet ack for 
"+TimeUtil.formatTime(delta));
+                                       } else return false;
+                               } else return false;
+                       }
+               }
+               pn.node.ps.wakeUp();
+               return false;
+       }
 
        /**
         * @return A packet number for a new outgoing packet.
@@ -727,6 +768,7 @@
                        if(isDeprecated)
                                throw new KeyChangedException();
                        sentPacketsContents.lockNeverBlock(packetNumber);
+                       timeWouldBlock = -1;
                        nextPacketNumber = packetNumber + 1;
                        if(logMINOR)
                                Logger.minor(this, "Allocated " + packetNumber 
+ " in allocateOutgoingPacketNumberNeverBlock for " + this);
@@ -859,7 +901,7 @@
                                                                
Logger.minor(this, "Packet " + qr.packetNumber + " sent over " + (now - 
qr.createdTime) + "ms ago and still not acked on " + this + " for " + pn);
                                                        if(now - qr.createdTime 
> 10 * 60 * 1000) {
                                                                
Logger.error(this, "Packet " + qr.packetNumber + " sent over " + (now - 
qr.createdTime) + "ms ago and still not acked on " + this + " for " + pn);
-                                                               throw new 
StillNotAckedException();
+                                                               throw new 
StillNotAckedException(this);
                                                        }
                                                }
                                                packetNumbers[realLength++] = 
packetNumber;

Modified: branches/db4o/freenet/src/freenet/node/LoggingConfigHandler.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/LoggingConfigHandler.java    
2008-11-29 19:18:00 UTC (rev 23980)
+++ branches/db4o/freenet/src/freenet/node/LoggingConfigHandler.java    
2008-11-29 19:21:46 UTC (rev 23981)
@@ -163,7 +163,7 @@
        
        // interval
        
-       config.register("interval", "1HOUR", 5, true, false, 
"LogConfigHandler.rotationInterval", "LogConfigHandler.rotationIntervalLong",
+       config.register("interval", "10MINUTE", 5, true, false, 
"LogConfigHandler.rotationInterval", "LogConfigHandler.rotationIntervalLong",
                        new StringCallback() {
                                        @Override
                                        public String get() {

Modified: branches/db4o/freenet/src/freenet/node/NodeDispatcher.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeDispatcher.java  2008-11-29 
19:18:00 UTC (rev 23980)
+++ branches/db4o/freenet/src/freenet/node/NodeDispatcher.java  2008-11-29 
19:21:46 UTC (rev 23981)
@@ -298,11 +298,7 @@
                node.getTicker().queueTimedJob(new FastRunnable() {
                        public void run() {
                                // Send the ack
-                               try {
                                        source.sendAnyUrgentNotifications(true);
-                               } catch (PacketSequenceException e) {
-                                       // Ignore
-                               }
                                finishDisconnect(m, source);
                        }
                }, 0);

Modified: branches/db4o/freenet/src/freenet/node/OutgoingPacketMangler.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/OutgoingPacketMangler.java   
2008-11-29 19:18:00 UTC (rev 23980)
+++ branches/db4o/freenet/src/freenet/node/OutgoingPacketMangler.java   
2008-11-29 19:21:46 UTC (rev 23981)
@@ -26,9 +26,11 @@
         * Any packets which cannot be sent will be requeued on the PeerNode.
         * @param onePacketOnly If true, we will only send one packet, and will 
requeue any
         * messages that don't fit in that single packet.
+        * @return True if we sent a packet.
+        * @throws BlockedTooLongException 
         */
-       public void processOutgoingOrRequeue(MessageItem[] messages, PeerNode 
pn,
-                       boolean neverWaitForPacketNumber, boolean dontRequeue, 
boolean onePacketOnly);
+       public boolean processOutgoingOrRequeue(MessageItem[] messages, 
PeerNode pn,
+                       boolean neverWaitForPacketNumber, boolean dontRequeue, 
boolean onePacketOnly) throws BlockedTooLongException;
 
        /**
         * Resend a single packet.

Modified: branches/db4o/freenet/src/freenet/node/PacketSender.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/PacketSender.java    2008-11-29 
19:18:00 UTC (rev 23980)
+++ branches/db4o/freenet/src/freenet/node/PacketSender.java    2008-11-29 
19:21:46 UTC (rev 23981)
@@ -4,15 +4,21 @@
 package freenet.node;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.TreeMap;
 import java.util.Vector;
 
 import org.tanukisoftware.wrapper.WrapperManager;
 
+import freenet.io.comm.Peer;
+import freenet.l10n.L10n;
+import freenet.node.useralerts.UserAlert;
 import freenet.support.FileLoggerHook;
+import freenet.support.HTMLNode;
 import freenet.support.Logger;
 import freenet.support.OOMHandler;
+import freenet.support.TimeUtil;
 import freenet.support.io.NativeThread;
 
 /**
@@ -251,6 +257,7 @@
                                        continue;
                                }
                                
+                               try {
                                if(pn.maybeSendPacket(now, rpiTemp, rpiIntTemp) 
&& canSendThrottled) {
                                        canSendThrottled = false;
                                        count = node.outputThrottle.getCount();
@@ -265,6 +272,11 @@
                                                newBrokeAt = i;
                                        }
                                }
+                               } catch (BlockedTooLongException e) {
+                                       Logger.error(this, "Waited too long: 
"+TimeUtil.formatTime(e.delta)+" to allocate a packet number to send to 
"+this+" on "+e.tracker+" - DISCONNECTING!");
+                                       pn.forceDisconnect(true);
+                                       onForceDisconnectBlockTooLong(pn, e);
+                               }
                                
                                long urgentTime = pn.getNextUrgentTime(now);
                                // Should spam the logs, unless there is a 
deadlock
@@ -409,6 +421,107 @@
                return brokeAt;
        }
 
+       private HashSet<Peer> peersDumpedBlockedTooLong = new HashSet<Peer>();
+       
+       private void onForceDisconnectBlockTooLong(PeerNode pn, 
BlockedTooLongException e) {
+               Peer p = pn.getPeer();
+               synchronized(peersDumpedBlockedTooLong) {
+                       peersDumpedBlockedTooLong.add(p);
+                       if(peersDumpedBlockedTooLong.size() > 1) return;
+               }
+               node.clientCore.alerts.register(peersDumpedBlockedTooLongAlert);
+       }
+       
+       private UserAlert peersDumpedBlockedTooLongAlert = new UserAlert() {
+
+               public String anchor() {
+                       return "disconnectedStillNotAcked";
+               }
+
+               public String dismissButtonText() {
+                       return null;
+               }
+
+               public short getPriorityClass() {
+                       return UserAlert.ERROR;
+               }
+
+               public String getShortText() {
+                       int sz;
+                       synchronized(peersDumpedBlockedTooLong) {
+                               sz = peersDumpedBlockedTooLong.size();
+                       }
+                       return l10n("somePeersDisconnectedBlockedTooLong", 
"count", Integer.toString(sz));
+               }
+
+               public HTMLNode getHTMLText() {
+                       HTMLNode div = new HTMLNode("div");
+                       Peer[] peers;
+                       synchronized(peersDumpedBlockedTooLong) {
+                               peers = peersDumpedBlockedTooLong.toArray(new 
Peer[peersDumpedBlockedTooLong.size()]);
+                       }
+                       L10n.addL10nSubstitution(div, 
"FNPPacketMangler.somePeersDisconnectedBlockedTooLongDetail", 
+                                       new String[] { "count", "link", "/link" 
}
+                                       , new String[] { 
Integer.toString(peers.length), "<a 
href=\"/?_CHECKED_HTTP_=https://bugs.freenetproject.org/\";>", "</a>" });
+                       HTMLNode list = div.addChild("ul");
+                       for(Peer peer : peers) {
+                               list.addChild("li", peer.toString());
+                       }
+                       return div;
+               }
+
+               public String getText() {
+                       StringBuffer sb = new StringBuffer();
+                       Peer[] peers;
+                       synchronized(peersDumpedBlockedTooLong) {
+                               peers = peersDumpedBlockedTooLong.toArray(new 
Peer[peersDumpedBlockedTooLong.size()]);
+                       }
+                       
sb.append(l10n("somePeersDisconnectedStillNotAckedDetail", 
+                                       new String[] { "count", "link", "/link" 
},
+                                       new String[] { 
Integer.toString(peers.length), "", "" } ));
+                       sb.append('\n');
+                       for(Peer peer : peers) {
+                               sb.append('\t');
+                               sb.append(peer.toString());
+                               sb.append('\n');
+                       }
+                       return sb.toString();
+               }
+               
+               public String getTitle() {
+                       return getShortText();
+               }
+
+               public Object getUserIdentifier() {
+                       return PacketSender.this;
+               }
+
+               public boolean isEventNotification() {
+                       return false;
+               }
+
+               public boolean isValid() {
+                       return true;
+               }
+
+               public void isValid(boolean validity) {
+                       // Ignore
+               }
+
+               public void onDismiss() {
+                       // Ignore
+               }
+
+               public boolean shouldUnregisterOnDismiss() {
+                       return false;
+               }
+
+               public boolean userCanDismiss() {
+                       return false;
+               }
+
+       };
+
        /** Wake up, and send any queued packets. */
        void wakeUp() {
                // Wake up if needed
@@ -417,12 +530,18 @@
                }
        }
 
+       protected String l10n(String key, String[] patterns, String[] values) {
+               return L10n.getString("PacketSender."+key, patterns, values);
+       }
+
+       protected String l10n(String key, String pattern, String value) {
+               return L10n.getString("PacketSender."+key, pattern, value);
+       }
+
        public void queueTimedJob(Runnable job, long offset) {
                queueTimedJob(job, "Scheduled job: "+job, offset, false);
        }
        
-       
-       
        public void queueTimedJob(Runnable runner, String name, long offset, 
boolean runOnTickerAnyway) {
                // Run directly *if* that won't cause any priority problems.
                if(offset <= 0 && !runOnTickerAnyway) {

Modified: branches/db4o/freenet/src/freenet/node/PeerNode.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/PeerNode.java        2008-11-29 
19:18:00 UTC (rev 23980)
+++ branches/db4o/freenet/src/freenet/node/PeerNode.java        2008-11-29 
19:21:46 UTC (rev 23981)
@@ -1256,8 +1256,13 @@
        */
        public long getNextUrgentTime(long now) {
                long t = Long.MAX_VALUE;
+               KeyTracker cur;
+               KeyTracker prev;
                synchronized(this) {
-               KeyTracker kt = currentTracker;
+                       cur = currentTracker;
+                       prev = previousTracker;
+               }
+               KeyTracker kt = cur;
                if(kt != null) {
                        long next = kt.getNextUrgentTime();
                        t = Math.min(t, next);
@@ -1265,7 +1270,7 @@
                                Logger.minor(this, "Next urgent time from 
curTracker less than now");
                        if(kt.hasPacketsToResend()) return now;
                }
-               kt = previousTracker;
+               kt = prev;
                if(kt != null) {
                        long next = kt.getNextUrgentTime();
                        t = Math.min(t, next);
@@ -1273,8 +1278,12 @@
                                Logger.minor(this, "Next urgent time from 
prevTracker less than now");
                        if(kt.hasPacketsToResend()) return now;
                }
+               try {
+                       if(!cur.wouldBlock(false))
+                               t = messageQueue.getNextUrgentTime(t, now);
+               } catch (BlockedTooLongException e) {
+                       // Ignore for now, it will come back around
                }
-               t = messageQueue.getNextUrgentTime(t, now);
                return t;
        }
        
@@ -1859,7 +1868,9 @@
                        unroutableNewerVersion = newer;
                        unroutableOlderVersion = older;
                        bootIDChanged = (thisBootID != this.bootID);
-                       if(bootIDChanged && logMINOR)
+                       if(bootIDChanged && wasARekey)
+                               Logger.error(this, "Changed boot ID while 
rekeying! from " + bootID + " to " + thisBootID + " for " + getPeer());
+                       else if(bootIDChanged && logMINOR)
                                Logger.minor(this, "Changed boot ID from " + 
bootID + " to " + thisBootID + " for " + getPeer());
                        this.bootID = thisBootID;
                        if(bootIDChanged) {
@@ -1896,7 +1907,7 @@
                        }
                        ctx = null;
                        isRekeying = false;
-                       timeLastRekeyed = now;
+                       timeLastRekeyed = now - (unverified ? 0 : 
FNPPacketMangler.MAX_SESSION_KEY_REKEYING_DELAY / 2);
                        totalBytesExchangedWithCurrentTracker = 0;
                        // This has happened in the past, and caused problems, 
check for it.
                        if(currentTracker != null && previousTracker != null && 
@@ -2407,7 +2418,7 @@
        * @throws PacketSequenceException If there is an error sending the 
packet
        * caused by a sequence inconsistency. 
        */
-       public boolean sendAnyUrgentNotifications(boolean forceSendPrimary) 
throws PacketSequenceException {
+       public boolean sendAnyUrgentNotifications(boolean forceSendPrimary) {
                boolean sent = false;
                if(logMINOR)
                        Logger.minor(this, "sendAnyUrgentNotifications");
@@ -2432,7 +2443,9 @@
                                } catch(KeyChangedException e) {
                                // Ignore
                                } catch(WouldBlockException e) {
-                               // Impossible, ignore
+                                       Logger.error(this, "Caught impossible: 
"+e, e);
+                               } catch(PacketSequenceException e) {
+                                       Logger.error(this, "Caught impossible: 
"+e, e);
                                }
                        }
                }
@@ -2450,7 +2463,9 @@
                                } catch(KeyChangedException e) {
                                // Ignore
                                } catch(WouldBlockException e) {
-                                       Logger.error(this, "Impossible: " + e, 
e);
+                                       Logger.error(this, "Caught impossible: 
"+e, e);
+                               } catch(PacketSequenceException e) {
+                                       Logger.error(this, "Caught impossible: 
"+e, e);
                                }
                }
                return sent;
@@ -4010,14 +4025,17 @@
         * @param now
         * @param rpiTemp
         * @param rpiTemp
+        * @throws BlockedTooLongException 
         */
-       public boolean maybeSendPacket(long now, Vector<ResendPacketItem> 
rpiTemp, int[] rpiIntTemp) {
+       public boolean maybeSendPacket(long now, Vector<ResendPacketItem> 
rpiTemp, int[] rpiIntTemp) throws BlockedTooLongException {
                // If there are any urgent notifications, we must send a packet.
                boolean mustSend = false;
+               boolean mustSendPacket = false;
                if(mustSendNotificationsNow(now)) {
                        if(logMINOR)
                                Logger.minor(this, "Sending notification");
                        mustSend = true;
+                       mustSendPacket = true;
                }
                // Any packets to resend? If so, resend ONE packet and then 
return.
                for(int j = 0; j < 2; j++) {
@@ -4074,6 +4092,7 @@
                                Logger.minor(this, "Sending keepalive");
                        keepalive = true;
                        mustSend = true;
+                       mustSendPacket = true;
                }
                
                ArrayList<MessageItem> messages = new 
ArrayList<MessageItem>(10);
@@ -4122,17 +4141,17 @@
                        // Send packets, right now, blocking, including any 
active notifications
                        // Note that processOutgoingOrRequeue will drop 
messages from the end
                        // if necessary to fit the messages into a single 
packet.
-                       
getOutgoingMangler().processOutgoingOrRequeue(messages.toArray(new 
MessageItem[messages.size()]), this, true, false, true);
+                       
if(!getOutgoingMangler().processOutgoingOrRequeue(messages.toArray(new 
MessageItem[messages.size()]), this, true, false, true)) {
+                               if(mustSendPacket) {
+                                       if(!sendAnyUrgentNotifications(false))
+                                               
sendAnyUrgentNotifications(true);
+                               }
+                       }
                        return true;
                } else {
                        if(mustSend) {
-                               try {
                                        if(sendAnyUrgentNotifications(false))
                                                return true;
-                               } catch (PacketSequenceException e) {
-                                       Logger.error(this, "Caught "+e, e);
-                                       return false;
-                               }
                                // Can happen occasionally as a race 
condition...
                                Logger.normal(this, "No notifications sent 
despite no messages and mustSend=true for "+this);
                        }

Modified: branches/db4o/freenet/src/freenet/node/StillNotAckedException.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/StillNotAckedException.java  
2008-11-29 19:18:00 UTC (rev 23980)
+++ branches/db4o/freenet/src/freenet/node/StillNotAckedException.java  
2008-11-29 19:21:46 UTC (rev 23981)
@@ -12,4 +12,10 @@
  */
 public class StillNotAckedException extends Exception {
 
+       public StillNotAckedException(KeyTracker tracker) {
+               this.tracker = tracker;
+       }
+       
+       final KeyTracker tracker;
+       
 }

Modified: branches/db4o/freenet/src/freenet/node/Version.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/Version.java 2008-11-29 19:18:00 UTC 
(rev 23980)
+++ branches/db4o/freenet/src/freenet/node/Version.java 2008-11-29 19:21:46 UTC 
(rev 23981)
@@ -24,11 +24,11 @@
        public static final String protocolVersion = "1.0";
 
        /** The build number of the current revision */
-       private static final int buildNumber = 1175;
+       private static final int buildNumber = 1176;
 
        /** Oldest build of Fred we will talk to */
-       private static final int oldLastGoodBuild = 1174;
-       private static final int newLastGoodBuild = 1175;
+       private static final int oldLastGoodBuild = 1175;
+       private static final int newLastGoodBuild = 1176;
        static final long transitionTime;
        
        static {


Property changes on: 
branches/db4o/freenet/src/freenet/support/BinaryBloomFilter.java
___________________________________________________________________
Modified: svn:mergeinfo
   - /trunk/freenet/src/freenet/support/BinaryBloomFilter.java:22002-23531
   + /trunk/freenet/src/freenet/support/BinaryBloomFilter.java:22002-23583


Property changes on: branches/db4o/freenet/src/freenet/support/BloomFilter.java
___________________________________________________________________
Modified: svn:mergeinfo
   - /trunk/freenet/src/freenet/support/BloomFilter.java:22002-23531
   + /trunk/freenet/src/freenet/support/BloomFilter.java:22002-23583


Property changes on: 
branches/db4o/freenet/src/freenet/support/CountingBloomFilter.java
___________________________________________________________________
Modified: svn:mergeinfo
   - /trunk/freenet/src/freenet/support/CountingBloomFilter.java:22002-23531
   + /trunk/freenet/src/freenet/support/CountingBloomFilter.java:22002-23583

Modified: 
branches/db4o/freenet/src/freenet/support/LimitedRangeIntByteArrayMap.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/LimitedRangeIntByteArrayMap.java  
2008-11-29 19:18:00 UTC (rev 23980)
+++ branches/db4o/freenet/src/freenet/support/LimitedRangeIntByteArrayMap.java  
2008-11-29 19:21:46 UTC (rev 23981)
@@ -146,6 +146,11 @@
         }
     }
     
+    public boolean wouldBlock(int index) {
+       if(minValue == -1) return false;
+       return (index - minValue >= maxRange);
+    }
+    
     /**
      * Wait until add(index, whatever) would return true.
      * If this returns, add(index, whatever) will work.


Property changes on: 
branches/db4o/freenet/test/freenet/support/io/MockInputStream.java
___________________________________________________________________
Modified: svn:mergeinfo
   - /trunk/freenet/test/freenet/support/io/MockInputStream.java:22002-23531
   + /trunk/freenet/test/freenet/support/io/MockInputStream.java:22002-23583

_______________________________________________
cvs mailing list
[email protected]
http://emu.freenetproject.org/cgi-bin/mailman/listinfo/cvs

Reply via email to