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.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 boolean hasMobStore = false;
174
175
176 if (regionManifests.get(MobUtils.getMobRegionInfo(tableName).getEncodedName()) != null) {
177 hasMobStore = true;
178 }
179 int realRegionCount = hasMobStore ? regionManifests.size() - 1 : regionManifests.size();
180 if (realRegionCount != regions.size()) {
181 errorMsg = "Regions moved during the snapshot '" +
182 ClientSnapshotDescriptionUtils.toString(snapshot) + "'. expected=" +
183 regions.size() + " snapshotted=" + realRegionCount + ".";
184 LOG.error(errorMsg);
185 }
186
187
188 for (HRegionInfo region : regions) {
189 SnapshotRegionManifest regionManifest = regionManifests.get(region.getEncodedName());
190 if (regionManifest == null) {
191
192 String mesg = " No snapshot region directory found for region:" + region;
193 if (errorMsg.isEmpty()) errorMsg = mesg;
194 LOG.error(mesg);
195 continue;
196 }
197
198 verifyRegionInfo(region, regionManifest);
199 }
200
201 if (!errorMsg.isEmpty()) {
202 throw new CorruptedSnapshotException(errorMsg);
203 }
204
205
206 SnapshotReferenceUtil.verifySnapshot(services.getConfiguration(), fs, manifest);
207 }
208
209
210
211
212
213
214 private void verifyRegionInfo(final HRegionInfo region,
215 final SnapshotRegionManifest manifest) throws IOException {
216 HRegionInfo manifestRegionInfo = HRegionInfo.convert(manifest.getRegionInfo());
217 if (!region.equals(manifestRegionInfo)) {
218 String msg = "Manifest region info " + manifestRegionInfo +
219 "doesn't match expected region:" + region;
220 throw new CorruptedSnapshotException(msg, snapshot);
221 }
222 }
223 }