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.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.hadoop.classification.InterfaceAudience;
27 import org.apache.hadoop.classification.InterfaceStability;
28 import org.apache.hadoop.fs.FileStatus;
29 import org.apache.hadoop.fs.FileSystem;
30 import org.apache.hadoop.fs.Path;
31 import org.apache.hadoop.fs.PathFilter;
32 import org.apache.hadoop.hbase.TableName;
33 import org.apache.hadoop.hbase.HRegionInfo;
34 import org.apache.hadoop.hbase.ServerName;
35 import org.apache.hadoop.hbase.catalog.MetaReader;
36 import org.apache.hadoop.hbase.io.HFileLink;
37 import org.apache.hadoop.hbase.master.MasterServices;
38 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
39 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
40 import org.apache.hadoop.hbase.regionserver.HRegionFileSystem;
41 import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
42 import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
43 import org.apache.hadoop.hbase.snapshot.CorruptedSnapshotException;
44 import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
45 import org.apache.hadoop.hbase.snapshot.SnapshotReferenceUtil;
46 import org.apache.hadoop.hbase.snapshot.TakeSnapshotUtils;
47 import org.apache.hadoop.hbase.util.FSTableDescriptors;
48 import org.apache.hadoop.hbase.util.FSUtils;
49 import org.apache.hadoop.hbase.util.FSVisitor;
50 import org.apache.hadoop.hbase.util.HFileArchiveUtil;
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
76
77
78
79
80 @InterfaceAudience.Private
81 @InterfaceStability.Unstable
82 public final class MasterSnapshotVerifier {
83 private static final Log LOG = LogFactory.getLog(MasterSnapshotVerifier.class);
84
85 private SnapshotDescription snapshot;
86 private FileSystem fs;
87 private Path rootDir;
88 private TableName tableName;
89 private MasterServices services;
90
91
92
93
94
95
96 public MasterSnapshotVerifier(MasterServices services, SnapshotDescription snapshot, Path rootDir) {
97 this.fs = services.getMasterFileSystem().getFileSystem();
98 this.services = services;
99 this.snapshot = snapshot;
100 this.rootDir = rootDir;
101 this.tableName = TableName.valueOf(snapshot.getTable());
102 }
103
104
105
106
107
108
109
110
111 public void verifySnapshot(Path snapshotDir, Set<String> snapshotServers)
112 throws CorruptedSnapshotException, IOException {
113
114 verifySnapshotDescription(snapshotDir);
115
116
117 verifyTableInfo(snapshotDir);
118
119
120 verifyRegions(snapshotDir);
121 }
122
123
124
125
126
127 private void verifySnapshotDescription(Path snapshotDir) throws CorruptedSnapshotException {
128 SnapshotDescription found = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);
129 if (!this.snapshot.equals(found)) {
130 throw new CorruptedSnapshotException("Snapshot read (" + found
131 + ") doesn't equal snapshot we ran (" + snapshot + ").", snapshot);
132 }
133 }
134
135
136
137
138
139 private void verifyTableInfo(Path snapshotDir) throws IOException {
140 FSTableDescriptors.getTableDescriptorFromFs(fs, snapshotDir);
141 }
142
143
144
145
146
147
148 private void verifyRegions(Path snapshotDir) throws IOException {
149 List<HRegionInfo> regions = MetaReader.getTableRegions(this.services.getCatalogTracker(),
150 tableName);
151
152 Set<String> snapshotRegions = SnapshotReferenceUtil.getSnapshotRegionNames(fs, snapshotDir);
153 if (snapshotRegions == null) {
154 String msg = "Snapshot " + ClientSnapshotDescriptionUtils.toString(snapshot) + " looks empty";
155 LOG.error(msg);
156 throw new CorruptedSnapshotException(msg);
157 }
158
159 String errorMsg = "";
160 if (snapshotRegions.size() != regions.size()) {
161 errorMsg = "Regions moved during the snapshot '" +
162 ClientSnapshotDescriptionUtils.toString(snapshot) + "'. expected=" +
163 regions.size() + " snapshotted=" + snapshotRegions.size() + ".";
164 LOG.error(errorMsg);
165 }
166
167 for (HRegionInfo region : regions) {
168 if (!snapshotRegions.contains(region.getEncodedName())) {
169
170 String mesg = " No snapshot region directory found for region:" + region;
171 if (errorMsg.isEmpty()) errorMsg = mesg;
172 LOG.error(mesg);
173 }
174
175 verifyRegion(fs, snapshotDir, region);
176 }
177 if (!errorMsg.isEmpty()) {
178 throw new CorruptedSnapshotException(errorMsg);
179 }
180 }
181
182
183
184
185
186
187
188 private void verifyRegion(final FileSystem fs, final Path snapshotDir, final HRegionInfo region)
189 throws IOException {
190
191 Path regionDir = new Path(snapshotDir, region.getEncodedName());
192
193
194 Path regionInfo = new Path(regionDir, HRegionFileSystem.REGION_INFO_FILE);
195
196 if (!fs.exists(regionInfo)) {
197 throw new CorruptedSnapshotException("No region info found for region:" + region, snapshot);
198 }
199
200 HRegionInfo found = HRegionFileSystem.loadRegionInfoFileContent(fs, regionDir);
201 if (!region.equals(found)) {
202 throw new CorruptedSnapshotException("Found region info (" + found
203 + ") doesn't match expected region:" + region, snapshot);
204 }
205
206
207 TakeSnapshotUtils.verifyRecoveredEdits(fs, snapshotDir, found, snapshot);
208
209
210 SnapshotReferenceUtil.visitRegionStoreFiles(fs, regionDir, new FSVisitor.StoreFileVisitor() {
211 public void storeFile(final String regionNameSuffix, final String family,
212 final String hfileName) throws IOException {
213 verifyStoreFile(snapshotDir, region, family, hfileName);
214 }
215 });
216 }
217
218 private void verifyStoreFile(final Path snapshotDir, final HRegionInfo regionInfo,
219 final String family, final String fileName) throws IOException {
220 Path refPath = null;
221 if (StoreFileInfo.isReference(fileName)) {
222
223 Path snapshotHFilePath = new Path(new Path(
224 new Path(snapshotDir, regionInfo.getEncodedName()), family), fileName);
225 refPath = StoreFileInfo.getReferredToFile(snapshotHFilePath);
226 if (!fs.exists(refPath)) {
227 throw new CorruptedSnapshotException("Missing parent hfile for: " + fileName, snapshot);
228 }
229 }
230
231 Path linkPath;
232 if (refPath != null && HFileLink.isHFileLink(refPath)) {
233 linkPath = new Path(family, refPath.getName());
234 } else if (HFileLink.isHFileLink(fileName)) {
235 linkPath = new Path(family, fileName);
236 } else {
237 linkPath = new Path(family, HFileLink.createHFileLinkName(tableName,
238 regionInfo.getEncodedName(), fileName));
239 }
240
241
242 HFileLink link = new HFileLink(services.getConfiguration(), linkPath);
243 if (!link.exists(fs)) {
244 throw new CorruptedSnapshotException("Can't find hfile: " + fileName
245 + " in the real (" + link.getOriginPath() + ") or archive (" + link.getArchivePath()
246 + ") directory for the primary table.", snapshot);
247 }
248 }
249 }