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.master.procedure;
019
020import static org.junit.Assert.assertEquals;
021
022import java.io.IOException;
023
024import org.apache.hadoop.conf.Configuration;
025import org.apache.hadoop.fs.Path;
026import org.apache.hadoop.hbase.HBaseClassTestRule;
027import org.apache.hadoop.hbase.HBaseTestingUtility;
028import org.apache.hadoop.hbase.TableName;
029import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
030import org.apache.hadoop.hbase.client.RegionInfo;
031import org.apache.hadoop.hbase.client.RegionInfoBuilder;
032import org.apache.hadoop.hbase.client.TableDescriptor;
033import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
034import org.apache.hadoop.hbase.master.HMaster;
035import org.apache.hadoop.hbase.procedure2.Procedure;
036import org.apache.hadoop.hbase.procedure2.ProcedureEvent;
037import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
038import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
039import org.apache.hadoop.hbase.procedure2.store.wal.WALProcedureStore;
040import org.apache.hadoop.hbase.testclassification.MasterTests;
041import org.apache.hadoop.hbase.testclassification.MediumTests;
042import org.apache.hadoop.hbase.util.CommonFSUtils;
043import org.junit.After;
044import org.junit.AfterClass;
045import org.junit.BeforeClass;
046import org.junit.ClassRule;
047import org.junit.Rule;
048import org.junit.Test;
049import org.junit.experimental.categories.Category;
050import org.junit.rules.TestName;
051import org.slf4j.Logger;
052import org.slf4j.LoggerFactory;
053
054@Category({MasterTests.class, MediumTests.class})
055public class TestMasterProcedureEvents {
056
057  @ClassRule
058  public static final HBaseClassTestRule CLASS_RULE =
059      HBaseClassTestRule.forClass(TestMasterProcedureEvents.class);
060
061  private static final Logger LOG = LoggerFactory.getLogger(TestCreateTableProcedure.class);
062
063  protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
064
065  @Rule
066  public TestName name = new TestName();
067
068  private static void setupConf(Configuration conf) throws IOException {
069    conf.setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 1);
070    conf.setBoolean(WALProcedureStore.USE_HSYNC_CONF_KEY, false);
071  }
072
073  @BeforeClass
074  public static void setupCluster() throws Exception {
075    Configuration conf = UTIL.getConfiguration();
076    setupConf(UTIL.getConfiguration());
077    UTIL.startMiniDFSCluster(3);
078    CommonFSUtils.setWALRootDir(conf, new Path(conf.get("fs.defaultFS"), "/tmp/wal"));
079    UTIL.startMiniCluster(2);
080    UTIL.waitUntilNoRegionsInTransition();
081  }
082
083  @AfterClass
084  public static void cleanupTest() throws Exception {
085    try {
086      UTIL.shutdownMiniCluster();
087    } catch (Exception e) {
088      LOG.warn("failure shutting down cluster", e);
089    }
090  }
091
092  @After
093  public void tearDown() throws Exception {
094    for (TableDescriptor htd: UTIL.getAdmin().listTableDescriptors()) {
095      LOG.info("Tear down, remove table=" + htd.getTableName());
096      UTIL.deleteTable(htd.getTableName());
097    }
098  }
099
100  @Test
101  public void testMasterInitializedEvent() throws Exception {
102    final TableName tableName = TableName.valueOf(name.getMethodName());
103    HMaster master = UTIL.getMiniHBaseCluster().getMaster();
104    ProcedureExecutor<MasterProcedureEnv> procExec = master.getMasterProcedureExecutor();
105
106    RegionInfo hri = RegionInfoBuilder.newBuilder(tableName).build();
107    TableDescriptor htd = TableDescriptorBuilder.newBuilder(tableName)
108      .setColumnFamily(ColumnFamilyDescriptorBuilder.of("f")).build();
109
110    while (!master.isInitialized()) {
111      Thread.sleep(250);
112    }
113    master.setInitialized(false); // fake it, set back later
114
115    // check event wait/wake
116    testProcedureEventWaitWake(master, master.getInitializedEvent(),
117      new CreateTableProcedure(procExec.getEnvironment(), htd, new RegionInfo[] { hri }));
118  }
119
120  private void testProcedureEventWaitWake(final HMaster master, final ProcedureEvent<?> event,
121      final Procedure<MasterProcedureEnv> proc) throws Exception {
122    final ProcedureExecutor<MasterProcedureEnv> procExec = master.getMasterProcedureExecutor();
123    final MasterProcedureScheduler procSched = procExec.getEnvironment().getProcedureScheduler();
124
125    final long startPollCalls = procSched.getPollCalls();
126    final long startNullPollCalls = procSched.getNullPollCalls();
127
128    // check that nothing is in the event queue
129    LOG.debug("checking " + event);
130    assertEquals(false, event.isReady());
131    assertEquals(0, event.getSuspendedProcedures().size());
132
133    // submit the procedure
134    LOG.debug("submit " + proc);
135    long procId = procExec.submitProcedure(proc);
136
137    // wait until the event is in the queue (proc executed and got into suspended state)
138    LOG.debug("wait procedure suspended on " + event);
139    while (event.getSuspendedProcedures().size() < 1) Thread.sleep(25);
140
141    // check that the proc is in the event queue
142    LOG.debug("checking " + event + " size=" + event.getSuspendedProcedures().size());
143    assertEquals(false, event.isReady());
144    assertEquals(1, event.getSuspendedProcedures().size());
145
146    // wake the event
147    LOG.debug("wake " + event);
148    event.wake(procSched);
149    assertEquals(true, event.isReady());
150
151    // wait until proc completes
152    LOG.debug("waiting " + proc);
153    ProcedureTestingUtility.waitProcedure(procExec, procId);
154
155    // check that nothing is in the event queue and the event is not suspended
156    assertEquals(true, event.isReady());
157    assertEquals(0, event.getSuspendedProcedures().size());
158    LOG.debug("completed execution of " + proc +
159      " pollCalls=" + (procSched.getPollCalls() - startPollCalls) +
160      " nullPollCalls=" + (procSched.getNullPollCalls() - startNullPollCalls));
161  }
162}