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 throw new IOException(e.getCause());
232 }
233 }
234 }
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249 private static void verifyStoreFile(final Configuration conf, final FileSystem fs,
250 final Path snapshotDir, final SnapshotDescription snapshot, final HRegionInfo regionInfo,
251 final String family, final SnapshotRegionManifest.StoreFile storeFile) throws IOException {
252 TableName table = TableName.valueOf(snapshot.getTable());
253 String fileName = storeFile.getName();
254
255 Path refPath = null;
256 if (StoreFileInfo.isReference(fileName)) {
257
258 refPath = new Path(new Path(regionInfo.getEncodedName(), family), fileName);
259 refPath = StoreFileInfo.getReferredToFile(refPath);
260 String refRegion = refPath.getParent().getParent().getName();
261 refPath = HFileLink.createPath(table, refRegion, family, refPath.getName());
262 if (!HFileLink.buildFromHFileLinkPattern(conf, refPath).exists(fs)) {
263 throw new CorruptedSnapshotException("Missing parent hfile for: " + fileName +
264 " path=" + refPath, snapshot);
265 }
266
267 if (storeFile.hasReference()) {
268
269
270 return;
271 }
272 }
273
274 Path linkPath;
275 if (refPath != null && HFileLink.isHFileLink(refPath)) {
276 linkPath = new Path(family, refPath.getName());
277 } else if (HFileLink.isHFileLink(fileName)) {
278 linkPath = new Path(family, fileName);
279 } else {
280 linkPath = new Path(family, HFileLink.createHFileLinkName(
281 table, regionInfo.getEncodedName(), fileName));
282 }
283
284
285 HFileLink link = HFileLink.buildFromHFileLinkPattern(conf, linkPath);
286 try {
287 FileStatus fstat = link.getFileStatus(fs);
288 if (storeFile.hasFileSize() && storeFile.getFileSize() != fstat.getLen()) {
289 String msg = "hfile: " + fileName + " size does not match with the expected one. " +
290 " found=" + fstat.getLen() + " expected=" + storeFile.getFileSize();
291 LOG.error(msg);
292 throw new CorruptedSnapshotException(msg, snapshot);
293 }
294 } catch (FileNotFoundException e) {
295 String msg = "Can't find hfile: " + fileName + " in the real (" +
296 link.getOriginPath() + ") or archive (" + link.getArchivePath()
297 + ") directory for the primary table.";
298 LOG.error(msg);
299 throw new CorruptedSnapshotException(msg, snapshot);
300 }
301 }
302
303
304
305
306
307
308
309
310
311
312 public static Set<String> getHFileNames(final Configuration conf, final FileSystem fs,
313 final Path snapshotDir) throws IOException {
314 SnapshotDescription desc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);
315 return getHFileNames(conf, fs, snapshotDir, desc);
316 }
317
318
319
320
321
322
323
324
325
326
327
328 private static Set<String> getHFileNames(final Configuration conf, final FileSystem fs,
329 final Path snapshotDir, final SnapshotDescription snapshotDesc)
330 throws IOException {
331 final Set<String> names = new HashSet<String>();
332 visitTableStoreFiles(conf, fs, snapshotDir, snapshotDesc, new StoreFileVisitor() {
333 @Override
334 public void storeFile(final HRegionInfo regionInfo, final String family,
335 final SnapshotRegionManifest.StoreFile storeFile) throws IOException {
336 String hfile = storeFile.getName();
337 if (HFileLink.isHFileLink(hfile)) {
338 names.add(HFileLink.getReferencedHFileName(hfile));
339 } else {
340 names.add(hfile);
341 }
342 }
343 });
344 return names;
345 }
346 }