1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.master.snapshot;
19
20 import java.io.IOException;
21 import java.util.List;
22 import java.util.Set;
23
24 import org.apache.hadoop.classification.InterfaceAudience;
25 import org.apache.hadoop.classification.InterfaceStability;
26 import org.apache.hadoop.fs.FSDataInputStream;
27 import org.apache.hadoop.fs.FileStatus;
28 import org.apache.hadoop.fs.FileSystem;
29 import org.apache.hadoop.fs.Path;
30 import org.apache.hadoop.fs.PathFilter;
31 import org.apache.hadoop.hbase.HRegionInfo;
32 import org.apache.hadoop.hbase.ServerName;
33 import org.apache.hadoop.hbase.catalog.MetaReader;
34 import org.apache.hadoop.hbase.master.MasterServices;
35 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
36 import org.apache.hadoop.hbase.regionserver.HRegion;
37 import org.apache.hadoop.hbase.regionserver.HRegionFileSystem;
38 import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
39 import org.apache.hadoop.hbase.exceptions.CorruptedSnapshotException;
40 import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
41 import org.apache.hadoop.hbase.snapshot.TakeSnapshotUtils;
42 import org.apache.hadoop.hbase.util.Bytes;
43 import org.apache.hadoop.hbase.util.FSTableDescriptors;
44 import org.apache.hadoop.hbase.util.FSUtils;
45 import org.apache.hadoop.hbase.util.HFileArchiveUtil;
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 @InterfaceAudience.Private
76 @InterfaceStability.Unstable
77 public final class MasterSnapshotVerifier {
78
79 private SnapshotDescription snapshot;
80 private FileSystem fs;
81 private Path rootDir;
82 private String tableName;
83 private MasterServices services;
84
85
86
87
88
89
90 public MasterSnapshotVerifier(MasterServices services, SnapshotDescription snapshot, Path rootDir) {
91 this.fs = services.getMasterFileSystem().getFileSystem();
92 this.services = services;
93 this.snapshot = snapshot;
94 this.rootDir = rootDir;
95 this.tableName = snapshot.getTable();
96 }
97
98
99
100
101
102
103
104
105 public void verifySnapshot(Path snapshotDir, Set<String> snapshotServers)
106 throws CorruptedSnapshotException, IOException {
107
108 verifySnapshotDescription(snapshotDir);
109
110
111 verifyTableInfo(snapshotDir);
112
113
114 verifyRegions(snapshotDir);
115 }
116
117
118
119
120
121 private void verifySnapshotDescription(Path snapshotDir) throws CorruptedSnapshotException {
122 SnapshotDescription found = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);
123 if (!this.snapshot.equals(found)) {
124 throw new CorruptedSnapshotException("Snapshot read (" + found
125 + ") doesn't equal snapshot we ran (" + snapshot + ").", snapshot);
126 }
127 }
128
129
130
131
132
133 private void verifyTableInfo(Path snapshotDir) throws IOException {
134 FSTableDescriptors.getTableDescriptor(fs, snapshotDir);
135 }
136
137
138
139
140
141
142 private void verifyRegions(Path snapshotDir) throws IOException {
143 List<HRegionInfo> regions = MetaReader.getTableRegions(this.services.getCatalogTracker(),
144 Bytes.toBytes(tableName));
145 for (HRegionInfo region : regions) {
146
147 if (region.isOffline() && (region.isSplit() || region.isSplitParent())) {
148 continue;
149 }
150
151 verifyRegion(fs, snapshotDir, region);
152 }
153 }
154
155
156
157
158
159
160
161 private void verifyRegion(FileSystem fs, Path snapshotDir, HRegionInfo region) throws IOException {
162
163 Path regionDir = new Path(snapshotDir, region.getEncodedName());
164 if (!fs.exists(regionDir)) {
165
166 throw new CorruptedSnapshotException("No region directory found for region:" + region,
167 snapshot);
168 }
169
170 Path regionInfo = new Path(regionDir, HRegionFileSystem.REGION_INFO_FILE);
171
172 if (!fs.exists(regionInfo)) {
173 throw new CorruptedSnapshotException("No region info found for region:" + region, snapshot);
174 }
175
176 HRegionInfo found = HRegionFileSystem.loadRegionInfoFileContent(fs, regionDir);
177 if (!region.equals(found)) {
178 throw new CorruptedSnapshotException("Found region info (" + found
179 + ") doesn't match expected region:" + region, snapshot);
180 }
181
182
183 TakeSnapshotUtils.verifyRecoveredEdits(fs, snapshotDir, found, snapshot);
184
185
186 PathFilter familiesDirs = new FSUtils.FamilyDirFilter(fs);
187 FileStatus[] columnFamilies = FSUtils.listStatus(fs, regionDir, familiesDirs);
188
189 if (columnFamilies == null) return;
190
191
192 Path tableNameSuffix = new Path(tableName);
193 Path regionNameSuffix = new Path(tableNameSuffix, region.getEncodedName());
194
195
196 Path archivedRegion = new Path(HFileArchiveUtil.getArchivePath(services.getConfiguration()),
197 regionNameSuffix);
198 Path realRegion = new Path(rootDir, regionNameSuffix);
199
200
201 for (FileStatus cf : columnFamilies) {
202 FileStatus[] hfiles = FSUtils.listStatus(fs, cf.getPath(), null);
203
204 if (hfiles == null || hfiles.length == 0) continue;
205
206 Path realCfDir = new Path(realRegion, cf.getPath().getName());
207 Path archivedCfDir = new Path(archivedRegion, cf.getPath().getName());
208 for (FileStatus hfile : hfiles) {
209
210 if (!StoreFileInfo.validateStoreFileName(hfile.getPath().getName())) {
211 throw new CorruptedSnapshotException("HFile: " + hfile.getPath()
212 + " is not a valid hfile name.", snapshot);
213 }
214
215
216 String fileName = hfile.getPath().getName();
217 Path file = new Path(realCfDir, fileName);
218 Path archived = new Path(archivedCfDir, fileName);
219 if (!fs.exists(file) && !file.equals(archived)) {
220 throw new CorruptedSnapshotException("Can't find hfile: " + hfile.getPath()
221 + " in the real (" + realCfDir + ") or archive (" + archivedCfDir
222 + ") directory for the primary table.", snapshot);
223 }
224 }
225 }
226 }
227 }