|
30 | 30 | import java.util.UUID; |
31 | 31 | import java.util.concurrent.CompletableFuture; |
32 | 32 | import java.util.concurrent.ConcurrentLinkedQueue; |
33 | | -import java.util.concurrent.CountDownLatch; |
34 | 33 | import java.util.concurrent.LinkedBlockingQueue; |
35 | 34 | import java.util.concurrent.ThreadPoolExecutor; |
36 | 35 | import java.util.concurrent.TimeUnit; |
37 | | -import java.util.concurrent.atomic.AtomicReference; |
38 | 36 | import java.util.concurrent.locks.Lock; |
39 | 37 | import org.apache.ignite.internal.failure.FailureContext; |
40 | 38 | import org.apache.ignite.internal.failure.FailureManager; |
@@ -94,8 +92,10 @@ public class Compactor extends IgniteWorker { |
94 | 92 |
|
95 | 93 | private final PartitionDestructionLockManager partitionDestructionLockManager; |
96 | 94 |
|
97 | | - /** Latch for pausing and resuming the compaction, {@code null} if there was no pause. */ |
98 | | - private final AtomicReference<CountDownLatch> pauseLatchRef = new AtomicReference<>(); |
| 95 | + private final Object pauseMux = new Object(); |
| 96 | + |
| 97 | + /** Guarded by {@link #pauseMux}. */ |
| 98 | + private boolean paused; |
99 | 99 |
|
100 | 100 | /** |
101 | 101 | * Creates new ignite worker with given parameters. |
@@ -506,40 +506,46 @@ private DeltaFileForCompaction( |
506 | 506 | * in parallel and subsequent calls will strictly be calls after {@link #resume}. |
507 | 507 | */ |
508 | 508 | public void pause() { |
509 | | - boolean casResult = pauseLatchRef.compareAndSet(null, new CountDownLatch(1)); |
| 509 | + synchronized (pauseMux) { |
| 510 | + assert !paused : "It is expected that a further pause will only occur after resume"; |
510 | 511 |
|
511 | | - assert casResult : "It is expected that there will be no parallel pause, resume or previous one has ended: " + pauseLatchRef.get(); |
| 512 | + paused = true; |
| 513 | + } |
512 | 514 | } |
513 | 515 |
|
514 | 516 | /** Resumes the compactor if it was paused. It is expected that this method will not be called multiple times in parallel. */ |
515 | 517 | public void resume() { |
516 | | - CountDownLatch latch = pauseLatchRef.get(); |
517 | | - |
518 | | - boolean casResult = pauseLatchRef.compareAndSet(latch, null); |
| 518 | + synchronized (pauseMux) { |
| 519 | + if (paused) { |
| 520 | + paused = false; |
519 | 521 |
|
520 | | - assert casResult : "It is expected that there will be no parallel pause or resume"; |
521 | | - |
522 | | - if (latch != null) { |
523 | | - latch.countDown(); |
| 522 | + pauseMux.notifyAll(); |
| 523 | + } |
524 | 524 | } |
525 | 525 | } |
526 | 526 |
|
527 | 527 | /** Must be called before each IO operation to provide other IO components with resources. */ |
528 | 528 | private void pauseCompactionIfNeeded() { |
529 | | - CountDownLatch latch = pauseLatchRef.get(); |
| 529 | + boolean interrupted = false; |
530 | 530 |
|
531 | | - if (latch != null) { |
532 | | - blockingSectionBegin(); |
| 531 | + synchronized (pauseMux) { |
| 532 | + while (paused) { |
| 533 | + blockingSectionBegin(); |
533 | 534 |
|
534 | | - try { |
535 | | - latch.await(); |
536 | | - } catch (InterruptedException e) { |
537 | | - LOG.debug("Compactor pause was interrupted", e); |
| 535 | + try { |
| 536 | + pauseMux.wait(); |
| 537 | + } catch (InterruptedException e) { |
| 538 | + LOG.debug("Compactor pause was interrupted", e); |
538 | 539 |
|
539 | | - Thread.currentThread().interrupt(); |
540 | | - } finally { |
541 | | - blockingSectionEnd(); |
| 540 | + interrupted = true; |
| 541 | + } finally { |
| 542 | + blockingSectionEnd(); |
| 543 | + } |
542 | 544 | } |
543 | 545 | } |
| 546 | + |
| 547 | + if (interrupted) { |
| 548 | + Thread.currentThread().interrupt(); |
| 549 | + } |
544 | 550 | } |
545 | 551 | } |
0 commit comments