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(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(snapshotFamilies.contains(familyName));
234 }
235 }
236
237
238 if (emptyTestFamilies != null) {
239 for (final byte[] familyName: emptyTestFamilies) {
240 assertFalse(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(regions.size(), regionCountExclusiveSplitParent);
260
261
262 for (HRegionInfo info : regions) {
263 String regionName = info.getEncodedName();
264 assertTrue(regionManifests.containsKey(regionName));
265 }
266 }
267
268
269
270
271
272
273
274
275
276
277 public static void waitForSnapshotToComplete(HMaster master,
278 SnapshotDescription snapshot, 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 admin.disableTable(tableName);
399 } catch (TableNotEnabledException tne) {
400 LOG.info("In attempting to disable " + tableName + " it turns out that the this table is " +
401 "already disabled.");
402 }
403 }
404 admin.snapshot(snapshotNameString, tableName);
405
406 List<SnapshotDescription> snapshots = SnapshotTestingUtils.assertExistsMatchingSnapshot(admin,
407 snapshotNameString, tableName);
408 if (snapshots == null || snapshots.size() != 1) {
409 Assert.fail("Incorrect number of snapshots for table " + tableName);
410 }
411
412 SnapshotTestingUtils.confirmSnapshotValid(snapshots.get(0), tableName, nonEmptyFamilyNames,
413 emptyFamilyNames, rootDir, admin, fs);
414 }
415
416
417
418
419
420
421
422
423
424 public static ArrayList corruptSnapshot(final HBaseTestingUtility util, final String snapshotName)
425 throws IOException {
426 final MasterFileSystem mfs = util.getHBaseCluster().getMaster().getMasterFileSystem();
427 final FileSystem fs = mfs.getFileSystem();
428
429 Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName,
430 mfs.getRootDir());
431 SnapshotDescription snapshotDesc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);
432 final TableName table = TableName.valueOf(snapshotDesc.getTable());
433
434 final ArrayList corruptedFiles = new ArrayList();
435 final Configuration conf = util.getConfiguration();
436 SnapshotReferenceUtil.visitTableStoreFiles(conf, fs, snapshotDir, snapshotDesc,
437 new SnapshotReferenceUtil.StoreFileVisitor() {
438 @Override
439 public void storeFile(final HRegionInfo regionInfo, final String family,
440 final SnapshotRegionManifest.StoreFile storeFile) throws IOException {
441 String region = regionInfo.getEncodedName();
442 String hfile = storeFile.getName();
443 HFileLink link = HFileLink.build(conf, table, region, family, hfile);
444 if (corruptedFiles.size() % 2 == 0) {
445 fs.delete(link.getAvailablePath(fs), true);
446 corruptedFiles.add(hfile);
447 }
448 }
449 });
450
451 assertTrue(corruptedFiles.size() > 0);
452 return corruptedFiles;
453 }
454
455
456
457
458 public static class SnapshotMock {
459 private final static String TEST_FAMILY = "cf";
460 public final static int TEST_NUM_REGIONS = 4;
461
462 private final Configuration conf;
463 private final FileSystem fs;
464 private final Path rootDir;
465
466 static class RegionData {
467 public HRegionInfo hri;
468 public Path tableDir;
469 public Path[] files;
470
471 public RegionData(final Path tableDir, final HRegionInfo hri, final int nfiles) {
472 this.tableDir = tableDir;
473 this.hri = hri;
474 this.files = new Path[nfiles];
475 }
476 }
477
478 public static class SnapshotBuilder {
479 private final RegionData[] tableRegions;
480 private final SnapshotDescription desc;
481 private final HTableDescriptor htd;
482 private final Configuration conf;
483 private final FileSystem fs;
484 private final Path rootDir;
485 private Path snapshotDir;
486 private int snapshotted = 0;
487
488 public SnapshotBuilder(final Configuration conf, final FileSystem fs,
489 final Path rootDir, final HTableDescriptor htd,
490 final SnapshotDescription desc, final RegionData[] tableRegions)
491 throws IOException {
492 this.fs = fs;
493 this.conf = conf;
494 this.rootDir = rootDir;
495 this.htd = htd;
496 this.desc = desc;
497 this.tableRegions = tableRegions;
498 this.snapshotDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(desc, rootDir);
499 new FSTableDescriptors(conf)
500 .createTableDescriptorForTableDirectory(snapshotDir, htd, false);
501 }
502
503 public HTableDescriptor getTableDescriptor() {
504 return this.htd;
505 }
506
507 public SnapshotDescription getSnapshotDescription() {
508 return this.desc;
509 }
510
511 public Path getSnapshotsDir() {
512 return this.snapshotDir;
513 }
514
515 public Path[] addRegion() throws IOException {
516 return addRegion(desc);
517 }
518
519 public Path[] addRegionV1() throws IOException {
520 return addRegion(desc.toBuilder()
521 .setVersion(SnapshotManifestV1.DESCRIPTOR_VERSION)
522 .build());
523 }
524
525 public Path[] addRegionV2() throws IOException {
526 return addRegion(desc.toBuilder()
527 .setVersion(SnapshotManifestV2.DESCRIPTOR_VERSION)
528 .build());
529 }
530
531 private Path[] addRegion(final SnapshotDescription desc) throws IOException {
532 if (this.snapshotted == tableRegions.length) {
533 throw new UnsupportedOperationException("No more regions in the table");
534 }
535
536 RegionData regionData = tableRegions[this.snapshotted++];
537 ForeignExceptionDispatcher monitor = new ForeignExceptionDispatcher(desc.getName());
538 SnapshotManifest manifest = SnapshotManifest.create(conf, fs, snapshotDir, desc, monitor);
539 manifest.addRegion(regionData.tableDir, regionData.hri);
540 return regionData.files;
541 }
542
543 private void corruptFile(Path p) throws IOException {
544 String manifestName = p.getName();
545
546
547 Path newP = new Path(p.getParent(), manifestName + "1");
548 fs.rename(p, newP);
549
550
551 FSDataOutputStream out = fs.create(p);
552
553
554
555 FSDataInputStream input = fs.open(newP);
556 byte[] buffer = new byte[25];
557 int len = input.read(0, buffer, 0, 25);
558 if (len > 1) {
559 out.write(buffer, 0, len - 1);
560 }
561 out.close();
562
563
564 fs.delete(newP);
565 }
566
567
568
569
570
571
572 public void corruptOneRegionManifest() throws IOException {
573 FileStatus[] manifestFiles = FSUtils.listStatus(fs, snapshotDir, new PathFilter() {
574 @Override public boolean accept(Path path) {
575 return path.getName().startsWith(SnapshotManifestV2.SNAPSHOT_MANIFEST_PREFIX);
576 }
577 });
578
579 if (manifestFiles.length == 0) return;
580
581
582 Path p = manifestFiles[0].getPath();
583 corruptFile(p);
584 }
585
586 public void missOneRegionSnapshotFile() throws IOException {
587 FileStatus[] manifestFiles = FSUtils.listStatus(fs, snapshotDir);
588 for (FileStatus fileStatus : manifestFiles) {
589 String fileName = fileStatus.getPath().getName();
590 if (fileName.endsWith(SnapshotDescriptionUtils.SNAPSHOTINFO_FILE)
591 || fileName.endsWith(".tabledesc")
592 || fileName.endsWith(SnapshotDescriptionUtils.SNAPSHOT_TMP_DIR_NAME)) {
593 fs.delete(fileStatus.getPath(), true);
594 }
595 }
596 }
597
598
599
600
601
602
603 public void corruptDataManifest() throws IOException {
604 FileStatus[] manifestFiles = FSUtils.listStatus(fs, snapshotDir, new PathFilter() {
605 @Override
606 public boolean accept(Path path) {
607 return path.getName().startsWith(SnapshotManifest.DATA_MANIFEST_NAME);
608 }
609 });
610
611 if (manifestFiles.length == 0) return;
612
613
614 Path p = manifestFiles[0].getPath();
615 corruptFile(p);
616 }
617
618 public Path commit() throws IOException {
619 ForeignExceptionDispatcher monitor = new ForeignExceptionDispatcher(desc.getName());
620 SnapshotManifest manifest = SnapshotManifest.create(conf, fs, snapshotDir, desc, monitor);
621 manifest.addTableDescriptor(htd);
622 manifest.consolidate();
623 SnapshotDescriptionUtils.completeSnapshot(desc, rootDir, snapshotDir, fs);
624 snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(desc, rootDir);
625 return snapshotDir;
626 }
627
628 public void consolidate() throws IOException {
629 ForeignExceptionDispatcher monitor = new ForeignExceptionDispatcher(desc.getName());
630 SnapshotManifest manifest = SnapshotManifest.create(conf, fs, snapshotDir, desc, monitor);
631 manifest.addTableDescriptor(htd);
632 manifest.consolidate();
633 }
634 }
635
636 public SnapshotMock(final Configuration conf, final FileSystem fs, final Path rootDir) {
637 this.fs = fs;
638 this.conf = conf;
639 this.rootDir = rootDir;
640 }
641
642 public SnapshotBuilder createSnapshotV1(final String snapshotName, final String tableName)
643 throws IOException {
644 return createSnapshot(snapshotName, tableName, SnapshotManifestV1.DESCRIPTOR_VERSION);
645 }
646
647 public SnapshotBuilder createSnapshotV1(final String snapshotName, final String tableName,
648 final int numRegions) throws IOException {
649 return createSnapshot(snapshotName, tableName, numRegions, SnapshotManifestV1.DESCRIPTOR_VERSION);
650 }
651
652 public SnapshotBuilder createSnapshotV2(final String snapshotName, final String tableName)
653 throws IOException {
654 return createSnapshot(snapshotName, tableName, SnapshotManifestV2.DESCRIPTOR_VERSION);
655 }
656
657 public SnapshotBuilder createSnapshotV2(final String snapshotName, final String tableName,
658 final int numRegions) throws IOException {
659 return createSnapshot(snapshotName, tableName, numRegions, SnapshotManifestV2.DESCRIPTOR_VERSION);
660 }
661
662 private SnapshotBuilder createSnapshot(final String snapshotName, final String tableName,
663 final int version) throws IOException {
664 return createSnapshot(snapshotName, tableName, TEST_NUM_REGIONS, version);
665 }
666
667 private SnapshotBuilder createSnapshot(final String snapshotName, final String tableName,
668 final int numRegions, final int version) throws IOException {
669 HTableDescriptor htd = createHtd(tableName);
670 RegionData[] regions = createTable(htd, numRegions);
671
672 SnapshotDescription desc = SnapshotDescription.newBuilder()
673 .setTable(htd.getNameAsString())
674 .setName(snapshotName)
675 .setVersion(version)
676 .build();
677
678 Path workingDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(desc, rootDir);
679 SnapshotDescriptionUtils.writeSnapshotInfo(desc, workingDir, fs);
680 return new SnapshotBuilder(conf, fs, rootDir, htd, desc, regions);
681 }
682
683 public HTableDescriptor createHtd(final String tableName) {
684 HTableDescriptor htd = new HTableDescriptor(tableName);
685 htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
686 return htd;
687 }
688
689 private RegionData[] createTable(final HTableDescriptor htd, final int nregions)
690 throws IOException {
691 Path tableDir = FSUtils.getTableDir(rootDir, htd.getTableName());
692 new FSTableDescriptors(conf).createTableDescriptorForTableDirectory(tableDir, htd, false);
693
694 assertTrue(nregions % 2 == 0);
695 RegionData[] regions = new RegionData[nregions];
696 for (int i = 0; i < regions.length; i += 2) {
697 byte[] startKey = Bytes.toBytes(0 + i * 2);
698 byte[] endKey = Bytes.toBytes(1 + i * 2);
699
700
701 HRegionInfo hri = new HRegionInfo(htd.getTableName(), startKey, endKey);
702 HRegionFileSystem rfs = HRegionFileSystem.createRegionOnFileSystem(conf, fs, tableDir, hri);
703 regions[i] = new RegionData(tableDir, hri, 3);
704 for (int j = 0; j < regions[i].files.length; ++j) {
705 Path storeFile = createStoreFile(rfs.createTempName());
706 regions[i].files[j] = rfs.commitStoreFile(TEST_FAMILY, storeFile);
707 }
708
709
710
711 startKey = Bytes.toBytes(2 + i * 2);
712 endKey = Bytes.toBytes(3 + i * 2);
713 hri = new HRegionInfo(htd.getTableName());
714 rfs = HRegionFileSystem.createRegionOnFileSystem(conf, fs, tableDir, hri);
715 regions[i+1] = new RegionData(tableDir, hri, regions[i].files.length);
716 for (int j = 0; j < regions[i].files.length; ++j) {
717 String refName = regions[i].files[j].getName() + '.' + regions[i].hri.getEncodedName();
718 Path refFile = createStoreFile(new Path(rootDir, refName));
719 regions[i+1].files[j] = rfs.commitStoreFile(TEST_FAMILY, refFile);
720 }
721 }
722 return regions;
723 }
724
725 private Path createStoreFile(final Path storeFile)
726 throws IOException {
727 FSDataOutputStream out = fs.create(storeFile);
728 try {
729 out.write(Bytes.toBytes(storeFile.toString()));
730 } finally {
731 out.close();
732 }
733 return storeFile;
734 }
735 }
736
737
738
739
740 public static void waitForTableToBeOnline(final HBaseTestingUtility util,
741 final TableName tableName)
742 throws IOException, InterruptedException {
743 HRegionServer rs = util.getRSForFirstRegionInTable(tableName);
744 List<Region> onlineRegions = rs.getOnlineRegions(tableName);
745 for (Region region : onlineRegions) {
746 region.waitForFlushesAndCompactions();
747 }
748
749 util.waitFor(60000, util.predicateTableAvailable(tableName));
750 }
751
752 public static void createTable(final HBaseTestingUtility util, final TableName tableName,
753 int regionReplication, final byte[]... families) throws IOException, InterruptedException {
754 HTableDescriptor htd = new HTableDescriptor(tableName);
755 htd.setRegionReplication(regionReplication);
756 for (byte[] family : families) {
757 HColumnDescriptor hcd = new HColumnDescriptor(family);
758 htd.addFamily(hcd);
759 }
760 byte[][] splitKeys = getSplitKeys();
761 util.createTable(htd, splitKeys);
762 assertEquals((splitKeys.length + 1) * regionReplication,
763 util.getHBaseAdmin().getTableRegions(tableName).size());
764 }
765
766 public static byte[][] getSplitKeys() {
767 byte[][] splitKeys = new byte[KEYS.length-2][];
768 for (int i = 0; i < splitKeys.length; ++i) {
769 splitKeys[i] = new byte[] { KEYS[i+1] };
770 }
771 return splitKeys;
772 }
773
774 public static void createTable(final HBaseTestingUtility util, final TableName tableName,
775 final byte[]... families) throws IOException, InterruptedException {
776 createTable(util, tableName, 1, families);
777 }
778
779 public static void loadData(final HBaseTestingUtility util, final TableName tableName, int rows,
780 byte[]... families) throws IOException, InterruptedException {
781 try (BufferedMutator mutator = util.getConnection().getBufferedMutator(tableName)) {
782 loadData(util, mutator, rows, families);
783 }
784 }
785
786 public static void loadData(final HBaseTestingUtility util, final BufferedMutator mutator, int rows,
787 byte[]... families) throws IOException, InterruptedException {
788
789 assertTrue(rows >= KEYS.length);
790 for (byte k0: KEYS) {
791 byte[] k = new byte[] { k0 };
792 byte[] value = Bytes.add(Bytes.toBytes(System.currentTimeMillis()), k);
793 byte[] key = Bytes.add(k, Bytes.toBytes(MD5Hash.getMD5AsHex(value)));
794 final byte[][] families1 = families;
795 final byte[] key1 = key;
796 final byte[] value1 = value;
797 mutator.mutate(createPut(families1, key1, value1));
798 rows--;
799 }
800
801
802 while (rows-- > 0) {
803 byte[] value = Bytes.add(Bytes.toBytes(System.currentTimeMillis()), Bytes.toBytes(rows));
804 byte[] key = Bytes.toBytes(MD5Hash.getMD5AsHex(value));
805 final byte[][] families1 = families;
806 final byte[] key1 = key;
807 final byte[] value1 = value;
808 mutator.mutate(createPut(families1, key1, value1));
809 }
810 mutator.flush();
811
812 waitForTableToBeOnline(util, mutator.getName());
813 }
814
815 private static Put createPut(final byte[][] families, final byte[] key, final byte[] value) {
816 byte[] q = Bytes.toBytes("q");
817 Put put = new Put(key);
818 put.setDurability(Durability.SKIP_WAL);
819 for (byte[] family: families) {
820 put.add(family, q, value);
821 }
822 return put;
823 }
824
825 public static void deleteAllSnapshots(final Admin admin)
826 throws IOException {
827
828 for (SnapshotDescription snapshot: admin.listSnapshots()) {
829 admin.deleteSnapshot(snapshot.getName());
830 }
831 SnapshotTestingUtils.assertNoSnapshots(admin);
832 }
833
834 public static void deleteArchiveDirectory(final HBaseTestingUtility util)
835 throws IOException {
836
837 MasterFileSystem mfs = util.getMiniHBaseCluster().getMaster().getMasterFileSystem();
838 Path archiveDir = new Path(mfs.getRootDir(), HConstants.HFILE_ARCHIVE_DIRECTORY);
839 mfs.getFileSystem().delete(archiveDir, true);
840 }
841
842 public static void verifyRowCount(final HBaseTestingUtility util, final TableName tableName,
843 long expectedRows) throws IOException {
844 Table table = new HTable(util.getConfiguration(), tableName);
845 try {
846 assertEquals(expectedRows, util.countRows(table));
847 } finally {
848 table.close();
849 }
850 }
851
852 public static void verifyReplicasCameOnline(TableName tableName, Admin admin,
853 int regionReplication) throws IOException {
854 List<HRegionInfo> regions = admin.getTableRegions(tableName);
855 HashSet<HRegionInfo> set = new HashSet<HRegionInfo>();
856 for (HRegionInfo hri : regions) {
857 set.add(RegionReplicaUtil.getRegionInfoForDefaultReplica(hri));
858 for (int i = 0; i < regionReplication; i++) {
859 HRegionInfo replica = RegionReplicaUtil.getRegionInfoForReplica(hri, i);
860 if (!regions.contains(replica)) {
861 Assert.fail(replica + " is not contained in the list of online regions");
862 }
863 }
864 }
865 assert(set.size() == getSplitKeys().length + 1);
866 }
867 }