/**
* 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.hadoop.hbase.crosssite;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableNotFoundException;
import org.apache.hadoop.hbase.crosssite.locator.ClusterLocator;
import org.apache.hadoop.hbase.crosssite.locator.ClusterLocatorRPCObject;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.hadoop.hbase.zookeeper.ZKUtil;
import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
import org.apache.zookeeper.KeeperException;
/**
* The operations in the cross site table are included.
*/
public class CrossSiteZNodes {
private static final String EPHEMERAL = "-ephemeral";
private static final String CLUSTER_EPHEMERAL = "-cluster-ephemeral";
private static final Log LOG = LogFactory.getLog(CrossSiteZNodes.class);
public final static String CROSS_SITE_ZNODE_NAME = "CrossSite";
public final static String CLUSTERS_ZNODE_NAME = "clusters";
public final static String TABLES_ZNODE_NAME = "tables";
public final static String CLUSTER_ADDRESS_ZNODE_NAME = "address";
public final static String CLUSTER_PEERS_ZNODE_NAME = "peers";
public final static String TABLE_STATE_ZNODE_NAME = "state";
public final static String TABLE_DESC_ZNODE_NAME = "desc";
public final static String TABLE_PROPOSED_DESC_ZNODE_NAME = "proposed_desc";
public final static String TABLE_SPLITKEYS_ZNODE_NAME = "splitkeys";
public final static String CLUSTER_LOCATOR_ZNODE_NAME = "locator";
public final static String HIERARCHY_ZNODE_NAME = "hierarchy";
private final ZooKeeperWatcher zkw;
private String crossSiteZNode;
private String clustersZNode;
private String tablesZNode;
private String hierarchyZNode;
/** The state of the Cross Site Table **/
// When adding new states later, make sure to add towards the end without disturbing the ordinal.
public static enum TableState {
ENABLED,
DISABLED,
ENABLING,
DISABLING,
DELETING,
MODIFYING,
ADDINGCOLUMN,
DELETINGCOLUMN,
MODIFYINGCOLUMN;
};
/**
*
* @param zkw
* @param createBaseZNode
* If true, the base znodes(CrossSite, clusters, tables and hierarchy) will be created if
* they're not present.
* @throws KeeperException
*/
public CrossSiteZNodes(ZooKeeperWatcher zkw, boolean createBaseZNode) throws KeeperException {
this.zkw = zkw;
this.crossSiteZNode = ZKUtil.joinZNode(zkw.baseZNode, CROSS_SITE_ZNODE_NAME);
this.clustersZNode = ZKUtil.joinZNode(crossSiteZNode, CLUSTERS_ZNODE_NAME);
this.tablesZNode = ZKUtil.joinZNode(crossSiteZNode, TABLES_ZNODE_NAME);
this.hierarchyZNode = ZKUtil.joinZNode(crossSiteZNode, HIERARCHY_ZNODE_NAME);
if (createBaseZNode) {
if (ZKUtil.checkExists(zkw, crossSiteZNode) == -1) {
ZKUtil.createWithParents(zkw, crossSiteZNode);
}
if (ZKUtil.checkExists(zkw, clustersZNode) == -1) {
ZKUtil.createWithParents(zkw, clustersZNode);
}
if (ZKUtil.checkExists(zkw, tablesZNode) == -1) {
ZKUtil.createWithParents(zkw, tablesZNode);
}
if (ZKUtil.checkExists(zkw, hierarchyZNode) == -1) {
ZKUtil.createWithParents(zkw, hierarchyZNode);
}
}
}
/**
* The constructor. The base znodes(CrossSite, clusters, tables and hierarchy) will be created if
* they're not present.
*
* @param zkw
* @throws KeeperException
*/
public CrossSiteZNodes(ZooKeeperWatcher zkw) throws KeeperException {
this(zkw, true);
}
/**
* @return the root znode for the cross site tables.
*/
public String getCrossSiteZNode() {
return crossSiteZNode;
}
/**
* @return the root znode for clusters.
*/
public String getClustersZNode() {
return clustersZNode;
}
/**
* Gets the znode path of the cross site tables.
*
* @return
*/
public String getTablesZNode() {
return tablesZNode;
}
/**
* Gets the znode path of the hierarchy.
*
* @return
*/
public String getHierarchyZNode() {
return hierarchyZNode;
}
/**
* Creates the znode for the cluster.
*
* @param clusterInfo
* @throws KeeperException
*/
public void createClusterZNode(ClusterInfo clusterInfo) throws KeeperException {
ZKUtil.createWithParents(zkw, getClusterZNode(clusterInfo.getName()));
ZKUtil.createWithParents(zkw, getClusterAddressZNode(clusterInfo.getName()),
Bytes.toBytes(clusterInfo.getAddress()));
String peersZNode = getClusterPeersZNode(clusterInfo.getName());
ZKUtil.createWithParents(zkw, peersZNode);
if (clusterInfo.getPeers() != null) {
for (ClusterInfo peer : clusterInfo.getPeers()) {
ZKUtil.createWithParents(zkw, ZKUtil.joinZNode(peersZNode, peer.getName()),
Bytes.toBytes(peer.getAddress()));
}
}
}
/**
* Creates the znode for the cluster.
*
* @param name
* @param address
* @throws KeeperException
*/
public void createClusterZNode(String name, String address) throws KeeperException {
ZKUtil.createWithParents(zkw, getClusterZNode(name));
ZKUtil.createWithParents(zkw, getClusterAddressZNode(name), Bytes.toBytes(address));
}
/**
* Creates the peer.
*
* @param clusterName
* @param peer
* @throws KeeperException
*/
public void createPeer(String clusterName, Pair<String, String> peer) throws KeeperException {
String peersZNode = getClusterPeersZNode(clusterName);
ZKUtil.createWithParents(zkw, ZKUtil.joinZNode(peersZNode, peer.getFirst()),
Bytes.toBytes(peer.getSecond()));
}
/**
* Deletes all the children nodes of the cluster but itself.
*
* @param clusterName
* @throws KeeperException
*/
public void deletePeers(String clusterName) throws KeeperException {
ZKUtil.deleteChildrenRecursively(zkw, getClusterPeersZNode(clusterName));
}
/**
* Deletes the peers and all their children.
*
* @param clusterName
* @param peers
* @throws KeeperException
*/
public void deletePeers(String clusterName, String[] peers) throws KeeperException {
String peersZNode = getClusterPeersZNode(clusterName);
if (peers != null && peers.length > 0) {
for (String peer : peers) {
ZKUtil.deleteNodeRecursively(zkw, ZKUtil.joinZNode(peersZNode, peer));
}
} else {
this.deletePeers(clusterName);
}
}
/**
* Deletes the znode of the cluster.
*
* @param clusterName
* @throws KeeperException
*/
public void deleteClusterZNode(String clusterName) throws KeeperException {
ZKUtil.deleteNodeRecursively(zkw, getClusterZNode(clusterName));
}
/**
* Creates the hierarchy znode.
*
* @throws KeeperException
*/
public void createHierarchyZNode() throws KeeperException {
ZKUtil.createWithParents(zkw, hierarchyZNode);
}
/**
* Creates the hierarchy.
*
* <pre>
* Parent | --child1 | --child2
* </pre>
*
* @param parent
* @param children
* @throws KeeperException
*/
public void createHierarchy(String parent, String[] children) throws KeeperException {
String parentZNode = ZKUtil.joinZNode(hierarchyZNode, parent);
ZKUtil.createWithParents(zkw, parentZNode);
for (String child : children) {
ZKUtil.createWithParents(zkw, ZKUtil.joinZNode(parentZNode, child));
}
}
/**
* Deletes the hierarchy under the parent including itself.
*
* @param parent
* @throws KeeperException
*/
public void deleteHierarchy(String parent) throws KeeperException {
String parentZNode = ZKUtil.joinZNode(hierarchyZNode, parent);
List<String> children = ZKUtil.listChildrenNoWatch(zkw, parentZNode);
ZKUtil.deleteNodeRecursively(zkw, ZKUtil.joinZNode(hierarchyZNode, parent));
if (children != null) {
for (String child : children) {
// since the child may be the parent itself, we need to add this check to avoid a infinite
// loop.
if (!child.equals(parent)) {
deleteHierarchy(child);
}
}
}
}
/**
* Deletes the hierarchy of the children, and delete the hierarchy between the parent and
* children.
*
* @param parent
* @param children
* @throws KeeperException
*/
public void deleteHierarchy(String parent, String[] children) throws KeeperException {
if (children != null && children.length > 0) {
String parentZNode = ZKUtil.joinZNode(hierarchyZNode, parent);
for (String child : children) {
ZKUtil.deleteNode(zkw, ZKUtil.joinZNode(parentZNode, child));
// since the child may be the parent itself, we need to add this check to avoid a infinite
// loop.
if (!child.equals(parent)) {
deleteHierarchy(child);
}
}
} else {
deleteHierarchy(parent);
}
}
/**
* Lists the addresses of the clusters.
*
* @return
* @throws KeeperException
*/
public Map<String, String> listClusterAddresses() throws KeeperException {
Map<String, String> clusterMap = new TreeMap<String, String>();
List<String> clusters = ZKUtil.listChildrenNoWatch(this.zkw, this.clustersZNode);
if (clusters != null) {
for (String cluster : clusters) {
clusterMap.put(cluster,
Bytes.toString(ZKUtil.getData(this.zkw, getClusterAddressZNode(cluster))));
}
}
return clusterMap;
}
/**
* Lists the cluster information.
*
* @return
* @throws KeeperException
*/
public Map<String, ClusterInfo> listClusterInfos() throws KeeperException {
Map<String, ClusterInfo> clusterMap = new TreeMap<String, ClusterInfo>();
List<String> clusters = ZKUtil.listChildrenNoWatch(this.zkw, this.clustersZNode);
if (clusters != null) {
for (String cluster : clusters) {
String address = Bytes.toString(ZKUtil.getData(this.zkw, getClusterAddressZNode(cluster)));
List<ClusterInfo> peers = getPeerClusters(cluster);
Set<ClusterInfo> peerSet = new TreeSet<ClusterInfo>();
if (peers != null) {
peerSet.addAll(peers);
}
ClusterInfo ci = new ClusterInfo(cluster, address, peerSet);
clusterMap.put(cluster, ci);
}
}
return clusterMap;
}
/**
* Returns the clusterInfo for the given clusterName
* @param clusterName
* @return
* @throws KeeperException
*/
public ClusterInfo getClusterInfo(String clusterName) throws KeeperException {
List<String> clusters = ZKUtil.listChildrenNoWatch(this.zkw, this.clustersZNode);
if (clusters != null) {
for (String cluster : clusters) {
if (cluster.equals(clusterName)) {
String address = Bytes
.toString(ZKUtil.getData(this.zkw, getClusterAddressZNode(cluster)));
if (address != null) {
List<ClusterInfo> peers = getPeerClusters(cluster);
Set<ClusterInfo> peerSet = new TreeSet<ClusterInfo>();
if (peers != null) {
peerSet.addAll(peers);
}
ClusterInfo ci = new ClusterInfo(cluster, address, peerSet);
return ci;
} else {
return null;
}
}
}
}
return null;
}
/**
* Lists the peers of the cluster.
*
* @param clusterName
* @return
* @throws KeeperException
*/
public List<String> listClusterPeers(String clusterName) throws KeeperException {
List<String> emptyResult = Collections.emptyList();
List<String> result = ZKUtil.listChildrenNoWatch(this.zkw, getClusterPeersZNode(clusterName));
return result == null ? emptyResult : result;
}
/**
* Gets the znode path of the cluster address.
*
* @param clusterName
* @return
*/
public String getClusterAddressZNode(String clusterName) {
return ZKUtil.joinZNode(getClusterZNode(clusterName), CLUSTER_ADDRESS_ZNODE_NAME);
}
/**
* Gets the znode path of the cluster peers.
*
* @param clusterName
* @return
*/
public String getClusterPeersZNode(String clusterName) {
return ZKUtil.joinZNode(getClusterZNode(clusterName), CLUSTER_PEERS_ZNODE_NAME);
}
/**
* Gets the peer znode path of cluster.
*
* @param clusterName
* @param peer
* @return
*/
public String getClusterPeerZNode(String clusterName, String peer) {
return ZKUtil.joinZNode(getClusterPeersZNode(clusterName), peer);
}
/**
* Gets the znode path of the cluster.
*
* @param clusterName
* @return
*/
public String getClusterZNode(String clusterName) {
return ZKUtil.joinZNode(this.clustersZNode, clusterName);
}
/**
* Gets all the peer clusters for the given cluster. Will return null when no peer available for
* the given cluster
*
* @param clusterName
* @return List of peer clusters
* @throws KeeperException
*/
public List<ClusterInfo> getPeerClusters(String clusterName) throws KeeperException {
List<String> peers = ZKUtil.listChildrenNoWatch(zkw, getClusterPeersZNode(clusterName));
List<ClusterInfo> cis = Collections.emptyList();
if (peers != null) {
cis = new ArrayList<ClusterInfo>();
for (String peer : peers) {
byte[] data = ZKUtil.getData(zkw, getClusterPeerZNode(clusterName, peer));
if (data != null) {
ClusterInfo ci = new ClusterInfo(peer, Bytes.toString(data), (ClusterInfo[]) null);
cis.add(ci);
}
}
}
return cis;
}
/**
* Gets the peers of the cluster.
*
* @param clusterName
* @param peers
* @return
* @throws KeeperException
*/
public List<ClusterInfo> getClusterPeers(String clusterName, String[] peers)
throws KeeperException {
if (peers != null && peers.length > 0) {
List<ClusterInfo> cis = new ArrayList<ClusterInfo>();
for (String peer : peers) {
byte[] data = ZKUtil.getData(zkw, getClusterPeerZNode(clusterName, peer));
if (data != null) {
ClusterInfo ci = new ClusterInfo(peer, Bytes.toString(data), (ClusterInfo[]) null);
cis.add(ci);
}
}
return cis;
} else {
return this.getPeerClusters(clusterName);
}
}
/**
* Sets the table state in zookeeper.
*
* @param tableName
* @param state
* @throws KeeperException
*/
public void setTableState(String tableName, TableState state) throws KeeperException {
ZKUtil.setData(this.zkw, getTableStateZNode(tableName), Bytes.toBytes(state.toString()));
}
/**
* @param tableName
* @return The state of the table stored in zookeeper.
* @throws KeeperException
* @throws TableNotFoundException
*/
public TableState getTableState(String tableName) throws KeeperException, TableNotFoundException {
byte[] data = ZKUtil.getData(this.zkw, getTableStateZNode(tableName));
if (data == null) {
throw new TableNotFoundException(tableName);
}
String str = Bytes.toString(data);
try {
return TableState.valueOf(str);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(str);
}
}
/**
* @param tableName
* @return The state of the table stored in zookeeper.
* @throws KeeperException
*/
public TableState getTableStateAllowNull(String tableName) throws KeeperException {
byte[] data = ZKUtil.getData(this.zkw, getTableStateZNode(tableName));
if (data == null) {
return null;
}
String str = Bytes.toString(data);
try {
return TableState.valueOf(str);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(str);
}
}
/**
* Finds all the state of the cross site tables.
*
* @return
* @throws KeeperException
* @throws TableNotFoundException
*/
public Map<String, TableState> listTableStates() throws KeeperException, TableNotFoundException {
Map<String, TableState> states = Collections.emptyMap();
List<String> tableNames = this.listTables();
if (!tableNames.isEmpty()) {
states = new HashMap<String, TableState>();
for (String tableName : tableNames) {
states.put(tableName, getTableState(tableName));
}
}
return states;
}
/**
* Check whether table exists or not
*
* @param tableName
* @return true if table exists.
* @throws KeeperException
*/
public boolean isTableStateExist(String tableName) throws KeeperException {
try {
this.getTableState(tableName);
} catch (TableNotFoundException e) {
return false;
}
return true;
}
/**
* Gets the znode path of the table state.
*
* @param tableName
* @return
*/
public String getTableStateZNode(String tableName) {
return ZKUtil.joinZNode(getTableZNode(tableName), TABLE_STATE_ZNODE_NAME);
}
/**
* Locks the table by creating an ephemeral znode for a table.
*
* @param tableName
* @return
* @throws KeeperException
*/
public boolean lockTable(String tableName) throws KeeperException {
boolean locked = ZKUtil.createEphemeralNodeAndWatch(zkw,
ZKUtil.joinZNode(crossSiteZNode, tableName + EPHEMERAL), null);
if (LOG.isDebugEnabled()) {
LOG.debug(locked ? "Locked" : "Could not lock" + " the table " + tableName);
}
return locked;
}
/**
* Unlocks the table by deleting the ephemeral znode.
*
* @param tableName
*/
public void unlockTable(String tableName) {
if (LOG.isDebugEnabled()) {
LOG.debug("Unlocking the table " + tableName);
}
try {
ZKUtil.deleteNode(zkw, ZKUtil.joinZNode(crossSiteZNode, tableName + EPHEMERAL));
} catch (KeeperException e) {
LOG.warn("Fail to unlock the table " + tableName, e);
}
}
/**
* Locks the table by creating an ephemeral znode for a cluster.
*
* @param clusterName
* @return
* @throws KeeperException
*/
public boolean lockCluster(String clusterName) throws KeeperException {
boolean locked = ZKUtil.createEphemeralNodeAndWatch(zkw,
ZKUtil.joinZNode(crossSiteZNode, clusterName + CLUSTER_EPHEMERAL), null);
if (LOG.isDebugEnabled()) {
LOG.debug(locked ? "Locked" : "Could not lock" + " the cluster " + clusterName);
}
return locked;
}
/**
* Unlocks the cluster by deleting the ephemeral znode.
*
* @param clusterName
*/
public void unlockCluster(String clusterName) {
if (LOG.isDebugEnabled()) {
LOG.debug("Unlocking the cluster " + clusterName);
}
try {
ZKUtil.deleteNode(zkw, ZKUtil.joinZNode(crossSiteZNode, clusterName + CLUSTER_EPHEMERAL));
} catch (KeeperException e) {
LOG.warn("Fail to unlock the cluster " + clusterName, e);
}
}
/**
* Gets the znode path of a table.
*
* @param tableName
* @return
*/
public String getTableZNode(String tableName) {
return ZKUtil.joinZNode(this.tablesZNode, tableName);
}
/**
* Gets the znode path of the table descriptor.
*
* @param tableName
* @return
*/
public String getTableDescZNode(String tableName) {
return ZKUtil.joinZNode(getTableZNode(tableName), TABLE_DESC_ZNODE_NAME);
}
/**
* Gets the znode path of the split keys.
*
* @param tableName
* @return
*/
public String getTableSplitKeysZNode(String tableName) {
return ZKUtil.joinZNode(getTableZNode(tableName), TABLE_SPLITKEYS_ZNODE_NAME);
}
/**
* @param tableName
* @return Initial split keys with which given table was created. Null when the table was created
* with out specifying any splits.
* @throws KeeperException
* @throws IOException
*/
public byte[][] getTableSplitKeys(String tableName) throws KeeperException, IOException {
byte[] data = ZKUtil.getData(zkw, getTableSplitKeysZNode(tableName));
return CrossSiteUtil.readSplitKeys(data);
}
/**
* Gets the znode path of the cluster locator.
*
* @param tableName
* @return
*/
public String getClusterLocatorZNode(String tableName) {
return ZKUtil.joinZNode(getTableZNode(tableName), CLUSTER_LOCATOR_ZNODE_NAME);
}
/**
* Creates the znode of a table.
*
* @param tableName
* @throws KeeperException
*/
public void createTableZNode(String tableName) throws KeeperException {
ZKUtil.createWithParents(this.zkw, getTableZNode(tableName));
}
/**
* Deletes the znode of a table.
*
* @param tableName
* @throws KeeperException
*/
public void deleteTableZNode(String tableName) throws KeeperException {
ZKUtil.deleteNodeRecursively(this.zkw, getTableZNode(tableName));
}
/**
* Modify the znode data of the table descriptor.
*
* @param tableName
* @param desc
* @throws KeeperException
* @throws IOException
*/
public void modifyTableDesc(String tableName, HTableDescriptor desc) throws KeeperException,
IOException {
// Do table existence check
getTableState(tableName);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
DataOutput out = new DataOutputStream(stream);
desc.write(out);
ZKUtil.setData(this.zkw, getTableDescZNode(tableName), stream.toByteArray());
stream.close();
}
/**
* Write the znode data of the new proposed table descriptor.
*
* @param tableName
* @param desc
* @throws KeeperException
* @throws IOException
*/
public void writeProposedTableDesc(String tableName, HTableDescriptor desc)
throws KeeperException, IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
DataOutput out = new DataOutputStream(stream);
desc.write(out);
// The node should be created here
ZKUtil.createSetData(this.zkw,
ZKUtil.joinZNode(getTableZNode(tableName), TABLE_PROPOSED_DESC_ZNODE_NAME),
stream.toByteArray());
stream.close();
}
/**
* Deletes the proposed HTD node from zk.
*
* @param tableName
* @throws KeeperException
* @throws IOException
*/
public void deleteProposedTableDesc(String tableName) throws KeeperException, IOException {
ZKUtil.deleteNode(zkw,
ZKUtil.joinZNode(getTableZNode(tableName), TABLE_PROPOSED_DESC_ZNODE_NAME));
}
/**
* Gets proposed HTD written to zk.
*
* @param tableName
* @return
* @throws KeeperException
* @throws IOException
*/
public HTableDescriptor getProposedTableDesc(String tableName) throws KeeperException,
IOException {
byte[] data = ZKUtil.getData(zkw,
ZKUtil.joinZNode(getTableZNode(tableName), TABLE_PROPOSED_DESC_ZNODE_NAME));
if(data == null) return null;
ByteArrayInputStream stream = new ByteArrayInputStream(data);
DataInput in = new DataInputStream(stream);
HTableDescriptor htd = new HTableDescriptor();
htd.readFields(in);
stream.close();
return htd;
}
/**
* Gets the table descriptor for the table descriptor znode.
*
* @param tableName
* @return
* @throws KeeperException
* @throws IOException
*/
public HTableDescriptor getTableDesc(String tableName) throws KeeperException, IOException {
// Do table existence check
getTableState(tableName);
byte[] data = ZKUtil.getData(this.zkw, getTableDescZNode(tableName));
ByteArrayInputStream stream = new ByteArrayInputStream(data);
DataInput in = new DataInputStream(stream);
HTableDescriptor htd = new HTableDescriptor();
htd.readFields(in);
stream.close();
return htd;
}
/**
* Gets the table descriptor for the table descriptor znode.
*
* @param tableName
* @return null if the table is not existent
* @throws KeeperException
* @throws IOException
*/
public HTableDescriptor getTableDescAllowNull(String tableName) throws KeeperException, IOException {
// Do table existence check
byte[] stateData = ZKUtil.getData(this.zkw, getTableStateZNode(tableName));
if (stateData == null) {
return null;
}
byte[] data = ZKUtil.getData(this.zkw, getTableDescZNode(tableName));
ByteArrayInputStream stream = new ByteArrayInputStream(data);
DataInput in = new DataInputStream(stream);
HTableDescriptor htd = new HTableDescriptor();
htd.readFields(in);
stream.close();
return htd;
}
/**
* Lists the descriptors of all the cross site tables.
*
* @return
* @throws KeeperException
* @throws IOException
*/
public HTableDescriptor[] listTableDescs() throws KeeperException, IOException {
return listTableDescs((Pattern) null);
}
/**
* Lists the descriptors of all the cross site tables with the pattern.
*
* @param pattern
* @return
* @throws KeeperException
* @throws IOException
*/
public HTableDescriptor[] listTableDescs(Pattern pattern) throws KeeperException, IOException {
List<HTableDescriptor> htds = Collections.emptyList();
List<String> tableNames = listTables();
if (tableNames != null && !tableNames.isEmpty()) {
htds = new ArrayList<HTableDescriptor>();
for (String tableName : tableNames) {
if (pattern == null || pattern.matcher(tableName).matches()) {
byte[] data = ZKUtil.getData(this.zkw, getTableDescZNode(tableName));
if (data != null) {
ByteArrayInputStream stream = new ByteArrayInputStream(data);
DataInput in = new DataInputStream(stream);
HTableDescriptor htd = new HTableDescriptor();
htd.readFields(in);
stream.close();
htds.add(htd);
}
}
}
}
return htds.toArray(new HTableDescriptor[0]);
}
/**
* Lists the descriptors of the cross site tables.
*
* @param tableNames
* @return
* @throws KeeperException
* @throws IOException
*/
public HTableDescriptor[] listTableDescs(List<String> tableNames) throws KeeperException,
IOException {
List<HTableDescriptor> htds = Collections.emptyList();
if (tableNames != null && !tableNames.isEmpty()) {
htds = new ArrayList<HTableDescriptor>();
for (String tableName : tableNames) {
byte[] data = ZKUtil.getData(this.zkw, getTableDescZNode(tableName));
if (data != null) {
ByteArrayInputStream stream = new ByteArrayInputStream(data);
DataInput in = new DataInputStream(stream);
HTableDescriptor htd = new HTableDescriptor();
htd.readFields(in);
stream.close();
htds.add(htd);
}
}
}
return htds.toArray(new HTableDescriptor[0]);
}
/**
* Lists all the cross site tables.
*
* @return
* @throws KeeperException
*/
public List<String> listTables() throws KeeperException {
List<String> emptyResult = Collections.emptyList();
List<String> result = ZKUtil.listChildrenNoWatch(zkw, tablesZNode);
return result == null ? emptyResult : result;
}
/**
* Gets all the cross site tables.
*
* @return an array of the table names.
* @throws KeeperException
*/
public String[] getTableNames() throws KeeperException {
List<String> results = Collections.emptyList();
List<String> tableNames = ZKUtil.listChildrenNoWatch(zkw, this.tablesZNode);
if (tableNames != null && !tableNames.isEmpty()) {
results = new ArrayList<String>();
for (String tableName : tableNames) {
byte[] data = ZKUtil.getData(this.zkw, getTableDescZNode(tableName));
if (data != null) {
results.add(tableName);
}
}
}
return results.toArray(new String[0]);
}
/**
* Gets the table names of all the cross site tables with the pattern.
*
* @param pattern
* @return
* @throws KeeperException
* @throws IOException
*/
public String[] getTableNames(Pattern pattern) throws KeeperException, IOException {
List<String> results = Collections.emptyList();
List<String> tableNames = ZKUtil.listChildrenNoWatch(zkw, this.tablesZNode);
if (tableNames != null && !tableNames.isEmpty()) {
results = new ArrayList<String>();
for (String tableName : tableNames) {
if (pattern.matcher(tableName).matches()) {
byte[] data = ZKUtil.getData(this.zkw, getTableDescZNode(tableName));
if (data != null) {
results.add(tableName);
}
}
}
}
return results.toArray(new String[0]);
}
/**
* Gets the znode data of the cluster locator.
*
* @param tableName
* @return
* @throws KeeperException
* @throws IOException
*/
public byte[] getClusterLocatorData(String tableName) throws KeeperException, IOException {
// Do table existence check
getTableState(tableName);
return ZKUtil.getData(this.zkw, getClusterLocatorZNode(tableName));
}
/**
* Gets a cluster locator.
*
* @param tableName
* @return
* @throws IOException
* @throws KeeperException
*/
public ClusterLocator getClusterLocator(String tableName) throws IOException, KeeperException {
byte[] clusterLocatorData = getClusterLocatorData(tableName);
ByteArrayInputStream stream = null;
try {
stream = new ByteArrayInputStream(clusterLocatorData);
DataInput in = new DataInputStream(stream);
ClusterLocatorRPCObject locator = new ClusterLocatorRPCObject();
locator.readFields(in);
return locator.getClusterLocator();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
LOG.warn("Fail to close the stream of reading cluster locator", e);
}
}
}
}
/**
* Checks whether the cluster is existent.
*
* @param clusterName
* @return
* @throws KeeperException
*/
public boolean clusterExists(String clusterName) throws KeeperException {
return ZKUtil.checkExists(this.zkw, getClusterZNode(clusterName)) >= 0;
}
/**
* Gets the cluster address.
*
* @param clusterName
* @return
* @throws KeeperException
*/
public String getClusterAddress(String clusterName) throws KeeperException {
if (!clusterExists(clusterName)) {
throw new IllegalArgumentException("The cluster " + clusterName + " is not found");
}
byte[] data = ZKUtil.getData(this.zkw, getClusterAddressZNode(clusterName));
return Bytes.toString(data);
}
/**
* Lists the clusters.
*
* @return
* @throws KeeperException
*/
public List<String> listClusters() throws KeeperException {
List<String> empty = Collections.emptyList();
List<String> result = ZKUtil.listChildrenNoWatch(this.zkw, this.clustersZNode);
return result == null ? empty : result;
}
/**
* Gets the map of the hierarchy.
*
* @return
* @throws KeeperException
*/
public Map<String, Set<String>> getHierarchyMap() throws KeeperException {
Map<String, Set<String>> hierarchy = new TreeMap<String, Set<String>>();
List<String> parents = ZKUtil.listChildrenNoWatch(this.zkw, this.hierarchyZNode);
if (parents != null) {
for (String parent : parents) {
List<String> children = ZKUtil.listChildrenNoWatch(this.zkw,
ZKUtil.joinZNode(this.hierarchyZNode, parent));
if (children != null) {
TreeSet<String> childrenSet = new TreeSet<String>();
childrenSet.addAll(children);
hierarchy.put(parent, childrenSet);
}
}
}
return hierarchy;
}
/**
* Checks whether the table is existent.
*
* @param tableName
* @return true if this table is existent.
* @throws KeeperException
*/
public boolean isTableExists(String tableName) throws KeeperException {
return (ZKUtil.checkExists(zkw, getTableZNode(tableName)) >= 0);
}
/**
* Checks whether the peer is existent.
*
* @param peer
* @return
* @throws KeeperException
*/
public boolean isPeerExists(String clusterName, String peer) throws KeeperException {
return (ZKUtil.checkExists(zkw, ZKUtil.joinZNode(getClusterPeersZNode(clusterName), peer)) >= 0);
}
}