001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.procedure2;
019
020import static org.junit.jupiter.api.Assertions.assertFalse;
021import static org.junit.jupiter.api.Assertions.assertTrue;
022
023import java.io.IOException;
024import java.util.concurrent.CountDownLatch;
025import java.util.concurrent.TimeUnit;
026import org.apache.hadoop.hbase.HBaseCommonTestingUtil;
027import org.apache.hadoop.hbase.procedure2.store.NoopProcedureStore;
028import org.apache.hadoop.hbase.testclassification.MasterTests;
029import org.apache.hadoop.hbase.testclassification.SmallTests;
030import org.junit.jupiter.api.AfterEach;
031import org.junit.jupiter.api.BeforeEach;
032import org.junit.jupiter.api.Tag;
033import org.junit.jupiter.api.Test;
034import org.slf4j.Logger;
035import org.slf4j.LoggerFactory;
036
037@Tag(MasterTests.TAG)
038@Tag(SmallTests.TAG)
039public class TestProcedureInMemoryChore {
040
041  private static final Logger LOG = LoggerFactory.getLogger(TestProcedureInMemoryChore.class);
042
043  private static final int PROCEDURE_EXECUTOR_SLOTS = 1;
044
045  private TestProcEnv procEnv;
046  private NoopProcedureStore procStore;
047  private ProcedureExecutor<TestProcEnv> procExecutor;
048
049  private HBaseCommonTestingUtil htu;
050
051  @BeforeEach
052  public void setUp() throws IOException {
053    htu = new HBaseCommonTestingUtil();
054
055    procEnv = new TestProcEnv();
056    procStore = new NoopProcedureStore();
057    procExecutor = new ProcedureExecutor<>(htu.getConfiguration(), procEnv, procStore);
058    procExecutor.testing = new ProcedureExecutor.Testing();
059    procStore.start(PROCEDURE_EXECUTOR_SLOTS);
060    ProcedureTestingUtility.initAndStartWorkers(procExecutor, PROCEDURE_EXECUTOR_SLOTS, true);
061  }
062
063  @AfterEach
064  public void tearDown() throws IOException {
065    procExecutor.stop();
066    procStore.stop(false);
067  }
068
069  @Test
070  public void testChoreAddAndRemove() throws Exception {
071    final int timeoutMSec = 50;
072    final int nCountDown = 5;
073
074    // submit the chore and wait for execution
075    CountDownLatch latch = new CountDownLatch(nCountDown);
076    TestLatchChore chore = new TestLatchChore(timeoutMSec, latch);
077    procExecutor.addChore(chore);
078    assertTrue(chore.isWaiting());
079    latch.await();
080
081    // remove the chore and verify it is no longer executed
082    assertTrue(chore.isWaiting());
083    procExecutor.removeChore(chore);
084    latch = new CountDownLatch(nCountDown);
085    chore.setLatch(latch);
086    latch.await(timeoutMSec * nCountDown, TimeUnit.MILLISECONDS);
087    LOG.info("chore latch count={}", latch.getCount());
088    assertFalse(chore.isWaiting());
089    assertTrue(latch.getCount() > 0, "latchCount=" + latch.getCount());
090  }
091
092  public static class TestLatchChore extends ProcedureInMemoryChore<TestProcEnv> {
093    private CountDownLatch latch;
094
095    public TestLatchChore(final int timeoutMSec, final CountDownLatch latch) {
096      super(timeoutMSec);
097      setLatch(latch);
098    }
099
100    public void setLatch(final CountDownLatch latch) {
101      this.latch = latch;
102    }
103
104    @Override
105    protected void periodicExecute(final TestProcEnv env) {
106      LOG.info("periodic execute {}", this);
107      latch.countDown();
108    }
109  }
110
111  private static class TestProcEnv {
112  }
113}