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