1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.wal;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNull;
24 import static org.junit.Assert.assertTrue;
25
26 import java.io.IOException;
27 import java.util.HashSet;
28 import java.util.Random;
29 import java.util.Set;
30 import java.util.concurrent.atomic.AtomicLong;
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.HColumnDescriptor;
40 import org.apache.hadoop.hbase.HConstants;
41 import org.apache.hadoop.hbase.HRegionInfo;
42 import org.apache.hadoop.hbase.HTableDescriptor;
43 import org.apache.hadoop.hbase.KeyValue;
44 import org.apache.hadoop.hbase.testclassification.MediumTests;
45 import org.apache.hadoop.hbase.ServerName;
46 import org.apache.hadoop.hbase.TableName;
47 import org.apache.hadoop.hbase.regionserver.MultiVersionConcurrencyControl;
48 import org.apache.hadoop.hbase.testclassification.MediumTests;
49 import org.apache.hadoop.hbase.util.Bytes;
50 import org.apache.hadoop.hbase.util.FSUtils;
51 import org.junit.After;
52 import org.junit.AfterClass;
53 import org.junit.Before;
54 import org.junit.BeforeClass;
55 import org.junit.Rule;
56 import org.junit.Test;
57 import org.junit.experimental.categories.Category;
58 import org.junit.rules.TestName;
59
60
61 import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
62
63 @Category(MediumTests.class)
64 public class TestDefaultWALProvider {
65 private static final Log LOG = LogFactory.getLog(TestDefaultWALProvider.class);
66
67 protected static Configuration conf;
68 protected static FileSystem fs;
69 protected static FileSystem walFs;
70 protected static Path walRootDir;
71 protected final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
72 protected MultiVersionConcurrencyControl mvcc;
73
74 @Rule
75 public final TestName currentTest = new TestName();
76
77 @Before
78 public void setUp() throws Exception {
79 mvcc = new MultiVersionConcurrencyControl();
80 FileStatus[] entries = fs.listStatus(new Path("/"));
81 for (FileStatus dir : entries) {
82 fs.delete(dir.getPath(), true);
83 }
84 walFs.delete(walRootDir, true);
85 }
86
87 @After
88 public void tearDown() throws Exception {
89 }
90
91 @BeforeClass
92 public static void setUpBeforeClass() throws Exception {
93
94 TEST_UTIL.getConfiguration().setInt("dfs.blocksize", 1024 * 1024);
95
96 TEST_UTIL.getConfiguration().setInt("dfs.namenode.heartbeat.recheck-interval", 5000);
97 TEST_UTIL.getConfiguration().setInt("dfs.heartbeat.interval", 1);
98 TEST_UTIL.getConfiguration().setInt("dfs.client.socket-timeout", 5000);
99
100
101 TEST_UTIL.getConfiguration()
102 .setInt("hbase.ipc.client.connect.max.retries", 1);
103 TEST_UTIL.getConfiguration().setInt(
104 "dfs.client.block.recovery.retries", 1);
105 TEST_UTIL.getConfiguration().setInt(
106 "hbase.ipc.client.connection.maxidletime", 500);
107 TEST_UTIL.startMiniDFSCluster(3);
108
109
110 walRootDir = TEST_UTIL.createWALRootDir();
111 conf = TEST_UTIL.getConfiguration();
112 fs = FSUtils.getRootDirFileSystem(conf);
113 walFs = FSUtils.getWALFileSystem(conf);
114 }
115
116 @AfterClass
117 public static void tearDownAfterClass() throws Exception {
118 walFs.delete(walRootDir, true);
119 TEST_UTIL.shutdownMiniCluster();
120 }
121
122 static String getName() {
123 return "TestDefaultWALProvider";
124 }
125
126 @Test
127 public void testGetServerNameFromWALDirectoryName() throws IOException {
128 ServerName sn = ServerName.valueOf("hn", 450, 1398);
129 String hl = walRootDir + "/" +
130 DefaultWALProvider.getWALDirectoryName(sn.toString());
131
132
133 assertNull(DefaultWALProvider.getServerNameFromWALDirectoryName(conf, null));
134 assertNull(DefaultWALProvider.getServerNameFromWALDirectoryName(conf, walRootDir.toUri().toString()));
135 assertNull(DefaultWALProvider.getServerNameFromWALDirectoryName(conf, ""));
136 assertNull(DefaultWALProvider.getServerNameFromWALDirectoryName(conf, " "));
137 assertNull(DefaultWALProvider.getServerNameFromWALDirectoryName(conf, hl));
138 assertNull(DefaultWALProvider.getServerNameFromWALDirectoryName(conf, hl + "qdf"));
139 assertNull(DefaultWALProvider.getServerNameFromWALDirectoryName(conf, "sfqf" + hl + "qdf"));
140
141 final String wals = "/WALs/";
142 ServerName parsed = DefaultWALProvider.getServerNameFromWALDirectoryName(conf,
143 walRootDir.toUri().toString() + wals + sn +
144 "/localhost%2C32984%2C1343316388997.1343316390417");
145 assertEquals("standard", sn, parsed);
146
147 parsed = DefaultWALProvider.getServerNameFromWALDirectoryName(conf, hl + "/qdf");
148 assertEquals("subdir", sn, parsed);
149
150 parsed = DefaultWALProvider.getServerNameFromWALDirectoryName(conf,
151 walRootDir.toUri().toString() + wals + sn +
152 "-splitting/localhost%3A57020.1340474893931");
153 assertEquals("split", sn, parsed);
154 }
155
156
157 protected void addEdits(WAL log, HRegionInfo hri, HTableDescriptor htd,
158 int times) throws IOException {
159 final byte[] row = Bytes.toBytes("row");
160 for (int i = 0; i < times; i++) {
161 long timestamp = System.currentTimeMillis();
162 WALEdit cols = new WALEdit();
163 cols.add(new KeyValue(row, row, row, timestamp, row));
164 log.append(htd, hri, getWalKey(hri.getEncodedNameAsBytes(), htd.getTableName(), timestamp),
165 cols, true);
166 }
167 log.sync();
168 }
169
170
171
172
173 WALKey getWalKey(final byte[] info, final TableName tableName, final long timestamp) {
174 return new WALKey(info, tableName, timestamp, mvcc);
175 }
176
177
178
179
180
181
182 protected void flushRegion(WAL wal, byte[] regionEncodedName, Set<byte[]> flushedFamilyNames) {
183 wal.startCacheFlush(regionEncodedName, flushedFamilyNames);
184 wal.completeCacheFlush(regionEncodedName);
185 }
186
187 private static final byte[] UNSPECIFIED_REGION = new byte[]{};
188
189 @Test
190 public void testLogCleaning() throws Exception {
191 LOG.info("testLogCleaning");
192 final HTableDescriptor htd =
193 new HTableDescriptor(TableName.valueOf("testLogCleaning")).addFamily(new HColumnDescriptor(
194 "row"));
195 final HTableDescriptor htd2 =
196 new HTableDescriptor(TableName.valueOf("testLogCleaning2"))
197 .addFamily(new HColumnDescriptor("row"));
198 final Configuration localConf = new Configuration(conf);
199 localConf.set(WALFactory.WAL_PROVIDER, DefaultWALProvider.class.getName());
200 final WALFactory wals = new WALFactory(localConf, null, currentTest.getMethodName());
201 final AtomicLong sequenceId = new AtomicLong(1);
202 try {
203 HRegionInfo hri = new HRegionInfo(htd.getTableName(),
204 HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW);
205 HRegionInfo hri2 = new HRegionInfo(htd2.getTableName(),
206 HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW);
207
208 final WAL log = wals.getWAL(UNSPECIFIED_REGION, null);
209
210
211
212 addEdits(log, hri, htd, 1);
213 log.rollWriter();
214 assertEquals(1, DefaultWALProvider.getNumRolledLogFiles(log));
215
216
217 addEdits(log, hri, htd, 2);
218 log.rollWriter();
219 assertEquals(2, DefaultWALProvider.getNumRolledLogFiles(log));
220
221
222 addEdits(log, hri, htd, 1);
223 addEdits(log, hri2, htd2, 1);
224 addEdits(log, hri, htd, 1);
225 addEdits(log, hri2, htd2, 1);
226 log.rollWriter();
227 assertEquals(3, DefaultWALProvider.getNumRolledLogFiles(log));
228
229
230
231 addEdits(log, hri2, htd2, 1);
232 log.startCacheFlush(hri.getEncodedNameAsBytes(), htd.getFamiliesKeys());
233 log.completeCacheFlush(hri.getEncodedNameAsBytes());
234 log.rollWriter();
235 assertEquals(2, DefaultWALProvider.getNumRolledLogFiles(log));
236
237
238
239
240 addEdits(log, hri2, htd2, 1);
241 log.startCacheFlush(hri2.getEncodedNameAsBytes(), htd2.getFamiliesKeys());
242 log.completeCacheFlush(hri2.getEncodedNameAsBytes());
243 log.rollWriter();
244 assertEquals(0, DefaultWALProvider.getNumRolledLogFiles(log));
245 } finally {
246 if (wals != null) {
247 wals.close();
248 }
249 }
250 }
251
252
253
254
255
256
257
258
259
260
261
262
263
264 @Test
265 public void testWALArchiving() throws IOException {
266 LOG.debug("testWALArchiving");
267 HTableDescriptor table1 =
268 new HTableDescriptor(TableName.valueOf("t1")).addFamily(new HColumnDescriptor("row"));
269 HTableDescriptor table2 =
270 new HTableDescriptor(TableName.valueOf("t2")).addFamily(new HColumnDescriptor("row"));
271 final Configuration localConf = new Configuration(conf);
272 localConf.set(WALFactory.WAL_PROVIDER, DefaultWALProvider.class.getName());
273 final WALFactory wals = new WALFactory(localConf, null, currentTest.getMethodName());
274 try {
275 final WAL wal = wals.getWAL(UNSPECIFIED_REGION, null);
276 assertEquals(0, DefaultWALProvider.getNumRolledLogFiles(wal));
277 HRegionInfo hri1 =
278 new HRegionInfo(table1.getTableName(), HConstants.EMPTY_START_ROW,
279 HConstants.EMPTY_END_ROW);
280 HRegionInfo hri2 =
281 new HRegionInfo(table2.getTableName(), HConstants.EMPTY_START_ROW,
282 HConstants.EMPTY_END_ROW);
283
284 hri1.setSplit(false);
285 hri2.setSplit(false);
286
287
288 addEdits(wal, hri1, table1, 1);
289 wal.rollWriter();
290
291 assertEquals(1, DefaultWALProvider.getNumRolledLogFiles(wal));
292
293 addEdits(wal, hri1, table1, 1);
294 wal.rollWriter();
295
296 assertEquals(2, DefaultWALProvider.getNumRolledLogFiles(wal));
297
298 addEdits(wal, hri1, table1, 3);
299 flushRegion(wal, hri1.getEncodedNameAsBytes(), table1.getFamiliesKeys());
300
301 wal.rollWriter();
302 assertEquals(0, DefaultWALProvider.getNumRolledLogFiles(wal));
303
304 addEdits(wal, hri2, table2, 1);
305 wal.rollWriter();
306 assertEquals(1, DefaultWALProvider.getNumRolledLogFiles(wal));
307
308 addEdits(wal, hri1, table1, 2);
309 wal.rollWriter();
310 assertEquals(2, DefaultWALProvider.getNumRolledLogFiles(wal));
311
312 addEdits(wal, hri2, table2, 2);
313 flushRegion(wal, hri1.getEncodedNameAsBytes(), table2.getFamiliesKeys());
314
315
316
317
318
319 wal.rollWriter();
320 assertEquals(2, DefaultWALProvider.getNumRolledLogFiles(wal));
321
322 addEdits(wal, hri2, table2, 2);
323 flushRegion(wal, hri2.getEncodedNameAsBytes(), table2.getFamiliesKeys());
324 wal.rollWriter();
325 assertEquals(0, DefaultWALProvider.getNumRolledLogFiles(wal));
326 } finally {
327 if (wals != null) {
328 wals.close();
329 }
330 }
331 }
332
333
334
335
336
337 @Test
338 public void testConcurrentWrites() throws Exception {
339
340
341 int errCode = WALPerformanceEvaluation.
342 innerMain(new Configuration(TEST_UTIL.getConfiguration()),
343 new String [] {"-threads", "3", "-verify", "-noclosefs", "-iterations", "3000"});
344 assertEquals(0, errCode);
345 }
346
347
348
349
350 @Test
351 public void setMembershipDedups() throws IOException {
352 final Configuration localConf = new Configuration(conf);
353 localConf.set(WALFactory.WAL_PROVIDER, DefaultWALProvider.class.getName());
354 final WALFactory wals = new WALFactory(localConf, null, currentTest.getMethodName());
355 try {
356 final Set<WAL> seen = new HashSet<WAL>(1);
357 final Random random = new Random();
358 assertTrue("first attempt to add WAL from default provider should work.",
359 seen.add(wals.getWAL(Bytes.toBytes(random.nextInt()), null)));
360 for (int i = 0; i < 1000; i++) {
361 assertFalse("default wal provider is only supposed to return a single wal, which should "
362 + "compare as .equals itself.",
363 seen.add(wals.getWAL(Bytes.toBytes(random.nextInt()), null)));
364 }
365 } finally {
366 wals.close();
367 }
368 }
369 }