private Map<String, String> queryExhibitors(Exhibitors localExhibitors) { Map<String, String> values = newValues(); long start = System.currentTimeMillis(); int retries = 0; boolean done = false; while (!done) { List<String> hostnames = Lists.newArrayList(localExhibitors.getHostnames()); if (hostnames.size() == 0) { done = true; } else { String hostname = hostnames.get(random.nextInt(hostnames.size())); try { String encoded = restClient.getRaw(hostname, localExhibitors.getRestPort(), restUriPath, MIME_TYPE); values.putAll(decodeExhibitorList(encoded)); done = true; } catch (Throwable e) { if (retryPolicy.allowRetry( retries++, System.currentTimeMillis() - start, RetryLoop.getDefaultRetrySleeper())) { log.warn("Couldn't get servers from Exhibitor. Retrying.", e); } else { log.error("Couldn't get servers from Exhibitor. Giving up.", e); done = true; } } } } return values; }
@VisibleForTesting protected void poll() { Exhibitors localExhibitors = exhibitors.get(); Map<String, String> values = queryExhibitors(localExhibitors); int count = getCountFromValues(values); if (count == 0) { log.warn("0 count returned from Exhibitors. Using backup connection values."); values = useBackup(localExhibitors); count = getCountFromValues(values); } if (count > 0) { int port = Integer.parseInt(values.get(VALUE_PORT)); StringBuilder newConnectionString = new StringBuilder(); List<String> newHostnames = Lists.newArrayList(); for (int i = 0; i < count; ++i) { if (newConnectionString.length() > 0) { newConnectionString.append(","); } String server = values.get(VALUE_SERVER_PREFIX + i); newConnectionString.append(server).append(":").append(port); newHostnames.add(server); } String newConnectionStringValue = newConnectionString.toString(); if (!newConnectionStringValue.equals(connectionString.get())) { log.info( "Connection string has changed. Old value (%s), new value (%s)", connectionString.get(), newConnectionStringValue); } Exhibitors newExhibitors = new Exhibitors( newHostnames, localExhibitors.getRestPort(), new Exhibitors.BackupConnectionStringProvider() { @Override public String getBackupConnectionString() throws Exception { return masterExhibitors .get() .getBackupConnectionString(); // this may be overloaded by clients. Make sure // there is always a method call to get the // value. } }); connectionString.set(newConnectionStringValue); exhibitors.set(newExhibitors); } }
private Map<String, String> useBackup(Exhibitors localExhibitors) { Map<String, String> values = newValues(); try { String backupConnectionString = localExhibitors.getBackupConnectionString(); int thePort = -1; int count = 0; for (String spec : backupConnectionString.split(",")) { spec = spec.trim(); String[] parts = spec.split(":"); if (parts.length == 2) { String hostname = parts[0]; int port = Integer.parseInt(parts[1]); if (thePort < 0) { thePort = port; } else if (port != thePort) { log.warn("Inconsistent port in connection component: " + spec); } values.put(VALUE_SERVER_PREFIX + count, hostname); ++count; } else { log.warn("Bad backup connection component: " + spec); } } values.put(VALUE_COUNT, Integer.toString(count)); values.put(VALUE_PORT, Integer.toString(thePort)); } catch (Exception e) { log.error("Couldn't get backup connection string", e); } return values; }