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.zookeeper.MetaTableLocator;
45
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 @InterfaceAudience.Private
75 @InterfaceStability.Unstable
76 public final class MasterSnapshotVerifier {
77 private static final Log LOG = LogFactory.getLog(MasterSnapshotVerifier.class);
78
79 private SnapshotDescription snapshot;
80 private FileSystem fs;
81 private Path rootDir;
82 private TableName tableName;
83 private MasterServices services;
84
85
86
87
88
89
90 public MasterSnapshotVerifier(MasterServices services, SnapshotDescription snapshot, Path rootDir) {
91 this.fs = services.getMasterFileSystem().getFileSystem();
92 this.services = services;
93 this.snapshot = snapshot;
94 this.rootDir = rootDir;
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(), fs,
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(fs, snapshotDir);
126 if (!this.snapshot.equals(found)) {
127 throw new CorruptedSnapshotException("Snapshot read (" + found
128 + ") doesn't equal snapshot we ran (" + snapshot + ").", snapshot);
129 }
130 }
131
132
133
134
135
136 private void verifyTableInfo(final SnapshotManifest manifest) throws IOException {
137 HTableDescriptor htd = manifest.getTableDescriptor();
138 if (htd == null) {
139 throw new CorruptedSnapshotException("Missing Table Descriptor", snapshot);
140 }
141
142 if (!htd.getNameAsString().equals(snapshot.getTable())) {
143 throw new CorruptedSnapshotException("Invalid Table Descriptor. Expected "
144 + snapshot.getTable() + " name, got " + htd.getNameAsString(), snapshot);
145 }
146 }
147
148
149
150
151
152
153 private void verifyRegions(final SnapshotManifest manifest) throws IOException {
154 List<HRegionInfo> regions;
155 if (TableName.META_TABLE_NAME.equals(tableName)) {
156 regions = new MetaTableLocator().getMetaRegions(services.getZooKeeper());
157 } else {
158 regions = MetaTableAccessor.getTableRegions(services.getZooKeeper(),
159 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 if (regionManifests.size() != regions.size()) {
173 errorMsg = "Regions moved during the snapshot '" +
174 ClientSnapshotDescriptionUtils.toString(snapshot) + "'. expected=" +
175 regions.size() + " snapshotted=" + regionManifests.size() + ".";
176 LOG.error(errorMsg);
177 }
178
179
180 for (HRegionInfo region : regions) {
181 SnapshotRegionManifest regionManifest = regionManifests.get(region.getEncodedName());
182 if (regionManifest == null) {
183
184 String mesg = " No snapshot region directory found for region:" + region;
185 if (errorMsg.isEmpty()) errorMsg = mesg;
186 LOG.error(mesg);
187 continue;
188 }
189
190 verifyRegionInfo(region, regionManifest);
191 }
192
193 if (!errorMsg.isEmpty()) {
194 throw new CorruptedSnapshotException(errorMsg);
195 }
196
197
198 SnapshotReferenceUtil.verifySnapshot(services.getConfiguration(), fs, manifest);
199 }
200
201
202
203
204
205
206 private void verifyRegionInfo(final HRegionInfo region,
207 final SnapshotRegionManifest manifest) throws IOException {
208 HRegionInfo manifestRegionInfo = HRegionInfo.convert(manifest.getRegionInfo());
209 if (!region.equals(manifestRegionInfo)) {
210 String msg = "Manifest region info " + manifestRegionInfo +
211 "doesn't match expected region:" + region;
212 throw new CorruptedSnapshotException(msg, snapshot);
213 }
214 }
215 }