public void run() { while (true) { IResponse resp = responseQueue.removeResponse(); Integer respId = (Integer) resp.getId(); SPFSession session = sessions.remove(respId); FutureSPFResult result = results.remove(respId); DNSLookupContinuation cont = (DNSLookupContinuation) session.getAttribute(ATTRIBUTE_STAGED_EXECUTOR_CONTINUATION); DNSResponse response; if (resp.getException() != null) { response = new DNSResponse((TimeoutException) resp.getException()); } else { response = new DNSResponse(resp.getValue()); } try { cont = cont.getListener().onDNSResponse(response, session); if (cont != null) { invokeAsynchService(session, result, cont, false); } else { execute(session, result, false); } } catch (Exception e) { SPFChecker checker = null; while (e != null) { while (checker == null || !(checker instanceof SPFCheckerExceptionCatcher)) { checker = session.popChecker(); } try { ((SPFCheckerExceptionCatcher) checker).onException(e, session); e = null; } catch (SPFResultException ex) { e = ex; } finally { checker = null; } } execute(session, result, false); } } }
/** * throttle should be true only when the caller thread is the client and not the worker thread. We * could even remove the throttle parameter and check the currentThread. This way the worker is * never "blocked" while outside callers will be blocked if our queue is too big (so this is not * fully "asynchronous"). */ private synchronized void invokeAsynchService( SPFSession session, FutureSPFResult result, DNSLookupContinuation cont, boolean throttle) { while (throttle && results.size() > 50) { try { this.wait(100); } catch (InterruptedException e) { } } int nextId = nextId(); sessions.put(new Integer(nextId), session); results.put(new Integer(nextId), result); session.setAttribute(ATTRIBUTE_STAGED_EXECUTOR_CONTINUATION, cont); dnsProbe.getRecordsAsynch(cont.getRequest(), nextId, responseQueue); }