I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit c455fa63 authored by zzz's avatar zzz
Browse files

* OCMOSJ:

      - Change from 5% reply requests to at least
        once per minute, in hopes of reducing IRC drops
      - More clean up of the cache cleaning
parent 59b624a4
No related branches found
No related tags found
No related merge requests found
...@@ -103,6 +103,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -103,6 +103,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
private static final Object _initializeLock = new Object(); private static final Object _initializeLock = new Object();
private static boolean _initialized = false; private static boolean _initialized = false;
private static final int CLEAN_INTERVAL = 5*60*1000; private static final int CLEAN_INTERVAL = 5*60*1000;
private static final int REPLY_REQUEST_INTERVAL = 60*1000;
/** /**
* Send the sucker * Send the sucker
...@@ -212,7 +213,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -212,7 +213,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
* *
* Key the cache on the source+dest pair. * Key the cache on the source+dest pair.
*/ */
private static HashMap _leaseSetCache = new HashMap(); private static HashMap<String, LeaseSet> _leaseSetCache = new HashMap();
private LeaseSet getReplyLeaseSet(boolean force) { private LeaseSet getReplyLeaseSet(boolean force) {
LeaseSet newLS = getContext().netDb().lookupLeaseSetLocally(_from.calculateHash()); LeaseSet newLS = getContext().netDb().lookupLeaseSetLocally(_from.calculateHash());
if (newLS == null) if (newLS == null)
...@@ -247,7 +248,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -247,7 +248,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
long now = getContext().clock().now(); long now = getContext().clock().now();
synchronized (_leaseSetCache) { synchronized (_leaseSetCache) {
if (!force) { if (!force) {
LeaseSet ls = (LeaseSet) _leaseSetCache.get(hashPair()); LeaseSet ls = _leaseSetCache.get(hashPair());
if (ls != null) { if (ls != null) {
if (ls.equals(newLS)) { if (ls.equals(newLS)) {
// still good, send it 10% of the time // still good, send it 10% of the time
...@@ -312,7 +313,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -312,7 +313,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
* lease). * lease).
* *
*/ */
private static HashMap _leaseCache = new HashMap(); private static HashMap<String, Lease> _leaseCache = new HashMap();
private boolean getNextLease() { private boolean getNextLease() {
_leaseSet = getContext().netDb().lookupLeaseSetLocally(_to.calculateHash()); _leaseSet = getContext().netDb().lookupLeaseSetLocally(_to.calculateHash());
if (_leaseSet == null) { if (_leaseSet == null) {
...@@ -325,7 +326,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -325,7 +326,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
// Use the same lease if it's still good // Use the same lease if it's still good
// Even if _leaseSet changed, _leaseSet.getEncryptionKey() didn't... // Even if _leaseSet changed, _leaseSet.getEncryptionKey() didn't...
synchronized (_leaseCache) { synchronized (_leaseCache) {
_lease = (Lease) _leaseCache.get(hashPair()); _lease = _leaseCache.get(hashPair());
if (_lease != null) { if (_lease != null) {
// if outbound tunnel length == 0 && lease.firsthop.isBacklogged() don't use it ?? // if outbound tunnel length == 0 && lease.firsthop.isBacklogged() don't use it ??
if (!_lease.isExpired(Router.CLOCK_FUDGE_FACTOR)) { if (!_lease.isExpired(Router.CLOCK_FUDGE_FACTOR)) {
...@@ -446,6 +447,14 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -446,6 +447,14 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
} }
} }
/**
* This cache is used to ensure that we request a reply every so often.
* Hopefully this allows the router to recognize a failed tunnel and switch,
* before upper layers like streaming lib fail, even for low-bandwidth
* connections like IRC.
*/
private static HashMap<String, Long> _lastReplyRequestCache = new HashMap();
/** /**
* Send the message to the specified tunnel by creating a new garlic message containing * Send the message to the specified tunnel by creating a new garlic message containing
* the (already created) payload clove as well as a new delivery status message. This garlic * the (already created) payload clove as well as a new delivery status message. This garlic
...@@ -456,18 +465,27 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -456,18 +465,27 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
*/ */
private void send() { private void send() {
if (_finished) return; if (_finished) return;
if (getContext().clock().now() >= _overallExpiration) { long now = getContext().clock().now();
if (now >= _overallExpiration) {
dieFatal(); dieFatal();
return; return;
} }
int existingTags = GarlicMessageBuilder.estimateAvailableTags(getContext(), _leaseSet.getEncryptionKey()); int existingTags = GarlicMessageBuilder.estimateAvailableTags(getContext(), _leaseSet.getEncryptionKey());
_outTunnel = selectOutboundTunnel(_to); _outTunnel = selectOutboundTunnel(_to);
// boolean wantACK = _wantACK || existingTags <= 30 || getContext().random().nextInt(100) < 5;
// what's the point of 5% random? possible improvements or replacements: // what's the point of 5% random? possible improvements or replacements:
// - wantACK if we changed their inbound lease (getNextLease() sets _wantACK) // DONE (getNextLease() is called before this): wantACK if we changed their inbound lease (getNextLease() sets _wantACK)
// - wantACK if we changed our outbound tunnel (selectOutboundTunnel() sets _wantACK) // DONE (selectOutboundTunnel() moved above here): wantACK if we changed our outbound tunnel (selectOutboundTunnel() sets _wantACK)
// - wantACK if we haven't in last 1m (requires a new static cache probably) // DONE (added new cache): wantACK if we haven't in last 1m (requires a new static cache probably)
boolean wantACK = _wantACK || existingTags <= 30 || getContext().random().nextInt(100) < 5; boolean wantACK;
synchronized (_lastReplyRequestCache) {
Long lastSent = _lastReplyRequestCache.get(hashPair());
wantACK = _wantACK || existingTags <= 30 ||
lastSent == null || lastSent.longValue() < now - REPLY_REQUEST_INTERVAL;
if (wantACK)
_lastReplyRequestCache.put(hashPair(), Long.valueOf(now));
}
PublicKey key = _leaseSet.getEncryptionKey(); PublicKey key = _leaseSet.getEncryptionKey();
SessionKey sessKey = new SessionKey(); SessionKey sessKey = new SessionKey();
...@@ -501,7 +519,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -501,7 +519,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
// we dont receive the reply? hmm...) // we dont receive the reply? hmm...)
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn(getJobId() + ": Unable to create the garlic message (no tunnels left or too lagged) to " + _toString); _log.warn(getJobId() + ": Unable to create the garlic message (no tunnels left or too lagged) to " + _toString);
getContext().statManager().addRateData("client.dispatchNoTunnels", getContext().clock().now() - _start, 0); getContext().statManager().addRateData("client.dispatchNoTunnels", now - _start, 0);
dieFatal(); dieFatal();
return; return;
} }
...@@ -539,12 +557,12 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -539,12 +557,12 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
} else { } else {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn(getJobId() + ": Could not find any outbound tunnels to send the payload through... this might take a while"); _log.warn(getJobId() + ": Could not find any outbound tunnels to send the payload through... this might take a while");
getContext().statManager().addRateData("client.dispatchNoTunnels", getContext().clock().now() - _start, 0); getContext().statManager().addRateData("client.dispatchNoTunnels", now - _start, 0);
dieFatal(); dieFatal();
} }
_clientMessage = null; _clientMessage = null;
_clove = null; _clove = null;
getContext().statManager().addRateData("client.dispatchPrepareTime", getContext().clock().now() - _start, 0); getContext().statManager().addRateData("client.dispatchPrepareTime", now - _start, 0);
if (!wantACK) if (!wantACK)
getContext().statManager().addRateData("client.dispatchNoACK", 1, 0); getContext().statManager().addRateData("client.dispatchNoACK", 1, 0);
} }
...@@ -582,7 +600,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -582,7 +600,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
/** /**
* This is the place where we make I2P go fast. * This is the place where we make I2P go fast.
* *
* We have four static caches. * We have five static caches.
* - The LeaseSet cache is used to decide whether to bundle our own leaseset, * - The LeaseSet cache is used to decide whether to bundle our own leaseset,
* which minimizes overhead. * which minimizes overhead.
* - The Lease cache is used to persistently send to the same lease for the destination, * - The Lease cache is used to persistently send to the same lease for the destination,
...@@ -590,6 +608,8 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -590,6 +608,8 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
* - The Tunnel and BackloggedTunnel caches are used to persistently use the same outbound tunnel * - The Tunnel and BackloggedTunnel caches are used to persistently use the same outbound tunnel
* for the same destination, * for the same destination,
* which keeps the streaming lib happy by minimizing out-of-order delivery. * which keeps the streaming lib happy by minimizing out-of-order delivery.
* - The last reply requested cache ensures that a reply is requested every so often,
* so that failed tunnels are recognized.
* *
*/ */
...@@ -629,17 +649,17 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -629,17 +649,17 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
} }
if (_lease != null) { if (_lease != null) {
synchronized(_leaseCache) { synchronized(_leaseCache) {
Lease l = (Lease) _leaseCache.get(key); Lease l = _leaseCache.get(key);
if (l != null && l.equals(_lease)) if (l != null && l.equals(_lease))
_leaseCache.remove(key); _leaseCache.remove(key);
} }
} }
if (_outTunnel != null) { if (_outTunnel != null) {
synchronized(_tunnelCache) { synchronized(_tunnelCache) {
TunnelInfo t =(TunnelInfo) _backloggedTunnelCache.get(key); TunnelInfo t = _backloggedTunnelCache.get(key);
if (t != null && t.equals(_outTunnel)) if (t != null && t.equals(_outTunnel))
_backloggedTunnelCache.remove(key); _backloggedTunnelCache.remove(key);
t = (TunnelInfo) _tunnelCache.get(key); t = _tunnelCache.get(key);
if (t != null && t.equals(_outTunnel)) if (t != null && t.equals(_outTunnel))
_tunnelCache.remove(key); _tunnelCache.remove(key);
} }
...@@ -652,17 +672,12 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -652,17 +672,12 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
*/ */
private static void cleanLeaseSetCache(RouterContext ctx, HashMap tc) { private static void cleanLeaseSetCache(RouterContext ctx, HashMap tc) {
long now = ctx.clock().now(); long now = ctx.clock().now();
List deleteList = new ArrayList();
for (Iterator iter = tc.entrySet().iterator(); iter.hasNext(); ) { for (Iterator iter = tc.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry)iter.next(); Map.Entry entry = (Map.Entry)iter.next();
String k = (String) entry.getKey(); String k = (String) entry.getKey();
LeaseSet l = (LeaseSet) entry.getValue(); LeaseSet l = (LeaseSet) entry.getValue();
if (l.getEarliestLeaseDate() < now) if (l.getEarliestLeaseDate() < now)
deleteList.add(k); iter.remove();
}
for (Iterator iter = deleteList.iterator(); iter.hasNext(); ) {
String k = (String) iter.next();
tc.remove(k);
} }
} }
...@@ -671,17 +686,12 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -671,17 +686,12 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
* Caller must synchronize on tc. * Caller must synchronize on tc.
*/ */
private static void cleanLeaseCache(HashMap tc) { private static void cleanLeaseCache(HashMap tc) {
List deleteList = new ArrayList();
for (Iterator iter = tc.entrySet().iterator(); iter.hasNext(); ) { for (Iterator iter = tc.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry)iter.next(); Map.Entry entry = (Map.Entry)iter.next();
String k = (String) entry.getKey(); String k = (String) entry.getKey();
Lease l = (Lease) entry.getValue(); Lease l = (Lease) entry.getValue();
if (l.isExpired(Router.CLOCK_FUDGE_FACTOR)) if (l.isExpired(Router.CLOCK_FUDGE_FACTOR))
deleteList.add(k); iter.remove();
}
for (Iterator iter = deleteList.iterator(); iter.hasNext(); ) {
String k = (String) iter.next();
tc.remove(k);
} }
} }
...@@ -690,17 +700,25 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -690,17 +700,25 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
* Caller must synchronize on tc. * Caller must synchronize on tc.
*/ */
private static void cleanTunnelCache(RouterContext ctx, HashMap tc) { private static void cleanTunnelCache(RouterContext ctx, HashMap tc) {
List deleteList = new ArrayList();
for (Iterator iter = tc.entrySet().iterator(); iter.hasNext(); ) { for (Iterator iter = tc.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry)iter.next(); Map.Entry entry = (Map.Entry)iter.next();
String k = (String) entry.getKey(); String k = (String) entry.getKey();
TunnelInfo tunnel = (TunnelInfo) entry.getValue(); TunnelInfo tunnel = (TunnelInfo) entry.getValue();
if (!ctx.tunnelManager().isValidTunnel(sourceFromHashPair(k), tunnel)) if (!ctx.tunnelManager().isValidTunnel(sourceFromHashPair(k), tunnel))
deleteList.add(k); iter.remove();
} }
for (Iterator iter = deleteList.iterator(); iter.hasNext(); ) { }
String k = (String) iter.next();
tc.remove(k); /**
* Clean out old reply times
* Caller must synchronize on tc.
*/
private static void cleanReplyCache(RouterContext ctx, HashMap tc) {
long now = ctx.clock().now();
for (Iterator iter = tc.values().iterator(); iter.hasNext(); ) {
Long l = (Long) iter.next();
if (l.longValue() < now - CLEAN_INTERVAL)
iter.remove();
} }
} }
...@@ -720,6 +738,9 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -720,6 +738,9 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
cleanTunnelCache(_ctx, _tunnelCache); cleanTunnelCache(_ctx, _tunnelCache);
cleanTunnelCache(_ctx, _backloggedTunnelCache); cleanTunnelCache(_ctx, _backloggedTunnelCache);
} }
synchronized(_lastReplyRequestCache) {
cleanReplyCache(_ctx, _lastReplyRequestCache);
}
} }
} }
...@@ -731,8 +752,8 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -731,8 +752,8 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
* Key the caches on the source+dest pair. * Key the caches on the source+dest pair.
* *
*/ */
private static HashMap _tunnelCache = new HashMap(); private static HashMap<String, TunnelInfo> _tunnelCache = new HashMap();
private static HashMap _backloggedTunnelCache = new HashMap(); private static HashMap<String, TunnelInfo> _backloggedTunnelCache = new HashMap();
private TunnelInfo selectOutboundTunnel(Destination to) { private TunnelInfo selectOutboundTunnel(Destination to) {
TunnelInfo tunnel; TunnelInfo tunnel;
long now = getContext().clock().now(); long now = getContext().clock().now();
...@@ -743,7 +764,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -743,7 +764,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
* if you were the originator by backlogging the tunnel, then removing the * if you were the originator by backlogging the tunnel, then removing the
* backlog and seeing if traffic came back or not. * backlog and seeing if traffic came back or not.
*/ */
tunnel = (TunnelInfo) _backloggedTunnelCache.get(hashPair()); tunnel = _backloggedTunnelCache.get(hashPair());
if (tunnel != null) { if (tunnel != null) {
if (getContext().tunnelManager().isValidTunnel(_from.calculateHash(), tunnel)) { if (getContext().tunnelManager().isValidTunnel(_from.calculateHash(), tunnel)) {
if (!getContext().commSystem().isBacklogged(tunnel.getPeer(1))) { if (!getContext().commSystem().isBacklogged(tunnel.getPeer(1))) {
...@@ -758,7 +779,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl { ...@@ -758,7 +779,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
_backloggedTunnelCache.remove(hashPair()); _backloggedTunnelCache.remove(hashPair());
} }
// Use the same tunnel unless backlogged // Use the same tunnel unless backlogged
tunnel = (TunnelInfo) _tunnelCache.get(hashPair()); tunnel = _tunnelCache.get(hashPair());
if (tunnel != null) { if (tunnel != null) {
if (getContext().tunnelManager().isValidTunnel(_from.calculateHash(), tunnel)) { if (getContext().tunnelManager().isValidTunnel(_from.calculateHash(), tunnel)) {
if (tunnel.getLength() <= 1 || !getContext().commSystem().isBacklogged(tunnel.getPeer(1))) if (tunnel.getLength() <= 1 || !getContext().commSystem().isBacklogged(tunnel.getPeer(1)))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment