|
10 | 10 | */
|
11 | 11 | public class MultiTenantMergeScheduler extends MergeScheduler {
|
12 | 12 |
|
13 |
| - // Shared global thread pool with lazy initialization |
14 |
| - private static class LazyHolder { |
15 |
| - static final ExecutorService MERGE_THREAD_POOL = |
16 |
| - Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() / 2); |
17 |
| - } |
| 13 | + // Shared global thread pool |
| 14 | + private static final ExecutorService MERGE_THREAD_POOL = Executors.newFixedThreadPool( |
| 15 | + Runtime.getRuntime().availableProcessors() / 2 |
| 16 | + ); |
18 | 17 |
|
19 |
| - // Use getMergeThreadPool() instead of direct access |
| 18 | + // Track active merges per writer |
| 19 | + private final List<Future<?>> activeMerges = Collections.synchronizedList(new ArrayList<>()); |
20 | 20 |
|
21 | 21 | @Override
|
22 | 22 | public void merge(MergeScheduler.MergeSource mergeSource, MergeTrigger trigger) throws IOException {
|
23 |
| - while (mergeSource.hasPendingMerges()) { // Use hasPendingMerges() instead of relying on null check |
| 23 | + while (true) { |
24 | 24 | MergePolicy.OneMerge merge = mergeSource.getNextMerge();
|
25 |
| - if (merge == null) { |
26 |
| - break; // Explicitly exit if no merge is available |
27 |
| - } |
| 25 | + if (merge == null) break; // No more merges |
28 | 26 |
|
29 |
| - // Submit merge task to the shared thread pool |
30 |
| - MERGE_THREAD_POOL.submit(() -> { |
| 27 | + // Submit merge task and track future |
| 28 | + Future<?> future = MERGE_THREAD_POOL.submit(() -> { |
31 | 29 | try {
|
32 | 30 | mergeSource.merge(merge);
|
33 | 31 | } catch (IOException e) {
|
34 | 32 | throw new RuntimeException("Merge operation failed", e);
|
35 | 33 | }
|
36 | 34 | });
|
37 | 35 |
|
| 36 | + activeMerges.add(future); |
| 37 | + |
38 | 38 | // Cleanup completed merges
|
39 | 39 | activeMerges.removeIf(Future::isDone);
|
40 | 40 | }
|
41 | 41 | }
|
42 | 42 |
|
| 43 | + private final ConcurrentHashMap<IndexWriter, List<Merge>> activeMerges = new ConcurrentHashMap<>(); |
| 44 | + |
43 | 45 | @Override
|
44 | 46 | public void close() throws IOException {
|
45 |
| - // Wait for all running merges to complete |
46 |
| - for (Future<?> future : activeMerges) { |
47 |
| - try { |
48 |
| - future.get(); // Wait for completion |
49 |
| - } catch (Exception e) { |
50 |
| - throw new IOException("Error while waiting for merges to finish", e); |
51 |
| - } |
| 47 | + IndexWriter currentWriter = getCurrentIndexWriter(); // Method to get the calling writer |
| 48 | + List<Merge> merges = activeMerges.getOrDefault(currentWriter, Collections.emptyList()); |
| 49 | + |
| 50 | + for (Merge merge : merges) { |
| 51 | + merge.waitForCompletion(); // Only wait for merges related to this writer |
52 | 52 | }
|
53 |
| - activeMerges.clear(); |
| 53 | + |
| 54 | + activeMerges.remove(currentWriter); // Cleanup after closing |
54 | 55 | }
|
| 56 | + |
55 | 57 |
|
56 | 58 | // Providing a method to shut down the global thread pool gracefully
|
57 | 59 | public static void shutdownThreadPool() {
|
|
0 commit comments