@@ -186,7 +186,7 @@ static void assureSufficientLiveReplicas(Locator locator, AbstractReplicationStr
186
186
total += dcCount .allReplicas ();
187
187
}
188
188
if (totalFull < blockForFullReplicas )
189
- throw UnavailableException .create (consistencyLevel , blockFor , total , blockForFullReplicas , totalFull );
189
+ throw UnavailableException .create (consistencyLevel , blockFor , blockForFullReplicas , total , totalFull );
190
190
break ;
191
191
}
192
192
// Fallthough on purpose for SimpleStrategy
@@ -812,7 +812,8 @@ private static <E extends Endpoints<E>> E contactForEachQuorumRead(Locator locat
812
812
});
813
813
}
814
814
815
- private static <E extends Endpoints <E >> E contactForRead (Locator locator , AbstractReplicationStrategy replicationStrategy , ConsistencyLevel consistencyLevel , boolean alwaysSpeculate , E candidates )
815
+ @ VisibleForTesting
816
+ public static <E extends Endpoints <E >> E contactForRead (Locator locator , AbstractReplicationStrategy replicationStrategy , ConsistencyLevel consistencyLevel , boolean alwaysSpeculate , E candidates )
816
817
{
817
818
/*
818
819
* If we are doing an each quorum query, we have to make sure that the endpoints we select
@@ -823,13 +824,45 @@ private static <E extends Endpoints<E>> E contactForRead(Locator locator, Abstra
823
824
*
824
825
* TODO: this is still very inconistently managed between {LOCAL,EACH}_QUORUM and other consistency levels - should address this in a follow-up
825
826
*/
827
+ candidates = reorderWithOneFullReplicaFirst (candidates );
826
828
if (consistencyLevel == EACH_QUORUM && replicationStrategy instanceof NetworkTopologyStrategy )
827
829
return contactForEachQuorumRead (locator , (NetworkTopologyStrategy ) replicationStrategy , candidates );
828
830
829
831
int count = consistencyLevel .blockFor (replicationStrategy ) + (alwaysSpeculate ? 1 : 0 );
830
832
return candidates .subList (0 , Math .min (count , candidates .size ()));
831
833
}
832
834
835
+ /**
836
+ * Reorders the provided list of replicas such that, if any transient replicas are present,
837
+ * a single full replica (if available) is placed first. The remaining replicas retain their original order(order by NodeProximity),
838
+ *
839
+ * @param endpoints the original set of replicas
840
+ * @param <E> a subtype of Endpoints
841
+ * @return the same set if there are no transient replicas or no full replica is found,
842
+ * otherwise a reordered set with the first full replica placed first
843
+ */
844
+ private static <E extends Endpoints <E >> E reorderWithOneFullReplicaFirst (E endpoints ) {
845
+ boolean hasTransient = false ;
846
+ Replica firstFull = null ;
847
+
848
+ for (Replica r : endpoints ) {
849
+ if (r .isTransient ()) hasTransient = true ;
850
+ if (firstFull == null && r .isFull ()) firstFull = r ;
851
+ }
852
+
853
+ if (!hasTransient || firstFull == null )
854
+ return endpoints ;
855
+
856
+ ReplicaCollection .Builder <E > builder = endpoints .newBuilder (endpoints .size ());
857
+ builder .add (firstFull );
858
+ for (Replica r : endpoints ) {
859
+ if (!r .equals (firstFull )) {
860
+ builder .add (r );
861
+ }
862
+ }
863
+
864
+ return builder .build ();
865
+ }
833
866
834
867
/**
835
868
* Construct a plan for reading from a single node - this permits no speculation or read-repair
0 commit comments