/** * 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; }