protected int getPeerCacheLimit() {
    synchronized (this) {
      if (activated.size() < announcers.size()) {

        return (0);
      }
    }

    if (SystemTime.getMonotonousTime() - create_time < 15 * 1000) {

      return (0);
    }

    TRTrackerAnnouncer active = getBestActive();

    if (active != null
        && provider != null
        && active.getStatus() == TRTrackerAnnouncerResponse.ST_ONLINE) {

      if (provider.getMaxNewConnectionsAllowed() > 0 && provider.getPendingConnectionCount() == 0) {

        return (5);

      } else {

        return (0);
      }
    }

    return (10);
  }
  public void update(boolean force) {
    List<TRTrackerAnnouncerHelper> to_update;

    synchronized (this) {
      to_update =
          is_manual ? announcers.getList() : new ArrayList<TRTrackerAnnouncerHelper>(activated);
    }

    for (TRTrackerAnnouncer announcer : to_update) {

      announcer.update(force);
    }
  }
  public void resetTrackerUrl(boolean shuffle) {
    try {
      split();

    } catch (Throwable e) {

      Debug.out(e);
    }

    for (TRTrackerAnnouncer announcer : announcers) {

      announcer.resetTrackerUrl(shuffle);
    }
  }
  public void setAnnounceDataProvider(TRTrackerAnnouncerDataProvider _provider) {
    List<TRTrackerAnnouncerHelper> to_set;

    synchronized (this) {
      provider = _provider;

      to_set = announcers.getList();
    }

    for (TRTrackerAnnouncer announcer : to_set) {

      announcer.setAnnounceDataProvider(provider);
    }
  }
  public void clearIPOverride() {
    List<TRTrackerAnnouncerHelper> to_clear;

    synchronized (this) {
      to_clear = announcers.getList();

      ip_override = null;
    }

    for (TRTrackerAnnouncer announcer : to_clear) {

      announcer.clearIPOverride();
    }
  }
  public void setIPOverride(String override) {
    List<TRTrackerAnnouncerHelper> to_set;

    synchronized (this) {
      to_set = announcers.getList();

      ip_override = override;
    }

    for (TRTrackerAnnouncer announcer : to_set) {

      announcer.setIPOverride(override);
    }
  }
  public void complete(boolean already_reported) {
    List<TRTrackerAnnouncerHelper> to_complete;

    synchronized (this) {
      complete = true;

      to_complete =
          is_manual ? announcers.getList() : new ArrayList<TRTrackerAnnouncerHelper>(activated);
    }

    for (TRTrackerAnnouncer announcer : to_complete) {

      announcer.complete(already_reported);
    }
  }
  public void stop(boolean for_queue) {
    List<TRTrackerAnnouncerHelper> to_stop;

    synchronized (this) {
      stopped = true;

      to_stop =
          is_manual ? announcers.getList() : new ArrayList<TRTrackerAnnouncerHelper>(activated);

      activated.clear();
    }

    for (TRTrackerAnnouncer announcer : to_stop) {

      announcer.stop(for_queue);
    }
  }
  public TRTrackerAnnouncer getBestAnnouncer() {
    int max = -1;

    TRTrackerAnnouncer max_announcer = null;

    for (TRTrackerAnnouncer announcer : announcers) {

      int status = announcer.getStatus();

      if (status > max) {

        max_announcer = announcer;
        max = status;
      }
    }

    return (max_announcer == null ? this : max_announcer);
  }
  public void destroy() {
    TRTrackerAnnouncerFactoryImpl.destroy(this);

    List<TRTrackerAnnouncerHelper> to_destroy;

    synchronized (this) {
      destroyed = true;

      to_destroy = announcers.getList();
    }

    for (TRTrackerAnnouncer announcer : to_destroy) {

      announcer.destroy();
    }

    TimerEvent ev = event;

    if (ev != null) {

      ev.cancel();
    }
  }
  public void setAnnounceResult(DownloadAnnounceResult result) {
    // this is only used for setting DHT results

    for (TRTrackerAnnouncer announcer : announcers) {

      if (announcer instanceof TRTrackerDHTAnnouncerImpl) {

        announcer.setAnnounceResult(result);

        return;
      }
    }

    // TODO: we should always create a DHT entry and have it denote DHT tracking for all
    // circustances
    // have the DHT plugin set it to offline if disabled

    List<TRTrackerAnnouncerHelper> x = announcers.getList();

    if (x.size() > 0) {

      x.get(0).setAnnounceResult(result);
    }
  }
  public void generateEvidence(IndentWriter writer) {
    for (TRTrackerAnnouncer announcer : announcers) {

      announcer.generateEvidence(writer);
    }
  }
  public String getStatusString() {
    TRTrackerAnnouncer max_announcer = getBestAnnouncer();

    return (max_announcer == null ? "" : max_announcer.getStatusString());
  }
  public int getStatus() {
    TRTrackerAnnouncer max_announcer = getBestAnnouncer();

    return (max_announcer == null ? -1 : max_announcer.getStatus());
  }
  public void setRefreshDelayOverrides(int percentage) {
    for (TRTrackerAnnouncer announcer : announcers) {

      announcer.setRefreshDelayOverrides(percentage);
    }
  }