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.snapshot;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertFalse;
22  
23  import org.apache.hadoop.fs.FSDataOutputStream;
24  import org.apache.hadoop.fs.FileStatus;
25  import org.apache.hadoop.fs.FileSystem;
26  import org.apache.hadoop.fs.Path;
27  import org.apache.hadoop.hbase.HBaseTestingUtility;
28  import org.apache.hadoop.hbase.SmallTests;
29  import org.apache.hadoop.hbase.errorhandling.ForeignException;
30  import org.apache.hadoop.hbase.errorhandling.ForeignExceptionDispatcher;
31  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
32  import org.apache.hadoop.hbase.regionserver.wal.HLog;
33  import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
34  import org.apache.hadoop.hbase.util.FSUtils;
35  import org.junit.Test;
36  import org.junit.experimental.categories.Category;
37  import org.mockito.Mockito;
38  
39  /**
40   * Test that we correctly copy the recovered edits from a directory
41   */
42  @Category(SmallTests.class)
43  public class TestCopyRecoveredEditsTask {
44  
45    private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
46  
47    @Test
48    public void testCopyFiles() throws Exception {
49  
50      SnapshotDescription snapshot = SnapshotDescription.newBuilder().setName("snapshot").build();
51      ForeignExceptionDispatcher monitor = Mockito.mock(ForeignExceptionDispatcher.class);
52      FileSystem fs = UTIL.getTestFileSystem();
53      Path root = UTIL.getDataTestDir();
54      String regionName = "regionA";
55      Path regionDir = new Path(root, regionName);
56      Path workingDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(snapshot, root);
57  
58      try {
59        // doesn't really matter where the region's snapshot directory is, but this is pretty close
60        Path snapshotRegionDir = new Path(workingDir, regionName);
61        fs.mkdirs(snapshotRegionDir);
62  
63        // put some stuff in the recovered.edits directory
64        Path edits = HLog.getRegionDirRecoveredEditsDir(regionDir);
65        fs.mkdirs(edits);
66        // make a file with some data
67        Path file1 = new Path(edits, "0000000000000002352");
68        FSDataOutputStream out = fs.create(file1);
69        byte[] data = new byte[] { 1, 2, 3, 4 };
70        out.write(data);
71        out.close();
72        // make an empty file
73        Path empty = new Path(edits, "empty");
74        fs.createNewFile(empty);
75  
76        CopyRecoveredEditsTask task = new CopyRecoveredEditsTask(snapshot, monitor, fs, regionDir,
77            snapshotRegionDir);
78        CopyRecoveredEditsTask taskSpy = Mockito.spy(task);
79        taskSpy.call();
80  
81        Path snapshotEdits = HLog.getRegionDirRecoveredEditsDir(snapshotRegionDir);
82        FileStatus[] snapshotEditFiles = FSUtils.listStatus(fs, snapshotEdits);
83        assertEquals("Got wrong number of files in the snapshot edits", 1, snapshotEditFiles.length);
84        FileStatus file = snapshotEditFiles[0];
85        assertEquals("Didn't copy expected file", file1.getName(), file.getPath().getName());
86  
87        Mockito.verify(monitor, Mockito.never()).receive(Mockito.any(ForeignException.class));
88        Mockito.verify(taskSpy, Mockito.never()).snapshotFailure(Mockito.anyString(),
89             Mockito.any(Exception.class));
90      } finally {
91        // cleanup the working directory
92        FSUtils.delete(fs, regionDir, true);
93        FSUtils.delete(fs, workingDir, true);
94      }
95    }
96  
97    /**
98     * Check that we don't get an exception if there is no recovered edits directory to copy
99     * @throws Exception on failure
100    */
101   @Test
102   public void testNoEditsDir() throws Exception {
103     SnapshotDescription snapshot = SnapshotDescription.newBuilder().setName("snapshot").build();
104     ForeignExceptionDispatcher monitor = Mockito.mock(ForeignExceptionDispatcher.class);
105     FileSystem fs = UTIL.getTestFileSystem();
106     Path root = UTIL.getDataTestDir();
107     String regionName = "regionA";
108     Path regionDir = new Path(root, regionName);
109     Path workingDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(snapshot, root);
110     try {
111       // doesn't really matter where the region's snapshot directory is, but this is pretty close
112       Path snapshotRegionDir = new Path(workingDir, regionName);
113       fs.mkdirs(snapshotRegionDir);
114       Path regionEdits = HLog.getRegionDirRecoveredEditsDir(regionDir);
115       assertFalse("Edits dir exists already - it shouldn't", fs.exists(regionEdits));
116 
117       CopyRecoveredEditsTask task = new CopyRecoveredEditsTask(snapshot, monitor, fs, regionDir,
118           snapshotRegionDir);
119       task.call();
120     } finally {
121       // cleanup the working directory
122       FSUtils.delete(fs, regionDir, true);
123       FSUtils.delete(fs, workingDir, true);
124     }
125   }
126 }