View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.wal;
20  
21  import java.io.IOException;
22  import java.util.HashSet;
23  import java.util.Random;
24  import java.util.Set;
25  
26  import static org.junit.Assert.assertEquals;
27  import static org.apache.hadoop.hbase.wal.BoundedGroupingStrategy.NUM_REGION_GROUPS;
28  import static org.apache.hadoop.hbase.wal.BoundedGroupingStrategy.DEFAULT_NUM_REGION_GROUPS;
29  import static org.apache.hadoop.hbase.wal.WALFactory.WAL_PROVIDER;
30  import static org.apache.hadoop.hbase.wal.RegionGroupingProvider.REGION_GROUPING_STRATEGY;
31  
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.apache.hadoop.conf.Configuration;
35  import org.apache.hadoop.fs.FileStatus;
36  import org.apache.hadoop.fs.FileSystem;
37  import org.apache.hadoop.fs.Path;
38  import org.apache.hadoop.hbase.HBaseTestingUtility;
39  import org.apache.hadoop.hbase.testclassification.LargeTests;
40  import org.apache.hadoop.hbase.util.Bytes;
41  import org.apache.hadoop.hbase.util.FSUtils;
42  import org.junit.After;
43  import org.junit.AfterClass;
44  import org.junit.Before;
45  import org.junit.BeforeClass;
46  import org.junit.Rule;
47  import org.junit.Test;
48  import org.junit.experimental.categories.Category;
49  import org.junit.rules.TestName;
50  
51  @Category({LargeTests.class})
52  public class TestBoundedRegionGroupingStrategy {
53    protected static final Log LOG = LogFactory.getLog(TestBoundedRegionGroupingStrategy.class);
54  
55    @Rule
56    public TestName currentTest = new TestName();
57    protected static Configuration conf;
58    protected static FileSystem fs;
59    protected final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
60  
61    @Before
62    public void setUp() throws Exception {
63      FileStatus[] entries = fs.listStatus(new Path("/"));
64      for (FileStatus dir : entries) {
65        fs.delete(dir.getPath(), true);
66      }
67    }
68  
69    @After
70    public void tearDown() throws Exception {
71    }
72  
73    @BeforeClass
74    public static void setUpBeforeClass() throws Exception {
75      conf = TEST_UTIL.getConfiguration();
76      // Make block sizes small.
77      conf.setInt("dfs.blocksize", 1024 * 1024);
78      // quicker heartbeat interval for faster DN death notification
79      conf.setInt("dfs.namenode.heartbeat.recheck-interval", 5000);
80      conf.setInt("dfs.heartbeat.interval", 1);
81      conf.setInt("dfs.client.socket-timeout", 5000);
82  
83      // faster failover with cluster.shutdown();fs.close() idiom
84      conf.setInt("hbase.ipc.client.connect.max.retries", 1);
85      conf.setInt("dfs.client.block.recovery.retries", 1);
86      conf.setInt("hbase.ipc.client.connection.maxidletime", 500);
87  
88      conf.setClass(WAL_PROVIDER, RegionGroupingProvider.class, WALProvider.class);
89      conf.set(REGION_GROUPING_STRATEGY, RegionGroupingProvider.Strategies.bounded.name());
90  
91      TEST_UTIL.startMiniDFSCluster(3);
92  
93      fs = TEST_UTIL.getDFSCluster().getFileSystem();
94    }
95  
96    @AfterClass
97    public static void tearDownAfterClass() throws Exception {
98      TEST_UTIL.shutdownMiniCluster();
99    }
100 
101   /**
102    * Write to a log file with three concurrent threads and verifying all data is written.
103    */
104   @Test
105   public void testConcurrentWrites() throws Exception {
106     // Run the WPE tool with three threads writing 3000 edits each concurrently.
107     // When done, verify that all edits were written.
108     int errCode = WALPerformanceEvaluation.innerMain(new Configuration(conf),
109         new String [] {"-threads", "3", "-verify", "-noclosefs", "-iterations", "3000"});
110     assertEquals(0, errCode);
111   }
112 
113   /**
114    * Make sure we can successfully run with more regions then our bound.
115    */
116   @Test
117   public void testMoreRegionsThanBound() throws Exception {
118     final String parallelism = Integer.toString(DEFAULT_NUM_REGION_GROUPS * 2);
119     int errCode = WALPerformanceEvaluation.innerMain(new Configuration(conf),
120         new String [] {"-threads", parallelism, "-verify", "-noclosefs", "-iterations", "3000",
121             "-regions", parallelism});
122     assertEquals(0, errCode);
123   }
124 
125   @Test
126   public void testBoundsGreaterThanDefault() throws Exception {
127     final int temp = conf.getInt(NUM_REGION_GROUPS, DEFAULT_NUM_REGION_GROUPS);
128     try {
129       conf.setInt(NUM_REGION_GROUPS, temp*4);
130       final String parallelism = Integer.toString(temp*4);
131       int errCode = WALPerformanceEvaluation.innerMain(new Configuration(conf),
132           new String [] {"-threads", parallelism, "-verify", "-noclosefs", "-iterations", "3000",
133               "-regions", parallelism});
134       assertEquals(0, errCode);
135     } finally {
136       conf.setInt(NUM_REGION_GROUPS, temp);
137     }
138   }
139 
140   @Test
141   public void testMoreRegionsThanBoundWithBoundsGreaterThanDefault() throws Exception {
142     final int temp = conf.getInt(NUM_REGION_GROUPS, DEFAULT_NUM_REGION_GROUPS);
143     try {
144       conf.setInt(NUM_REGION_GROUPS, temp*4);
145       final String parallelism = Integer.toString(temp*4*2);
146       int errCode = WALPerformanceEvaluation.innerMain(new Configuration(conf),
147           new String [] {"-threads", parallelism, "-verify", "-noclosefs", "-iterations", "3000",
148               "-regions", parallelism});
149       assertEquals(0, errCode);
150     } finally {
151       conf.setInt(NUM_REGION_GROUPS, temp);
152     }
153   }
154 
155   /**
156    * Ensure that we can use Set.add to deduplicate WALs
157    */
158   @Test
159   public void setMembershipDedups() throws IOException {
160     final int temp = conf.getInt(NUM_REGION_GROUPS, DEFAULT_NUM_REGION_GROUPS);
161     WALFactory wals = null;
162     try {
163       conf.setInt(NUM_REGION_GROUPS, temp*4);
164       // Set HDFS root directory for storing WAL
165       FSUtils.setRootDir(conf, TEST_UTIL.getDataTestDirOnTestFS());
166 
167       wals = new WALFactory(conf, null, currentTest.getMethodName());
168       final Set<WAL> seen = new HashSet<WAL>(temp*4);
169       final Random random = new Random();
170       int count = 0;
171       // we know that this should see one of the wals more than once
172       for (int i = 0; i < temp*8; i++) {
173         final WAL maybeNewWAL = wals.getWAL(Bytes.toBytes(random.nextInt()), null);
174         LOG.info("Iteration " + i + ", checking wal " + maybeNewWAL);
175         if (seen.add(maybeNewWAL)) {
176           count++;
177         }
178       }
179       assertEquals("received back a different number of WALs that are not equal() to each other " +
180           "than the bound we placed.", temp*4, count);
181     } finally {
182       if (wals != null) {
183         wals.close();
184       }
185       conf.setInt(NUM_REGION_GROUPS, temp);
186     }
187   }
188 }