|
20 | 20 | import java.util.ArrayList; |
21 | 21 | import java.util.EnumMap; |
22 | 22 | import java.util.List; |
| 23 | +import java.util.Locale; |
23 | 24 | import java.util.Map; |
24 | 25 | import java.util.Map.Entry; |
25 | 26 | import java.util.Optional; |
@@ -939,4 +940,94 @@ static final class MergeReader { |
939 | 940 | this.hardLiveDocs = hardLiveDocs; |
940 | 941 | } |
941 | 942 | } |
| 943 | + |
| 944 | + /** |
| 945 | + * Observer for merge operations returned by {@link IndexWriter#forceMergeDeletes(boolean)}. |
| 946 | + * Provides methods to query merge status and wait for completion. |
| 947 | + * |
| 948 | + * <p>When no merges are needed, {@link #numMerges()} returns 0. In this case, {@link #await()} |
| 949 | + * returns {@code true} immediately since there is nothing to wait for. |
| 950 | + * |
| 951 | + * @lucene.experimental |
| 952 | + */ |
| 953 | + public static final class MergeObserver { |
| 954 | + private final MergePolicy.MergeSpecification spec; |
| 955 | + |
| 956 | + MergeObserver(MergePolicy.MergeSpecification spec) { |
| 957 | + this.spec = spec; |
| 958 | + } |
| 959 | + |
| 960 | + /** |
| 961 | + * Returns the number of merges in this specification. |
| 962 | + * |
| 963 | + * @return number of merges, or 0 if no merges were scheduled |
| 964 | + */ |
| 965 | + public int numMerges() { |
| 966 | + return spec == null ? 0 : spec.merges.size(); |
| 967 | + } |
| 968 | + |
| 969 | + /** |
| 970 | + * Returns the number of completed merges in this specification. Useful for tracking merge |
| 971 | + * progress: {@code numCompletedMerges() / numMerges()}. |
| 972 | + * |
| 973 | + * @return number of completed merges |
| 974 | + */ |
| 975 | + public int numCompletedMerges() { |
| 976 | + if (spec == null) { |
| 977 | + return 0; |
| 978 | + } |
| 979 | + int completed = 0; |
| 980 | + for (OneMerge merge : spec.merges) { |
| 981 | + if (merge.mergeCompleted.isDone()) { |
| 982 | + completed++; |
| 983 | + } |
| 984 | + } |
| 985 | + return completed; |
| 986 | + } |
| 987 | + |
| 988 | + /** |
| 989 | + * Waits for all merges in this specification to complete. Returns immediately if no merges were |
| 990 | + * scheduled. |
| 991 | + * |
| 992 | + * @return {@code true} if all merges completed successfully or no merges were needed, {@code |
| 993 | + * false} on error |
| 994 | + */ |
| 995 | + public boolean await() { |
| 996 | + return spec == null || spec.await(); |
| 997 | + } |
| 998 | + |
| 999 | + /** |
| 1000 | + * Waits for all merges in this specification to complete, with timeout. Returns immediately if |
| 1001 | + * no merges were scheduled. |
| 1002 | + * |
| 1003 | + * @param timeout maximum time to wait |
| 1004 | + * @param unit time unit for timeout |
| 1005 | + * @return {@code true} if all merges completed within timeout or no merges were needed, {@code |
| 1006 | + * false} on timeout or error |
| 1007 | + */ |
| 1008 | + public boolean await(long timeout, TimeUnit unit) { |
| 1009 | + return spec == null || spec.await(timeout, unit); |
| 1010 | + } |
| 1011 | + |
| 1012 | + /** |
| 1013 | + * Returns a {@link CompletableFuture} that completes when all merges finish. Returns an |
| 1014 | + * already-completed future if no merges were scheduled. |
| 1015 | + * |
| 1016 | + * @return future that completes when merges finish |
| 1017 | + */ |
| 1018 | + public CompletableFuture<Void> awaitAsync() { |
| 1019 | + return spec == null |
| 1020 | + ? CompletableFuture.completedFuture(null) |
| 1021 | + : spec.getMergeCompletedFutures(); |
| 1022 | + } |
| 1023 | + |
| 1024 | + @Override |
| 1025 | + public String toString() { |
| 1026 | + if (spec == null) { |
| 1027 | + return "MergeObserver: no merges"; |
| 1028 | + } |
| 1029 | + return String.format( |
| 1030 | + Locale.ROOT, "MergeObserver: %d merges\n%s", numMerges(), spec.toString()); |
| 1031 | + } |
| 1032 | + } |
942 | 1033 | } |
0 commit comments