1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.snapshot;
20
21 import java.io.IOException;
22 import java.io.FileNotFoundException;
23 import java.text.SimpleDateFormat;
24 import java.util.concurrent.atomic.AtomicInteger;
25 import java.util.concurrent.atomic.AtomicLong;
26 import java.util.Date;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 import org.apache.hadoop.fs.Path;
32 import org.apache.hadoop.fs.FileSystem;
33 import org.apache.hadoop.classification.InterfaceAudience;
34 import org.apache.hadoop.classification.InterfaceStability;
35 import org.apache.hadoop.conf.Configured;
36 import org.apache.hadoop.util.StringUtils;
37 import org.apache.hadoop.util.Tool;
38 import org.apache.hadoop.util.ToolRunner;
39
40 import org.apache.hadoop.conf.Configuration;
41 import org.apache.hadoop.hbase.HBaseConfiguration;
42 import org.apache.hadoop.hbase.HTableDescriptor;
43 import org.apache.hadoop.hbase.io.HFileLink;
44 import org.apache.hadoop.hbase.io.HLogLink;
45 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
46 import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
47 import org.apache.hadoop.hbase.snapshot.SnapshotReferenceUtil;
48 import org.apache.hadoop.hbase.util.Bytes;
49 import org.apache.hadoop.hbase.util.FSUtils;
50 import org.apache.hadoop.hbase.util.FSTableDescriptors;
51
52
53
54
55
56
57
58
59
60
61 @InterfaceAudience.Public
62 @InterfaceStability.Evolving
63 public final class SnapshotInfo extends Configured implements Tool {
64 private static final Log LOG = LogFactory.getLog(SnapshotInfo.class);
65
66 private FileSystem fs;
67 private Path rootDir;
68
69 private HTableDescriptor snapshotTableDesc;
70 private SnapshotDescription snapshotDesc;
71 private Path snapshotDir;
72
73 @Override
74 public int run(String[] args) throws IOException, InterruptedException {
75 String snapshotName = null;
76 boolean showSchema = false;
77 boolean showFiles = false;
78 boolean showStats = false;
79
80
81 for (int i = 0; i < args.length; i++) {
82 String cmd = args[i];
83 try {
84 if (cmd.equals("-snapshot")) {
85 snapshotName = args[++i];
86 } else if (cmd.equals("-files")) {
87 showFiles = true;
88 } else if (cmd.equals("-stats")) {
89 showStats = true;
90 } else if (cmd.equals("-schema")) {
91 showSchema = true;
92 } else if (cmd.equals("-h") || cmd.equals("--help")) {
93 printUsageAndExit();
94 } else {
95 System.err.println("UNEXPECTED: " + cmd);
96 printUsageAndExit();
97 }
98 } catch (Exception e) {
99 printUsageAndExit();
100 }
101 }
102
103 if (snapshotName == null) {
104 System.err.println("Missing snapshot name!");
105 printUsageAndExit();
106 return 1;
107 }
108
109 Configuration conf = getConf();
110 fs = FileSystem.get(conf);
111 rootDir = FSUtils.getRootDir(conf);
112
113
114 if (!loadSnapshotInfo(snapshotName)) {
115 System.err.println("Snapshot '" + snapshotName + "' not found!");
116 return 1;
117 }
118
119 printInfo();
120 if (showSchema) printSchema();
121 if (showFiles || showStats) printFiles(showFiles);
122
123 return 0;
124 }
125
126
127
128
129
130
131 private boolean loadSnapshotInfo(final String snapshotName) throws IOException {
132 snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);
133 if (!fs.exists(snapshotDir)) {
134 LOG.warn("Snapshot '" + snapshotName + "' not found in: " + snapshotDir);
135 return false;
136 }
137
138 snapshotDesc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);
139 snapshotTableDesc = FSTableDescriptors.getTableDescriptor(fs, snapshotDir);
140 return true;
141 }
142
143
144
145
146 private void printInfo() {
147 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
148 System.out.println("Snapshot Info");
149 System.out.println("----------------------------------------");
150 System.out.println(" Name: " + snapshotDesc.getName());
151 System.out.println(" Type: " + snapshotDesc.getType());
152 System.out.println(" Table: " + snapshotDesc.getTable());
153 System.out.println(" Format: " + snapshotDesc.getVersion());
154 System.out.println("Created: " + df.format(new Date(snapshotDesc.getCreationTime())));
155 System.out.println();
156 }
157
158
159
160
161 private void printSchema() {
162 System.out.println("Table Descriptor");
163 System.out.println("----------------------------------------");
164 System.out.println(snapshotTableDesc.toString());
165 System.out.println();
166 }
167
168
169
170
171
172 private void printFiles(final boolean showFiles) throws IOException {
173 final String table = snapshotDesc.getTable();
174 final Configuration conf = getConf();
175
176 if (showFiles) {
177 System.out.println("Snapshot Files");
178 System.out.println("----------------------------------------");
179 }
180
181
182 final AtomicInteger hfileArchiveCount = new AtomicInteger();
183 final AtomicInteger hfilesMissing = new AtomicInteger();
184 final AtomicInteger hfilesCount = new AtomicInteger();
185 final AtomicInteger logsMissing = new AtomicInteger();
186 final AtomicInteger logsCount = new AtomicInteger();
187 final AtomicLong hfileArchiveSize = new AtomicLong();
188 final AtomicLong hfileSize = new AtomicLong();
189 final AtomicLong logSize = new AtomicLong();
190 SnapshotReferenceUtil.visitReferencedFiles(fs, snapshotDir,
191 new SnapshotReferenceUtil.FileVisitor() {
192 public void storeFile (final String region, final String family, final String hfile)
193 throws IOException {
194 Path path = new Path(family, HFileLink.createHFileLinkName(table, region, hfile));
195 HFileLink link = new HFileLink(conf, path);
196 boolean inArchive = false;
197 long size = -1;
198 try {
199 if ((inArchive = fs.exists(link.getArchivePath()))) {
200 size = fs.getFileStatus(link.getArchivePath()).getLen();
201 hfileArchiveSize.addAndGet(size);
202 hfileArchiveCount.addAndGet(1);
203 } else {
204 size = link.getFileStatus(fs).getLen();
205 hfileSize.addAndGet(size);
206 hfilesCount.addAndGet(1);
207 }
208 } catch (FileNotFoundException e) {
209 hfilesMissing.addAndGet(1);
210 }
211
212 if (showFiles) {
213 System.out.printf("%8s %s/%s/%s/%s %s%n",
214 (size < 0 ? "-" : StringUtils.humanReadableInt(size)),
215 table, region, family, hfile,
216 (inArchive ? "(archive)" : (size < 0) ? "(NOT FOUND)" : ""));
217 }
218 }
219
220 public void recoveredEdits (final String region, final String logfile)
221 throws IOException {
222 Path path = SnapshotReferenceUtil.getRecoveredEdits(snapshotDir, region, logfile);
223 long size = fs.getFileStatus(path).getLen();
224 logSize.addAndGet(size);
225 logsCount.addAndGet(1);
226
227 if (showFiles) {
228 System.out.printf("%8s recovered.edits %s on region %s%n",
229 StringUtils.humanReadableInt(size), logfile, region);
230 }
231 }
232
233 public void logFile (final String server, final String logfile)
234 throws IOException {
235 HLogLink logLink = new HLogLink(conf, server, logfile);
236 long size = -1;
237 try {
238 size = logLink.getFileStatus(fs).getLen();
239 logSize.addAndGet(size);
240 logsCount.addAndGet(1);
241 } catch (FileNotFoundException e) {
242 logsMissing.addAndGet(1);
243 }
244
245 if (showFiles) {
246 System.out.printf("%8s log %s on server %s %s%n",
247 (size < 0 ? "-" : StringUtils.humanReadableInt(size)),
248 logfile, server,
249 (size < 0 ? "(NOT FOUND)" : ""));
250 }
251 }
252 });
253
254
255 System.out.println();
256 if (hfilesMissing.get() > 0 || logsMissing.get() > 0) {
257 System.out.println("**************************************************************");
258 System.out.printf("BAD SNAPSHOT: %d hfile(s) and %d log(s) missing.%n",
259 hfilesMissing.get(), logsMissing.get());
260 System.out.println("**************************************************************");
261 }
262
263 System.out.printf("%d HFiles (%d in archive), total size %s (%.2f%% %s shared with the source table)%n",
264 hfilesCount.get() + hfileArchiveCount.get(), hfileArchiveCount.get(),
265 StringUtils.humanReadableInt(hfileSize.get() + hfileArchiveSize.get()),
266 ((float)hfileSize.get() / (hfileSize.get() + hfileArchiveSize.get())) * 100,
267 StringUtils.humanReadableInt(hfileSize.get())
268 );
269 System.out.printf("%d Logs, total size %s%n",
270 logsCount.get(), StringUtils.humanReadableInt(logSize.get()));
271 System.out.println();
272 }
273
274 private void printUsageAndExit() {
275 System.err.printf("Usage: bin/hbase %s [options]%n", getClass().getName());
276 System.err.println(" where [options] are:");
277 System.err.println(" -h|-help Show this help and exit.");
278 System.err.println(" -snapshot NAME Snapshot to examine.");
279 System.err.println(" -files Files and logs list.");
280 System.err.println(" -stats Files and logs stats.");
281 System.err.println(" -schema Describe the snapshotted table.");
282 System.err.println();
283 System.err.println("Examples:");
284 System.err.println(" hbase " + getClass() + " \\");
285 System.err.println(" -snapshot MySnapshot -files");
286 System.exit(1);
287 }
288
289
290
291
292
293
294
295
296 static int innerMain(final String [] args) throws Exception {
297 return ToolRunner.run(HBaseConfiguration.create(), new SnapshotInfo(), args);
298 }
299
300 public static void main(String[] args) throws Exception {
301 System.exit(innerMain(args));
302 }
303 }