1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.mapreduce;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.hadoop.conf.Configuration;
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.CategoryBasedTimeout;
28 import org.apache.hadoop.hbase.Cell;
29 import org.apache.hadoop.hbase.CellScanner;
30 import org.apache.hadoop.hbase.HBaseTestingUtility;
31 import org.apache.hadoop.hbase.TableName;
32 import org.apache.hadoop.hbase.client.Admin;
33 import org.apache.hadoop.hbase.client.HTable;
34 import org.apache.hadoop.hbase.client.Result;
35 import org.apache.hadoop.hbase.io.HFileLink;
36 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
37 import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
38 import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
39 import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils;
40 import org.apache.hadoop.hbase.util.Bytes;
41 import org.apache.hadoop.hbase.util.FSUtils;
42 import org.apache.hadoop.hbase.util.HFileArchiveUtil;
43 import org.junit.Assert;
44 import org.junit.Rule;
45 import org.junit.Test;
46 import org.junit.rules.TestRule;
47
48 import static org.junit.Assert.assertFalse;
49
50 import java.io.IOException;
51 import java.util.Arrays;
52
53 public abstract class TableSnapshotInputFormatTestBase {
54 private static final Log LOG = LogFactory.getLog(TableSnapshotInputFormatTestBase.class);
55 @Rule public final TestRule timeout = CategoryBasedTimeout.builder().
56 withTimeout(this.getClass()).withLookingForStuckThread(true).build();
57 protected final HBaseTestingUtility UTIL = new HBaseTestingUtility();
58 protected static final int NUM_REGION_SERVERS = 2;
59 protected static final byte[][] FAMILIES = {Bytes.toBytes("f1"), Bytes.toBytes("f2")};
60
61 protected FileSystem fs;
62 protected Path rootDir;
63
64 public void setupCluster() throws Exception {
65 setupConf(UTIL.getConfiguration());
66 UTIL.setJobWithoutMRCluster();
67 UTIL.startMiniCluster(NUM_REGION_SERVERS, true);
68 rootDir = UTIL.getHBaseCluster().getMaster().getMasterFileSystem().getRootDir();
69 fs = rootDir.getFileSystem(UTIL.getConfiguration());
70 }
71
72 public void tearDownCluster() throws Exception {
73 UTIL.shutdownMiniCluster();
74 }
75
76 private static void setupConf(Configuration conf) {
77
78 conf.setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true);
79 }
80
81 protected abstract void testWithMockedMapReduce(HBaseTestingUtility util, String snapshotName,
82 int numRegions, int numSplitsPerRegion, int expectedNumSplits) throws Exception;
83
84 protected abstract void testWithMapReduceImpl(HBaseTestingUtility util, TableName tableName,
85 String snapshotName, Path tableDir, int numRegions, int numSplitsPerRegion, int expectedNumSplits,
86 boolean shutdownCluster) throws Exception;
87
88 protected abstract byte[] getStartRow();
89
90 protected abstract byte[] getEndRow();
91
92 @Test
93 public void testWithMockedMapReduceSingleRegion() throws Exception {
94 testWithMockedMapReduce(UTIL, "testWithMockedMapReduceSingleRegion", 1, 1, 1);
95 }
96
97 @Test
98 public void testWithMockedMapReduceMultiRegion() throws Exception {
99 testWithMockedMapReduce(UTIL, "testWithMockedMapReduceMultiRegion", 10, 1, 8);
100 }
101
102 @Test
103 public void testWithMapReduceSingleRegion() throws Exception {
104 testWithMapReduce(UTIL, "testWithMapReduceSingleRegion", 1, 1, 1, false);
105 }
106
107 @Test
108 public void testWithMapReduceMultiRegion() throws Exception {
109 testWithMapReduce(UTIL, "testWithMapReduceMultiRegion", 10, 1, 8, false);
110 }
111
112 @Test
113 public void testWithMapReduceMultipleMappersPerRegion() throws Exception {
114 testWithMapReduce(UTIL, "testWithMapReduceMultiRegion", 10, 5, 50, false);
115 }
116
117 @Test
118
119 public void testWithMapReduceAndOfflineHBaseMultiRegion() throws Exception {
120 testWithMapReduce(UTIL, "testWithMapReduceAndOfflineHBaseMultiRegion", 10, 1, 8, true);
121 }
122
123
124 @Test
125 public void testRestoreSnapshotDoesNotCreateBackRefLinks() throws Exception {
126 setupCluster();
127 TableName tableName = TableName.valueOf("testRestoreSnapshotDoesNotCreateBackRefLinks");
128 String snapshotName = "foo";
129
130 try {
131 createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 1);
132
133 Path tmpTableDir = UTIL.getRandomDir();
134
135 testRestoreSnapshotDoesNotCreateBackRefLinksInit(tableName, snapshotName,tmpTableDir);
136
137 Path rootDir = FSUtils.getRootDir(UTIL.getConfiguration());
138 for (Path regionDir : FSUtils.getRegionDirs(fs, FSUtils.getTableDir(rootDir, tableName))) {
139 for (Path storeDir : FSUtils.getFamilyDirs(fs, regionDir)) {
140 for (FileStatus status : fs.listStatus(storeDir)) {
141 System.out.println(status.getPath());
142 if (StoreFileInfo.isValid(status)) {
143 Path archiveStoreDir = HFileArchiveUtil.getStoreArchivePath(UTIL.getConfiguration(),
144 tableName, regionDir.getName(), storeDir.getName());
145
146 Path path = HFileLink.getBackReferencesDir(storeDir, status.getPath().getName());
147
148 assertFalse("There is a back reference in " + path, fs.exists(path));
149
150 path = HFileLink.getBackReferencesDir(archiveStoreDir, status.getPath().getName());
151
152 assertFalse("There is a back reference in " + path, fs.exists(path));
153 }
154 }
155 }
156 }
157 } finally {
158 UTIL.getHBaseAdmin().deleteSnapshot(snapshotName);
159 UTIL.deleteTable(tableName);
160 tearDownCluster();
161 }
162 }
163
164 public abstract void testRestoreSnapshotDoesNotCreateBackRefLinksInit(TableName tableName,
165 String snapshotName, Path tmpTableDir) throws Exception;
166
167 protected void testWithMapReduce(HBaseTestingUtility util, String snapshotName,
168 int numRegions, int numSplitsPerRegion, int expectedNumSplits, boolean shutdownCluster) throws Exception {
169 setupCluster();
170 try {
171 Path tableDir = util.getRandomDir();
172 TableName tableName = TableName.valueOf("testWithMapReduce");
173 testWithMapReduceImpl(util, tableName, snapshotName, tableDir, numRegions,
174 numSplitsPerRegion, expectedNumSplits, shutdownCluster);
175 } finally {
176 tearDownCluster();
177 }
178 }
179
180 protected static void verifyRowFromMap(ImmutableBytesWritable key, Result result)
181 throws IOException {
182 byte[] row = key.get();
183 CellScanner scanner = result.cellScanner();
184 while (scanner.advance()) {
185 Cell cell = scanner.current();
186
187
188 Assert.assertEquals(0, Bytes.compareTo(row, 0, row.length,
189 cell.getRowArray(), cell.getRowOffset(), cell.getRowLength()));
190 }
191
192 for (int j = 0; j < FAMILIES.length; j++) {
193 byte[] actual = result.getValue(FAMILIES[j], FAMILIES[j]);
194 Assert.assertArrayEquals("Row in snapshot does not match, expected:" + Bytes.toString(row)
195 + " ,actual:" + Bytes.toString(actual), row, actual);
196 }
197 }
198
199 protected static void createTableAndSnapshot(HBaseTestingUtility util, TableName tableName,
200 String snapshotName, byte[] startRow, byte[] endRow, int numRegions)
201 throws Exception {
202 try {
203 LOG.debug("Ensuring table doesn't exist.");
204 util.deleteTable(tableName);
205 } catch(Exception ex) {
206
207 }
208
209 LOG.info("creating table '" + tableName + "'");
210 if (numRegions > 1) {
211 util.createTable(tableName, FAMILIES, 1, startRow, endRow, numRegions);
212 } else {
213 util.createTable(tableName, FAMILIES);
214 }
215 Admin admin = util.getHBaseAdmin();
216
217 LOG.info("put some stuff in the table");
218 HTable table = new HTable(util.getConfiguration(), tableName);
219 util.loadTable(table, FAMILIES);
220
221 Path rootDir = FSUtils.getRootDir(util.getConfiguration());
222 FileSystem fs = rootDir.getFileSystem(util.getConfiguration());
223
224 LOG.info("snapshot");
225 SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName,
226 Arrays.asList(FAMILIES), null, snapshotName, rootDir, fs, true);
227
228 LOG.info("load different values");
229 byte[] value = Bytes.toBytes("after_snapshot_value");
230 util.loadTable(table, FAMILIES, value);
231
232 LOG.info("cause flush to create new files in the region");
233 admin.flush(tableName);
234 table.close();
235 }
236
237 }