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 static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.assertNotNull;
23  import static org.junit.Assert.assertNotSame;
24  import static org.junit.Assert.assertNull;
25  import static org.junit.Assert.assertTrue;
26  
27  import java.io.IOException;
28  import java.util.NavigableSet;
29  
30  import org.apache.hadoop.conf.Configuration;
31  import org.apache.hadoop.fs.FSDataOutputStream;
32  import org.apache.hadoop.fs.FileSystem;
33  import org.apache.hadoop.fs.Path;
34  import org.apache.hadoop.hbase.HBaseTestingUtility;
35  import org.apache.hadoop.hbase.HConstants;
36  import org.apache.hadoop.hbase.KeyValueTestUtil;
37  import org.apache.hadoop.hbase.ServerName;
38  import org.apache.hadoop.hbase.testclassification.SmallTests;
39  import org.apache.hadoop.hbase.TableName;
40  import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos.SplitLogTask.RecoveryMode;
41  import org.apache.hadoop.hbase.wal.WALSplitter.EntryBuffers;
42  import org.apache.hadoop.hbase.wal.WALSplitter.PipelineController;
43  import org.apache.hadoop.hbase.wal.WALSplitter.RegionEntryBuffer;
44  import org.apache.hadoop.hbase.util.Bytes;
45  import org.apache.hadoop.hbase.util.FSUtils;
46  import org.junit.Test;
47  import org.junit.experimental.categories.Category;
48  
49  // imports for things that haven't moved from regionserver.wal yet.
50  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
51  
52  /**
53   * Simple testing of a few WAL methods.
54   */
55  @Category(SmallTests.class)
56  public class TestWALMethods {
57    private static final byte[] TEST_REGION = Bytes.toBytes("test_region");;
58    private static final TableName TEST_TABLE =
59        TableName.valueOf("test_table");
60  
61    private final HBaseTestingUtility util = new HBaseTestingUtility();
62  
63    @Test
64    public void testServerNameFromWAL() throws Exception {
65      Path walPath = new Path("/hbase/WALs/regionserver-2.example.com,22101,1487767381290", "regionserver-2.example.com%2C22101%2C1487767381290.null0.1487785392316");
66      ServerName name = DefaultWALProvider.getServerNameFromWALDirectoryName(walPath);
67      assertEquals(ServerName.valueOf("regionserver-2.example.com", 22101, 1487767381290L), name);
68    }
69  
70    @Test
71    public void testServerNameFromTestWAL() throws Exception {
72      Path walPath = new Path("/user/example/test-data/12ff1404-68c6-4715-a4b9-775e763842bc/WALs/TestWALRecordReader", "TestWALRecordReader.default.1487787939118");
73      ServerName name = DefaultWALProvider.getServerNameFromWALDirectoryName(walPath);
74      assertNull(name);
75    }
76  
77    /**
78     * Assert that getSplitEditFilesSorted returns files in expected order and
79     * that it skips moved-aside files.
80     * @throws IOException
81     */
82    @Test public void testGetSplitEditFilesSorted() throws IOException {
83      FileSystem fs = FileSystem.get(util.getConfiguration());
84      Path regiondir = util.getDataTestDir("regiondir");
85      fs.delete(regiondir, true);
86      fs.mkdirs(regiondir);
87      Path recoverededits = WALSplitter.getRegionDirRecoveredEditsDir(regiondir);
88      String first = WALSplitter.formatRecoveredEditsFileName(-1);
89      createFile(fs, recoverededits, first);
90      createFile(fs, recoverededits, WALSplitter.formatRecoveredEditsFileName(0));
91      createFile(fs, recoverededits, WALSplitter.formatRecoveredEditsFileName(1));
92      createFile(fs, recoverededits, WALSplitter
93          .formatRecoveredEditsFileName(11));
94      createFile(fs, recoverededits, WALSplitter.formatRecoveredEditsFileName(2));
95      createFile(fs, recoverededits, WALSplitter
96          .formatRecoveredEditsFileName(50));
97      String last = WALSplitter.formatRecoveredEditsFileName(Long.MAX_VALUE);
98      createFile(fs, recoverededits, last);
99      createFile(fs, recoverededits,
100       Long.toString(Long.MAX_VALUE) + "." + System.currentTimeMillis());
101 
102     final Configuration walConf = new Configuration(util.getConfiguration());
103     FSUtils.setRootDir(walConf, regiondir);
104     (new WALFactory(walConf, null, "dummyLogName")).getWAL(new byte[] {}, null);
105 
106     NavigableSet<Path> files = WALSplitter.getSplitEditFilesSorted(fs, regiondir);
107     assertEquals(7, files.size());
108     assertEquals(files.pollFirst().getName(), first);
109     assertEquals(files.pollLast().getName(), last);
110     assertEquals(files.pollFirst().getName(),
111       WALSplitter
112         .formatRecoveredEditsFileName(0));
113     assertEquals(files.pollFirst().getName(),
114       WALSplitter
115         .formatRecoveredEditsFileName(1));
116     assertEquals(files.pollFirst().getName(),
117       WALSplitter
118         .formatRecoveredEditsFileName(2));
119     assertEquals(files.pollFirst().getName(),
120       WALSplitter
121         .formatRecoveredEditsFileName(11));
122   }
123 
124   private void createFile(final FileSystem fs, final Path testdir,
125       final String name)
126   throws IOException {
127     FSDataOutputStream fdos = fs.create(new Path(testdir, name), true);
128     fdos.close();
129   }
130 
131   @Test
132   public void testRegionEntryBuffer() throws Exception {
133     WALSplitter.RegionEntryBuffer reb = new WALSplitter.RegionEntryBuffer(
134         TEST_TABLE, TEST_REGION);
135     assertEquals(0, reb.heapSize());
136 
137     reb.appendEntry(createTestLogEntry(1));
138     assertTrue(reb.heapSize() > 0);
139   }
140 
141   @Test
142   public void testEntrySink() throws Exception {
143     Configuration conf = new Configuration();
144     RecoveryMode mode = (conf.getBoolean(HConstants.DISTRIBUTED_LOG_REPLAY_KEY, false) ?
145       RecoveryMode.LOG_REPLAY : RecoveryMode.LOG_SPLITTING);
146 
147     EntryBuffers sink = new EntryBuffers(new PipelineController(), 1*1024*1024);
148     for (int i = 0; i < 1000; i++) {
149       WAL.Entry entry = createTestLogEntry(i);
150       sink.appendEntry(entry);
151     }
152 
153     assertTrue(sink.totalBuffered > 0);
154     long amountInChunk = sink.totalBuffered;
155     // Get a chunk
156     RegionEntryBuffer chunk = sink.getChunkToWrite();
157     assertEquals(chunk.heapSize(), amountInChunk);
158 
159     // Make sure it got marked that a thread is "working on this"
160     assertTrue(sink.isRegionCurrentlyWriting(TEST_REGION));
161 
162     // Insert some more entries
163     for (int i = 0; i < 500; i++) {
164       WAL.Entry entry = createTestLogEntry(i);
165       sink.appendEntry(entry);
166     }
167     // Asking for another chunk shouldn't work since the first one
168     // is still writing
169     assertNull(sink.getChunkToWrite());
170 
171     // If we say we're done writing the first chunk, then we should be able
172     // to get the second
173     sink.doneWriting(chunk);
174 
175     RegionEntryBuffer chunk2 = sink.getChunkToWrite();
176     assertNotNull(chunk2);
177     assertNotSame(chunk, chunk2);
178     long amountInChunk2 = sink.totalBuffered;
179     // The second chunk had fewer rows than the first
180     assertTrue(amountInChunk2 < amountInChunk);
181 
182     sink.doneWriting(chunk2);
183     assertEquals(0, sink.totalBuffered);
184   }
185 
186   private WAL.Entry createTestLogEntry(int i) {
187     long seq = i;
188     long now = i * 1000;
189 
190     WALEdit edit = new WALEdit();
191     edit.add(KeyValueTestUtil.create("row", "fam", "qual", 1234, "val"));
192     WALKey key = new WALKey(TEST_REGION, TEST_TABLE, seq, now,
193         HConstants.DEFAULT_CLUSTER_ID);
194     WAL.Entry entry = new WAL.Entry(key, edit);
195     return entry;
196   }
197 
198 }
199