| /* |
| * 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.util.Formattable; |
| import java.util.Formatter; |
| import java.util.List; |
| import java.util.Map.Entry; |
| import java.util.TreeMap; |
| import java.util.TreeSet; |
| import java.util.UUID; |
| |
| import org.apache.accumulo.core.Constants; |
| import org.apache.accumulo.core.cli.Help; |
| import org.apache.accumulo.core.conf.Property; |
| import org.apache.accumulo.core.conf.SiteConfiguration; |
| import org.apache.accumulo.fate.zookeeper.ServiceLock; |
| import org.apache.accumulo.fate.zookeeper.ZooCache; |
| import org.apache.accumulo.fate.zookeeper.ZooReader; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.beust.jcommander.Parameter; |
| |
| public class ListInstances { |
| |
| private static final Logger log = LoggerFactory.getLogger(ListInstances.class); |
| |
| private static final int NAME_WIDTH = 20; |
| private static final int UUID_WIDTH = 37; |
| private static final int MANAGER_WIDTH = 30; |
| |
| private static final int ZOOKEEPER_TIMER_MILLIS = 30 * 1000; |
| |
| static class Opts extends Help { |
| @Parameter(names = "--print-errors", description = "display errors while listing instances") |
| boolean printErrors = false; |
| @Parameter(names = "--print-all", |
| description = "print information for all instances, not just those with names") |
| boolean printAll = false; |
| @Parameter(names = {"-z", "--zookeepers"}, description = "the zookeepers to contact") |
| String keepers = null; |
| } |
| |
| static Opts opts = new Opts(); |
| static int errors = 0; |
| |
| public static void main(String[] args) { |
| opts.parseArgs(ListInstances.class.getName(), args); |
| |
| if (opts.keepers == null) { |
| var siteConfig = SiteConfiguration.auto(); |
| opts.keepers = siteConfig.get(Property.INSTANCE_ZK_HOST); |
| } |
| |
| String keepers = opts.keepers; |
| boolean printAll = opts.printAll; |
| boolean printErrors = opts.printErrors; |
| |
| listInstances(keepers, printAll, printErrors); |
| |
| } |
| |
| static synchronized void listInstances(String keepers, boolean printAll, boolean printErrors) { |
| errors = 0; |
| |
| System.out.println("INFO : Using ZooKeepers " + keepers); |
| ZooReader rdr = new ZooReader(keepers, ZOOKEEPER_TIMER_MILLIS); |
| ZooCache cache = new ZooCache(keepers, ZOOKEEPER_TIMER_MILLIS); |
| |
| TreeMap<String,UUID> instanceNames = getInstanceNames(rdr, printErrors); |
| |
| System.out.println(); |
| printHeader(); |
| |
| for (Entry<String,UUID> entry : instanceNames.entrySet()) { |
| printInstanceInfo(cache, entry.getKey(), entry.getValue(), printErrors); |
| } |
| |
| TreeSet<UUID> instancedIds = getInstanceIDs(rdr, printErrors); |
| instancedIds.removeAll(instanceNames.values()); |
| |
| if (printAll) { |
| for (UUID uuid : instancedIds) { |
| printInstanceInfo(cache, null, uuid, printErrors); |
| } |
| } else if (!instancedIds.isEmpty()) { |
| System.out.println(); |
| System.out.println("INFO : " + instancedIds.size() |
| + " unamed instances were not printed, run with --print-all to see all instances"); |
| } else { |
| System.out.println(); |
| } |
| |
| if (!printErrors && errors > 0) { |
| System.err.println( |
| "WARN : There were " + errors + " errors, run with --print-errors to see more info"); |
| } |
| } |
| |
| private static class CharFiller implements Formattable { |
| |
| char c; |
| |
| CharFiller(char c) { |
| this.c = c; |
| } |
| |
| @Override |
| public void formatTo(Formatter formatter, int flags, int width, int precision) { |
| |
| StringBuilder sb = new StringBuilder(); |
| for (int i = 0; i < width; i++) { |
| sb.append(c); |
| } |
| formatter.format(sb.toString()); |
| } |
| |
| } |
| |
| private static void printHeader() { |
| System.out.printf(" %-" + NAME_WIDTH + "s| %-" + UUID_WIDTH + "s| %-" + MANAGER_WIDTH + "s%n", |
| "Instance Name", "Instance ID", "Manager"); |
| System.out.printf( |
| "%" + (NAME_WIDTH + 1) + "s+%" + (UUID_WIDTH + 1) + "s+%" + (MANAGER_WIDTH + 1) + "s%n", |
| new CharFiller('-'), new CharFiller('-'), new CharFiller('-')); |
| |
| } |
| |
| private static void printInstanceInfo(ZooCache cache, String instanceName, UUID iid, |
| boolean printErrors) { |
| String manager = getManager(cache, iid, printErrors); |
| if (instanceName == null) { |
| instanceName = ""; |
| } |
| |
| if (manager == null) { |
| manager = ""; |
| } |
| |
| System.out.printf("%" + NAME_WIDTH + "s |%" + UUID_WIDTH + "s |%" + MANAGER_WIDTH + "s%n", |
| "\"" + instanceName + "\"", iid, manager); |
| } |
| |
| private static String getManager(ZooCache cache, UUID iid, boolean printErrors) { |
| |
| if (iid == null) { |
| return null; |
| } |
| |
| try { |
| var zLockManagerPath = |
| ServiceLock.path(Constants.ZROOT + "/" + iid + Constants.ZMANAGER_LOCK); |
| byte[] manager = ServiceLock.getLockData(cache, zLockManagerPath, null); |
| if (manager == null) { |
| return null; |
| } |
| return new String(manager, UTF_8); |
| } catch (Exception e) { |
| handleException(e, printErrors); |
| return null; |
| } |
| } |
| |
| private static TreeMap<String,UUID> getInstanceNames(ZooReader zk, boolean printErrors) { |
| |
| String instancesPath = Constants.ZROOT + Constants.ZINSTANCES; |
| |
| TreeMap<String,UUID> tm = new TreeMap<>(); |
| |
| List<String> names; |
| |
| try { |
| names = zk.getChildren(instancesPath); |
| } catch (Exception e) { |
| handleException(e, printErrors); |
| return tm; |
| } |
| |
| for (String name : names) { |
| String instanceNamePath = Constants.ZROOT + Constants.ZINSTANCES + "/" + name; |
| try { |
| UUID iid = UUID.fromString(new String(zk.getData(instanceNamePath), UTF_8)); |
| tm.put(name, iid); |
| } catch (Exception e) { |
| handleException(e, printErrors); |
| tm.put(name, null); |
| } |
| } |
| |
| return tm; |
| } |
| |
| private static TreeSet<UUID> getInstanceIDs(ZooReader zk, boolean printErrors) { |
| TreeSet<UUID> ts = new TreeSet<>(); |
| |
| try { |
| List<String> children = zk.getChildren(Constants.ZROOT); |
| |
| for (String iid : children) { |
| if (iid.equals("instances")) { |
| continue; |
| } |
| try { |
| ts.add(UUID.fromString(iid)); |
| } catch (Exception e) { |
| log.error("Exception: ", e); |
| } |
| } |
| } catch (Exception e) { |
| handleException(e, printErrors); |
| } |
| |
| return ts; |
| } |
| |
| private static void handleException(Exception e, boolean printErrors) { |
| if (printErrors) { |
| log.error("{}", e.getMessage(), e); |
| } |
| |
| errors++; |
| } |
| } |