1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.snapshot;
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 java.io.IOException;
25 import java.util.Collections;
26 import java.util.ArrayList;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Set;
31 import java.util.TreeSet;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.hadoop.conf.Configuration;
36 import org.apache.hadoop.fs.FSDataOutputStream;
37 import org.apache.hadoop.fs.FileSystem;
38 import org.apache.hadoop.fs.FileStatus;
39 import org.apache.hadoop.fs.FSDataInputStream;
40 import org.apache.hadoop.fs.Path;
41 import org.apache.hadoop.fs.PathFilter;
42 import org.apache.hadoop.hbase.HBaseTestingUtility;
43 import org.apache.hadoop.hbase.HColumnDescriptor;
44 import org.apache.hadoop.hbase.HConstants;
45 import org.apache.hadoop.hbase.HRegionInfo;
46 import org.apache.hadoop.hbase.HTableDescriptor;
47 import org.apache.hadoop.hbase.TableName;
48 import org.apache.hadoop.hbase.TableNotEnabledException;
49 import org.apache.hadoop.hbase.classification.InterfaceAudience;
50 import org.apache.hadoop.hbase.client.Admin;
51 import org.apache.hadoop.hbase.client.BufferedMutator;
52 import org.apache.hadoop.hbase.client.Durability;
53 import org.apache.hadoop.hbase.client.HTable;
54 import org.apache.hadoop.hbase.client.Put;
55 import org.apache.hadoop.hbase.client.Table;
56 import org.apache.hadoop.hbase.errorhandling.ForeignExceptionDispatcher;
57 import org.apache.hadoop.hbase.client.RegionReplicaUtil;
58 import org.apache.hadoop.hbase.io.HFileLink;
59 import org.apache.hadoop.hbase.master.HMaster;
60 import org.apache.hadoop.hbase.master.MasterFileSystem;
61 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
62 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
63 import org.apache.hadoop.hbase.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;
64 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsSnapshotDoneRequest;
65 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsSnapshotDoneResponse;
66 import org.apache.hadoop.hbase.regionserver.HRegionFileSystem;
67 import org.apache.hadoop.hbase.regionserver.HRegionServer;
68 import org.apache.hadoop.hbase.regionserver.Region;
69 import org.apache.hadoop.hbase.util.Bytes;
70 import org.apache.hadoop.hbase.util.FSTableDescriptors;
71 import org.apache.hadoop.hbase.util.FSVisitor;
72 import org.apache.hadoop.hbase.util.FSUtils;
73 import org.apache.hadoop.hbase.util.MD5Hash;
74 import org.junit.Assert;
75
76 import com.google.protobuf.ServiceException;
77
78
79
80
81 @InterfaceAudience.Private
82 public final class SnapshotTestingUtils {
83
84 private static final Log LOG = LogFactory.getLog(SnapshotTestingUtils.class);
85 private static byte[] KEYS = Bytes.toBytes("0123456789");
86
87 private SnapshotTestingUtils() {
88
89 }
90
91
92
93
94
95
96
97 public static void assertNoSnapshots(Admin admin) throws IOException {
98 assertEquals("Have some previous snapshots", 0, admin.listSnapshots()
99 .size());
100 }
101
102
103
104
105
106 public static List<SnapshotDescription> assertExistsMatchingSnapshot(
107 Admin admin, String snapshotName, TableName tableName)
108 throws IOException {
109
110 List<SnapshotDescription> snapshots = admin.listSnapshots();
111
112 List<SnapshotDescription> returnedSnapshots = new ArrayList<SnapshotDescription>();
113 for (SnapshotDescription sd : snapshots) {
114 if (snapshotName.equals(sd.getName()) &&
115 tableName.equals(TableName.valueOf(sd.getTable()))) {
116 returnedSnapshots.add(sd);
117 }
118 }
119
120 Assert.assertTrue("No matching snapshots found.", returnedSnapshots.size()>0);
121 return returnedSnapshots;
122 }
123
124
125
126
127 public static void assertOneSnapshotThatMatches(Admin admin,
128 SnapshotDescription snapshot) throws IOException {
129 assertOneSnapshotThatMatches(admin, snapshot.getName(),
130 TableName.valueOf(snapshot.getTable()));
131 }
132
133
134
135
136
137 public static List<SnapshotDescription> assertOneSnapshotThatMatches(
138 Admin admin, String snapshotName, TableName tableName)
139 throws IOException {
140
141 List<SnapshotDescription> snapshots = admin.listSnapshots();
142
143 assertEquals("Should only have 1 snapshot", 1, snapshots.size());
144 assertEquals(snapshotName, snapshots.get(0).getName());
145 assertEquals(tableName, TableName.valueOf(snapshots.get(0).getTable()));
146
147 return snapshots;
148 }
149
150
151
152
153
154 public static List<SnapshotDescription> assertOneSnapshotThatMatches(
155 Admin admin, byte[] snapshot, TableName tableName) throws IOException {
156 return assertOneSnapshotThatMatches(admin, Bytes.toString(snapshot),
157 tableName);
158 }
159
160 public static void confirmSnapshotValid(HBaseTestingUtility testUtil,
161 SnapshotDescription snapshotDescriptor, TableName tableName, byte[] family)
162 throws IOException {
163 MasterFileSystem mfs = testUtil.getHBaseCluster().getMaster().getMasterFileSystem();
164 confirmSnapshotValid(snapshotDescriptor, tableName, family,
165 mfs.getRootDir(), testUtil.getHBaseAdmin(), mfs.getFileSystem());
166 }
167
168
169
170
171
172 public static void confirmSnapshotValid(
173 SnapshotDescription snapshotDescriptor, TableName tableName,
174 byte[] testFamily, Path rootDir, Admin admin, FileSystem fs)
175 throws IOException {
176 ArrayList nonEmptyTestFamilies = new ArrayList(1);
177 nonEmptyTestFamilies.add(testFamily);
178 confirmSnapshotValid(snapshotDescriptor, tableName,
179 nonEmptyTestFamilies, null, rootDir, admin, fs);
180 }
181
182
183
184
185 public static void confirmEmptySnapshotValid(
186 SnapshotDescription snapshotDescriptor, TableName tableName,
187 byte[] testFamily, Path rootDir, Admin admin, FileSystem fs)
188 throws IOException {
189 ArrayList emptyTestFamilies = new ArrayList(1);
190 emptyTestFamilies.add(testFamily);
191 confirmSnapshotValid(snapshotDescriptor, tableName,
192 null, emptyTestFamilies, rootDir, admin, fs);
193 }
194
195
196
197
198
199
200
201 public static void confirmSnapshotValid(
202 SnapshotDescription snapshotDescriptor, TableName tableName,
203 List<byte[]> nonEmptyTestFamilies, List<byte[]> emptyTestFamilies,
204 Path rootDir, Admin admin, FileSystem fs) throws IOException {
205 final Configuration conf = admin.getConfiguration();
206
207
208 Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(
209 snapshotDescriptor, rootDir);
210 assertTrue("target snapshot directory, '"+ snapshotDir +"', doesn't exist.", fs.exists(snapshotDir));
211
212 SnapshotDescription desc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);
213
214
215 final Set<byte[]> snapshotFamilies = new TreeSet<byte[]>(Bytes.BYTES_COMPARATOR);
216
217 SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, desc);
218 Map<String, SnapshotRegionManifest> regionManifests = manifest.getRegionManifestsMap();
219 for (SnapshotRegionManifest regionManifest: regionManifests.values()) {
220 SnapshotReferenceUtil.visitRegionStoreFiles(regionManifest,
221 new SnapshotReferenceUtil.StoreFileVisitor() {
222 @Override
223 public void storeFile(final HRegionInfo regionInfo, final String family,
224 final SnapshotRegionManifest.StoreFile storeFile) throws IOException {
225 snapshotFamilies.add(Bytes.toBytes(family));
226 }
227 });
228 }
229
230
231 if (nonEmptyTestFamilies != null) {
232 for (final byte[] familyName: nonEmptyTestFamilies) {
233 assertTrue("Expected snapshot to contain family '" + Bytes.toString(familyName) + "', but it does not.", snapshotFamilies.contains(familyName));
234 }
235 }
236
237
238 if (emptyTestFamilies != null) {
239 for (final byte[] familyName: emptyTestFamilies) {
240 assertFalse("Expected snapshot to skip empty family '" + Bytes.toString(familyName) + "', but it is present.", snapshotFamilies.contains(familyName));
241 }
242 }
243
244
245 List<HRegionInfo> regions = admin.getTableRegions(tableName);
246
247 RegionReplicaUtil.removeNonDefaultRegions(regions);
248
249
250
251 int regionCountExclusiveSplitParent = 0;
252 for (SnapshotRegionManifest snapshotRegionManifest : regionManifests.values()) {
253 HRegionInfo hri = HRegionInfo.convert(snapshotRegionManifest.getRegionInfo());
254 if (hri.isOffline() && (hri.isSplit() || hri.isSplitParent())) {
255 continue;
256 }
257 regionCountExclusiveSplitParent++;
258 }
259 assertEquals("Wrong number of regions.", regions.size(), regionCountExclusiveSplitParent);
260
261
262 for (HRegionInfo info : regions) {
263 String regionName = info.getEncodedName();
264 assertTrue("Missing region name: '" + regionName + "'", regionManifests.containsKey(regionName));
265 }
266 }
267
268
269
270
271
272
273
274
275
276
277 public static void waitForSnapshotToComplete(HMaster master, SnapshotDescription snapshot,
278 long sleep) throws ServiceException {
279 final IsSnapshotDoneRequest request = IsSnapshotDoneRequest.newBuilder()
280 .setSnapshot(snapshot).build();
281 IsSnapshotDoneResponse done = IsSnapshotDoneResponse.newBuilder()
282 .buildPartial();
283 while (!done.getDone()) {
284 done = master.getMasterRpcServices().isSnapshotDone(null, request);
285 try {
286 Thread.sleep(sleep);
287 } catch (InterruptedException e) {
288 throw new ServiceException(e);
289 }
290 }
291 }
292
293
294
295
296
297 public static void snapshot(Admin admin,
298 final String snapshotName, final String tableName,
299 SnapshotDescription.Type type, int numTries) throws IOException {
300 int tries = 0;
301 CorruptedSnapshotException lastEx = null;
302 while (tries++ < numTries) {
303 try {
304 admin.snapshot(snapshotName, TableName.valueOf(tableName), type);
305 return;
306 } catch (CorruptedSnapshotException cse) {
307 LOG.warn("Got CorruptedSnapshotException", cse);
308 lastEx = cse;
309 }
310 }
311 throw lastEx;
312 }
313
314 public static void cleanupSnapshot(Admin admin, byte[] tableName)
315 throws IOException {
316 SnapshotTestingUtils.cleanupSnapshot(admin, Bytes.toString(tableName));
317 }
318
319 public static void cleanupSnapshot(Admin admin, String snapshotName)
320 throws IOException {
321
322 admin.deleteSnapshot(snapshotName);
323 assertNoSnapshots(admin);
324 }
325
326
327
328
329
330
331
332
333
334 public static void expectSnapshotDoneException(HMaster master,
335 IsSnapshotDoneRequest snapshot,
336 Class<? extends HBaseSnapshotException> clazz) {
337 try {
338 master.getMasterRpcServices().isSnapshotDone(null, snapshot);
339 Assert.fail("didn't fail to lookup a snapshot");
340 } catch (ServiceException se) {
341 try {
342 throw ProtobufUtil.getRemoteException(se);
343 } catch (HBaseSnapshotException e) {
344 assertEquals("Threw wrong snapshot exception!", clazz, e.getClass());
345 } catch (Throwable t) {
346 Assert.fail("Threw an unexpected exception:" + t);
347 }
348 }
349 }
350
351
352
353
354
355
356
357
358
359 public static ArrayList<String> listHFileNames(final FileSystem fs, final Path tableDir)
360 throws IOException {
361 final ArrayList<String> hfiles = new ArrayList<String>();
362 FSVisitor.visitTableStoreFiles(fs, tableDir, new FSVisitor.StoreFileVisitor() {
363 @Override
364 public void storeFile(final String region, final String family, final String hfileName)
365 throws IOException {
366 hfiles.add(hfileName);
367 }
368 });
369 Collections.sort(hfiles);
370 return hfiles;
371 }
372
373
374
375
376
377
378 public static void createSnapshotAndValidate(Admin admin,
379 TableName tableName, String familyName, String snapshotNameString,
380 Path rootDir, FileSystem fs, boolean onlineSnapshot)
381 throws Exception {
382 ArrayList<byte[]> nonEmptyFamilyNames = new ArrayList<byte[]>(1);
383 nonEmptyFamilyNames.add(Bytes.toBytes(familyName));
384 createSnapshotAndValidate(admin, tableName, nonEmptyFamilyNames,
385 snapshotNameString, rootDir, fs, onlineSnapshot);
386 }
387
388
389
390
391
392 public static void createSnapshotAndValidate(Admin admin,
393 TableName tableName, List<byte[]> nonEmptyFamilyNames, List<byte[]> emptyFamilyNames,
394 String snapshotNameString, Path rootDir, FileSystem fs, boolean onlineSnapshot)
395 throws Exception {
396 if (!onlineSnapshot) {
397 try {
398 LOG.info("prepping for offline snapshot.");
399 admin.disableTable(tableName);
400 } catch (TableNotEnabledException tne) {
401 LOG.info("In attempting to disable " + tableName + " it turns out that the this table is " +
402 "already disabled.");
403 }
404 }
405 LOG.info("taking snapshot.");
406 admin.snapshot(snapshotNameString, tableName);
407
408 LOG.info("Confirming snapshot exists.");
409 List<SnapshotDescription> snapshots = SnapshotTestingUtils.assertExistsMatchingSnapshot(admin,
410 snapshotNameString, tableName);
411 if (snapshots == null || snapshots.size() != 1) {
412 Assert.fail("Incorrect number of snapshots for table " + tableName);
413 }
414
415 LOG.info("validating snapshot.");
416 SnapshotTestingUtils.confirmSnapshotValid(snapshots.get(0), tableName, nonEmptyFamilyNames,
417 emptyFamilyNames, rootDir, admin, fs);
418 }
419
420
421
422
423
424
425
426
427
428 public static ArrayList corruptSnapshot(final HBaseTestingUtility util, final String snapshotName)
429 throws IOException {
430 final MasterFileSystem mfs = util.getHBaseCluster().getMaster().getMasterFileSystem();
431 final FileSystem fs = mfs.getFileSystem();
432
433 Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName,
434 mfs.getRootDir());
435 SnapshotDescription snapshotDesc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);
436 final TableName table = TableName.valueOf(snapshotDesc.getTable());
437
438 final ArrayList corruptedFiles = new ArrayList();
439 final Configuration conf = util.getConfiguration();
440 SnapshotReferenceUtil.visitTableStoreFiles(conf, fs, snapshotDir, snapshotDesc,
441 new SnapshotReferenceUtil.StoreFileVisitor() {
442 @Override
443 public void storeFile(final HRegionInfo regionInfo, final String family,
444 final SnapshotRegionManifest.StoreFile storeFile) throws IOException {
445 String region = regionInfo.getEncodedName();
446 String hfile = storeFile.getName();
447 HFileLink link = HFileLink.build(conf, table, region, family, hfile);
448 if (corruptedFiles.size() % 2 == 0) {
449 fs.delete(link.getAvailablePath(fs), true);
450 corruptedFiles.add(hfile);
451 }
452 }
453 });
454
455 assertTrue(corruptedFiles.size() > 0);
456 return corruptedFiles;
457 }
458
459
460
461
462 public static class SnapshotMock {
463 private final static String TEST_FAMILY = "cf";
464 public final static int TEST_NUM_REGIONS = 4;
465
466 private final Configuration conf;
467 private final FileSystem fs;
468 private final Path rootDir;
469
470 static class RegionData {
471 public HRegionInfo hri;
472 public Path tableDir;
473 public Path[] files;
474
475 public RegionData(final Path tableDir, final HRegionInfo hri, final int nfiles) {
476 this.tableDir = tableDir;
477 this.hri = hri;
478 this.files = new Path[nfiles];
479 }
480 }
481
482 public static class SnapshotBuilder {
483 private final RegionData[] tableRegions;
484 private final SnapshotDescription desc;
485 private final HTableDescriptor htd;
486 private final Configuration conf;
487 private final FileSystem fs;
488 private final Path rootDir;
489 private Path snapshotDir;
490 private int snapshotted = 0;
491
492 public SnapshotBuilder(final Configuration conf, final FileSystem fs,
493 final Path rootDir, final HTableDescriptor htd,
494 final SnapshotDescription desc, final RegionData[] tableRegions)
495 throws IOException {
496 this.fs = fs;
497 this.conf = conf;
498 this.rootDir = rootDir;
499 this.htd = htd;
500 this.desc = desc;
501 this.tableRegions = tableRegions;
502 this.snapshotDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(desc, rootDir, conf);
503 new FSTableDescriptors(conf, snapshotDir.getFileSystem(conf), rootDir)
504 .createTableDescriptorForTableDirectory(snapshotDir, htd, false);
505 }
506
507 public HTableDescriptor getTableDescriptor() {
508 return this.htd;
509 }
510
511 public SnapshotDescription getSnapshotDescription() {
512 return this.desc;
513 }
514
515 public Path getSnapshotsDir() {
516 return this.snapshotDir;
517 }
518
519 public Path[] addRegion() throws IOException {
520 return addRegion(desc);
521 }
522
523 public Path[] addRegionV1() throws IOException {
524 return addRegion(desc.toBuilder()
525 .setVersion(SnapshotManifestV1.DESCRIPTOR_VERSION)
526 .build());
527 }
528
529 public Path[] addRegionV2() throws IOException {
530 return addRegion(desc.toBuilder()
531 .setVersion(SnapshotManifestV2.DESCRIPTOR_VERSION)
532 .build());
533 }
534
535 private Path[] addRegion(final SnapshotDescription desc) throws IOException {
536 if (this.snapshotted == tableRegions.length) {
537 throw new UnsupportedOperationException("No more regions in the table");
538 }
539
540 RegionData regionData = tableRegions[this.snapshotted++];
541 ForeignExceptionDispatcher monitor = new ForeignExceptionDispatcher(desc.getName());
542 SnapshotManifest manifest = SnapshotManifest.create(conf, fs, snapshotDir, desc, monitor);
543 manifest.addRegion(regionData.tableDir, regionData.hri);
544 return regionData.files;
545 }
546
547 private void corruptFile(Path p) throws IOException {
548 String manifestName = p.getName();
549
550
551 Path newP = new Path(p.getParent(), manifestName + "1");
552 fs.rename(p, newP);
553
554
555 FSDataOutputStream out = fs.create(p);
556
557
558
559 FSDataInputStream input = fs.open(newP);
560 byte[] buffer = new byte[25];
561 int len = input.read(0, buffer, 0, 25);
562 if (len > 1) {
563 out.write(buffer, 0, len - 1);
564 }
565 out.close();
566
567
568 fs.delete(newP);
569 }
570
571
572
573
574
575
576 public void corruptOneRegionManifest() throws IOException {
577 FileStatus[] manifestFiles = FSUtils.listStatus(fs, snapshotDir, new PathFilter() {
578 @Override public boolean accept(Path path) {
579 return path.getName().startsWith(SnapshotManifestV2.SNAPSHOT_MANIFEST_PREFIX);
580 }
581 });
582
583 if (manifestFiles.length == 0) return;
584
585
586 Path p = manifestFiles[0].getPath();
587 corruptFile(p);
588 }
589
590 public void missOneRegionSnapshotFile() throws IOException {
591 FileStatus[] manifestFiles = FSUtils.listStatus(fs, snapshotDir);
592 for (FileStatus fileStatus : manifestFiles) {
593 String fileName = fileStatus.getPath().getName();
594 if (fileName.endsWith(SnapshotDescriptionUtils.SNAPSHOTINFO_FILE)
595 || fileName.endsWith(".tabledesc")
596 || fileName.endsWith(SnapshotDescriptionUtils.SNAPSHOT_TMP_DIR_NAME)) {
597 fs.delete(fileStatus.getPath(), true);
598 }
599 }
600 }
601
602
603
604
605
606
607 public void corruptDataManifest() throws IOException {
608 FileStatus[] manifestFiles = FSUtils.listStatus(fs, snapshotDir, new PathFilter() {
609 @Override
610 public boolean accept(Path path) {
611 return path.getName().startsWith(SnapshotManifest.DATA_MANIFEST_NAME);
612 }
613 });
614
615 if (manifestFiles.length == 0) return;
616
617
618 Path p = manifestFiles[0].getPath();
619 corruptFile(p);
620 }
621
622 public Path commit() throws IOException {
623 ForeignExceptionDispatcher monitor = new ForeignExceptionDispatcher(desc.getName());
624 SnapshotManifest manifest = SnapshotManifest.create(conf, fs, snapshotDir, desc, monitor);
625 manifest.addTableDescriptor(htd);
626 manifest.consolidate();
627 Path workingDir = snapshotDir;
628 Path completedSnapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(desc, rootDir);
629 SnapshotDescriptionUtils.completeSnapshot(completedSnapshotDir, workingDir, fs,
630 workingDir.getFileSystem(conf), conf);
631 snapshotDir = completedSnapshotDir;
632 return snapshotDir;
633 }
634
635 public void consolidate() throws IOException {
636 ForeignExceptionDispatcher monitor = new ForeignExceptionDispatcher(desc.getName());
637 SnapshotManifest manifest = SnapshotManifest.create(conf, fs, snapshotDir, desc, monitor);
638 manifest.addTableDescriptor(htd);
639 manifest.consolidate();
640 }
641 }
642
643 public SnapshotMock(final Configuration conf, final FileSystem fs, final Path rootDir) {
644 this.fs = fs;
645 this.conf = conf;
646 this.rootDir = rootDir;
647 }
648
649 public SnapshotBuilder createSnapshotV1(final String snapshotName, final String tableName)
650 throws IOException {
651 return createSnapshot(snapshotName, tableName, SnapshotManifestV1.DESCRIPTOR_VERSION);
652 }
653
654 public SnapshotBuilder createSnapshotV1(final String snapshotName, final String tableName,
655 final int numRegions) throws IOException {
656 return createSnapshot(snapshotName, tableName, numRegions, SnapshotManifestV1.DESCRIPTOR_VERSION);
657 }
658
659 public SnapshotBuilder createSnapshotV2(final String snapshotName, final String tableName)
660 throws IOException {
661 return createSnapshot(snapshotName, tableName, SnapshotManifestV2.DESCRIPTOR_VERSION);
662 }
663
664 public SnapshotBuilder createSnapshotV2(final String snapshotName, final String tableName,
665 final int numRegions) throws IOException {
666 return createSnapshot(snapshotName, tableName, numRegions, SnapshotManifestV2.DESCRIPTOR_VERSION);
667 }
668
669 private SnapshotBuilder createSnapshot(final String snapshotName, final String tableName,
670 final int version) throws IOException {
671 return createSnapshot(snapshotName, tableName, TEST_NUM_REGIONS, version);
672 }
673
674 private SnapshotBuilder createSnapshot(final String snapshotName, final String tableName,
675 final int numRegions, final int version) throws IOException {
676 HTableDescriptor htd = createHtd(tableName);
677 RegionData[] regions = createTable(htd, numRegions);
678
679 SnapshotDescription desc = SnapshotDescription.newBuilder()
680 .setTable(htd.getNameAsString())
681 .setName(snapshotName)
682 .setVersion(version)
683 .build();
684
685 Path workingDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(desc, rootDir, conf);
686 SnapshotDescriptionUtils.writeSnapshotInfo(desc, workingDir, workingDir.getFileSystem(conf));
687 return new SnapshotBuilder(conf, fs, rootDir, htd, desc, regions);
688 }
689
690 public HTableDescriptor createHtd(final String tableName) {
691 HTableDescriptor htd = new HTableDescriptor(tableName);
692 htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
693 return htd;
694 }
695
696 private RegionData[] createTable(final HTableDescriptor htd, final int nregions)
697 throws IOException {
698 Path tableDir = FSUtils.getTableDir(rootDir, htd.getTableName());
699 new FSTableDescriptors(conf).createTableDescriptorForTableDirectory(tableDir, htd, false);
700
701 assertTrue(nregions % 2 == 0);
702 RegionData[] regions = new RegionData[nregions];
703 for (int i = 0; i < regions.length; i += 2) {
704 byte[] startKey = Bytes.toBytes(0 + i * 2);
705 byte[] endKey = Bytes.toBytes(1 + i * 2);
706
707
708 HRegionInfo hri = new HRegionInfo(htd.getTableName(), startKey, endKey);
709 HRegionFileSystem rfs = HRegionFileSystem.createRegionOnFileSystem(conf, fs, tableDir, hri);
710 regions[i] = new RegionData(tableDir, hri, 3);
711 for (int j = 0; j < regions[i].files.length; ++j) {
712 Path storeFile = createStoreFile(rfs.createTempName());
713 regions[i].files[j] = rfs.commitStoreFile(TEST_FAMILY, storeFile);
714 }
715
716
717
718 startKey = Bytes.toBytes(2 + i * 2);
719 endKey = Bytes.toBytes(3 + i * 2);
720 hri = new HRegionInfo(htd.getTableName());
721 rfs = HRegionFileSystem.createRegionOnFileSystem(conf, fs, tableDir, hri);
722 regions[i+1] = new RegionData(tableDir, hri, regions[i].files.length);
723 for (int j = 0; j < regions[i].files.length; ++j) {
724 String refName = regions[i].files[j].getName() + '.' + regions[i].hri.getEncodedName();
725 Path refFile = createStoreFile(new Path(rootDir, refName));
726 regions[i+1].files[j] = rfs.commitStoreFile(TEST_FAMILY, refFile);
727 }
728 }
729 return regions;
730 }
731
732 private Path createStoreFile(final Path storeFile)
733 throws IOException {
734 FSDataOutputStream out = fs.create(storeFile);
735 try {
736 out.write(Bytes.toBytes(storeFile.toString()));
737 } finally {
738 out.close();
739 }
740 return storeFile;
741 }
742 }
743
744
745
746
747 public static void waitForTableToBeOnline(final HBaseTestingUtility util,
748 final TableName tableName)
749 throws IOException, InterruptedException {
750 HRegionServer rs = util.getRSForFirstRegionInTable(tableName);
751 List<Region> onlineRegions = rs.getOnlineRegions(tableName);
752 for (Region region : onlineRegions) {
753 region.waitForFlushesAndCompactions();
754 }
755
756 util.waitFor(60000, util.predicateTableAvailable(tableName));
757 }
758
759 public static void createTable(final HBaseTestingUtility util, final TableName tableName,
760 int regionReplication, final byte[]... families) throws IOException, InterruptedException {
761 HTableDescriptor htd = new HTableDescriptor(tableName);
762 htd.setRegionReplication(regionReplication);
763 for (byte[] family : families) {
764 HColumnDescriptor hcd = new HColumnDescriptor(family);
765 htd.addFamily(hcd);
766 }
767 byte[][] splitKeys = getSplitKeys();
768 util.createTable(htd, splitKeys);
769 assertEquals((splitKeys.length + 1) * regionReplication,
770 util.getHBaseAdmin().getTableRegions(tableName).size());
771 }
772
773 public static byte[][] getSplitKeys() {
774 byte[][] splitKeys = new byte[KEYS.length-2][];
775 for (int i = 0; i < splitKeys.length; ++i) {
776 splitKeys[i] = new byte[] { KEYS[i+1] };
777 }
778 return splitKeys;
779 }
780
781 public static void createTable(final HBaseTestingUtility util, final TableName tableName,
782 final byte[]... families) throws IOException, InterruptedException {
783 createTable(util, tableName, 1, families);
784 }
785
786 public static void loadData(final HBaseTestingUtility util, final TableName tableName, int rows,
787 byte[]... families) throws IOException, InterruptedException {
788 try (BufferedMutator mutator = util.getConnection().getBufferedMutator(tableName)) {
789 loadData(util, mutator, rows, families);
790 }
791 }
792
793 public static void loadData(final HBaseTestingUtility util, final BufferedMutator mutator, int rows,
794 byte[]... families) throws IOException, InterruptedException {
795
796 assertTrue(rows >= KEYS.length);
797 for (byte k0: KEYS) {
798 byte[] k = new byte[] { k0 };
799 byte[] value = Bytes.add(Bytes.toBytes(System.currentTimeMillis()), k);
800 byte[] key = Bytes.add(k, Bytes.toBytes(MD5Hash.getMD5AsHex(value)));
801 final byte[][] families1 = families;
802 final byte[] key1 = key;
803 final byte[] value1 = value;
804 mutator.mutate(createPut(families1, key1, value1));
805 rows--;
806 }
807
808
809 while (rows-- > 0) {
810 byte[] value = Bytes.add(Bytes.toBytes(System.currentTimeMillis()), Bytes.toBytes(rows));
811 byte[] key = Bytes.toBytes(MD5Hash.getMD5AsHex(value));
812 final byte[][] families1 = families;
813 final byte[] key1 = key;
814 final byte[] value1 = value;
815 mutator.mutate(createPut(families1, key1, value1));
816 }
817 mutator.flush();
818
819 waitForTableToBeOnline(util, mutator.getName());
820 }
821
822 private static Put createPut(final byte[][] families, final byte[] key, final byte[] value) {
823 byte[] q = Bytes.toBytes("q");
824 Put put = new Put(key);
825 put.setDurability(Durability.SKIP_WAL);
826 for (byte[] family: families) {
827 put.add(family, q, value);
828 }
829 return put;
830 }
831
832 public static void deleteAllSnapshots(final Admin admin)
833 throws IOException {
834
835 for (SnapshotDescription snapshot: admin.listSnapshots()) {
836 admin.deleteSnapshot(snapshot.getName());
837 }
838 SnapshotTestingUtils.assertNoSnapshots(admin);
839 }
840
841 public static void deleteArchiveDirectory(final HBaseTestingUtility util)
842 throws IOException {
843
844 MasterFileSystem mfs = util.getMiniHBaseCluster().getMaster().getMasterFileSystem();
845 Path archiveDir = new Path(mfs.getRootDir(), HConstants.HFILE_ARCHIVE_DIRECTORY);
846 mfs.getFileSystem().delete(archiveDir, true);
847 }
848
849 public static void verifyRowCount(final HBaseTestingUtility util, final TableName tableName,
850 long expectedRows) throws IOException {
851 Table table = new HTable(util.getConfiguration(), tableName);
852 try {
853 assertEquals(expectedRows, util.countRows(table));
854 } finally {
855 table.close();
856 }
857 }
858
859 public static void verifyReplicasCameOnline(TableName tableName, Admin admin,
860 int regionReplication) throws IOException {
861 List<HRegionInfo> regions = admin.getTableRegions(tableName);
862 HashSet<HRegionInfo> set = new HashSet<HRegionInfo>();
863 for (HRegionInfo hri : regions) {
864 set.add(RegionReplicaUtil.getRegionInfoForDefaultReplica(hri));
865 for (int i = 0; i < regionReplication; i++) {
866 HRegionInfo replica = RegionReplicaUtil.getRegionInfoForReplica(hri, i);
867 if (!regions.contains(replica)) {
868 Assert.fail(replica + " is not contained in the list of online regions");
869 }
870 }
871 }
872 assert(set.size() == getSplitKeys().length + 1);
873 }
874 }