21
21
22
22
import org .apache .http .Header ;
23
23
import org .apache .http .HttpHost ;
24
+ import org .apache .http .client .AuthCache ;
25
+ import org .apache .http .impl .auth .BasicScheme ;
26
+ import org .apache .http .impl .client .BasicAuthCache ;
24
27
import org .apache .http .impl .nio .client .CloseableHttpAsyncClient ;
25
28
import org .elasticsearch .client .DeadHostStateTests .ConfigurableTimeSupplier ;
26
29
import org .elasticsearch .client .RestClient .NodeTuple ;
35
38
import java .util .List ;
36
39
import java .util .Map ;
37
40
import java .util .concurrent .CountDownLatch ;
38
- import java .util .concurrent .atomic .AtomicInteger ;
39
41
import java .util .concurrent .TimeUnit ;
42
+ import java .util .concurrent .atomic .AtomicInteger ;
40
43
41
44
import static java .util .Collections .singletonList ;
42
45
import static org .elasticsearch .client .RestClientTestUtil .getHttpMethods ;
43
46
import static org .hamcrest .Matchers .instanceOf ;
44
47
import static org .junit .Assert .assertEquals ;
48
+ import static org .junit .Assert .assertSame ;
45
49
import static org .junit .Assert .assertThat ;
46
50
import static org .junit .Assert .assertTrue ;
47
51
import static org .junit .Assert .fail ;
@@ -407,8 +411,8 @@ public String toString() {
407
411
* blacklist time. It'll revive the node that is closest
408
412
* to being revived that the NodeSelector is ok with.
409
413
*/
410
- assertEquals (singletonList (n1 ), RestClient .selectHosts (nodeTuple , blacklist , new AtomicInteger (), NodeSelector .ANY ));
411
- assertEquals (singletonList (n2 ), RestClient .selectHosts (nodeTuple , blacklist , new AtomicInteger (), not1 ));
414
+ assertEquals (singletonList (n1 ), RestClient .selectNodes (nodeTuple , blacklist , new AtomicInteger (), NodeSelector .ANY ));
415
+ assertEquals (singletonList (n2 ), RestClient .selectNodes (nodeTuple , blacklist , new AtomicInteger (), not1 ));
412
416
413
417
/*
414
418
* Try a NodeSelector that excludes all nodes. This should
@@ -449,23 +453,23 @@ private void assertSelectLivingHosts(List<Node> expectedNodes, NodeTuple<List<No
449
453
Map <HttpHost , DeadHostState > blacklist , NodeSelector nodeSelector ) throws IOException {
450
454
int iterations = 1000 ;
451
455
AtomicInteger lastNodeIndex = new AtomicInteger (0 );
452
- assertEquals (expectedNodes , RestClient .selectHosts (nodeTuple , blacklist , lastNodeIndex , nodeSelector ));
456
+ assertEquals (expectedNodes , RestClient .selectNodes (nodeTuple , blacklist , lastNodeIndex , nodeSelector ));
453
457
// Calling it again rotates the set of results
454
458
for (int i = 1 ; i < iterations ; i ++) {
455
459
Collections .rotate (expectedNodes , 1 );
456
460
assertEquals ("iteration " + i , expectedNodes ,
457
- RestClient .selectHosts (nodeTuple , blacklist , lastNodeIndex , nodeSelector ));
461
+ RestClient .selectNodes (nodeTuple , blacklist , lastNodeIndex , nodeSelector ));
458
462
}
459
463
}
460
464
461
465
/**
462
- * Assert that {@link RestClient#selectHosts } fails on the provided arguments.
466
+ * Assert that {@link RestClient#selectNodes } fails on the provided arguments.
463
467
* @return the message in the exception thrown by the failure
464
468
*/
465
- private String assertSelectAllRejected ( NodeTuple <List <Node >> nodeTuple ,
469
+ private static String assertSelectAllRejected ( NodeTuple <List <Node >> nodeTuple ,
466
470
Map <HttpHost , DeadHostState > blacklist , NodeSelector nodeSelector ) {
467
471
try {
468
- RestClient .selectHosts (nodeTuple , blacklist , new AtomicInteger (0 ), nodeSelector );
472
+ RestClient .selectNodes (nodeTuple , blacklist , new AtomicInteger (0 ), nodeSelector );
469
473
throw new AssertionError ("expected selectHosts to fail" );
470
474
} catch (IOException e ) {
471
475
return e .getMessage ();
@@ -478,5 +482,56 @@ private static RestClient createRestClient() {
478
482
new Header [] {}, nodes , null , null , null );
479
483
}
480
484
485
+ public void testRoundRobin () throws IOException {
486
+ int numNodes = randomIntBetween (2 , 10 );
487
+ AuthCache authCache = new BasicAuthCache ();
488
+ List <Node > nodes = new ArrayList <>(numNodes );
489
+ for (int i = 0 ; i < numNodes ; i ++) {
490
+ Node node = new Node (new HttpHost ("localhost" , 9200 + i ));
491
+ nodes .add (node );
492
+ authCache .put (node .getHost (), new BasicScheme ());
493
+ }
494
+ NodeTuple <List <Node >> nodeTuple = new NodeTuple <>(nodes , authCache );
495
+
496
+ //test the transition from negative to positive values
497
+ AtomicInteger lastNodeIndex = new AtomicInteger (-numNodes );
498
+ assertNodes (nodeTuple , lastNodeIndex , 50 );
499
+ assertEquals (-numNodes + 50 , lastNodeIndex .get ());
500
+
501
+ //test the highest positive values up to MAX_VALUE
502
+ lastNodeIndex .set (Integer .MAX_VALUE - numNodes * 10 );
503
+ assertNodes (nodeTuple , lastNodeIndex , numNodes * 10 );
504
+ assertEquals (Integer .MAX_VALUE , lastNodeIndex .get ());
505
+
506
+ //test the transition from MAX_VALUE to MIN_VALUE
507
+ //this is the only time where there is most likely going to be a jump from a node
508
+ //to another one that's not necessarily the next one.
509
+ assertEquals (Integer .MIN_VALUE , lastNodeIndex .incrementAndGet ());
510
+ assertNodes (nodeTuple , lastNodeIndex , 50 );
511
+ assertEquals (Integer .MIN_VALUE + 50 , lastNodeIndex .get ());
512
+ }
481
513
514
+ private static void assertNodes (NodeTuple <List <Node >> nodeTuple , AtomicInteger lastNodeIndex , int runs ) throws IOException {
515
+ int distance = lastNodeIndex .get () % nodeTuple .nodes .size ();
516
+ /*
517
+ * Collections.rotate is not super intuitive: distance 1 means that the last element will become the first and so on,
518
+ * while distance -1 means that the second element will become the first and so on.
519
+ */
520
+ int expectedOffset = distance > 0 ? nodeTuple .nodes .size () - distance : Math .abs (distance );
521
+ for (int i = 0 ; i < runs ; i ++) {
522
+ Iterable <Node > selectedNodes = RestClient .selectNodes (nodeTuple , Collections .<HttpHost , DeadHostState >emptyMap (),
523
+ lastNodeIndex , NodeSelector .ANY );
524
+ List <Node > expectedNodes = nodeTuple .nodes ;
525
+ int index = 0 ;
526
+ for (Node actualNode : selectedNodes ) {
527
+ Node expectedNode = expectedNodes .get ((index + expectedOffset ) % expectedNodes .size ());
528
+ assertSame (expectedNode , actualNode );
529
+ index ++;
530
+ }
531
+ expectedOffset --;
532
+ if (expectedOffset < 0 ) {
533
+ expectedOffset += nodeTuple .nodes .size ();
534
+ }
535
+ }
536
+ }
482
537
}
0 commit comments