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.FileNotFoundException;
22 import java.io.IOException;
23 import java.io.InterruptedIOException;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Set;
27 import java.util.concurrent.Callable;
28 import java.util.concurrent.ExecutorService;
29 import java.util.concurrent.ExecutionException;
30 import java.util.concurrent.ExecutorCompletionService;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.hadoop.hbase.classification.InterfaceAudience;
35 import org.apache.hadoop.conf.Configuration;
36 import org.apache.hadoop.fs.FileStatus;
37 import org.apache.hadoop.fs.FileSystem;
38 import org.apache.hadoop.fs.Path;
39 import org.apache.hadoop.hbase.HRegionInfo;
40 import org.apache.hadoop.hbase.TableName;
41 import org.apache.hadoop.hbase.io.HFileLink;
42 import org.apache.hadoop.hbase.mob.MobUtils;
43 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
44 import org.apache.hadoop.hbase.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;
45 import org.apache.hadoop.hbase.wal.DefaultWALProvider;
46 import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
47 import org.apache.hadoop.hbase.util.FSUtils;
48 import org.apache.hadoop.hbase.util.FSVisitor;
49 import org.apache.hadoop.hbase.util.HFileArchiveUtil;
50
51
52
53
54 @InterfaceAudience.Private
55 public final class SnapshotReferenceUtil {
56 public static final Log LOG = LogFactory.getLog(SnapshotReferenceUtil.class);
57
58 public interface StoreFileVisitor {
59 void storeFile(final HRegionInfo regionInfo, final String familyName,
60 final SnapshotRegionManifest.StoreFile storeFile) throws IOException;
61 }
62
63 public interface SnapshotVisitor extends StoreFileVisitor,
64 FSVisitor.LogFileVisitor {
65 }
66
67 private SnapshotReferenceUtil() {
68
69 }
70
71
72
73
74
75
76
77
78 public static Path getLogsDir(Path snapshotDir, String serverName) {
79 return new Path(snapshotDir, DefaultWALProvider.getWALDirectoryName(serverName));
80 }
81
82
83
84
85
86
87
88
89
90
91 public static void visitReferencedFiles(final Configuration conf, final FileSystem fs,
92 final Path snapshotDir, final SnapshotVisitor visitor)
93 throws IOException {
94 SnapshotDescription desc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);
95 visitReferencedFiles(conf, fs, snapshotDir, desc, visitor);
96 }
97
98
99
100
101
102
103
104
105
106
107
108 public static void visitReferencedFiles(final Configuration conf, final FileSystem fs,
109 final Path snapshotDir, final SnapshotDescription desc, final SnapshotVisitor visitor)
110 throws IOException {
111 visitTableStoreFiles(conf, fs, snapshotDir, desc, visitor);
112 visitLogFiles(fs, snapshotDir, visitor);
113 }
114
115
116
117
118
119
120
121
122
123
124
125 static void visitTableStoreFiles(final Configuration conf, final FileSystem fs,
126 final Path snapshotDir, final SnapshotDescription desc, final StoreFileVisitor visitor)
127 throws IOException {
128 SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, desc);
129 List<SnapshotRegionManifest> regionManifests = manifest.getRegionManifests();
130 if (regionManifests == null || regionManifests.size() == 0) {
131 LOG.debug("No manifest files present: " + snapshotDir);
132 return;
133 }
134
135 for (SnapshotRegionManifest regionManifest: regionManifests) {
136 visitRegionStoreFiles(regionManifest, visitor);
137 }
138 }
139
140
141
142
143
144
145
146
147 static void visitRegionStoreFiles(final SnapshotRegionManifest manifest,
148 final StoreFileVisitor visitor) throws IOException {
149 HRegionInfo regionInfo = HRegionInfo.convert(manifest.getRegionInfo());
150 for (SnapshotRegionManifest.FamilyFiles familyFiles: manifest.getFamilyFilesList()) {
151 String familyName = familyFiles.getFamilyName().toStringUtf8();
152 for (SnapshotRegionManifest.StoreFile storeFile: familyFiles.getStoreFilesList()) {
153 visitor.storeFile(regionInfo, familyName, storeFile);
154 }
155 }
156 }
157
158
159
160
161
162
163
164
165
166 public static void visitLogFiles(final FileSystem fs, final Path snapshotDir,
167 final FSVisitor.LogFileVisitor visitor) throws IOException {
168 FSVisitor.visitLogFiles(fs, snapshotDir, visitor);
169 }
170
171
172
173
174
175
176
177
178
179
180
181 public static void verifySnapshot(final Configuration conf, final FileSystem fs,
182 final Path snapshotDir, final SnapshotDescription snapshotDesc) throws IOException {
183 SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);
184 verifySnapshot(conf, fs, manifest);
185 }
186
187
188
189
190
191
192
193
194
195
196 public static void verifySnapshot(final Configuration conf, final FileSystem fs,
197 final SnapshotManifest manifest) throws IOException {
198 final SnapshotDescription snapshotDesc = manifest.getSnapshotDescription();
199 final Path snapshotDir = manifest.getSnapshotDir();
200 concurrentVisitReferencedFiles(conf, fs, manifest, new StoreFileVisitor() {
201 @Override
202 public void storeFile(final HRegionInfo regionInfo, final String family,
203 final SnapshotRegionManifest.StoreFile storeFile) throws IOException {
204 verifyStoreFile(conf, fs, snapshotDir, snapshotDesc, regionInfo, family, storeFile);
205 }
206 });
207 }
208
209 public static void concurrentVisitReferencedFiles(final Configuration conf, final FileSystem fs,
210 final SnapshotManifest manifest, final StoreFileVisitor visitor) throws IOException {
211 final SnapshotDescription snapshotDesc = manifest.getSnapshotDescription();
212 final Path snapshotDir = manifest.getSnapshotDir();
213
214 List<SnapshotRegionManifest> regionManifests = manifest.getRegionManifests();
215 if (regionManifests == null || regionManifests.size() == 0) {
216 LOG.debug("No manifest files present: " + snapshotDir);
217 return;
218 }
219
220 ExecutorService exec = SnapshotManifest.createExecutor(conf, "VerifySnapshot");
221 final ExecutorCompletionService<Void> completionService =
222 new ExecutorCompletionService<Void>(exec);
223 try {
224 for (final SnapshotRegionManifest regionManifest: regionManifests) {
225 completionService.submit(new Callable<Void>() {
226 @Override
227 public Void call() throws IOException {
228 visitRegionStoreFiles(regionManifest, visitor);
229 return null;
230 }
231 });
232 }
233 try {
234 for (int i = 0; i < regionManifests.size(); ++i) {
235 completionService.take().get();
236 }
237 } catch (InterruptedException e) {
238 throw new InterruptedIOException(e.getMessage());
239 } catch (ExecutionException e) {
240 if (e.getCause() instanceof CorruptedSnapshotException) {
241 throw new CorruptedSnapshotException(e.getCause().getMessage(), snapshotDesc);
242 } else {
243 IOException ex = new IOException();
244 ex.initCause(e.getCause());
245 throw ex;
246 }
247 }
248 } finally {
249 exec.shutdown();
250 }
251 }
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266 private static void verifyStoreFile(final Configuration conf, final FileSystem fs,
267 final Path snapshotDir, final SnapshotDescription snapshot, final HRegionInfo regionInfo,
268 final String family, final SnapshotRegionManifest.StoreFile storeFile) throws IOException {
269 TableName table = TableName.valueOf(snapshot.getTable());
270 String fileName = storeFile.getName();
271
272 Path refPath = null;
273 if (StoreFileInfo.isReference(fileName)) {
274
275 refPath = new Path(new Path(regionInfo.getEncodedName(), family), fileName);
276 refPath = StoreFileInfo.getReferredToFile(refPath);
277 String refRegion = refPath.getParent().getParent().getName();
278 refPath = HFileLink.createPath(table, refRegion, family, refPath.getName());
279 if (!HFileLink.buildFromHFileLinkPattern(conf, refPath).exists(fs)) {
280 throw new CorruptedSnapshotException("Missing parent hfile for: " + fileName +
281 " path=" + refPath, snapshot);
282 }
283
284 if (storeFile.hasReference()) {
285
286
287 return;
288 }
289 }
290
291 Path linkPath;
292 if (refPath != null && HFileLink.isHFileLink(refPath)) {
293 linkPath = new Path(family, refPath.getName());
294 } else if (HFileLink.isHFileLink(fileName)) {
295 linkPath = new Path(family, fileName);
296 } else {
297 linkPath = new Path(family, HFileLink.createHFileLinkName(
298 table, regionInfo.getEncodedName(), fileName));
299 }
300
301
302 HFileLink link = null;
303 if (MobUtils.isMobRegionInfo(regionInfo)) {
304
305 link = HFileLink.buildFromHFileLinkPattern(MobUtils.getQualifiedMobRootDir(conf),
306 HFileArchiveUtil.getArchivePath(conf), linkPath);
307 } else {
308
309 link = HFileLink.buildFromHFileLinkPattern(conf, linkPath);
310 }
311 try {
312 FileStatus fstat = link.getFileStatus(fs);
313 if (storeFile.hasFileSize() && storeFile.getFileSize() != fstat.getLen()) {
314 String msg = "hfile: " + fileName + " size does not match with the expected one. " +
315 " found=" + fstat.getLen() + " expected=" + storeFile.getFileSize();
316 LOG.error(msg);
317 throw new CorruptedSnapshotException(msg, snapshot);
318 }
319 } catch (FileNotFoundException e) {
320 String msg = "Can't find hfile: " + fileName + " in the real (" +
321 link.getOriginPath() + ") or archive (" + link.getArchivePath()
322 + ") directory for the primary table.";
323 LOG.error(msg);
324 throw new CorruptedSnapshotException(msg, snapshot);
325 }
326 }
327
328
329
330
331
332
333
334
335
336
337 public static Set<String> getHFileNames(final Configuration conf, final FileSystem fs,
338 final Path snapshotDir) throws IOException {
339 SnapshotDescription desc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);
340 return getHFileNames(conf, fs, snapshotDir, desc);
341 }
342
343
344
345
346
347
348
349
350
351
352
353 private static Set<String> getHFileNames(final Configuration conf, final FileSystem fs,
354 final Path snapshotDir, final SnapshotDescription snapshotDesc)
355 throws IOException {
356 final Set<String> names = new HashSet<String>();
357 visitTableStoreFiles(conf, fs, snapshotDir, snapshotDesc, new StoreFileVisitor() {
358 @Override
359 public void storeFile(final HRegionInfo regionInfo, final String family,
360 final SnapshotRegionManifest.StoreFile storeFile) throws IOException {
361 String hfile = storeFile.getName();
362 if (HFileLink.isHFileLink(hfile)) {
363 names.add(HFileLink.getReferencedHFileName(hfile));
364 } else {
365 names.add(hfile);
366 }
367 }
368 });
369 return names;
370 }
371
372
373
374
375
376
377
378
379
380 public static Set<String> getWALNames(final FileSystem fs, final Path snapshotDir)
381 throws IOException {
382 final Set<String> names = new HashSet<String>();
383 visitLogFiles(fs, snapshotDir, new FSVisitor.LogFileVisitor() {
384 @Override
385 public void logFile (final String server, final String logfile) throws IOException {
386 names.add(logfile);
387 }
388 });
389 return names;
390 }
391 }