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 org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.hadoop.conf.Configuration;
24  import org.apache.hadoop.hbase.HBaseTestingUtility;
25  import org.apache.hadoop.hbase.HRegionInfo;
26  import org.apache.hadoop.hbase.HTableDescriptor;
27  import org.apache.hadoop.hbase.HColumnDescriptor;
28  import org.apache.hadoop.hbase.TableName;
29  import org.apache.hadoop.hbase.client.Table;
30  import org.apache.hadoop.hbase.master.HMaster;
31  import org.apache.hadoop.hbase.master.AssignmentManager;
32  import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
33  import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
34  import org.apache.hadoop.hbase.procedure2.store.wal.WALProcedureStore;
35  import org.apache.hadoop.hbase.regionserver.HRegionServer;
36  import org.apache.hadoop.hbase.testclassification.MasterTests;
37  import org.apache.hadoop.hbase.testclassification.MediumTests;
38  import org.junit.AfterClass;
39  import org.junit.BeforeClass;
40  import org.junit.Test;
41  import org.junit.experimental.categories.Category;
42  
43  import static org.junit.Assert.assertEquals;
44  import static org.junit.Assert.assertTrue;
45  
46  @Category({MasterTests.class, MediumTests.class})
47  public class TestMasterProcedureEvents {
48    private static final Log LOG = LogFactory.getLog(TestCreateTableProcedure.class);
49  
50    protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
51  
52    private static void setupConf(Configuration conf) {
53      conf.setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 8);
54      conf.setBoolean(WALProcedureStore.USE_HSYNC_CONF_KEY, false);
55    }
56  
57    @BeforeClass
58    public static void setupCluster() throws Exception {
59      setupConf(UTIL.getConfiguration());
60      UTIL.startMiniCluster(3);
61    }
62  
63    @AfterClass
64    public static void cleanupTest() throws Exception {
65      try {
66        UTIL.shutdownMiniCluster();
67      } catch (Exception e) {
68        LOG.warn("failure shutting down cluster", e);
69      }
70    }
71  
72    @Test
73    public void testMasterInitializedEvent() throws Exception {
74      TableName tableName = TableName.valueOf("testMasterInitializedEvent");
75      HMaster master = UTIL.getMiniHBaseCluster().getMaster();
76      ProcedureExecutor<MasterProcedureEnv> procExec = master.getMasterProcedureExecutor();
77      MasterProcedureScheduler procSched = procExec.getEnvironment().getProcedureQueue();
78  
79      HRegionInfo hri = new HRegionInfo(tableName);
80      HTableDescriptor htd = new HTableDescriptor(tableName);
81      HColumnDescriptor hcd = new HColumnDescriptor("f");
82      htd.addFamily(hcd);
83  
84      while (!master.isInitialized()) Thread.sleep(250);
85      master.setInitialized(false); // fake it, set back later
86  
87      CreateTableProcedure proc = new CreateTableProcedure(
88        procExec.getEnvironment(), htd, new HRegionInfo[] { hri });
89  
90      long pollCalls = procSched.getPollCalls();
91      long nullPollCalls = procSched.getNullPollCalls();
92  
93      long procId = procExec.submitProcedure(proc);
94      for (int i = 0; i < 10; ++i) {
95        Thread.sleep(100);
96        assertEquals(pollCalls + 1, procSched.getPollCalls());
97        assertEquals(nullPollCalls, procSched.getNullPollCalls());
98      }
99  
100     master.setInitialized(true);
101     ProcedureTestingUtility.waitProcedure(procExec, procId);
102 
103     assertEquals(pollCalls + 2, procSched.getPollCalls());
104     assertEquals(nullPollCalls, procSched.getNullPollCalls());
105   }
106 
107   @Test
108   public void testServerCrashProcedureEvent() throws Exception {
109     TableName tableName = TableName.valueOf("testServerCrashProcedureEventTb");
110     HMaster master = UTIL.getMiniHBaseCluster().getMaster();
111     ProcedureExecutor<MasterProcedureEnv> procExec = master.getMasterProcedureExecutor();
112     MasterProcedureScheduler procSched = procExec.getEnvironment().getProcedureQueue();
113 
114     while (!master.isServerCrashProcessingEnabled() || !master.isInitialized() ||
115         master.getAssignmentManager().getRegionStates().isRegionsInTransition()) {
116       Thread.sleep(25);
117     }
118 
119     UTIL.createTable(tableName, HBaseTestingUtility.COLUMNS[0]);
120     try (Table t = UTIL.getConnection().getTable(tableName)) {
121       // Load the table with a bit of data so some logs to split and some edits in each region.
122       UTIL.loadTable(t, HBaseTestingUtility.COLUMNS[0]);
123     }
124 
125     master.setServerCrashProcessingEnabled(false);  // fake it, set back later
126 
127     long pollCalls = procSched.getPollCalls();
128     long nullPollCalls = procSched.getNullPollCalls();
129 
130     // Kill a server. Master will notice but do nothing other than add it to list of dead servers.
131     HRegionServer hrs = getServerWithRegions();
132     boolean carryingMeta = master.getAssignmentManager()
133         .isCarryingMeta(hrs.getServerName()) == AssignmentManager.ServerHostRegion.HOSTING_REGION;
134     UTIL.getHBaseCluster().killRegionServer(hrs.getServerName());
135     hrs.join();
136 
137     // Wait until the expiration of the server has arrived at the master. We won't process it
138     // by queuing a ServerCrashProcedure because we have disabled crash processing... but wait
139     // here so ServerManager gets notice and adds expired server to appropriate queues.
140     while (!master.getServerManager().isServerDead(hrs.getServerName())) Thread.sleep(10);
141 
142     // Do some of the master processing of dead servers so when SCP runs, it has expected 'state'.
143     master.getServerManager().moveFromOnlineToDeadServers(hrs.getServerName());
144 
145     long procId = procExec.submitProcedure(
146       new ServerCrashProcedure(procExec.getEnvironment(), hrs.getServerName(), true, carryingMeta));
147 
148     for (int i = 0; i < 10; ++i) {
149       Thread.sleep(100);
150       assertEquals(pollCalls + 1, procSched.getPollCalls());
151       assertEquals(nullPollCalls, procSched.getNullPollCalls());
152     }
153 
154     // Now, reenable processing else we can't get a lock on the ServerCrashProcedure.
155     master.setServerCrashProcessingEnabled(true);
156     ProcedureTestingUtility.waitProcedure(procExec, procId);
157 
158     LOG.debug("server crash processing poll calls: " + procSched.getPollCalls());
159     assertTrue(procSched.getPollCalls() >= (pollCalls + 2));
160     assertEquals(nullPollCalls, procSched.getNullPollCalls());
161 
162     UTIL.deleteTable(tableName);
163   }
164 
165   private HRegionServer getServerWithRegions() {
166     for (int i = 0; i < 3; ++i) {
167       HRegionServer hrs = UTIL.getHBaseCluster().getRegionServer(i);
168       if (hrs.getNumberOfOnlineRegions() > 0) {
169         return hrs;
170       }
171     }
172     return null;
173   }
174 }