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.mob.MobUtils;
38 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
39 import org.apache.hadoop.hbase.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;
40 import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
41 import org.apache.hadoop.hbase.snapshot.CorruptedSnapshotException;
42 import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
43 import org.apache.hadoop.hbase.snapshot.SnapshotManifest;
44 import org.apache.hadoop.hbase.snapshot.SnapshotReferenceUtil;
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 fs;
82 private Path rootDir;
83 private TableName tableName;
84 private MasterServices services;
85
86
87
88
89
90
91 public MasterSnapshotVerifier(MasterServices services, SnapshotDescription snapshot, Path rootDir) {
92 this.fs = services.getMasterFileSystem().getFileSystem();
93 this.services = services;
94 this.snapshot = snapshot;
95 this.rootDir = rootDir;
96 this.tableName = TableName.valueOf(snapshot.getTable());
97 }
98
99
100
101
102
103
104
105
106
107 public void verifySnapshot(Path snapshotDir, Set<String> snapshotServers)
108 throws CorruptedSnapshotException, IOException {
109 SnapshotManifest manifest = SnapshotManifest.open(services.getConfiguration(), fs,
110 snapshotDir, snapshot);
111
112 verifySnapshotDescription(snapshotDir);
113
114
115 verifyTableInfo(manifest);
116
117
118 verifyRegions(manifest);
119 }
120
121
122
123
124
125 private void verifySnapshotDescription(Path snapshotDir) throws CorruptedSnapshotException {
126 SnapshotDescription found = SnapshotDescriptionUtils.readSnapshotInfo(fs, 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.getConnection(), tableName);
160 }
161
162 RegionReplicaUtil.removeNonDefaultRegions(regions);
163
164 Map<String, SnapshotRegionManifest> regionManifests = manifest.getRegionManifestsMap();
165 if (regionManifests == null) {
166 String msg = "Snapshot " + ClientSnapshotDescriptionUtils.toString(snapshot) + " looks empty";
167 LOG.error(msg);
168 throw new CorruptedSnapshotException(msg);
169 }
170
171 String errorMsg = "";
172 boolean hasMobStore = false;
173
174
175 if (regionManifests.get(MobUtils.getMobRegionInfo(tableName).getEncodedName()) != null) {
176 hasMobStore = true;
177 }
178 int realRegionCount = hasMobStore ? regionManifests.size() - 1 : regionManifests.size();
179 if (realRegionCount != regions.size()) {
180 errorMsg = "Regions moved during the snapshot '" +
181 ClientSnapshotDescriptionUtils.toString(snapshot) + "'. expected=" +
182 regions.size() + " snapshotted=" + realRegionCount + ".";
183 LOG.error(errorMsg);
184 }
185
186
187 for (HRegionInfo region : regions) {
188 SnapshotRegionManifest regionManifest = regionManifests.get(region.getEncodedName());
189 if (regionManifest == null) {
190
191 String mesg = " No snapshot region directory found for region:" + region;
192 if (errorMsg.isEmpty()) errorMsg = mesg;
193 LOG.error(mesg);
194 continue;
195 }
196
197 verifyRegionInfo(region, regionManifest);
198 }
199
200 if (!errorMsg.isEmpty()) {
201 throw new CorruptedSnapshotException(errorMsg);
202 }
203
204
205 SnapshotReferenceUtil.verifySnapshot(services.getConfiguration(), fs, manifest);
206 }
207
208
209
210
211
212
213 private void verifyRegionInfo(final HRegionInfo region,
214 final SnapshotRegionManifest manifest) throws IOException {
215 HRegionInfo manifestRegionInfo = HRegionInfo.convert(manifest.getRegionInfo());
216 if (!region.equals(manifestRegionInfo)) {
217 String msg = "Manifest region info " + manifestRegionInfo +
218 "doesn't match expected region:" + region;
219 throw new CorruptedSnapshotException(msg, snapshot);
220 }
221 }
222 }