134
134
import java .util .Collections ;
135
135
import java .util .Comparator ;
136
136
import java .util .HashSet ;
137
+ import java .util .Iterator ;
137
138
import java .util .LinkedHashMap ;
138
139
import java .util .List ;
139
140
import java .util .Map ;
@@ -1387,17 +1388,17 @@ public void testVersioningCreateExistsException() throws IOException {
1387
1388
1388
1389
protected List <Engine .Operation > generateSingleDocHistory (boolean forReplica , VersionType versionType ,
1389
1390
boolean partialOldPrimary , long primaryTerm ,
1390
- int minOpCount , int maxOpCount ) {
1391
+ int minOpCount , int maxOpCount , String docId ) {
1391
1392
final int numOfOps = randomIntBetween (minOpCount , maxOpCount );
1392
1393
final List <Engine .Operation > ops = new ArrayList <>();
1393
- final Term id = newUid ("1" );
1394
+ final Term id = newUid (docId );
1394
1395
final int startWithSeqNo ;
1395
1396
if (partialOldPrimary ) {
1396
1397
startWithSeqNo = randomBoolean () ? numOfOps - 1 : randomIntBetween (0 , numOfOps - 1 );
1397
1398
} else {
1398
1399
startWithSeqNo = 0 ;
1399
1400
}
1400
- final String valuePrefix = forReplica ? "r_" : "p_" ;
1401
+ final String valuePrefix = ( forReplica ? "r_" : "p_" ) + docId + "_ " ;
1401
1402
final boolean incrementTermWhenIntroducingSeqNo = randomBoolean ();
1402
1403
for (int i = 0 ; i < numOfOps ; i ++) {
1403
1404
final Engine .Operation op ;
@@ -1419,7 +1420,7 @@ protected List<Engine.Operation> generateSingleDocHistory(boolean forReplica, Ve
1419
1420
throw new UnsupportedOperationException ("unknown version type: " + versionType );
1420
1421
}
1421
1422
if (randomBoolean ()) {
1422
- op = new Engine .Index (id , testParsedDocument ("1" , null , testDocumentWithTextField (valuePrefix + i ), B_1 , null ),
1423
+ op = new Engine .Index (id , testParsedDocument (docId , null , testDocumentWithTextField (valuePrefix + i ), B_1 , null ),
1423
1424
forReplica && i >= startWithSeqNo ? i * 2 : SequenceNumbers .UNASSIGNED_SEQ_NO ,
1424
1425
forReplica && i >= startWithSeqNo && incrementTermWhenIntroducingSeqNo ? primaryTerm + 1 : primaryTerm ,
1425
1426
version ,
@@ -1428,7 +1429,7 @@ protected List<Engine.Operation> generateSingleDocHistory(boolean forReplica, Ve
1428
1429
System .currentTimeMillis (), -1 , false
1429
1430
);
1430
1431
} else {
1431
- op = new Engine .Delete ("test" , "1" , id ,
1432
+ op = new Engine .Delete ("test" , docId , id ,
1432
1433
forReplica && i >= startWithSeqNo ? i * 2 : SequenceNumbers .UNASSIGNED_SEQ_NO ,
1433
1434
forReplica && i >= startWithSeqNo && incrementTermWhenIntroducingSeqNo ? primaryTerm + 1 : primaryTerm ,
1434
1435
version ,
@@ -1443,7 +1444,7 @@ protected List<Engine.Operation> generateSingleDocHistory(boolean forReplica, Ve
1443
1444
1444
1445
public void testOutOfOrderDocsOnReplica () throws IOException {
1445
1446
final List <Engine .Operation > ops = generateSingleDocHistory (true ,
1446
- randomFrom (VersionType .INTERNAL , VersionType .EXTERNAL , VersionType .EXTERNAL_GTE , VersionType .FORCE ), false , 2 , 2 , 20 );
1447
+ randomFrom (VersionType .INTERNAL , VersionType .EXTERNAL , VersionType .EXTERNAL_GTE , VersionType .FORCE ), false , 2 , 2 , 20 , "1" );
1447
1448
assertOpsOnReplica (ops , replicaEngine , true );
1448
1449
}
1449
1450
@@ -1460,7 +1461,8 @@ public void testOutOfOrderDocsOnReplicaOldPrimary() throws IOException {
1460
1461
try (Store oldReplicaStore = createStore ();
1461
1462
InternalEngine replicaEngine =
1462
1463
createEngine (oldSettings , oldReplicaStore , createTempDir ("translog-old-replica" ), newMergePolicy ())) {
1463
- final List <Engine .Operation > ops = generateSingleDocHistory (true , randomFrom (VersionType .INTERNAL , VersionType .EXTERNAL ), true , 2 , 2 , 20 );
1464
+ final List <Engine .Operation > ops =
1465
+ generateSingleDocHistory (true , randomFrom (VersionType .INTERNAL , VersionType .EXTERNAL ), true , 2 , 2 , 20 , "1" );
1464
1466
assertOpsOnReplica (ops , replicaEngine , true );
1465
1467
}
1466
1468
}
@@ -1530,28 +1532,83 @@ private void assertOpsOnReplica(List<Engine.Operation> ops, InternalEngine repli
1530
1532
}
1531
1533
}
1532
1534
1533
- public void testConcurrentOutOfDocsOnReplica () throws IOException , InterruptedException {
1534
- final List <Engine .Operation > ops = generateSingleDocHistory (true , randomFrom (VersionType .INTERNAL , VersionType .EXTERNAL ), false , 2 , 100 , 300 );
1535
- final Engine .Operation lastOp = ops .get (ops .size () - 1 );
1536
- final String lastFieldValue ;
1537
- if (lastOp instanceof Engine .Index ) {
1538
- Engine .Index index = (Engine .Index ) lastOp ;
1539
- lastFieldValue = index .docs ().get (0 ).get ("value" );
1535
+ public void testConcurrentOutOfOrderDocsOnReplica () throws IOException , InterruptedException {
1536
+ final List <Engine .Operation > opsDoc1 =
1537
+ generateSingleDocHistory (true , randomFrom (VersionType .INTERNAL , VersionType .EXTERNAL ), false , 2 , 100 , 300 , "1" );
1538
+ final Engine .Operation lastOpDoc1 = opsDoc1 .get (opsDoc1 .size () - 1 );
1539
+ final String lastFieldValueDoc1 ;
1540
+ if (lastOpDoc1 instanceof Engine .Index ) {
1541
+ Engine .Index index = (Engine .Index ) lastOpDoc1 ;
1542
+ lastFieldValueDoc1 = index .docs ().get (0 ).get ("value" );
1540
1543
} else {
1541
1544
// delete
1542
- lastFieldValue = null ;
1545
+ lastFieldValueDoc1 = null ;
1546
+ }
1547
+ final List <Engine .Operation > opsDoc2 =
1548
+ generateSingleDocHistory (true , randomFrom (VersionType .INTERNAL , VersionType .EXTERNAL ), false , 2 , 100 , 300 , "2" );
1549
+ final Engine .Operation lastOpDoc2 = opsDoc2 .get (opsDoc2 .size () - 1 );
1550
+ final String lastFieldValueDoc2 ;
1551
+ if (lastOpDoc2 instanceof Engine .Index ) {
1552
+ Engine .Index index = (Engine .Index ) lastOpDoc2 ;
1553
+ lastFieldValueDoc2 = index .docs ().get (0 ).get ("value" );
1554
+ } else {
1555
+ // delete
1556
+ lastFieldValueDoc2 = null ;
1543
1557
}
1544
- shuffle (ops , random ());
1545
- concurrentlyApplyOps (ops , engine );
1558
+ // randomly interleave
1559
+ final AtomicLong seqNoGenerator = new AtomicLong ();
1560
+ Function <Engine .Operation , Engine .Operation > seqNoUpdater = operation -> {
1561
+ final long newSeqNo = seqNoGenerator .getAndIncrement ();
1562
+ if (operation instanceof Engine .Index ) {
1563
+ Engine .Index index = (Engine .Index ) operation ;
1564
+ return new Engine .Index (index .uid (), index .parsedDoc (), newSeqNo , index .primaryTerm (), index .version (),
1565
+ index .versionType (), index .origin (), index .startTime (), index .getAutoGeneratedIdTimestamp (), index .isRetry ());
1566
+ } else {
1567
+ Engine .Delete delete = (Engine .Delete ) operation ;
1568
+ return new Engine .Delete (delete .type (), delete .id (), delete .uid (), newSeqNo , delete .primaryTerm (),
1569
+ delete .version (), delete .versionType (), delete .origin (), delete .startTime ());
1570
+ }
1571
+ };
1572
+ final List <Engine .Operation > allOps = new ArrayList <>();
1573
+ Iterator <Engine .Operation > iter1 = opsDoc1 .iterator ();
1574
+ Iterator <Engine .Operation > iter2 = opsDoc2 .iterator ();
1575
+ while (iter1 .hasNext () && iter2 .hasNext ()) {
1576
+ final Engine .Operation next = randomBoolean () ? iter1 .next () : iter2 .next ();
1577
+ allOps .add (seqNoUpdater .apply (next ));
1578
+ }
1579
+ iter1 .forEachRemaining (o -> allOps .add (seqNoUpdater .apply (o )));
1580
+ iter2 .forEachRemaining (o -> allOps .add (seqNoUpdater .apply (o )));
1581
+ // insert some duplicates
1582
+ allOps .addAll (randomSubsetOf (allOps ));
1546
1583
1547
- assertVisibleCount (engine , lastFieldValue == null ? 0 : 1 );
1548
- if (lastFieldValue != null ) {
1584
+ shuffle (allOps , random ());
1585
+ concurrentlyApplyOps (allOps , engine );
1586
+
1587
+ engine .refresh ("test" );
1588
+
1589
+ if (lastFieldValueDoc1 != null ) {
1549
1590
try (Searcher searcher = engine .acquireSearcher ("test" )) {
1550
1591
final TotalHitCountCollector collector = new TotalHitCountCollector ();
1551
- searcher .searcher ().search (new TermQuery (new Term ("value" , lastFieldValue )), collector );
1592
+ searcher .searcher ().search (new TermQuery (new Term ("value" , lastFieldValueDoc1 )), collector );
1593
+ assertThat (collector .getTotalHits (), equalTo (1 ));
1594
+ }
1595
+ }
1596
+ if (lastFieldValueDoc2 != null ) {
1597
+ try (Searcher searcher = engine .acquireSearcher ("test" )) {
1598
+ final TotalHitCountCollector collector = new TotalHitCountCollector ();
1599
+ searcher .searcher ().search (new TermQuery (new Term ("value" , lastFieldValueDoc2 )), collector );
1552
1600
assertThat (collector .getTotalHits (), equalTo (1 ));
1553
1601
}
1554
1602
}
1603
+
1604
+ int totalExpectedOps = 0 ;
1605
+ if (lastFieldValueDoc1 != null ) {
1606
+ totalExpectedOps ++;
1607
+ }
1608
+ if (lastFieldValueDoc2 != null ) {
1609
+ totalExpectedOps ++;
1610
+ }
1611
+ assertVisibleCount (engine , totalExpectedOps );
1555
1612
}
1556
1613
1557
1614
private void concurrentlyApplyOps (List <Engine .Operation > ops , InternalEngine engine ) throws InterruptedException {
@@ -1591,12 +1648,12 @@ private void concurrentlyApplyOps(List<Engine.Operation> ops, InternalEngine eng
1591
1648
}
1592
1649
1593
1650
public void testInternalVersioningOnPrimary () throws IOException {
1594
- final List <Engine .Operation > ops = generateSingleDocHistory (false , VersionType .INTERNAL , false , 2 , 2 , 20 );
1651
+ final List <Engine .Operation > ops = generateSingleDocHistory (false , VersionType .INTERNAL , false , 2 , 2 , 20 , "1" );
1595
1652
assertOpsOnPrimary (ops , Versions .NOT_FOUND , true , engine );
1596
1653
}
1597
1654
1598
1655
public void testVersionOnPrimaryWithConcurrentRefresh () throws Exception {
1599
- List <Engine .Operation > ops = generateSingleDocHistory (false , VersionType .INTERNAL , false , 2 , 10 , 100 );
1656
+ List <Engine .Operation > ops = generateSingleDocHistory (false , VersionType .INTERNAL , false , 2 , 10 , 100 , "1" );
1600
1657
CountDownLatch latch = new CountDownLatch (1 );
1601
1658
AtomicBoolean running = new AtomicBoolean (true );
1602
1659
Thread refreshThread = new Thread (() -> {
@@ -1716,7 +1773,7 @@ public void testNonInternalVersioningOnPrimary() throws IOException {
1716
1773
final Set <VersionType > nonInternalVersioning = new HashSet <>(Arrays .asList (VersionType .values ()));
1717
1774
nonInternalVersioning .remove (VersionType .INTERNAL );
1718
1775
final VersionType versionType = randomFrom (nonInternalVersioning );
1719
- final List <Engine .Operation > ops = generateSingleDocHistory (false , versionType , false , 2 , 2 , 20 );
1776
+ final List <Engine .Operation > ops = generateSingleDocHistory (false , versionType , false , 2 , 2 , 20 , "1" );
1720
1777
final Engine .Operation lastOp = ops .get (ops .size () - 1 );
1721
1778
final String lastFieldValue ;
1722
1779
if (lastOp instanceof Engine .Index ) {
@@ -1794,8 +1851,8 @@ public void testNonInternalVersioningOnPrimary() throws IOException {
1794
1851
}
1795
1852
1796
1853
public void testVersioningPromotedReplica () throws IOException {
1797
- final List <Engine .Operation > replicaOps = generateSingleDocHistory (true , VersionType .INTERNAL , false , 1 , 2 , 20 );
1798
- List <Engine .Operation > primaryOps = generateSingleDocHistory (false , VersionType .INTERNAL , false , 2 , 2 , 20 );
1854
+ final List <Engine .Operation > replicaOps = generateSingleDocHistory (true , VersionType .INTERNAL , false , 1 , 2 , 20 , "1" );
1855
+ List <Engine .Operation > primaryOps = generateSingleDocHistory (false , VersionType .INTERNAL , false , 2 , 2 , 20 , "1" );
1799
1856
Engine .Operation lastReplicaOp = replicaOps .get (replicaOps .size () - 1 );
1800
1857
final boolean deletedOnReplica = lastReplicaOp instanceof Engine .Delete ;
1801
1858
final long finalReplicaVersion = lastReplicaOp .version ();
@@ -1815,7 +1872,7 @@ public void testVersioningPromotedReplica() throws IOException {
1815
1872
}
1816
1873
1817
1874
public void testConcurrentExternalVersioningOnPrimary () throws IOException , InterruptedException {
1818
- final List <Engine .Operation > ops = generateSingleDocHistory (false , VersionType .EXTERNAL , false , 2 , 100 , 300 );
1875
+ final List <Engine .Operation > ops = generateSingleDocHistory (false , VersionType .EXTERNAL , false , 2 , 100 , 300 , "1" );
1819
1876
final Engine .Operation lastOp = ops .get (ops .size () - 1 );
1820
1877
final String lastFieldValue ;
1821
1878
if (lastOp instanceof Engine .Index ) {
0 commit comments