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);
503 new FSTableDescriptors(conf)
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 SnapshotDescriptionUtils.completeSnapshot(desc, rootDir, snapshotDir, fs);
628 snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(desc, rootDir);
629 return snapshotDir;
630 }
631
632 public void consolidate() throws IOException {
633 ForeignExceptionDispatcher monitor = new ForeignExceptionDispatcher(desc.getName());
634 SnapshotManifest manifest = SnapshotManifest.create(conf, fs, snapshotDir, desc, monitor);
635 manifest.addTableDescriptor(htd);
636 manifest.consolidate();
637 }
638 }
639
640 public SnapshotMock(final Configuration conf, final FileSystem fs, final Path rootDir) {
641 this.fs = fs;
642 this.conf = conf;
643 this.rootDir = rootDir;
644 }
645
646 public SnapshotBuilder createSnapshotV1(final String snapshotName, final String tableName)
647 throws IOException {
648 return createSnapshot(snapshotName, tableName, SnapshotManifestV1.DESCRIPTOR_VERSION);
649 }
650
651 public SnapshotBuilder createSnapshotV1(final String snapshotName, final String tableName,
652 final int numRegions) throws IOException {
653 return createSnapshot(snapshotName, tableName, numRegions, SnapshotManifestV1.DESCRIPTOR_VERSION);
654 }
655
656 public SnapshotBuilder createSnapshotV2(final String snapshotName, final String tableName)
657 throws IOException {
658 return createSnapshot(snapshotName, tableName, SnapshotManifestV2.DESCRIPTOR_VERSION);
659 }
660
661 public SnapshotBuilder createSnapshotV2(final String snapshotName, final String tableName,
662 final int numRegions) throws IOException {
663 return createSnapshot(snapshotName, tableName, numRegions, SnapshotManifestV2.DESCRIPTOR_VERSION);
664 }
665
666 private SnapshotBuilder createSnapshot(final String snapshotName, final String tableName,
667 final int version) throws IOException {
668 return createSnapshot(snapshotName, tableName, TEST_NUM_REGIONS, version);
669 }
670
671 private SnapshotBuilder createSnapshot(final String snapshotName, final String tableName,
672 final int numRegions, final int version) throws IOException {
673 HTableDescriptor htd = createHtd(tableName);
674 RegionData[] regions = createTable(htd, numRegions);
675
676 SnapshotDescription desc = SnapshotDescription.newBuilder()
677 .setTable(htd.getNameAsString())
678 .setName(snapshotName)
679 .setVersion(version)
680 .build();
681
682 Path workingDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(desc, rootDir);
683 SnapshotDescriptionUtils.writeSnapshotInfo(desc, workingDir, fs);
684 return new SnapshotBuilder(conf, fs, rootDir, htd, desc, regions);
685 }
686
687 public HTableDescriptor createHtd(final String tableName) {
688 HTableDescriptor htd = new HTableDescriptor(tableName);
689 htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
690 return htd;
691 }
692
693 private RegionData[] createTable(final HTableDescriptor htd, final int nregions)
694 throws IOException {
695 Path tableDir = FSUtils.getTableDir(rootDir, htd.getTableName());
696 new FSTableDescriptors(conf).createTableDescriptorForTableDirectory(tableDir, htd, false);
697
698 assertTrue(nregions % 2 == 0);
699 RegionData[] regions = new RegionData[nregions];
700 for (int i = 0; i < regions.length; i += 2) {
701 byte[] startKey = Bytes.toBytes(0 + i * 2);
702 byte[] endKey = Bytes.toBytes(1 + i * 2);
703
704
705 HRegionInfo hri = new HRegionInfo(htd.getTableName(), startKey, endKey);
706 HRegionFileSystem rfs = HRegionFileSystem.createRegionOnFileSystem(conf, fs, tableDir, hri);
707 regions[i] = new RegionData(tableDir, hri, 3);
708 for (int j = 0; j < regions[i].files.length; ++j) {
709 Path storeFile = createStoreFile(rfs.createTempName());
710 regions[i].files[j] = rfs.commitStoreFile(TEST_FAMILY, storeFile);
711 }
712
713
714
715 startKey = Bytes.toBytes(2 + i * 2);
716 endKey = Bytes.toBytes(3 + i * 2);
717 hri = new HRegionInfo(htd.getTableName());
718 rfs = HRegionFileSystem.createRegionOnFileSystem(conf, fs, tableDir, hri);
719 regions[i+1] = new RegionData(tableDir, hri, regions[i].files.length);
720 for (int j = 0; j < regions[i].files.length; ++j) {
721 String refName = regions[i].files[j].getName() + '.' + regions[i].hri.getEncodedName();
722 Path refFile = createStoreFile(new Path(rootDir, refName));
723 regions[i+1].files[j] = rfs.commitStoreFile(TEST_FAMILY, refFile);
724 }
725 }
726 return regions;
727 }
728
729 private Path createStoreFile(final Path storeFile)
730 throws IOException {
731 FSDataOutputStream out = fs.create(storeFile);
732 try {
733 out.write(Bytes.toBytes(storeFile.toString()));
734 } finally {
735 out.close();
736 }
737 return storeFile;
738 }
739 }
740
741
742
743
744 public static void waitForTableToBeOnline(final HBaseTestingUtility util,
745 final TableName tableName)
746 throws IOException, InterruptedException {
747 HRegionServer rs = util.getRSForFirstRegionInTable(tableName);
748 List<Region> onlineRegions = rs.getOnlineRegions(tableName);
749 for (Region region : onlineRegions) {
750 region.waitForFlushesAndCompactions();
751 }
752
753 util.waitFor(60000, util.predicateTableAvailable(tableName));
754 }
755
756 public static void createTable(final HBaseTestingUtility util, final TableName tableName,
757 int regionReplication, final byte[]... families) throws IOException, InterruptedException {
758 HTableDescriptor htd = new HTableDescriptor(tableName);
759 htd.setRegionReplication(regionReplication);
760 for (byte[] family : families) {
761 HColumnDescriptor hcd = new HColumnDescriptor(family);
762 htd.addFamily(hcd);
763 }
764 byte[][] splitKeys = getSplitKeys();
765 util.createTable(htd, splitKeys);
766 assertEquals((splitKeys.length + 1) * regionReplication,
767 util.getHBaseAdmin().getTableRegions(tableName).size());
768 }
769
770 public static byte[][] getSplitKeys() {
771 byte[][] splitKeys = new byte[KEYS.length-2][];
772 for (int i = 0; i < splitKeys.length; ++i) {
773 splitKeys[i] = new byte[] { KEYS[i+1] };
774 }
775 return splitKeys;
776 }
777
778 public static void createTable(final HBaseTestingUtility util, final TableName tableName,
779 final byte[]... families) throws IOException, InterruptedException {
780 createTable(util, tableName, 1, families);
781 }
782
783 public static void loadData(final HBaseTestingUtility util, final TableName tableName, int rows,
784 byte[]... families) throws IOException, InterruptedException {
785 try (BufferedMutator mutator = util.getConnection().getBufferedMutator(tableName)) {
786 loadData(util, mutator, rows, families);
787 }
788 }
789
790 public static void loadData(final HBaseTestingUtility util, final BufferedMutator mutator, int rows,
791 byte[]... families) throws IOException, InterruptedException {
792
793 assertTrue(rows >= KEYS.length);
794 for (byte k0: KEYS) {
795 byte[] k = new byte[] { k0 };
796 byte[] value = Bytes.add(Bytes.toBytes(System.currentTimeMillis()), k);
797 byte[] key = Bytes.add(k, Bytes.toBytes(MD5Hash.getMD5AsHex(value)));
798 final byte[][] families1 = families;
799 final byte[] key1 = key;
800 final byte[] value1 = value;
801 mutator.mutate(createPut(families1, key1, value1));
802 rows--;
803 }
804
805
806 while (rows-- > 0) {
807 byte[] value = Bytes.add(Bytes.toBytes(System.currentTimeMillis()), Bytes.toBytes(rows));
808 byte[] key = Bytes.toBytes(MD5Hash.getMD5AsHex(value));
809 final byte[][] families1 = families;
810 final byte[] key1 = key;
811 final byte[] value1 = value;
812 mutator.mutate(createPut(families1, key1, value1));
813 }
814 mutator.flush();
815
816 waitForTableToBeOnline(util, mutator.getName());
817 }
818
819 private static Put createPut(final byte[][] families, final byte[] key, final byte[] value) {
820 byte[] q = Bytes.toBytes("q");
821 Put put = new Put(key);
822 put.setDurability(Durability.SKIP_WAL);
823 for (byte[] family: families) {
824 put.add(family, q, value);
825 }
826 return put;
827 }
828
829 public static void deleteAllSnapshots(final Admin admin)
830 throws IOException {
831
832 for (SnapshotDescription snapshot: admin.listSnapshots()) {
833 admin.deleteSnapshot(snapshot.getName());
834 }
835 SnapshotTestingUtils.assertNoSnapshots(admin);
836 }
837
838 public static void deleteArchiveDirectory(final HBaseTestingUtility util)
839 throws IOException {
840
841 MasterFileSystem mfs = util.getMiniHBaseCluster().getMaster().getMasterFileSystem();
842 Path archiveDir = new Path(mfs.getRootDir(), HConstants.HFILE_ARCHIVE_DIRECTORY);
843 mfs.getFileSystem().delete(archiveDir, true);
844 }
845
846 public static void verifyRowCount(final HBaseTestingUtility util, final TableName tableName,
847 long expectedRows) throws IOException {
848 Table table = new HTable(util.getConfiguration(), tableName);
849 try {
850 assertEquals(expectedRows, util.countRows(table));
851 } finally {
852 table.close();
853 }
854 }
855
856 public static void verifyReplicasCameOnline(TableName tableName, Admin admin,
857 int regionReplication) throws IOException {
858 List<HRegionInfo> regions = admin.getTableRegions(tableName);
859 HashSet<HRegionInfo> set = new HashSet<HRegionInfo>();
860 for (HRegionInfo hri : regions) {
861 set.add(RegionReplicaUtil.getRegionInfoForDefaultReplica(hri));
862 for (int i = 0; i < regionReplication; i++) {
863 HRegionInfo replica = RegionReplicaUtil.getRegionInfoForReplica(hri, i);
864 if (!regions.contains(replica)) {
865 Assert.fail(replica + " is not contained in the list of online regions");
866 }
867 }
868 }
869 assert(set.size() == getSplitKeys().length + 1);
870 }
871 }