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

Skip to content
Snippets Groups Projects
Commit 5aa33574 authored by jrandom's avatar jrandom Committed by zzz
Browse files

2006-02-18 jrandom

    * Migrate the outbound packets from a central component to the individual
      per-peer components, substantially cutting down on lock contention when
      dealing with higher degrees.
    * Load balance the outbound SSU transfers evenly across peers, rather than
      across messages (so peers with few messages won't be starved by peers
      with many).
    * Reduce the frequency of router info rebuilds (thanks bar!)
parent 12027513
No related branches found
No related tags found
No related merge requests found
$Id: history.txt,v 1.404 2006/02/17 17:29:33 jrandom Exp $
$Id: history.txt,v 1.405 2006/02/18 01:48:48 jrandom Exp $
2006-02-18 jrandom
* Migrate the outbound packets from a central component to the individual
per-peer components, substantially cutting down on lock contention when
dealing with higher degrees.
* Load balance the outbound SSU transfers evenly across peers, rather than
across messages (so peers with few messages won't be starved by peers
with many).
* Reduce the frequency of router info rebuilds (thanks bar!)
2006-02-18 jrandom
* Add a new AIMD throttle in SSU to control the number of concurrent
......
......@@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
*
*/
public class RouterVersion {
public final static String ID = "$Revision: 1.347 $ $Date: 2006/02/17 17:29:32 $";
public final static String ID = "$Revision: 1.348 $ $Date: 2006/02/18 01:38:30 $";
public final static String VERSION = "0.6.1.10";
public final static long BUILD = 3;
public final static long BUILD = 4;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);
......
......@@ -169,6 +169,7 @@ public class EstablishmentManager {
msg.getTarget().getIdentity(),
new SessionKey(addr.getIntroKey()), addr);
_outboundStates.put(to, state);
SimpleTimer.getInstance().addEvent(new Expire(to, state), 10*1000);
}
}
if (state != null) {
......@@ -187,6 +188,33 @@ public class EstablishmentManager {
notifyActivity();
}
private class Expire implements SimpleTimer.TimedEvent {
private RemoteHostId _to;
private OutboundEstablishState _state;
public Expire(RemoteHostId to, OutboundEstablishState state) {
_to = to;
_state = state;
}
public void timeReached() {
Object removed = null;
synchronized (_outboundStates) {
removed = _outboundStates.remove(_to);
if (removed != _state) { // oops, we must have failed, then retried
_outboundStates.put(_to, removed);
removed = null;
}/* else {
locked_admitQueued();
}*/
}
if (removed != null) {
_context.statManager().addRateData("udp.outboundEstablishFailedState", _state.getState(), _state.getLifetime());
if (_log.shouldLog(Log.WARN))
_log.warn("Timing out expired outbound: " + _state);
processExpired(_state);
}
}
}
/**
* How many concurrent inbound sessions to deal with
*/
......@@ -213,11 +241,11 @@ public class EstablishmentManager {
state = (InboundEstablishState)_inboundStates.get(from);
if (state == null) {
state = new InboundEstablishState(_context, from.getIP(), from.getPort(), _transport.getLocalPort());
state.receiveSessionRequest(reader.getSessionRequestReader());
isNew = true;
_inboundStates.put(from, state);
}
}
state.receiveSessionRequest(reader.getSessionRequestReader());
if (isNew) {
if (!_transport.introducersRequired()) {
long tag = _context.random().nextLong(MAX_TAG_VALUE);
......@@ -332,6 +360,7 @@ public class EstablishmentManager {
msg.getTarget().getIdentity(),
new SessionKey(addr.getIntroKey()), addr);
_outboundStates.put(to, qstate);
SimpleTimer.getInstance().addEvent(new Expire(to, qstate), 10*1000);
for (int i = 0; i < queued.size(); i++) {
OutNetMessage m = (OutNetMessage)queued.get(i);
......@@ -361,7 +390,7 @@ public class EstablishmentManager {
private void handleCompletelyEstablished(InboundEstablishState state) {
long now = _context.clock().now();
RouterIdentity remote = state.getConfirmedIdentity();
PeerState peer = new PeerState(_context);
PeerState peer = new PeerState(_context, _transport);
peer.setCurrentCipherKey(state.getCipherKey());
peer.setCurrentMACKey(state.getMACKey());
peer.setCurrentReceiveSecond(now - (now % 1000));
......@@ -396,7 +425,7 @@ public class EstablishmentManager {
private PeerState handleCompletelyEstablished(OutboundEstablishState state) {
long now = _context.clock().now();
RouterIdentity remote = state.getRemoteIdentity();
PeerState peer = new PeerState(_context);
PeerState peer = new PeerState(_context, _transport);
peer.setCurrentCipherKey(state.getCipherKey());
peer.setCurrentMACKey(state.getMACKey());
peer.setCurrentReceiveSecond(now - (now % 1000));
......@@ -721,6 +750,7 @@ public class EstablishmentManager {
// _log.debug("# outbound states: " + _outboundStates.size());
for (Iterator iter = _outboundStates.values().iterator(); iter.hasNext(); ) {
OutboundEstablishState cur = (OutboundEstablishState)iter.next();
if (cur == null) continue;
if (cur.getState() == OutboundEstablishState.STATE_CONFIRMED_COMPLETELY) {
// completely received
iter.remove();
......@@ -770,46 +800,7 @@ public class EstablishmentManager {
if (outboundState != null) {
if (outboundState.getLifetime() > MAX_ESTABLISH_TIME) {
if (outboundState.getState() != OutboundEstablishState.STATE_CONFIRMED_COMPLETELY) {
if (_log.shouldLog(Log.WARN))
_log.warn("Lifetime of expired outbound establish: " + outboundState.getLifetime());
while (true) {
OutNetMessage msg = outboundState.getNextQueuedMessage();
if (msg == null)
break;
_transport.failed(msg, "Expired during failed establish");
}
String err = null;
switch (outboundState.getState()) {
case OutboundEstablishState.STATE_CONFIRMED_PARTIALLY:
err = "Took too long to establish remote connection (confirmed partially)";
break;
case OutboundEstablishState.STATE_CREATED_RECEIVED:
err = "Took too long to establish remote connection (created received)";
break;
case OutboundEstablishState.STATE_REQUEST_SENT:
err = "Took too long to establish remote connection (request sent)";
break;
case OutboundEstablishState.STATE_PENDING_INTRO:
err = "Took too long to establish remote connection (intro failed)";
break;
case OutboundEstablishState.STATE_UNKNOWN: // fallthrough
default:
err = "Took too long to establish remote connection (unknown state)";
}
Hash peer = outboundState.getRemoteIdentity().calculateHash();
_context.shitlist().shitlistRouter(peer, err);
_transport.dropPeer(peer);
//_context.profileManager().commErrorOccurred(peer);
} else {
while (true) {
OutNetMessage msg = outboundState.getNextQueuedMessage();
if (msg == null)
break;
_transport.send(msg);
}
}
processExpired(outboundState);
} else {
switch (outboundState.getState()) {
case OutboundEstablishState.STATE_UNKNOWN:
......@@ -847,6 +838,49 @@ public class EstablishmentManager {
return nextSendTime;
}
private void processExpired(OutboundEstablishState outboundState) {
if (outboundState.getState() != OutboundEstablishState.STATE_CONFIRMED_COMPLETELY) {
if (_log.shouldLog(Log.WARN))
_log.warn("Lifetime of expired outbound establish: " + outboundState.getLifetime());
while (true) {
OutNetMessage msg = outboundState.getNextQueuedMessage();
if (msg == null)
break;
_transport.failed(msg, "Expired during failed establish");
}
String err = null;
switch (outboundState.getState()) {
case OutboundEstablishState.STATE_CONFIRMED_PARTIALLY:
err = "Took too long to establish remote connection (confirmed partially)";
break;
case OutboundEstablishState.STATE_CREATED_RECEIVED:
err = "Took too long to establish remote connection (created received)";
break;
case OutboundEstablishState.STATE_REQUEST_SENT:
err = "Took too long to establish remote connection (request sent)";
break;
case OutboundEstablishState.STATE_PENDING_INTRO:
err = "Took too long to establish remote connection (intro failed)";
break;
case OutboundEstablishState.STATE_UNKNOWN: // fallthrough
default:
err = "Took too long to establish remote connection (unknown state)";
}
Hash peer = outboundState.getRemoteIdentity().calculateHash();
_context.shitlist().shitlistRouter(peer, err);
_transport.dropPeer(peer);
//_context.profileManager().commErrorOccurred(peer);
} else {
while (true) {
OutNetMessage msg = outboundState.getNextQueuedMessage();
if (msg == null)
break;
_transport.send(msg);
}
}
}
/**
* Driving thread, processing up to one step for an inbound peer and up to
......@@ -881,13 +915,15 @@ public class EstablishmentManager {
long delay = nextSendTime - now;
if ( (nextSendTime == -1) || (delay > 0) ) {
if (delay > 5000)
delay = 5000;
boolean interrupted = false;
try {
synchronized (_activityLock) {
if (_activity > 0)
return;
if (nextSendTime == -1)
_activityLock.wait();
_activityLock.wait(5000);
else
_activityLock.wait(delay);
}
......
......@@ -590,7 +590,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
buf.append(" lifetime: ").append(now - peer.getKeyEstablishedTime());
buf.append(" time since send/recv/ack: ").append(timeSinceSend).append(" / ");
buf.append(timeSinceRecv).append(" / ").append(timeSinceAck);
/*
buf.append("Existing peers: \n");
synchronized (_peersByIdent) {
for (Iterator iter = _peersByIdent.keySet().iterator(); iter.hasNext(); ) {
......@@ -617,13 +617,16 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
buf.append("\n");
}
}
*/
_log.warn(buf.toString(), new Exception("Dropped by"));
}
_introManager.remove(peer);
_fragments.dropPeer(peer);
// a bit overzealous - perhaps we should only rebuild the external if the peer being dropped
// is one of our introducers?
rebuildExternalAddress();
// is one of our introducers? dropping it only if we are considered 'not reachable' is a start
if (introducersRequired())
rebuildExternalAddress();
if (peer.getRemotePeer() != null) {
dropPeerCapacities(peer);
......@@ -723,6 +726,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
msg.timestamp("sending on UDP transport");
Hash to = msg.getTarget().getIdentity().calculateHash();
PeerState peer = getPeerState(to);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Sending to " + (to != null ? to.toBase64() : ""));
if (peer != null) {
long lastSend = peer.getLastSendFullyTime();
long lastRecv = peer.getLastReceiveTime();
......@@ -736,14 +741,23 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
// peer is waaaay idle, drop the con and queue it up as a new con
dropPeer(peer, false);
msg.timestamp("peer is really idle, dropping con and reestablishing");
if (_log.shouldLog(Log.DEBUG))
_log.debug("Proactive reestablish to " + to.toBase64());
_establisher.establish(msg);
_context.statManager().addRateData("udp.proactiveReestablish", now-lastSend, now-peer.getKeyEstablishedTime());
return;
}
}
msg.timestamp("enqueueing for an already established peer");
_outboundMessages.add(msg);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Add to fragments for " + to.toBase64());
if (true) // skip the priority queue and go straight to the active pool
_fragments.add(msg);
else
_outboundMessages.add(msg);
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Establish new connection to " + to.toBase64());
msg.timestamp("establishing a new connection");
_establisher.establish(msg);
}
......@@ -752,20 +766,23 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
if (_log.shouldLog(Log.DEBUG))
_log.debug("Injecting a data message to a new peer: " + peer);
OutboundMessageState state = new OutboundMessageState(_context);
state.initialize(msg, peer);
_fragments.add(state);
boolean ok = state.initialize(msg, peer);
if (ok)
_fragments.add(state);
}
public OutNetMessage getNextMessage() { return getNextMessage(-1); }
//public OutNetMessage getNextMessage() { return getNextMessage(-1); }
/**
* Get the next message, blocking until one is found or the expiration
* reached.
*
* @param blockUntil expiration, or -1 if indefinite
*/
/*
public OutNetMessage getNextMessage(long blockUntil) {
return _outboundMessages.getNext(blockUntil);
}
*/
// we don't need the following, since we have our own queueing
......@@ -791,7 +808,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
}
void rebuildExternalAddress() { rebuildExternalAddress(true); }
void rebuildExternalAddress(boolean allowRebuildRouterInfo) {
void rebuildExternalAddress(boolean allowuterInfo) {
if (_context.router().isHidden())
return;
......@@ -937,10 +954,10 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public void failed(OutboundMessageState msg) {
if (msg == null) return;
int consecutive = 0;
OutNetMessage m = msg.getMessage();
if ( (msg.getPeer() != null) &&
( (msg.getMaxSends() >= OutboundMessageFragments.MAX_VOLLEYS) ||
(msg.isExpired())) ) {
OutNetMessage m = msg.getMessage();
long recvDelay = _context.clock().now() - msg.getPeer().getLastReceiveTime();
long sendDelay = _context.clock().now() - msg.getPeer().getLastSendFullyTime();
if (m != null)
......@@ -959,7 +976,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
dropPeer(msg.getPeer(), false);
}
noteSend(msg, false);
super.afterSend(msg.getMessage(), false);
if (m != null)
super.afterSend(m, false);
}
private void noteSend(OutboundMessageState msg, boolean successful) {
......@@ -1011,8 +1029,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
if (_log.shouldLog(Log.DEBUG))
_log.debug("Sending message succeeded: " + msg);
noteSend(msg, true);
if (msg.getMessage() != null)
super.afterSend(msg.getMessage(), true);
OutNetMessage m = msg.getMessage();
if (m != null)
super.afterSend(m, true);
}
public int countActivePeers() {
......@@ -1171,8 +1190,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
buf.append(idleOut);
buf.append("s</code></td>");
int recvBps = (idleIn > 10 ? 0 : peer.getReceiveBps());
int sendBps = (idleOut > 10 ? 0 : peer.getSendBps());
int recvBps = (idleIn > 2 ? 0 : peer.getReceiveBps());
int sendBps = (idleOut > 2 ? 0 : peer.getSendBps());
buf.append("<td valign=\"top\" ><code>");
buf.append(formatKBps(recvBps));
......
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