View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.master.procedure;
20  
21  import java.io.IOException;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.conf.Configuration;
26  import org.apache.hadoop.hbase.HBaseTestingUtility;
27  import org.apache.hadoop.hbase.HConstants;
28  import org.apache.hadoop.hbase.HRegionInfo;
29  import org.apache.hadoop.hbase.HTableDescriptor;
30  import org.apache.hadoop.hbase.HColumnDescriptor;
31  import org.apache.hadoop.hbase.TableName;
32  import org.apache.hadoop.hbase.client.Table;
33  import org.apache.hadoop.hbase.master.HMaster;
34  import org.apache.hadoop.hbase.master.AssignmentManager;
35  import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
36  import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
37  import org.apache.hadoop.hbase.regionserver.HRegionServer;
38  import org.apache.hadoop.hbase.testclassification.MasterTests;
39  import org.apache.hadoop.hbase.testclassification.MediumTests;
40  import org.junit.After;
41  import org.junit.AfterClass;
42  import org.junit.Before;
43  import org.junit.BeforeClass;
44  import org.junit.Test;
45  import org.junit.experimental.categories.Category;
46  
47  import static org.junit.Assert.assertEquals;
48  import static org.junit.Assert.assertTrue;
49  
50  @Category({MasterTests.class, MediumTests.class})
51  public class TestMasterProcedureEvents {
52    private static final Log LOG = LogFactory.getLog(TestCreateTableProcedure.class);
53  
54    protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
55  
56    private static long nonceGroup = HConstants.NO_NONCE;
57    private static long nonce = HConstants.NO_NONCE;
58  
59    private static void setupConf(Configuration conf) {
60      conf.setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 8);
61      conf.setBoolean("hbase.procedure.store.wal.use.hsync", false);
62    }
63  
64    @BeforeClass
65    public static void setupCluster() throws Exception {
66      setupConf(UTIL.getConfiguration());
67      UTIL.startMiniCluster(3);
68    }
69  
70    @AfterClass
71    public static void cleanupTest() throws Exception {
72      try {
73        UTIL.shutdownMiniCluster();
74      } catch (Exception e) {
75        LOG.warn("failure shutting down cluster", e);
76      }
77    }
78  
79    @Test
80    public void testMasterInitializedEvent() throws Exception {
81      TableName tableName = TableName.valueOf("testMasterInitializedEvent");
82      HMaster master = UTIL.getMiniHBaseCluster().getMaster();
83      ProcedureExecutor<MasterProcedureEnv> procExec = master.getMasterProcedureExecutor();
84      MasterProcedureScheduler procSched = procExec.getEnvironment().getProcedureQueue();
85  
86      HRegionInfo hri = new HRegionInfo(tableName);
87      HTableDescriptor htd = new HTableDescriptor(tableName);
88      HColumnDescriptor hcd = new HColumnDescriptor("f");
89      htd.addFamily(hcd);
90  
91      while (!master.isInitialized()) Thread.sleep(250);
92      master.setInitialized(false); // fake it, set back later
93  
94      CreateTableProcedure proc = new CreateTableProcedure(
95        procExec.getEnvironment(), htd, new HRegionInfo[] { hri });
96  
97      long pollCalls = procSched.getPollCalls();
98      long nullPollCalls = procSched.getNullPollCalls();
99  
100     long procId = procExec.submitProcedure(proc, HConstants.NO_NONCE, HConstants.NO_NONCE);
101     for (int i = 0; i < 10; ++i) {
102       Thread.sleep(100);
103       assertEquals(pollCalls + 1, procSched.getPollCalls());
104       assertEquals(nullPollCalls, procSched.getNullPollCalls());
105     }
106 
107     master.setInitialized(true);
108     ProcedureTestingUtility.waitProcedure(procExec, procId);
109 
110     assertEquals(pollCalls + 2, procSched.getPollCalls());
111     assertEquals(nullPollCalls, procSched.getNullPollCalls());
112   }
113 
114   @Test
115   public void testServerCrashProcedureEvent() throws Exception {
116     TableName tableName = TableName.valueOf("testServerCrashProcedureEventTb");
117     HMaster master = UTIL.getMiniHBaseCluster().getMaster();
118     ProcedureExecutor<MasterProcedureEnv> procExec = master.getMasterProcedureExecutor();
119     MasterProcedureScheduler procSched = procExec.getEnvironment().getProcedureQueue();
120 
121     while (!master.isServerCrashProcessingEnabled() || !master.isInitialized() ||
122         master.getAssignmentManager().getRegionStates().isRegionsInTransition()) {
123       Thread.sleep(25);
124     }
125 
126     UTIL.createTable(tableName, HBaseTestingUtility.COLUMNS[0]);
127     try (Table t = UTIL.getConnection().getTable(tableName)) {
128       // Load the table with a bit of data so some logs to split and some edits in each region.
129       UTIL.loadTable(t, HBaseTestingUtility.COLUMNS[0]);
130     }
131 
132     master.setServerCrashProcessingEnabled(false);  // fake it, set back later
133 
134     long pollCalls = procSched.getPollCalls();
135     long nullPollCalls = procSched.getNullPollCalls();
136 
137     // Kill a server. Master will notice but do nothing other than add it to list of dead servers.
138     HRegionServer hrs = getServerWithRegions();
139     boolean carryingMeta = master.getAssignmentManager()
140         .isCarryingMeta(hrs.getServerName()) == AssignmentManager.ServerHostRegion.HOSTING_REGION;
141     UTIL.getHBaseCluster().killRegionServer(hrs.getServerName());
142     hrs.join();
143 
144     // Wait until the expiration of the server has arrived at the master. We won't process it
145     // by queuing a ServerCrashProcedure because we have disabled crash processing... but wait
146     // here so ServerManager gets notice and adds expired server to appropriate queues.
147     while (!master.getServerManager().isServerDead(hrs.getServerName())) Thread.sleep(10);
148 
149     // Do some of the master processing of dead servers so when SCP runs, it has expected 'state'.
150     master.getServerManager().moveFromOnelineToDeadServers(hrs.getServerName());
151 
152     long procId = procExec.submitProcedure(
153       new ServerCrashProcedure(hrs.getServerName(), true, carryingMeta));
154 
155     for (int i = 0; i < 10; ++i) {
156       Thread.sleep(100);
157       assertEquals(pollCalls + 1, procSched.getPollCalls());
158       assertEquals(nullPollCalls, procSched.getNullPollCalls());
159     }
160 
161     // Now, reenable processing else we can't get a lock on the ServerCrashProcedure.
162     master.setServerCrashProcessingEnabled(true);
163     ProcedureTestingUtility.waitProcedure(procExec, procId);
164 
165     LOG.debug("server crash processing poll calls: " + procSched.getPollCalls());
166     assertTrue(procSched.getPollCalls() >= (pollCalls + 2));
167     assertEquals(nullPollCalls, procSched.getNullPollCalls());
168 
169     UTIL.deleteTable(tableName);
170   }
171 
172   private HRegionServer getServerWithRegions() {
173     for (int i = 0; i < 3; ++i) {
174       HRegionServer hrs = UTIL.getHBaseCluster().getRegionServer(i);
175       if (hrs.getNumberOfOnlineRegions() > 0) {
176         return hrs;
177       }
178     }
179     return null;
180   }
181 }