diff --git a/CHANGES.txt b/CHANGES.txt index ec4341f6542..44e345bba70 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -432,6 +432,8 @@ Release 0.21.0 - Unreleased HBASE-2797 Another NPE in ReadWriteConsistencyControl HBASE-2831 Fix '$bin' path duplication in setup scripts (Nicolas Spiegelberg via Stack) + HBASE-2781 ZKW.createUnassignedRegion doesn't make sure existing znode is + in the right state (Karthik Ranganathan via JD) IMPROVEMENTS HBASE-1760 Cleanup TODOs in HTable diff --git a/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java b/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java index b4ba5ab15c0..979739e3a07 100644 --- a/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java +++ b/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java @@ -993,8 +993,9 @@ public class RegionManager { // should never happen LOG.error("Error creating event data for " + HBaseEventType.M2ZK_REGION_OFFLINE, e); } - zkWrapper.createUnassignedRegion(info.getEncodedName(), data); - LOG.debug("Created UNASSIGNED zNode " + info.getRegionNameAsString() + " in state " + HBaseEventType.M2ZK_REGION_OFFLINE); + zkWrapper.createOrUpdateUnassignedRegion(info.getEncodedName(), data); + LOG.debug("Created/updated UNASSIGNED zNode " + info.getRegionNameAsString() + + " in state " + HBaseEventType.M2ZK_REGION_OFFLINE); s = new RegionState(info, RegionState.State.UNASSIGNED); regionsInTransition.put(info.getRegionNameAsString(), s); } diff --git a/src/main/java/org/apache/hadoop/hbase/zookeeper/ZooKeeperWrapper.java b/src/main/java/org/apache/hadoop/hbase/zookeeper/ZooKeeperWrapper.java index 74b0446fa30..f292b253c62 100644 --- a/src/main/java/org/apache/hadoop/hbase/zookeeper/ZooKeeperWrapper.java +++ b/src/main/java/org/apache/hadoop/hbase/zookeeper/ZooKeeperWrapper.java @@ -1073,6 +1073,14 @@ public class ZooKeeperWrapper implements Watcher { } } + /** + * Given a region name and some data, this method creates a new the region + * znode data under the UNASSGINED znode with the data passed in. This method + * will not update data for existing znodes. + * + * @param regionName - encoded name of the region + * @param data - new serialized data to update the region znode + */ public void createUnassignedRegion(String regionName, byte[] data) { String znode = getZNode(getRegionInTransitionZNode(), regionName); if(LOG.isDebugEnabled()) { @@ -1109,6 +1117,66 @@ public class ZooKeeperWrapper implements Watcher { } } + /** + * Given a region name and some data, this method updates the region znode + * data under the UNASSGINED znode with the latest data. This method will + * update the znode data only if it already exists. + * + * @param regionName - encoded name of the region + * @param data - new serialized data to update the region znode + */ + public void updateUnassignedRegion(String regionName, byte[] data) { + String znode = getZNode(getRegionInTransitionZNode(), regionName); + // this is an update - make sure the node already exists + if(!exists(znode, true)) { + LOG.error("Cannot update " + znode + " - node does not exist" ); + return; + } + + if(LOG.isDebugEnabled()) { + // Check existing state for logging purposes. + Stat stat = new Stat(); + byte[] oldData = null; + try { + oldData = readZNode(znode, stat); + } catch (IOException e) { + LOG.error("Error reading data for " + znode); + } + if(oldData == null) { + LOG.debug("While updating UNASSIGNED region " + regionName + " - node exists with no data" ); + } + else { + LOG.debug("While updating UNASSIGNED region " + regionName + " exists, state = " + (HBaseEventType.fromByte(oldData[0]))); + } + } + synchronized(unassignedZNodesWatched) { + unassignedZNodesWatched.add(znode); + try { + writeZNode(znode, data, -1, true); + } catch (IOException e) { + LOG.error("Error writing data for " + znode + ", could not update state to " + (HBaseEventType.fromByte(data[0]))); + } + } + } + + /** + * This method will create a new region in transition entry in ZK with the + * speficied data if none exists. If one already exists, it will update the + * data with whatever is passed in. + * + * @param regionName - encoded name of the region + * @param data - serialized data for the region znode + */ + public void createOrUpdateUnassignedRegion(String regionName, byte[] data) { + String znode = getZNode(getRegionInTransitionZNode(), regionName); + if(exists(znode, true)) { + updateUnassignedRegion(regionName, data); + } + else { + createUnassignedRegion(regionName, data); + } + } + public void deleteUnassignedRegion(String regionName) { String znode = getZNode(getRegionInTransitionZNode(), regionName); try {