HBASE-17460 enable_table_replication can not perform cyclic replication of a table - revert due to reproducible test failure
This commit is contained in:
parent
f4202a1205
commit
3fc2889f7a
|
@ -1076,7 +1076,7 @@ public class HColumnDescriptor implements Comparable<HColumnDescriptor> {
|
||||||
public int compareTo(HColumnDescriptor o) {
|
public int compareTo(HColumnDescriptor o) {
|
||||||
int result = Bytes.compareTo(this.name, o.getName());
|
int result = Bytes.compareTo(this.name, o.getName());
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
// punt on comparison for ordering, just calculate difference.
|
// punt on comparison for ordering, just calculate difference
|
||||||
result = this.values.hashCode() - o.values.hashCode();
|
result = this.values.hashCode() - o.values.hashCode();
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
result = -1;
|
result = -1;
|
||||||
|
|
|
@ -40,9 +40,9 @@ import org.apache.hadoop.hbase.classification.InterfaceStability;
|
||||||
import org.apache.hadoop.hbase.client.Durability;
|
import org.apache.hadoop.hbase.client.Durability;
|
||||||
import org.apache.hadoop.hbase.client.RegionReplicaUtil;
|
import org.apache.hadoop.hbase.client.RegionReplicaUtil;
|
||||||
import org.apache.hadoop.hbase.exceptions.DeserializationException;
|
import org.apache.hadoop.hbase.exceptions.DeserializationException;
|
||||||
import org.apache.hadoop.hbase.security.User;
|
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.TableSchema;
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.TableSchema;
|
||||||
|
import org.apache.hadoop.hbase.security.User;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1041,106 +1041,6 @@ public class HTableDescriptor implements Comparable<HTableDescriptor> {
|
||||||
return compareTo((HTableDescriptor)obj) == 0;
|
return compareTo((HTableDescriptor)obj) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Detects whether replication has been already enabled on any of the column families of this
|
|
||||||
* table descriptor.
|
|
||||||
* @return true if any of the column families has replication enabled.
|
|
||||||
*/
|
|
||||||
public boolean isReplicationEnabled() {
|
|
||||||
// Go through each Column-Family descriptor and check if the
|
|
||||||
// Replication has been enabled already.
|
|
||||||
// Return 'true' if replication has been enabled on any CF,
|
|
||||||
// otherwise return 'false'.
|
|
||||||
//
|
|
||||||
boolean result = false;
|
|
||||||
Iterator<HColumnDescriptor> it = this.families.values().iterator();
|
|
||||||
|
|
||||||
while (it.hasNext()) {
|
|
||||||
HColumnDescriptor tempHcd = it.next();
|
|
||||||
if (tempHcd.getScope() != HConstants.REPLICATION_SCOPE_LOCAL) {
|
|
||||||
result = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compare the contents of the descriptor with another one passed as a parameter for replication
|
|
||||||
* purpose. The REPLICATION_SCOPE field is ignored during comparison.
|
|
||||||
* @param obj descriptor on source cluster which needs to be replicated.
|
|
||||||
* @return true if the contents of the two descriptors match (ignoring just REPLICATION_SCOPE).
|
|
||||||
* @see java.lang.Object#equals(java.lang.Object)
|
|
||||||
*/
|
|
||||||
public boolean compareForReplication(Object obj) {
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (obj == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!(obj instanceof HTableDescriptor)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean result = false;
|
|
||||||
|
|
||||||
// Create a copy of peer HTD as we need to change its replication
|
|
||||||
// scope to match with the local HTD.
|
|
||||||
HTableDescriptor peerHtdCopy = new HTableDescriptor(this);
|
|
||||||
|
|
||||||
// Copy the replication scope of local Htd to remote Htd.
|
|
||||||
HTableDescriptor localHtd = (HTableDescriptor) obj;
|
|
||||||
|
|
||||||
result = (peerHtdCopy.copyReplicationScope(localHtd) == 0);
|
|
||||||
|
|
||||||
// If copy was successful, compare the two tables now.
|
|
||||||
if (result == true) {
|
|
||||||
result = (peerHtdCopy.compareTo(localHtd) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies the REPLICATION_SCOPE of table descriptor passed as an argument. Before copy, the method
|
|
||||||
* ensures that the name of table and column-families should match.
|
|
||||||
* @param localHtd - The HTableDescriptor of table from source cluster.
|
|
||||||
* @return 0 If the name of table and column families match and REPLICATION_SCOPE copied
|
|
||||||
* successfully. 1 If there is any mismatch in the names.
|
|
||||||
*/
|
|
||||||
public int copyReplicationScope(final HTableDescriptor localHtd)
|
|
||||||
{
|
|
||||||
// Copy the REPLICATION_SCOPE only when table names and the names of
|
|
||||||
// Column-Families are same.
|
|
||||||
int result = this.name.compareTo(localHtd.name);
|
|
||||||
|
|
||||||
if (result == 0) {
|
|
||||||
Iterator<HColumnDescriptor> remoteHCDIter = families.values().iterator();
|
|
||||||
Iterator<HColumnDescriptor> localHCDIter = localHtd.families.values().iterator();
|
|
||||||
|
|
||||||
while (remoteHCDIter.hasNext() && localHCDIter.hasNext()) {
|
|
||||||
HColumnDescriptor remoteHCD = remoteHCDIter.next();
|
|
||||||
HColumnDescriptor localHCD = localHCDIter.next();
|
|
||||||
|
|
||||||
String remoteHCDName = remoteHCD.getNameAsString();
|
|
||||||
String localHCDName = localHCD.getNameAsString();
|
|
||||||
|
|
||||||
if (remoteHCDName.equals(localHCDName))
|
|
||||||
{
|
|
||||||
remoteHCD.setScope(localHCD.getScope());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see java.lang.Object#hashCode()
|
* @see java.lang.Object#hashCode()
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
@ -4086,9 +4087,7 @@ public class HBaseAdmin implements Admin {
|
||||||
* Connect to peer and check the table descriptor on peer:
|
* Connect to peer and check the table descriptor on peer:
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li>Create the same table on peer when not exist.</li>
|
* <li>Create the same table on peer when not exist.</li>
|
||||||
* <li>Throw an exception if the table already has replication enabled on any of the column
|
* <li>Throw exception if the table exists on peer cluster but descriptors are not same.</li>
|
||||||
* families.</li>
|
|
||||||
* <li>Throw an exception if the table exists on peer cluster but descriptors are not same.</li>
|
|
||||||
* </ol>
|
* </ol>
|
||||||
* @param tableName name of the table to sync to the peer
|
* @param tableName name of the table to sync to the peer
|
||||||
* @param splits table split keys
|
* @param splits table split keys
|
||||||
|
@ -4106,32 +4105,20 @@ public class HBaseAdmin implements Admin {
|
||||||
Configuration peerConf = getPeerClusterConfiguration(peerDesc);
|
Configuration peerConf = getPeerClusterConfiguration(peerDesc);
|
||||||
try (Connection conn = ConnectionFactory.createConnection(peerConf);
|
try (Connection conn = ConnectionFactory.createConnection(peerConf);
|
||||||
Admin repHBaseAdmin = conn.getAdmin()) {
|
Admin repHBaseAdmin = conn.getAdmin()) {
|
||||||
HTableDescriptor localHtd = getTableDescriptor(tableName);
|
HTableDescriptor htd = getTableDescriptor(tableName);
|
||||||
HTableDescriptor peerHtd = null;
|
HTableDescriptor peerHtd = null;
|
||||||
if (!repHBaseAdmin.tableExists(tableName)) {
|
if (!repHBaseAdmin.tableExists(tableName)) {
|
||||||
repHBaseAdmin.createTable(localHtd, splits);
|
repHBaseAdmin.createTable(htd, splits);
|
||||||
} else {
|
} else {
|
||||||
peerHtd = repHBaseAdmin.getTableDescriptor(tableName);
|
peerHtd = repHBaseAdmin.getTableDescriptor(tableName);
|
||||||
if (peerHtd == null) {
|
if (peerHtd == null) {
|
||||||
throw new IllegalArgumentException("Failed to get table descriptor for table "
|
throw new IllegalArgumentException("Failed to get table descriptor for table "
|
||||||
+ tableName.getNameAsString() + " from peer cluster " + peerDesc.getPeerId());
|
+ tableName.getNameAsString() + " from peer cluster " + peerDesc.getPeerId());
|
||||||
} else {
|
} else if (!peerHtd.equals(htd)) {
|
||||||
// To support cyclic replication (HBASE-17460), we need to match the
|
throw new IllegalArgumentException("Table " + tableName.getNameAsString()
|
||||||
// REPLICATION_SCOPE of table on both the clusters. We should do this
|
+ " exists in peer cluster " + peerDesc.getPeerId()
|
||||||
// only when the replication is not already enabled on local HTD (local
|
+ ", but the table descriptors are not same when compared with source cluster."
|
||||||
// table on this cluster).
|
+ " Thus can not enable the table's replication switch.");
|
||||||
//
|
|
||||||
if (localHtd.isReplicationEnabled()) {
|
|
||||||
throw new IllegalArgumentException("Table " + tableName.getNameAsString()
|
|
||||||
+ " has replication already enabled for atleast one Column Family.");
|
|
||||||
} else {
|
|
||||||
if (!peerHtd.compareForReplication(localHtd)) {
|
|
||||||
throw new IllegalArgumentException("Table " + tableName.getNameAsString()
|
|
||||||
+ " exists in peer cluster " + peerDesc.getPeerId()
|
|
||||||
+ ", but the table descriptors are not same when compared with source cluster."
|
|
||||||
+ " Thus can not enable the table's replication switch.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.hadoop.hbase.client.replication;
|
package org.apache.hadoop.hbase.client.replication;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -26,9 +29,9 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
@ -59,9 +62,6 @@ import org.apache.hadoop.hbase.replication.ReplicationQueuesClientArguments;
|
||||||
import org.apache.hadoop.hbase.util.Pair;
|
import org.apache.hadoop.hbase.util.Pair;
|
||||||
import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
|
import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* This class provides the administrative interface to HBase cluster
|
* This class provides the administrative interface to HBase cluster
|
||||||
|
|
Loading…
Reference in New Issue