1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.snapshot;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.LinkedList;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.TreeMap;
34 import java.util.concurrent.ThreadPoolExecutor;
35
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.apache.hadoop.hbase.classification.InterfaceAudience;
39 import org.apache.hadoop.conf.Configuration;
40 import org.apache.hadoop.fs.FileStatus;
41 import org.apache.hadoop.fs.FileSystem;
42 import org.apache.hadoop.fs.Path;
43 import org.apache.hadoop.hbase.HRegionInfo;
44 import org.apache.hadoop.hbase.HTableDescriptor;
45 import org.apache.hadoop.hbase.TableName;
46 import org.apache.hadoop.hbase.backup.HFileArchiver;
47 import org.apache.hadoop.hbase.MetaTableAccessor;
48 import org.apache.hadoop.hbase.client.Connection;
49 import org.apache.hadoop.hbase.errorhandling.ForeignExceptionDispatcher;
50 import org.apache.hadoop.hbase.io.HFileLink;
51 import org.apache.hadoop.hbase.io.Reference;
52 import org.apache.hadoop.hbase.mob.MobUtils;
53 import org.apache.hadoop.hbase.monitoring.MonitoredTask;
54 import org.apache.hadoop.hbase.monitoring.TaskMonitor;
55 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
56 import org.apache.hadoop.hbase.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;
57 import org.apache.hadoop.hbase.regionserver.HRegion;
58 import org.apache.hadoop.hbase.regionserver.HRegionFileSystem;
59 import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
60 import org.apache.hadoop.hbase.util.Bytes;
61 import org.apache.hadoop.hbase.util.FSUtils;
62 import org.apache.hadoop.hbase.util.ModifyRegionUtils;
63 import org.apache.hadoop.hbase.util.Pair;
64 import org.apache.hadoop.io.IOUtils;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 @InterfaceAudience.Private
108 public class RestoreSnapshotHelper {
109 private static final Log LOG = LogFactory.getLog(RestoreSnapshotHelper.class);
110
111 private final Map<byte[], byte[]> regionsMap =
112 new TreeMap<byte[], byte[]>(Bytes.BYTES_COMPARATOR);
113
114 private final Map<String, Pair<String, String> > parentsMap =
115 new HashMap<String, Pair<String, String> >();
116
117 private final ForeignExceptionDispatcher monitor;
118 private final MonitoredTask status;
119
120 private final SnapshotManifest snapshotManifest;
121 private final SnapshotDescription snapshotDesc;
122 private final TableName snapshotTable;
123
124 private final HTableDescriptor tableDesc;
125 private final Path rootDir;
126 private final Path tableDir;
127
128 private final Configuration conf;
129 private final FileSystem fs;
130 private final boolean createBackRefs;
131
132 public RestoreSnapshotHelper(final Configuration conf,
133 final FileSystem fs,
134 final SnapshotManifest manifest,
135 final HTableDescriptor tableDescriptor,
136 final Path rootDir,
137 final ForeignExceptionDispatcher monitor,
138 final MonitoredTask status) {
139 this(conf, fs, manifest, tableDescriptor, rootDir, monitor, status, true);
140 }
141
142 public RestoreSnapshotHelper(final Configuration conf,
143 final FileSystem fs,
144 final SnapshotManifest manifest,
145 final HTableDescriptor tableDescriptor,
146 final Path rootDir,
147 final ForeignExceptionDispatcher monitor,
148 final MonitoredTask status,
149 final boolean createBackRefs)
150 {
151 this.fs = fs;
152 this.conf = conf;
153 this.snapshotManifest = manifest;
154 this.snapshotDesc = manifest.getSnapshotDescription();
155 this.snapshotTable = TableName.valueOf(snapshotDesc.getTable());
156 this.tableDesc = tableDescriptor;
157 this.rootDir = rootDir;
158 this.tableDir = FSUtils.getTableDir(rootDir, tableDesc.getTableName());
159 this.monitor = monitor;
160 this.status = status;
161 this.createBackRefs = createBackRefs;
162 }
163
164
165
166
167
168 public RestoreMetaChanges restoreHdfsRegions() throws IOException {
169 ThreadPoolExecutor exec = SnapshotManifest.createExecutor(conf, "RestoreSnapshot");
170 try {
171 return restoreHdfsRegions(exec);
172 } finally {
173 exec.shutdown();
174 }
175 }
176
177 private RestoreMetaChanges restoreHdfsRegions(final ThreadPoolExecutor exec) throws IOException {
178 LOG.debug("starting restore");
179
180 Map<String, SnapshotRegionManifest> regionManifests = snapshotManifest.getRegionManifestsMap();
181 if (regionManifests == null) {
182 LOG.warn("Nothing to restore. Snapshot " + snapshotDesc + " looks empty");
183 return null;
184 }
185
186 RestoreMetaChanges metaChanges = new RestoreMetaChanges(tableDesc, parentsMap);
187
188
189
190 Set<String> regionNames = new HashSet<String>(regionManifests.keySet());
191
192 HRegionInfo mobRegion = MobUtils.getMobRegionInfo(snapshotManifest.getTableDescriptor()
193 .getTableName());
194
195
196 List<HRegionInfo> tableRegions = getTableRegions();
197 if (tableRegions != null) {
198 monitor.rethrowException();
199 for (HRegionInfo regionInfo: tableRegions) {
200 String regionName = regionInfo.getEncodedName();
201 if (regionNames.contains(regionName)) {
202 LOG.info("region to restore: " + regionName);
203 regionNames.remove(regionName);
204 metaChanges.addRegionToRestore(regionInfo);
205 } else {
206 LOG.info("region to remove: " + regionName);
207 metaChanges.addRegionToRemove(regionInfo);
208 }
209 }
210
211
212 monitor.rethrowException();
213 status.setStatus("Restoring table regions...");
214 if (regionNames.contains(mobRegion.getEncodedName())) {
215
216 List<HRegionInfo> mobRegions = new ArrayList<HRegionInfo>(1);
217 mobRegions.add(mobRegion);
218 restoreHdfsMobRegions(exec, regionManifests, mobRegions);
219 regionNames.remove(mobRegion.getEncodedName());
220 }
221 restoreHdfsRegions(exec, regionManifests, metaChanges.getRegionsToRestore());
222 status.setStatus("Finished restoring all table regions.");
223
224
225 monitor.rethrowException();
226 status.setStatus("Starting to delete excess regions from table");
227 removeHdfsRegions(exec, metaChanges.getRegionsToRemove());
228 status.setStatus("Finished deleting excess regions from table.");
229 }
230
231
232 if (regionNames.size() > 0) {
233 List<HRegionInfo> regionsToAdd = new ArrayList<HRegionInfo>(regionNames.size());
234
235 monitor.rethrowException();
236
237 if (regionNames.contains(mobRegion.getEncodedName())) {
238 cloneHdfsMobRegion(regionManifests, mobRegion);
239 regionNames.remove(mobRegion.getEncodedName());
240 }
241 for (String regionName: regionNames) {
242 LOG.info("region to add: " + regionName);
243 regionsToAdd.add(HRegionInfo.convert(regionManifests.get(regionName).getRegionInfo()));
244 }
245
246
247 monitor.rethrowException();
248 status.setStatus("Cloning regions...");
249 HRegionInfo[] clonedRegions = cloneHdfsRegions(exec, regionManifests, regionsToAdd);
250 metaChanges.setNewRegions(clonedRegions);
251 status.setStatus("Finished cloning regions.");
252 }
253
254 return metaChanges;
255 }
256
257
258
259
260 public static class RestoreMetaChanges {
261 private final Map<String, Pair<String, String> > parentsMap;
262 private final HTableDescriptor htd;
263
264 private List<HRegionInfo> regionsToRestore = null;
265 private List<HRegionInfo> regionsToRemove = null;
266 private List<HRegionInfo> regionsToAdd = null;
267
268 RestoreMetaChanges(HTableDescriptor htd, Map<String, Pair<String, String> > parentsMap) {
269 this.parentsMap = parentsMap;
270 this.htd = htd;
271 }
272
273 public HTableDescriptor getTableDescriptor() {
274 return htd;
275 }
276
277
278
279
280 public boolean hasRegionsToAdd() {
281 return this.regionsToAdd != null && this.regionsToAdd.size() > 0;
282 }
283
284
285
286
287
288
289
290 public List<HRegionInfo> getRegionsToAdd() {
291 return this.regionsToAdd;
292 }
293
294
295
296
297 public boolean hasRegionsToRestore() {
298 return this.regionsToRestore != null && this.regionsToRestore.size() > 0;
299 }
300
301
302
303
304
305
306 public List<HRegionInfo> getRegionsToRestore() {
307 return this.regionsToRestore;
308 }
309
310
311
312
313 public boolean hasRegionsToRemove() {
314 return this.regionsToRemove != null && this.regionsToRemove.size() > 0;
315 }
316
317
318
319
320
321
322
323 public List<HRegionInfo> getRegionsToRemove() {
324 return this.regionsToRemove;
325 }
326
327 void setNewRegions(final HRegionInfo[] hris) {
328 if (hris != null) {
329 regionsToAdd = Arrays.asList(hris);
330 } else {
331 regionsToAdd = null;
332 }
333 }
334
335 void addRegionToRemove(final HRegionInfo hri) {
336 if (regionsToRemove == null) {
337 regionsToRemove = new LinkedList<HRegionInfo>();
338 }
339 regionsToRemove.add(hri);
340 }
341
342 void addRegionToRestore(final HRegionInfo hri) {
343 if (regionsToRestore == null) {
344 regionsToRestore = new LinkedList<HRegionInfo>();
345 }
346 regionsToRestore.add(hri);
347 }
348
349 public void updateMetaParentRegions(Connection connection,
350 final List<HRegionInfo> regionInfos) throws IOException {
351 if (regionInfos == null || parentsMap.isEmpty()) return;
352
353
354 Map<String, HRegionInfo> regionsByName = new HashMap<String, HRegionInfo>(regionInfos.size());
355 List<HRegionInfo> parentRegions = new LinkedList<>();
356 for (HRegionInfo regionInfo: regionInfos) {
357 if (regionInfo.isSplitParent()) {
358 parentRegions.add(regionInfo);
359 } else {
360 regionsByName.put(regionInfo.getEncodedName(), regionInfo);
361 }
362 }
363
364
365 for (HRegionInfo regionInfo: parentRegions) {
366 Pair<String, String> daughters = parentsMap.get(regionInfo.getEncodedName());
367 if (daughters == null) {
368
369
370 LOG.warn("Skip update of unreferenced offline parent: " + regionInfo);
371 continue;
372 }
373
374
375 if (daughters.getSecond() == null) {
376 daughters.setSecond(daughters.getFirst());
377 }
378
379 LOG.debug("Update splits parent " + regionInfo.getEncodedName() + " -> " + daughters);
380 MetaTableAccessor.addRegionToMeta(connection, regionInfo,
381 regionsByName.get(daughters.getFirst()),
382 regionsByName.get(daughters.getSecond()));
383 }
384 }
385 }
386
387
388
389
390 private void removeHdfsRegions(final ThreadPoolExecutor exec, final List<HRegionInfo> regions)
391 throws IOException {
392 if (regions == null || regions.size() == 0) return;
393 ModifyRegionUtils.editRegions(exec, regions, new ModifyRegionUtils.RegionEditTask() {
394 @Override
395 public void editRegion(final HRegionInfo hri) throws IOException {
396 HFileArchiver.archiveRegion(conf, fs, hri);
397 }
398 });
399 }
400
401
402
403
404 private void restoreHdfsRegions(final ThreadPoolExecutor exec,
405 final Map<String, SnapshotRegionManifest> regionManifests,
406 final List<HRegionInfo> regions) throws IOException {
407 if (regions == null || regions.size() == 0) return;
408 ModifyRegionUtils.editRegions(exec, regions, new ModifyRegionUtils.RegionEditTask() {
409 @Override
410 public void editRegion(final HRegionInfo hri) throws IOException {
411 restoreRegion(hri, regionManifests.get(hri.getEncodedName()));
412 }
413 });
414 }
415
416
417
418
419 private void restoreHdfsMobRegions(final ThreadPoolExecutor exec,
420 final Map<String, SnapshotRegionManifest> regionManifests,
421 final List<HRegionInfo> regions) throws IOException {
422 if (regions == null || regions.size() == 0) return;
423 ModifyRegionUtils.editRegions(exec, regions, new ModifyRegionUtils.RegionEditTask() {
424 @Override
425 public void editRegion(final HRegionInfo hri) throws IOException {
426 restoreMobRegion(hri, regionManifests.get(hri.getEncodedName()));
427 }
428 });
429 }
430
431 private Map<String, List<SnapshotRegionManifest.StoreFile>> getRegionHFileReferences(
432 final SnapshotRegionManifest manifest) {
433 Map<String, List<SnapshotRegionManifest.StoreFile>> familyMap =
434 new HashMap<String, List<SnapshotRegionManifest.StoreFile>>(manifest.getFamilyFilesCount());
435 for (SnapshotRegionManifest.FamilyFiles familyFiles: manifest.getFamilyFilesList()) {
436 familyMap.put(familyFiles.getFamilyName().toStringUtf8(),
437 new ArrayList<SnapshotRegionManifest.StoreFile>(familyFiles.getStoreFilesList()));
438 }
439 return familyMap;
440 }
441
442
443
444
445
446 private void restoreRegion(final HRegionInfo regionInfo,
447 final SnapshotRegionManifest regionManifest) throws IOException {
448 restoreRegion(regionInfo, regionManifest, new Path(tableDir, regionInfo.getEncodedName()));
449 }
450
451
452
453
454
455 private void restoreMobRegion(final HRegionInfo regionInfo,
456 final SnapshotRegionManifest regionManifest) throws IOException {
457 if (regionManifest == null) {
458 return;
459 }
460 restoreRegion(regionInfo, regionManifest,
461 MobUtils.getMobRegionPath(conf, tableDesc.getTableName()));
462 }
463
464
465
466
467
468 private void restoreRegion(final HRegionInfo regionInfo,
469 final SnapshotRegionManifest regionManifest, Path regionDir) throws IOException {
470 Map<String, List<SnapshotRegionManifest.StoreFile>> snapshotFiles =
471 getRegionHFileReferences(regionManifest);
472
473 String tableName = tableDesc.getTableName().getNameAsString();
474
475
476 for (Path familyDir: FSUtils.getFamilyDirs(fs, regionDir)) {
477 byte[] family = Bytes.toBytes(familyDir.getName());
478 Set<String> familyFiles = getTableRegionFamilyFiles(familyDir);
479 List<SnapshotRegionManifest.StoreFile> snapshotFamilyFiles =
480 snapshotFiles.remove(familyDir.getName());
481 if (snapshotFamilyFiles != null) {
482 List<SnapshotRegionManifest.StoreFile> hfilesToAdd =
483 new ArrayList<SnapshotRegionManifest.StoreFile>();
484 for (SnapshotRegionManifest.StoreFile storeFile: snapshotFamilyFiles) {
485 if (familyFiles.contains(storeFile.getName())) {
486
487 familyFiles.remove(storeFile.getName());
488 } else {
489
490 hfilesToAdd.add(storeFile);
491 }
492 }
493
494
495 for (String hfileName: familyFiles) {
496 Path hfile = new Path(familyDir, hfileName);
497 LOG.trace("Removing hfile=" + hfileName +
498 " from region=" + regionInfo.getEncodedName() + " table=" + tableName);
499 HFileArchiver.archiveStoreFile(conf, fs, regionInfo, tableDir, family, hfile);
500 }
501
502
503 for (SnapshotRegionManifest.StoreFile storeFile: hfilesToAdd) {
504 LOG.debug("Adding HFileLink " + storeFile.getName() +
505 " to region=" + regionInfo.getEncodedName() + " table=" + tableName);
506 restoreStoreFile(familyDir, regionInfo, storeFile, createBackRefs);
507 }
508 } else {
509
510 LOG.trace("Removing family=" + Bytes.toString(family) +
511 " from region=" + regionInfo.getEncodedName() + " table=" + tableName);
512 HFileArchiver.archiveFamily(fs, conf, regionInfo, tableDir, family);
513 fs.delete(familyDir, true);
514 }
515 }
516
517
518 for (Map.Entry<String, List<SnapshotRegionManifest.StoreFile>> familyEntry:
519 snapshotFiles.entrySet()) {
520 Path familyDir = new Path(regionDir, familyEntry.getKey());
521 if (!fs.mkdirs(familyDir)) {
522 throw new IOException("Unable to create familyDir=" + familyDir);
523 }
524
525 for (SnapshotRegionManifest.StoreFile storeFile: familyEntry.getValue()) {
526 LOG.trace("Adding HFileLink " + storeFile.getName() + " to table=" + tableName);
527 restoreStoreFile(familyDir, regionInfo, storeFile, createBackRefs);
528 }
529 }
530 }
531
532
533
534
535 private Set<String> getTableRegionFamilyFiles(final Path familyDir) throws IOException {
536 FileStatus[] hfiles = FSUtils.listStatus(fs, familyDir);
537 if (hfiles == null) return Collections.emptySet();
538
539 Set<String> familyFiles = new HashSet<String>(hfiles.length);
540 for (int i = 0; i < hfiles.length; ++i) {
541 String hfileName = hfiles[i].getPath().getName();
542 familyFiles.add(hfileName);
543 }
544
545 return familyFiles;
546 }
547
548
549
550
551
552 private HRegionInfo[] cloneHdfsRegions(final ThreadPoolExecutor exec,
553 final Map<String, SnapshotRegionManifest> regionManifests,
554 final List<HRegionInfo> regions) throws IOException {
555 if (regions == null || regions.size() == 0) return null;
556
557 final Map<String, HRegionInfo> snapshotRegions =
558 new HashMap<String, HRegionInfo>(regions.size());
559
560
561 HRegionInfo[] clonedRegionsInfo = new HRegionInfo[regions.size()];
562 for (int i = 0; i < clonedRegionsInfo.length; ++i) {
563
564 HRegionInfo snapshotRegionInfo = regions.get(i);
565 clonedRegionsInfo[i] = cloneRegionInfo(snapshotRegionInfo);
566
567
568 String snapshotRegionName = snapshotRegionInfo.getEncodedName();
569 String clonedRegionName = clonedRegionsInfo[i].getEncodedName();
570 regionsMap.put(Bytes.toBytes(snapshotRegionName), Bytes.toBytes(clonedRegionName));
571 LOG.info("clone region=" + snapshotRegionName + " as " + clonedRegionName);
572
573
574 snapshotRegions.put(clonedRegionName, snapshotRegionInfo);
575 }
576
577
578 ModifyRegionUtils.createRegions(exec, conf, rootDir, tableDir,
579 tableDesc, clonedRegionsInfo, new ModifyRegionUtils.RegionFillTask() {
580 @Override
581 public void fillRegion(final HRegion region) throws IOException {
582 HRegionInfo snapshotHri = snapshotRegions.get(region.getRegionInfo().getEncodedName());
583 cloneRegion(region, snapshotHri, regionManifests.get(snapshotHri.getEncodedName()));
584 }
585 });
586
587 return clonedRegionsInfo;
588 }
589
590
591
592
593
594 private void cloneHdfsMobRegion(final Map<String, SnapshotRegionManifest> regionManifests,
595 final HRegionInfo region) throws IOException {
596
597 Path clonedRegionPath = MobUtils.getMobRegionPath(conf, tableDesc.getTableName());
598 cloneRegion(clonedRegionPath, region, regionManifests.get(region.getEncodedName()));
599 }
600
601
602
603
604
605
606
607
608
609
610
611
612 private void cloneRegion(final Path regionDir, final HRegionInfo snapshotRegionInfo,
613 final SnapshotRegionManifest manifest) throws IOException {
614 final String tableName = tableDesc.getTableName().getNameAsString();
615 for (SnapshotRegionManifest.FamilyFiles familyFiles: manifest.getFamilyFilesList()) {
616 Path familyDir = new Path(regionDir, familyFiles.getFamilyName().toStringUtf8());
617 for (SnapshotRegionManifest.StoreFile storeFile: familyFiles.getStoreFilesList()) {
618 LOG.info("Adding HFileLink " + storeFile.getName() + " to table=" + tableName);
619 restoreStoreFile(familyDir, snapshotRegionInfo, storeFile, createBackRefs);
620 }
621 }
622 }
623
624
625
626
627
628
629
630
631
632
633
634
635 private void cloneRegion(final HRegion region, final HRegionInfo snapshotRegionInfo,
636 final SnapshotRegionManifest manifest) throws IOException {
637 cloneRegion(new Path(tableDir, region.getRegionInfo().getEncodedName()), snapshotRegionInfo,
638 manifest);
639 }
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654 private void restoreStoreFile(final Path familyDir, final HRegionInfo regionInfo,
655 final SnapshotRegionManifest.StoreFile storeFile, final boolean createBackRef)
656 throws IOException {
657 String hfileName = storeFile.getName();
658 if (HFileLink.isHFileLink(hfileName)) {
659 HFileLink.createFromHFileLink(conf, fs, familyDir, hfileName, createBackRef);
660 } else if (StoreFileInfo.isReference(hfileName)) {
661 restoreReferenceFile(familyDir, regionInfo, storeFile);
662 } else {
663 HFileLink.create(conf, fs, familyDir, regionInfo, hfileName, createBackRef);
664 }
665 }
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685 private void restoreReferenceFile(final Path familyDir, final HRegionInfo regionInfo,
686 final SnapshotRegionManifest.StoreFile storeFile) throws IOException {
687 String hfileName = storeFile.getName();
688
689
690 Path refPath =
691 StoreFileInfo.getReferredToFile(new Path(new Path(new Path(new Path(snapshotTable
692 .getNamespaceAsString(), snapshotTable.getQualifierAsString()), regionInfo
693 .getEncodedName()), familyDir.getName()), hfileName));
694 String snapshotRegionName = refPath.getParent().getParent().getName();
695 String fileName = refPath.getName();
696
697
698 String clonedRegionName = Bytes.toString(regionsMap.get(Bytes.toBytes(snapshotRegionName)));
699 if (clonedRegionName == null) clonedRegionName = snapshotRegionName;
700
701
702 Path linkPath = null;
703 String refLink = fileName;
704 if (!HFileLink.isHFileLink(fileName)) {
705 refLink = HFileLink.createHFileLinkName(snapshotTable, snapshotRegionName, fileName);
706 linkPath = new Path(familyDir,
707 HFileLink.createHFileLinkName(snapshotTable, regionInfo.getEncodedName(), hfileName));
708 }
709
710 Path outPath = new Path(familyDir, refLink + '.' + clonedRegionName);
711
712
713 if (storeFile.hasReference()) {
714 Reference reference = Reference.convert(storeFile.getReference());
715 reference.write(fs, outPath);
716 } else {
717 InputStream in;
718 if (linkPath != null) {
719 in = HFileLink.buildFromHFileLinkPattern(conf, linkPath).open(fs);
720 } else {
721 linkPath = new Path(new Path(HRegion.getRegionDir(snapshotManifest.getSnapshotDir(),
722 regionInfo.getEncodedName()), familyDir.getName()), hfileName);
723 in = fs.open(linkPath);
724 }
725 OutputStream out = fs.create(outPath);
726 IOUtils.copyBytes(in, out, conf);
727 }
728
729
730 String regionName = Bytes.toString(regionsMap.get(regionInfo.getEncodedNameAsBytes()));
731 LOG.debug("Restore reference " + regionName + " to " + clonedRegionName);
732 synchronized (parentsMap) {
733 Pair<String, String> daughters = parentsMap.get(clonedRegionName);
734 if (daughters == null) {
735 daughters = new Pair<String, String>(regionName, null);
736 parentsMap.put(clonedRegionName, daughters);
737 } else if (!regionName.equals(daughters.getFirst())) {
738 daughters.setSecond(regionName);
739 }
740 }
741 }
742
743
744
745
746
747
748
749
750
751 public HRegionInfo cloneRegionInfo(final HRegionInfo snapshotRegionInfo) {
752 return cloneRegionInfo(tableDesc.getTableName(), snapshotRegionInfo);
753 }
754
755 public static HRegionInfo cloneRegionInfo(TableName tableName, HRegionInfo snapshotRegionInfo) {
756 HRegionInfo regionInfo = new HRegionInfo(tableName,
757 snapshotRegionInfo.getStartKey(), snapshotRegionInfo.getEndKey(),
758 snapshotRegionInfo.isSplit(), snapshotRegionInfo.getRegionId());
759 regionInfo.setOffline(snapshotRegionInfo.isOffline());
760 return regionInfo;
761 }
762
763
764
765
766 private List<HRegionInfo> getTableRegions() throws IOException {
767 LOG.debug("get table regions: " + tableDir);
768 FileStatus[] regionDirs = FSUtils.listStatus(fs, tableDir, new FSUtils.RegionDirFilter(fs));
769 if (regionDirs == null) return null;
770
771 List<HRegionInfo> regions = new ArrayList<HRegionInfo>(regionDirs.length);
772 for (int i = 0; i < regionDirs.length; ++i) {
773 HRegionInfo hri = HRegionFileSystem.loadRegionInfoFileContent(fs, regionDirs[i].getPath());
774 regions.add(hri);
775 }
776 LOG.debug("found " + regions.size() + " regions for table=" +
777 tableDesc.getTableName().getNameAsString());
778 return regions;
779 }
780
781
782
783
784
785
786
787
788
789
790 public static RestoreMetaChanges copySnapshotForScanner(Configuration conf, FileSystem fs,
791 Path rootDir, Path restoreDir, String snapshotName) throws IOException {
792
793 if (!restoreDir.getFileSystem(conf).getUri().equals(rootDir.getFileSystem(conf).getUri())) {
794 throw new IllegalArgumentException("Filesystems for restore directory and HBase root directory " +
795 "should be the same");
796 }
797 if (restoreDir.toUri().getPath().startsWith(rootDir.toUri().getPath())) {
798 throw new IllegalArgumentException("Restore directory cannot be a sub directory of HBase " +
799 "root directory. RootDir: " + rootDir + ", restoreDir: " + restoreDir);
800 }
801
802 Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);
803 SnapshotDescription snapshotDesc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);
804 SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);
805
806 MonitoredTask status = TaskMonitor.get().createStatus(
807 "Restoring snapshot '" + snapshotName + "' to directory " + restoreDir);
808 ForeignExceptionDispatcher monitor = new ForeignExceptionDispatcher();
809
810
811
812 RestoreSnapshotHelper helper = new RestoreSnapshotHelper(conf, fs,
813 manifest, manifest.getTableDescriptor(), restoreDir, monitor, status, false);
814 RestoreMetaChanges metaChanges = helper.restoreHdfsRegions();
815
816 if (LOG.isDebugEnabled()) {
817 LOG.debug("Restored table dir:" + restoreDir);
818 FSUtils.logFileSystemState(fs, restoreDir, LOG);
819 }
820 return metaChanges;
821 }
822 }