/** * Check for calls which have timed out. * Timed out calls will be removed and failed. * The remaining milliseconds until the next timeout will be updated. * * @param calls The collection of calls. * * @return The number of calls which were timed out. */ int handleTimeouts(Collection<Call> calls, String msg) { int numTimedOut = 0; for (Iterator<Call> iter = calls.iterator(); iter.hasNext(); ) { Call call = iter.next(); int remainingMs = calcTimeoutMsRemainingAsInt(now, call.deadlineMs); if (remainingMs < 0) { call.fail(now, new TimeoutException(msg)); iter.remove(); numTimedOut++; } else { nextTimeoutMs = Math.min(nextTimeoutMs, remainingMs); } } return numTimedOut; }
/** * Check whether a pending call can be assigned a node. Return true if the pending call was either * transferred to the callsToSend collection or if the call was failed. Return false if it * should remain pending. */ private boolean maybeDrainPendingCall(Call call, long now) { try { Node node = call.nodeProvider.provide(); if (node != null) { log.trace("Assigned {} to node {}", call, node); call.curNode = node; getOrCreateListValue(callsToSend, node).add(call); return true; } else { log.trace("Unable to assign {} to a node.", call); return false; } } catch (Throwable t) { // Handle authentication errors while choosing nodes. log.debug("Unable to choose node for {}", call, t); call.fail(now, t); return true; } }
/** * Queue a call for sending. * * If the AdminClient thread has exited, this will fail. Otherwise, it will succeed (even * if the AdminClient is shutting down). This function should called when retrying an * existing call. * * @param call The new call object. * @param now The current time in milliseconds. */ void enqueue(Call call, long now) { if (log.isDebugEnabled()) { log.debug("Queueing {} with a timeout {} ms from now.", call, call.deadlineMs - now); } boolean accepted = false; synchronized (this) { if (newCalls != null) { newCalls.add(call); accepted = true; } } if (accepted) { client.wakeup(); // wake the thread if it is in poll() } else { log.debug("The AdminClient thread has exited. Timing out {}.", call); call.fail(Long.MAX_VALUE, new TimeoutException("The AdminClient thread has exited.")); } }
call.fail(now, response.versionMismatch()); } else if (response.wasDisconnected()) { AuthenticationException authException = client.authenticationException(call.curNode()); if (authException != null) { call.fail(now, authException); } else { call.fail(now, new DisconnectException(String.format( "Cancelled %s request with correlation id %s due to node %s being disconnected", call.callName, correlationId, response.destination()))); if (log.isTraceEnabled()) log.trace("{} handleResponse failed with {}", call, prettyPrintException(t)); call.fail(now, t);
requestBuilder = call.createRequest(timeoutMs); } catch (Throwable throwable) { call.fail(now, new KafkaException(String.format( "Internal error sending %s to %s.", call.callName, node))); continue;
/** * Initiate a new call. * * This will fail if the AdminClient is scheduled to shut down. * * @param call The new call object. * @param now The current time in milliseconds. */ void call(Call call, long now) { if (hardShutdownTimeMs.get() != INVALID_SHUTDOWN_TIME) { log.debug("The AdminClient is not accepting new calls. Timing out {}.", call); call.fail(Long.MAX_VALUE, new TimeoutException("The AdminClient thread is not accepting new calls.")); } else { enqueue(call, now); } }