From ea2be02a292afe3dd90a075d6270ba6270bf9516 Mon Sep 17 00:00:00 2001 From: zzz Date: Mon, 5 Nov 2012 17:23:32 +0000 Subject: [PATCH] * RequestLeaseSetJob: Only disconnect client after multiple dropped lease set requests; reduce timeout, other cleanups --- history.txt | 18 +++++++- .../src/net/i2p/router/RouterVersion.java | 2 +- .../router/client/ClientConnectionRunner.java | 41 +++++++++++-------- .../net/i2p/router/client/ClientManager.java | 8 ++-- .../client/ClientManagerFacadeImpl.java | 2 + .../i2p/router/client/LeaseRequestState.java | 3 ++ .../i2p/router/client/RequestLeaseSetJob.java | 41 ++++++++++--------- 7 files changed, 73 insertions(+), 42 deletions(-) diff --git a/history.txt b/history.txt index 634e385b0..783e80d92 100644 --- a/history.txt +++ b/history.txt @@ -1,6 +1,20 @@ +2012-11-05 zzz + * Console: + - Fix NPE after restart (ticket #763) + - Move more nonces out of system properties + * i2psnark: + - More DHT limits + - Announce to backup trackers if DHT is empty + - Use PEX and DHT info in torrent peer count + - Don't use temp files for announces + * PeerManager: Don't reorganize as often if it takes too long (ticket #765) + * RequestLeaseSetJob: Only disconnect client after multiple dropped + lease set requests; reduce timeout, other cleanups + * Unsigned Update: Fix notification on failure + 2012-11-02 kytv -* German, Portuguese, and Swedish translation updates from Transifex -* Refreshed English po files to push to TX. + * German, Portuguese, and Swedish translation updates from Transifex + * Refreshed English po files to push to TX. 2012-11-02 zzz * configstats: Fix group sorting, translate groups diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index f6e6df3a5..4e28a2c8d 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 4; + public final static long BUILD = 5; /** for example "-test" */ public final static String EXTRA = ""; diff --git a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java index cfe23fa98..36b368906 100644 --- a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java +++ b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java @@ -71,6 +71,7 @@ class ClientConnectionRunner { private final Map _messages; /** lease set request state, or null if there is no request pending on at the moment */ private LeaseRequestState _leaseRequest; + private int _consecutiveLeaseRequestFails; /** currently allocated leaseSet, or null if none is allocated */ private LeaseSet _currentLeaseSet; /** set of messageIds created but not yet ACCEPTED */ @@ -100,6 +101,7 @@ class ClientConnectionRunner { // e.g. on local access private static final int MAX_MESSAGE_ID = 0x4000000; + private static final int MAX_LEASE_FAILS = 5; private static final int BUF_SIZE = 32*1024; /** @since 0.9.2 */ @@ -191,12 +193,17 @@ class ClientConnectionRunner { /** data for the current leaseRequest, or null if there is no active leaseSet request */ LeaseRequestState getLeaseRequest() { return _leaseRequest; } - void setLeaseRequest(LeaseRequestState req) { + /** @param req non-null */ + public void failLeaseRequest(LeaseRequestState req) { + boolean disconnect = false; synchronized (this) { - if ( (_leaseRequest != null) && (req != _leaseRequest) ) - _log.error("Changing leaseRequest from " + _leaseRequest + " to " + req); - _leaseRequest = req; + if (_leaseRequest == req) { + _leaseRequest = null; + disconnect = ++_consecutiveLeaseRequestFails > MAX_LEASE_FAILS; + } } + if (disconnect) + disconnectClient("Too many leaseset request fails"); } /** already closed? */ @@ -287,6 +294,7 @@ class ClientConnectionRunner { if (_log.shouldLog(Log.DEBUG)) _log.debug("LeaseSet created fully: " + state + " / " + ls); _leaseRequest = null; + _consecutiveLeaseRequestFails = 0; } } if ( (state != null) && (state.getOnGranted() != null) ) @@ -351,9 +359,8 @@ class ClientConnectionRunner { _acceptedPending.add(id); if (_log.shouldLog(Log.DEBUG)) - _log.debug("** Receiving message [" + id.getMessageId() + "] with payload of size [" - + payload.getSize() + "]" + " for session [" + _sessionId.getSessionId() - + "]"); + _log.debug("** Receiving message " + id.getMessageId() + " with payload of size " + + payload.getSize() + " for session " + _sessionId.getSessionId()); //long beforeDistribute = _context.clock().now(); // the following blocks as described above SessionConfig cfg = _config; @@ -380,7 +387,7 @@ class ClientConnectionRunner { if (sid == null) return; if (_log.shouldLog(Log.DEBUG)) _log.debug("Acking message send [accepted]" + id + " / " + nonce + " for sessionId " - + sid, new Exception("sendAccepted")); + + sid); MessageStatusMessage status = new MessageStatusMessage(); status.setMessageId(id.getMessageId()); status.setSessionId(sid.getSessionId()); @@ -486,10 +493,11 @@ class ClientConnectionRunner { return; // already requesting } else { _leaseRequest = state = new LeaseRequestState(onCreateJob, onFailedJob, _context.clock().now() + expirationTime, set); - _log.debug("Not already requesting, continue to request " + set); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("New request: " + state); } } - _context.jobQueue().addJob(new RequestLeaseSetJob(_context, this, set, _context.clock().now() + expirationTime, onCreateJob, onFailedJob, state)); + _context.jobQueue().addJob(new RequestLeaseSetJob(_context, this, state)); } private class Rerequest implements SimpleTimer.TimedEvent { @@ -646,8 +654,8 @@ class ClientConnectionRunner { if (!alreadyAccepted(_messageId)) { _log.warn("Almost send an update for message " + _messageId + " to " + MessageStatusMessage.getStatusString(msg.getStatus()) - + " for session [" + _sessionId.getSessionId() - + "] before they knew the messageId! delaying .5s"); + + " for session " + _sessionId.getSessionId() + + " before they knew the messageId! delaying .5s"); _lastTried = _context.clock().now(); requeue(REQUEUE_DELAY); return; @@ -680,15 +688,14 @@ class ClientConnectionRunner { if (_log.shouldLog(Log.DEBUG)) _log.info("Updating message status for message " + _messageId + " to " + MessageStatusMessage.getStatusString(msg.getStatus()) - + " for session [" + _sessionId.getSessionId() - + "] (with nonce=2), retrying after [" - + (_context.clock().now() - _lastTried) - + "]"); + + " for session " + _sessionId.getSessionId() + + " (with nonce=2), retrying after " + + (_context.clock().now() - _lastTried)); } else { if (_log.shouldLog(Log.DEBUG)) _log.debug("Updating message status for message " + _messageId + " to " + MessageStatusMessage.getStatusString(msg.getStatus()) - + " for session [" + _sessionId.getSessionId() + "] (with nonce=2)"); + + " for session " + _sessionId.getSessionId() + " (with nonce=2)"); } try { diff --git a/router/java/src/net/i2p/router/client/ClientManager.java b/router/java/src/net/i2p/router/client/ClientManager.java index c1816bfd0..1a07da10e 100644 --- a/router/java/src/net/i2p/router/client/ClientManager.java +++ b/router/java/src/net/i2p/router/client/ClientManager.java @@ -62,6 +62,8 @@ class ClientManager { private static final int INTERNAL_QUEUE_SIZE = 256; + private static final long REQUEST_LEASESET_TIMEOUT = 60*1000; + public ClientManager(RouterContext context, int port) { _ctx = context; _log = context.logManager().getLog(ClientManager.class); @@ -275,6 +277,8 @@ class ClientManager { * within the timeout specified, queue up the onFailedJob. This call does not * block. * + * UNUSED, the call below without jobs is always used. + * * @param dest Destination from which the LeaseSet's authorization should be requested * @param set LeaseSet with requested leases - this object must be updated to contain the * signed version (as well as any changed/added/removed Leases) @@ -290,12 +294,10 @@ class ClientManager { + dest.calculateHash().toBase64() + ". disconnected?"); _ctx.jobQueue().addJob(onFailedJob); } else { - runner.requestLeaseSet(set, _ctx.clock().now() + timeout, onCreateJob, onFailedJob); + runner.requestLeaseSet(set, timeout, onCreateJob, onFailedJob); } } - private static final int REQUEST_LEASESET_TIMEOUT = 120*1000; - public void requestLeaseSet(Hash dest, LeaseSet ls) { ClientConnectionRunner runner = getRunner(dest); if (runner != null) { diff --git a/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java b/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java index e422e9917..ff40c2115 100644 --- a/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java +++ b/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java @@ -110,6 +110,8 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade implements Inte * within the timeout specified, queue up the onFailedJob. This call does not * block. * + * UNUSED, the call below without jobs is always used. + * * @param dest Destination from which the LeaseSet's authorization should be requested * @param set LeaseSet with requested leases - this object must be updated to contain the * signed version (as well as any changed/added/removed Leases) diff --git a/router/java/src/net/i2p/router/client/LeaseRequestState.java b/router/java/src/net/i2p/router/client/LeaseRequestState.java index 50f4003ca..67968df3b 100644 --- a/router/java/src/net/i2p/router/client/LeaseRequestState.java +++ b/router/java/src/net/i2p/router/client/LeaseRequestState.java @@ -28,6 +28,9 @@ class LeaseRequestState { private final long _expiration; private boolean _successful; + /** + * @param expiration absolute time + */ public LeaseRequestState(Job onGranted, Job onFailed, long expiration, LeaseSet requested) { _onGranted = onGranted; _onFailed = onFailed; diff --git a/router/java/src/net/i2p/router/client/RequestLeaseSetJob.java b/router/java/src/net/i2p/router/client/RequestLeaseSetJob.java index 1abb54c88..72147c060 100644 --- a/router/java/src/net/i2p/router/client/RequestLeaseSetJob.java +++ b/router/java/src/net/i2p/router/client/RequestLeaseSetJob.java @@ -31,7 +31,7 @@ class RequestLeaseSetJob extends JobImpl { private final ClientConnectionRunner _runner; private final LeaseRequestState _requestState; - public RequestLeaseSetJob(RouterContext ctx, ClientConnectionRunner runner, LeaseSet set, long expiration, Job onCreate, Job onFail, LeaseRequestState state) { + public RequestLeaseSetJob(RouterContext ctx, ClientConnectionRunner runner, LeaseRequestState state) { super(ctx); _log = ctx.logManager().getLog(RequestLeaseSetJob.class); _runner = runner; @@ -42,6 +42,7 @@ class RequestLeaseSetJob extends JobImpl { } public String getName() { return "Request Lease Set"; } + public void runJob() { if (_runner.isDead()) return; @@ -59,21 +60,23 @@ class RequestLeaseSetJob extends JobImpl { msg.setSessionId(_runner.getSessionId()); for (int i = 0; i < _requestState.getRequested().getLeaseCount(); i++) { - msg.addEndpoint(_requestState.getRequested().getLease(i).getGateway(), _requestState.getRequested().getLease(i).getTunnelId()); + msg.addEndpoint(_requestState.getRequested().getLease(i).getGateway(), + _requestState.getRequested().getLease(i).getTunnelId()); } try { //_runner.setLeaseRequest(state); _runner.doSend(msg); - getContext().jobQueue().addJob(new CheckLeaseRequestStatus(getContext(), _requestState)); - return; + getContext().jobQueue().addJob(new CheckLeaseRequestStatus()); } catch (I2CPMessageException ime) { getContext().statManager().addRateData("client.requestLeaseSetDropped", 1, 0); _log.error("Error sending I2CP message requesting the lease set", ime); _requestState.setIsSuccessful(false); - _runner.setLeaseRequest(null); - _runner.disconnectClient("I2CP error requesting leaseSet"); - return; + if (_requestState.getOnFailed() != null) + RequestLeaseSetJob.this.getContext().jobQueue().addJob(_requestState.getOnFailed()); + _runner.failLeaseRequest(_requestState); + // Don't disconnect, the tunnel will retry + //_runner.disconnectClient("I2CP error requesting leaseSet"); } } @@ -84,14 +87,12 @@ class RequestLeaseSetJob extends JobImpl { * */ private class CheckLeaseRequestStatus extends JobImpl { - private final LeaseRequestState _req; private final long _start; - public CheckLeaseRequestStatus(RouterContext enclosingContext, LeaseRequestState state) { - super(enclosingContext); - _req = state; + public CheckLeaseRequestStatus() { + super(RequestLeaseSetJob.this.getContext()); _start = System.currentTimeMillis(); - getTiming().setStartAfter(state.getExpiration()); + getTiming().setStartAfter(_requestState.getExpiration()); } public void runJob() { @@ -100,20 +101,22 @@ class RequestLeaseSetJob extends JobImpl { _log.debug("Already dead, dont try to expire the leaseSet lookup"); return; } - if (_req.getIsSuccessful()) { + if (_requestState.getIsSuccessful()) { // we didn't fail - RequestLeaseSetJob.CheckLeaseRequestStatus.this.getContext().statManager().addRateData("client.requestLeaseSetSuccess", 1, 0); + CheckLeaseRequestStatus.this.getContext().statManager().addRateData("client.requestLeaseSetSuccess", 1); return; } else { - RequestLeaseSetJob.CheckLeaseRequestStatus.this.getContext().statManager().addRateData("client.requestLeaseSetTimeout", 1, 0); + CheckLeaseRequestStatus.this.getContext().statManager().addRateData("client.requestLeaseSetTimeout", 1); if (_log.shouldLog(Log.ERROR)) { long waited = System.currentTimeMillis() - _start; - _log.error("Failed to receive a leaseSet in the time allotted (" + waited + "): " + _req + " for " + _log.error("Failed to receive a leaseSet in the time allotted (" + waited + "): " + _requestState + " for " + _runner.getConfig().getDestination().calculateHash().toBase64()); } - _runner.disconnectClient("Took too long to request leaseSet"); - if (_req.getOnFailed() != null) - RequestLeaseSetJob.this.getContext().jobQueue().addJob(_req.getOnFailed()); + if (_requestState.getOnFailed() != null) + RequestLeaseSetJob.this.getContext().jobQueue().addJob(_requestState.getOnFailed()); + _runner.failLeaseRequest(_requestState); + // Don't disconnect, the tunnel will retry + //_runner.disconnectClient("Took too long to request leaseSet"); } } public String getName() { return "Check LeaseRequest Status"; }