2007-09-22 zzz

* Send messages for the same destination out the same outbound
      tunnel to reduce out-of-order delivery.
This commit is contained in:
zzz
2007-09-23 02:44:34 +00:00
committed by zzz
parent 9145eedc35
commit cf4d2b17c9
5 changed files with 66 additions and 5 deletions

View File

@ -1,4 +1,8 @@
$Id: history.txt,v 1.588 2007-09-18 14:09:21 zzz Exp $
$Id: history.txt,v 1.589 2007-09-19 20:44:05 zzz Exp $
2007-09-22 zzz
* Send messages for the same destination out the same outbound
tunnel to reduce out-of-order delivery.
2007-09-19 zzz
* i2psnark: Fix broken multifile torrent Delete;

View File

@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
*
*/
public class RouterVersion {
public final static String ID = "$Revision: 1.524 $ $Date: 2007-09-18 14:09:19 $";
public final static String ID = "$Revision: 1.525 $ $Date: 2007-09-19 20:44:02 $";
public final static String VERSION = "0.6.1.29";
public final static long BUILD = 6;
public final static long BUILD = 7;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);

View File

@ -41,6 +41,9 @@ public interface TunnelManagerFacade extends Service {
*
*/
boolean isInUse(Hash peer);
/** Is a tunnel a valid member of the pool? */
public boolean isValidTunnel(Hash client, TunnelInfo tunnel);
/** how many tunnels are we participating in? */
public int getParticipatingCount();
@ -85,6 +88,7 @@ class DummyTunnelManagerFacade implements TunnelManagerFacade {
public TunnelInfo selectOutboundTunnel() { return null; }
public TunnelInfo selectOutboundTunnel(Hash destination) { return null; }
public boolean isInUse(Hash peer) { return false; }
public boolean isValidTunnel(Hash client, TunnelInfo tunnel) { return false; }
public int getParticipatingCount() { return 0; }
public int getFreeTunnelCount() { return 0; }
public int getOutboundTunnelCount() { return 0; }

View File

@ -2,6 +2,7 @@ package net.i2p.router.message;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@ -378,7 +379,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
+ _lease.getTunnelId() + " on "
+ _lease.getGateway().toBase64());
_outTunnel = selectOutboundTunnel();
_outTunnel = selectOutboundTunnel(_to);
if (_outTunnel != null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(getJobId() + ": Sending tunnel message out " + _outTunnel.getSendTunnelId(0) + " to "
@ -434,6 +435,45 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
}
}
/**
* Use the same outbound tunnel as we did for the same destination previously,
* if possible, to keep the streaming lib happy
*
*/
private static HashMap _tunnelCache = new HashMap();
private static long _cleanTime = 0;
private TunnelInfo selectOutboundTunnel(Destination to) {
TunnelInfo tunnel;
long now = getContext().clock().now();
synchronized (_tunnelCache) {
if (now - _cleanTime > 5*60*1000) { // clean out periodically
List deleteList = new ArrayList();
for (Iterator iter = _tunnelCache.keySet().iterator(); iter.hasNext(); ) {
Destination dest = (Destination) iter.next();
tunnel = (TunnelInfo) _tunnelCache.get(dest);
if (!getContext().tunnelManager().isValidTunnel(_from.calculateHash(), tunnel))
deleteList.add(dest);
}
for (Iterator iter = deleteList.iterator(); iter.hasNext(); ) {
Destination dest = (Destination) iter.next();
_tunnelCache.remove(dest);
}
_cleanTime = now;
}
tunnel = (TunnelInfo) _tunnelCache.get(to);
if (tunnel != null) {
if (getContext().tunnelManager().isValidTunnel(_from.calculateHash(), tunnel))
return(tunnel);
else
_tunnelCache.remove(to);
}
tunnel = selectOutboundTunnel();
if (tunnel != null)
_tunnelCache.put(to, tunnel);
}
return tunnel;
}
/**
* Pick an arbitrary outbound tunnel to send the message through, or null if
* there aren't any around

View File

@ -187,6 +187,19 @@ public class TunnelPoolManager implements TunnelManagerFacade {
return true;
}
public boolean isValidTunnel(Hash client, TunnelInfo tunnel) {
if (tunnel.getExpiration() < _context.clock().now())
return false;
TunnelPool pool;
if (tunnel.isInbound())
pool = (TunnelPool)_clientInboundPools.get(client);
else
pool = (TunnelPool)_clientOutboundPools.get(client);
if (pool == null)
return false;
return pool.listTunnels().contains(tunnel);
}
public TunnelPoolSettings getInboundSettings() { return _inboundExploratory.getSettings(); }
public TunnelPoolSettings getOutboundSettings() { return _outboundExploratory.getSettings(); }
public void setInboundSettings(TunnelPoolSettings settings) { _inboundExploratory.setSettings(settings); }
@ -498,7 +511,7 @@ public class TunnelPoolManager implements TunnelManagerFacade {
String cap = getCapacity(peer);
TunnelId id = (info.isInbound() ? info.getReceiveTunnelId(j) : info.getSendTunnelId(j));
if (_context.routerHash().equals(peer))
out.write("<td><i>" + peer.toBase64().substring(0,4) + (id == null ? "" : ":" + id) + "</i>" + cap + "</td>");
out.write("<td>" + (id == null ? "" : "" + id) + "</td>");
else
out.write("<td>" + peer.toBase64().substring(0,4) + (id == null ? "" : ":" + id) + cap + "</td>");
}