/**
   * Helper method to connect to a peer
   *
   * @param peerId peer's identifier
   * @return object representing the peer
   * @throws ReplicationException
   */
  private ReplicationPeer getPeer(String peerId) throws ReplicationException {
    Configuration peerConf = getPeerConf(peerId);
    if (peerConf == null) {
      return null;
    }
    if (this.ourClusterKey.equals(ZKUtil.getZooKeeperClusterKey(peerConf))) {
      LOG.debug("Not connecting to " + peerId + " because it's us");
      return null;
    }

    ReplicationPeer peer =
        new ReplicationPeer(peerConf, peerId, ZKUtil.getZooKeeperClusterKey(peerConf));
    try {
      peer.startStateTracker(this.zookeeper, this.getPeerStateNode(peerId));
    } catch (KeeperException e) {
      throw new ReplicationException(
          "Error starting the peer state tracker for peerId=" + peerId, e);
    }

    try {
      peer.startTableCFsTracker(this.zookeeper, this.getTableCFsNode(peerId));
    } catch (KeeperException e) {
      throw new ReplicationException(
          "Error starting the peer tableCFs tracker for peerId=" + peerId, e);
    }

    peer.getZkw().registerListener(new PeerRegionServerListener(peer));
    return peer;
  }
 @Override
 public void disconnectFromPeer(String peerId) {
   ReplicationPeer rp = this.peerClusters.get(peerId);
   if (rp != null) {
     rp.getZkw().close();
     this.peerClusters.remove(peerId);
   }
 }
 /**
  * Returns all region servers from given peer
  *
  * @param peerClusterId (byte) the cluster to interrogate
  * @return addresses of all region servers
  */
 public List<HServerAddress> getSlavesAddresses(String peerClusterId) {
   if (this.peerClusters.size() == 0) {
     return new ArrayList<HServerAddress>(0);
   }
   ReplicationPeer peer = this.peerClusters.get(peerClusterId);
   if (peer == null) {
     return new ArrayList<HServerAddress>(0);
   }
   peer.setRegionServers(fetchSlavesAddresses(peer.getZkw()));
   return peer.getRegionServers();
 }
 @Override
 public synchronized void nodeChildrenChanged(String path) {
   if (path.equals(regionServerListNode)) {
     try {
       LOG.info("Detected change to peer regionservers, fetching updated list");
       peer.setRegionServers(fetchSlavesAddresses(peer.getZkw()));
     } catch (KeeperException e) {
       LOG.fatal("Error reading slave addresses", e);
     }
   }
 }
 /**
  * A private method used to re-establish a zookeeper session with a peer cluster.
  *
  * @param ke
  * @param peer
  */
 private void reconnectPeer(KeeperException ke, ReplicationPeer peer) {
   if (ke instanceof ConnectionLossException
       || ke instanceof SessionExpiredException
       || ke instanceof AuthFailedException) {
     LOG.warn("Lost the ZooKeeper connection for peer " + peer.getClusterKey(), ke);
     try {
       peer.reloadZkWatcher();
       peer.getZkw().registerListener(new PeerRegionServerListener(peer));
     } catch (IOException io) {
       LOG.warn("Creation of ZookeeperWatcher failed for peer " + peer.getClusterKey(), io);
     }
   }
 }
 @Override
 public UUID getPeerUUID(String peerId) {
   ReplicationPeer peer = this.peerClusters.get(peerId);
   if (peer == null) {
     return null;
   }
   UUID peerUUID = null;
   try {
     peerUUID = ZKClusterId.getUUIDForCluster(peer.getZkw());
   } catch (KeeperException ke) {
     reconnectPeer(ke, peer);
   }
   return peerUUID;
 }
 /**
  * This method connects this cluster to another one and registers it in this region server's
  * replication znode
  *
  * @param peerId id of the peer cluster
  */
 public boolean connectToPeer(String peerId) throws IOException {
   if (this.clientOnly) {
     return false;
   }
   if (this.peerClusters.containsKey(peerId)) {
     return false;
     // TODO remove when we support it
   } else if (this.peerClusters.size() > 0) {
     LOG.warn("Multiple slaves feature not supported");
     return false;
   }
   ReplicationPeer peer = getPeer(peerId);
   if (peer == null) {
     return false;
   }
   this.peerClusters.put(peerId, peer);
   this.zookeeperWrapper.ensureExists(
       this.zookeeperWrapper.getZNode(this.rsServerNameZnode, peerId));
   LOG.info("Added new peer cluster " + peer.getClusterKey());
   return true;
 }
 @Override
 public boolean connectToPeer(String peerId) throws ReplicationException {
   if (peerClusters == null) {
     return false;
   }
   if (this.peerClusters.containsKey(peerId)) {
     return false;
   }
   ReplicationPeer peer = null;
   try {
     peer = getPeer(peerId);
   } catch (Exception e) {
     throw new ReplicationException("Error connecting to peer with id=" + peerId, e);
   }
   if (peer == null) {
     return false;
   }
   this.peerClusters.put(peerId, peer);
   LOG.info("Added new peer cluster " + peer.getClusterKey());
   return true;
 }
 @Override
 public List<ServerName> getRegionServersOfConnectedPeer(String peerId) {
   if (this.peerClusters.size() == 0) {
     return Collections.emptyList();
   }
   ReplicationPeer peer = this.peerClusters.get(peerId);
   if (peer == null) {
     return Collections.emptyList();
   }
   List<ServerName> addresses;
   try {
     addresses = fetchSlavesAddresses(peer.getZkw());
   } catch (KeeperException ke) {
     if (LOG.isDebugEnabled()) {
       LOG.debug("Fetch salves addresses failed.", ke);
     }
     reconnectPeer(ke, peer);
     addresses = Collections.emptyList();
   }
   peer.setRegionServers(addresses);
   return peer.getRegionServers();
 }
 @Override
 public boolean getStatusOfPeerFromBackingStore(String id) throws ReplicationException {
   try {
     if (!peerExists(id)) {
       throw new IllegalArgumentException("peer " + id + " doesn't exist");
     }
     String peerStateZNode = getPeerStateNode(id);
     try {
       return ReplicationPeer.isStateEnabled(ZKUtil.getData(this.zookeeper, peerStateZNode));
     } catch (KeeperException e) {
       throw new ReplicationException(e);
     } catch (DeserializationException e) {
       throw new ReplicationException(e);
     }
   } catch (KeeperException e) {
     throw new ReplicationException(
         "Unable to get status of the peer with id=" + id + " from backing store", e);
   }
 }
 public PeerRegionServerListener(ReplicationPeer replicationPeer) {
   super(replicationPeer.getZkw());
   this.peer = replicationPeer;
   this.regionServerListNode = peer.getZkw().rsZNode;
 }