|
114 | 114 | import org.elasticsearch.index.mapper.SourceFieldMapper; |
115 | 115 | import org.elasticsearch.index.mapper.Uid; |
116 | 116 | import org.elasticsearch.index.mapper.VersionFieldMapper; |
| 117 | +import org.elasticsearch.index.merge.OnGoingMerge; |
117 | 118 | import org.elasticsearch.index.seqno.LocalCheckpointTracker; |
118 | 119 | import org.elasticsearch.index.seqno.ReplicationTracker; |
119 | 120 | import org.elasticsearch.index.seqno.RetentionLease; |
@@ -2639,6 +2640,85 @@ public void testMergeThreadLogging() throws Exception { |
2639 | 2640 | } |
2640 | 2641 | } |
2641 | 2642 |
|
| 2643 | + public void testMergeEstimatesMemorySize() throws Exception { |
| 2644 | + |
| 2645 | + try (Store store = createStore()) { |
| 2646 | + LogMergePolicy lmp = newLogMergePolicy(); |
| 2647 | + lmp.setMergeFactor(2); |
| 2648 | + |
| 2649 | + EngineConfig config = config(defaultSettings, store, createTempDir(), lmp, null); |
| 2650 | + |
| 2651 | + store.createEmpty(); |
| 2652 | + final String translogUuid = Translog.createEmptyTranslog( |
| 2653 | + config.getTranslogConfig().getTranslogPath(), |
| 2654 | + SequenceNumbers.NO_OPS_PERFORMED, |
| 2655 | + shardId, |
| 2656 | + primaryTerm.get() |
| 2657 | + ); |
| 2658 | + store.associateIndexWithNewTranslog(translogUuid); |
| 2659 | + |
| 2660 | + AtomicInteger estimatedMerges = new AtomicInteger(); |
| 2661 | + AtomicInteger actualMerges = new AtomicInteger(); |
| 2662 | + Set<Long> estimatedMemorySizes = Collections.synchronizedSet(new HashSet<>()); |
| 2663 | + |
| 2664 | + InternalEngine engine = new InternalTestEngine(config) { |
| 2665 | + @Override |
| 2666 | + protected IndexWriter createWriter(Directory directory, IndexWriterConfig iwc) throws IOException { |
| 2667 | + return new IndexWriter(directory, iwc) { |
| 2668 | + @Override |
| 2669 | + public void merge(MergePolicy.OneMerge merge) throws IOException { |
| 2670 | + actualMerges.addAndGet(1); |
| 2671 | + super.merge(merge); |
| 2672 | + } |
| 2673 | + }; |
| 2674 | + } |
| 2675 | + |
| 2676 | + @Override |
| 2677 | + protected ElasticsearchMergeScheduler createMergeScheduler(ShardId shardId, IndexSettings indexSettings) { |
| 2678 | + return new ElasticsearchConcurrentMergeScheduler(shardId, indexSettings) { |
| 2679 | + @Override |
| 2680 | + protected long estimateMergeMemory(MergePolicy.OneMerge merge) { |
| 2681 | + // Estimate merge memory randomly, and record the estimated merges and memory sizes for later comparison |
| 2682 | + long estimation = randomLongBetween(1, 100000000L); |
| 2683 | + estimatedMerges.addAndGet(1); |
| 2684 | + estimatedMemorySizes.add(estimation); |
| 2685 | + return estimation; |
| 2686 | + } |
| 2687 | + |
| 2688 | + @Override |
| 2689 | + protected void beforeMerge(OnGoingMerge merge) { |
| 2690 | + // Checks the estimation is available before merging, and that it has been done previously |
| 2691 | + assertThat(merge.getMemoryBytesNeeded(), Matchers.greaterThan(0L)); |
| 2692 | + assertTrue(estimatedMemorySizes.remove(merge.getMemoryBytesNeeded())); |
| 2693 | + } |
| 2694 | + |
| 2695 | + @Override |
| 2696 | + protected void afterMerge(OnGoingMerge merge) {} |
| 2697 | + }; |
| 2698 | + } |
| 2699 | + }; |
| 2700 | + recoverFromTranslog(engine, translogHandler, Long.MAX_VALUE); |
| 2701 | + |
| 2702 | + int numDocs = randomIntBetween(10, 100); |
| 2703 | + for (int i = 0; i < numDocs; i++) { |
| 2704 | + engine.index(indexForDoc(testParsedDocument(randomIdentifier(), null, testDocument(), B_1, null))); |
| 2705 | + if (randomBoolean()) { |
| 2706 | + engine.flush(); |
| 2707 | + engine.forceMerge(true, 1, false, UUIDs.randomBase64UUID()); |
| 2708 | + } |
| 2709 | + } |
| 2710 | + |
| 2711 | + assertBusy(() -> { |
| 2712 | + // All scheduled merges have been done |
| 2713 | + assertThat(estimatedMerges.get(), is(actualMerges.get())); |
| 2714 | + // All estimations have been accounted for |
| 2715 | + assertTrue(estimatedMemorySizes.isEmpty()); |
| 2716 | + }); |
| 2717 | + |
| 2718 | + engine.close(); |
| 2719 | + } |
| 2720 | + } |
| 2721 | + |
2642 | 2722 | public void testSeqNoAndCheckpoints() throws IOException, InterruptedException { |
2643 | 2723 | final int opCount = randomIntBetween(1, 256); |
2644 | 2724 | long primarySeqNo = SequenceNumbers.NO_OPS_PERFORMED; |
|
0 commit comments