/** The handler threw a Throwable, i.e. failed due to a serious bug. * Unlock the handler, and record the throwable in case of future problems. * @param t The Throwable thrown by the RequestHandler. */ public void handlerThrew(Throwable t) { synchronized(this) { this.handlerThrew = t; } unlockHandler(); // FIXME optimise synchronization in a clean way. }
@Override void sent(boolean success) { // As soon as the originator receives the messages, he can reuse the slot. // Unlocking on sent is a reasonable compromise between: // 1. Unlocking immediately avoids problems with the recipient reusing the slot when he's received the data, therefore us rejecting the request and getting a mandatory backoff, and // 2. However, we do want SSK requests from the datastore to be counted towards the total when accepting requests. // This is safe however. // We have already done the request so there is no outgoing request. // A node might be able to get a few more slots in flight by not acking the SSK messages, but it would quickly stall. // Furthermore, we would start sending hard rejections when the send queue gets past a certain point. // So it is neither beneficial for the node nor a viable DoS. // Alternative solution would be to wait until the pubkey and data have been acked before unlocking and sending the headers, but this appears not to be necessary. tag.unlockHandler(); } };
@Override public void acked(boolean timedOutMessage) { tag.unlockHandler(); // will remove transfer rs.ackOpennet(dataSource); applyByteCounts(); }
@Override public void onDataFoundLocally() { tag.unlockHandler(); listener.onSucceeded(); }
private void unregisterRequestHandlerWithNode() { RequestSender r; synchronized(this) { r = rs; } if(r != null) { PeerNode p = r.successFrom(); if(p != null) tag.finishedWaitingForOpennet(p); } tag.unlockHandler(); }
/** * Sends the 'final' packet of a request in such a way that the thread can be freed (made non-runnable/exit) * and the byte counter will still be accurate. */ private void sendTerminal(Message msg) { if(logMINOR) Logger.minor(this, "sendTerminal(" + msg + ")", new Exception("debug")); if(sendTerminalCalled) throw new IllegalStateException("sendTerminal should only be called once"); else sendTerminalCalled = true; // Unlock handler immediately. // Otherwise the request sender will think the slot is free as soon as it // receives it, but we won't, so we may reject his requests and get a mandatory backoff. tag.unlockHandler(); try { source.sendAsync(msg, new TerminalMessageByteCountCollector(), this); } catch (NotConnectedException e) { // Will have called the callback, so caller doesn't need to worry about it. } } boolean sendTerminalCalled = false;
tag.unlockHandler(); rs.ackOpennet(dataSource); } else { tag.unlockHandler(); applyByteCounts();
@Override public void timedOut() { tag.unlockHandler(); try { dataSource.sendAsync(DMT.createFNPOpennetCompletedTimeout(uid), rs.finishOpennetOnAck(dataSource), RequestHandler.this); } catch (NotConnectedException e) { // Ignore } rs.ackOpennet(rs.successFrom()); applyByteCounts(); }
tag.unlockHandler(); return; rs.addListener(listener); if(rs.uid != uid) tag.unlockHandler();
tag.unlockHandler(rejectReason.soft);