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  package org.apache.hadoop.hbase.wal;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.apache.hadoop.conf.Configuration;
23  import org.apache.hadoop.fs.FileStatus;
24  import org.apache.hadoop.fs.FileSystem;
25  import org.apache.hadoop.fs.Path;
26  import org.apache.hadoop.hbase.HBaseTestingUtility;
27  import org.apache.hadoop.hbase.TableName;
28  import org.apache.hadoop.hbase.HTableDescriptor;
29  import org.apache.hadoop.hbase.HColumnDescriptor;
30  import org.apache.hadoop.hbase.KeyValue;
31  import org.apache.hadoop.hbase.HConstants;
32  import org.apache.hadoop.hbase.HRegionInfo;
33  import org.apache.hadoop.hbase.fs.HFileSystem;
34  import org.apache.hadoop.hbase.regionserver.MultiVersionConcurrencyControl;
35  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
36  import org.apache.hadoop.hbase.testclassification.MediumTests;
37  import org.apache.hadoop.hbase.util.Bytes;
38  import org.apache.hadoop.hbase.util.FSUtils;
39  import org.junit.AfterClass;
40  import org.junit.Before;
41  import org.junit.BeforeClass;
42  import org.junit.Test;
43  import org.junit.experimental.categories.Category;
44  
45  import java.io.IOException;
46  import java.util.ArrayList;
47  import java.util.Collections;
48  import java.util.List;
49  
50  import static org.junit.Assert.assertEquals;
51  
52  @Category(MediumTests.class)
53  public class TestWALRootDir {
54    private static final Log LOG = LogFactory.getLog(TestWALRootDir.class);
55    private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
56    private static Configuration conf;
57    private static FileSystem fs;
58    private static FileSystem walFs;
59    static final TableName tableName = TableName.valueOf("TestWALWALDir");
60    private static final byte [] rowName = Bytes.toBytes("row");
61    private static final byte [] family = Bytes.toBytes("column");
62    private static HTableDescriptor htd;
63    private static Path walRootDir;
64    private static Path rootDir;
65    private static WALFactory wals;
66  
67    @Before
68    public void setUp() throws Exception {
69      cleanup();
70    }
71  
72    @BeforeClass
73    public static void setUpBeforeClass() throws Exception {
74      conf = TEST_UTIL.getConfiguration();
75      TEST_UTIL.startMiniDFSCluster(1);
76      rootDir = TEST_UTIL.createRootDir();
77      walRootDir = TEST_UTIL.createWALRootDir();
78      fs = FSUtils.getRootDirFileSystem(conf);
79      walFs = FSUtils.getWALFileSystem(conf);
80      htd = new HTableDescriptor(tableName);
81      htd.addFamily(new HColumnDescriptor(family));
82    }
83  
84    @AfterClass
85    public static void tearDownAfterClass() throws Exception {
86      cleanup();
87      TEST_UTIL.shutdownMiniDFSCluster();
88    }
89  
90    @Test
91    public void testWALRootDir() throws Exception {
92      HRegionInfo regionInfo = new HRegionInfo(tableName);
93      wals = new WALFactory(conf, null, "testWALRootDir");
94      WAL log = wals.getWAL(regionInfo.getEncodedNameAsBytes(), regionInfo.getTable().getNamespace());
95  
96      assertEquals(1, getWALFiles(walFs, walRootDir).size());
97      byte [] value = Bytes.toBytes("value");
98      WALEdit edit = new WALEdit();
99      edit.add(new KeyValue(rowName, family, Bytes.toBytes("1"),
100         System.currentTimeMillis(), value));
101     long txid = log.append(htd,regionInfo, getWalKey(System.currentTimeMillis(), regionInfo, 0), edit, true);
102     log.sync(txid);
103     assertEquals("Expect 1 log have been created", 1, getWALFiles(walFs, walRootDir).size());
104     log.rollWriter();
105     //Create 1 more WAL
106     assertEquals(2, getWALFiles(walFs, new Path(walRootDir, HConstants.HREGION_LOGDIR_NAME)).size());
107     edit.add(new KeyValue(rowName, family, Bytes.toBytes("2"),
108         System.currentTimeMillis(), value));
109     txid = log.append(htd, regionInfo, getWalKey(System.currentTimeMillis(), regionInfo, 1), edit, true);
110     log.sync(txid);
111     log.rollWriter();
112     log.shutdown();
113 
114     assertEquals("Expect 3 logs in WALs dir", 3, getWALFiles(walFs, new Path(walRootDir, HConstants.HREGION_LOGDIR_NAME)).size());
115   }
116 
117   protected WALKey getWalKey(final long time, HRegionInfo hri, final long startPoint) {
118     return new WALKey(hri.getEncodedNameAsBytes(), tableName, time, new MultiVersionConcurrencyControl(startPoint));
119   }
120 
121   private List<FileStatus> getWALFiles(FileSystem fs, Path dir)
122       throws IOException {
123     List<FileStatus> result = new ArrayList<FileStatus>();
124     LOG.debug("Scanning " + dir.toString() + " for WAL files");
125 
126     FileStatus[] files = fs.listStatus(dir);
127     if (files == null) return Collections.emptyList();
128     for (FileStatus file : files) {
129       if (file.isDirectory()) {
130         // recurse into sub directories
131         result.addAll(getWALFiles(fs, file.getPath()));
132       } else {
133         String name = file.getPath().toString();
134         if (!name.startsWith(".")) {
135           result.add(file);
136         }
137       }
138     }
139     return result;
140   }
141 
142   private static void cleanup() throws Exception{
143     walFs.delete(walRootDir, true);
144     fs.delete(rootDir, true);
145   }
146 
147 }
148