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