blob: abb24eba5dc1338ea4dfbbb5194c2575ce18f064 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.accumulo.server.util;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.PrintStream;
import java.util.Base64;
import org.apache.accumulo.core.cli.ConfigOpts;
import org.apache.accumulo.fate.zookeeper.ZooReaderWriter;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.data.Stat;
import com.beust.jcommander.Parameter;
public class DumpZookeeper {
private static ZooReaderWriter zk = null;
private static class Encoded {
public String encoding;
public String value;
Encoded(String e, String v) {
encoding = e;
value = v;
}
}
static class Opts extends ConfigOpts {
@Parameter(names = {"-r", "-root", "--root"},
description = "Root ZooKeeper directory to start dump at")
String root = "/";
@Parameter(names = {"-x", "-xml", "--xml"},
description = "Output dump as XML (instead of human readable")
boolean xml = false;
}
public static void main(String[] args) throws KeeperException, InterruptedException {
Opts opts = new Opts();
opts.parseArgs(DumpZookeeper.class.getName(), args);
PrintStream out = System.out;
zk = new ZooReaderWriter(opts.getSiteConfiguration());
if (opts.xml) {
writeXml(out, opts.root);
} else {
writeHumanReadable(out, opts.root);
}
}
private static void writeXml(PrintStream out, String root)
throws KeeperException, InterruptedException {
write(out, 0, "<dump root='%s'>", root);
for (String child : zk.getChildren(root)) {
if (!child.equals("zookeeper")) {
childXml(out, root, child, 1);
}
}
write(out, 0, "</dump>");
}
private static void childXml(PrintStream out, String root, String child, int indent)
throws KeeperException, InterruptedException {
String path = root + "/" + child;
if (root.endsWith("/")) {
path = root + child;
}
Stat stat = zk.getStatus(path);
if (stat == null) {
return;
}
String type = "node";
if (stat.getEphemeralOwner() != 0) {
type = "ephemeral";
}
if (stat.getNumChildren() == 0) {
if (stat.getDataLength() == 0) {
write(out, indent, "<%s name='%s'/>", type, child);
} else {
Encoded value = value(path);
write(out, indent, "<%s name='%s' encoding='%s' value='%s'/>", type, child, value.encoding,
value.value);
}
} else {
if (stat.getDataLength() == 0) {
write(out, indent, "<%s name='%s'>", type, child);
} else {
Encoded value = value(path);
write(out, indent, "<%s name='%s' encoding='%s' value='%s'>", type, child, value.encoding,
value.value);
}
for (String c : zk.getChildren(path)) {
childXml(out, path, c, indent + 1);
}
write(out, indent, "</node>");
}
}
private static Encoded value(String path) throws KeeperException, InterruptedException {
byte[] data = zk.getData(path);
for (byte element : data) {
// does this look like simple ascii?
if (element < ' ' || element > '~') {
return new Encoded("base64", Base64.getEncoder().encodeToString(data));
}
}
return new Encoded(UTF_8.name(), new String(data, UTF_8));
}
private static void write(PrintStream out, int indent, String fmt, Object... args) {
for (int i = 0; i < indent; i++) {
out.print(" ");
}
out.println(String.format(fmt, args));
}
private static void writeHumanReadable(PrintStream out, String root)
throws KeeperException, InterruptedException {
write(out, 0, "%s:", root);
for (String child : zk.getChildren(root)) {
if (!child.equals("zookeeper")) {
childHumanReadable(out, root, child, 1);
}
}
}
private static void childHumanReadable(PrintStream out, String root, String child, int indent)
throws KeeperException, InterruptedException {
String path = root + "/" + child;
if (root.endsWith("/")) {
path = root + child;
}
Stat stat = zk.getStatus(path);
if (stat == null) {
return;
}
String node = child;
if (stat.getEphemeralOwner() != 0) {
node = "*" + child + "*";
}
if (stat.getDataLength() == 0) {
write(out, indent, "%s:", node);
} else {
write(out, indent, "%s: %s", node, value(path).value);
}
if (stat.getNumChildren() > 0) {
for (String c : zk.getChildren(path)) {
childHumanReadable(out, path, c, indent + 1);
}
}
}
}