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.Map;
23 import java.util.Set;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.hadoop.hbase.classification.InterfaceAudience;
28 import org.apache.hadoop.hbase.classification.InterfaceStability;
29 import org.apache.hadoop.fs.FileSystem;
30 import org.apache.hadoop.fs.Path;
31 import org.apache.hadoop.hbase.TableName;
32 import org.apache.hadoop.hbase.HRegionInfo;
33 import org.apache.hadoop.hbase.HTableDescriptor;
34 import org.apache.hadoop.hbase.client.RegionReplicaUtil;
35 import org.apache.hadoop.hbase.MetaTableAccessor;
36 import org.apache.hadoop.hbase.master.MasterServices;
37 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
38 import org.apache.hadoop.hbase.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;
39 import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
40 import org.apache.hadoop.hbase.snapshot.CorruptedSnapshotException;
41 import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
42 import org.apache.hadoop.hbase.snapshot.SnapshotManifest;
43 import org.apache.hadoop.hbase.snapshot.SnapshotReferenceUtil;
44 import org.apache.hadoop.hbase.util.FSUtils;
45 import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
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 private static final Log LOG = LogFactory.getLog(MasterSnapshotVerifier.class);
79
80 private SnapshotDescription snapshot;
81 private FileSystem workingDirFs;
82 private TableName tableName;
83 private MasterServices services;
84
85
86
87
88
89
90 public MasterSnapshotVerifier(MasterServices services,
91 SnapshotDescription snapshot, FileSystem workingDirFs) {
92 this.workingDirFs = workingDirFs;
93 this.services = services;
94 this.snapshot = snapshot;
95 this.tableName = TableName.valueOf(snapshot.getTable());
96 }
97
98
99
100
101
102
103
104
105
106 public void verifySnapshot(Path snapshotDir, Set<String> snapshotServers)
107 throws CorruptedSnapshotException, IOException {
108 SnapshotManifest manifest = SnapshotManifest.open(services.getConfiguration(), workingDirFs,
109 snapshotDir, snapshot);
110
111 verifySnapshotDescription(snapshotDir);
112
113
114 verifyTableInfo(manifest);
115
116
117 verifyRegions(manifest);
118 }
119
120
121
122
123
124 private void verifySnapshotDescription(Path snapshotDir) throws CorruptedSnapshotException {
125 SnapshotDescription found = SnapshotDescriptionUtils.readSnapshotInfo(workingDirFs,
126 snapshotDir);
127 if (!this.snapshot.equals(found)) {
128 throw new CorruptedSnapshotException("Snapshot read (" + found
129 + ") doesn't equal snapshot we ran (" + snapshot + ").", snapshot);
130 }
131 }
132
133
134
135
136
137 private void verifyTableInfo(final SnapshotManifest manifest) throws IOException {
138 HTableDescriptor htd = manifest.getTableDescriptor();
139 if (htd == null) {
140 throw new CorruptedSnapshotException("Missing Table Descriptor", snapshot);
141 }
142
143 if (!htd.getNameAsString().equals(snapshot.getTable())) {
144 throw new CorruptedSnapshotException("Invalid Table Descriptor. Expected "
145 + snapshot.getTable() + " name, got " + htd.getNameAsString(), snapshot);
146 }
147 }
148
149
150
151
152
153
154 private void verifyRegions(final SnapshotManifest manifest) throws IOException {
155 List<HRegionInfo> regions;
156 if (TableName.META_TABLE_NAME.equals(tableName)) {
157 regions = new MetaTableLocator().getMetaRegions(services.getZooKeeper());
158 } else {
159 regions = MetaTableAccessor.getTableRegions(services.getZooKeeper(),
160 services.getConnection(), tableName);
161 }
162
163 RegionReplicaUtil.removeNonDefaultRegions(regions);
164
165 Map<String, SnapshotRegionManifest> regionManifests = manifest.getRegionManifestsMap();
166 if (regionManifests == null) {
167 String msg = "Snapshot " + ClientSnapshotDescriptionUtils.toString(snapshot) + " looks empty";
168 LOG.error(msg);
169 throw new CorruptedSnapshotException(msg);
170 }
171
172 String errorMsg = "";
173 if (regionManifests.size() != regions.size()) {
174 errorMsg = "Regions moved during the snapshot '" +
175 ClientSnapshotDescriptionUtils.toString(snapshot) + "'. expected=" +
176 regions.size() + " snapshotted=" + regionManifests.size() + ".";
177 LOG.error(errorMsg);
178 }
179
180
181 for (HRegionInfo region : regions) {
182 SnapshotRegionManifest regionManifest = regionManifests.get(region.getEncodedName());
183 if (regionManifest == null) {
184
185 String mesg = " No snapshot region directory found for region:" + region;
186 if (errorMsg.isEmpty()) errorMsg = mesg;
187 LOG.error(mesg);
188 continue;
189 }
190
191 verifyRegionInfo(region, regionManifest);
192 }
193
194 if (!errorMsg.isEmpty()) {
195 throw new CorruptedSnapshotException(errorMsg);
196 }
197
198
199
200 SnapshotReferenceUtil.verifySnapshot(services.getConfiguration(),
201 FSUtils.getRootDirFileSystem(services.getConfiguration()), manifest);
202 }
203
204
205
206
207
208
209 private void verifyRegionInfo(final HRegionInfo region,
210 final SnapshotRegionManifest manifest) throws IOException {
211 HRegionInfo manifestRegionInfo = HRegionInfo.convert(manifest.getRegionInfo());
212 if (!region.equals(manifestRegionInfo)) {
213 String msg = "Manifest region info " + manifestRegionInfo +
214 "doesn't match expected region:" + region;
215 throw new CorruptedSnapshotException(msg, snapshot);
216 }
217 }
218 }