1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.client;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertTrue;
23
24 import com.google.common.collect.Lists;
25 import java.io.File;
26 import java.io.IOException;
27 import java.nio.file.Paths;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.UUID;
33 import org.apache.commons.io.FileUtils;
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.hadoop.conf.Configuration;
37 import org.apache.hadoop.fs.FileSystem;
38 import org.apache.hadoop.fs.Path;
39 import org.apache.hadoop.hbase.HBaseTestingUtility;
40 import org.apache.hadoop.hbase.HConstants;
41 import org.apache.hadoop.hbase.HTableDescriptor;
42 import org.apache.hadoop.hbase.TableName;
43 import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
44 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
45 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription.Type;
46 import org.apache.hadoop.hbase.regionserver.ConstantSizeRegionSplitPolicy;
47 import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
48 import org.apache.hadoop.hbase.snapshot.SnapshotDoesNotExistException;
49 import org.apache.hadoop.hbase.snapshot.SnapshotManifestV1;
50 import org.apache.hadoop.hbase.snapshot.SnapshotManifestV2;
51 import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils;
52 import org.apache.hadoop.hbase.testclassification.LargeTests;
53 import org.apache.hadoop.hbase.util.Bytes;
54 import org.apache.hadoop.hbase.util.FSUtils;
55 import org.junit.After;
56 import org.junit.AfterClass;
57 import org.junit.Before;
58 import org.junit.BeforeClass;
59 import org.junit.Test;
60 import org.junit.experimental.categories.Category;
61 import org.junit.runner.RunWith;
62 import org.junit.runners.Parameterized;
63
64
65
66
67
68
69
70 @Category(LargeTests.class)
71 @RunWith(Parameterized.class)
72 public class TestSnapshotTemporaryDirectory {
73
74 @Parameterized.Parameters public static Iterable<Integer> data() {
75 return Arrays
76 .asList(SnapshotManifestV1.DESCRIPTOR_VERSION, SnapshotManifestV2.DESCRIPTOR_VERSION);
77 }
78
79 @Parameterized.Parameter public int manifestVersion;
80
81 private static final Log LOG = LogFactory.getLog(TestSnapshotTemporaryDirectory.class);
82 protected static final int NUM_RS = 2;
83 protected static String TEMP_DIR =
84 Paths.get("").toAbsolutePath().toString() + Path.SEPARATOR + UUID.randomUUID().toString();
85
86 protected static Admin admin;
87 protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
88 protected static final String STRING_TABLE_NAME = "test";
89 protected static final byte[] TEST_FAM = Bytes.toBytes("fam");
90 protected static final TableName TABLE_NAME = TableName.valueOf(STRING_TABLE_NAME);
91
92
93
94
95
96
97 @BeforeClass public static void setupCluster() throws Exception {
98 setupConf(UTIL.getConfiguration());
99 UTIL.startMiniCluster(NUM_RS);
100 admin = UTIL.getHBaseAdmin();
101 }
102
103 private static void setupConf(Configuration conf) {
104
105 conf.setInt("hbase.regionsever.info.port", -1);
106
107 conf.setInt("hbase.hregion.memstore.flush.size", 25000);
108
109
110 conf.setInt("hbase.hstore.compaction.min", 10);
111 conf.setInt("hbase.hstore.compactionThreshold", 10);
112
113 conf.setInt("hbase.hstore.blockingStoreFiles", 12);
114
115 conf.setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true);
116 conf.set(HConstants.HBASE_REGION_SPLIT_POLICY_KEY,
117 ConstantSizeRegionSplitPolicy.class.getName());
118 conf.set(SnapshotDescriptionUtils.SNAPSHOT_WORKING_DIR, "file://" + new Path(TEMP_DIR, ".tmpDir").toUri());
119 }
120
121 @Before public void setup() throws Exception {
122 HTableDescriptor htd = new HTableDescriptor(TABLE_NAME);
123 htd.setRegionReplication(getNumReplicas());
124 UTIL.createTable(htd, new byte[][] { TEST_FAM }, UTIL.getConfiguration());
125 }
126
127 protected int getNumReplicas() {
128 return 1;
129 }
130
131 @After public void tearDown() throws Exception {
132 UTIL.deleteTable(TABLE_NAME);
133 SnapshotTestingUtils.deleteAllSnapshots(UTIL.getHBaseAdmin());
134 SnapshotTestingUtils.deleteArchiveDirectory(UTIL);
135 }
136
137 @AfterClass public static void cleanupTest() {
138 try {
139 UTIL.shutdownMiniCluster();
140 FileUtils.deleteDirectory(new File(TEMP_DIR));
141 } catch (Exception e) {
142 LOG.warn("failure shutting down cluster", e);
143 }
144 }
145
146 @Test(timeout = 180000) public void testRestoreDisabledSnapshot()
147 throws IOException, InterruptedException {
148 long tid = System.currentTimeMillis();
149 TableName tableName = TableName.valueOf("testtb-" + tid);
150 byte[] emptySnapshot = Bytes.toBytes("emptySnaptb-" + tid);
151 byte[] snapshotName0 = Bytes.toBytes("snaptb0-" + tid);
152 byte[] snapshotName1 = Bytes.toBytes("snaptb1-" + tid);
153 int snapshot0Rows;
154 int snapshot1Rows;
155
156
157 SnapshotTestingUtils.createTable(UTIL, tableName, getNumReplicas(), TEST_FAM);
158 admin.disableTable(tableName);
159
160
161 takeSnapshot(tableName, Bytes.toString(emptySnapshot), true);
162
163
164 admin.enableTable(tableName);
165 SnapshotTestingUtils.loadData(UTIL, tableName, 500, TEST_FAM);
166 try (Table table = UTIL.getConnection().getTable(tableName)) {
167 snapshot0Rows = UTIL.countRows(table);
168 }
169 admin.disableTable(tableName);
170
171
172 takeSnapshot(tableName, Bytes.toString(snapshotName0), true);
173
174
175 admin.enableTable(tableName);
176 SnapshotTestingUtils.loadData(UTIL, tableName, 500, TEST_FAM);
177 try (Table table = UTIL.getConnection().getTable(tableName)) {
178 snapshot1Rows = UTIL.countRows(table);
179 }
180
181 SnapshotTestingUtils.verifyRowCount(UTIL, tableName, snapshot1Rows);
182 admin.disableTable(tableName);
183 takeSnapshot(tableName, Bytes.toString(snapshotName1), true);
184
185
186 admin.restoreSnapshot(snapshotName0);
187 admin.enableTable(tableName);
188 SnapshotTestingUtils.verifyRowCount(UTIL, tableName, snapshot0Rows);
189 SnapshotTestingUtils.verifyReplicasCameOnline(tableName, admin, getNumReplicas());
190
191
192 admin.disableTable(tableName);
193 admin.restoreSnapshot(emptySnapshot);
194 admin.enableTable(tableName);
195 SnapshotTestingUtils.verifyRowCount(UTIL, tableName, 0);
196 SnapshotTestingUtils.verifyReplicasCameOnline(tableName, admin, getNumReplicas());
197
198
199 admin.disableTable(tableName);
200 admin.restoreSnapshot(snapshotName1);
201 admin.enableTable(tableName);
202 SnapshotTestingUtils.verifyRowCount(UTIL, tableName, snapshot1Rows);
203 SnapshotTestingUtils.verifyReplicasCameOnline(tableName, admin, getNumReplicas());
204
205
206 UTIL.deleteTable(tableName);
207 admin.restoreSnapshot(snapshotName1);
208 SnapshotTestingUtils.verifyRowCount(UTIL, tableName, snapshot1Rows);
209 SnapshotTestingUtils.verifyReplicasCameOnline(tableName, admin, getNumReplicas());
210 }
211
212 @Test(timeout = 180000) public void testRestoreEnabledSnapshot()
213 throws IOException, InterruptedException {
214 long tid = System.currentTimeMillis();
215 TableName tableName = TableName.valueOf("testtb-" + tid);
216 byte[] emptySnapshot = Bytes.toBytes("emptySnaptb-" + tid);
217 byte[] snapshotName0 = Bytes.toBytes("snaptb0-" + tid);
218 byte[] snapshotName1 = Bytes.toBytes("snaptb1-" + tid);
219 int snapshot0Rows;
220 int snapshot1Rows;
221
222
223 SnapshotTestingUtils.createTable(UTIL, tableName, getNumReplicas(), TEST_FAM);
224
225
226 takeSnapshot(tableName, Bytes.toString(emptySnapshot), false);
227
228
229 SnapshotTestingUtils.loadData(UTIL, tableName, 500, TEST_FAM);
230 try (Table table = UTIL.getConnection().getTable(tableName)) {
231 snapshot0Rows = UTIL.countRows(table);
232 }
233
234
235 takeSnapshot(tableName, Bytes.toString(snapshotName0), false);
236
237
238 SnapshotTestingUtils.loadData(UTIL, tableName, 500, TEST_FAM);
239 try (Table table = UTIL.getConnection().getTable(tableName)) {
240 snapshot1Rows = UTIL.countRows(table);
241 }
242
243 SnapshotTestingUtils.verifyRowCount(UTIL, tableName, snapshot1Rows);
244 takeSnapshot(tableName, Bytes.toString(snapshotName1), false);
245
246
247 admin.disableTable(tableName);
248 admin.restoreSnapshot(snapshotName0);
249 admin.enableTable(tableName);
250 SnapshotTestingUtils.verifyRowCount(UTIL, tableName, snapshot0Rows);
251 SnapshotTestingUtils.verifyReplicasCameOnline(tableName, admin, getNumReplicas());
252
253
254 admin.disableTable(tableName);
255 admin.restoreSnapshot(emptySnapshot);
256 admin.enableTable(tableName);
257 SnapshotTestingUtils.verifyRowCount(UTIL, tableName, 0);
258 SnapshotTestingUtils.verifyReplicasCameOnline(tableName, admin, getNumReplicas());
259
260
261 admin.disableTable(tableName);
262 admin.restoreSnapshot(snapshotName1);
263 admin.enableTable(tableName);
264 SnapshotTestingUtils.verifyRowCount(UTIL, tableName, snapshot1Rows);
265 SnapshotTestingUtils.verifyReplicasCameOnline(tableName, admin, getNumReplicas());
266
267
268 UTIL.deleteTable(tableName);
269 admin.restoreSnapshot(snapshotName1);
270 SnapshotTestingUtils.verifyRowCount(UTIL, tableName, snapshot1Rows);
271 SnapshotTestingUtils.verifyReplicasCameOnline(tableName, admin, getNumReplicas());
272 }
273
274
275
276
277
278
279 @Test(timeout = 300000) public void testOfflineTableSnapshot() throws Exception {
280 Admin admin = UTIL.getHBaseAdmin();
281
282 SnapshotTestingUtils.assertNoSnapshots(admin);
283
284
285 Table table = UTIL.getConnection().getTable(TABLE_NAME);
286 UTIL.loadTable(table, TEST_FAM, false);
287
288 LOG.debug("FS state before disable:");
289 FSUtils
290 .logFileSystemState(UTIL.getTestFileSystem(), FSUtils.getRootDir(UTIL.getConfiguration()),
291 LOG);
292
293
294 admin.disableTable(TABLE_NAME);
295
296 LOG.debug("FS state before snapshot:");
297 FSUtils
298 .logFileSystemState(UTIL.getTestFileSystem(), FSUtils.getRootDir(UTIL.getConfiguration()),
299 LOG);
300
301
302 final String SNAPSHOT_NAME = "offlineTableSnapshot";
303 byte[] snapshot = Bytes.toBytes(SNAPSHOT_NAME);
304 takeSnapshot(TABLE_NAME, SNAPSHOT_NAME, true);
305 LOG.debug("Snapshot completed.");
306
307
308 List<SnapshotDescription> snapshots =
309 SnapshotTestingUtils.assertOneSnapshotThatMatches(admin, snapshot, TABLE_NAME);
310
311
312 FileSystem fs = UTIL.getHBaseCluster().getMaster().getMasterFileSystem().getFileSystem();
313 Path rootDir = UTIL.getHBaseCluster().getMaster().getMasterFileSystem().getRootDir();
314 LOG.debug("FS state after snapshot:");
315 FSUtils
316 .logFileSystemState(UTIL.getTestFileSystem(), FSUtils.getRootDir(UTIL.getConfiguration()),
317 LOG);
318
319 SnapshotTestingUtils
320 .confirmSnapshotValid(snapshots.get(0), TABLE_NAME, TEST_FAM, rootDir, admin, fs);
321
322 admin.deleteSnapshot(snapshot);
323 SnapshotTestingUtils.assertNoSnapshots(admin);
324 }
325
326
327
328
329
330
331
332 @Test(timeout = 180000) public void testSnapshotCloneContents() throws Exception {
333
334 SnapshotTestingUtils.assertNoSnapshots(admin);
335
336
337 Table table = UTIL.getConnection().getTable(TABLE_NAME);
338 UTIL.loadTable(table, TEST_FAM);
339 table.close();
340
341 String snapshot1 = "TableSnapshot1";
342 takeSnapshot(TABLE_NAME, snapshot1, false);
343 LOG.debug("Snapshot1 completed.");
344
345 TableName clone = TableName.valueOf("Table1Clone");
346 admin.cloneSnapshot(snapshot1, clone, false);
347
348 Scan original = new Scan();
349 Scan cloned = new Scan();
350 ResultScanner originalScan = admin.getConnection().getTable(TABLE_NAME).getScanner(original);
351 ResultScanner clonedScan =
352 admin.getConnection().getTable(TableName.valueOf("Table1Clone")).getScanner(cloned);
353
354 Iterator<Result> i = originalScan.iterator();
355 Iterator<Result> i2 = clonedScan.iterator();
356 assertTrue(i.hasNext());
357 while (i.hasNext()) {
358 assertTrue(i2.hasNext());
359 assertEquals(Bytes.toString(i.next().getValue(TEST_FAM, new byte[] {})),
360 Bytes.toString(i2.next().getValue(TEST_FAM, new byte[] {})));
361 }
362 assertFalse(i2.hasNext());
363 admin.deleteSnapshot(snapshot1);
364 UTIL.deleteTable(clone);
365 admin.close();
366 }
367
368 @Test(timeout = 180000) public void testOfflineTableSnapshotWithEmptyRegion() throws Exception {
369
370
371
372 SnapshotTestingUtils.assertNoSnapshots(admin);
373
374 LOG.debug("FS state before disable:");
375 FSUtils
376 .logFileSystemState(UTIL.getTestFileSystem(), FSUtils.getRootDir(UTIL.getConfiguration()),
377 LOG);
378 admin.disableTable(TABLE_NAME);
379
380 LOG.debug("FS state before snapshot:");
381 FSUtils
382 .logFileSystemState(UTIL.getTestFileSystem(), FSUtils.getRootDir(UTIL.getConfiguration()),
383 LOG);
384
385
386 byte[] snapshot = Bytes.toBytes("testOfflineTableSnapshotWithEmptyRegion");
387 takeSnapshot(TABLE_NAME, Bytes.toString(snapshot), true);
388 LOG.debug("Snapshot completed.");
389
390
391 List<SnapshotDescription> snapshots =
392 SnapshotTestingUtils.assertOneSnapshotThatMatches(admin, snapshot, TABLE_NAME);
393
394
395 FileSystem fs = UTIL.getHBaseCluster().getMaster().getMasterFileSystem().getFileSystem();
396 Path rootDir = UTIL.getHBaseCluster().getMaster().getMasterFileSystem().getRootDir();
397 LOG.debug("FS state after snapshot:");
398 FSUtils
399 .logFileSystemState(UTIL.getTestFileSystem(), FSUtils.getRootDir(UTIL.getConfiguration()),
400 LOG);
401
402 List<byte[]> emptyCfs = Lists.newArrayList(TEST_FAM);
403 List<byte[]> nonEmptyCfs = Lists.newArrayList();
404 SnapshotTestingUtils
405 .confirmSnapshotValid(snapshots.get(0), TABLE_NAME, nonEmptyCfs, emptyCfs, rootDir,
406 admin, fs);
407
408 admin.deleteSnapshot(snapshot);
409 SnapshotTestingUtils.assertNoSnapshots(admin);
410 }
411
412
413 @Test(timeout = 180000) public void testEnsureTemporaryDirectoryTransfer() throws Exception {
414 Admin admin = null;
415 TableName tableName2 = TableName.valueOf("testListTableSnapshots");
416 try {
417 admin = UTIL.getHBaseAdmin();
418
419 HTableDescriptor htd = new HTableDescriptor(tableName2);
420 UTIL.createTable(htd, new byte[][] { TEST_FAM }, UTIL.getConfiguration());
421
422 String table1Snapshot1 = "Table1Snapshot1";
423 takeSnapshot(TABLE_NAME, table1Snapshot1, false);
424 LOG.debug("Snapshot1 completed.");
425
426 String table1Snapshot2 = "Table1Snapshot2";
427 takeSnapshot(TABLE_NAME, table1Snapshot2, false);
428 LOG.debug("Snapshot2 completed.");
429
430 String table2Snapshot1 = "Table2Snapshot1";
431 takeSnapshot(TABLE_NAME, table2Snapshot1, false);
432 LOG.debug("Table2Snapshot1 completed.");
433
434 List<SnapshotDescription> listTableSnapshots = admin.listTableSnapshots("test.*", ".*");
435 List<String> listTableSnapshotNames = new ArrayList<String>();
436 assertEquals(3, listTableSnapshots.size());
437 for (SnapshotDescription s : listTableSnapshots) {
438 listTableSnapshotNames.add(s.getName());
439 }
440 assertTrue(listTableSnapshotNames.contains(table1Snapshot1));
441 assertTrue(listTableSnapshotNames.contains(table1Snapshot2));
442 assertTrue(listTableSnapshotNames.contains(table2Snapshot1));
443 } finally {
444 if (admin != null) {
445 try {
446 admin.deleteSnapshots("Table.*");
447 } catch (SnapshotDoesNotExistException ignore) {
448 }
449 if (admin.tableExists(tableName2)) {
450 UTIL.deleteTable(tableName2);
451 }
452 admin.close();
453 }
454 }
455 }
456
457 private void takeSnapshot(TableName tableName, String snapshotName, boolean disabled)
458 throws IOException {
459 Type type = disabled ? Type.DISABLED : Type.FLUSH;
460 SnapshotDescription desc = SnapshotDescription.newBuilder()
461 .setTable(tableName.getNameAsString())
462 .setName(snapshotName)
463 .setVersion(manifestVersion)
464 .setType(type)
465 .build();
466 admin.snapshot(desc);
467 }
468 }