org.postgresql.hostchooser.MultiHostChooser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of postgresql Show documentation
Show all versions of postgresql Show documentation
PostgreSQL JDBC Driver JDBC4
/*-------------------------------------------------------------------------
*
* Copyright (c) 2014, PostgreSQL Global Development Group
*
*
*-------------------------------------------------------------------------
*/
package org.postgresql.hostchooser;
import static java.lang.Boolean.parseBoolean;
import static java.lang.Integer.parseInt;
import static java.util.Arrays.asList;
import static java.util.Collections.shuffle;
import static java.util.Collections.sort;
import org.postgresql.hostchooser.GlobalHostStatusTracker.HostSpecStatus;
import org.postgresql.util.HostSpec;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
/**
* HostChooser that keeps track of known host statuses.
*/
public class MultiHostChooser implements HostChooser {
private HostSpec[] hostSpecs;
private final HostRequirement targetServerType;
private int hostRecheckTime;
private boolean loadBalance;
protected MultiHostChooser(HostSpec[] hostSpecs, HostRequirement targetServerType,
Properties info) {
this.hostSpecs = hostSpecs;
this.targetServerType = targetServerType;
hostRecheckTime = parseInt(info.getProperty("hostRecheckSeconds", "10")) * 1000;
loadBalance = parseBoolean(info.getProperty("loadBalanceHosts", "false"));
}
public Iterator iterator() {
List candidates =
GlobalHostStatusTracker.getCandidateHosts(hostSpecs, targetServerType, hostRecheckTime);
// if no candidates are suitable (all wrong type or unavailable) then we try original list in
// order
if (candidates.isEmpty()) {
return asList(hostSpecs).iterator();
}
if (candidates.size() == 1) {
return asList(candidates.get(0).host).iterator();
}
sortCandidates(candidates);
shuffleGoodHosts(candidates);
return extractHostSpecs(candidates).iterator();
}
private void sortCandidates(List candidates) {
if (targetServerType == HostRequirement.any) {
return;
}
sort(candidates, new HostSpecByTargetServerTypeComparator());
}
private void shuffleGoodHosts(List candidates) {
if (!loadBalance) {
return;
}
int count;
for (count = 1; count < candidates.size(); count++) {
HostSpecStatus hostSpecStatus = candidates.get(count);
if (hostSpecStatus.status != null
&& !targetServerType.allowConnectingTo(hostSpecStatus.status)) {
break;
}
}
if (count == 1) {
return;
}
List goodHosts = candidates.subList(0, count);
shuffle(goodHosts);
}
private List extractHostSpecs(List hostSpecStatuses) {
List hostSpecs = new ArrayList(hostSpecStatuses.size());
for (HostSpecStatus hostSpecStatus : hostSpecStatuses) {
hostSpecs.add(hostSpecStatus.host);
}
return hostSpecs;
}
class HostSpecByTargetServerTypeComparator implements Comparator {
@Override
public int compare(HostSpecStatus o1, HostSpecStatus o2) {
int r1 = rank(o1.status, targetServerType);
int r2 = rank(o2.status, targetServerType);
return r1 == r2 ? 0 : r1 > r2 ? -1 : 1;
}
private int rank(HostStatus status, HostRequirement targetServerType) {
if (status == HostStatus.ConnectFail) {
return -1;
}
switch (targetServerType) {
case master:
return status == HostStatus.Master || status == null ? 1 : 0;
case slave:
return status == HostStatus.Slave || status == null ? 1 : 0;
case preferSlave:
return status == HostStatus.Slave || status == null ? 2
: status == HostStatus.Master ? 1 : 0;
default:
return 0;
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy