public void shutdown() throws InterruptedException {
    if (!isShutdown.getAndSet(true)) {
      // Shut down any pending fetchers
      LOG.info(
          "Shutting down pending fetchers on source"
              + srcNameTrimmed
              + ": "
              + runningFetchers.size());
      lock.lock();
      try {
        wakeLoop.signal(); // signal the fetch-scheduler
        for (Fetcher fetcher : runningFetchers) {
          fetcher.shutdown(); // This could be parallelized.
        }
      } finally {
        lock.unlock();
      }

      if (this.schedulerExecutor != null && !this.schedulerExecutor.isShutdown()) {
        this.schedulerExecutor.shutdownNow();
      }
      if (this.fetcherExecutor != null && !this.fetcherExecutor.isShutdown()) {
        this.fetcherExecutor.shutdownNow(); // Interrupts all running fetchers.
      }
    }
    // All threads are shutdown.  It is safe to shutdown SSL factory
    if (httpConnectionParams.isSSLShuffleEnabled()) {
      HttpConnection.cleanupSSLFactory();
    }
  }
 @Override
 public void onFailure(Throwable t) {
   // Unsuccessful - the fetcher may not have shutdown correctly. Try shutting it down.
   fetcher.shutdown();
   if (isShutdown.get()) {
     LOG.info("Already shutdown. Ignoring error from fetcher: " + t);
   } else {
     LOG.error("Fetcher failed with error: ", t);
     shuffleError = t;
     inputContext.fatalError(t, "Fetch failed");
     doBookKeepingForFetcherComplete();
   }
 }
 @Override
 public void onSuccess(FetchResult result) {
   fetcher.shutdown();
   if (isShutdown.get()) {
     LOG.info("Already shutdown. Ignoring event from fetcher");
   } else {
     Iterable<InputAttemptIdentifier> pendingInputs = result.getPendingInputs();
     if (pendingInputs != null && pendingInputs.iterator().hasNext()) {
       InputHost inputHost =
           knownSrcHosts.get(InputHost.createIdentifier(result.getHost(), result.getPort()));
       assert inputHost != null;
       for (InputAttemptIdentifier input : pendingInputs) {
         inputHost.addKnownInput(input);
       }
       pendingHosts.add(inputHost);
     }
     doBookKeepingForFetcherComplete();
   }
 }