private synchronized void purgeDeadEntries() {
    if ((System.currentTimeMillis() - lastPurge > minPurgeFrequency)) {
      synchronized (discrepancies) {
        synchronized (liveServers) {
          lastPurge = System.currentTimeMillis();

          Server oldestLive = liveServers.isEmpty() ? null : liveServers.first();
          Set<Server> deadServers =
              oldestLive == null
                  ? discrepancies.keySet()
                  : discrepancies.headMap(oldestLive).keySet();

          int excess = deadServers.size() - maxDeadServers;
          if (excess > 0) {
            Set<Server> toClean = new HashSet<Server>();
            for (Server server : deadServers) {
              long min = System.currentTimeMillis() - minDeadServerTime;
              if (excess > 0 && server.getTimestampChecked() < min) {
                for (TimestampDiscrepancyObserver observer : observers) {
                  if (observer.canRemoveDeadEntry(server.getNode(), server.getTimestampChecked())
                      == false) {
                    // vetoed
                    continue;
                  }
                }

                // If we reached here it wasn't vetoed
                toClean.add(server);
                excess--;
              } else {
                // We've removed enough or the rest are newer than
                // the minimum, so stop checking
                break;
              }
            }

            for (Server toRemove : toClean) {
              discrepancies.remove(toRemove);
            }
          }
        }
      }
    }
  }
  private void updateTimestampDiscrepancy(
      Server server, TimestampDiscrepancy discrepancy, boolean live) {
    discrepancies.put(server, discrepancy);
    nodesByName.put(server.getNode().getName(), server.getNode());
    if (live) {
      liveServers.add(server);
    }

    synchronized (unresolvedRemoteDependencies) {
      Map<Server, TimestampDiscrepancy> unresolved =
          unresolvedRemoteDependencies.remove(server.getNode());
      if (unresolved != null) {
        convertRemoteDiscrepanciesToLocalTime(unresolved, discrepancy);
      }
    }

    for (TimestampDiscrepancyObserver observer : observers) {
      observer.timestampDiscrepancyChanged(server.getNode(), discrepancy);
    }
  }