@@ -49,6 +49,7 @@ public class DCAwareRoundRobinPolicy implements LoadBalancingPolicy {
4949 private final AtomicInteger index = new AtomicInteger ();
5050 private final String localDc ;
5151 private final int usedHostsPerRemoteDc ;
52+ private final boolean dontHopForLocalCL ;
5253
5354 /**
5455 * Creates a new datacenter aware round robin policy given the name of
@@ -74,6 +75,15 @@ public DCAwareRoundRobinPolicy(String localDc) {
7475 * <p>
7576 * The name of the local datacenter provided must be the local
7677 * datacenter name as known by Cassandra.
78+ * <p>
79+ * If {@code usedHostsPerRemoteDc > 0}, then if for a query no host
80+ * in the local datacenter can be reached and if the consistency
81+ * level of the query is not {@code LOCAL_ONE} or {@code LOCAL_QUORUM},
82+ * then up to {@code usedHostsPerRemoteDc} host per remote data-center
83+ * will be tried by the policy as a fallback. Please note that no
84+ * remote host will be used for {@code LOCAL_ONE} and {@code LOCAL_QUORUM}
85+ * since this would change the meaning of the consistency level (and
86+ * thus somewhat break the consistency contract).
7787 *
7888 * @param localDc the name of the local datacenter (as known by
7989 * Cassandra).
@@ -86,8 +96,41 @@ public DCAwareRoundRobinPolicy(String localDc) {
8696 * connections to them will be maintained).
8797 */
8898 public DCAwareRoundRobinPolicy (String localDc , int usedHostsPerRemoteDc ) {
99+ this (localDc , usedHostsPerRemoteDc , false );
100+ }
101+
102+ /**
103+ * Creates a new DCAwareRoundRobin policy given the name of the local
104+ * datacenter and that uses the provided number of host per remote
105+ * datacenter as failover for the local hosts.
106+ * <p>
107+ * This constructor is equivalent to {@link DCAwareRoundRobinPolicy(String, int)}
108+ * but allows to override the policy of never using remote data-center
109+ * nodes for {@code LOCAL_ONE} and {@code LOCAL_QUORUM} queries. It is
110+ * however inadvisable to do so in almost all cases, as this would
111+ * potentially break consistency guarantees and if you are fine with that,
112+ * it's probably better to use a weaker consitency like {@code ONE}, {@code
113+ * TWO} or {@code THREE}. As such, this constructor should generally
114+ * be avoided in favor of {@link DCAwareRoundRobinPolicy(String, int)}.
115+ * Use it only if you know and understand what you do.
116+ *
117+ * @param localDc the name of the local datacenter (as known by
118+ * Cassandra).
119+ * @param usedHostsPerRemoteDc the number of host per remote
120+ * datacenter that policies created by the returned factory should
121+ * consider. Created policies {@code distance} method will return a
122+ * {@code HostDistance.REMOTE} distance for only {@code
123+ * usedHostsPerRemoteDc} hosts per remote datacenter. Other hosts
124+ * of the remote datacenters will be ignored (and thus no
125+ * connections to them will be maintained).
126+ * @param allowRemoteDCsForLocalConsistencyLevel whether or not the
127+ * policy may return remote host when building query plan for query
128+ * having consitency {@code LOCAL_ONE} and {@code LOCAL_QUORUM}.
129+ */
130+ public DCAwareRoundRobinPolicy (String localDc , int usedHostsPerRemoteDc , boolean allowRemoteDCsForLocalConsistencyLevel ) {
89131 this .localDc = localDc ;
90132 this .usedHostsPerRemoteDc = usedHostsPerRemoteDc ;
133+ this .dontHopForLocalCL = !allowRemoteDCsForLocalConsistencyLevel ;
91134 }
92135
93136 @ Override
@@ -158,7 +201,7 @@ public HostDistance distance(Host host) {
158201 * try first for querying, which one to use as failover, etc...
159202 */
160203 @ Override
161- public Iterator <Host > newQueryPlan (Query query ) {
204+ public Iterator <Host > newQueryPlan (final Query query ) {
162205
163206 CopyOnWriteArrayList <Host > localLiveHosts = perDcLiveHosts .get (localDc );
164207 final List <Host > hosts = localLiveHosts == null ? Collections .<Host >emptyList () : cloneList (localLiveHosts );
@@ -192,6 +235,9 @@ protected Host computeNext() {
192235 return currentDcHosts .get (c );
193236 }
194237
238+ if (dontHopForLocalCL && query .getConsistencyLevel ().isDCLocal ())
239+ return endOfData ();
240+
195241 if (remoteDcs == null ) {
196242 Set <String > copy = new HashSet <String >(perDcLiveHosts .keySet ());
197243 copy .remove (localDc );
0 commit comments