docs: public Map<Integer, HostInfo> waitForGroupJoin(int expectedHosts) {
          Map<Integer, HostInfo> hostInfos = Maps.newTreeMap();
  
          try {
              while (true) {
                  ZKUtil.FutureWatcher fw = new ZKUtil.FutureWatcher();
                  final List<String> children = m_zk.getChildren(CoreZK.hosts, fw);
                  final int numChildren = children.size();
  
                  for (String child : children) {
                      final HostInfo info = HostInfo.fromBytes(m_zk.getData(ZKUtil.joinZKPath(CoreZK.hosts, child), false, null));
  
                      hostInfos.put(parseHostId(child), info);
                  }
  
                  /*
                   * If the target number of hosts has been reached
                   * break out
                   */
                  if ( numChildren == expectedHosts) {
                      break;
                  }
  
  
                  /*
                   * If there are extra hosts that means too many Volt procs were started.
                   * Kill this node based on the assumption that we are the extra one. In most
                   * cases this is correct and fine and in the worst case the cluster will hang coming up
                   * because two or more hosts killed themselves
                   */
                  if ( numChildren > expectedHosts) {
                      org.voltdb.VoltDB.crashLocalVoltDB("Expected to find " + expectedHosts +
                              " hosts in cluster at startup but found " + numChildren +
                              ".  Terminating this host.", false, null);
                  }
                  fw.get();
              }
          } catch (Exception e) {
              org.voltdb.VoltDB.crashLocalVoltDB("Error waiting for hosts to be ready", false, e);
          }
  
          assert hostInfos.size() == expectedHosts;
          return hostInfos;
      }