/**
   * Constructor used by region servers, connects to the peer cluster right away.
   *
   * @param zookeeperWrapper zkw to wrap
   * @param conf conf to use
   * @param replicating atomic boolean to start/stop replication
   * @param rsName the name of this region server, null if using RZH only to use the helping methods
   * @throws IOException
   */
  public ReplicationZookeeperWrapper(
      ZooKeeperWrapper zookeeperWrapper,
      Configuration conf,
      final AtomicBoolean replicating,
      String rsName)
      throws IOException {
    this.zookeeperWrapper = zookeeperWrapper;
    this.conf = conf;
    this.clientOnly = rsName == null;
    String replicationZNodeName = conf.get("zookeeper.znode.replication", "replication");
    String peersZNodeName = conf.get("zookeeper.znode.replication.peers", "peers");
    String repMasterZNodeName = conf.get("zookeeper.znode.replication.master", "master");
    this.replicationStateNodeName = conf.get("zookeeper.znode.replication.state", "state");
    String clusterIdZNodeName = conf.get("zookeeper.znode.replication.clusterId", "clusterId");
    String rsZNodeName = conf.get("zookeeper.znode.replication.rs", "rs");
    this.ourClusterKey =
        this.conf.get(HConstants.ZOOKEEPER_QUORUM)
            + ":"
            + this.conf.get("hbase.zookeeper.property.clientPort")
            + ":"
            + this.conf.get(HConstants.ZOOKEEPER_ZNODE_PARENT);

    this.peerClusters = new HashMap<String, ReplicationPeer>();
    this.replicationZNode =
        zookeeperWrapper.getZNode(zookeeperWrapper.getParentZNode(), replicationZNodeName);
    this.peersZNode = zookeeperWrapper.getZNode(replicationZNode, peersZNodeName);
    this.zookeeperWrapper.ensureExists(this.peersZNode);
    this.rsZNode = zookeeperWrapper.getZNode(replicationZNode, rsZNodeName);

    this.replicating = replicating;
    readReplicationStateZnode();
    String idResult =
        Bytes.toString(this.zookeeperWrapper.getData(this.replicationZNode, clusterIdZNodeName));
    this.clusterId = idResult == null ? Byte.toString(HConstants.DEFAULT_CLUSTER_ID) : idResult;
    if (this.clientOnly) {
      this.rsServerNameZnode = null;
    } else {
      this.rsServerNameZnode = this.zookeeperWrapper.getZNode(rsZNode, rsName);
      connectExistingPeers();
    }
  }
 /**
  * @param id
  * @throws IllegalArgumentException Thrown when the peer doesn't exist
  */
 public void removePeer(String id) {
   try {
     if (!peerExists(id)) {
       throw new IllegalArgumentException("Cannot remove inexisting peer");
     }
     this.zookeeperWrapper.deleteZNode(zookeeperWrapper.getZNode(this.peersZNode, id), true);
   } catch (InterruptedException e) {
     LOG.error(e);
   } catch (KeeperException e) {
     LOG.error(e);
   }
 }
 /**
  * Get the list of hlogs for the specified region server and peer cluster
  *
  * @param rs server names of the rs
  * @param id peer cluster
  * @param watch the watch to set
  * @return a list of hlogs
  */
 public List<String> getListHLogsForPeerForRS(String rs, String id, Watcher watch) {
   return this.zookeeperWrapper.listZnodes(
       zookeeperWrapper.getZNode(zookeeperWrapper.getZNode(rsZNode, rs), id), watch);
 }
 /**
  * Get the list of peer clusters for the specified server names
  *
  * @param rs server names of the rs
  * @param watch the watch to set
  * @return a list of peer cluster
  */
 public List<String> getListPeersForRS(String rs, Watcher watch) {
   return this.zookeeperWrapper.listZnodes(zookeeperWrapper.getZNode(rsZNode, rs), watch);
 }
 private boolean peerExists(String id) {
   return this.zookeeperWrapper.exists(zookeeperWrapper.getZNode(this.peersZNode, id), false);
 }